MySQL中的数据备份与还原(导出导入)实践总结

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: MySQL中的数据备份与还原(导出导入)实践总结

数据备份与还原的常用方式:数据表备份,单表数据备份,SQL备份和 增量备份。

物理备份与逻辑备份

物理备份:备份数据文件,转储数据库物理文件到某一目录。物理备份恢复速度比较快,但占用空间比较大,MySQL中可以用xtrabackup工具来进行物理备份。

逻辑备份:对数据库对象利用工具进行导出工作,汇总入备份文件内。逻辑备份恢复速度慢,但占用空间小,更灵活。MySQL中常用的逻辑备份工具为mysqldump。逻辑备份就是备份SQL语句,在恢复的时候执行备份的SQL语句实现数据库数据的重现。

【1】mysqldump实现逻辑备份

mysqldump命令执行时,可以将数据库备份成一个文本文件,该文件中实际上包含多个create和insert语句,使用这些语句可以重新创建表和插入数据。

  • 查出需要备份的标的结构,在文本文件中生成一个create语句
  • 将表中的所有记录转换成一条insert语句。

基本语法

mysqldump -u 用户名称 -h 主机名称 -p密码 待备份的数据库名称[tbname,[tbname...]] > 备份文件名称.sql
# 如果在Windows环境下则是mysqldump.exe

当然,备份的文件并非一定要求后缀名称为.sql , 后缀名为.txt也是可以的。

① 备份单个数据库

如下备份数据库testindex,包含该库所有表和数据。

mysqldump -uroot -h localhost -p testindex > /var/lib/mysql/backup/testindex.sql

如下所示是备份的文件,其中下面这部分是MySQL的数据库版本信息,非MySQL将不会识别。

# 将系统变量赋值给用户变量,末尾会再恢复 40101表示数据库版本 4.01.01
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0                                                                                                                                                              */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

57a26f1fae524fb7b07f2cc33964483c.png

--开头的都是SQL语句的注释。以 /*! 开头、*/ 结尾的语句为可执行的MySQL注释,这些语句可以被MySQL执行,但在其他数据库管理系统中被作为注释忽略,这可以提高数据库的可移植性。


可以看到文件开头指明了备份文件使用的mysqldump工具的版本号,接下来是备份主机信息以及备份的数据库的名称,最后是MySQL服务器的版本号,这里是8.0.25。

② 备份全部数据库

mysqldump -uroot -h localhost -p  --all-databases> /var/lib/mysql/backup/alldatabases.sql
#或
mysqldump -uroot -h localhost -p  -A> /var/lib/mysql/backup/alldatabases.sql

③ 备份部分数据库

使用 --databases-B 参数,该参数后面跟数据库名称,多个数据库间用空格隔开。如果指定databases参数,备份文件中会存在创建数据库的语句,如果不指定参数,则不存在。

语法如下:

mysqldump -uroot -h localhost -p  --databases [dbname1 [dbname2...]]> /var/lib/mysql/backup/备份文件名称.sql
#或
mysqldump -uroot -h localhost -p  -B [dbname1 [dbname2...]]> /var/lib/mysql/backup/备份文件名称.sql

④ 备份部分表

mysqldump -uroot -h localhost -p  数据库名称 [表名1 [表名2...]]> /var/lib/mysql/backup/备份文件名称.sql

⑤ 备份单表的部分数据

有时候我们只需要备份某个表的一部分数据,这时可以使用--where选项。

举例备份用户表中id小于5的数据:

mysqldump -uroot -p testindex tb_sys_user --where="id<5" > user_part_id5_low_bak.sql

⑥ 排除某些表的备份

如果我们想备份某个库,但是某些表数据量很大或者与业务关联不大,这个时候可以考虑排除掉这些表。同样的,选项 --ignore-table 可以完成这个功能。

mysqldump -uroot -p testindex --ignore-table=testindex.tb_sys_user > no_user_bak.sql

⑦ 只备份结构或只备份数据

只备份结构可以使用 --no-data 简写为 -d选项,只备份数据可以使用--no-create-info简写为-t选项

  • 只备份结构
mysqldump -uroot -p testindex --no-data > no_data.sql
  • 只备份数据
mysqldump -uroot -p testindex --no-create-info > no_create_info.sql

⑧ 备份中包含存储过程、函数、事件

mysqldump备份默认是不包含存储过程,自定义函数及事件的。可以使用--routines-R选项来备份存储过程及函数,使用 --events-E参数来备份事件。

可以使用下面的SQL查看当前库有哪些存储过程或函数

select specific_name,routine_type,routine_schema from information_schema.routines where ro

【2】mysql命令恢复数据

使用mysqldump命令将数据库中的数据备份成一个文本文件,需要恢复时,可以使用mysql命令来恢复备份的数据。

mysql命令可以执行备份文件中的create语句和insert语句,通过create语句来创建数据库和表,通过insert语句来插入备份的数据。

基本语法:

mysql -u 用户名 -p [dbname] < 备份文件.sql

其中,dbname参数表示数据库名称,该参数是可选参数。指定数据库名称时,表示还原该数据库下的表。此时需要确保MySQL服务器中已经创建了该名的数据库。不指定数据库名时,表示还原文件中所有的数据库。此时SQL文件中包含有create database语句,不需要MySQL服务器中已存在这些数据库。

① 单库备份中恢复单库

如果备份文件中包含了创建数据库的语句,则恢复的时候不需要指定数据库名称:

mysql -uroot -p < testindex.sql

否则需要指定数据库名称:

mysql -uroot -p testindex < testindex.sql

② 全量备份恢复

如果我们有数据库昨天的全量备份,可以如下操作

mysql -uroot -p < all.sql

如果使用 --all-databases 参数备份了所有的数据库,那么恢复时不需要指定数据库。对应的SQL文件包含有create database语句,可通过该语句创建数据库。

③ 从全量备份中恢复单库

如下所示从全量备份中分离出单个库的备份:

sed -n '/^-- Current Database: `testindex`/,/^-- Current Database: `/p' alldatabases.sql

分离完成后我们再导入testindex.sql即可恢复单个库。

④ 从单库备份中恢复单表

如我们有testindex库的备份,但是只需要恢复tb_sys_user表。

cat testindex.sql|sed -e '/./{H;$!d;}' -e 'x;/CREATE TABLE `tb_sys_user`/!d;q' >tb_sys_user_structure.sql
cat testindex.sql| grep --ignore-case 'insert into `tb_sys_user`' >tb_sys_user_data.sql

用shell语法分离出创建表的语句及插入数据的语句后,再依次导入即可完成恢复。

⑤使用SQL指令进行还原

语法格式如下:

source 文件目录

示例如下:

source /var/lib/mysql/backup/testindex.sql

【3】物理备份与恢复

① 物理备份:直接复制整个数据库

直接将MySQL中的数据库文件复制出来,这种方法最简单速度页最快。但为了保证备份的一致性,需要保证:

  • 方式1:备份前,将服务器停止
  • 方式2:备份前,对相关表执行FLUSH TABLES WITH READ LOCK操作。这样当复制数据库目录中的文件时,允许其他客户继续查询表。同时,FLUSH TABLES语句来确保开始备份前将所有激活的索引页写入硬盘。

这种方式方便、快捷,但不是最好的备份方法。因为实际情况可能不允许停止MySQL服务器或者锁住表,而且这种方法对InnoDB存储引擎的表不适用。对于MyISAM存储引擎的表,这样备份和还原很方便。但是还原时最好是相同版本的MySQL数据库,否则可能会存在文件类型不同的情况。


注意,物理备份完毕后,执行 UNLOCK TABLES来结束其他客户对表的修改行为。

# 将数据库文件复制到backup下
cp -r /var/lib/mysql/testindex /var/lib/mysql/backup/
#删除数据库文件
rm -rf /var/lib/mysql/testindex
# 这时候进行验证,可以看到该数据库下表数据时不存在的

② 物理恢复:直接复制到数据库目录

需要注意如下两点

  • 必须确保备份数据的数据库和待恢复的数据库服务器的主版本号相同,才能保证这两个MySQL数据库文件类型是相同的
  • 这种方式对MyISAM类型的表有效,对于InnoDB类型的表无效。因为InnoDB的表空间不能直接复制

在Linux操作系统下,复制到数据库目录后,一定要将数据库的用户和组变成mysql:

#赋予权限
chown -R mysql.mysql /var/lib/mysql/dbname

其中,两个mysql分表表示组合用户,“-R”参数可以改变文件夹下所有子文件的用户和组。

#恢复数据库文件
cp -r  /var/lib/mysql/backup/testindex /var/lib/mysql/
#赋予权限
chown -R mysql.mysql /var/lib/mysql/testindex
#重启MySQL服务
systemctl restart mysqld

【4】单表数据备份与还原

① select…into outfile表数据备份

  • 特点:每次只能备份一张表,只能备份数据(表结构不能备份);
  • 通常的使用方式:将表中的数据导出到文件;
  • 备份:从表中选出一部分数据保存到外部的文件中;

通常在数据(表)库备份中不会使用该方式。

语法格式如下:

select * /字段列表 into outfile 文件所在路径 from 数据源;
//前提:外部文件不存在。

mysql默认对导出的目录有权限限制,也就是说使用命令进行导出的时候,需要指定目录操作。可以查询secure_file_priv 变量值来查看目录:

mysql> show variables like 'secure_file_priv';
+------------------+-----------------------+
| Variable_name    | Value                 |
+------------------+-----------------------+
| secure_file_priv | /var/lib/mysql-files/ |
+------------------+-----------------------+
1 row in set (0.01 sec)

参数secure_file_priv 的可选值和作用分别是:

  • 如果设置为empty,表示不限制文件生成的位置,这是不安全的设置;
  • 如果设置为一个表示路径的字符串,就要去生成的文件只能放在这个指定的目录或者它的子目录
  • 如果设置为NULL,就表示禁止在这个MySQL实例上执行 select…info outfile操作。
mysql> select * from tb_sys_user into outfile "/opt/tb_sys_user.txt";
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it canno                                                                                                                                               t execute this statement

我们导出到/var/lib/mysql-files/ 则正常执行:

select * from tb_sys_user into outfile "/var/lib/mysql-files/tb_sys_user.txt";

高级备份–自己指定字段和行的处理方式

语法格式如下:

select */字段列表 into outfile 文件所在路径 fields 字段处理 lines 行处理 from 数据源;

Fields :字段处理。

Enclosed by:字段使用什么内容包裹,默认是 ‘’—空字符串。

Terminated by:字段以什么结束,默认是’\t’----Tab键。

Escaped by:特殊符号用什么方式处理,默认是’\',使用反斜杠转义。

Lines:行处理。

Starting by:每行以什么开始,默认是 ‘’-----空字符串。

Terminated by:每行以什么结束,默认是’\r\n’----换行符。

测试如下:

select * into OUTFILE 'D:/temDirectory/backup.txt' 
-- 字段处理
FIELDS
ENCLOSED by '"'-- 数据使用双引号包裹;
TERMINATED by '|' -- 使用竖线分隔字段数据;
-- 行处理
LINES
STARTING by 'START:'
FROM p_user

20170613085041951.png

② 使用mysqldump命令导出文本文件

mysqldump  -uroot -p -T "/var/lib/mysql-files" testindex tb_sys_use

mysqldump命令执行完毕后,在指定的目录/var/lib/mysql-files 下生成了tb_sys_user.sql 和 tb_sys_user.txt文件。


上述命令生成的tb_sys_user.sql文件内容包含表的create语句,没有数据的insert into语句。


b_sys_user.txt内容只包含表中的数据:

[root@localhost mysql-files]# cat tb_sys_user.txt
1       jane    11      男
2       tom     12      男
3       lucy    18      女
4       jack    17      男
5       janus   16      男
6       lily    17      女

mysqldump导出到文本文件时,也可以使用fields选项,要求字段之间使用逗号分隔,所有字符类型字符值用双引号括起来:

mysqldump  -uroot -p -T "/var/lib/mysql-files" testindex tb_sys_user --fields-terminated-by',' --fields-optionally-enclosed-by='\"'

③ 使用mysql命令导出文本文件

如下所示导出数据库testindex中tb_sys_user表数据到文本文件:

mysql -uroot -p --execute="select * from tb_sys_user;" testindex > "/var/lib/mysql-files/tb_sys_user.txt"
[root@localhost mysql-files]# cat tb_sys_user.txt
id      name    age     sex
1       jane    11      男
2       tom     12      男
3       lucy    18      女
4       jack    17      男
5       janus   16      男
6       lily    17      女

使用 --veritcal参数将该提交记录分为多行显式:

mysql -uroot -p  --vertical --execute="select * from tb_sys_user;" testindex > "/var

fa411f20ac2645f7a062cdc2bda8ffc4.png

④ 使用LOAD DATA INFILE方式导入文本文件

将一个在外部保存的数据重新恢复到表中(前提是表结构必须存在)。

语法格式如下:

Load data infile 文件所在路径 into table 表名[(字段列表)] [fields 字段处理]  [lines 行处理]
//怎么导出去的就怎么还原(fields,lines)

示例如下:

#Linux下
load data infile '/var/lib/mysql-files/tb_sys_user.txt' into table testindex.tb_sys_user;
# windows下 如果导出的时候使用了fields lines选项...
Load data infile 'D:/temDirectory/backup.txt'  into table p_user 
FIELDS
ENCLOSED by '"'-- 数据使用双引号包裹;
TERMINATED by '|' -- 使用竖线分隔字段数据;
-- 行处理
LINES
STARTING by 'START:'

⑤ 使用mysqlimport方式导入文本文件

导出的时候字段之间使用逗号隔开,字段值使用双引号括起来:

select * from testindex.tb_sys_user into outfile '/var/lib/mysql-files/tb_sys_user.txt' fields terminated by ',' enclosed by '\"' ;

使用mysqlimport命令将tb_sys_user.txt文件内容导入到数据库testindex的tb_sys_user表中:

mysqlimport -uroot -p testindex '/var/lib/mysql-files/tb_sys_user.txt' --fields-terminated-by=',' --fields-optionally-enclosed-by='\"'

此外还有一种为“增量备份”,不是针对数据或者SQL指令进行备份,而是针对MySQL服务器的日志文件进行备份。

增量备份定义:指定时间段开始备份,备份数据不会重复,而且所有的操作都会备份(大项目都用增量备份)。


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
8天前
|
缓存 关系型数据库 MySQL
MySQL 索引优化与慢查询优化:原理与实践
通过本文的介绍,希望您能够深入理解MySQL索引优化与慢查询优化的原理和实践方法,并在实际项目中灵活运用这些技术,提升数据库的整体性能。
28 5
|
18天前
|
SQL 关系型数据库 MySQL
MySQL导入.sql文件后数据库乱码问题
本文分析了导入.sql文件后数据库备注出现乱码的原因,包括字符集不匹配、备注内容编码问题及MySQL版本或配置问题,并提供了详细的解决步骤,如检查和统一字符集设置、修改客户端连接方式、检查MySQL配置等,确保导入过程顺利。
|
21天前
|
存储 关系型数据库 MySQL
PHP与MySQL动态网站开发:从基础到实践####
本文将深入探讨PHP与MySQL的结合使用,展示如何构建一个动态网站。通过一系列实例和代码片段,我们将逐步了解数据库连接、数据操作、用户输入处理及安全防护等关键技术点。无论您是初学者还是有经验的开发者,都能从中获益匪浅。 ####
|
27天前
|
关系型数据库 MySQL Java
MySQL索引优化与Java应用实践
【11月更文挑战第25天】在大数据量和高并发的业务场景下,MySQL数据库的索引优化是提升查询性能的关键。本文将深入探讨MySQL索引的多种类型、优化策略及其在Java应用中的实践,通过历史背景、业务场景、底层原理的介绍,并结合Java示例代码,帮助Java架构师更好地理解并应用这些技术。
26 2
|
1月前
|
关系型数据库 MySQL Linux
Linux环境下MySQL数据库自动定时备份实践
数据库备份是确保数据安全的重要措施。在Linux环境下,实现MySQL数据库的自动定时备份可以通过多种方式完成。本文将介绍如何使用`cron`定时任务和`mysqldump`工具来实现MySQL数据库的每日自动备份。
97 3
|
1月前
|
存储 监控 关系型数据库
MySQL自增ID耗尽解决方案:应对策略与实践技巧
在MySQL数据库中,自增ID(AUTO_INCREMENT)是一种特殊的属性,用于自动为新插入的行生成唯一的标识符。然而,当自增ID达到其最大值时,会发生什么?又该如何解决?本文将探讨MySQL自增ID耗尽的问题,并提供一些实用的解决方案。
42 1
|
17天前
|
SQL 关系型数据库 MySQL
PHP与MySQL的高效交互:从基础到实践####
本文深入探讨了PHP与MySQL数据库之间的高效交互技术,涵盖了从基础连接到高级查询优化的全过程。不同于传统的摘要概述,这里我们直接以一段精简代码示例作为引子,展示如何在PHP中实现与MySQL的快速连接与简单查询,随后文章将围绕这一核心,逐步展开详细讲解,旨在为读者提供一个从入门到精通的实战指南。 ```php <?php // 数据库配置信息 $servername = "localhost"; $username = "root"; $password = "password"; $dbname = "test_db"; // 创建连接 $conn = new mysqli($se
22 0
|
2月前
|
NoSQL 关系型数据库 MySQL
MySQL与Redis协同作战:百万级数据统计优化实践
【10月更文挑战第21天】 在处理大规模数据集时,传统的单体数据库解决方案往往力不从心。MySQL和Redis的组合提供了一种高效的解决方案,通过将数据库操作与高速缓存相结合,可以显著提升数据处理的性能。本文将分享一次实际的优化案例,探讨如何利用MySQL和Redis共同实现百万级数据统计的优化。
109 9
|
2月前
|
SQL 存储 关系型数据库
SQL文件导入MySQL数据库的详细指南
数据库中的数据转移是一项常规任务,无论是在数据迁移过程中,还是在数据备份、还原场景中,导入导出SQL文件显得尤为重要。特别是在使用MySQL数据库时,如何将SQL文件导入数据库是一项基本技能。本文将详细介绍如何将SQL文件导入MySQL数据库,并提供一个清晰、完整的步骤指南。这篇文章的内容字数大约在
342 1
|
2月前
|
XML 关系型数据库 MySQL
MySQL 导出某些数据的技术详解
MySQL 导出某些数据的技术详解
156 2