一、事務描述
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 的自動提交;
血淚教訓:曾經自信過了頭的一次 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盾)。