操作系统 | CentOS 7.6 |
数据库 | DM8_20240712 |
目录
概述
此篇文档介绍了数据库还原与恢复的几个常见场景及操作步骤,备份还原的相关理论不做介绍。
本文有四个部分。首先介绍了开启归档的两种方法,第二部分介绍了DMRMAN还原与恢复的3个案例,第三、四部分是2个特殊场景,这2个场景不依赖备份集、不需要脱机,可以快速恢复数据文件或误删除的数据。
1、开启归档
归档配置有两种方式:一是联机归档配置,数据库实例启动情况下,使用 SQL 语句完成 dmarch.ini 和 ARCH_INI 配置;二是手动配置归档,数据库实例未启动的情况下,手动编写 dmarch.ini 文件和设置参数 ARCH_INI。下面将分别说明这两种归档如何配置。
1.1、联机配置
--DBA权限登录数据库
ALTER DATABASE MOUNT;
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE ADD ARCHIVELOG 'DEST = /dm8/data/PROD/archlog, TYPE = local,FILE_SIZE = 68, SPACE_LIMIT = 1056';
ALTER DATABASE OPEN;
1.2、手动配置
#关闭数据库
DmServiceTEST stop #按实际情况修改
#在 dm.ini 所在目录,创建 dmarch.ini 文件。
vi dmarch.ini
[ARCHIVE_LOCAL1]
ARCH_TYPE = LOCAL
ARCH_DEST = /dm8/data/PROD/archlog
ARCH_FILE_SIZE = 1024
ARCH_SPACE_LIMIT = 2048
##编辑 dm.ini 文件,设置参数ARCH_INI=1
vi dm.ini
ARCH_INI=1
#启动数据库实例,数据库已运行于归档模式。
DmServiceTEST start #按实际情况修改
2、DMRMAN还原与恢复案例
这一节我们选取了三个案例,分别是"从备份集恢复"、"从归档恢复"、"还原数据到新库"。这三个案例使用了DMRMAN,DMRMAN是达梦数据库脱机备份还原工具,还原数据库之前需要关闭数据库。
开始测试之前,简单解释一下什么是"从备份集恢复"?什么是"从归档恢复"?
举个例子,假如我们在早上10点执行联机完全备份,11点备份完成,11点之后数据库处理了大量业务,12点数据库发生故障停机。
备份集是11点生成的,数据库执行RESTORE操作后,用备份集RECOVER只能恢复到11点时的数据库状态,数据库中没有11点至12点之间的业务数据。这就是案例1要模拟的场景。
第2个案例"从归档恢复",是指执行完RESTORE操作后,使用归档日志RECOVER。可以将数据库恢复到12点停机前的状态,也可以将数据库恢复到11点至12点之间任意时间点。
2.1、从备份集恢复
第一步:准备
新建一张表tb_test用于验证。备份完成之前向tb_test插入2条数据,备份完成后插入第3条数据。之后开始RESTORE与RECOVER,预计使用“备份集”恢复成功后,表tb_test中有2条数据。
--1.数据准备
SQL>create TABLE tb_test(c1 varchar2(10));
SQL>insert into tb_test values('a');
SQL>commit;
--2.完全备份
SQL>BACKUP DATABASE TO FULL_BAK_20240815_01 BACKUPSET '/dm8/data/dm_bak/db_full_bak_20240815_01' DEVICE TYPE DISK BACKUPINFO '完全备份';
--3.插入数据
SQL>insert into tb_test values('b');
SQL>commit;
--4.增量备份
SQL> BACKUP DATABASE INCREMENT WITH BACKUPDIR '/dm8/data/dm_bak' BACKUPSET '/dm8/data/dm_bak/db_increment_bak_20240815_01';
--5.插入数据
SQL> insert into tb_test values('b');
SQL> commit;
--6.查看备份集
SQL> select * from V$BACKUPSET;
未选定行
#没查询到时因为没有添加备份目录
--7.添加备份目录
SQL> select SF_BAKSET_BACKUP_DIR_ADD('DISK','/dm8/data/dm_bak');
--8.查看备份集
SQL> select backup_name,backup_path from SYS.V$BACKUPSET t;
行号 BACKUP_NAME BACKUP_PATH
---------- ----------------------------------- ---------------------------------------------
1 FULL_BAK_20240815_01 /dm8/data/dm_bak/db_full_bak_20240815_01
2 DB_INCREMENT_20240815_020723_368412 /dm8/data/dm_bak/db_increment_bak_20240815_01
--9.用系统命令查看
[dmdba@localhost dm_bak]$ ll
total 0
drwxr-xr-x. 2 dmdba dinstall 114 Aug 15 02:05 db_full_bak_20240815_01
drwxr-xr-x. 2 dmdba dinstall 87 Aug 15 02:07 db_increment_bak_20240815_01
第二步:还原与恢复
# 1.停止数据库
DmServiceTEST stop
#2.检验备份集是否正确
RMAN> check backupset '/dm8/data/dm_bak/db_increment_bak_20240815_01';
#3.还原
RMAN>RESTORE DATABASE '/dm8/data/PROD/dm.ini' FROM BACKUPSET '/dm8/data/dm_bak/db_increment_bak_20240815_01';
#4.用备份集恢复
RMAN>RECOVER DATABASE '/dm8/data/PROD/dm.ini' FROM BACKUPSET '/dm8/data/dm_bak/db_increment_bak_20240815_01';
#5.更新数据库魔数
RMAN>RECOVER DATABASE '/dm8/data/PROD/dm.ini' UPDATE DB_MAGIC;
第三步:检查
#启动数据库
DmServiceTEST start
--查看数据
SQL> select * from tb_test;
行号 C1
---------- --
1 a
2 b
本案例是用数据集完成的recover,test表中有2条记录符合预期。
2.2、利用归档恢复
第一步:准备
新创建一张表tb_test2用于本案例的验证。备份完成之前向tb_test2插入2条数据,备份完成之后插入第3条,间隔一定时间后插入第4条记录,并记录第3条数据与第4条数据中间的时间点。
预计,第二步使用归档完全恢复之后,表tb_test2中有4条数据,第三步恢复到指定时间点完成后,表tb_test2中有3条数据。
--1.数据准备
create TABLE tb_test2(c1 varchar2(10));
insert into tb_test2 values('a');
commit;
--2.完全备份
BACKUP DATABASE TO FULL_BAK_20240815_02 BACKUPSET '/dm8/data/dm_bak/db_full_bak_20240815_02' DEVICE TYPE DISK BACKUPINFO '完全备份2';
--3.插入数据
insert into tb_test2 values('b');
commit;
--4.增量备份
BACKUP DATABASE INCREMENT WITH BACKUPDIR '/dm8/data/dm_bak'
TO INC_BAK_20240815_02
backupset '/dm8/data/dm_bak/db_increment_bak_20240815_02';
--5.插入数据
insert into tb_test2 values('c');
commit;
--6.查看系统时间
SELECT sysdate; -- 这里不能用now
2024-08-15 03:13:58.296335
--7.插入数据
insert into tb_test2 values('d');
commit;
--8.查看系统时间
SELECT sysdate; -- 这里不能用now
2024-08-15 03:15:20.305172
--9.查看备份集
SQL> select * from V$BACKUPSET;
未选定行
#为什么又查不到了?
--添加备份目录
select SF_BAKSET_BACKUP_DIR_ADD('DISK','/dm8/data/dm_bak');
--查看备份集
select * from SYS.V$BACKUPSET t;
SQL> select backup_name,backup_path from SYS.V$BACKUPSET t;
行号 BACKUP_NAME BACKUP_PATH
---------- ----------------------------------- ---------------------------------- -----------
1 FULL_BAK_20240815_01 /dm8/data/dm_bak/db_full_bak_20240815_01
2 DB_INCREMENT_20240815_020723_368412 /dm8/data/dm_bak/db_increment_bak_20240815_01
3 FULL_BAK_20240815_02 /dm8/data/dm_bak/db_full_bak_20240815_02
4 INC_BAK_20240815_02 /dm8/data/dm_bak/db_increment_bak_20240815_02
--10.用系统命令查看
[dmdba@localhost dm_bak]$ ll
total 0
drwxr-xr-x. 2 dmdba dinstall 114 Aug 15 02:05 db_full_bak_20240815_01
drwxr-xr-x. 2 dmdba dinstall 114 Aug 15 03:10 db_full_bak_20240815_02
drwxr-xr-x. 2 dmdba dinstall 87 Aug 15 02:07 db_increment_bak_20240815_01
drwxr-xr-x. 2 dmdba dinstall 87 Aug 15 03:12 db_increment_bak_20240815_02
第二步:测试完全恢复
#1.停止数据库
DmServiceTEST stop
#2.检验备份集是否正确
RMAN> check backupset '/dm8/data/dm_bak/db_increment_bak_20240815_02';
#3.还原
RMAN>RESTORE DATABASE '/dm8/data/PROD/dm.ini' FROM BACKUPSET '/dm8/data/dm_bak/db_increment_bak_20240815_02';
#4.用归档恢复
RMAN>recover database '/dm8/data/PROD/dm.ini' with archivedir '/dm8/data/PROD/archlog';
#5.更新数据库魔数
RMAN>RECOVER DATABASE '/dm8/data/PROD/dm.ini' UPDATE DB_MAGIC;
#6.验证数据
#启动数据库
DmServiceTEST start
SQL> select * from tb_test2;
行号 C1
---------- --
1 a
2 b
3 c
4 d
表tb_test2有4条记录,符合预期。
第三步:测试恢复到指定时间点
#1.停止数据库
DmServiceTEST stop
#2.检验备份集是否正确
RMAN> check backupset '/dm8/data/dm_bak/db_increment_bak_20240815_02';
#3.还原
RMAN>RESTORE DATABASE '/dm8/data/PROD/dm.ini' FROM BACKUPSET '/dm8/data/dm_bak/db_increment_bak_20240815_02';
#4.用归档恢复到指定时间
RMAN>recover database '/dm8/data/PROD/dm.ini' with archivedir '/dm8/data/PROD/archlog' UNTIL TIME '2024-08-15 03:13:58';
#5.更新数据库魔数
RMAN>RECOVER DATABASE '/dm8/data/PROD/dm.ini' UPDATE DB_MAGIC;
#6.验证数据
#启动数据库
DmServiceTEST start
SQL> select * from tb_test2;
行号 C1
---------- --
1 a
2 b
3 c
#表tb_test2有3条记录,符合预期
2.3、还原数据到新库
可以考虑用这个方法实现相同版本DM数据库之间的迁移。
第一步:创建新数据库
/dm8/dmdbms/bin/dminit PATH=/dm8/data DB_NAME=PROD1 INSTANCE_NAME=TEST1 PORT_NUM=5238 CASE_SENSITIVE=1
第二步:把案例二的备份集还原到新库
#1.停止数据库
#2.检验备份集是否正确
RMAN> check backupset '/dm8/data/dm_bak/db_increment_bak_20240815_02';
#3还原
RMAN>RESTORE DATABASE '/dm8/data/PROD1/dm.ini' FROM BACKUPSET '/dm8/data/dm_bak/db_increment_bak_20240815_02';
#4.用备份集恢复
RMAN>recover database '/dm8/data/PROD1/dm.ini' FROM BACKUPSET '/dm8/data/dm_bak/db_increment_bak_20240815_02';
#5.更新数据库魔数
RMAN>RECOVER DATABASE '/dm8/data/PROD1/dm.ini' UPDATE DB_MAGIC;
#6.验证数据
#启动数据库
dmserver path=/dm8/data/PROD1/dm.ini
比对源数据库和新库的表空间、用户、模式、表等对象完全一致,符合预期
3、数据文件误删除的快速恢复
LINUX 系统中被删除的文件,只要其句柄没有被关闭,可以在/proc/<pid>/fd 中找到
其对应的文件副本。其中<pid>指打开该文件的进程 id。
利用该方法,结合 OS 命令,DM 提供失效文件的恢复方案如下:
1、 调用系统过程 SP_TABLESPACE_PREPARE_RECOVER(表空间名称)准备进行恢复;
2、 如果使用过程中 DM 报错表空间数据文件被删除,通过操作系统的 ps 命令找到当前 dmserver 的 PID:ps -ef|grep dmserver;
3、 使用操作系统 ll 命令查看被删除文件对应的副本:ll /proc/<PID>/fd,会发现被删除的文件后有(deleted)字样;
4、 使用操作系统的 cp 命令将文件复制到原位置:cp 源路径 目的路径;
5、 复制成功后,调用系统过程 SP_TABLESPACE_RECOVER(表空间名称)完成表空间失效文件的恢复。注意,要保证数据文件正确修复,需要保证在 SP_TABLESPACE_PREPARE_RECOVER后进行数据文件的复制。
下面我们模拟下恢复过程:
1.测试准备
本案例中表DMUSER1.TABLE_1所在的表空间是TBS1,表空间TBS1下有数据文件/dm8/data/PROD/TBS1_01.DBF。我们用rm命令删除/dm8/data/PROD/TBS1_01.DBF,再用上述方法找回文件,最后修复表空间。
-- 1.查看表空间对应的数据文件
SQL> select t.name,d.path from SYS.V$TABLESPACE t
2 left join SYS.V$DATAFILE d on(d.GROUP_ID=T.ID);
行号 NAME PATH
---------- ------ --------------------------
1 MAIN /dm8/data/PROD/MAIN.DBF
2 ROLL /dm8/data/PROD/ROLL.DBF
3 TEMP /dm8/data/PROD/TEMP.DBF
4 TBS1 /dm8/data/PROD/TBS1_01.DBF
5 SYSTEM /dm8/data/PROD/SYSTEM.DBF
--2.模拟误删除数据文件
rm /dm8/data/PROD/TBS1_01.DBF
--3. 检查数据文件是否存在
SP_FILE_SYS_CHECK();
--4.查看数据库
SQL> SELECT * FROM DMUSER1.TABLE_1;
服务器[127.0.0.1:5237]:处于普通打开状态
已连接
SELECT * FROM DMUSER1.TABLE_1;
[-3433]:表空间处于脱机状态.
已用时间: 0.451(毫秒). 执行号:0.
2.开始恢复
#1. 表空间失效文件恢复准备
SQL> SP_TABLESPACE_PREPARE_RECOVER('TBS1');
#2. 查找dmserver 进程号
[root@localhost ~]# ps -ef|grep dmserver
dmdba 58300 1 0 06:17 pts/3 00:00:00 /dm8/dmdbms/bin/dmserver path=/dm8/data/PROD/dm.ini -noconsole
root 58859 39642 0 06:24 pts/0 00:00:00 grep --color=auto dmserver
#3. 查看进程目录下的文件
[root@localhost ~]# ll /proc/58300/fd
total 0
lr-x------. 1 dmdba dinstall 64 Aug 15 06:17 0 -> /dev/null
l-wx------. 1 dmdba dinstall 64 Aug 15 06:17 1 -> /dev/null
lrwx------. 1 dmdba dinstall 64 Aug 15 06:17 10 -> /dm8/data/PROD/MAIN.DBF
lrwx------. 1 dmdba dinstall 64 Aug 15 06:17 11 -> /dm8/data/PROD/TBS1_01.DBF (deleted)
#4. 还原文件
cp -p /proc/58300/fd/11 /dm8/data/PROD/TBS1_01.DBF
#5. 修复表空间文件
SQL> SP_TABLESPACE_RECOVER('TBS1');
DMSQL 过程已成功完成
#6.验证
SELECT count(*) FROM DMUSER1.TABLE_1;
SQL> SELECT count(*) FROM DMUSER1.TABLE_1;
行号 COUNT(*)
---------- --------------------
1 16
数据文件恢复成功!
4、利用闪回技术恢复误删除数据
当系统 INI 参数 ENABLE_FLASHBACK 置为 1 时,闪回功能开启,可以使用闪回表或进行闪回查询。
闪回表是在数据库联机时,通过只回退对指定表及其相关对象所做的更改,将表里的数据回退到历史的某个时间点,而不需要执行传统的时间点恢复操作。比如回退到用户误删除数据之前的时间点,从而将误删除的数据恢复回来,在这个操作过程中,数据库仍然可用而且不需要额外的空间。
闪回表利用的是 UNDO 表空间里所记录的数据被改变前的值。因此,如果因保留时间超过了初始化参数 UNDO_RETENTION 所指定的值,从而导致闪回表时所需要的 UNDO 数据被其他事务覆盖的话,那么就不能将表中数据恢复到指定的时间了。
与介质恢复相比,闪回表在易用性、可用性和还原时间方面有明显的优势。
下面我们模拟下恢复过程:
1.检查ini配置
SQL> select T.PARA_VALUE from v$dm_ini t where t.PARA_NAME='ENABLE_FLASHBACK';
行号 PARA_NAME PARA_VALUE
---------- ---------------- ----------
1 ENABLE_FLASHBACK 0
2 UNDO_RETENTION 90.000000
2.开启闪回
UNDO_RETENTION设置的是保留闪回数据的时间,单位是秒,默认值是90秒,本例中保留1小时。
--DBA权限登录数据库
SP_SET_PARA_VALUE(1,'ENABLE_FLASHBACK',1);
SP_SET_PARA_DOUBLE_VALUE(1,'UNDO_RETENTION',360);
3.数据准备
准备数据,并记录时间。注意查询数据库时间用sysdate,不要用now()。
SELECT count(*) FROM DMUSER1.TABLE_1;
SQL> SELECT count(*) FROM DMUSER1.TABLE_1;
行号 COUNT(*)
---------- --------------------
1 6
--记录时间,注意这里不要使用Now()函数
SQL> select sysdate;
行号 SYSDATE
---------- -------------------
1 2024-08-15 07:06:46
4.模拟误删除数据
SQL> delete from DMUSER1.TABLE_1;
SQL> Commit;
SQL> SELECT count(*) FROM DMUSER1.TABLE_1;
行号 COUNT(*)
---------- --------------------
1 0
5.恢复数据
SQL> FLASHBACK TABLE DMUSER1.TABLE_1 TO TIMESTAMP '2024-08-15 07:06:46';
SQL> SELECT count(*) FROM DMUSER1.TABLE_1;
行号 COUNT(*)
---------- --------------------
1 6
数据恢复成功!