# 备份 ## 概述 通常来讲,备份分为如下类型: - Hot Backup(热备):在数据库运行的同时直接备份,同时也被称为`在线备份` - Cold Backup(冷备):在数据库停止的情况下进行备份,一般只需要复制数据库的物理文件`离线备份` - Warm Backup(温备):Warm Backup类似于Hot Backup,同样也是在数据库运行时进行备份,但是和Hot Backup相比,Warm Backup会对当前数据库的操作存在影响(`例如,在备份时添加全局的共享锁,从而保证备份数据的一致性`)、 按照备份后的文件内容,也可以对备份做出如下划分: - 逻辑备份:对mysql而言,逻辑备份代表备份后产生的文件,其文件内容是可读的,一般由文本组成,内容是`sql语句`或是`表内的实际数据` - 常用的逻辑备份有`mysqldump`和`select * into outfile`等,这种方式可以观察导出文件的内容 - 对于逻辑备份而言,其恢复过程一般耗时较长 - 裸文件备份:裸文件备份是指对数据库的物理文件进行复制,既可以在数据库运行时进行复制,也可以在数据库停止运行时复制 - 对于裸文件备份,其数据恢复的耗时一般远小于逻辑备份 若按照数据库备份的内容,即可以对备份做出如下划分: - 完全备份:完全备份是指对数据库中所有数据做一个全量备份 - 增量备份:增量备份是指在上次完全备份的基础上,对发生修改的数据进行备份 - 日志备份:对于mysql而言,日志备份主要是指对mysql数据库的binlog进行备份,其记录了`对数据库造成修改的事件`,通过对binlog进行replay,能够实现数据库的`point-in-time`恢复 - 对于mysql数据库的`replication`,其原理即是异步的将binlog传输到slave数据库,并在slave数据库对binlog的内容进行replay ### 增量备份原理 在mysql中,并没有官方的增量备份方法被提供,大多是通过binlog来完成增量备份的工作。通过binlog来实现的备份较增量备份方案来说效率较低。 `xtrabackup`工具提供了增量备份方案,其原理是通过记录每页最后的checkpoint lsn,如果大于之前全量备份时的lsn,那么就对该页进行备份,否则无需备份该页。 ### 数据一致性 在进行数据备份时,`要求数据在备份时是一致的`。例如在玩家购买道具时,其会先扣款并对道具进行增加,如果数据不一致,那么则可能发生扣款已经发生但是道具尚未被添加这类数据不一致的情况。 对于innodb而言,由于其支持mvcc,故而对保证数据一致性的备份实现比较简单。在备份时,可以先开启一个事务,然后导出一系列相关的表,然后提交。由于undo log和read view的设计,可以保证事务中读取到的数据是一致的。 对于mysqldump工具而言,可以通过添加`--single-transaction`选项来获取innodb的一致性备份,原理和上述所示的相同,备份逻辑会在一个长事务中执行。`在使用mysqldump进行备份时,务必添加--single-transaction选项`。 ## Cold Backup 对于innodb存储引擎而言,cold backup相对简单,只需要备份mysql数据库的frm文件(mysql8中没有该类型文件)、共享表空间文件、独立表空间文件、redo log文件即可。另外,建议定期备份mysql数据库的配置文件`my.cnf`,有利于恢复操作。 cold backup存在如下优点: - 备份简单,仅需复制相关文件即可 - 备份文件易于在不同操作系统、不同mysql版本上进行复制 - 恢复速度快,仅需拷贝文件即可,无需执行sql语句也无需进行索引重建 cold backup存在如下缺点: - innodb存储引擎的cold backup文件通常要比逻辑文件大很多,因为表空间中存放着很多其他数据,例如`undo log段`和`change buffer`等 - cold backup并不总是可以轻易跨平台,操作系统、mysql版本、文件大小写敏感、浮点格式都会造成问题 > change buffer也是系统表空间的一部分,故而,change buffer也存在磁盘页。在进行cold backup时,同样需要备份change buffer。 ## 逻辑备份 ### mysqldump mysqldump工具通常用于创建数据库的备份或是在不同数据库之间对数据进行移植,如从mysql低版本升级到mysql高版本,或从mysql数据库迁移到oracle、sql server等数据库。 mysqldump的语法如下所示: ```sql mysqldump [arguments] >file_name ``` 如果想用mysqldump备份所有的数据库,可以使用如下命令: ```sql mysqldump --all-databases >dump.sql ``` 如果想要备份指定的数据库,可以使用如下命令 ```sql mysqldump --databases db1 db2 db3 > dump.sql ``` 通过`--single-transaction`可以保证备份的一致性,示例如下: ```sql mysqldump --single-transaction test >test_backup.sql ``` 上述操作针对`test`数据库创建了一个备份。 备份出的内容为表结构和表数据。 mysqldump命令用友如下较为重要的参数: #### --single-transaction 当指定了`--single-transaction`参数后,其在备份开始前会先执行`start transaction`命令,从而保证备份数据的一致性。 该参数只针对innodb存储引擎有效,且在启用该参数进行备份时,需要确保没有ddl语句在执行,一致性读操作并不能对ddl进行隔离。 #### --lock-tables(`-l`) 在备份时,会依次对表进行锁定,一般用于myisam存储引擎,在备份时只能对数据库执行读操作,同样可以保证备份的一致性。 对于innodb存储引擎,并不需要使用`-l`参数,使用`--single-transaction`参数即能够保证备份数据的一致性。 > `--single-transaction`选项和`--lock-tables`选项是互斥的,并不能够同时指定。 #### --lock-all-tables(`-x`) 在使用`-x`时,会针对数据库中所有的表都进行加锁,其能够避免`--lock-tables`不能锁住所有的表的问题。 #### --add-drop-database 在`create database`之前先调用`drop database`,该选项需要和`--all-databases`/`--databases`一起使用。默认情况下,导出的备份中并不会含有`create database`语句,除非手动指定该选项。 #### --routinues 该选项用于备份存储过程和函数 #### --triggers 该选项用于备份触发器 #### --hex-blob 将`binary, varbinary, blog, text`类型备份为16进制的格式。 ### select ... into outfile `select ... into outfile`也是一种逻辑备份方法,用于导出一张表中的数据,示例如下: ```sql select * into outfile '/root/a.txt` from a; ``` 其中,导出路径的权限必须是`mysql:mysql`的,否则mysql会报错没有导出权限。 如果想要导出的文件已经存在,同样也会报错。 ## 逻辑备份恢复 ### mysqldump mysqldump的逻辑备份恢复比较简单,只需要执行备份出的sql语句即可,示例如下 ```bash mysql -uroot -p source /home/mysql/test_backup.sql ``` ### 二进制日志的备份和恢复 通过二进制日志,用户可以实现point-in-time的恢复。 在备份二进制日志之前,可以通过`flush logs`命令来生成一个新的二进制日志文件,然后对之前的二进制日志文件进行备份。 可以通过`mysqlbinlog`命令对二进制日志进行恢复,示例如下: ```bash mysqlbinlog binlog.0000001 | mysql -uroot -p test ``` 如果要恢复多个二进制文件,可以按照如下方式: ```bash mysqlbinlog binlog.[0-10]* | mysql -u root -p test ``` 也可以通过`mysqlbinlog`命令导入到一个文件,然后再对文件执行source。 可以通过`--start-position`和`--stop-position`从二进制日志的指定偏移量来进行恢复,这样可以针对某些语句进行跳过,示例如下: ```bash mysqlbinlog --start-position=107856 binlog.0000001 | mysql -uroot -p test ``` `--start-datetime`和`--stop-datetime`则是可以选择从二进制日志的某个时间点来进行恢复。