資料庫事務(簡稱:事務)是資料庫管理系統執行過程中的乙個邏輯單位,由乙個有限的資料庫操作序列構成。
當多個使用者併發運算元據庫時,資料庫為每乙個使用者開啟不同的事務。這些事務如果不加以隔離,會產生一些問題。看下面的例子:
髒讀
事務a
事務b
前提amy賬戶餘額是100
時間1: b事務開始
bob給自己老媽轉500,結果轉給了amy,這個事務做了,但未提交
時間2: a事務開始,並完成
如果amy可以讀取未提交的資料,這時候她會查到餘額為600
時間3: b事務回滾
bob意識到自己的錯誤,回滾剛才的事務
總結100才是amy真實的餘額,600為臟資料讀取的產物,是實實在在的誤導。
不可重複讀
事務a
事務b
前提amy賬戶餘額是100
時間1: a事務開始
amy查詢到自己的餘額是100
時間2: b事務開始,並完成
bob給amy轉了500
時間3: a事務重複,並完成
amy查詢到自己的餘額是600
總結在事務a存續期間,針對相同的資料做了兩次相同的查詢,但數額不同(儘管數額都是當時時間點真實的餘額)。
知道真相的也就算了,不知道的以為自己被欺負/騙/耍了。
幻讀
事務a
事務b
前提時間1: a事務開始
amy查詢,當前持有金額 >500 的**個數為多少?結果返回2個
時間2: b事務開始,並完成
三個產品分別被扣了管理費100塊,成了100,500,800
時間3: a事務重複,並完成
amy查詢,當前持有金額 >500 的**個數為多少?結果返回1個
總結在事務a存續期間,針對同一批資料做了兩次相同的檢索,但得結果不同(儘管檢索出來的資料在當時時間點是真實的)。
知道真相的也就算了,不知道的以為自己被欺負/騙/耍了。
歸納一下這些問題的特點:
問題
特點1
特點2
特點3**
髒讀
dirty read
某事務a讀取了另一事務b未提交的資料
注:未提交意味著之後會有提交和回滾兩個狀態,回滾才是導造成a讀資料前後不一致的根本原因;
但一般認為,只要是a讀了b未提交的資料,就是髒讀
不可重複讀
non-repeatable read
某事務a讀取了另一事務b已提交的資料
a查詢的是某乙個資料項
重點在於更新修改資料
幻讀
phantom read
某事務a讀取了另一事務b已提交的資料
a查詢的是一批資料整體(如個數)
重點在於新增或刪除資料
對於特點3**來說,還有一種解釋:
不可重複讀重點在於update和delete,而幻讀的重點在於insert。如果用鎖機制來解釋的話,即想要避免「不可重複讀」,在事務a第一次讀資料的時候,把這些資料加鎖,就可以阻止update和delete操作,其他事物無法改寫資料。但這個方法不能阻止另乙個事務b進行insert操作,之後a會發現莫名其妙多了一條資料,即發生了幻讀。幻讀需要靠serializable隔離級別來避免(即讀用讀鎖,寫用寫鎖,讀鎖和寫鎖互斥,但會極大的降低資料庫的併發能力),所以說,不可重複讀和幻讀,從鎖機制角度來說,區別比較大,也可以認為,從控制的角度來看, 兩者的區別就比較大。
不可重複讀, 只需要鎖住滿足條件的記錄
幻讀, 要鎖住滿足條件及其相近的記錄
其實,除了髒讀,不可重複讀,幻讀,還有另一種問題,丟失更新,即兩個事務同時讀取同一條記錄,a先修改記錄,b也修改記錄(b是不知道a修改過),b提交資料後b的修改結果覆蓋了a的修改結果。
髒讀,不可重複讀,幻讀
髒讀,不可重複讀,幻讀是由於資料庫事務的隔離性導致的問題。髒讀 乙個事務讀取到了其它未提交事務操作的記錄。不可重複讀 乙個事務a內,首次查詢到一條相同記錄,然後事務b修改該條記錄並提交,事務a再次執行相同查詢,得到了事務b更新後的結果,事務a兩次相同的查詢,卻得到了不同的結果,這個叫做不可重複讀。是...
髒讀 不可重複讀 幻讀
髒讀 事務a使用了資料,但是還沒來得及提交,事務b就使用了這個資料,對於事務b來說就是髒讀。允許髒讀 sql server select from category with nolock 不可重複讀 事務a在9點和12點都會操作乙份資料,但是在10點的時候,事務b也操作了該份資料,並且使其數值進行...
髒讀 不可重複讀 幻讀
總結 對於不可重複讀和幻讀的區別是 不可重複讀圈了一塊地,這塊地不允許任何人動用,但是不管旁邊的地方是否開闢了一塊地。幻讀是不僅是圈的地,而且附近也不允許有新的地。這個對於區間查詢會有影響。所以不可重複讀和幻讀最大的區別是區間查詢的結果會不會一樣。幻讀保證結果一樣,但是不可重複讀不保證。mysql的...