你們好, 我是公衆號:java小杰要加油,
今天來分享一個關於mysql的知識點—— mysql中的鎖
這個鎖結構中有兩個比較關鍵的信息(其實還有不少信息,後面再聊)java
Q: 能描述一下兩個事務併發修改同一條數據時,mysql這個鎖是怎麼避免髒寫的嗎?A :事務T1在更改這條數據前,就先內存中生成一把鎖與此數據相關聯(is_waiting爲false,表明沒有等待),而後咔咔一頓操做更改數據,這個時候,事務T2來了,發現此記錄已經有一把鎖與之相關聯了(就是T1那一把鎖),而後就開始等待(is_waiting爲true表明正在等待),事務T1更改完數據提交事務後,就會把此事務對應的所結構釋放掉,而後檢測一下還有沒有與此記錄相關聯的鎖,結果發現T2還在苦苦的等待,就把T2的鎖結構的(is_waiting爲false,表明沒有等待)而後把T2事務對應的線程喚醒,T2獲取鎖成功繼續執行,整體流程如上。mysql
在讀-寫 / 寫 -讀的狀況下會出現髒讀,不可重複讀,幻讀的現象,不一樣的隔離級別能夠避免不一樣的問題,具體相關內容能夠看小杰的這篇文章 京東面試官問我:「聊聊MySql事務,MVCC?」 面試
不過貼心的我仍是列出來了 注:√表明可能發生,×表明不可能發生sql
隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
讀未提交(read uncommitted RU) | √ | √ | √ |
讀提交(read committed RC) | × | √ | √ |
可重複讀(repeatable read RR) | × | × | √ |
串行化(serializable ) | × | × | × |
可是 RR在某些程度上避免了幻讀的發生併發
怎麼避免髒讀、不可重複讀、幻讀這些現象呢?其實有兩種方案mvc
- mvcc裏面最重要的莫過於ReadView了,它的存在保證了事務不能夠讀取到未提交的事務所做的更改,避免了髒讀。
- 在RC隔離級別下,每次select讀操做都會生成ReadView
- 在RR隔離級別下,只有第一次select讀操做纔會生成ReadView,以後的select讀操做都複用這一個ReadView
某些業務場景不容許讀取舊記錄的值,每次讀取都要讀取最新的值。
例如銀行取款事務中,先把餘額讀取出來,再對餘額進行操做。當這個事務在讀取餘額時,不容許其餘事務對此餘額進行訪問讀取,直到取款事務結束後才能夠訪問餘額。因此在讀數據的時候也要加鎖
當使用 讀寫都加鎖這個方案來避免併發事務 寫-寫、 讀-寫、 寫-讀時而產生的 髒讀, 不可重複讀, 幻讀現象時,那麼這個鎖它就要作到,讀讀時不相互影響,上面三種狀況時要相互阻塞,這時鎖也分了好幾類,咱們繼續往下看
他們之間兼容關係以下 √表明能夠兼容,×表明不可兼容jvm
兼容性 | S鎖 | X鎖 |
---|---|---|
S鎖 | √ | × |
X鎖 | × | × |
SELECT .. LOCK IN SHARE MODE # 對讀取的記錄添加S鎖 SELECT .. FOR UPDATE # 對讀取的記錄添加X鎖
前面提到的鎖都是針對記錄的,其實一個事務也能夠在表級進行加鎖(S鎖、X鎖)ui
但是怎麼可能無緣無故的就給表加鎖呢,難道沒什麼條件嗎?答案是確定有條件的spa
可是這個怎麼確保呢?難道要一行一行的遍歷表中的全部數據嗎?固然不是啦,聰明的大佬們想出了下面這兩把鎖線程
- 意向共享鎖(Intention Shared Lock):簡稱IS鎖,當事務準備在某記錄上加S鎖時,須要先在表級別加上一個IS鎖
- 意向獨佔鎖(Intention Exclusive Lock):簡稱IX鎖,當事務準備在某記錄上加X鎖時,須要先在表級別加上一個IX鎖
讓咱們來看下加上這兩把鎖以後的效果是什麼樣子的
而後 通過上面的操做以後
這幾種鎖的兼容性以下表
兼容性 | IS鎖(表級鎖) | S鎖 | IX鎖(表級鎖) | X鎖 |
---|---|---|---|---|
IS鎖(表級鎖) | √ | √ | √ | × |
S鎖 | √ | √ | × | × |
IX鎖(表級鎖) | √ | × | √ | × |
X鎖 | × | × | × | × |
- IS、IX鎖都是表級鎖,他們能夠共存。
- 他們的提出僅僅是爲了在以後加表級別的S鎖或者X鎖時能夠快速判斷表中的記錄是否被上鎖,避免用遍歷的方式來查看一行一行的去查看而已
若是被加鎖的記錄符合下面四條狀態的話,那麼這些記錄的鎖則會合到一個鎖結構中
而後咱們再來依此看下這個所結構每一個部分的信息都是什麼意思
表鎖/行鎖信息:行級鎖
* Page Number:記錄所在的頁號
n_bits = (1+(n_recs+LOCK_PAGE_BITMAP_MARGIN)/ 8)x 8
LOCK_PAGE_BITMAP_MARGIN是固定的值爲64,n_recs指當前界面一共有多少條記錄(包含僞記錄以及在垃圾鏈表中的記錄),
lock_mode(鎖模式):低4比特位表示
lock_type(鎖類型):第5~8比特位表示
rec_lock_type(行鎖的具體類型):其他的比特位表示
LOCK_WAIT(十進制的256):也就是當
事務T1 要給user表中的記錄加鎖,假設這些記錄存儲在表空間號爲20,頁號爲21的頁面上,T1給id=1的記錄加S型Record Lock鎖,假如當前頁面一共有5條記錄(3條用戶記錄和2條僞記錄)
過程:先給表加IS鎖,不過咱們如今不關心,只關心行級鎖,
具體生成的所結構以下圖所示