// session A
begin;
select * from t1 where id = 1 //
//session B
begin;
select * from t1 where id = 1
update t1 set amonut=amount+1 where id = 1
//session A
select * from t1 where id = 1 //v1
// session B
commit
// session A
select * from t1 where id = 1 //v2
commit
select * from t1 where id = 1 //v3
複製代碼
上面的查詢分析來分析每一個事務隔離級別下v1,v2,v3不一樣的顯示mysql
MySQL 中,實際上每條記錄在更新的時候都會同時記錄一條回滾操做。記錄上的最新值,經過回滾操做,均可以獲得前一個狀態的值sql
假設一個值從1被按順序的改成2,3,4,在回滾日誌裏面就會有下面的記錄數據庫
read-view A -> 將2改成1
read-view B -> 將3改成2 將4改成3
read-view C -> 當前值4
複製代碼
經過不一樣時刻啓動不一樣的read-view,在視圖A,B,C裏面,這個記錄的值分別爲1,2,4,同一記錄存在多個版本,就是數據庫的多版本(MVCC).對於 read-view A,要獲得 1,就必須將當前值依次執行圖中全部的回滾操做獲得.同時你會發現,即便如今有另一個事務正在將 4 改爲 5,這個事務跟 read-view A、B、C 對應的事務是不會衝突的session
在不須要的時候才刪除。也就是說,系統會判斷,當沒有事務再須要用到這些回滾日誌時,回滾日誌會被刪除,當系統裏沒有比這個回滾日誌更早的 read-view 的時候就會刪除.spa
長事務意味着系統裏面會存在很老的事務視圖。因爲這些事務隨時可能訪問數據庫裏面的任何數據,因此這個事務提交以前,數據庫裏面它可能用到的回滾記錄都必須保留,這就會致使大量佔用存儲空間.==長事務還佔用鎖資源,也可能拖垮整個庫==日誌
每一個事務都有一個事務ID,叫作transaction id(遞增)code
事務在啓動時,找到已提交的最大事務ID記爲up_limit_id。事務
事務在更新一條語句時,好比id=1改成了id=2.會把id=1和該行以前的row trx_id寫到undo log裏,而且在數據頁上把id的值改成2,而且把修改這條語句的transactionid記在該行行頭資源
一個事務要查看一條數據時,必須先用該事務的up_limit_id與該行的transaction id作比對,若是up_limit_id>=transactionid,那麼能夠看.若是up_limit_id<transaction id,則只能去undo log裏去取。去undo log查找數據的時候,也須要作比對,必須up_limit_id>transaction id,才返回數據it
// session A
start transaction with consistent snapshot //立刻啓動事務
// session B
start transaction with consistent snapshot
// session C
UPDATE t set k=k+1 where id =1
// session B
UPDATE t set k=k+1 where id =1
SELECT k from t where id = 1 //查詢結果 3
// session A
SELECT k from t where id = 1 //查詢結果 1
commit
// session B
comit
複製代碼
一個數據版本,對於一個事務視圖來講,除了本身的更新老是可見之外,有三種狀況
上面的例子 咱們將事務C也進行聲明事務,接下來看看會怎麼樣
// session A
start transaction with consistent snapshot //立刻啓動事務
// session B
start transaction with consistent snapshot
// session C
start transaction with consistent snapshot // C也啓動事務
UPDATE t set k=k+1 where id =1
// session B
UPDATE t set k=k+1 where id =1
SELECT k from t where id = 1 //查詢結果 3
// session C
commit
// session A
SELECT k from t where id = 1 //查詢結果 1
commit
// session B
comit
複製代碼
相對於上個版原本說,事務B的更新的時候,事務C還未進行提交,這樣的話當前A,B的查詢結果會是什麼樣子呢?
上一篇文章中提到的「兩階段鎖協議」就要上場了。事務 C’沒提交,也就是說 (1,2) 這個版本上的寫鎖還沒釋放。而事務 B 是當前讀,必需要讀最新版本,並且必須加鎖,所以就被鎖住了,==必須等到事務 C’釋放這個鎖==,才能繼續它的當前讀
可重複讀的核心就是==一致性讀==;而事務更新數據的時候,只能用當前讀。若是當前的記錄的行鎖被其餘事務佔用的話,就須要進入鎖等待。而讀提交的邏輯和可重複讀的邏輯相似,它們最主要的區別是: