mvcc和读写冲突

每个读的事务都要去lock cf里面去扫描判断key上是否有锁,我感觉遇到读写冲突然后等待的情况是不是挺多的。

1 个赞

我觉得应该也不会太多,悲观事务在执行commit之前,lock cf里面是占位符,读事务看到占位符就bypass了。只有真正开始执行commit操作的时候,才会把占位锁改成prewirte锁,这时读事务才有可能遇到读写冲突

哦,原来是这样的。

1 个赞

想请问下老师,mvcc去读取数据的时候,先是从lock cf 里面做判断,还是先从wrtie cf 里面做判断呢?

https://cloud.tencent.com/developer/news/466426

1 个赞

先读lock cf,再去读write cf,wirte cf中没有数据(大于255字节)再去default cf读

请问下老师,有相应的官方文档或者文章说明或者代码片段嘛

东旭这篇上古博文的后面简单描述了读流程,可供参考

好的,谢谢老师的回复

感觉题主想问的是:

1)mvcc多版本控制,有写写冲突、读写冲突,写写冲突无法避免,但是读写怎么会有冲突呢?

2)其实读写也会有冲突的,原因如下:

(1)当前读请求(点读场景除外,点读不需要从pd获取read_start_ts tso),然后去lock cf 查看是否有读取记录的锁信息 {key,[0,read_start_ts]},如果有,说明有其他的事务正在进行prewrite阶段,如果lock cf没有,继续查找write cf,查找是 {key,[read_start_ts,infinite]},如果有,说明有其他事务在进行commit阶段。总的来说当前的读请求就不满足,需要等待,即所谓的读写冲突。如果两个都没有,则满足读请求。

(2) 那也许会问上面情况中不管lock cf 是否有读取记录key的锁信息,不管write cf是否有事务的提交信息,如果有的话,为什么不去读取当前写事务write_start_ts之前的版本数据呢,即 {key,[0,write_start_ts)} 注意这里时间是右闭区间,这里的write_start_ts < read_start_ts, 那就不会有读写冲突了吗? 那要看write cf存储的是什么数据(事务key的提交信息和小于256字节的 row record信息),能否读取到这个数据?答案是代价更大,还不一定能读取到。

点读不需要从pd获取read_start_ts tso?---->这个是为什么呢?有文章或者代码可以说明嘛

曾经看到一个篇文章说tikv 在percolator模型的实践和优化中说point get 不需要start_ts,读取latest版本数据即可,一时半会找不到,回头我再找找。

是不是说这个: https://blog.csdn.net/vivo_tech/article/details/120411708

4.2.3 Point Read Without Timestamp 对于每个事务,我们需要先分配一个start_ts,然后保证事务只能看到在start_ts之前提交的数据。但是如果一个事务只读取一个key的数据,我们是否有必要为其分配一个start_ts呢?答案是否定的,我们只需要读取这个key的最新数据就可以了。

2 个赞

是的,赞一个

如果没有start.tso,怎么做比较呢,不是很理解啊

请问下,老师,这篇文章里面说的 对于读请求,遇到这类悲观锁的时候,不用像乐观事务那样等待解锁,可以直接返回最新的数据即可(至于为什么,读者可以仔细想想)。

其中,对于读请求—>这里指的读是快照都还是当前读呢?

遇到这类悲观锁的时候—>这里说的锁是占位锁,还是说是已经 将占位的悲观锁改写成标准的 Percolator 模型的锁?

遇到这类悲观锁的时候—>这里说的锁是占位锁,还是说是已经 将占位的悲观锁改写成标准的 Percolator 模型的锁?

这里应该说的是快照读遇到占位锁。首先,一般说的读请求都是快照读,如果是当前读的话,肯定会明确说明是当前读,因为当前读很特殊,读的是已提交的最新版本数据,并且需要上锁。另外假设他这里说的是当前读,那遇到悲观锁,不管是占位符还是prewrite锁,都是要被阻塞的,不可能直接返回最新的数据即可。文章里这句话,我理解是想说,当快照读遇到占位锁时,说明行上有事务,但是还没有执行COMMIT,因此肯定是不可见的,所以就直接去write cf上读小于自己start_ts的最新数据即可

感谢老师,我的理解也是这样的,当快照读遇到lock cf 里面有占位锁的时候,这说明持有这个占位锁的事务还未提交,因此是不可见的。