主从可能存在延迟,客户端执行完一个更新事务后马上发起查询,如果查询选择的是从库的话,就有可能读到刚刚的事务更新之前的状态。
这种“在从库上会读到系统的一个过期状态”的现象,在这篇文章里,我们暂且称之为“过期读”。
- 强制走主库方案;
将查询请求做分类。
必须要拿到最新结果的请求,强制将其发到主库上。(商品交易成功页面)
可以读到旧数据的请求,才将其发到从库上。(最新商品上线)
- sleep 方案;
主库更新后,读从库之前先 sleep 一下。具体的方案就是,类似于执行一条 selectsleep(1) 命令
用 Ajax直接把客户端输入的内容作为“新的商品”显示在页面上,而不是真正地去数据库做查询。
- 判断主备无延迟方案;
1.seconds_behind_master 参数的值
2.Master_Log_File 和 Read_Master_Log_Pos,表示的是读到的主库的最新位点;
Relay_Master_Log_File 和 Exec_Master_Log_Pos,表示的是备库执行的最新位点
3.Auto_Position=1 ,表示这对主备关系使用了 GTID 协议。
Retrieved_Gtid_Set,是备库收到的所有日志的 GTID 集合;
Executed_Gtid_Set,是备库所有已经执行完成的 GTID 集合。
- 配合 semi-sync 方案;
半同步复制设计:
1. 事务提交的时候,主库把 binlog 发给从库;
2. 从库收到 binlog 以后,发回给主库一个 ack,表示收到了;
3. 主库收到这个 ack 以后,才能给客户端返回“事务完成”的确认。
- 等主库位点方案;
select master_pos_wait(file, pos[, timeout]);
- 等 GTID 方案。
select wait_for_executed_gtid_set(gtid1, timeout);