鎖
事務的隔離性由鎖來實現
MySQL并發事務訪問相同記錄
并發事務訪問相同記錄的情況大致可以分為3種:
讀-讀的情況
讀-讀情況,即并發事務相繼讀取相同的記錄。讀取操作本身不會對記錄由有任何的影響,并不會引起什么問題,所以允許這種情況的發生。
寫-寫的情況
寫-寫情況,即并發事務相繼對相同的記錄做出改動。
讀-寫或寫-讀情況
讀-寫或寫-讀,即一個事務進行讀取操作,另一個進行改動操作,這種情況下產生臟讀、不可重復讀、幻讀的問題
怎么解決臟讀、不可重復讀、幻讀這些問題呢?其實有兩種可選的解決方案:
方案1:讀操作利用多版本并發控制(MVCC) ,寫操作利用加鎖
方案2:讀、寫操作都采用加鎖的方式
鎖的不同角度分類
從數據操作的類型劃分:讀鎖、寫鎖
從數據操作的粒度劃分:表級鎖、頁級鎖、行鎖
表級鎖
意向鎖
意向鎖要解決的問題
意向鎖的并發性
意向鎖不會與行級的共享/排他鎖互斥!正因為如此,意向鎖并不會影響到多個事務對不同數據行加排他鎖時的并發性(不然我們直接用普通的表鎖就行了)
自增鎖(AUTO-INC鎖)
元數據鎖
InnoDB中的行鎖
行鎖(Row Lock)也稱為記錄鎖,顧名思義,就是鎖住某一行(某條記錄Row)。需要注意的是,Mysql服務器并沒有實現行鎖機制,行級鎖只在存儲引擎層實現。
優點:鎖定力度小,發生鎖沖突概率低,可以實現的并發度高。
缺點:對于鎖的開銷比較大,加鎖會比較慢,容易出現死鎖。
InnoDB與MyISAM的最大不同有兩點:一是支持事務(TRANSACTION);二是采用行級鎖
記錄鎖(Record Locks)
間隙鎖(Gap Locks)
Mysql在Repeatable Read 隔離界別下是可以解決幻讀問題的,解決方案有兩種,可以采用MVCC方案解決,也可以采用加鎖方案解決。但是在使用加鎖方案解決時有個一大問題,就是事務在第一次執行讀取操作的時候,那些幻影記錄尚不存在,我們無法給這些幻影記錄 加上記錄鎖。InnoDB提出了一種稱之為Gap Locks的鎖,官方的類型名稱為:LOCK_GAP
id值為8的記錄加了gap鎖,意味著不允許別的事務在id值為8的記錄前邊的間隙插入新的記錄。
gap鎖的提出僅僅是為了防止插入幻影記錄而提出的,雖然有共享gap鎖和獨占gap鎖的說法,但是他們起到的作用是相同的。而且如果對一條記錄加了gap鎖(不論是共享gap鎖還是獨占gap鎖),并不會限制其他事務對這條記錄加記錄鎖或者繼續加gap鎖。
間隙鎖擴大了鎖住的范圍,可能會引起死鎖
臨鍵鎖(Next-Key Locks)
臨鍵鎖=記錄鎖+間隙鎖
插入意向鎖(Insert Intention Locks)
頁鎖
從對待鎖的態度劃分為:樂觀鎖、悲觀鎖
從對待鎖的態度來看鎖的話,可以將鎖分為樂觀鎖和悲觀鎖,從名字可以看出這兩種鎖是兩種看待數據并發的思維方式。需要注意的是,樂觀鎖和悲觀鎖并不是鎖,而是鎖的設計思想。
悲觀鎖(數據庫的鎖層面)
樂觀鎖(程序層面)
兩種鎖的適用場景
按照加鎖的方式劃分:顯式鎖、隱式鎖
隱式鎖
其他鎖之-全局鎖
其他鎖之死鎖
兩個事務都持有對方需要的鎖,并且在等待對方釋放,并且雙方都不會釋放自己的鎖
如何處理死鎖
方式1:等待,直到超時(innodb_lock_wait_timeout=50s)
方式2:使用死鎖檢測進行死鎖處理
鎖的內存結構
type_mode的信息
鎖監控
視頻鏈接:B站