问题出现得很突然,日志倒是留得挺全。一主一从的 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
怎么算真的好了,看的是同一批现象。下单后立刻查询能读到刚写入的记录,主从位点在事务提交后一秒内追平,读写分离中间件里写后读的命中全部落在主库。
半同步只能缩小窗口不能消除,真正要一致就得让关键读走主库,别指望调小延迟解决业务语义问题。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。
