MyBatis查詢介面返回大量資料導致OOM
阿新 • • 發佈:2018-11-25
MyBatis查詢介面返回大量資料導致OOM
異常描述
- 介面除錯過程中發現程式執行中斷,DEBUG跟蹤到Mapper中的查詢介面報錯,沒有接收到返回值且丟擲 out of memory 異常
異常定位
- 逐步DEBUG,對比傳入底層的引數及最終的執行的SQL,發現WHERE條件均沒有傳參,即此時是全表查詢,且資料量很大,導致了OOM異常的發生
異常反思
- 介面複用性:Mapper.java 是 DAO 層中介面,無論是 Service 層或 Business 層都會間接或直接的呼叫 Mapper.java 中的介面
- 介面命名沒有見名知義
- 除了使用MyBatis工具自動生產的介面外,其餘介面均是為了開發某個功能時新增的,此時為了排序、為了某個特定值的傳參或者有時候自己開發者覺得某個值肯定不會空,而沒有使用 test 進行引數判空,其他開發人員在方法呼叫時直接根據介面名稱和返回值就斷定方法適合自己使用,而沒有檢視底層的Mapper.xml中的SQL實現,導致問題出現
- 特定功能開發的介面要通過名稱註明,避免其他人誤呼叫
- 共用的介面功能,通過 Map 或 PO 類作為引數的介面,每個屬性都要加 test 判斷,且需注意 order limit 與 屬性條件使用順序,避免報語法錯誤
- 介面命名沒有見名知義
- 查詢介面一定要使用分頁,呼叫介面前對入參進入處理,如果是集合,則拆分為500或1000一組,分批查詢
- 即使是返回一條資料,也加上 limit 1
OOM常見異常型別
-
堆異常
- 記憶體洩露
- 物件引用一直未釋放
- 開發過程中使用到的物件、集合,使用完畢後直接賦值為null,等待GC
- 避免物件不使用依然向下一個方法中傳遞
- 方法內的形參不使用時及時進行方法重構
- 物件引用一直未釋放
- 記憶體溢位
- 生成物件過大
- 合理設計表結構,避免物件中內容過多
- 物件生命週期過長
- 開闢無用空間
- 在迴圈中建立新的物件
- 可以改為在迴圈外宣告物件,在迴圈內例項化物件,始終是同一個物件
- 可以改為克隆
- 在迴圈中建立新的物件
- 堆空間大小設定不合理,手動調整
- 生成物件過大
- 記憶體洩露
-
棧異常
- 用於存放各個方法的內部變量表
- 當大量的方法被呼叫,而又未及時結束,或者單個方法內部定義了大量區域性變數
-
方法區
- 用於存放類的定義Class檔案和常量池等
- 專案中類過多
-
參考資料
解決方案
- 因為jdbc預設會把查詢結果集全部返回到客戶端導致oom錯誤
- 返回的資料量的大小大於了JVM分割槽中記憶體空間的大小
- 參考資料