什麼是事務
一組原子性的SQL語句,可以提交或回滾的原子工作單元 。當事務對數據庫進行多次更改時,要麼在提交事務後所有更改成功,要麼在回滾事務時撤消所有更改。
事務特性
ACID特性
- A: atomicity(原子性):整個事務中的所有操作要麼全部成功,要麼全部失敗後回滾;
- C: consistency(一致性):整個數據庫總是從一個一致性狀態轉換爲另一個一致性狀態;
- I: isolation(隔離性):一個事務所做的的操作在提交之前,是不被其它事務所見的;
- D: durability(持久性):事務一旦提交,其所做的修改會永久保存於數據庫中。
事務生命週期
事務管理
顯式啓動事務:
BEGIN
BEGIN WORK
START TRANSACTION
結束事務:
# 提交
COMMIT
# 回滾
ROLLBACK
注:只有事務型的存儲引擎的DML語句才能支持此類操作
自動提交:
默認爲1,爲0時設爲非自動提交
> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set (0.00 sec)
set autocommit={1|0}
注:建議顯式請求和提交事務,而不要使用“自動提交”功能。
事務支持保存點:
SAVEPOINT identifier
ROLLBACK [WORK] TO [SAVEPOINT] identifier
RELEASE SAVEPOINT identifier
查看事務:
# 查看當前的事務
SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
#查看當前鎖定的事務
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
#查看當前等鎖的事務
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
事務隔離級別
MySQL事務支持四種隔離級別,從上至下更加嚴格
事務隔離級別 | 說明 | 髒讀可能性 | 不可重複讀可能性 | 幻讀可能性 | 加讀鎖 |
---|---|---|---|---|---|
READ UNCOMMITTED | 可讀取到未提交數據,產生髒讀 | Yes | Yes | Yes | No |
READ COMMITTED | 可讀取到提交數據,但未提交數據不可讀,產生不可重複讀,即可讀取到多個提交數據,導致每次讀取的數據不一致 | No | Yes | Yes | No |
REPEATABLE READ | 可重複讀,多次讀取數據都一致,產生幻讀,即讀取過程中,即使有其它提交的事務修改數據,仍只能讀取到未修改前的舊數據。此爲MySQL默認設置 | Yes | Yes | Yes | No |
SERIALIZABLE | 可串行化,未提交的讀事務阻塞修改事務(加讀鎖,但不阻塞讀事務),或者未提交的修改事務阻塞讀事務(加寫鎖,其它事務的讀,寫都不可以執行)。會導致併發性能差 | No | No | No | Yes |
MVCC和事務的隔離級別
MVCC(多版本併發控制機制)只在REPEATABLE READ和READ COMMITTED兩個隔離級別下工作。其他兩個隔離級別都和MVCC不兼容,因爲READ UNCOMMITTED總是讀取最新的數據行,而不是符合當前事務版本的數據行。而SERIALIZABLE則會對所有讀取的行都加鎖
如何指定事務隔離級別
參考:https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_tx_isolation
1.系統變量tx_isolation指定,默認爲REPEATABLE-READ,有效範圍:Global, Session
# 語法:
set tx_isolatioin='value';
# 有效值
READ-UNCOMMITTED
READ-COMMITTED
REPEATABLE-READ
SERIALIZABLE
2.服務器選項中指定
在/etc/my.cnf文件的[mysqld]塊中使用transaction-isolation選項設置
[mysqld]
transaction-isolation = value
事務隔離級別驗證
背景:通過兩個終端顯示啓動兩個事務來驗證,用作驗證的user表的表內容和表結構如下
mysql> desc user;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(30) | NO | | NULL | |
+-------+------------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)
mysql> select * from user;
+----+-------+
| id | name |
+----+-------+
| 2 | root |
| 3 | admin |
+----+-------+
2 rows in set (0.00 sec)
1.READ UNCOMMITTED級別
2.READ COMMITTED級別
3.REPEATABLE READ級別
4.SERIALIZABLE級別
未提交的讀事務阻塞修改事務(加讀鎖,但不阻塞讀事務)
未提交的修改事務阻塞讀事務(加寫鎖,其它事務的讀、寫都不可以執行)
注:此種事務隔離級別會導致併發性能差。
附加案例:如果一個事務產生了寫鎖,然後一直未結束事務,這樣會導致其它事務的讀、寫都不可以執行,對於這種情況,可以找到未結束並且導致阻塞的事務,手動將其kill。
拿上面未提交的修改事務阻塞讀事務的案例來驗證
打開第三個會話執行以下操作
死鎖