达梦数据库DM8数据文件损坏无备份恢复

无备份数据恢复实验

  • 实验说明
  • 一、开启归档
  • 二、开启记录逻辑操作功能
  • 三、构建测试环境
  • 四、模拟操作业务
  • 五、破坏数据文件
  • 六、尝试重启数据库
    • 6.1 数据库实例无法启动。
    • 6.2 数据库服务无法启动
    • 6.3 手动启动无法启动
  • 七、恢复数据库服务
    • 7.1 将控制文件导出为文本
    • 7.2 找到对应的内容并删除
    • 7.3 重建数据文件
    • 7.4 数据库启动成功
    • 7.5 登录数据库检查
  • 八、数据恢复
    • 8.1 首先重建用户和表空间
    • 8.2 开始日志挖掘
      • 开挖之前需要恢复的数据在哪些归档日志里
      • 加载需要挖掘的日志
      • 开挖,配置具体的挖掘范围
      • 查看挖掘结果
      • 处理结果集
      • 导出SQL脚本
      • 执行脚本
      • 验证,数据恢复结果。
  • 九、 来个备份吧

实验说明

测试场景: 某一个非核心表空间使用的数据文件丢失或损坏,无备份,有归档,对其进行恢复。

为什么一定是非核心表空间,因为SYSTEM这种系统表空间一旦损坏必须全库进行恢复,无法通过其他手段进行恢复。

敲重点:备份非常重要、备份非常重要、备份非常重要

一、开启归档

没有备份、也没有归档是无法进行数据恢复的,能够在无备份情况下恢复 一定是开启了归档,并且归档日志保存完整。

SQL> alter database mount;
操作已执行
已用时间: 359.952(毫秒). 执行号:0.
SQL> alter database add archivelog 'type=local,dest=/dm8/arch1,file_size=64,space_limit=0';
操作已执行
已用时间: 0.712(毫秒). 执行号:0.
SQL> alter database archivelog;
操作已执行
已用时间: 0.312(毫秒). 执行号:0.
SQL> alter database open;
操作已执行
已用时间: 373.182(毫秒). 执行号:0.
SQL> select name,status$,arch_mode from v$database;

行号     NAME STATUS$     ARCH_MODE
---------- ---- ----------- ---------
1          PROD 4           Y

已用时间: 0.528(毫秒). 执行号:263982.
SQL>

二、开启记录逻辑操作功能

RLOG_APPEND_LOGIC:(必须大于1才可以使用日志挖掘功能)
是否启用在日志中记录逻辑操作的功能, 取值范围 0、 1、 2、3
0: 不启用; 1、 2、 3 启用。
1: 如果有主键列, 记录 UPDATE 和 DELETE操作时只包含主键列信息,若没有主键列则包含所有列信息;
2:不论是否有主键列, 记录UPDATE 和 DELETE 操作时都包含所有列的信息;
3: 记录 UPDATE 时包含更新列的信息以及ROWID, 记录 DELETE 时只有 ROWID

SQL> sp_set_para_value(1,'RLOG_APPEND_LOGIC',1);
DMSQL 过程已成功完成
已用时间: 2.361(毫秒). 执行号:1403.
SQL> select para_name, para_value from v$dm_ini where para_name in ('ARCH_INI','RLOG_APPEND_LOGIC');

行号     PARA_NAME         PARA_VALUE
---------- ----------------- ----------
1          RLOG_APPEND_LOGIC 1
2          ARCH_INI          1

已用时间: 2.443(毫秒). 执行号:1404.

三、构建测试环境

在这一步里,我们要进行以下几步操作:
1、创建了一个名为TC01的表空间,创建一个用户TEST_TC 设置他的默认表空间为TC01。
2、然后在TEST_TC用户下创建一张表,在表里构造一些数据。
3、通过系统视图进行操作确认。

--创建表空间
SQL> create tablespace TC01 datafile '/dm8/data/PROD/TC01.DBF' size 50;
操作已执行
已用时间: 13.068(毫秒). 执行号:263974.
--创建用户,指定默认表空间
SQL> CREATE user TEST_TC IDENTIFIED BY TEST00001 DEFAULT TABLESPACE TC01 DEFAULT INDEX TABLESPACE TC01;
操作已执行
已用时间: 33.409(毫秒). 执行号:263975.
--在新建的用户下创建表
SQL> CREATE TABLE TEST_TC.T1 (ID INT , NAME VARCHAR(50));
操作已执行
已用时间: 51.978(毫秒). 执行号:263976.
--写入一条数据
SQL> INSERT INTO TEST_TC.T1 VALUES (1,'数据文件恢复测试');
影响行数 1

已用时间: 0.519(毫秒). 执行号:263977.
SQL> commit;
操作已执行
已用时间: 0.838(毫秒). 执行号:263978.
--通过视图查询TC01表空间下已经有了T1表
SQL> select tablespace_NAME,segment_name,segment_type from dba_segments where tablespace_name='TC01';

行号     TABLESPACE_NAME SEGMENT_NAME SEGMENT_TYPE
---------- --------------- ------------ ------------
1          TC01            T1           TABLE

已用时间: 87.608(毫秒). 执行号:263979.
--查询TC01表空间的数据文件路径
SQL> select  tablespace_name,file_name,round(bytes/1024/1024) mb from dba_data_files where tablespace_name='TC01';

行号     TABLESPACE_NAME FILE_NAME               MB
---------- --------------- ----------------------- --
1          TC01            /dm8/data/PROD/TC01.DBF 50

已用时间: 3.026(毫秒). 执行号:263980.

四、模拟操作业务

在这里我们模拟一些业务操作,以便我们验证数据恢复是否成功。

SQL> update  TEST_TC.t1 set id=id+1;
影响行数 1

已用时间: 0.547(毫秒). 执行号:263983.
SQL> update  TEST_TC.t1 set id=id+1;
影响行数 1

已用时间: 0.547(毫秒). 执行号:263983.
SQL> commit;
操作已执行
已用时间: 0.672(毫秒). 执行号:263984.
SQL> select * from TEST_TC.t1;

行号     ID          NAME
---------- ----------- ------------------------
1          3           数据文件恢复测试

已用时间: 0.951(毫秒). 执行号:263985.

五、破坏数据文件

通过控制台调用操作系统命令,使用其他文件覆盖数据文件TC01.DBF

SQL> host cp /dm8/bin/disql /dm8/data/PROD/TC01.DBF

SQL>

六、尝试重启数据库

6.1 数据库实例无法启动。

数据库无法open

SQL> shutdown immediate;
操作已执行
已用时间: 0.224(毫秒). 执行号:0.
SQL> startup
2   ;
连接丢失
SQL>

6.2 数据库服务无法启动

数据库服务启动失败

[root@bogon bin]# systemctl start DmServiceTEST.service
Job for DmServiceTEST.service failed because the control process exited with error code.
See "systemctl status DmServiceTEST.service" and "journalctl -xe" for details.
[root@bogon bin]#

6.3 手动启动无法启动

查看启动过程无法完成,报错信息也不是很有针对性,嗯~ o( ̄▽ ̄)o

[root@bogon bin]# ./dmserver path=/dm8/data/PROD/dm.ini
file dm.key not found, use default license!
version info: develop
DM Database Server x64 V8 1-2-18-21.11.11-150669-10013-ENT  startup...
Normal of FAST
Normal of DEFAULT
Normal of RECYCLE
Normal of KEEP
Normal of ROLL
Database mode = 0, oguid = 0
License will expire on 2022-11-11
begin redo pwr log collect, last ckpt lsn: 173291 ...
redo pwr log collect finished
main rfil[/dm8/data/PROD/PROD01.log]'s grp collect 0 valid pwr record, discard 0 invalid pwr record
EP[0]'s cur_lsn[173291], file_lsn[173291]
begin redo log recover, last ckpt lsn: 173291 ...
redo log recover finished
ndct db load finished
浮点数例外

七、恢复数据库服务

现在整个数据库服务已经无法启动了,我们要通过修改控制文件先把数据库服务恢复。
表空间、数据库文件信息都写在控制文件里,我们只需要删除控制文件中损坏的数据文件信息就可以让服务启动。

7.1 将控制文件导出为文本

控制文件是一个ctl结尾的二进制文件,无法直接进行修改,需要转为文本。

[dmdba@bogon bin]$  ./dmctlcvt type=1 src=/dm8/data/PROD/dm.ctl dest=/dm8/dmctl.txt
DMCTLCVT V8
convert ctl to txt success!

7.2 找到对应的内容并删除

在控制文件里 找到 TC01 的描述和 /dm8/data/PROD/TC01.DBF 数据文件的表述,整段全部都删掉。

[dmdba@bogon bin]$ vi /dm8/dmctl.txt

#===============================================

# table space name
ts_name=TC01
 # table space ID
ts_id=12
# table space status
ts_state=0
# table space cache
ts_cache=NORMAL
# DSC node number
ts_nth=0
# table space create time
ts_create_time=DATETIME '2022-1-18 19:22:22'
# table space modify time
ts_modify_time=DATETIME '2022-1-18 19:22:22'
# table space encrypt flag
ts_encrypt_flag=0
# table space copy num
ts_copy_num=0
# table space region size flag
ts_size_flag=0

#-----------------------------------------------

# file path
fil_path=/dm8/data/PROD/TC01.DBF
# mirror path
mirror_path=
# file id
# whether the file is auto extend
autoextend=1
# file create time
fil_create_time=DATETIME '2022-1-18 19:22:22'
# file modify time
fil_modify_time=DATETIME '2022-1-18 19:22:22'
# the max size of file
fil_max_size=0
# next size of file
fil_next_size=0

#===============================================

7.3 重建数据文件

将文件文本重新转为ctl文件,覆盖原来的控制文件

[dmdba@bogon bin]$ ./dmctlcvt type=2 src=/dm8/dmctl.txt dest=/dm8/data/PROD/dm.ctl
DMCTLCVT V8
convert txt to ctl success!

7.4 数据库启动成功

重启数据库成功,o( ̄▽ ̄)ブ

[root@bogon bin]# ./dmserver path=/dm8/data/PROD/dm.ini
file dm.key not found, use default license!
version info: develop
DM Database Server x64 V8 1-2-18-21.11.11-150669-10013-ENT  startup...
Normal of FAST
Normal of DEFAULT
Normal of RECYCLE
Normal of KEEP
Normal of ROLL
Database mode = 0, oguid = 0
License will expire on 2022-11-11
begin redo pwr log collect, last ckpt lsn: 173291 ...
redo pwr log collect finished
main rfil[/dm8/data/PROD/PROD01.log]'s grp collect 0 valid pwr record, discard 0 invalid pwr record
EP[0]'s cur_lsn[173291], file_lsn[173291]
begin redo log recover, last ckpt lsn: 173291 ...
redo log recover finished
ndct db load finished
ndct fill fast pool finished
iid page's trxid[49430]
NEXT TRX ID = 49431
pseg_collect_mgr_items, total collect 0 active_trxs, 0 cmt_trxs, 0 pre_cmt_trxs, 0 active_pages, 0 cmt_pages, 0 pre_cmt_pages, 0 mgr pages, 0 mgr recs!
total 0 active crash trx, pseg_crash_trx_rollback sys_only(0) begin ...
pseg_crash_trx_rollback end, total 0 active crash trx, include 0 empty_trxs, 0 empty_pages which only need to delete mgr recs.
pseg_crash_trx_rollback end
pseg recv finished
nsvr_startup end.
aud sys init success.
aud rt sys init success.
systables desc init success.
ndct_db_load_info success.
nsvr_process_before_open begin.
nsvr_process_before_open success.
total 0 active crash trx, pseg_crash_trx_rollback sys_only(0) begin ...
pseg_crash_trx_rollback end, total 0 active crash trx, include 0 empty_trxs, 0 empty_pages which only need to delete mgr recs.
pseg_crash_trx_rollback end
SYSTEM IS READY.

7.5 登录数据库检查

登录数据库正常

[dmdba@bogon bin]$ ./disql SYSDBA/dameng123@localhost:5237

服务器[localhost:5237]:处于普通打开状态
登录使用时间 : 1.411(ms)
disql V8
SQL>

经过检查 用户、表空间、表 都已经不见了

SQL> select username,default_tablespace from dba_users where username='TEST_TC';
未选定行

已用时间: 5.974(毫秒). 执行号:500.
SQL> select tablespace_name from dba_tablespaces WHERE tablespace_name='TC01';
未选定行

已用时间: 2.519(毫秒). 执行号:501.
SQL> select tablespace_NAME,segment_name,segment_type from dba_segments where segment_name='T1';
未选定行

已用时间: 120.287(毫秒). 执行号:502.
SQL>


八、数据恢复

下面开始进行数据恢复。

8.1 首先重建用户和表空间

我们这里对用户进行了重命名TEST_TC 改为了 TEST_TC01

SQL> create tablespace TC01 datafile '/dm8/data/PROD/TC01_1.DBF' size 50;
操作已执行
已用时间: 63.315(毫秒). 执行号:508.
SQL> CREATE user TEST_TC01 IDENTIFIED BY TEST00001 DEFAULT TABLESPACE TC01 DEFAULT INDEX TABLESPACE TC01;
操作已执行
已用时间: 51.114(毫秒). 执行号:509.

8.2 开始日志挖掘

开挖之前需要恢复的数据在哪些归档日志里

通过归档日志的创建日志进行筛选

SQL> select NAME,FIRST_TIME from v$archived_log where FIRST_TIME >'2022-01-19 12:00:00';

行号     NAME                                                                     FIRST_TIME
---------- ------------------------------------------------------------------------ --------------------------
1         /dm8/arch1/ARCHIVE_LOCAL3_0x6910E0E3[0]_2022-01-19_13-03-59.log          2022-01-19 13:03:14.606557
2         /dm8/arch1/ARCHIVE_LOCAL3_0x6910E0E3[0]_2022-01-19_13-39-42.log          2022-01-19 13:37:31.975000
3         /dm8/arch1/ARCHIVE_LOCAL3_0x6910E0E3[0]_2022-01-19_13-45-56.log		   2022-01-19 13:39:59.013000

3 rows got

已用时间: 1.523(毫秒). 执行号:520.

加载需要挖掘的日志

这里有几个日志文件就需要执行几次。

SQL> call dbms_logmnr.add_logfile('/dm8/arch1/ARCHIVE_LOCAL3_0x6910E0E3[0]_2022-01-19_13-03-59.log');
DMSQL 过程已成功完成
已用时间: 42.461(毫秒). 执行号:511.
SQL> call dbms_logmnr.add_logfile('/dm8/arch1/ARCHIVE_LOCAL3_0x6910E0E3[0]_2022-01-19_13-39-42.log');
DMSQL 过程已成功完成
已用时间: 0.512(毫秒). 执行号:512.
SQL> call dbms_logmnr.add_logfile('/dm8/arch1/ARCHIVE_LOCAL3_0x6910E0E3[0]_2022-01-19_13-45-56.log');
DMSQL 过程已成功完成
已用时间: 1.070(毫秒). 执行号:513.

开挖,配置具体的挖掘范围

SQL> Call dbms_logmnr.start_logmnr(
    options  => 2128
   ,starttime=> to_date('2022-01-18 00:00:00','yyyy-mm-dd hh24:mi:ss')
   ,endtime  => to_date('2022-01-18 23:59:59','yyyy-mm-dd hh24:mi:ss')
);
DMSQL 过程已成功完成
已用时间: 188.525(毫秒). 执行号:514.

options整个参数用于配置挖掘模式。
提供如下表所列的可选模式,各模式可以通过 + 或者按位或来进行组合。
其它位的值 如 1、 4、 8等目前不支持,配置后不会报错,但是没有效果。
例如,组合全部模式,则取值 计算方法为 16+64+2048=2128,那么 OPTIONS值取就是 2128。
达梦数据库DM8数据文件损坏无备份恢复_第1张图片

查看挖掘结果

这时已经可以看到我们之前执行的语句了。

SQL> select sql_redo from V$logmnr_contents where sql_redo like '%T1%' ORDER BY timestamp;

行号     SQL_REDO
---------- -----------------------------------------------------------------------------------------
1          CREATE TABLE TEST_TC.T1 (ID INT , NAME VARCHAR(50))
2          INSERT INTO "TEST_TC"."T1"("ID", "NAME") VALUES(1, '数据文件恢复测试')
3          UPDATE "TEST_TC"."T1" SET "ID" = 2 WHERE "ID" = 1 AND "NAME" = '数据文件恢复测试'
4          UPDATE "TEST_TC"."T1" SET "ID" = 3 WHERE "ID" = 2 AND "NAME" = '数据文件恢复测试'

处理结果集

因为我们重建用户的时候修改了用户名,可以通过字符串替换的方式修改sql语句。
另外我们发现上面的语句查出来的数据结尾都没有分号,为了方便执行,我们也把分号拼接上。

SQL> select replace(sql_redo,'TEST_TC','TEST_TC01')||';' from V$logmnr_contents where sql_redo like '%T1%' ORDER BY timestamp;

行号     REPLACE(SQL_REDO,'TEST_TC','TEST_TC01')||';'
---------- --------------------------------------------------------------------------------------------
1          CREATE TABLE TEST_TC01.T1 (ID INT , NAME VARCHAR(50));
2          INSERT INTO "TEST_TC01"."T1"("ID", "NAME") VALUES(1, '数据文件恢复测试');
3          UPDATE "TEST_TC01"."T1" SET "ID" = 2 WHERE "ID" = 1 AND "NAME" = '数据文件恢复测试';
4          UPDATE "TEST_TC01"."T1" SET "ID" = 3 WHERE "ID" = 2 AND "NAME" = '数据文件恢复测试';

导出SQL脚本

我们测试的环境SQL脚本比较少,所以手动执行都可以。
如果有大量的SQL语句需要执行,就需要生成一个脚本文件来批量运行。

首先:格式处理,除掉表头、去掉行号、去掉返回的行数等无用的提示。
这样我们就获得了干干净净的SQL查询结果集了

SQL> set HEA off
SQL> select replace(sql_redo,'TEST_TC','TEST_TC01')||';' from V$logmnr_contents where sql_redo like '%T1%' ORDER BY timestamp;

1          CREATE TABLE TEST_TC01.T1 (ID INT , NAME VARCHAR(50));
2          INSERT INTO "TEST_TC01"."T1"("ID", "NAME") VALUES(1, '数据文件恢复测试');
3          UPDATE "TEST_TC01"."T1" SET "ID" = 2 WHERE "ID" = 1 AND "NAME" = '数据文件恢复测试';
4          UPDATE "TEST_TC01"."T1" SET "ID" = 3 WHERE "ID" = 2 AND "NAME" = '数据文件恢复测试';

已用时间: 51.065(毫秒). 执行号:527.

SQL> set LINESHOW off
SQL> /
CREATE TABLE TEST_TC01.T1 (ID INT , NAME VARCHAR(50));
INSERT INTO "TEST_TC01"."T1"("ID", "NAME") VALUES(1, '数据文件恢复测试');
UPDATE "TEST_TC01"."T1" SET "ID" = 2 WHERE "ID" = 1 AND "NAME" = '数据文件恢复测试';
UPDATE "TEST_TC01"."T1" SET "ID" = 3 WHERE "ID" = 2 AND "NAME" = '数据文件恢复测试';

已用时间: 47.678(毫秒). 执行号:530.
SQL> set TIMING off
SQL> /
CREATE TABLE TEST_TC01.T1 (ID INT , NAME VARCHAR(50));
INSERT INTO "TEST_TC01"."T1"("ID", "NAME") VALUES(1, '数据文件恢复测试');
UPDATE "TEST_TC01"."T1" SET "ID" = 2 WHERE "ID" = 1 AND "NAME" = '数据文件恢复测试';
UPDATE "TEST_TC01"."T1" SET "ID" = 3 WHERE "ID" = 2 AND "NAME" = '数据文件恢复测试';

SQL>

将SQL的输出导出到/dm8/t1.sql 这个文件里。 输出完成后,对1.sql还要进行简单的编辑。
这个文件,把第一行的查询语句,和最后一个的spool off 关闭语句删掉 就可以了。

SQL> spool /dm8/t1.sql append
SQL> select replace(sql_redo,'TEST_TC','TEST_TC01')||';' from V$logmnr_contents where sql_redo like '%T1%' ORDER BY timestamp;
CREATE TABLE TEST_TC01.T1 (ID INT , NAME VARCHAR(50));
INSERT INTO "TEST_TC01"."T1"("ID", "NAME") VALUES(1, '数据文件恢复测试');
UPDATE "TEST_TC01"."T1" SET "ID" = 2 WHERE "ID" = 1 AND "NAME" = '数据文件恢复测试';
UPDATE "TEST_TC01"."T1" SET "ID" = 3 WHERE "ID" = 2 AND "NAME" = '数据文件恢复测试';

SQL> spool off

执行脚本

通过 start 调用sql脚本,所有语句就都执行了。别忘了commti 提交事务。

SQL> start /dm8/t1.sql
SQL> CREATE TABLE TEST_TC01.T1 (ID INT , NAME VARCHAR(50));
操作已执行
SQL> INSERT INTO "TEST_TC01"."T1"("ID", "NAME") VALUES(1, '数据文件恢复测试');
影响行数 1

SQL> UPDATE "TEST_TC01"."T1" SET "ID" = 2 WHERE "ID" = 1 AND "NAME" = '数据文件恢复测试';
影响行数 1

SQL> UPDATE "TEST_TC01"."T1" SET "ID" = 3 WHERE "ID" = 2 AND "NAME" = '数据文件恢复测试';
影响行数 1

SQL> commit;
操作已执行
SQL>

验证,数据恢复结果。

最后 我们通过 查询T1 表里的数据来验证恢复结果。
可以看到已经恢复了文件损坏前的数据了。

SQL> select * from TEST_TC01.T1;
3           数据文件恢复测试

九、 来个备份吧

恢复完别忘了对数据库进行备份。
以下为 备份数据库、备份表空间、备份表的语句。

SQL> backup database backupset '/dm8/backup/20220119' ;
操作已执行

SQL> backup tablespace TC01 backupset '/dm8/backup/20220119_TC01';
操作已执行

SQL> backup table test_tc01.t1 backupset '/dm8/backup/20220119_TC01_T1';
操作已执行

达梦技术社区地址:https://eco.dameng.com

你可能感兴趣的:(达梦数据库,数据库,sql,database)