问题出现得很突然,日志倒是留得挺全。一主一从的 MySQL 5.7 做了读写分离,用户下单成功后立刻刷新订单列表却是空的,再刷一次才出现,show slave status 里 Seconds_Behind_Master 显示 0,可主从位点还差几条。

刚开始盯着「读写分离中间件把写后立刻的读也发到了从库,没有做写后读绑定」,折腾了半个多小时,排掉了。

把日志和配置对完,能解释这个现象的基本就这几处。从库的 SQL 线程把事件应用完才更新位点,读到的一瞬间可能还差最后一个事务。少数情况下是半同步没开,主库提交成功就返回,压根不等从库确认收到 binlog。

另外,从库开了并行复制,不同库的事务完成顺序与主库不一致。

第一件事是比对主从的位点差多少

mysql -e 'show master status\G' && mysql -e 'show slave status\G' | grep -E 'Relay_Master_Log_File|Exec_Master_Log_Pos'

再往下确认半同步插件的状态

mysql -e 'show variables like "rpl_semi_sync_master_enabled";'

随后打开半同步,让主库等从库确认

mysql -e 'install plugin rpl_semi_sync_master soname "semisync_master.so"; set global rpl_semi_sync_master_enabled=1;'

剩下的就是把写后读的请求固定打到主库再验证

curl -s -b /tmp/session.txt http://127.0.0.1/order/list | head -c 200

怎么算真的好了,看的是同一批现象。下单后立刻查询能读到刚写入的记录,主从位点在事务提交后一秒内追平,读写分离中间件里写后读的命中全部落在主库。

半同步只能缩小窗口不能消除,真正要一致就得让关键读走主库,别指望调小延迟解决业务语义问题。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。

作者 9823189