事務一致性的測試
框架:spring
數據庫:innodb
spring事務的串行化
isolation=Isolation.SERIALIZABLE
-
多個串行化事務發生衝突會拋出死鎖異常
-
串行化和不可重複讀發生衝突的情況
事務1:串行化
事務2:不可重複讀(默認隔離級別)
執行順序 | 結果 |
---|---|
1開啓 - 2開啓 - 2結束 - 1結束 | 事務1正常,事務2發生死鎖異常 |
1開啓 - 2開啓 - 1結束 - 2結束 | 事務2的操作覆蓋了事務1的操作 |
2開啓 - 1開啓 - 1結束 - 2結束 | 事務2的操作覆蓋了事務1的操作 |
2開啓 - 1開啓 - 2結束 - 1結束 | 事務1正常,事務2發生死鎖異常 |
總結:
- 事務1開啓時給數據上鎖,具體哪種鎖沒有研究
- 如果事務2先結束,提交事務時由於事務1沒有釋放鎖,所以會發生死鎖異常,這種結果可以保證一致性
- 如果事務2後結束,提交事務時事務1已經釋放了鎖,事務2使用舊數據更新數據庫導致數據不一致
排他鎖(悲觀鎖)
前提:需要保證一致的邏輯在一個事務中
先申請排他鎖
加鎖:select … for update
例如:
SELECT id, value
FROM t_pessimistic
WHERE id = 1
FOR UPDATE
會對查詢結果的每行加排他鎖
如果沒有其他事務對查詢結果中的任一行使用排他鎖時可以成功獲得鎖,否則會阻塞直到獲得鎖
如果發生衝突的機率較低,每次都加鎖會產生額外開銷
適合發生衝突機率高的情況
樂觀鎖
代碼中實現的樂觀鎖好像不太穩定
給需要保證一致性的表增加版本號字段
每次執行update或delete時,驗證版本號,如果不一致就重試
如果發生衝突的機率較高,可能會重試多次,反而影響效率
適合發生衝突機率低的情況
總結
要保證數據的一致性,同一個表應該使用同一種鎖