一. MySQL 5.6引入了GTID的概念,那么GTID是何方神圣?其实也不复杂,就是一个全局事务标示符。使用GTID时,每次事务提交都会在binlog里生成1个唯一的标示符,它由UUID和事务ID组成。首次提交的事务ID为1,第二次为2,第三次为3,以此例推。uuid是服务器的身份ID,在第一次启动MySQL时,会自动生成一个server_uuid, 并且默认写入到数据目录下的auto.cnf文件里。我们一般无需修改,官方也不建议修改。更为详细的可以参考MariaDB官方文档

https://mariadb.com/kb/en/mariadb/mariadb-documentation/replication-cluster-multi-master/replication/parallel-replication/

[root@mysql-server- data]# pwd
/root/sandboxes/msb_5_6_19/data
[root@mysql-server- data]# cat auto.cnf
[auto]
server-uuid=9b0147c3-eed0-11e3--000c29e3621e
[root@mysql-server- data]#

那么基于GTID的Replication有啥好处?好处主要有以下2点:

(1)在传统的复制里面,当发生故障,需要主从切换,需要找到binlog和pos点,然后change master to指向新的master,相对来说比较麻烦,也容易出错。在MySQL 5.6里面,不用再找binlog和pos点,我们只需要知道master的ip,端口,以及账号密码就行,因为复制是自动的,MySQL会通过内部机制GTID自动找点同步。

(2)多线程复制(基于库)。在MySQL 5.6以前的版本,slave的复制是单线程的。一个事件一个事件的读取应用。而master是并发写入的,所以延时是避免不了的。唯一有效的方法是把多个库放在多台slave,这样又有点浪费服务器。在MySQL 5.6里面,我们可以把多个表放在多个库,这样就可以使用多线程复制,当只有1个库,多线程复制是没有用的。

GTID相关特性默认是关闭的(难道官方还觉得不够成熟),如下:

mysql [localhost] {msandbox} ((none)) > show variables like '%gtid%';
+--------------------------+-----------+
| Variable_name | Value |
+--------------------------+-----------+
| enforce_gtid_consistency | OFF |
| gtid_executed | |
| gtid_mode | OFF |
| gtid_next | AUTOMATIC |
| gtid_owned | |
| gtid_purged | |
+--------------------------+-----------+
6 rows in set (0.01 sec) mysql [localhost] {msandbox} ((none)) >

binlog里面也不会有GTID相关的记录,和普通复制时是一样的,如下:

[root@mysql-server- data]# mysqlbinlog --no-defaults -v --base64-output=DECODE-ROWS mysql_sandbox5619-bin.
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at
# :: server id end_log_pos Start: binlog v , server v 5.6.-log created :: at startup
# Warning: this binlog is either in use or was not closed properly.
ROLLBACK/*!*/;
# at
# :: server id end_log_pos Query thread_id= exec_time= error_code=
SET TIMESTAMP=/*!*/;
SET @@session.pseudo_thread_id=/*!*/;
SET @@session.foreign_key_checks=, @@session.sql_auto_is_null=, @@session.unique_checks=, @@session.autocommit=/*!*/;
SET @@session.sql_mode=/*!*/;
SET @@session.auto_increment_increment=, @@session.auto_increment_offset=/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=,@@session.collation_connection=,@@session.collation_server=/*!*/;
SET @@session.lc_time_names=/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
drop database yayunz
/*!*/;
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
[root@mysql-server- data]#

当开启GTID特性以后,binlog记录格式是这样的(具体开启后面介绍)

注意:(当启用GTID以后,binlog格式变化很大,如果继续采用低版本的mysqlbinlog命令查看,将会得到如下错误)。

[root@mysql-server- data]# mysqlbinlog --no-defaults -v --base64-output=DECODE-ROWS mysql-bin.
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at
# :: server id end_log_pos Start: binlog v , server v 5.6.-log created ::
ERROR: Error in Log_event::read_log_event(): 'Sanity check failed', data_len: , event_type:
ERROR: Could not read entry at offset : Error in log format or read error.
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
[root@mysql-server- data]#

下面是使用MySQL 5.6的mysqlbinlog命令查看开启了GTID日志的记录。

[root@mysql-server- data]# /data/sandbox_mysql/5.6./bin/mysqlbinlog --no-defaults -v --base64-output=DECODE-ROWS mysql-bin. | tail -n
DELIMITER /*!*/;
# at
# :: server id end_log_pos CRC32 0xcb49c4fe Start: binlog v , server v 5.6.-log created ::
# at
# :: server id end_log_pos CRC32 0x0e40da64 Previous-GTIDs
# 9b0147c3-eed0-11e3--000c29e3621e:
# at
# :: server id end_log_pos CRC32 0x52fc16ed GTID [commit=yes]
SET @@SESSION.GTID_NEXT= '9b0147c3-eed0-11e3-9821-000c29e3621e:2'/*!*/;
# at
# :: server id end_log_pos CRC32 0xf652f593 Query thread_id= exec_time= error_code=
SET TIMESTAMP=/*!*/;
SET @@session.pseudo_thread_id=/*!*/;
SET @@session.foreign_key_checks=, @@session.sql_auto_is_null=, @@session.unique_checks=, @@session.autocommit=/*!*/;
SET @@session.sql_mode=/*!*/;
SET @@session.auto_increment_increment=, @@session.auto_increment_offset=/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=,@@session.collation_connection=,@@session.collation_server=/*!*/;
SET @@session.lc_time_names=/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
create database dyy
/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
# at
# :: server id end_log_pos CRC32 0x68ff3fc0 Rotate to mysql-bin. pos:
DELIMITER ;
# End of log file
ROLLBACK /* added by mysqlbinlog */;
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
[root@mysql-server- data]#

我们从上面输出可以清楚的看见事务id如下(根据上面提到的,这个是第二个事务):

SET @@SESSION.GTID_NEXT= '9b0147c3-eed0-11e3-9821-000c29e3621e:2'/*!*/;

GTID的简单工作流程如下:

(1)在master上产生一个事务并且提交,并且写入binlog

(2)master上的binlog发送到slave,slave接收完毕并且写入relay log,slave读取到这个GTID,并设置gtid_next的值,例如:

SET @@SESSION.GTID_NEXT= '9b0147c3-eed0-11e3-9821-000c29e3621e:2

然后告诉slave接下来的事务必须使用GTID,并写入到它自己的binlog里。
(3)slave检查并确认这个GTID没有被使用,如果没有被使用,那么开始执行这个事务并写入到它自己的binlog里。

(4)由于gtid_next的值不是空的,slave不会尝试去生成一个新的gtid,而是通过主从复制来获取GTID。

二.  基于GTID的Replication的配置如下(最少配置选项,master和slave一样,server-id则需要不一样了,下面的参数只是针对于GTID,对于复制过滤选项和普通复制一样,因为GTID模式的复制也可以转换为普通模式的复制)

binlog_format = row
gtid-mode = ON
enforce-gtid-consistency = ON
log-bin=mysql-bin
log-slave-updates

少了相关选项,启动则报错,这是其中的报错日志,如下:

-- ::  [ERROR] --gtid-mode=ON or UPGRADE_STEP_1 or UPGRADE_STEP_2 requires --log-bin and --log-slave-updates

其中binlog_format = row不是必须的,但是推荐使用ROW格式,具体的参考我前面的文章提到的原因。

上面参数主从都配置以后,下面我们就来完成一个基于GTID的Replication(和普通复制有少量区别)

(1)在master上授权账户;

mysql [localhost] {root} ((none)) > GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.0.10' IDENTIFIED BY '';
Query OK, 0 rows affected (0.00 sec) mysql [localhost] {root} ((none)) > flush privileges;
Query OK, 0 rows affected (0.00 sec) mysql [localhost] {root} ((none)) >

(2)在master上备份要同步的库(这里的备份参数大家自行查阅文档,当然有几个参数或许用不到)

[root@mysql-server- msb_5_6_19]# mysqldump -uroot -pmsandbox -S /tmp/mysql_sandbox5619.sock -q -R --triggers --opt --single-transaction --flush-logs --master-data= dyy > /tmp/dyy.sql
[root@mysql-server- msb_5_6_19]#

(3)将备份的数据在slave上导入:

[root@mysql-server- ~]# mysql -uroot -pmsandbox -S /tmp/mysql_sandbox5619.sock < dyy.sql
[root@mysql-server- ~]#

(4)进行change master to操作

mysql [localhost] {root} (dyy) > CHANGE MASTER TO MASTER_HOST='192.168.0.100',MASTER_PORT=5619,MASTER_USER='repl',MASTER_PASSWORD='',master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.03 sec) mysql [localhost] {root} (dyy) > show warnings;
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note | 1759 | Sending passwords in plain text without SSL/TLS is extremely insecure. |
| Note | 1760 | Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information. |
+-------+------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec) mysql [localhost] {root} (dyy) >

可以看见成功,但是有两个警告,原来在MySQL 5.6里面越来越严格了,说不推荐这种使用方法。

mysql [localhost] {root} (dyy) > start slave;
Query OK, 0 rows affected (0.01 sec) mysql [localhost] {root} (dyy) > show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.0.100
Master_User: repl
Master_Port: 5619
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 151
Relay_Log_File: mysql_sandbox5619-relay-bin.000002
Relay_Log_Pos: 361
Relay_Master_Log_File: mysql-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: 151
Relay_Log_Space: 577
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: 9b0147c3-eed0-11e3-9821-000c29e3621e
Master_Info_File: /root/sandboxes/msb_5_6_19/data/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
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: 9b0147c3-eed0-11e3-9821-000c29e3621e:1-13,
d3c1aada-fad2-11e3-a66f-000c29ce3f18:1-85
Auto_Position: 1
1 row in set (0.00 sec) mysql [localhost] {root} (dyy) >

如果使用GTID模式的复制而change master to还使用普通模式的,则会报错。 

三. GTID的局限性(或者说还不够完善的地方)

(1)目前GTID还不支持MyISAM表(GTID是基于事务的)

(2)对CREATE TABLE ..... SELECT语句不支持。

mysql [localhost] {root} (dyy) > create table dyy select * from t1;
ERROR 1786 (HY000): CREATE TABLE ... SELECT is forbidden when @@GLOBAL.ENFORCE_GTID_CONSISTENCY = 1.
mysql [localhost] {root} (dyy) >

(3)必须开启enforce-gtid-consistency参数,否则启动MySQL报错,如下所示:

-- ::  [ERROR] --gtid-mode=ON or UPGRADE_STEP_1 requires --enforce-gtid-consistency
-- :: [ERROR] Aborting

注:在5.6.9的版本还不支持创建临时表,我测试的是5.6.19的版本,已经可以创建临时表了。

四.  多线程复制(基于库)

多线程复制由参数slave-paralles-workers控制,设定从服务器的SQL线程数;0表示关闭多线程复制功能;默认为0,最大可以设置为1024个线程。在从库的配置文件[mysqld]段落添加配置:

slave_parallel_workers = 

重启MySQL以后使用show processlist看到如下所示:

mysql [localhost] {msandbox} ((none)) > show processlist;
+----+-------------+-----------+------+---------+------+-----------------------------------------------------------------------------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------------+-----------+------+---------+------+-----------------------------------------------------------------------------+------------------+
| | system user | | NULL | Connect | | Slave has read all relay log; waiting for the slave I/O thread to update it | NULL |
| | system user | | NULL | Connect | | Waiting for master to send event | NULL |
| | system user | | NULL | Connect | | Waiting for an event from Coordinator | NULL |
| | system user | | NULL | Connect | | Waiting for an event from Coordinator | NULL |
| | system user | | NULL | Connect | | Waiting for an event from Coordinator | NULL |
| | system user | | NULL | Connect | | Waiting for an event from Coordinator | NULL |
| | system user | | NULL | Connect | | Waiting for an event from Coordinator | NULL |
| | system user | | NULL | Connect | | Waiting for an event from Coordinator | NULL |
| | msandbox | localhost | NULL | Query | | init | show processlist |
+----+-------------+-----------+------+---------+------+-----------------------------------------------------------------------------+------------------+
rows in set (0.00 sec) mysql [localhost] {msandbox} ((none)) >

此外用于保证relog信息以及master信息不丢失,需要设置相关参数来保证,可以参考我前面的文章。

总结:

我们尽可能的把一个库中的表按照业务逻辑拆分为多个库,这样在master上写操作时,slave就可以根据我们设置的线程数进行多线程复制,减少了传统复制的问题--延时。比如2个库我们就可以开启2个线程,3个库就可以开启3个线程,以此类推。还有目前GTID好像还不太成熟,官方的版本里面也没有默认开启,所以还需要进行大量的测试。

参考资料

http://dev.mysql.com/doc/refman/5.6/en/replication-options-gtids.html

http://dev.mysql.com/doc/refman/5.5/en/replication-howto.html

MySQL 5.6 GTID Replication的更多相关文章

  1. MySQL 5.6 GTID Replication【转】

    一. MySQL 5.6引入了GTID的概念,那么GTID是何方神圣?其实也不复杂,就是一个全局事务标示符.使用GTID时,每次事务提交都会在binlog里生成1个唯一的标示符,它由UUID和事务ID ...

  2. Repair MySQL 5.6 GTID replication by injecting empty transactions

    Since SQL_SLAVE_SKIP_COUNTER doesn’t work with GTID we need to find a way to ignore that transaction ...

  3. MYSQL Statement violates GTID consistency: Updates to non-transactional tables can only be done in either autocommitted statements or single-statement transactions, and never in the same statement as

    [2019-04-21 10:17:20] [ERROR] [org.hibernate.engine.jdbc.spi.SqlExceptionHelper:144] Statement viola ...

  4. (5.7)mysql高可用系列——MySQL中的GTID复制(理论篇)【转】

    转自:https://blog.csdn.net/wmq880204/article/details/53160078 一.GTID的概述: 1.全局事物标识:global transaction i ...

  5. MySQL5.7 GTID学习笔记,[MySQL 5.6] GTID实现、运维变化及存在的bug

      GTID(global transaction identifier)是对于一个已提交事务的全局唯一编号,前一部分是server_uuid,后面一部分是执行事务的唯一标志,通常是自增的. 下表整理 ...

  6. [MySQL 5.6] GTID实现、运维变化及存在的bug

    [MySQL 5.6] GTID实现.运维变化及存在的bug http://www.tuicool.com/articles/NjqQju 由于之前没太多深入关注gtid,这里给自己补补课,本文是我看 ...

  7. How to create/restore a slave using GTID replication in MySQL 5.6

    MySQL 5.6 is GA! Now we have new things to play with and in my personal opinion the most interesting ...

  8. 基于GTID Replication主从数据不一致操作

    基本的M-S结构   现在master与slave主机数据一致:   mysql> select * from t1; +------+ | id   | +------+ |    1 | | ...

  9. 【MySql】——MHA+GTID+failover+binlog-server+Atlas

    一.环境准备 1.mysql-db01 #系统版本 [root@mysql-db01 ~]# cat /etc/redhat-release CentOS release 6.7 (Final) #内 ...

随机推荐

  1. ubuntu中的环境变量

    写这句话,给自己提个醒吧,添加路径(所谓的环境变量):系统会去相应的目录中找可执行文件,到时候只要输入命令名字,可以不用输入完整的路径

  2. 为什么说Redis是单线程的以及Redis为什么这么快!

    参考文章:https://blog.csdn.net/xlgen157387/article/details/79470556 redis简介 Redis是一个开源的内存中的数据结构存储系统,它可以用 ...

  3. linux 查看信息-磁盘分区&网络

    磁盘和分区 1.查看挂接的分区状态 2.查看所有交换分区 3.查看启动时IDE设备检测状况 网络 1.查看网络接口属性 2.查看防火墙设置 3.查看路由表 4.查看所有监听端口 5.查看所有已经建立的 ...

  4. wamp环境搭建(apache安装,mysql安装,php安装)

    1.软件安装说明 WAMP:Window操作系统+Apache软件+PHP解析器+MySQL软件 2.Apache执行流程 用户向服务器端发送请求àDNS解析àIP地址à端口àApache服务 Apa ...

  5. 《Linux就该这么学》第四天课程

     秦时明月经典语录: 侠道:五步之内,百人不当.十年磨剑,一孤侠道——荆轲 我发了一些课堂笔记,供你们参考 原创地址:https://www.linuxprobe.com/chapter-03.htm ...

  6. PB的一些记录

    断点设置在函数内,发现返回值没有,需要取消函数内断点才正常 加密--采用矩阵乘法 行列式取+_1的矩阵与逆矩阵其元素都是整数,, 可以使用matlab来找到这些矩阵 A* I   =E       A ...

  7. ESP-IDF版本2.1.1

    版本2.1.1是一个错误修复版本.它包括对KRACK和BlueBorne漏洞的修复. 版本2.1.1的文档可在http://esp-idf.readthedocs.io/en/v2.1.1/上找到. ...

  8. html 基本用法

    html表单表格基本用法,直接贴代码. <html> <head> <title>html基础</title> </head> </b ...

  9. iowait过高处理

    网管告警: 告警主机:YiDHLWJKFZ-js-app- 主机IP:192.168.***.*** 告警项目:system.cpu.util[,iowait] 告警时间: :: 告警等级:Warni ...

  10. Dynamic Programming | Set 1 (Overlapping Subproblems Property)

    动态规划是这样一种算法范式:将复杂问题划分为子问题来求解,并且将子问题的结果保存下来以避免重复计算.如果一个问题拥有以下两种性质,则建议使用动态规划来求解. 1 重叠子问题(Overlapping S ...