MySQL 备份恢复

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL 备份恢复相关的知识,希望对你有一定的参考价值。

mysql 备份恢复

================================================================================

概述:


================================================================================

备份和恢复(数据):

  1.介绍

备份:存储的数据副本;

  • 原始数据:持续改变;(考虑问题)

恢复:把副本应用到线上系统;

  • 仅能恢复至备份操作时刻的数据状态;

时间点恢复:

  • binary logs; (二进制日志)

为什么备份?

  • 灾难恢复:硬件故障(冗余)、软件故障(bug)、自然灾害、黑客攻击、误操作、...

  • 测试;

备份时应该注意事项:

  • 能容忍最多丢失多少数据;

  • 恢复数据需要在多长时间内完成;

  • 需要恢复哪些数据;

做恢复演练:

  • 测试备份的可用性;

  • 增强恢复操作效率;

    ...

 2.备份类型

备份的数据的集范围:

完全备份和部分备份

  • 完全备份:整个数据集;

  • 部分备份:数据集的一部分,比如部分表;

完全备份、增量备份、差异备份:

  • 完全备份

  • 增量备份:仅备份自上一次完全备份或增量备份以来变量的那部分数据;

  • 差异备份:仅备份自上一次完全备份以来变量的那部数据;

物理备份、逻辑备份:

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

  • 逻辑备份:从数据库导出数据另存在一个或多个文件中;

根据数据服务是否在线:

  • 热备:读写操作均可进行的状态下所做的备份;

  • 温备:可读但不可写状态下进行的备份;

  • 冷备:读写操作均不可进行的状态下所做的备份;

 3.备份需要考虑的因素、备份策略及备份内容

备份需要考虑因素:

  • 锁定资源多长时间?

  • 备份过程的时长?

  • 备份时的服务器负载?

  • 恢复过程的时长?

备份策略:

  • 完全+差异+时间点还原(二进制日志binlog)

  • 完全+增量+时间点还原 (二进制日志binlog)

  • 注意:事务日志和二进制日志应该放在有冗余能力的磁盘上,RAID10最好

备份手段:

  • 物理

  • 逻辑

备份什么?

  • 数据

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

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

  • 服务器的配置文件

备份,多久一次?

  • 数据变化量;

  • 可用的备份存储空间;

 4.备份工具:

mysqldump:mysql服务自带的备份工具;逻辑备份工具;

  • 完全、部分备份;

  • InnoDB:热备;

  • MyISAM:温备;

cp/tar

  • lvm2:快照(请求一个全局锁),之后立即释放锁,达到几乎热备的效果;物理备份;

  • 注意:不能仅备份数据文件;要同时备份事务日志;

  • 前提:要求数据文件和事务日志位于同一个逻辑卷;

xtrabackup:

  由Percona提供,开源工具,支持对InnoDB做热备,物理备份工具;

  • 完全备份、部分备份;

  • 完全备份、增量备份;

  • 完全备份、差异备份;

mysqlhotcopy

select:

  • 备份:SELECT cluase INTO OUTFILE ‘FILENAME‘;

  • 恢复:CREATE TABLE 

  • 导入:LOAD DATA 

备份工具--mysqldump:

作用:

  • 逻辑备份、完全备份、部分备份;

二次封装工具:

  • mydumper   //能够实现并行备份

  • phpMyAdmin

Usage: 

  • mysqldump [OPTIONS] database [tables]

       //只备份指定库中的所有表,没有create database语句

  • mysqldump [OPTIONS] --databases [OPTIONS] DB1 [DB2 DB3...]

      //可以备份多个数据库,也可以指定备份哪个数据库

  • mysqldump [OPTIONS] --all-databases [OPTIONS]

     //备份所有数据库

MyISAM存储引擎:支持温备,备份时要锁定表;

  • -x, --lock-all-tables:锁定所有库的所有表,读锁;

  • -l, --lock-tables:锁定指定库所有表;

InnoDB存储引擎:支持温备和热备;

  • --single-transaction:创建一个事务,基于此快照执行备份;

   注意:一定要备份时间点一致的数据

其它选项:

  • -R, --routines:存储过程和存储函数;

  • --triggers      //触发器

  • -E, --events    //时间调度器   

  • --master-data[=#]

    记录备份那一刻开始时binlog处于哪一个文件的哪一个位置

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

      2:记录为CHANGE MASTER TO语句,此语句被注释;

  • --flush-logs:锁定表完成后,即进行日志刷新操作(使二进制日志滚动一下);

使用备份脚本实现自动化备份

注意:

  • 数据备份时要保留备份时的时间戳作为备份文件名的一部分;

  • 备份好的文件要做异地另存;

演示:

 1.备份hellodb数据库的所有表,操作如下:

[[email protected] ~]# mkdir mysql.bak  # 这里我先创建一个专门存放备份的目录

# 使用mysqldump 指明用户账户,要备份的数据库和重定向的位置即可
[[email protected] ~]# mysqldump -uroot -hlocalhost -ptaoxiu hellodb > ./mysql.bak/hellodb.sql.1

[[email protected] ~]# ls ./mysql.bak/
hellodb.sql.1

# 查看备份的hellodb数据库,可以看到表头显示的版本信息,数据库名称等
[[email protected] ~]# cat mysql.bak/hellodb.sql.1 
-- MySQL dump 10.14  Distrib 5.5.44-MariaDB, for Linux (x86_64)
--
-- Host: localhost    Database: hellodb
-- ------------------------------------------------------
-- Server version	5.5.44-MariaDB

/*!40101 SET @[email protected]@CHARACTER_SET_CLIENT */;
/*!40101 SET @[email protected]@CHARACTER_SET_RESULTS */;
/*!40101 SET @[email protected]@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @[email protected]@TIME_ZONE */;
/*!40103 SET TIME_ZONE=‘+00:00‘ */;
/*!40014 SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @[email protected]@SQL_MODE, SQL_MODE=‘NO_AUTO_VALUE_ON_ZERO‘ */;
/*!40111 SET @[email protected]@SQL_NOTES, SQL_NOTES=0 */;

 2.如上题,因为我们仅是备份指定数据库的所有表,所以没有create database语句,现在我们添加

--databases选项来备份,可以指明要备份的单个或者多个数据库,这样的话就create database语句了;

[[email protected] ~]# mysqldump -uroot -hlocalhost -ptaoxiu --databases hellodb > ./mysql.bak/hellodb.sql.2
[[email protected] ~]# ll -h mysql.bak
total 16K
-rw-r--r-- 1 root root 7.6K Dec  2 18:27 hellodb.sql.1
-rw-r--r-- 1 root root 7.8K Dec  2 18:41 hellodb.sql.2

[[email protected] ~]# cat mysql.bak/hellodb.sql.2
-- MySQL dump 10.14  Distrib 5.5.44-MariaDB, for Linux (x86_64)
--
-- Host: localhost    Database: hellodb
-- ------------------------------------------------------
-- Server version	5.5.44-MariaDB

/*!40101 SET @[email protected]@CHARACTER_SET_CLIENT */;
/*!40101 SET @[email protected]@CHARACTER_SET_RESULTS */;
/*!40101 SET @[email protected]@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @[email protected]@TIME_ZONE */;
/*!40103 SET TIME_ZONE=‘+00:00‘ */;
/*!40014 SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @[email protected]@SQL_MODE, SQL_MODE=‘NO_AUTO_VALUE_ON_ZERO‘ */;
/*!40111 SET @[email protected]@SQL_NOTES, SQL_NOTES=0 */;

--
-- Current Database: `hellodb`
--
# 存在创建数据库的语句
CREATE DATABASE /*!32312 IF NOT EXISTS*/ `hellodb` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `hellodb`;

 3.备份整个数据库,使用--all-databases选项

[[email protected] ~]# mysqldump -uroot -hlocalhost -ptaoxiu --all-databases > ./mysql.bak/data.sql.3
[[email protected] ~]# ll -h mysql.bak
total 15M
-rw-r--r-- 1 root root  15M Dec  2 18:45 data.sql.3   # 备份的所有数据库,明显文件大很多
-rw-r--r-- 1 root root 7.6K Dec  2 18:27 hellodb.sql.1
-rw-r--r-- 1 root root 7.8K Dec  2 18:41 hellodb.sql.2

 4.假如我们的备份策略为完全+增量+binlog备份,要使用binlog二进制日志重读,就要确定从备份那一刻开始,binlog的起始文件位置,这时就要使用--master-data=[#]选项,(确保二进制日志是开启的)

[[email protected] ~]# mysqldump -uroot -hlocalhost -ptaoxiu --master-data=2 --databases hellodb > ./mysql.bak/hellodb.sql.2

[[email protected] ~]# cat mysql.bak/hellodb.sql.2
-- MySQL dump 10.14  Distrib 5.5.44-MariaDB, for Linux (x86_64)
--
-- Host: localhost    Database: hellodb
-- ------------------------------------------------------
-- Server version	5.5.44-MariaDB-log

/*!40101 SET @[email protected]@CHARACTER_SET_CLIENT */;
/*!40101 SET @[email protected]@CHARACTER_SET_RESULTS */;
/*!40101 SET @[email protected]@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @[email protected]@TIME_ZONE */;
/*!40103 SET TIME_ZONE=‘+00:00‘ */;
/*!40014 SET @[email protected]@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @[email protected]@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @[email protected]@SQL_MODE, SQL_MODE=‘NO_AUTO_VALUE_ON_ZERO‘ */;
/*!40111 SET @[email protected]@SQL_NOTES, SQL_NOTES=0 */;

--
-- Position to start replication or point-in-time recovery from
--
   # 可以看到在备份的那一刻,二进制日志处在master-log.000004,POS为245
-- CHANGE MASTER TO MASTER_LOG_FILE=‘master-log.000003‘, MASTER_LOG_POS=245;

--
-- Current Database: `hellodb`
--

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `hellodb` /*!40100 DEFAULT CHARACTER SET utf8 */;

USE `hellodb`;


-----------------------------------------------------------------------

基于备份做时间点恢复数据库:

   上,我们已经备份好了hellodb的数据库,假如在备份之后,用户又修改了hellodb数据库的内容,之后hellodb数据库因为某些原因挂了,这时,我们除了借助于备份的数据库之外,还要借助于二进制日志文件binlog才能把数据库恢复到崩溃前的时间点。

 1.为了演示效果这里我首先修改一下hellodb数据库,模拟在hellodb数据库数据备份之后,崩溃之前,用户增加,修改的hellodb数据库中的内容,如下:

MariaDB [hellodb]> SELECT * FROM courses; # 修改之前的hellodb数据库courses表
+----------+----------------+
| CourseID | Course         |
+----------+----------------+
|        1 | Hamo Gong      |
|        2 | Kuihua Baodian |
|        3 | Jinshe Jianfa  |
|        4 | Taijiquan      |
|        5 | Daiyu Zanghua  |
|        6 | Weituo Zhang   |
|        7 | Dagou Bangfa   |
|       14 | Zabbix         |
+----------+----------------+
8 rows in set (0.00 sec)

MariaDB [hellodb]> INSERT INTO courses (Course) VALUES (‘Puppet‘),(‘Ansible‘);
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

MariaDB [hellodb]> DELETE FROM courses WHERE CourseID=2;
Query OK, 1 row affected (0.07 sec)

MariaDB [hellodb]> SELECT * FROM courses;  # 修改之后的hellodb数据库courses表
+----------+---------------+
| CourseID | Course        |
+----------+---------------+
|        1 | Hamo Gong     |
|        3 | Jinshe Jianfa |
|        4 | Taijiquan     |
|        5 | Daiyu Zanghua |
|        6 | Weituo Zhang  |
|        7 | Dagou Bangfa  |
|       14 | Zabbix        |
|       15 | Puppet        |
|       16 | Ansible       |
+----------+---------------+
9 rows in set (0.00 sec)


MariaDB [(none)]> drop database hellodb; # 删除hellodb数据库,模拟数据库崩溃
Query OK, 7 rows affected (0.08 sec)

 2.如上hellodb数据库已经崩溃,现在要做恢复,就要准备好备份的数据库文件hellodb.sql和要做时间点恢复的二进制日志文件,如下:

 1)首先准备要做时间点恢复的二进制日志文件

# 首先准备二进制日志文件
[[email protected] ~]# ls /var/lib/mysql/
aria_log.00000001  centos7.log       ibdata1      ib_logfile1        master-log.000002  master-log.000004  mydb   mysql.sock          Syslog  testdb  zabbix
aria_log_control   centos7-slow.log  ib_logfile0  master-log.000001  master-log.000003  master-log.index   mysql  performance_schema  test    ultrax

# 因为我最后执行的那个DELETE删除hellodb数据库的命令也会被记录在二进制日志文件中,所以,
# 要把最后的那个position截取掉,这里我重定向到/tmp/如下:
[[email protected] ~]# mysqlbinlog --stop-position=7996 /var/lib/mysql/master-log.000004 > /tmp/mylog.sql

 2)准备好备份好的hellodb数据库的备份文件hellodb.sql

[[email protected] ~]# ls mysql.bak
data.sql.3  hellodb.sql.1  hellodb.sql.2  hellodb.sql.4

[[email protected] ~]# cp mysql.bak/hellodb.sql.2 /tmp/hellodb.sql  # 假设在/tmp目录下
[[email protected] ~]# ls /tmp/

 3.测试,登录数据库,因为在恢复数据时会执行大量的写操作,但没有必要记录在二进制日志文件中,所以,可以关闭当前会话的二进制日志文件;然后倒入hellodb.sql脚本,可以发现hellodb数据库正常恢复到备份的时间点的数据,如下:

[[email protected] ~]# mysql -ptaoxiu
Welcome to the MariaDB monitor.  Commands end with ; or \g.

MariaDB [(none)]> SET sql_log_bin=OFF;  # 关闭当前会话的二进制日志文件
Query OK, 0 rows affected (0.00 sec)

MariaDB [(none)]> \. /tmp/hellodb.sql   # 倒入hellodb.sql脚本文件
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)
...

MariaDB [hellodb]> select * from courses; # 查询发现数据已经恢复到备份时间点的数据
+----------+----------------+
| CourseID | Course         |
+----------+----------------+
|        1 | Hamo Gong      |
|        2 | Kuihua Baodian |
|        3 | Jinshe Jianfa  |
|        4 | Taijiquan      |
|        5 | Daiyu Zanghua  |
|        6 | Weituo Zhang   |
|        7 | Dagou Bangfa   |
|       14 | Zabbix         |
+----------+----------------+
8 rows in set (0.00 sec)

 4.接下来,我们要想恢复到数据库崩溃之前的时间点,就要借助于二进制日志文件来恢复,如下:

MariaDB [(none)]> \. /tmp/mylog.sql  # 导入二进制日志文件的sql脚本
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)
...
MariaDB [hellodb]> select * from courses; # 查看数据可以发现,hellodb库的courses表恢复到了崩溃前我们修改的数据状态了
+----------+---------------+
| CourseID | Course        |
+----------+---------------+
|        1 | Hamo Gong     |
|        3 | Jinshe Jianfa |
|        4 | Taijiquan     |
|        5 | Daiyu Zanghua |
|        6 | Weituo Zhang  |
|        7 | Dagou Bangfa  |
|       14 | Zabbix        |
|       15 | Puppet        |
|       16 | Ansible       |
+----------+---------------+
9 rows in set (0.00 sec)

MariaDB [(none)]> SET sql_log_bin=ON;  # 开启记录二进制日志的文件
Query OK, 0 rows affected (0.00 sec)




基于lvm2的备份:

备份过程如下:

技术分享

备份工具---Xtrabackup:


















本文出自 “逐梦小涛” 博客,请务必保留此出处http://1992tao.blog.51cto.com/11606804/1879047

以上是关于MySQL 备份恢复的主要内容,如果未能解决你的问题,请参考以下文章

mysql数据没有备份误删了怎么恢复

mysql数据没有备份误删了怎么恢复

mysql备份与恢复

MySQL基于mysqldump及lvmsnapshot备份恢复

MySQL数据库 数据备份与恢复

MySQL备份恢复