写在前面
背景其实出现在两周前了,当时只是简单地排查了下原因就草草了事,今天再次仔细研究了下官方文档,发现还是有些嚼头的,多半是自己之前没有去刻意的思考,其实一点点小特性,有时候还是可以让我们的工作简化很多的。
奇怪的小案例
这个小案例可能对于某些人来说并不陌生,当时的情境是给一个客户执行一个dump文件,就这么一个小小的操作,后来尽然让客户发现了蹊跷:导入的数据备库上没有。
同事告知给我的情况,我也是觉得蛮不可思议,立马与客户配合客户再次确认,发现确实是操作没有同步过去,马上检查了主备复制状况,一切正常。
同事怀着侥幸的心理打开dump文件,发现了如下一个明显的SET指令:
SET @@SESSION.SQL_LOG_BIN= 0;
这个指令大家一看便知,就是在会话级临时禁掉binlog的产生,看来这个蹊跷的问题就是由它所致。那么为什么mysqldump的导出文件会出现这个set指令呢?
马上就在官方文档上找到了答案。
The --set-gtid-purged option has the following effect on binary logging when the dump file is reloaded:
● --set-gtid-purged=OFF: SET @@SESSION.SQL_
LOG_BIN=0; is not added to the output.
● --set-gtid-purged=ON: SET @@SESSION.SQL_LOG_BIN=0; is added to the output.
● --set-gtid-purged=AUTO: SET @@SESSION.SQL_LOG_BIN=0; is added to the output if GTIDs are enabled on the server you are backing up (that is, if AUTO evaluates to ON).
This option was added in MySQL 5.6.9.
那么再来概述一下事情的原由。这个导出文件的源数据库开启了gtid mode,因此默认的dump选项导致了dump文件中添加指令'SET @@SESSION.SQL_LOG_BIN= 0;',然后在客户的另一个主备环境进行导入,由于主库导入的操作没有产生任何binlog,因此备库上没有主库新导入的数据。
人工补完数据后,告知客户可以通过--set-gtid-purged这个参数来控制导入操作是否被复制。
故事卒。
mysqldump的复制支持选项
案例过后,除了诧异,便是对mysqldump的复制选项重新研究了一番,稍微总结了下,发现还是有点收获。接下来简单归类,聊一下基于mysqldump的特性,如何简单的做复制架构搭建。
1.主从结构
这种场景最简单,就是从一个生产库通过mysqldump来复制出一个从库的需求,结构如下
1)非gtid mode
master-data选项:
If the option value is 2, the CHANGE MASTER TO statement is written as an SQL comment, and thus is informative only; it has no effect when the dump file is reloaded. If the option value is 1, the statement is not written as a comment and takes effect when the dump file is reloaded.
从这里可以看到,在非gtid模式下,通过--master-data选项,可以将主库dump时的binlog file以及position记录下来,那么change master就会变得很简单,甚至在innodb引擎下,在线添加从库根本不需要对主库形成任何阻塞。
如下,
# mysqldump -h127.0.0.1 -uroot -p -P3301 --single-transaction --master-data=2 test t1
2)gtid mode
set-gtid-purged选项
This option enables control over global transaction ID (GTID) information written to the dump file, by indicating whether to add a SET @@global.gtid_purged statement to the output. This option may also cause a statement to be written to the output that disables binary logging while the dump file is being reloaded.
而在gtid模式下,这个操作变得更加简单,设置这个参数为ON(或者默认值),我们甚至不需要关心从库执行到了哪个主库上的transaction id,因为dump命令执行时的gtid被记录下来,并且直接用来设置从库的gtid_purged参数,这个就是为什么gtid模式下在线添加从库如此简单的原因。
如下,
# mysqldump -h127.0.0.1 -uroot -p -P3301 --single-transaction --set-gtid-purged=ON test t1
2.主主结构
即从一个生产库通过mysqldump复制出一个从库,并且与当前实例互为主备,结构如下。
这里不讨论非gtid模式了,和前面所说的使用方式一致。
而在讨论gtid模式下的这种场景之前,这里先回归到这个案例,为什么mysql默认会有这个举动,自动禁掉导入操作的binlog生成?先回顾下gtid特性的使用方式,一个实例的全局事务id,不管在哪个实例上被使用,标识方式都是server_uuid:tran_id,其中server_uuid标识角色,tran_id标识执行的事务,而gtid_purge参数标识已经执行过的某个实例上的事务。因此,dump文件导入意味着从实例执行了主库上id为m--n的事务,而这些更新默认不被认为是从实例上的行为,这种思维是很科学的,因为复制,即代表接受某个实例对数据的变更。
而主库只需要做一个简单的change master指令就够了,因为新添加的从库并没有任何更新操作。或许有些人曾经有过困惑,在线做这么奇葩的事情,本来很紧张,然后莫名其妙的很简单就搞定了。。
3.一主多从结构
这种场景也是我们平时工作中比较常见的,即需要在线新增一个从库。结构如下
--dump-slave
This option is similar to --master-data except that it is used to dump a replication slave server to produce a dump file that can be used to set up another server as a slave that has the same master as the dumped server. It causes the dump output to include a CHANGE MASTER TO statement that indicates the binary log coordinates (file name and position) of the dumped slave's master.
--include-master-host-port
For the CHANGE MASTER TO statement in a slave dump produced with the --dump-slave option, add MASTER_HOST and MASTER_PORT options for the host name and TCP/IP port number of the slave's master.
从这里可以看到,这两个选项可以让你从一个从库上复制实例的时候,即获取到一个数据副本,同时收获需要做的change master语句,轻松地从A→B复制出一个A→C。也就是从当前从库,复制出一个新的从库,两个从库同时指向一个主库。这样不管是否为gtid模式,都能够在完全不影响主库的前提下扩展从库。
gtid模式如下,
# mysqldump -h127.0.0.1 -uroot -p -P3302 --single-transaction --set-gtid-purged=ON --dump-slave=2 --include-master-host-port liu testb
非gtid模式如下,
# mysqldump -h127.0.0.1 -uroot -p -P3302 --single-transaction --set-gtid-purged=OFF --dump-slave=2 --include-master-host-port liu testb
结语
虽然只是一个小小的案例,却能带来很多思考,看来真正理解一款产品,对于平时的运维工作还是十分重要的。