- MySQL之间数据复制的基础是二进制日志文件(binary log file)。一台MySQL数据库一旦启用二进制日志后,其作为master,它的数据库中所有操作都会以“事件”的方式记录在二进制日志中,其他数据库作为slave通过一个I/O线程与主服务器保持通信,并监控master的二进制日志文件的变化,如果发现master二进制日志文件发生变化,则会把变化复制到自己的中继日志中,然后slave的一个SQL线程会把相关的“事件”执行到自己的数据库中,以此实现从数据库和主数据库的一致性,也就实现了主从复制。
rhel6.5系统
master:172.25.25.5
slave:172.25.25.6
mysql 版本:5.7.17-1.el6.x86_64
在master与slave节点都进行数据库的安装
[root@server5 mnt]# vim /etc/my.cnf
内容如下:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
server-id=1 # 必须为 1 到 232–1 之间的一个正整数值
log-bin=mysql-bin # 启动二进制日志系统
# binlog-do-db=""
# 二进制需要同步的数据库名,如果需要同步多个库,例如要再同步 halo库,再添加一行“binlog-do-db=halo”,以此类推
# binlog-ignore-db="" # 禁止同步的数据库
编辑完成重启服务
[root@server5 mnt]# /etc/init.d/mysqld restart
创建授权用户并查看master状态
登录数据库,并进行如下操作:
mysql> grant replication slave on *.* to bleach@'172.25.25.%' identified by 'Redhat_123';
# 建立授权用户
mysql> Flush privileges;
mysql> show master status;
# 查看master状态
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 1157 | | | |
+------------------+----------+--------------+------------------+-------------------+
记住file 与 position,再对slave进行操作时需要用到
[root@server6 ~]# vim /etc/my.cnf
添加如下内容即可:
server-id=2
添加完成重启服务
为slave添加master
登录数据库后执行如下:
mysql> change master to master_host='172.25.25.5',
> master_user='bleach', # 授权用户
> master_password='Redhat_123', # 授权用户的密码
> master_log_file='mysql-bin.000003', # master的二进制文件
> master_log_pos=1157;
mysql> start slave; # 启动slave
mysql> show slave status\G # 查看slave状态
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.25.25.5
Master_User: bleach
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 1157
Relay_Log_File: server6-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes # yes 表示连接上
Slave_SQL_Running: Yes # yes 表示连接上
slave上要开启read_only,只读,不然可能会因为不小心的操作导致数据不一致以及主从复制出现问题
这样最简单的mysql AB 主从复制就建立成功
在主库进行新建数据库与表的操作,可在从库中看到相同的信息
master 下执行:
mysql> create database test;
- GTID即全局事务ID(global transaction identifier),GTID实际上是由UUID+TID组成的。其中UUID是一个MySQL实例的唯一标识。TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增,所以GTID能够保证每个MySQL实例事务的执行(不会重复执行同一个事务,并且会补全没有执行的事务)。下面是一个GTID的具体形式:
4e659069-3cd8-11e5-9a49-001c4270714e:1-77
通过GTID来进行主从复制,不用进行二进制日志与master POS号的设定
基本环境与上述AB式复制相同,需要全新的实验环境
master:server5:172.25.25.5
slave:server6:172.25.25.6
修改配置文件,添加GTID相关参数
[root@server5 mnt]# vim /etc/my.cnf
内容如下:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
server-id=1 # 必须为 1 到 232–1 之间的一个正整数值
log-bin=mysql-bin # 启动二进制日志系统
gtid-mode=on # 开启GTID模式
enforce-gtid-consistency=1
在数据库中执行如下操作:
mysql> grant replication slave on *.* to bleach@'172.25.25.%' identified by 'Redhat_123';
Query OK, 0 rows affected, 1 warning (0.37 sec)
mysql> Flush privileges;
Query OK, 0 rows affected (0.13 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+------------------------------------------+
| mysql-bin.000004 | 601 | | | 005dab91-9ef4-11e8-8771-5254004e671f:1-2 |
+------------------+----------+--------------+------------------+------------------------------------------+
1 row in set (0.00 sec)
启用GTID
[root@server6 mysql]# vim /etc/my.cnf
编辑内容如下:
server-id=2
gtid-mode=on
enforce-gtid-consistency=1
在slave中进行如下操作
mysql> change master to master_host='172.25.25.5',master_user='bleach',master_password='Redhat_123',master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.57 sec)
mysql> start slave;
Query OK, 0 rows affected (0.03 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.25.25.5
Master_User: bleach
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 601
Relay_Log_File: server6-relay-bin.000002
Relay_Log_Pos: 814
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
....................省略.....................
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: 005dab91-9ef4-11e8-8771-5254004e671f:1-2
Executed_Gtid_Set: 005dab91-9ef4-11e8-8771-5254004e671f:1-2
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
- 一般主从复制,有三个线程参与,都是单线程:Binlog Dump(主) —–>IO Thread (从) —–> SQL Thread(从)。复制出现延迟一般出在两个地方
1)SQL线程忙不过来(可能需要应用数据量较大,可能和从库本身的一些操作有锁和资源的冲突;主库可以并发写,SQL线程不可以;主要原因)
2)网络抖动导致IO线程复制延迟(次要原因)。
MySQL从5.6开始有了SQL Thread多个的概念,可以并发还原数据,即并行复制技术。- MySQL5.6中,设置参数slave_parallel_workers=4(>1),即可有4个SQL Thread(coordinator线程)来进行并行复制,其状态为:Waiting for an evant from Coordinator。
但是其并行只是基于Schema的,也就是基于库的。如果数据库实例中存在多个Schema,这样设置对于Slave复制的速度可以有比较大的提升。通常情况下单库多表是更常见的一种情形,
那基于库的并发就没有卵用。其核心思想是:不同schema下的表并发提交时的数据不会相互影响,即slave节点可以用对relay log中不同的schema各分配一个类似SQL功能的线程,
来重放relay log中主库已经提交的事务,保持数据与主库一致。
在MySQL 5.7中,引入了基于组提交的并行复制(Enhanced Multi-threaded Slaves),设置参数slave_parallel_workers>0并且global.slave_parallel_type=‘LOGICAL_CLOCK’,即可支持一个schema下,slave_parallel_workers个的worker线程并发执行relay log中主库提交的事务。其核心思想:一个组提交的事务都是可以并行回放(配合binary log group commit);
slave机器的relay log中 last_committed相同的事务(sequence_num不同)可以并发执行。
其中,变量slave-parallel-type可以有两个值:DATABASE 默认值,基于库的并行复制方式;LOGICAL_CLOCK:基于组提交的并行复制方式
MySQL 5.7开启Enhanced Multi-Threaded Slave配置:
slave配置文件中添加如下内容:
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON
只需要在slave下进行操作
具体操作如下:
编辑slave数据库的配置文件,添加内容
[root@server6 mysql]# vim /etc/my.cnf
#
server-id=2
gtid-mode=on
enforce-gtid-consistency=1
slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON
- master_info_repository解释
开启MTS功能后,务必将参数master_info_repostitory设置为TABLE,这样性能可以有50%~80%的提升。这是因为并行复制开启后对于元master.info这个文件的更新将会大幅提升,资源的竞争也会变大。在之前InnoSQL的版本中,添加了参数来控制刷新master.info这个文件的频率,甚至可以不刷新这个文件。因为刷新这个文件是没有必要的,即根据master-info.log这个文件恢复本身就是不可靠的。在MySQL 5.7中,I可以将master_info_repository设置为TABLE,来减小这部分的开销。- slave_parallel_workers解释
若将slave_parallel_workers设置为0,则MySQL 5.7退化为原单线程复制,但将slave_parallel_workers设置为1,则SQL线程功能转化为coordinator线程,但是只有1个worker线程进行回放,也是单线程复制。然而,这两种性能却又有一些的区别,因为多了一次coordinator线程的转发,因此slave_parallel_workers=1的性能反而比0还要差
mysql> show processlist;
与修改前进行比较
结果增加了16条,就是配置slave-parallel-workers=16的作用,也就是开启了并行复制的结果。
- 半同步复制的原理
1、当Slave主机连接到Master时,能够查看其是否处于半同步复制的机制。
2、当Master上开启半同步复制的功能时,至少应该有一个Slave开启其功能。此时,一个线程在Master上提交事务将受到阻塞,直到得知一个已开启半同步复制功能的Slave已收到此事务的所有事件,或等待超时。
3、当一个事务的事件都已写入其relay-log中且已刷新到磁盘上,Slave才会告知已收到。
4、如果等待超时,也就是Master没被告知已收到,此时Master会自动转换为异步复制的机制。当至少一个半同步的Slave赶上了,Master与其Slave自动转换为半同步复制的机制。
5、半同步复制的功能要在Master,Slave都开启,半同步复制才会起作用;否则,只开启一边,它依然为异步复制。- 同步,异步,半同步复制的对比
- 同步复制:Master提交事务,直到事务在所有的Slave都已提交,此时才会返回客户端,事务执行完毕。缺点:完成一个事务可能会有很大的延迟。
- 异步复制:当Slave准备好才会向Master请求binlog。缺点:不能保证一些事件都能够被所有的Slave所接收。
- 半同步复制:半同步复制工作的机制处于同步和异步之间,Master的事务提交阻塞,只要一个Slave已收到该事务的事件且已记录。它不会等待所有的Slave都告知已收到,且它只是接收,并不用等其完全执行且提交。
进行半同步操作
环境与上述并行复制相同
mysql> show variables like ‘have_dynamic_loading’;
#确保value为YES
安装,模块,开启半同步
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.10 sec)
mysql> set global rpl_semi_sync_master_enabled=ON;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like '%semi%';
+-------------------------------------------+------------+
| Variable_name | Value |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled | ON |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_for_slave_count | 1 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_SYNC |
+-------------------------------------------+------------+
6 rows in set (0.00 sec)
进行插件安装
mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.08 sec)
mysql> set global rpl_semi_sync_slave_enabled=ON;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like '%semi%';
+---------------------------------+-------+
| Variable_name | Value |
+---------------------------------+-------+
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
+---------------------------------+-------+
2 rows in set (0.00 sec)
mysql> show status like '%rpl_semi_sync%';