事务回滚标志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发起查询期间,对应记录可能已经发生多次修改,需要业务能兼容这些数据变化,无法保证业务能查到Binlo*生时间点的数据。