本帖最后由 mkt_cemon 于 2017-6-19 17:42 编辑
日常mysql运维中,使用mysqldump进行数据库和表的备份是非常普遍和高效的命令。那么mysqldump是如何保证备份出来的数据是一致的?接下来我们使用mysql的general log来跟踪分析一下备份的过程。
mysqldump命令在做备份时,为了保证数据的一致性和便于在指定时间点的恢复,通常需要跟single-transaction和master-data两个参数一起使用,所以在分析之前,我们先简单介绍一下这两个参数的含义:
--single-transaction:
1.png (376.33 KB, 下载次数: 15)
2017-6-19 17:24 上传
在开启dump操作时,会创建一个快照,这相当于此刻的一致性视图,即在整个dump的过程中是被当做一个事务的,这样就能保证同一事务下读取的数据都是一致的。但是此时如果有其他会话在做DDL操作(ALTER/DROP/RENAME/TRUNCATE TABLE),则会破坏数据的一致性,所以需要添加lock-tables锁住表用来保证数据的一致性。
--master-data:
2.png (374.99 KB, 下载次数: 5)
2017-6-19 17:25 上传
此命令是为了获取在dump时候的master 的binlog文件名和position的位置。当他等于1时,显示change master的输出结果。等于2时,注释掉此命令的输出结果。由此我们可以知道,当等于1时dump出来的数据,恢复在slave上是非常方便的。
接下来,我们就开启general log来跟踪dump的过程:
一、确保generallog正常开启
3.png (272.95 KB, 下载次数: 6)
2017-6-19 17:26 上传
二、本实验使用test1库作为需要备份出来的库,且库中有表数据。
4.png (326.39 KB, 下载次数: 2)
2017-6-19 17:27 上传
5.png (208.32 KB, 下载次数: 3)
2017-6-19 17:39 上传
三、使用mysqldump备份出test1库
[root@localhost~]# mysqldump -uroot -p --single-transaction --master-data=2 -B test1>2T.sql
四、备份完成后查看general log内容如下:
6.png (463.09 KB, 下载次数: 3)
2017-6-19 17:39 上传
7.png (467.7 KB, 下载次数: 4)
2017-6-19 17:40 上传
8.png (394.89 KB, 下载次数: 7)
2017-6-19 17:40 上传
五、分析mysqldump过程:
第二行:可以看出dump命令链接正式进入数据库。
第五行:flushtables操作。该操作会将内存中缓存的表结构数据同步到磁盘中。
第六行:做了FLUSH TABLES WITH READ LOCK操作获得一个全局锁,确保此时数据是一致的。
第七行:将当前会话的事务隔离级别恢复成默认的RR模式,使得当前事务可重复读。
第八行:开启一个事务,并设置成快照级别。
第九行:查询数据库的GTID是否开启。
第十行:获取binlog的文件名及position的位置。
第十一行:释放全局锁。
第十二行至十三行:通过select语句查询test1库的状态。
第十四行:查询一下字典。
第十五行:进入要备份的test1库。
第十六行:查看建库语句。
第十七行:创建一个事务恢复点sp。
第十八行:查看需要备份的库中都有哪些表。
第十九行:查看表T1状态。
第二十行:设置表名和列名的格式。
第二十一行:设置字符集为二进制。
第二十二行:查看T1的建表语句。
第二十三行:设置字符集为UTF8。
第二十四行:输出表的所有信息。
第二十五行:查询T1中数据,如果表中数据很大,mysql会使用limit来进行分段获取。
第二十六行:设置字符集为二进制。
第二十七行:进入test1库。
第二十八行:查看数据库的编码格式。
第二十九行:查看T1表的触发器。
第三十行:设置字符集为UTF8。
第三十一行:ROLLBAKC到sp事务点。
第三十二行至四十四行:相同操作获取test1库中的T2表数据。
第四十五行:当所有数据都获取完成后释放掉事务回滚点sp。
至此,我们可以总结下mysqldump的备份原理:通过设置READ LOCK获取数据库全局锁后,RR事务隔离级别下记录当前的日志文件名和日志位置position,然后释放掉全局锁。接下来创建一个事务的回滚点,所有数据的获取都是获取的是这个sp回滚点数据。最后释放掉回滚点sp。当然,对于MyISAM存储引擎,备份是直接锁全表的。
值得注意点:从分析mysqldump过程中我们可以知道,此命令在开始时刻会带来数据库瞬时的锁定(FLUSHTABLES WITH READ LOCK),虽然锁定时间是非常短暂的,但是却会带来非常大的数据库隐患,因为在此过程中,如果执行有DDL语句,就会导致此命令堵塞并最终异常退出。所以在做备份时间节点的选择上,需要根据数据库环境选择在负载压力最小,且没有以上操作时候进行备份。