今天介紹下,在 MySQL
的 InnoDB
存儲引擎中,事務隔離是如何實現的。sql
InnoDB
裏面每一個事務有一個惟一的事務 ID
,叫做 transaction id
。它是在事務開始的時候向 InnoDB
的事務系統申請的,是按申請順序嚴格遞增的。數據庫
對於數據庫的每行記錄,都會有三個隱藏字段:db_trx_id (事務 id)
、db_roll_pt (回滾指針)
、delete_flag(刪除標記)
。— 有懂的朋友,還望別細糾,其實 delete_flag
是在頭信息中,這裏是爲了方便理解數組
對於 DML
操做來講:ui
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
。咱們會用此語句建表及初始化數據,用於下面舉例:spa
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);
複製代碼
數據初始狀態爲:3d
如當前的隔離界別爲 Repeatable Read
,下面是 SQL 的執行過程:指針
那麼對於第 8,10,12,13 行來講,查詢的結果應該是什麼呢?code
結果應該分別是:2,1,3,1 。cdn
下面咱們來逐步回放,MySQL 底層是如何實現這整個過程的:blog
第 1 行:表示每一個事務的 ID 號,其中 read view
取的是全部當前活躍的事務 ID 數組,活躍指的是,已開啓並生成事務 ID 但未提交的事務。max id
取的是,目前爲止,最大的事務 ID,不管是否已提交。咱們還稱 read view
數組中,最小的值爲 min id
。
第 2 - 4 行:表示分別開啓使用,並建立此事務的 read view
及 max id
,要注意的是,這裏我並無使用 begin/start transaction
來開啓事務,是由於它們並不會立刻建立 read view
及 max id
,而是在執行第一條 select
語句後,來進行建立的。
第 5 行爲修改 k 的值,自增 1,按照上面所說的規則,修改後:
第 6 行,提交 ID 爲 102 的事務。
第 7 行執行了一個簡單查詢,未手動開啓事務,但也會自動開啓並生成 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。
第 8 行,當前的事務的一致性視圖爲 read view: [100, 101]
,max id: 101
一樣根據規則,第一個數據的 db_trx_id
爲 102,符合規則 2,不可見,那麼根據指針 db_roll_pt
繼續查找,找到 db_trx_id
爲 10 的數據,符合規則 1,數據可見,查詢結果爲 1。
第 9 行,修改 k 的值,自增 1,按照上面所說的規則,修改後:
第 10 行,當前的事務的一致性視圖爲 read view: [100]
,max id: 100
一樣根據規則,第一個數據的 db_trx_id
爲 100,符合規則 3.1,在 read view
數組中,可是此 id 爲當前事務 id,因此但是可見的,查詢結果爲 3。
第 11 行,當前的事務的一致性視圖爲 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。
第 12 - 13 行,爲提交事務語句。
處於 Read Committed 讀已提交
也可套用上面的規則,不過一致性視圖: read view
和 max id
的建立時機,是每一條 select
語句時從新生成。你根據上面的內容,能夠本身動手試驗下讀已提交。