Fork me on GitHub
Suzf  Blog

[译] How to create/restore a slave using GTID replication in MySQL 5.6

在 Mysql 5.6 中,里面有许多新的特性;我个人认为其中最有用的是在复制中支持 全局事务ID(Global Transaction ID)。
这篇文章不是用来介绍什么是GTID,关于它的工作原理这里有很多文章介绍:
http://dev.mysql.com/doc/refman/5.6/en/replication-gtids-concepts.html

这里值得一提的是,如果你想GTID支持log_slave_updates,需要启用从服务器和考虑到性能的影响。

还有,这篇文章更趋向于实用,我们将要看到如何使用 GTID 创建/恢复 新的slaves 从 master上。

如何创建一个新的 slave 节点
我们不需要知道的现在二进制日志和位置,当GTID启用的时候想,这些事不需要的。
相反,我们需要知道哪个GTID出现在master上并且在slave上设置。 MySQL与GTID相关的两个全局变量是:

gtid_executed:它包含了集合中的所有事务记录在二进制日志
gtid_purged:它包含从二进制日志中删除所有事务记录的集合

所以,现在,这个过程是这样的:
在master上做一个备份并记录 gtid_executed 的值
在slave上恢复备份并将 gtid_purged 设置成master上gtid_executed 的值

新的mysqldump 可以为我们做这些工作。让我们来看看如何在master上备份的并且在slave 上恢复它来建立一个新的 Replication Server的一个例子。
master > show global variables like 'gtid_executed';
+---------------+-------------------------------------------+
| Variable_name | Value                                     |
+---------------+-------------------------------------------+
| gtid_executed | 9a511b7b-7059-11e2-9a24-08002762b8af:1-13 |
+---------------+-------------------------------------------+
master > show global variables like 'gtid_purged';
+---------------+------------------------------------------+
| Variable_name | Value                                    |
+---------------+------------------------------------------+
| gtid_purged   | 9a511b7b-7059-11e2-9a24-08002762b8af:1-2 |
+---------------+------------------------------------------+

现在我们可以使用mysqldump 备份master:
# mysqldump --all-databases --single-transaction --triggers --routines --host=127.0.0.1 --port=18675 --user=msandbox --password=msandbox > dump.sql

生成的备份文件将包括以下信息:
# grep PURGED dump.sql
SET @@GLOBAL.GTID_PURGED='9a511b7b-7059-11e2-9a24-08002762b8af:1-13';

因此,在slave上进行数据恢复的时候,它将设置GTID_PURGED为master上GTID_EXECUTED的值。
所以现在,我们需要恢复转储和启动复制:
slave1 > show global variables like 'gtid_executed';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| gtid_executed |       |
+---------------+-------+
slave1 > show global variables like 'gtid_purged';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| gtid_purged   |       |
+---------------+-------+
slave1 > slave1> source test.sql;
[...]
slave1 > show global variables like 'gtid_executed';
+---------------+-------------------------------------------+
| Variable_name | Value                                     |
+---------------+-------------------------------------------+
| gtid_executed | 9a511b7b-7059-11e2-9a24-08002762b8af:1-13 |
+---------------+-------------------------------------------+
slave1 > show global variables like 'gtid_purged';
+---------------+-------------------------------------------+
| Variable_name | Value                                     |
+---------------+-------------------------------------------+
| gtid_purged   | 9a511b7b-7059-11e2-9a24-08002762b8af:1-13 |
+---------------+-------------------------------------------+

最后一步是用GTID的自动配置方法配置slave:
slave1 > CHANGE MASTER TO MASTER_HOST="127.0.0.1", MASTER_USER="msandbox", MASTER_PASSWORD="msandbox", MASTER_PORT=18675, MASTER_AUTO_POSITION = 1;

如何用快速的方法修复有问题的slave
让我们想象一下,我们的slave节点已经停止了好几天,并master二进制日志已被清除。这就是我们得到的错误:
Slave_IO_Running: No
Slave_SQL_Running: Yes
Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.'

所以,让我们试着去解决它。首先,我们有一个不太好快速的方法,即,一点到另一点 GTID 在二进制日志中。首先,我们得得到 GTID_EXECUTED 在master上:
master > show global variables like 'GTID_EXECUTED';
+---------------+-------------------------------------------+
| Variable_name | Value                                     |
+---------------+-------------------------------------------+
| gtid_executed | 9a511b7b-7059-11e2-9a24-08002762b8af:1-14 |
+---------------+-------------------------------------------+

我们在slave上设置它
slave> set global GTID_EXECUTED="9a511b7b-7059-11e2-9a24-08002762b8af:1-14"
ERROR 1238 (HY000): Variable 'gtid_executed' is a read only variable

错误! 记住,我们从master上得到 GTID_EXECUTED 的值,之后子在slave上设置 GTID_PURGED
slave1 > set global GTID_PURGED="9a511b7b-7059-11e2-9a24-08002762b8af:1-14";
ERROR 1840 (HY000): GTID_PURGED can only be set when GTID_EXECUTED is empty.

错误又出现了,GTID_EXECUTED 应该是空的在改变 GTID_PURGED 前,但是我们不能改变它使用 SET,
因为这是一个只读的变量。 这里唯一的方法是使用 reset master(是的,在slave节点上)
slave1> reset master;
slave1 > show global variables like 'GTID_EXECUTED';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| gtid_executed |       |
+---------------+-------+
slave1 > set global GTID_PURGED="9a511b7b-7059-11e2-9a24-08002762b8af:1-14";
slave1> start slave io_thread;
slave1> show slave status\G
[...]
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
[...]

现在,如果你没有见到类似的错误[primary/unique key duplication],你可以使用 pt-table-checksum 和 pt-table-sync 来检查数据库的完整性。

如何使用一个好的方法修复slave节点 话费时间稍长
好的方法是使用mysqldump 再次在master上备份数据。
我们执行在master上执行dump并且在slave上恢复,就像上面看到的那样。
slave1 [localhost] {msandbox} ((none)) > source test.sql;
[...]
ERROR 1840 (HY000): GTID_PURGED can only be set when GTID_EXECUTED is empty.
[...]

哦!这里很值得一提的是这种错误信息可以消失在执行完命令之后。
因为恢复数据的过程需要继续。 谨慎些。

同样的错误 同样的解决方法
slave1> reset master;
slave1> source test.sql;
slave1> start slave;
slave1> show slave status\G
[...]
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
[...]

结论
我们需要改变我们的思想在新的 GTID 下。现在二进制日志和位置信息已经不再我们的考虑范围之内了。
gtid_executed和gtid_purged是我们的新朋友。新版本Xtrabackup都全力支持GTID的。您可以查看下面的文章:

http://www.percona.com/blog/2013/05/09/how-to-create-a-new-or-repair-a-broken-gtid-based-slave-with-percona-xtrabackup/

原文: percona_blog