テーブルを膨らませてテーブルスペースをむさぼり食う



適切なムードを与える画像



良い一日!



インターネット全般、特にHabréには、破損したブロックの修復に関する多くの出版物があります。 たとえば、これは無傷のデータを引き出すことに関するものであり、壊れたLOBセグメントに対する勝利の物語です。



このような記事でインターネットへの多数のリンクを提供することはありません。 しかし、これらの記事のほとんどには共通の機能があります。 データが保存された(または判明したために破棄された)場合、表領域内のすべての空き領域をキャプチャして、破損した空きブロックを無効にすることをお勧めします。 そして、何らかの理由でこの提案は説明的です。



仕様を追加してください!



食べる(ほぼ写真の魚のような)スクリプトを作成し、Oracle DBのすべての空き領域を解放します。



準備部。


壊れたブロックを見ました:

select * from v$database_block_corruption;
      
      





彼らがいることを確認してください。



すべての「空き」ブロックは正確に見えましたか(突然別の壊れたセグメントが失われましたか?):

 SELECT e.owner, e.segment_type, e.segment_name, e.partition_name, c.file# , greatest(e.block_id, c.block#) corr_start_block# , least(e.block_id+e.blocks-1, c.block#+c.blocks-1) corr_end_block# , least(e.block_id+e.blocks-1, c.block#+c.blocks-1) - greatest(e.block_id, c.block#) + 1 blocks_corrupted , null description FROM dba_extents e, v$database_block_corruption c WHERE e.file_id = c.file# AND e.block_id <= c.block# + c.blocks - 1 AND e.block_id + e.blocks - 1 >= c.block# UNION SELECT s.owner, s.segment_type, s.segment_name, s.partition_name, c.file# , header_block corr_start_block# , header_block corr_end_block# , 1 blocks_corrupted , 'Segment Header' description FROM dba_segments s, v$database_block_corruption c WHERE s.header_file = c.file# AND s.header_block between c.block# and c.block# + c.blocks - 1 UNION SELECT null owner, null segment_type, null segment_name, null partition_name, c.file# , greatest(f.block_id, c.block#) corr_start_block# , least(f.block_id+f.blocks-1, c.block#+c.blocks-1) corr_end_block# , least(f.block_id+f.blocks-1, c.block#+c.blocks-1) - greatest(f.block_id, c.block#) + 1 blocks_corrupted , 'Free Block' description FROM dba_free_space f, v$database_block_corruption c WHERE f.file_id = c.file# AND f.block_id <= c.block# + c.blocks - 1 AND f.block_id + f.blocks - 1 >= c.block# order by file#, corr_start_block#;
      
      







壊れた空きブロックがあるTSのすべてのファイルの自動拡張を無効にすることを忘れないでください。 物忘れの結果はあまり快適ではないかもしれません。

はい、ファイルを「圧縮」する時間があります。 しかし、なぜ追加の問題が必要なのでしょうか?

 select 'alter database datafile '|| file_name|| ' '|| ' autoextend off;' from dba_data_files where TABLESPACE_NAME='PSAPSR3';
      
      





チームのリストを取得しました。 それらを起動しました。 次に、同じ方法で、autoextendを返すコマンドのリストを作成します。

しかし、ここでは注意する必要があります。 データファイルが別のディスクにあるのでしょうか? そして、彼らは異なる拡張設定を持っていますか? ここで注意する価値があります。



(はい、私の専門は「SAP BASISスペシャリスト」です。これは、テーブルスペースの名前の選択について説明しています。結局、そこでエラーを修正する必要があります。)



そして今だけ、準備手順が完了します。



本体


Oracle sqlを使用するには、 SQL Developerを使用します 。 必要なものはすべて揃っていますが、不要なものは観察されません。



何が欲しい?

すべての空きテーブルスペースブロックを再フォーマットします。 これを行うには、テーブルを作成し、場所がなくなるまでエクステントを追加します。



通常、必要なことを行うPL \ SQLスクリプトを次に示します。

 SET SERVEROUTPUT ON DECLARE type ARR_TABLE is table of varchar2(13); TBLS ARR_TABLE:=ARR_TABLE(); I number; SPACE_AVAILABLE float; --   tablespace TABLESPACE_FOR_FULL CONSTANT varchar2(20) := 'PSAPSR3'; --  .   ? USER_SCHEMA CONSTANT varchar2(20) := 'SAPSR3'; --    TS function TABLESPACE_FREESIZE(TN varchar2) return number as si number; begin SELECT round(sum(bytes)/1048576,2) into si from DBA_FREE_SPACE where TABLESPACE_NAME = TN; return SI; end TABLESPACE_FREESIZE; --        ora-1653 procedure create_new_tables as N number; I number; UNABLE_TO_EXTEND EXCEPTION; PRAGMA EXCEPTION_INIT(UNABLE_TO_EXTEND,-1653); BEGIN N:=TBLS.COUNT; N:=N+1; TBLS.extend; TBLS(N):='TESTTABLE'||N; execute immediate 'create table '||USER_SCHEMA||'.'||TBLS(n)||\' (id number(10), USER_NAME varchar2(10), CREATE_DATE date) tablespace '||TABLESPACE_FOR_FULL; WHILE true LOOP begin execute immediate 'alter table '||USER_SCHEMA||'.'||TBLS(n)||' allocate extent'; EXCEPTION when UNABLE_TO_EXTEND then EXIT; end; END LOOP; end create_new_tables; BEGIN -- DBMS_OUTPUT.PUT_LINE( 'Time start: '||TO_CHAR(sysdate, 'DD-MM-YYYY HH24:MI:SS')); SPACE_AVAILABLE:=TABLESPACE_FREESIZE(TABLESPACE_FOR_FULL); DBMS_OUTPUT.PUT_LINE('Space available='||SPACE_AVAILABLE); -- WHILE SPACE_AVAILABLE>0.001 LOOP CREATE_NEW_TABLES(); SPACE_AVAILABLE:=TABLESPACE_FREESIZE(TABLESPACE_FOR_FULL); --  TABLESPACE_FREESIZE   NULL   -  . end LOOP; --   for I in 1..TBLS.COUNT LOOP execute immediate 'drop table '||USER_SCHEMA||\'.'||TBLS(I); end LOOP; DBMS_OUTPUT.PUT_LINE( 'Time end: '||TO_CHAR(sysdate, 'DD-MM-YYYY HH24:MI:SS')); end;
      
      





(2つの余分なスラッシュ「\」に注意してください。「テーブルの作成」と「テーブルの削除」の行では、ハイライトが表示されないようにします。戦闘使用前に取り壊す必要があります。非常に迷惑なのは、その後の「インフィデル」の検索です。)



繰り返しますが、与えられた定数TABLESPACE_FOR_FULLとUSER_SCHEMAは、データベースの詳細を暗示しているようです。

操作アルゴリズムについてコメントする必要はないようです。



そのような方法の速度は私に合っています。



 anonymous block completed Time start: 22-10-2013 13:10:10 Space available=827,88 Time end: 22-10-2013 13:10:11 anonymous block completed Time start: 22-10-2013 13:10:27 Space available=10668,75 Time end: 22-10-2013 13:10:46 anonymous block completed Time start: 22-10-2013 13:11:26 Space available=99266,81 Time end: 22-10-2013 13:14:37
      
      







3分で100Gb未満。 機器が非常に大きな役割を果たしていることは明らかですが、機器が弱く、特別なサイズがない場合です。 さらに、Tbの空き領域はかなり奇妙な状況です。



最終ステップ


自動拡張を返すようになったので、データベースチェックを行うことができます。



 rman target /
      
      





そして

 BACKUP VALIDATE database;
      
      







そうすると、v $ database_block_corruptionビューがきれいになります...よくわかります。



エピローグ


短くて速い方法はありますか? そうでなければなりません。 必須です。 私は3週間前にPL \ SQLで書き始めました。 そして何よりも、私はDBAではなくSAP BASISの専門家です。

これで十分です。 しかし、プロからこの問題の解決策を見ることは興味深いでしょう。



All Articles