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