MySQL数据库的备份和恢复(重中之重)

MySQL数据库的备份和恢复

1 备份恢复概述

为什么要备份

灾难恢复:硬件故障、软件故障、自然灾害、黑客攻击、误操作测试等数据丢失场景

备份注意要点

  • 能容忍最多丢失多少数据
  • 恢复数据需要在多长时间空完成
  • 需要恢复哪些数据

还原要点

  • 做还原测试,用于测试备份的可用性
  • 还原演练,写成规范的技术文档

备份类型

  • 完全备份,部分备份
    完全备份:整个数据集
    部分备份:只备份数据子集,如部分库或表
  • 完全备份、增量备份、差异备份
    增量备份:仅备份最近一次完全备份或增量备份(如果存在增量)以来变化的数据,备份较快,还原复杂
    差异备份:仅备份最近一次完全备份以来变化的数据,备份较慢,还原简单

增量备份
差异备份
注意:二进制日志文件不应该与数据文件放在同一磁盘

  • 冷、温、热备份
    冷备:读、写操作均不可进行,数据库停止服务
    温备:读操作可执行,但写操作不可执行
    热备:读、写操作均可执行
    MyISAM:温备,不支持热备

    ​ InnoDB:都支持

  • 物理和逻辑备份
    物理备份:直接备份数据文件进行备份,与存储引擎有关,占用较多的空间,速度快
    逻辑备份:从数据库中“导出”数据另存而进行的备份,与存储引擎无关,占用空间少,速度慢,可能丢失精度

备份时需要考虑的因素

  • 温备的持锁多久
  • 备份产生的负载
  • 备份过程的时长
  • 恢复过程的时长

备份什么

  • 数据
  • 二进制日志、InnoDB的事务日志
  • 用户账号、权限设置,程序代码(存储过程、函数、触发器、事件调度器)
  • 服务器的配置文件

备份工具

  • cp, tar等复制归档工具:物理备份工具,适用所有存储引擎;只支持冷备;完全和部分备份
  • LVM的快照:先加读锁,做快照后解锁,几乎热备;借助文件系统工具进行备份
  • mysqldump:逻辑备份工具,适用所有存储引擎,对MyISAM存储引擎进行温备;支持完全或部
    分备份;对InnoDB存储引擎支持热备,结合binlog的增量备份
  • xtrabackup:由Percona提供支持对InnoDB做热备(物理备份)的工具,支持完全备份、增量备份
    MariaDB Backup: 从MariaDB 10.1.26开始集成,基于Percona XtraBackup 2.3.8实现
  • mysqlbackup:热备份, MySQL Enterprise Edition组件
  • mysqlhotcopy:PERL 语言实现,几乎冷备,仅适用于MyISAM存储引擎,使用LOCK TABLES、
    FLUSH TABLES和cp或scp来快速备份数据库

基于LVM的快照备份

  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 # -s -p r -n NAME /DEV/VG_NAME/LV_NAME
    
  4. 释放锁

    mysql> UNLOCK TABLES;
    
  5. 挂载快照卷,执行数据备份

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

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

范例:数据库冷备份和还原

#在目标主机服务器(10.0.0.111)安装mariadb-server,不启动服务
[root@centos8 ~]# yum install mariadb-server -y

#在源主机(10.0.0.107)上执行
[root@CentOS8-1 ~]# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 9
Server version: 10.3.17-MariaDB-log MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| hellodb            |
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.004 sec)

MariaDB [(none)]> exit
Bye
[root@CentOS8-1 ~]# systemctl stop  mariadb
[root@CentOS8-1 ~]# scp -r /var/lib/mysql/* 10.0.0.111:/var/lib/mysql/
[root@CentOS8-1 ~]# scp /etc/my.cnf.d/mariadb-server.cnf 10.0.0.111:/etc/my.cnf.d/
[root@CentOS8-1 ~]# scp -r /data/mysql/logs 10.0.0.111:/data/mysql/   #二进制日志文件夹需要在目标主机自己创建/data/mysql     用rsync复制可以保留属性

#在目标主机(10.0.0.111)上执行
[root@centos8 ~]# chown -R mysql.mysql /etc/my.cnf.d/mariadb-server.cnf
[root@centos8 ~]# chown -R mysql.mysql /var/lib/mysql/
[root@centos8 ~# chown -R mysql.mysql /data/mysql/logs/
[root@centos8 ~]# systemctl start mariadb
[root@centos8 ~]# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 9
Server version: 10.3.17-MariaDB-log MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| hellodb            |
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
4 rows in set (0.001 sec)

MariaDB [(none)]> 

 It's OK

2 mysqldump备份工具

2.1 mysqldump说明

逻辑备份工具
mysqldump, mydumper, phpMyAdmin
Schema和数据存储在一起、巨大的SQL语句、单个巨大的备份文件

mysqldump:是MySQL的客户端命令,通过mysql协议连接至mysql服务器进行备份

命令格式

mysqldump [OPTIONS] database [tables] #支持指定数据库和指定多表的备份,但数据库本身定义不备份
mysqldump [OPTIONS] –B DB1 [DB2 DB3...] #支持指定数据库备份,包含数据库本身定义也会备份
mysqldump [OPTIONS] –A [OPTIONS] #备份所有数据库,包含数据库本身定义也会备份

mysqldump参考:

https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html

mysqldump 常见通用选项:

-A, --all-databases 		#备份所有数据库,含create database
-B, --databases db_name… 	#指定备份的数据库,包括create database语句
-E, --events:				#备份相关的所有event scheduler
-R, --routines:				#备份所有存储过程和自定义函数
--triggers:					#备份表相关触发器,默认启用,用--skip-triggers,不备份触发器
--default-character-set=utf8 	#指定字符集
--master-data[=#]: 			#此选项须启用二进制日志
#1:所备份的数据之前加一条记录为CHANGE MASTER TO语句,非注释,不指定#,默认为1,适合于主从复制多机使用
#2:记录为被注释的#CHANGE MASTER TO语句,适合于单机使用
#此选项会自动关闭--lock-tables功能,自动打开-x | --lock-all-tables功能(除非开启--single-transaction)
-F, --flush-logs #备份前滚动日志,锁定表完成后,执行flush logs命令,生成新的二进制日志文件,配合-A 或 -B 选项时,会导致刷新多次数据库。建议在同一时刻执行转储和日志刷新,可通过和--single-transaction或-x,--master-data 一起使用实现,此时只刷新一次二进制日志
--compact 					#去掉注释,适合调试,生产不使用
-d, --no-data 				#只备份表结构
-t, --no-create-info 		#只备份数据,不备份create table
-n,--no-create-db		    #不备份create database,可被-A或-B覆盖
--flush-privileges 			#备份mysql或相关时需要使用
-f, --force				    #忽略SQL错误,继续执行
--hex-blob  				#使用十六进制符号转储二进制列,当有包括BINARY, VARBINARY,BLOB,BIT的数据类型的列时使用,避免乱码
-q, --quick 				#不缓存查询,直接输出,加快备份速度

mysqldump的MyISAM存储引擎相关的备份选项:

MyISAM不支持事务,只能支持温备;不支持热备,所以必须先锁定要备份的库,而后启动备份操作

-x,--lock-all-tables #加全局读锁,锁定所有库的所有表,同时加--single-transaction或--lock-tables	选项会关闭此选项功能,注意:数据量大时,可能会导致长时间无法并发访问数据库
-l,--lock-tables #对于需要备份的每个数据库,在启动备份之前分别锁定其所有表,默认为on,--skip-lock-tables选项可禁用,对备份MyISAM的多个库,可能会造成数据不一致
#注:以上选项对InnoDB表一样生效,实现温备,但不推荐使用

mysqldump的InnoDB存储引擎相关的备份选项:

InnoDB 存储引擎支持事务,可以利用事务的相应的隔离级别,实现热备,也可以实现温备但不建议用

--single-transaction
#此选项Innodb中推荐使用,不适用MyISAM,此选项会开始备份前,先执行START TRANSACTION指令开启事务
#此选项通过在单个事务中转储所有表来创建一致的快照。 仅适用于存储在支持多版本控制的存储引擎中的表(目前只有InnoDB可以); 转储不保证与其他存储引擎保持一致。 在进行单事务转储时,要确保有效的转储文件(正确的表内容和二进制日志位置),没有其他连接应该使用以下语句:ALTER TABLE,DROP TABLE,RENAME TABLE,TRUNCATE TABLE,此选项和--lock-tables(此选项隐含提交挂起的事务)选项是相互排斥,备份大型表时,建议将--single-transaction选项和--quick结合一起使用
2.2 生产环境实战备份策略

InnoDB建议备份策略

mysqldump –uroot -p –A –F –E –R --single-transaction --master-data=1 --flush-privileges  --triggers --default-character-set=utf8 --hex-blob >${BACKUP}/fullbak_${BACKUP_TIME}.sql

MyISAM建议备份策略

mysqldump –uroot -p –A –F –E –R –x --master-data=1 --flush-privileges --
triggers --default-character-set=utf8 --hex-blob
>${BACKUP}/fullbak_${BACKUP_TIME}.sql
2.3 mysqldump 备份还原实战案例
2.3.1 实战案例:特定数据库的备份脚本
#!/bin/bash
#
TIME=`date +%F_%H-%M-%S`
DIR=/data/backup
DB=hellodb
PASS=swyer
mysqldump -uroot -p"$PASS" -F --single-transaction --master-data=2 --default-character-set=utf8 -q -B $DB | gzip > ${DIR}/${DB}_${TIME}.sql.gz

2.3.2 实战案例:分库备份并压缩
[root@centos8 ~]#mysql -uroot -e 'show databases'|sed -rn '/^(Database|information_schema|performance_schema)$/!s#(.*)# mysqldump -B \1 |gzip > /data/\1.sql.gz#p' |bash
[root@CentOS8-1 ~]# mysql -uroot  -e 'show databases'|grep -Ev '^(Database|information_schema|performance_schema)$' | sed -rn 's# (.*)#mysqldump -B \1 | gzip > /data/\1.sql.gz#p' |bash
[root@CentOS8-1 ~]# mysql -uroot -e 'show databases'|grep -Ev '^(Database|information_schema|performance_schema)$'|while read db;do mysqldump -B $db|gzip >/data/$db.sql.gz;done

[root@CentOS8-1 ~]# for db in `mysql -uroot -e 'show databases'|grep -Ev '^(Database|information_schema|performance_schema)$'`;do mysqldump -B $db | gzip > /data/$db.sql.gz;done

[root@CentOS8-1 ~]# cat backup_db.sh 
#!/bin/bash
#
TIME=`date +%F_%H-%M-%S`
DIR=/data/backup
PASS=swyer
[ -d "$DIR" ] || mkdir $DIR
for DB in `mysql -uroot -p${PASS}    -e 'show databases' | grep -Ev "^Database|.*schema$"`;
do
	mysqldump -F --single-transaction --master-data=2 --default-character-set=utf8 -q -B $DB | gzip > ${DIR}/${DB}_${TIME}.sql.gz
done
[root@CentOS8-1 ~]# 

2.3.3 实战案例:完全备份和还原
#开启二进制日志
[root@CentOS8-1 ~]# vim /etc/my.cnf.d/mariadb-server.cnf 
[mysqld]
log-bin
[root@CentOS8-1 ~]# systemctl restart mariadb

#备份
[root@CentOS8-1 ~]# mysqldump -uroot -pswyer -A -F --single-transaction --master-data=2 |gzip >/data/all-`date +%F-%T`.sql.gz

#还原
#在一台全新的机器上试验
[root@centos8 ~]# dnf install mariadb-server
[root@centos8 ~]# gunzip /data/all-2020-02-25-18\:29\:33.sql.gz  #或者使用gzip -d
[root@centos8 ~]#systemctl start mariadb
[root@centos8 ~]#mysql </data/all-2020-02-25-18\:29\:33.sql
[root@centos8 ~]# mysql -uroot -pswyer
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 9
Server version: 10.3.17-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> set sql_log_bin=on;   #开启二进制
Query OK, 0 rows affected (0.000 sec)

MariaDB [(none)]> 

2.3.4 实战案例:利用二进制日志,还原数据库最新状态
#二进制日志独立存放
[root@CentOS8-1 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
log-bin=/data/mysql/mysql-bin

[root@CentOS8-1 ~]# systemctl restart mariadb

#完全备份,并记录备份的二进制位置
[root@CentOS8-1 ~]# mysqldump -uroot -pswyer -A -F --default-character-set=utf8 --single-transaction --master-data=2 |gzip >/data/backup/all_`date +%F`.sql.gz

#修改数据库
MariaDB [hellodb]> insert teachers (name,age,gender)value('swyer',18,'M');
MariaDB [hellodb]> insert teachers (name,age,gender)value('xiaozhangzi',18,'M');
MariaDB [hellodb]> update teachers set gender='F' where tid=6;
MariaDB [hellodb]> update teachers set name='zhangwenmin',age=20 where tid=6;
Query OK, 1 row affected (0.002 sec)
Rows matched: 1  Changed: 1  Warnings: 0

MariaDB [hellodb]> select * from teachers;
+-----+---------------+-----+--------+
| TID | Name          | Age | Gender |
+-----+---------------+-----+--------+
|   1 | Song Jiang    |  45 | M      |
|   2 | Zhang Sanfeng |  94 | M      |
|   3 | Miejue Shitai |  77 | F      |
|   4 | Lin Chaoying  |  93 | F      |
|   5 | swyer         |  18 | M      |
|   6 | zhangwenmin   |  20 | F      |
+-----+---------------+-----+--------+
6 rows in set (0.000 sec)


#损坏数据库
[root@CentOS8-1 ~]# rm -rf /var/lib/mysql/*

#还原
[root@CentOS8-1 ~]# cd /data/backup/
[root@CentOS8-1 backup]# ls
all_2020-02-25.sql.gz
[root@CentOS8-1 backup]# gunzip all_2020-02-25.sql.gz 

#CentOS8需要事先生成数据库相关文件,CentOS7 不需要执行此步
[root@CentOS8-1 ~]# mysql_install_db --user=mysql
[root@CentOS8-1 ~]# ls /var/lib/mysql/
aria_log.00000001  ib_buffer_pool  ib_logfile0  mysql               test
aria_log_control   ibdata1         ib_logfile1  performance_schema
[root@CentOS8-1 ~]# systemctl restart mariadb

MariaDB [(none)]> show master logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |       375 |
| mysql-bin.000002 |      1243 |
| mysql-bin.000003 |     28240 |
| mysql-bin.000004 |       342 |
+------------------+-----------+
4 rows in set (0.001 sec)

MariaDB [(none)]> set sql_log_bin=0;
Query OK, 0 rows affected (0.000 sec)

MariaDB [(none)]> source /data/backup/all_2020-02-25.sql

[root@CentOS8-1 ~]# grep -i '^-- change master to' /data/backup/all_2020-02-25.sql 
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=371;
[root@CentOS8-1 ~]# 

#二进制日志的备份
[root@CentOS8-1 ~]# mysqlbinlog /data/mysql/mysql-bin.000002 --start-position=371 >/data/backup/inc.sql
[root@CentOS8-1 ~]# mysqlbinlog /data/mysql/mysql-bin.000003 >>/data/backup/inc.sql
[root@CentOS8-1 ~]# 

MariaDB [mysql]> set sql_log_bin=0;
MariaDB [mysql]> source /data/backup/inc.sql
MariaDB [mysql]> set sql_log_bin=1;

2.3.5 实战案例:mysqldump 和二进制日志结合实现增量备份
[root@CentOS8-1 ~]# mysqldump -uroot -pswyer  -A -F --single-transaction --master-data=2 |gzip >/data/backup/all_`date +%F`.sql.gz

#解压查看二进制文件位置
[root@CentOS8-1 ~]# grep -i '^-- change master to' /data/backup/all_2020-02-25.sql
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000007', MASTER_LOG_POS=385;

#将之后的二进制日志进行复制备份
[root@CentOS8-1 ~]# ls /data/mysql/
mysql-bin.000001  mysql-bin.000003  mysql-bin.000005  mysql-bin.000007
mysql-bin.000002  mysql-bin.000004  mysql-bin.000006  mysql-bin.index
[root@CentOS8-1 ~]# cp /data/mysql/mysql-bin.000007 /data/backup/
[root@CentOS8-1 ~]# mysqlbinlog --start-position=385 /data/backup/mysql-bin.000007  >/data/backup/inc.sql
[root@CentOS8-1 ~]# 

2.3.6 恢复误删除的表

案例说明:每天2:30做完全备份,早上10:00误删除students,10:10才发现故障,现需要将数据
库还原到10:10的状态,且恢复被删除的students表

#完全备份
[root@CentOS8-1 ~]# mysqldump -uroot -pswyer -A -F --single-transaction --master-data=2 > /data/backup/allbackup_`date +%F_%T`.sql
[root@CentOS8-1 ~]# ll /data/backup/
total 480
-rw-r--r-- 1 root root 487999 Feb 25 21:07 allbackup_2020-02-25_21:07:33.sql

#完全备份后数据更新
MariaDB [hellodb]> insert students (name,age,gender) value('tom',20,'M');
Query OK, 1 row affected (0.002 sec)

MariaDB [hellodb]> insert students (name,age,gender) value('jerry',25,'M');
Query OK, 1 row affected (0.001 sec)

#10:10误删了一个重要的表
MariaDB [hellodb]> drop table students;
Query OK, 0 rows affected (0.006 sec)

MariaDB [hellodb]> 

#后续其它表继续更新
MariaDB [hellodb]> insert teachers (name,age,gender)values('swyer',18,'M');
Query OK, 1 row affected (0.001 sec)

MariaDB [hellodb]> insert teachers (name,age,gender)values('zhangwenmin',25,'F');
Query OK, 1 row affected (0.001 sec)

MariaDB [hellodb]> select * from teachers;
+-----+---------------+-----+--------+
| TID | Name          | Age | Gender |
+-----+---------------+-----+--------+
|   1 | Song Jiang    |  45 | M      |
|   2 | Zhang Sanfeng |  94 | M      |
|   3 | Miejue Shitai |  77 | F      |
|   4 | Lin Chaoying  |  93 | F      |
|   5 | swyer         |  18 | M      |
|   6 | zhangwenmin   |  20 | F      |
|   7 | swyer         |  18 | M      |
|   8 | zhangwenmin   |  25 | F      |
+-----+---------------+-----+--------+
8 rows in set (0.000 sec)

MariaDB [hellodb]> 

#10:10发现表删除,进行还原
MariaDB [(none)]> set sql_log_bin=0;  #禁用二进制日志
Query OK, 0 rows affected (0.000 sec)

MariaDB [test]> source /data/backup/allbackup_2020-02-25_21:07:33.sql

#停止数据库访问

#从完全备份中,找到二进制位置
[root@CentOS8-1 ~]# grep -i '^-- change master to' /data/backup/allbackup_2020-02-25_21\:07\:33.sql 
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000008', MASTER_LOG_POS=385;
#备份从完全备份后的二进制日志
[root@CentOS8-1 ~]# mysqlbinlog --start-position=385 /data/mysql/mysql-bin.000008  > /data/backup/inc.sql
[root@CentOS8-1 ~]# 

#找到误删除的语句,从备份中删除此语句,如果文件过大,可以使用sed实现
[root@CentOS8-1 ~]# sed -i 's/^DROP TABLE `students.*/^#DROP TABLE `students.*/' /data/backup/inc.sql 
#或者 sed -i '/DROP TABLE `students/d' /data/backup/inc.sql
#利用完全备份和修改过的二进制日志进行还原
MariaDB [hellodb]> set sql_log_bin=0;
MariaDB [hellodb]> source /data/backup/inc.sql
MariaDB [hellodb]> set sql_log_bin=1;

It's OK
发布了12 篇原创文章 · 获赞 0 · 访问量 407

猜你喜欢

转载自blog.csdn.net/swyer_66/article/details/104571743