全國(guó)咨詢(xún)/投訴熱線(xiàn):400-618-4000

首頁(yè)技術(shù)文章正文

看懂這篇文章-你就懂了數(shù)據(jù)庫(kù)死鎖產(chǎn)生的場(chǎng)景和解決方法

更新時(shí)間:2022-11-18 來(lái)源:黑馬程序員 瀏覽量:

  一、什么是死鎖

   加鎖(Locking)是數(shù)據(jù)庫(kù)在并發(fā)訪(fǎng)問(wèn)時(shí)保證數(shù)據(jù)一致性和完整性的主要機(jī)制。任何事務(wù)都需要獲得相應(yīng)對(duì)象上的鎖才能訪(fǎng)問(wèn)數(shù)據(jù),讀取數(shù)據(jù)的事務(wù)通常只需要獲得讀鎖(共享鎖),修改數(shù)據(jù)的事務(wù)需要獲得寫(xiě)鎖(排他鎖)。當(dāng)兩個(gè)事務(wù)互相之間需要等待對(duì)方釋放獲得的資源時(shí),如果系統(tǒng)不進(jìn)行干預(yù)則會(huì)一直等待下去,也就是進(jìn)入了死鎖(deadlock)狀態(tài)。

  二、死鎖產(chǎn)生的場(chǎng)景

       1.數(shù)據(jù)庫(kù)表準(zhǔn)備

  1.1. 創(chuàng)建數(shù)據(jù)庫(kù)表

#創(chuàng)建數(shù)據(jù)庫(kù)
create database chuanzhi;
#選擇數(shù)據(jù)庫(kù)
use chuanzhi;
#創(chuàng)建測(cè)試表
CREATE TABLE `tb_heima` (
  `id` INT NOT NULL,
  `username` VARCHAR(45) NULL,
  PRIMARY KEY (`id`)
);
#插入測(cè)試數(shù)據(jù)
INSERT INTO `tb_heima` (`id`, `username`) VALUES ('1', '傳智教育-教育行業(yè)A股IPO第一股');

  2.死鎖場(chǎng)景演示

  2.1. 打開(kāi)一個(gè)dos窗口

  - mysql -u賬號(hào) -p密碼,進(jìn)入mysql命令行輸入:

1668751410706_1.jpg

  - 開(kāi)啟一個(gè)事務(wù),mysql> begin;

1668751421998_2.jpg

  - 執(zhí)行更新語(yǔ)句,mysql> update tb_heima set username = 'heima' where id =1;

1668751440774_3.jpg

  注意:此時(shí)更新是成功的,但并未提交事務(wù)。

  2.2.再打開(kāi)一個(gè)dos窗口

  - 登錄mysql,開(kāi)啟另一個(gè)事務(wù)操作同上。

  - 再次執(zhí)行更新語(yǔ)句,mysql> update tb_heima set username = 'heima' where id =1;

1668751463719_4.jpg

  注意:此時(shí)第二個(gè)窗口處于等待中,需要等待第一個(gè)窗口釋放寫(xiě)鎖才能執(zhí)行成功。

  - 等待一段時(shí)候后,第二個(gè)窗口報(bào)錯(cuò)了

1668751477001_5.jpg

  注意:由于第一個(gè)窗口未提交事務(wù),導(dǎo)致第二個(gè)窗口在等待一段時(shí)候后,超過(guò)鎖定等待超時(shí)。

  三、解決死鎖問(wèn)題

  通過(guò)mysql客戶(hù)端工具連接,按照以下步驟執(zhí)行。

  - select from information_schema.innodb_lock_waits; 鎖等待的信息,可以看到堵塞和被堵塞者

1668751494057_6.jpg

  注意:超過(guò)鎖定等待超時(shí)后,此條記錄會(huì)消失,也就是說(shuō)正在阻塞的記錄在此表才能查看到。

  - select * from information_schema.innodb_trx; 查詢(xún)鎖事務(wù)狀態(tài)信息

1668751505559_7.jpg

  注意:查詢(xún)出死鎖后,得到trx_mysql_thread_id死鎖的id。

  - kill sessionId; 殺掉有問(wèn)題的session

kill 15;
kill 16;

  - 再次執(zhí)行select * from information_schema.innodb_trx; # 查詢(xún)鎖事務(wù)狀態(tài)信息

1668751519210_8.jpg

  注意:確認(rèn)此表是否存在鎖事務(wù)記錄,如果沒(méi)有則說(shuō)明死鎖問(wèn)題已經(jīng)解決。

  四、如何避免死鎖

       1.對(duì)于數(shù)據(jù)庫(kù)的多表操作時(shí),盡量按照相同的順序進(jìn)行處理,盡量避免同時(shí)鎖定兩個(gè)資源,如操作A和B兩張表時(shí),總是按先A后B的順序處理, 必須同時(shí)鎖定兩個(gè)資源時(shí),要保證在任何時(shí)刻都應(yīng)該按照相同的順序來(lái)鎖定資源。

  2. 所有的update和delete操作必須走唯一索引

  3. SQL語(yǔ)句中不要使用太復(fù)雜的關(guān)聯(lián)多表的查詢(xún);使用“執(zhí)行計(jì)劃”對(duì)SQL語(yǔ)句進(jìn)行分析,對(duì)于有全表掃描的SQL語(yǔ)句,建立相應(yīng)的索引進(jìn)行優(yōu)化。

  4. 把SELECT放在Update語(yǔ)句前

  5. 避免事務(wù)中的用戶(hù)等待交互

分享到:
在線(xiàn)咨詢(xún) 我要報(bào)名
和我們?cè)诰€(xiàn)交談!