mysql 事務隔離級別的實現原理

目錄

 

一、事務的四要素(ACID)

二、mysql的事務的隔離級別

三、多版本併發控制(multi-version concurrency control)

3.1 功能

3.2 原理


一、事務的四要素(ACID)

1. 原子性(atomicity):all done  或者 all not  done

2. 一致性(consistency):事務開啓和結束之後,數據的完整性沒有被破壞

3. 隔離性(isolation):一個事務的執行不能被另一個事務干擾

4. 持久性 (durability):事務一旦提交,對於數據庫的變更是永久性的

二、mysql的事務的隔離級別

隔離級別 髒讀 不可重複讀 幻讀
讀未提交(read uncommitted) ✔️ ✔️ ✔️
讀已提交(read committed) ✔️ ✔️
可重複讀(repeatable read) ✔️
串行化(serializable)

默認的隔離級別是:可重複讀(repeatable read)

 

髒讀:事務A讀了事務B更新但未提交的數據,事務B回滾之後,A讀到的就是髒數據

不可重複讀:事務A需要多次讀同一數據,事務B在事務A讀數據的過程中,對數據進行了更新,則A多次讀同一數據,結果不一致

幻讀:事務A讀某一個數據,其他事務又執行了插入操作,事務A再次按照同一條件查詢時,數據變多了

 

三、多版本併發控制(multi-version concurrency control)

3.1 功能

       使得InnoDB在read committed和 repeatable read兩種隔離級別下的一致性讀有了保障。換句話說,在這兩種隔離級別下,每個事物執行普通的select時,查詢到的都是已經提交的數據或是當前事務更新的數據。這個技術是一項非常強大的技術,可以使得查詢操作不用等待鎖釋放就能執行。當然這並不是一項通用技術,一些其他的數據庫產品以及mysql的其他存儲引擎並不支持。

3.2 原理

3.2.1 版本鏈

InnoDB存儲引擎會給數據庫的每一行增加三個隱藏字段

1. row_id:如果存在主鍵或是非NULL唯一鍵,該字段非必須

2. trx_id:事務ID,每次對某一個記錄進行更新時,會把更新這條記錄的事務ID賦值給隱藏的trx_id字段

3. roll_ptr:每次對某條記錄進行修改時,這個隱藏列會存一個指針,可以通過這個指針找到修改之前的數據

3.2.2 ReadView

ReadView中包含4個主要內容:

(1) m_ids:生成當前ReadView時,當前系統中的活躍事務列表

(2)min_trx_id:生成當前ReadView時,當前當前系統中最小的活躍事務Id,即m_ids中的最小值

(3)max_trx_id:生成當前ReadView時,系統應該給下一個事務分配的id值

(4)creator_trx_id:生成當前ReadView的事務Id


注意:max_trx_id並不是m_ids中的最大值,事務ID是遞增分配的。

e.g. 比如m_ids中有1,2,3三個活躍事務,之後事務3提交了,那麼生成新的ReadView時,m_ids中只有1,2兩個事務,而max_trx_id=4


3.2.3 一致性讀(consistent read)

對於讀已提交和可重複讀兩種隔離級別,可以藉助ReadView,按照如下規則實現一致性讀:

(1)如果被訪問版本的trx_id與creator_trx_id相同,則表示當前事務正在訪問自己修改的版本,該版本數據對當前事務可見;

(2)如果被訪問版本的trx_id小於min_trx_id,則表示生成該ReadView時,當前版本的數據已經提交,該版本數據對當前事務可見;

(3)如果被訪問版本的trx_id大於max_trx_id,表示生成該ReadView時,該版本的事務還未開啓,該版本的數據對當前事務不可見;

(4)如果被訪問版本的trx_id大於min_trx_id,小於max_trx_id,就需要判斷當前版本的trx_id是否在m_ids中。如果在,則表示當前版本還爲提交,該版本數據不可用;如果不在,則表示該版本數據已經提交,該版本數據可以被當前事務訪問

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章