基于二进制日志的复制
配置
主:
#复制的各个服务器上不允许相同
server_id=1
#该值将用作日志序列的基本名称。服务器通过在基本名称中添加数字后缀来依次创建二进制日志文件
log-bin=master_bin
#在复制中获得最大的一致性
sync_binlog=1
#在复制中获得最大的持久性
innodb_flush_log_at_trx_commit=1
复制I/O线程在将每个接收到的事务写入磁盘后将中继日志同步到磁盘值1是最安全的选择,因为在意外停止的情况下,您最多会从中继日志中丢失一个事件。但是,它也是最慢的选择
sync_relay_log=1
binlog_format =ROW
binlog_row_image=minimal
副本:
server_id=2
#副本不需要启用二进制日志记录就可以进行复制。但是,副本上的二进制日志记录意味着副本的二进制日志可用于数据备份和崩溃恢复
log-bin=slave1_bin
//从主库读取的事件会记录到二进制日志中,但是如果从库要作为源使用,那么将不能启用
log_slave_updates=on
#设置复制元数据库存储在为mysql.slave_master_info表中,即使服务器意外中断,副本的进度信息始终与已应用于数据库的信息一致
master_info_repository=TABLE
relay_log_info_repository=TABLE
#设置只读,防止副本进行意外的更改
super_read_only=on
//并行复制,解决复制延迟问题
slave-parallel-type=LOGICAL_CLOCK
执行复制事务的应用程序线程数
slave-parallel-workers=16
relay_log_recovery=ON
//设置中继日志文件和索引文件的路径和名称
relay_log = /var/log/relaylog/host_name-relay-bin
relay_log_index=/var/log/relaylog/*host_name*-relay-bin.index
//每个通道都会自动清除其自己的中继日志
relay_log_purge=on
//中继日志的大小,超过此将关闭当前日志,并重新打开一个新的日志,默认值0,允许4096B-1G和0,不能超过max_binlog_size的值
max-relay-log-size = 100M
执行命令
主:
创建用户:复制用户仅需要REPLICATION SLAVE权限
mysql> CREATE USER 'repl'@'%.example.com' IDENTIFIED BY 'password';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%.example.com';
获取二进制日志坐标:
刷新所有表并阻止写入语句:
mysql> FLUSH TABLES WITH READ LOCK;
在源上的另一个会话中,使用该SHOW MASTER STATUS语句确定当前二进制日志文件的名称和位置:
mysql > SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 | 73 | test | manual,mysql |
+------------------+----------+--------------+------------------+
副本:
配置连接到主服务器的信息
mysql> CHANGE MASTER TO
-> MASTER_HOST='source_host_name',
-> MASTER_USER='replication_user_name',
-> MASTER_PASSWORD='replication_password',
-> MASTER_LOG_FILE='recorded_log_file_name',
-> MASTER_LOG_POS=recorded_log_position;
从源扩展增加副本
将源上的数据复制到副本中,减少启动副本时获取源历史数据时间过长的问题
方法1:
使用mysqldump --master-data转储源服务器,--master-data将导出副本配置主服务器需要的信息
mysqldump -u root -p --all-databases --master-data > dbdump.sql
在副本中导入转储文件
shell> mysql -u root -p < dbdump.sql
查看dbdump.sql中CHANGE MASTER TO的信息,然后配置副本
mysql> CHANGE MASTER TO
-> MASTER_HOST='source_host_name',
-> MASTER_USER='replication_user_name',
-> MASTER_PASSWORD='replication_password',
-> MASTER_LOG_FILE='recorded_log_file_name',
-> MASTER_LOG_POS=recorded_log_position;
方法2:
获取读锁并获取源的状态,刷新所有表并阻止写入语句
mysql> FLUSH TABLES WITH READ LOCK;
在源上的另一个会话中,使用该 SHOW MASTER STATUS语句确定当前二进制日志文件的名称和位置:
mysql > SHOW MASTER STATUS;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000003 | 73 | test | manual,mysql |
+------------------+----------+--------------+------------------+
在另一个会话中,关闭源服务器:
shell> mysqladmin -u root -p shutdown
打包MySQL数据文件。以下示例显示了执行此操作的常用方法。您只需要选择其中之一:
shell> tar cf /tmp/db.tar ./data
shell> zip -r /tmp/db.zip ./data
shell> rsync --recursive ./data /tmp/dbdatas
重新启动源服务器。将文件复制到副本中(复制后设置文件权限,以使副本可以访问和修改)(从副本上的数据目录中删除auto.cnf文件,以便使其生成的新的服务器UUID启动副本。因为服务器UUID必须是唯一的)
在副本上配置源服务器:
使用--skip-slave-start选项启动副本
mysqld --skip-slave-start --user=mysql
配置源服务器
CHANGE MASTER TO
-> MASTER_HOST='source_host_name',
-> MASTER_USER='replication_user_name',
-> MASTER_PASSWORD='replication_password',
-> MASTER_LOG_FILE='recorded_log_file_name',
-> MASTER_LOG_POS=recorded_log_position;
启动复制线程:
mysql> START SLAVE;
从现有副本扩展新副本
停止现有副本并记录副本状态信息,尤其是源的二进制日志文件和中继日志文件的位置。(不需要停止源)
mysql> STOP SLAVE;
mysql> SHOW SLAVE STATUS\G
关闭现有副本:
shell> mysqladmin shutdown
将数据目录从现有副本复制到新副本,包括日志文件和中继日志文件。(复制之前,确保现有副本相关的所有文件是否实际存储在数据目录中。复制后,从新副本上的数据目录的副本中删除auto.cnf文件,以便使其他生成新的服务器UUID启动新副本。服务器UUID必须是唯一的)
复制完成后,重新启动现有副本
在新副本上,编辑配置,并为新副本提供一个源服务器或任何现有副本未使用的唯一服务器ID(server_id)。
使用--skip-slave-start选项启动新副本,使复制不自动启用。确认新副本与现有副本一样具有正确的设置。并验证服务器ID和服务器UUID对于新副本正确且唯一
SHOW SLAVE STATUS
启动复制:
mysql> START SLAVE;
基于GTID复制
配置
主:
server_id=1
log-bin=master_bin
gtid_mode=ON
enforce-gtid-consistency=ON
sync_binlog=1
innodb_flush_log_at_trx_commit=1
sync_relay_log=1
binlog_format =ROW
binlog_row_image=minimal
副本:
server_id=2
log-bin=slave1_bin
log_slave_updates=on
master_info_repository=TABLE
relay_log_info_repository=TABLE
gtid_mode=ON
enforce-gtid-consistency=ON
relay_log_purge=on
max-relay-log-size = 100M
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
relay_log_recovery=ON
执行命令
主:
创建用户:复制用户仅需要REPLICATION SLAVE权限
mysql> CREATE USER 'repl'@'%.example.com' IDENTIFIED BY 'password';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%.example.com';
副本:
配置连接到主服务器的信息
指定副本将源用作复制数据源并使用自动定位。告诉副本使用基于GTID的事务的源作为复制数据源。
mysql> CHANGE MASTER TO
> MASTER_HOST = host,
> MASTER_PORT = port,
> MASTER_USER = user,
> MASTER_PASSWORD = password,
> MASTER_AUTO_POSITION = 1;
start slave;
扩展副本
简单复制:在新服务器上启用GTID,并配置指定源服务器,等待副本追赶上源的数据,会花费较长的时间
将源数据和事务复制到副本:只需要相对较少的时间副本即可赶上源
方法1、mysqldump --set-gtid-purged=auto|on 以在转储中包含关于已执行事务的信息。然后在副本上导入转储文件。
方法2、打包MySQL数据文件复制到副本
方法3、使用mysqlbinlog--read-from-remote-server --read-from-remote-master从源服务器获取二进制导入到新副本。
方法4、将源服务器的二进制日志文件复制到副本,使用mysqlbinlog --read-from-remote-server --raw从副本中复制副本,使用mysqlbinlog将这些文件读入到副本中以将二进制日志文件导出为SQL文件,然后将这些文件传递给mysql客户端进行处理
shell> mysqlbinlog copied-binlog.000001 copied-binlog.000002 | mysql -u root -p
如果源服务器在其二进制日志中具有完整的事务历史记录(即GTID集 @@GLOBAL.gtid_purged为空),则可以使用这些方法3和4
半同步复制
配置
需要在上述的配置
主:
加载插件
plugin-load=rpl_semi_sync_master=semisync_master.so
在源上启用半同步复制,1启用 0禁用,默认值为0
rpl_semi_sync_master_enabled=1
控制源在超时并恢复为异步复制之前等待复制副本提交确认的等待时间。默认值为10000毫秒(10秒)
rpl_semi_sync_master_timeout=10000
配置源返回到会话之前,每个事务必须收到的副本确认的数量,默认值为1
rpl_semi_sync_master_wait_for_slave_count=1
副本:
加载插件
plugin-load=rpl_semi_sync_slave=semisync_slave.so
在副本上启用半同步复制,1启用 0禁用,默认值为0(关闭)
rpl_semi_sync_slave_enabled=1
执行命令
主:
安装半同步插件,当没有在配置文件中加载插件时使用
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
副本
安装半同步插件
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
在副本运行时配置半同步复制,那么执行
STOP SLAVE IO_THREAD;
SET GLOBAL rpl_semi_sync_slave_enabled = 1;
START SLAVE IO_THREAD;
验证插件是否安装成功
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';
+----------------------+---------------+
| PLUGIN_NAME | PLUGIN_STATUS |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE |
+----------------------+---------------+
如果安装插件时提示此类错误,则必须安装libimf
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
ERROR 1126 (HY000): Can't open shared library
'/usr/local/mysql/lib/plugin/semisync_master.so'
(errno: 22 libimf.so: cannot open shared object file:
No such file or directory)
监控
状态监控
查看半同步副本的数量
show status like 'Rpl_semi_sync_master_clients';
半同步复制当前是否可在源上运行。如果已启用插件并且未发生提交确认,则该值为1。如果未启用插件或源由于提交确认超时而退回到异步复制,则为0。
show status like 'Rpl_semi_sync_master_status';
副本未成功确认的提交数
show status like 'Rpl_semi_sync_master_no_tx';
副本成功确认的提交数。
show status like 'Rpl_semi_sync_master_yes_tx';
半同步复制当前是否可在副本上运行。如果已启用插件并且复制I / O线程正在运行,则为1,否则为0。
show status like 'Rpl_semi_sync_slave_status';
查看半同步复制的操作,主副服务器上不相同
SHOW STATUS LIKE 'Rpl_semi_sync%';
变量监控
反应半同步复制的配置,主副服务器上不相同
SHOW VARIABLES LIKE 'rpl_semi_sync%';
延迟复制
配置
使副本服务器有意地在源后面至少延迟指定的时间
CHANGE MASTER TO MASTER_DELAY = N;
查询状态
SHOW SLAVE STATUS
SQL_Delay:一个非负整数,指示副本必须滞后于源的秒数。
SQL_Remaining_Delay:如果此字段包含一个整数,指示延迟剩余的秒数。在其他时间,此字段为NULL。
Slave_SQL_Running_State:指示SQL线程的状态(类似于 Slave_IO_State)。
多源复制
基于GTID的多源副本
将现有数据复制到副本中:
转储db1上source1和数据库db2上 source2的转储:
mysqldump -u<user> -p<password> --single-transaction --triggers --routines --set-gtid-purged=ON --databases db1 > dumpM1.sql
mysqldump -u<user> -p<password> --single-transaction --triggers --routines --set-gtid-purged=ON --databases db2 > dumpM2.sql
记录下每个转储文件的gtid_purged值。例如,对于在MySQL 5.6或5.7上创建的转储文件,可以提取如下值:
cat dumpM1.sql | grep GTID_PURGED | cut -f2 -d'=' | cut -f2 -d$'\''
cat dumpM2.sql | grep GTID_PURGED | cut -f2 -d'=' | cut -f2 -d$'\''
source1: 2174B383-5441-11E8-B90A-C80AA9429562:1-1029
source2: 224DA167-0C0C-11E8-8442-00059A3C7B00:1-2695
从每个转储文件中将包含SET @@GLOBAL.gtid_purged语句删除 。
sed '/GTID_PURGED/d' dumpM1.sql > dumpM1_nopurge.sql
sed '/GTID_PURGED/d' dumpM2.sql > dumpM2_nopurge.sql
使用mysql客户端将每个已编辑的转储文件导入副本。例如:
mysql -u<user> -p<password> < dumpM1_nopurge.sql
mysql -u<user> -p<password> < dumpM2_nopurge.sql
在副本上,发出RESET MASTER清除GTID执行历史记录(如上所述,假定所有转储文件都已导入,并且副本上没有包含GTID的有用事务)。然后发出一条SET @@GLOBAL.gtid_purged语句,将 gtid_purged值设置为所有转储文件中所有GTID集的并集,如您在步骤2中记录的(如果转储文件中GTID集之间存在(或可能存在)重叠事务,则可以使用操作GTID的存储函数预先进行检查并计算所有GTID集。)例如:
mysql> RESET MASTER;
mysql> SET @@GLOBAL.gtid_purged = "2174B383-5441-11E8-B90A-C80AA9429562:1-1029, 224DA167-0C0C-11E8-8442-00059A3C7B00:1-2695";
配置源
mysql> CHANGE MASTER TO MASTER_HOST="source1", MASTER_USER="ted", MASTER_PASSWORD="password", MASTER_AUTO_POSITION=1 FOR CHANNEL "source_1";
mysql> CHANGE MASTER TO MASTER_HOST="source2",MASTER_USER="ted", MASTER_PASSWORD="password", MASTER_AUTO_POSITION=1 FOR CHANNEL "source_2";
基于二进制日志
启动复制
mysql> START SLAVE;
mysql> START SLAVE FOR CHANNEL "source_1";
mysql> START SLAVE FOR CHANNEL "source_2";
查看副本的状态
mysql> SHOW SLAVE STATUS\G
SELECT * FROM performance_schema.replication_connection_status\G
查看副本指定源通道的状态
mysql> SHOW SLAVE STATUS FOR CHANNEL "source_1"\G
SELECT * FROM performance_schema.replication_connection_status WHERE CHANNEL_NAME='source_1'\G
停止副本所有通道
STOP SLAVE;
停止副本指定命名的通道
STOP SLAVE FOR CHANNEL "source_1";
重置副本所有通道
RESET SLAVE;
重置副本指定通道
RESET SLAVE FOR CHANNEL "source_1";
筛选复制
源:
--binlog-do-db和--binlog-ignore-db选项控制写入二进制日志的库和表
副本:
--replicate-*副本启动时决定是执行还是忽略从源接收的语句
CHANGE REPLICATION FILTER决定是执行还是忽略从源接收的语句
将不同数据库复制到不同副本
告诉复制SQL线程将复制限制为其中任何更新的表与指定的数据库和表名称模式匹配的语句,从而创建复制筛选器。模式可以包含% 和_通配符,其含义与LIKE 模式匹配运算符相同。要指定多个表,请多次使用此选项,每个表一次。通配符需要用\转义
--replicate-wild-do-table=db_name.tbl_name
或
CHANGE REPLICATION FILTER REPLICATE_WILD_DO_TABLE = ('db1.new%', 'db2.new%');
创建一个复制过滤器,以防止复制SQL线程复制任何表与给定通配符模式匹配的语句。要指定多个要忽略的表,请多次使用此选项,每个表一次。
--replicate-wild-ignore-table=db_name.tbl_name
或
CHANGE REPLICATION FILTER REPLICATE_WILD_IGNORE_TABLE = ('db1.new%', 'db2.new%');