首页 >数据库 >mysql教程 >MySQL 5.6 中的 GTID:新的复制协议; br_MySQL 的新方法

MySQL 5.6 中的 GTID:新的复制协议; br_MySQL 的新方法

WBOY
WBOY原创
2016-06-01 13:14:461076浏览

许多人感兴趣的 MySQL 5.6 功能之一是全局事务 ID (GTID)。这是有充分理由的:将从站重新连接到新的主站一直是一个挑战,而在启用 GTID 时却变得如此微不足道。然而,使用 GTID 不仅是用唯一标识符替换旧的二进制日志文件/位置,而且还使用新的复制协议。如果您没有意识到这一点,它就会咬人。

复制协议:旧与新

旧协议非常简单:从属设备以特定的位置连接到给定的二进制日志文件

新协议略有不同:从站首先发送其已执行的 GTID 范围,然后主站发送每个丢失的交易。它还保证具有给定 GTID 的事务只能在特定从属设备上执行一次。

实际上,它会改变什么吗?嗯,它可能会改变很多事情。想象一下以下情况:您想要从 trx 4 开始复制,但由于某种原因,从属设备上缺少 trx 2。

MySQL 5.6 中的 GTID:新的复制协议; br_MySQL 的新方法

使用旧的复制协议,trx 2 将使用新复制协议时永远不会执行,它自动执行。

以下是 2 种常见情况,您可以在其中看到新复制协议的运行情况。

跳过交易

众所周知,当您想要跳过交易并且启用 GTID 时,不再支持旧的SET GLOBAL sql_slave_skip_counter = N。相反,要跳过 GTID XXX:N 事务,您必须注入一个空事务:

mysql> SET gtid_next = 'XXX:N';mysql> BEGIN; COMMIT;mysql> SET gtid_next = 'AUTOMATIC';

mysql>SETgtid_next='XXX:N';

mysql>BEGIN;COMMIT;

mysql>SETgtid_next='AUTOMATIC';

mysql>SETgtid_next='XXX:N';

sql_slave_skip_countermysql>BEGIN;COMMIT;

mysql>SETgtid_next='AUTOMATIC';

为什么不能使用MySQL 5.6 中的 GTID:新的复制协议; br_MySQL 的新方法2?因为新的复制协议!

想象一下我们有 3 个服务器,如下图所示:sql_slave_skip_counter

    让我们假设
  • 被允许并且已经被允许在 S2 上用于跳过 trx 2。如果将 S2 作为 S1 的从属,会发生什么?
  • 两个服务器将交换已执行 GTID 的范围,并且 S1 将意识到它必须将 trx 2 发送到 S2。那么两个选择:

如果 trx 2 仍在 S1 的二进制日志中,则会发送到 S2,并且不再跳过该事务。sql_slave_skip_counter

如果 trx 2 没有S1 的二进制日志中不再存在,您将收到复制错误。

这显然不安全,这就是为什么

不允许使用 GTID。跳过事务的唯一安全选择是执行假事务而不是真实事务。

错误事务

如果您在从属服务器上本地执行事务(在 MySQL 中称为错误事务)文档),如果你把这个slave提升为新的master会发生什么?

使用旧的复制协议,基本上什么都没有(准确地说,新的master和它的slave之间的数据会不一致,但是那稍后可能会修复)。

使用新协议,错误事务将被识别为到处丢失,并将在故障转移时自动执行,这有可能破坏复制。
# S1mysql> CREATE DATABASE mydb;# Mmysql> CREATE DATABASE IF NOT EXISTS mydb;# Thanks to 'IF NOT EXITS', replication doesn't break on S1. Now move S2 to S1:# S2mysql> STOP SLAVE; CHANGE MASTER TO MASTER_HOST='S1'; START SLAVE;# This creates a conflict with existing data!mysql> SHOW SLAVE STATUS/G[...]Last_SQL_Errno: 1007 Last_SQL_Error: Error 'Can't create database 'mydb'; database exists' on query. Default database: 'mydb'. Query: 'CREATE DATABASE mydb'[...]
# S1

mysql>CREATEDATABASEmydb;

# M

mysql>CREATEDATABASEIFNOTEXISTSmydb;

# Thanks to 'IF NOT EXITS', replication doesn't break on S1. Now move S2 to S1:

# S2

mysql>STOPSLAVE;CHANGEMASTERTOMASTER_HOST='S1';STARTSLAVE;

# This creates a conflict with existing data!

mysql>SHOWSLAVESTATUS/G

[...]

Last_SQL_Errno:1007

              Last_SQL_Error:Error'Can'tcreatedatabase'mydb';databaseexists' on query. Default database: 'mydb'. Query: 'CREATEDATABASEmydb'

[...]
让我们假设你有一个主站 (M) 和 2 个从站 (S1 和 S2)。以下是 2 个简单场景,从节点重新连接到新主节点将会失败(具有不同的复制错误):# 场景 1
# S1 mysql>CREATEDATABASEmydb;# Mmysql>CREATEDATABASEIFNOTEXISTSmydb;# 感谢“IF NOT EXITS”,S1 上的复制不会中断。现在将 S2 移动到 S1:# S2mysql>STOPSLAVE;CHANGEMASTERTOMASTER_HOST='S1';STARTSLAVE;# 这会与现有数据发生冲突!mysql>SHOWSLAVESTATUS /G[...]Last_SQL_Errno:1007              Last_SQL_Error: 查询时出现错误“无法创建数据库“mydb”;数据库存在”。默认数据库:“mydb”。查询:'CREATEDATABASEmydb'[...]

# Scenario 2

# S1mysql> CREATE DATABASE mydb;# Now, we'll remove this transaction from the binary logs# S1mysql> FLUSH LOGS;mysql> PURGE BINARY LOGS TO 'mysql-bin.000008';# Mmysql> CREATE DATABASE IF NOT EXISTS mydb;# S2mysql> STOP SLAVE; CHANGE MASTER TO MASTER_HOST='S1'; START SLAVE;# The missing transaction is no longer available in the master's binary logs!mysql> SHOW SLAVE STATUS/G[...]Last_IO_Errno: 1236Last_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.'[...]
# S1

mysql>CREATEDATABASEmydb;

# Now, we'll remove this transaction from the binary logs

# S1

mysql>FLUSHLOGS;

mysql>PURGEBINARYLOGSTO'mysql-bin.000008';

# M

mysql>CREATEDATABASEIFNOTEXISTSmydb;

# S2

mysql>STOPSLAVE;CHANGEMASTERTOMASTER_HOST='S1';STARTSLAVE;

# The missing transaction is no longer available in the master's binary logs!

mysql>SHOWSLAVESTATUS/G

[...]

Last_IO_Errno:1236

                Last_IO_Error:Gotfatalerror1236frommasterwhenreadingdatafrombinarylog:'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.'

[...]

As you can understand, errant transactions should be avoided with GTID-based replication. If you need to run a local transaction, your best option is to disable binary logging for that specific statement:

mysql> SET SQL_LOG_BIN = 0;mysql> # Run local transaction

mysql>SETSQL_LOG_BIN=0;

mysql># Run local transaction

Conclusion

GTIDs are a great step forward in the way we are able to reconnect replicas to other servers. But they also come with new operational challenges. If you plan to use GTIDs, make sure you correctly understand the new replication protocol, otherwise you may end up breaking replication in new and unexpected ways.

I’ll do more exploration about errant transactions in a future post.

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn