InnoDB數(shù)據(jù)庫(kù)死鎖問(wèn)題處理
場(chǎng)景描述
在update表的時(shí)候出現(xiàn)DeadlockLoserDataAccessException異常 (Deadlock found when trying to get lock; try restarting transaction...)。
問(wèn)題分析
這個(gè)異常并不會(huì)影響用戶使用,因?yàn)閿?shù)據(jù)庫(kù)遇到死鎖會(huì)自動(dòng)回滾并重試。用戶的感覺(jué)就是操作稍有卡頓。但是監(jiān)控老是報(bào)異常,所以需要解決一下。
解決方法
在應(yīng)用程序中update的地方使用try-catch。
我自己封裝了一個(gè)函數(shù),如下。
/** * 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ù)連接。
延伸:數(shù)據(jù)庫(kù)死鎖
數(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ù)死鎖是如何產(chǎn)生的呢?
InnoDB實(shí)現(xiàn)的是行鎖 (row level lock),分為共享鎖 (S) 和 互斥鎖 (X)。
共享鎖用于事務(wù)read一行。
互斥鎖用于事務(wù)update或delete一行。
當(dāng)客戶A持有共享鎖S,并請(qǐng)求互斥鎖X;同時(shí)客戶B持有互斥鎖X,并請(qǐng)求共享鎖S。以上情況,會(huì)發(fā)生數(shù)據(jù)庫(kù)死鎖。如果還不夠清楚,請(qǐng)看下面的例子。
數(shù)據(jù)庫(kù)死鎖例子
首先,客戶A創(chuàng)建一個(gè)表T,并向T中插入一條數(shù)據(jù),客戶A開(kāi)始一個(gè)select事務(wù),所以拿著共享鎖S。
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> START TRANSACTION; Query OK, 0 rows affected (0.00 sec) mysql> DELETE FROM t WHERE i = 1;
刪除操作需要互斥鎖 (X),但是互斥鎖X和共享鎖S是不能相容的。所以刪除事務(wù)被放到鎖請(qǐng)求隊(duì)列中,客戶B阻塞。
最后,客戶A也想刪除表T中的那條數(shù)據(jù):
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??纯纯蛻鬉,B的狀態(tài):
客戶A: 拿著鎖S,等待著客戶B釋放鎖X。
客戶B: 拿著鎖X,等待著客戶A釋放鎖S。
發(fā)生死鎖后,InnoDB會(huì)為對(duì)一個(gè)客戶產(chǎn)生錯(cuò)誤信息并釋放鎖。返回給客戶的信息:
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction
所以,另一個(gè)客戶可以正常執(zhí)行任務(wù)。死鎖結(jié)束。
- mysql 數(shù)據(jù)庫(kù)死鎖原因及解決辦法
- Mysql 數(shù)據(jù)庫(kù)死鎖過(guò)程分析(select for update)
- 簡(jiǎn)單說(shuō)明Oracle數(shù)據(jù)庫(kù)中對(duì)死鎖的查詢及解決方法
- Mybatis update數(shù)據(jù)庫(kù)死鎖之獲取數(shù)據(jù)庫(kù)連接池等待
- MySQL數(shù)據(jù)庫(kù)的一次死鎖實(shí)例分析
- 講解Oracle數(shù)據(jù)庫(kù)中結(jié)束死鎖進(jìn)程的一般方法
- 記一次公司倉(cāng)庫(kù)數(shù)據(jù)庫(kù)服務(wù)器死鎖過(guò)程及解決辦法
- 查詢Sqlserver數(shù)據(jù)庫(kù)死鎖的一個(gè)存儲(chǔ)過(guò)程分享
- MySQL數(shù)據(jù)庫(kù)之Purge死鎖問(wèn)題解析
- 5分鐘快速了解數(shù)據(jù)庫(kù)死鎖產(chǎn)生的場(chǎng)景和解決方法
相關(guān)文章
關(guān)于MySQL數(shù)據(jù)庫(kù)死鎖的案例和解決方案
MySQL Update語(yǔ)句防止死鎖是指在修改MySQL數(shù)據(jù)庫(kù)的數(shù)據(jù)時(shí),為避免多個(gè)進(jìn)程同時(shí)修改同一數(shù)據(jù)行而造成死鎖的情況,引入了一些機(jī)制來(lái)防止死鎖的產(chǎn)生,本文介紹了一個(gè) MySQL 數(shù)據(jù)庫(kù)死鎖的案例和解決方案,需要的朋友可以參考下2023-09-09MySQL實(shí)現(xiàn)簡(jiǎn)單的創(chuàng)建庫(kù)和創(chuàng)建表操作方法
MySQL是最常用的數(shù)據(jù)庫(kù),在數(shù)據(jù)庫(kù)操作中基本都是增刪改查操作,簡(jiǎn)稱CRUD,這篇文章主要給大家介紹了關(guān)于MySQL實(shí)現(xiàn)簡(jiǎn)單的創(chuàng)建庫(kù)和創(chuàng)建表操作方法的相關(guān)資料,需要的朋友可以參考下2023-11-11mysql數(shù)據(jù)庫(kù)優(yōu)化需要遵守的原則
這是我在網(wǎng)上看到的一篇不錯(cuò)的mysql數(shù)據(jù)庫(kù)優(yōu)化文章,拿出來(lái)和大家分享,希望可以幫助你們2012-12-12linux系統(tǒng)中mysql數(shù)據(jù)庫(kù)的導(dǎo)入和導(dǎo)出
本文給大家簡(jiǎn)單記錄了一下在linux系統(tǒng)中mysql數(shù)據(jù)庫(kù)的導(dǎo)入和導(dǎo)出的方法,有相同需求的小伙伴可以參考下2016-02-02解決mysql報(bào)錯(cuò)ERROR 1049 (42000): Unknown dat
對(duì)于錯(cuò)誤代碼1049(42000):Unknown database ‘?dāng)?shù)據(jù)庫(kù)‘,這個(gè)錯(cuò)誤通常表示您正在嘗試訪問(wèn)一個(gè)不存在的數(shù)據(jù)庫(kù),本文給出了解決方法,您可以按照文中步驟進(jìn)行操作,需要的朋友可以參考下2024-01-01MySQL中CONCAT和GROUP_CONCAT方法的區(qū)別詳解
本文主要介紹了MySQL中CONCAT和GROUP_CONCAT方法的區(qū)別詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01