MySQL复制slave遇到SET@@SESSION.GTID_NEXT='ANONYMOUS'后挂起;

mau*_*ers 5 mysql replication binlog

我最近在 Ubuntu Server 16.04 下安装了两个相同的 MySQL 5.7 默认安装,并将它们配置为执行二进制日志复制。到目前为止,这一直工作正常,但突然复制停止继续,从属查询线程以 100% CPU 运行而没有做任何工作。

经过一番搜索,我发现从站状态表明它远远落后于主站。在Relay_Master_Log_File和位置Exec_Master_Log_Pos指示的binlog文件上使用mysqlbinlog,发现在这个位置执行的语句是:

SET @@SESSION.GTID_NEXT= 'ANONYMOUS';

在尝试执行此语句时,从站以某种方式挂起,将 CPU 负载发送到 100%(这是我首先发现情况的方式)。

除了让奴隶跳过使用SET GLOBAL sql_slave_skip_counter=1它的语句之外,我不清楚这个问题的实际原因是什么,以及我应该如何解决这个问题。

任何帮助将非常感激!

Pan*_*Pan 5

TL;DR:这可能是由于表设计不佳加上基于 ROW 的复制造成的。

我刚刚遇到了这个问题。我被要求将旧数据库移动到新服务器并设置复制。

我发现实际上并不是主题中的语句导致奴隶挂起(SET @@SESSION.GTID_NEXT = 'ANONYMOUS')。该语句在交易开始时发出。

mysql> SHOW BINLOG EVENTS IN 'mysql-bin.000196' FROM 96754384 LIMIT 5000;
+------------------+-----------+----------------+-----------+-------------+----------------------------------------------+
| Log_name         | Pos       | Event_type     | Server_id | End_log_pos | Info                                         |
+------------------+-----------+----------------+-----------+-------------+----------------------------------------------+
| mysql-bin.000196 |  96754384 | Anonymous_Gtid |         1 |    96754449 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'         |
| mysql-bin.000196 |  96754449 | Query          |         1 |    96754537 | BEGIN                                        |
| mysql-bin.000196 |  96754537 | Table_map      |         1 |    96754608 | table_id: 241 (db.bad_table)                 |
| mysql-bin.000196 |  96754608 | Delete_rows    |         1 |    96762805 | table_id: 241                                |
| mysql-bin.000196 |  96762805 | Delete_rows    |         1 |    96771002 | table_id: 241                                |
...
| mysql-bin.000196 | 106681175 | Delete_rows    |         1 |   106689372 | table_id: 241                                |
| mysql-bin.000196 | 106689372 | Delete_rows    |         1 |   106697569 | table_id: 241                                |
| mysql-bin.000196 | 106697569 | Delete_rows    |         1 |   106697626 | table_id: 241 flags: STMT_END_F              |
| mysql-bin.000196 | 106697626 | Xid            |         1 |   106697657 | COMMIT /* xid=28382600 */                    |
| mysql-bin.000196 | 106697657 | Rotate         |         1 |   106697704 | mysql-bin.000197;pos=4                       |
+------------------+-----------+----------------+-----------+-------------+----------------------------------------------+
1219 rows in set (0.02 sec)
Run Code Online (Sandbox Code Playgroud)

该表有 6600 万行。我发现它没有主键或唯一键。负责此操作的查询在主服务器上使用索引扫描。

mysql> SHOW VARIABLES LIKE '%binlog_format%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW   |
+---------------+-------+
1 row in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

为了让从服务器使用基于 ROW 的复制来复制它,它需要在从服务器上执行大约 1200 次全表扫描。1200 在这里可能是一个相当小的数字。它可能是数十万。复制确实有效,但通过这种设计,“seconds_behind_master”将无限增长。

我将向该表添加主键和分区。我还会请我的同事重写他们的代码,这样就不再需要批量删除了。这可能需要添加额外的列。

编辑:我没有足够的分数来评论其他帖子,所以我现在将在这里添加我的评论。我相信像其他人提到的那样发出“SET GLOBAL sql_slave_skip_counter = 1”会跳过整个事务并导致数据不一致。如果我错了纠正我。

一个快速的解决方法是将 binlog 格式更改为 QUERY 或 MIXED。这些格式也可能导致数据不一致,因此我建议查找并修复根本原因,而不是更改 binlog 格式。