两个关键参数【取自MYSQL官网】
- gtid_executed is computed as the union of the GTIDs in
Previous_gtids_log_event
in the most recent binary log file, the GTIDs of transactions in that binary log file, and the GTIDs stored in themysql.gtid_executed
table. This GTID set contains all the GTIDs that have been used (or added explicitly to gtid_purged) on the server, whether or not they are currently in a binary log file on the server. It does not include the GTIDs for transactions that are currently being processed on the server (@@GLOBAL.gtid_owned
). - gtid_purged is computed by first adding the GTIDs in
Previous_gtids_log_event
in the most recent binary log file and the GTIDs of transactions in that binary log file. This step gives the set of GTIDs that are currently, or were once, recorded in a binary log on the server (gtids_in_binlog
). Next, the GTIDs inPrevious_gtids_log_event
in the oldest binary log file are subtracted fromgtids_in_binlog
. This step gives the set of GTIDs that are currently recorded in a binary log on the server (gtids_in_binlog_not_purged
). Finally,gtids_in_binlog_not_purged
is subtracted from gtid_executed. The result is the set of GTIDs that have been used on the server, but are not currently recorded in a binary log file on the server, and this result is used to initialize gtid_purged.
综上总结:
gtid_executed 是记录着 Mysql server 一直以来执行过的 GTID 记录集合。gtid_purged 是 gtid_executed 的子集,它的 GTID 记录集合是那些已被清除的 binlog 文件上相关的 GTID 记录。通俗公式就是:gtid_purged + 现存的 binlog 文件的 GTIDS = gtid_executed。
GTID 在备份与恢复中的优点与缺点
GTID 是 Mysql 事务的一个标识 ID,Mysql 的 SQL 语句都是以事务的形式运行的,哪怕你不是手工开启的事务。它一般的用处就是能将 binlog 文件分片,类似于数组,GTID 就是数组下标,而它的内容就是事务的执行操作。这样,在增量恢复时就可以很方便的执行你想要的一个GTID范围。同理,Mysql 的主从复制也是借助 GTID 实现的,从库按顺序遍历主库传来 binlog 文件上的 GTID 来执行里面的事务操作,以达到同步主库数据状态的效果。
因为 GTID 是用于标识事务,因此它具有唯一性,也就是说,同一个 GTID 不会在同一个 Mysql 实例上执行2次,这就导致当用带有 GTID 信息的备份文件恢复当前数据库时,会出现 GTID 冲突之类的报错,例如:
ERROR 1840 (HY000) at line 24: @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.
生产环境备份语句:
#全量备份
mysqldump -u$USER -p$PASSWORD -h$HOST -P$PORT --single-transaction -A -R -E --triggers --flush-logs --master-data=2 > all.sql
#单库备份
mysqldump -u$USER -p$PASSWORD -h$HOST -P$PORT --single-transaction -R -E --triggers --flush-logs --master-data=2 $DB > db.sql
mysqldump 默认是带 --set-gtid-purged=ON 的,而这个参数是决定备份文件是否携带 SET @@GLOBAL.GTID_PURGED=【GTID集合】的执行语句,如果不想包含该语句,可以显式写明 --set-gtid-purged=OFF 。
但是按照 MYSQL 官网的说明,In MySQL 5.7, you can only change the value of gtid_purged when gtid_executed (and therefore gtid_purged) is empty. 该规则限制了用 --set-gtid-purged=ON 备份得到的文件只适用于初始化新从库的场景(可能还有别的场景,但是博主暂时没发现新适用场景)。所以当你想用 Mysql 实例 A 的带 GTID 信息的备份文件来恢复 A 上的数据,是会出现 GTID 冲突的相关报错的。
那么,当你的状况只允许你用某个 Mysql 实例的,用 --set-gtid-purged=ON dump 下来的备份文件恢复数据时,你只能借助另外一个可以调用 reset Master 命令的 Mysql 实例又或者是新创建的 Mysql 实例来恢复。操作步骤如下:
1.先执行 reset Master 命令(如果是新创建的数据库实例不需要执行),将备份文件的数据恢复到充当“小白鼠”的 Mysql 实例上。
2.将该全备文件之后的增量日志(binlog文件)也导到数据库上。注意增量日志的 GTID 范围,例如你是因为误操作导致数据丢失,如果不跳过你执行误操作的那个事务对应的 GTID ,那简直是白给一场。
3.将你要恢复表或者库的数据,从“小白鼠”上导出来,此时 mysqldump 命令需要带上 --set-gtid-purged=OFF 参数。
4.最后,set sql_log_bin=0 ( 如果你想把此次恢复操作记录到当前Mysql 实例的 binlog 文件的话,你可以不执行,但一般肯定是不记录的 ),然后再导入你的步骤3导出来的数据文件,可以使用 “source 数据文件路径”的 SQL 语句来执行,再执行 set sql_log_bin=1 将 binlog 日志记录开启。
RESET MASTER 语句的工作原理
以下是官网描述:
When you issue RESET MASTER, the following reset operations are carried out:
- The value of the gtid_purged system variable is set to an empty string (
''
). - The global value (but not the session value) of the gtid_executed system variable is set to an empty string.
- The
mysql.gtid_executed
table is cleared (see mysql.gtid_executed Table). - If the server has binary logging enabled, the existing binary log files are deleted and the binary log index file is cleared.
综上总结:
该命令会将 gtid_executed[全局] 和 gtid_purged 的值置为空字符串,且 mysql.gtid_executed
表的数据,现存的 binlog 文件以及 binlog 的 index 文件也清空。因此该命令对于生产环境要谨慎操作。
想了解更多与运维开发相关的知识分享,可以关注 “沐峯运维” 公众号