rdb为什么会数据丢失(gh-ost翻车使用后导致数据丢失)

相信对于很多 DBA 同学来说,由 Github 网站开源的在线 DDL 工具 gh-ost ,相信不会陌生。

rdb为什么会数据丢失(gh-ost翻车使用后导致数据丢失)(1)

对比另一款在线 DDL 工具 pt-osc,gh-ost 的开销更小。gh-ost 通过二进制日志(binlog)记录 DDL 变更过程中的修改,而 pt-osc 通过触发器记录修改变化。

显然,触发器开销更大,且 5.7 版本之前一张表只能有一个类型的触发器,因此使用 pt-osc 的限制也更多些。

因此,使用工具 gh-ost 来进行在线表结构变更操作几乎可以认为是目前 MySQL 的一种标准变更规范

然而,gh-ost 翻车了!在我们的生产环境中,使用 gh-ost 进行表结构变更后,导致了1条数据的丢失!

在金融业务中,数据丢失是绝对不容许发生的场景

我们的工程师同学经过周末连番的源码研究与测试,最终定位这的确是 gh-ost 代码 bug。

这意味着之前所有通过 gh-ost 进行 MySQL 数据库变更的操作,都有可能触发数据丢失。

复盘

接着,我给同学们复盘下使用 gh-ost 导致数据丢失的原因。

gh-ost 的基本实现原理如下图所示,具体实现不在本文章赘述,感兴趣的可移步官网:https://github.com/github/gh-ost

rdb为什么会数据丢失(gh-ost翻车使用后导致数据丢失)(2)

从源码实现的角度看,gh-ost 经历以下几个关键函数步骤:

1. addDMLEventsListener:添加对于二进制日志的过滤采集(指定表的二进制日志过滤)

2. ReadMigrationRangeValues:获取对应表唯一索引的max、min值

3. onBeforeRowCopy:将捕获的二进制日志应用到表 *_gho

4. iterateChunks:根据 min、max 值,批量插入数据到表 *_gho

5. rename & drop 新旧表

但是,存在一种可能性,addDMLEventListner后,对应的二进制日志“丢失”了!

这种情况发生的原因可能是因为 MySQL 数据库启用了 after_sync 模式的半同步复制(二阶段提交)。

怎么理解呢?可以通过下面的时序图来看:

rdb为什么会数据丢失(gh-ost翻车使用后导致数据丢失)(3)

从上图可以看到,在某些场景下,可能发生 gh-ost 开始捕获 DML 操作后的二进制日志,但是之前的二进制事务并没有提交!

在上图的案例中,步骤1 addDMLEventsListener 将会捕获记录5以后发生的日志。

然而,在步骤2 ReadMigrationRangeValues 中,获取 min、max的值将会是1、4。

这是因为由于 after_sync 半同步模式,记录5对应的事务还未提交(如网络原因,或从机宕机等场景),记录5对于 gh-ost 中的函数 ReadMigrationRangeValues 是不可见的。

因此,步骤3、4只会插入记录1-4,以及回放记录5之后的所有日志,但会丢失记录5。

既然知道了原因,那么修复就变得非常简单了。只需要在获取 min、max的边界值的时候通过一致性读取即可

SELECT MIN(UK),MAX(UK) FROM xxxLOCK IN SHARE MODE;

通过 LOCK IN SHARE MODE,即便发生上述 after_sync 半同步等待问题,则在函数 ReadMigrationRangeValues 执行过程中,需要等待上述事务提交才能完成边界值的获取。

这时,边界值就会变为1、5,从而不会导致数据的丢失。

总结

从上述复盘看,gh-ost 数据丢失的可能性是比较大的,而且并不只是一条记录的丢失。

理论上可以是最后一组提交事务的数量,且每个事务可能影响的记录也不止一条。

反观工具 pt-osc,其通过触发器捕获增量日志,因此不存在该问题。

另一方面,从这个案例中可以看到一致性共享读取的使用场景。

FOR UPDATE 的一致性排他读取大家都了解,但 LOCK IN SHARE MODE 何时使用呢?这个场景给了你很好的答案。

最后,在金融场景不能仅仅相信数据库的一致性检查。

在上述场景下,主从数据核对检查依然是一致的,没有数据丢失。

所以,金融场景一定还要有业务层的数据核对,通过逻辑核对,确保数据库中的数据是没有任何物理丢失。

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页