事務概念 轉

事務概念

我們在實際業務場景中,經常會遇到數據頻繁修改讀取的問題。在同一時刻,不同的業務邏輯對同一個表數據進行修改,這種衝突 很可能造成數據不可挽回的錯亂,所以我們需要用事務來對數據進行管理。

什麼事務?數據庫中事務的四大特性:

  • 原子性(Atomicity):操作這些指令時,要麼全部執行成功,要麼全部不執行。只要其中一個指令執行失敗,所有的指令都執行失敗 ,數據進行回滾,回到執行指令前的數據狀態。
  • 一致性(Consistency):事務的執行使數據從一個狀態轉換爲另一個狀態,但是對於整個數據的完整性保持穩定。
  • 隔離性(Isolation):在該事務執行的過程中,無論發生的任何數據的改變都應該只存在於該事務之中,對外界不存在任何影響。 只有在事務確定正確提交之後,纔會顯示該事務對數據的改變。其他事務才能獲取到這些改變後的數據。
  • 持久性(Durability):當事務正確完成後,它對於數據的改變是永久性的。

通俗點講,事務就是一系列指令的集合。


併發事務導致的問題

在許多事務處理同一個數據時,如果沒有采取有效的隔離機制,那麼併發處理數據時,會帶來一些的問題。 問題分爲5類,包括3類數據讀問題:髒讀、不可重複讀和幻讀。兩類數據更新問題:第一類丟失更新、第二類丟失更新。

1.髒讀:一個事務讀取到另一個事務未提交的更新數據。

小明的銀行卡餘額裏有100元。現在他打算用手機點一個外賣飲料,需要付款10元。但是這個時候,他的女朋友看中了一件衣服95元  
,她正在使用小明的銀行卡付款。於是小明在付款的時候,程序後臺讀取到他的餘額只有5塊錢了,根本不夠10元,所以系統拒絕了
他的交易,告訴餘額不足。但是小明的女朋友最後因爲密碼錯誤,無法進行交易。小明非常鬱悶,明明銀行卡里還有100元,怎麼會 
餘額不足呢?(他女朋友更鬱悶。。。)

2.不可重複讀:一個事務兩次讀取同一行的數據,結果得到不同狀態的結果,中間正好另一個事務更新了該數據,兩次結果相異, 不可被信任。

小明在手機上購買起購價爲1W元理財產品。系統首先要判斷他的餘額夠不夠購買理財產品,如果足夠再獲取當前的餘額,進行申請。
系統第一次讀取到小明的餘額還剩1W元,剛好足夠購買產品。但是這個時候剛好他女朋友又看中了一個包包5000元,這次密碼終於
不會再錯誤的女朋友毫不猶豫刷了小明的銀行卡買下了這個包包。但是這個系統剛好在進行第二次確認,發現小明的餘額上只有5
000元,根本不夠購買。於是系統很生氣,拒絕了小明的購買行爲,告訴他,你真是個騙子!!!

3.虛讀(幻讀):一個事務讀取到另一事務已提交的insert數據。

公司財務A在進行員工薪資覈算業務,需要對小明的工資進行計算並錄入系統,必須查詢兩次明細信息,然後將後一次的明細信息計
算總數出來。財務在第一次明細查詢時,基本工資2000元,全勤獎1000元,提成2000元,共計5000元。在進行第二次計算時,財務
B突然接到通知,需要把下個月的節日福利也在這個月的工資中發放,每人100元。於是財務B在每個人的工資明細中又加了一條節
日福利100元。而此時財務A獲得第二次查詢小明的工資明細後,發現工資明細變成了4條數據,總數是5100元。兩次計算結果相差
100元,財務A奇怪這多出來的一條明細100元是哪裏來的呢?(都怪財務B不告訴A。。。)

注意:不可重複讀和幻讀的區別是:前者是指讀到了已經提交的事務的更改數據(修改或刪除),後者是指讀到了其他已經提交事務的新增數據。 對於這兩種問題解決採用不同的辦法,防止讀到更改數據,只需對操作的數據添加行級鎖,防止操作中的數據 發生變化;二防止讀到新增數據,往往需要添加表級鎖,將整張表鎖定,防止新增數據(oracle採用多版本數據的方式實現)。

4.第一類丟失更新:撤銷一個事務時,把其他事務已提交的更新數據覆蓋。

小明去銀行櫃檯存錢,他的賬戶裏原來的餘額爲100元,現在打算存入100元。在他存錢的過程中,銀行年費扣了5元,餘額只剩95元
。突然他又想着這100元要用來請女朋友看電影吃飯,不打算存了。在他撤回存錢操作後,餘額依然爲他存錢之前的100元。所以那5塊錢到底扣了誰的?

5.第二類丟失更新:是不可重複讀的特殊情況。如果兩個事物都讀取同一行,然後兩個都進行寫操作,並提交,第一個事物所做的改變就會丟失。

小明和女朋友一起去逛街。女朋友看中了一支口紅,(對,女朋友就是用來表現買買買的)小明大方的掏出了自己的銀行卡,告訴女朋友:
親愛的,隨便刷,隨便買,我坐着等你。然後小明就坐在商城座椅上玩手機,等着女朋友。這個時候,程序員的聊天羣裏有人推薦了一本書,
小明一看,哎呀,真是本好書,還是限量發行呢,我一定更要買到。於是小明趕緊找到購買渠道,進行付款操作。而同時,小明的女朋友也
在不亦樂乎的買買買,他們同時進行了一筆交易操作,但是這個時候銀行系統出了問題,當他們都付款成功後,卻發現,銀行只扣了小明的
買書錢,卻沒有扣去女朋友此時交易的錢。哈哈哈,小明真是太開心了!

爲了解決上述問題,數據庫通過鎖機制解決併發訪問的問題。根據鎖定對象不同:分爲行級鎖和表級鎖;根據併發事務鎖定的關係上看:分爲共享鎖定和獨佔鎖定, 共享鎖定會防止獨佔鎖定但允許其他的共享鎖定。而獨佔鎖定既防止共享鎖定也防止其他獨佔鎖定。爲了更改數據,數據庫必須在進行更改的行上施加行獨佔鎖定, insert、update、delete和selsct for update語句都會隱式採用必要的行鎖定。

但是直接使用鎖機制管理是很複雜的,基於鎖機制,數據庫給用戶提供了不同的事務隔離級別,只要設置了事務隔離級別,數據庫就會分析事務中的sql語句然後 自動選擇合適的鎖。

mysql中的事務隔離級別

  • Serializable (串行化):可避免髒讀、不可重複讀、幻讀的發生。
  • Repeatable read (可重複讀):可避免髒讀、不可重複讀的發生。
  • Read committed (讀已提交):可避免髒讀的發生。
  • Read uncommitted (讀未提交):最低級別,任何情況都無法保證。

在MySQL數據庫中,支持上面四種隔離級別,默認的爲Repeatable read (可重複讀);而在Oracle數據庫中,只支持Serializable (串行化)級別和Read committed (讀已提交)這兩種級別,其中默認的爲Read committed級別。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章