[MySQL源码] 在复制线程事务提交与更新relay-log.info之间crash导致的复制不一致

转载请署名:印风

——————————————-

最近发现一种情况,在xid event和flush_relay_log_info中间crash,可能会导致数据不一致。

即事务提交了,但relay-log.info文件还没更新,这会造成重启crash recovery后事务被重复执行一次。
幸好,在innodb层记录了这些信息。并且Percona也提供了一个选项来利用这些信息。
1.相关全局变量
在trx/trx0sys.c文件中定义了如下变量
最后一个commit的事务的slave信息:
trx_sys_mysql_master_log_name
trx_sys_mysql_master_log_pos
trx_sys_mysql_relay_log_name
trx_sys_mysql_relay_log_pos
最后一个commit的binlog信息:
trx_sys_mysql_bin_log_name
trx_sys_mysql_bin_log_pos
2.写入信息
那么在什么时候会记录这些信息呢?
在函数mysql_bin_log_commit_pos中,确定写入innodb的binlog位置,backtrace如下
#0  mysql_bin_log_commit_pos
#1  0x00000000007c88d4 in innobase_commit_ordered_low
#2  0x00000000007cca97 in innobase_commit_ordered
#3  0x000000000071efc5 in run_commit_ordered
#4  MYSQL_BIN_LOG::trx_group_commit_leader
#5  0x000000000071f49d in MYSQL_BIN_LOG::write_transaction_to_binlog_events
#6  0x000000000071f681 in MYSQL_BIN_LOG::write_transaction_to_binlog
#7  0x000000000071ff6b in binlog_flush_cache
#8  binlog_commit_flush_trx_cache
#9  MYSQL_BIN_LOG::log_and_order
#10 0x000000000068a112 in ha_commit_trans
#11 0x000000000062f2fd in trans_commit_stmt
#12 0x000000000057c6bc in mysql_execute_command
在函数innobase_commit_ordered_low中先调用mysql_bin_log_commit_pos确定位置
再调用innobase_commit_low,如果是slave线程,直接访问active_mi->rli,将当前执行完的relay log坐标及对应binlog坐标拷贝到trx的成员变量中。然后调用trx_commit_for_mysql->trx_commit_off_kernel
当有对数据做更改时,及insert_undo和update_undo不为空时,调用trx_write_serialisation_history
这里会先更新undo,然后调用trx_sys_update_mysql_binlog_offset来更新ibdata中的relaylog/binlog里的坐标信息。这些都是在一个mtr中提交。
3.
重启后,会在完成crash recovery后,打印相关信息。
innobase_init
   –>innobase_start_or_create_for_mysql
         –>recv_recovery_from_checkpoint_finish
             –>trx_sys_print_mysql_master_log_pos 打印relay log信息,并将其拷贝到上述变量中
             –>trx_sys_print_mysql_binlog_offset  打印binlog信息
然后如果变量将相关信息记录到以上几个变量中。
在回到innobase_init函数后,会根据innobase_overwrite_relay_log_info来重写relay-log.info文件。
2977     if(innobase_overwrite_relay_log_info) {
……
直接重写relay-log.info文件
}
innobase_overwrite_relay_log_info 对应的MySQL选项是innodb_recovery_update_relay_log。
我们只要开启该参数,就会进入这部分代码逻辑。
因此,最好开启skip-slave-start,并需要关注err log中打印出来的信息与relay-log.info中的信息是否一致。当然,如果你使用了别的引擎,这些信息就没什么作用了。
关于该选项的文档:
相关链接:

 

Post Footer automatically generated by wp-posturl plugin for wordpress.


Comments

Leave a Reply

Your email address will not be published. Name and email are required


Current month ye@r day *