ACID
原子性:要么都做,要么都不做
一致性:保證原子性,即全部做或者全做就是一致的
隔離性:每個事務間不互相影響 isolation
持續性:永久的改變
例子:從A賬戶取出1萬元到B賬戶
事務:
BEGIN TRANSACTION
讀取A賬戶的存款Balance
Balance=Balance-amount
IF (Balance<0) THEN
ROLLBACK
ELSE
讀取B賬戶的存款Balance1
Balance1=Balcance1+amount
COMMIT
不可重復讀&臟讀&幻讀
不可重復讀
兩次讀的結果不同。比如:
- 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
會話一:
set tx_isolation='read-uncommitted'
start transaction;
insert into user values(1200,'Tracy',121231,'asdaf') //開啟事務,不提交
會話二:
查不到
更改成“read-uncommitted”,立馬可以查詢到,即臟讀:
會話一Rollback一發,然后會話二就幻讀了:
找不到tracy了。
讀提交(Read-committed)
只有提交之后的事務才能被查詢到。
將會話二改成 read-committed。
然后在會話一的事務里刪除一行數據但不提交
start transaction;
delete from user where username='yave'
會話一種可以立即查詢到刪除,但是會話二中還是原結果,
在會話二中查詢結果:
在會話一中commit之后,會話二的查詢結果:
可重復讀(Repeatable-read)
當事務隔離級別設置為REPEATABLE-READ(可重復讀)時,在這種狀態下,同一個事務中的多次查詢結果都是一致的(既不會出現不可重復讀的現象),即使在此期間其他會話更新了數據,這些數據對其也是不可見的。
在事務二中先開啟事務并進行查詢操作;
在事務一中刪除一行:
start transaction;
delete from user where username='tracy';
commit
繼續在事務二中查詢,查詢中tracy依然存在:
提交事務二,并開啟新事務查詢:
串行化(Serializable)
當事務隔離級別設置為SERIALIZABLE(串行讀)時,在這種狀態下,一個會話事務中的select操作將會阻塞其他事務的寫(add、update和delete)操作,但不會阻塞讀。
比較
l DEFAULT 使用數據庫設置的隔離級別 ( 默認 ) ,由 DBA 默認的設置來決定隔離級別 .
l READ_UNCOMMITTED 會出現臟讀、不可重復讀、幻讀 ( 隔離級別最低,并發性能高 )
l READ_COMMITTED 會出現不可重復讀、幻讀問題(鎖定正在讀取的行)
l REPEATABLE_READ 會出幻讀(鎖定所讀取的所有行)
l SERIALIZABLE 保證所有的情況不會發生(鎖表)