MySQL数据的备份与恢复

1. 备份基础

1.1 热备份、温备份、冷备份

  • 热备:读写操作均可执行(InnoDB:热备)

  • 温备:读操作可执行,但写操作不成(MyISAM:温备,不能热备)

  • 冷备:读写操作均不可进行

1.2 物理备份、逻辑备份

  • 物理备份:直接复制数据文件进行备份

  • 逻辑备份:从数据库中“导出”数据另存而进行的备份,逻辑备份与存储引擎无关

1.3 备份时需要考虑的因素

  • 持锁多久

  • 备份过程的时长

  • 备份负载

  • 恢复过程的时长

1.4 备份什么

  • 数据

  • 二进制日志、InnoDB的事务日志

  • 代码(存储过程、存储函数、触发器、事件调度器)

  • 服务器的配置文件

1.5 备份工具

  • mysqldump:逻辑备份工具,适用所有存储引擎,温备,完全备份、部分备份,对InnoDB存储引擎支持热备

  • cp,tar等复制归档工具:物理备份工具,适用所有存储引擎,冷备:完全备份,部分备份

  • lvm2的快照:几乎热备:借助于文件系统管理工具进行备份

  • mysqlhotcopy:几乎冷备:仅适用于MyISAM存储引擎

1.6 备份工具的选择

  • mysqldump+复制binlog

    • mysqldump:完全备份

    • 复制binlog中指定时间范围的event:增量备份

  • lvm2快照+复制binlog

    • lvm2快照:使用cp或者tar等做物理备份:完全备份

    • 复制binlog中指定时间范围的event:增量备份

  • xtrabackup

    • 对于MyISAM:不能热备,不能增量

    • 对于InnoDB:LSN热备,增量

假设一个10G或100G的数据库,很显然如果使用mysqldump备份,将会非常麻烦,而且速度很慢
而,这时候采用xtrabackup每周一次完全备份,每天一次增量备份,在加上binlog备份做时间点,
是比较理想的

2. mysqldump

客户端命令,通过mysql协议连接至mysqld服务器

注意:二进制日志文件不应该和数据文件放在同一磁盘

语法:

mysqldump [options] [db_name [tbl_name ...]]

备份的数据集:

  • -A,–all-databases
  • -B db1_name,db2_name,…
shell> mysqldump [options] db_name [tbl_name ...]	不会自动生成create database语句
shell> mysqldump [options] --databases db_name ...
shell> mysqldump [options] --all-databases

示例

mysqldump -uroot -p12345 -B worker | gzip >/server/worker_$(date +%F)-$(uname -n).sql.gz

2.1 对MyISAM存储引擎来说,要先锁定备份库,而后启动备份操作,因为MyISAM仅只支持温备

锁定方法:

--lock-all-tables(-x):锁定所有库的所有表,施加的是全局读锁,其他人可以继续读

--lock-tables(-l):对于每个单独的数据库,在启动备份之前锁定其所有表

以上对InnoDB表一样生效,不过对InnoDB表来说,只能实现温备

2.2 InnoDB:支持热备

–single-transaction

2.3 其他选项:

  • -E,–events:备份指定数据库相关的所有event scheduler

  • -R,–routines:备份指定数据库相关的所有存储过程和存储函数

  • –triggers:备份表相关的触发器

  • –master-data:后面有两个值

    • 1:记录为CHANGE MASTER TO语句,此语句不被注释

    • 2:记录为注释的CHANGE MASTER TO语句,建议使用

  • –flush-logs:锁定表完成后,执行flush logs日志

示例:使用mysqldump完成备份还原,并结合二进制日志做时间点还原

主机上操作

mysqldump -uroot --all-databases --lock-all-tables --master-data=2 > /root/all.sql
rsync -aP all.sql 10.134.115.56::root/tmp/
less  /root/all.sql 找到CHANCE MASTER TO MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=245
mysqlbinlog --start-position=245 /var/lib/mysql/mysql-bin.000001 > incre.sql
rsync -aP incre.sql 10.134.115.56::root/tmp/
mysqldump -uroot -B zabbix --single-transaction |gzip >/search/zabbix_$(date +%F)_$(uname -n).sql.gz
rsync -aP zabbix_2018-02-05_bjsjs_115_94.sql.gz 10.134.112.56::root/search/

备机上操作

1 临时关掉二进制日志 SET sql_log_bin=OFF;(在同一个会话中操作)

2 mysql < /tmp/all.sql

3 mysql < /tmp/incre.sql

4 还原完成后,再次开启 SET sql_log_bin=ON; (在同一个会话中操作)
--lock-all-tables:线上不建议使用(施加的是全局读锁),如果备份时间多长,因为会长时间影响到事务无法使用

gunzip zabbix_2018-02-05_bjsjs_115_94.sql.gz zabbix.sql

mysql < /search/zabbix.sql
第一步:导出所有的表结构
mysqldump -d zabbix -uroot -padtech_0419 > zabbix_table.sql
恢复表结构:
mysql zabbix < /search/backup/zabbix_table.sql

第二笔:导出表数据(排除一些大表数据)
mysqldump -uroot -padtech_0419 zabbix \
--ignore-table=zabbix.history \
--ignore-table=zabbix.history_str \
--ignore-table=zabbix.history_uint \
--ignore-table=zabbix.history_text \
--ignore-table=zabbix.trends \
--ignore-table=zabbix.trends_uint > zabbix_data.sql
恢复数据:
mysql zabbix < /search/backup/zabbix_data.sql

3 基于lvm2的备份

# 建立逻辑卷
fdisk /dev/sda
n
默认
+10G
w
partx -a /dev/sda
pvcreate /dev/sda7					# 创建物理卷
vgcreate myvg /dev/sda7			    # 创建逻辑卷组myvg
lvcreate -L +5G -n mydata myvg		# 创建lv,名字为mydata,从myvg中创建
lvs								    # 查看
mkfs.xfs /dev/myvg/mydata			# 格式化	
mount /dev/myvg/mydata /data/		# 挂载到/data/上
mkdir -p /data/mysql
chown -R mysql.mysql  /data/mysql
vim /etc/my.cnf.d/server.cnf
[mysqld]
datadir=/data/mysql
systemctl start mariadb.service

备份步骤

(1) 请求锁定所有表

mysql > flush tables with read lock;  # 将所有表的数据从内存中同步到硬盘上,时间和数据大小有关

(2) 记录二进制日志文件及事件位置

mysql > flush logs;				  # 滚动日志,方便记录
mysql > show master status;		  # 记录位置
mysql -e 'show master status' > /path/to/somefile

(3)为逻辑卷创建快照

lvcreate -L 5G -n mydata  -p r -s  /dev/myvg/mydata
-r 只读
-n 快照名
-L 大小

(4) 释放锁

mysql > unlock tables;

(5) 挂载快照卷,执行数据备份

mount /dev/myvg/mydata /data/

cp -a /data/mysql /backup/

(6) 备份完成后,删除快照卷

(7) 制定好策略,通过原卷备份二进制日志

恢复步骤

cp -a /backup/* /data/mysql
mysqlbinlog --start-position=245 /var/lib/mysql/mysql-bin.000004 > incre.sql
mysql > SET sql_log_bin=OFF;
source incre.sql
SET sql_log_bin=ON; 

4 xtrabackup

percona-server 用的是改进版的InnoDB,叫XtraDB

mysql

mariadb 用的是改进版的InnoDB,叫XtraDB(mysql>show engines;)

xtrabackup仅对InnoDB支持热备、支持增量;对MyISAM支持温备,不支持增量

下载链接:

libev.so
http://rpmfind.net/linux/rpm2html/search.php?query=libev.so.4%28%29%2864bit%29&submit=Search+...&system=&arch=

xtrabackup
https://www.percona.com/downloads/XtraBackup/LATEST/

安装

wget ftp://rpmfind.net/linux/dag/redhat/el6/en/x86_64/dag/RPMS/libev-4.15-1.el6.rf.x86_64.rpm
rpm -ivh libev-4.15-1.el6.rf.x86_64.rpm 
yum install perl-DBD-MySQL
rpm -ivh percona-xtrabackup-24-2.4.9-1.el6.x86_64.rpm

4.1 完全备份

mkdir -p /search/backup/
innobackupex --defaults-file=/tmp/other-my.cnf --user=DBUSER --password=DBUSERPASS /backups
innobackupex --defaults-file=/etc/my.cnf --user=zabbix --password=adto_zabbix /search/backup/

# 输出结果:
180209 15:48:20 Executing UNLOCK TABLES
180209 15:48:20 All tables unlocked
180209 15:48:20 Backup created in directory '/search/backup/2018-02-09_14-23-10/'
MySQL binlog position: filename 'mysql-bin.000746', position '364603374', GTID of the last change '0-1-203942020'
180209 15:48:20 [00] Writing /search/backup/2018-02-09_14-23-10/backup-my.cnf
180209 15:48:20 [00]        ...done
180209 15:48:20 [00] Writing /search/backup/2018-02-09_14-23-10/xtrabackup_info
180209 15:48:20 [00]        ...done
xtrabackup: Transaction log of lsn (3660802401086) to (3662590160378) was copied.
180209 15:48:20 completed OK!

如果要使用一个最小权限的用户进行备份,则可基于如下命令创建此类用户:

mysql > create user 'bkpuser'@'localhost' identified by '123455'
mysql > revoke all privileges,grant option from 'bkpuser'
mysql > grant reload,lock tables,replication client on *.* to 'zabbix'@'localhost' identified by 'adto_zabbix';
mysql > flush privelges;

使用innobackupex备份时,其会调用xtrabackup备份所有的InnoDB表,复制所有关于表结构定义的相关问题(.frm)
以及MyISAM,MERGE、CSV和ARCHIVE表的相关文件,同时还会备份触发器和数据库配置信息相关的文件。这些文件会被保存一个以时间命名的目录中

在备份的同时,innobackupex还会在备份目录中创建如下文件

  • xtrabackup_checkpoints —备份类型(如完全或增量)、备份状态(如是否已经为prepared状态)和LSN(日志序列号)
    范围信息
    每个InnoDB页(通常为16k大小),都会包含一个日志序列号,即LSN,LSN是整个数据库系统的系统版本号,每个页面相关的LSN能够表明此页面最近是如何发生改变的

  • xtrabackup_binlog_info:mysql服务器当前正在使用的二进制日志文件及到备份这一刻为止二进制日志时间的位置

  • xtrabackup_binlog_pos_innodb:二进制日志文件及用于InnoDB或XtraDB表的二进制日志文件的当前position

  • xtrabackup_binary:备份中用到的xtrabackup可执行文件

  • bakup-my.cnf:备份命令用到的配置选项信息

在使用innobackupex进行备份时,还可以使用–no-timestamp选项来阻止命令自动创建一个以时间命令的目录,如此一来,innobackupex命令将会创建一个BACKUP-DIR目录来存储备份数据

innobackupex --user=DBUSER --password=DBUSERPASS /path/to/BACKUP-DIR/ --no-timestamp

4.2 准备(prepare)一个完全备份

一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件的事务,因此,此时数据文件仍处于不一致状态,“准备”的主要作用正是通过回滚尚未提交的事务
及同步已经提交的事务至数据文件也使得数据文件处于一致性状态
innobackupex命令的–apply-log选项可用于实现上述功能

备份恢复示例:

第一步:备份:

# Master:10.134.112.56
innobackupex --defaults-file=/etc/my.cnf --user=zabbix --password=adto_zabbix /search/backup/ --use-memory=10G

如果执行正确,其后面输出的几行信息通常如下

MySQL数据的备份与恢复_第1张图片

在实现“准备”的过程中,innobackupex通常还可以使用–use-memory选项来指定其可以使用的内存的大小,默认通常为100M,如果有足够的内存可用,可以多划分一下内存给prepare的过程,以提高其完成速度

第二步:恢复(也需要安装xtrabackup):

# Slave:10.134.116.20
# 停止mysql
systemctl stop mariadb.service 或 service mysql stop
# 备份原mysql的datadir
mv /search/mariadb/data /search/mariadb/data_bak
mkdir /var/lib/mysql

# 整理备份
innobackupex --apply-log /search/backup/2020-03-17_11-08-40 --use-memory=10G
# 如果执行正确,其后面输出的几行信息通常如下:
InnoDB: 5.7.13 started; log sequence number 4627007360021
xtrabackup: starting shutdown with innodb_fast_shutdown = 1
InnoDB: FTS optimize thread exiting.
InnoDB: Starting shutdown...
InnoDB: Shutdown completed; log sequence number 4627007361606
180409 18:28:49 completed OK!

# 还原操作(拷贝文件到MySQL datadir)
innobackupex --copy-back /search/backup/2020-03-17_11-08-40
# 结果
180209 18:22:15 [01] Copying ./xtrabackup_binlog_pos_innodb to /search/mariadb/data/xtrabackup_binlog_pos_innodb
180209 18:22:15 [01]        ...done
180209 18:22:15 [01] Copying ./ibtmp1 to /search/mariadb/data/ibtmp1
180209 18:22:15 [01]        ...done
180209 18:22:15 completed OK!

# 修改文件权限,启动mysql服务
chown -R mysql.mysql /search/mariadb/
rm -f /search/mariadb/data/ib_logfile*
systemctl start mariadb.service 或 service mysql start

4.3 从一个完全备份中恢复数据

注意:恢复不用启动MySQL
innobackupex命令的–copy-back选项用于执行恢复操作,其通过复制所有数据相关的文件至mysql服务器
DATADIR目录来执行恢复过程,innobackupex通过backup-my.cnf来获取DATADIR目录的相关信息

innobackupex --copy-back /path/to/BACKUP-DIR
# 如果执行正确,其后面输出的几行信息通常如下:
innobackupex:Starting to copy InnoDB log files
innobackupex: Finished copying back files
120407 09:01:40 innobakupex:completed OK!

请确保如上信息的最后一行出现“innobakupex:completed OK!”

当数据恢复至DATADIR目录以后,还需要确保所有数据文件的属主和属组均为正确的用户,如mysql,否则,在启动
mysqld之前还需要实现修改数据文件的属主和属组,如chown -R mysql.mysql /data/mysql

4.4 使用innobakupex进行增量备份

每个InnoDB的页面都会包含一个LSN信息,每当相关的数据发生改变,相关的页面的LSN就会自动增长,这正是InnoDB表可以进行增量备份的基础,即 innobakupex通过备份上次完全备份之后发生的改变的页面来实现

要实现第一次增量备份,可以使用下面的命令进行:

innobackupex --incremental /backup --incremental-basedir=BASEDIR

innobackupex --defaults-file=/etc/my.cnf --user=zabbix --password=adto_zabbix --incremental-basedir=/search/backup/2018-04-09_15-54-52 --incremental /search/backup/ --use-memory=10G

incremental-basedir=全备的目录

–incremental=增量备份的目录

其中,BASEDIR指的是完全备份所在的目录,此命令执行结束后,innobackupex命令会在/backup目录中创建一个新的以时间命名的目录以存放所有的增量备份数据,另外,在执行过增量备份之后再一次进行增量备份时,
其–incremental-basedir应该指向上一次的增量备份所在的目录

需要注意的是,增量备份仅能用于InnoDB或XtraDB表,对MyISAM表而言,执行增量备份时其实进行的是全量备份

“准备”(prepare)增量备份与整理完全备份有着一些不同,尤其要注意的是:

  • 需要在每个备份(包括完全和各个增量备份)上,将已经提交的事务进行“重放”,“重放”之后,所有的备份数据将合并到完全备份上

  • 基于所有的备份将未提交的事务进行“回滚”

于是,操作就变成了

innobackupex --apply-log --redo-only BASE-DIR

应用全量日志

innobackupex --defaults-file=/etc/my.cnf --apply-log --redo-only /search/backup/2018-04-09_15-54-52

接着执行:

innobackupex --apply-log --redo-only BASE-DIR --incremental-dir=INCREMENTAL-DIR-1

innobackupex --defaults-file=/etc/my.cnf --apply-log --redo-only /search/backup/2018-04-09_15-54-52  --incremental-dir /search/backup/2018-04-10_14-25-28

而后是第二个增量(最后一个增量不需要–redo-only)

innobackupex --apply-log  BASE-DIR --incremental-dir=INCREMENTAL-DIR-2

其中BASE-DIR指的是完全备份所在的目录,而INCREMENTAL-DIR-1指的是第一次增量备份的目录,INCREMENTAL-DIR-2指的是第二次增量备份的目录,其他以此类推,即如果有多次增量备份,每一次都要执行如上操作

示例:增量备份及恢复

create table testtb(id int);
insert into testdb values(1),(10),(99);

先做一次完全备份

innobackupex /backup

之后连上数据库再进行一次修改

insert into testdb values(2),(20),(299);
insert into testdb values(3),(30),(399);

做增量备份(基于–incremental-basedir=/backup/2017-11-15_12-37-31做增量)

innobackupex --incremental /backup --incremental-basedir=/backup/2017-11-15_12-37-31

将增量合并到完全备份上,然后用完全备份做还原

# 1 停掉数据库
sysemctl stop mariadb.service

# 2 整理全量备份(2018-04-09_15-54-52)
innobackupex --defaults-file=/etc/my.cnf --apply-log --redo-only /search/backup/2018-04-09_15-54-52

# 3 应用增量日志到完全备份(最后一次增量不需要使用--redo-only )
innobackupex --defaults-file=/etc/my.cnf --apply-log  /search/backup/2018-04-09_15-54-52  --incremental-dir /search/backup/2018-04-11_14-25-24

# 4 还原操作
rm -rf /data/mysql/*
rm -rf /data/binlogs/*
innobackupex --defaults-file=/etc/my.cnf --copy-back /search/backup/2018-04-09_15-54-52(全量日志)
chown -R mysql.mysql /data/mysql

# 5 启动mysql
rm -f /data/mysql/ib_logfile*
systemctl start mariadb.service

# 6 查看
mysql > slect * from testtb;

4.5 Xtrabackup的“流”及“备份压缩”功能

Xtrabakeup对备份的数据文件支持“流”功能,即可以将备份的数据通过STDOUT传输给tar程序进行归档,而不是默认的直接保存至某备份目录中,要使用此功能,仅需要使用–stream选项即可,如:

innobackupex --stream=tar /backup | gzip > /backup/$(date +%F_%H-%M-%S).tar.gz

甚至也可以使用类似如下命令将数据备份至其他服务器

innobackupex --stream=tar /backup | ssh [email protected] "cat - > /backups/$(date +%F_%H-%M-%S).tar"

此外,在执行本地备份时,还可以使用–parallel选项对多个文件进行并行复制,此选项用于指定在复制时启动的线程数目,当然,在实际进行备份时要利用此功能的便利性,也需要启用innodb_file_pre_table选项或共享的表空间通过
innodb_data_file_path选项存储在多个ibdata文件中,对某一数据库的多个文件的复制无法利用此功能,其简单使用方法如下

innobackupex --parallel /path/to/backup

同时,innobackupex备份的数据文件也可以存储至远程主机,这可以使用–remote-host选项来实现:

innobackupex [email protected] /path/in/remote /host/to/backup

4.6 导入或导出单张表

默认情况下,InnoDB表不能通过直接复制表文件的方式在mysql服务器之间进行移植,即便使用了innodb_file_pre_table选项,二使用Xtrabackup工具可以实现此种功能,不过,此时需要“导出”表的mysql服务器

启用了innodb_file_pre_table选项(严格来说,是要“导出”的表在其创建之前,mysql服务器就启用了innodb_file_pre_table选项),并且“导入”表的服务器同事启用了innodb_file_pre_table和innodb_expand_import选项

(1)“导出”表

导出表是在备份的perpare阶段进行的,因此,一旦完全备份完成,就可以在perpare过程中通过–export选项将某表导出了

innobackupex --apply-log --export /path/to/backup

此命令会为每个innodb表的空间创建一个以.exp结尾的文件,这些已.exp结尾的文件则可以用于导入至其他服务器

(2)“导入”表

要在mysql服务器上导入来自于其他服务器的某innodb表,需要现在当前服务器上创建一个跟原表表结构一致的表
而后才能实现将表导入,

mysql > create table mytable(...) engine=InnoDB;

然后将此表的表空间删除

mysql > alter table mydatabase.mytable discard tablesapce;

接下来,将来自于“导出”表的服务器的mytable表的mytable.ibd和mytable.exp文件复制到当前服务器的数据目录
然后使用如下命令将其“导入”

mysql > alter table mydatabase.mytable import tablespace;

示例:

innobackupex /backups
innobackupex --apply-log --export /backups/2017-11-16_12-48-23
mysql > create database mydb;
mysql > use mydb;
mysql > create table studentd(StuID,.....)
mysql > alter table students discard tablesapce;
rsync -aP /backups/2017-11-16_12-48-23/hellodb/{students.exp,students.idb} 10.134.115.56::root/data/mysql/mydb/
chown -R mysql.mysql /data/mysql/mydb/*
mysql > alter table students import tablespace;

4.7 使用Xtrabackup对数据库进行部分备份

Xtrabackup也可以实现部分备份,即只备份某个或某些指定的数据库和某数据库中某个或某些表,单要使用此功能,必须启动innodb_file_pre_table选项,即每张表保存为一个独立的文件,同时,其也不支持–stream选项,即不支持将数据通过管道传输给其他程序进行处理

此外,还原部分备份跟还原全部数据的备份也有所不同,即你不能通过简单地将prepared的部分备份使用–copy-backup选项直接复制回数据目录,而是要通过导入表的方向来实现还原,当然,有些情况下,部分备份也可以直接通过
–copy-backup进行还原,但这种方式还原而来的数据多数会产生数据不一致的问题,因此,无论如何不推荐使用这种方式

你可能感兴趣的:(MySQL)