mysql mvcc gap lock_为什么说 MVCC 和 Gap Lock 解决了 MySQL 的幻读问题

周一的时候被问到了幻读的问题,之前都是看别人写的文章没有建套环境来实际操作一下。

其实很多问题不仅是要看源码,还是需要动动手,光看还是会忘记。

先说结论在忽略参数设置的情况下, MySQL 的确使用 MVCC 配合 Gap Lock 解决了 RR 隔离级别下的当前读(用 Gap Lock)和快照读(用 MVCC)的幻读问题。

我们先来建立测试用的基础表

CREATE TABLE `t` (

`id` int(11) NOT NULL,

`c` int(11) DEFAULT NULL,

`d` int(11) DEFAULT NULL,

PRIMARY KEY (`id`),

KEY `c` (`c`)

) ENGINE=InnoDB;

insert into t values(0,0,0),(5,5,5),

(10,10,10),(15,15,15),(20,20,20),(25,25,25);

MVCC 快照读解决幻读

然后 先来看看在 RR 级别下因为 MVCC 的关系解决幻读的情况

session1

session2

session3

line 1

begin;

select * from t where d =5;

line 2

update t set d = 5 where id = 0

line 3

select * from t where d =5;

line 4

insert into t value(1, 1, 5)

line 5

select * from t where d =5;

line 6

commit;

line 1 session 1

mysql>begin;

Query OK, 0 rows affected (0.00sec)

mysql> select * from t where d = 5;+----+------+------+

| id | c | d |

+----+------+------+

| 5 | 5 | 5 |

+----+------+------+

1 row in set (0.00 sec)

line 2 session 2 执行后 line 3 session 1

mysql> update t set d = 5 where id =0;

Query OK,1 row affected (0.00sec)

Rows matched:1 Changed: 1Warnings: 0

mysql> select * from t where d = 5;+----+------+------+

| id | c | d |

+----+------+------+

| 5 | 5 | 5 |

+----+------+------+

1 row in set (0.00 sec)

line 4 session3 执行后的 line 5 session 1

mysql> insert into t value (1, 1, 5);

Query OK,1 row affected (0.01sec)

mysql> select * from t where d = 5;+----+------+------+

| id | c | d |

+----+------+------+

| 5 | 5 | 5 |

+----+------+------+

1 row in set (0.00 sec)

可以看到在快照读的情况下, RR 隔离级别可以通过 MVCC 保护自己事务内的数据,无论外面如何修改。

Gap Lock 解决当前读下的幻读

当前读的情况下我们就无法达到刚才的效果了,还是刚才那个流程

session1

session2

session3

line 1

begin;

select * from t where d =5 for update;

line 2

update t set d = 5 where id = 0

line 3

select * from t where d =5 for update;

line 4

insert into t value(1, 1, 5)

line 5

select * from t where d =5 for update;

line 6

commit;

我为 session 1里的所有查询都加上当前读的 for update 。会发现从 session2 开始就被阻塞了。

这里就是在执行 select * from t where d = 5 for update 的时候因为 d 上没有索引的关系,MySQL 直接将该字段的全部范围都打上了 Gap Lock,所以无法执行插入更新操作,就阻塞住了。

可以看到通过 Gap Lock 我们即使在当前读也被阻止了幻读,因为 Gap Lock 的关系 session c 尝试往里插入新数据也同样被阻塞从而保证了数据的一致性。

所以回到文中开始的那个问题,MySQL 在 RR 事务隔离级别下,的确通过 MVCC 以及 Gap Lock 解决了幻读问题,是我答错了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值