在5.6开始,mysql支持基于gtid的复制。
要启用基于gtid的复制,得使用如下参数:
gtid_mode = ON
enforce_gtid_consistency = ON
gtid就是全局事务id。
全局的意思是在整个复制环境中这个全局中。
基于gtid复制就是master的每一个对数据库引起的变更(专业叫event)都会被标记一个gtid值。
一个gtid值像这样:e2e2f927-e75c-11e5-ac89-5c260a17ccde:20。
一个gtid-sets值表示很多event的集合,像这样:e2e2f927-e75c-11e5-ac89-5c260a17ccde:1-5500,表示e2e2f927-e75c-11e5-ac89-5c260a17ccde这个实例的1到5500号事务。
e2e2f927-e75c-11e5-ac89-5c260a17ccde,表示一个mysql实例的uuid值。20,表示事务号(也可以理解为事务序列号)。
在slave端我们可以show slave status\G一下,然后看到这样的输出:
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.77
Master_User: backup
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000018
Read_Master_Log_Pos: 194
Relay_Log_File: host_name-relay-bin.000038
Relay_Log_Pos: 367
Relay_Master_Log_File: mysql-bin.000018
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: 194
Relay_Log_Space: 744
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: 2
Master_UUID: e2e2f927-e75c-11e5-ac89-5c260a17ccde
Master_Info_File: mysql.slave_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: 1cced57b-e75e-11e5-b742-5c260a17ccde:1-6,
e2e2f927-e75c-11e5-ac89-5c260a17ccde:1-5500
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
mysql>
红色部分Retrieved_Gtid_Set表示slave端接收到的gtid-set。在slave重启之后,该值会被清空。
而Executed_Gtid_Set表示slave端实际执行的gtid-set。
而我的测试环境中出现如下情况:
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.77
Master_User: backup
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000018
Read_Master_Log_Pos: 1017
Relay_Log_File: host_name-relay-bin.000038
Relay_Log_Pos: 551
Relay_Master_Log_File: mysql-bin.000018
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1432
Last_Error: Error 'server name: 'fedlink' doesn't exist!' on query. Default database: 'test'. Query: 'CREATE TABLE `t_area` (
`id` varchar(255) NOT NULL,
`address` varchar(255) DEFAULT NULL,
`level` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`sort` int(11) NOT NULL,
`telephone` varchar(255) DEFAULT NULL,
`visible` bit(1) NOT NULL,
`parentId` varchar(255) DEFAULT NULL,
`number` varchar(255) DEFAULT NULL,
`theCode` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FKCB5AB178745ED9CF` (`parentId`)
) ENGINE=FEDERATED DEFAULT CHARSET=utf8
connection='fedlink/t_area''
Skip_Counter: 0
Exec_Master_Log_Pos: 378
Relay_Log_Space: 1567
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: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1432
Last_SQL_Error: Error 'server name: 'fedlink' doesn't exist!' on query. Default database: 'test'. Query: 'CREATE TABLE `t_area` (
`id` varchar(255) NOT NULL,
`address` varchar(255) DEFAULT NULL,
`level` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`sort` int(11) NOT NULL,
`telephone` varchar(255) DEFAULT NULL,
`visible` bit(1) NOT NULL,
`parentId` varchar(255) DEFAULT NULL,
`number` varchar(255) DEFAULT NULL,
`theCode` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FKCB5AB178745ED9CF` (`parentId`)
) ENGINE=FEDERATED DEFAULT CHARSET=utf8
connection='fedlink/t_area''
Replicate_Ignore_Server_Ids:
Master_Server_Id: 2
Master_UUID: e2e2f927-e75c-11e5-ac89-5c260a17ccde
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State:
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp: 160322 11:00:14
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: e2e2f927-e75c-11e5-ac89-5c260a17ccde:5501-5502
Executed_Gtid_Set: 1cced57b-e75e-11e5-b742-5c260a17ccde:1-6,
e2e2f927-e75c-11e5-ac89-5c260a17ccde:1-5501
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
mysql>
上述输出可得出,Slave_SQL_Running: No表示复制SQL线程失败停止了。
Retrieved_Gtid_Set是5501-5502,而实际只重演到5501,5502并没有执行。
并且根据Last_Error得出,由于fedlink这个server不存在导致t_area表创建失败,进而导致复制重演SQL线程失败。
那么问题来了:
1. 为什么fedlink这个server的定义没有被复制?
2. 如何解决这个复制错误,以重新启动复制SQL线程?
原来,根据文档对CREATE SERVER的,描述:
In MySQL 5.7, CREATE SERVER is not written to the binary log, regardless of the logging format that is in use.
In MySQL 5.7, ALTER SERVER is not written to the binary log, regardless of the logging format that is in use.
也就是不管binlog_format如何设置,CREATE SERVER与ALTER SERVER操作不会被binlog,也就不会被复制。(我去,这绝对是不应该的)。
那么现在的问题是,如何解决这个复制SQL失败的问题呢?
根据分析,SQL线程失败是由于fedlink这个server在slave端不存在的原因导致的。
所以我们可以手工在slave端执行CREATE SERVER fedlink的语句。
还有另外一种方式(这里其实我并不推荐):我们可以跳过5502这个event。如下:
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.77
Master_User: backup
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000018
Read_Master_Log_Pos: 1017
Relay_Log_File: host_name-relay-bin.000038
Relay_Log_Pos: 551
Relay_Master_Log_File: mysql-bin.000018
Slave_IO_Running: Yes
Slave_SQL_Running: No
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 1432
Last_Error: Error 'server name: 'fedlink' doesn't exist!' on query. Default database: 'test'. Query: 'CREATE TABLE `t_area` (
`id` varchar(255) NOT NULL,
`address` varchar(255) DEFAULT NULL,
`level` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`sort` int(11) NOT NULL,
`telephone` varchar(255) DEFAULT NULL,
`visible` bit(1) NOT NULL,
`parentId` varchar(255) DEFAULT NULL,
`number` varchar(255) DEFAULT NULL,
`theCode` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FKCB5AB178745ED9CF` (`parentId`)
) ENGINE=FEDERATED DEFAULT CHARSET=utf8
connection='fedlink/t_area''
Skip_Counter: 0
Exec_Master_Log_Pos: 378
Relay_Log_Space: 1984
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: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 1432
Last_SQL_Error: Error 'server name: 'fedlink' doesn't exist!' on query. Default database: 'test'. Query: 'CREATE TABLE `t_area` (
`id` varchar(255) NOT NULL,
`address` varchar(255) DEFAULT NULL,
`level` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`sort` int(11) NOT NULL,
`telephone` varchar(255) DEFAULT NULL,
`visible` bit(1) NOT NULL,
`parentId` varchar(255) DEFAULT NULL,
`number` varchar(255) DEFAULT NULL,
`theCode` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `FKCB5AB178745ED9CF` (`parentId`)
) ENGINE=FEDERATED DEFAULT CHARSET=utf8
connection='fedlink/t_area''
Replicate_Ignore_Server_Ids:
Master_Server_Id: 2
Master_UUID: e2e2f927-e75c-11e5-ac89-5c260a17ccde
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State:
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp: 160322 11:28:01
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set: e2e2f927-e75c-11e5-ac89-5c260a17ccde:5501-5502
Executed_Gtid_Set: 1cced57b-e75e-11e5-b742-5c260a17ccde:1-6,
e2e2f927-e75c-11e5-ac89-5c260a17ccde:1-5501
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
mysql> stop slave;
Query OK, 0 rows affected (0.09 sec)
mysql> set gtid_next="e2e2f927-e75c-11e5-ac89-5c260a17ccde:5502";
Query OK, 0 rows affected (0.00 sec)
mysql> begin;commit;
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.02 sec)
mysql> set gtid_next="AUTOMATIC";
Query OK, 0 rows affected (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected (0.07 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.1.77
Master_User: backup
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000018
Read_Master_Log_Pos: 1017
Relay_Log_File: host_name-relay-bin.000040
Relay_Log_Pos: 360
Relay_Master_Log_File: mysql-bin.000018
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: 1017
Relay_Log_Space: 777
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: 2
Master_UUID: e2e2f927-e75c-11e5-ac89-5c260a17ccde
Master_Info_File: mysql.slave_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: e2e2f927-e75c-11e5-ac89-5c260a17ccde:5501-5502
Executed_Gtid_Set: 1cced57b-e75e-11e5-b742-5c260a17ccde:1-6,
e2e2f927-e75c-11e5-ac89-5c260a17ccde:1-5502
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
mysql>
复制SQL线程成功启动。
但是很明显,此时有个问题:主备库不一致,1. fedlink这个server存在master端,但是不存在slave端。2. test.t_area表master存在而slave端不存在。
下面来解决这个问题:
先在slave端手工创建t_area表:
mysql> CREATE TABLE `t_area` (
-> `id` VARCHAR(255) NOT NULL,
-> `address` VARCHAR(255) DEFAULT NULL,
-> `level` INT(11) NOT NULL,
-> `name` VARCHAR(255) DEFAULT NULL,
-> `sort` INT(11) NOT NULL,
-> `telephone` VARCHAR(255) DEFAULT NULL,
-> `visible` BIT(1) NOT NULL,
-> `parentId` VARCHAR(255) DEFAULT NULL,
-> `number` VARCHAR(255) DEFAULT NULL,
-> `theCode` VARCHAR(255) DEFAULT NULL,
-> PRIMARY KEY (`id`),
-> KEY `FKCB5AB178745ED9CF` (`parentId`)
-> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.35 sec)
mysql>
然后在master端drop表这个表:
mysql> drop table t_area;
Query OK, 0 rows affected (0.14 sec)
mysql>
此时slave端的t_area表也被删除。
然后再在slave端手工创建fedlink:
mysql> CREATE SERVER fedlink
-> FOREIGN DATA WRAPPER mysql
-> OPTIONS (
-> USER 'root',
-> PASSWORD '20127163',
-> HOST '192.168.1.166',
-> PORT 3306,
-> DATABASE 'cms'
-> ) ;
Query OK, 1 row affected (0.08 sec)
mysql>
再回到master端创建带CONNECTION子句的t_area表:
mysql> CREATE TABLE `t_area` (
-> `id` VARCHAR(255) NOT NULL,
-> `address` VARCHAR(255) DEFAULT NULL,
-> `level` INT(11) NOT NULL,
-> `name` VARCHAR(255) DEFAULT NULL,
-> `sort` INT(11) NOT NULL,
-> `telephone` VARCHAR(255) DEFAULT NULL,
-> `visible` BIT(1) NOT NULL,
-> `parentId` VARCHAR(255) DEFAULT NULL,
-> `number` VARCHAR(255) DEFAULT NULL,
-> `theCode` VARCHAR(255) DEFAULT NULL,
-> PRIMARY KEY (`id`),
-> KEY `FKCB5AB178745ED9CF` (`parentId`)
-> ) ENGINE=FEDERATED DEFAULT CHARSET=utf8
-> CONNECTION='fedlink/t_area';
Query OK, 0 rows affected (0.08 sec)
mysql>
观察slave端也成功创建。