[20250512]drop table的恢复3(包含lob类型字段).txt
–//作为系列测试,增加drop table的恢复(包含lob类型字段)的情况,建立表包含lob字段,每个lob字段包含2个段,1个数据段,1个其
–//索引段。当drop table时,相关数据段全部删除(包括索引段也会一起删除,不过对于恢复,索引可以重建),这样通过rowid方式恢
–//复需要建立的新表相关数据段指向原来的旧表的数据段,通过测试说明问题。
1.环境:
SCOTT@book01p> @ ver2
==============================
PORT_STRING : x86_64/Linux 2.4.xx
VERSION : 21.0.0.0.0
BANNER : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 – Production
BANNER_FULL : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 – Production
Version 21.3.0.0.0
BANNER_LEGACY : Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 – Production
CON_ID : 0
PL/SQL procedure successfully completed.
2.测试环境建立:
SCOTT@book01p> create table t5 (id number ,text clob);
Table created.
SCOTT@book01p> insert into t5 select rownum,to_char(rownum)||lpad(‘x’,3964,’x’) from dual connect by level <=1e4;
10000 rows created.
SCOTT@book01p> commit ;
Commit complete.
–//记录相关数据段号:
SCOTT@book01p> @ o2 t5
SCOTT@book01p> @pr
==============================
O_OWNER : SCOTT
O_OBJECT_NAME : T5
O_OBJECT_TYPE : TABLE
SEG_PART_NAME :
O_STATUS : VALID
OID : 128559
D_OID : 128559
CREATED : 2025-05-12 15:27:44
LAST_DDL_TIME : 2025-05-12 15:27:44
PL/SQL procedure successfully completed.
SCOTT@book01p> @lob scott.%128559%
SCOTT@book01p> @pr
==============================
OWNER : SCOTT
TABLE_NAME : T5
COLUMN_NAME : TEXT
SEGMENT_NAME : SYS_LOB0000128559C00002$$
TABLESPACE_NAME : USERS
INDEX_NAME : SYS_IL0000128559C00002$$
CHUNK : 8192
PCTVERSION :
RETENTION :
FREEPOOLS :
CACHE : NO
LOGGING : YES
ENCRYPT : NO
COMPRESSION : NO
DEDUPLICATION : NO
IN_ROW : YES
FORMAT : ENDIAN NEUTRAL
PARTITIONED : NO
SECUREFILE : YES
SEGMENT_CREATED : YES
RETENTION_TYPE : DEFAULT
RETENTION_VALUE :
VALUE_BASED : NO
MAX_INLINE : 4000
PL/SQL procedure successfully completed.
SCOTT@book01p> @ o2 SYS_LOB0000128559C00002$$
SCOTT@book01p> @ pr
==============================
O_OWNER : SCOTT
O_OBJECT_NAME : SYS_LOB0000128559C00002$$
O_OBJECT_TYPE : LOB
SEG_PART_NAME :
O_STATUS : VALID
OID : 128560
D_OID : 128560
CREATED : 2025-05-12 15:27:44
LAST_DDL_TIME : 2025-05-12 15:27:44
PL/SQL procedure successfully completed.
SCOTT@book01p> @ o2 SYS_IL0000128559C00002$$
SCOTT@book01p> @ pr
==============================
O_OWNER : SCOTT
O_OBJECT_NAME : SYS_IL0000128559C00002$$
O_OBJECT_TYPE : INDEX
SEG_PART_NAME :
O_STATUS : VALID
OID : 128561
D_OID : 128561
CREATED : 2025-05-12 15:27:44
LAST_DDL_TIME : 2025-05-12 15:27:44
PL/SQL procedure successfully completed.
–//T5表的数据段号128559。字段text的lob段号128560,其索引段号128561、
SCOTT@book01p> drop table t5 purge ;
Table dropped.
SYS@book01p> @ versions obj$ OBJ#,DATAOBJ#,name s ” ” “versions_operation=’D’ and VERSIONS_STARTTIME>=’2025-05-12 15:32:10′”
VERSIONS_STARTTIME VERSIONS_ENDTIME VERSIONS_STARTSCN VERSIONS_ENDSCN VERSIONS_XID V ROWID OBJ# DATAOBJ# NAME
——————– ——————– —————– ————— —————- – —————— ———- ———- ——————————
2025-05-12 15:32:12. 41543968 09001100A51F0000 D AAAAASAABAAAI6GAAD 128560 128560 SYS_LOB0000128559C00002$$
2025-05-12 15:32:12. 41543968 09001100A51F0000 D AAAAASAABAAAI6GAAH 128559 128559 T5
2025-05-12 15:32:12. 41543968 09001100A51F0000 D AAAAASAABAAAI6GAAA 128561 128561 SYS_IL0000128559C00002$$
–//通过版本查询也能够确定删除表以及相关数据段号。
3.开始恢复:
–//不能直接建立新表在原来的表空间,为了避免建立新表的覆盖问题.可以在原表空间增加一个数据文件:
ALTER TABLESPACE USERS
ADD DATAFILE ‘/u01/oradata/BOOK/book01p/users02.dbf’
SIZE 100M
AUTOEXTEND ON
NEXT 4M
MAXSIZE UNLIMITED;
SYS@book01p> alter database datafile ‘/u01/oradata/BOOK/book01p/users01.dbf’ offline drop;
Database altered.
–//注:因为我的测试环境没有打开归档,导致直接offline报错,加入drop没有问题,注意并非真正意思删除。
SYS@book01p> recover datafile 12;
Media recovery complete.
–//顺手先recover datafile 12;以后可以直接online。
–//然后再建立新表绕开这个覆盖问题。
–//建立的表要加入SEGMENT CREATION IMMEDIATE,不然oracle认为是空表,无法通过rowid方式读取。
SCOTT@book01p> create table t5_drop (id number ,text clob) SEGMENT CREATION IMMEDIATE ;
Table created.
SCOTT@book01p> column PARTITION_NAME noprint
SCOTT@book01p> select * from dba_extents where segment_name=’T5_DROP’;
SCOTT@book01p> @ pr
==============================
OWNER : SCOTT
SEGMENT_NAME : T5_DROP
PARTITION_NAME :
SEGMENT_TYPE : TABLE
TABLESPACE_NAME : USERS
EXTENT_ID : 0
FILE_ID : 17
BLOCK_ID : 128
BYTES : 65536
BLOCKS : 8
RELATIVE_FNO : 17
PL/SQL procedure successfully completed.
–//建立的新表使用的数据段不在数据文件号12上。
–//建立表空间TSP_AUDIT略。
–//ALTER USER SCOTT QUOTA UNLIMITED ON TSP_AUDIT;
SCOTT@book01p> create table bak_t5 tablespace TSP_AUDIT as select * from scott.t5_drop where 0=1;
Table created.
–//扫描获得信息插入的表bak_t5放在另外的表空间,避免覆盖原来的数据文件信息。
–//修改相关段号:
SYS@book01p> @ versions obj$ OBJ#,DATAOBJ#,name s ” ” “versions_operation=’I’ and VERSIONS_STARTTIME>=’2025-05-12 15:32:10′”
VERSIONS_STARTTIME VERSIONS_ENDTIME VERSIONS_STARTSCN VERSIONS_ENDSCN VERSIONS_XID V ROWID OBJ# DATAOBJ# NAME
——————– ——————– —————– ————— —————- – —————— ———- ———- ——————————
2025-05-12 15:39:44. 41545595 04000800821F0000 I AAAAASAABAAAI6GAAD 128563 128563 SYS_LOB0000128562C00002$$
2025-05-12 15:39:44. 41545595 04000800821F0000 I AAAAASAABAAAI6GAAG 128562 128562 T5_DROP
2025-05-12 15:39:44. 41545595 04000800821F0000 I AAAAASAABAAAI6GAAA 128564 128564 SYS_IL0000128562C00002$$
2025-05-12 15:42:45. 41548664 06000400471F0000 I AAAAASAABAAAI6GAAL 128566 128566 SYS_LOB0000128565C00002$$
2025-05-12 15:42:45. 41548664 06000400471F0000 I AAAAASAABAAAI6GAAH 128565 128565 BAK_T5
2025-05-12 15:42:45. 41548664 06000400471F0000 I AAAAASAABAAAI6GAAK 128567 128567 SYS_IL0000128565C00002$$
6 rows selected.
–//建立新表以及lob以及索引段号分别是128562,128563,128564
–//修改指向旧表T5.
update (select OBJ#,DATAOBJ#,OWNER#,NAME from obj$ where obj#=128562) set DATAOBJ#=128559;
update (select OBJ#,DATAOBJ#,OWNER#,NAME from obj$ where obj#=128563) set DATAOBJ#=128560;
update (select OBJ#,DATAOBJ#,OWNER#,NAME from obj$ where obj#=128564) set DATAOBJ#=128561;
commit ;
SYS@book01p> alter system flush shared_pool;
System altered.
–//扫描数据文件确定数据段号。
$ . finddoid.sh 12 128 32640 128559
data_object_id 128559 max_row = 153
–//该脚本顺便确定数据块的最大行记录153条。
–//建立2个文件:
$ paste scan_128559.txt scan_row_128559.txt | head -4
12,171 151
12,172 151
12,173 151
12,174 153
$ sed ‘s/^/insert into scanblock values (/;s/$/);/’ scan_128559.txt | head -3
insert into scanblock values (12,171);
insert into scanblock values (12,172);
insert into scanblock values (12,173);
$ sed ‘s/^/insert into scanblock values (/;s/$/);/’ scan_128559.txt >| xy.txt
SYS@book01p> create table scott.scanblock ( file_id number,block_id number ) tablespace TSP_AUDIT;
Table created.
–//注意建立的新表一定不能使用原来的表空间,避免覆盖。
–//执行xy.txt脚本,注意提交。
SYS@book01p> set timing on
SYS@book01p> @ txt/truncT.txt SCOTT T5_DROP SCOTT BAK_T5 152
PL/SQL procedure successfully completed.
Elapsed: 00:00:19.85
SYS@book01p> set timing off
–//参数5=152,行号从0开始计数。
–//补充应该可以再改进减少扫描范围,另外写一篇blog。
SCOTT@book01p> select count(*) from bak_t5;
COUNT(*)
———-
10000
–//完全恢复。
4.收尾还原:
update (select OBJ#,DATAOBJ#,OWNER#,NAME from obj$ where obj#=128562) set DATAOBJ#=128562;
update (select OBJ#,DATAOBJ#,OWNER#,NAME from obj$ where obj#=128563) set DATAOBJ#=128563;
update (select OBJ#,DATAOBJ#,OWNER#,NAME from obj$ where obj#=128564) set DATAOBJ#=128564;
commit ;
5.附上相关执行脚本:
$ cat finddoid.sh
#! /bin/bash
# argv1=file_number argv2=begin_block argvs3=end_block argv4=data_object_id
file_number=$1
begin_block=$2
end_block=$3
data_object_id=$4
# scan begin_block to end_block,define search scope.
/bin/rm scan_${data_object_id}.txt 2>/dev/null
#seq -f “%-1.0f” $begin_block $end_block | xargs -IQ echo -e “host echo $file_number,Q \np /d dba $file_number,Q ktbbh.ktbbhsid.ktbbhod1” | \
#rlbbed | grep “^BBED” | egrep “$file_number,|ub4 ktbbhod1″ | awk ‘{print $NF}’ | paste -d” ” – – | awk -v a=$data_object_id ‘$2==a {print $1}’ >| scan_${data_object_id}.txt
seq -f “%-1.0f” $begin_block $end_block | xargs -IQ echo -e “host echo -n $file_number,Q \np /d dba $file_number,Q ktbbh.ktbbhsid.ktbbhod1” | \
rlbbed | grep -B1 –no-group-separator “ub4 ktbbhod1″ | awk ‘{print $NF}’ | paste -d” ” – – | awk -v a=$data_object_id ‘$2==a {print $1}’ >| scan_${data_object_id}.txt
# scan begin_block to end_block,obtain max row.
/bin/rm scan_row_${data_object_id}.txt 2>/dev/null
cat scan_${data_object_id}.txt | xargs -IQ echo p dba Q kdbt[0].kdbtnrow | rlbbed | grep kdbtnrow | awk ‘{print $NF}’ >| scan_row_${data_object_id}.txt
max_row=$(sort -nr scan_row_${data_object_id}.txt | head -1)
echo data_object_id $data_object_id max_row = $max_row
$ cat txt/truncT.txt
DECLARE
v_fno NUMBER;
v_s_bno NUMBER;
v_e_bno NUMBER;
v_rowid ROWID;
v_owner VARCHAR2 (100) := ‘&&1’;
v_table VARCHAR2 (100) := ‘&&2’;
v_o_owner VARCHAR2 (100) := ‘&&3’;
v_o_table VARCHAR2 (100) := ‘&&4’;
v_dataobj NUMBER;
v_sql VARCHAR2 (4000);
v_tablespace VARCHAR2 (100);
nrows NUMBER;
BEGIN
nrows := 0;
SELECT data_object_id
INTO v_dataobj
FROM dba_objects
WHERE owner = v_owner AND object_name = v_table;
SELECT tablespace_name
INTO v_tablespace
FROM dba_tables
WHERE owner = v_owner AND table_name = v_table;
— FOR i
— IN (SELECT relative_fno, block_id, blocks FROM dba_extents WHERE owner = v_owner AND segment_name = v_table AND extent_id = 0
— UNION ALL
— SELECT relative_fno, block_id, blocks FROM dba_free_space WHERE tablespace_name = v_tablespace
— UNION ALL
— SELECT relative_fno, block_id, blocks
— FROM (SELECT relative_fno
— ,block_id
— ,blocks
— ,ROW_NUMBER () OVER (PARTITION BY owner, segment_name, partition_name ORDER BY extent_id DESC)
— rn
— FROM dba_extents
— WHERE tablespace_name = v_tablespace AND extent_id > 0)
— WHERE rn = 1)
for i in (select file_id relative_fno,block_id, 1 blocks from scott.scanblock)
LOOP
v_fno := i.relative_fno;
v_s_bno := i.block_id;
v_e_bno := i.block_id + i.blocks – 1;
–v_e_bno:=i.block_id+1-1; –//using scanblock method
FOR j IN v_s_bno .. v_e_bno
LOOP
BEGIN
FOR x IN 0 .. &&5
LOOP
v_rowid := DBMS_ROWID.rowid_create ( 1 ,v_dataobj ,v_fno ,j ,x);
v_sql :=
‘insert into ‘
|| v_o_owner
|| ‘.’
|| v_o_table
|| ‘ select * from ‘
|| v_owner
|| ‘.’
|| v_table
|| ‘ where rowid=:1’;
EXECUTE IMMEDIATE v_sql USING v_rowid;
IF SQL%ROWCOUNT = 1
THEN
nrows := nrows + 1;
END IF;
IF (MOD (nrows, 10000) = 0)
THEN
COMMIT;
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
NULL;
END;
COMMIT;
END LOOP;
END LOOP;
END;
/
来源链接:https://www.cnblogs.com/lfree/p/18874856
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
暂无评论内容