truncate恢复表,在11.2.0.4文件系统和19c asm上测试通过

参考:Fy_Recover_Data 2014.03.07 更新 -- 现在可以从离线文件中恢复被Truncated的数据了 [HelloDBA.COM]

oracle truncate表 恢复操作_ElanJie的博客-CSDN博客_truncate恢复

代码下载:

http://www.hellodba.com/Download/FY_Recover_Data.zip

SQL> conn /as sysdba
Connected.
SQL> @/home/oracle/restore.sql --默认回车即可
Enter value for files: 
old  30:   --   1. Temp Restore and Recover tablespace & files                     ---
new  30:   --   1. Temp Restore and Recover tablespace                      ---

Package created.

Package body created.

SQL> 
SQL> 
SQL> 
SQL> conn jyc/jyc
Connected.
SQL> select name from v$datafile;

NAME
--------------------------------------------------------------------------------
+DATA/CISDB/DATAFILE/system.257.1024323415
+DATA/CISDB/DATAFILE/users.304.1024826209
+DATA/CISDB/DATAFILE/sysaux.258.1024323449
+DATA/CISDB/DATAFILE/undotbs1.259.1024323465
+DATA/CISDB/DATAFILE/undotbs2.265.1024323677
+DATA/CISDB/DATAFILE/users.260.1024323465
+DATA/CISDB/DATAFILE/jyc.305.1024826301

7 rows selected.

SQL> select * from t1;

ID
----------
         1
         2
         3

SQL> truncate table t1;

Table truncated.

查看t1所在文件位置:

select distinct b.file_name from dba_extents a,dba_data_files b where a.file_id=b.file_id and a.SEGMENT_NAME='T1' and a.OWNER='JYC';

快速拷贝到相应位置:

如果是普通文件
cp xxx /tmp/xxx.dat
如果是asm:
su - grid
asmcmd
ASMCMD> cp data1/dbat1/datafile/ASM_DATA.360.839931591 /tmp/ams_data.dat  

SQL> conn /as sysdba
Connected.
SQL> exec fy_recover_data.recover_truncated_table('JYC','T1');

PL/SQL procedure successfully completed.

exec fy_recover_data.recover_truncated_table('JYC','T1',1,'/tmp','/tmp/asm_data_1;/tmp/asm_data_2;');

SQL> conn jyc/jyc           
Connected.
SQL> select table_name from user_tables;

TABLE_NAME
--------------------------------------------------------------------------------
TEST
DMLTEST
HYBRID_TEST
T1
T1$
T1$$

6 rows selected.

SQL> select * from t1$;

no rows selected

SQL> select * from t1$$;

ID
----------
         1
         2
         3

SQL> select * from t1;

no rows selected

SQL> alter table jyc.t1 nologging;

Table altered.

SQL> insert /*+append*/ into jyc.t1 select * from jyc.t1$$;

3 rows created.

SQL> commit;

Commit complete.

SQL> alter table jyc.t1 logging;

Table altered.

SQL> select * from t1;

ID
----------
         1
         2
         3

SQL> select name from v$datafile;

NAME
--------------------------------------------------------------------------------
+DATA/CISDB/DATAFILE/system.257.1024323415
+DATA/CISDB/DATAFILE/users.304.1024826209
+DATA/CISDB/DATAFILE/sysaux.258.1024323449
+DATA/CISDB/DATAFILE/undotbs1.259.1024323465
+DATA/CISDB/DATAFILE/undotbs2.265.1024323677
+DATA/CISDB/DATAFILE/users.260.1024323465
+DATA/CISDB/DATAFILE/jyc.305.1024826301
/tmp/FY_REC_DATA.DAT
/tmp/FY_RST_DATA.DAT

9 rows selected.

SQL> select name from v$tablespace;

NAME
------------------------------
SYSAUX
SYSTEM
UNDOTBS1
USERS
TEMP
UNDOTBS2
JYC
FY_REC_DATA
FY_RST_DATA

9 rows selected.

SQL> drop tablespace FY_REC_DATA including contents and datafiles;

Tablespace dropped.

SQL> drop tablespace FY_RST_DATA including contents and datafiles;

Tablespace dropped.

SQL>

代码:

create or replace package FY_Recover_Data is----------------------------------------------------------------------------- WWW.HelloDBA.COM                                                     ----- Created By: Fuyuncat                                                 ----- Created Date: 08/08/2012                                             ----- Email: Fuyuncat@gmail.com                                            ----- Copyright (c), 2014, WWW.HelloDBA.COM All rights reserved.           ----- Latest Version: http://www.HelloDBA.com/download/FY_Recover_Data.zip -----                                                                      ----- Update Logs                                                          ----- 15/08/2012, Fuyuncat:                                                -----   1. Fixed Bug in Clean_Up_Ts (Not change TS status correctly)        -----   2. Added Exception Handle when Restore Data                        -----   3. Added Parameter in recover_table,                               -----            to balance Fault Tolerance and Performance                -----                                                                      ----- 16/08/2012, Fuyuncat:                                                -----   1. Enhanced corrupted block processing, get rows as possilbe       -----                                                                      ----- 17/08/2012, Fuyuncat:                                                -----   1. Omit the LOB columns raised ORA-22922 exception                 -----                                                                      ----- 20/08/2012, Fuyuncat:                                                -----   1. Omit the LOB columns via db link                                -----                                                                      ----- 22/08/2012, Fuyuncat:                                                -----   1. Updated logging and tracing interface                           -----                                                                      ----- 19/02/2014, Fuyuncat:                                                -----   1. Temp Restore and Recover tablespace & files                     -----      will be created on temp folder                                  -----   2. Handle tablespace has files located at diff folders             -----   3. Handle tables on ASM                                            -----                                                                      ----- 05/03/2014, Fuyuncat:                                                -----   1. Fixed bugs                                                      -----   2. Use existing dirctory if applicable                             -----   3. Recover data from offline files                                 ------------------------------------------------------------------------------type r_cursor is REF CURSOR;type o_fileprop is record (file# number,status$ number);type t_fileprops is table of o_fileprop;/************************************************************************** recover truncated table**** tgtowner: Owner of Target Table to be recovered;** tgttable: Name of Target Table to be recovered;** datapath: Absolute path of Data Files;** fbks: block number to be filled in recovery table;** offline_files: Offline data files that data should be recovered from;**    foramt: full_path_file1;full_path_file2...;************************************************************************/procedure recover_truncated_table( tow varchar2, ttb varchar2,fbks number default 1, tmppath varchar2 default null,offline_files varchar2 default null);/************************************************************************** dump a block in raw, for testing**** hdfile: Data file name;** srcdir: data file directory** blknb: block number to be dumped;** blksz: block size;************************************************************************/procedure dump_seg_block_raw( hdfile varchar2,srcdir varchar2, blknb number,blksz number default 8192);
/*procedure test_chain(filename varchar2, blknum number, startpos number,repcont raw,srcdir varchar2 default 'FY_DATA_DIR');
*//************************************************************************** Set Initial parameters**** tracing: trace the process for debug;** logging: show logging information;** repobjid: replace the data object id wiht the recover table data object id;************************************************************************/procedure init_set( tracing boolean default true,logging boolean default true,repobjid boolean default true);
end FY_Recover_Data;
/
create or replace package body FY_Recover_Data is----------------------------------------------------------------------------- WWW.HelloDBA.COM                                                     ----- Created By: Fuyuncat                                                 ----- Created Date: 08/08/2012                                             ----- Email: Fuyuncat@gmail.com                                            ----- Copyright (c), 2014, WWW.HelloDBA.COM All rights reserved.            ----- Latest Version: http://www.HelloDBA.com/download/FY_Recover_Data.zip   ------------------------------------------------------------------------------s_tracing       boolean:= false;s_logging       boolean:= true;s_repobjid      boolean:= false;procedure init_set (tracing boolean default true,logging boolean default true,repobjid boolean default true)asbegins_tracing := tracing;s_logging := logging;s_repobjid := repobjid;end;procedure trace (msg varchar2)asbeginif s_tracing thendbms_output.put_line(to_char(sysdate, 'HH24:MI:SS')||': '||msg);end if;end;procedure log (msg varchar2)asbeginif s_logging thendbms_output.put_line(to_char(sysdate, 'HH24:MI:SS')||': '||msg);end if;end;function d2r (dig varchar2,len number default 0)return rawisbegin--trace('[d2r] hextoraw(lpad(trim(to_char('||dig||', ''XXXXXXXX'')),'||len||',''0''))');return hextoraw(lpad(trim(to_char(dig, 'XXXXXXXX')),len,'0'));end;                /************************************************************************** Copy file**** srcdir: Directory of Source File;** srcfile: Source File Name;** dstdir: Directory of Destination File;** dstfile: Destination File Name;************************************************************************/procedure copy_file(srcdir varchar2, srcfile varchar2, dstdir varchar2, dstfile in out varchar2)as--p_srcdir varchar2(255) := upper(srcdir);--p_srcfile varchar2(255) := upper(srcfile);--p_dstdir varchar2(255) := upper(dstdir);--p_dstfile varchar2(255) := upper(dstfile);p_srcdir varchar2(255) := srcdir;p_srcfile varchar2(255) := srcfile;p_dstdir varchar2(255) := dstdir;p_dstfile varchar2(255) := dstfile;file_copied boolean := false;retries pls_integer := 0;beginif dstdir is null thenp_dstdir := p_srcdir;end if;if dstfile is null thenp_dstfile := p_srcfile||'$';dstfile := p_dstfile;end if;while not file_copied loopbegintrace('[copy_file] begin copy file: '||p_srcdir||'\'||p_srcfile||' => '||p_dstdir||'\'||p_dstfile);--'DBMS_FILE_TRANSFER.copy_file(p_srcdir, p_srcfile, p_dstdir, p_dstfile);trace('[copy_file] completed.');file_copied := true;exception when others then-- file already existsif sqlcode = -19504 and instr(dbms_utility.format_error_stack,'ORA-27038')>0 and retries < 10 thentrace('[copy_file] file '||p_dstdir||'\'||p_dstfile||' exists, rename to '||dstfile||retries);retries := retries+1;p_dstfile := dstfile||retries;file_copied := false;else --log(dbms_utility.format_error_backtrace);file_copied := true;raise;end if;end;end loop;dstfile := p_dstfile;end;/************************************************************************** Remove file**** dir: Directory of the File;** file: File to be removed;************************************************************************/procedure remove_file(dir varchar2, file varchar2)asbegintrace('[remove_file] Begin to remove file '||dir||'/'||file);utl_file.fremove(dir,file);trace('[remove_file] '||dir||'/'||file||' has been removed.');end;function gen_table_name(tgttable varchar2,plus     varchar2 default '',genowner varchar2 default user)return varchar2asgentab varchar2(30);beginselect upper(tgttable||plus||surfix) into gentab from (select surfix from (select null surfix from dual union all select level surfix from dual connect by level <= 255) where not exists (select 1 from dba_tables where owner = genowner and table_name = upper(tgttable||plus||surfix)) order by surfix nulls first) where rownum<=1;return gentab;end;function gen_file_name( tgtfile varchar2,plus    varchar2 default '')return varchar2asgenfile varchar2(30);slash char(1);beginselect decode(instr(platform_name, 'Windows'),0,'/','\') into slash from v_$database where rownum<=1;select tgtfile||plus||surfix||'.DAT' into genfile from (select surfix from (select null surfix from dual union all select level surfix from dual connect by level <= 255) where not exists (select 1 from dba_data_files where file_name like '%'||slash||tgtfile||plus||surfix||'.DAT') order by surfix nulls first) where rownum<=1; --'return genfile;end;function gen_ts_name( tgtts  varchar2,plus   varchar2 default '')return varchar2asgents varchar2(30);beginselect tgtts||plus||surfix into gents from (select surfix from (select null surfix from dual union all select level surfix from dual connect by level <= 255) where not exists (select 1 from dba_tablespaces where tablespace_name = tgtts||plus||surfix) order by surfix nulls first) where rownum<=1;return gents;end;procedure create_directory (path varchar2,dir in out varchar2)asexists_path pls_integer;exists_dir varchar2(256);slash char(1);beginselect decode(instr(platform_name, 'Windows'),0,'/','\') into slash from v_$database where rownum<=1;-- windowsif slash='\' thenselect count(1), max(directory_name) into exists_path, exists_dir from dba_directories where owner=user and upper(directory_path)||decode(substr(directory_path,length(directory_path)),slash,'',slash)=upper(path)||decode(substr(path,length(path)),slash,'',slash);else -- linux/unixselect count(1), max(directory_name) into exists_path, exists_dir from dba_directories where owner=user and directory_path||decode(substr(directory_path,length(directory_path)),slash,'',slash)=path||decode(substr(path,length(path)),slash,'',slash);end if;trace('[create_directory] Exists directory number '||exists_path);if exists_path=0 thenselect dir||surfix into dir from (select surfix from (select null surfix from dual union all select level surfix from dual connect by level <= 255) where not exists (select 1 from dba_directories where directory_name = dir||surfix) order by surfix nulls first) where rownum<=1;log('New Directory Name: '||dir);execute immediate 'create directory '||dir||' as '''||path||'''';elsedir := exists_dir;log('Use existing Directory Name: '||dir);end if;end;procedure replace_segmeta_in_file(tmpdir varchar2, tmpcopyf varchar2, dstdir varchar2, dstfile in out varchar2,dstisfilesystem boolean,tgtobjid number,newobjid number, dtail raw,addpos number,addinfo raw,blksz number default 8192,endianess number default 1)asbfr    utl_file.file_type;bfw    utl_file.file_type; hsz    number := 24;objr   raw(4);objn   number;dhead  raw(32);dbody  raw(32767);nbody  raw(32767);p_tmpdir varchar2(255) := tmpdir;p_tmpcopyf varchar2(255) := tmpcopyf;p_dstdir varchar2(255) := dstdir;p_tmpdstfile varchar2(255);p_finaldstdir varchar2(255);beginif p_dstdir is null thenp_dstdir := p_tmpdir;end if;trace('[replace_objid_in_file] replace object id in '||tmpdir||'\'||tmpcopyf||' ['||tgtobjid||' => '||newobjid||']'); --'if not dstisfilesystem thenp_tmpdstfile := gen_file_name(dstfile,'');copy_file(dstdir,dstfile,p_tmpdir,p_tmpdstfile);p_finaldstdir := p_tmpdir;elsep_tmpdstfile := dstfile;p_finaldstdir := p_dstdir;end if;bfr := utl_file.fopen(p_tmpdir, p_tmpcopyf, 'RB');bfw := utl_file.fopen(p_finaldstdir, p_tmpdstfile, 'WB');while true loopbeginnbody := '';utl_file.get_raw(bfr, dhead, hsz);exit when dhead is null;utl_file.get_raw(bfr, dbody, blksz-hsz);--objr := hextoraw(substrb(rawtohex(dbody), 1, 8));objr := utl_raw.substr(dbody, 1, 4);if endianess > 0 thenobjn := to_number(rawtohex(utl_raw.reverse(objr)), 'XXXXXXXX');elseobjn := to_number(rawtohex(objr), 'XXXXXXXX');end if;-- replace data object id with the recover object id--if objn = tgtobjid and substrb(rawtohex(dhead), 1, 2) = '06' thenif objn = tgtobjid thenif addpos <= hsz then--utl_file.put_raw(bfw, utl_raw.concat(utl_raw.substr(dhead, 1, addpos-1), addinfo, utl_raw.substr(dhead, addpos+utl_raw.length(addinfo))));nbody := utl_raw.concat(nbody, utl_raw.substr(dhead, 1, addpos-1), addinfo, utl_raw.substr(dhead, addpos+utl_raw.length(addinfo)));else--utl_file.put_raw(bfw, dhead);nbody := utl_raw.concat(nbody, dhead);end if;--utl_file.put_raw(bfw, utl_raw.concat(utl_raw.substr(dhead, 1, 8), addinfo, utl_raw.substr(dhead, 9+utl_raw.length(addinfo))));--nbody := utl_raw.concat(nbody, utl_raw.substr(dhead, 1, 8), addinfo, utl_raw.substr(dhead, 9+utl_raw.length(addinfo)));--trace('[replace_objid_in_file] old id in raw: '||rawtohex(objr));if endianess > 0 then--trace('[replace_objid_in_file] new id in raw: '||utl_raw.reverse(d2r(newobjid, 8)));--utl_file.put_raw(bfw, utl_raw.reverse(d2r(newobjid, 8)));nbody := utl_raw.concat(nbody, utl_raw.reverse(d2r(newobjid, 8)));else--trace('[replace_objid_in_file] new id in raw: '||(d2r(newobjid, 8)));--utl_file.put_raw(bfw, d2r(newobjid, 8));nbody := utl_raw.concat(nbody, d2r(newobjid, 8));end if;-- skip objidif addpos > hsz+5 and addinfo is not null thentrace('[replace_objid_in_file] old body len: '||utl_raw.length(dbody)||' new = 4 + '||utl_raw.length(utl_raw.substr(dbody, 5, addpos-hsz-5))||' + '||utl_raw.length(addinfo)||' + '||utl_raw.length(utl_raw.substr(dbody, addpos-hsz-4+utl_raw.length(addinfo), blksz-(addpos-1)-utl_raw.length(dtail)-utl_raw.length(addinfo)))||' + 4');--utl_file.put_raw(bfw, utl_raw.concat(utl_raw.substr(dbody, 5, addpos-hsz-5), addinfo, utl_raw.substr(dbody, addpos-hsz, blksz-(addpos-1)-utl_raw.length(dtail)-utl_raw.length(addinfo))));nbody := utl_raw.concat(nbody, utl_raw.substr(dbody, 5, addpos-hsz-5), addinfo, utl_raw.substr(dbody, addpos-hsz-4+utl_raw.length(addinfo), blksz-(addpos-1)-utl_raw.length(dtail)-utl_raw.length(addinfo)));--trace('[replace_objid_in_file] new body len: '||utl_raw.length(nbody));elsif addpos = hsz+5 and addinfo is not null then--utl_file.put_raw(bfw, utl_raw.concat(addinfo, utl_raw.substr(dbody, addpos-hsz, blksz-(addpos-1)-utl_raw.length(dtail)-utl_raw.length(addinfo))));nbody := utl_raw.concat(nbody, addinfo, utl_raw.substr(dbody, addpos-hsz, blksz-(addpos-1)-utl_raw.length(dtail)-utl_raw.length(addinfo)));else--utl_file.put_raw(bfw, utl_raw.substr(dbody, 5, blksz-hsz-4-utl_raw.length(dtail)));nbody := utl_raw.concat(nbody, utl_raw.substr(dbody, 5, blksz-hsz-4-utl_raw.length(dtail)));end if;--trace('[replace_objid_in_file] tail in raw: '||dtail||'('||utl_raw.length(dtail)||')');--utl_file.put_raw(bfw, dtail);nbody := utl_raw.concat(nbody, dtail);trace('[replace_objid_in_file] new body length: '||utl_raw.length(nbody));else--utl_file.put_raw(bfw, dhead);--utl_file.put_raw(bfw, dbody);nbody := utl_raw.concat(nbody, dhead, dbody);end if;--if utl_raw.length(nbody) != blksz then--  trace('[replace_objid_in_file] new body length: '||utl_raw.length(nbody));--end if;utl_file.put_raw(bfw, nbody);utl_file.fflush(bfw);exceptionwhen no_data_found thenexit;when others thentrace('[replace_objid_in_file] '||SQLERRM);trace('[replace_objid_in_file] '||dbms_utility.format_error_backtrace);exit;end;end loop;utl_file.fclose(bfw);utl_file.fclose(bfr);if not dstisfilesystem thencopy_file(p_tmpdir,p_tmpdstfile,dstdir,dstfile);remove_file(p_tmpdir,p_tmpdstfile);end if;trace('[replace_objid_in_file] completed.');end;function get_cols_no_lob( recowner varchar2, rectab varchar2)return varchar2ascols        varchar2(32767);colno       number := 0;begincols := '';for col_rec in (select column_name, data_type, nullable from dba_tab_cols where owner = recowner and table_name = rectab) loopif col_rec.data_type NOT LIKE '%LOB' thenif colno > 0 thencols := cols||',';end if;cols := cols||col_rec.column_name;colno := colno + 1;end if;end loop;return cols;end;function restore_table_row_no_lob(recowner varchar2, rectab varchar2, rstowner varchar2, rsttab varchar2,cols varchar2,rid rowid)return numberasrecnum      number := 0;beginbeginexecute immediate 'insert /*+*/ into '||rstowner||'.'||rsttab||'('||cols||') select '||cols||' from '||recowner||'.'||rectab||' where rowid = :rid' using rid;recnum := recnum + SQL%ROWCOUNT;exception when others thentrace('[restore_table_row_no_lob] '||SQLERRM);trace('[restore_table_row_no_lob] '||dbms_utility.format_error_backtrace);null;end;  return recnum;end;function restore_table_in_rows( recowner varchar2, rectab varchar2, rstowner varchar2, rsttab varchar2)return numberasrecnum      number := 0;blk_cur     r_cursor;objid       number;fid         number;blkno       number;rnum        number;gnum        number;cols        varchar2(32767);beginbegin--trace('[restore_table_in_rows] '||'select dbms_rowid.rowid_object(rowid) objid, dbms_rowid.rowid_relative_fno(rowid) fid, dbms_rowid.rowid_block_number(rowid) blkno, count(1) rnum from '||recowner||'.'||rectab||' group by dbms_rowid.rowid_object(rowid), dbms_rowid.rowid_relative_fno(rowid), dbms_rowid.rowid_block_number(rowid)');open blk_cur for 'select dbms_rowid.rowid_object(rowid) objid, dbms_rowid.rowid_relative_fno(rowid) fid, dbms_rowid.rowid_block_number(rowid) blkno, count(1) rnum from '||recowner||'.'||rectab||' group by dbms_rowid.rowid_object(rowid), dbms_rowid.rowid_relative_fno(rowid), dbms_rowid.rowid_block_number(rowid)';loopfetch blk_cur into objid, fid, blkno, rnum;exit when blk_cur%NOTFOUND;trace('[restore_table_in_rows] expected rows: '||rnum);gnum := 0;--trace('[restore_table_in_rows] block: '||blkno);for i in 1..rnum loopbegin--trace('[restore_table_in_rows] row: '||i);--execute immediate 'insert /*+*/into '||rstowner||'.'||rsttab||' select * from '||recowner||'.'||rectab||' where rowid = dbms_rowid.rowid_create(1, :objid, :fid, :blkno, :i)' using objid, fid, blkno, i-1;execute immediate 'insert /*+*/into '||rstowner||'.'||rsttab||' select * from '||recowner||'.'||rectab||' where dbms_rowid.rowid_relative_fno(ROWID)=:fid and dbms_rowid.rowid_block_number(ROWID)=:blkno and dbms_rowid.rowid_row_number(ROWID)=:i' using fid, blkno, i-1;recnum := recnum + SQL%ROWCOUNT;gnum := gnum + SQL%ROWCOUNT;exception when others thenif sqlcode = -22922 then-- trace('[restore_table_in_rows] Warning: Unrecoverable Lob found!');if cols is null thencols := get_cols_no_lob(recowner, rectab);end if;recnum := recnum + restore_table_row_no_lob(recowner, rectab, rstowner, rsttab, cols, dbms_rowid.rowid_create(1, objid, fid, blkno, i-1));elsetrace('[restore_table_in_rows] '||SQLERRM);trace('[restore_table_in_rows] '||dbms_utility.format_error_backtrace);end if;null;end;end loop;if gnum != rnum thenlog('Warning: '||(rnum-gnum)||' records lost!');end if;end loop;exception when others thentrace('[restore_table_in_rows] '||sqlerrm);trace('[restore_table_in_rows] '||dbms_utility.format_error_backtrace);null;end;  return recnum;end;function restore_table_in_rows_remote(recowner varchar2, rectab varchar2, rstowner varchar2, rsttab varchar2,dblink varchar2)return numberasrecnum      number := 0;blk_cur     r_cursor;objid       number;fid         number;blkno       number;rnum        number;cols        varchar2(32767);beginbegin--rollback;open blk_cur for 'select dbms_rowid.rowid_object(rowid) objid, dbms_rowid.rowid_relative_fno(rowid) fid, dbms_rowid.rowid_block_number(rowid) blkno, count(1) rnum from '||recowner||'.'||rectab||' group by dbms_rowid.rowid_object(rowid), dbms_rowid.rowid_relative_fno(rowid), dbms_rowid.rowid_block_number(rowid)';loopfetch blk_cur into objid, fid, blkno, rnum;exit when blk_cur%NOTFOUND;trace('[restore_table_in_rows_remote] expected rows: '||rnum);for i in 1..rnum loopbegin--execute immediate 'insert /*+no_append*/into '||rstowner||'.'||rsttab||' select * from '||recowner||'.'||rectab||'@'||dblink||' where rowid = dbms_rowid.rowid_create(1, :objid, :fid, :blkno, :i)' using objid, fid, blkno, i-1;execute immediate 'insert /*+*/into '||rstowner||'.'||rsttab||' select * from '||recowner||'.'||rectab||'@'||dblink||' where dbms_rowid.rowid_relative_fno(ROWID)=:fid and dbms_rowid.rowid_block_number(ROWID)=:blkno and dbms_rowid.rowid_row_number(ROWID)=:i' using fid, blkno, i-1;recnum := recnum + SQL%ROWCOUNT;--commit;exception when others thenif sqlcode = -22922 thenif cols is null thencols := get_cols_no_lob(recowner, rectab);end if;recnum := recnum + restore_table_row_no_lob(recowner, rectab, rstowner, rsttab, cols, dbms_rowid.rowid_create(1, objid, fid, blkno, i-1));elsetrace('[restore_table_in_rows_remote] '||SQLERRM);trace('[restore_table_in_rows_remote] '||dbms_utility.format_error_backtrace);--commit;end if;null;end;end loop;end loop;end;  return recnum;end;function restore_table_ctas(recowner varchar2, rectab varchar2, rstowner varchar2, rsttab varchar2)return numberasrecnum      number := 0;tmptab      varchar2(30);begintmptab := gen_table_name(rsttab, '', rstowner);beginexecute immediate 'create table '||rstowner||'.'||tmptab||' as select /*+full(t)*/* from '||recowner||'.'||rectab||' t';execute immediate 'insert /*+append*/ into '||rstowner||'.'||rsttab||' select /*+full(t)*/* from '||recowner||'.'||tmptab||' t';recnum := SQL%ROWCOUNT;execute immediate 'drop table '||rstowner||'.'||tmptab;exception when others then--trace('[restore_table_ctas] '||SQLERRM);--trace('[restore_table_ctas] '||dbms_utility.format_error_backtrace);null;end;  return recnum;end;function restore_table_no_lob(recowner varchar2, rectab varchar2, rstowner varchar2, rsttab varchar2)return numberasrecnum      number := 0;cols        varchar2(32767);begincols := get_cols_no_lob(recowner, rectab);begin--execute immediate 'alter system flush buffer_cache';execute immediate 'insert /*+append*/ into '||rstowner||'.'||rsttab||'('||cols||') select /*+full(t)*/'||cols||' from '||recowner||'.'||rectab||' t';recnum := recnum + SQL%ROWCOUNT;exception when others then--raise;if sqlcode = -22922 thennull;elserecnum := recnum + restore_table_in_rows(recowner, rectab, rstowner, rsttab);end if;end;trace('[restore_table_no_lob] '||recnum||' records recovered');return recnum;end;function restore_table( recowner varchar2, rectab varchar2, rstowner varchar2, rsttab varchar2,selflink varchar2 default '')return numberasrecnum      number := 0;expnum      number := 0;beginbegintrace('[restore_table] Trying to restore data to '||rstowner||'.'||rsttab);execute immediate 'alter system flush buffer_cache';if s_tracing thenexecute immediate 'select /*+full(t)*/count(*) from '||recowner||'.'||rectab||' t' into expnum;trace('[restore_table] Expected Records in this round: '||expnum);end if;execute immediate 'insert /*+append*/ into '||rstowner||'.'||rsttab||' select /*+full(t)*/* from '||recowner||'.'||rectab||' t';recnum := recnum + SQL%ROWCOUNT;if s_tracing and expnum != SQL%ROWCOUNT thentrace('[restore_table] '||(expnum-SQL%ROWCOUNT)||' records lost!');return -1; -- for testend if;exception when others then--raise;if sqlcode = -22922 thenlog('Warning: Unrecoverable Lob found!');recnum := recnum + restore_table_in_rows_remote(recowner, rectab, rstowner, rsttab, selflink);--recnum := recnum + restore_table_no_lob(recowner, rectab, rstowner, rsttab);elsetrace(SQLERRM);trace('[restore_table] '||dbms_utility.format_error_backtrace);--recnum := recnum + restore_table_in_rows_remote(recowner, rectab, rstowner, rsttab, selflink);--return -1; -- testrecnum := recnum + restore_table_in_rows(recowner, rectab, rstowner, rsttab);end if;end;execute immediate 'alter system flush buffer_cache';trace('[restore_table] '||recnum||' records recovered');return recnum;end;procedure get_seg_meta( segowner varchar2,segname varchar2,tmpdir varchar2,dtail out raw, addinfo out raw, blksz number default 8192)asfrw    raw(32767);firstblk  number;slash char(1);hdfile varchar2(255);hdfpath varchar2(4000);hdfdir varchar2(255) := 'TMP_HF_DIR'; finaldir varchar2(255);bfo    utl_file.file_type;i      number := 0;beginselect decode(instr(platform_name, 'Windows'),0,'/','\') into slash from v_$database where rownum<=1;select header_block+1 into firstblk from dba_segments where owner = segowner and segment_name = segname;select substr(file_name,instr(d.file_name, slash, -1)+1),substr(file_name,1,instr(d.file_name, slash, -1))into hdfile, hdfpathfrom dba_data_files d, dba_segments s where s.header_file = d.file_id and s.owner = segowner and s.segment_name = segname; --'trace('[get_seg_meta] '||hdfpath||hdfile);create_directory(hdfpath,hdfdir);-- copy ASM file to temp os folderif hdfpath like '+%' or hdfpath like '/dev/%' thencopy_file(hdfdir,hdfile,tmpdir,hdfile);finaldir := tmpdir;elsefinaldir := hdfdir;end if;bfo := utl_file.fopen(finaldir, hdfile, 'RB');-- reach to the truncated data blocksi := 0;while true loopbeginutl_file.get_raw(bfo, frw, blksz);i := i+1;exit when i = firstblk;exception when others thenexit;end;end loop;utl_file.get_raw(bfo, frw, blksz);dtail := utl_raw.substr(frw, blksz-3, 4);addinfo := utl_raw.substr(frw, 39, 2);utl_file.fclose(bfo);if hdfpath like '+%' or hdfpath like '/dev/%' thenremove_file(tmpdir,hdfile);end if;-- execute immediate 'drop directory '||hdfdir;end;function get_seg_data_id( segowner varchar2,segname varchar2,tmpdir varchar2, blksz number default 8192,endianess number default 1)return number                            asfrw    raw(32767);hsz    number := 28;firstblk  number;slash char(1);hdfile varchar2(255);hdfpath varchar2(4000);hdfdir varchar2(255) := 'TMP_HF_DIR';finaldir varchar2(255);bfo    utl_file.file_type;i      number := 0;objr   raw(4);objn   number;beginselect decode(instr(platform_name, 'Windows'),0,'/','\') into slash from v_$database where rownum<=1;select header_block+1 into firstblk from dba_segments where owner = segowner and segment_name = segname;select substr(file_name,instr(d.file_name, slash, -1)+1),substr(file_name,1,instr(d.file_name, slash, -1))into hdfile, hdfpathfrom dba_data_files d, dba_segments s where s.header_file = d.file_id and s.owner = segowner and s.segment_name = segname; --'trace('[get_seg_data_id] '||hdfpath||hdfile);create_directory(hdfpath,hdfdir);-- copy ASM file to temp os folderif hdfpath like '+%' or hdfpath like '/dev/%' thencopy_file(hdfdir,hdfile,tmpdir,hdfile);finaldir := tmpdir;elsefinaldir := hdfdir;end if;bfo := utl_file.fopen(finaldir, hdfile, 'RB');-- reach to the truncated data blocksi := 0;while true loopbeginutl_file.get_raw(bfo, frw, blksz);i := i+1;exit when i = firstblk;exception when others thenexit;end;end loop;utl_file.get_raw(bfo, frw, hsz);objr := utl_raw.substr(frw, 25, 4);if endianess > 0 thenobjn := to_number(rawtohex(utl_raw.reverse(objr)), 'XXXXXXXX');elseobjn := to_number(rawtohex(objr), 'XXXXXXXX');end if;utl_file.fclose(bfo);if hdfpath like '+%' or hdfpath like '/dev/%' thenremove_file(tmpdir,hdfile);end if;-- execute immediate 'drop directory '||hdfdir;return objn;end;/************************************************************************** Recover Table Data From Special Data File;**** oriobjid: Object Id of Table to be Recovered;** recowner: Owner of Table to be used as recovering dummy table;** rectable: Name of Table to be used as recovering dummy table;** rstowner: Owner of Table to store the recovered data;** rsttable: Name of Table to store the recovered data;** srcdir: Directory of the Data File to be recovered;** srcfile: Name of the Data File to be recovered;** srcisfilesystem: Is the source file located in file system or not;** tmpdir: Temp Directory to create restore tablespace and other temp files;** recfile: Name of Data File that rectable is stored;** coryfile: Name of Copy of Data File that rectable is stored;** blksz: Block size of the Tablespace Storing the Table to be recovered;** selflink: database link refer to instance self connect to dba account;************************************************************************/procedure recover_table(oriobjid number,recowner varchar2, rectab varchar2, rstowner varchar2, rsttab varchar2,srcdir varchar2,srcfile varchar2, srcisfilesystem boolean, tmpdir varchar2, recfile varchar2, copyfile varchar2, blksz number default 8192,fillblks number default 5,selflink varchar2 default '',endianess number default 1,recnum in out number,truncblks in out number)asp_tmpsrcfile varchar2(30);p_finalsrcdir varchar2(255);-- blk    blob;--vrw    raw(32767);frw    raw(32767);tsz    number := 4;hsz    number := 28;objr   raw(4);objn   number;dtail  raw(4);dhead  raw(32);dbody  raw(32767);--bfr    bfile;bfo    utl_file.file_type;bfr    utl_file.file_type;bfw    utl_file.file_type; fillednum number := 0;dummyheader number;dummyblks   number;blkstofill  number := fillblks;i           number := 0;j           number := 0;rstnum      number := 0;beginselect header_block+1, blocks-3 into dummyheader, dummyblks from dba_segments where owner = recowner and segment_name = rectab;if blkstofill > dummyblks thenblkstofill := dummyblks;end if;if not srcisfilesystem thenp_tmpsrcfile := gen_file_name(srcfile,'');copy_file(srcdir, srcfile,tmpdir,p_tmpsrcfile);p_finalsrcdir := tmpdir;elsep_tmpsrcfile := srcfile;p_finalsrcdir := srcdir;end if;bfo := utl_file.fopen(p_finalsrcdir, p_tmpsrcfile, 'RB');--utl_file.get_raw(bfo, dbody, blksz-hsz-tsz);--utl_file.get_raw(bfo, dtail, tsz);bfr := utl_file.fopen(tmpdir, copyfile, 'RB');bfw := utl_file.fopen(tmpdir, recfile, 'WB');-- reach to the transaction blocks to be filledi := 0;while true loopbeginutl_file.get_raw(bfr, frw, blksz);utl_file.put_raw(bfw, frw);i := i+1;exit when i=dummyheader+fillednum;exception when others then--raise;--trace('[recover_table] block NO.: '||i);exit;end;end loop;-- go through the data file of truncated tablewhile true loopbegin--trace('[recover_table] '||j);j := j+1;--objr := substrb(rawtohex(dhead), 49, 8);utl_file.get_raw(bfo, dhead, hsz);if hsz <= 24 thenutl_file.get_raw(bfo, dbody, blksz-tsz-hsz);--objr := substrb(rawtohex(dbody), 49-hsz*2, 8);objr := utl_raw.substr(dbody, 25-hsz, 4);else--objr := substrb(rawtohex(dhead), 49, 8);objr := utl_raw.substr(dhead, 25, 4);end if;if endianess > 0 then--objn := to_number(utl_raw.reverse(hextoraw(objr)), 'XXXXXXXX');objn := to_number(rawtohex(utl_raw.reverse(objr)), 'XXXXXXXX');else--objn := to_number(hextoraw(objr), 'XXXXXXXX');objn := to_number(rawtohex(objr), 'XXXXXXXX');end if;-- check if block belongs to truncated tableif objn != oriobjid or substrb(rawtohex(dhead), 1, 2) != '06' thenif hsz > 24 thenutl_file.get_raw(bfo, dbody, blksz-hsz);elseutl_file.get_raw(bfo, dtail, tsz);end if;else--trace('[recover_table] Find it.');truncblks := truncblks + 1;if hsz > 24 thenutl_file.get_raw(bfo, dbody, blksz-hsz-tsz);end if;utl_file.get_raw(bfo, dtail, tsz);if not utl_file.is_open(bfr) thenbfr := utl_file.fopen(tmpdir, copyfile, 'RB');end if;if not utl_file.is_open(bfw) thenbfw := utl_file.fopen(tmpdir, recfile, 'WB');end if;-- filling the trans blockutl_file.get_raw(bfr, dhead, hsz);utl_file.put_raw(bfw, dhead); -- put original headerutl_file.put_raw(bfw, dbody); -- replace bodyutl_file.get_raw(bfr, dbody, blksz-hsz-tsz); -- forward pointer in original file copyutl_file.get_raw(bfr, dtail, tsz); -- get original tailutl_file.put_raw(bfw, dtail); -- put original tailfillednum := fillednum+1;i := i+1;-- no trans data block left, copy recovered data to backup table and fill the left blocksif fillednum >= blkstofill then--if fillednum+blkstofill-1 >= dummyblks thenbeginwhile true loopbeginutl_file.get_raw(bfr, frw, blksz);utl_file.put_raw(bfw, frw);i := i+1;exception when others thenif utl_file.is_open(bfr) thenutl_file.fclose(bfr);end if;if utl_file.is_open(bfw) thenutl_file.fclose(bfw);end if;exit;end;end loop;rstnum := restore_table(recowner, rectab, rstowner, rsttab, selflink);-- for testexit when rstnum < 0;recnum := recnum+rstnum;fillednum := 0;commit;bfr := utl_file.fopen(tmpdir, copyfile, 'RB');bfw := utl_file.fopen(tmpdir, recfile, 'WB');-- go to the transaction blocks againi := 0;while true loopbeginutl_file.get_raw(bfr, frw, blksz);utl_file.put_raw(bfw, frw);i := i+1;exit when i=dummyheader+fillednum;exception when others then--raise;--trace('[recover_table] block NO.: '||i);exit;end;end loop;utl_file.fflush(bfw);exception when others thentrace('[recover_table 2-1] '||sqlerrm);trace('[recover_table 2-1] '||dbms_utility.format_error_backtrace);null;end;end if;end if;exception when no_data_found thenexit;when others thentrace('[recover_table 2-2] '||sqlerrm);trace('[recover_table 2-2] '||dbms_utility.format_error_backtrace);exit;end;end loop;-- last blocks not full filled dummy table--if fillednum+blkstofill-1 < dummyblks thenif fillednum < blkstofill and rstnum>=0 thenbeginwhile true loopbeginutl_file.get_raw(bfr, frw, blksz);utl_file.put_raw(bfw, frw);i := i+1;exception when others thenif utl_file.is_open(bfr) thenutl_file.fclose(bfr);end if;if utl_file.is_open(bfw) thenutl_file.fclose(bfw);end if;exit;end;end loop;recnum := recnum+restore_table(recowner, rectab, rstowner, rsttab, selflink);--fillednum := 0;commit;end;end if;if utl_file.is_open(bfr) thenutl_file.fclose(bfr);end if;if utl_file.is_open(bfw) thenutl_file.fclose(bfw);end if;if utl_file.is_open(bfo) thenutl_file.fclose(bfo);end if;utl_file.fclose_all();log(truncblks||' truncated data blocks found. ');log(recnum||' records recovered in backup table '||rstowner||'.'||rsttab);if not srcisfilesystem thenremove_file(tmpdir,p_tmpsrcfile);end if;end;/************************************************************************** Recover Table Data From Data Files of Targe Table;**** tgtowner: Owner of Target Table to be recovered;** tgttable: Name of Target Table to be recovered;** recowner: Owner of Table to be used as recovering dummy table;** rectable: Name of Table to be used as recovering dummy table;** rstowner: Owner of Table to store the recovered data;** rsttable: Name of Table to store the recovered data;** tmpdir: Temp Directory to create restore tablespace and other temp files;** srcfile: Name of the Data File to be recovered;** recfile: Name of Data File that rectable is stored;** copydir: Directory of Copy of Data File that rectable is stored;** coryfile: Name of Copy of Data File that rectable is stored;** blksz: Block size of the Tablespace Storing the Table to be recovered;** selflink: database link refer to instance self connect to dba account;************************************************************************/procedure recover_table(tgtowner varchar2,tgttable varchar2,recowner varchar2, rectab varchar2, rstowner varchar2, rsttab varchar2, tmpdir varchar2, recfile varchar2, copyfile varchar2, blksz number default 8192,fillblks number default 5,selflink varchar2 default '',offline_files varchar2 default null)astgtobjid    number;recobjid    number;endianess   number;slash       char(1);filedir     varchar2(255) := 'TMP_DATA_FILE_DIR';tmpcopyf    varchar2(256);tsname      varchar2(30);readprop    varchar2(30);dtail       raw(4);addinfo     raw(32);recnum      number := 0;truncblks   number := 0;trecnum     number := 0;ttruncblks  number := 0;beginexecute immediate 'truncate table '||rstowner||'.'||rsttab;execute immediate 'alter system set db_block_checking=false scope=memory';execute immediate 'alter system set db_block_checksum=false scope=memory';execute immediate 'alter system set "_db_block_check_objtyp"=false scope=memory';execute immediate 'alter session set events ''10231 trace name context forever, level 10''';execute immediate 'alter session set events ''10233 trace name context forever, level 10''';select instr(platform_name, 'Windows'), decode(instr(platform_name, 'Windows'),0,'/','\') into endianess, slash from v_$database where rownum<=1;select data_object_id into recobjid from dba_objects where owner = recowner and object_name = rectab and object_type='TABLE' and rownum<=1;log('begin to recover table '||tgtowner||'.'||tgttable);tgtobjid := get_seg_data_id(tgtowner, tgttable, tmpdir, blksz, endianess);if offline_files is not null thenfor file_rec in (with target_string as (select /*+inline*/offline_files str, ';' spliter from dual),files as (select trim(regexp_substr(str, '[^'||spliter||']+', 1, level)) file_name  from target_stringconnect by level <= length (regexp_replace (str, '[^'||spliter||']+'))  + 1)select substr(file_name,instr(file_name, slash, -1)+1) as filename,substr(file_name,1,instr(file_name, slash, -1)) as filepath from fileswhere file_name is not null) loop --'beginlog('Recovering data in datafile '||file_rec.filepath||file_rec.filename);recnum := 0;truncblks := 0;create_directory(file_rec.filepath,filedir);recover_table(tgtobjid, recowner, rectab, rstowner, rsttab, filedir, file_rec.filename, (file_rec.filepath not like '+%' and file_rec.filepath not like '/dev/%'), tmpdir, recfile, copyfile, blksz, fillblks, selflink, endianess, recnum, truncblks);-- execute immediate 'drop directory '||filedir;trecnum := trecnum + recnum;ttruncblks := ttruncblks + truncblks;exception when others thentrace('[recover_table 1] '||sqlerrm);trace('[recover_table 1] '||dbms_utility.format_error_backtrace);end;end loop;elseif s_repobjid thenget_seg_meta(recowner, rectab, tmpdir, dtail, addinfo, blksz);select tablespace_name into tsname from dba_tables where owner = tgtowner and table_name = tgttable and rownum<=1;select STATUS into readprop from dba_tablespaces where tablespace_name = tsname;if readprop != 'READ ONLY' thenexecute immediate 'alter tablespace '||tsname||' read only';execute immediate 'alter system flush buffer_cache';end if;--for file_rec in (select substr(file_name,decode(instr(d.file_name, '\', -1), 0, instr(file_name, '/', -1), instr(file_name, '\', -1))+1) as filename,--                        substr(file_name,1,decode(instr(d.file_name, '\', -1), 0, instr(file_name, '/', -1), instr(file_name, '\', -1))) as filepath  --                   from dba_data_files d, dba_tables t --                   where d.tablespace_name = t.tablespace_name and t.owner = tgtowner and t.table_name = tgttable) loop --'for file_rec in (select substr(file_name,instr(d.file_name, slash, -1)+1) as filename,substr(file_name,1,instr(d.file_name, slash, -1)) as filepath  from dba_data_files d, dba_tables t where d.tablespace_name = t.tablespace_name and t.owner = tgtowner and t.table_name = tgttable) loop --'beginlog('Recovering data in datafile '||file_rec.filepath||file_rec.filename);recnum := 0;truncblks := 0;create_directory(file_rec.filepath,filedir);tmpcopyf := gen_file_name(file_rec.filename, '');copy_file(filedir, file_rec.filename, tmpdir, tmpcopyf);--replace_segmeta_in_file(srcdir, tmpcopyf, srcdir, file_rec.filename, tgtobjid, recobjid, dtail, 39, addinfo, blksz, endianess);replace_segmeta_in_file(tmpdir, tmpcopyf, filedir, file_rec.filename, (file_rec.filepath not like '+%' and file_rec.filepath not like '/dev/%'), tgtobjid, recobjid, dtail, 39, '', blksz, endianess);recover_table(recobjid, recowner, rectab, rstowner, rsttab, filedir, file_rec.filename, (file_rec.filepath not like '+%' and file_rec.filepath not like '/dev/%'), tmpdir, recfile, copyfile, blksz, fillblks, selflink, endianess, recnum, truncblks);--recover_table(tgtobjid, recowner, rectab, rstowner, rsttab, srcdir, file_rec.filename, recdir, recfile, copydir, copyfile, blksz, fillblks, selflink, endianess);copy_file(tmpdir, tmpcopyf, filedir, file_rec.filename);remove_file(tmpdir, tmpcopyf);-- execute immediate 'drop directory '||filedir;trecnum := trecnum + recnum;ttruncblks := ttruncblks + truncblks;trace('[recover_table 1] '||tmpcopyf||' removed.');exception when others thentrace('[recover_table 1] '||sqlerrm);trace('[recover_table 1] '||dbms_utility.format_error_backtrace);end;end loop;if readprop != 'READ ONLY' thenexecute immediate 'alter tablespace '||tsname||' read write';end if;elsefor file_rec in (select substr(file_name,instr(d.file_name, slash, -1)+1) as filename,substr(file_name,1,instr(d.file_name, slash, -1)) as filepath  from dba_data_files d, dba_tables t where d.tablespace_name = t.tablespace_name and t.owner = tgtowner and t.table_name = tgttable) loop --'beginlog('Recovering data in datafile '||file_rec.filepath||file_rec.filename);recnum := 0;truncblks := 0;create_directory(file_rec.filepath,filedir);recover_table(tgtobjid, recowner, rectab, rstowner, rsttab, filedir, file_rec.filename, (file_rec.filepath not like '+%' and file_rec.filepath not like '/dev/%'), tmpdir, recfile, copyfile, blksz, fillblks, selflink, endianess, recnum, truncblks);-- execute immediate 'drop directory '||filedir;trecnum := trecnum + recnum;ttruncblks := ttruncblks + truncblks;exception when others thentrace('[recover_table 1] '||sqlerrm);trace('[recover_table 1] '||dbms_utility.format_error_backtrace);end;end loop;end if;end if;log('Total: '||ttruncblks||' truncated data blocks found. ');log('Total: '||trecnum||' records recovered in backup table '||rstowner||'.'||rsttab);execute immediate 'alter session set events ''10233 trace name context off''';execute immediate 'alter session set events ''10231 trace name context off''';execute immediate 'alter system set "_db_block_check_objtyp"=true scope=memory';execute immediate 'alter system set db_block_checksum=true scope=memory';execute immediate 'alter system set db_block_checking=true scope=memory';log('Recovery completed.');end;/************************************************************************** Prepare the data files to be use during recovering;**** tgtowner: Owner of Target Table to be recovered;** tgttable: Name of Target Table to be recovered;** datapath: Absolute path of Data Files;** datadir: Directory to be created referring to datapath;** rects: Tablespace to store the recovering dummy table;** recfile: Name of Data File to store the recovering dummy table;** rstts: Tablespace to store table storing the recovered data;** rstfile: Name of Data File to store restoring table;** blksz: Block size of the Tablespace Storing the Table to be recovered;** rectsblks: block number of recovery tablespace** rectsblks: block number of restore tablespace************************************************************************/procedure prepare_files(tgtowner varchar2,tgttable varchar2,tmppath varchar2,rects out varchar2, recfile out varchar2, rstts out varchar2, rstfile out varchar2, blksz out varchar2,rectsblks number default 16,rsttsblks number default 2560)asext_mgmt   varchar2(30);ss_mgmt    varchar2(30);slash      char(1);beginselect decode(instr(platform_name, 'Windows'),0,'/','\') into slash from v_$database where rownum<=1;select block_size, extent_management, segment_space_management into blksz, ext_mgmt, ss_mgmt from dba_tablespaces ts, dba_tables t where t.tablespace_name = ts.tablespace_name and t.owner = upper(tgtowner) and t.table_name = upper(tgttable);--select 'FY_REC_DATA'||surfix into rects from (select surfix from (select null surfix from dual union all select level surfix from dual connect by level <= 255) where not exists (select 1 from dba_tablespaces where tablespace_name = 'FY_REC_DATA'||surfix) order by surfix nulls first) where rownum<=1;--select 'FY_REC_DATA'||surfix||'.DAT' into recfile from (select surfix from (select null surfix from dual union all select level surfix from dual connect by level <= 255) where not exists (select 1 from dba_data_files where file_name like '%\FY_REC_DATA'||surfix||'.DAT') order by surfix nulls first) where rownum<=1;rects := gen_ts_name('FY_REC_DATA','');recfile := gen_file_name('FY_REC_DATA','');log('Recover Tablespace: '||rects||'; Data File: '||recfile);execute immediate 'create tablespace '||rects||' datafile '''||rtrim(tmppath, slash)||slash||recfile||''' size '||to_char(blksz*rectsblks/1024)||'K autoextend off extent management '||ext_mgmt||' SEGMENT SPACE MANAGEMENT '||ss_mgmt; --'--select 'FY_RST_DATA'||surfix into rstts from (select surfix from (select null surfix from dual union all select level surfix from dual connect by level <= 255) where not exists (select 1 from dba_tablespaces where tablespace_name = 'FY_REST_DATA'||surfix) order by surfix nulls first) where rownum<=1;--select 'FY_RST_DATA'||surfix||'.DAT' into rstfile from (select surfix from (select null surfix from dual union all select level surfix from dual connect by level <= 255) where not exists (select 1 from dba_data_files where file_name like '%\FY_REST_DATA'||surfix||'.DAT') order by surfix nulls first) where rownum<=1;rstts := gen_ts_name('FY_RST_DATA','');rstfile := gen_file_name('FY_RST_DATA','');log('Restore Tablespace: '||rstts||'; Data File: '||rstfile);execute immediate 'create tablespace '||rstts||' datafile '''||rtrim(tmppath, slash)||slash||rstfile||''' size '||to_char(blksz*rsttsblks/1024)||'K autoextend on extent management '||ext_mgmt||' SEGMENT SPACE MANAGEMENT '||ss_mgmt; --'end;/************************************************************************** Clean up existing Recover and Restore Tablespace. Drop tables in the tablespaces**** rects: Recover tablespace name** rects: Restore tablespace name, default NULL, will not do cleaning up;************************************************************************/procedure clean_up_ts(rects varchar2, rstts varchar2 default null)asreadprop varchar2(30);beginselect STATUS into readprop from dba_tablespaces where tablespace_name = rects;if readprop = 'READ ONLY' thenexecute immediate 'alter tablespace '||rects||' read write';end if;for tab_rec in (select owner, table_name from dba_tables where tablespace_name = rects) loopexecute immediate 'drop table '||tab_rec.owner||'.'||tab_rec.table_name;end loop;if rstts is not null thenfor tab_rec in (select owner, table_name from dba_tables where tablespace_name = rstts) loopexecute immediate 'drop table '||tab_rec.owner||'.'||tab_rec.table_name;end loop;end if;end;/************************************************************************** Fill Blocks of Recovering Table, to format the blocks;**** tgtowner: Owner of Target Table to be recovered;** tgttable: Name of Target Table to be recovered;** tmpdir: Temp Directory to be used to create the restore tablespace and files;** rects: Tablespace to store the recovering dummy table;** recfile: Name of Data File to store the recovering dummy table;** rstts: Tablespace to store table storing the recovered data;** blks: Number blocks in Initial Extent of the recovering dummy table;** recowner: Owner of Table to be used as recovering dummy table;** rstowner: Owner of Table to store the recovered data;** rectable: Name of Table to be used as recovering dummy table;** rsttable: Name of Table to store the recovered data;** coryfile: Name of Copy of Data File that rectable is stored;************************************************************************/procedure fill_blocks(tgtowner varchar2,tgttable varchar2,tmpdir varchar2, rects varchar2,recfile varchar2,rstts varchar2,blks number default 8,recowner varchar2 default user,rstowner varchar2 default user,rectab in out varchar2,rsttab in out varchar2,copyfile out varchar2)asblksz  number;blkno  number;cols   varchar2(32767);vals   varchar2(32767);colno  number := 0;beginif rectab is null thenselect block_size into blksz from dba_tablespaces ts, dba_tables t where t.tablespace_name = ts.tablespace_name and t.owner = upper(tgtowner) and t.table_name = upper(tgttable);-- select upper(tgttable||'$'||surfix) into rectab from (select surfix from (select null surfix from dual union all select level surfix from dual connect by level <= 255) where not exists (select 1 from dba_tables where owner = recowner and table_name = upper(tgttable||'$'||surfix)) order by surfix nulls first) where rownum<=1;rectab := gen_table_name(tgttable, '$', recowner);log('Recover Table: '||recowner||'.'||rectab);--trace('[fill_blocks] create table '||recowner||'.'||rectab||' tablespace '||rects||' storage(initial '||to_char(blks*blksz/1024)||'K) as select * from '||tgtowner||'.'||tgttable||' where 1=2');execute immediate 'create table '||recowner||'.'||rectab||' tablespace '||rects||' storage(initial '||to_char(blks*blksz/1024)||'K) as select * from '||tgtowner||'.'||tgttable||' where 1=2';else--execute immediate 'truncate table '||recowner||'.'||rectab;execute immediate 'delete from '||recowner||'.'||rectab;commit;end if;cols := '';vals := '';for col_rec in (select column_name, data_type, nullable from dba_tab_cols where owner = recowner and table_name = rectab) loopif col_rec.nullable = 'N' thenexecute immediate 'alter table '||recowner||'.'||rectab||' modify '||col_rec.column_name||' null';end if;if colno < 6 thenif col_rec.data_type like '%CHAR%' or col_rec.data_type like '%RAW%' thenif colno > 0 thencols := cols||',';vals := vals||',';end if;cols := cols||col_rec.column_name;vals := vals||'''A''';colno := colno + 1;elsif col_rec.data_type like '%NUMBER%' or col_rec.data_type = 'FLOAT' thenif colno > 0 thencols := cols||',';vals := vals||',';end if;cols := cols||col_rec.column_name;vals := vals||'0';colno := colno + 1;elsif col_rec.data_type LIKE '%TIMESTAMP%' or col_rec.data_type = 'DATE' thenif colno > 0 thencols := cols||',';vals := vals||',';end if;cols := cols||col_rec.column_name;vals := vals||'sysdate';colno := colno + 1;end if;end if;end loop;--select upper(tgttable||'$$'||surfix) into rsttab from (select surfix from (select null surfix from dual union all select level surfix from dual connect by level <= 255) where not exists (select 1 from dba_tables where owner = rstowner and table_name = upper(tgttable||'$$'||surfix)) order by surfix nulls first) where rownum<=1;if rsttab is null thenrsttab := gen_table_name(tgttable, '$$', rstowner);log('Restore Table: '||rstowner||'.'||rsttab);execute immediate 'create table '||rstowner||'.'||rsttab||' tablespace '||rstts||' as select * from '||recowner||'.'||rectab||' where 1=2';elseexecute immediate 'truncate table '||rstowner||'.'||rsttab;end if;--trace('[fill_blocks] insert into '||recowner||'.'||rectab||'('||cols||') values ('||vals||')');while true loopexecute immediate 'insert into '||recowner||'.'||rectab||'('||cols||') values ('||vals||')';execute immediate 'select count(unique(dbms_rowid.rowid_block_number( rowid ))) from '||recowner||'.'||rectab into blkno ;exit when blkno >= blks-3;end loop;commit;execute immediate 'alter system flush buffer_cache';execute immediate 'delete from '||recowner||'.'||rectab;commit;execute immediate 'alter system flush buffer_cache';trace('[fill_blocks] Data Blocks formatted.');execute immediate 'alter tablespace '||rects||' read only';select 'FY_REC_DATA_COPY'||surfix||'.DAT' into copyfile from (select surfix from (select null surfix from dual union all select level surfix from dual connect by level <= 255) where not exists (select 1 from dba_data_files where file_name like '%FY_REC_DATA_COPY'||surfix||'.DAT') order by surfix nulls first) where rownum<=1;copy_file(tmpdir, recfile, tmpdir, copyfile);log('Copy file of Recover Tablespace: '||copyfile);end;/************************************************************************** Create recovery table on new file of truncated table's tablespace;**** tgtowner: Owner of Target Table to be recovered;** tgttable: Name of Target Table to be recovered;** datadir: Directory to be created referring to datapath;** rects: Tablespace to store the recovering dummy table;** recfid: ID of Data File to store the recovering dummy table;** recfile: Name of Data File to store the recovering dummy table;** rectable: Name of Table to be used as recovering dummy table;** blks: Number blocks in Initial Extent of the recovering dummy table;** rectsblks: block number of recovery tablespace************************************************************************/procedure create_rectab_on_tgttab_ts( tgtowner varchar2,tgttable varchar2,datadir varchar2, recowner varchar2 default user,rects out varchar2,recfid in out number,recfile out varchar2,rectab out varchar2,blks number default 8,rectsblks number default 16)asblksz  number;tsid   number;tsonline number;datapath varchar2(32767);r_files r_cursor;filelist t_fileprops;tn     number;beginselect ts.ts#, ts.name, ts.online$, blocksize into tsid, rects, tsonline, blksz from sys.ts$ ts, dba_tables t where t.tablespace_name = ts.name and t.owner = upper(tgtowner) and t.table_name = upper(tgttable);if tsonline = 4 thenexecute immediate 'alter tablespace '||rects||' read write';end if;if recfid is null thenopen r_files for select file#,status$ bulk from sys.file$ where ts#=tsid;fetch r_files bulk collect into filelist;recfile := gen_file_name('FY_REC_DATA','');select rtrim(directory_path, '\')||'\' into datapath from dba_directories where directory_name = datadir; --'execute immediate 'alter tablespace '||rects||' add datafile '''||datapath||recfile||''' size '||to_char(rectsblks*blksz/1024)||'K';select file_id into recfid from dba_data_files where tablespace_name = rects and (file_name like '%\'||recfile or file_name like '%/'||recfile); --'elseopen r_files for select file#,status$ bulk from sys.file$ where ts#=tsid and file#!=recfid;fetch r_files bulk collect into filelist;trace('[create_rectab_on_tgttab_ts] file id: '||recfid);select decode(instr(file_name, '/', -1), 0, substr(file_name,instr(file_name, '\', -1)+1), substr(file_name,instr(file_name, '/', -1)+1)) into recfile from dba_data_files where file_id = recfid; --'end if;log('Recover Tablespace: '||recfile||'('||recfid||')');for i in 1..filelist.count loopupdate sys.file$ f set status$=1 where ts#=tsid and file# = filelist(i).file#;end loop;commit;execute immediate 'alter system flush buffer_cache';--select file# into tn from sys.file$ where ts#=tsid and status$=2;--trace('[create_rectab_on_tgttab_ts] inactive files: '||filelist.count);--trace('[create_rectab_on_tgttab_ts] active file id: '||tn);rectab := gen_table_name(tgttable, '$', recowner);log('Recover Table: '||recowner||'.'||rectab);--dbms_lock.sleep(3);execute immediate 'create table '||recowner||'.'||rectab||' tablespace '||rects||' storage(initial '||to_char(blks*blksz/1024)||'K) as select * from '||tgtowner||'.'||tgttable||' where 1=2';select header_file  into tn from dba_segments where owner = recowner and segment_name = rectab;trace('[create_rectab_on_tgttab_ts] header file: '||filelist.count);for i in 1..filelist.count loopupdate sys.file$ f set status$=filelist(i).status$ where ts#=tsid and file# = filelist(i).file#;end loop;commit;execute immediate 'alter system flush buffer_cache';end;procedure replace_segraw_in_file( srcdir varchar2, srcfile varchar2, dstdir varchar2, dstfile varchar2,blknum number,startpos number,repcont raw,blksz number default 8192)asbfr    utl_file.file_type;bfw    utl_file.file_type; dbody  raw(32767);i      number;p_srcdir varchar2(255) := srcdir;p_srcfile varchar2(255) := srcfile;p_dstdir varchar2(255) := dstdir;p_dstfile varchar2(255) := dstfile;beginif p_dstdir is null thenp_dstdir := p_srcdir;end if;trace('[replace_segraw_in_file] replace block id: '||blknum||' start: '||startpos||' content: '||repcont);bfr := utl_file.fopen(p_srcdir, p_srcfile, 'RB');bfw := utl_file.fopen(p_dstdir, p_dstfile, 'WB');i := 0;while true loopbeginutl_file.get_raw(bfr, dbody, blksz);utl_file.put_raw(bfw, dbody);i := i+1;exit when i = blknum-1;exception when others thenexit;end;end loop;utl_file.get_raw(bfr, dbody, blksz);if startpos<=1 thenutl_file.put_raw(bfw, utl_raw.concat(repcont, utl_raw.substr(dbody, 1+utl_raw.length(repcont))));elseutl_file.put_raw(bfw, utl_raw.concat(utl_raw.substr(dbody, 1, startpos-1), repcont, utl_raw.substr(dbody, startpos+utl_raw.length(repcont))));end if;while true loopbeginutl_file.get_raw(bfr, dbody, blksz);utl_file.put_raw(bfw, dbody);exceptionwhen no_data_found thenexit;when others thentrace('[replace_segraw_in_file] '||SQLERRM);trace('[replace_segraw_in_file] '||dbms_utility.format_error_backtrace);exit;end;end loop;utl_file.fclose(bfw);utl_file.fclose(bfr);trace('[replace_segraw_in_file] completed.');end;procedure dump_seg_block_raw( hdfile varchar2,srcdir varchar2, blknb number,blksz number default 8192)asfrw    raw(32767);bfo    utl_file.file_type;bfw    utl_file.file_type;i      number := 0;beginbfo := utl_file.fopen(srcdir, hdfile, 'RB');bfw := utl_file.fopen(srcdir, hdfile||'_'||blknb||'.BLK', 'WB');-- reach to the truncated data blocksi := 0;while true loopbeginutl_file.get_raw(bfo, frw, blksz);i := i+1;exit when i = blknb;exception when others thenexit;end;end loop;utl_file.get_raw(bfo, frw, blksz);utl_file.put_raw(bfw, frw);utl_file.fclose(bfo);utl_file.fclose(bfw);end;
/*------------------------------------------------------------------------------------------procedure test_chain(filename varchar2, blknum number, startpos number,repcont raw,srcdir varchar2 default 'FY_DATA_DIR')astmpcopyf varchar2(256);beginexecute immediate 'alter system set db_block_checking=false scope=memory';execute immediate 'alter system set db_block_checksum=false scope=memory';execute immediate 'alter system set "_db_block_check_objtyp"=false scope=memory';execute immediate 'alter session set events ''10231 trace name context forever, level 10''';execute immediate 'alter session set events ''10233 trace name context forever, level 10''';begintmpcopyf := gen_file_name(filename, '$');trace('[test_chain] bakcup file '||tmpcopyf);copy_file(srcdir, filename, srcdir, tmpcopyf);replace_segraw_in_file(srcdir, tmpcopyf, srcdir, filename, blknum, startpos, repcont, 8192);execute immediate 'alter system flush buffer_cache';for rec in (select * from t_chain where rowid='AABFUoAAHAAAABFAAA') loopnull;end loop;trace('[test_chain] table query completed');exception when others thentrace('[test_chain] '||sqlerrm);trace('[test_chain] '||dbms_utility.format_error_backtrace);end;copy_file(srcdir, tmpcopyf, srcdir, filename);remove_file(srcdir, tmpcopyf);trace('[test_chain] '||tmpcopyf||' removed.');execute immediate 'alter system set db_block_checking=true scope=memory';execute immediate 'alter system set db_block_checksum=true scope=memory';execute immediate 'alter system set "_db_block_check_objtyp"=true scope=memory';execute immediate 'alter session set events ''10231 trace name context off''';execute immediate 'alter session set events ''10233 trace name context off''';exception when others thentrace('[test_chain] '||sqlerrm);trace('[test_chain] '||dbms_utility.format_error_backtrace);end;
------------------------------------------------------------------------------------------*/procedure test_rec1( tow varchar2 default 'DEMO', ttb varchar2 default 'T_CHAIN',fbks number default 1, tmppath varchar2 default '/tmp/') --'astgtowner varchar2(30):= upper(tow);tgttable varchar2(30):= upper(ttb);tmpdir varchar2(30);rects varchar2(30);recfile varchar2(30); rstts varchar2(30);rstfile varchar2(30);blksz number;rectab varchar2(30);rsttab varchar2(30);copyfile varchar2(30);begintmpdir := 'FY_DATA_DIR';create_directory(tmppath, tmpdir);prepare_files(tgtowner, tgttable, tmpdir, rects, recfile, rstts, rstfile, blksz);rects := 'FY_REC_DATA';rstts := 'FY_RST_DATA';recfile := 'FY_REC_DATA.DAT';fill_blocks(tgtowner, tgttable, tmpdir, rects, recfile, rstts, 8, tgtowner, tgtowner, rectab, rsttab, copyfile);recover_table(tgtowner, tgttable, tgtowner, rectab, tgtowner, rsttab, tmpdir, recfile, copyfile, blksz, fbks, 'myself');-- execute immediate 'drop directory '||tmpdir;end;procedure test_rec2( tow varchar2 default 'DEMO', ttb varchar2 default 'T_CHAIN',fbks number default 1)astgtowner varchar2(30):= upper(tow);tgttable varchar2(30):= upper(ttb);tmpdir varchar2(30);rects varchar2(30);recfile varchar2(30); rstts varchar2(30);blksz number;rectab varchar2(30);rsttab varchar2(30);copyfile varchar2(30);begintmpdir := 'FY_DATA_DIR';rects := 'FY_REC_DATA';rstts := 'FY_RST_DATA';recfile := 'FY_REC_DATA.DAT';clean_up_ts(rects, rstts);select block_size into blksz from dba_tablespaces ts, dba_tables t where ts.tablespace_name = t.tablespace_name and t.owner = tgtowner and t.table_name = tgttable;fill_blocks(tgtowner, tgttable, tmpdir, rects, recfile, rstts, 8, tgtowner, tgtowner, rectab, rsttab, copyfile);recover_table(tgtowner, tgttable, tgtowner, rectab, tgtowner, rsttab, tmpdir, recfile, copyfile, blksz, fbks, 'myself');-- execute immediate 'drop directory '||tmpdir;end;procedure test_rec3( tow varchar2 default 'DEMO', ttb varchar2 default 'T_CHAIN',fbks number default 1,fid number default null)astgtowner varchar2(30):= upper(tow);tgttable varchar2(30):= upper(ttb);tmpdir varchar2(30);rects varchar2(30);recfile varchar2(30); rstts varchar2(30);blksz number;rectab varchar2(30);rsttab varchar2(30);copyfile varchar2(30);recfid number:= fid;begintmpdir := 'FY_DATA_DIR';rstts := 'FY_RST_DATA';--begin--  execute immediate 'drop table '||tgtowner||'.'||tgttable||'$';--  execute immediate 'drop table '||tgtowner||'.'||tgttable||'$$';--exception when others then--  null;--end;create_rectab_on_tgttab_ts(tgtowner, tgttable, tmpdir, tgtowner, rects, recfid, recfile, rectab, 8, 16);select block_size into blksz from dba_tablespaces ts, dba_tables t where ts.tablespace_name = t.tablespace_name and t.owner = tgtowner and t.table_name = tgttable;fill_blocks(tgtowner, tgttable, tmpdir, rects, recfile, rstts, 8, tgtowner, tgtowner, rectab, rsttab, copyfile);recover_table(tgtowner, tgttable, tgtowner, rectab, tgtowner, rsttab, tmpdir, recfile, copyfile, blksz, fbks, 'myself');-- execute immediate 'drop directory '||tmpdir;begin--execute immediate 'drop table '||tgtowner||'.'||rectab;--execute immediate 'alter tablespace '||rects||' drop datafile '||recfid;--exception when others thennull;end;end;procedure recover_truncated_table( tow varchar2, ttb varchar2,fbks number default 1, tmppath varchar2 default null,offline_files varchar2 default null) --'astgtowner varchar2(30):= upper(tow);tgttable varchar2(30):= upper(ttb);tmpdir varchar2(30);rects varchar2(30);recfile varchar2(30); rstts varchar2(30);rstfile varchar2(30);blksz number;rectab varchar2(30);rsttab varchar2(30);copyfile varchar2(30);fy_ts_cnt number:= 0;endianess pls_integer;temppath varchar2(32767):=tmppath;beginselect instr(platform_name, 'Windows') into endianess from v_$database where rownum<=1;if temppath is null thenif endianess > 0 thentemppath:='c:\temp\';elsetemppath:='/tmp/';end if;end if;dbms_output.enable(999999);tmpdir := 'FY_DATA_DIR';rects := 'FY_REC_DATA';rstts := 'FY_RST_DATA';recfile := 'FY_REC_DATA.DAT';create_directory(temppath, tmpdir);select count(*) into fy_ts_cnt from dba_tablespaces where tablespace_name in (rects,rstts);if fy_ts_cnt = 2 thenclean_up_ts(rects, rstts);select substr(file_name,decode(instr(file_name, '\', -1), 0, instr(file_name, '/', -1), instr(file_name, '\', -1))+1)into recfilefrom dba_data_fileswhere tablespace_name = rectsand rownum<=1;elseprepare_files(tgtowner, tgttable, temppath, rects, recfile, rstts, rstfile, blksz);end if;select block_size into blksz from dba_tablespaces ts, dba_tables t where ts.tablespace_name = t.tablespace_name and t.owner = tgtowner and t.table_name = tgttable;fill_blocks(tgtowner, tgttable, tmpdir, rects, recfile, rstts, 8, tgtowner, tgtowner, rectab, rsttab, copyfile);recover_table(tgtowner, tgttable, tgtowner, rectab, tgtowner, rsttab, tmpdir, recfile, copyfile, blksz, fbks, 'myself', offline_files);log('Data has been recovered to '||tgtowner||'.'||rsttab);--execute immediate 'DROP TABLESPACE '||rects||' INCLUDING CONTENTS AND DATAFILES ';--execute immediate 'DROP TABLESPACE '||rstts||' INCLUDING CONTENTS AND DATAFILES ';--remove_file(tmpdir,recfile);--remove_file(tmpdir,rstfile);remove_file(tmpdir,copyfile);-- execute immediate 'DROP DIRECTORY '||tmpdir;end;beginnull;
end FY_Recover_Data;
/

truncate的恢复相关推荐

  1. truncate后恢复包---FY_Recover_Data.pck 包的内容

    truncate后恢复包---FY_Recover_Data.pck 包的内容 > > < < < < < < < < < < ...

  2. Oracle 数据库误truncate table恢复过程

    北京某国企客户 Oracle 11g R2 数据库误truncate table CM_CHECK_ITEM_HIS,表数据丢失,业务查询到该表时报错,此时发现数据库的备份不能用,表数据无法查询. 客 ...

  3. TRUNCATE TABLE恢复-脚本

    基于本周二发的文章<TRUNCATE恢复-bbed>(详戳),有些朋友或许对块结构和bbed不熟悉,且bbed的方法也较为复杂,那么大家也可以尝试使用本文的方法来修复. 结合truncat ...

  4. oracle truncate可以恢复吗,恢复truncate表

    如果数据库是非归档模式且没有备份,此时如果drop掉一张表,有办法可以恢复吗?当然可以,而且是完全恢复:http://blog.sina.com.cn/s/blog_61cd89f60102ed97. ...

  5. oracle对查询结果求和_某国企Oracle数据库误truncate table恢复案例

    [故障情况概述] 北京某国企客户 Oracle 11g R2 数据库误truncate table CM_CHECK_ITEM_HIS,表数据丢失,业务查询到该表时报错,此时发现数据库的备份不能用,表 ...

  6. 深入解析:TRUNCATE TABLE 的内部原理解析与恢复思路

    摘要 众所周知,truncate table 是一种快速清空表内数据的一种方式,与 delete 方式不同,truncate 只产生非常少的 redo 和 undo,就实现了清空表数据并降低表 HWM ...

  7. sql truncate_如何在SQL Delete和SQL Truncate语句后使用数据库备份恢复数据

    sql truncate This article explores the recovery of data removed by SQL Delete and SQL Truncate state ...

  8. 2.5.1 MySQL数据库备份恢复基础讲解

    MySQL数据库备份恢复基础 MySQL常见的故障类型 对于用户来说,数据库中保存的数据通常至关重要,所以要采取各种手段来防止各种可能的数据损失和数据故障. DBA主要任务就是维持数据库的高可靠性运行 ...

  9. 获取表数据_mysql数据库部分表被truncate,部分数据被delete的解决过程

    服务器数据恢复环境部署及故障原因: 华为云ECS网站服务器,服务器采用linux操作系统,数据库版本号5.6,. 在执行数据库版本更新测试时,错误地将本应在测试库执行的sql脚本执行于生产库,导致部分 ...

最新文章

  1. 编码能力的提升?_20131228
  2. php钩子函数示例,PHP中钩子函数的实现与认识
  3. 跨平台屏幕/摄像头RTMP推流模块设计要点
  4. python 不等于_python零基础(二)
  5. EasyUI:textbox自定义验证手机号(正则)
  6. 点云配准_各类ICP介及特征配准流程介绍
  7. C语言文件读写(输入输出重定向)
  8. C4D OC渲染器混合材质置换问题求助
  9. 建立强有力的人脉关系
  10. C#基础之vs2010安装与使用教程
  11. 今日头条文章满多少字算原创
  12. COPYPASTE: AN AUGMENTATION METHOD FOR SPEECH EMOTION RECOGNITION -论文阅读
  13. 金山WPS2018安卓实习面试经历
  14. Keepalived HAProxy应用
  15. HDLBits练习(三)多路复用器,算术电路,卡诺图电路
  16. D. New Year and the Permutation Concatenation 题解翻译+思路解释(官方为主,我为补充)+普通人能看得懂的代码(我照着思路写的哈哈哈)
  17. 求圆形矩形面积java_Java求矩形面积和圆形面积的异常处理实例
  18. 与基础事务管理器的通信失败 存货申请_图文并茂讲解分布式事务的实现原理...
  19. 简单介绍三个C语言图形库C语言其实最擅长的是写纯数据处理的程序 . 非得用C语言写个界面程序那将会变得很困难 . 我刚开始学C语言就是从hello world 开始的 , 后来慢慢开始学从三个数中找
  20. python插值_python插值

热门文章

  1. 论文中的双斜杠是什么意思
  2. List里的remove方法
  3. 对面积的曲面积分(第一类曲面积分)
  4. 菜鸟入门Docker—练习使用Docker
  5. 强强联手:Pyston团队宣布加入Anaconda!
  6. 如何对扫描文件进行编辑
  7. ps2022 - 处理彩色扫描件原件图片为小于400KB的图片
  8. BZOJ2570:算符破译题解
  9. Jordan 标准型定理
  10. python全栈开发工程师培训