mysql 5.7并行复制

关于mysql 5.7的并行复制策略,mysql 5.7.22开始支持的 基于writeset的并行复制策略
mysql多线程复制,需要遵循两个基本原则:1.不能造成更新覆盖,这就要求更新同一行的两个事务,必须被分发到同一个worker中,2.同一个事务不能被拆开,必须放到同一worker中!
一:5.7.22之前的COMMIT_ORDER并行复制方式,借助mysql的组提交,根据mysql两阶段提交,可以知道能达到redo  log  prepare阶段以及commit阶段的事务,就表示事务已经通过锁冲突的检验了!换句话说只要不是更新同一行,就可以并行复制!
MySQL 5.7 commit_order的并行复制策略的思想是:
1). 同时处于 prepare 状态的事务,在备库执行时是可以并行的;
2). 处于 prepare 状态的事务,与处于 commit 状态的事务之间,在备库执行时也是可以并行的,
针对commit_order的方式的并行复制策略,可以通过修改如下两个参数来影响并发的事务个数!
1) binlog_group_commit_sync_delay 参数,表示延迟多少微秒后才调用 fsync;
2)binlog_group_commit_sync_no_delay_count 参数,表示累积多少次以后才调用fsync。这两个参数是用于故意拉长 binlog 从 write 到 fsync的时间,以此减少 binlog 的写盘次数。在 MySQL 5.7 的并行复制策略里(COMMIT_ORDER方式),它们可以用来制造更多的“同时处于 prepare 阶段的事务”。这样就增加了备库复制的并行度。
二:mysql 5.7.22开始的基于writeset的并行复制策略中
2.1即便是主库是单线程执行的,那么从库也可能是并行的,只要没有冲突!之前COMMIT_ORDER方式是判断同时处于redo prepare或者commit的事务可以一同提交,这些事务的last committed一样。现在基于writeset的并发复制,计算last committed的方式发生变化,会依照事务的 write_set 中的HASH值与已提交的事务的 write_set 进行比对,如果没有冲突,则当前事务与最后一个已提交的事务共享相同的 last_commited, 否则将从全局已提交的 write_set 中删除那个冲突的事务以及之前提交的所有write_set,并退化到 COMMIT_ORDER 计算last_committed 。 每次计算完事务的 last_committed 值以后,检测当前全局已提交事务的 write_set 是否已经超过了 binlog_transaction_dependency_history_size 设置的值,如果超过,则清空已提交事务的全局 write_set,从新开始记录,清空之后意味着下一个也就是第一个事务肯定是COMMIT_ORDER方式计算last_committed,之后发生的事务再次对比已提交的事务的write_set,所以从库并行执行的最大事务个数还受这个binlog_transaction_dependency_history_size 参数影响!
2.2 binlog_transaction_dependency_history_size参数
在代码实现上,MySQL采用一个vector的变量存储已经提交的事务的HASH值(也就是writeset方式),所有已经提交的事务的所修改的主键和非空的UniqueKey的值经过HASH后与该vector中的值对比,由此来判断当前提交的事务是否与最近一段时间已经提交的事务更新了同一行,并以此确定依赖关系。
该向量的大小由参数binlog_transaction_dependency_history_size控制,取值范围为1-1000000 ,初始默认值为25000
2.3在计算writeset的时候,库名+表名+主键+唯一键(有的话),为什么需要加唯一键,
因为如果某个表主键为id ,唯一键为a,  主库执行:session A先 执行update t1 set  a=6  where  id=1; session B 执行update t1 set a=1 where id=2,, 那么如果你在计算writeset的时候没有考虑唯一键,那么这两个session的事务可能会在从库并行执行,就有可能sesstion B先执行而导致唯一键冲突而失败!
2.4对于没有主键的表 ,或者是有外键约束的表,writeset策略是没法并行的,也会暂时退化为单线程模型!
因为wirteset是通过 库名+表名+主键值+(唯一键名字和非空键值)来确定的唯一性的,
如果你没有主键,那么你不能保证算出来的hash 值是唯一的,因为唯一键可以为空,所以没有主键是不能用writeset的。又因为如果表上有外键,级联更新的行不会记录到binlog中,这样的冲突检测就不准确!
三:影响并行事务的多少的参数:
3.1针对commit_order的方式的并行复制策略,可以通过修改如下两个参数来影响并发的事务个数!
借助组提交,同一个组的last committed值一样,
1) binlog_group_commit_sync_delay 参数,表示延迟多少微秒后才调用 fsync;
2)binlog_group_commit_sync_no_delay_count 参数,表示累积多少次以后才调用fsync。这两个参数是用于故意拉长 binlog 从 write 到 fsync的时间,以此减少 binlog 的写盘次数。在 MySQL 5.7 的并行复制策略里(COMMIT_ORDER方式),它们可以用来制造更多的“同时处于 prepare 阶段的事务”。这样就增加了备库复制的并行度。
3.2针对writeset的并行复制方式:
binlog_transaction_dependency_history_size参数,控制最近一段时间已经提交的事务的个数,这个参数越大,理论上writeset的并行复制的事务可能会越多!
小结:不管是COMMIT_ORDER方式还是writeset方式的并行策略,从库都是判断last_committed是不是一样来决定事务是不是可以并行复制的;不同的复制策略只不过主库计算last_committed的方式不一样;writeset的力度更细,


请使用浏览器的分享功能分享到微信等