《Mysql實(shí)例InnoDB數(shù)據(jù)庫(kù)死鎖問(wèn)題處理》要點(diǎn):
本文介紹了Mysql實(shí)例InnoDB數(shù)據(jù)庫(kù)死鎖問(wèn)題處理,希望對(duì)您有用。如果有疑問(wèn),可以聯(lián)系我們。
場(chǎng)景描述MYSQL應(yīng)用
在update表的時(shí)候呈現(xiàn)DeadlockLoserDataAccessException異常 (Deadlock found when trying to get lock; try restarting transaction...).MYSQL應(yīng)用
問(wèn)題闡發(fā)MYSQL應(yīng)用
這個(gè)異常并不會(huì)影響用戶使用,因?yàn)閿?shù)據(jù)庫(kù)遇到死鎖會(huì)自動(dòng)回滾并重試.用戶的感覺(jué)就是操作稍有卡頓.但是監(jiān)控老是報(bào)異常,所以需要辦理一下.MYSQL應(yīng)用
解決辦法MYSQL應(yīng)用
在應(yīng)用法式中update的地方使用try-catch.MYSQL應(yīng)用
我本身封裝了一個(gè)函數(shù),如下.MYSQL應(yīng)用
/** * 2016-03-15 * linxuan * handle deadlock while update table */ private void updateWithDeadLock(TestMapper mapper, Test record) throws InterruptedException { boolean oops; int retries = 5; do{ oops = false; try{ mapper.updateByPrimaryKeySelective(record); } catch (DeadlockLoserDataAccessException dlEx){ oops = true; Thread.sleep((long) (Math.random() * 500)); } finally { } } while(oops == true && retries-- >0); }
我用的是mybatis,所以只需將mapper傳進(jìn)函數(shù),如果不用mybatis,需要本身創(chuàng)建并關(guān)閉數(shù)據(jù)庫(kù)連接.MYSQL應(yīng)用
延伸:數(shù)據(jù)庫(kù)死鎖MYSQL應(yīng)用
數(shù)據(jù)庫(kù)死鎖是事務(wù)性數(shù)據(jù)庫(kù) (如SQL Server, MySql等)經(jīng)常遇到的問(wèn)題.除非數(shù)據(jù)庫(kù)死鎖問(wèn)題頻繁出現(xiàn)導(dǎo)致用戶無(wú)法操作,一般情況下數(shù)據(jù)庫(kù)死鎖問(wèn)題不嚴(yán)重.在應(yīng)用程序中進(jìn)行try-catch就可以.那么數(shù)據(jù)死鎖是如何發(fā)生的呢?MYSQL應(yīng)用
InnoDB實(shí)現(xiàn)的是行鎖 (row level lock),分為共享鎖 (S) 和 互斥鎖 (X).MYSQL應(yīng)用
共享鎖用于事務(wù)read一行.
互斥鎖用于事務(wù)update或delete一行.
當(dāng)客戶A持有共享鎖S,并哀求互斥鎖X;同時(shí)客戶B持有互斥鎖X,并哀求共享鎖S.以上情況,會(huì)發(fā)生數(shù)據(jù)庫(kù)死鎖.如果還不夠清楚,請(qǐng)看下面的例子.MYSQL應(yīng)用
數(shù)據(jù)庫(kù)死鎖例子MYSQL應(yīng)用
首先,客戶A創(chuàng)立一個(gè)表T,并向T中插入一條數(shù)據(jù),客戶A開(kāi)始一個(gè)select事務(wù),所以拿著共享鎖S.MYSQL應(yīng)用
mysql> CREATE TABLE t (i INT) ENGINE = InnoDB; Query OK, 0 rows affected (1.07 sec) mysql> INSERT INTO t (i) VALUES(1); Query OK, 1 row affected (0.09 sec) mysql> START TRANSACTION; Query OK, 0 rows affected (0.00 sec) mysql> SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE; +------+ | i | +------+ | 1 | +------+
然后,客戶B開(kāi)始一個(gè)新事務(wù),新事務(wù)是delete表T中的唯一一條數(shù)據(jù).MYSQL應(yīng)用
mysql> START TRANSACTION; Query OK, 0 rows affected (0.00 sec) mysql> DELETE FROM t WHERE i = 1;
刪除操作需要互斥鎖 (X),但是互斥鎖X和共享鎖S是不能相容的.所以刪除事務(wù)被放到鎖哀求隊(duì)列中,客戶B阻塞.MYSQL應(yīng)用
最后,客戶A也想刪除表T中的那條數(shù)據(jù):MYSQL應(yīng)用
mysql> DELETE FROM t WHERE i = 1; ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
死鎖產(chǎn)生了!因?yàn)榭蛻鬉必要鎖X來(lái)刪除行,而客戶B拿著鎖X并正在等待客戶A釋放鎖S.看看客戶A,B的狀態(tài):MYSQL應(yīng)用
客戶A: 拿著鎖S,期待著客戶B釋放鎖X.
客戶B: 拿著鎖X,期待著客戶A釋放鎖S.
MYSQL應(yīng)用
發(fā)生死鎖后,InnoDB會(huì)為對(duì)一個(gè)客戶產(chǎn)生差錯(cuò)信息并釋放鎖.返回給客戶的信息:MYSQL應(yīng)用
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction
所以,另一個(gè)客戶可以正常執(zhí)行任務(wù).死鎖停止.MYSQL應(yīng)用
歡迎參與《Mysql實(shí)例InnoDB數(shù)據(jù)庫(kù)死鎖問(wèn)題處理》討論,分享您的想法,維易PHP學(xué)院為您提供專業(yè)教程。
轉(zhuǎn)載請(qǐng)注明本頁(yè)網(wǎng)址:
http://www.snjht.com/jiaocheng/13099.html