1. 程式人生 > >Mysql 中的MVCC原理,undo日誌的依賴

Mysql 中的MVCC原理,undo日誌的依賴

ont http ref 存儲 使用 key 並不是 說過 同時

一、 MVCC 原理了解

?
原文點擊:MVCC原理淺析

  • MVCC: Multi-Version Concurrency Control
    多版本並發控制:當mysql 開啟事務操作時,或者數據庫崩潰恢復,都會用到MVCC機制,而不只是單單靠行鎖去實現。而是一起使用
    ?
    當使用鎖(尤其排他鎖-行鎖)進行並發控制,開銷是非常大的 ,而使用MVCC機制來做,能一定程度的代替行鎖,就可以有效降低系統開銷

InnoDB的MVCC,是通過在每行記錄後面保存兩個隱藏的列來實現的,這兩個列,分別保存了這個行的創建時間,一個保存的是行的刪除時間。這裏存儲的並不是實際的時間值,而是系統版本號(可以理解為事務的ID),沒開始一個新的事務,系統版本號就會自動遞增,事務開始時刻的系統版本號會作為事務的ID.

話外內容:############開始###############

InnoDB的內核,會對所有row數據增加三個內部屬性:

(1)DB_TRX_ID,6字節,記錄每一行最近一次修改它的事務ID;

(2)DB_ROLL_PTR,7字節,記錄指向回滾段undo日誌的指針;

(3)DB_ROW_ID,6字節,單調遞增的行ID;

話外內容:############結束###############

如:列子,假設版本好初始為1

create table tb(
id int auto_increment primary key,
name cahr(32));

創建幾條數據:insert 操作:第一個事務ID為1

start transaction;
insert into tb(name) values('shenjian') ;
insert into tb(name) values('zhangshan');
insert into tb(name) values('lisi');
commit;
id name 創建時間(事務ID) 刪除時間(事務ID)
1 shenjian 1 undefinded
2 zhangsan 1 undefinded
3 lisi 1 undefinded

對select 的影響:

  1. innodb 只會去查找版本好小於或等於(早於)當前事務ID的數據行,這樣可以確保事務讀取的行,要麽是在事務開始前已經存在的,要麽是事務自身插入或者修改過的

  2. 行的刪除版本要麽未定義,要麽大於當前事務版本號,這可以確保事務讀取到的行,在事務開始之前未被刪除.
    只有1、2同時滿足的記錄,才能返回作為查詢結果.

例2:delete操作
InnoDB會為刪除的每一行保存當前系統的版本號(事務的ID)作為刪除標識.
看下面的具體例子分析:
第二個事務,ID為2;

start transaction;
select * from tb;  //(第一步操作:1)
select * from tb;  //(第二部操作:2)
commit; 

假設:在這個事務的的執行過程中到第一步操作:1 的時候。
又開啟了一個新事務(ID 為3)向表中執行Insert 操作插入數據

start transaction;
insert into tb(name) values('wangwu') ;
commit;

此時的表中數據為:

id name 創建時間(事務ID) 刪除時間(事務ID)
1 shenjian 1 undefinded
2 zhangsan 1 undefinded
3 lisi 1 undefinded
4 wangwu 3 undefinded

然後剛才事務2,中的第二步:2 開始執行,引文id=4的數據的創建時間(事務ID為3),執行當前事務的ID為2,而InnoDB只會查找事務ID小於等於當前事務ID的數據行,所以id=4的數據行並不會在執行事務2中的第二步:2 中被檢索出來,在事務2中的兩條select 語句檢索出來的數據都只會下表:

id name 創建時間(事務ID) 刪除時間(事務ID)
1 shenjian 1 undefinded
2 zhangsan 1 undefinded
3 lisi 1 undefinded

再假設:假設在執行事務ID為2的過程中,剛執行到了第一步:1,假設事務執行完事務3後,接著又執行了事務4;
事務4:

st art transaction;
delete  from tb where id=1;
commit;

此時數據庫中的表為:

id name 創建時間(事務ID) 刪除時間(事務ID)
1 shenjian 1 4
2 zhangsan 1 undefinded
3 lisi 1 undefinded
4 wangwu 3 undefinded

接著執行事務ID為2的第二步:2,根據select 檢索條件可以知道,它會檢索創建時間(創建事務的ID)小於當前事務ID的行和刪除時間(刪除事務的ID)大於當前事務的行,而id=4的行上面已經說過,而id=1的行由於刪除時間(刪除事務的ID)大於當前事務的ID,所以事務2的第二步:2 select * from tb 會把id=1的數據檢索出來.所以,事務2中的兩條select 語句檢索出來的數據都如下:

id name 創建時間(事務ID) 刪除時間(事務ID)
1 shenjian 1 4
2 zhangsan 1 undefinded
3 lisi 1 undefinded

update:
InnoDB執行UPDATE,實際上是新插入了一行記錄,並保存其創建時間為當前事務的ID,同時保存當前事務ID到要UPDATE的行的刪除時間.

再再假設:
假設在執行完事務2的第一步:1 後又執行,其它用戶執行了事務3,4,這時,又有一個用戶對這張表執行了UPDATE操作:

第5個事務:

start transaction;
update tb set name='xxx' where id=2;
commit;

按照update的更新原則:會生成新的一行,並在原來要修改的列的刪除時間列上添加本事務ID,得到表如下:

id name 創建時間(事務ID) 刪除時間(事務ID)
1 shenjian 1 4
2 zhangsan 1 5
3 lisi 1 undefinded
4 wangwu 3 undefinded
2 xxx 5 undefinded

繼續執行事務2第二步:2,根據select 語句的檢索條件(創建時間事務ID小於自己查詢事務ID的,和刪除時間事務ID大於自身的查詢事務ID),得到下表:

id name 創建時間(事務ID) 刪除時間(事務ID)
1 shenjian 1 4
2 zhangsan 1 5
3 lisi 1 undefinded

並得不到上上個表的ID=4的第四行(因為創建事務ID=3 > 查詢事務ID=2) 和第五行Update 事務創建的ID=2 的更新數據(因為 創建他的Update 事務ID=5 > 查詢事務ID=2)

Mysql 中的MVCC原理,undo日誌的依賴