mysql事務級別及幻讀情況模擬
mysql是大家常用的關係型資料儲存資料庫,為了保證一組操作的原子性(同時成功/同時失敗)利用了事務。但是同一時間上讀寫可能存在的重複讀、幻讀/髒讀等問題,就涉及到事務級別(預設級別:RR 可重複讀 REPEATABLE-READ)設定。
事務級別分為:未提交可讀(read uncommitted) 提交可讀(read committed)可重複讀(repeatable read)序列化(Serializable)
read uncommitted:事務未提交時即可讀取,可能導致髒讀。
read committed:事務提交後才可讀取,但不可重複讀(更新事務未提交前,其它查詢為老值,但同一事務記憶體在更新前後查詢不一致問題)(發生在update操作時)。
repeatable read: 可重複讀,但是可能幻讀(發生在insert操作時)。
幻讀:A事務第一次查詢時只存在一條,B事務新增一條記錄,A事務再更新操作時更新成功兩條。
幻讀具體案例:
A事務:
SELECT * FROM `ims_user`; #查詢結果1條
B事務:
INSERT ims_user ( NAME,STATUS) VALUES( 'c3',3); #新插入一條
COMMIT ;
A事務:
SELECT * FROM `ims_user`;#查詢結果還是1條
UPDATE ims_user SET `status` = 4 WHERE `status`=3; #更新結果2條。
COMMIT ;
幻讀產生可能原因分析:
1、結果快取:我們可以先插入,後查詢則結果正常。
驗證步驟:
B事務:
INSERT ims_user ( NAME,STATUS) VALUES( 'c3',3); #新插入一條
COMMIT ;
A事務:
SELECT * FROM `ims_user`;#查詢結果正常,新插入資料可查詢到
2、無鎖:“SELECT * FROM `ims_user`;”查詢從快照中讀,不存在鎖。當發生“UPDATE/DELETE/INSERT”時為當前讀,會產生行鎖、表鎖或者間隙鎖(RR機制下)。
解決方案:
1、切換事務級別為Serializable。
2、悲觀鎖:SELECT * FROM `ims_user` for update;
Serializable:序列化事務機制,序列處理任務。犧牲效能,保證資料。
其它:
檢視當前事務級別:SELECT @@tx_isolation;
檢視當前事務是否自動提交:show VARIABLES LIKE 'autocommit';