日常mysql运维中,使用mysqldump进行数据库和表的备份是非常普遍和高效的命令。那么mysqldump是如何保证备份出来的数据是一致的?接下来我们使用mysql的general log来跟踪分析一下备份的过程。
mysqldump命令在做备份时,通常需要跟single-transaction和master-data两个参数一起使用才能保证数据的一致性,所以在分析之前,我们先简单介绍一下这两个参数的含义:
--single-transaction:

在开启一个事务dump前,创建一个快照,并设置事务的隔离级别为RR模式(可重复读模式),这样就能保证同一事务下读取的数据都是一致的。但是此时如果有其他会话在做DDL操作(ALTER/DROP/RENAME/TRUNCATE TABLE),则会破坏数据的一致性,所以需要添加lock-tables锁住表用来保证数据的一致性。
--master-data:

此命令是为了获取在dump时候的master 的binlog文件名和position的位置。当他等于1时,显示change master的输出结果。等于2时,注释掉此命令的输出结果。由此我们可以知道,当等于1时dump出来的数据,恢复在slave上是非常方便的。
接下来,我们就开启general log来跟踪dump的过程:
一、确保general log正常开启

二、本实验使用test1库作为需要备份出来的库,且库中有表数据。


三、使用mysqldump备份出test1库
[root@localhost ~]# mysqldump -uroot -p --single-transaction --master-data=2 -B test1 >2T.sql
四、备份完成后查看general log内容如下:



五、分析mysqldump过程:
第二行:可以看出dump命令链接正式进入数据库。
第五行:做了flush tables操作。为了防止有DDL操作。
第六行:做了FLUSH TABLES WITH READ LOCK操作获得一个全局锁,确保此时数据是一致的。
第七行:将当前会话的事务隔离级别改为RR模式,为了让当前事务可重复读。
第八行:开启一个事务,并设置成快照级别。
第九行:查询数据库的GTID是否开启。
第十行:获取binlog的文件名及postition的位置。
第十一行:释放全局锁。
第十二行至十三行:通过select语句查询test1库的状态。
第十四行:查询一下字典。
第十五行:进入要备份的test1库。
第十六行:查看建库语句。
第十七行:创建一个事务恢复点sp。
第十八行:查看需要备份的库中都有哪些表。
第十九行:查看表T1状态。
第二十行:设置表名和列名的格式。
第二十一行:设置字符集为二进制。
第二十二行:查看T1的建表语句。
第二十三行:设置字符集为UTF8。
第二十四行:输出表的所有信息。
第二十五行:查询T1中数据,如果表中数据很大,mysql会使用limit来进行分段获取。
第二十六行:设置字符集为二进制。
第二十七行:进入test1库。
第二十八行:查看数据库的编码格式。
第二十九行:查看T1表游标。
第三十行:设置字符集为UTF8。
第三十一行:ROLLBAKC到sp事务点。
第三十二行至四十四行:相同操作获取test1库中的T2表数据。
第四十五行:当所有数据都获取完成后释放掉事务回滚点sp。
至此,我们可以总结出,mysqldump在备份时候,是通过设置数据库全局锁后,设置RR事务隔离级别使得当前事务可以进行重复读,然后记录下当前的日志位置。然后释放掉全局锁。接下来创建一个事务的回滚点,所有的数据都是获取的这个回滚点sp时候的数据。最后释放掉回滚点。这样就能保证备份的数据都是一致性的(sp点)。




