數(shù)據(jù)庫鎖(lock)

??看了兩本書,一本是《高性能MySQL》,一本是《MySQL技術(shù)內(nèi)幕——InnoDB存儲引擎》,感覺要不寫點什么,就白看了,本篇主要以MySQL的InnoDB為例,聊聊lock的相關(guān)東西

一、什么是lock

??鎖是數(shù)據(jù)庫系統(tǒng)區(qū)別于文件系統(tǒng)的一個關(guān)鍵性特征,鎖機制用于管理對共享資源的并發(fā)訪問,而lock主要是針對數(shù)據(jù)庫中的對象,如表、頁、行,并且一般lock的對象僅在事務(wù)commit或rollback后進行釋放。

??對于InnoDB可以通過如下命令來觀察鎖的情況

    select * from information_schema.INNODB_TRX; #查看事務(wù)情況

    select * from information_schema.INNODB_LOCKS; #查看鎖情況

    select * from information_schema.INNODB_LOCK_WAITS; #查看鎖等待情況

二、InnoDB中l(wèi)ock的類型

InnoDB存儲引擎實現(xiàn)了以下兩種標準的行級鎖

??共享鎖(S Lock):也叫讀鎖,故名思議在讀取的時候給數(shù)據(jù)對象加鎖

??排他鎖(X Lock):也叫寫鎖,為了避免并發(fā)寫出現(xiàn)不可預(yù)知的后果,在修改數(shù)據(jù)對象的時候給數(shù)據(jù)加鎖

??一個記錄(row),可以同時擁有多個S鎖,但是同時只能擁有一個X鎖,X鎖會阻塞其他線程對記錄的操作,需要注意的是S鎖和X鎖都是行鎖,兼容是指對同一記錄(row)鎖的兼容情況,下面有一個鎖的兼容表

鎖兼容示意圖

三、一致性非鎖定讀

??什么是一致性非鎖定讀和一致性鎖定讀,他們各有什么優(yōu)缺點,如何使用他們(顯示或者隱身使用),他們跟其他那些東西還有什么樣的關(guān)聯(lián),對其影響如何

??一致性非鎖定讀是指的是InnoDB存儲引擎通過多版本控制(MVCC)的技術(shù)來讀取行數(shù)據(jù),就算被讀取行正在執(zhí)行更新和刪除操作也不會被阻塞,相反地,InnoDB存儲引擎會去讀取行的一個快照數(shù)據(jù)。

??之所以叫做一致性非鎖定讀,是因為不需要等待訪問行上的X鎖的釋放。非鎖定讀極大的提高了數(shù)據(jù)庫的并發(fā)性能,在InnoDB存儲引擎中默認的就是以這種方式讀取,需要注意的是,不同的事務(wù)隔離級別下是否采用一致性非鎖定讀和快照數(shù)據(jù)的定義也都各不相同。

??在MySQL(其他的實現(xiàn)方式不一樣,比如PostgreSQL)的InnoDB中,僅在 READ COMMITTED 和 REPEATABLE READ下使用MVCC,所以也僅在這兩張隔離級別下才會使用一致性非鎖定讀。對于快照數(shù)據(jù)版本,在 READ COMMITTED 下總是讀取被鎖定行的最新的一份快照;而在 REPEATABLE READ 下總是讀取事務(wù)開始時的行數(shù)據(jù)版本(不會出現(xiàn)幻讀)

四、一致性鎖定讀

??有了上面一致性非鎖定讀的解釋,相信一致性鎖定讀就更好理解,簡單來說就是在讀取行的時候不在允許其他用戶對行進行修改和刪除,也叫做不允許加排它鎖

??在某些情況下,用戶需要顯示地對數(shù)據(jù)庫讀取操作進行加鎖以保證數(shù)據(jù)邏輯一致性,這時候就需要用到手動加鎖的情況,InnoDB提供了兩種讀取時手動加鎖的方法如下

    SELECT ... FOR UPDATE

    SELECT ... LOCK IN SHARE MODE

??兩個語句實現(xiàn)上是有一定區(qū)別的, FOR UPDATE 是對讀取的行加一個X鎖,而 LOCK IN SHARE MODE 對讀取行加一個S鎖。在使用的時候需要將語句放在事務(wù)中執(zhí)行,一旦離開事務(wù)鎖就會自動釋放,當然為了防止死鎖,時間長了數(shù)據(jù)庫也會自動釋放鎖

??這里需要注意的是,在使用了MVCC的事務(wù)隔離級別下即便是加了X鎖,其他用戶也是可以讀取數(shù)據(jù)的,只是讀取的是對應(yīng)快照數(shù)據(jù)。在 SERIALIZABLE 隔離級別下就可看到兩個語句的不同,F(xiàn)OR UPDATE 會阻塞其他用戶對行的讀取,而 LOCK IN SHARE MODE 卻不會。

五、鎖的算法

InnoDB存儲引擎有三種行鎖算法:

??Record Lock:單個行記錄上的鎖

??Gap Lock:間隙鎖,鎖定一個范圍,但不包含記錄本身

??Next-Key Lock:Gap Lock + Record Lock,鎖定一個范圍,并且鎖定記錄本身

??InnoDB對于行的查詢都使用了Next-Key Lock的算法,Record Lock比較好理解,Gap Lock要復(fù)雜點,因為InnoDB在索引、主鍵、事務(wù)隔離級別都會對其有一定的影響

1、條件查詢單列,非索引
??此時當我們通過for update顯示鎖定某一行的時候,其實根據(jù)Next-Key Lock算法會采用間隙鎖的方式,這時增加、刪除、修改其他行都會被阻塞,其鎖定的是(-∞,+∞)


單列無索引鎖定區(qū)間示意圖

2、條件查詢單列,非唯一索引
??同上,存儲引擎還是會使用Next-Key Lock的方式,不過這時鎖定的不在是(-∞,+∞),而是鎖定的我們指定行的前后區(qū)間,即(pre,x]和(x,next)。所以我們在操作pre和之前,以及next和之后的行都不會阻塞


單列非唯一索引鎖定區(qū)間示意圖

3、條件查詢單列,唯一索引
??InnoDB對于這種情況會有特殊的優(yōu)化,由于是唯一索引,所以沒必要在指定鎖定一行時使用間隙鎖,這時候會降級使用Record Lock,僅鎖住索引記錄本身,需要注意主鍵也是唯一索引
4、條件查詢多列,多索引
??這種情況其實就是取的一個并集,每個列對應(yīng)索引鎖定的區(qū)間合起來的并集
5、聯(lián)合索引的問題
??這個在書中有特別提到,當一個唯一索引是聯(lián)合索引時,但是查詢條件僅是其中部分列的話,還是會使用Next-Key Lock
6、顯示關(guān)閉使用Gap Lock
??可以通過修改事務(wù)隔離級別READ COMMITTED顯示關(guān)閉
??通設(shè)置參數(shù)innodb_locks_unsafe_for_binlog=1
7、Next-Key Locking 與幻象問題
??Mysql中默認事務(wù)隔離級別下,即REPEATABLE READ下,InnoDB存儲引擎采用Next-Key Locking機制就可以保證幻象問題,而不需要使用SERIALIZABLE隔離級別

五、阻塞、死鎖

阻塞

??因為不同鎖之間的兼容性關(guān)系,在有些時刻一個事務(wù)中的鎖需要等待另外一個事務(wù)中的鎖釋放它所占用的資源。這就是阻塞,阻塞并不是一件壞事情,其實是為了確保事務(wù)可以并發(fā)且正常的運行,在InnoDB存儲引擎中,有一些變量來控制等待的相關(guān)操作
??innodb_lock_wait_timeout:控制等待的時間(默認50秒)
??innodb_rollback_on_timeout:設(shè)定是否在等待超時時對進行中的事務(wù)進行回滾操作(默認是OFF,不回滾)

死鎖

??死鎖是指兩個或兩個以上的事務(wù)在執(zhí)行過程中,因爭奪鎖資源而造成的一種互相等待的現(xiàn)象

如何解決死鎖?
1、超時回滾
??當事務(wù)相互等待的時候,一個事務(wù)等待時間超過設(shè)置的閥值,就將其回滾,而另外的事務(wù)就能繼續(xù)的進行
??缺點也是顯而易見的,如果超時的事務(wù)所占權(quán)重比較大,如事務(wù)操作更新了很多行,占用了較多的undo log,這時顯得就不合適了,因為回滾的這個事務(wù)的時間相對另外的事務(wù)所占時間可能會很多
2、wait-for garph(等待圖)
??這是一種主動的死鎖檢查方式,InnoDB引擎也采用這種方式,在每個事務(wù)請求鎖并發(fā)生等待時都會判斷是否存在回路,若存在,通常來說InnoDB選擇回滾undo量最小的事務(wù),wait-for garph要求數(shù)據(jù)庫保存兩種信息,1、鎖的信息鏈表;2、事務(wù)等待鏈表。通過這樣的鏈表可以構(gòu)造出一張圖,而圖中存在回路就代表存在死鎖。

影響死鎖概率的因素
1、系統(tǒng)中事務(wù)的數(shù)量,越多發(fā)生死鎖概率越大
2、每個事務(wù)操作的數(shù)量,操作數(shù)量越多,概率越大
3、操作數(shù)據(jù)的集合,越小發(fā)生死鎖概率越大

六、基于鎖的并發(fā)思考

擴展閱讀
關(guān)于MySQL/InnoDB的加鎖規(guī)則擴展閱讀,作者分析的很透徹
http://hedengcheng.com/?p=771

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容