日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747


MySQL InnoDB存儲(chǔ)引擎:行鎖的3種算法

行鎖的三種算法

InnoDB存儲(chǔ)引擎有3種行鎖的算法,其分別是:

  • Record Lock:?jiǎn)蝹€(gè)行記錄上的范圍
  • Gap Lock:間隙鎖,鎖定一個(gè)范圍,但不包含記錄本身
  • Next-Key Lock:Gap Lock + Record Lock,鎖定一個(gè)范圍,并且鎖定記錄本身

Record Lock總是會(huì)鎖住索引記錄,如果InnoDB存儲(chǔ)引擎建立的時(shí)候沒有設(shè)置任何一個(gè)索引,這時(shí)InnoDB存儲(chǔ)引擎會(huì)使用隱式的主鍵來進(jìn)行鎖定。

Next-Key Lock是結(jié)合了Gap Lock和Record Lock的一種鎖定算法,在Next-Key Lock算法下,innodb對(duì)于行的查詢都是采用這種鎖定算法。例如一個(gè)索引有9,11,13,20這4個(gè)值,那么該索引可能被Next-Key Locking的范圍為(左開右閉 ):(- &,9](9,11](13,20](20,+ &)

采用Next-Key Lock的鎖定技術(shù)稱為Next-Key Locking。這種設(shè)計(jì)的目的是為了解決幻讀(Phantom Problem)。利用這種鎖定技術(shù),鎖定的不是單個(gè)值,而是一個(gè)范圍。

當(dāng)查詢的索引含有唯一屬性時(shí),innodb存儲(chǔ)引擎會(huì)對(duì)Next-Key Lock進(jìn)行優(yōu)化,將其降級(jí)為Record Lock,即鎖住索引記錄本身,而不再是范圍。對(duì)于唯一索引,其加上的是Record Lock,僅鎖住記錄本身。但也有特別情況,那就是唯一索引由多個(gè)列組成,而查詢僅是查找多個(gè)唯一索引列中的其中一個(gè),那么加鎖的情況依然是Next-key lock。

DROP TABLE
IF EXISTS t;

CREATE TABLE t (a INT PRIMARY KEY);
INSERT INTO t
VALUES
(1),
(2),
(5);

 

MySQL InnoDB存儲(chǔ)引擎:行鎖的3種算法

 

表t中共有1、2、5三個(gè)值。在上面的例子中,在會(huì)話A中首先對(duì)a=5進(jìn)行X鎖定。而由于a是主鍵且唯一,因此鎖定的僅是5這個(gè)值,而不是(2,5)這個(gè)范圍,這樣在會(huì)話B中插入值4而不會(huì)阻塞,可以立即插入并返回。即鎖定由Next-Key Lock算法降級(jí)為了Record Lock,從而提高應(yīng)用的并發(fā)性。正如前面所介紹的,Next-Key降級(jí)為Record Lock僅在查詢的列是唯一索引的情況下。若是輔助索引,則情況會(huì)完全不同。同樣,首先根據(jù)如下代碼創(chuàng)建測(cè)試表Z:

CREATE TABLE Z (
a INT,
b INT,
PRIMARY KEY (a),
KEY (b)
);

INSERT INTO Z
VALUES
(1, 1),
(3, 1),
(5, 3),
(7, 6),
(10, 8);

表Z的列b是輔助索引,若在會(huì)話A中執(zhí)行下面的SQL語句:

SELECT * FROM Z WHERE b=3 FOR UPDATE;

很明顯,這時(shí)SQL語句通過索引列b進(jìn)行查詢,因此其使用傳統(tǒng)的Next-Key Locking技術(shù)加鎖,并且由于有兩個(gè)索引,其需要分別進(jìn)行鎖定對(duì)于聚集索引,其僅對(duì)列a等于5的索引加上Record Lock。而對(duì)于輔助索引,其加上的是Next-Key Locking,鎖定的范圍是(1,3),特別需要注意的是,InnoDB存儲(chǔ)引擎會(huì)對(duì)輔助索引下一個(gè)鍵值加上gap lock,即還有一個(gè)輔助索引范圍為(3,6)的鎖。 因此,若在新會(huì)話B中運(yùn)行下面的SQL語句,都會(huì)被阻塞:

SELECT * FROM Z WHERE a=5 LOCK IN SHARE MODE;
INSERT INTO Z SELECT 4,2;
INSERT INTO Z SELECT 6,5;

第一個(gè)SQL語句不能執(zhí)行,因?yàn)樵跁?huì)話A中執(zhí)行的SQL語句已經(jīng)聚集索引中列a=5的值加上X鎖,因此執(zhí)行會(huì)被阻塞。第二個(gè)SQL語句,主鍵插入4,沒有問題,但是插入的輔助索引值2在鎖定的范圍(1,3)中因此執(zhí)行同樣會(huì)被阻塞。第三個(gè)SQL語句,插入的主鍵6沒有被鎖定,5也不在范圍(1,3)之間。但插入的值5在另一個(gè)鎖定范圍(3,6)中,故同樣需要等待。而下面的SQL語句,不會(huì)被阻塞,可以立即執(zhí)行:

INSERT INTO Z SELECT 8,6;
INSERT INTO Z SEELCT 2,0;
INSERT INTO Z SELECT 6,7;

從上面的例子中可以看到,Gap Lock的作用是為了阻止多個(gè)事務(wù)將記錄插入到同一個(gè)范圍內(nèi),而這會(huì)導(dǎo)致Phantom Problem問題的產(chǎn)生。 例如在上面的例子中,會(huì)話A中用戶已經(jīng)鎖定了b=3的記錄。若此時(shí)沒有Gap Lock鎖定(3,6),那么用戶可以插入索引b列為3的記錄,這會(huì)導(dǎo)致會(huì)話A中的用戶再次執(zhí)行同樣查詢時(shí)會(huì)返回不同的記錄,導(dǎo)致Phantom Problem問題的產(chǎn)生。

用戶可以通過以下兩種方式來顯式地關(guān)閉Gap Lock:

  • 將事務(wù)的隔離級(jí)別設(shè)置為READ COMMITTED
  • 將參數(shù)innodb_locks_unsafe_for_binlog設(shè)置為1

在上述的配置下,除了外鍵約束和唯一性檢查依然需要的Gap Lock,其余情況僅使用Record Lock進(jìn)行鎖定。但需要牢記的是,上述設(shè)置破壞了事務(wù)的隔離性,并且對(duì)于replication,可能會(huì)導(dǎo)致主從數(shù)據(jù)的不一致。此外,從性能上來看,READ COMMITTED也不會(huì)優(yōu)于默認(rèn)的事務(wù)隔離級(jí)別READ REPEATABLE。

在InnoDB存儲(chǔ)引擎中,對(duì)于INSERT的操作,其會(huì)檢查插入記錄的下一條記錄是否被鎖定,若已被鎖定,則不允許查詢。對(duì)于上面的例子,會(huì)話A已經(jīng)鎖定了表z中b=3的記錄,即已經(jīng)鎖定了(1,3)的范圍,這時(shí)若在其他會(huì)話中進(jìn)行如下的插入同樣會(huì)導(dǎo)致阻塞:

INSERT INTO Z SELECT 2,2;

因?yàn)樵谳o助索引列b上插入值為2的記錄時(shí),會(huì)監(jiān)測(cè)到下一個(gè)記錄3已經(jīng)被索引。而將插入修改為如下的值,可以立即執(zhí)行:

INSERT INTO Z SELECT 2,0;

最后再次提醒的是,對(duì)于唯一鍵值的鎖定,Next-Key Lock降級(jí)為Record Lock僅存在于查詢所有的唯一索引一列。若唯一索引由多個(gè)列組成,而查詢是查找多個(gè)唯一索引列中的其中一個(gè),那么查詢其實(shí)是range類型查詢,而不是point類型查詢故InnoDB存儲(chǔ)引擎依然使用Next-Key Lock進(jìn)行鎖定。

最后再次提醒的是,對(duì)于唯一鍵值的鎖定,Next-Key Lock降級(jí)為Record Lock僅存在于查詢所有的唯一索引一列。若唯一索引由多個(gè)列組成,而查詢是查找多個(gè)唯一索引列中的其中一個(gè),那么查詢其實(shí)是range類型查詢,而不是point類型查詢故InnoDB存儲(chǔ)引擎依然使用Next-Key Lock進(jìn)行鎖定。

解決 Phantom Problem

在默認(rèn)的事務(wù)隔離級(jí)別下,即REPEATABLE READ下,InnoDB存儲(chǔ)引擎采用Next-Key Locking機(jī)制來避免Phantom Problem (幻像問題)。這點(diǎn)可能不同于與其他的數(shù)據(jù)庫(kù),如Oracle數(shù)據(jù)庫(kù),因?yàn)槠淇赡苄枰赟ERIALIZABLE的事務(wù)隔離級(jí)別下才能解決 Phantom Problem。

Phantom Problem是指在同一事務(wù)下,連續(xù)執(zhí)行兩次同樣的SQL語句可能導(dǎo)致不同的結(jié)果,第二次的SQL語句可能會(huì)返回之前不存在的行。

下面將演示這個(gè)例子,使用前一小節(jié)所創(chuàng)建的表t。表t由1、2、5這三個(gè)值組成:

DROP TABLE
IF EXISTS t;

CREATE TABLE t (a INT PRIMARY KEY);
INSERT INTO t
VALUES
(1),
(2),
(5);

若這時(shí)事務(wù)T1執(zhí)行如下的SQL語句:

SELECT * FROM t WHERE a> 2 FOR UPDATE;

注意這時(shí)事務(wù)T1并沒有進(jìn)行提交操作,上述應(yīng)該返回5這個(gè)結(jié)果。若與此同時(shí),另一個(gè)事務(wù)T2插入了 4這個(gè)值,并且數(shù)據(jù)庫(kù)允許該操作,那么事務(wù)T1再次執(zhí)行上述SQL語句會(huì)得到結(jié)果4和5。這與第一次得到的結(jié)果不同,違反了事務(wù)的隔離性,即當(dāng)前事務(wù)能夠看到其他事務(wù)的結(jié)果。其過程如表6-13所示:

 

MySQL InnoDB存儲(chǔ)引擎:行鎖的3種算法

 

InnoDB存儲(chǔ)引擎采用Next-Key Locking的算法避免Phantom Problem。對(duì)于上述的SQL語句SELECT * FROM t WHERE a>2 FOR UPDATE,其鎖住的不是5這單個(gè)值,而是對(duì)(2, +〇〇)這個(gè)范圍加了 X鎖。因此任何對(duì)于這個(gè)范圍的插入都是不被允許的,從而避免 Phantom Problem。

InnoDB存儲(chǔ)引擎默認(rèn)的事務(wù)隔離級(jí)別是REPEATABLE READ,在該隔離級(jí)別下,其采用Next-Key Locking的方式來加鎖。而在事務(wù)隔離級(jí)別READ COMMITTED下,其僅采用Record Lock,因此在上述的示例中,會(huì)話A需要將事務(wù)的隔離級(jí)別設(shè)置為READ COMMITTED。

此外,用戶可以通過InnoDB存儲(chǔ)引擎的Next-Key Locking機(jī)制在應(yīng)用層面實(shí)現(xiàn)唯一性的檢查。 例如:

SELECT * FROM table WHERE col=xxx LOCK IN SHARE MODE;
If not found any row:
# unique for insert value
INSERT INTO table VALUES (...);

如果用戶通過索引査詢一個(gè)值,并對(duì)該行加上一個(gè)SLock,那么即使査詢的值不在,其鎖定的也是一個(gè)范圍,因此若沒有返回任何行,那么新插人的值一定是唯一的。也許有讀者會(huì)有疑問,如果在進(jìn)行第一步SELECT •••LOCK IN SHARE MODE操作時(shí),有多個(gè)事務(wù)并發(fā)操作,那么這種唯一性檢査機(jī)制是否存在問題。其實(shí)并不會(huì),因?yàn)檫@時(shí)會(huì)導(dǎo)致死鎖,只有一個(gè)事務(wù)的插人操作會(huì)成功,而其余的事務(wù)會(huì)拋出死鎖的錯(cuò)誤,如表6-14所示。

 

MySQL InnoDB存儲(chǔ)引擎:行鎖的3種算法

 


 

分享到:
標(biāo)簽:行鎖
用戶無頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定