mysql的mvcc MySQL的MVCC機制

2021-10-18 02:31:04 字數 4087 閱讀 4680

1、mvcc簡介

1.1 mvcc是什麼?

mvcc,multi-version concurrency control,多版本併發控制。mvcc 是一種併發控制的方法,一般在資料庫管理系統中,實現對資料庫的併發訪問;

1.2 mvcc是為了解決什麼?

大多數的mysql事務型儲存引擎,如,innodb,falcon以及pbxt都不使用一種簡單的行鎖機制.事實上,他們都和mvcc–多版本併發控制來一起使用

大家都應該知道,鎖機制可以控制併發操作,但是其系統開銷較大,而mvcc可以在大多數情況下代替行級鎖,使用mvcc,能降低其系統開銷

眾所周知,在mysql中,myisam使用的是表鎖,innodb使用的是行鎖。而innodb的事務分為四個隔離級別,其中預設的隔離級別repeatable read需要兩個不同的事務相互之間不能影響,而且還能支援併發,這點悲觀鎖是達不到的,所以repeatable read採用的就是樂觀鎖,而樂觀鎖的實現採用的就是mvcc。正是因為有了mvcc,才造就了innodb強大的事務處理能力。

mvcc解決的問題是讀寫互相不阻塞的問題,每次更新都產生乙個新的版本,讀的話可以讀歷史版本。試想,如果乙個資料只有乙個版本,那麼多個事務對這個資料進行讀寫是不是需要讀寫鎖來保護?

乙個讀寫事務在執行的過程中在訪問資料之前先加讀/寫鎖這種實現叫做悲觀鎖,悲觀體現在,先加鎖,獨佔資料,防止別人加鎖。

樂觀鎖呢,讀寫事務,在真正的提交之前,不加讀/寫鎖,而是先看一下資料的版本/時間戳,等到真正提交的時候再看一下版本/時間戳,如果兩次相同,說明別人期間沒有對資料進行過修改,那麼就可以放心提交。

樂觀體現在,訪問資料時不提前加鎖。在資源衝突不激烈的場合,用樂觀鎖效能較好。如果資源衝突嚴重,樂觀鎖的實現會導致事務提交的時候經常看到別人在他之前已經修改了資料,然後要進行回滾或者重試,還不如一上來就加鎖。

所以通常我們把沒有開啟mvcc特性的,使用原來的鎖機制來保證資料一致性的這種鎖叫悲觀鎖,

而對開啟mvcc機制的鎖,叫做樂觀鎖。

1.3 mvcc實現

mvcc是通過儲存資料在某個時間點的快照來實現的. 不同儲存引擎的mvcc實現是不同的,典型的有樂觀併發控制和悲觀併發控制.

2、mvcc具體實現

下面,我們通過innodb的mvcc實現來分析mvcc使怎樣進行併發控制的.

innodb的mvcc,是通過在每行記錄後面儲存兩個隱藏的列來實現的,這兩個列,分別儲存了這個行的建立時間,乙個儲存的是行的刪除時間。這裡儲存的並不是實際的時間值,而是系統版本號(可以理解為事務的id),沒開始乙個新的事務,系統版本號就會自動遞增,事務開始時刻的系統版本號會作為事務的id.下面看一下在repeatable read隔離級別下,mvcc具體是如何操作的.

2.1簡單的小例子

create table yang(

id int primary key auto_increment,

name varchar(20));

假設系統的版本號從1開始.

insert

innodb為新插入的每一行儲存當前系統版本號作為版本號.

第乙個事務id為1;

start transaction;

insert into yang values(null,'yang') ;

insert into yang values(null,'long');

insert into yang values(null,'fei');

commit;

對應在資料中的表如下(後面兩列是隱藏列,我們通過查詢語句並看不到)

idname建立時間(事務id)刪除時間(事務id)

yang

undefined

long

undefined

feiundefined

select

innodb會根據以下兩個條件檢查每行記錄:

a.innodb只會查詢版本早於當前事務版本的資料行(也就是,行的系統版本號小於或等於事務的系統版本號),這樣可以確保事務讀取的行,要麼是在事務開始前已經存在的,要麼是事務自身插入或者修改過的.

b.行的刪除版本要麼未定義,要麼大於當前事務版本號,這可以確保事務讀取到的行,在事務開始之前未被刪除.

只有a,b同時滿足的記錄,才能返回作為查詢結果.

delete

innodb會為刪除的每一行儲存當前系統的版本號(事務的id)作為刪除標識.

看下面的具體例子分析:

第二個事務,id為2;

start transaction;

select * from yang; //(1)

select * from yang; //(2)

commit;

假設1假設在執行這個事務id為2的過程中,剛執行到(1),這時,有另乙個事務id為3往這個表裡插入了一條資料;

第三個事務id為3;

start transaction;

insert into yang values(null,'tian');

commit;

這時表中的資料如下:

idname建立時間(事務id)刪除時間(事務id)

yang

undefined

long

undefined

feiundefined

tian

undefined

然後接著執行事務2中的(2),由於id=4的資料的建立時間(事務id為3),執行當前事務的id為2,而innodb只會查詢事務id小於等於當前事務id的資料行,所以id=4的資料行並不會在執行事務2中的(2)被檢索出來,在事務2中的兩條select 語句檢索出來的資料都只會下表:

idname建立時間(事務id)刪除時間(事務id)

yang

undefined

long

undefined

feiundefined

假設2假設在執行這個事務id為2的過程中,剛執行到(1),假設事務執行完事務3後,接著又執行了事務4;

第四個事務:

start transaction;

delete from yang where id=1;

commit;

此時資料庫中的表如下:

idname建立時間(事務id)刪除時間(事務id)

yang

long

undefined

feiundefined

tian

undefined

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

idname建立時間(事務id)刪除時間(事務id)

yang

long

undefined

feiundefined

update

innodb執行update,實際上是新插入了一行記錄,並儲存其建立時間為當前事務的id,同時儲存當前事務id到要update的行的刪除時間.

假設3假設在執行完事務2的(1)後又執行,其它使用者執行了事務3,4,這時,又有乙個使用者對這張表執行了update操作:

第5個事務:

start transaction;

update yang set name='long' where id=2;

commit;

根據update的更新原則:會生成新的一行,並在原來要修改的列的刪除時間列上新增本事務id,得到表如下:

idname建立時間(事務id)刪除時間(事務id)

yang

long

feiundefined

tian

undefined

long

undefined

繼續執行事務2的(2),根據select 語句的檢索條件,得到下表:

idname建立時間(事務id)刪除時間(事務id)

yang

long

feiundefined

還是和事務2中(1)select 得到相同的結果.

mysql 設定mvcc mysql的MVCC機制

一 undo log版本鏈 我們在執行update,insert,delete的時候會生成undo log日誌,以防止回滾使用。一條sql執行,會生成一條undo log日誌 其中trx id就是執行這條sql的事務id,roll pointer指向對同乙個值修改的undo log日誌,因為當前沒有...

mysql的恢復 MYSQL的恢復

恢復就簡單多了!只要執行該備份檔案就行了,該備份檔案是sql哦!恢復完全備份mysql uroot p backup.sql 就這麼簡單!恢復增量備份mysqlbinlog mysql bin.000002 mysql u root p 注意此次恢復過程亦會寫入日誌檔案,如果資料量很大,建議先關閉日...

mysql的查詢日誌 mysql

這篇文章總結了mysql中查詢日誌的知識點。mysql中,日誌可以按照功能分為如下幾類。錯誤日誌 查詢日誌 慢查詢日誌 二進位制日誌 中繼日誌 innodb儲存引擎級別的事務日誌 查詢日誌 查詢日誌在mysql中被稱之為general log 通用日誌 不要被 查詢日誌 的名字誤導,錯誤的以為查詢日...