MySQL数据库
什么是 MySQL 复制
复制的定义
复制是指在主 MySQL 服务器(master)上写入的数据被发送到一个或多个独立的从服务器(slave)并在这些服务器上执行。
复制的应用场景
- 备份:通过从服务器定期备份数据,减轻主服务器负担。
- 读负载分摊:将读取操作分布到多个从服务器上以实现可扩展性。
- 故障切换/高可用性(Failover/HA):在主服务器故障时,从服务器接管服务。
复制的类型
-
异步复制(Asynchronous Replication):
- 基本的主从(master-slave)架构。
- 主服务器记录操作到二进制日志,从服务器读取并执行。
- 主从服务器在特定时间点可能处于不同状态,适合处理网络中断。
-
半异步复制(Semi-Asynchronous Replication):
复制的配置模式
-
标准模式(Master -> Slave):
- 主服务器向从服务器单向复制数据。
-
双主模式(Master <-> Master):
- 两台服务器互为主从。
- 注意:
- 没有一致性检查。
- 即使配置了
auto_increment_increment
和auto_increment_offset
,也不建议同时对两台服务器执行写操作以避免冲突。
异步复制
基本原理
主服务器写入二进制日志文件,从服务器通过读取这些日志文件重放查询语句实现数据同步。由于是异步的,主从服务器在某些时间点可能状态不一致,但这种模式可以容忍网络断开。
配置主服务器
在主服务器的 /etc/mysql/my.cnf
文件中的 [mysqld]
部分添加以下配置:
-
定义服务器 ID:
server-id = 1
-
启用二进制日志:
log-bin # 或指定日志路径: log-bin = /var/log/mysql/mysql-bin.log
-
创建用于复制的用户:
CREATE USER 'myreplication'; SET PASSWORD FOR 'myreplication' = PASSWORD('mypass'); GRANT REPLICATION SLAVE ON *.* TO 'myreplication';
-
验证服务器 ID:
SHOW VARIABLES LIKE 'server_id';
配置从服务器
在从服务器的 /etc/mysql/my.cnf
文件中的 [mysqld]
部分添加以下配置:
-
定义唯一的服务器 ID(不同于主服务器和其他从服务器):
server-id = 2
-
验证服务器 ID:
SHOW VARIABLES LIKE 'server_id';
-
声明从服务器主机名(可选):
report-host=slave1
-
声明主服务器:
CHANGE MASTER TO MASTER_HOST='master_addr', MASTER_USER='myreplication', MASTER_PASSWORD='mypass';
-
从备份设置复制的起点(如从主服务器备份开始同步时需添加以下内容):
MASTER_LOG_FILE='<binary_log_from_master>', MASTER_LOG_POS=<master_binary_log_position>;
-
启动复制:
START SLAVE;
此操作将在数据目录(通常为 /var/lib/mysql/
)下生成名为 master.info
的文件,该文件保存从服务器的配置和状态。
注意事项
-
设置
--relay-log
: 如果未设置中继日志(relay log),可能导致从服务器在主机名更改后复制中断。建议在配置中指定:relay-log=mysqld-relay-bin
-
配置主从服务器时,确保使用唯一的
server-id
和日志设置,以避免循环复制或数据不一致。
MySQL 复制状态检查与维护
检查复制状态
在从服务器上检查
-
查看复制状态:
SHOW SLAVE STATUS;
或使用更易读的格式:
SHOW SLAVE STATUS\G
-
示例输出:
*************************** 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_Running
和Slave_SQL_Running
均应为Yes
。Seconds_Behind_Master
表示从服务器相对于主服务器的延迟(以秒计),正常情况下应为0
。
-
查看全局变量:
SHOW GLOBAL VARIABLES LIKE "%SLAVE%";
在主服务器上检查
-
查看从服务器连接:
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
-
查看从服务器信息(如果启用了
report-host
):SHOW SLAVE HOSTS;
示例输出:
+-----------+---------+------+-------------------+-----------+ | Server_id | Host | Port | Rpl_recovery_rank | Master_id | +-----------+---------+------+-------------------+-----------+ | 2 | myslave | 3306 | 0 | 1 | +-----------+---------+------+-------------------+-----------+
维护复制一致性
-
避免写入关键数据到从服务器: 从服务器应仅作为只读节点使用,不要进行写操作。
-
确保主从初始数据一致: 在设置复制时,主从服务器的数据必须完全一致。
-
使用相同版本的 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.
跳过错误
-
停止从服务器:
STOP SLAVE;
-
设置跳过计数:
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;
-
重启复制:
START SLAVE;
注意:SQL_SLAVE_SKIP_COUNTER
会跳过指定数量的语句,包括有效和无效的语句。
使用工具修复复制
Maatkit 提供了一些实用工具:
mk-slave-restart
:自动重启从服务器复制。mk-table-checksum
:校验主从表的一致性。mk-table-sync
:基于校验结果同步主从数据。
卸载复制
-
重置从服务器:
RESET SLAVE;
- 这会暂停复制并清空从服务器配置,同时删除
master.info
文件。
- 这会暂停复制并清空从服务器配置,同时删除
-
防止自动重启复制: 在配置文件中添加以下内容:
slave-skip-start
-
验证重置:
SHOW SLAVE STATUS;
输出应为空。
SQL 提示
通过在 SQL 请求前添加注释,可以控制复制的行为。例如,通过 PHP 的 Mysqlnd
插件:
MYSQLND_MS_MASTER_SWITCH
:强制在主服务器上执行请求。MYSQLND_MS_SLAVE_SWITCH
:强制在从服务器上执行请求。MYSQLND_MS_LAST_USED_SWITCH
:强制在上一次使用的服务器上执行请求。
联合表
MySQL 的 Federated 存储引擎可以作为复制和集群的替代方案,允许在一台服务器上创建与另一台服务器同步的表。
参考: