宜未雨而綢繆,毋臨渴而掘井mysql
數據庫事務(Database Transaction) ,是指做爲單個邏輯工做單元執行的一系列操做,要麼徹底地執行,要麼徹底地不執行。sql
一個數據庫事務一般包含對數據庫進行讀或寫的一個操做序列。它的存在包含有如下兩個目的:數據庫
固然並非全部的數據庫都支持事務,事務通常有四個屬性:原子性、一致性、隔離性、持久性。簡稱:ACID原則。接下來咱們舉例逐個分析:併發
舉例:分佈式
咱們用一個轉帳的案例結合每一個性質分析,例如:帳戶A向帳戶B轉帳,主要分爲一下幾個步驟:性能
原子性排序
保證6個步驟要麼所有執行,要麼所有不執行,若是失敗了就把事務回滾到轉帳的初始狀態。好比:在執行到第五步的以後,帳戶B忽然註銷了找不到了,此時帳戶A的錢也扣了,就必須事務回滾到原來各自的狀態也就是A的餘額500。事務
一致性get
在轉帳以前A和B的帳戶共有500+500=1000,而轉帳成功以後,A和B的帳戶是400+600=1000,就是數據的狀態在執行該事務操做以後從一個狀態改變到了另一個狀態it
隔離性
在A給B轉帳過程當中,只要事務沒有提交,A和B的帳戶餘額不會存在變化。可是此時帳戶C也在向帳戶B轉帳,最終兩個事務提交以後帳戶B的餘額應該是帳戶A轉帳的金額加上帳戶C轉帳的金額。也就是說多個事務之間不會相互影響,至於C給B轉帳的時候獲取B的餘額是已經加了A給B轉帳的餘額仍是沒加,這個和事務的隔離級別有關係。
持久性
一旦轉帳成功(事務提交),兩個帳戶的裏面的錢就會真的發生變化(會把數據寫入數據庫作持久化保存)!
隔離級別 | 髒讀 | 不可重複讀 | 幻讀 |
---|---|---|---|
Read-uncommitted | √ | √ | √ |
Read-committed | × | √ | √ |
Repeatable-read | × | × | √ |
Serializable | × | × | × |
做用:全部事務均可以看到其餘未提交事務的執行結果
例子:
又到月底了,小明的老婆要準備給小明發生活費了,小明的老婆給小明打了500塊,但該事務並無提交,而此時小明正好在查餘額,發現是550塊,高興的差點蹦了起來.天有不測風雲,忽然小明的老婆發現多打了50塊,因而回滾事務,修改金額,而後將事務提交,最後小明空歡喜異常。
做用:一個事務只能看見已經提交事務所作的改變
例子:
某個夜黑風高的夜晚,小明豐富的夜生活開始了,小明拿着工資卡去消費,pos機讀取卡的信息的時候有500,而此時小紅也正好在網上轉帳,把小明工資卡的500元轉到另外一帳戶,並小明以前提交了事務,當小明釦款時,系統檢查到小明的工資卡已經沒有錢,扣款失敗,小明十分納悶,明明卡里有錢,爲何會說餘額不足,出現上述狀況,即咱們所說的不可重複讀,兩個併發的事務,「事務1:小明消費」、「事務2:小紅網上轉帳」,事務1事先讀取了數據,事務2緊接了更新了數據,並提交了事務,而事務1再次讀取該數據時,數據已經發生了改變,當隔離級別設置爲Read committed時,避免了髒讀,可是可能會形成不可重複讀。
Repeatable read
做用:當用戶讀取某一範圍的數據行時,另外一個事務又在該範圍內插入了新行,當用戶再讀取該範圍的數據行時,發現和以前不同。
例子:
小紅最近發現小明老是很晚回家而且常常不接電話,因而小紅開始查小明當月信用卡的總消費金額,消費金額爲50,而小明此時正好在收銀臺買單,消費1000元,即新增了一條1000元的消費記錄,並提交了事務,隨後小紅將小明當月信用卡消費的明細打印了出來,卻發現消費總額爲1050元,小紅很詫異,覺得出現了幻覺
做用:最高級別,防止上述3種狀況,事務串行執行,慎用這是最高的隔離級別,它經過強制事務排序,使之不可能相互衝突,從而避免了髒讀,不可重複讀,幻讀。簡言之,它是在每一個讀的數據行上加上共享鎖。在這個級別,可能致使大量的超時現象和鎖競爭,併發性能最差,在分佈式事務中可能會被用到。