如何使用 MyDumper 重建 MySQL 副本?

0 阅读9分钟

作者:David Ducos,Percona 团队 DBA。

原文:www.percona.com/blog/rebuil…

1. 什么是 MyDumper?

当副本因损坏或漂移而失效时,如果无法使用 pt-table-sync,标准解决方案是从主数据库的全新副本重建副本。传统上,为了快速重建副本,我们会使用 物理备份,但在某些情况下,逻辑备份仍然必不可少。例如,当您迁移到特定供应商(例如:从 MariaDB 迁移到 MySQL)或存储引擎(过去是从 MyISAM 迁移到 InnoDB,现在是从 InnoDB 迁移到 RocksDB)、升级到新的数据库版本或迁移到云端解决方案时。

逻辑备份 正是在这种情况下发挥作用,它提供了可移植性和简易性,但前提是能够快速执行。MyDumper 应运而生,成为一款必不可少的现代化解决方案,它兼具两者的优势:逻辑转储的跨平台、跨版本灵活性,以及以往只有物理方法才能实现的并行、多线程速度,使其成为快速重建一致性副本的理想之选。

2. 备份

第一步是进行备份。mydumper 有多个参数可供使用,本例中我们将使用以下参数:

mydumper -v 4 -o data --clear 
--regex '^(?!(mysql.|sys.))' 
--source-data

前 3 行与日志记录和备份目录有关,第二行用于忽略 mysqlsys 模式,最后 –source-data 将指示 mydumper 将恢复后复制配置所需的所有信息保存到元数据文件中,位于 [source] 部分。

以下是输出示例:

[source]
# Channel_Name = '' # It can be used to setup replication FOR CHANNEL
# SOURCE_LOG_FILE = "binlog.000020"
# SOURCE_LOG_POS = 6803936
#SOURCE_HOST = "172.17.0.3"
#SOURCE_PORT =
#SOURCE_USER = ""
#SOURCE_PASSWORD = ""
#SOURCE_SSL = {0|1}
executed_gtid_set = "941fdce6-47c4-11f0-87b2-0242ac110006:1-52"
SOURCE_LOG_FILE = "binlog.000020"
SOURCE_LOG_POS = 6803936
#SOURCE_AUTO_POSITION = {0|1}
myloader_exec_reset_replica = 0
myloader_exec_change_source = 0
myloader_exec_start_replica = 0

如图所示,这些选项已启用:

executed_gtid_set = "941fdce6-47c4-11f0-87b2-0242ac110006:1-52"
SOURCE_LOG_FILE = "binlog.000020"
SOURCE_LOG_POS = 6803936

但是,这些命令的执行已被禁用:

myloader_exec_reset_replica = 0
myloader_exec_change_source = 0
myloader_exec_start_replica = 0
We can enable them, if we set --source-data=7, then the metadata will change to:
myloader_exec_reset_replica = 1
myloader_exec_change_source = 1
myloader_exec_start_replica = 1

这是自动配置复制所必需的。

3. 配置复制

默认情况下将使用 SOURCE_LOG_FILESOURCE_LOG_POS,但如果您配置 SOURCE_AUTO_POSITION = 1,则可以设置 GTID 位置。

如您所知,要设置复制,我们需要执行 CHANGE SOURCE 命令。但是,根据您的具体使用情况,您可能需要执行 RESET REPLICA 命令,并且在执行 CHANGE SOURCE 命令后,通常需要执行 START REPLICA 命令。如果您在元数据文件中使用以下方式进行设置,myloader 可以自动完成此操作:

myloader_exec_reset_replica = 1
myloader_exec_change_source = 1
myloader_exec_start_replica = 1

或者,您可以在 myloader 中使用 --source-data=7 作为参数。是的!myloader 也接受 --source-data 参数。

根据您的使用场景,您可能需要在元数据文件中配置以下其他选项:

#SOURCE_HOST = "172.17.0.3"
#SOURCE_PORT =
#SOURCE_USER = ""
#SOURCE_PASSWORD = ""
#SOURCE_SSL = {0|1}
executed_gtid_set = "941fdce6-47c4-11f0-87b2-0242ac110006:1-52"
SOURCE_LOG_FILE = "binlog.000020"
SOURCE_LOG_POS = 6803936
#SOURCE_AUTO_POSITION = {0|1}

由于存在多种使用场景,如果您想从头开始重建副本,则需要按如下方式配置:

[source]
SOURCE_HOST = "172.17.0.3"
SOURCE_PORT = 3306
SOURCE_USER = "replica"
SOURCE_PASSWORD = "r3pl1c4"
executed_gtid_set = "941fdce6-47c4-11f0-87b2-0242ac110006:1-52"
SOURCE_LOG_FILE = "binlog.000020"
SOURCE_LOG_POS = 6803936
myloader_exec_reset_replica = 1
myloader_exec_change_source = 1
myloader_exec_start_replica = 1

如果您已经建立了一个正在运行的复制系统,并且想要在不更改主机或凭据的情况下重建它,那么您可以按以下方式进行配置:

[source]
executed_gtid_set = "941fdce6-47c4-11f0-87b2-0242ac110006:1-52"
SOURCE_LOG_FILE = "binlog.000020"
SOURCE_LOG_POS = 6803936
myloader_exec_reset_replica = 0
myloader_exec_change_source = 1
myloader_exec_start_replica = 1

SSL 是 myloader--source-data 参数可以设置的另一个选项,无需在元数据文件中使用 SOURCE_SSL。完整的选项列表如下:exec_start_slave (1)exec_change_master (2)exec_reset_slave (4)SSL (8)auto_position (16)exec_start_replica_until (32)。根据您要设置的配置和要执行的语句,您需要将这些值相加,并将其传递给 --source-data 参数。

4. 恢复

配置好元数据文件后,即可执行 myloader,其界面如下所示:

myloader -d data -v 4 
-o --max-threads-for-schema-creation=1 
-h replica_host

在日志中,你会发现 myloader 发送了以下命令:

2025-12-18 16:57:09 [INFO] - Schema create checksum confirmed for sakila
2025-12-18 16:57:09 [INFO] - Sending reset replica
2025-12-18 16:57:09 [INFO] - Sending change replication source
2025-12-18 16:57:09 [INFO] - Sending start replica
2025-12-18 16:57:09 [INFO] - Restore completed

mydumper 会发送命令,但不会检查输出,这意味着如果复制配置失败或无法启动,您需要手动检查并修复。但是,它会检测到命令是否失败,例如,如果使用了 SOURCE_USER 而不是 SOURCE_USER

2025-12-18 17:02:56 [WARNING] - Sending replication command: CHANGE REPLICATION SOURCE TO SOURCE_HOST = "172.17.0.4", SUORCE_USER = "root", SOURCE_PASSWORD = "", SOURCE_LOG_FILE = "binlog.000020", SOURCE_LOG_POS = 1362220 FOR CHANNEL ''; - ERROR 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SUORCE_USER = "root", SOURCE_PASSWORD = "", SOURCE_LOG_FILE = "binlog.000020", SO' at line 1

5. 对故障副本进行重建

有一个有趣的用例,我们可以使用 START REPLICA UNTIL 来修复某些表的偏移,而 pt-table-sync 或重建整个副本是不可能的。

假设我们有一个源数据库和一个副本数据库,我们发现副本数据库上的数据发生了,并且复制过程停止并出现如下错误:

LAST_ERROR_MESSAGE: Worker 1 failed executing transaction 'ANONYMOUS' at source log binlog.000020, end_log_pos 1369103; Could not execute Update_rows event on table test.test_table; Can't find record in 'test_table', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's source log binlog.000020, end_log_pos 1369103

我们检查了二进制日志,发现它因对一组行进行更新而失败:

# at 1368995
#251218 19:34:59 server id 1 end_log_pos 1369103 CRC32 0x60a481d6 Update_rows: table id 344 flags: STMT_END_F
### UPDATE `test`.`test_table`
### WHERE
### @1=12 /* INT meta=0 nullable=0 is_null=0 */
### @2=7062 /* INT meta=0 nullable=1 is_null=0 */
### SET
### @1=12 /* INT meta=0 nullable=0 is_null=0 */
### @2=7063 /* INT meta=0 nullable=1 is_null=0 */
### UPDATE `test`.`test_table`
### WHERE
### @1=15 /* INT meta=0 nullable=0 is_null=0 */
### @2=7521 /* INT meta=0 nullable=1 is_null=0 */
### SET
### @1=15 /* INT meta=0 nullable=0 is_null=0 */
### @2=7522 /* INT meta=0 nullable=1 is_null=0 */
### UPDATE `test`.`test_table`
### WHERE
### @1=17 /* INT meta=0 nullable=0 is_null=0 */
### @2=8706 /* INT meta=0 nullable=1 is_null=0 */
### SET
### @1=17 /* INT meta=0 nullable=0 is_null=0 */
### @2=8707 /* INT meta=0 nullable=1 is_null=0 */
### UPDATE `test`.`test_table`
### WHERE
### @1=18 /* INT meta=0 nullable=0 is_null=0 */
### @2=8108 /* INT meta=0 nullable=1 is_null=0 */
### SET
### @1=18 /* INT meta=0 nullable=0 is_null=0 */
### @2=8109 /* INT meta=0 nullable=1 is_null=0 */
# at 1369103

我们检查了数据库,发现数据确实发生了偏移:

源端

mysql> select count(*) from test.test_table;
+----------+
| count(*) |
+----------+
| 15 |
+----------+
1 row in set (0.00 sec)

副本

mysql> select count(*) from test.test_table;
+----------+
| count(*) |
+----------+
| 14 |
+----------+
1 row in set (0.00 sec)

使用 MyDumper,我们可以按照以下步骤重建表:

我们需要忽略该表,以便副本能够赶上进度。

mysql-replica> STOP REPLICA;
Query OK, 0 rows affected (0.00 sec)

mysql-replica> CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE= (test.test_table);
Query OK, 0 rows affected (0.00 sec)

mysql-replica> START REPLICA;
Query OK, 0 rows affected (0.00 sec)

副本更新完成后,我们需要停止副本:

mysql-replica> STOP REPLICA;
Query OK, 0 rows affected (0.00 sec)

并对源服务器进行备份:

mydumper -v 4 -o data --clear 
-T test.test_table 
--source-data

我们使用 -T 来备份有问题的表,而 –source-data 将启用我们需要的元数据文件上的复制变量。

然后,我们使用正确的值通过 --source-data 参数恢复表。

myloader -d data -v 4 
-o --max-threads-for-schema-creation=1 
-h replica_host 
--source-data=32

第 32 行是执行 START REPLICA UNTIL

最后,我们移除忽略表选项并重新启动副本:

mysql-replica> CHANGE REPLICATION FILTER REPLICATE_IGNORE_TABLE= ();
Query OK, 0 rows affected (0.00 sec)

mysql-replica> START REPLICA;
Query OK, 0 rows affected (0.00 sec)

myloader 在备份开始时执行的 START REPLICA UNTIL 将强制副本在备份表的位置停止,从而使我们能够在一致的场景中继续复制。

6. 结论

从传统的数据转储方法转向 MyDumper 不仅仅意味着性能的提升,更代表着数据完整性和迁移性的现代化。通过将备份过程从单线程执行的限制中解耦,数据库管理员现在可以像以往处理小型测试环境一样灵活地处理海量数据集。

MyDumper 集成到您的标准操作手册中,可确保您能够应对各种不可预测的情况 —— 无论是紧急副本重建还是计划内的架构迁移。在数据量持续呈指数级增长的时代,拥有一款兼具逻辑灵活性和并行速度的工具至关重要,而 MyDumper 正是这样一款工具。将其保留在您的工具箱中,下次遇到“仅逻辑恢复”场景时,您将拥有显著的竞争优势。