介绍:
- 基于GTID的复制是从Mysql5.6开始支持的一种新的复制方式,此方式与传统基于日志的方式存在很大的差异,在原来的基于日志的复制中,从服务器连接到主服务器并告诉主服务器要从哪个二进制日志的偏移量开始执行增量同步,这时我们如果指定的日志偏移量不对,这与可能造成主从数据的不一致,而基于GTID的复制会避免。
- 在基于GTID的复制中,首先从服务器会告诉主服务器已经在从服务器执行完了哪些事务的GTID值,然后主库会有把所有没有在从库上执行的事务,发送到从库上进行执行,并且使用GTID的复制可以保证同一个事务只在指定的从库上执行一次,这样可以避免由于偏移量的问题造成数据不一致。
- 什么是GTID,也就是全局事务ID,其保证为每一个在主上提交的事务在复制集群中可以生成一个唯一的ID。
- 一个GITD由两部分组成的,分别是source_id 和transaction_id,GTID=source_id:transaction_id,其中source_id就是执行事务的主库的server-uuid值,server-uuid值是在mysql服务首次启动生成的,保存在数据库的数据目录中,在数据目录中有一个auto.conf文件,这个文件保存了server-uuid值(唯一的)。而事务ID则是从1开始自增的序列,表示这个事务是在主库上执行的第几个事务,Mysql会保证这个事务和GTID是一比一的关系。
配置主数据库服务器需要做的大概和传统的主从配置差不多,需要起码的在主服务器上建立复制账号,还要配置数据库日志文件的目录,这是必须的启动bin_log日志。
可以指定bin_log存放目录,而不是用数据目录,分开存储是个好习惯,特别是如果把日志和数据放在不同的磁盘分区上,这样不但可以避免日志的增长把数据磁盘分区占满,也可以提高了磁盘IO。如bin_log = /usr/local/mysql/log/mysql-bin。优点
A:很方便的进行故障转移,因为GTID是全局唯一的标识符,所以就很简单知道哪些事务在从服务器没有执行,在多个从服务器也没必要进行多个日志偏移量配置了.B:从库和主库的数据一致性。
缺点
A:故障处理比日志处理复杂。
B:执行语句的一些限制。
Step 1.开始配置GTID主从复制
说明:虚拟机IP:192.168.82.154(Master) 192.168.82.167(Slave)
此操作版本为mysql5.7
1.配置文件 mysql主库
$ vim /etc/my.cnf
server-id=1
log-bin=master-bin
#重启生效
$ service mysqld restart
2.配置数据库(在master创建复制账号)
mysql> grant replication slave on *.* to 'repl'@'192.168.82.167' identified by 'M)OKM*UHB7ygv6';
Query OK, 0 rows affected, 1 warning (0.02 sec)
3.mysq从库配置文件
$ vim /etc/my.cnf
server-id=2
log-bin=slave-bin
4.配置mysql从库
mysql> change master to master_host='192.168.82.154',master_user='repl',master_password='M)OKM*UHB7ygv6',master_log_file='master-bin.000001',master_log_pos=602;
Query OK, 0 rows affected, 2 warnings (0.04 sec)
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.82.154
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000001
Read_Master_Log_Pos: 602
Relay_Log_File: linuxgitlab-relay-bin.000002
Relay_Log_Pos: 321
Relay_Master_Log_File: master-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 602
Relay_Log_Space: 534
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: 5e59ae4e-b380-11e9-a1ae-000c29c8098f
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
ERROR:
No query specified
5.主从同步测试
#master
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| |
+--------------------+
4 rows in set (0.02 sec)
mysql> create database user;
Query OK, 1 row affected (0.01 sec)
#slave
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| sys |
| user |
+--------------------+
5 rows in set (0.02 sec)
Step 2.利用mysql5.7的GTID来实现主从复制
说明:GTID(Global Transaction ID)是对于一个已提交事务的编号,并且是一个全局唯一的编号。它的官方定义如下:GTID = source_id :transaction_id
每一个 GTID 代表一个数据库事务.
1.配置配置文件(/etc/my.cnf)并重启mysql(主都配置一样)
$ vim /etc/my.cnf
gtid_mode=ON
enforce-gtid-consistency=true
#重启
$ service mysqld restart
2.配置从数据库
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
mysql> change master to master_host='192.168.82.154',master_user='repl',master_password='M)OKM*UHB7ygv6',master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.09 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.82.154
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000002
Read_Master_Log_Pos: 154
Relay_Log_File: linuxgitlab-relay-bin.000002
Relay_Log_Pos: 369
Relay_Master_Log_File: master-bin.000002
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 154
Relay_Log_Space: 582
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: 5e59ae4e-b380-11e9-a1ae-000c29c8098f
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 1
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
Step 3.配置多线程同步
Mysql 5.7 对主从复制增加了一种类型,共有两种类型,( 默认是DATABASE)如下:
- DATABASE 基于库的并行复制 , 每个数据库对应一个复制线程
- LOGICAL_CLOCK 基于组提交的并行复制方式,同一个数据库下可以有多个线程
1.当前配置下的主从复制的进程数
说明:可以看到当前只有一个主进程在等待同步
mysql> show processlist;
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| 4 | root | localhost | user | Query | 0 | starting | show processlist |
| 5 | system user | | NULL | Connect | 8725 | Waiting for master to send event | NULL |
| 6 | system user | | NULL | Connect | 1335 | Slave has read all relay log; waiting for more updates | NULL |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
3 rows in set (0.01 sec)
2.查看复制类型和并行数量配置
说明:当前的复制类型是 DATABASE,也就是统一数据库下只有一个线程进行复制,不能并行复制
mysql> show variables like 'slave_parallel_type';
+---------------------+----------+
| Variable_name | Value |
+---------------------+----------+
| slave_parallel_type | DATABASE |
+---------------------+----------+
1 row in set (0.23 sec)
3.查看当前并行工作的进程数
说明:当前并行工作的进程数是 0
mysql> show variables like 'slave_parallel_workers';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| slave_parallel_workers | 0 |
+------------------------+-------+
1 row in set (0.01 sec)
4.配置多线程---操作从库
#停止slave
mysql> stop slave;
Query OK, 0 rows affected (0.06 sec)
#设置复制类型为 LOGICAL_CLOCK
mysql> set global slave_parallel_type='logical_clock';
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'slave_parallel_type';
+---------------------+---------------+
| Variable_name | Value |
+---------------------+---------------+
| slave_parallel_type | LOGICAL_CLOCK |
+---------------------+---------------+
1 row in set (0.03 sec)
#设置并行数量为4
mysql> set global slave_parallel_workers=4;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'slave_parallel_workers';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| slave_parallel_workers | 4 |
+------------------------+-------+
1 row in set (0.02 sec)
#启动从库
mysql> start slave;
Query OK, 0 rows affected (0.15 sec)
#查看一下当前工作的线程数
mysql> show processlist;
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| 4 | root | localhost | user | Query | 0 | starting | show processlist |
| 7 | system user | | NULL | Connect | 9 | Waiting for master to send event | NULL |
| 8 | system user | | NULL | Connect | 9 | Slave has read all relay log; waiting for more updates | NULL |
| 9 | system user | | NULL | Connect | 9 | Waiting for an event from Coordinator | NULL |
| 10 | system user | | NULL | Connect | 9 | Waiting for an event from Coordinator | NULL |
| 11 | system user | | NULL | Connect | 9 | Waiting for an event from Coordinator | NULL |
| 12 | system user | | NULL | Connect | 9 | Waiting for an event from Coordinator | NULL |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
7 rows in set (0.00 sec)
注释:最后说一下为什么需要多线程复制?因为主从之间的同步会有延时,多线程的目的是为了尽量减少这个延时时间。如何优化主从是一个系统的功能,不同的场景需要不同的解决方案,但是多线程至少从基础上能减少延迟时间。另外根据数据库的实际情况,能否真正减少延时,以及配置多少线程,则需要反复的测试得出适合自己的数据