MySQL复制技术

南笙酒味 提交于 2020-03-02 21:50:08


在这里插入图片描述

原理

复制原理

  1. mster的I/O线程会将DML等语句写入binlog中。
  2. slave的I/O线程会请求master的log dump线程,将读取到的binlog的文件名和位置记录到master-info文件中,以便下次向master直接要该位置后的数据,并将binlog写入relay log。
  3. 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:

  1. 启用binlog
  2. 配置server-id
  3. 创建slave账号

slave:

  1. 启用relay log
  2. 配置server-id
  3. 使用slave账号

同步过滤

两种方法:

  1. master
binlog_do_db=			# 数据库白名单,会写入binlog
binlog_ignore_db=		# 数据库黑名单,不会写入binlog
  1. 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

  1. 添加配置
#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
  1. 创建授权账号
#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;
  1. 使用授权账号
#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
  1. 主从确认
#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

  1. 添加配置
#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
  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;
  1. 使用授权账号
#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
  1. 主从确认
#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,并跟踪其位置,实现从服务器多主,而主之间未互为复制时针对每个域的不同位置开始复制。

工作原理

  1. master提交一个事务,产生GTID,同时记录到binlog中。

  2. binlog传输到slave,并转存到relay-log,slave sql线程读取这个gtid并设置gtid_next变量,表示下一个要执行的gtid。

  3. 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使用

  1. 配置文件
主
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日志
  1. 配置命令
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

  1. 添加配置
#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
  1. 授权账号
MariaDB [(none)]> grant replication slave, replication client on *.* to 'slave_1'@'10.10.10.%' identified by '123';
  1. 确定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                                    |
+--------------------------------------------+
  1. 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配置:

  1. 添加配置
#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
  1. 添加授权帐号
#master1 and master2
grant replication slave, replication client on *.* to 'slave'@'10.10.10.%' identified by '123';
  1. 授权同步配置
  • 查看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配置:

  1. 配置文件
#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
  1. 同步数据
  • 双主服务器已经启动,现在上面的数据是一直的,我们可以选取任一服务器进行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
  1. 授权同步配置
  • 使用双主时建好的授权用户
#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;

在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!