淺談數據庫事務
原子性
原子性是指事務包含的所有操作要麽全部成功,要麽全部失敗。
例小王要向小李轉賬200元。則賬要麽轉賬成功小王賬戶減200元,小李賬戶加200元,要麽執行失敗,兩者賬戶都不動。
一致性
一致性是指事務執行之前和執行之後都必須處於一致性狀態。
假設轉賬前小王和小李的余額之和是2000元,那麽不管他們之間進行了多少次轉賬,他們的余額之和肯定還是2000元。
隔離性
隔離性是當多個事務並發操作數據庫時,不能被其他事務的操作所幹擾
例小王銀行卡只有200元了,他要向小李轉賬200元時銀行方面進行銀行卡的年費扣除則這兩個操作必定不可能都成功。
持久性
持久性是指一個事務一旦提交,那麽對數據庫中的數據的改變就是永久性的。
當小王和小李之間進行一次轉賬時,這筆轉賬記錄便永久的保存在數據庫裏.
並發事務存在的問題
上方提到了數據庫事務的隔離性,先看一下如果事務之間不進行隔離的話可能出現什麽問題
臟讀
臟讀是指在一個事務處理過程裏讀取了另一個未提交的事務中的數據。
當一個事務正在多次修改某個數據,而在這個事務中這多次的修改都還未提交,這時一個並發的事務來訪問該數據,就會造成兩個事務得到的數據不一致。同上方的例子:小王向小李轉賬200元,對應SQL命令如下
update account set balance=balance+200 where name=’小李’; update account set balance=balance-200 where name=’小王’;
當只執行第一條SQL時,小李查詢余額發現確實錢已到賬(此時即發生了臟讀),而之後如果該事務不提交或者出現異常,則所有操作都將回滾,那麽小李再次查看賬戶時就會發現錢其實並沒有到賬。
不可重復讀
例如事務T1在讀取某一數據,而事務T2立馬修改了這個數據並且提交事務給數據庫,事務T1再次讀取該數據就得到了不同的結果,這個時候就發生了不可重復讀。
幻讀
例如事務T1對一個表中所有的行的某個數據項做了從“1”修改為“2”的操作,這時事務T2又對這個表中插入了一行數據項,而這個數據項的數值還是為“1”並且提交給數據庫。而操作事務T1的用戶如果再查看剛剛修改的數據,會發現還有一行沒有修改,其實這行是從事務T2中添加的,就好像產生幻覺一樣,這就是發生了幻讀。
幻讀和不可重復讀都是讀取了另一條已經提交的事務,所不同的是不可重復讀查詢的是同一個數據項,而幻讀針對的是一批數據。
事務的隔離級別
- Read uncommitted (讀未提交):最低級別,任何情況都無法保證。
- Read committed (讀已提交):可避免臟讀的發生。
- Repeatable read (可重復讀):可避免臟讀、不可重復讀的發生。
- Serializable (串行化):可避免臟讀、不可重復讀、幻讀的發生。
註意
上方隔離級別從低到高,隔離級別越高效率越低。
在MySQL數據庫中,支持上面四種隔離級別,默認為Repeatable read
在Oracle數據庫中,只支持Serializable和Read committed ,默認為Read committed級別
淺談數據庫事務