ITPub博客

首页 > > > MyRocks在XA事务场景的使用和优化-1

MyRocks在XA事务场景的使用和优化-1

作者:u_ea6ef15d346a 时间:2019-06-24 19:59:04 0 删除 编辑

本文介绍MyRocks在网易互联网核心业务上的实践,在推进MyRocks落地过程中,遇到了很多问题,主要集中在xa事务上,所以本文讨论的重点是MyRocks在xa事务上的实践。

MyRocks 在某业务上线后遇到了下面与xa有关的问题:

  1. Slave无法回放xa事务
  2. session 退出后 xa prepare的数据丢失
  3. 内存泄漏问题
  4. 使用 mysqladmin 无法shutdown 从库问题
  5. stop slave 导致从库crash问题

本文会分三篇文章介绍上面这些问题,从代码层面分析原因以及我们是如何解决的。

上:zhuanlan.zhihu.com/p/70

中:zhuanlan.zhihu.com/p/70

下:zhuanlan.zhihu.com/p/70

slave 无法回放xa 事务

这个问题还得从 MySQL 5.7 对XA事务的改进说起,5.7之前,xa prepare 的数据是没有持久化的,如果在xa commit 之前 session 退出或者mysqld crash,数据就丢了。为了解决这个问题,MySQL5.7将外部XA在binlog中的记录分成了两部分,使用两个GTID来记录。执行prepare的时候就记录一次binlog,执行commit/rollback再记录一次。由于XA是分成两部分记录,那么XA事务在binlog中就可能是交叉出现的。Slave端的SQL线程在回放的时候需要能够在这些不同事务间切换。

MySQL的解决方法是在xa start的时候,存储引擎分离与当前线程thd绑定的事务对象,xa prepare的时候重新绑定xa start分离的事务对象,这是引擎层的做法,server层的做法是在xa prepare的时候先创建一个具有相同xid的transaction_ctx对象,然后把原xid的transaction_ctx从server层的transaction_cache中移除,解除与thd的绑定,最后把新创建的transaction_ctx插入到transaction_cache中。但是这里要提一点的是,MySQL XA Replication的实现只考虑了innodb一种事务引擎的情况,当添加其他事务引擎的时候,原本的一些代码逻辑就会有问题,下文中会在介绍。

引擎层 handlerton 新增了接口来实现分离和绑定的逻辑:

void (*replace_native_transaction_in_thd)(THD *thd, void *new_trx_arg,void **ptr_trx_arg);

innodb 已经实现了该接口。

xa start xid的时候调用上面的函数,入参 new_trx_arg=NULL, ptr_trx_arg = &thd->ha_data[innodb_hton_ptr->slot].ha_ptr_backup。

xa prepare xid的时候还会调用上面的函数,入参new_trx_arg=&thd->ha_data[innodb_hton_ptr->slot].ha_ptr_backup, ptr_trx_arg=NULL。xa prepare 的时候,事务对象trx 在trx_disconnect_prepared函数中与thd解除关联,并且从trx_sys->mysql_trx_list中移除。xa commit xid 的时候在trx_sys->mysql_rw_list链表中查找该xid对应的trx,找到后提交然后释放trx对象。

MyRocks也必须实现该接口才能保证slave端顺利回放 xa 事务在binlog中交叉出现的这种场景,InnoSQL仿照innodb的方式实现replace_native_transaction_in_thd接口解决了问题。

Session退出导致xa prepare的数据丢失

MyRocks处理xa事务时还存在一个问题,xa prepare后,如果session退出会导致数据丢失。这是因为Session退出时会调用引擎的close_connection API接口,对于rocksdb,是rocksdb_close_connectioin函数:

导致数据丢失的原因是delete tx, tx是Rdb_transaction_impl的对象,看一下它的析构函数:

上来就执行一个rollback(),rollback()函数底层还会继续调用rocksdb的事务对象回滚掉事务,导致数据丢失。可以在析构函数中判断如果事务处于prepare状态,则不执行rollback,其他资源可以释放。

这样session退出可以确保已经prepare的xa事务数据不丢。

原文作者:;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-12-12

  • 博文量
    120
  • 访问量
    483