tidb 事务执行过程中读数据是当前读还是快照读?

请问下,tidb执行事务的时候,需要先将事务涉及到的数据从tikv 读到tidb server的内存中,去tikv上去读数据时候,我的理解是当前读吧(直接读取最新的数据)不需要根据start.tso去进行判断,但是官网这里的表述是发生事务的时候

  1. TiDB 从 TiKV 获取 start_ts 版本下对应的数据。


这里的表述是值这个读请求的意思是指单纯的一个只读事务,还是说这是个写事务,先读取再更改数据?
我的理解是在1个tidb的写事务中(比如update),去读数据的时候应该直接当前读(加锁读取最新的数据)不需要根据start.tso去进行判断吧?不知道我的这个理解是否正确

https://docs.pingcap.com/zh/tidb/stable/optimistic-transaction#tidb-乐观事务模型

不管是乐观事务,还是悲观事务,不论是读请求,还是写请求,都有可能在同一个时间点发生
这个时候,就会产生问题:

  1. 读的时候是 X 值,写的时候是否需要保持一致?
  2. 写的时候是 X 值,然后在读的时候是否需要保持一致?
  3. 因为是 N 个请求,会落在同一个时间点,或者相邻的时间点上,需要获取时间周期内最新的有效值

因为悲观事务和乐观事务,对于数据处理的方式不一样,要结合几个点去看会更合适

童牧的事务解读,推荐你看看

有点烧脑,做好心理准备 :cowboy_hat_face:

1 个赞

当前读是悲观事务模式下的概念,乐观事务模式下的读都是快照读,加锁和锁冲突检查都是在prewrite阶段来解决的

https://docs.pingcap.com/zh/tidb/stable/sql-faq#tidb-是否支持-select-for-update
https://docs.pingcap.com/zh/tidb/stable/pessimistic-transaction#悲观事务模式的行为

除悲观锁下 select for update 是当前读,其他情况的 select 都是快照读,不加锁的。

2 个赞

啊,tidb 在乐观事务模式下不支持当前读,也就是说,在乐观模式下,读只存在快照读一种形式?像这种select xxx for update的当前读是不支持的?

乐观事务支持select for update,但任然是快照读,因此和select的结果是一样的,只是在COMMIT时走了一下加锁解锁的流程

老师,你好
其实不是很能够理解哈,那么请问下,如果在乐观事务模式下,去执行一条update 语句更新数据,那肯定是先把这条数据读到tidb server的mem buffer 中,那么读这条数据的时候,也是按照快照读的方式去读取这条数据嘛(通过该事务的start.tso去进行对比)?那么这样读到的数据不是最新的?有没有可能存在什么问题呢?

比如MySQL的update去更新数据的时候,就是直接通过当前读,读到数据的最新版本,在这个数据的最新版本上更新数据

不存在问题。在prewrite阶段有个步骤,就是进行版本检查,检查write列的commit_ts是否晚于自己的start_ts,如果是,说明有版本冲突(有其它事务已经提交),直接取消整个事务。因此乐观事务虽然是快照读,但是它提交成功的前提是没有其它事务比自己先提交,这也保证了即使快照读也是最新数据。另外这里不能和MySQL进行对比,MySQL没有乐观事务

那这个应该就不是读数据了把,只是判断一下是否有比自己到的start_ts;

其实也是可以理解为,在乐观事务模型下,更新数据的时候,虽然是按照快照读的方式读取数据,其实是可以读到最新的数据

可以这么理解,否则会报write conflict

该主题在最后一个回复创建后60天后自动关闭。不再允许新的回复。