mysql 复制

mysql复制的最小单位是event,而不是一条一条的SQL语句。(binlog_format一定为row,否则主从数据可能会不一致。其实哪怕为row格式了,也可能不一致。)

为了保障数据一致性必须设置的参数:

sync_binlog=1

innodb_flush_log_at_trx_commit=1

relay_log_recovery=1

这个参数是为了保证IO线程的高可用。原因是IO线程接收到master的event后,会写一个master.log的文件,记录当前接受到的位点。同时还会写relay log。把以上参数设为1后,如果从库crash了,那么会清空当前所有relay log,并以SQL线程记录的位点从master上重新拉取event。也就是说,IO线程的高可用,依赖于SQL线程的高可用。

 

relay_log_info_repository=table

这个参数的作用是保证SQL线程的高可用。当主节点把event发到从机的relay_log后,从机开始应用event,然后它会有一个relay_info.log的文件,记录当前event应用到哪了。而另一个参数sync_relay_log_info控制应用多少个event之后

写一次relay_info.log。也就是说,极端情况下,你从节点crash了,会重复执行sync_relay_log_info个事务。这样主从就不一致了。而把上述参数设置为table后,从库会在mysql.slave_relay_log_info这张表中记录当前位点。并且这个操作是一个原子操作,图示如下:

begin:

apply log event;

apply log event;

update mysql.slave_relay_log_info;

commit;

 

如果你要做级联复制的话,从库要把log_slave_updates打开

master_info_repository=table 这个参数也能打开,不过对高可靠没有帮助。

 

并行复制:

关于slave_parallel_type

logical_clock。逻辑时钟的并行回放,很简单,你event在主上面是怎么执行的,我在从上面就怎么执行。

这个是基于组提交进行的。说白了,在主库上,你一个组内提交的事务,是一定没有锁冲突的。所以到了从库,你的事务只要在一个组内的,就能进行分发到不同线程同时执行。 你binlog中,last_commit只要相同,那么就是在一组的。可以mysqlbinlog -vv  xxxxxx | grep last_commit看一下。

 

writeset。从8.0开始支持。这个特性,哪怕你主库没有组提交,从库也能并行回放。原理是只要你事务和事务之间,主键不一致。说明这几个事务是可以并行回放的。

 

 

semi—sync:

这个功能出现的原因。是mysql在这之前,复制是异步的。主库是不关心的从库拉了多少event过去,也不关心你event执行成什么样子了。

而半同步复制,就是我一个事务commit了,至少要保障我有一个从机接收到了日志。

参数:

plugin-dir

plugin-load="rpl_semi_sync_master:rpl_semi_sync_master.so;rpl_semi_sync_slave:rpl_semi_sync_slave.so"

rpl_semi_sync_master_enable

rpl_semi_sync_slave_enable

rpl_semi_sync_master_timeout

rpl_semi_sync_master_wait_point=after_sync/after_commit

这个参数很重要。如果是传统异步复制,在主库event进入从库的TCP/IP队列之后,就会向主库发送ACK。

结合下前面的内容,MySQL的2阶段提交。after_sync指的就是在innodb prepare log和write binlog 之后必须要等待从库的ACK才会进入到innodb commit log。

而after_commit就类似于上面,主库等待ACK是在innodb commit log之后。

两者的区别是,如果你的rpl_semi_sync_master_timeout无限大,所有从库的io线程都断了。你insert一条记录。after_sync在主库上读不到数据,而after_commit能读到。

after_sync又被称为无损复制。

posted @ 2022-07-04 15:02  拿什么救赎  阅读(37)  评论(0编辑  收藏  举报