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