数据库备份策略 | |
完全备份 | 备份所有的数据 |
物理备份采用的就是完全备份 | |
增量备份 | 备份上次备份后,所有新的数据 |
差异备份 | 备份上次完全备份后,所有新的数据 |
增量备份和差异备份的区别:
增量备份是根据上一次备份后进行备份,不管什么备份都算,所以不会出现冗余备份
而差异备份,是从上一次完全备份开始备份,也就是说,上次完全备份后不管有多少增量或者差异备份,都不理会,从上次完全备份开始,所有新数据进行备份
假如,第一天为给数据库完全备份,第二天我先加了3个数据,第三天加了5个数据,第四天加了1个数据
如果我采用增量备份,那么第二天备份3个数据,第三天备份5个数据,第四天备份1个数据
如果我采用差异备份,那么第二天备份3个数据,第三天备份8个数据,第四天备份9个数据
数据库完全备份方式
物理备份
也叫冷备份: cp、tar
原理很简单,把存储数据库信息的文件进行备份,也就是/var/lib/mysql下的文件复制备份起来即可
# 使用拷贝进行备份
cp -r /var/lib/mysql /mysql.bak
# 或者用tar压缩
tar -zPcf /mysql.bak.bz.tar /var/lib/mysql
物理恢复
把备份的数据库文件再拷贝回原来的位置即可
不过有两点要注意:
1. 授予权限,因为所有的操作都是root执行的,其所有者和所有组都是root,我们要改成mysql,不然数据库起不来
2. 恢复前最好先停掉mysqld的服务,然后再做恢复操作。
systemctl stop mysqld
rm -rf /var/lib/mysql
# 如果是拷贝备份的话
cp -r /mysql.bak /var/lib/mysql
# 如果是tar压缩备份
tar -xf /mysql.bak.bz.tar
chown -R mysql:mysql /var/lib/mysql
systemctl restart mysqld
逻辑备份
使用命令进行备份,支持所有的备份策略。
备份操作: mysqldump -u 用户 -p密码 保存的数据 [--flush-logs] > 路径/备份名.sql
注意: 备份的时候,选择的用户必须有读取保存数据的读权限 ,
如果开启了日志功能,那么我们做了备份后就可以把日志信息存储进行刷新,这样可以让差异备份标示一个新的完全备份
操作后会在备份时候写的的 路径 下出现 备份名.sql 的文件,里面就是备份的数据。
保存的数据 | ||
--all-databases | 所有库和表 | 备份的是所有库的信息,以其库中所有表的信息和数据 |
-A | ||
数据库名 | 单个库 | 备份的是库中所有表的信息和数据,并不保存库的信息 |
数据库名 表名 | 单张表 | 备份的是具体表的信息和数据 |
数据库名 表名1 …… 表名n | 一个库下的多张表 | 备份的是具体表的信息和数据 |
-B 数据库1 …… 数据库n | 多个库 | 备份多个库的信息,以及里面所有表的信息和数据 |
逻辑恢复
命令行下进行恢复操作:
恢复操作: mysql -u 用户 -p密码 [ 库名 ] < 路径/备份名.sql
库名的书写: 具体情况分析,在任何情况下,库名写上都是不会错的,不过有的时候是可以不写库名的,有的时候不写库名会报错,如果备份数据的时候备份有库的信息,那么就不用写库名,如果没有,那就必须写一个已经创建的库名
具体说,当备份的时候,保存数据是 所有库(-A) 或者 多个库(-B) 的时候,不用写库名,其他时候必须写一个已经创建好的库。
在登陆状态下进行恢复操作:
命令: source 路径/备份名.sql
和上面情况一样,如果没有备份库信息,就要先use进入某个库,然后进行恢复操作
当然在一个库下可以进行,备份有库信息的备份信息的恢复操作
缺点:
1. 备份信息只保存数据到进行备份时刻的数据信息,备份后进行的所有操作都不会被备份,也不能恢复;
2. 恢复的时候,会用写锁锁定表,这样表恢复阶段就不能进行任何操作。
数据库差异备份方法 — binlog
binlog 是一个二进制日志 ,主要用于 记录所有更改数据的操作(增删改操作)
优点: 记录除查询以外所有SQL命令,实时备份,可以用于数据恢复,是配置mysql主从同步的必要条件
原理: 通过实时记录,所有用户对数据库的操作,在需要恢复数据的时候,可以重新把操作进行一次,因为是差异备份,还原到上次的完全备份后,把到想恢复到的时间点的命令调出执行一遍就可以恢复成功数据
存储binlog有2种文件:
以数字结尾的是记录日志内容的,数据记录在数字最大的哪个文件中,而日志信息也是按照文件后缀名从小到大记录所有修改命令
以index结尾的是记录索引内容的,标示有哪些日志文件。
日志三个记录格式 | |
statement | 每条修改的sql命令都回记录在日志中 |
row | 不记录上下文的信息,仅仅保存那条信息被修改了,修改成什么样子 |
mixed | 以上两个格式混用,既记录量sql命令,也记录信息被修改的情况 |
配置文件的基本解释
binlog_format="mixed" 选择使用哪个记录格式
server_id=66 # 一个标示,一般用主机名编号
log_bin[=日志存储位置/名字] # 启动binlog日志备份,并指定文件名前缀
# 如果不写日志存储位置,默认存在/var/lib/mysql/下
# 如果不写等于和名字,就启动binlog并以当前主机名作为文件名前缀
max_binlog_size=大小 # 指定日志达到多大存储空间的时候,创建一个新的日志文件存储,默认为500M
查看当前的日志文件和记录偏移量
show master status;
配置binlog
启动binlog日志记录
sed -i '/\[mysqld\]/abinlog_format="mixed"' /etc/my.cnf
sed -i '/\[mysqld\]/aserver_id=66' /etc/my.cnf
sed -i '/\[mysqld\]/alog_bin' /etc/my.cnf
systemctl restart mysqld
ls /var/lib/mysql/*-bin.* &>/null && echo binlog start is OK || echo binlog start is wrong
如果想自定义日志名称和存储位置
mkdir /自定义的存储位置
chown mysql /自定义的存储位置
sed -i '/\[mysqld\]/abinlog_format="mixed"' /etc/my.cnf
sed -i '/\[mysqld\]/aserver_id=66' /etc/my.cnf
sed -i '/\[mysqld\]/alog_bin=/自定义的存储位置/自定义日志名称' /etc/my.cnf
systemctl restart mysqld
ls /自定义的存储位置/日志名称.* &>/null && echo binlog start is OK || echo binlog start is wrong
注意: 上面两个操作都修改量配置文件/etc/my.cnf,上下两个操作不能一起做,只能选择一个,如果做了一个想做另一个,必须到配置文件中把相关配置(binlog_format、server_id、log_bin)删除,再继续操作
查看日志信息:
[root@mysql ~]# mysqlbinlog 路径/日志名
日志信息中有很多行是 # at 数字 这是一个偏移量,可以理解为一个时间点,在选项中用于分隔标示日志信息,
如果选项写了开始和结束的偏移量,就是把这两个偏移量间的日志信息返回给客户端
如果想具体查看某个命令的记录,比如查看insert命令的历史信息
[root@mysql ~]# mysqlbinlog 路径/日志名 | grep ^insert
如果想按照时间点筛选出日志信息,可以通过添加选项
[root@mysql ~]# mysqlbinlog 选项 路径/日志名
--start-datetime='yyyy-mm-dd hh:mm:ss' | 设置命令返回从什么时间开始的日志 |
--stop-datetime='yyyy-mm-dd hh:mm:ss' | 设置命令返回到什么时候时候结束的日志 |
--start-position=偏移量 | 设置命令返回从什么偏移量开始的日志 |
--stop-position=偏移量 | 设置命令返回到什么偏移量结束的日志 |
刷新binlog日志存储
日志存储的大小达到配置文件中标示的值的时候,就会自动创建一个新的日志信息,但是如果想单独给下面做的操作进行备份,那么就刷新binlog,这样就会立刻创建一个新的日志文件,在操作完成后,再刷新一次创建一个文件来记录后面的操作,这样刚刚的所有操作就都记录一个文件中了。
flush logs;
清除binlog日志信息
可以通过命令行进行操作,但是不建议
直接删除文件 rm -f 路径/日志名 ,根据需要删除具体版本的日志信息即可,但是还要把索引文件中的信息删除了
当然可能有多个版本号,如果想全部删除,在版本号位置用*代替,把日志文件和索引文件全部删除了
最好通过验证进入mysql中,用命令进行操作
# 删除指定日志之前的文件,指定日志不会被删除
mysql> purge master logs to '日志名';
# 删除所有日志
mysql> reset master;
恢复数据
这是一个差异备份,一定是要在记录前做一个完全备份的,那么恢复的时候,先恢复完全备份的信息;
然后查看日志信息,找到开始节点,和想恢复到的时间节点的日志信息(选项只要一个开始一个结束即可,可以混合时间和节点使用)
[root@mysql ~]# mysqlbinlog --start-position=偏移量 --stop-position=偏移量 路径/日志名 | mysql -u 用户 -p密码
[root@mysql ~]# mysqlbinlog --start-datetime=时间 --stop-datetime=时间 路径/日志名 | mysql -u 用户 -p密码
注意:
1. 如果完全备份是用冷备份,而且没有修改日志存储位置的话,要先把日志信息拷贝出来,再恢复完全备份
2. 查看恢复时间点的时候,命令后面要找到commit字段后面的时间才算完整,否则最后一个命令并不会执行完毕
3. 如果以时间作为分隔的标示。开始和结束写的那秒的操作不会进行,可以再多写 1秒 即可
4. 有的时候一秒中有很多操作,如果这秒中有不想要的操作,只能从日志中查看偏移量,以偏移量为分隔标示。
5. 很多时候,我们都是在进行一个误操作然后想恢复,那么我们想恢复数据到的时间点就在最后的时间点,这时候我们可以
总结:
1. 修改配置文件/etc/my.cnf,打开binlog日志记录功能
2. 使用mysqldump进行完全备份
3. 开启服务,在需要的时候先重新恢复完全备份,然后使用日志进行恢复即可。
4. 每隔一段时间更新一下完全备份的数据,并且刷新日志存储。
percona 软件实现完全备份和增量备份
使用 XtraBackup工具 (一个强大的在线热备份工具,由Percona组织提供)
对XtraBackup工具,有两个组件,xtrabackup(支持InnoDB、XtraDB引擎);innobackupex(支持InnoDB、XtraDB、MyISAM引擎)
不过XtraBackup只支持对InnoDB引擎完全备份和增量备份两中备份方式,其他引擎只能做完全备份,所以想使用该软件做备份,最好让存储引擎是InnoDB。
安装percona
装包,在资源中有上传rpm包,当然包括一个依赖包,两个一起安装,还有一些其他的依赖包,一般的iso镜像中是有的,就没列上
装完就可以使用命令进行备份了
命令格式: innobackupex 选项 备份信息保存的位置
选项
--user 用户名 | 指定用户名 |
--host 主机名 | 指定主机名 |
--port 端口 | 指定端口号 |
--databases='库名' | 指定数据库 |
--databases='库1,库2' | |
--databases='库名.表名' | |
--no-timestamp | 指代不用日期命名文件存储的子目录名,直接在后面的存储位置存储数据 |
--apply-log | 准备还原 |
--copy-back | 回复数据 |
--incremental 目录 | 增量备份 |
--incremental-basedir=目录名 | 指定上一次备份数据存储的目录名 |
完全备份:
备份命令格式
[root@mysql ~]# innobackupex --user 用户名 --password 密码 其他选项 备份信息保存的位置
注意:
1. 如果没有 --no-timestamp 这选项,备份信息存储在设置的存储位置之下,一个以时间命名的子文件夹下
2. 必须备份mysql、sys、performance_schema这三个系统库
恢复数据:
0. 关闭数据库服务 systemctl stop mysqld
1. 准备恢复(删除目录)
# 删除数据库下的所有数据,注意只能删除目录下的内容,不能把mysql目录删除量
[root@mysql ~]# rm -rf /var/lib/mysql/*
[root@mysql ~]# innobackupex --apply-log 备份存储的位置
2. 拷贝
[root@mysql ~]# innobackupex --copy-back 备份存储的位置
3. 赋权 chown -R mysql:mysql /var/lib/mysql
4. 重启服务 systemctl restart mysqld
增量备份
备份命令格式:
[root@mysql ~]# innobackupex --user 用户 --password 密码 --no-timestamp 其他选项 --incremental /增量备份信息存储位置 --incremental-basedir=/上一次备份存储位置
注意:
1. 上一次备份年具体的存储位置,如果上一次存储没写 --no-timestamp 选项,那么他的具体存储位置是写的位置下的时间命名的目录
2. 如果上一次也是增量备份,也可以继续这个操作,这就是在上次增量备份的基础上,再进行增量备份
增量备份的恢复
1. 停止服务
[root@mysql ~]# systemctl stop mysqld
2. 删除数据库当前文件内容
[root@mysql ~]# rm -rf /var/lib/mysql
3. 准备恢复、合并日志
[root@mysql ~]# innobackupex --apply-log --redo-only /完全备份位置
[root@mysql ~]# innobackupex --apply-log --redo-only /完全备份位置/ --incremental-dir='第一个增量备份位置'
[root@mysql ~]# innobackupex --apply-log --redo-only /完全备份位置/ --incremental-dir='第二个增量备份位置' ……
4. 开始恢复
[root@mysql ~]# innobackupex --copy-back /完全备份位置
5. 修改权限
[root@mysql ~]# chown -R mysql:mysql /var/lib/mysql
6. 重启服务
[root@mysql ~]# systemctl restart mysqld
* 删除增量备份文件(可不执行该操作)
# 因为所有备份信息合并到完全备份日志文件中了,所以可以删除增量备份文件
rm -rf '第一个增量备份位置' '第二个增量备份位置'
恢复单个表数据
0. 进行备份,只要对表所在库进行备份,当然也可以对整个数据库备份
1. 停止服务
2. 创建一个和要备份的表的结构一模一样的表,然后删除这个表的表空间
mysql> create table 表名(表机构);
mysql> alter table 库名.表名 discard tablespace;
3. 将表信息从备份中导出 (如果是增量备份就先把所有增量备份合并到完备备份中)
[root@mysql ~]# innobackupex --user 用户 --password 密码 --databases="库名字" --apply-log --export /备份存储目录
4. 将表数据拷贝到数据库文件中
[root@mysql ~]# cp 备份目录/库名/表名.{ibd,cfg,exp} /var/lib/mysql/库名/
5.修改权限
[root@mysql ~]# chown mysql:mysql /var/lib/mysql/库名/
6. 将数据导入到数据库中
mysql> alter table 库名.表名 import tablespace;
对于innobackupex操作总结:
1. 备份的基本操作: 备份的操作很简单,一条命令就能解决问题,如果是增量备份多两个选项指定备份位置和上一个备份存储的位置
innobackupex --user=用户名 --password=密码 选项(--incremental等) 备份存储位置
2. 备份恢复的基本操作: 停 删 准备,拷贝 修改,重启服务,具体解释如下:
基本的库恢复操作: 停 服务,删 除mysql文件,准备 恢复(--apply-log),拷贝 恢复(--copy-back),修改 权限,重启服务
完全备份恢复就是一步一个命令完成 ; 增量备份恢复准备恢复阶段需要把所有增量数据合并到最初的完全配置文件中 。
单个表的恢复:停 服务,删 除表空间(手动创建一个表结构),准备 恢复(--apply-log、--export) , 拷贝 文件(.ibd,.cfg,.exp),修改 权限,重启服务
各种备份对比:
物理备份 将所有数据保存下来,简单粗暴,用的不多
逻辑备份 mysqldump将数据库备份成一个文件,如果想在另一个服务器上搭建一个一模一样的数据库,用这个备份方法
日志备份binlog 做主从同步的时候,用来记录每个数据变化的操作
percona的innobackup备份 备份数据库最好的备份方案,可以将备份数据保存到其他存储服务器中,能做一个数据的完全备份以及后来每个阶段的增量备份。
注意:
1. 恢复数据需要停止服务,所以innobackupex后面不需要跟上用户名和密码,而备份是一定要加上用户名密码的
2. 任何备份恢复操作后,都需要确认权限,最好在恢复后把mysql文件夹下所有的文件的 所有者 都改为mysql用户
备份存储内的文件作用
xtrabackup_checkpoints 记录备份类型
backup_type = full-prepared # 记录当前备份是什么方式,full-prepared代表完全备份,incremental代表增量备份
from_lsn = 0 # 开始记录的位置,一般上一个备份服务器结束的位置就是本服务器的开始位置
to_lsn = 6758990 # 记录到什么位置
last_lsn = 6758999
compact = 0
recover_binlog_info = 0 # 是一个日志序列,这个只有是innodb引擎的有事务操作,所以只有innodb有这一项
备份中记录在库中各个文件的作用 | |
表.cfg,exp | 表存储的数据内容 |
表.frm | 库中的表结构 |
表.ibd | 库中的表内容和索引信息 |
db.opt | 库的基本信息 |