MySQL事務(wù)隔離級(jí)別是數(shù)據(jù)庫(kù)為解決并發(fā)事務(wù)間數(shù)據(jù)一致性問題而設(shè)計(jì)的核心機(jī)制,其核心作用是控制一個(gè)事務(wù)對(duì)另一個(gè)事務(wù)提交數(shù)據(jù)的可見性,平衡事務(wù)的一致性(ACID中的I,隔離性)與系統(tǒng)并發(fā)性能。MySQL共支持4種標(biāo)準(zhǔn)隔離級(jí)別(由低到高排序),默認(rèn)隔離級(jí)別為「可重復(fù)讀」,不同級(jí)別對(duì)應(yīng)不同的并發(fā)問題解決方案,以下從核心概念、各級(jí)別詳解、實(shí)操命令、注意事項(xiàng)等維度全面拆解。
一、核心前置概念
在理解隔離級(jí)別前,需先明確并發(fā)事務(wù)中常見的3類數(shù)據(jù)一致性問題(隔離級(jí)別本質(zhì)就是解決這些問題),按影響程度從高到低排序:
臟讀(Dirty Read):一個(gè)事務(wù)讀取到另一個(gè)事務(wù)未提交的數(shù)據(jù)。未提交的數(shù)據(jù)可能因事務(wù)回滾而失效,導(dǎo)致讀取到“無(wú)效數(shù)據(jù)”,破壞數(shù)據(jù)準(zhǔn)確性。
不可重復(fù)讀(Non-Repeatable Read):同一事務(wù)內(nèi),多次讀取同一批數(shù)據(jù),結(jié)果不一致。原因是兩次讀取之間,其他事務(wù)修改并提交了該批數(shù)據(jù),破壞事務(wù)內(nèi)數(shù)據(jù)的一致性。
幻讀(Phantom Read):同一事務(wù)內(nèi),多次執(zhí)行相同的查詢語(yǔ)句(如范圍查詢),返回的結(jié)果行數(shù)不一致。原因是兩次查詢之間,其他事務(wù)新增或刪除了符合查詢條件的數(shù)據(jù),類似“出現(xiàn)了幻影數(shù)據(jù)”。
補(bǔ)充說(shuō)明:隔離級(jí)別越高,對(duì)并發(fā)的限制越嚴(yán)格,能解決的并發(fā)問題越多,但系統(tǒng)性能損耗越大;反之,隔離級(jí)別越低,性能越好,但數(shù)據(jù)一致性風(fēng)險(xiǎn)越高。開發(fā)中需根據(jù)業(yè)務(wù)場(chǎng)景選擇合適的隔離級(jí)別,而非盲目追求最高級(jí)別。
二、MySQL 4種事務(wù)隔離級(jí)別詳解(重點(diǎn))
MySQL支持的4種隔離級(jí)別完全遵循SQL標(biāo)準(zhǔn),且針對(duì)默認(rèn)級(jí)別(可重復(fù)讀)做了專屬優(yōu)化,以下逐一詳解,包含核心定義、解決的并發(fā)問題、存在的不足、適用場(chǎng)景及實(shí)操命令。
1. 讀未提交(Read Uncommitted,最低隔離級(jí)別)
核心定義
一個(gè)事務(wù)可以讀取到另一個(gè)事務(wù)尚未提交的修改數(shù)據(jù),無(wú)需等待對(duì)方提交。這是隔離級(jí)別最低的一種,幾乎沒有隔離性可言。
并發(fā)問題處理
僅保證事務(wù)的原子性(要么全做,要么全不做),無(wú)法解決任何并發(fā)問題——臟讀、不可重復(fù)讀、幻讀均會(huì)出現(xiàn)。
典型場(chǎng)景
極少在實(shí)際開發(fā)中使用,僅適用于對(duì)數(shù)據(jù)一致性要求極低、追求極致并發(fā)性能的臨時(shí)場(chǎng)景,例如:臨時(shí)統(tǒng)計(jì)系統(tǒng)的粗略數(shù)據(jù)(無(wú)需精準(zhǔn),僅需快速返回結(jié)果)、測(cè)試環(huán)境的臨時(shí)數(shù)據(jù)查詢。
實(shí)操命令
設(shè)置當(dāng)前會(huì)話隔離級(jí)別:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;驗(yàn)證:開啟兩個(gè)會(huì)話,會(huì)話1開啟事務(wù)并修改數(shù)據(jù)(不提交),會(huì)話2可直接讀取到未提交的數(shù)據(jù)。
2. 讀已提交(Read Committed,常用普通級(jí)別)
核心定義
一個(gè)事務(wù)只能讀取到另一個(gè)事務(wù)已經(jīng)提交的修改數(shù)據(jù),無(wú)法讀取未提交的數(shù)據(jù)。這是大多數(shù)數(shù)據(jù)庫(kù)(如Oracle、SQL Server)的默認(rèn)隔離級(jí)別。
并發(fā)問題處理
解決了臟讀(僅讀取已提交數(shù)據(jù),避免無(wú)效數(shù)據(jù)),但仍存在不可重復(fù)讀、幻讀。
示例:會(huì)話1開啟事務(wù),第一次讀取數(shù)據(jù)為100;會(huì)話2開啟事務(wù),修改數(shù)據(jù)為200并提交;會(huì)話1再次讀取同一數(shù)據(jù),結(jié)果變?yōu)?00,即“不可重復(fù)讀”。
典型場(chǎng)景
適用于大多數(shù)普通業(yè)務(wù)場(chǎng)景,兼顧性能和基礎(chǔ)數(shù)據(jù)一致性,例如:電商訂單查詢、用戶信息展示、普通數(shù)據(jù)統(tǒng)計(jì)(無(wú)需事務(wù)內(nèi)多次讀取一致)、內(nèi)容管理系統(tǒng)。
實(shí)操命令
設(shè)置當(dāng)前會(huì)話隔離級(jí)別:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;驗(yàn)證:會(huì)話1未提交的修改,會(huì)話2無(wú)法讀??;會(huì)話1提交后,會(huì)話2才能讀取到最新數(shù)據(jù)。
3. 可重復(fù)讀(Repeatable Read,MySQL 默認(rèn)級(jí)別)
核心定義
同一事務(wù)內(nèi),多次讀取同一批數(shù)據(jù),結(jié)果始終保持一致(即便其他事務(wù)修改并提交了該數(shù)據(jù))。這是MySQL的默認(rèn)隔離級(jí)別,也是實(shí)際開發(fā)中最常用的級(jí)別。
MySQL專屬優(yōu)化
MySQL通過(guò)「MVCC(多版本并發(fā)控制)」機(jī)制對(duì)可重復(fù)讀進(jìn)行了優(yōu)化:事務(wù)開啟時(shí),會(huì)生成一個(gè)“一致性視圖”(快照),后續(xù)所有讀取操作都基于這個(gè)快照,不受其他事務(wù)提交的影響。因此,MySQL的可重復(fù)讀的實(shí)際效果優(yōu)于SQL標(biāo)準(zhǔn),能大幅減少幻讀的出現(xiàn)(僅極端場(chǎng)景下會(huì)存在幻讀)。
并發(fā)問題處理
解決了臟讀、不可重復(fù)讀,基本避免幻讀(極端場(chǎng)景除外)。
極端幻讀示例:會(huì)話1開啟事務(wù),查詢“id>10”的所有數(shù)據(jù)(共5條);會(huì)話2開啟事務(wù),新增一條id=11的數(shù)據(jù)并提交;會(huì)話1再次執(zhí)行相同查詢,仍返回5條數(shù)據(jù)(基于快照);但會(huì)話1執(zhí)行更新操作(如更新id>10的所有數(shù)據(jù)),會(huì)更新到6條數(shù)據(jù)(包含新增的id=11),此時(shí)再查詢,會(huì)返回6條數(shù)據(jù),即“幻讀”。
典型場(chǎng)景
適用于絕大多數(shù)業(yè)務(wù)場(chǎng)景,尤其是對(duì)事務(wù)內(nèi)數(shù)據(jù)一致性有要求、同時(shí)需要兼顧并發(fā)性能的場(chǎng)景,例如:金融對(duì)賬、用戶余額管理、訂單創(chuàng)建與支付、數(shù)據(jù)批量處理。
實(shí)操命令
設(shè)置當(dāng)前會(huì)話隔離級(jí)別:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;驗(yàn)證:會(huì)話1開啟事務(wù)后,會(huì)話2修改并提交的數(shù)據(jù),會(huì)話1多次讀取仍為初始快照數(shù)據(jù);會(huì)話1提交后,才能讀取到最新數(shù)據(jù)。
4. 串行化(Serializable,最高隔離級(jí)別)
核心定義
最高隔離級(jí)別,所有事務(wù)按順序依次執(zhí)行(類似單線程執(zhí)行),不允許并發(fā)執(zhí)行。事務(wù)執(zhí)行時(shí),會(huì)對(duì)涉及的表或行加鎖,其他事務(wù)需等待當(dāng)前事務(wù)完成后才能執(zhí)行,完全杜絕所有并發(fā)問題。
并發(fā)問題處理
完全解決臟讀、不可重復(fù)讀、幻讀,數(shù)據(jù)一致性達(dá)到最高,但并發(fā)性能最差。
注意:串行化會(huì)導(dǎo)致大量鎖等待、超時(shí),甚至死鎖,僅在極端場(chǎng)景下使用。
典型場(chǎng)景
適用于對(duì)數(shù)據(jù)一致性要求極高、不考慮并發(fā)性能損耗的核心場(chǎng)景,例如:金融支付、資金轉(zhuǎn)賬、賬務(wù)結(jié)算、核心業(yè)務(wù)的庫(kù)存扣減(不允許任何數(shù)據(jù)不一致)。
實(shí)操命令
設(shè)置當(dāng)前會(huì)話隔離級(jí)別:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;驗(yàn)證:會(huì)話1開啟事務(wù)并操作數(shù)據(jù)(未提交),會(huì)話2執(zhí)行相同表的操作會(huì)被阻塞,直至?xí)?提交或回滾。
三、4種隔離級(jí)別與并發(fā)問題對(duì)應(yīng)表(核心匯總)
| 事務(wù)隔離級(jí)別 | 臟讀 | 不可重復(fù)讀 | 幻讀 | 并發(fā)性能 | 適用場(chǎng)景 |
|---|---|---|---|---|---|
| 讀未提交 | ? 存在 | ? 存在 | ? 存在 | 最高 | 臨時(shí)粗略統(tǒng)計(jì)、測(cè)試環(huán)境 |
| 讀已提交 | ? 不存在 | ? 存在 | ? 存在 | 較高 | 普通業(yè)務(wù)、訂單查詢、數(shù)據(jù)展示 |
| 可重復(fù)讀(默認(rèn)) | ? 不存在 | ? 不存在 | ?? 極少存在 | 中等 | 絕大多數(shù)業(yè)務(wù)、金融對(duì)賬、余額管理 |
| 串行化 | ? 不存在 | ? 不存在 | ? 不存在 | 最低 | 金融支付、資金轉(zhuǎn)賬、核心賬務(wù) |
四、實(shí)操常用命令(必記)
以下命令適用于MySQL 8.0及以上版本(5.7版本命令類似,僅變量名略有差異,如transaction_isolation可替換為tx_isolation),分為“查看”和“設(shè)置”兩類,方便日常排查和配置。
1. 查看隔離級(jí)別
查看當(dāng)前會(huì)話隔離級(jí)別(僅對(duì)當(dāng)前連接有效):
SELECT @@transaction_isolation;查看全局隔離級(jí)別(對(duì)所有新連接有效,不影響已存在的連接):
SELECT @@global.transaction_isolation;
2. 設(shè)置隔離級(jí)別
設(shè)置當(dāng)前會(huì)話隔離級(jí)別(臨時(shí)生效,關(guān)閉連接后失效):
SET TRANSACTION ISOLATION LEVEL 隔離級(jí)別名稱;(如SET TRANSACTION ISOLATION LEVEL READ COMMITTED;)設(shè)置全局隔離級(jí)別(永久生效,需重啟MySQL服務(wù)):
SET GLOBAL TRANSACTION ISOLATION LEVEL 隔離級(jí)別名稱;配置文件設(shè)置(永久生效,無(wú)需頻繁執(zhí)行命令):修改MySQL配置文件(my.cnf/my.ini),添加
transaction-isolation=隔離級(jí)別名稱(如transaction-isolation=REPEATABLE READ),保存后重啟MySQL。
五、關(guān)鍵注意事項(xiàng)(避坑重點(diǎn))
隔離級(jí)別與事務(wù)生效的區(qū)別:隔離級(jí)別不影響事務(wù)本身是否生效(如回滾、提交),僅影響并發(fā)事務(wù)間的數(shù)據(jù)可見性。很多開發(fā)者會(huì)將“隔離級(jí)別設(shè)置不當(dāng)導(dǎo)致的數(shù)據(jù)不一致”誤判為“事務(wù)不生效”,需注意區(qū)分。
默認(rèn)級(jí)別不可隨意修改:MySQL默認(rèn)的“可重復(fù)讀”已能滿足絕大多數(shù)業(yè)務(wù)需求,除非有明確的業(yè)務(wù)場(chǎng)景(如金融支付),否則不建議修改為“串行化”(會(huì)嚴(yán)重影響性能),也不建議降低為“讀未提交”(數(shù)據(jù)一致性無(wú)法保證)。
MVCC僅適用于InnoDB引擎:MySQL的MVCC機(jī)制(優(yōu)化可重復(fù)讀)僅對(duì)InnoDB引擎有效,MyISAM等非事務(wù)引擎不支持隔離級(jí)別,也不支持MVCC,需確保表使用InnoDB引擎。
全局隔離級(jí)別對(duì)已有連接無(wú)效:設(shè)置全局隔離級(jí)別后,僅對(duì)設(shè)置后新建立的數(shù)據(jù)庫(kù)連接有效,已存在的連接仍使用之前的隔離級(jí)別,需重啟連接或手動(dòng)設(shè)置當(dāng)前會(huì)話級(jí)別。
避免過(guò)度追求高隔離級(jí)別:高隔離級(jí)別意味著高鎖開銷、低并發(fā),需根據(jù)業(yè)務(wù)優(yōu)先級(jí)權(quán)衡——核心數(shù)據(jù)(資金、賬務(wù))用串行化,普通數(shù)據(jù)用讀已提交/可重復(fù)讀,臨時(shí)數(shù)據(jù)用讀未提交。
幻讀的補(bǔ)充說(shuō)明:MySQL的可重復(fù)讀通過(guò)MVCC避免了大部分幻讀,若需完全杜絕幻讀,可使用串行化,或在查詢時(shí)加行鎖/表鎖(如SELECT ... FOR UPDATE)。
六、總結(jié)
MySQL事務(wù)隔離級(jí)別的核心是“平衡一致性與并發(fā)性能”,4種級(jí)別各有適用場(chǎng)景,無(wú)需盲目追求最高級(jí)別。實(shí)際開發(fā)中,建議遵循以下原則:
無(wú)特殊需求,直接使用默認(rèn)的“可重復(fù)讀”,兼顧一致性和性能;
普通業(yè)務(wù)(如展示、查詢),可使用“讀已提交”,提升并發(fā)性能;
核心數(shù)據(jù)(如資金、賬務(wù)),使用“串行化”,確保數(shù)據(jù)絕對(duì)一致;
臨時(shí)統(tǒng)計(jì)、測(cè)試場(chǎng)景,可臨時(shí)使用“讀未提交”,追求極致性能。
同時(shí),需牢記隔離級(jí)別的實(shí)操命令和避坑注意事項(xiàng),避免因配置不當(dāng)導(dǎo)致數(shù)據(jù)不一致,或因過(guò)度追求高隔離級(jí)別導(dǎo)致系統(tǒng)性能瓶頸。