本節內容就來聊聊這個話題,首先從快照讀開始:
1.1 定義
普通讀(也稱快照讀,英文名:consistent read),就是單純的 select 語句,不包括下面這兩類語句:
select ... for updateselect ... lock in share mode
普通讀的執行方式是生成 readview,直接利用 mvcc 機制來進行讀取,並不會對記錄進行加鎖。
小貼士對於 serializable 隔離級別來說,如果 autocommit 系統變數被設定為off,那普通讀的語句會轉變為鎖定讀,和在普通的 select 語句後邊加 lock in share mode 達成的效果一樣。1.2 實現方式
普通讀是通過 undo log + mvcc 來實現的,具體我們再仔細聊聊:
下圖右側黃色部分是資料:一行資料記錄,主鍵 id 是 10,object = 'goland' ,被 update 更新為 object = 'python' 。
事務會先使用「排他鎖」鎖定該行,將該行當前的值複製到 undo log 中,然後再真正地修改當前行的值,最後填寫事務的 db_trx_id ,使用回滾指標 db_roll_ptr 指向 undo log 中修改前的行。
這裡解釋一下 db_trx_id 和 db_roll_ptr 所代表的含義:
小貼士insert undo log 只在事務回滾時需要, 事務提交就可以刪掉了。update undo log 包括 update 和 delete , 回滾和快照讀都需要。聊完快照讀,再聊聊當前讀(也稱鎖定讀,locking read)。
2.1 定義
當前讀,讀取的是最新版本,並且需要先獲取對應記錄的鎖,如以下這些 sql 型別:
select ... lock in share mode 、select ... for update、
update 、delete 、insert
當然,獲取什麼型別的鎖取決於當前事務的隔離級別、語句的執行計畫、查詢條件等因素。例如,要 update 一條記錄,在事務執行過程中,如果不加鎖,那麼另乙個事務可以 delete 這條資料並且能成功 commit ,就會產生衝突了。所以 update 的時候肯定要是當前讀,得到最新的資訊並且鎖定相應的記錄。
2.2 實現方式
當前讀是通過 next-key 鎖(行記錄鎖+間隙鎖)來是實現的。
這裡補充下行鎖的 3 種演算法:行鎖(record lock):鎖直接加在索引記錄上面。下面通過乙個例子來說明當前讀的實現方式,例如下面這條 sql: delete from t where age = 7;間隙鎖(gap lock):是 innodb 為了解決幻讀問題時引入的鎖機制,所以只有在 read repeatable 、serializable 隔離級別才有。
next-key lock :record lock + gap lock,鎖定乙個範圍並且鎖定記錄本身 。
進行下面的實驗:
測試可知 delete from t where age = 7; 語句在 age 上的加鎖區間為 (4,10) ,**如下:
當前讀和快照讀
在mvcc併發控制中,讀操作可以分成兩類 快照讀 snapshot read 與當前讀 current read 快照讀,讀取的是記錄的可見版本 有可能是歷史版本 不用加鎖。當前讀,讀取的是記錄的最新版本,並且,當前讀返回的記錄,都會加上鎖,保證其他事務不會再併發修改這條記錄。innodb的預設事務...
當前讀和快照讀
innodb的預設事務隔離級別是rr 可重複讀 它的實現技術是mvcc。基於版本的控制協議。該技術不僅可以保證innodb的可重複讀,而且可以防止幻讀。但是它防止的是快照讀,也就是讀取的資料雖然是一致的,但是資料是歷史資料。如何做到保證資料是一致的 也就是乙個事務,其內部讀取對應某乙個資料的時候,資...
mysql 快照讀和當前讀
以下都是在可重複讀隔離級別情況下的 快照讀 普通的不加鎖的select就是快照讀。通過readview實現,可重複讀級別時,整個事務的普通select都是使用同乙個readview。readview相關請看文章 總之,可以理解為當前事務建立後,會立即生成乙個快照,查詢的結果都是基於這個快照。新的其他...