MySQL 幻读和不可重复读的区别

4 篇文章 0 订阅
1 篇文章 0 订阅

背景

最近在学习 MySQL 的事务,幻读和不可重复读很容易搞混。故做此记录总结。先给出两者的定义。

  • 不可重复读
    如果一个事务修改了另一个未提交事务读取的数据,就意味着发生了不可重复读现象。
    r1[x]…w2[x]…((c1 or a1) and (c2 or a2) in any order)
    解释下:r1[x] 表示事务 T1 读字段 x 的值,然后 w2[x] 表示事务 T2 修改了 x 的值
  • 幻读
    如果一个事务先根据某些搜索条件查询出一些记录,在该事物未提交的时候,另一个事务写入了一些符合那些搜索条件的记录(INSERT、DELETE、UPDATE 操作),就意味着发生了幻读操作。

MySQL 的 REPEATABLE READ 可重复读,下文简称为 RR 通过 MVCC 版本链解决了幻读问题,还可以避免可重复读问题。下面看实例。

客户端 1: 开启事务,从表中读数据

mysql> begin;

mysql> select * from user;
+----+----------+--------+-------+
| id | userName | gender | email |
+----+----------+--------+-------+
|  1 | aaron    | M      | sunne |
|  2 | abin     | W      | NULL  |
|  3 | cool     | M      | NULL  |
|  4 | fourth   | W      | ????? |
|  5 | fifth    | W      | abcde |
|  6 | six      | W      | NULL  |
+----+----------+--------+-------+
6 rows in set (0.01 sec)

客户端 2:插入数据,隐式提交事务

mysql> insert into user values(null, 'seven', 'W', 'alll');

客户端 1:再次查询


mysql> select * from user;
+----+----------+--------+-------+
| id | userName | gender | email |
+----+----------+--------+-------+
|  1 | aaron    | M      | sunne |
|  2 | abin     | W      | NULL  |
|  3 | cool     | M      | NULL  |
|  4 | fourth   | W      | ????? |
|  5 | fifth    | W      | abcde |
|  6 | six      | W      | NULL  |
+----+----------+--------+-------+
6 rows in set (0.01 sec)

可以看到 RR 隔离级别避免了幻读。至于可重复读,我们可以修改比如 id = 5 的数据来复现,就不做赘述了。

修改隔离级别

我们修改隔离级别为 READ COMMITTED:已提交读,下位简称为 RC,来复现可重复读出现的问题。
首先修改客户端 1 和客户端 2 的隔离级别:

mysql> set session transaction isolation level read committed;
mysql> select  @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| READ-COMMITTED          |
+-------------------------+
1 row in set (0.00 sec)

客户端 1 开启事务读表:

mysql> begin;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from user;
+----+----------+--------+-------+
| id | userName | gender | email |
+----+----------+--------+-------+
|  1 | aaron    | M      | sunne |
|  2 | abin     | W      | NULL  |
|  3 | cool     | M      | NULL  |
|  4 | fourth   | W      | ????? |
|  5 | fifth    | W      | abcde |
|  6 | six      | W      | NULL  |
|  7 | seven    | W      | alll  |
|  8 | seven    | M      | hah   |
+----+----------+--------+-------+
8 rows in set (0.00 sec)

客户端 2 修改表数据隐式提交:

mysql> update user set userName = '7' where id = 7;

客户端 1 再次读取数据:

mysql> select * from user;
+----+----------+--------+-------+
| id | userName | gender | email |
+----+----------+--------+-------+
|  1 | aaron    | M      | sunne |
|  2 | abin     | W      | NULL  |
|  3 | cool     | M      | NULL  |
|  4 | fourth   | W      | ????? |
|  5 | fifth    | W      | abcde |
|  6 | six      | W      | NULL  |
|  7 | 7        | W      | alll  |
|  8 | seven    | M      | hah   |
+----+----------+--------+-------+
8 rows in set (0.00 sec)

此时客户端 1 读到 id = 7 的 userName = 7,和第一次读取时不一样,出现了不可重复读。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值