基于组提交的并行复制
在MySQL复制运行过程中,可能由于主从机器性能差异、大事务、大表DDL等原因导致主从复制延迟。并且由于SQL线程是单线程串行执行,当主节点写入压力较大时也非常容易造成复制延迟,针对这种情况,MySQL5.6提供了并行复制功能。其中把SQL线程分为coordinator_thread和worker,coordinator线程主要负责判断是否可并行执行,然后选择Worker线程执行事务的二进制日志,如果是DDL或是事务跨schema这种不可并行执行的,则等待worker线程执行完成后再执行当前日志。
并行复制维护着一张hash表,其记录了每个数据库有多少事务分发出去,执行事务的worker线程,因此分配线程是以数据库名分发的,当一个实例只有一个一个schema时,并行复制并不会带来有效提升。
随后,MySQL5.7推出了基于组提交的并行复制机制,即一个组提交的事务是可以并行回放到从库,原理是基于锁冲突检测,因为事务进入到prepare阶段,就说明事务之间没有冲突。组提交的信息存在binlog中,如果未开启GTID在5.7中提供了一种Anonymous_gtid的二进制日志event_type
|
|
如果事务具有相同的last_committed,则表示在同一个组内,可以进行并行回放。
开启组提交并行复制需要设置以下参数:
- slave_parallel_workers:worker线程数
- slave_parallel_type:并行复制类型,默认为5.6中的DATABASE,组提交模式需要设置为LOGICAL_CLOCK
此外,还有两个参数可以用于控制组提交的频率:
- binlog_group_commit_sync_delay:表示binlog提交后等待延迟多少时间再同步到磁盘,单位为微妙,默认值为0。设置延迟可以让多个事务在同一时刻提交,提高binlog组提交的并发率和效率,从而提高slave的吞吐量
- binlog_group_commit_sync_no_delay_count:表示在等待上面参数时,如果满足事务量,则结束等待直接提交。需要设置事务数,默认为0
Tips:如果需要强制slave上的binlog提交顺序和master一样,保证GTID的顺序,可以设置slave_preserve_commit_order,前提是开启了logical_clock和binlog(开启该参数对性能有一点影响)
ERROR 1864
开启logical_clock后可能会遇到如下错误
|
|
主要是因为从库slave_pending_jobs_size_max参数小于主库max_allowed_packet,需要将其设置大于主库max_allowed_packet
基于write set并行复制
在MySQL5.7.22中,MySQL又增加了一个并行复制策略:基于write set的并行复制。write set的思想在于不同事务的不同记录不重复,则都可以在从机上并行回访,达到一种按行分发的模式,并行性能更上一步。
参数binlog-transaction-dependency-tracking控制该策略,有三个可选值:
- COMMIT_ORDER:根据同时进入prepare和commit来判断是否可以并行的策略
- WRITESET:对于事务涉及的每一行,计算出hash值,组成一个writeset集合,当两个事务没有操作相同的行,它们的writeset就不存在交集,可以并行处理
- WRITESET_SESSION:在WRITESET基础上添加了一个约束,在主库上同一个线程先后执行的两个事务,在从节点执行时要保证相同的先后顺序
如果想要使用writeset,需要在主库设置下列两个参数:
|
|
writeset集合中的每一个元素都是hash值,hash值和transaction_write_set_extraction参数的算法有关,hash值作为唯一标识是通过"db+table+index+value"计算出来的,如果表上还存在唯一索引,insert对应的writeset就需要多增 加一个hash值。每行数据的具体格式为:
主键/唯一键 | 分隔符 | 库名 | 分隔符 | 库名长度 | 表名 | 分隔符 | 表名长度 | 键字段 | 分隔符 | 长度 – | – | – | – | – | – | – | – | –| – |