国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術(shù)文章
文章詳情頁

Mysql技術(shù)內(nèi)幕之InnoDB鎖的深入講解

瀏覽:14日期:2023-10-07 15:48:55
前言

自7月份換工作以來,期間一直在學(xué)習(xí)MySQL的相關(guān)知識,聽了一些視頻課,但是一直好奇那些講師的知識是從哪里學(xué)習(xí)的。于是想著從書籍中找答案。畢竟一直

看視頻也不是辦法,不能形成自己的知識。于是想著看書汲取知識,看了幾本MySQL的相關(guān)書籍,包括《深入淺出Mysql》《高性能Mysql》《Mysql技術(shù)內(nèi)幕》,發(fā)現(xiàn)那些講

師講的內(nèi)容確實(shí)都在書上有出現(xiàn)過,于是確信看書才是正確的汲取知識方式。本片主要記錄了Mysql的鎖機(jī)制的學(xué)習(xí)。

1.什么是鎖

鎖是計(jì)算機(jī)協(xié)調(diào)多個進(jìn)程或線程并發(fā)訪問某一資源的機(jī)制。在數(shù)據(jù)庫中,除傳統(tǒng)的計(jì)算資源(如CPU、RAM、I/O等)的爭用以外,數(shù)據(jù)也是一種供許多用戶共享的資源。

如何保證數(shù)據(jù)并發(fā)訪問的一致性、有效性是所有數(shù)據(jù)庫必須解決的一個問題,鎖沖突也是影響數(shù)據(jù)庫并發(fā)訪問性能的一個重要因素。

相對其他數(shù)據(jù)庫而言,MySQL 的鎖機(jī)制比較簡單,其最顯著的特點(diǎn)是不同的存儲引擎支持不同的鎖機(jī)制。比如,MyISAM和MEMORY存儲引擎采用的是表級鎖(table-level

locking);BDB存儲引擎采用的是頁面鎖(page-levellocking),但也支持表級鎖;InnoDB存儲引擎既支持行級鎖(row-levellocking),也支持表級鎖,但默認(rèn)情況下是采用行級鎖。

MySQL這3種鎖的特性可大致歸納如下。

表級鎖:開銷小,加鎖快;不會出現(xiàn)死鎖;鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)度最低。 行級鎖:開銷大,加鎖慢;會出現(xiàn)死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。 頁面鎖:開銷和加鎖時間界于表鎖和行鎖之間;會出現(xiàn)死鎖;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般。

3種鎖的使用角度:

表級鎖更適合于以查詢?yōu)橹鳎挥猩倭堪此饕龡l件更新數(shù)據(jù)的應(yīng)用,如Web應(yīng)用; 行級鎖則更適合于有大量按索引條件并發(fā)更新少量不同數(shù)據(jù),同時又有并發(fā)查詢的應(yīng)用,如一些在線事務(wù)處理(OLTP)系統(tǒng)。 BDB的頁面鎖已經(jīng)被InnoDB取代,不做討論。2.InnoDB存儲引擎中的鎖2.1鎖的類型

InnoDB存儲引擎實(shí)現(xiàn)了如下兩種標(biāo)準(zhǔn)的行級鎖:

共享鎖(S Lock),允許事務(wù)讀一行數(shù)據(jù)。 排他鎖(X Lock),允許事務(wù)刪除或更新一行數(shù)據(jù)。

如果一個事務(wù)T1已經(jīng)獲得了行r的共享鎖,那么另外的事務(wù)T2可以立即獲得行r的共享鎖,因?yàn)樽x取沒有改變行r的數(shù)據(jù),稱這種情況

為鎖兼容(Lock Compatible)。但若有其他的事務(wù)T3想獲得行r的排他鎖,則其必須等待事務(wù)T1、T2釋放行r的共享鎖——這種情況稱為鎖不兼容。

X S X 不兼容 不兼容 S 不兼容 兼容

此外,InnoDB存儲引擎支持多粒度鎖定,這種鎖定允許事務(wù)在行級上鎖和表鎖上的鎖同時存在。為了支持在不同粒度上進(jìn)行加鎖操作,InnoDB存

儲引擎支持一種額外的鎖方式,稱之為意向鎖。意向鎖是將鎖定的對象分為多個層次,意向鎖意味著事務(wù)希望在更細(xì)粒度上進(jìn)行加鎖。 ​ InnoDB存

儲引擎支持意向鎖設(shè)計(jì)比較簡練,其意向鎖即為表級別的鎖。設(shè)計(jì)目的主要是為了在一個事務(wù)中揭示下一行將被請求的鎖類型。其支持兩種意向鎖:

意向共享鎖(IS Lock),事務(wù)想要獲得一張表中某幾行的共享鎖 意向排他鎖(IX Lock),事務(wù)想要獲得一張表中某幾行的排他鎖2.2 一致性非鎖定讀

一致性的非鎖定讀(consistant nonlocking read)是指InnoDB存儲引擎通過多版本控制(multi versioning)的方法來讀取當(dāng)前執(zhí)行時間數(shù)據(jù)庫中行的

數(shù)據(jù)。如果讀取的行正在執(zhí)行Delete或Update操作,這時讀取操作不會因此去等待行上鎖的釋放。相反地,InnoDB存儲引擎會去讀取行的一個快照

版本。如下如所示。

Mysql技術(shù)內(nèi)幕之InnoDB鎖的深入講解

上圖直觀地展現(xiàn)了InnoDB存儲引擎一致性的非鎖定讀。之所以稱為非鎖定讀,因?yàn)椴恍枰却L問的行上X鎖的釋放。快照數(shù)據(jù)是指該行的之前版本

的數(shù)據(jù),該實(shí)現(xiàn)是通過undo段來完成。而undo用來在事務(wù)中回滾數(shù)據(jù),因此快照數(shù)據(jù)本身是沒有額外的開銷。此外,讀取快照數(shù)據(jù)是不需要上鎖的,

因?yàn)闆]有事務(wù)需要對歷史的數(shù)據(jù)進(jìn)行修改操作。

通過上圖可以知道,快照數(shù)據(jù)其實(shí)就是當(dāng)前行數(shù)據(jù)之前的歷史版本,每行記錄可能有多個版本,一般稱這種技術(shù)為行多版本技術(shù)。由此帶來的并發(fā)控制,

稱之為多版本并發(fā)控制(Multi Version Concurrency Control, MVCC)。

在事務(wù)隔離級別READ COMMITTED和REPEATABLE READ下,InnoDB存儲引擎使用非鎖定的一致性讀。然而,對于快照數(shù)據(jù)的定義卻不相同。在READ

COMMITTED事務(wù)隔離級別下,對于快照數(shù)據(jù),非一致性讀總是讀取被鎖定行的最新一份快照數(shù)據(jù)。而在REPEATABLE READ事務(wù)隔離級別下,對于快照

數(shù)據(jù),非一致性讀總是讀取事務(wù)開始時的行數(shù)據(jù)版本。如下表所示示例:

時間 會話A 會話B 1 begin 2 select * from t_user where id = 1; 3 begin 4 update t_user set id = 10 where id = 1; 5 select * from t_user where id = 1; 6 commit; 7 select * from t_user where id = 1; 8 commit;

假設(shè)原本id = 1的記錄是存在的,大家可以按上表時間順序執(zhí)行對應(yīng)的會話,比較及驗(yàn)證2者的不同。

2.3 一致性鎖定讀

在默認(rèn)配置下,在事務(wù)的隔離級別為REPEATABLE READ模式下,InnoDB存儲引擎的select操作使用一致性非鎖定讀。但是在某些情況下,用戶需要顯示地

對數(shù)據(jù)庫讀取操作進(jìn)行加鎖以保證數(shù)據(jù)邏輯的一致性。而這要求數(shù)據(jù)庫支持加鎖語句,即使時對于select的只讀操作。InnoDB存儲引擎對于select語句支持兩

種一致性的鎖定讀(locking read)操作:

select ··· for update select ··· lock in share mode

select ··· for update對讀取的行記錄加一個X鎖,其他事務(wù)不能對已鎖定的行加上任何鎖。select ··· lock in share mode對讀取的行記錄加一個S鎖,其他事務(wù)可

以向被鎖定的行加S鎖,但是如果加X鎖,則會被阻塞。

對于一致性非鎖定讀,即使讀取的行已被執(zhí)行了select ··· for update,也是可以進(jìn)行讀取的。此外,select ··· for update或者select ··· lock in share mode必須在

一個事務(wù)中,當(dāng)事務(wù)提交了,鎖也就釋放了。因此在使用上述兩種select鎖定語句時,務(wù)必加上begin,start transaction或者set autocommit=0。

3 鎖的算法3.1行鎖的3中算法

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

Record Lock:單個行記錄上的鎖 Gap Lock:間隙鎖,鎖定一個范圍,但不包含記錄本身 Next-Key Lock:Gap Lock + Record Lock,鎖定一個范圍,并且鎖定記錄本身

Record Lock總是會去鎖住主鍵索引記錄,如果InnoDB存儲引擎表在建立的時候沒有設(shè)置任何一個主鍵或唯一非空索引,那么這時InnoDB存儲引擎會使用隱式的

主鍵來進(jìn)行鎖定。

Next-Key Lock是結(jié)合了Gap Lock+Record Lock的一種鎖定算法,在Next-Key Lock算法下,InnoDB對于行的查詢都是采用這種鎖定算法。假如一個索引有10,11

,13和20這4個值,那么該索引可能被Next-Key Locking的區(qū)間為:

(-無窮,10] ,(10,11], (11,13], (13,20], (20,+無窮)

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

當(dāng)查詢的索引含有唯一屬性時,InnoDB存儲引擎會對Next-Key Lock進(jìn)行優(yōu)化將其降級為Record Lock,即僅鎖住索引本身,而不是范圍。下面演示一個例子。

mysql> create table t (a int primary key);Query OK, 0 rows affected (0.01 sec)​mysql> insert into t select 1;Query OK, 1 row affected (0.00 sec)Records: 1 Duplicates: 0 Warnings: 0​mysql> insert into t select 2;Query OK, 1 row affected (0.00 sec)Records: 1 Duplicates: 0 Warnings: 0​mysql> insert into t select 5;Query OK, 1 row affected (0.01 sec)Records: 1 Duplicates: 0 Warnings: 0

接著按下表時間順序執(zhí)行操作。

時間 會話A 會話B 1 begin; 2 select * from t where a = 5 for update; 3 begin; 4 insert into t select 4; 5 commit; #成功,不需要等待 6 commit;

表t共有1,2,5三個值。在上面的例子中,在會話A中首先對a=5進(jìn)行X鎖定。而由于a是主鍵且唯一,因此鎖定的僅是5這個值,而不是(2,5)這個范圍,這樣在會話

B中插入值4而不會阻塞,可以立即插入并返回。即鎖定由Next-Key Lock算法降級為了Record Lock,從而提高應(yīng)用的并發(fā)性。

如上,Next-Key Lock降級為Record Lock僅在查詢的列是唯一索引的情況下。若是輔助索引,則情況會完全不同。同樣,首先創(chuàng)建測試表z進(jìn)行測試:

mysql> create table z (a int ,b int ,primary key(a), key(b));mysql> insert into z select 1,1;mysql> insert into z select 3,1;mysql> insert into z select 5,3;mysql> insert into z select 7,6;mysql> insert into z select 10,8;

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

mysql> select * from z where b = 3 for update;

很明顯,這時SQL語句通過索引列b進(jìn)行查詢,因此其使用傳統(tǒng)的Next-Key Locking技術(shù)加鎖,并且由于有兩個索引,其需要分別進(jìn)行鎖定。對于聚集索引,其僅對列

a等于5的索引加上Record Lock。而對于輔助索引,其加上的是Next-Key Lock,鎖定的范圍是(1,3),特別需要注意的是,InnoDB存儲引擎還會對輔助索引下一個

鍵值加上gap lock,即還有一個輔助索引范圍為(3,6)的鎖。因此,若在新會話B中運(yùn)行下面的SQL語句,都會被阻塞:

mysql> select * from z where a = 5 lock in share mode;mysql> insert into z select 4,2;mysql> insert into z select 6,5;

第一個SQL語句不能執(zhí)行,因?yàn)樵跁扐中執(zhí)行的SQL語句已經(jīng)對聚集索引中列a=5的值加上X鎖,因此執(zhí)行會被阻塞。第二個SQL語句,主鍵插入4,沒有問題,但是插入

的輔助索引值2在鎖定的范圍(1,3)中,因此執(zhí)行同樣會被阻塞。第三個SQL語句,插入的主鍵6沒有被鎖定,5也不在范圍(1,3)之間。但插入的值5在另一個鎖定的

范圍(3,6)中,故同樣需要等待。而下面的SQL語句,不會被阻塞,可以立即執(zhí)行:

mysql> insert into z select 8,6;mysql> insert into z select 2,0;mysql> insert into z select 6,7;

從上面的例子可以看到,Gap Lock的作用是為了阻止多個事務(wù)將記錄插入到同一個范圍內(nèi),而這會導(dǎo)致幻讀問題的產(chǎn)生。假如在上面的例子中,會話A中用戶已經(jīng)鎖定了

b=3的記錄。若此時沒有Gap Lock鎖定(3,6),那么用戶可以插入索引b列為3的記錄,這會導(dǎo)致會話A中的用戶再次執(zhí)行同樣查詢時會返回不同的記錄,即幻讀。

這里主要探究的是InnoDB存儲引擎鎖表的機(jī)制,至少自己明白了Mysql的行鎖機(jī)制,不知道讀者是否有疑問,歡迎留言。下次會記錄關(guān)于Mysql事務(wù)特性及其內(nèi)部的實(shí)現(xiàn)機(jī)制,

包括mysql的內(nèi)部架構(gòu),InnoDB buffer Pool,redo log, undo log等具體的詳解,目前只是對知識過了一遍,但還未總結(jié)。

總結(jié)

到此這篇關(guān)于Mysql技術(shù)內(nèi)幕之InnoDB鎖的文章就介紹到這了,更多相關(guān)Mysql InnoDB鎖內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: MySQL 數(shù)據(jù)庫
相關(guān)文章:
主站蜘蛛池模板: 中文字幕高清在线天堂网 | 日韩一级视频在线观看播放 | 国产天堂在线一区二区三区 | 99久久国产综合精品2020 | 亚洲国产精品日韩在线观看 | 视频在线一区二区 | 日本aaaa级毛片在线看 | 久久精品一| 欧美国产日本高清不卡 | 国产性自拍 | 午夜欧美日韩在线视频播放 | 午夜影院免费入口 | 久久福利网站 | a级毛片毛片免费观看永久 a级毛片毛片免费很很综合 | 最新国产午夜精品视频不卡 | 美女拍拍拍爽爽爽爽爽爽 | 久久久久综合给合狠狠狠 | 久久国产一区二区 | 国产精品分类视频分类一区 | 国产精品久久毛片 | 欧美高清一区 | 国产婷婷一区二区三区 | 国产乱码精品一区二区三区四川人 | 国产成人精品久久综合 | 国产精品一区久久精品 | 亚洲 欧美 手机 在线观看 | 日韩aⅴ在线观看 | 国产大尺度福利视频在线观看 | 欧美亚洲激情视频 | 在线播放另类 | 欧美成人怡红院在线观看 | 国产精品免费观看视频 | 可以免费观看欧美一级毛片 | 爆操巨乳美女 | 91原创视频在线观看 | 亚洲国产日韩在线 | 九九精品激情在线视频 | 日本wwww视频| 亚洲另类激情综合偷自拍 | 欧美日韩在线视频免费完整 | 91视频一区 |