* 爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
背景
--single-transaction
和
--master-data
也都加上了,为什么还会出现问题?
猜想
先看下备份出来的 sql 文件,发现了一个与平常不一样的地方,在文件的开头没有看到 SET @@GLOBAL.GTID_PURGED
的语句,排查后发现这个语句写到了文件的结尾。
--
-- GTID state at the end of the backup
--
SET @@GLOBAL.GTID_PURGED='cb75d9d8-5328-11ec-87b4-02000aba3c08:1-13637422';
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2021-11-30 20:24:21复制
Replication: The contents of the gtid_executed and gtid_purged GTID sets were not persisted after restoring a dump taken using mysqldump. The dump file sequence has now been changed so that the mysql schema (which contains the mysql.gtid_executed table) is not dropped after the gtid_purged GTID set is written. A new option --skip-mysql-schema is added for mysqldump which lets you choose not to drop the mysql schema at all. (Bug #32843447)
实验
先创建一张表,往里面造多一点数据,保证有足够的备份时间可以操作:
mysql> create database test;
Query OK, 1 row affected (0.00 sec)
mysql> use test
Database changed
mysql> create table test(id int,name varchar(10),msg varchar(100))engine=innodb;
Query OK, 0 rows affected (0.09 sec)
mysql> insert into test values(1,'aaa','fasgsagaehgag'),(2,'bbb','fasgahfjfjfjfjfjfj'),(3,'ccc','fasg4hegegeege');
Query OK, 3 rows affected (0.03 sec)
Records: 3 Duplicates: 0 Warnings: 0
...
mysql> insert into test select * from test;
Query OK, 3145728 rows affected (17.38 sec)复制
使用 5.7.33 版本的 mysqldump 进行备份:
当前的 gtid 值:
mysql> show master status;
+------------------+-----------+--------------+------------------+-----------------------------------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+-----------+--------------+------------------+-----------------------------------------------+
| mysql-bin.000002 | 123212851 | | | d04c5260-48e3-11ec-865e-02000aba3c05:1-145899 |
+------------------+-----------+--------------+------------------+-----------------------------------------------+
1 row in set (0.00 sec)
然后执行备份:
mysqldump -u -p -h -P --single-transaction --master-data=2 --set-gtid-purged=on -ER --databases test > 1.sql
备份过程中用另外一个线程插入数据:
mysql> insert into test values(5,'qqq','gdhdhdjhdjdjdjdjd');
Query OK, 1 row affected (0.02 sec)复制
SET @@GLOBAL.GTID_PURGED
语句在文件的开头,值为d04c5260-48e3-11ec-865e-02000aba3c05:1-145899
,数据里不包含备份过程中插入的行。
SET @@GLOBAL.GTID_PURGED
语句在文件的结尾,值为d04c5260-48e3-11ec-865e-02000aba3c05:1-145900
,数据里不包含备份过程中插入的行。
排查
我们再从 general log 去寻找问题的根本原因,下面来看下两次备份时 general log 里的内容:
5.7.33:
2021-12-02T15:57:49.407761+08:00 91450 Query /*!40100 SET @@SQL_MODE='' */
2021-12-02T15:57:49.408036+08:00 91450 Query /*!40103 SET TIME_ZONE='+00:00' */
2021-12-02T15:57:49.408243+08:00 91450 Query FLUSH /*!40101 LOCAL */ TABLES
2021-12-02T15:57:49.408874+08:00 91450 Query FLUSH TABLES WITH READ LOCK
2021-12-02T15:57:49.409007+08:00 91450 Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
2021-12-02T15:57:49.409112+08:00 91450 Query START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */
2021-12-02T15:57:49.409433+08:00 91450 Query SHOW VARIABLES LIKE 'gtid\_mode'
2021-12-02T15:57:49.413486+08:00 91450 Query SELECT @@GLOBAL.GTID_EXECUTED
2021-12-02T15:57:49.413648+08:00 91450 Query SHOW MASTER STATUS
2021-12-02T15:57:49.413758+08:00 91450 Query UNLOCK TABLES
...
2021-12-02T15:58:06.659969+08:00 91450 Quit
5.7.36:
2021-12-02T16:24:08.865982+08:00 93058 Query /*!40100 SET @@SQL_MODE='' */
2021-12-02T16:24:08.866188+08:00 93058 Query /*!40103 SET TIME_ZONE='+00:00' */
2021-12-02T16:24:08.866355+08:00 93058 Query FLUSH /*!40101 LOCAL */ TABLES
2021-12-02T16:24:08.867006+08:00 93058 Query FLUSH TABLES WITH READ LOCK
2021-12-02T16:24:08.867110+08:00 93058 Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
2021-12-02T16:24:08.867214+08:00 93058 Query START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */
2021-12-02T16:24:08.867379+08:00 93058 Query SHOW VARIABLES LIKE 'gtid\_mode'
2021-12-02T16:24:08.869615+08:00 93058 Query SHOW MASTER STATUS
2021-12-02T16:24:08.869788+08:00 93058 Query UNLOCK TABLES
...
2021-12-02T16:24:21.685552+08:00 93058 Query SELECT @@GLOBAL.GTID_EXECUTED
2021-12-02T16:24:21.754689+08:00 93058 Quit复制
@@GLOBAL.GTID_EXECUTED
后才释放锁,这样可以保证数据和 GTID 能保持一致。
但 5.7.36 是在备份完所有数据之后才去获取 @@GLOBAL.GTID_EXECUTED
,这样意味着备份期间新增的 GTID 也写到了备份文件里,但没有备份相关的数据,导致数据和 GTID 不一致。
总结
SET @@GLOBAL.GTID_PURGED
顺序都与旧版本一样。通过对比源码,发现这个改动没有出现在 8.0.27 的 mysqldump 代码中,不知道为什么会有这样的情况。
已将此问题提交给官方:https://bugs.mysql.com/bug.php?id=105761
文章推荐:
社区近期动态

