MySQL Exec_Master_Log_Pos 值大于 Read_Master_Log_Pos

V R*_*lli 5 mysql replication binlog

我正在尝试修复一个 MySQL 复制设置。从属侧的数据库表之一被删除,并接收到来自主侧的更新,但由于缺少表,这些更新不会写入数据库。这个设置已经好几个月没有修复了,奴隶有很多事情要赶上。我观察到 Exec_Master_Log_Pos 值大于 Read_Master_Log_Pos ,这不应该是这种情况。这是某种错误吗?估计等slave赶上master就会恢复正常。有人熟悉这种情况吗?

Rol*_*DBA 10

这是我在 DBA 职业生涯中见过数十次的经典场景。在我解释这个之前,我想和你分享一些东西。很久以前我学到了一些关于二进制日志中的位置的知识。它实际上表示记录 SQL 事务时到特定位置的字节数。

例子

当你第一次启动一个启用了二进制日志的 mysql 实例时,你会得到一个空的二进制日志。每个版本的 MySQL 都有不同大小的空二进制日志(请参阅我的Feb 04, 2011帖子MySQL master binlog corruption)让我们在此示例中使用 MySQL 5.5。这是mysqlbinlog在我的 Windows 桌面上运行的 MySQL 5.5 的空二进制日志的输出:

C:\MySQL_5.5.12\data>dir mysql-bin.000001
 Volume in drive C has no label.
 Volume Serial Number is 2C92-485B

 Directory of C:\MySQL_5.5.12\data

08/16/2012  02:29 PM               107 mysql-bin.000001
               1 File(s)            107 bytes
               0 Dir(s)  191,225,950,208 bytes free

C:\MySQL_5.5.12\data>mysqlbinlog mysql-bin.000001
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#120816 14:29:55 server id 1  end_log_pos 107   Start: binlog v 4, server v 5.5.12-log created 120816 14:29:55 at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
BINLOG '
IzwtUA8BAAAAZwAAAGsAAAABAAQANS41LjEyLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAjPC1QEzgNAAgAEgAEBAQEEgAAVAAEGggAAAAICAgCAA==
'/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
Run Code Online (Sandbox Code Playgroud)

该文件正好是 107 个字节,其中包含标有end_log_pos 107. 如果您要设置新安装的从站,您将运行

CHANGE MASTER TO
MASTER_HOST='IP_of_Master',
MASTER_PORT=3306,
MASTER_USER='repluser',
MASTER_PASSWORD='replpass',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=107;
Run Code Online (Sandbox Code Playgroud)

然后,运行START SLAVE;。就是这样。MySQL 复制从那里起飞。

现在,您的情况...

我遇到你的情况(MySQL Exec_Master_Log_Pos value greater than Read_Master_Log_Pos)的唯一原因是这个(仍在写作)......

具有两个线程的 MySQL 复制功能

  • IO 线程:负责维护与主节点的连接。它用于收集记录在 Master 的二进制日志中的 SQL 条目并将这些条目存储在 Slave 的中继日志中。
  • SQL Thread:负责从Slave的本地中继日志中读取条目,执行SQL,轮转完全使用的中继日志。

您的问题与 IO 线程有关。如果 IO 线程遇到任何间歇性,它很可能会计算出来自 Master 的传入 SQL 语句的大小,但从未有机会实际读取 SQL 语句。我可以绝对肯定地说,因为在上面发布的示例中,在end_log_pos实际读取语句本身之前,在 SQL 语句的标题中读取了 。这通常发生在以下情况下:

  • mysqld 在复制时在 Master 上重新启动
  • 复制时主数据库服务器崩溃
  • Master和Slave之间的会话期间可能丢失的数据包

补救

发生这种情况时最简单的补救方法是跳到 Master 上的下一个二进制日志。

假设你有以下

  • 在 Master 上运行 MySQL 5.5
  • Read_Master_Log_FileSHOW SLAVE STATUS\Gmysql-bin.012345

补救方法是运行这个(跳到下一个二进制日志mysql-bin.012346

STOP SLAVE;
CHANGE MASTER TO
master_log_file='mysql-bin.012346',
master_log_pos=107;
START SLAVE;
Run Code Online (Sandbox Code Playgroud)

这将从 Slave 上次停止的地方开始。这应该是您在低写入环境中的解决方案,并且如果 Master 拥有 Slave 需要的所有二进制日志。

可是等等...

你说奴隶被打破已经有几个月了。Master 上的下一个二进制日志可能不再存在。如果您CHANGE MASTER TO现在运行命令,它将清除您现在拥有的所有二进制日志。你能做什么 ???

不幸的是,您必须从头开始重建 Slave。

您必须在 Slave 上执行以下操作

echo "STOP SLAVE;" > MySQLData.sql
MYSQLDUMP_OPTIONS="-hIP_of_Master -u... -p..."
MYSQLDUMP_OPTIONS="${MYSQLDUMP_OPTIONS} --all-databases --triggers --routines"
MYSQLDUMP_OPTIONS="${MYSQLDUMP_OPTIONS} --master-data=1 --single-transaction"
mysqldump ${MYSQLDUMP_OPTIONS} >> MySQLData.sql
echo "START SLAVE;" >> MySQLData.sql
mysqldump -uroot -prootpass < MySQLData.sql
Run Code Online (Sandbox Code Playgroud)

这将停止从站,重新加载数据,并启动从站。该选项master-data=1CHANGE MASTER TO在 MySQLData.sql 的第 23 行写入命令。

试一试 !!!