数据库恢复方案

数据库恢复方案

http://netkiller.github.io/journal/db.restore.html

MrNeo Chen (netkiller)陈景峰(BG7NYT)


中国广东省深圳市龙华新区民治街道溪山美地
518131
+86 13113668890
+86 755 29812080
<[email protected]>

$Id$

版权 © 2011, 2012, 2013 http://netkiller.github.io

$Date$

摘要

这里所谈的内容是对备份数据的恢复,不是对损坏数据表的恢复,或者说灾难恢复。

我的系列文档

Netkiller Architect 手札 Netkiller Developer 手札 Netkiller PHP 手札 Netkiller Python 手札 Netkiller Testing 手札 Netkiller Cryptography 手札
Netkiller Linux 手札 Netkiller CentOS 手札 Netkiller FreeBSD 手札 Netkiller Security 手札 Netkiller Version 手札 Netkiller Web 手札
Netkiller Monitoring 手札 Netkiller Storage 手札 Netkiller Mail 手札 Netkiller Shell 手札 Netkiller Network 手札 Netkiller Database 手札
Netkiller PostgreSQL 手札 Netkiller MySQL 手札 Netkiller NoSQL 手札 Netkiller LDAP 手札 Netkiller Cisco IOS 手札 Netkiller H3C 手札
Netkiller Multimedia 手札 Netkiller Docbook 手札 Netkiller 开源软件 手札      

目录

1. 背景 2. 备份方式分析 3. 恢复方案 3.1. 第一种 3.2. 第二种 3.3. 第三种 3.4. 第四种 4. 手工恢复

1. 背景

我们来假设一个场景。

你是否适用 mysqldump 每隔一段时间备份一次数据库,每个备份一个数据文件。

公司决策你是不是因为数据持续增加,有些数据已经不会再查询,会删除旧的历史数据。

有时公司突然说要恢复历史数据,有可能全补回复,有可能部分恢复。

你将怎么做?

2. 备份方式分析

首先看看备份方式,你是不是采用这种方法备份

我使用一串数字表述数据库数据递增情况,数据的增长变化

垂直轴表示备份时间轴

最常见的备份方法,完全备份

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 。。。
|.......| 第一次备份
|.................| 第二次备份
|...........................| 第三次备份
|......................................| 第四次备份
|................................................| 第五次备份

下面这种备份方式也比较常见,这种方式很有规律。

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 。。。
|.......| 第一次备份
        |..........| 删除上一次以备份内容,第二次备份
                   |..........| 删除上一次以备份内容,第三次备份数据库
                              |..........| 删除上一次以备份内容,第四次备份
                                         |.........| 删除上一次以备份内容,第五次备份

更复杂的情况,无规律可循

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 。。。
|.......| 第一次备份
|..................| 第二次备份
        |......................| 删除一部分数据后同时做第三次备份数据库
                   |......................| 又删除一部分数据,第四次备份
                   |.............................| 第五次备份,没有删除数据
                   |......................................| 第六次备份,依然没有删除数据
                                          |..........................| 删除很多数据,第七次备份

以此类推,删除原因有多种,如空间不足,改善查询性能。。。等等

最杂的情况,无规律可循,同时交叉数据可能会有更新

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 。。。
|...o...| 第一次备份
|.....o............| 第二次备份
        |....o...o.............| 删除一部分数据后同时做第三次备份数据库
                   |.o..o..o..............| 又删除一部分数据,第四次备份
                   |....o......o.......o.........| 第五次备份,没有删除数据
                   |.......o.......o.........o............| 第六次备份,依然没有删除数据
                                          |.o....o......o............| 删除很多数据,第七次备份

我用'o' 表示与上次备份中有差异的部分。

3. 恢复方案

,最好恢复,第二种。

上面所提三种备份方式

第一种

最好恢复,100% 都能搞定.

第二种

恢复起来稍复杂,仍能搞得定.

第三种

比较复杂,因为本档案中存在重复记录,费点脑筋

第四种

最复杂,看似复杂,其实也不复杂,跟第三种差不多.

3.1. 第一种

这种备份非常简单,菜鸟也搞搞定

文本格式回复

cat dbname.sql | mysql -u user -p pass -h localhost yourdb

压缩格式恢复

zcat dbname.sql。gz | mysql -u user -p pass -h localhost yourdb

或者先使用gunzip解压,再恢复数据

gunzip dbname.sql。gz
cat dbname.sql | mysql -u user -p pass -h localhost yourdb

提示

很多人喜欢用tar打包,我不见这样做,一个文件时无需使用tar打包的,画蛇添足

仅使用gzip压缩,可以方便使用zcat直接操作文件。

3.2. 第二种

这种备份时连续的,只要依次按顺序恢复即可。

zcat dbname1.sql。gz | mysql -u user -p pass -h localhost yourdb
zcat dbname2.sql。gz | mysql -u user -p pass -h localhost yourdb
zcat dbname3.sql。gz | mysql -u user -p pass -h localhost yourdb
...
...
zcat dbname10.sql。gz | mysql -u user -p pass -h localhost yourdb

也可以跳跃恢复数据

zcat dbname2.sql。gz | mysql -u user -p pass -h localhost yourdb
zcat dbname3.sql。gz | mysql -u user -p pass -h localhost yourdb
zcat dbname5.sql。gz | mysql -u user -p pass -h localhost yourdb
zcat dbname10.sql。gz | mysql -u user -p pass -h localhost yourdb

反向恢复数据

zcat dbname20.sql。gz | mysql -u user -p pass -h localhost yourdb
zcat dbname15.sql。gz | mysql -u user -p pass -h localhost yourdb
zcat dbname13.sql。gz | mysql -u user -p pass -h localhost yourdb
zcat dbname1.sql。gz | mysql -u user -p pass -h localhost yourdb

总之怎么恢复都可以

3.3. 第三种

这种恢复建议按照顺序进行,即可以顺时间轴恢复也可以逆时间轴,条件是表结构需要有主键(PK)

正时序恢复案例,

zcat dbname1.sql。gz | mysql -u user -p pass -h localhost yourdb
zcat dbname2.sql。gz | mysql -u user -p pass -h localhost yourdb
zcat dbname3.sql。gz | mysql -u user -p pass -h localhost yourdb

逆时序恢复数据

zcat dbname3.sql。gz | mysql -u user -p pass -h localhost yourdb
zcat dbname2.sql。gz | mysql -u user -p pass -h localhost yourdb
zcat dbname1.sql。gz | mysql -u user -p pass -h localhost yourdb

因为有主键,所以已存在的重复记录不会被重复插入。

insert 方式有要求

必须是

insert into dbtable(f1, f2, f3...) value (v1, v2, v3);
insert into dbtable(f1, f2, f3...) value (v1, v2, v3);
insert into dbtable(f1, f2, f3...) value (v1, v2, v3);

不能是

insert into dbtable(f1, f2, f3...) value (v1, v2, v3), (v1, v2, v3), value (v1, v2, v3);

3.4. 第四种

这种恢复必须按照顺序进行,即可以顺时间轴恢复也可以逆时间轴,但处理上稍有不同.一旦操作错误数据就会损坏,同时也有很多条件。

顺时序恢复数据, 只需将 insert 替换为 replace 即可

replace into dbtable(f1, f2, f3...) value (v1, v2, v3);
replace into dbtable(f1, f2, f3...) value (v1, v2, v3);
replace into dbtable(f1, f2, f3...) value (v1, v2, v3);

新数据总会覆盖旧数据

但逆向就不同了,逆时序恢复数据与上面第三种相同, 恢复过程中旧数据在 insert 的时候不会覆盖现有的新数据。仅仅将失去的数据恢复到数据库中。

操作要十分谨慎,理解正向与逆向的不同,方能操作。

4. 手工恢复

有时上面所讲的四种恢复方法不能满足你需求,我们模拟一个场景,假如你需要恢复一个时间段的数据,或者ID字段去一个范围等等,上面所举例子均为一刀切。该怎么办呢?

不用担心方法总是有的

INSERT ... SELECT

INSERT [LOW_PRIORITY | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name [(col_name,...)]
    SELECT ...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

REPLACE ... SELECT

REPLACE [LOW_PRIORITY | DELAYED]
    [INTO] tbl_name
    [PARTITION (partition_name,...)]  
    [(col_name,...)]
    SELECT ...

例 1. INSERT ... SELECT

INSERT INTO tbl_name_new SELECT * FROM tbl_name_old WHERE name = 'netkiller';
INSERT INTO db_new.tbl_name SELECT * FROM db_old.tbl_name WHERE id > '10000';

这里仅给一个简单实例,因为每个人的需求都不同,你只需灵活变通,发挥你的想象力。

你可能感兴趣的:(mysql,netkiller,PostgreSQL)