我有一个普通的 MySQL 复制,使用“混合”模式。
mysql slave 延迟计算的行为非常奇怪 - 一分钟是0
,之后是3630
秒(或类似的数字),然后回到0
,依此类推。显然,复制配置有问题,因为 MySQL 根据中继日志中的时间戳计算延迟。
我试过检查服务器的时间,这是相同的(SELECT NOW()
在 MySQL 中使用)。我还检查了SELECT @@system_time_zone
主从上设置为 CDT的时区 ( )。
我还可以验证什么以确保此问题得到解决?有没有其他人遇到过这个问题?
MySQL 复制基于一些事情对 Seconds_Behind_Master 执行奇怪的计算。
这是一个 SHOW SLAVE STATUS\G 以及如何从 Master 中识别最后执行的 SQL
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 10.17.20.102
Master_User: replicant
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.002814
Read_Master_Log_Pos: 823078734
Relay_Log_File: relay-bin.007364
Relay_Log_Pos: 823078879
Relay_Master_Log_File: mysql-bin.002814
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 823078734
Relay_Log_Space: 823079071
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
请注意 SHOW SLAVE STATUS\G 中的以下字段
要计算 Seconds_Behind_Master,它基本上可以计算出
NOW() as recorded in Master LogFile 'Master_Log_File' LogPos 'Read_Master_Log_Pos'
minus
NOW() on the Slave
Run Code Online (Sandbox Code Playgroud)
这个数字会间歇性地增长,因为 I/O 线程可以从 Master 收集更多条目并将其加载到最后一个中继日志中,同时处理位于 Master LogFile 'Relay_Master_Log_File' 和 Master LogPos 'Exec_Master_Log_Pos' 的 SQL 语句。这个增加的数字还表现为三 (3) 个变量的变化:Relay_Log_Space、Master_Log_File、Read_Master_Log_Pos。如果 Seconds_Behind_Master 为 0,这很好地表明 Read_Master_Log_Pos 和 Exec_Master_Log_Pos 几乎相同。同样值得注意的是,长时间运行的 SQL 会欺骗您认为复制落后了。一旦该 SQL 语句完成并且没有其他语句充分积压,Seconds_Behind_Master 可能会急剧下降,甚至降至 0。
那么,为什么 Seconds_Behind_Master 会在 0 和递增的数字之间来回反弹。通过 I/O 线程传输 SQL 时的网络延迟可能会导致计算错误,因为TIMESTAMP
在最后一个中继日志的后面还没有到达所需的变量(请记住这是异步复制)。要验证这一点,请mysqlbinlog
针对任何二进制日志或中继日志运行并查看TIMESTAMP
变量在语句之间写入的位置。
此行为于 2007 年 6 月 22 日首次得到解决,据称该错误已在那时得到修复。
这是采用 MySQL 复制并正确拧紧其头部的一种可靠方法(对于此示例,使用相同的 SHOW SLAVE STATUS\G)
使用 Relay_Master_Log_File mysql-bin.002814 和 Exec_Master_Log_Pos 823078734 作为 Log FilePosition to Restart From,运行这些命令
STOP SLAVE;
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.002814',MASTER_LOG_POS=823078734;
START SLAVE;
Run Code Online (Sandbox Code Playgroud)
这些步骤应该 1) 杀死 I/O 和 SQL 线程,2) 清除所有收集的中继日志,3) 从新的中继日志开始,以及 4) 建立新的 I/O 和 SQL 线程。
从这里开始复制应该很好。至于这个 bug 能否真正得到解决,现在掌握在 Oracle 手中(最后一句并没有激发任何信心,是吗???)