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

臟讀就是一個事務(wù)讀取到了另一個事務(wù)還沒有提交的數(shù)據(jù)
不可重復(fù)度就是一個事務(wù)兩次相同的sql,查詢結(jié)果返回的結(jié)果卻不一樣,由于另外一個事務(wù)修改并提交導(dǎo)致的
幻讀就是插入的時候提示已經(jīng)有了,但是查詢的時候是空的
2.1 READ UNCOMMITTED(讀未提交)
定義
在此隔離級別下,事務(wù)可以讀取其他事務(wù)尚未提交的修改(臟讀)。這意味著一個事務(wù)可以看到另一個事務(wù)尚未提交的中間狀態(tài)數(shù)據(jù)。
特點
- 允許臟讀:事務(wù)可以讀取其他事務(wù)未提交的修改。
 - 并發(fā)性能高:由于鎖的粒度較小,減少了鎖競爭,提高了并發(fā)性能。
 - 數(shù)據(jù)一致性差:容易出現(xiàn)臟讀、不可重復(fù)讀和幻讀問題。
 
優(yōu)點
- 高并發(fā):適用于對并發(fā)性能要求極高,且可以容忍一定程度數(shù)據(jù)不一致的場景。
 
缺點
- 數(shù)據(jù)不一致:可能導(dǎo)致臟讀,影響數(shù)據(jù)的準(zhǔn)確性和一致性。
 - 不適合大多數(shù)應(yīng)用:由于數(shù)據(jù)不一致的風(fēng)險,通常不推薦在生產(chǎn)環(huán)境中使用。
 
適用場景
- 數(shù)據(jù)準(zhǔn)確性要求不高,且對并發(fā)性能有極高要求的場景(如某些實時數(shù)據(jù)分析)。
 
示例
假設(shè)有兩個事務(wù) T1 和 T2:
- T1 修改了一行數(shù)據(jù)但尚未提交。
 - T2 在 T1 提交前讀取了該行數(shù)據(jù),看到了 T1 的未提交修改(臟讀)。
 
2.2 READ COMMITTED(讀已提交)
定義
在此隔離級別下,事務(wù)只能讀取已經(jīng)提交的其他事務(wù)所做的修改。每個查詢只會看到在該查詢開始之前已經(jīng)提交的數(shù)據(jù)。
特點
- 防止臟讀:事務(wù)不會讀取其他事務(wù)未提交的修改。
 - 允許不可重復(fù)讀:同一個事務(wù)在不同時間執(zhí)行相同的查詢可能會看到不同的結(jié)果,因為其他事務(wù)可能已經(jīng)提交了修改。
 - 并發(fā)性能較高:相比 SERIALIZABLE,減少了鎖的持有時間,提高了并發(fā)性能。
 
優(yōu)點
- 避免臟讀:確保事務(wù)不會讀取到未提交的臟數(shù)據(jù)。
 - 適中的并發(fā)性能:適用于大多數(shù)需要一定數(shù)據(jù)一致性的應(yīng)用場景。
 
缺點
- 可能出現(xiàn)不可重復(fù)讀:同一事務(wù)多次讀取同一數(shù)據(jù)可能得到不同結(jié)果。
 - 仍可能出現(xiàn)幻讀:在某些情況下,事務(wù)可能會看到其他事務(wù)插入的新行。
 
適用場景
- 大多數(shù)在線事務(wù)處理(OLTP)系統(tǒng),需要保證數(shù)據(jù)的基本一致性,同時要求較高的并發(fā)性能。
 
示例
- T1 讀取一行數(shù)據(jù)。
 - T2 修改并提交該行數(shù)據(jù)。
 - T1 再次讀取同一行數(shù)據(jù),看到 T2 的修改(不可重復(fù)讀)。
 
2.3 REPEATABLE READ(可重復(fù)讀)
定義
在此隔離級別下,事務(wù)在執(zhí)行期間多次讀取同一數(shù)據(jù)時,會看到一致的結(jié)果,即使其他事務(wù)已經(jīng)修改了這些數(shù)據(jù)。MySQL 的 InnoDB 存儲引擎通過多版本并發(fā)控制(MVCC)實現(xiàn)這一點。
特點
- 防止臟讀和不可重復(fù)讀:事務(wù)在整個執(zhí)行過程中看到的數(shù)據(jù)是一致的。
 - 防止幻讀(部分):在 MySQL 的 InnoDB 中,通過間隙鎖(Gap Locks)防止幻讀,但在某些情況下仍可能出現(xiàn)幻讀。
 - 并發(fā)性能適中:相比 READ COMMITTED,進一步減少了不可重復(fù)讀的問題,但鎖的粒度較大,可能影響并發(fā)性能。
 
優(yōu)點
- 高度一致性:確保事務(wù)多次讀取同一數(shù)據(jù)時的一致性。
 - 防止大多數(shù)并發(fā)問題:避免了臟讀、不可重復(fù)讀和大部分幻讀問題。
 
缺點
- 可能出現(xiàn)幻讀:在某些復(fù)雜查詢條件下,仍可能出現(xiàn)幻讀。
 - 鎖的粒度較大:可能影響并發(fā)性能,尤其是在高并發(fā)環(huán)境下。
 
適用場景
- 需要高度數(shù)據(jù)一致性的應(yīng)用,如金融系統(tǒng)、訂單處理系統(tǒng)等。
 
示例
- T1 開始一個事務(wù)并讀取某范圍內(nèi)的行。
 - T2 在該范圍內(nèi)插入新行并提交。
 - T1 再次讀取同一范圍的行,不會看到 T2 插入的新行(防止幻讀,但在某些條件下仍可能看到)。
 
2.4 SERIALIZABLE(串行化)
定義
這是最高的隔離級別,要求事務(wù)必須順序執(zhí)行,以避免并發(fā)問題。在此級別下,事務(wù)會對讀取的數(shù)據(jù)加鎖,防止其他事務(wù)對其進行修改或插入。
特點
- 完全防止并發(fā)問題:防止臟讀、不可重復(fù)讀和幻讀。
 - 事務(wù)串行執(zhí)行:實際上將并發(fā)事務(wù)轉(zhuǎn)換為串行執(zhí)行,確保數(shù)據(jù)的一致性。
 - 并發(fā)性能低:由于事務(wù)需要等待彼此完成,嚴(yán)重限制了并發(fā)性能。
 
優(yōu)點
- 最高的數(shù)據(jù)一致性:確保在任何情況下都不會出現(xiàn)并發(fā)問題。
 - 簡單實現(xiàn):不需要復(fù)雜的并發(fā)控制機制。
 
缺點
- 極低的并發(fā)性能:事務(wù)需要串行執(zhí)行,極大地影響了系統(tǒng)的吞吐量和響應(yīng)時間。
 - 容易造成鎖爭用和死鎖:高并發(fā)環(huán)境下容易導(dǎo)致鎖等待和死鎖。
 
適用場景
- 對數(shù)據(jù)一致性要求極高的場景,且可以接受較低的并發(fā)性能,如銀行交易系統(tǒng)。
 
示例
- T1 開始一個事務(wù)并讀取某范圍內(nèi)的行。
 - T2 嘗試在該范圍內(nèi)插入新行,但由于 T1 的鎖,T2 必須等待 T1 完成。
 - T1 完成后,T2 才能插入新行,確保數(shù)據(jù)的一致性。
 
3. MySQL 中的隔離級別設(shè)置
在 MySQL 中,可以通過以下方式設(shè)置事務(wù)的隔離級別:
3.1 查看當(dāng)前的隔離級別
SHOW VARIABLES LIKE 'transaction_isolation';
或者
SELECT @@GLOBAL.transaction_isolation, @@SESSION.transaction_isolation;
3.2 設(shè)置全局隔離級別
設(shè)置全局隔離級別會影響所有新連接,當(dāng)前已經(jīng)存在的會話不會受到影響。
SET GLOBAL TRANSACTION ISOLATION LEVEL SERIALIZABLE;
3.3 設(shè)置當(dāng)前會話的隔離級別
設(shè)置當(dāng)前會話的隔離級別,只影響當(dāng)前會話及之后新建的子會話。
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
3.4 設(shè)置下一個事務(wù)的隔離級別
僅對下一個事務(wù)生效,事務(wù)結(jié)束后恢復(fù)到之前的隔離級別。
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; START TRANSACTION; -- 事務(wù)內(nèi)容 COMMIT;
4. 不同隔離級別的并發(fā)問題對比
| 隔離級別 | 臟讀(Dirty Read) | 不可重復(fù)讀(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:讀未提交導(dǎo)致臟讀
場景:電商系統(tǒng)中,訂單支付和庫存扣減。
- T1(事務(wù)1):開始支付訂單,減少庫存,但尚未提交。
 - T2(事務(wù)2):查詢訂單狀態(tài)和庫存,看到 T1 的未提交修改(庫存減少)。
 - T1:回滾事務(wù),庫存恢復(fù),但 T2 已經(jīng)基于臟數(shù)據(jù)進行了后續(xù)操作。
 
結(jié)果:庫存數(shù)據(jù)不一致,可能導(dǎo)致超賣。
案例 2:讀已提交避免臟讀,但可能出現(xiàn)不可重復(fù)讀
場景:銀行轉(zhuǎn)賬系統(tǒng),賬戶余額查詢和更新。
- T1:查詢賬戶 A 的余額。
 - T2:向賬戶 A 轉(zhuǎn)賬,更新余額并提交。
 - T1:再次查詢賬戶 A 的余額,看到 T2 的修改(不可重復(fù)讀)。
 
結(jié)果:雖然避免了臟讀,但同一事務(wù)內(nèi)多次讀取同一數(shù)據(jù)得到不同結(jié)果,可能導(dǎo)致邏輯錯誤。
案例 3:可重復(fù)讀保證一致性
場景:在線訂票系統(tǒng),查詢和預(yù)訂座位。
- T1:查詢某趟列車的剩余座位,顯示有空位。
 - T2:在同一列車上預(yù)訂一個座位并提交。
 - T1:再次查詢剩余座位,仍然顯示之前的結(jié)果(不變),因為使用了可重復(fù)讀。
 
結(jié)果:確保了 T1 在事務(wù)內(nèi)看到的一致性,避免了不可重復(fù)讀和幻讀。
案例 4:串行化確保最高一致性
場景:股票交易系統(tǒng),訂單匹配和執(zhí)行。
- T1:查詢某股票的買賣盤,找到匹配的買單。
 - T2:在同一時間嘗試修改同一股票的買賣盤,但由于 T1 的鎖,T2 必須等待。
 - T1:完成訂單匹配和執(zhí)行后,T2 才能繼續(xù)操作。
 
結(jié)果:確保了數(shù)據(jù)的高度一致性,避免了所有并發(fā)問題,但犧牲了并發(fā)性能。
到此這篇關(guān)于MySQL中隔離級別的4種小結(jié)的文章就介紹到這了,更多相關(guān)MySQL 隔離級別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
 MySQL中distinct與group by語句的一些比較及用法講解
這篇文章主要介紹了MySQL中distinct與group by的一些比較及用法講解,二者在查詢操作中的用法有很多相似之處,需要的朋友可以參考下2016-01-01
 解決Mysql 8.0.17 winx64版本安裝過程中遇到的問題
這篇文章主要介紹了Mysql 8.0.17 winx64版本安裝過程中遇到的問題 ,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-08-08
 mySQL之關(guān)鍵字的執(zhí)行優(yōu)先級講解
這篇文章主要介紹了mySQL之關(guān)鍵字的執(zhí)行優(yōu)先級講解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11
 window10系統(tǒng)下mysql5.7安裝審計插件(親測有用)
mysql有沒oracle這樣的審計功能,突然想在mysql做審計怎么辦,下面帶大家從零開始給mysql安裝審計插件,親測絕對可用哦,需要的朋友可以參考下2022-09-09
 使用phpMyAdmin批量修改Mysql數(shù)據(jù)表前綴的方法
這篇文章主要介紹了使用phpMyAdmin批量修改Mysql數(shù)據(jù)表前綴的方法,需要的朋友可以參考下2015-09-09
 mybatis-plus分頁傳入?yún)?shù)后sql where條件沒有l(wèi)imit分頁信息操作
這篇文章主要介紹了mybatis-plus分頁傳入?yún)?shù)后sql where條件沒有l(wèi)imit分頁信息操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11
 php開啟mysqli擴展之后如何連接數(shù)據(jù)庫
Mysqli是php5之后才有的功能,沒有開啟擴展的朋友可以打開您的php.ini的配置文件;相對于mysql有很多新的特性和優(yōu)勢,需要了解的朋友可以參考下2012-12-12

