国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 數(shù)據(jù)庫 > MySQL > 正文

InnoDB數(shù)據(jù)庫死鎖問題處理

2024-07-24 13:08:55
字體:
供稿:網(wǎng)友
本文給大家講解的是mysql數(shù)據(jù)庫InnoDB類型,在update表的時候出現(xiàn)死鎖現(xiàn)象的原因及解決辦法,有需要的小伙伴可以參考下。
 

場景描述

在update表的時候出現(xiàn)DeadlockLoserDataAccessException異常 (Deadlock found when trying to get lock; try restarting transaction...)。

問題分析

這個異常并不會影響用戶使用,因為數(shù)據(jù)庫遇到死鎖會自動回滾并重試。用戶的感覺就是操作稍有卡頓。但是監(jiān)控老是報異常,所以需要解決一下。

解決方法

在應(yīng)用程序中update的地方使用try-catch。

我自己封裝了一個函數(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傳進函數(shù),如果不用mybatis,需要自己創(chuàng)建并關(guān)閉數(shù)據(jù)庫連接。

延伸:數(shù)據(jù)庫死鎖

數(shù)據(jù)庫死鎖是事務(wù)性數(shù)據(jù)庫 (如SQL Server, MySql等)經(jīng)常遇到的問題。除非數(shù)據(jù)庫死鎖問題頻繁出現(xiàn)導(dǎo)致用戶無法操作,一般情況下數(shù)據(jù)庫死鎖問題不嚴(yán)重。在應(yīng)用程序中進行try-catch就可以。那么數(shù)據(jù)死鎖是如何產(chǎn)生的呢?

InnoDB實現(xiàn)的是行鎖 (row level lock),分為共享鎖 (S) 和 互斥鎖 (X)。

共享鎖用于事務(wù)read一行。
互斥鎖用于事務(wù)update或delete一行。
當(dāng)客戶A持有共享鎖S,并請求互斥鎖X;同時客戶B持有互斥鎖X,并請求共享鎖S。以上情況,會發(fā)生數(shù)據(jù)庫死鎖。如果還不夠清楚,請看下面的例子。

數(shù)據(jù)庫死鎖例子

首先,客戶A創(chuàng)建一個表T,并向T中插入一條數(shù)據(jù),客戶A開始一個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開始一個新事務(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ù)被放到鎖請求隊列中,客戶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)生了!因為客戶A需要鎖X來刪除行,而客戶B拿著鎖X并正在等待客戶A釋放鎖S。看看客戶A,B的狀態(tài):

客戶A: 拿著鎖S,等待著客戶B釋放鎖X。
客戶B: 拿著鎖X,等待著客戶A釋放鎖S。

發(fā)生死鎖后,InnoDB會為對一個客戶產(chǎn)生錯誤信息并釋放鎖。返回給客戶的信息:

ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction
所以,另一個客戶可以正常執(zhí)行任務(wù)。死鎖結(jié)束。



發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 大港区| 邹平县| 德钦县| 赣榆县| 邹城市| 梓潼县| 隆子县| 介休市| 崇左市| 宜川县| 吴堡县| 新野县| 赣州市| 梅河口市| 瑞昌市| 南宁市| 利辛县| 汽车| 苍溪县| 哈巴河县| 乡宁县| 大冶市| 邢台市| 汾阳市| 加查县| 秦安县| 台中县| 武邑县| 长海县| 云霄县| 漳平市| 昔阳县| 珠海市| 南丰县| 城固县| 禄劝| 永清县| 呼玛县| 杨浦区| 襄垣县| 娱乐|