mysql之事務詳解
我們知道,應用中的一個業務邏輯,往往由多條語句組合完成。那麼我們就可以簡單地將事務理解為一組SQL語句的集合,要麼這個集合全部成功集合,要麼這個集合就全部失敗退回到第一句之前的狀態。
語法
我們先來看看事務的語法。現在的社會比較浮躁,大家往往只在乎如何解決問題,而不去考慮問題的本質到底是什麼。
所以我決定先來介紹事務的語法:
1. 開啟事務start transaction,可以簡寫為 begin
2. 然後記錄之後需要執行的一組sql
3. 提交commit
4. 如果所有的sql都執行成功,則提交,將sql的執行結果持久化到資料表內。
5. 回滾rollback
6. 如果存在失敗的sql,則需要回滾,將sql的執行結果,退回到事務開始之時
7. 無論回滾還是提交,都會關閉事務
8. 還有一點需要注意,就是事務只針對當前連線。
下面我們來進行演示:
使用第一個連結A,開啟事務後,執行一條update語句。
結果成功,資料已經變成修改之後!
此時我們沒有提交。
再從其他連線B來檢視,發現數據為更改:
此時如果連線A選擇提交,也就是commit操作。則連線B的資料也會發生變化。
而如果連線A選擇回滾,也就是rollback操作。則連線A再次查詢則發現數據還原。
基本原理
語法說完了,浮躁的人也不用繼續看下去了。下面簡單說一下事務的基本原理吧。
提交,就會將結果持久化,不提交就不會。
如果我們不開啟事務,只執行一條sql,馬上就會持久化資料
這是因為mysql預設對sql語句的執行是自動提交的。
也就是說,開啟事務,實際上就是關閉了自動提交的功能,改成了commit手動提交!
我們可以通過簡單的對是否自動提交加以設定,完成開啟事務的目的!
自動提交的特徵是儲存在服務的一個autocommit的變數內。可以進行修改:
還需要注意一點,就是事務類似於外來鍵約束,只被innodb引擎支援。
特點
下面來說說事務的特點ACID。也就是原子性,一致性,隔離性和永續性。
原子性:事務是不可分割的。
一致性:保證資料在事務的執行週期內,是一致的!
隔離型:多個事務之間的干擾關係!隔離級別!
永續性
事務併發
事務併發會帶來一些問題,所以才有了不同的事務隔離級別。要想了解事務的隔離級別,就必須首先了解事務併發會帶來的問題。
一般來說,會出現三類資料讀問題和資料更新問題。
髒讀
一個事務正在對一條記錄做修改,但未提交,另一個事務讀取了這些髒資料,並進一步處理,就會產生未提交的資料依賴。
舉一個例子:
時間 | 轉賬事務A | 取款事務B |
---|---|---|
T1 | 開始事務 | |
T2 | 開始事務 | |
T3 | 查詢賬戶餘額為1000元 | |
T4 | 取出500元把餘額改為500元 | |
T5 | 查詢賬戶餘額為500元(髒讀) | |
T6 | 撤銷事務餘額恢復為1000元 | |
T7 | 匯入100元把餘額改為600元 | |
T8 | 提交事務 |
A讀取了B尚未提交的髒數,導致最後餘額為600元。
不可重複讀
一個事務在不同時間讀取資料不一致。
舉一個例子:
時間 | 取款事務A | 轉賬事務B |
---|---|---|
T1 | 開始事務 | |
T2 | 開始事務 | |
T3 | 查詢賬戶餘額為1000元 | |
T4 | 查詢賬戶餘額為1000元 | |
T5 | 取出100元把餘額改為900元 | |
T6 | 提交事務 | |
T7 | 查詢賬戶餘額為900元(和T4讀取的不一致) |
可以看到最後讀取的資料不一致。
幻讀
幻讀和不可重複讀的概念類似,都是不同時間資料不一致,只不過幻讀是針對新增資料,而不可重複讀是針對更改資料。
看一個例子:
時間 | 統計金額事務A | 轉賬事務B |
---|---|---|
T1 | 開始事務 | |
T2 | 開始事務 | |
T3 | 統計總存款數為10000元 | |
T4 | 新增一個存款賬戶,存款為100元 | |
T5 | 提交事務 | |
T6 | 再次統計總存款數為10100元(幻象讀) |
更新丟失
兩個事務對同一資料進行更新,後者會覆蓋先者的更新。
時間 | 取款事務A | 轉賬事務B |
---|---|---|
T1 | 開始事務 | |
T2 | 開始事務 | |
T3 | 查詢賬戶餘額為1000元 | |
T4 | 查詢賬戶餘額為1000元 | |
T5 | 匯入100元把餘額改為1100元 | |
T6 | 提交事務 | |
T7 | 取出100元將餘額改為900元 | |
T8 | 撤銷事務 | |
T9 | 餘額恢復為1000元(丟失更新) |
隔離級別
事務併發帶來的問題前文已經描述得非常仔細了。事務的隔離級別就是為了針對併發出現的問題,不同的級別可以保證不同的一致性。
為了解決上面講到的併發事務處理帶來的問題,SQL標準提出了4個等級的事務隔離級別。不同的隔離級別在同樣的環境下會出現不同的結果。
下面看看四種隔離級別的比較:
隔離級別 | 讀資料一致性 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|---|
未提交讀(Read uncommitted) | 最低級別,只能保證不讀取物理上損壞的資料 | 是 | 是 | 是 |
已提交讀(Read committed) | 語句級 | 否 | 是 | 是 |
可重複讀(Repeatable read) | 事務級 | 否 | 否 | 是 |
可序列化(Serializable) | 最高級別,事務級 | 否 | 否 | 否 |