MySQL5.6 GTID Replication

   MySQL 5.6 的新特性之一,是加入了全局事务 ID (Global Transaction ID) 来强化数据库的主备一致性,故障恢复,以及容错能力。官方文档:http://dev.mysql.com/doc/refman/5.6/en/replication-gtids.html在这篇文档里,我们可以知道GTID(全局事务 ID) 的官方定义是:GTID实际上是由UUID+TID组成的,其中UUID是一个MySQL实例的唯一标识,TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增。

 

那么基于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的工作原理:

1、master更新数据时,会在事务前产生GTID,一同记录到binlog日志中。
2、slave端的i/o 线程将变更的binlog,写入到本地的relay log中。
3、sql线程从relay log中获取GTID,然后对比slave端的binlog是否有记录。
4、如果有记录,说明该GTID的事务已经执行,slave会忽略。
5、如果没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog。
6、在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。

 

下面我们说下基于GTID复制的搭建(当MySQL5.6的版本安装好后,在数据目录下有一个auto.cnf的文件,就是存放着server-uuid):

查看GTID的相关的一些变量:

root@xuanzhi (master)>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.00 sec)

root@xuanzhi (master)>

可以看到,官方的MySQL5.6默认是没开启GTID的。

如果没有开启GTID选项,在binlog里,也看不到GTID的信息,以下binlog是没开启的Binlog日志信息:

[root@mysql-master ~]# /usr/local/mysql-3306/bin/mysqlbinlog --no-defaults -v --base64-output=DECODE-ROWS /home/mysql-3306/data/mysql-bin.000003 
/*!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 4
#150628 18:02:33 server id 1  end_log_pos 120 CRC32 0x42bbbf2b  Start: binlog v 4, server v 5.6.10-log created 150628 18:02:33
# Warning: this binlog is either in use or was not closed properly.
# at 120
#150628 18:02:50 server id 1  end_log_pos 242 CRC32 0x693a437d  Query   thread_id=2     exec_time=0     error_code=0
use `xuanzhi`/*!*/;
SET TIMESTAMP=1435485770/*!*/;
SET @@session.pseudo_thread_id=2/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1075838976/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
DROP TABLE `tb1` /* generated by server */
/*!*/;
# at 242
#150628 18:03:04 server id 1  end_log_pos 442 CRC32 0x8147c0f8  Query   thread_id=2     exec_time=0     error_code=0
SET TIMESTAMP=1435485784/*!*/;
CREATE TABLE `tb1` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
/*!*/;
# at 442
#150628 18:03:19 server id 1  end_log_pos 517 CRC32 0xac178240  Query   thread_id=2     exec_time=0     error_code=0
View Code

在master的my.cnf添加以下选择开启GTID:

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

 其中binlog_format = row不是必须的,但是推荐使用ROW格式,具体的参考我前面的文章提到的原因,有些有很好奇为什么要设置log-slave-updates呢?嘻嘻,这个问题下面来揭晓,我们在不加log-slave-updates启动MySQL报以下错:

2015-06-28 18:20:38 26032 [Note] InnoDB: 1.2.10 started; log sequence number 1666405
2015-06-28 18:20:38 26032 [ERROR] --gtid-mode=ON or UPGRADE_STEP_1 or UPGRADE_STEP_2 requires --log-bin and --log-slave-updates
2015-06-28 18:20:38 26032 [ERROR] Aborting

所以必须在配置文件添加上log-slave-updates才能正常启动。
我们查看下开启GTID后的Binlog信息如下:

[root@mysql-master mysql-3306]# /usr/local/mysql-3306/bin/mysqlbinlog --no-defaults -v --base64-output=DECODE-ROWS /home/mysql-3306/data/mysql-bin.000005
/*!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 4
#150628 18:24:24 server id 1  end_log_pos 120 CRC32 0xfde1a899  Start: binlog v 4, server v 5.6.10-log created 150628 18:24:24
# Warning: this binlog is either in use or was not closed properly.
# at 120
#150628 18:24:24 server id 1  end_log_pos 151 CRC32 0xd0531b1e  Previous-GTIDs
# [empty]
# at 151
#150628 18:26:19 server id 1  end_log_pos 199 CRC32 0xb55c00a9  GTID [commit=yes]
SET @@SESSION.GTID_NEXT= '62c879aa-1d73-11e5-8d91-2c768ad07874:1'/*!*/;
# at 199
#150628 18:26:19 server id 1  end_log_pos 274 CRC32 0x1809848f  Query   thread_id=1     exec_time=0     error_code=0
SET TIMESTAMP=1435487179/*!*/;
SET @@session.pseudo_thread_id=1/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1075838976/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C utf8 *//*!*/;
SET @@session.character_set_client=33,@@session.collation_connection=33,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 274
#150628 18:26:19 server id 1  end_log_pos 326 CRC32 0x97cc2ba2  Table_map: `xuanzhi`.`tb1` mapped to number 70
# at 326
#150628 18:26:19 server id 1  end_log_pos 369 CRC32 0x1cfed777  Write_rows: table id 70 flags: STMT_END_F
### INSERT INTO `xuanzhi`.`tb1`
### SET
###   @1=5
###   @2='ee'
# at 369
#150628 18:26:19 server id 1  end_log_pos 400 CRC32 0xff6c1187  Xid = 10
COMMIT/*!*/;
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-master mysql-3306]# 
View Code

很明显的看到比之前多了一些信息,如下:

#150628 18:26:19 server id 1  end_log_pos 199 CRC32 0xb55c00a9  GTID [commit=yes]
SET @@SESSION.GTID_NEXT= '62c879aa-1d73-11e5-8d91-2c768ad07874:1'/*!*/;

小伙伴应该注意一个问题,当用低版本的mysqlbinlog命令去查看高版本的binlog日志会出现以下的错误,所以建议用对应版本的mysqlbinlog命令查看:

[root@mysql-master ~]# mysqlbinlog --no-defaults -v --base64-output=DECODE-ROWS /home/mysql-3306/data/mysql-bin.000003 > aa.sql
ERROR: Error in Log_event::read_log_event(): 'Sanity check failed', data_len: 43, event_type: 30
[root@mysql-master ~]# 

 

二、开始搭建基于GTID的主从复制:

(1)在master上授权用来同步的用户:

root@xuanzhi (master)>grant replication slave on *.* to 'repl'@'192.168.100.143' identified by '123456';
Query OK, 0 rows affected (0.00 sec)

root@xuanzhi (master)>flush privileges;
Query OK, 0 rows affected (0.00 sec)

root@xuanzhi (master)>

(2)在master备份要同步的库,方法有很多,我用mysqldump来完成这动作:

[root@mysql-master ~]# mysqldump -uroot -p123456 -S /home/mysql-3306/mysql.sock --single-transaction --master-data=2 -q -A > ./all.sql
Warning: Using a password on the command line interface can be insecure.
Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events. 
[root@mysql-master ~]# 

为了安全起见,我觉得应该在备份的时候关了GTID

[root@mysql-master ~]# /usr/local/mysql-3306/bin/mysqldump -uroot -p123456 -S /home/mysql-3306/mysql.sock  --set-gtid-purged=OFF --single-transaction --master-data=2 -q -A > ./all.sql
Warning: Using a password on the command line interface can be insecure.
[root@mysql-master ~]# cat /home/mysql-3306/data/auto.cnf 

 

 

(3)把数据拷贝到slave服务器上:

[root@mysql-master ~]# scp all.sql 192.168.100.142:/root

(4)slave上也要开启GTID,所以在slave配置文件添加以下内容(注意server_id要跟Master不一样)

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

(5)导入数据并执行change master操作:

[root@mysql-slave mysql-3308]# mysql -uroot -p123456 -S /home/mysql-3308/mysql.sock  < /root/all.sql

 基于GTID复制的change master to要带上master_auto_position选项:

root@xuanzhi (slave)>change master to master_host='192.168.100.143',master_port=3306,master_user='repl',master_password='123456',master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.53 sec)

root@xuanzhi (slave)>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 see the MySQL Manual for more about this issue and possible alternatives. |
+-------+------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

 启动slave,又来警告了,我们查看下警告说了啥:

root@xuanzhi (slave)>start slave;
Query OK, 0 rows affected, 1 warning (0.20 sec)

root@xuanzhi (slave)>show warnings;
+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                                                                               |
+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Note  | 1753 | slave_transaction_retries is not supported in multi-threaded slave mode. In the event of a transient failure, the slave will not retry the transaction and will stop. |
+-------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

说选项slave_transaction_retries在多线程模式不支持。好吧,把它关了吧(我的版本是5.6.10,这版本可能在这方面可能存在问题,详细可以查看http://dev.mysql.com/doc/refman/5.6/en/start-slave.html

root@xuanzhi (slave)>stop slave; 
Query OK, 0 rows affected (0.09 sec)

root@xuanzhi (slave)>SET @@GLOBAL.slave_transaction_retries = 0;
Query OK, 0 rows affected (0.00 sec)

root@xuanzhi (slave)>start slave;  
Query OK, 0 rows affected (0.23 sec)

root@xuanzhi (slave)>show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.100.143
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000005
          Read_Master_Log_Pos: 1058
               Relay_Log_File: mysql-master-relay-bin.000007
                Relay_Log_Pos: 408
        Relay_Master_Log_File: mysql-bin.000005
             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: 1058
              Relay_Log_Space: 666
              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: 62c879aa-1d73-11e5-8d91-2c768ad07874
             Master_Info_File: /home/mysql-3308/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: 62c879aa-1d73-11e5-8d91-2c768ad07874:1-4,
f2ede1dc-1d73-11e5-8d95-2c768ad07874:1-124
                Auto_Position: 1
1 row in set (0.00 sec)

root@xuanzhi (slave)>

貌似5.6.19后的版本就在启动start slave的时候,就没那么警告了:

mysql> select version();
+------------+
| version()  |
+------------+
| 5.6.25-log |
+------------+
1 row in set (0.00 sec)

mysql> change master to master_host='192.168.100.143',master_port=3306,master_user='repl',master_password='123456',master_auto_position=1;
Query OK, 0 rows affected, 2 warnings (0.37 sec)

mysql
> start slave; Query OK, 0 rows affected (0.04 sec)

如果确定要使用5.6版本,尽可能使用靠后点的新版本!!!

 

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

(1)有人说目前GTID还不支持MyISAM表(GTID是基于事务的),我测试过了是支持的:

root@xuanzhi (master)>show create table tb2\G
*************************** 1. row ***************************
       Table: tb2
Create Table: CREATE TABLE `tb2` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

root@xuanzhi (master)>insert into tb2 select 1,'aa';
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

root@xuanzhi (master)>insert into tb2 select 2,'bb';
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

在slave查看数据是否同步可以了

root@xuanzhi (slave)>show create table tb2\G
*************************** 1. row ***************************
       Table: tb2
Create Table: CREATE TABLE `tb2` (
  `id` int(11) DEFAULT NULL,
  `name` varchar(10) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

root@xuanzhi (slave)>select * from tb2;
+------+------+
| id   | name |
+------+------+
|    1 | aa   |
|    2 | bb   |
+------+------+
2 rows in set (0.00 sec)

root@xuanzhi (slave)>

我们进行Binlog分析可以看到,是有GTID产生的

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

root@xuanzhi (master)>create table test select * from tb1;
ERROR 1786 (HY000): CREATE TABLE ... SELECT is forbidden when ENFORCE_GTID_CONSISTENCY = 1.
root@xuanzhi (master)>

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

20145-06-28 23:44:27 17563 [ERROR] --gtid-mode=ON or UPGRADE_STEP_1 requires --enforce-gtid-consistency
20145-06-28 23:44:27 17563 [ERROR] Aborting

 

四.  多线程复制(基于库,5.7很有可能实现基于表级别的多线程复制,值得期待)

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

slave_parallel_workers = 6

此参数支持动态修改,灰常方便:

root@xuanzhi (slave)>set global slave_parallel_workers = 6;
Query OK, 0 rows affected (0.00 sec)

root@xuanzhi (slave)>show processlist;
+----+-------------+-----------+---------+---------+------+-----------------------------------------------------------------------------+------------------+
| Id | User        | Host      | db      | Command | Time | State                                                                       | Info             |
+----+-------------+-----------+---------+---------+------+-----------------------------------------------------------------------------+------------------+
| 36 | root        | localhost | xuanzhi | Query   |    0 | init                                                                        | show processlist |
| 37 | system user |           | NULL    | Connect | 3839 | Waiting for master to send event                                            | NULL             |
| 38 | system user |           | NULL    | Connect | 2054 | Slave has read all relay log; waiting for the slave I/O thread to update it | NULL             |
| 39 | system user |           | NULL    | Connect | 3839 | Waiting for an event from Coordinator                                       | NULL             |
| 40 | system user |           | NULL    | Connect | 3839 | Waiting for an event from Coordinator                                       | NULL             |
| 41 | system user |           | NULL    | Connect | 3839 | Waiting for an event from Coordinator                                       | NULL             |
| 42 | system user |           | NULL    | Connect | 2054 | Waiting for an event from Coordinator                                       | NULL             |
| 43 | system user |           | NULL    | Connect | 2054 | Waiting for an event from Coordinator                                       | NULL             |
| 44 | system user |           | NULL    | Connect | 2054 | Waiting for an event from Coordinator                                       | NULL             |
| 45 | system user |           | NULL    | Connect | 2054 | Waiting for an event from Coordinator                                       | NULL             |
+----+-------------+-----------+---------+---------+------+-----------------------------------------------------------------------------+------------------+
7 rows in set (0.00 sec)

 

 

总结:

     一、MySQL5.6相对MySQL5.5在功能和性能上都提升了不少,建议使用MySQL5.6的版本,如果要用5.6的版本,尽量使用靠后点的5.6的版本

     二、MySQL 5.6里面,不用再找binlog和pos点,我们只需要知道master的ip,端口,以及账号密码就行,因为复制是自动的,MySQL会通过内部机制GTID自动找点同步,相比之传统复制可用性更高,更合适一主多从架构

     三、我们尽可能的把一个库中的表按照业务逻辑拆分为多个库,这样在master上写操作时,slave就可以根据我们设置的线程数进行多线程复制,减少了传统复制的问题--延时。

 

http://www.cnblogs.com/abobo/p/4242417.html

http://www.cnblogs.com/gomysql/p/3816031.html

 

 

 

作者:陆炫志

出处:xuanzhi的博客 http://www.cnblogs.com/xuanzhi201111

您的支持是对博主最大的鼓励,感谢您的认真阅读。本文版权归作者所有,欢迎转载,但请保留该声明。

 

posted @ 2015-06-29 23:56  GoogSQL  阅读(1324)  评论(0编辑  收藏  举报