简介
主从复制是利用MySQL复制机制将数据复制到另外一台或多台MySQL服务器上,被复制的服务器称为主服务器,复制的服务器称为从服务器。一般是一主多从。主从复制的好处主要是数据备份、负载均衡(读写分离)、高可用等。
中继日志
中继日志应用于主从复制中,从服务器在收到主服务器修改事件时将事件写入到中继日志文件中,中继日志就像一个队列,事件在里面排队等待从服务器接收。和二进制日志索引文件一样,还有一个中继日志索引文件,索引文件列出所有中继日志文件,此文件是文本的因此可以直接查看,文件的最后一行就是当前正在使用的中继日志文件。
中继日志文件默认的基本名是HOSTNAME-relay-bin,基本文件名加上一组顺序编号000001、000002...就是中继日志文件名了,例如localhost-relay-bin.000001。每次启动服务器、执行刷新日志命令(flush logs)以及中继日志文件到达最大长度的时候,服务器会按顺序号生成下一个中继日志文件,参数max_relay_log_size决定了中继日志最大长度。中继日志索引文件名默认是中继日志基本文件名加上.index。参数relay_log、relay_log_index可以修改中继日志和中继日志索引文件名。
工作原理
在复制关系形成的时候,要复制的数据库的状态和数据在主从服务器上必须完全一致,此后主服务器的数据修改才会被正确的复制到从服务器上。二进制日志负责在主从服务器间传递数据,因此主服务器必须开启二进制日志功能。每个从服务器都必须具备连接到主服务器并请求数据复制的权限,从服务器会告诉主服务器上次连接时已经复制到二进制日志的什么位置,主服务器从上次复制结束的位置开始传输数据给从服务器,当从服务器复制完成所有数据后,会进入等待状态。当主服务器再次发生数据修改时会继续记录到二进制日志中以便向从服务器传输。每一个从服务器的连接也会占用主服务器的max_connections参数配置的最大连接数。
半同步复制
主服务器在执行完客户端提交的请求后会立即将结果返回给客户端,并不关心从主服务器是否已经接收并处理。异步复制会导致主服务器和从服务器可能有短时间的数据不一致。通常这个时间是由网络和系统等决定的。如果出现不一致,而同时主服务器又宕机,这时从服务器中的数据就是不完整的,于是便有了半同步复制。
半同步复制是主服务器在执行完客户端提交的请求后不是立刻返回给客户端,而是等待至少一个从服务器接收到并写到中继日志中才返回给客户端。优点是主从数据一致,缺点是主库的请求延迟增加,吞吐量会降低,这个延迟最少是一个TCP/IP往返的时间。所以半同步复制最好在低延时的网络中使用。MySQL以插件的形式支持半同步复制。
并行复制
主从复制,有三种线程参与:Binlog Dump(主)、I/O线程 (从)、SQL Thread(从)。
MySQL5.6之前,从服务器只有两条线程,I/O线程负责接收主服务器的修改事件并把它们写入到中继日志,SQL线程负责读取中继日志的事件并执行它们,在处理完每个中继日志后删除它。这两个线程互不干扰。即使从服务器的多个数据库的数据还原也是只有一个SQL线程。
MySQL从5.6开始,I/O线程和SQL线程变成了coordinator线程和worker线程,coordinator线程包含I/O和SQL线程的功能,worker线程类似SQL线程。coordinator线程会判断是否允许并行,如果不允许则自己执行数据还原,如果允许则分发给多个worker线程并行还原。但是5.6的并行复制是针对多个数据库的,即每个数据库一个worker线程,这样假设只有一个数据库需要复制,那么就无法并行还原了。
MySQL5.7开始,可以称为真正的并行复制。5.7引入了参数slave-parallel-type,可选值有DATABASE(默认值,基于库的并行复制方式)和LOGICAL_CLOCK(基于组提交的并行复制方式)。参数slave_parallel_workers设置并行执行的worker线程数。在从服务器上配置slave-parallel-type=LOGICAL_CLOCK且slave_parallel_workers大于1就可以开启并行复制了。
并行复制可以大幅度降低主从延迟。但并不是slave_parallel_workers越大越好,slave_parallel_workers过大和过小,都可能带来负面性能影响,比如引起coordinator线程的判断、分发等开销增加。因此需要因地制宜。
server_id必须是唯一的,值在1到2^32-1之间。
master-info-repository参数值决定从服务器如何存储主服务器相关的复制状态。master-info-repository=file时,会在从服务器data目录下生成master.info 文件,如果master-info-repository=table,信息就会存在从服务器的mysql.slave_master_info表中。不要移动或者编辑相关的文件和表,想要更改配置通过再次执行change master to 语句,变更会自动保存到相关的文件和表。
mysql.slave_relay_log_info表中。
relay_log_recovery表示当中继日志损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的中继日志,并且重新从主服务器上获取,这样就保证了中继日志的完整性。默认未开启。
replicate_ignore_db参数可以将不复制的默认数据库排除在外,replicate_do_db恰恰相反,它是只复制指定的默认数据库。默认数据库就是use参数指定的数据库。因此这两个参数跨库会有问题,比如replicate_ignore_db=db1或者replicate_do_db=db2,先use db1,再update db2.table1...,那么update db2.table1...会被忽略。
skip-slave-start能防止复制进程随着从服务器的启动而启动。
配置
主服务器配置
[mysqld]
server_id=1
log_bin
从服务器配置
[mysqld]
server_id=2
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=8
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON
replicate_do_db=db1
replicate_do_db=db2
skip-slave-start
在主服务器上创建拥有复制权限的用户
CREATE USER 'slave1'@'192.168.22.133' IDENTIFIED BY 'slave1'
GRANT REPLICATION SLAVE ON *.* TO 'slave1'@'192.168.22.133'
查看主服务器的二进制日志文件名和下一次复制起始位置
FLUSH TABLES;
SHOW MASTER STATUS;
File Position
localhost-bin.000001 297
首先手动将主数据库的数据库传输到从数据库,要保证开启主从复制时,要复制的数据库的状态和数据在主从服务器上必须完全一致。可以利用mysqldump,假设要同步的数据库有2个,分别是db1和db2,主服务器ip为192.168.22.1,从数据库ip为192.168.22.133,端口是3306,执行以下命令将db1和db2传输到从服务器,mysqldump -h 192.168.22.1 -u root -p --databases db1 | mysql -h 192.168.22.133 -u root -p。当然也可以利用其他备份方式。
在从服务器上设置主服务器连接和复制信息
CHANGE MASTER TO
-- 主服务器ip
MASTER_HOST = '192.168.22.1',
-- 主服务器端口
MASTER_PORT = 3306,
-- 主服务器拥有复制权限的用户
MASTER_USER = 'slave1',
-- 用户密码
MASTER_PASSWORD = 'slave1',
-- 主服务器二进制日志文件名
MASTER_LOG_FILE = 'localhost-bin.000001',
-- 主服务器二进制日志下一次复制起始位置
MASTER_LOG_POS = 297;
从服务器启动复制程序
START SLAVE;
从服务器关闭复制程序
STOP SLAVE;
查看从服务器状态
SHOW PROCESSLIST;
SHOW SLAVE STATUS;
删除从服务器
stop slave;
reset slave all;