文章目录
- 1、MySQL复制模式
- 2、MySQL复制的兼容性
- 3、与MySQL复制相关的两种日志
- 3.1、中继日志
- 3.2、MySQL复制的状态日志
- 4、MySQL主从复制的实施示例
- 4.1、主从库安装
- 4.2、主库配置
- 4.3、从库的配置
- 4.4、启动复制和确认成功
- 5、对MySQL复制的监控
- 6、MySQL监控的运维
- 6.1、在从库修改主库配置
- 6.2、在从库启动和停止复制
- 6.3、在主库显示从库
- 6.4、更改从库从哪个主库同步的方法
- 7、其他类型复制
- 7.1、MySQL主主复制
- 7.1.1、基本配置
- 7.1.2、自增键冲突问题解决
- 7.2、MySQL级联复制
- 7.3、MySQL跨IDC复制
1、MySQL复制模式
- MySQL有三种复制模式,如下所示
复制模式参数值 | 模式名称 | 说明 | 优点 | 缺点 |
---|---|---|---|---|
statement | 基于SQL语句的复制 | 即逻辑复制,通过执行主库上所执行过的语句实现数据复制 | 简单容易、日志更小、日志可读性利于排查问题 | 有些操作将无法正确复制到从库,例如带LIMIT子句但没有使用ORDER BY的操作等,例如对于存储过程和触发器的支持。另外从库需要锁住更多的记录 |
row | 基于行的复制 | 物理复制,将对数据的修改本身复制到从库 | 所有改变均被复制,更安全和精确,更少的锁表 | 日志更大、可读性差,要求主从表结构完全一致 |
mixed | 混合模式 | 以逻辑复制为主,遇到某些特殊情况例如使用了UUID(),则改为物理复制 | 兼具语句模式的高效和行模式的准确,推荐使用混合模式 |
- 复制模式支持在运行时动态修改,命令如下。注意,从库是可以自行调整以适应主库复制模式的,所以只需要修改主库复制模式:
mysql> SET GLOBAL binlog_format = 'STATEMENT';
mysql> SET SESSION binlog_format = 'STATEMENT';
2、MySQL复制的兼容性
- 主库和从库版本尽量保持一致,以免后续碰到其他问题。
- 主从库版本不一致时,建议从库的版本高于主库,绝大部分情况下MySQL都支持此类复制。主库高版本到从库低版本的复制可能是可行的,但官方不保证支持。
- 主从库之间不要跨越大版本号,那样可能会出问题,比如从MySQL4.1复制到MySQL5.1。如果一定要这么做,为了降低风险,可以考虑在中间插入一个MySQL5.0版本的从库以避免一些意外问题的发生。
- 将生产环境的MySQL升级前,先升级从库的版本,验证和保证复制功能正常。
3、与MySQL复制相关的两种日志
3.1、中继日志
- 默认情况下,中继日志使用host_name-relay-bin.nnnnnn形式的文件名,其中host_name是从服务器主机名,nnnnnn是序列号。用连续的序列号来创建连续的中继日志文件,从000001开始。从服务器跟踪索引文件中目前正在使用的中继日志。中继日志索引文件名默认为host_name-relay-bin.index。默认会在服务器的数据目录中创建这些文件。可以用–relay-log和–relay-log-index服务器选项覆盖默认文件名。强烈建议指定默认文件名,即日志文件名不要有主机名前缀,这样会方便迁移操作和故障处理。
- 中继日志与二进制日志的格式相同,并且可以用mysqlbinlog读取。SQL线程执行完中继日志中的所有事件并且不再需要中继日志之后,会立即自动删除它。没有直接删除中继日志的机制,因为SQL线程可以负责完成。
3.2、MySQL复制的状态日志
- 从库在数据目录中会另外创建两个小文件,默认名为master.info和relay-log.info,它们包含了SHOW SLAVE STATUS语句的输出所显示的信息。状态文件保存在硬盘上,因此从服务器关闭时不会丢失状态文件。下次启动从服务器时,读取这些文件以确定它已经从主服务器读取了多少二进制日志,以及处理自己的中继日志的程度。由I/O线程更新master.info文件。由SQL线程更新relay-log.info文件。
- 当备份从服务器的数据时,你还应备份这两个小文件及中继日志文件。它们可用来在恢复从服务器的数据后继续进行复制。
- 如果丢失了中继日志但仍然有relay-log.info文件,那么你可以通过检查该文件来确定SQL线程已经执行的主服务器中二进制日志的程度,例如如下命令显示:当前从库正好执行到主库日志文件mysql -bin.006800,执行的位置是401289356。然后我们可以用Master_Log_Fi le和Master_LOG_POS选项执行CHANGE MASTER命令来告诉从服务器需要重新从该点读取二进制日志。
shell> cat relay-log.info
/usr/local/mysql/log/relay-bin.015161
401289501
mysql-bin.006800
401289356
4、MySQL主从复制的实施示例
4.1、主从库安装
- 安装好主库和从库,在主库上启用二进制日志,注意主从库的server-id必须设置为不一样,建议server-id可以设置为IP的后8位加上端口(port),类似如下。
[mysqld]
log-bin=mysql-bin
server-id=1713306 # server-id可以跟服务器的IP一致
4.2、主库配置
- 记录主库当前的二进制日志文件的File和Position,如下所示:
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 154 | | | |
+------------------+----------+--------------+------------------+-------------------+
- 在主库中创建用于复制的专门账号,授予权限,允许从库来访问,命令如下:
GRANT replication slave,replication client ON *.* TO replic_user IDENTIFIED BY 'xxxxxxxxxxx';
4.3、从库的配置
- 编辑从库的配置文件,如下展示一个从库的配置文件示例:只有server-id必须设置,其他选项是可选的,对这些选项解释如下:
- log_bin=mysql-bin:建议主从配置一样的名字,不然在以后的配置中,处理问题会复杂很多。
- log_slave_updates=1:log_slave_updates决定了在执行复制时是否还要将这些SQL操作写入从库自身的二进制日志里,为1则写入,为0则不写入。如果这个库未来可能设置为主库,则将这个值设置为1。设置为1的缺点是造成更大的I/O写入。
- read_only=1:只有SUPER权限的用户才可以修改数据。
server_id = 1723306
log_slave_updates = 1
log_bin = mysql-bin
relay_log = /path_to_mysql_log/mysql-relay-bin
read_only = 1
- 在从库上执行如下语句,其中MASTER_LOG_FILE和MASTER_LOG_POS是之前第二个步骤里记录的主库的File和Position的值。千万不要使用在配置文件里指定master_host、master_port的方式,这些配置只在第一次启动MySQL时才生效:
mysql >
CHANGE MASTER TO
MASTER_HOST='192.168.124.171',
MASTER_PORT=3306,
MASTER_USER='replic_user',
MASTER_PASSWORD='xxxxxxxxxxx',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
4.4、启动复制和确认成功
- 在从库上执行如下命令启动slave。
mysql> start slave;
- 在从库上检查复制是否正常: Slave_IO_Running、 Slave_SQL_Running的值应该为YES, Seconds_Behind_Master应该不是NULL。
mysql> SHOW SLAVE STATUS \G;
……
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
……
Seconds_Behind_Master: 0
……
5、对MySQL复制的监控
可以在从库通过SHOW SLAVE STATUS监控MySQL复制的状态,对于其输出参数,说明如下:
6、MySQL监控的运维
6.1、在从库修改主库配置
- 可以通过CHANGE MASTER TO命令动态修改连接主库的信息,例如修改复制用户的密码,注意修改时只需要指定发生了变化的参数,不需要指定为发生变化的参数。
- 以下参数可以修改:
- MASTER_HOST和MASTER_PORT指定了主库的IP和PORT。
- MASTER_LOG_FILE和MASTER_LOG_POS指定了主库的二进制日志的名称和位置。
- MASTER_USER和MASTER_PASSWORD指定了复制用户的账号和密码,将使用这个账号去连接主库,所以主库需要给予这个账号REPLICATION SLAVE的权限来复制数据。
- CHANGE MASTER TO会删除所有的中继日志文件并启动一个新的日志,除非您指定了RELAY_LOG_FILE或RELAY_LOG_POS。在此情况下,中继日志将被保持。
- CHANGE MASTER TO命令将会更新master.info和relay-log.info文件的内容。
- 以下为一个修改的完整示例,先停止从库的复制,再修改,然后启动复制:
mysql> STOP SLAVE;
mysql> CHANGE MASTER TO MASTER_PASSWORD='new3cret';
mysql> START SLAVE;
6.2、在从库启动和停止复制
- 不含选项的START/STOP SLAVE会同时启动/停止两个从库线程(即I/O线程和SQL线程)。STARTSLAVE要求SUPER权限。
- 可以单独启动或停止某个线程,如下示例:
2.1. 启动I/O线程:
mysql> START SLAVE IO_THREAD
2.2. 启动SQL线程:
mysql> START SLAVE SQL_THREAD
- START SALVE可以通过添加一个UNTIL子句,指定从库复制直到达到主服务器二进制日志中的一个给定点为止。如果在该语句中指定了SQL_THREAD选项,则它只会启动SQL线程。否则,它会同时启动两个从库线程。一般情况下,我们仅操控SQL线程。
mysql> START SLAVE [SQL_THREAD] UNTIL MASTER_LOG_FILE = 'log_name', MASTER_LOG_POS = log_pos
6.3、在主库显示从库
可以运行如下命令显示当前主库的所有从库:
mysql> SHOW SLAVE HOSTS;
6.4、更改从库从哪个主库同步的方法
假设有A、B、C、D共4个MySQL实例,A是主库,B、C、D是从库。现在需要调整架构为B做A的从库,C、D是B的从库。我们可以按照如下的步骤进行调整。
- 分别关闭B、C、D从库的SLAVE:
mysql> STOP SLAVE;
- 查看主库A上的日志位置信息,命令如下。
mysql> show master status;
+-------------------------+----------------+---------------------+-------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------------+----------------+---------------------+-------------------------+
| mysql-bin.000003 | 307827324 | | |
+-------------------------+----------------+---------------------+-------------------------+
- 在所有从库B、C、D上运行如下命令,等同步到指定的位置时,自动断开SQL线程。此时B、C、D上面的数据应该是一致的,都同步到了A库的某个日志点。
mysql> START SLAVE SQL_THREAD UNTIL MASTER_LOG_FILE = ' mysql-bin.000003', MASTER_LOG_POS = 307827324;
-
在B库上运行SHOW MASTER STATUS记录下日志的位置信息log file name、log_file_positiion。
-
在C、D从库运行如下命令,指向新的主库B。
mysql > STOP SLAVE;
mysql > RESET SLAVE;
mysql >
CHANGE MASTER TO
MASTER_HOST='11.11.11.11',
MASTER_PORT=3306,
MASTER_USER='replic_user',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='log file name',
MASTER_LOG_POS=log_file_positiion;
- 最后,在B库上运行START SLAVE命令,这样就可以调整A为主库,B为A的从库,C、D是B的从库。
7、其他类型复制
7.1、MySQL主主复制
7.1.1、基本配置
- 配置主主复制的步骤很简单,对每个库分别执行配置主从复制的步骤,就是先按照主从节点做配置,然后再反过来,把从节点当主节点,主节点当从节点再配置一遍即可。
- 一定要确保任一时刻只写一个库,主主复制是为了故障冗余而不是为了多点写入,所以一般应配置为Active-Standby(主备),而不是Active-Active(双活)。一般而言,配置为主主复制会导致维护更加复杂,可能还会带来隐患,需要更完善的监控措施和自动化手段。
7.1.2、自增键冲突问题解决
- 配置为主主复制,需要解决的主要问题是自增键/主键冲突:服务器变auto_increment_increment用于控制自增列值增加的间隔。auto_increment_offset用于确定自增列值的起点。假设有两台主机A、B,它们互为主从,那么对my.cnf的mysqld节可增加配置如下。
- A主机
auto_increment_increment=3
auto_increment_offset=1
- B主机
auto_increment_increment=3
auto_increment_offset=2
- 我们还需要注意,除了自增字段不能互相冲突之外,所有表的键值也不能互相冲突,同一时刻的操作需要保证不会插入相同的键值。
7.2、MySQL级联复制
假如需要配置成A→B→C→D→E这样的形式,箭头表示复制到,那么可按如下步骤进行。注意节点越多,健壮性越差,建议不要超过4~5个节点。
- 首先打开各实例的log_slave_updates选项,首尾两个实例也可以不用打开。
- 确保各主机的server-id不同。
- 配置每一对主从,A→B,B→C,C→D,D→E。
7.3、MySQL跨IDC复制
- 跨IDC复制架构的部署与单机房部署链式复制(级联复制)的从库并没有区别,但由于网络的不稳定,可能会导致复制的不稳定,维护代价较高,而且可能需要外网IP才能进行复制,降低了安全性。
- 跨IDC的复制,建议还是采用普通的主从架构,而不要采用链式的复制架构,简单的主从架构更稳健。
- 尽量只在中心主库进行写入,其他机房只用于读,这样既可以简化架构,也可以避免多点写入带来的维护一致性的难题。如果是M-M的架构,也应该将一个机房作为备用(Standby),仅作容灾。
- 数据量较大的时候,网络可能会成为瓶颈,建议使用混合日志的复制模式。可在从库中设置slave_compressed_protocol=1压缩传输数据,此选项可进行动态设置。
- 由于跨IDC的主从复制,重新搭建代价比较大,在明确知道数据库出现何种错误时,可以忽略此错误,可使用“slave-skip-errors=error_code1,error_code2…|al l”,但不要滥用,否则容易导致主从不一致而不自知。
- 由于跨IDC的复制,网络可能会不稳定,应用程序应该处理网络延时对用户体验的影响。