前言:

MySQL 逻辑备份工具最常用的就是 mysqldump 了,一般我们都是备份整个实例或部分业务库。不清楚你有没有做过恢复,恢复场景可能就比较多了,比如我想恢复某个库或某个表等。那么如何从全备中恢复单库或单表,这其中又有哪些隐藏的坑呢?这篇文章我们一起来看下。

1.如何恢复单库或单表

前面文章有介绍过 MySQL 的备份与恢复。可能我们每个数据库实例中都不止一个库,一般备份都是备份整个实例,但恢复需求又是多种多样的,比如说我想只恢复某个库或某张表,这个时候应该怎么操作呢?

如果你的实例数据量不大,可以在另外一个环境恢复出整个实例,然后再单独备份出所需库或表用来恢复。不过这种方法不够灵活,并且只适用数据量比较少的情况。

其实从全备中恢复单库还是比较方便的,有个 --one-database 参数可以指定单库恢复,下面来具体演示下:

# 查看及备份所有库mysql> show databases;+--------------------+| Database      |+--------------------+| information_schema || mysql       || performance_schema || sbtest       || sys        || testdb       || testdb2      |+--------------------+mysqldump -uroot -pxxxx -R -E --single-transaction --all-databases > all_db.sql# 删除testdb库 并进行单库恢复mysql> drop database testdb;Query OK, 36 rows affected (2.06 sec)# 貌似恢复前 testdb库不存在的话要手动新建mysql -uroot -pxxxx --one-database testdb < all_db.sql
# 从全备中恢复单库sed -n '/^-- Current Database: `testdb`/,/^-- Current Database: `/p' all_db.sql > testdb.sql# 筛选出单表语句cat all_db.sql | sed -e '/./{H;$!d;}' -e 'x;/CREATE TABLE `test_tb`/!d;q' > /tmp/test_tb_info.sql cat all_db.sql | grep --ignore-case 'insert into `test_tb`' > /tmp/test_tb_data.sql

对于上述手动筛选来恢复单库或单表的方法,看起来简单方便,其实隐藏着一个小坑,下面我们来具体演示下:

# 备份整个实例mysqldump -uroot -pxxxx -R -E --single-transaction --all-databases > all_db.sql# 手动备份下test_tb 然后删除test_tbmysql> create table test_tb_bak like test_tb;Query OK, 0 rows affected (0.03 sec)mysql> insert into test_tb_bak select * from test_tb;Query OK, 4 rows affected (0.02 sec)Records: 4 Duplicates: 0 Warnings: 0mysql> drop table test_tb;Query OK, 0 rows affected (0.02 sec)# 从全备中筛选test_db建表及插数据语句cat all_db.sql | sed -e '/./{H;$!d;}' -e 'x;/CREATE TABLE `test_tb`/!d;q' > test_tb_info.sql cat all_db.sql | grep --ignore-case 'insert into `test_tb`' > test_tb_data.sql# 查看得到的语句 貌似没问题cat test_tb_info.sqlDROP TABLE IF EXISTS `test_tb`;/*!40101 SET @saved_cs_client   = @@character_set_client */;/*!40101 SET character_set_client = utf8 */;CREATE TABLE `test_tb` ( `inc_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键', `col1` int(11) NOT NULL, `col2` varchar(20) DEFAULT NULL, `col_dt` datetime DEFAULT NULL, `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', PRIMARY KEY (`inc_id`)) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8 COMMENT='测试表';/*!40101 SET character_set_client = @saved_cs_client */;cat test_tb_data.sqlINSERT INTO `test_tb` VALUES (1,1001,'dsfs','2020-08-04 12:12:36','2020-09-17 06:19:27','2020-09-17 06:19:27'),(2,1002,'vfsfs','2020-09-04 12:12:36','2020-09-17 06:19:27','2020-09-17 06:19:27'),(3,1003,'adsfsf',NULL,'2020-09-17 06:19:27','2020-09-17 06:19:27'),(4,1004,'walfd','2020-09-17 14:19:27','2020-09-17 06:19:27','2020-09-18 07:52:13');# 执行恢复单表操作mysql -uroot -pxxxx testdb < test_tb_info.sqlmysql -uroot -pxxxx testdb < test_tb_data.sql# 查看恢复数据 并和备份表比对mysql> select * from test_tb;+--------+------+--------+---------------------+---------------------+---------------------+| inc_id | col1 | col2  | col_dt       | create_time     | update_time     |+--------+------+--------+---------------------+---------------------+---------------------+|   1 | 1001 | dsfs  | 2020-08-04 12:12:36 | 2020-09-17 06:19:27 | 2020-09-17 06:19:27 ||   2 | 1002 | vfsfs | 2020-09-04 12:12:36 | 2020-09-17 06:19:27 | 2020-09-17 06:19:27 ||   3 | 1003 | adsfsf | NULL        | 2020-09-17 06:19:27 | 2020-09-17 06:19:27 ||   4 | 1004 | walfd | 2020-09-17 14:19:27 | 2020-09-17 06:19:27 | 2020-09-18 07:52:13 |+--------+------+--------+---------------------+---------------------+---------------------+4 rows in set (0.00 sec)mysql> select * from test_tb_bak;+--------+------+--------+---------------------+---------------------+---------------------+| inc_id | col1 | col2  | col_dt       | create_time     | update_time     |+--------+------+--------+---------------------+---------------------+---------------------+|   1 | 1001 | dsfs  | 2020-08-04 12:12:36 | 2020-09-17 14:19:27 | 2020-09-17 14:19:27 ||   2 | 1002 | vfsfs | 2020-09-04 12:12:36 | 2020-09-17 14:19:27 | 2020-09-17 14:19:27 ||   3 | 1003 | adsfsf | NULL        | 2020-09-17 14:19:27 | 2020-09-17 14:19:27 ||   4 | 1004 | walfd | 2020-09-17 14:19:27 | 2020-09-17 14:19:27 | 2020-09-18 15:52:13 |+--------+------+--------+---------------------+---------------------+---------------------+4 rows in set (0.00 sec)

那么你会问了,为什么全部恢复不会出问题呢?问的好,我们看下备份文件就知道了。

# 备份文件开头-- MySQL dump 10.13 Distrib 5.7.23, for Linux (x86_64)---- Host: localhost  Database:-- -------------------------------------------------------- Server version    5.7.23-log/*!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 */;/*!40101 SET NAMES utf8 */;/*!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 */;# 备份文件结尾/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;-- Dump completed on 2020-09-18 15:56:40

看到这里,不知道你是否看懂了呢,可能有过备份恢复经验的同学好理解些。解决上述问题的方法也很简单,那就是在执行SQL文件前,更改当前会话时区为0,再次来演示下:

# 清空test_db表数据mysql> truncate table test_tb;Query OK, 0 rows affected (0.02 sec)# 文件开头增加时区声明vim test_tb_data.sqlset session TIME_ZONE='+00:00';INSERT INTO `test_tb` VALUES (1,1001,'dsfs','2020-08-04 12:12:36','2020-09-17 06:19:27','2020-09-17 06:19:27'),(2,1002,'vfsfs','2020-09-04 12:12:36','2020-09-17 06:19:27','2020-09-17 06:19:27'),(3,1003,'adsfsf',NULL,'2020-09-17 06:19:27','2020-09-17 06:19:27'),(4,1004,'walfd','2020-09-17 14:19:27','2020-09-17 06:19:27','2020-09-18 07:52:13');# 执行恢复并比对 发现数据正确mysql> select * from test_tb;+--------+------+--------+---------------------+---------------------+---------------------+| inc_id | col1 | col2  | col_dt       | create_time     | update_time     |+--------+------+--------+---------------------+---------------------+---------------------+|   1 | 1001 | dsfs  | 2020-08-04 12:12:36 | 2020-09-17 14:19:27 | 2020-09-17 14:19:27 ||   2 | 1002 | vfsfs | 2020-09-04 12:12:36 | 2020-09-17 14:19:27 | 2020-09-17 14:19:27 ||   3 | 1003 | adsfsf | NULL        | 2020-09-17 14:19:27 | 2020-09-17 14:19:27 ||   4 | 1004 | walfd | 2020-09-17 14:19:27 | 2020-09-17 14:19:27 | 2020-09-18 15:52:13 |+--------+------+--------+---------------------+---------------------+---------------------+4 rows in set (0.00 sec)mysql> select * from test_tb_bak;+--------+------+--------+---------------------+---------------------+---------------------+| inc_id | col1 | col2  | col_dt       | create_time     | update_time     |+--------+------+--------+---------------------+---------------------+---------------------+|   1 | 1001 | dsfs  | 2020-08-04 12:12:36 | 2020-09-17 14:19:27 | 2020-09-17 14:19:27 ||   2 | 1002 | vfsfs | 2020-09-04 12:12:36 | 2020-09-17 14:19:27 | 2020-09-17 14:19:27 ||   3 | 1003 | adsfsf | NULL        | 2020-09-17 14:19:27 | 2020-09-17 14:19:27 ||   4 | 1004 | walfd | 2020-09-17 14:19:27 | 2020-09-17 14:19:27 | 2020-09-18 15:52:13 |+--------+------+--------+---------------------+---------------------+---------------------+4 rows in set (0.00 sec)

我们在网络中很容易搜索出恢复单库或单表的方法,大多都有提到上述利用 sed 、grep 命令来手动筛选的方法。但大部分文章都未提及可能出现的问题,如果你的表字段有timestamp 类型,用这种方法要格外注意。无论面对哪种恢复需求,我们都要格外小心,不要造成越恢复越糟糕的情况,最好有个空实例演练下,然后再进行恢复。

更多相关文章

  1. MySQL系列多表连接查询92及99语法示例详解教程
  2. Linux下MYSQL 5.7 找回root密码的问题(亲测可用)
  3. MySQL 什么时候使用INNER JOIN 或 LEFT JOIN
  4. android从服务器下载文件(php+apache+win7+MySql)
  5. 【有图】android通过jdbc连接mysql(附文件)
  6. android 通过php 连接 mysql
  7. android通过php连接mysql数据库!!!!
  8. 关于Android连接远程数据库(mysql、oracle)
  9. 图书馆座位管理系统(android,java后台,mysql)

随机推荐

  1. php pi函数是什么意思
  2. php chop函数是什么意思
  3. Android网络状态实时监听实例代码(二)
  4. Android百度地图Poi检索开发总结
  5. Android(安卓)设置 横屏 竖屏
  6. android 一键锁屏 开发
  7. Android中使用PreferenceActivity创建菜
  8. 安装 | Android(安卓)studio 3.5.2安装教
  9. Android(安卓)Rootkit开发技术要点 (一)
  10. Android(安卓)Messenger 进程间通信