mysql 事務,鎖,隔離機制

Nooooone發表於2021-06-27

mysql架構

  • 為了解併發問題,引入鎖,mysql中鎖分為讀鎖和寫鎖,即share lock和exclusive lock。故名思義,share lock之間不互斥,share lock和exclusive lock之間互斥,exclusive lock之間互斥。mysql 提供行鎖row lock和表鎖 table lock的multiple granularity locking。對於表鎖,mysql提供一種意圖鎖的機制,意圖鎖也是分為兩種,intention share lock和intention exclusive lock。對於intention lock
    • Before a transaction can acquire a shared lock on a row in a table, it must first acquire an IS lock or stronger on the table.
    • Before a transaction can acquire an exclusive lock on a row in a table, it must first acquire an IX lock on the table.
    • Intention locks do not block anything except full table requests (for example, LOCK TABLES ... WRITE). The main purpose of intention locks is to show that someone is locking a row, or going to lock a row in the table
    • intention lock之間並不互斥,intention lock只是告訴你有人對錶中的某些行在上鎖。
  • mysql row lock是在儲存引擎層實現的,不同的儲存引擎可能有不同的實現方式

事務

  • 事務是指一批操作,要麼全部成功,要麼全部失敗。
  • 資料庫事務的ACID特性
    • atomicity原子性:即一個事務已一個原子的操作執行,是一個不可分隔的最小單元,事務中的操作,要麼全部執行成功,要麼全部失敗。
    • consistency 一致性:資料庫總是從一個一致的狀態轉移到另一個一致的狀態
    • isolation: 隔離性:一個事務中的修改,在什麼時候對另一個事務可見
    • durability: 永續性: 提交的事務不會丟失
  • 隔離級別
  • 隔離級別是對不同的事務而言的。
    • read uncommitted:一個事務中未提交的修改也對另外的事務可見,在這裡隔離級別下,會出現髒讀,即事務1未提交的修改可能被別的事務可見。
    • read committed: 一個事務提交commit後的修改才對另一個事務可見。但是可能會出現不可重複讀的問題,即在一個事務1中,連續select兩次,得到的結果不同,因為在這中間,可能記錄被別的事務修改了。
    • repeatable read:一個事務中,多次select的結果總是相同的,但可能出現幻讀的情況,即雖然對於同一行的結果,始終是相同的,但可能別的事務在insert別的行,導致一個事務中間看到的記錄是不同的。
    • serializable:事務序列執行。
  • 怎麼解決不可重複讀問題?在一個事務開始時,對涉及到的row加上行鎖即可以保證另一個事務無法修改這一行。但是這解不了幻讀的問題,因為別的事務可能insert的是別的行。這時候,需要引入gap lock。不僅鎖這一個row,還鎖這個row的前後間隙。具體怎麼鎖,根據查詢條件是走唯一索引還是非唯一索引,是走等值匹配還是範圍匹配有不同的gap lock lock的範圍,但一個原則就是:保證你這個語句的查詢範圍內的資料不會被其他事務insert進去。
  • 事務的兩段鎖:
    • 在事務的執行過程中,隨時可以進行鎖定,但只有事務執行完畢commit或者rollBack的時候,才會釋放鎖。

MVCC 多版本併發控制

  • 前面說鎖分為讀鎖和寫鎖,這是一種悲觀鎖,MVCC是一種樂觀鎖,通過版本號控制,讀副本的方式,來使得select讀不用加鎖,每次都讀副本,同時保證讀到的都是事務開始之前寫入的資料。因為大多數資料庫操作都是讀多寫少的,通過MVCC,讀操作不用加鎖,減少了鎖衝突的概率,提高吞吐。select和事務又有啥關係呢?對於mysql,預設是auto-commit模式,如果不顯示的開啟一個事務,每個查詢都被當作一個事務來執行。
  • mvcc怎麼實現的
    • 每條記錄後面增加兩個version,建立version和刪除version。
    • 對於select語句,只篩選那些建立version小於等於事務version(保證查詢到的記錄在當前事務開始之前就已經存在了),且刪除version在當前version之後的(保證記錄在當前事務開始的時候,未被刪除)
    • insert 語句:插入新一行,建立version等於當前事務version
    • update語句:新插入一行,建立version等於當前事務version,之前行的刪除version設定為當前事務version
    • delete語句: 當前行的刪除version設定為當前事務version。

快照讀和當前讀

  • select語句讀的是快照,通過讀快照,在RR級別也不會有幻讀,對於select for update這種當前讀,通過next-key lock解決幻讀問題。

refer

相關文章