日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 运维知识 > 数据库 >内容正文

数据库

《MySQL——加锁规则(待补全,有些没看懂)》

發(fā)布時(shí)間:2023/12/1 数据库 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《MySQL——加锁规则(待补全,有些没看懂)》 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

catalog

    • 加鎖規(guī)則
    • 等值查詢間隙鎖
    • 非唯一索引等值鎖
    • 主鍵索引范圍鎖
    • 非唯一索引范圍鎖
    • 唯一索引范圍鎖 bug
    • 非唯一索引上存在"等值"的例子
    • limit語(yǔ)句加鎖
    • 關(guān)于死鎖

總結(jié)

1、查詢過程中訪問到的對(duì)象才會(huì)加鎖,而加鎖的基本單位是next-key lock(前開后閉);
2、等值查詢上MySQL的優(yōu)化:索引上的等值查詢,如果是唯一索引,next-key lock會(huì)退化為行鎖,如果不是唯一索引,需要訪問到第一個(gè)不滿足條件的值,此時(shí)next-key lock會(huì)退化為間隙鎖;
3、范圍查詢:無(wú)論是否是唯一索引,范圍查詢都需要訪問到不滿足條件的第一個(gè)值為止;

加鎖規(guī)則

默認(rèn)這里的隔離級(jí)別是可重復(fù)讀。
原則1:加鎖的基本單位是next-key lock。該鎖的區(qū)間是前開后閉
原則2:查找過程中訪問到的對(duì)象才會(huì)加鎖
優(yōu)化1:索引上的等值查詢,給唯一索引加鎖的時(shí)候,next-key lock退化為行鎖
優(yōu)化2:索引上的等值查詢,向右遍歷時(shí)且最后一個(gè)值不滿足等值條件的時(shí)候,next-key lock退化為間隙鎖
bug:唯一索引上的范圍查詢會(huì)訪問到不滿足條件的第一個(gè)值為止。

建表語(yǔ)句:

CREATE TABLE `t` (`id` int(11) NOT NULL,`c` int(11) DEFAULT NULL,`d` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY `c` (`c`) ) ENGINE=InnoDB;insert into t values(0,0,0),(5,5,5), (10,10,10),(15,15,15),(20,20,20),(25,25,25);

等值查詢間隙鎖

非唯一索引等值鎖

session A給索引c上c=5這一行加上讀鎖。

根據(jù)原則1,加鎖單位是next-key lock ,因此會(huì)給(0,5]加上next-key lock.

c是普通索引,因此訪問c=5后還需要向右遍歷,查到c=10才放棄。

根據(jù)原則2,訪問到的都要加鎖,因此要給(5,10]加上next-key lock;

同時(shí)符合優(yōu)化2:等值判斷,向右遍歷,最后一個(gè)值不滿足c=5,于是退化為間隙鎖(5,10);

(前面分析的(0, 5]間隙鎖還是存在的,合起來(lái)存在(0, 5]和(5, 10)兩個(gè)間隙鎖 )

根據(jù)原則2,只有訪問到的對(duì)象才會(huì)加鎖,這個(gè)查詢使用的是覆蓋索引,并不需要訪問主鍵索引,所以主鍵索引上沒有加任何鎖,所以session B的update語(yǔ)句可以執(zhí)行完成。

**訪問到的對(duì)象才會(huì)加鎖,這個(gè)“對(duì)象”指的是列,不是 記錄行。 補(bǔ)充一下: 加鎖,是加在索引上的。 列上,有索引,就加在索引上; 列上,沒有索引,就加在主鍵上; **

session C要插入(7,7,7)記錄,會(huì)被session A 的間隙鎖(5,10)鎖住。

lock in share mode 只鎖覆蓋索引,for update 會(huì)順便給主鍵索引上滿足條件的行加上行鎖。

總結(jié):

鎖是加在索引上的;

用lock in share mode 來(lái)給行加讀鎖避免數(shù)據(jù)被更新的話,就必須繞過覆蓋索引的優(yōu)化,在查詢字段中加入索引中不存在的字段。

如將session A的語(yǔ)句:

select id from t where c=5 lock in share mode;

修改為

select d from t where c = 5 lock in share mode;

數(shù)據(jù)行加讀鎖,如果查詢字段使用了覆蓋索引,訪問到的對(duì)象只有普通索引,并沒有訪問到主鍵索引,則不會(huì)鎖主鍵索引。如果沒有使用覆蓋索引,且當(dāng)前查詢是for update ,update 和 delete 都是當(dāng)前讀,則會(huì)回表查詢,訪問到主鍵索引,這樣主鍵索引也會(huì)加鎖。

主鍵索引范圍鎖

對(duì)于表t,有兩個(gè)查詢語(yǔ)句,這兩個(gè)語(yǔ)句加鎖范圍不同:

select * from t where id = 10 for update; select * from t where id >= 10 and id < 11 for update;

這兩句話邏輯上等價(jià),但是加鎖規(guī)則不一樣。

執(zhí)行流程:

1、找到第一個(gè)id=10的行,因此本該是next-key lock (5,10]。根據(jù)優(yōu)化1,主鍵id上的等值條件,退化成行鎖,只加id = 10這一行的行鎖

2、范圍查找繼續(xù)往后找,找到id=15這一行停下來(lái),因此需要加next-key lock (10,15].

所以,session A這時(shí)候鎖的范圍就是主鍵索引上,行鎖id = 10和next-key lock(10,15]。 因?yàn)槭欠秶樵?#xff0c;不是等值查詢,所以不會(huì)進(jìn)行優(yōu)化2; 所以會(huì)出現(xiàn)B C的block情況。

需要注意 首次session A 定位查找id=10的行時(shí)候,是當(dāng)作等值查詢來(lái)判斷的,而向右掃描到id=15的時(shí)候,用的是范圍查詢判斷。

--引用: 1. 先走主鍵id索引, 拿出id=10的那一行, (注意這里是等值查詢) 2. 再?gòu)膇d=10的那一行開始, 不斷地往右遍歷拿出每一行, 直到它的 id 不滿足 大于等于10, 小于11 這個(gè)條件后, 再停止 (注意這里就是范圍查詢) 根據(jù)一開始的Creae table/ insert values等語(yǔ)句(10后面就是15), 還有再根據(jù)加鎖規(guī)則(原則1, 原則2, 優(yōu)化1, 優(yōu)化2, bug5): 執(zhí)行步驟1時(shí), 因?yàn)槭堑戎挡樵?span id="ozvdkddzhkzd" class="token punctuation">, 主鍵索引又是唯一索引, 根據(jù)原則1, 原則2, 優(yōu)化1, 最終只加行鎖10; 執(zhí)行步驟2時(shí), 因?yàn)槭欠秶樵?span id="ozvdkddzhkzd" class="token punctuation">, 主鍵索引又是唯一索引, 根據(jù)原則1, 原則2, Bug5, 而不滿足條件的第一個(gè)值就是15, 所以最終要加鎖(10, 15]; 這一塊相對(duì)還是比較繁瑣的

非唯一索引范圍鎖

唯一索引范圍鎖 bug

非唯一索引上存在"等值"的例子

給表t插入一條新紀(jì)錄

insert into t values(30,10,30);

此時(shí)表里面就有了兩個(gè)c=10的行。 因?yàn)橹麈I是唯一的, 所以不存在完全相同的兩行 ,此時(shí)的索引c為:

兩個(gè)c=10,但是主鍵id不同(分別為10和30),因此這兩個(gè)c=10的記錄之間也是有間隙的。
這里使用delete語(yǔ)句來(lái)驗(yàn)證。delete原則和之前update原則一樣。

session A遍歷的時(shí)候,先訪問第一個(gè)c=10的記錄。根據(jù)原則1:這里加的是

(c = 5,id = 5) 到(c = 10,id = 10)這個(gè)next-key lock.

然后,session A向右查找,直到碰到(c=15,id=15)這一行,循環(huán)才結(jié)束。根據(jù)優(yōu)化2,這是一個(gè)等值查詢,向右查找到了不滿足條件的行,所以會(huì)退化成(c=10,id=10)到(c=15,id=15)的間隙鎖。

也就是說(shuō),這個(gè)delete語(yǔ)句在索引c上的加鎖范圍,如下:

注意(c=5,id=5)和(c=15,id=15)這兩行都沒有鎖。

limit語(yǔ)句加鎖

關(guān)于死鎖

next-key lock實(shí)際上是間隙鎖和行鎖加起來(lái)的結(jié)果。


分析流程:

1、session A啟動(dòng)事務(wù)執(zhí)行查詢語(yǔ)句加lock in share mode,在索引c上加了next-key lock(5,10]和間隙鎖(10,15);

2、session B的update語(yǔ)句在索引c上加next-key lock(5,10],進(jìn)入鎖等待;

3、然后session A要再插入(8,8,8)這一行,被session B的間隙鎖鎖住。由于出現(xiàn)了死鎖,InnoDB讓session B回滾。

我們認(rèn)為session B的加鎖還沒申請(qǐng)成功。

但是,其實(shí)session B的"加next-key lock(5,10]"操作實(shí)際上分成了兩步,先是加(5,10)的間隙鎖,加鎖成功;然后加c=10的行鎖,第二步才被鎖住。

也就是說(shuō)我們分析加鎖的具體步驟時(shí),需要分成間隙鎖和行鎖兩段來(lái)執(zhí)行。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的《MySQL——加锁规则(待补全,有些没看懂)》的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。