本文主要包括一下內容: ?(1) 事務的概念與ACID ?(2)事務的隔離級別 ?(3)MySQL中的事務
1. 事務與ACID
理解事務是其它高級概念的基礎。
事務:事務就是一組原子性的SQL查詢,或則說是一個獨立的執行單元,要么全部成功,要么全部失敗,如果失敗了就回滾到事務之前的查詢。
下面來理解一下數據庫中關于ACID的概念:原子性、一致性、隔離性、持久性。
(1)原子性:事務中的操作是一個不可分割的整體單元,要么全部都做,要么全部不做。
(2)一致性:事務執行前后數據庫都必須處于一致性狀態。
(3)隔離性:通常來說,一個事物所做的修改在最終提交之前對其余事務是不可見的。這里就涉及到事務的隔離級別的問題了。
(4)持久性:一旦事務提交完成,修改就是永久的,即使服務器宕機也不會影響到。
為了更好地理解ACID,下面以銀行賬戶轉賬為例進行說明:
--?開始事務START?TRANSACTION; --?查詢支票賬戶余額+ SELECT?balance?FROM?checking?WHERE?customer_id?=?10233276;+ --?將支票賬戶減去200UPDATE?checking?SET?balance?=?balance?-?200.00?WHERE?customer_id?=?10233276; --?將余額賬戶增加200UPDATE?savings?SET?balance?=?balance?+?200.00?WHERE?customer_id?=?10233276; --?提交事務更新COMMIT;
原子性:要么完全提交(10233276的checking余額減少200,savings 的余額增加200),要么完全回滾(兩個表的余額都不發生變化)
一致性:這個例子的一致性體現在 200元不會因為數據庫系統運行到第3行之后,第4行之前時崩潰而不翼而飛,因為事物還沒有提交。
隔離性:允許在一個事務中的操作語句會與其他事務的語句隔離開,比如事務A運行到第3行之后,第4行之前,此時事務B去查詢checking余額時,它仍然能夠看到在事務A中被減去的200元(賬戶錢不變),因為事務A和B是彼此隔離的。在事務A提交之前,事務B觀察不到數據的改變。
持久性:這個很好理解,就是事務提交之后修改就是永久的。
事務跟鎖一樣都會需要大量工作,因此你可以根據你自己的需要來決定是否需要事務支持,從而選擇不同的存儲引擎。
2. 事務的隔離級別
SQL定義了四種隔離級別,用來限定事務內哪些數據是可見的。很明顯低級別的隔離級別擁有更高的并發性,系統開銷也更加小,但是隨之而來的就是帶來的數據安全性問題。
Read Uncommitted(未提交讀)
在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。讀取未提交的數據,也被稱之為臟讀(Dirty Read)。該級別用的很少。
Read Committed(提交讀)
這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它滿足了隔離的簡單定義:一個事務只能看見已經提交事務所做的改變,換句話說就是事務提交之前對其余事務不可見。這種隔離級別也支持不可重復讀(Nonrepeatable Read),因為同一事務的其他實例在該實例處理其間可能會有新的commit,所以同一select查詢可能返回不同結果。
Repeatable Read(可重復讀)
這是MySQL的默認事務隔離級別,它確保同一事務的多個實例在并發讀取數據時,會看到同樣的數據行。不過理論上,這會導致另一個棘手的問題:幻讀 (Phantom Read)。簡單的說,幻讀指當用戶讀取某一范圍的數據行時,另一個事務又在該范圍內插入了新行,當用戶再讀取該范圍的數據行時,會發現有新的“幻影” 行。InnoDB和Falcon存儲引擎通過多版本并發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。
Serializable(可串行化)
這是最高的隔離級別,它強制事務都是串行執行的,使之不可能相互沖突,從而解決幻讀問題。換言之,它是在每個讀的數據行上加上共享鎖。在這個級別,可能導致大量的超時現象和鎖競爭。
MySQL中實現這四種隔離界別可能產生的問題如下:
3. MySQL中的事務
MySQL中默認的是采取自動提交模式(AutoCommit),也就是說只要不是顯示的開啟一個事務,每個查詢操作都被當做一個事務執行提交的操作。
我們可以通過設置 AUTOCOMMIT 查詢來啟動或則禁用自動提交模式。
設置1表示啟用AUTOCOMMIT,0表示禁用AUTOCOMMIT。
本文主要包括一下內容:
?(1) 事務的概念與ACID
?(2)事務的隔離級別
?(3)MySQL中的事務