併發事務的問題
對於同時運行的多個事務,當這些事務訪問數據庫中相同的數據時,如果沒有采取便要的隔離機制,就會導致各種併發問題:
- 髒讀:對於兩個事務T1,T2,T1讀取了T2已經更新但還沒有提交的字段之後,如果T2回滾,那麼T1讀取的數據就是臨時且無效的
- 不可重複讀:兩個事物A和B,A讀取了一個字段,然後B更新了該字段,之後A再次讀取同一個字段,值就不同了
- 幻讀:對於兩個事物A和B,A從一個表中讀取了一些字段,然後B在該表中插入了一些新的行。之後,若A再次讀取同一個表,會多出幾行數據。
數據庫事物的隔離級別
數據庫系統必須具有隔離併發運行各個事務的能力,使它們不會相互影響,避免各種併發問題
隔離級別:
髒讀 | 不可重複讀 | 幻讀 | |
---|---|---|---|
read uncommitted:允許讀未提交的數據,髒讀、不可重複讀、幻讀的問題都會出現 | × | × | × |
read committed:讀已提交的數據,可以避免髒讀。但不可重複讀和歡度問題仍然存在 | √ | × | × |
repeatable read:可重複讀取數據(mysql默認),確保事務可以從一個字段中讀取相同的值,在這個事務持續期間,禁止其他事務對這個字段進行更新,可以避免髒讀和不可重複讀,但幻讀的問題仍然存在 | √ | √ | × |
serializable:串行化,所有併發問題都可以解決,但性能十分低下 | √ | √ | √ |
SELECT @@tx_isolation;//查看當前數據庫的隔離級別
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;//設置當前數據庫的隔離級別
案例:
設置爲read uncommited,會出現髒讀現象:
設置爲read committed則可以避免髒讀的問題,但會導致兩次的查詢結果不一樣
保存點 savepoint
和rollback一起使用,用於回滾到特定位置
SET autocommit=0;
START TRANSACTION;
DELETE FROM account WHERE id=25
SAVEPOINT a;#設置保存點
DELETE FROM account WHERE id=28;
ROLLBACK TO a;#回滾到保存點
delete和truncate在事務中的區別
delete:支持是回滾
truncate:不支持回滾