MySQL 事務隔離級別
一、事務描述
1、事務的四個特性 ACID
1. A:原子性 =一個事務或者都成功、或者都失敗;
2. C:一致性 = 在整個事務的生命週期裡面,查詢到的資料是一致的;
MVCC多版本併發控制:利用undo儲存某一時刻資料快照,通過版本號來減少鎖的爭用,保證各個事務互不影響。
3. I: 隔離性 = 隔離級別;
4. D:永續性 =只要事務commit,這個事務不會因為系統的崩潰而丟失;
永續性和原子性對於所有的支援事務的資料庫都是一樣的,都滿足。
2、常見事務格式
start transaction;
DML ( insert; delete; update; )
commit;
3、MySQL 預設每一條 DML 是一個事務
通過引數 'autocommit' 進行控制是否預設提交事務;
mysql> show variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit| ON| +---------------+-------+ 1 row in set (0.01 sec)SQL 自動提交開啟,有一定的危險性(沒有 rollback )。
牆裂推薦: 關閉 SQL 的自動提交;
血淚教訓: 曾經自信過了頭的一次 sitesup (其實也是有反覆確認),同時疏忽了備份,命令列下一個回車敲下去,發現問題大發了……所以,備份 + 顯式 Commit 很重要 。
4、大事務+長事務
資料庫的大事務和長事務會帶來undo的持續增加、undo暴增,空間不可複用;
事務資訊表: information_schema.INNODB_TRX,用來檢視長事務、大事務。
5、空閒事務+鎖
start transaction;
update;
…… // 空閒等待,時間可能不可控
…… // 空閒等待
update;
commit;
1. 事務和事務鎖有一定的關係:事務不提交、行鎖就不會釋放、事務鎖就不會消失
2. 死鎖:是指兩個或兩個以上的事務在執行過程中,因爭奪鎖資源而造成的一種相互等待的現象。死鎖出現的概率是非常低的,因為innodb內建有死鎖檢查機制,當出現死鎖時會自動回滾佔用undo資源少的事務。
二、事務隔離級別
0、隔離性
1. MySQL 有多個隔離級別,可以調整,隔離性越弱併發性越好;
2. 每個資料庫都有自己預設的隔離級別
mysql> show variables like '%iso%'; +---------------+-----------------+ | Variable_name | Value| +---------------+-----------------+ | tx_isolation| REPEATABLE-READ | +---------------+-----------------+ 1 row in set (0.01 sec)
會話級別設定:set @@session.tx_isolation=……
1、READ-UNCOMMITED
未提交讀 ,隔離性最弱,但併發性最好;
事務中的修改,即使沒有提交,對其他事務也都是可見的,也就是說事務可以讀取未提交的資料,讀到髒資料(髒讀,dirty read);
2、READ-COMMITED
大部分資料庫系統的預設隔離級別都是READ-COMMITED,但MySQL不是;
1.提交讀 ,一個事務從開始直到提交之前,所做的任何修改對其他事務都是不可見的;
2.不可重複讀 ,在同一個事務中,同一個SQL執行多次(該記錄修改事務提交前、提交後),得到的結果可能不同:幻讀;
3、REPEATABLE-READ
可重複讀 ,MySQL預設隔離級別;
在同一個事務中,同一個SQL執行多次,得到的結果是相同的;
1. 對於普通 select 來說,通過 MVCC 來實現,解決髒讀問題、幻讀問題;
2. 對於 dml、select for update,通過範圍鎖實現,解決幻讀問題;
4、SERIALIZABLE
(serializable 連載、序列化 ) 隔離性最高,沒有併發;
對於同一個資料來說,在同一個時間段內,只能有一個會話可以訪問,包括select和dml,通過執行事務序列執行,避免幻讀問題;
也就是說,對於同一行記錄,“寫”會加“寫鎖”,“讀”會加“讀鎖”。當出現讀寫鎖衝突的時候,後訪問的事務必須等前一個事務執行完成,才能繼續執行。
注意: 業務有序列化的需求,但是我們不會設定資料庫事務為序列化隔離級別,而是在應用端設定解決(例:U盾)。