在一主多从的环境下,由于同步的问题,会出现主库记录已更改,从库尚未收到binlog或者尚未应用binlog的情况,这时如果我们在从库上读取该记录,会读取到以前的数据,称之为“过期读” ,对于有的业务来说这是不允许的,所以从程序的角度,在程序应用读写分离时,需要考虑到这个因素。
强制走主库方案:
对于那些对实时性要求比较高的业务查询请求,将其分配给主库,实时性要求低的分配给从库。
有点"取巧"的意思,且受业务限制比较大。
判断主备无延迟方案:
1)通过seconds_behind_master判断(精度存疑)
2)对比位点判断
Master_log_file和Read_Master_Log_Pos表示的是读取到主库的最新位点,Relay_Master_Log_File和Exec_Master_Log_Pos表示的是备库执行到的最新位点
如果这两组值完全相同,则表明接收到的日志已经同步完成
3)对比GTID判断
Auto_Position=1表明主备使用的是GTID协议。
Retrieved_Gtid_Set表示的是备库收到的GTID的集合,Executed_Gtid_Set表示的是备库执行完成的GTID的集合
如果这两个集合相同,则表明接收到的日志已经同步完成
semi_sync:
为了处理那种主库事务已经执行提交返回客户端,从库还未收到binlog的场景。
semi_sync的思路:
1.事务提交的时候,主库把binlog发给从库
2.从库收到binlog后,发送给主库一个ACK,表示收到
3.主库在收到ACK后,返回给客户端"事务完成"的信息(如果是一主多从的话,主库收到任意从库返回的ACK后就给客户端返回确认)
等主库位点方案:
select master_pos_wait(file, pos[,timeout]);
在从库执行,参数file和pos指的是主库上的文件名和位置,timeout可以选,设置为正整数N表示这个函数最多等待N秒。
函数正常返回的话,是一个正整数M,表示从库从执行命令开始到应用完file和pos表示的binlog的位置,共执行的事务数。如果返回0则表示命令执行时该binlog已执行过。如果等待超时,返回-1
等GTID方案:
select wait_for_executed_gtid_set(gtid_set[,timeout]);
在从库执行,等待,直到从库执行的事务中包含传入的gtid_set,返回0。超时返回1。
由于从Mysql 5.7.6开始,事务的GTID可以直接从返回包中获取到,所以主库在执行完事务之后不需要再去主库上查询来定位事务
参数session_track_gtids设置为own_gtid,然后可以通过api接口mysql_session_track_get_first从返回包中解析GTID