作者:朱明豪,新炬网络高级技术专家。
一、复制概述
MySQL复制就是同步一个mysql数据库(master)上的所有改变到另一台mysql数据库(slave),所有数据库的改变记录到binary log。复制经常用来创建主节点的一个可靠副本,用于备份、故障恢复等。
MySQL支持三种复制方式:基于SQL语句的复制(statement-based replication,SBR),基于行的复制(row-based replication,RBR),混合模式复制(mixed-based replication,MBR)。以上方式都是通过在主库上记录binary log、在备库重放日志的方式实现异步数据复制。异步复制必然导致在同一时间点备库上的数据可能与主库的不一致,并且无法保证主备之间的延迟。
复制会主库带来主要的开销:二进制日志的开销;备库请求从主库读取旧的二进制日志文件的I/O开销;从一个高吞吐量的主库上复制到多个备库,唤醒多个复制线程发送事件的累加开销。
二、原理介绍
复制是通过slave重放master上的binary log,重新执行,实现的数据同步。
主要有三个步骤:
1.master记录数据变更到二进制日志(Binary Log)
2.slave复制主库上的Binary Log到自己的中继日志(relay log)
3.slave重放中继日志的事件,在slave上重新执行。
具体实现如下图:
MySQL主从复制原理:
1.数据变更时,Master将数据变更的事件记录到binary log
2.Master发送信号,唤醒Dump thread,通知其有新的事件产生。
3.Dumpthread将新事务发送给Slave的I/O线程。
4.Slave的I/OThread会将接受到的事件记录到relay log
5.Slave的SQLThread从relay log中读取事件
6.SQLThread在Slave重放读取的事件,从而实现备库数据的更新
Mysql复制配置完成后,各线程显示情况:
Master的binlog dump线程
Slave的IO thread和SQLthread
三、简单搭建
根据mysql复制的原理,建立基本的复制需要三个简单步骤:
1.配置一个mysql数据库为Master
2.配置一个mysql数据库为slave
3.将slave连接到Master
(一)配置Master
1、参数配置
将mysql数据库配置为Master,需要启动binary log和设置唯一的server_id。Binary log保存Master上的所有改变,server_id用于区分mysql数据库。相关参数为log_bin、log_bin_index、server_id,设置这几个参数需要停止mysql数据库。
将配置参数添加到my.cnf的[mysqld]
2、创建复制账号
Slave启动一个标准的客户端连接到Master,并请求Master将所有的改变的转储给它,Slave连接时要求Master上需要一个有特定复制权限的用户。需要在Master、Slave上都创建。
创建复制账号并赋予适当的权限
(二)配置Slave
1、参数配置
与Master一样需要配置server id和relay log。
将配置参数添加到my.cnf的[mysqld]
2、初始化slave
为了保持与master的一致,slave必须是master同步数据某个时间点的一致性快照。因此需要三部分数据:
在某个时间点Master同步数据的一致性快照。
快照时间点master的当前binary log文件和改时间点在binary log中的偏移量。
从快照时间到当前的binary log。
获得master同步时间某个时间点的一致性快照的有如下方法:
冷备份
关闭master,把数据文件复制到备库。重启主库后,会使用新的binary log文件,通过show master status获得当前binary log文件和起始点。
Mysqldump
针对innodb表,通过选项--single-transaction,可以获得事务开始前的一致性数据。如果非事务性表,可以使用选项--lock-all-tables获得所有表的一致性快照。
存储快照或备份
只要知道快照或备份对应的binary log的坐标,就可以把快照或备份恢复到备库,然后使用CHANGEMASTER TO指定binary log的坐标。
Percona xtrabackup
Xtrabackup是percona公司开发的一款开源的热备份工具,能够在备份时不堵塞mysql数据库的操作。
(三)连接master和slave
现在需要指定slave从master的binarylog那个点开始复制。因此需要知道master的4部分信息:
主机名
端口号
Master上的replicationslave权限的用户账号
用户密码
起始Binlog日志文件
起始复制点
下面是开始复制的基本命令:
这样就完成了复制的简单配置。
我们可以通过线程列表查看到具体的复制线程。在Master上可以看到由slave IO线程向master发起的连接。
在备库上也可以看到两个线程,一个是IO线程,一个是SQL线程。并且IO线程和SQL线程总是运行在“system user”账号下。
上述的输出来自一台已经运行了一段时间的mysql数据库,所以IO线程在master和slave上的Time列的值较大。SQL线程在slave上已经空闲了1126658秒,这意味着1126658秒内没有重放任务事件。
四、复制扩展
(一)级联复制
Log_slave_updates参数可以让备库变成其他mysql数据库的主库。启用该参数后,MySQL会将其执行过的事件记录到自己的binary log中;这样它的备库就可以从其日志中获取变更事件并执行。下图演示了执行过程。
(二)过滤复制
复制过滤有两种方式:主库上过滤记录到binary log中的时间,备库上重放执行时过滤中继日志的事件。下图展示这两种类型:
binlog-do-db和binlog-ignore-db参数,在主库上生效,直接控制binary log的记录内容。可从如下实验得到证明。
Master操作
Binlog日志记录内容,未发现sakila库的相关事件。
--replicate-*选项,在从master获取变更事件记录到relay log时不进行过滤,relay log仍然保存master 所有的变更事件;而是在SQL thread重放时进行过滤。可从如下实验得到证明。
Master操作
在sakila库下进行操作。
Slave 操作
查看relay log记录内容
查看执行情况,发现未执行过滤项”sakila.t%”的内容。
(三)半同步复制
1、半同步复制原理
半同步复制是google提供的一组mysql和innodb的扩展补丁,目前集成到mysql5.5以后的版本中。它能够保证主库和至少一台从库之间的数据一致性。
它的原理是:
在主库事务提交存储引擎后返回客户端前,至少有一台从库,确认更新已经写入其Relay Log (不是应用到slave)。
出现超时,主库会暂时还原为常规的异步复制模式继续复制,直到一台设置为半同步复制模式的从库及时收到信息后,再切回半同步模式。
下图为半同步复制的事物提交过程:
2、配置半同步复制
半同步复制要求master和slave都支持。启动半同步复制的步骤如下:
五、管理维护
(一)常用参数
(二)常用命令
主库:
1、SHOWBINLOG EVENTS; 所有的变更事件
显示binary log的的变更事件,缺省为第一个binlog文件
语法:
SHOWBINLOG EVENTS [IN 'log_name'][FROM pos][LIMIT [offset,] row_count]
2、showmaster status;
当前binlog文件名称,及下个event的Position 。
3、showslave hosts;
显示当前注册到master的slave列表
4、resetmaster;
删除binary log index 中所有binary log
清空binary log index file
创建一个新的binary log file( .000001)
所有注册到master的slave将失效
5、showmaster logs;
等同于SHOW BINARY LOGS,查看主库上binary log的文件列表,经常在PURGE BINARY LOGS之前使用。
6、PURGEBINARY LOGS
删除binlog index中,指定文件或时间之前binlog文件
PURGEBINARY LOGS TO 'mysql-bin.010';
PURGEBINARY LOGS BEFORE '2008-04-02 22:46:26';
从库:
1、changemaster to
设置slave的同步选项
常用写法:
2、resetslave
删除所有relay log,并生成一个新relay log
重置master.info,relay.info
MASTER_DELAY重置为0
需要stop slave
3、resetslave all
情况change master to信息,删除slave在master的注册信息。show slave status \G;为空,主库show slave hosts 删除该slave 信息
4、STOPSLAVE
停止slave的复制线程。
STOP SLAVE IO_THREAD/SQL_THREAD
单独停止IO_THREAD/SQL_THREAD线程
5、startslave
启动slave的复制线程。
Start SLAVEIO_THREAD/SQL_THREAD
单独启动IO_THREAD/SQL_THREAD线程
start slaveuntil …;
执行到某个点时停止.
6、showslave status
显示当前slave的复制运行状况
六、参考文档
《MySQl 5.7 Reference Manual-Chapter 17 Replication》
《MySQl 5.7 Reference Manual-Chapter 13 SQL Statement Syntax》
《高性能MySQL_第3版》
《高可用MySQL_第2版》