半同步机制
MySQL复制默认情况下是异步的。其复制机制中,为了实现RPO=0,出现了半同步复制机制。与异步复制相比,半同步复制对性能有了一定不小的的影响,但反向提高了数据完整性。

半同步机制向复制副本发送提交并等待复制副本确认接收的TCP/IP往返ACK。这意味着半同步复制最适用于通过快速网络通信的近距离服务器,最不适用于通过慢速网络通信的远程服务器。如果在没有任何副本确认事务的情况下发生超时,则源将恢复到异步复制。当至少有一个半同步副本出现时,源将返回到半同步复制状态。
问题点
版本:5.7.22 5.7.35
运行环境都是启动半同步情况下,模拟从库进程(ogg,canal)的场景下,mysql服务crash。
then mysql command show_slave_hosts; this is hang after crash
####
mysqld got signal 11 ;
。。。
Thread pointer: 0x7f828020fde0
Attempting backtrace. You can use the following information to find out
where mysqld died. If you see no messages after this, something went
terribly wrong...
stack_bottom = 7f83e257cea8 thread_stack 0x40000
/mysqld(my_print_stacktrace+0x35)[0xf4b6d5]
/mysqld(handle_fatal_signal+0x4a4)[0x7d0d74]
/lib64/libpthread.so.0(+0xf370)[0x7f8971afa370]
/mysqld(pfs_start_mutex_wait_v1+0x17)[0x1255157]
/mysqld(_Z14get_slave_uuidP3THDP6String+0x6f)[0xefdeaf]
/mysqld(_Z16show_slave_hostsP3THD+0xa88)[0xf00528]
/mysqld(_Z21mysql_execute_commandP3THDb+0x2a4d)[0xd1806d]
/mysqld(_Z11mysql_parseP3THDP12Parser_state+0x40d)[0xd1aaad]
/mysqld(_Z16dispatch_commandP3THDPK8COM_DATA19enum_server_command+0x119a)[0xd1bcca]
/mysqld(_Z10do_commandP3THD+0x194)[0xd1cb74]
/mysqld(handle_connection+0x29c)[0xdedaec]
/mysqld(pfs_spawn_thread+0x174)[0x1256a94]
/lib64/libpthread.so.0(+0x7dc5)[0x7f8971af2dc5]
/lib64/libc.so.6(clone+0x6d)[0x7f89705b073d]
#other log file:
2022-02-10T06:29:40.622149+08:00 728 [Note] Aborted connection 728 to db: 'unconnected' user: 'ogg_user' host: '*.*.*.*' (Failed on my_net_write())
2022-02-10T06:29:40.745417+08:00 729 [Note] Stop asynchronous binlog_dump to slave (server_id: 958840896)
2022-02-10T06:29:40.814955+08:00 730 [Note] Stop asynchronous binlog_dump to slave (server_id: 958840896)
2022-02-10T06:29:40.815035+08:00 730 [Note] Aborted connection 730 to db: 'unconnected' user: 'ogg_user' host: '*.*.*.*' (Failed on my_net_write())
2022-02-10T06:29:40.890298+08:00 731 [Note] Stop asynchronous binlog_dump to slave (server_id: 958840896)
问题分析:
从错误信息里可以看出,半同步导致crash。首先半同步先从show_slave_hosts获取从库信息,之后通过get_slave_uuid获取服务为uuid。当通过uuid时候导致crash。看情况 ogg_user链接 信息 驻留在
查看主节点注册的从库hosts信息,发现有个Slave_UUID为空:

正常情况下:

目前解决方式:
1.通过重新配置,查看是否释放uuid为空的信息
2.直接把主节点重新启动一下。
3.把对应的模拟从库进程,放到从库上面。
MySQL8.0 半同步优化
从MySQL 8.0.23中,可以通过启用系统变量replication_sender_observe_commit_only(限制回调)和replication_optimize_for_static_plugin_config(添加共享锁并避免不必要的锁获取)来提高半同步复制的性能。启用此系统变量时,无法卸载半同步复制插件,因此必须禁用该系统变量,然后才能执行卸载。
从代码里说明来看在多个复制元情况下,只有复制观察者的提交钩子将被调用,其他所有已注册的钩子调用将被跳过。
*/
extern bool opt_replication_optimize_for_static_plugin_config;
/**
Variable to keep the value set for the
`replication_sender_observe_commit_only` global.
When this global variable is set to `1`, only the replication observer's
commit hook will be called, every other registered hook invocation is skipped.
*/
extern std::atomic<bool> opt_replication_sender_observe_commit_only;
备注:
目前这两个参数还需要节制使用。在8.0.27提交的bug里会导致启动半同步失败。
设置replication_sender_observe_commit_only为半同步源节点,重启mysqld后其副本无法启动半同步复制。 https://bugs.mysql.com/bug.php?id=105400
总结
目前MySQL本身复制没有触发过类似问题,但一些伪装成从库的进程。比如gh-ost,ogg,canal都有能触发上诉问题的可能。这些第三方工具,需要做一定的判断机制。也可以选择到8.0版本开启上诉新参数,是否能避免这些问题。
当然官方半同步机制里可以优化,比如那些节点需要ack验证,同时指定ack验证的节点顺序等。
参考
https://bugs.mysql.com/bug.php?id=102548
https://bugs.mysql.com/bug.php?id=105400




