一、事務的概念
事務就是一組原子性的SQL查詢,或者說一個獨立的作業單元,如果資料庫引擎能夠成功地對資料庫應用該組查詢的全部陳述句,那么就執行該組查詢,如果其中有任何一條陳述句因為崩潰或其他原因無法執行,那么所有的陳述句都不會執行,也就是說,事務內的陳述句,要么全部執行成功,要么全部執行失敗,
可以通過一個銀行事例來解釋事務的必要性,假設有以下場景:現在用戶A想通過銀行轉賬200元給用戶B,那么至少需要三個步驟:
1、檢查用戶A的賬戶余額高于200元,
2、用戶A賬戶減去200元,
3、用戶B賬戶增加200元,
假設賬戶A扣錢后系統出現故障,則會出現賬戶A扣了錢,但賬戶B沒收到錢的情況,為保證上訴三個步驟要么全部執行成功,要么全部執行失敗,需打包在一個事務中,任何一個步驟失敗,則回滾所有的步驟,
二、事務的ACID
ACID表示原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持久性(durability),一個良好的事務處理系統,必須具備這些標準特性,
原子性(atomicity):
一個事務必須被視為一個不可分割的最小作業單元,整個事務的所有操作要么全部執行成功,要么全部失敗回滾,對于一個事務來說,不可能只執行其中的一部分操作,這就是事務的原子性,
一致性(consistency):
資料庫總是從一個一致性的狀態轉換到另一個一致性的狀態,在前面的例子中,用了事務后,假設執行第三步的時候系統崩潰了,賬戶A不會損失200元,因為事務最終沒有提交,所以事務中所做的修改也不會保存到資料庫中,保持資料的一致性,
隔離性(isolation):
通常來說,一個事務所做的修改在最終提交以前,對其他事務是不可見的(這個和事務隔離級別有關),在前面的例子中,當執行完第二步驟,第三步驟還沒開始的時候,此時有另外一個程式開始運行,則看不到賬戶A的余額被扣除了200元,
持久性(durability):
一旦事務提交,則其所做的修改就會永久保存到資料庫中,此時即使系統崩潰,修改的資料也不會丟失,
三、事務的隔離級別
前面說到事務的隔離性其實和事務的隔離級別有關,在SQL標準中定義了四種隔離級別,每一種級別都規定了一個事務中所做的修改,哪些在事務內和事務間是可見的,哪些是不可見的,較低級別的隔離通常可以執行更高的并發,系統的開銷也更低,
下面簡單的介紹一下四種隔離級別,
未提交讀(read uncommitted):
在未提交讀級別,事務的修改,即使沒有提交,對其他事務也都是可見的,事務可以讀取未提交的資料,這也被稱為臟讀,這個級別會導致很多問題,從性能上來說,未提交讀不會比其他級別好太多,但卻缺乏其他級別的很多好處,除非真的有非常必要的理由,在實際應用中一般很少使用,
舉例:事務A讀取到資料1,將資料改成2,即使事務A還沒提交,事務B也能讀取到資料2,
提交讀(read committed):
大多數資料庫系統的默認隔離級別都是提交讀(但MySQL不是),提交讀滿足前面提到的隔離性的簡單定義:一個事務開始時,只能看見已經提交的事務所做的修改,換句話說,一個事務從開始直到提交之前,所做的任何修改對其他事務都是不可見的,這個級別有時候也叫做不可重復讀,因為在同一個事務內兩次執行相同的查詢,可能會得到不一樣的結果,
舉例:事務B開啟時讀到資料1,接下來事務A開啟,把這個資料改成2,提交,B再次讀取這個資料,會讀到最新的資料2,
可重復讀(repeatable read):
可重復讀解決了臟讀的問題,該級別保證了在同一事務中多次讀取同樣記錄的結果是一致的,
舉例:事務B開啟時讀到資料1,接下來事務A開啟,把這個資料改成2,提交,B再次讀取這個資料,仍然讀取到資料1,
但是理論上,可重復讀隔離級別還是無法解決另一個幻讀的問題,所謂幻讀,指的是當某個事務在讀取某個范圍內的記錄時,另一個事務又在該范圍內插入了新的記錄,當之前的事務再次讀取該范圍的記錄時,會產生幻行,讀取到新插入的資料,不過MySQL中的InnoDB存盤引擎通過多版本并發控制(MVCC)解決了幻讀的問題,可重復讀是MySQL的默認事務隔離級別,
可串行化(serializable):
可串行化是最高的隔離級別,它通過強制事務串行執行,避免了前面說的幻讀的問題,簡單來說,可串行化隔離級別會在讀取的每一行資料上都加鎖,所以可能導致大量的超時和鎖爭用的問題,實際應用中也很少用到這個隔離級別,只有在非常需要確保資料的一致性而且可以接受沒有并發的情況下,才考慮采用該級別,
接下來用一個表格說明這四種隔離級別:
| 隔離級別 | 臟讀可能性 | 不可重復讀可能性 | 幻讀可能性 | 加鎖讀 |
| 未提交讀 | Yes | Yes | Yes | No |
| 提交讀 | No | Yes | Yes | No |
| 可重復讀 | No | No | Yes | No |
| 可串行化 | No | No | No | Yes |
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/48498.html
標籤:MySQL
