MySQL InnoDB 事务begin开启后还能读到变更内容 原因及解决

先说结论

执行begin之后并没有真的开启事务,事务开启是在第一次对数据表操作的时候。

场景还原

我们在把一张表接入binlog(MySQL的二进制日志文件)同步的时候,首次接入需要做下面这些操作:

  1. 全局读锁,所有人无法写入。因为读锁了,所以所有人无法改变现状,不能写入新的内容。
  2. 开启事务
  3. 读取binlog最后位置,记录后就可以增量从这里拉取
  4. 释放全局读锁 
  5. 同步全量数据,因为在事务里面,我们读取的是一份不会发生变化的快照

整体解释以下,因为如果我们把一张表接入增量系统,就需要先全量初始化,但是如何界定增量全量对得上呢,就需要短时锁全表,进行获取binlog最后位置,开启事务保证当前状态不发生改变。

但是理想很丰满,现实我们测试便知。

测试过程

我们用两个账号分别建立数据库连接来模拟接入服务的连接和其他操作数据库连接的操作。

连接A:查看当前数据

连接A:开始上锁

给数据库上一个全局的读锁,上锁成功,返回OK

FLUSH TABLES WITH READ LOCK

连接A:开启事务

BEGIN

连接A:读取binlog最后位置 

可以通过下面的语句获取binlog的最后位置

在大多数基于binlog实现增量同步更新的系统中,都支持通过MySQL的binlog指定位置开始消费的能力。

show master status;

连接B:修改数据

我们使用另外一个账号建立的连接修改其中一条数据,将id为2的数据从 “李四” 修改为 “赵九” 。

理论上将,连接A已经开启了事务,对本次修改应该不感知。

UPDATE `cdc_test`.`member` SET `username` = '赵九' WHERE `id` = 2;

连接A:查询全部内容

查询全部内容发现数据已经被修改

SELECT * FROM member

结论

在编写这个代码的时候,发现一直获取不到我们期望的表信息不变的结果。

最后发现,如果希望在后来的读取中读取快照内容,必须在加锁期间,读取数据触发事务开始。

所以,我们可以发现,InnoDB的事务并非从begin开始,而是我们第一次对表操作的时候开始的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员麻薯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值