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的工作原理:
下面我们说下基于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
在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]#
很明显的看到比之前多了一些信息,如下:
#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 您的支持是对博主最大的鼓励,感谢您的认真阅读。本文版权归作者所有,欢迎转载,但请保留该声明。
|