
原理
复制原理
- mster的I/O线程会将DML等语句写入binlog中。
- slave的I/O线程会请求master的log dump线程,将读取到的binlog的文件名和位置记录到master-info文件中,以便下次向master直接要该位置后的数据,并将binlog写入relay log。
- slave的SQL线程会定时检查relay log,完成更新。
复制技术
-
异步复制
master提交事务后,通知dump线程将bonlog发送slave的I/O线程,然后master就继续处理事务,不等待slvaer服务器同步是否完成。 -
半同步复制
master提交事务后,通知dump线程将bonlog发送slave的I/O线程,至少一个slave将binlog写入到relay log后,mater才能继续处理事务。相当于给一个slave同步,其他slave异步。 -
同步复制
master提交事务后,通知dump线程将bonlog发送slave的I/O线程,当所有从库都同步完成该事务后,mater才能继续处理事务。
复制中,异步master不用等待slave同步反馈,所以性能最高,但可靠性最低;同步master必须等待全部slave同步反馈,所以性能最低,但可靠性最高;而半同步,在数据安全上我们确认slave至少有一台同步完成,在速度方面也是折中,所以性能和可靠都居中。
配置
配置过程
master:
- 启用binlog
- 配置server-id
- 创建slave账号
slave:
- 启用relay log
- 配置server-id
- 使用slave账号
同步过滤
两种方法:
- master
binlog_do_db= # 数据库白名单,会写入binlog
binlog_ignore_db= # 数据库黑名单,不会写入binlog
- slave
经过测试不好用,建议不使用
Replicate_Do_DB= # 复制DB白名单
Replicate_Ignore_DB= # 复制DB黑名单
Replicate_Do_Table= # 复制Table白名单
Replicate_Ignore_Table= # 复制Table黑名单
Replicate_Wild_Do_Table= # 复制Table白名单,支持通配符
Replicate_Wild_Ignore_Table= # 复制Table黑名单,支持通配符
相关文件
#slave
master.info #记录slave和master的连接信息
relay-log.info #保存复制的binlog和本地的relay log的对应关系
如果在slvae的配置文件加上下面两个选项,则信息记录到表中去非文件
master-info-repository=table
relay-log-info-repository=table
监控维护
- 复制监控
#master
show master status
show binlog events
show binary logs
#slave
show slaver status
- 清理日志
#bin-log
purge binary logs to 'binlog_file'
purge binary logs before 'datetime'
expire_logs_days=n #自动清理
#relay-log
relay_log_purge=on #自动清理
实验
实验环境
- 服务器,两主两从
10.10.10.10 master_1
10.10.10.11 master_2
10.10.10.20 slaver_1
10.10.10.21 slaver_2
M-S
- 添加配置
#master_1
[mysqld]
server-id=10
log-bin=/var/lib/mysql/master_1_bin
expire_logs_days=10
binlog_do_db=cr
binlog_ignore_db=mysql
#slavr_1
server-id=20
relay-log=/var/lib/mysql/slaver_1_relay
read-only=on
- 创建授权账号
#start master_1
[root@master_1 ~]# systemctl start mariadb
#master_1
MariaDB [(none)]> grant replication slave,replication client on *.* to "slave"@"10.10.10.%" identified by "123";
MariaDB [(none)]> flush privileges;
- 使用授权账号
#start slaver_1
[root@slaver_1 ~]# systemctl start mariadb
#配置slvaer_1
change master to master_host='master_1',master_user='slave',master_password='123',master_log_file='master_1_bin.000002', master_log_pos=647;
#启动slaver_1
MariaDB [(none)]> start slave
- 主从确认
#slaver_1
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
- 其他说明
如果主服务器事前运行一段时间有大量数据,这里我们可以使用mysqldump导入slaver,利用master-data=1选项获取binlog文件和位置,如下语句:
CHANGE MASTER TO MASTER_LOG_FILE='master_1_bin.000002', MASTER_LOG_POS=740;
[root@master_2 ~]# echo "set sql_log_bin=off;source /root/b.sql;change master to master_host='master_1',master_user='master_2',master_password='123'" | mysql -uroot -p
MariaDB [(none)]> change master to master_host='master_1',master_user='master_2',master_password='123';
MariaDB [(none)]> start slave;
M-M
- 添加配置
#master_1
[mysqld]
server-id=10
log-bin=/var/lib/mysql/master_1_bin
expire_logs_days=10
binlog_do_db=cr
binlog_ignore_db=mysql
relay-log=/var/lib/mysql/relay_1_relay
log-slave-updates=1
#master_2
server-id=20
log-bin=/var/lib/mysql/master_2_bin
expire_logs_days=10
binlog_do_db=cr
binlog_ignore_db=mysql
relay-log=/var/lib/mysql/master_2_relay
log-slave-updates=1
- 创建授权账号
#master_1
[root@master_1 ~]# systemctl start mariadb
MariaDB [(none)]> grant replication slave,replication client on *.* to "master_2"@"10.10.10.%" identified by "123";
MariaDB [(none)]> flush privileges;
#master_2
[root@master_2 ~]# systemctl start mariadb
MariaDB [(none)]> grant replication slave,replication client on *.* to "master_1"@"10.10.10.%" identified by "123";
MariaDB [(none)]> flush privileges;
- 使用授权账号
#master_1
[root@slaver_1 ~]# systemctl start mariadb
change master to master_host='master_1',master_user='master_2',master_password='123';
MariaDB [(none)]> start slave
#master_2
[root@slaver_1 ~]# systemctl start mariadb
change master to master_host='master_2',master_user='master_1',master_password='123';
MariaDB [(none)]> start slave
- 主从确认
#master_1
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
#master_2
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
GTID
GTID
- mysql的GTID
GTID=server_uuid:transaction_id
server_uuid: #mysql实例唯一标识
transaction_id: #已提交的事务数量,递增
- mariadb的GTID
GTID=domain ID:server ID:Sequence Number
domain ID: #域id
server ID: #服务id
Sequence Number: #序列号
GTID好处
- 易于更改从服务器连接其他主服务器并从其复制
从服务器记录从旧主服务器的最后一个时间组的全局事务ID。由于全局事物ID在整个复制组中已知,因此从服务器知道在新主服务器何处恢复复制。使用旧式复制,从服务器只知道住服务器最后一次binlog的名字和偏移量,是没有办法确定在新主服务器何处开始复制。 - 以碰撞安全方式记录从站状态
从服务器全局变量gtid_slave_pos记录当前位置。主服务器传送过来的binlog中包含gtid_slave_pos和日志内容,即从服务器复制状态信息和数据信息是在同一事物中完成,这使状态崩溃安全。旧式复制,将状态信息记录在relay-log.info中,与数据相互独立,如果从服务器崩溃,状态信息和数据信息容易失去同步。
domain ID
-
据我理解类似与ospf设置区域。
-
适用于多源复制、多主环形拓扑或手动更新。可能会发生这种情况,多主之间未相互同步状态,导致从服务器与多个主服务器的binlog顺序不同,使用单个GTID是无法完全记录当前状态。
-
域ID是GTID的第一个组件,用于处理此问题。
-
二进制日志从多个主服务器过来,组成多个不同的流,每个流使用域ID标识自己。从服务器记录每个流的最后一个GTID,并跟踪其位置,实现从服务器多主,而主之间未互为复制时针对每个域的不同位置开始复制。
工作原理
-
master提交一个事务,产生GTID,同时记录到binlog中。
-
binlog传输到slave,并转存到relay-log,slave sql线程读取这个gtid并设置gtid_next变量,表示下一个要执行的gtid。
-
slave 读取到gtid首先对比slave的bin-log是否有该gtid,有表示执行过则忽略,无则判断其他session是否持有该gtid,有则避免重复执行,无则执行。
自动同步
- ABC三主机,A主BC从,当A主机宕机后,B主机升主,BC怎么确定bin-log文件和位置。当B升主,C连接到B,找到由A发来的最新gtid发送给B,B就从该gtid的下个gtid开始发送事务给C。
GTID使用
- 配置文件
主
server-id=n #server_id
log-bin='/path/filename' #bin-log日志
log_slave_updates=on #记录由replication机制sql线程读取,relay-log执行的sql语句记录到bin-log中
#由于binlog的产生会让从服务器复制数据,所以从服务器会多次复制一个事务。
从
server-id=n #server_id
relay-log='/path/filename' #relay-log日志
- 配置命令
CHANGE MASTER TO master_use_gtid = { slave_pos | current_pos | no }
slave_pos:服务器作为从服务器relay-log的的gtid
current_pos:服务器本地bin-log的gtid
no:不使用gtid,如果未显示关闭gtid,手动指定master_log_file和master_log_pos,依旧使用gtid
-
如果一个主服务器变为从服务器 master_use_gtid=current_pos;current_pos记录了服务器当前的最新状态,当他作为从服务器便以这个位置进行复制。
-
如果一个服务器作为从服务器 master_use_grid=slave_pos;因为当前服务器如果有DML、DDL语句时会改变current_pos,如果使用current_pos则会导致状态不一,应使用slave_pos。
M-S—手动设置gtid
- 添加配置
#mster_1
server-id=10
log-bin=/var/lib/mysql/master_1_bin
expire_logs_days=10
#slave_1
server-id=20
relay-log=/var/lib/mysql/slave_1_relay
- 授权账号
MariaDB [(none)]> grant replication slave, replication client on *.* to 'slave_1'@'10.10.10.%' identified by '123';
- 确定gtid
MariaDB [(none)]> show master status;
+---------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+---------------------+----------+--------------+------------------+
| master_1_bin.000002 | 779 | | |
+---------------------+----------+--------------+------------------+
MariaDB [(none)]> select binlog_gtid_pos('master_1_bin.000002',779); #对应全局变量gtid_binlog_pos
+--------------------------------------------+
| binlog_gtid_pos('master_1_bin.000002',779) |
+--------------------------------------------+
| 0-10-46 |
+--------------------------------------------+
- slave配置
MariaDB [(none)]> set global gtid_slave_pos='0-10-46'
MariaDB [(none)]> change master to master_host='master_1', master_user='slave_1', master_password='123', master_use_gtid=slave_pos;
MariaDB [(none)]> start slave;
MariaDB [(none)]> show slave status \G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: master_1
Master_User: slave_1
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master_1_bin.000002 #bin-log文件
Read_Master_Log_Pos: 779 #bin-log位置
Relay_Log_File: slave_1_relay.000002 #relay-log文件
Relay_Log_Pos: 690 ##relay-log位置
Relay_Master_Log_File: master_1_bin.000002 #中继的日志文件
Slave_IO_Running: Yes #I/O线程
Slave_SQL_Running: Yes #SQL线程
Using_Gtid: Slave_Pos #使用的gtid
Gtid_IO_Pos: 0-10-46 #gtid值
...
M-M-S-S—自动设置gtid
- 10.10.10.10 master1
- 10.10.10.11 slave1
- 10.10.10.20 master2
- 10.10.10.21 slave2
M-M配置:
- 添加配置
#master1
server_id=10
log-bin=master1_bin
expire_logs_days=10
binlog_ignore_db=mysql
binlog_ignore_db=information
relay-log=master1_slave
#master2
server_id=20
log-bin=master2_bin
expire_logs_days=10
binlog_ignore_db=mysql
binlog_ignore_db=information
relay-log=master2_slave
- 添加授权帐号
#master1 and master2
grant replication slave, replication client on *.* to 'slave'@'10.10.10.%' identified by '123';
- 授权同步配置
- 查看current_pos作为为对方的slave_pos。
show variables like '%gtid%';
#master1
set global gtid_slave_pos='0-20-3';
change master to master_host='master2', master_user='slave', master_password='123', master_use_gtid=slave_pos;
start slave;
#master2
set global gtid_slave_pos='0-10-3';
change master to master_host='master1', master_user='slave', master_password='123', master_use_gtid=slave_pos;
start slave;
- 查看gtid的相关变量
M-M-S-S配置:
- 配置文件
#master1
server_id=11
relay_log=slave1_relay
#以下参数选配
master-info-repository=table
relay-log-info-repository=table
log-bin=slave1_bin
log_slave_updates=on
expire_logs_days=10
replicate_ignore_db=mysql
replicate_ignore_db=information
#master2
server_id=21
relay_log=slave2_relay
#以下参数选配
master-info-repository=table
relay-log-info-repository=table
log-bin=slave2_bin
log_slave_updates=on
expire_logs_days=10
replicate_ignore_db=mysql
replicate_ignore_db=information
- 同步数据
- 双主服务器已经启动,现在上面的数据是一直的,我们可以选取任一服务器进行mysqldump备份,恢复数据。
#slave1 and slave2
备份数据
mysqldump --all-databases --single-transaction --master-data=0 --gtid -h'master1' -u'root' -p'123' > `date +%F`.sql
打开备份文件插入
sed -i "1i set sql_log_bin=off;" 2020-03-02.sql #防止恢复数据产生binlog
- 授权同步配置
- 使用双主时建好的授权用户
#slave1 and slave2
恢复数据
mysql < 2020-03-02.sql
添加主服务器
change master to master_host='master1', master_user='slave', master_password='123', master_log_file='master1_bin.000005', master_log_pos=725;
change master to master_host='master2', master_user='slave', master_password='123', master_log_file='master2_bin.000006', master_log_pos=344;
start all slaves;
## start slave 'master1';
## start slave 'master2';
查看是否成功
show slave 'master1'\G;
show slave 'master2'\G;
来源:CSDN
作者:alucardXXOO
链接:https://blog.csdn.net/alucardXXOO/article/details/104479289