OOM:java
1.快速恢復業務:若是是集羣中的一臺機器故障,先隔離故障服務器;若是是多臺,則根據Nginx轉發策略,對該功能轉發到單獨的集羣,與其餘流量隔離,確保其餘業務不受影響mysql
2.收集內存溢出Dump文件:方式有兩種:spring
1.設置JVM啓動參數sql
-XX:+HeapDumpOnOutOfMemoryError數據庫
-XX:HeapDumpPath=/opt/jvmdumpapache
設置以後,在每次發生內存溢出時,JVM會自動將堆轉儲,dump文件存放在-XX:HeapDumpPath指定的路徑下服務器
2.使用jmap命令收集併發
經過jamp -dump:live,format=b,file=/opt/jvm/dump.hprof pid運維
3.分析dump文件:能夠經過MAT(Memory Analyzer Tool)進行分析,使用MAT打開Dump文件後,首頁截圖以下:jvm
工具按鈕介紹:
:直方圖視圖,將堆中全部的內存消耗狀況統計出來,其如圖所示:
:內存使用樹狀結構,以線程爲維度,樹狀形式展開,如圖所示:
線程棧,其截圖以下:
根據該圖,能夠明確,堆的總大小爲1.9G,被4個線程所有佔據,致使其餘線程沒法再申請資源,拋出堆內存溢出錯誤。
接下來,我一般的作法是直接去看這個視圖(以線程爲基本維度,查找線程中佔用內存的對象),爲後續定位排查提供必要的依據。
從上面的截圖中能夠得出以下關鍵信息點:
org.apache.ibatis.executor.result.DefaultResultHandler內部持有一個List,其原始爲java.util.HashMap,從這個類基本能夠看出是與數據庫的查詢相關,對數據庫返回結果的解碼並組織成HashMap。
這個List中的元素總共有146033個,初步能夠判斷出是在一次查詢中從數據庫中一次查詢出了太多數據,形成了內存溢出。
因爲SQL查詢代碼中,是用HashMap來接收數據庫中的返回字段,沒法一時間看出是那個查詢,那咱們能不能精確找到是哪個查詢,哪一行代碼,甚至與哪一條SQL語句呢?
答案是能夠的,咱們能夠從視圖一探究竟。
舒適提示:
視圖使用技巧:展開技巧:沿着使用率最高的項一層一層進行展開,直至發現具體佔用內存的對象。
接下來咱們從 視圖去尋找是哪一個方法,哪條SQL語句觸發的。
具體方法:首先徹底展開一個線程,從展開圖的底部向上尋找:
其線程的入口(控制層代碼)
繼續往上查找,要找到SQL語句,應該找到Mybatis處理結果集相關的類,如圖所示:
而後展開boundSql即能找到SQL語句:
而後鼠標能夠放在SQL屬性中,右鍵,能夠將SQL語句複製出來。
因爲這裏涉及到公司的代碼機密,故在這裏不貼出具體的SQL語句。
這裏根據後面的分析,原來是在作導出功能的時候,沒有使用分頁對數據進行分頁查詢,分頁寫入Excel文件,而是一次將所有數據查詢,致使導出功能若是併發數超過4個時,就會將全部內存耗盡。
解決方案:
首先在運維層面將該請求導入到指定的一臺服務器上,是導出任務與其餘任務進行隔離,避免對其餘重要服務形成影響。
項目組對其代碼進行修復,可使用分頁查數據,而後分配寫入Excel。
死鎖:
1.查看系統日誌,找到對應的死鎖方法:
org.springframework.dao.CannotAcquireLockException: could not execute statement; SQL [n/a]; nested exception is org.hibernate.exception.LockAcquisitionException: could not execute statement
at com.kuding.order.services.ChildOrderService.lambda$modifyChildOrderDeliverStatus$23(ChildOrderService.java:423)
at com.kuding.order.services.ChildOrderService.modifyChildOrderDeliverStatus(ChildOrderService.java:416)
at com.kuding.order.controllers.ChildOrderController.modifyDeliveringStatus(ChildOrderController.java:68)
at com.kuding.common.basestructure.filters.GeetestFilter.doFilter(GeetestFilter.java:102)
Caused by: org.hibernate.exception.LockAcquisitionException: could not execute statement
at com.kuding.common.basestructure.interfaces.daointerfacesv2.AbstractDao.create(AbstractDao.java:22)
Caused by: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
2.在mysql中使用命令:SHOW ENGINE INNODB STATUS;總能獲取到最近一些問題信息,經過搜索deadlock 關鍵字便可找到死鎖的相關日誌信息。
分析哪些語句申請鎖資源衝突,結合1來肯定對應的代碼,經過使用分佈式鎖或者修改獲取數據鎖順序來修復