MVCC可以保存多少历史版本?

  1. TiDB 中的各种超时 | PingCAP 文档中心

GC 超时

TiDB 的事务的实现采用了 MVCC(多版本并发控制)机制,当新写入的数据覆盖旧的数据时,旧的数据不会被替换掉,而是与新写入的数据同时保留,并以时间戳来区分版本。TiDB 通过定期 GC 的机制来清理不再需要的旧数据。

默认配置下 TiDB 可以保障每个 MVCC 版本(一致性快照)保存 10 分钟,读取时间超过 10 分钟的事务,会收到报错 GC life time is shorter than transaction duration

  1. MVCC

很多数据库都会实现多版本并发控制 (MVCC),TiKV 也不例外。设想这样的场景:两个客户端同时去修改一个 Key 的 Value,如果没有数据的多版本控制,就需要对数据上锁,在分布式场景下,可能会带来性能以及死锁问题。TiKV 的 MVCC 实现是通过在 Key 后面添加版本号来实现,简单来说,没有 MVCC 之前,可以把 TiKV 看做这样的:

Key1 -> Value
Key2 -> Value
……
KeyN -> Value

有了 MVCC 之后,TiKV 的 Key 排列是这样的:

Key1_Version3 -> Value
Key1_Version2 -> Value
Key1_Version1 -> Value
……
Key2_Version4 -> Value
Key2_Version3 -> Value
Key2_Version2 -> Value
Key2_Version1 -> Value
……
KeyN_Version2 -> Value
KeyN_Version1 -> Value
……

注意,对于同一个 Key 的多个版本,版本号较大的会被放在前面,版本号小的会被放在后面(见 Key-Value 一节,Key 是有序的排列),这样当用户通过一个 Key + Version 来获取 Value 的时候,可以通过 Key 和 Version 构造出 MVCC 的 Key,也就是 Key_Version。然后可以直接通过 RocksDB 的 SeekPrefix(Key_Version) API,定位到第一个大于等于这个 Key_Version 的位置。
当用户确信自己需要更长的读取时间时,比如在使用了 Mydumper 做全量备份的场景中(Mydumper 备份的是一致性的快照),可以通过调整 TiDB 中mysql.tidb 表中的 tikv_gc_life_time 的值来调大 MVCC 版本保留时间,需要注意的是 tikv_gc_life_time 的配置是立刻影响全局的,调大它会为当前所有存在的快照增加生命时长,调小它会立即缩短所有快照的生命时长。过多的 MVCC 版本会拖慢 TiKV 的处理效率,在使用 Mydumper 做完全量备份后需要及时把 tikv_gc_life_time 调整回之前的设置。

更多关于 GC 的信息,请参考 GC 机制简介文档。

事务超时

垃圾回收 (GC) 不会影响到正在执行的事务。但悲观事务的运行仍有上限,有基于事务超时的限制(TiDB 配置文件 [performance] 类别下的 max-txn-ttl 修改,默认为 60 分钟)和基于事务使用内存的限制。

形如 INSERT INTO t10 SELECT * FROM t1 的 SQL 语句,不会受到 GC 的影响,但超过了 max-txn-ttl 的时间后,会由于超时而回滚。

看完这两篇文章后,我想问TiDB MVCC是否是严格的10分钟(无事务)保留机制,就是是否过了10分钟就必须已经完成清理历史数据? 另外10分钟内如果有多个更新是否全部都保留?10分钟感觉默认值比较短
像Oracle MySQL都有undo 表空间的概念,TiDB是否也有这种概念? 或者换句话问,TiDB中的mvcc是否也和普通数据一样存储,是否有单独的TiKV Region ?或者类似undo表空间的地方?

如果你设置mvcc的保留时间是10分钟,那就是严格的只保留10分钟内的数据,但是并不一定过了10分钟就马上清理,gc清理也是有设置的,每个多长时间一清,以及清理的线程数等,10分钟内多个更新都会保留的,默认值确实比较短,你可以在考虑自己集群性能的情况下,设置成合适的时间。
orcle和mysql对于历史数据使用undo来处理,undo的原理是将你修改过的数据单独存放到undo,如果需要获取,就从undo里面拿,但是tidb使用的是mvcc,这是两个不同的概念,tidb的mvcc就相当于给每条数据存储都打上时间戳,存储到你当前表里的region中,你正常查的时候,直接取最新时间戳的数据返回给你,如果你查历史数据,就找对应时间戳的数据返回给你,不会单独存放在其他的region中。

好的,感谢回复,我看你的回复是MVCC默认10分钟,全部更新保留,没有undo表空间的概念就是本地多版本。

tidb底层是键值对也就是kv没有表空间的概念,数据被修改实际上是插入了新的修改后的kv,gc操作有个定时时间,默认10分钟,kv过期也有个时间差默认也是10分钟,都可以改

学习了

请参考这个
https://docs.pingcap.com/zh/tidb/stable/read-historical-data#历史数据保留策略

此话题已在最后回复的 60 天后被自动关闭。不再允许新回复。