初學(xué)者從源碼理解MySQL死鎖問題
通過好多個(gè)深夜艱難的單步調(diào)試,終于找到了一個(gè)理想的斷點(diǎn),可以看到大部分獲取鎖的過程
代碼在lock0lock.c
的static enum db_err lock_rec_lock()
函數(shù)中,這個(gè)函數(shù)會顯示,獲取鎖的過程,以及獲取鎖成功與否。
場景1:通過主鍵進(jìn)行刪除
表結(jié)構(gòu)
CREATE TABLE `t1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=InnoDB; delete from t1 where id = 10;
可以看到,對索引 PRIMARY 加鎖,mode = 1027,1027是什么意思呢?1027 = LOCK_REC_NOT_GAP + LOCK_X(非 gap 的記錄鎖且是 X 鎖)
過程如下
結(jié)論:根據(jù)主鍵 id 去刪除數(shù)據(jù),且沒有其它索引的情況下,此 SQL 只需要在 id = 10 這條記錄上對主鍵索引加 X 鎖即可
場景2:通過唯一索引進(jìn)行刪除
表結(jié)構(gòu)做了微調(diào),增加了 name 的唯一索引
構(gòu)造數(shù)據(jù) CREATE TABLE `t2` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL DEFAULT '', PRIMARY KEY (`id`), UNIQUE KEY `uk_name` (`name`) ) ; INSERT INTO `t2` (`id`, `name`) VALUES (1,'M'), (2,'Y'), (3,'S'), (4,'Q'), (5,'L'); 測試sql語句 delete from t2 where name = "Y"
來看實(shí)際源碼調(diào)試的結(jié)果
第一步:
第二步:
結(jié)論:這個(gè)過程是先對唯一鍵 uk_name 加 X 鎖,然后再對聚簇索引(主鍵索引)加 X 鎖
過程如下
場景3:通過普通索引進(jìn)行刪除
構(gòu)造數(shù)據(jù) CREATE TABLE `t3` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL DEFAULT '', PRIMARY KEY (`id`), KEY `idx_name` (`name`) ); INSERT INTO `t3` (`id`, `name`) VALUES (1,'N'), (2,'G'), (3,'I'), (4,'N'), (5,'X'); 測試語句: delete from t3 where name = "N";
調(diào)試過程如圖:
結(jié)論:通過普通索引進(jìn)行更新時(shí),會對滿足條件的所有普通索引加 X 鎖,同時(shí)會對相關(guān)的主鍵索引加 X 鎖
過程如下
場景4:不走索引進(jìn)行刪除
CREATE TABLE `t4` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(10) NOT NULL DEFAULT '', PRIMARY KEY (`id`) ) INSERT INTO `t4` (`id`, `name`) VALUES (1,'M'), (2,'Y'), (3,'S'), (4,'Q'), (5,'L'); delete from t4 where name = "S";
總共有 5 把 X 鎖,剩下的 3 把就不一一放上來了
結(jié)論:不走索引進(jìn)行更新時(shí),sql 會走聚簇索引(主鍵索引)對全表進(jìn)行掃描,因此每條記錄,無論是否滿足條件,都會被加上X鎖。還沒完...
但是為了效率考量,MySQL做了優(yōu)化,對于不滿足條件的記錄,會在判斷后放鎖,最終持有的,是滿足條件的記錄上的鎖,但是不滿足條件的記錄上的加鎖/放鎖動(dòng)作不會省略。
過程如下
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
MySQL中的SHOW FULL PROCESSLIST命令實(shí)現(xiàn)
SHOW FULL PROCESSLIST命令是MySQL中一個(gè)非常有用的工具,可以幫助我們理解和監(jiān)控MySQL服務(wù)器的狀態(tài),本文主要介紹了MySQL中的SHOW FULL PROCESSLIST命令,感興趣的可以了解一下2023-11-11window10下mysql 8.0.20 安裝配置方法圖文教程
這篇文章主要為大家詳細(xì)介紹了window10下mysql 8.0.20 安裝配置方法圖文教程,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-05-05解決遠(yuǎn)程連接mysql很慢的方法(mysql_connect 打開連接慢)
有次同事提出開發(fā)使用的mysql數(shù)據(jù)庫連接很慢,因?yàn)槲覀兊膍ysql開發(fā)數(shù)據(jù)庫是單獨(dú)一臺機(jī)器部署的,所以認(rèn)為可能是網(wǎng)絡(luò)連接問題導(dǎo)致的。2011-07-07MySQL中列子查詢與行子查詢操作的學(xué)習(xí)教程
這篇文章主要介紹了MySQL中列子查詢與行子查詢操作的學(xué)習(xí)教程,子查詢是MySQL入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-12-12