MySQL,优化和复制

Vin*_*ann 4 mysql replication

我有两个 MySQL(实际上是 MariaDB)服务器,一个主服务器和一个带有标准复制的从属服务器。在不到一个月的时间里,我的奴隶已经有两次无法使用了。

这是我的经历:

  • 使用我的监控工具注意到从站每秒的查询量下降
  • 用mysql客户端连接服务器,运行 SHOW SLAVE STATUS \G
  • 注意一切看起来都很正常(等待主人发送事件,主人后面的秒数 = 0 等)
  • 尝试停止复制 STOP SLAVE
  • STOP SLAVE 挂起
  • 无法使用客户端连接到服务器
  • SHOW SLAVE STATUS \G在另一个已经连接的客户端上执行,它也挂了。

之后,我看到了使用 CPU 的 MySQL 进程,我看到了很多使用 iotop 的磁盘写入,所以我让它做它的东西一段时间。

15 分钟后,我杀死了 MySQL 进程 -9,因为我感到沮丧。然后我重新启动 MySQL,我可以连接和运行查询,很好。

我执行SHOW SLAVE STATUS \G现在可以工作了,它看起来很正常:master 后面的秒数 = 0,等待事件。然后我继续在 master 上执行CREATE DATABASE foobar以查看复制是否有效,但它没有。

同样,那时我看到了很多磁盘写入,所以我认为复制正在赶上。两个小时后,我终于决定检查SHOW PROCESSLIST,我看到执行的只是一个OPTIMIZE TABLE table1 ...,然后我记得我上次遇到了完全相同的问题。

我用那个查询终止了这个进程,然后我重新执行SHOW PROCESSLIST,果然它赶上了主人。SHOW SLAVE STAUTS \G报告落后master 15k 秒,这是连贯的。

无论如何,在那堵文字墙之后,我的问题是:

  • 为什么 OPTIMIZE 查询会阻止复制追赶?
  • 我可以阻止那些 OPTIMIZE 查询吗?我没有放置任何 cron 来做到这一点,据我所知,/etc/cron.{d,daily,hourly,weekly} 中没有任何内容。

谢谢。

Rol*_*DBA 5

你的第一个问题

为什么 OPTIMIZE 查询会阻止复制追赶?

MySQL 复制中的 SQL 线程将来自中继日志的 SQL 命令作为 FIFO 队列(即先到先服务器)进行处理。一旦 SQL 线程看到一个命令,它就会处理它直到完成。与此同时,Seconds_Behind_Master 一直在爬行。

当 Slave 上的 SQL 线程正在运行时OPTIMIZE TABLE,一旦您运行STOP SLAVE;OPTIMIZE TABLE,SQL 线程就会在 SQL 线程终止之前完成运行。这就是STOP SLAVE;挂起的原因。要验证这一点,请打开另一个 mysql 会话并运行SHOW PROCESSLIST;,您应该看到OPTIMIZE TABLE带有 status 的行Killing slave...

你的第二个问题

我可以阻止那些 OPTIMIZE 查询吗?我没有放置任何 cron 来做到这一点,据我所知,/etc/cron.{d,daily,hourly,weekly} 中没有任何内容。

某人或某物正在运行OPTIMIZE TABLE. 您必须在所有工作或 PHP 应用程序中寻找它。使用mysqlbinlog实用程序将所有二进制日志转储到文本文件中。然后,grep 文本文件 for OPTIMIZE TABLEor optimize table。它被提交到 binlogs 的时间戳将是关于命令的几行。

当您OPTIMIZE TABLE在作业或 PHP 代码中找到该命令时,只需运行以下命令:

SET SQL_LOG_BIN=0; OPTIMIZE TABLE tblname; SET SQL_LOG_BIN=1;
Run Code Online (Sandbox Code Playgroud)

这不会OPTIMIZE TABLE在 binlogs 中注册,从而防止 Slave 复制它。

正如下面评论中刚刚指出的那样,您也可以替换

OPTIMIZE TABLE tblname;
Run Code Online (Sandbox Code Playgroud)

具有以下其中一项:

OPTIMIZE NO_WRITE_TO_BINLOG TABLE tblname;
OPTIMIZE LOCAL TABLE tblname;
Run Code Online (Sandbox Code Playgroud)

限制OPTIMIZE TABLE命令登陆二进制日志,从而防止复制它。