设置异步MySQL复制:逐步指南

通过这份权威的逐步指南,掌握异步MySQL复制设置。学习如何通过调整`my.cnf`设置、建立安全的复制用户账户以及使用`mysqldump`执行关键初始数据快照,正确配置主服务器和从服务器。本文提供实用命令和基本故障排除技巧,确保高效数据同步并最小化复制延迟,以实现可扩展的数据库架构。

设置异步MySQL复制:逐步指南

异步MySQL复制仍然是数据库设置中最有用的构建块之一。你可以将其用于只读副本、更安全的备份、报告副本、迁移暂存和灾难恢复。关键点是“异步”:源服务器提交事务时无需等待副本应用它。这避免了源服务器因每次副本写入而阻塞,但也意味着副本可能出现延迟。

许多MySQL命令中的旧术语是“master”和“slave”。较新的MySQL版本在SHOW REPLICA STATUSCHANGE REPLICATION SOURCE TO等命令中使用“source”和“replica”。在旧系统、示例和脚本中,你仍可能看到旧命令。本指南在解释中使用source和replica,并首先展示新命令形式,同时注明旧语法差异。

示例使用两台服务器:

  • 源服务器:192.168.1.100
  • 副本服务器:192.168.1.101
  • 复制用户:repl_user
  • 范围:所有数据库,除非你有意过滤

如果你之前没有执行过此过程,请先在测试环境中进行。当一切干净时,复制设置很简单。当源服务器繁忙、转储不一致或副本已包含旧数据时,设置会变得棘手。

在修改配置之前

确认基本条件:

  • 两台服务器运行兼容的MySQL版本。
  • 副本可以通过MySQL端口(通常为3306)访问源服务器。
  • 你拥有两个MySQL实例的管理员访问权限。
  • 你可以编辑MySQL配置文件并在需要时重启MySQL。
  • 副本为空,或者你确切知道哪些现有数据需要替换。
  • 源服务器有足够的磁盘空间用于二进制日志。

在副本主机上,测试基本网络访问:

nc -vz 192.168.1.100 3306

如果nc不可用,使用telnet或云提供商的连接工具。在配置复制之前,修复防火墙、安全组、绑定地址和路由。如果TCP路径被阻塞,复制用户也无济于事。

配置源服务器

源服务器必须将更改写入二进制日志。副本读取这些事件并将其存储在中继日志中,然后应用它们。

在源服务器上编辑MySQL配置文件。常见位置是/etc/mysql/mysql.conf.d/mysqld.cnf/etc/my.cnf或从这些路径包含的文件。在[mysqld]下添加或验证以下设置:

[mysqld]
server-id=1
log-bin=mysql-bin
binlog_format=ROW

server-id在复制拓扑中的每台服务器上必须唯一。log-bin启用二进制日志记录。binlog_format=ROW是大多数现代复制设置的实用默认值,因为它记录行更改,而不是依赖语句重新执行行为。

小心使用binlog-do-dbbinlog-ignore-db。过滤听起来方便,但可能会让你意外,因为基于语句的行为取决于会话选择的默认数据库。如果你需要过滤复制,请有意设计和测试。对于首次可靠设置,复制所有内容。

在源服务器上重启MySQL:

sudo systemctl restart mysql
# 或者,在某些系统上
sudo systemctl restart mysqld

验证设置:

SHOW VARIABLES LIKE 'server_id';
SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'binlog_format';

log_bin应为ONserver_id应为非零且唯一。

创建复制用户

在源服务器上创建一个专用账户,供副本使用。如果网络设计允许,将主机限制为副本地址:

CREATE USER 'repl_user'@'192.168.1.101' IDENTIFIED BY 'use_a_real_secret_here';
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.1.101';

在MySQL授权中,权限名称仍然是REPLICATION SLAVE,尽管较新的文档在其他地方通常说“replica”。

从副本主机测试登录:

mysql -h 192.168.1.100 -u repl_user -p

如果失败,立即修复身份验证和网络。常见原因包括源服务器上的bind-address、防火墙规则、用户主机不匹配、DNS解析到不同地址以及身份验证插件与旧客户端不兼容。

配置副本服务器

在副本上,配置不同的server-id。中继日志通常自动启用用于复制,但显式命名可以使操作更清晰:

[mysqld]
server-id=2
relay_log=mysql-relay-bin
read_only=ON

为了更强保护,考虑在设置后使用super_read_only=ONread_only不会阻止每个特权账户写入。super_read_only对于不应接受应用程序写入的副本更安全,但你可能需要临时关闭它以执行某些管理任务。

重启副本上的MySQL并验证:

sudo systemctl restart mysql
SHOW VARIABLES LIKE 'server_id';
SHOW VARIABLES LIKE 'read_only';

获取一致的初始快照

副本必须从与特定二进制日志位置匹配的数据副本开始。如果快照和位置不匹配,复制可能启动但仍然错误。

对于以InnoDB为主的数据库,mysqldump --single-transaction通常是最简单的一致方法。它避免了对事务表进行长时间的全局读锁。在较新的MySQL版本中包含--source-data=2,以便转储将源二进制日志文件和位置记录为注释行。旧版本使用--master-data=2

在可以连接到源服务器的可信主机上运行此命令:

mysqldump -h 192.168.1.100 -u root -p \
  --all-databases \
  --single-transaction \
  --routines \
  --triggers \
  --events \
  --source-data=2 \
  > source_dump.sql

如果你的MySQL版本不支持--source-data,使用:

mysqldump -h 192.168.1.100 -u root -p \
  --all-databases \
  --single-transaction \
  --routines \
  --triggers \
  --events \
  --master-data=2 \
  > source_dump.sql

--single-transaction对于InnoDB一致性是安全的,但它不能以相同方式使非事务性MyISAM表一致。如果你仍有MyISAM表,计划一个维护窗口或使用其他备份方法获取一致快照。

检查转储中记录的复制坐标:

grep -m 1 -E "CHANGE (MASTER|REPLICATION SOURCE)" source_dump.sql

你应该看到包含二进制日志文件和位置的注释行。保留它。在将副本指向源服务器时,你将使用它,除非你选择基于GTID的复制。

在副本上导入快照

使用常规安全方法将转储传输到副本:

scp source_dump.sql db-replica:/tmp/source_dump.sql

在副本上,确保你不会意外写入现有生产类数据集。如果此副本应为干净副本,根据迁移计划删除并重新创建需要替换的内容。然后导入:

mysql -u root -p < /tmp/source_dump.sql

对于大型转储,在screentmux中运行导入,并监控磁盘空间。由于/var/lib/mysql/tmp空间不足导致的导入失败会浪费时间,并可能留下半加载的副本。

将副本指向源服务器

在MySQL 8.0.23及更新版本上,使用CHANGE REPLICATION SOURCE TO

CHANGE REPLICATION SOURCE TO
  SOURCE_HOST='192.168.1.100',
  SOURCE_USER='repl_user',
  SOURCE_PASSWORD='use_a_real_secret_here',
  SOURCE_LOG_FILE='mysql-bin.000001',
  SOURCE_LOG_POS=1234;

用转储中的值替换文件和位置。如果你使用旧语法,等效命令是:

CHANGE MASTER TO
  MASTER_HOST='192.168.1.100',
  MASTER_USER='repl_user',
  MASTER_PASSWORD='use_a_real_secret_here',
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=1234;

如果你的环境使用GTID,设置不同。你通常在两台服务器上配置GTID模式,恢复保留GTID状态的转储,并使用SOURCE_AUTO_POSITION=1而不是文件和位置。不要随意混合GTID和文件位置指令;选择一种方法并测试。

关于GTID复制的简短说明

GTID复制在设置后通常更容易操作,因为MySQL通过全局事务ID跟踪事务,而不是让你手动管理二进制日志文件和位置。在故障转移、源服务器更改和副本重建时尤其有用。

但这并不意味着你应该在迁移过程中随意启用它。两台服务器需要兼容的GTID设置,并且你的备份或转储过程必须保留正确的GTID状态。常见模式是配置:

[mysqld]
gtid_mode=ON
enforce_gtid_consistency=ON

然后,在恢复GTID感知转储后,使用以下命令配置副本:

CHANGE REPLICATION SOURCE TO
  SOURCE_HOST='192.168.1.100',
  SOURCE_USER='repl_user',
  SOURCE_PASSWORD='use_a_real_secret_here',
  SOURCE_AUTO_POSITION=1;

仅当源服务器和副本的GTID历史干净且可理解时使用此方法。如果不确定,文件和位置复制对于首次设置更容易推理。最糟糕的选择是混合两种方法的示例,直到复制启动但事务历史并非你所想。

启动复制:

START REPLICA;

旧语法:

START SLAVE;

检查状态:

SHOW REPLICA STATUS\G

旧语法:

SHOW SLAVE STATUS\G

关键字段:

字段 健康值 说明
Replica_IO_Running Yes 副本可以连接并获取二进制日志事件。
Replica_SQL_Running Yes 副本可以应用中继日志事件。
Last_IO_Error 网络、凭据或源日志问题在此显示。
Last_SQL_Error 数据冲突和应用错误在此显示。
Seconds_Behind_Source 低或下降 粗略的延迟指标。

旧输出使用Slave_IO_RunningSlave_SQL_RunningSeconds_Behind_Master

使用小写操作测试

在线程显示Yes后不要宣布成功。在源服务器上创建一个小测试表或在现有测试模式中插入无害行,然后验证它出现在副本上。

源服务器示例:

CREATE DATABASE IF NOT EXISTS repl_check;
CREATE TABLE IF NOT EXISTS repl_check.heartbeat (
  id INT PRIMARY KEY,
  checked_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
REPLACE INTO repl_check.heartbeat (id) VALUES (1);

在副本上:

SELECT * FROM repl_check.heartbeat;

这可以捕获简单错误,例如指向错误的源服务器、过滤掉数据库或使用过时的坐标。

保护复制通道

如果复制流量穿越不可信网络,需要TLS。即使在私有网络内,许多团队现在也偏好加密数据库流量,因为网络边界随时间变化。

至少,创建复制用户和通道,以便凭据不与应用程序账户共享。对于基于TLS的通道,根据MySQL版本配置证书,然后在复制源配置中包含SSL选项。具体选项因版本和证书策略而异,但意图相同:副本应验证它正在连接到预期的源服务器,并保护传输中的凭据和行更改。

同时保持复制用户的权限狭窄。它不需要广泛的DDL或DML访问权限。如果有人获得该密码,影响范围应限于读取复制日志,而不是写入应用程序数据。

常见设置问题

如果Replica_IO_RunningNo,副本无法获取事件。检查:

  • SOURCE_HOST正确。
  • 源服务器在预期地址和端口上监听。
  • 防火墙和安全组允许流量。
  • 复制用户主机与副本的源IP匹配。
  • 密码和身份验证插件与副本的客户端/服务器版本兼容。
  • 请求的二进制日志文件在源服务器上仍然存在。

如果Replica_SQL_RunningNo,副本获取了事件但无法应用。检查Last_SQL_Error。重复键通常意味着副本未从精确匹配的快照初始化,或有人直接写入副本。缺失行通常意味着数据漂移。使用SQL_SLAVE_SKIP_COUNTER跳过事务可能使线程继续,但也可能使副本错误。仅当你理解失败的事务并接受分歧风险时使用它。

如果设置后延迟很高,让副本追赶并观察Seconds_Behind_Source是否下降。大型转储导入后启动复制可能会留下积压。如果延迟增长而不是缩小,检查副本上的磁盘I/O和源服务器上的写入量。

设置后保持副本健康

在源服务器上配置二进制日志保留,以便副本能够承受维护和故障。现代MySQL使用binlog_expire_logs_seconds

[mysqld]
binlog_expire_logs_seconds=604800

该示例保留日志约7天。根据恢复需求和磁盘容量选择值。旧系统可能使用expire_logs_days

监控复制状态和延迟。至少,当任一复制线程停止、延迟超过容忍度以及源服务器磁盘使用因二进制日志未清除而增长时发出警报。对于数据一致性检查,许多团队使用Percona Toolkit工具,如pt-table-checksumpt-table-sync,但在生产规模数据上运行前请仔细测试。

最后,在确认副本为只读、已追赶并受监控之前,保持应用程序流量远离副本。接受意外写入的副本比没有副本更糟糕,因为损坏可能在故障转移或恢复之前保持隐藏。

当起始快照、二进制日志坐标、权限和监控都对齐时,异步复制运行良好。大多数失败的设置源于其中一项被假设而未经验证。