MySQL 5.7 同时开启半同步复制和复制压缩协议slave_compressed_protocol=ON,会触发MySQL Bug,导致主库事务提交卡住。
一、环境配置:
- MySQL 5.7.19 1主2从
- slave_compressed_protocol=ON
- 主库:rpl_semi_sync_master_enabled=ON,rpl_semi_sync_slave_enabled=OFF
- 从库:rpl_semi_sync_master_enabled=OFF,rpl_semi_sync_slave_enabled=ON
为了验证效果,将半同步超时参数设置大一点。
rpl_semi_sync_master_timeout=1000000
二、Bug验证
往主库写入数据,会卡住,大概30秒后,才写入成功。
mysql> insert into tb select 6;
Query OK, 1 row affected (31.78 sec)
Records: 1 Duplicates: 0 Warnings: 0
在从库上检查写入的数据确实已经复制到了从库,进一步发现,数据复制到从库,并不需要等30秒,在主库提交后,几乎立刻就能复制到从库,但是主库始终会卡30秒左右,才显示提交成功。
查看主、从库的错误日志,发现如下:
2020-02-14T15:52:11.278985+08:00 0 [ERROR] Read semi-sync reply magic number error
2020-02-14T15:52:11.280066+08:00 0 [ERROR] /usr/local/mysql/bin/mysqld: Got timeout reading communication packets
网上搜索,发现这个Bug早已存在,见地址:https://bugs.mysql.com/bug.php?id=86230
简单地说,就是主库的半同步接收ack的线程无法识别复制压缩协议,一直等待半同步ack,直到超时或者heartbeat心跳。好在官方在8.0.4和5.7.21中修复了这个Bug。
之前提到主库会等30秒才显示成功,为什么是30秒,这个30秒与哪个参数有关?经过排查,最终发现30秒与参数
master_heartbeat_period有关,调整该参数到60秒,发现主库写入数据等待60秒才成功。
change master to master_heartbeat_period=60;
mysql> insert into tb select 11;
Query OK, 1 row affected (1 min 1.82 sec)
Records: 1 Duplicates: 0 Warnings: 0
三、结论:
slave_compressed_protocol 与 半同步一起使用会触发Bug,如果想规避该Bug,如下建议,任选其一:
- 不开启复制压缩协议
- 不开启半同步复制
- 升级MySQL版本到 5.7.21 及以上,或者 8.0.4 及以上。