今天介紹下,在 MySQL
的 InnoDB
存儲引擎中,事務隔離是如何實現的。
InnoDB
里面每個事務有一個唯一的事務 ID
,叫作 transaction id
。它是在事務開始的時候向 InnoDB
的事務系統申請的,是按申請順序嚴格遞增的。
對于數據庫的每行記錄,都會有三個隱藏字段:db_trx_id (事務 id)
、db_roll_pt (回滾指針)
、delete_flag(刪除標記)
?!?nbsp;有懂的朋友,還望別細糾,其實 delete_flag
是在頭信息中,這里是為了方便理解
對于 DML
操作來說:
db_trx_id
的值為當前事務 id
, db_roll_pt
為 null
。db_trx_id
置為當前事務的 id
,db_roll_pt
是一個指針,指向復制前的那一條的。db_trx_id
置為當前事務的 id
,db_roll_pt
是一個指針,指向復制前的那一條的。并把 delete_flag
置為 true
。我們會用此語句建表及初始化數據,用于下面舉例:
CREATE TABLE `t` (
`id` int(11) NOT NULL,
`k` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
insert into t(id, k) values(1, 1);
數據初始狀態為:
如當前的隔離界別為 Repeatable Read
,下面是 SQL 的執行過程:
那么對于第 8,10,12,13 行來說,查詢的結果應該是什么呢?
結果應該分別是:2,1,3,1 。
下面我們來逐步回放,MySQL 底層是如何實現這整個過程的:
read view
取的是所有當前活躍的事務 ID 數組,活躍指的是,已開啟并生成事務 ID 但未提交的事務。max id
取的是,目前為止,最大的事務 ID,不論是否已提交。我們還稱 read view
數組中,最小的值為 min id
。read view
及 max id
,要注意的是,這里我并沒有使用 begin/start transaction
來開啟事務,是因為它們并不會馬上創建 read view
及 max id
,而是在執行第一條 select
語句后,來進行創建的。第 6 行,提交 ID 為 102 的事務。
read view
及 max id
,分別為 read-view: [100, 101]
,max-id: 103
此時會根據查詢規則,進行查找,規則如下:
如果數據的 db_trx_id < min id
,則說明數據在開啟當前事務前已提交的,內容可見。
如果數據的 db_trx_id > max id
,則說明數據在此事務啟動后生成的,內容不可見。
如果數據的 min id <= db_trx_id <= max id
,則還分為兩種情況:
3.1 若 db_trx_id
在 read view
的數組中,表示這個版本是由還沒提交的事務生成的,不可見,但如果是自己的事務,則可見。
3.2. 若不在數據中,則表示這個版本是已經提交了的事務生成的,可見。
示意圖如下:
當前的事務的一致性視圖為 read view: [100, 101]
,max id: 103
,那么根據這個規則,在上面的數據鏈中查詢數據,從最新的藍色,開始找,找到第一個數據的 db_trx_id
為 102,符合規則 3.2 屬于可見范圍,查詢結果為 2。
read view: [100, 101]
,max id: 101
同樣根據規則,第一個數據的 db_trx_id
為 102,符合規則 2,不可見,那么根據指針 db_roll_pt
繼續查找,找到 db_trx_id
為 10 的數據,符合規則 1,數據可見,查詢結果為 1。第 10 行,當前的事務的一致性視圖為 read view: [100]
,max id: 100
同樣根據規則,第一個數據的 db_trx_id
為 100,符合規則 3.1,在 read view
數組中,但是此 id 為當前事務 id,所以可是可見的,查詢結果為 3。
read view: [100, 101]
,max id: 101
同樣根據規則,第一個數據的 db_trx_id
為 100,符合規則 3.1,在 read view
中,但是此 id 不為當前事務 id,所以內容可見的,那么根據指針 db_roll_pt
繼續查找,找到 db_trx_id
為 102 的數據,符合規則 2,不可見,繼續根據指針 db_roll_pt
查找,找到 db_trx_id
為 10 的數據,符合規則 1,數據可見,查詢結果為 1。處于 Read Committed 讀已提交
也可套用上面的規則,不過一致性視圖: read view
和 max id
的創建時機,是每一條 select
語句時重新生成。你根據上面的內容,可以自己動手試驗下讀已提交。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。