MySQL Transaction--MySQL事务提交流程02

事务回滚标志XID

XID作为事务是否回滚的判断数据,在事务Prepare阶段分别写入Undo Log(内存)和Binlog Cache(内存)中,Undo日志会产生Redo日志,并在后续的flush阶段和Sync阶段写到操作系统文件缓存和物理磁盘上,在数据库实例故障恢复时,Undo Log能通过已经固化到磁盘的Redo Log来进行恢复。

复制主从节点同步Binlog

参数sync_binlog决定Binlog的刷盘策略,当sync_binlog = 0时,Binlog文件的刷盘操作由操作系统控制,当sync_binlog = N且N != 1时,Binlog文件的刷盘操作需等待Binlog的N次提交,因此只有当sync_binlog != 1时,主节点无需等待Binlog刷盘即可向从节点发送Binlog。

  • 当sync_binlog != 1时,当Binlog Cache中的数据Flush到操作系统缓存后,便会唤醒Dump进程发送Binlog Event。
  • 当sync_binlog = 1时,需等到Binlog Cache中数据Flush到操作喜欢缓存且调用Sync命令将数据刷新到物理磁盘后,才会唤醒Dump进程发送Binlog Event。

半同步复制差异

半同步复制after_sync和after_commit的主要区别在于:

  • 当参数rep_semi_sync_master_wait_point=AFTER_SYNC时,先等待从库返回ACK再进行InnoDb层事务提交
  • 当参数rep_semi_sync_master_wait_point=AFTER_COMMIT时,先进行InnoDb层事务提交再等待从库返回ACK

参数binlog_order_commits决定InnoDb层事务提交在那个阶段完成:

  • 当binlog_order_commits=1时,InnoDb层事务提交需要按照Binlog顺序进行提交,在事务提交的Commit阶段完成。
  • 当binlog_order_commits=0时,InnoDb层事务提交无需按照Binlog顺序进行提交,在事务提交的Clean阶段完成。

主节点数据延迟问题

某些业务使用阿里云开源的Canal监听主库Binlog变化,并接收到Binlog后会立即向主库发起查询,在极端情况下,会发现主库上无法查询到该条Binlog对应的数据记录,返回空结果集导致业务异常。

阿里云在MySQL主实例上默认配置参数如下:

innodb_flush_log_at_trx_commit = 1
sync_binlog = 1
binlog_order_commits = 0
rpl_semi_sync_master_wait_point = after_sync

PS:阿里云在MySQL 5.6版本也实现after_sync模式。

怀疑原因:

由于sync_binlog = 1,主节点在Sync阶段进行Binlog刷盘后向从节点和Canal发送Binlog,并在commit阶段等到半同步的从节点发送ACK响应,在接收到从节点ACK响应前,主节点上事务持有锁并处于活跃状态,此时Canal接收到Binlog并向主节点发起查询,由于事务仍处理活跃未提交状态,因此无法读取到未提交事务产生的"新数据"。

解决办法:

由于业务已经规避物理删除记录逻辑主键更新的问题,因此当业务接收到一条Binlog后,理论上必然可以按照该binlog找到对应记录,因此当按照主键查询返回空时,对该操作进行休眠重试,直到查询返回记录。

遗留问题:

从主节点产生Binlog到业务基于Binlog发起查询期间,对应记录可能已经发生多次修改,需要业务能兼容这些数据变化,无法保证业务能查到Binlog产生时间点的数据。

posted @ 2021-07-29 08:33  TeyGao  阅读(197)  评论(0编辑  收藏  举报