MySQL事務(wù)隔離級(jí)別詳解
1. 開啟事務(wù)start transaction,可以簡(jiǎn)寫為 begin2. 然后記錄之后需要執(zhí)行的一組sql 3. 提交commit 4. 如果所有的sql都執(zhí)行成功,則提交,將sql的執(zhí)行結(jié)果持久化到數(shù)據(jù)表內(nèi)。 5. 回滾rollback 6. 如果存在失敗的sql,則需要回滾,將sql的執(zhí)行結(jié)果,退回到事務(wù)開始之時(shí) 7. 無論回滾還是提交,都會(huì)關(guān)閉事務(wù)!需要再次開啟,才能使用。 8. 還有一點(diǎn)需要注意,就是事務(wù)只針對(duì)當(dāng)前連接。
下面我們來進(jìn)行演示:
使用第一個(gè)鏈接A,開啟事務(wù)后,執(zhí)行一條update語(yǔ)句。 結(jié)果成功,數(shù)據(jù)已經(jīng)變成修改之后!

此時(shí)我們沒有提交。 再?gòu)钠渌B接B來查看,發(fā)現(xiàn)數(shù)據(jù)末更改:

此時(shí)如果連接A選擇提交,也就是commit操作。則連接B的數(shù)據(jù)也會(huì)發(fā)生變化。
而如果連接A選擇回滾,也就是rollback操作。則連接A再次查詢則發(fā)現(xiàn)數(shù)據(jù)還原。
語(yǔ)法說完了,浮躁的人也不用繼續(xù)看下去了。下面簡(jiǎn)單說一下事務(wù)的基本原理吧。提交,就會(huì)將結(jié)果持久化,不提交就不會(huì)。
如果我們不開啟事務(wù),只執(zhí)行一條sql,馬上就會(huì)持久化數(shù)據(jù),可以看出,普通的執(zhí)行就是立即提交。 這是因?yàn)镸ySQL默認(rèn)對(duì)sql語(yǔ)句的執(zhí)行是自動(dòng)提交的。
也就是說,開啟事務(wù),實(shí)際上就是關(guān)閉了自動(dòng)提交的功能,改成了commit手動(dòng)提交!
我們可以通過簡(jiǎn)單的對(duì)是否自動(dòng)提交加以設(shè)置,完成開啟事務(wù)的目的!自動(dòng)提交的特征是保存在服務(wù)的一個(gè)autocommit的變量?jī)?nèi)。可以進(jìn)行修改:
set autocommit = 0;關(guān)閉
set autocommit = 1;開啟還需要注意一點(diǎn),就是事務(wù)類似于外鍵約束,只被innodb引擎支持。
下面來說說事務(wù)的特點(diǎn)ACID。也就是原子性,一致性,隔離性和持久性。
原子性:事務(wù)的一組操作是原子的不可再分割的,這組操作要么同時(shí)完成要么同時(shí)不完成。類似于一個(gè)CAS(compare and swap)(有時(shí)間會(huì)講解cas)
一致性:事務(wù)在執(zhí)行前后數(shù)據(jù)的完整性保持不變。(例:原本的外鍵約束在進(jìn)行事務(wù)成功后不會(huì)損壞)
隔離:當(dāng)多個(gè)事務(wù)同時(shí)操作一個(gè)數(shù)據(jù)庫(kù)時(shí),可能存在并發(fā)問題,此時(shí)應(yīng)保證各個(gè)事務(wù)要進(jìn)行隔離,事務(wù)之間不能互相干擾。
持久性:事務(wù)一旦被提交,就不可能再被回滾!
事務(wù)并發(fā)會(huì)帶來一些問題,所以才有了不同的事務(wù)隔離級(jí)別。要想了解事務(wù)的隔離級(jí)別,就必須首先了解事務(wù)并發(fā)會(huì)帶來的問題。一般來說,會(huì)出現(xiàn)三類數(shù)據(jù)讀問題和數(shù)據(jù)更新問題。
一個(gè)事務(wù)正在對(duì)一條記錄做修改,但未提交,另一個(gè)事務(wù)讀取了這些臟數(shù)據(jù),并進(jìn)一步處理,就會(huì)產(chǎn)生未提交的數(shù)據(jù)依賴。舉一個(gè)例子:
| 時(shí)間 | 轉(zhuǎn)賬事務(wù)A | 取款事務(wù)B |
|---|---|---|
| T1 | 開始事務(wù) | |
| T2 | 開始事務(wù) | |
| T3 | 查詢賬戶余額為1000元 | |
| T4 | 取出500元把余額改為500元 | |
| T5 | 查詢賬戶余額為500元(臟讀) | |
| T6 | 撤銷事務(wù)余額恢復(fù)為1000元 | |
| T7 | 匯入100元把余額改為600元 | |
| T8 | 提交事務(wù) |
A讀取了B尚未提交的臟數(shù),導(dǎo)致最后余額為600元。
一個(gè)事務(wù)在不同時(shí)間讀取數(shù)據(jù)不一致。 舉一個(gè)例子:
| 時(shí)間 | 取款事務(wù)A | 轉(zhuǎn)賬事務(wù)B |
|---|---|---|
| T1 | 開始事務(wù) | |
| T2 | 開始事務(wù) | |
| T3 | 查詢賬戶余額為1000元 | |
| T4 | 查詢賬戶余額為1000元 | |
| T5 | 取出100元把余額改為900元 | |
| T6 | 提交事務(wù) | |
| T7 | 查詢賬戶余額為900元(和T4讀取的不一致) |
可以看到最后讀取的數(shù)據(jù)不一致。
幻讀和不可重復(fù)讀的概念類似,都是不同時(shí)間數(shù)據(jù)不一致,只不過幻讀是針對(duì)新增數(shù)據(jù),而不可重復(fù)讀是針對(duì)更改數(shù)據(jù)。看一個(gè)例子:
| 時(shí)間 | 統(tǒng)計(jì)金額事務(wù)A | 轉(zhuǎn)賬事務(wù)B |
|---|---|---|
| T1 | 開始事務(wù) | |
| T2 | 開始事務(wù) | |
| T3 | 統(tǒng)計(jì)總存款數(shù)為10000元 | |
| T4 | 新增一個(gè)存款賬戶,存款為100元 | |
| T5 | 提交事務(wù) | |
| T6 | 再次統(tǒng)計(jì)總存款數(shù)為10100元(幻象讀) |
事務(wù)并發(fā)帶來的問題前文已經(jīng)描述得非常仔細(xì)了。事務(wù)的隔離級(jí)別就是為了針對(duì)并發(fā)出現(xiàn)的問題,不同的級(jí)別可以保證不同的一致性。
為了解決上面講到的并發(fā)事務(wù)處理帶來的問題,SQL標(biāo)準(zhǔn)提出了4個(gè)等級(jí)的事務(wù)隔離級(jí)別。不同的隔離級(jí)別在同樣的環(huán)境下會(huì)出現(xiàn)不同的結(jié)果。
隔離級(jí)別設(shè)置及查看
mysql> select @@tx_isolation;+-----------------+| @@tx_isolation |+-----------------+| REPEATABLE-READ |+-----------------+1 row in set (0.00 sec)mysql> set tx_isolation = 0; (備注:0 - 3 對(duì)應(yīng)數(shù)據(jù)庫(kù)四種隔離級(jí)別)Query OK, 0 rows affected (0.00 sec)
下面看看四種隔離級(jí)別的比較:
Read Uncommitted(讀取未提交內(nèi)容)
在該隔離級(jí)別,所有事務(wù)都可以看到其他未提交事務(wù)的執(zhí)行結(jié)果。本隔離級(jí)別很少用于實(shí)際應(yīng)用,因?yàn)樗男阅芤膊槐绕渌?jí)別好多少。讀取未提交的數(shù)據(jù),也被稱之為臟讀(Dirty Read)。
Read Committed(讀取提交內(nèi)容)
這是大多數(shù)數(shù)據(jù)庫(kù)系統(tǒng)的默認(rèn)隔離級(jí)別(但不是MySQL默認(rèn)的)。它滿足了隔離的簡(jiǎn)單定義:一個(gè)事務(wù)只能看見已經(jīng)提交事務(wù)所做的改變。這種隔離級(jí)別也支持所謂的不可重復(fù)讀(Nonrepeatable Read),因?yàn)橥皇聞?wù)的其他實(shí)例在該實(shí)例處理其間可能會(huì)有新的commit,所以同一select可能返回不同結(jié)果。
Repeatable Read(可重讀)
這是MySQL的默認(rèn)事務(wù)隔離級(jí)別,它確保同一事務(wù)的多個(gè)實(shí)例在并發(fā)讀取數(shù)據(jù)時(shí),會(huì)看到同樣的數(shù)據(jù)行。不過理論上,這會(huì)導(dǎo)致另一個(gè)棘手的問題:幻讀(Phantom Read)。簡(jiǎn)單的說,幻讀指當(dāng)用戶讀取某一范圍的數(shù)據(jù)行時(shí),另一個(gè)事務(wù)又在該范圍內(nèi)插入了新行,當(dāng)用戶再讀取該范圍的數(shù)據(jù)行時(shí),會(huì)發(fā)現(xiàn)有新的“幻影”行。InnoDB和Falcon存儲(chǔ)引擎通過多版本并發(fā)控制(MVCC,Multiversion Concurrency Control)機(jī)制解決了該問題。
Serializable(可串行化) 這是最高的隔離級(jí)別,它通過強(qiáng)制事務(wù)排序,使之不可能相互沖突,從而解決幻讀問題。簡(jiǎn)言之,它是在每個(gè)讀的數(shù)據(jù)行上加上共享鎖。在這個(gè)級(jí)別,可能導(dǎo)致大量的超時(shí)現(xiàn)象和鎖競(jìng)爭(zhēng)。
| 隔離級(jí)別 | 讀數(shù)據(jù)一致性 | 臟讀 | 不可重復(fù)讀 | 幻讀 |
|---|---|---|---|---|
| 未提交讀(Read uncommitted) | 最低級(jí)別,只能保證不讀取物理上損壞的數(shù)據(jù) | 是 | 是 | 是 |
| 已提交讀(Read committed) | 語(yǔ)句級(jí) | 否 | 是 | 是 |
| 可重復(fù)讀(Repeatable read) | 事務(wù)級(jí) | 否 | 否 | 是 |
| 可序列化(Serializable) | 最高級(jí)別,事務(wù)級(jí) | 否 | 否 | 否 |
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注