MySQL中隔離級別的4種小結
在數(shù)據(jù)庫管理系統(tǒng)中,事務隔離級別(Transaction Isolation Levels)決定了事務之間如何相互隔離,以防止數(shù)據(jù)不一致和其他并發(fā)問題。MySQL 提供了四種標準的事務隔離級別,每種級別在并發(fā)性能和數(shù)據(jù)一致性之間有不同的權衡。本文將詳細介紹這四種隔離級別,包括它們的定義、特點、優(yōu)缺點以及適用場景。
1. 事務隔離級別的概念
事務隔離級別定義了事務在執(zhí)行過程中如何與其他事務隔離,以確保數(shù)據(jù)的完整性和一致性。不同的隔離級別通過不同的鎖機制和并發(fā)控制策略來實現(xiàn),從而在并發(fā)性能和數(shù)據(jù)一致性之間取得平衡。
2. MySQL 的四種事務隔離級別
MySQL 支持 ANSI SQL 標準定義的四種事務隔離級別,按照隔離程度從低到高依次為:
- READ UNCOMMITTED(讀未提交)
- READ COMMITTED(讀已提交)
- REPEATABLE READ(可重復讀)
- SERIALIZABLE(串行化)

臟讀就是一個事務讀取到了另一個事務還沒有提交的數(shù)據(jù)
不可重復度就是一個事務兩次相同的sql,查詢結果返回的結果卻不一樣,由于另外一個事務修改并提交導致的
幻讀就是插入的時候提示已經有了,但是查詢的時候是空的
2.1 READ UNCOMMITTED(讀未提交)
定義
在此隔離級別下,事務可以讀取其他事務尚未提交的修改(臟讀)。這意味著一個事務可以看到另一個事務尚未提交的中間狀態(tài)數(shù)據(jù)。
特點
- 允許臟讀:事務可以讀取其他事務未提交的修改。
- 并發(fā)性能高:由于鎖的粒度較小,減少了鎖競爭,提高了并發(fā)性能。
- 數(shù)據(jù)一致性差:容易出現(xiàn)臟讀、不可重復讀和幻讀問題。
優(yōu)點
- 高并發(fā):適用于對并發(fā)性能要求極高,且可以容忍一定程度數(shù)據(jù)不一致的場景。
缺點
- 數(shù)據(jù)不一致:可能導致臟讀,影響數(shù)據(jù)的準確性和一致性。
- 不適合大多數(shù)應用:由于數(shù)據(jù)不一致的風險,通常不推薦在生產環(huán)境中使用。
適用場景
- 數(shù)據(jù)準確性要求不高,且對并發(fā)性能有極高要求的場景(如某些實時數(shù)據(jù)分析)。
示例
假設有兩個事務 T1 和 T2:
- T1 修改了一行數(shù)據(jù)但尚未提交。
- T2 在 T1 提交前讀取了該行數(shù)據(jù),看到了 T1 的未提交修改(臟讀)。
2.2 READ COMMITTED(讀已提交)
定義
在此隔離級別下,事務只能讀取已經提交的其他事務所做的修改。每個查詢只會看到在該查詢開始之前已經提交的數(shù)據(jù)。
特點
- 防止臟讀:事務不會讀取其他事務未提交的修改。
- 允許不可重復讀:同一個事務在不同時間執(zhí)行相同的查詢可能會看到不同的結果,因為其他事務可能已經提交了修改。
- 并發(fā)性能較高:相比 SERIALIZABLE,減少了鎖的持有時間,提高了并發(fā)性能。
優(yōu)點
- 避免臟讀:確保事務不會讀取到未提交的臟數(shù)據(jù)。
- 適中的并發(fā)性能:適用于大多數(shù)需要一定數(shù)據(jù)一致性的應用場景。
缺點
- 可能出現(xiàn)不可重復讀:同一事務多次讀取同一數(shù)據(jù)可能得到不同結果。
- 仍可能出現(xiàn)幻讀:在某些情況下,事務可能會看到其他事務插入的新行。
適用場景
- 大多數(shù)在線事務處理(OLTP)系統(tǒng),需要保證數(shù)據(jù)的基本一致性,同時要求較高的并發(fā)性能。
示例
- T1 讀取一行數(shù)據(jù)。
- T2 修改并提交該行數(shù)據(jù)。
- T1 再次讀取同一行數(shù)據(jù),看到 T2 的修改(不可重復讀)。
2.3 REPEATABLE READ(可重復讀)
定義
在此隔離級別下,事務在執(zhí)行期間多次讀取同一數(shù)據(jù)時,會看到一致的結果,即使其他事務已經修改了這些數(shù)據(jù)。MySQL 的 InnoDB 存儲引擎通過多版本并發(fā)控制(MVCC)實現(xiàn)這一點。
特點
- 防止臟讀和不可重復讀:事務在整個執(zhí)行過程中看到的數(shù)據(jù)是一致的。
- 防止幻讀(部分):在 MySQL 的 InnoDB 中,通過間隙鎖(Gap Locks)防止幻讀,但在某些情況下仍可能出現(xiàn)幻讀。
- 并發(fā)性能適中:相比 READ COMMITTED,進一步減少了不可重復讀的問題,但鎖的粒度較大,可能影響并發(fā)性能。
優(yōu)點
- 高度一致性:確保事務多次讀取同一數(shù)據(jù)時的一致性。
- 防止大多數(shù)并發(fā)問題:避免了臟讀、不可重復讀和大部分幻讀問題。
缺點
- 可能出現(xiàn)幻讀:在某些復雜查詢條件下,仍可能出現(xiàn)幻讀。
- 鎖的粒度較大:可能影響并發(fā)性能,尤其是在高并發(fā)環(huán)境下。
適用場景
- 需要高度數(shù)據(jù)一致性的應用,如金融系統(tǒng)、訂單處理系統(tǒng)等。
示例
- T1 開始一個事務并讀取某范圍內的行。
- T2 在該范圍內插入新行并提交。
- T1 再次讀取同一范圍的行,不會看到 T2 插入的新行(防止幻讀,但在某些條件下仍可能看到)。
2.4 SERIALIZABLE(串行化)
定義
這是最高的隔離級別,要求事務必須順序執(zhí)行,以避免并發(fā)問題。在此級別下,事務會對讀取的數(shù)據(jù)加鎖,防止其他事務對其進行修改或插入。
特點
- 完全防止并發(fā)問題:防止臟讀、不可重復讀和幻讀。
- 事務串行執(zhí)行:實際上將并發(fā)事務轉換為串行執(zhí)行,確保數(shù)據(jù)的一致性。
- 并發(fā)性能低:由于事務需要等待彼此完成,嚴重限制了并發(fā)性能。
優(yōu)點
- 最高的數(shù)據(jù)一致性:確保在任何情況下都不會出現(xiàn)并發(fā)問題。
- 簡單實現(xiàn):不需要復雜的并發(fā)控制機制。
缺點
- 極低的并發(fā)性能:事務需要串行執(zhí)行,極大地影響了系統(tǒng)的吞吐量和響應時間。
- 容易造成鎖爭用和死鎖:高并發(fā)環(huán)境下容易導致鎖等待和死鎖。
適用場景
- 對數(shù)據(jù)一致性要求極高的場景,且可以接受較低的并發(fā)性能,如銀行交易系統(tǒng)。
示例
- T1 開始一個事務并讀取某范圍內的行。
- T2 嘗試在該范圍內插入新行,但由于 T1 的鎖,T2 必須等待 T1 完成。
- T1 完成后,T2 才能插入新行,確保數(shù)據(jù)的一致性。
3. MySQL 中的隔離級別設置
在 MySQL 中,可以通過以下方式設置事務的隔離級別:
3.1 查看當前的隔離級別
SHOW VARIABLES LIKE 'transaction_isolation';
或者
SELECT @@GLOBAL.transaction_isolation, @@SESSION.transaction_isolation;
3.2 設置全局隔離級別
設置全局隔離級別會影響所有新連接,當前已經存在的會話不會受到影響。
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
3.3 設置當前會話的隔離級別
設置當前會話的隔離級別,只影響當前會話及之后新建的子會話。
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
3.4 設置下一個事務的隔離級別
僅對下一個事務生效,事務結束后恢復到之前的隔離級別。
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; START TRANSACTION; -- 事務內容 COMMIT;
4. 不同隔離級別的并發(fā)問題對比
| 隔離級別 | 臟讀(Dirty Read) | 不可重復讀(Non-Repeatable Read) | 幻讀(Phantom Read) |
|---|---|---|---|
| READ UNCOMMITTED | 可能發(fā)生 | 可能發(fā)生 | 可能發(fā)生 |
| READ COMMITTED | 不會發(fā)生 | 可能發(fā)生 | 可能發(fā)生 |
| REPEATABLE READ | 不會發(fā)生 | 不會發(fā)生 | 可能發(fā)生(InnoDB 部分防止) |
| SERIALIZABLE | 不會發(fā)生 | 不會發(fā)生 | 不會發(fā)生 |
5. 實際案例分析
案例 1:讀未提交導致臟讀
場景:電商系統(tǒng)中,訂單支付和庫存扣減。
- T1(事務1):開始支付訂單,減少庫存,但尚未提交。
- T2(事務2):查詢訂單狀態(tài)和庫存,看到 T1 的未提交修改(庫存減少)。
- T1:回滾事務,庫存恢復,但 T2 已經基于臟數(shù)據(jù)進行了后續(xù)操作。
結果:庫存數(shù)據(jù)不一致,可能導致超賣。
案例 2:讀已提交避免臟讀,但可能出現(xiàn)不可重復讀
場景:銀行轉賬系統(tǒng),賬戶余額查詢和更新。
- T1:查詢賬戶 A 的余額。
- T2:向賬戶 A 轉賬,更新余額并提交。
- T1:再次查詢賬戶 A 的余額,看到 T2 的修改(不可重復讀)。
結果:雖然避免了臟讀,但同一事務內多次讀取同一數(shù)據(jù)得到不同結果,可能導致邏輯錯誤。
案例 3:可重復讀保證一致性
場景:在線訂票系統(tǒng),查詢和預訂座位。
- T1:查詢某趟列車的剩余座位,顯示有空位。
- T2:在同一列車上預訂一個座位并提交。
- T1:再次查詢剩余座位,仍然顯示之前的結果(不變),因為使用了可重復讀。
結果:確保了 T1 在事務內看到的一致性,避免了不可重復讀和幻讀。
案例 4:串行化確保最高一致性
場景:股票交易系統(tǒng),訂單匹配和執(zhí)行。
- T1:查詢某股票的買賣盤,找到匹配的買單。
- T2:在同一時間嘗試修改同一股票的買賣盤,但由于 T1 的鎖,T2 必須等待。
- T1:完成訂單匹配和執(zhí)行后,T2 才能繼續(xù)操作。
結果:確保了數(shù)據(jù)的高度一致性,避免了所有并發(fā)問題,但犧牲了并發(fā)性能。
到此這篇關于MySQL中隔離級別的4種小結的文章就介紹到這了,更多相關MySQL 隔離級別內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
mysql 8.0.18各版本安裝及安裝中出現(xiàn)的問題(精華總結)
這篇文章主要介紹了mysql 8.0.18各版本安裝及安裝中出現(xiàn)的問題,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-12-12
django2.2版本連接mysql數(shù)據(jù)庫的方法
這篇文章主要介紹了django2.2版本如何連接mysql數(shù)據(jù)庫,本文圖文并茂給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-10-10
CentOS 7搭建多實例MySQL8的詳細教程(想要幾個搞幾個)
這篇文章主要介紹了CentOS 7搭建多實例MySQL8的詳細教程(想要幾個搞幾個),本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-05-05
mysql創(chuàng)建外鍵報錯的原因及解決(can't?not?create?table)
這篇文章主要介紹了mysql創(chuàng)建外鍵報錯的原因及解決方案(can't?not?create?table),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09

