概述
事務(wù)(Transaction)是由一系列對(duì)系統(tǒng)中數(shù)據(jù)進(jìn)行訪問與更新的操作所組成的一個(gè)程序執(zhí)行邏輯單元。
ACID
事務(wù)具有4個(gè)基本特征,分別是:原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Duration),簡(jiǎn)稱ACID。隔離級(jí)別
ACID這4個(gè)特征中,最難理解的是隔離性。在標(biāo)準(zhǔn)SQL規(guī)范中,定義了4個(gè)事務(wù)隔離級(jí)別,不同的隔離級(jí)別對(duì)事務(wù)的處理不同。4個(gè)隔離級(jí)別分別是:讀未提及(READ_UNCOMMITTED)、讀已提交(READ_COMMITTED)、可重復(fù)讀(REPEATABLE_READ)、順序讀(SERIALIZABLE)。事務(wù)并發(fā)引起的問題
數(shù)據(jù)庫(kù)在不同的隔離性級(jí)別下并發(fā)訪問可能會(huì)出現(xiàn)以下幾種問題:臟讀(Dirty Read)、不可重復(fù)讀(Unrepeatable Read)、幻讀(Phantom Read)。
事務(wù)的思維導(dǎo)圖

ACID
1. 原子性(Atomicity)
事務(wù)的原子性是指事務(wù)必須是一個(gè)原子的操作序列單元。事務(wù)中包含的各項(xiàng)操作在一次執(zhí)行過程中,只允許出現(xiàn)兩種狀態(tài)之一。
- 全部執(zhí)行成功
- 全部執(zhí)行失敗
任何一項(xiàng)操作都會(huì)導(dǎo)致整個(gè)事務(wù)的失敗,同時(shí)其它已經(jīng)被執(zhí)行的操作都將被撤銷并回滾,只有所有的操作全部成功,整個(gè)事務(wù)才算是成功完成。
2. 一致性(Consistency)
事務(wù)的一致性是指事務(wù)的執(zhí)行不能破壞數(shù)據(jù)庫(kù)數(shù)據(jù)的完整性和一致性,一個(gè)事務(wù)在執(zhí)行之前和執(zhí)行之后,數(shù)據(jù)庫(kù)都必須處以一致性狀態(tài)。
比如:如果從A賬戶轉(zhuǎn)賬到B賬戶,不可能因?yàn)锳賬戶扣了錢,而B賬戶沒有加錢。
3. 隔離性(Isolation)
事務(wù)的隔離性是指在并發(fā)環(huán)境中,并發(fā)的事務(wù)是互相隔離的,一個(gè)事務(wù)的執(zhí)行不能被其它事務(wù)干擾。也就是說,不同的事務(wù)并發(fā)操作相同的數(shù)據(jù)時(shí),每個(gè)事務(wù)都有各自完整的數(shù)據(jù)空間。
一個(gè)事務(wù)內(nèi)部的操作及使用的數(shù)據(jù)對(duì)其它并發(fā)事務(wù)是隔離的,并發(fā)執(zhí)行的各個(gè)事務(wù)是不能互相干擾的。
隔離性分4個(gè)級(jí)別,下面會(huì)介紹。
4. 持久性(Duration)
事務(wù)的持久性是指事務(wù)一旦提交后,數(shù)據(jù)庫(kù)中的數(shù)據(jù)必須被永久的保存下來。即使服務(wù)器系統(tǒng)崩潰或服務(wù)器宕機(jī)等故障。只要數(shù)據(jù)庫(kù)重新啟動(dòng),那么一定能夠?qū)⑵浠謴?fù)到事務(wù)成功結(jié)束后的狀態(tài)。
事務(wù)隔離級(jí)別
1. 讀未提及(READ_UNCOMMITTED)
讀未提及,該隔離級(jí)別允許臟讀取,其隔離級(jí)別是最低的。換句話說,如果一個(gè)事務(wù)正在處理某一數(shù)據(jù),并對(duì)其進(jìn)行了更新,但同時(shí)尚未完成事務(wù),因此還沒有提交事務(wù);而以此同時(shí),允許另一個(gè)事務(wù)也能夠訪問該數(shù)據(jù)。
臟讀示例:
在事務(wù)A和事務(wù)B同時(shí)執(zhí)行時(shí)可能會(huì)出現(xiàn)如下場(chǎng)景:
| 時(shí)間 | 事務(wù)A(存款) | 事務(wù)B(取款) |
|---|---|---|
| T1 | 開始事務(wù) | —— |
| T2 | —— | 開始事務(wù) |
| T3 | —— | 查詢余額(1000元) |
| T4 | —— | 取出1000元(余額0元) |
| T5 | 查詢余額(0元) | —— |
| T6 | —— | 撤銷事務(wù)(余額恢復(fù)1000元) |
| T7 | 存入500元(余額500元) | —— |
| T8 | 提交事務(wù) | —— |
余額應(yīng)該為1500元才對(duì)。請(qǐng)看T5時(shí)間點(diǎn),事務(wù)A此時(shí)查詢的余額為0,這個(gè)數(shù)據(jù)就是臟數(shù)據(jù),他是事務(wù)B造成的,很明顯是事務(wù)沒有進(jìn)行隔離造成的。
2. 讀已提交(READ_COMMITTED)
讀已提交是不同的時(shí)候執(zhí)行的時(shí)候只能獲取到已經(jīng)提交的數(shù)據(jù)。
這樣就不會(huì)出現(xiàn)上面的臟讀的情況了。
不可重復(fù)讀示例
可是解決了臟讀問題,但是還是解決不了可重復(fù)讀問題。
| 時(shí)間 | 事務(wù)A(存款) | 事務(wù)B(取款) |
|---|---|---|
| T1 | 開始事務(wù) | —— |
| T2 | —— | 開始事務(wù) |
| T3 | —— | 查詢余額(1000元) |
| T4 | 查詢余額(1000元) | —— |
| T5 | —— | 取出1000元(余額0元) |
| T6 | —— | 提交事務(wù) |
| T7 | 查詢余額(0元) | —— |
| T8 | 提交事務(wù) | —— |
事務(wù)A其實(shí)除了查詢兩次以外,其它什么事情都沒做,結(jié)果錢就從1000編程0了,這就是不可重復(fù)讀的問題。
3. 可重復(fù)讀(REPEATABLE_READ)
可重復(fù)讀就是保證在事務(wù)處理過程中,多次讀取同一個(gè)數(shù)據(jù)時(shí),該數(shù)據(jù)的值和事務(wù)開始時(shí)刻是一致的。因此該事務(wù)級(jí)別進(jìn)制了不可重復(fù)讀取和臟讀,但是有可能出現(xiàn)幻讀的數(shù)據(jù)。
幻讀
幻讀就是指同樣的事務(wù)操作,在前后兩個(gè)時(shí)間段內(nèi)執(zhí)行對(duì)同一個(gè)數(shù)據(jù)項(xiàng)的讀取,可能出現(xiàn)不一致的結(jié)果。
| 時(shí)間 | 事務(wù)A(統(tǒng)計(jì)總存款) | 事務(wù)B(存款) |
|---|---|---|
| T1 | 開始事務(wù) | —— |
| T2 | —— | 開始事務(wù) |
| T3 | 統(tǒng)計(jì)總存款(1000元) | —— |
| T4 | —— | 存入100元 |
| T5 | —— | 提交事務(wù) |
| T6 | 提交總存款(10100) | —— |
| T7 | 提交事務(wù) | —— |
銀行工作人員在一個(gè)事務(wù)中多次統(tǒng)計(jì)總存款時(shí)看到結(jié)果不一樣。如果要解決幻讀,那只能使用順序讀了。
4. 順序讀(SERIALIZABLE)
順序讀是最嚴(yán)格的事務(wù)隔離級(jí)別。它要求所有的事務(wù)排隊(duì)順序執(zhí)行,即事務(wù)只能一個(gè)接一個(gè)地處理,不能并發(fā)。
事務(wù)隔離級(jí)別對(duì)比
| 事務(wù)隔離級(jí)別 | 臟 讀 | 不可重復(fù)讀 | 幻 讀 |
|---|---|---|---|
| 讀未提及(READ_UNCOMMITTED) | 允許 | 允許 | 允許 |
| 讀已提交(READ_COMMITTED) | 禁止 | 允許 | 允許 |
| 可重復(fù)讀(REPEATABLE_READ) | 禁止 | 禁止 | 允許 |
| 順序讀(SERIALIZABLE) | 禁止 | 禁止 | 禁止 |
4種事務(wù)隔離級(jí)別從上往下,級(jí)別越高,并發(fā)性越差,安全性就越來越高。
一般數(shù)據(jù)默認(rèn)級(jí)別是讀以提交或可重復(fù)讀。