mysql数据备份从备份方式上可分为物理备份和逻辑备份,物理备份有mysql企业版自带工具,或者选择percona的开源备份工具percona-xtra-backup,可以简称pxb。
pxb主要对innodb引擎的表进行备份,同时也会全备份myisam表数据,原理大概是这样:开启读取redo日志的线程,记录备份期间数据的变化情况,同时记录下此刻的lsn,然后以page为单位扫描出所有数据文件中page块中lsn号小于等于之前记录的lsn号的page,即找出了所有在备份期间没有修改的page块,同时加上读取的redo日志内容,那么在数据恢复的时候,通过备份文件加上日志文件即可恢复出完整的innodb引擎数据。
本篇主要说mysqldump,重新认识下mysqldump这个常用的工具。mysqldump是mysql自带的逻辑备份工具,多用于数据量较小的库做整库备份,把数据结构和内容以语句的形式备份成便于执行的sql文件,数据迁移相对简单,数据量小的时候也非常快捷。(数据量在百G以内可以使用)
这里不多介绍具体的命令,我们重点关注mysqldump如何在数据导出过程中保持某个时点的数据一致性,也就是说在导出所有数据,均是这一时点的数据,不会因为表在导出过程中,其他dml操作对导出数据造成影响。
直接给出生产中使用备份命令:
mysqldump -ubacker -p --default-character-set=utf8 --single-transaction --flush-logs --master-dat
a=2 --databases test1 test2 test3 | gzip > $backupdir/full_iTOU_$time.sql.gz
重点关注 --single-transaction --flush-logs --master-data=2 这三个选项
官方手册中对single-transaction
--single-transaction
This option sets the transaction isolation mode to REPEATABLE READ and sends a START TRANSACTION SQL statement to the server before dumping data. It is useful only with transactional tables such as InnoDB, because then it dumps the consistent state of the database at the time when START TRANSACTION was issued without blocking any applications.
这个选项做了两件事情,1是设置了事务的隔离级别为可重复读,2是启动了事务;起到的作用就是:对于innoDB,保证了导出数据的一致性,并且不会阻塞应用系统。
When using this option, you should keep in mind that only InnoDB tables are dumped in a consistent state. For example, any MyISAM or MEMORY tables dumped while using this option may still change state.
这个选项能够保证导出InnoDB引擎的表是一致性的状态,其他引擎MyISAM或者MEMORY表的导出数据仍然可能不是一致性状态的。
While a --single-transaction dump is in process, to ensure a valid dump file (correct table contents and binary log coordinates), no other connection should use the following statements: ALTER TABLE, CREATE TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE. A consistent read is not isolated from those statements, so use of them on a table to be dumped can cause the SELECT that is performed by mysqlpump to retrieve the table contents to obtain incorrect contents or fail.
在导出数据的过程中,需要保证dump文件的有效性;因为ALTER TABLE, CREATE TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE 这些DDL语句会改变表结构,一致性读并不会对隔离这些语句,那么这些语句会导致导出数据不正确或者失败。
那我们使用--single-transaction,并开启general日志,看看具体都做了什么操作。
tips:在研究mysql后台操作时,可以把详细日志开启,以便获取更细致的信息。
Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
设置隔离级别为可重复读
Query START TRANSACTION /*!40100 WITH CONSISTENT SNAPSHOT */
开启事物并且设置一致性快照,在这个transaction中所有的查询均能得到同一版本的数据,通过MVCC来实现。
注意:
(1)此刻打开其他session对表做DML操作:例如,表中有100万行数据,delete这个表的所有数据,然后再插入100万行数据,正常情况下表空间大小应该和原空间大小差不多;但这个时候的因为插入100万数据,会增加几乎一倍,也就是说实际上物理上100万行数据因为有session需要,并未真正的在磁盘中删除。
也就是通过mvcc的数据的快照版本会存放在自身的数据表空间里,在未真正失去作用之前,会一直保留。
另外与ORACLE数据库做对比,已删除数据的快照从UNDO表空间去获取,如果UNDO表空间内数据被覆盖无法找到,则会报错到前端,ORA-01555快照过久
(2)此时并不会对表结构做保护,如果对表做ddl操作,会导致导出报错。
mysqldump: Couldn't execute 'show create table `z_test`': Table 'test.z_test' doesn't exist (1146)
再看看--single-transaction --master-data=2
官方手册中master-data 参数的解释:
Use this option to dump a master replication server to produce a dump file that can be used to set up another server as a slave of the master. 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 server. These are the master server coordinates from which the slave should start replicating after you load the dump file into the slave.
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. If no option value is specified, the default value is 1.
This option requires the RELOAD privilege and the binary log must be enabled.
The --master-data option automatically turns off --lock-tables. It also turns on --lock-all-tables, unless --single-transaction also is specified, in which case, a global read lock is acquired only for a short time at the beginning of the dump (see the description for --single-transaction). In all cases, any action on logs happens at the exact moment of the dump.
It is also possible to set up a slave by dumping an existing slave of the master, using the --dump-slave option, which overrides --master-data and causes it to be ignored if both options are used.
使用这个选项备份出的文件可以做用来搭建slave,输出的dump文件中有change master to的语句,包含二进制日志文件的坐标,用来告诉slave该从哪里开始进行日志的复制。
如果选项值是2,这条语句会被加注释;如果选项值是1,则语句没注释,还原的时候会被执行;
使用此选项,会默认关闭--lock-tables和--lock-all-tables选项。
为了确保备份出来的数据在某一个时点的一致性,可以通过两种方式来实现:
(1)先对所有表加读锁,备份数据,等待备份数据结束后,解开读锁。
主要通过flush table with read lock来实现,FTWRL三个步骤
1.上全局读锁(lock_global_read_lock)
2.清理表缓存(close_cached_tables)
3.上全局COMMIT锁(make_global_read_lock_block_commit)
(2)先对所有表加读锁,设置隔离级别为可重复读,开启事物,解锁,备份数据。
因为开启了事务,查询结果的一致性可以通过MVCC多版本并发控制来实现。
那么实际上持有读锁的时间会非常短,也就是通常 --single-transaction 加--master-data联合使用的原因。
第一种方法会加MDL 元数据锁,备份期间所有表的DML,DDL均无法执行。
第二种方法通过MVCC来实现,备份期间可以对表执行DDL操作,可能会导致整体数据结构不一致。
值得注意的是 flush table 是个比较重的动作,可能会引起问题,例如:
SESSION a:一个大表的查询正在执行,
SESSION b:执行flush table命令,需要等待查询结束后做再表缓存的清理,此时等待状态为(Waiting for table flush)
这时如果有第三个session查询查询此表,则同样会被阻塞,等待状态为(Waiting for table flush)