回到过去,找回遗失的珍宝 - TiDB 的历史读功能

简介: 数据作为业务的核心,关系着整个业务的生死,所以对于数据库来说,数据的安全性是放在首位的,从宏观角度来看,安全性不仅仅在于的数据库本身足够稳定不会主动的丢失数据,有的时候更是对业务本身甚至人为失误造成损失是否有足够且便捷的应对方案,例如在游戏行业中经常遇到的反作弊(作弊玩家回档)问题,对于金融业务的审计需求等等,如果在数据库层面上提供相关机制,会让业务开发的工作量和复杂度减少很多。传统的方案会定期备份数据,几天一次,甚至一天一次,把数据全量备份。当意外发生的时候,可以用来还原。但是用备份数据还原,代价还是非常大的,所有备份时间点后的数据都会丢失,你绝对不希望走到这一步。另外全量备份带来的存储

数据作为业务的核心,关系着整个业务的生死,所以对于数据库来说,数据的安全性是放在首位的,从宏观角度来看,安全性不仅仅在于的数据库本身足够稳定不会主动的丢失数据,有的时候更是对业务本身甚至人为失误造成损失是否有足够且便捷的应对方案,例如在游戏行业中经常遇到的反作弊(作弊玩家回档)问题,对于金融业务的审计需求等等,如果在数据库层面上提供相关机制,会让业务开发的工作量和复杂度减少很多。

传统的方案会定期备份数据,几天一次,甚至一天一次,把数据全量备份。当意外发生的时候,可以用来还原。但是用备份数据还原,代价还是非常大的,所有备份时间点后的数据都会丢失,你绝对不希望走到这一步。另外全量备份带来的存储和计算资源的额外开销,对于企业来说也是一笔不小的成本。

可是这种事情是无法完全避免的,我们所有的人都会犯错。对于一个快速迭代的业务,应用的代码不可能做到全面充分的测试,很可能因为应用逻辑的 Bug 导致数据写错,或者被恶意用户找到 bug,当你发现问题时,可以立即把应用回滚到旧版本,但是写错的数据却会一直留在数据库里。

出现这种问题的时候,你该怎么办?你只知道有些数据不对了,但是对的数据是什么,你不知道。如果能回到过去,找回之前的数据该多好。

TiDB 针对这样的需求和场景支持历史版本的读取,所以可以将错误的版本之前的数据取出来,将损失降到最低。

如何使用 TiDB 的历史读功能
使用这个功能非常简单,只需要执行一个 SET 语句:

set @@tidb_snapshot = "2016-10-10 09:30:11.123"

这个 session variable 的名字是 TiDB 里定义的 tidb_snapshot, 值是一个时间的字符串,精确到毫秒,执行了这个语句之后,之后这个客户端发出的所有读请求,读到的都是这个时间点看到的数据,这时是不能进行写操作的,因为历史是无法改变的。如果想退出历史读模式,读取最新数据,只需要再次执行一个 SET 语句:

set @@tidb_snapshot = ""

把 tidb_snapshot 设置成空字符串就可以了。

即使在那个历史时间点后,发生了 Schema 更改也没有关系,TiDB 会使用当时的 Schema 执行 SQL 请求。

TiDB 历史读功能和其他数据库的比较
这个功能 MySQL 并不支持,但是在其他的数据库里,比如 Oracle, PostgreSQL 里有类似的功能,叫做历史表(Temporial Table),是一个SQL 标准。使用的方法是需要你用特殊的建表语法,额外创建一张历史表,历史表比原表多了两个系统定义的字段,代表有效时间,这多出的两个字段是系统维护的。当原表更新数据的时候,系统会把旧版本数据插入到历史表里,当你查询历史数据时,需要用一个特殊的语法指定历史时间,得到需要的结果。

TiDB 和其他数据库的历史表功能相比,主要有以下两个优势:

1,系统默认支持

如果不是默认的行为,我们通常不会特意去建一张历史表,到真正需要用到的时候,你会发现历史表没有创建。

2,使用方便

不需要额外建一张表,不需要用特殊的语法查询。

3,全局视角,而不是以表为单位

TiDB 即使执行了 Drop Table, Drop Database 这样的操作,也可以读到旧的数据。

TiDB 的历史读功能的实现
MVCC
为了方便理解,我们这里把实现原理做了一下简化,去掉了分布式事务相关的部分,TiDB 真正的实现会复杂一些。如果想了解完整的实现细节,请持续关注 TiDB,我们会在后期逐步完善卖QQ靓号平台事务模型部分的文档帮助大家了解。

TiDB 的底层是 TiKV, TiKV 底层的存储引擎是 RocksDB, 存储的都是基本的 Key/Value Pair。在 SQL 层的一张表的一行,经过两次编码后,才得到最终的,存在 RocksDB 里的 key。

第一次编码得到的 Key,包含了 table ID 和 record ID,得到这个 key 可以定位到这一行。

第二次编码在第一次编码的 Key 的基础上,添加一个全局递增的时间戳,这个时间戳就是数据写入的时间。

所有的 Key 都带着一个全局唯一的时间戳,也就意味着,新的写入不会覆盖旧的写入,即使是删除操作,写入也只是一个删除标记,并没有真正的删数据。同一行数据的多个版本是同时存在 RocksDB 里,按照时间顺序,连续的排列在一起。

当一个读事务开始时,会从一个集群的时间分配器获取一个时间戳,这个时间点之前写入的数据,对这个事务是可见的,这个时间点之后写入的数据,对这个事务是不可见的,所以这个事务可以保证 Repeatable Read 这个隔离级别。

TiDB 在向 TiKV 发起读请求时会带上这个时间戳,在 TiKV 拿到这个时间戳后,会比较这个时间戳和这一行的多个版本,找到不大于这时间戳的最大的版本,返回给 TiDB。

以上就是 TiDB MVCC 的简化版的原理。

所以 TiDB 其实原本就是用一个历史时间来读取数据的,只不过这个历史时间是系统在事务开始时自动获取的当前时间。使用 tidb_snapshot 这个 session variable,实际上是用一个用户指定的时间取代系统自动获取的时间去读取数据。

你可能会有一个疑问,如果所有的版本都保留,数据占用的空间会不会无限膨胀?

这里就需要介绍 TiDB 的垃圾回收机制了。

TiDB 的垃圾回收
TiDB 会定期执行垃圾回收的任务,把过老的旧版本删掉,真正的从 RocksDB 里删掉,这样空间就不会无限膨胀了。

那么多久以前的老的数据会被删掉呢?这个 GC 的过期时间,是通过配置一个参数来控制的,你可以配置成十分钟,一个小时,一天或永远不回收。

所以,TiDB 的历史读功能是有限制的,只能读取到 GC 过期时间之后的数据,你可能会希望把时间设置的尽量久,但是这也是有代价的,GC 过期时间设置的越久,空间占用的会越大,读性能也会有所下降,如何配置这个时间,就要看业务的类型和需求了。

如果数据非常重要,安全是首要考虑的因素,或数据更新变动很少,建议把 GC 过期时间设置的长一点。如果数据不那么重要,或数据更新很频繁,建议把 GC 过期时间设置的短一点。

总结
TiDB 的历史读功能,把 TiDB 原生的读取机制开放出来,让用户用最简单的方式使用,我们希望这个功能,可以给 TiDB 的用户创造更多的价值。

目录
相关文章
|
3月前
|
算法 Shell
数据魔术师:如何在ClkLog中恢复丢失数据并实现数据更新
​ 在数字化的世界里,数据就是企业的血液,是推动业务发展的关键动力。想象一下,你正在运行你的业务,依赖ClkLog为你提供的数据,突然,由于网络波动或其他原因,定时脚本未能执行,页面上的数据缺失了。或者你刚刚优化了你的算法,但你需要重新计算以前的数据以便与新的算法保持一致。这种情况下,数据的完整性和稳定性就显得尤为重要,它们不仅影响业务的正常运行,而且直接关系到业务决策的准确性和及时性。
数据魔术师:如何在ClkLog中恢复丢失数据并实现数据更新
|
4月前
|
存储 Windows
删除的视频怎样才能恢复?详尽指南
误删视频别慌,本文概览实用恢复技巧。首要行动:停用涉事存储以防数据覆盖。探索回收站,检索近期删除。备份是宝藏,搜寻云或外置硬盘。软件救星谨慎付费,试用验证。极端情况,专家服务可开盘恢复,代价高昂需权衡。
删除的视频怎样才能恢复?详尽指南
|
6月前
|
弹性计算 监控
阿里云 历史服务器怎么查看
【1月更文挑战第15天】【1月更文挑战第74篇】阿里云 历史服务器怎么查看
207 5
从堆里找回“丢失”的代码相关命令简介
从堆里找回“丢失”的代码相关命令简介
|
SQL 数据可视化 数据库
新司机的致胜法宝,使用ApexSql Log2018快速恢复数据库被删除的数据
新司机的致胜法宝,使用ApexSql Log2018快速恢复数据库被删除的数据
|
SQL 安全 关系型数据库
正确、安全的手动删除历史binlog,尽情释放磁盘空间。
正确、安全的手动删除历史binlog,尽情释放磁盘空间。
1043 0
|
SQL 数据库连接 数据库
游戏版本要回滚,还好我机智备份了数据库,代码直接拿走
今天有空整了下之前写的数据库备份的代码。
275 0
游戏版本要回滚,还好我机智备份了数据库,代码直接拿走
|
关系型数据库 MySQL 数据库
Mysql 遇到神奇的“本次本客户端效现象”,数据库并未被改变 + 神奇“卡顿现象”
Mysql 遇到神奇的“本次本客户端效现象”,数据库并未被改变 + 神奇“卡顿现象”
198 0
Mysql 遇到神奇的“本次本客户端效现象”,数据库并未被改变 + 神奇“卡顿现象”
|
存储 运维 关系型数据库
十年难得一遇!从数据误删到全量恢复的惊险记录
线上的数据库服务我们有完善的备份策略和恢复预案,数据即使被误删除了也是能够恢复的,误删除的数据量恢复只是时间问题。但各位同学自己部署的测试环境或者是在自己电脑中的开发环境的数据库就没有同级别的资源保障了。如果恰好你又把一些不能丢失的数据放到了这种环境中,那么建议要做定期备份,有备才能无患。
下一篇
无影云桌面