什么是 MySQL 复制

复制的定义

复制是指在主 MySQL 服务器(master)上写入的数据被发送到一个或多个独立的从服务器(slave)并在这些服务器上执行。


复制的应用场景

  1. 备份:通过从服务器定期备份数据,减轻主服务器负担。
  2. 读负载分摊:将读取操作分布到多个从服务器上以实现可扩展性。
  3. 故障切换/高可用性(Failover/HA):在主服务器故障时,从服务器接管服务。

复制的类型

  1. 异步复制(Asynchronous Replication):

    • 基本的主从(master-slave)架构。
    • 主服务器记录操作到二进制日志,从服务器读取并执行。
    • 主从服务器在特定时间点可能处于不同状态,适合处理网络中断。
  2. 半异步复制(Semi-Asynchronous Replication):

    • 基于异步复制,确保至少有一个从服务器完成同步后主服务器才提交查询
    • 增加了数据安全性

复制的配置模式

  1. 标准模式(Master -> Slave):

    • 主服务器向从服务器单向复制数据。
  2. 双主模式(Master <-> Master):

    • 两台服务器互为主从。
    • 注意
      • 没有一致性检查。
      • 即使配置了 auto_increment_incrementauto_increment_offset,也不建议同时对两台服务器执行写操作以避免冲突。

异步复制

基本原理

主服务器写入二进制日志文件,从服务器通过读取这些日志文件重放查询语句实现数据同步。由于是异步的,主从服务器在某些时间点可能状态不一致,但这种模式可以容忍网络断开。


配置主服务器

在主服务器的 /etc/mysql/my.cnf 文件中的 [mysqld] 部分添加以下配置:

  1. 定义服务器 ID

    server-id = 1
    
  2. 启用二进制日志

    log-bin
    # 或指定日志路径:
    log-bin = /var/log/mysql/mysql-bin.log
    
  3. 创建用于复制的用户

    CREATE USER 'myreplication';
    SET PASSWORD FOR 'myreplication' = PASSWORD('mypass');
    GRANT REPLICATION SLAVE ON *.* TO 'myreplication';
    
  4. 验证服务器 ID

    SHOW VARIABLES LIKE 'server_id';
    

配置从服务器

在从服务器的 /etc/mysql/my.cnf 文件中的 [mysqld] 部分添加以下配置:

  1. 定义唯一的服务器 ID(不同于主服务器和其他从服务器):

    server-id = 2
    
  2. 验证服务器 ID

    SHOW VARIABLES LIKE 'server_id';
    
  3. 声明从服务器主机名(可选):

    report-host=slave1
    
  4. 声明主服务器

    CHANGE MASTER TO MASTER_HOST='master_addr', 
    MASTER_USER='myreplication', 
    MASTER_PASSWORD='mypass';
    
  5. 从备份设置复制的起点(如从主服务器备份开始同步时需添加以下内容):

    MASTER_LOG_FILE='<binary_log_from_master>', 
    MASTER_LOG_POS=<master_binary_log_position>;
    
  6. 启动复制

    START SLAVE;
    

此操作将在数据目录(通常为 /var/lib/mysql/)下生成名为 master.info 的文件,该文件保存从服务器的配置和状态。


注意事项

  1. 设置 --relay-log: 如果未设置中继日志(relay log),可能导致从服务器在主机名更改后复制中断。建议在配置中指定:

    relay-log=mysqld-relay-bin
    
  2. 配置主从服务器时,确保使用唯一的 server-id 和日志设置,以避免循环复制或数据不一致。

MySQL 复制状态检查与维护


检查复制状态

在从服务器上检查

  1. 查看复制状态

    SHOW SLAVE STATUS;
    

    或使用更易读的格式:

    SHOW SLAVE STATUS\G
    
  2. 示例输出

    *************************** 1. row ***************************
                 Slave_IO_State: 
                    Master_Host: master_addr
                    Master_User: myreplication
                    Master_Port: 3306
    ...
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
    

    关键字段

    • Slave_IO_RunningSlave_SQL_Running 均应为 Yes
    • Seconds_Behind_Master 表示从服务器相对于主服务器的延迟(以秒计),正常情况下应为 0
  3. 查看全局变量

    SHOW GLOBAL VARIABLES LIKE "%SLAVE%";
    

在主服务器上检查

  1. 查看从服务器连接

    SHOW PROCESSLIST\G
    

    示例输出

    *************************** 6. row ***************************
         Id: 14485
       User: myreplication
       Host: 10.1.0.106:33744
         db: NULL
    Command: Binlog Dump
       Time: 31272
      State: Has sent all binlog to slave; waiting for binlog to be updated
       Info: NULL
    
  2. 查看从服务器信息(如果启用了 report-host

    SHOW SLAVE HOSTS;
    

    示例输出

    +-----------+---------+------+-------------------+-----------+
    | Server_id | Host    | Port | Rpl_recovery_rank | Master_id |
    +-----------+---------+------+-------------------+-----------+
    |         2 | myslave | 3306 |                 0 |         1 | 
    +-----------+---------+------+-------------------+-----------+
    

维护复制一致性

  1. 避免写入关键数据到从服务器: 从服务器应仅作为只读节点使用,不要进行写操作。

  2. 确保主从初始数据一致: 在设置复制时,主从服务器的数据必须完全一致。

  3. 使用相同版本的 MySQL: 建议主从服务器使用相同版本的 MySQL 以避免兼容性问题。


修复复制问题

复制错误的排查

当复制出现问题时,MySQL 会在系统日志(通常为 /var/log/syslog)中记录错误。例如:

Oct 15 21:11:19 builder mysqld[4266]: 101015 21:11:19 [ERROR] Slave: Error 'Table 'mybase.form' doesn't exist' on query.

跳过错误

  1. 停止从服务器:

    STOP SLAVE;
    
  2. 设置跳过计数:

    SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
    
  3. 重启复制:

    START SLAVE;
    

注意SQL_SLAVE_SKIP_COUNTER 会跳过指定数量的语句,包括有效和无效的语句。


使用工具修复复制

Maatkit 提供了一些实用工具:

  • mk-slave-restart:自动重启从服务器复制。
  • mk-table-checksum:校验主从表的一致性。
  • mk-table-sync:基于校验结果同步主从数据。

卸载复制

  1. 重置从服务器

    RESET SLAVE;
    
    • 这会暂停复制并清空从服务器配置,同时删除 master.info 文件。
  2. 防止自动重启复制: 在配置文件中添加以下内容:

    slave-skip-start
    
  3. 验证重置

    SHOW SLAVE STATUS;
    

    输出应为空。


SQL 提示

通过在 SQL 请求前添加注释,可以控制复制的行为。例如,通过 PHPMysqlnd 插件:

  • MYSQLND_MS_MASTER_SWITCH:强制在主服务器上执行请求。
  • MYSQLND_MS_SLAVE_SWITCH:强制在从服务器上执行请求。
  • MYSQLND_MS_LAST_USED_SWITCH:强制在上一次使用的服务器上执行请求。

联合表

MySQL 的 Federated 存储引擎可以作为复制和集群的替代方案,允许在一台服务器上创建与另一台服务器同步的表。

参考

最后修改: 2025年01月17日 星期五 19:34