記一次Mysql故障排查(lock wait timeout exceeded;try restarting transaction)


最近接了一個(gè)鍋,進(jìn)入新公司接手了一個(gè)進(jìn)入交付階段的項(xiàng)目.在code?review的時(shí)候發(fā)現(xiàn)很多問題,然后開始修復(fù)bug.

在測(cè)試階段突然發(fā)現(xiàn)幾乎所有涉及到更新的操作都失敗,下面貼出異常信息.

第一次出現(xiàn)的時(shí)候百度了一下,猜想可能是多服務(wù)部署資源沖突,重啟服務(wù)故障消失.所以沒有特別重視

第二次出現(xiàn)的時(shí)候只有測(cè)試環(huán)境部署,不存在多機(jī)資源沖突的問題,猜想是多線程資源交叉導(dǎo)致的,于是給可能導(dǎo)致資源競(jìng)爭(zhēng)的地方加上了分布式鎖.

由于無法重現(xiàn)故障,所以并沒有確認(rèn)問題得到解決.

第三次故障依舊,當(dāng)發(fā)現(xiàn)問題依然存在的時(shí)候,開始認(rèn)真反思,發(fā)現(xiàn)自己解決問題的思路明顯有問題,過于片面,一直都只在應(yīng)用層面尋求解決問題的辦法,而且解決問題的方式也只是在嘗試百度出來的方法.并沒有去思考更深層的問題.

知道自己的問題之后開始結(jié)合業(yè)務(wù)在MySQL上尋找解決問題的思路


在Mysql5.5中,information_schema 庫中增加了三個(gè)關(guān)于鎖的表(MEMORY引擎);

INNODB_TRX## 當(dāng)前運(yùn)行的所有事務(wù)

INNODB_LOCKS ## 當(dāng)前出現(xiàn)的鎖

  INNODB_LOCK_WAITS ## 鎖等待的對(duì)應(yīng)關(guān)系

通過查詢INNODB_TRX發(fā)現(xiàn)

當(dāng)前事務(wù)中又兩個(gè)RUNNING狀態(tài)開始時(shí)間在一個(gè)小時(shí)之前

開始一直以為是鎖表了

查看了INNODB_LOCKS?事務(wù)信息之后發(fā)現(xiàn)有4行數(shù)據(jù)被鎖住了一直沒有釋放

從這里開始發(fā)現(xiàn)問題了,應(yīng)用已經(jīng)拋了異常,事務(wù)理所當(dāng)然的應(yīng)該回滾才對(duì),為什么資源依然沒有釋放,導(dǎo)致持續(xù)的阻塞呢?

其實(shí)最開始的異常信息就已經(jīng)給出了答案,回到開始的地方,再看異常信息就很清楚了,應(yīng)用里面的異常類是MySQLTransactionRollBackException

是一個(gè)回滾異常,這就說明在事務(wù)回滾的時(shí)候出了問題資源沒有得到釋放

然后開始查詢MySQLTransactionRollBackException?相關(guān)的信息

這個(gè)時(shí)候innodb_rollback_on_timeout=0(默認(rèn)配置)這個(gè)MySQL的配置開始進(jìn)入我的視線,

舉個(gè)栗子

事務(wù)在鎖等待超時(shí)后是回滾事務(wù)內(nèi)所有的statement還是最后一條語句;

?0表示rollback最后一條語句,默認(rèn)值;有點(diǎn)坑爹啊(細(xì)思極恐)

?1表示回滾事務(wù)內(nèi)所有的statements;(此參數(shù)是只讀參數(shù),需在my.cnf中配置,并且重啟生效;)

吃過一次虧,這次并沒有盲目的相信百度到的信息

于是開始測(cè)試

一、驗(yàn)證innodb_rollback_on_timeout=off的情況


測(cè)試表結(jié)構(gòu)

1.session?A

? ? 開啟事務(wù),事務(wù)未提交,鎖住id=1的數(shù)據(jù)

d

2.session B?

開啟事務(wù),執(zhí)行更新id=2的數(shù)據(jù)成功(事務(wù)未提交,鎖住id=2),然后請(qǐng)求id=1等待鎖超時(shí),id=2的數(shù)據(jù)更改為222.


3.session C

請(qǐng)求id=2的數(shù)據(jù)50秒后顯示等待鎖超時(shí)

執(zhí)行SELECT * FROM information_schema.INNODB_TRX;

可發(fā)現(xiàn)有資源一直未釋放,具體到測(cè)試數(shù)據(jù)中就是id=2的資源一直被鎖定,線程一直被掛起.

總結(jié):通過實(shí)驗(yàn)基本可以確定是業(yè)務(wù)資源交叉導(dǎo)致死鎖之后資源沒釋放造成的持續(xù)阻塞,

二.驗(yàn)證innodb_rollback_on_timeout=on

修改配置后將驗(yàn)證innodb_rollback_on_timeout=off的步驟再走一遍

發(fā)現(xiàn)鎖等待只能在業(yè)務(wù)層面盡量避免

on/off的區(qū)別在于session?C進(jìn)入時(shí)不會(huì)持續(xù)阻塞,session B異常后全部回滾

綜上:基本確定是innodb_rollback_on_timeout默認(rèn)配置的鍋.

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容