一次野事務排查
測試環境出了一個很神奇的問題。
某一個事務鎖了很多不同表的不同記錄(暫且先叫他野事務),導致其他事務都阻塞了.
這個野事務往往持續數個小時,並不提交或者回滾,就生生的佔在那裡。
野事務鎖的表,相互之間沒有任何的關聯.不能定位到某一個業務或者模組.
經過排查,這個問題和我們的開發方式有關係.
雖然使用了Spring,但是居然沒有使用Spring的事務管理機制.
絕大多數的資料庫操作,都是依賴於自動提交.另外少數的模組,使用了手動開啟的程式設計式事務管理.
但是程式設計式事務的一個分支判斷出現了bug,沒有提交事務或者回滾.
導致了這個連線歸還連線池之後(這時候這個連線 autocommit尚在false狀態)
其他自動提交的模組如果使用這個連線執行,那麼就會不斷的加鎖,而不釋放.從而導致一系列怪異神奇的現象.
當時出問題的程式碼示例如下
在第10行的程式碼,未結束事務而直接返回,是造成這個問題的原因.
開發同事之所以不使用spring的事務管理,是因為如果要spring回滾事務,需要丟擲異常,而他們還想返回一個業務上的狀態值.
比如
return createFailResult(baseParam, RetEnum.RET_METADATA_USER_NOT_EXISTS);
其實我覺得不如使用自定義異常,繼承RuntimeException,然後增加一個業務狀態的資料成員.
經過這次排查,小有收穫,也糾正了自己的一個錯誤認識。
原來一直以為 mysql
start transaction 是 set autocommit=false 的同義詞.
但是兩種方式,還有差別.
但是set autocommit=false不會提交之前的事務.
某一個事務鎖了很多不同表的不同記錄(暫且先叫他野事務),導致其他事務都阻塞了.
這個野事務往往持續數個小時,並不提交或者回滾,就生生的佔在那裡。
野事務鎖的表,相互之間沒有任何的關聯.不能定位到某一個業務或者模組.
經過排查,這個問題和我們的開發方式有關係.
雖然使用了Spring,但是居然沒有使用Spring的事務管理機制.
絕大多數的資料庫操作,都是依賴於自動提交.另外少數的模組,使用了手動開啟的程式設計式事務管理.
但是程式設計式事務的一個分支判斷出現了bug,沒有提交事務或者回滾.
導致了這個連線歸還連線池之後(這時候這個連線 autocommit尚在false狀態)
其他自動提交的模組如果使用這個連線執行,那麼就會不斷的加鎖,而不釋放.從而導致一系列怪異神奇的現象.
當時出問題的程式碼示例如下
- public Map<String, Object> xxxMethod(String jsonParam) {
- BaseParam baseParam = JsonUtil.getObjectFromJson(jsonParam, BaseParam.class);
- Map<String, Object> bizParamMap = baseParam.getBizParamMap();
- DefaultTransactionDefinition def = new DefaultTransactionDefinition();
- TransactionStatus status = transactionManager_vvlivemetadata.getTransaction(def);
- try {
- UserBaseinfo userBaseinfo = userBaseinfoMapper.selectByPrimaryKey(lineUserID);
- if (userBaseinfo == null) {
- return createFailResult(baseParam, RetEnum.RET_METADATA_USER_NOT_EXISTS);
- }
- LiveLineInfo liveLineInfo = new LiveLineInfo();
- liveLineInfo.setLiveLineID(lineUserList.get(0).getLiveLineID());
- liveLineInfo.setLiveID(liveID);
- liveLineInfo.setUserID(userID);
- liveLineInfo.setLineUserID(lineUserID);
- liveLineInfo.setStatus((short) 0);
- int liveLineInfoRetNum = liveLineInfoMapper.updateByPrimaryKeySelective(liveLineInfo);
- if (liveLineInfoRetNum != 1) {
- transactionManager_vvlivemetadata.rollback(status);// bug 當時沒加
- _log.error("取消連麥失敗, 房間上麥資訊狀態修改失敗. jsonParam={}, liveLineInfoRetNum={}",
- jsonParam, liveLineInfoRetNum);
- return createFailResult(baseParam, RetEnum.RET_DB_FAIL);
- }
- liveLineInfoMapper.updateOthersShowPosBatch(liveID, lineUserList.get(0).getShowPos());
- transactionManager_vvlivemetadata.commit(status);
- return createBizResult(baseParam, jsonResult);
- } catch (Exception e) {
- transactionManager_vvlivemetadata.rollback(status);
- return createFailResult(baseParam, RetEnum.RET_DB_FAIL);
- }
- }
在第10行的程式碼,未結束事務而直接返回,是造成這個問題的原因.
開發同事之所以不使用spring的事務管理,是因為如果要spring回滾事務,需要丟擲異常,而他們還想返回一個業務上的狀態值.
比如
return createFailResult(baseParam, RetEnum.RET_METADATA_USER_NOT_EXISTS);
其實我覺得不如使用自定義異常,繼承RuntimeException,然後增加一個業務狀態的資料成員.
經過這次排查,小有收穫,也糾正了自己的一個錯誤認識。
原來一直以為 mysql
start transaction 是 set autocommit=false 的同義詞.
但是兩種方式,還有差別.
- set autocommit=false;
- update t set str='edmond' where id=1;
- -- start transaction會提交之前的事務
- start transaction;
但是set autocommit=false不會提交之前的事務.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-2128120/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 線上併發事務死鎖問題排查
- 專案中Spring事務失效的場景問題排查Spring
- 記一次oom問題排查OOM
- 記錄一次問題排查
- 記錄一次木馬排查
- 日常Bug排查-應用Commit報錯事務並沒有回滾MIT
- 記一次 Laravel MethodNotAllowedHttpException 問題排查LaravelHTTPException
- 一次快取效能問題排查快取
- 一次線上死迴圈的排查
- 記一次Oracle死鎖/阻塞排查Oracle
- 記一次axios原始碼排查iOS原始碼
- 記一次線上FGC問題排查GC
- 線上的一次fullgc排查過程GC
- 一次訊息消費服務的記憶體洩漏排查小記記憶體
- 記一次FreeBSD系統中mysql服務異常的排查過程MySql
- 記一次hadoop yarn環境無法提交任務的問題排查HadoopYarn
- 一次ORACLE分散式事務鎖異常處理分析Oracle分散式
- 十、Redis事務、事務鎖Redis
- 記一次線上SpringCloud-Feign請求服務超時異常排查SpringGCCloud
- 一次django記憶體異常排查Django記憶體
- 記一次OOM問題排查過程OOM
- 記一次神奇的Mysql死鎖排查MySql
- 一次minerd肉雞木馬的排查思路
- 一次奇怪的的bug排查過程
- 一次容器MySQL的效能問題排查MySql
- 記一次排查CPU高的問題
- 一次生產環境OOM排查OOM
- 原始碼解析丨一次慢SQL排查原始碼SQL
- 分散式事務之Spring事務與JMS事務(二)分散式Spring
- MySQL事務(一)認識事務MySql
- 什麼是事務、事務特性、事務隔離級別、spring事務傳播特性?Spring
- 解Bug之路-記一次呼叫外網服務概率性失敗問題的排查
- 事務
- 編輯 Java 中的事務 — JDBC 事務和 JTA 事務JavaJDBC
- 一次 Java 記憶體洩漏的排查Java記憶體
- 排查Mysql突然變慢的一次過程MySql
- 一次線上介面超時的排查過程
- 一次StackOverflowError排查,原因竟然和Dubbo有關!Error