全面分析與總結 MySQL 事務中那些事兒

事務基礎路線

相關書籍推薦

事務定義

事務就是一組 DML 語句的集合。事務保證了對數據庫中數據的一致性操作。

存儲引擎

在日常開發中,我們常用的存儲引擎有 InnoDB 和 MyISAM 兩種存儲引擎。然而 MyISAM 是不支持事務操作的。

事務的提交方式

示例代碼

CREATE TABLE `user`  (
`id` int(10) UNSIGNED ZEROFILL NOT NULL AUTO_INCREMENT,
`name` varchar(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`age` int(11) NULL DEFAULT 0,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;

mysql [email protected]:demo> desc user;
+-------+------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+-------+
| id | int(10) unsigned | NO | PRI | <null> | |
| name | varchar(10) | NO | | <null> | |
| age | int(11) | YES | | 0 | |
+-------+------------------+------+-----+---------+-------+
3 rows in set
Time: 0.012s

-- 插入語句
insert into `user`(`id`,`name`, `age`) values
(1,'張三', 12),(2,'李四', 13),(3,'王五',14),(4,'趙六',15);

MySQL 中的事務默認採用的是自動提交,即一條 SQL 語句就是一個事務。默認提交方式可以通過參數 auto_commit 參數進行設置。MySQL 中的事務提交方式主要分爲手動提交和自動提交方式。隱式提交屬於自動提交的一種特殊方式。

自動提交

下面的 SQL 語句,針對 user 表做一個 update 操作,當MySQL 執行這條 SQL 語句之後,數據就進行了持久化存儲,數據就不能進行回滾了,除非我們手動的 update 回原來的數據。

// 執行 update 語句之前表數據
mysql [email protected]:demo> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 張三 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+------+-----+
4 rows in set
Time: 0.009s
// 執行 update 語句
mysql [email protected]:demo> update `user` set name = '張三1' where id = 1;
Query OK, 1 row affected
Time: 0.004s
// 查詢update 語句之後的表數據
mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三1 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+-------+-----+
4 rows in set
Time: 0.010s

通過上面的示例代碼,可以看出,在默認的情況下,我們執行一個 SQL 語句,就會自動的存儲到表中。

手動提交

手動處理事務的提交方式,需要用到commit 關鍵字。下面羅列幾個 MySQL 事務中需要涉及到的幾個關鍵詞。begin: 開啓一個事務,也可以使用 start transaction,兩者都是等價的。

rollback: 回滾一個事務的操作 ,也可以使用 rollback work,兩者都是等價的。

commit: 提交一個事務的操作, 也可以使用 commit work,兩者都是等價的。

savepoint transactionId: 保存一個事務點。

release transactionId: 釋放一個事務點。

rollback transactionId: 回滾到指定的事務點。

1.此時我們新建一個客戶端A,開啓一個事務操作。

// 開啓事務
mysql [email protected]:demo> begin;
Query OK, 0 rows affected
Time: 0.002s
// 執行 update 語句
mysql [email protected]:demo> update `user` set name = '張三' where id = 1;
Query OK, 1 row affected
Time: 0.002s
// 查看當前事務修改結果
mysql [email protected]:demo> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 張三 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+------+-----+
4 rows in set
Time: 0.010s

2.此時新建一個客戶端 B,開啓一個事務操作。

// 開啓一個事務
mysql [email protected]:demo> begin;
Query OK, 0 rows affected
Time: 0.002s
// 執行查詢語句
mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三1 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+-------+-----+
4 rows in set
Time: 0.010s

通過上面的對比,發現在客戶端 A 執行了一個 update 操作,事務內查詢id=1 的 name 值爲張三,然而在客戶端 B 查詢到 id=1 的 name 值爲張三 1。這就是事務之間的隔離性(可重複讀)。是因爲客戶端 A 還沒執行 commit 操作。

隱式提交

這裏的隱式提交指的是事務的嵌套,就是一個事務裏面包含着另外的一個事務。當事務裏面在開啓事務時,第一個事務默認會執行 commit 操作。1.此時我們新建一個客戶端A,開啓一個事務操作。

mysql [email protected]:demo> begin;
Query OK, 0 rows affected
Time: 0.002s
mysql [email protected]:demo> update `user` set name = '張三1' where id = 1;
Query OK, 1 row affected
Time: 0.002s
mysql [email protected]:demo> begin;
Query OK, 0 rows affected
Time: 0.002s
// 執行 sql 查詢語句
mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三1 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+-------+-----+
4 rows in set
Time: 0.009s

此時在客戶端 A 的事務內又開啓了另外一個事務,執行 SQL 查詢語句後,發現數據是修改後的值。

2.此時新建一個客戶端 B,無需開啓事務。

mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三1 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+-------+-----+
4 rows in set
Time: 0.009s

從理論上分析,由於客戶端 A 的事務沒有提交,此時我們查詢到的數據不應該是事務內修改後的值,然而我們執行查詢時,發現數據表的值是修改後的值,這證明嵌套事務會自動提交(此時的事務隔離級別是可重複讀)。如果你認爲當前的事務隔離級別是未提交讀,那你可以嘗試關閉 MySQL 服務這極端的操作在來查詢數據,你的到的結果也是如此。

提交點

所謂的提交點,就是指在一個事務中,做一個類似於數據快照一樣的操作。在數據爲提交之前,我們可以針對不同的數據快照進行回退。代碼演示:

// 開啓事務
mysql [email protected]:demo> begin;
Query OK, 0 rows affected
Time: 0.002s
// 查看修改前的數據
mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+-------+-----+
4 rows in set
Time: 0.010s
// 創建一個 savepoint
mysql [email protected]:demo> savepoint trans_1;
Query OK, 1 row affected
Time: 0.002s
// 執行修改操作
mysql [email protected]:demo> update `user` set name = '張三1' where id = 1;
Query OK, 1 row affected
Time: 0.002s
mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三1 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+-------+-----+
4 rows in set
Time: 0.010s
// 回滾savepoint
mysql [email protected]:demo> rollback trans_1;
// 查詢數據
mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+-------+-----+
4 rows in set
Time: 0.010s

執行回滾快照之後,update 語句執行的修改操作被撤回了。

事務的四大特性

事務的四大特性分別指的是 ACID,只有具備這四大特性的數據庫,纔可具備事務的操作。這四大特性分別是原子性、持久性、隔離性和持久性。

原子性

定義:原子性指的是事務操作具備原子操作,一個事務裏面的 SQL 操作要麼全部成功要麼全部失敗,不能存在一些 SQL 成功,一些 SQL 執行失敗。場景:銀行轉賬,你給小明轉賬 100 塊,此時給小明的賬戶增加 100 塊是一個 SQL 語句,你賬戶上減少 100 塊是一個 SQL 語句,原子性就是指的這兩個 SQL 要全部成功。示例:

update user_account set money = money - 100.00 where user_name = '自己';
update user_account set money = money + 100.00 where user_name = '小明';

一致性

定義:一致性指的是事務操作前後必須滿足業務約束。場景:銀行轉賬,你當前賬戶有 200 塊,小明有 100 塊。你給小明轉賬 100 塊之後,你賬戶有 100 塊,小明賬戶有 200 塊。此時不管是轉賬失敗還是成功,賬戶的總金額還是和轉賬之前的總金額保持一致的。示例:

// 計算事務操作之前的總和
select sum(money) as sum_money from user_account where user_name = '自己' and user_name = '小明';
|-----sum_money-----|
| 300.00 |
update user_account set money = money - 100.00 where user_name = '自己';
update user_account set money = money + 100.00 where user_name = '小明';
// 計算事務操作之後的總和
select sum(money) as sum_money from user_account where user_name = '自己' and user_name = '小明';
|-----sum_money-----|
| 300.00 |

隔離性

定義:隔離性指的是多個事務之間是相互隔離的,事務之間是互不受影響的。但這種場景需要考慮事務的隔離級別。文章後面內容頁會針對事務之間的隔離級別做特別的演示。場景:銀行轉賬,你當前賬戶存在 200 塊錢,你此時給小明轉賬 100 塊,同時你女朋友用你的賬戶在執行支付操作,這兩種場景屬於兩個事務操作,兩種操作是互不受影響的。示例:

// 轉賬小明操作
update user_account set money = money - 100.00 where user_name = '自己';
// 女朋友支付操作
update user_account set money = money - 100.00 where user_name = '自己';

持久性

定義:持久性指的是事務一旦提交,就不能進行回滾(撤回),永久的保存在磁盤中。場景:銀行轉賬,你當前給小明轉賬 100,點擊了確認操作,此時你後悔轉賬了,此時是沒法撤回的,因爲這個操作已經被提交,也就表明小明賬戶上已經多 100 了。

// 開啓事務
begin;
update user_account set money = money - 100.00 where user_name = '自己';
update user_account set money = money + 100.00 where user_name = '小明';
// 提交操作
commit;
select money from user_account where user_name = '自己'; // 100.00
select money from user_account where user_name = '小明'; // 200.00
// 執行回滾
rollback
//此時金額是不發生改變
select money from user_account where user_name = '自己'; // 100.00
select money from user_account where user_name = '小明'; // 200.00

事務隔離級別

事務的隔離級別是針對兩個或兩個以上的事務之間是否相互是隔離的,這裏的隔離其實就是指的事務對數據做了操作,在事務在commit 之前,其他的未提交事務是否可以讀到相應修改的數據。大致邏輯如下圖:

1.當事務1 開啓時,數據表中的 id=1 的數據,age=2;

2.事務1執行 update 操作,將 id=1的數據,age 設置爲 1;

3.此時在事務 1 還未提交時,開啓事務 2;

4.事務2 對數據表id=1 的數據進去 select;

5.由於事務 1 執行了 update 操作,當事務 2 去執行 select 操作時,是返回 age=1?還是 age=2?這就涉及到事務的隔離級別。

系統隔離級別

MySQ默認使用的可重複讀隔離級別。如下可以查看 MySQL 事務隔離級別。

mysql [email protected]:demo> show variables like '%iso%';
+-----------------------+-----------------+
| Variable_name | Value |
+-----------------------+-----------------+
| transaction_isolation | REPEATABLE-READ |
| tx_isolation | REPEATABLE-READ |
+-----------------------+-----------------+
2 rows in set
Time: 0.011s

transaction_isolation是tx_isolation 的別名,推薦使用transaction_isolation選項,因爲在 MySQL8 開始,tx_isolation將被廢棄。

未提交讀

定義:所謂的未提交讀,指的是當一個事務 A內對數據做了操作還沒有執行commit ,另外一個事務B是可以讀到事務A修改後的數據。如上圖中,事務二去做查詢時,返回的值就是 2。設置隔離級別:

mysql [email protected]:demo> set session transaction isolation level READ UNCOMMITTED;
Query OK, 0 rows affected
Time: 0.002s
mysql [email protected]:demo> show variables like '%iso%';
+-----------------------+------------------+
| Variable_name | Value |
+-----------------------+------------------+
| transaction_isolation | READ-UNCOMMITTED |
| tx_isolation | READ-UNCOMMITTED |
+-----------------------+------------------+
2 rows in set
Time: 0.010s

代碼演示:

「1.開始事務 A。」

// 開啓事務前查詢數據
mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三1 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+-------+-----+
4 rows in set
Time: 0.010s
// 設置當前會話的隔離級別
mysql [email protected]:demo> set session transaction isolation level READ UNCOMMITTED;
Query OK, 0 rows affected
Time: 0.002s
// 開啓事務
mysql [email protected]:demo> begin;
Query OK, 0 rows affected
Time: 0.002s
// 執行修改操作
mysql [email protected]:demo> update `user` set name = '張三' where id = 1;
Query OK, 1 row affected
Time: 0.002s
// 查詢數據已被修改(但當前事務還未被提交)
mysql [email protected]:demo> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 張三 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+------+-----+
4 rows in set
Time: 0.011s

「2.開啓事務 B。」

// 設置當前會話的隔離級別
mysql [email protected]:demo> set session transaction isolation level READ UNCOMMITTED;
Query OK, 0 rows affected
Time: 0.002s
// 開啓事務
mysql [email protected]:demo> begin;
Query OK, 0 rows affected
Time: 0.002s
// 執行 SQL 查詢
mysql [email protected]:demo> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 張三 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+------+-----+
4 rows in set
Time: 0.011s

通過上面的事務 A 和事務 B 可以看得出,在事務 A 還沒提交時,事務 B 就能讀取到事務A 修改後的數據。在演示代碼時,需要注意的是,需要在事務 A 開啓之後執行 update 操作之前,將事務 B 開啓。

提交讀

定義:所謂的提交讀,指的是當一個事務 A內對數據做了操作並且提交了,另外一個事務B在還未提交時,是可以讀到事務A修改後的數據。如上圖中,事務二去做查詢時,如果此時事務一已經執行了 commit,此時返回的結果仍是 2。設置隔離級別:

mysql [email protected]:demo> set session transaction isolation level READ COMMITTED;
Query OK, 0 rows affected
Time: 0.002s

代碼演示:

「1.開始事務 A。」

mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三1 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+-------+-----+
4 rows in set
Time: 0.011s
// 設置當前會話的事務隔離級別
mysql [email protected]:demo> set session transaction isolation level READ COMMITTED;
Query OK, 0 rows affected
Time: 0.002s
// 開啓事務
mysql [email protected]:demo> begin;
Query OK, 0 rows affected
Time: 0.002s
// 執行修改操作
mysql [email protected]:demo> update `user` set name = '張三' where id = 1;
Query OK, 1 row affected
Time: 0.002s
// 提交事務
mysql [email protected]:demo> commit;
Query OK, 0 rows affected
Time: 0.003s
// 查看事務執行結果
mysql [email protected]:demo> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 張三 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+------+-----+
4 rows in set
Time: 0.011s

「2.開啓事務 B。」

// 設置當前會話的事務隔離級別
mysql [email protected]:demo> set session transaction isolation level READ COMMITTED;
Query OK, 0 rows affected
Time: 0.002s
// 開啓事務
mysql [email protected]:demo> begin;
Query OK, 0 rows affected
Time: 0.002s
// 查看數據(此時事務 A 一定要處於未執行 commit 語句)
mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三1 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+-------+-----+
4 rows in set
Time: 0.011s
// 再次查看數據(此時事務 A 一定要處於執行 commit 語句)
mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+-------+-----+
4 rows in set
Time: 0.011s

通過上面的示例代碼,可以看出,當事務 A 提交之後,事務 B 內就可以讀到修改後的數據。記住在事務 B 內執行 select 語句時,事務 A 的提交狀態。

可重複讀

定義:所謂的可重複讀,指的是當一個事務 A內對數據做了操作並且提交了,另外一個事務B在還未提交時,讀到的數據永遠是事務B開始時的狀態,是不會讀取到事務 A 提交後的數據。如上圖中,事務二去做查詢時,如果此時事務一已經執行了 commit,此時返回的結果是 1。設置隔離級別:

mysql [email protected]:demo> set session transaction isolation level REPEATABLE-READ;
Query OK, 0 rows affected
Time: 0.002s

「1.開啓事務 A。」

mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三1 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+-------+-----+
4 rows in set
Time: 0.011s
// 設置當前會話的事務隔離級別
mysql [email protected]:demo> set session transaction isolation level REPEATABLE-READ;
Query OK, 0 rows affected
Time: 0.002s
// 開啓事務
mysql [email protected]:demo> begin;
Query OK, 0 rows affected
Time: 0.002s
// 執行修改操作
mysql [email protected]:demo> update `user` set name = '張三' where id = 1;
Query OK, 1 row affected
Time: 0.002s
// 提交事務
mysql [email protected]:demo> commit;
Query OK, 0 rows affected
Time: 0.003s
// 查看事務執行結果
mysql [email protected]:demo> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 張三 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+------+-----+
4 rows in set
Time: 0.011s

「2.開啓事務 B。」

mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三1 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+-------+-----+
4 rows in set
Time: 0.011s
// 設置當前會話的事務隔離級別
mysql [email protected]:demo> set session transaction isolation level REPEATABLE-READ;
Query OK, 0 rows affected
Time: 0.002s
// 開啓事務
mysql [email protected]:demo> begin;
Query OK, 0 rows affected
Time: 0.002s
// 執行查詢操作
mysql [email protected]:demo> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 張三1 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+------+-----+
4 rows in set
Time: 0.011s
// 提交事務
mysql [email protected]:demo> commit;
Query OK, 0 rows affected
Time: 0.003s
// 查看事務執行結果
mysql [email protected]:demo> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 張三 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
+----+------+-----+
4 rows in set
Time: 0.011s

通過上面的示例代碼,可以看出,當事務 A 提交之後,事務 B 內是不可以讀到修改後的數據,當事務 B 提交之後(事務 B 沒錯 DML 語句操作),但是查詢到數據和事務 A 提交後的結果一致。

串行

定義:所謂的串行,指的是當一個事務 A內對數據做了操作並且處於未提交狀態,另外一個事務B在去操作數據時,是不會被立馬執行的,而是需要等到事務 Acommit 之後,纔可以進行數據操作。如上圖中,事務二去做查詢時,如果此時事務一處於未提交狀態,事務二會一直處於等待狀態,直到事務 A commit 之後返回結果值 2。設置隔離級別:

set session transaction isolation level serializable;
mysql [email protected]:demo> begin;
Query OK, 0 rows affected
Time: 0.002s

代碼演示:

「1.開始事務 A」

// 設置當前會話的隔離級別
mysql [email protected]:demo>set session transaction isolation level serializable;
// 開啓事務
mysql [email protected]:demo> begin;
Query OK, 0 rows affected
Time: 0.002s
// 執行修改
mysql [email protected]:demo> update `user` set name = '張三1' where id = 1;
Query OK, 1 row affected
Time: 0.002s
// 提交事務
mysql [email protected]:demo> commit;
Query OK, 0 rows affected
Time: 0.004s
// 檢測修改
mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三1 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
| 5 | 小QI | 16 |
+----+-------+-----+
5 rows in set
Time: 0.009s

「2.開始事務 B」

// 設置當前會話的隔離級別
mysql [email protected]:demo>set session transaction isolation level serializable;
// 開啓事務
mysql [email protected]:demo> begin;
Query OK, 0 rows affected
Time: 0.002s
// 執行查詢(此時事務 A 一定要還未執行 commit 命令)
mysql [email protected]:demo> select * from user;
+----+-------+-----+
| id | name | age |
+----+-------+-----+
| 1 | 張三1 | 12 |
| 2 | 李四 | 13 |
| 3 | 王五 | 14 |
| 4 | 趙六 | 15 |
| 5 | 小QI | 16 |
+----+-------+-----+
5 rows in set
Time: 14.159s(查詢消耗時間,是由於 sessionA處於阻塞過程中)

此時一定要特別注重事務 B 在執行 select 語句所用的時間,這裏爲什麼是 14s 多,就是因爲在這段時間中,事務 A 還未處於commit 狀態,因此事務 B 在執行查詢時,一直處於等待狀態,直到事務 A 進行了 commit 操作。

隔離級別的幾種現象

事務隔離級別 髒讀 不可重複度 幻讀 加鎖度
未提交讀 ×
提交讀 × ×
可重複讀 × × ×
串行 × × ×

髒讀:指的是事務處於未提交狀態,對數據做了操作,其他的事務是可以讀取到當前事務所做的操作。

不可重複度:一個事務 A對數據做了操作並進行了提交。其他事務對於事務A在提交前和提交後讀到的數據不一致。側重(update/delete)語句。

幻讀:一個事務 A對數據做了操作並進行了提交。其他事務對於事務A在提交前和提交後讀到的數據不一致。側重(insert)語句。

可重複讀:事務 B 在提交前,不管事務 A 是否提交,讀到的數據永遠是事務 B 開始時的狀態。

隔離級別優缺點分析

a.通過上面幾種情況的分析,可重複讀的隔離級別是最優的選擇。真正做到了事務之間是相互隔離,避免了髒讀、不可重複讀和幻讀的問題。b.串行是最大程度上保證了數據的一致性,但是屬於枷鎖處理,併發性不高。c.未提交讀和不可重複度,雖然存在數據不一致的情況,但效率更高,適合用在對數據一致性要求不高的場景中。

閱讀推薦

1.爲什麼不建議把數據庫部署在docker容器內?

2.宇宙最好用的編程文檔查詢工具

3.這可能是 Mac 上最好用的繪圖軟件。

4.MongoDB都有哪些使用的業務場景

5.國內都有哪些免費的圖牀


本文分享自微信公衆號 - 卡二條的技術圈(qq1005349393)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章