semisync
通过上面的步骤介绍,我们看到,在binlog文件的最新位置更新的时候,就已经通过signal_update函数发送信号给binlog的dump线程,该线程就可以将事务的binlog同步到从库,从库接收到日志之后,就可以relay日志,实现了主从同步。因此,再次重复说明一下,按照上面的解释,在事务真正提交完成之前就开始发送了binlog已经更新的信号,dump线程收到信号,即可以进行binlog的同步。而semisync的作用是什么呢?
实际上,有没有semisync机制,上面介绍的mysql的有关事务提交中关于binlog的流程都是一样的,semisync的作用,只是主从之间的一个确认过程,主库等待从库返回相关位置的binlog已经同步到从库的确认,(而实际实现则是等待dump线程给用户会话线程一个回复),没有得到确认之前(或者等待时间达到timeout),事务提交则在该函数(步骤)上等待直至获得返回。具体执行binlog已经同步到某个位置的的确认函数为repl_semi_report_binlog_sync,函数如下:
int repl_semi_report_binlog_sync(Binlog_storage_param *param,
constchar *log_file,
my_off_t log_pos)
{
if(rpl_semi_sync_master_wait_point == WAIT_AFTER_SYNC)
return repl_semisync.commitTrx(log_file, log_pos);
return 0;
}
通过观察上述函数,我们可以看到有个rpl_semi_sync_master_wait_point变量与WAIT_AFTER_SYNC比较,如果不相等,则直接返回,直接返回则表示不需要在此时此刻确认binlog是否已经同步,而这个变量的取值来自于半同步参数semi_sync_master_wait_point的初始设置,我们可以设置为after_sync与after_commit。这两个参数含义的区别是:after_sync是在将binlog sync到disk之后(具体是否真正sync由参数sync_binlog的值决定)进行日志同步确认,而after_commit是将事务完成在innodb里面提交之后再进行binlog的同步确认。两者确认的时间点不同,after_sync要早于after_commit.
接下来,我们来看repl_semisync.commitTrx 这个函数,这个函数有两个传入参数,一个是binlog文件,一个binlog文件的位移。我们来看这个函数的含义吧。算了,还是直接用源码的注释来解释吧。
上面的注释说得相当清楚,就是该commiTRX函数会等待binlog-dump返回已经同步到该位置的报告,如果还没有同步到该位置,则继续等待,直到超时返回。
当会话线程收到该函数的返回时,事务的提交过程继续往下走,直至在innodb真正提交。