mysql-事務-校驗不可重複讀和幻象讀

mysql-事務-校驗不可重複讀和幻象讀

問題描述

爲了驗證mysql在默唸的隔離級別是不是解決了不可重複讀和幻象讀的問題

預備

  • 不可重複讀: 事務A讀到了事務B已經提交的修改數據
  • 幻象讀: 事務A讀到了事務B已經提交的新增數據

校驗

查看mysql數據庫默認隔離級別


mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set

驗證是否解決不可重複讀

  • 事務A查詢用戶金額,此時開啓事務B
  • 事務B修改用戶的金額,並提交事務
  • 查看事務A中是否讀取到事務B提交的修改

事務A                           |    事務B
mysql> start transaction;       |    mysql> start transaction;
Query OK, 0 rows affected       |    Query OK, 0 rows affected
                                |    
mysql> select * from t_account; |    mysql> select * from t_account;
+----+---------+--------+       |    +----+---------+--------+
| id | user_id | amount |       |    | id | user_id | amount |
+----+---------+--------+       |    +----+---------+--------+
|  1 |       1 |     23 |       |    |  1 |       1 |     23 |
+----+---------+--------+       |    +----+---------+--------+
1 row in set                    |    1 row in set
                                |    
                                |    mysql> update t_account set amount=10 where user_id=1;
                                |    Query OK, 1 row affected
                                |    Rows matched: 1  Changed: 1  Warnings: 0
                                |    mysql> select * from t_account;
                                |    +----+---------+--------+
                                |    | id | user_id | amount |
                                |    +----+---------+--------+
                                |    |  1 |       1 |     10 |
                                |    +----+---------+--------+
                                |    1 row in set
                                |    # 事務B提交修改
                                |    mysql> commit;
                                |    Query OK, 0 rows affected
mysql> select * from t_account; |
+----+---------+--------+       |
| id | user_id | amount |       |
+----+---------+--------+       |
|  1 |       1 |     23 |       |
+----+---------+--------+       |
1 row in set                    |


# 事務A也提交
mysql> commit;
Query OK, 0 rows affected

mysql> select * from t_account;
+----+---------+--------+
| id | user_id | amount |
+----+---------+--------+
|  1 |       1 |     10 |
+----+---------+--------+
1 row in set


可以發現,直至事務B提交了事務,在事務A中,也沒有讀取到事務B修改的值。只有事務A也提交事務,才能查詢到修改的值,但這已經沒有事務了

驗證是否解決幻象讀

  • 事務A查詢用戶金額,此時開啓事務B
  • 事務B新增另一個用戶的帳戶,並提交事務
  • 查看事務A中是否讀取到事務B提交的新增用戶的帳戶的數據

事務A                           | 事務B
mysql> start transaction;       | mysql> start transaction;
Query OK, 0 rows affected       | Query OK, 0 rows affected
                                | 
mysql> select * from t_account; | mysql> select * from t_account;
+----+---------+--------+       | +----+---------+--------+
| id | user_id | amount |       | | id | user_id | amount |
+----+---------+--------+       | +----+---------+--------+
|  1 |       1 |     10 |       | |  1 |       1 |     10 |
+----+---------+--------+       | +----+---------+--------+
1 row in set                    | 1 row in set
                                | 
                                | mysql> INSERT INTO `dbl`.`t_account` (`user_id`, `amount`)
								|								VALUES ('2', '8');
                                | 
                                | Query OK, 1 row affected
                                | mysql> select * from t_account;
                                | +----+---------+--------+
                                | | id | user_id | amount |
                                | +----+---------+--------+
                                | |  1 |       1 |     10 |
                                | |  3 |       2 |      8 |
                                | +----+---------+--------+
                                | 2 rows in set
                                | 
                                | mysql> commit;
                                | Query OK, 0 rows affected
mysql> select * from t_account; |
+----+---------+--------+       |
| id | user_id | amount |       |
+----+---------+--------+       |
|  1 |       1 |     10 |       |
+----+---------+--------+       |
1 row in set                    |


可以發現,直至事務B提交了事務,在事務A中,也沒有讀取到事務B新增的帳戶數據

結論

由上述驗證,發現,mysql默認的隔離級別(repeatable read)確實解決了不可重複讀和幻象讀的問題

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