在MySQL中,我們使用到了它的各種類鎖;按照它的維度,有各種鎖
- 從數據庫的操作粒度有,表鎖,行鎖。
- 從數據庫的操作的類型,有讀鎖和寫鎖。
- 性能上有樂觀鎖和悲觀鎖。
在上一篇文章中的事務隔離級別,需要解決的是不可重復讀和幻讀問題,所以在遍歷掃描聚集索引記錄時,為了防止掃描過的索引被其他事務修改,從而導致數據不一致。這里引用了間隙鎖
間隙鎖(Gap Lock)
鎖的是這兩個值直接的間隙,間隙鎖的在可重復讀隔離級別下才會生效。
MVCC(Multi-Version Concurrency Control)
隔離性就是靠MVCC機制來保證的,對一行數據的讀和寫兩個操作默認是不會通過加鎖互斥來保證隔離性,避免了頻繁加鎖互斥。
MySQL在可重復讀和讀已提交的隔離級別實現了MVCC機制。
undo日志版本鏈與read view機制
undo日志版本是指一行數據被多個事務依次修改后,每個事務修改完成后,MySQL會保留修改前的數據undo回滾日志,并用2個隱藏日志trx_id和roll_pointer把這些undo日志串聯起來形成一個歷史版本記錄鏈。
在可重復讀隔離級別,當事務開啟,執行任何查詢sql時會生成當前失誤的一致性視圖read-view,該視圖在事務結束之前永遠都不會變化;
這個視圖由執行查詢時所有未提交事務id數組(數組最小的id為min_id)和已創建的最大事務id(max_id)組成,事務里的任何sql查詢結果需要從對應版本鏈里的最新數據逐條跟read_view做對比從而得到最終的快照結果。
版本鏈對比規則:
1.如果row的trx_id落在最小min_id部分(trx_id < min_id),表示這個版本是已提交的事務生成的,這個數據是可見的。
2.如果row的trx_id落在最大部分(trx_id > max_id),表示這個版本是將來期待的事務生成的,是不可見的。
3.如果row的trx_id落在了之間(min_id <= trx_id <= max_id),那么就有2種情況
a.若trx_id在視圖數組中,標識這個版本是由還沒提交的事務生成的,不可見。
b.若trx_id不在視圖數組中,表示這個版本是已經提交了的事務生成的,可見。
事務隔離級別為 讀已提交的,每次執行sql都會重新生成read-view,故不會出現上述問題。
RR級別中,select1的事務中,查詢的結果為500,雖然事務100進行了更新數據,再次進行select1的事務時,由于屬于上述版本中的版本鏈對比,commite結果也不可見,故而第二次查詢的結果依舊為500.
而select 2開始查詢的時候,由于已經commite,故而查詢結果為1000.
如果是RC隔離級別的話,每次的read view會進行變化,兩次查詢會為 500和1000