事務ACID&隔離&臟讀&不可重復讀&幻讀

ACID

原子性:要么都做,要么都不做
一致性:保證原子性,即全部做或者全做就是一致的
隔離性:每個事務間不互相影響 isolation
持續性:永久的改變

例子:從A賬戶取出1萬元到B賬戶
事務:

BEGIN TRANSACTION
    讀取A賬戶的存款Balance
    Balance=Balance-amount
    IF (Balance<0) THEN
        ROLLBACK
    ELSE
        讀取B賬戶的存款Balance1
        Balance1=Balcance1+amount
        COMMIT

不可重復讀&臟讀&幻讀

不可重復讀

兩次讀的結果不同。比如:

  1. T1:W1=100 T2 update W2=200 T1檢查有問題

臟讀

上個銀行轉賬的事務:
T1: A賬戶在減去amount得到一個數
T2:讀取A賬戶的賬戶值
T1:發現賬戶值小于0,回滾
T2:呵呵呵呵呵

幻讀

其實也是不可重讀的一種。有兩種情況
T2直接把W1刪除了,結果T1再一查,怎么沒有數據了。
或是T2又在W1后面填了一個元素,T1一查怎么多了數據

隔離級別

讀未提交(Read-Uncommitted)

一個會話更新的數據會被其他的會話馬上看到,即使未提交。
默認的是REEDABLE_READ(可重復讀)

tx_isolation: 隔離級別

select @@global.tx_isolation,@@session.tx_isolation,@@tx_isolation
image.png

會話一:

set tx_isolation='read-uncommitted'
start transaction;
insert into user values(1200,'Tracy',121231,'asdaf') //開啟事務,不提交

會話二:
查不到

更改成“read-uncommitted”,立馬可以查詢到,即臟讀:

image.png

會話一Rollback一發,然后會話二就幻讀了:

image.png

找不到tracy了。

讀提交(Read-committed)

只有提交之后的事務才能被查詢到。

將會話二改成 read-committed。

然后在會話一的事務里刪除一行數據但不提交

start transaction;
delete from user where username='yave'

會話一種可以立即查詢到刪除,但是會話二中還是原結果,
在會話二中查詢結果:

image.png

在會話一中commit之后,會話二的查詢結果:

image.png

可重復讀(Repeatable-read)

當事務隔離級別設置為REPEATABLE-READ(可重復讀)時,在這種狀態下,同一個事務中的多次查詢結果都是一致的(既不會出現不可重復讀的現象),即使在此期間其他會話更新了數據,這些數據對其也是不可見的。

在事務二中先開啟事務并進行查詢操作;

image.png

在事務一中刪除一行:

start transaction;
delete from user where username='tracy';
commit

繼續在事務二中查詢,查詢中tracy依然存在:

image.png

提交事務二,并開啟新事務查詢:

image.png

串行化(Serializable)

當事務隔離級別設置為SERIALIZABLE(串行讀)時,在這種狀態下,一個會話事務中的select操作將會阻塞其他事務的寫(add、update和delete)操作,但不會阻塞讀。

比較

l DEFAULT 使用數據庫設置的隔離級別 ( 默認 ) ,由 DBA 默認的設置來決定隔離級別 .

l READ_UNCOMMITTED 會出現臟讀、不可重復讀、幻讀 ( 隔離級別最低,并發性能高 )

l READ_COMMITTED 會出現不可重復讀、幻讀問題(鎖定正在讀取的行)

l REPEATABLE_READ 會出幻讀(鎖定所讀取的所有行)

l SERIALIZABLE 保證所有的情況不會發生(鎖表)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容