MySQL/复制
复制意味着写入主 MySQL 服务器的数据将被发送到单独的服务器并在那里执行。
应用
- 备份
- 将读取访问分散到多个服务器以实现可扩展性
- 故障转移/高可用性
复制类型
- 异步复制(基本主从)
- 半异步复制(异步复制 + 强制在完成查询之前进行 1 次从服务器复制)
复制配置
- 标准:主->从
- 双主:主<->主
在主主复制中,两个主机同时是主服务器和从服务器。 服务器 A 复制到服务器 B,服务器 B 复制到服务器 A。 没有一致性检查,即使配置了 auto_increment_increment/auto_increment_offset,也不应将两个服务器用于并发写入。
这是最简单的复制。 主服务器写入二进制日志文件,从服务器可以读取此日志文件(可能选择性地读取)以重放查询语句。 它是异步的,这意味着主服务器和从服务器在特定时间点可能具有不同的状态; 此外,此设置可以承受网络断开连接。
在 /etc/mysql/my.cnf
中,在 [mysqld]
部分
- 定义服务器标识符(检测循环?); 通常我们会使用
1
表示服务器,但它可以是不同的
server-id = 1
- 复制基于 二进制日志,因此请启用它们
log-bin # or log-bin = /var/log/mysql/mysql-bin.log
为从服务器创建一个新用户以连接
CREATE USER 'myreplication';
SET PASSWORD FOR 'myreplication' = PASSWORD('mypass');
GRANT REPLICATION SLAVE ON *.* to 'myreplication';
验证您的服务器标识符
SHOW VARIABLES LIKE 'server_id';
在 /etc/mysql/my.cnf
中,在 [mysqld]
部分
- 定义服务器标识符,与主服务器不同(以及与其他从服务器不同)
server-id = 2
- 使用以下命令验证
SHOW VARIABLES LIKE 'server_id';
- 您还可以将从服务器主机名声明给主服务器(参见下面的
SHOW SLAVE HOSTS
)
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;
这将在您的数据目录中创建一个名为 master.info
的文件,通常为 /var/lib/mysql/master.info
; 此文件将包含从服务器配置和状态。
待办事项
Oct 15 21:11:19 builder mysqld[4266]: 101015 21:11:19 [Warning] Neither --relay-log nor --relay-log-index were used; so replication may break when this MySQL server acts as a slave and has his hostname changed!! Please use '--relay-log=mysqld-relay-bin' to avoid this problem.
在从服务器上,键入
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
您可以检查复制的异步性质
Seconds_Behind_Master: 0
另请参阅
mysql> SHOW GLOBAL VARIABLES LIKE "%SLAVE%";
您可以在进程列表中看到来自从服务器的连接。
mysql> 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
,从服务器也可见于
mysql> SHOW SLAVE HOSTS; +-----------+---------+------+-------------------+-----------+ | Server_id | Host | Port | Rpl_recovery_rank | Master_id | +-----------+---------+------+-------------------+-----------+ | 2 | myslave | 3306 | 0 | 1 | +-----------+---------+------+-------------------+-----------+ 1 row in set (0.00 sec)
请注意,这种复制是一种简单的重放,类似于将 mysqldump
输出馈送到 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. Default database: 'mybase'. Query: 'INSERT INTO `form` (`form_id`,`timestamp`,`user_id`) VALUES ('abed',1287172429,0)', Error_code: 1146
最好的方法是完全重置复制。
您也可以手动修复错误,然后要求 MySQL 以这种方式跳过 1
条语句
STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; START SLAVE;
您可以将 SQL_SLAVE_SKIP_COUNTER
设置为任何数字,例如 100
。 请注意,在这种情况下,它将跳过有效语句和无效语句,而不仅仅是错误。
另一种修复损坏复制的方法是使用 Maatkit 工具。
- mk-slave-restart(如果存在更多错误,并且
SQL_SLAVE_SKIP_COUNTER
无济于事,则重新启动从服务器上的复制) - mk-table-checksum(在主服务器和从服务器上执行表的校验和)
- mk-table-sync(根据 mk-table-checksum 生成的统计信息,将从服务器与主服务器同步)
要擦除复制
- 键入
mysql> RESET SLAVE;
- 注意:此时,MySQL 暂停了从服务器并使用默认值替换了配置。
master.info
文件也被删除。 - 重新启动 MySQL 以清除所有配置。
警告:STOP SLAVE
将停止复制。 它可以手动重新启动,或者(默认情况下)如果您重新启动 MySQL 服务器,它将自动恢复。 为了在启动过程中避免复制的自动启动,请在您的配置文件中添加
slave-skip-start
如果您想永久停止复制(并将服务器用于其他目的),则需要如上所述重置配置。
此时,您的从服务器配置应该完全为空
mysql> SHOW SLAVE STATUS; Empty set (0.00 sec)
一些提示可以放在每个有关复制的请求之前的注释中。 例如通过 PHP Mysqlnd 插件(用于本机驱动程序)。[1]
- MYSQLND_MS_MASTER_SWITCH:强制在主服务器上执行请求。
- MYSQLND_MS_SLAVE_SWITCH:强制在从服务器上执行请求。
- MYSQLND_MS_LAST_USED_SWITCH:强制在最后使用的服务器上执行请求。
作为复制和集群的替代方案,MySQL Federated 存储引擎允许您在服务器上创建一个表,该表与另一个服务器上的相同表同步。