数据库的事务隔离技术 之 MVCC
在mysql中,提供了兩種事務隔離技術,第一個是mvcc,第二個是next-key技術。
這個在使用不同的語句的時候可以動態選擇。不加lock in share mode之類的就使用mvcc。否則使用next-key。
mvcc的優勢是不加鎖,并發性高。缺點是不是實時數據。next-key的優勢是獲取實時數據,但是需要加鎖。
同時需要注意幾點:
1.事務的快照時間點是以第一個select來確認的。所以即便事務先開始。但是select在后面的事務的update之類的語句后進行,那么它是可以獲取后面的事務的對應的數據。
2.mysql中數據的存放還是會通過版本記錄一系列的歷史數據,這樣,可以根據版本查找數據。
?本片博文先講解MVCC技術,下一篇博文講解next-key技術
?
多版本并發控制(Multi-Version Concurrency Control, MVCC)是 MySQL 的 InnoDB 存儲引擎實現隔離級別的一種具體方式,用于實現提交讀和可重復讀這兩種隔離級別。而未提交讀隔離級別總是讀取最新的數據行,無需使用 MVCC。可串行化隔離級別需要對所有讀取的行都加鎖,單純使用 MVCC 無法實現。
版本號
- 系統版本號:是一個遞增的數字,每開始一個新的事務,系統版本號就會自動遞增。
- 事務版本號:事務開始時的系統版本號。
隱藏的列
MVCC 在每行記錄后面都保存著兩個隱藏的列,用來存儲兩個版本號:
- 創建版本號:指示創建一個數據行的快照時的系統版本號;
- 刪除版本號:如果該快照的刪除版本號大于當前事務版本號表示該快照有效,否則表示該快照已經被刪除了。
Undo 日志
MVCC 使用到的快照存儲在 Undo 日志中,該日志通過回滾指針把一個數據行(Record)的所有快照連接起來。
?
實現過程
以下實現過程針對可重復讀隔離級別。
當開始新一個事務時,該事務的版本號肯定會大于當前所有數據行快照的創建版本號,理解這一點很關鍵。
1. SELECT
多個事務必須讀取到同一個數據行的快照,并且這個快照是距離現在最近的一個有效快照。但是也有例外,如果有一個事務正在修改該數據行,那么它可以讀取事務本身所做的修改,而不用和其它事務的讀取結果一致。
把沒有對一個數據行做修改的事務稱為 T,T 所要讀取的數據行快照的創建版本號必須小于 T 的版本號,因為如果大于或者等于 T 的版本號,那么表示該數據行快照是其它事務的最新修改,因此不能去讀取它。除此之外,T 所要讀取的數據行快照的刪除版本號必須大于 T 的版本號,因為如果小于等于 T 的版本號,那么表示該數據行快照是已經被刪除的,不應該去讀取它。
2. INSERT
將當前系統版本號作為數據行快照的創建版本號。
3. DELETE
將當前系統版本號作為數據行快照的刪除版本號。
4. UPDATE
將當前系統版本號作為更新前的數據行快照的刪除版本號,并將當前系統版本號作為更新后的數據行快照的創建版本號。可以理解為先執行 DELETE 后執行 INSERT。
?
快照讀與當前讀
1. 快照讀
使用 MVCC 讀取的是快照中的數據,這樣可以減少加鎖所帶來的開銷。
select * from table ...;2. 當前讀
讀取的是最新的數據,需要加鎖。以下第一個語句需要加 S 鎖,其它都需要加 X 鎖。
select * from table where ? lock in share mode; select * from table where ? for update; insert; update; delete;?
快照讀
??讀取的是記錄數據的可見版本(可能是過期的數據),不用加鎖
當前讀
??讀取的是記錄數據的最新版本,并且當前讀返回的記錄都會加上鎖,保證其他事務不會再并發的修改這條記錄
??概念說的比較虛,也不好理解,接著舉一個例子吧,假設你開啟了兩個事務,分別是A和B,這里有個張表,user表,里面有四條數據
?
1、insert 快照讀(照片)
??當你執行select *之后,在A與B事務中都會返回4條一樣的數據,這是不用想的,當執行select的時候,innodb默認會執行快照讀,相當于就是給你目前的狀態拍了一張照片,以后執行select 的時候就會返回當前照片里面的數據,當其他事務提交了也對你不造成影響,和你沒關系,這就實現了可重復讀了,那這個照片是什么時候生成的呢?不是開啟事務的時候,是當你第一次執行select的時候,也就是說,當A開啟了事務,然后沒有執行任何操作,這時候B insert了一條數據然后commit,這時候A執行 select,那么返回的數據中就會有B添加的那條數據......之后無論再有其他事務commit都沒有關系,因為照片已經生成了,而且不會再生成了,以后都會參考這張照片。(這就是為什么數據可能是過期數據的原因)
2、update、insert、delete 當前讀
??當你執行這幾個操作的時候默認會執行當前讀,也就是會讀取最新的記錄,也就是別的事務提交的數據你也可以看到,這樣很好理解啊,假設你要update一個記錄,另一個事務已經delete這條數據并且commit了,這樣不是會產生沖突嗎,所以你update的時候肯定要知道最新的信息啊。
??我在這里介紹一下update的過程吧,首先會執行當前讀,然后把返回的數據加鎖,之后執行update,然后把鎖釋放掉。加鎖是防止別的事務在這個時候對這條記錄做什么,默認加的是排他鎖,也就是你讀都不可以,這樣就可以保證數據不會出錯了。
總結
以上是生活随笔為你收集整理的数据库的事务隔离技术 之 MVCC的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 数据库的封锁
- 下一篇: 数据库事务隔离技术之 Next-Key