在Linux环境下,不小心删除了达梦数据库表空间文件,导致表空间为离线状态,从而影响数据库正常工作。对于DBA而言,数据恢复是必备的基本功,在此以一个例子来说明如何恢复,本文操作都用命令行操作完成。
测试环境为虚拟机,操作系统为麒麟Linux高级服务器版,达梦数据库为DM8 (dm8_20220525_x86_rh6_64) ,具体版本信息如下:
操作系统版本信息:
# cat /etc/os-release
NAME="Kylin Linux Advanced Server"
VERSION="V10 (Lance)"
ID="kylin"
VERSION_ID="V10"
PRETTY_NAME="Kylin Linux Advanced Server V10 (Lance)"
ANSI_COLOR="0;31"
达梦数据库版本信息:
$ disql sysdba/SYSDBA:5236
服务器[LOCALHOST:5236]:处于普通打开状态
登录使用时间 : 10.199(ms)
disql V8
SQL> select * from v$version;
行号 BANNER
---------- ---------------------------------
1 DM Database Server 64 V8
2 DB Version: 0x7000c
3 03134283890-20220525-161267-10045
已用时间: 2.921(毫秒). 执行号:500.
为避免影响现有学习环境,因此单独创建一个实例来进行演示说明,我的数据库安装位置为/dm8,具体数据库软件的安装则不再演示。
su - dmdba
cd /dm8/bin
./dminit path='/dm8/data' db_name='DMTMP' instance_name='TMPINST' sysdba_pwd=Dameng123 port_num=5238 page_size=8 --数据库创建在/dm8/data/DMTMP
initdb V8
db version: 0x7000c
file dm.key not found, use default license!
License will expire on 2023-05-25
Normal of FAST
Normal of DEFAULT
Normal of RECYCLE
Normal of KEEP
Normal of ROLL
log file path: /dm8/data/DMTMP/DMTMP01.log
log file path: /dm8/data/DMTMP/DMTMP02.log
write to dir [/dm8/data/DMTMP].
create dm database success. 2023-04-19 13:43:31
## 创建完成后,启动数据库实例(本演示不创建系统服务,仅以前台启动演示)
$ /dm8/bin/dmserver /dm8/data/DMTMP/dm.ini
file dm.key not found, use default license!
version info: develop
DM Database Server 64 V8 03134283890-20220525-161267-10045 startup...
...
...(略)
pseg_crash_trx_rollback end
SYSTEM IS READY.
## 检查数据库服务是否在侦听5238端口(建库时指定的端口)
## 在另外一个终端中执行下面的命令进行检查
$ netstat -antlp|grep -i listen
(Not all processes could be identified, non-owned process info
will not be shown, you would have to be root to see it all.)
tcp 0 0 0.0.0.0:5901 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN -
tcp6 0 0 :::4236 :::* LISTEN 1313/dmap
tcp6 0 0 :::5901 :::* LISTEN -
tcp6 0 0 :::5236 :::* LISTEN 43860/dmserver
tcp6 0 0 :::5238 :::* LISTEN 44204/dmserver ###这个就是我新创建的演示实例
tcp6 0 0 :::22 :::* LISTEN -
$ disql sysdba/Dameng123:5238
服务器[LOCALHOST:5238]:处于普通打开状态
登录使用时间 : 3.367(ms)
disql V8
SQL> select * from v$instance;
行号 NAME INSTANCE_NAME INSTANCE_NUMBER HOST_NAME SVR_VERSION DB_VERSION START_TIME STATUS$ MODE$ OGUID DSC_SEQNO DSC_ROLE BUILD_VERSION
---------- ------- ------------- --------------- --------- -------------------------- ------------------- ------------------- ------- ------ ----------- ----------- -------- ----------------------------------
BUILD_TIME
--------------------
1 TMPINST TMPINST 1 KylinDCA1 DM Database Server x64 V8 DB Version: 0x7000c 2023-04-19 13:50:25 OPEN NORMAL 0 0 NULL 1-2-114-22.05.25-161267-10045-ENT
May 25 2022 11:22:12
已用时间: 18.921(毫秒). 执行号:55200.
SQL> select * from v$database;
行号 NAME CREATE_TIME ARCH_MODE LAST_CKPT_TIME STATUS$ ROLE$ MAX_SIZE TOTAL_SIZE DSC_NODES OPEN_COUNT STARTUP_COUNT LAST_STARTUP_TIME
---------- ----- ------------------- --------- ------------------- ----------- ----------- -------------------- -------------------- ----------- ----------- -------------------- -------------------
1 DMTMP 2023-04-19 13:43:30 N 2023-04-19 13:56:26 4 0 0 20992 1 1 1 2023-04-19 13:50:30
已用时间: 1.036(毫秒). 执行号:55201.
-- 在disql中执行
-- 开启归档
alter database mount;
alter database ARCHIVELOG;
alter database ADD ARCHIVELOG 'type=local, dest=/dm8/arch2,file_size=64,space_limit=10240'; -- 归档路径为/dm8/arch2
alter DATABASE OPEN;
select arch_mode from v$database;
行号 ARCH_MODE
---------- ---------
1 Y
已用时间: 1.958(毫秒). 执行号:55202.
目前数据库已经是归档模式,归档文件存放位置为/dm8/arch2
创建表空间:
create tablespace TBS1 DATAFILE 'TBS01.DBF' size 32;
SQL> select PATH,CREATE_TIME from v$datafile;
行号 PATH CREATE_TIME
---------- -------------------------- -------------------
1 /dm8/data/DMTMP/SYSTEM.DBF 2023-04-19 13:43:30
2 /dm8/data/DMTMP/ROLL.DBF 2023-04-19 13:43:30
3 /dm8/data/DMTMP/TEMP.DBF 2023-04-19 13:50:25
4 /dm8/data/DMTMP/MAIN.DBF 2023-04-19 13:43:30
5 /dm8/data/DMTMP/TBS01.DBF 2023-04-19 14:14:13 -- 新创建的表空间文件
已用时间: 1.187(毫秒). 执行号:55205.
创建测试表:
create table mytable(id int, name VARCHAR(20)) TABLESPACE TBS1;
insert into mytable(id,name) values(1,'赵');
insert into mytable(id,name) values(2,'钱');
insert into mytable(id,name) values(3,'孙');
insert into mytable(id,name) values(4,'李');
insert into mytable(id,name) values(5,'周');
insert into mytable(id,name) values(6,'吴');
commit;
select * from mytable;
行号 ID NAME
---------- ----------- ----
1 1 赵
2 2 钱
3 3 孙
4 4 李
5 5 周
6 6 吴
6 rows got
已用时间: 1.421(毫秒). 执行号:55214.
虽然本次恢复两法中,不会用全备份进行恢复,但为了养成好习惯,还是先来个全备份,归档也来个备份。
-- 全备份 disql中执行
SQL> BACKUP DATABASE FULL TO FULLBAK10 BACKUPSET '/dm8/backup/full/FULLBAK10' ;
-- [-8117]:等待归档刷盘,请稍后重试.
-- 遇到这个情况,我处理是把数据库重启下,估计是因为修改归档后没有重启数据库。
-- 查看备份是否存在{结果还把另外一个实例的备份给找出来了}
SQL> SF_BAKSET_BACKUP_DIR_ADD('DISK','/dm8/backup/full');
SQL> select DEVICE_TYPE,BACKUP_PATH,OBJECT_NAME,BACKUP_TIME from SYS."V$BACKUPSET" order BY BACKUP_TIME desc;
行号 DEVICE_TYPE BACKUP_PATH OBJECT_NAME BACKUP_TIME
---------- ----------- -------------------------- ----------- --------------------------
1 DISK /dm8/backup/full/FULLBAK10 DMTMP 2023-04-19 14:46:42.562072 -- DMTMP的全库备份
2 DISK /dm8/backup/full/FULLBAK02 DMDB 2023-04-19 12:28:17.869941
3 DISK /dm8/backup/full/FULLBAK01 DMDB 2023-04-18 16:04:20.590783
已用时间: 31.062(毫秒). 执行号:506.
SQL> BACKUP TABLESPACE TBS1 to TBS1BAK11 BACKUPSET '/dm8/backup/full/TBS1BAK11';
操作已执行
已用时间: 00:00:05.475. 执行号:507.
SQL> select DEVICE_TYPE,BACKUP_PATH,OBJECT_NAME,BACKUP_TIME from SYS."V$BACKUPSET" order BY BACKUP_TIME desc;
行号 DEVICE_TYPE BACKUP_PATH OBJECT_NAME BACKUP_TIME
---------- ----------- -------------------------- ----------- --------------------------
1 DISK /dm8/backup/full/TBS1BAK11 TBS1 2023-04-19 15:04:17.417713 -- 多了个表空间的备份
2 DISK /dm8/backup/full/FULLBAK10 DMTMP 2023-04-19 14:46:42.562072
3 DISK /dm8/backup/full/FULLBAK02 DMDB 2023-04-19 12:28:17.869941
4 DISK /dm8/backup/full/FULLBAK01 DMDB 2023-04-18 16:04:20.590783
已用时间: 28.842(毫秒). 执行号:508.
SQL> BACKUP ARCHIVE LOG ALL to ARCHIVEBAK12 BACKUPSET '/dm8/backup/full/ARCHIVEBAK12' ; -- 归档日志备份
操作已执行
已用时间: 00:00:05.759. 执行号:510.
SQL> select DEVICE_TYPE,BACKUP_PATH,OBJECT_NAME,BACKUP_TIME from SYS."V$BACKUPSET" order BY BACKUP_TIME desc;
行号 DEVICE_TYPE BACKUP_PATH OBJECT_NAME BACKUP_TIME
---------- ----------- ----------------------------- ----------- --------------------------
1 DISK /dm8/backup/full/ARCHIVEBAK12 ARCHIVE 2023-04-19 15:22:52.356470 -- 新增一个归档日志备份
2 DISK /dm8/backup/full/TBS1BAK11 TBS1 2023-04-19 15:04:17.417713
3 DISK /dm8/backup/full/FULLBAK10 DMTMP 2023-04-19 14:46:42.562072
4 DISK /dm8/backup/full/FULLBAK02 DMDB 2023-04-19 12:28:17.869941
5 DISK /dm8/backup/full/FULLBAK01 DMDB 2023-04-18 16:04:20.590783
已用时间: 30.748(毫秒). 执行号:511.
以上通过disql执行的备份,都是联机热备份。
故障发生前,我们先看下目前数据库的魔数和唯一魔数信息
SQL> select 'db_magic' "参数",db_magic as "值"
union ALL
select 'permanent_magic',permanent_magic;
行号 参数 值
---------- --------------- --------------------
1 db_magic 754488622
2 permanent_magic 458133940
已用时间: 1.188(毫秒). 执行号:509.
$ cd /dm8/data/DMTMP
$ ls -l
总用量 856156
drwxr-xr-x 2 dmdba dinstall 6 4月 19 13:43 bak
drwxr-xr-x 2 dmdba dinstall 258 4月 19 14:46 ctl_bak
-rw-r--r-- 1 dmdba dinstall 338 4月 19 14:03 dmarch.ini
-rw-r--r-- 1 dmdba dinstall 6144 4月 19 14:46 dm.ctl
-rw-r--r-- 1 dmdba dinstall 59132 4月 19 14:03 dm.ini
-rw-r--r-- 1 dmdba dinstall 895 4月 19 13:43 dminit20230419134328.log
-rw-r--r-- 1 dmdba dinstall 633 4月 19 13:43 dm_service.prikey
-rw-r--r-- 1 dmdba dinstall 268435456 4月 19 15:27 DMTMP01.log
-rw-r--r-- 1 dmdba dinstall 268435456 4月 19 14:46 DMTMP02.log
drwxr-xr-x 2 dmdba dinstall 6 4月 19 13:43 HMAIN
-rw-r--r-- 1 dmdba dinstall 134217728 4月 19 13:43 MAIN.DBF
-rw-r--r-- 1 dmdba dinstall 12 4月 19 13:50 rep_conflict.log
-rw-r--r-- 1 dmdba dinstall 134217728 4月 19 15:25 ROLL.DBF
-rw-r--r-- 1 dmdba dinstall 481 4月 19 13:43 sqllog.ini
-rw-r--r-- 1 dmdba dinstall 27262976 4月 19 14:46 SYSTEM.DBF
-rw-r--r-- 1 dmdba dinstall 33554432 4月 19 14:30 TBS01.DBF
-rw-r--r-- 1 dmdba dinstall 10485760 4月 19 14:46 TEMP.DBF
drwxr-xr-x 2 dmdba dinstall 6 4月 19 13:50 trace
$ rm -f TBS01.DBF
在disql中检查文件被删除后表空间及表数据
SQL> select * from mytable;
行号 ID NAME
---------- ----------- ----
1 1 赵
2 2 钱
3 3 孙
4 4 李
5 5 周
6 6 吴
6 rows got
已用时间: 1.193(毫秒). 执行号:512.
SQL> SP_FILE_SYS_CHECK(); -- 执行系统文件检查
DMSQL 过程已成功完成
已用时间: 0.658(毫秒). 执行号:513.
SQL> select * from mytable;
select * from mytable; -- 无法查询到表数据
[-3433]:表空间处于脱机状态.
已用时间: 0.308(毫秒). 执行号:0.
这个方法利用数据库备份来进行还原恢复,因为是表空间文件意外被删除,我们首先用表空间还原恢复法。此种方法,前提是开启了归档和有备份
第一步:表空间还原
利用之前备份的表空间备份,进行还原。要还原表空间,首先要关闭数据库实例,然后进入到dmrman中进行操作,否则在dmrman中会报告下面的错误:
-137:服务器正在运行或者存在其他进程正在操作同一个库
$ ./dmrman
dmrman V8
RMAN> RESTORE database '/dm8/data/DMTMP/dm.ini' TABLESPACE TBS1 FROM BACKUPSET '/dm8/backup/full/TBS1BAK11'; -- 第一步还原表空间
第二步:恢复数据库
RECOVER DATABASE '/dm8/data/DMTMP/dm.ini' TABLESPACE "TBS1" WITH ARCHIVEDIR '/dm8/arch2';
RMAN> RECOVER DATABASE '/dm8/data/DMTMP/dm.ini' TABLESPACE "TBS1" WITH ARCHIVEDIR '/dm8/arch2'; -- 第二步恢复表空间
Database mode = 0, oguid = 0
Normal of FAST
Normal of DEFAULT
Normal of RECYCLE
Normal of KEEP
Normal of ROLL
EP[0]'s cur_lsn[41125], file_lsn[41125]
[Percent:100.00%][Speed:0.00PKG/s][Cost:00:00:00][Remaining:00:00:00]
recover successfully.
time used: 445.261(ms)
-- 这两步就完成了表空间的恢复,特别提醒,不需要更新db_magic
在dmdba用户下启动数据库
$ /dm8/bin/dmserver /dm8/data/DMTMP/dm.ini
file dm.key not found, use default license!
version info: develop
DM Database Server 64 V8 03134283890-20220525-161267-10045 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 2023-05-25
file lsn: 41125
ndct db load finished
...(略)
SYSTEM IS READY.
# 启动数据库正常
disql中查询数据
SQL> select * from mytable;
服务器[LOCALHOST:5238]:处于普通打开状态
已连接
行号 ID NAME
---------- ----------- ----
1 1 赵
2 2 钱
3 3 孙
4 4 李
5 5 周
6 6 吴
6 rows got
已用时间: 2.070(毫秒). 执行号:500.
SQL> select sysdate();
行号 SYSDATE()
---------- -------------------
1 2023-04-19 15:55:48
已用时间: 0.984(毫秒). 执行号:501.
SQL> select PATH,CREATE_TIME,status$ from v$datafile;
行号 PATH CREATE_TIME STATUS$
---------- -------------------------- ------------------- -----------
1 /dm8/data/DMTMP/SYSTEM.DBF 2023-04-19 13:43:30 1
2 /dm8/data/DMTMP/ROLL.DBF 2023-04-19 13:43:30 1
3 /dm8/data/DMTMP/TEMP.DBF 2023-04-19 15:51:07 1
4 /dm8/data/DMTMP/MAIN.DBF 2023-04-19 13:43:30 1
5 /dm8/data/DMTMP/TBS01.DBF 2023-04-19 15:44:06 1
已用时间: 1.282(毫秒). 执行号:503.
结论:通过之前表空间备份和归档日志,可以将意外删除的表空间文件给恢复。
注意,上面的操作,我们并没有修改魔数
SQL> select 'db_magic' "参数",db_magic as "值"
2 union ALL
3 select 'permanent_magic',permanent_magic;
行号 参数 值
---------- --------------- --------------------
1 db_magic 754488622
2 permanent_magic 458133940
已用时间: 22.413(毫秒). 执行号:517.
SQL>
该方法可以在没有数据库文件备份的情况下,恢复误删除的表空间文件。但是前提条件是有时间限制,并且不能重启服务器,不能重启数据库服务,并且不能删除关键的系统表空间。
该恢复方法主要是利用了在Linux系统中,只要其文件句柄(file handle)没有被关闭,可以在/proc/<pid>/fd中找到其对应的文件副本。利用该方法,结合操作系统命令,我们可以在数据库不停的情况下,实现表空间的恢复。
具体演示过程如下:
$ ls -l
总用量 856160
drwxr-xr-x 2 dmdba dinstall 6 4月 19 13:43 bak
drwxr-xr-x 2 dmdba dinstall 4096 4月 19 15:51 ctl_bak
-rw-r--r-- 1 dmdba dinstall 338 4月 19 14:03 dmarch.ini
-rw-r--r-- 1 dmdba dinstall 6144 4月 19 15:51 dm.ctl
-rw-r--r-- 1 dmdba dinstall 59132 4月 19 14:03 dm.ini
-rw-r--r-- 1 dmdba dinstall 895 4月 19 13:43 dminit20230419134328.log
-rw-r--r-- 1 dmdba dinstall 633 4月 19 13:43 dm_service.prikey
-rw-r--r-- 1 dmdba dinstall 268435456 4月 19 16:14 DMTMP01.log
-rw-r--r-- 1 dmdba dinstall 268435456 4月 19 15:51 DMTMP02.log
drwxr-xr-x 2 dmdba dinstall 6 4月 19 13:43 HMAIN
-rw-r--r-- 1 dmdba dinstall 134217728 4月 19 13:43 MAIN.DBF
-rw-r--r-- 1 dmdba dinstall 12 4月 19 13:50 rep_conflict.log
-rw-r--r-- 1 dmdba dinstall 134217728 4月 19 16:12 ROLL.DBF
-rw-r--r-- 1 dmdba dinstall 481 4月 19 13:43 sqllog.ini
-rw-r--r-- 1 dmdba dinstall 27262976 4月 19 15:54 SYSTEM.DBF
-rw-r--r-- 1 dmdba dinstall 33554432 4月 19 15:48 TBS01.DBF
-rw-r--r-- 1 dmdba dinstall 10485760 4月 19 15:51 TEMP.DBF
drwxr-xr-x 2 dmdba dinstall 6 4月 19 13:50 trace
[dmdba@KylinDCA1 DMTMP]$ rm -f TBS01.DBF ## 删除文件
disql中执行
SQL> SP_FILE_SYS_CHECK();
DMSQL 过程已成功完成
已用时间: 1.785(毫秒). 执行号:504.
SQL> select PATH,CREATE_TIME,status$ from v$datafile;
行号 PATH CREATE_TIME STATUS$
---------- -------------------------- ------------------- -----------
1 /dm8/data/DMTMP/SYSTEM.DBF 2023-04-19 13:43:30 1
2 /dm8/data/DMTMP/ROLL.DBF 2023-04-19 13:43:30 1
3 /dm8/data/DMTMP/TEMP.DBF 2023-04-19 15:51:07 1
4 /dm8/data/DMTMP/MAIN.DBF 2023-04-19 13:43:30 1
5 /dm8/data/DMTMP/TBS01.DBF 2023-04-19 15:44:06 0
已用时间: 0.339(毫秒). 执行号:505.
SQL> select * from mytable;
select * from mytable;
[-3433]:表空间处于脱机状态.
已用时间: 134.618(毫秒). 执行号:0.
SQL> SP_TABLESPACE_PREPARE_RECOVER('TBS1'); -- 第一步执行系统函数
此时表空间状态已经是0(离线状态),相关表也不能查询。
在bash终端中操作
$ ps -ef|grep dmserver
dmdba 43860 1 0 13:04 pts/3 00:00:48 /dm8/bin/dmserver path=/dm8/data/DMDB/dm.ini -noconsole
dmdba 45079 44116 0 15:51 pts/2 00:00:13 /dm8/bin/dmserver /dm8/data/DMTMP/dm.ini
dmdba 45372 39357 0 16:20 pts/0 00:00:00 grep dmserver
进程ID为45079是我们演示库的进程
$ ls -la /proc/45079/fd
总用量 0
dr-x------ 2 dmdba dinstall 0 4月 19 16:21 .
dr-xr-xr-x 9 dmdba dinstall 0 4月 19 15:51 ..
lrwx------ 1 dmdba dinstall 64 4月 19 16:21 0 -> /dev/pts/2
lrwx------ 1 dmdba dinstall 64 4月 19 16:21 1 -> /dev/pts/2
lrwx------ 1 dmdba dinstall 64 4月 19 16:21 10 -> /dm8/data/DMTMP/ROLL.DBF
lrwx------ 1 dmdba dinstall 64 4月 19 16:21 11 -> /dm8/data/DMTMP/MAIN.DBF
lrwx------ 1 dmdba dinstall 64 4月 19 16:21 12 -> '/dm8/data/DMTMP/TBS01.DBF (deleted)' ## 该文件已经被删除,但其现在还被dmserver打开,文件句柄是12
lr-x------ 1 dmdba dinstall 64 4月 19 16:21 13 -> 'pipe:[543380]'
l-wx------ 1 dmdba dinstall 64 4月 19 16:21 14 -> 'pipe:[543380]'
lr-x------ 1 dmdba dinstall 64 4月 19 16:21 15 -> 'pipe:[543381]'
$ cp /proc/45079/fd/12 /dm8/data/DMTMP/TBS01.DBF ## 12 为已经删除文件句柄
$ ll /dm8/data/DMTMP/TBS01.DBF
-rw-r--r-- 1 dmdba dinstall 33554432 4月 19 16:24 /dm8/data/DMTMP/TBS01.DBF ## 将该文件句柄复制到一个文件,该文件名就指定为原来文件名
接下来在disql中执行
SQL> SP_TABLESPACE_RECOVER('TBS1'); -- 第二步
DMSQL 过程已成功完成
已用时间: 4.107(毫秒). 执行号:511.
SQL> SP_FILE_SYS_CHECK(); -- 第三步
DMSQL 过程已成功完成
已用时间: 0.550(毫秒). 执行号:512.
SQL> select PATH,CREATE_TIME,status$ from v$datafile;
行号 PATH CREATE_TIME STATUS$
---------- -------------------------- ------------------- -----------
1 /dm8/data/DMTMP/SYSTEM.DBF 2023-04-19 13:43:30 1
2 /dm8/data/DMTMP/ROLL.DBF 2023-04-19 13:43:30 1
3 /dm8/data/DMTMP/TEMP.DBF 2023-04-19 15:51:07 1
4 /dm8/data/DMTMP/MAIN.DBF 2023-04-19 13:43:30 1
5 /dm8/data/DMTMP/TBS01.DBF 2023-04-19 15:44:06 1 -- 表空间状态恢复正常
已用时间: 0.608(毫秒). 执行号:513.
SQL> select * from mytable;
行号 ID NAME
---------- ----------- ----
1 1 赵
2 2 钱
3 3 孙
4 4 李
5 5 周
6 6 吴
6 rows got
已用时间: 0.351(毫秒). 执行号:514.
在Linux环境下,利用上述两种办法,我们都实现了表空间的恢复。方法一应当说是比较规范和通用的方法,它支持Windows、Linux以及其它Unix平台。它实现的前提条件是数据库开启了归档模式,并且有数据库全备份或者表空间备份,以及归档日志备份。而方法二是一种针对特定的操作系统,利用操作系统提供的特性,结合数据库系统函数实现。该方式有局限,但是也有在线操作、不重启数据库就能恢复的优点。
三天培训,收获良多!在此特谢谢程青讲师,谢谢达梦培训的其他老师。
2023年8期DCA学员虫虫于成都
文章
阅读量
获赞