MySQL事務隔離機制詳解
前言
如何控制並發是數據庫領域中非常重要的問題之一,MySQL為瞭解決並發帶來的問題,設計瞭事務隔離機制、鎖機制、MVCC機制,用一整套機制來解決並發問題,本文主要介紹事務隔離機制。
一、什麼是數據庫事務
事務transaction(簡寫tx),在數據庫中,事務是指一組邏輯操作,這些操作要麼全部執行,要麼全部不執行,是一個不可分割的工作單位。事務由事務開始與結束之間執行的全部數據庫操作組成
。
事務具有以下4大特性,簡稱ACID:
1、原子性(A
tomicity)
事務是一個原子操作單元,是不可分割的最小工作單元,就像化學中的原子,其對數據的修改,要麼全都執行,要麼全都不執行
。
2、一致性(C
onsistent)
一致性是指事務必須使數據庫從一個一致性狀態變換到另一個一致性狀態。
一致性也稱作是完整性,就是說事務的執行不能破壞數據庫的一致性,在事務開始和完成時,數據都必須保持一致狀態。這意味著所有相關的數據規則都必須應用於事務的修改,以保持數據的完整性
。
3、隔離性(I
solation)
數據庫提供一定的隔離機制,當多個事務並發訪問時,保證事務在不受外部並發操作影響的“獨立”環境執行
,當然瞭,不同的隔離級別決定瞭有多“獨立”。
4、持久性(D
urable)
事務完成之後,它對於數據的修改是永久性的
,即使出現系統故障也能夠保持。
小結:原子性,持久性大傢基本都能秒懂,隔離性也還好大傢稍微想想都能理解,就是接下來要講的隔離級別,但對一致性很多人被官方概念繞住瞭,其實就是在多事務並發時要保證數據的一致和完整,不理解的話先看下面的問題。
二、事務並發帶來的4類問題
1、臟讀(Dirty Reads)
事務A讀取到瞭事務B修改但尚未提交的數據,然後事務B回滾瞭,因此事務A基於此數據做的操作都是無效的,就是讀到瞭“臟”數據(實際上不應該存在的數據),所以叫臟讀。
2、臟寫或丟失更新(Lost Update)
第一類丟失更新:撤銷rollback
一個事務時,把其他事務已經提交更新的數據回滾
掉瞭。
第二類丟失更新:提交commit
一個事務時,把其他事務已經提交更新的數據覆蓋
掉瞭。
3、不可重復讀(Non-Repeatable Reads)
在事務A中,按相同的條件執行查詢過的sql,返回結果發生瞭修改或被刪除瞭,這種現象就叫做“不可重復讀”。
4、幻讀(Phantom Reads)
在事務A中,按相同的條件執行查詢過的sql,返回結果中有新數據(是其它事務插入的),就好像發生瞭幻覺一樣,這就叫“幻讀”。
小結:不可重復讀的和幻讀很容易混淆,不可重復讀側重於修改或刪除,幻讀側重於新增。就這個結論網上很多博主寫的是
不可重復讀側重於修改,幻讀側重於新增或刪除(包括一些知名博主),大傢請註意刪除不屬於幻讀,我會在第四段演示時求證。另外後面我會單獨安排一篇介紹MVCC機制,到時你自然會明白這裡的原因。
三、事務4種隔離級別
在SQL標準中定義瞭四種隔離級別,每一種級別都規定瞭一個事務中所做的修改,哪些是在事務內和事務間可見的,哪些是不可見的。較低級別的隔離通常可以執行更高的並發,系統的開銷也更低。
每種隔離級別可能出現的問題如下:
事務隔離級別 | 臟讀 | 不可重復讀 | 幻讀 |
---|---|---|---|
讀未提交(RU) | 可能 |
可能 |
可能 |
讀已提交(RC) | 不可能 | 可能 |
可能 |
可重復讀(RR) | 不可能 | 不可能 | 可能 |
串行化(Serializable) | 不可能 | 不可能 | 不可能 |
1、讀未提交(Read uncommitted,RU)
事務中的修改,即使沒有提交,對其他事務也都是可見的,由於可能造成臟讀,所以在實際應用中一般很少使用。
2、讀已提交(Read committed,RC)
事務A修改並提交的數據才會對其它事務可見,所以解決臟讀的問題。大多數數據庫系統的默認隔離級別都是讀已提交(像Oracle、PostgreSQL、SqlServer,但Mysql不是)。
3、可重復讀(Repeatable read,RR)
Mysql默認的事務隔離級別。它保證瞭在同一個事務中多次讀取相同記錄的結果是一致的,所以解決瞭臟讀和不可重復讀問題,但未徹底解決幻讀。
4、串行化(Serializable)
可串行化是最高的隔離級別。它通過強制事務串行執行,避免瞭前面所說的臟讀,不可重復讀和幻讀問題。簡單來說,可串行化會在讀取的每一行數據上都加上鎖,所以可能導致大量的超時和鎖爭用問題。實際應用中也很少用到這個隔離級別,隻有在非常需要確保數據的一致性而且可以接受沒有並發的情況下,才考慮用該級別。
四、Mysql演示4種隔離級別
在MySQL中,InnoDB引擎支持事務,MyISAM引擎不支持事務,所以本文實驗的測試環境:Windows 10 + MySQL5.7 + InnoDB。
Mysql5.7可以通過命令select @@tx_isolation;
語句來查看:
mysql> select @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | +-----------------+
設置4種隔離級別的命令:
set tx_isolation='read-uncommitted'; set tx_isolation='read-committed'; set tx_isolation='repeatable-read'; set tx_isolation='serializable';
開始事務:
begin;
提交事務:
commit;
回滾事務:
rollback;
1、讀未提交(RU)
set tx_isolation='read-uncommitted'; select @@tx_isolation; begin;
驗證臟讀
2、讀已提交(RC)
set tx_isolation='read-committed'; select @@tx_isolation; begin;
驗證解決臟讀,存在不可重復讀
驗證幻讀
3、可重復讀(RR)
set tx_isolation='repeatable-read'; select @@tx_isolation; begin;
驗證解決臟讀和不可重復讀
上面說的不可重復讀側重於修改或刪除
,求證請看下面的截圖,
驗證幻讀
Mysql的RR級別在一定程度上解決瞭幻讀問題,但不夠徹底,至於為什麼這麼說?還是那句話,得深入理解MVCC機制,這個會單獨安排一篇,敬請期待!
4、串行化(Serializable)
set tx_isolation='serializable'; select @@tx_isolation; begin;
如果長時間阻塞,最後會鎖等待超時,拋出異常:ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
換成是在事務A執行,結果也是一樣會阻塞,直到其它事務完成或超時拋出同樣的異常。
對於update也是同樣的道理,詳細如下圖:
總結
通過本文我們已經詳細說明瞭:
事務4大特性:ACID事務並發帶來的4類問題:臟讀、臟寫、不可重復讀、幻讀事務的4種隔離級別:讀未提交、讀已提交、可重復讀、串行化Mysql提供的4種隔離級別演示
剩下的MySQL鎖機制和MVCC機制,我們下文見!
參考文章:
什麼是事務?
三分鐘圖解事務隔離級別,看一遍就懂
MySQL事務隔離級別詳解
MySQL的四種事務隔離級別
透徹解讀mysql的可重復讀、幻讀及實現原理
【MySQL (三) | 五分鐘搞清楚MySQL事務隔離級別】
到此這篇關於MySQL事務隔離機制的文章就介紹到這瞭,更多相關mysql事務隔離內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- MySQL事務(transaction)看這篇就足夠瞭
- MySQL事務與鎖實例教程詳解
- mysql數據庫隔離級別詳解
- MySQL數據庫事務transaction示例講解教程
- MySQL多版本並發控制MVCC底層原理解析