MySQL中的事務(wù)隔離級(jí)別詳解
一、事務(wù)并發(fā)問題
在多個(gè)事務(wù)同時(shí)操作同一份數(shù)據(jù)時(shí),可能會(huì)出現(xiàn)以下幾種并發(fā)問題:
- 臟讀(Dirty Read):一個(gè)事務(wù)讀取了另一個(gè)未提交事務(wù)修改的數(shù)據(jù),如果后者回滾,則前者讀取到的數(shù)據(jù)是無效的。
- 不可重復(fù)讀(Non-repeatable Read):同一個(gè)事務(wù)中,執(zhí)行兩次相同的查詢,由于另一個(gè)事務(wù)的提交,查詢結(jié)果不同。
- 幻讀(Phantom Read):一個(gè)事務(wù)在兩次查詢之間,另一事務(wù)插入或刪除了數(shù)據(jù),導(dǎo)致前后查詢的記錄數(shù)不一致。
為了避免這些問題,SQL 標(biāo)準(zhǔn)定義了四種事務(wù)隔離級(jí)別,MySQL 也支持這四種級(jí)別。
二、MySQL 事務(wù)隔離級(jí)別
MySQL 通過 SET TRANSACTION ISOLATION LEVEL 語句來設(shè)置事務(wù)隔離級(jí)別:
SET SESSION TRANSACTION ISOLATION LEVEL <級(jí)別>; SET GLOBAL TRANSACTION ISOLATION LEVEL <級(jí)別>;
其中 <級(jí)別> 可以是 READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 或 SERIALIZABLE。
1. READ UNCOMMITTED(讀未提交)
特點(diǎn):
- 事務(wù)可以讀取其他未提交事務(wù)的數(shù)據(jù)。
- 可能發(fā)生“臟讀”問題。
- 性能較好,因?yàn)椴粫?huì)使用鎖限制讀取。
示例:
- 事務(wù)A修改了一條記錄但尚未提交。
- 事務(wù)B在事務(wù)A提交之前讀取了修改后的數(shù)據(jù)。
- 如果事務(wù)A回滾,那么事務(wù)B讀取到的數(shù)據(jù)就是“臟數(shù)據(jù)”。
適用場(chǎng)景:
- 允許讀取未提交的數(shù)據(jù),適用于不太關(guān)心數(shù)據(jù)一致性的應(yīng)用,如日志記錄、監(jiān)控?cái)?shù)據(jù)等。
2. READ COMMITTED(讀已提交)
特點(diǎn):
- 只能讀取已經(jīng)提交的數(shù)據(jù),避免了“臟讀”。
- 可能發(fā)生“不可重復(fù)讀”問題。
- MySQL InnoDB 通過 MVCC(多版本并發(fā)控制)來實(shí)現(xiàn)此隔離級(jí)別。
示例:
- 事務(wù)A讀取一條記錄。
- 事務(wù)B修改該記錄并提交。
- 事務(wù)A再次讀取該記錄,發(fā)現(xiàn)數(shù)據(jù)發(fā)生了變化(不可重復(fù)讀)。
適用場(chǎng)景:
- 適用于大多數(shù) OLTP(在線事務(wù)處理)系統(tǒng),如銀行轉(zhuǎn)賬、訂單管理系統(tǒng),保證讀取的數(shù)據(jù)是已提交的但允許數(shù)據(jù)更新。
3. REPEATABLE READ(可重復(fù)讀)(MySQL 默認(rèn)級(jí)別)
特點(diǎn):
- 事務(wù)內(nèi)多次讀取同一條數(shù)據(jù)時(shí),數(shù)據(jù)保持一致(即使其他事務(wù)修改并提交了數(shù)據(jù))。
- 通過 MVCC 實(shí)現(xiàn)可重復(fù)讀。
- 避免了“臟讀”和“不可重復(fù)讀”。
- 但仍然可能發(fā)生“幻讀”問題。
示例:
- 事務(wù)A第一次讀取某條數(shù)據(jù)。
- 事務(wù)B修改該數(shù)據(jù)并提交。
- 事務(wù)A再次讀取該數(shù)據(jù),發(fā)現(xiàn)數(shù)據(jù)未改變(因?yàn)槭聞?wù)A讀取的是事務(wù)開始時(shí)的快照)。
如何解決幻讀?
- MySQL InnoDB 通過 間隙鎖(Next-Key Locking) 機(jī)制來解決幻讀問題,即鎖住范圍,使得其他事務(wù)無法插入新的數(shù)據(jù),從而防止幻讀。
適用場(chǎng)景:
- 適用于高并發(fā)場(chǎng)景,尤其是金融行業(yè),如銀行賬戶查詢和訂單管理系統(tǒng)。
4. SERIALIZABLE(可串行化)
特點(diǎn):
- 最高級(jí)別的隔離,完全避免臟讀、不可重復(fù)讀和幻讀。
- 事務(wù)必須依次執(zhí)行,不能并行,通常會(huì)使用 表鎖 或 行鎖。
- 并發(fā)性能極差,適用于對(duì)數(shù)據(jù)一致性要求極高的場(chǎng)景。
示例:
- 事務(wù)A讀取某一條數(shù)據(jù),同時(shí)事務(wù)B必須等事務(wù)A完成后才能讀取或修改該數(shù)據(jù)。
適用場(chǎng)景:
- 適用于需要嚴(yán)格數(shù)據(jù)一致性的場(chǎng)景,如財(cái)務(wù)結(jié)算、票務(wù)系統(tǒng)等。
三、MySQL 默認(rèn)事務(wù)隔離級(jí)別
MySQL InnoDB 存儲(chǔ)引擎的默認(rèn)事務(wù)隔離級(jí)別是 REPEATABLE READ(可重復(fù)讀),這與 SQL 標(biāo)準(zhǔn)的默認(rèn)級(jí)別(READ COMMITTED)不同。MySQL 通過 MVCC(多版本并發(fā)控制)和 間隙鎖 解決了幻讀問題,因此 REPEATABLE READ 在 MySQL 中比 SQL 標(biāo)準(zhǔn)更強(qiáng)。
如果想修改默認(rèn)的事務(wù)隔離級(jí)別,可以在 my.cnf(MySQL 配置文件)中修改:
[mysqld] transaction-isolation = REPEATABLE-READ
或在運(yùn)行時(shí)更改:
SET GLOBAL TRANSACTION ISOLATION LEVEL READ COMMITTED;
四、不同隔離級(jí)別對(duì)并發(fā)問題的影響
| 隔離級(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ā)生 ?(MySQL 中不會(huì)) |
| SERIALIZABLE | 不會(huì)發(fā)生 ? | 不會(huì)發(fā)生 ? | 不會(huì)發(fā)生 ? |
五、如何選擇合適的隔離級(jí)別?
- READ UNCOMMITTED:適用于對(duì)數(shù)據(jù)一致性要求不高的場(chǎng)景,如日志分析、緩存數(shù)據(jù)等。
- READ COMMITTED:適用于大多數(shù)業(yè)務(wù)場(chǎng)景,如電商系統(tǒng)、用戶管理系統(tǒng)等,避免臟讀,提高并發(fā)性能。
- REPEATABLE READ(MySQL 默認(rèn)):適用于金融系統(tǒng)、庫存管理,保證事務(wù)內(nèi)數(shù)據(jù)的一致性,防止不可重復(fù)讀。
- SERIALIZABLE:適用于對(duì)數(shù)據(jù)一致性要求極高的場(chǎng)景,如銀行結(jié)算、核心財(cái)務(wù)系統(tǒng),但性能損耗較大。
總結(jié)
- READ UNCOMMITTED:可能發(fā)生臟讀、不可重復(fù)讀、幻讀,性能最高但安全性最低。
- READ COMMITTED:防止臟讀,但可能發(fā)生不可重復(fù)讀和幻讀。
- REPEATABLE READ(MySQL 默認(rèn)):防止臟讀和不可重復(fù)讀,MySQL 還能避免幻讀,適用于大多數(shù)高并發(fā)業(yè)務(wù)。
- SERIALIZABLE:所有并發(fā)問題都能避免,但性能最差。
MySQL 默認(rèn)采用 REPEATABLE READ,主要是因?yàn)?MySQL 通過 MVCC 解決了大部分的并發(fā)問題,既能保持較高的事務(wù)隔離級(jí)別,又不會(huì)影響太多的性能。
MySQL中的事務(wù)隔離級(jí)別有四種,分別為:
讀未提交(Read Uncommitted):
該級(jí)別允許事務(wù)讀取其他事務(wù)尚未提交的數(shù)據(jù)(臟讀)。這意味著一個(gè)事務(wù)可以讀取到另一個(gè)事務(wù)中間狀態(tài)的數(shù)據(jù),可能會(huì)導(dǎo)致數(shù)據(jù)不一致。讀已提交(Read Committed):
該級(jí)別保證事務(wù)只能讀取到已提交的數(shù)據(jù),防止臟讀。即使如此,仍然允許發(fā)生“不可重復(fù)讀”(在同一事務(wù)中兩次讀取同一數(shù)據(jù),值可能不同,因?yàn)榱硪粋€(gè)事務(wù)已經(jīng)修改了數(shù)據(jù)并提交)。可重復(fù)讀(Repeatable Read):
該級(jí)別保證在一個(gè)事務(wù)中多次讀取同一數(shù)據(jù)時(shí),結(jié)果始終一致,避免了“不可重復(fù)讀”。但是,仍然可能會(huì)出現(xiàn)“幻讀”(即事務(wù)讀取的結(jié)果集發(fā)生了變化,因?yàn)榱硪粋€(gè)事務(wù)插入了新的記錄)。串行化(Serializable):
這是最高的隔離級(jí)別,強(qiáng)制事務(wù)串行執(zhí)行,即事務(wù)排隊(duì)執(zhí)行,一個(gè)事務(wù)在完成之前,其他事務(wù)無法訪問相同的數(shù)據(jù)。這可以完全避免臟讀、不可重復(fù)讀和幻讀,但性能會(huì)較低。
到此這篇關(guān)于MySQL中的事務(wù)隔離級(jí)別有哪些的文章就介紹到這了,更多相關(guān)mysql事務(wù)隔離級(jí)別內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 生產(chǎn)環(huán)境的MySQL事務(wù)隔離級(jí)別方式
- MySQL的事務(wù)的基本要素和事務(wù)隔離級(jí)別詳解
- mysql的事務(wù)隔離級(jí)別詳細(xì)解析
- 一文帶你搞懂MySQL的事務(wù)隔離級(jí)別
- 一文帶你了解MySQL之事務(wù)隔離級(jí)別和MVCC
- 解決MySql8.0 查看事務(wù)隔離級(jí)別報(bào)錯(cuò)的問題
- 詳解MySQL中事務(wù)隔離級(jí)別的實(shí)現(xiàn)原理
- mysql、oracle默認(rèn)事務(wù)隔離級(jí)別的說明
- MySQL事務(wù)及Spring隔離級(jí)別實(shí)現(xiàn)原理詳解
- MySQL查看和修改事務(wù)隔離級(jí)別的實(shí)例講解
- MySQL四種事務(wù)隔離級(jí)別詳解
相關(guān)文章
淺析MySQL數(shù)據(jù)的導(dǎo)出與導(dǎo)入知識(shí)點(diǎn)
在本文里我們給大家分享了關(guān)于MySQL數(shù)據(jù)的導(dǎo)出與導(dǎo)入的相關(guān)實(shí)例和知識(shí)點(diǎn)內(nèi)容,需要的朋友們跟著學(xué)習(xí)下。2019-03-03
實(shí)操M(fèi)ySQL+PostgreSQL批量插入更新insertOrUpdate
這篇文章主要介紹了MYsql和PostgreSQL優(yōu)勢(shì)對(duì)比以及如何實(shí)現(xiàn)MySQL + PostgreSQL批量插入更新insertOrUpdate,附含詳細(xì)的InserOrupdate代碼實(shí)例,需要的朋友可以參考下2021-08-08
MySQL占用內(nèi)存較大與CPU過高測(cè)試與解決辦法
為了裝mysql環(huán)境測(cè)試,裝上后發(fā)現(xiàn)啟動(dòng)后MySQL占用內(nèi)存了很大,達(dá)8百多兆。網(wǎng)上搜索了一下,得到高人指點(diǎn)my.ini。再也沒見再詳細(xì)的了..只好打開my.ini逐行的啃,雖然英文差了點(diǎn),不過多少M(fèi)還是看得明的2018-03-03

