1.前言
本章记录数据库的备份与恢复操作。MySQL提供了很多工具完成备份工作:mysqldump、ibbackup、replication,也可以使用一些第三方的工具完成,如xtrabacup、LVM快照等。
2.备份与恢复概述
根据备份方法的不同,可以将备份分为:
Hot Backup(热备):指的是在数据库运行中直接备份,对运行没有影响
Cold Backup(冷备):在数据库停止的情况下,这种备份最简单,一般就复制物理文件即可
Warm Backup(温备):在数据库运行中,但是对数据库操作会有影响,如加一个全局的读锁保证备份数据的一致性
备份后的文件,又可以分为:
逻辑备份:指备份出的文件内容是可读的,一般是文本文件,内容是一条条SQL语句,或者是表内实际数据组成。如mysqldump和select * into outfile的方法。这类方法的好处是可以观察导出的文件内容,一般适用于数据库的升级、迁移等工作。但是缺点是恢复所需要的时间往往比较长。
裸文件备份:指复制数据库的物理文件,既可以是在数据库运行中的复制,也可以是在数据库停止运行时直接的数据文件复制。这类备份的恢复时间往往较逻辑备份要短。
按照备份数据库的内容,又可分为:
完全备份:对数据库进行一个完整的备份
增量备份:对上次完整备份的基础上,对更改的数据进行备份
日志备份:通过对一个完全备份进行二级制日志的重做来完成数据库的point-in-time的恢复工作。MySQL数据库的复制原理就是异步实时地将二进制日志重做传送并应用到从数据库。
对MySQL来说,官方没有提供真正的增量备份的方法,大部分是通过二进制日志完成增量备份的工作。这种备份较之真正的增量备份来说,效率还是很低的。因为可能对一个页执行多次SQL完成重做。对于真正的增量备份,只需要记录当前每页最后的检查点的LSN,如果大于之前全备时的LSN,则备份该页,否则不用备份,这大大加快了备份的速度和恢复的时间,同时也是xtrabackup工具增量备份的原理。
此外还要注意理解数据库备份一致性,要求在备份的时候数据在这一时间点上是一致的。例如:买东西,扣钱得东西,但是备份过程中备份了扣钱,而没有备份得东西就很糟糕了。
InnoDB支持MVCC功能,因此实现一致的备份比较简单。用户可以先开启一个事务,然后导出一组相关的表,最后提交。事务的隔离级别当然是要REPEATABLE READ,这样就可以给出一个完美的一致性备份。
对于mysqldump备份工具来说,可以通过添加--single-transaction选项获得InnoDB存储引擎的一致性备份,原理和之前所说的相同。
最后,任何时候都需要做好远程异地备份,容灾的防范。
3.冷备
对于InnoDB存储引擎的冷备非常简单,只需要备份MySQL数据库的frm文件,共享表空间文件,独立表空间文件*.ibd,重做日志文件。另外,建议备份MySQL数据库的配置文件my.cnf,有利于恢复操作。
一台机器的冷备是不够的,要将数据放在远程的机房。
冷备的优点是:
备份简单,只需要复制相关文件即可
备份文件易于在不同操作系统,不同MySQL版本上进行恢复
恢复相当简单,只需要把文件恢复到指定位置即可
恢复速度快,不需要执行任何SQL语句,也不需要重建索引
冷备的缺点是:
文件比逻辑文件大很多,因为表空间存放很多其它数据,比如undo段,插入缓冲等。
冷备也不总是可以轻易跨平台,操作系统、MySQL版本、文件大小写敏感、浮点数格式都会成为问题。
4.逻辑备份
4.1 mysqldump
mysqldump [arguments] > file_name
如果想备份所有的数据库,使用--all-databases选项:
mysqldump --all-databases > dump.sql
如果想要备份指定的数据库 --databases db1 db2 db3
如果想要对test这个架构进行备份,可以使用:
mysqldump --single-transaction test > test_backup.sql 之前说了--single-transaction用于保证备份的一致性
参数有很多,可以使用mysqldump --help查看,下面介绍一些比较重要的参数:
--single-transaction: 在备份开始前,先执行START TRANSACTION命令,以获得备份的一致性,当前该参数只对InnoDB存储引擎有效。
--lock-tables:在备份中,一次锁住每个架构下的所有表。一般用于MyISAM存储引擎,可以保证一致性。这个参数与上面参数是互斥的,只能用一个。如果有两种表,只能选择这个。但是只能保证同一架构下的一致性,不能保证所有架构下的一致性。
--lock-all-tables: 用于避免上面说的一致性问题,锁住所有的表
--add-drop-database:在create database前先进行drop database。这个参数需要和--all-databases或者--databases选项一起使用。
--master-data[=value]:通过该参数产生的备份转存文件主要用来建立一个replication。当value为1时,转存文件中记录CHANGE MASTER语句。为2时,CHANGE MASTER语句被写出SQL注释。默认值为空。这个会忽略--lock-tables选项,如果没有使用--single-transaction就会自动加上--lock-all-tables选项。
--events: 备份事件调度器
--routines:备份存储过程和函数
--triggers:备份触发器
--hex-blob:将BINARY、VARBINARY、BLOG、BIT列类型备份为十六进制的格式。文本模式下有些字符可能看不见。
--tab=path:产生TAB分割的数据文件。
--where:导出指定的文件数据
4.2 SELECT ... INFO OUTFILE
这个也是一种逻辑备份的方法,更准确地说是导出一张表中的数据。
SELECT [column 1], [column 2] ...
INTO
OUTFILE 'file_name'
[{FIELDS | COLUMNS}
[TERMINATED BY 'string'] 表示分隔符
[[OPTIONALLY] ENCLOSED BY 'char'] 表示对字符串的包含符
[ESCAPED BY 'char']] 表示转义符
[ LINES
[ STARTING BY 'string'] 表示每行开始的字符串
[ TERMINATED BY 'string'] 表示每行结束的字符串
]
FROM TABLE WHERE...
4.3 逻辑备份的恢复
mysqldump的恢复操作比较简单,因为备份的就是SQL,执行这个文件就可以了。
mysql -uroot -p < test_backup.sql
如果导出时包含了创建和删除数据库的SQL语句,那么必须确保删除架构时,架构目录下没有其他与数据库相关的文件,否则会出错。
因为逻辑备份的文件是由SQL语句组成的,也可以通过SOURCE命令来执行导出的逻辑备份文件:
source /home/mysql/test_back.sql
通过mysqldump可以恢复数据库,但是其可以导出存储过程,触发器,事件,数据,但是不能导出视图。因此如果使用了视图,备份完数据库后,还需要导出视图的定义,或备份视图定义的文件frm,并在恢复时导入。
4.4 LOAD DATA INFILE
若通过mysqldump-tab,或者通过select into outfile导出的数据需要恢复,这时可以通过命令LOAD DATA INFILE进行导入。语法如下:
LOAD DATA INTO TABLE a IGNORE 1 LINES INFILES '/home/mysql/a.txt'
[REPLACE | IGNORE] INTO TABLE tbl_name
[CHARACTER SET charset_name]
[{FIELDS | COLUMNS}
[ TERMINATED BY 'string']
[[OPTIONALLY] ENCLOSED BY 'char']
[ESCAPED BY 'char']
]
[LINES
[STARTING BY 'string']
[TERMINATED BY 'string']
]
[IGNORE number LINES]
[(col_name_or_user_var, ...)]
[SET col_name= expr, ...]
可以设置导入过程忽略对外键的检查,加快导入速度:set @@foreign_key_checks=0
4.5 mysqlimport
这是MySQL提供的一个命令行程序,从本质上来说,是LOAD DATA INFILE的命令接口,大部分选项和LOAD DATA INFILE语法相同。
mysqlimport [options] db_name textfile1 [textfile2...]
不同的是,其可以用来导入多张表。并且通过--user-thread参数并发地导入不同的文件。并发是指同时导入多个文件,不是同时操作一个文件。
5. 二级制日志备份与恢复
二级制日志非常关键,用户可以通过它完成point-in-time的恢复工作。MySQL的replication同样需要二进制日志,默认情况下是不开启的,需要配置log-bin=mysql-bin
在之前说过,只是简单的启用二进制日志是不够的,需要一些其他参数保证最为安全和正确地记录二进制日志,因此对于InnoDB存储引擎,推荐的二进制日志的服务器配置应该是:
log-bin = mysql-bin
sync_binlog = 1
innodb_support_xa=1
在备份二进制日志文件前,可以通过FLUSH LOGS命令生成一个新的二进制日志文件,然后备份之前的。
恢复二进制日志也非常简单,通过mysqlbinlog即可。
mysqlbinlog [options] log_file
6 热备
6.1 ibbackup
这个是InnoDB存储引擎官方提供的热备工具,可以同时备份MyISAM存储引擎和INNODB存储引擎表。对InnoDB的备份工作原理如下:
1.记录备份开始时,InnoDB存储引擎重做日志文件检查点的LSN。
2.复制共享表空间文件以及独立表空间文件
3.记录复制完表空间文件后,InnoDB存储引擎重做日志文件检查点的LSN
4.复制在备份时产生的重做日志。
对于事务的数据库,如Oracle和SQL Server,热备的原理大致和上相同。可以发现在备份期间不会对数据库本身有任何影响,所做的操作只是复制数据库文件,因此任何对数据库的操作都是允许的,不会阻塞任何操作。
ibbackup的优点如下:
1.在线备份,不阻塞任何的SQL
2.备份性能好,实质是复制数据库文件和重做日志文件
3.支持压缩备份,通过选项,支持不同级别的压缩
4.跨平台支持,可以运行再linux、windows和主流的unix系统上
ibbackup对InnoDB存储引擎表的恢复步骤如下:
1.恢复表空间文件
2.应用重做日志文件
ibbackup提供了一种高性能的热备方式,是首选方式。但是其是收费的,不过开源的原因,社区的力量,Percona公司做了一款免费的XtraBackup热备工具,其实现了所有ibbackup功能,并扩展支持了真正的增量备份功能。
6.2 XtraBackup
该工具支持MySQL5.0以上版本,在GPL v2开源下发布。
命令是: xtrabackup--backup | --prepare [OPTIONS],具体可选参数就不进行介绍了。
如果要做一个完全备份,可以执行命令:
xtrabackup --backup
6.3 XtraBackup实现增量备份
MySQL数据库本身提供的工具并不支持真正的增量备份,更准确地说,二进制日志的恢复应该是point-in-time的恢复而不是增量备份。
XtraBackup支持增量备份,工作原理如下:
1.首先完成一个全备,记录下此时检查点的LSN
2.在进行增量备份时,比较表空间中每个页的LSN是否大于上次备份时的LSN,如果是,则备份该页,同时记录下当前检查点的LSN。
xtrabackup --backup --target-dir=/backup/base 全备份
xtrabackup --backup --target-dir=/backup/delta --incremental-basedir=/backup/base 增量备份
xtrabackup --prepare --target-dir=/backup/base 准备增量
xtrabackup --prepare --target-dir=/backup/base --incremental-basedir=/backup/delta 添加增量数据
7 快照备份
MySQL本身不支持快照功能,所以快照备份是指通过文件系统支持的快照功能对数据库进行备份。备份的前提是将所有数据库文件放在同一个文件分区中,然后对该分区进行快照操作。
支持快照的文件系统设备包括FreeBSD的UFS文件系统,Solaris的ZFS文件系统,GUN/Linux的逻辑管理器(LVM)等。这里以LVM为例进行介绍,UFS和ZFS的快照实现大致和LVM相似。
LVM是LINUX系统下对磁盘分区进行管理的一种机制。LVM在硬盘和分区上建立一个逻辑层,来提高磁盘分区管理的灵活性。管理员可以通过LVM系统轻松管理磁盘分区。例如,将若干个磁盘分区连接成一个整块的卷组,形成一个存储池。管理员可以在卷组上随意创建逻辑卷,并进一步在逻辑卷上创建文件系统。管理员通过LVM可以方便地调整卷组的大小,并且可以对磁盘存储按照组的方式进行命名、管理和分配。
vgdisplay命令查看系统中有哪些卷组。lvdisplay可以用来查看当前系统中有哪些逻辑卷。
LVM使用了写时复制技术来创建快照。当创建一个快照时,仅复制原始卷中数据的元数据,并不会有数据的物理操作,因此快照的创建过程是非常快的。当快照创建完成,原始卷上有写操作时,快照会跟踪原始卷块的改变,将要改变的数据在改变之前复制到快照预留的空间中,因此这个原理称为写时复制。对于读取操作,如果读取的数据块是创建快照后没有修改过的,会将读操作直接重定向原始卷上,如果修改过,就直接读取保存在快照中该块在原始卷上改变之前的数据。采取写时复制机制保证了读取快照时得到的数据与快照创建时一致。
8 复制
8.1 复制的工作原理
复制是MySQL数据库提供的一种高可用高性能的解决方案,一般用来建立大型应用。总体来说,replication的工作原理分为以下3个步骤:
1.主服务器(master)把数据更改记录到二进制日志中。
2.从服务器(slave)把主服务器的二进制日志复制到自己的中继日志中
3.从服务器重做中继日志中的日志,把更改应用到自己的数据库上,以达到数据的最终一致性。
复制的原理其实就是一个完全备份加上二进制日志备份的还原。不同的是这个二进制日志的还原操作基本上实时在进行中。这里要注意,复制不是完全实时进行同步的,而是异步实时。这中间存在主从服务器之间的执行延时,如果主服务器压力很大,则可能导致从服务器延时较大。
从服务器有2个线程,一个是IO线程,负责读取主服务器的二进制日志,并将其保存为中继日志。另一个线程是SQL线程,复制执行中继日志。MySQL4.0版本之前,从服务器只有1个线程,既负责读取二进制日志,又复制执行二进制日志中的SQL语句。这样不符合高性能的要求,已淘汰。SHOW FULL PROCESSLIST可以看见相关内容。
SHOW SLAVE STATUS和SHOW MASTER STATUS可以观察一下延迟。主要是观察从服务器的read_master_log_pos和主服务器的当前二进制偏移量position,知道二者的差距。
8.2 快照+复制的备份架构
复制可以用来作为备份,但功能不仅限于备份,主要功能如下:
1.数据分布。由于MySQL数据库提供的复制并不需要很大的带宽要求,因此可以在不同的数据中心之间实现数据的复制。
2.读取的负载平衡。通过建立多个从服务器,可以将读取平均地分布到这些从服务器中,并且减少主服务器的压力。一般通过DNS的Round-Robin和Linux的LVS功能实现
3.数据库备份。复制对备份很有帮助,但是从服务器不是备份,不能完全代替备份。
4.高可用性和故障转移。通过复制建立的从服务器有助于故障转移,减少故障的停机时间和恢复时间。
建议在从服务器上启用read-only选项,保证从服务器上的数据仅与主服务器进行同步,避免其他线程修改。[mysqld] read-only
启用read-only选项后,如果操作从服务器的用户没有super权限,则对从服务器进行任何的修改都会抛出错误。