在上篇中,咱們介紹了MySQL中的全局鎖和表鎖。git
今天,咱們專一於介紹一下行鎖,這個在平常開發和麪試中經常困擾咱們的問題。github
因爲全局鎖和表鎖對增刪改查的性能都會有較大影響,因此,咱們天然會想到,面試
只須要對有修改的行加鎖就好了,這就是行鎖。數據庫
在事務中,事務1更新了一行主鍵爲1的數據行,那麼,在這個事務釋放鎖以前,事務2是不能操做的。併發
另外,有一個不少人容易混淆的概念,就是行鎖何時釋放?高併發
搞清這個事情,須要瞭解什麼叫做 兩階段鎖。性能
什麼是兩階段鎖呢?舉個例子你就明白了。優化
若是你明白了兩階段鎖的含義,你就會知道,事務2的updat語句會阻塞,直到事務1提交之後才能繼續執行。日誌
因此,這裏再次強調一下,兩階段鎖的含義。
在 InnoDB 事務中,行鎖是在須要的時候才加上的,但並不是語句執行完了了就馬上釋放, 而是要等到事務結束時才釋放。
注意,除了update語句能加寫鎖外,另外,還有一種對select語句加寫鎖的方式,就是
當前讀:Select …. for update
2.1 什麼是幻讀
面試的時候,面試官常常會喜歡問數據庫的事務隔離級別。
你們要能回答出四種隔離級別,四種隔離級別的含義。
再多問一點,會問你什麼是髒讀,什麼是幻讀,哪一個隔離級別會解決什麼問題。
首先明確一下,什麼是幻讀?
一樣是一個事務,在事務中先後兩次查詢,出現了不一樣的結果。
不一樣之處在於,髒讀是針對update,也就是同一行的數據出現了不一致。
注意,幻讀出現的場景
第一:事務的隔離級別爲可重複讀,且是當前讀
第二:幻讀僅專指新插入的行,在範圍查詢中,後一次查詢出現了新的數據行。
2.2 怎麼解決幻讀
這些若是你都能答上,面試官可能會繼續追問,幻讀是怎麼產生的,又是怎麼被解決的。
即便咱們給全部update涉及的行都加上了行鎖,仍是沒法解決新插入的記錄,由於這些記錄本來不存在,天然沒法加上行鎖。
那怎麼辦呢?爲了解決這個問題,innodb只好引入新的鎖,間隙鎖(Gap Lock)。
「間隙鎖,鎖的是兩個值之間的空隙」。
舉個例子:
在四條記錄,ID=0,10,20,30中,會產生以下的五個間隙範圍
注意,行鎖的衝突是行與行之間的衝突,是行鎖與行鎖之間的。與間隙鎖衝突的是往「間隙中插入數據」這個操做,間隙鎖自己不會產生衝突。
間隙鎖和行鎖合稱爲next-key lock。
每一個next-key lock是前開後閉的。間隙鎖自己是前開後開的。
小tips
標準的事務隔離級別中,可重複讀只解決髒讀問題,沒法解決幻讀問題。可是在innodb中,用next-key lock解決了幻讀的問題。
3.1 兩階段鎖的優化應用
上面的基礎知識中,解釋了什麼是 兩階段鎖。
那麼,對咱們業務開發中有什麼借鑑意義呢?
既然咱們知道了,行鎖必須在整個事務徹底提交後纔會釋放,那麼,若是咱們的事物中須要鎖住多行,就要把最可能形成鎖衝突,或者是鎖住最多行的語句儘量地日後放。
舉個例子,小A在線上購買了商家B的一個產品,這個購買的動做能夠簡化爲3個操做:
1)小A的銀行帳戶餘額扣款x;
2)商家B的銀行帳戶餘額增長x;
3)添加一條交易記錄;
這裏,涉及到兩個update操做,和一個insert操做。爲了保證交易的原子性,將三個動做放在了一個事務中。
那怎麼安排三個語句的前後順序呢?若是不仔細考慮,那麼就多是隨意選個123或者213的順序了。
仔細想一想呢?
顯然,這裏最容易形成衝突的是步驟2),可能同時有多個用戶購買商家B的產品,而後須要給商家B的餘額作update操做。
另外,步驟3)是insert操做,最不容易出現鎖衝突。
因此,最好的步驟順序是3)-> 1) -> 2),將最容易產生衝突的操做放在最後執行,那麼會比2)->1) ->3)的順序,大大提升併發度。
3.2 間隙鎖的問題與優化
間隙鎖的引入也帶來了一些新的問題,好比:下降併發度,可能致使死鎖。
由於間隙鎖的引入,可能會致使一樣的語句鎖住了更大的範圍。
那怎麼辦呢?
注意,間隙鎖在可重複讀級別下才是有效的。
因此,只要咱們的業務不須要可重複讀的保證,咱們就能夠把隔離級別設置爲讀提交(也是阿里雲rds數據庫的默認隔離級別),就沒有間隙鎖了。
而後,爲了解決可能的數據和日誌不一致的問題,須要把binlog格式設置爲row。
讀提交級別 + binlog的row格式,也是通常公司數據庫的標準配置。
如今,你知道緣由了吧:)
參考:
丁奇《MySQL 實戰45講》
看到這裏了,原創不易,點個關注、點個贊吧,你最好看了~
知識碎片從新梳理,構建Java知識圖譜:https://github.com/saigu/JavaKnowledgeGraph(歷史文章查閱很是方便)
掃碼關注個人公衆號「阿丸筆記」,第一時間獲取最新更新。同時能夠免費獲取海量Java技術棧電子書、各個大廠面試題。