背景其实出现在两周前了,当时只是简单地排查了下原因就草草了事,今天再次仔细研究了下官方文档,发现还是有些嚼头的,多半是自己之前没有去刻意的思考,其实一点点小特性,有时候还是可以让我们的工作简化很多的。
这个小案例可能对于某些人来说并不陌生,当时的情境是给一个客户执行一个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来复制出一个从库的需求,结构如下
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
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
即从一个生产库通过mysqldump复制出一个从库,并且与当前实例互为主备,结构如下。 这里不讨论非gtid模式了,和前面所说的使用方式一致。 而在讨论gtid模式下的这种场景之前,这里先回归到这个案例,为什么mysql默认会有这个举动,自动禁掉导入操作的binlog生成?先回顾下gtid特性的使用方式,一个实例的全局事务id,不管在哪个实例上被使用,标识方式都是server_uuid:tran_id,其中server_uuid标识角色,tran_id标识执行的事务,而gtid_purge参数标识已经执行过的某个实例上的事务。因此,dump文件导入意味着从实例执行了主库上id为m--n的事务,而这些更新默认不被认为是从实例上的行为,这种思维是很科学的,因为复制,即代表接受某个实例对数据的变更。 而主库只需要做一个简单的change master指令就够了,因为新添加的从库并没有任何更新操作。或许有些人曾经有过困惑,在线做这么奇葩的事情,本来很紧张,然后莫名其妙的很简单就搞定了。。
这种场景也是我们平时工作中比较常见的,即需要在线新增一个从库。结构如下
--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
虽然只是一个小小的案例,却能带来很多思考,看来真正理解一款产品,对于平时的运维工作还是十分重要的。