web-dev-qa-db-ja.com

OracleでTimestamp_to_scnおよびScn_to_timestampを使用する方法

私はこれをクエリの結果として持っています:

select cast(to_date(a.start_time,'mm/dd/yyyy hh:mi:ss pm') as timestamp) date_of_call,
ora_rowscn from calling_table a where rownum <= 10;

       DATE_OF_CALLING          ORA_ROWSCN

26-JUL-13 12.29.28.000000000 PM 8347567733892
26-JUL-13 12.29.35.000000000 PM 8347567733892
26-JUL-13 12.29.35.000000000 PM 8347567733892
26-JUL-13 12.29.38.000000000 PM 8347567733892
26-JUL-13 12.29.44.000000000 PM 8347567733892
26-JUL-13 12.29.47.000000000 PM 8347567733892
26-JUL-13 12.29.48.000000000 PM 8347567733892
26-JUL-13 12.29.48.000000000 PM 8347567733892
26-JUL-13 12.29.48.000000000 PM 8347567733892
26-JUL-13 12.29.56.000000000 PM 8347567733892

しかし、timestamp_to_scn関数を使用してこのタイムスタンプをscnに変換しようとすると、次のエラーが発生します。

ORA-08180:指定された時間に基づいてスナップショットが見つかりませんORA-06512: "SYS.TIMESTAMP_TO_SCN"、行1 08180にあります。00000-"指定された時間に基づいてスナップショットが見つかりません" *原因:時間をSCNに一致させることができませんマッピングテーブル。 *アクション:より長い時間を使用してみてください。

そして、ora_rowscnでscn_to_timestampを使用してその列をタイムスタンプに変換すると、次のエラーが発生します。

ORA-08181:指定された番号は有効なシステム変更番号ではありませんORA-06512: "SYS.SCN_TO_TIMESTAMP"、1行目08181。00000-"指定された番号は有効なシステム変更番号ではありません" *原因:指定されたscnは範囲を超えていました有効なscnの。 *アクション:有効なscnを使用してください。

私が間違っているのは何ですか?

13
MontyPython

あなたは遠くを振り返ろうとしています。システムで管理されているREDO /フラッシュバック・ウィンドウにあるSCNとの間でのみ変換できます。変更が期限切れになると、マッピングは失われます。

これは説明されています ドキュメント内

SCNが生成されたときのSCNとタイムスタンプの間の関連付けは、一定期間データベースによって記憶されます。データベースが自動UNDO管理モードで実行されている場合、この期間は自動調整されたUNDO保存期間の最大値であり、データベース内のすべてのフラッシュバックアーカイブの保存期間ですが、120時間以上です。アソシエーションが古くなるまでの時間は、データベースが開いているときにのみ経過します。 SCN_TO_TIMESTAMPの引数に指定されたSCNが古すぎると、エラーが返されます。

これらはOracleの内部メカニズムの一部であり、使用が制限されることに注意してください。もちろん、同じウィンドウ内でのフラッシュバッククエリには便利です。

22
Alex Poole

SCN_TO_TIMESTAMPは、いくつかの内部アルゴリズムを使用して、イベントが発生したときにSCNとTIMEの間のマッピングを行い、適切な近似でジョブを実行します。しかし、限界があります。 UNDOデータが期間をカバーしていない場合、過去に遠くに行くことはできません。

その場合、元に戻すデータの制限に達したときに独自のマッピングを作成するトリッキーな方法があります。 SCN_TO_TIMESTAMPほど良くはありませんが、データによっては概算になります。

必要なのは、継続的に挿入が行われているテーブルを見つけることだけです。監査テーブルsys.aud $を使用します。独自のものを使用することもできますが、テーブルには、行がいつ挿入されたかを示すタイムファイリングが必要です。また、SCNとDATEがある場合は、SCNとDATEを別のテーブルにマップできます。

sys.aud $を使用する場合は、次のことに注意してください。

  1. アクセス権を付与したり、ora_rowscnとntimestamp#の2つのフィールドを持つ単純なビューを作成したりするには、dbaが必要になる場合があります。
  2. データベースで行われているアクティビティが多ければ多いほど、マッピングはより正確になります。通常、sys.aud $テーブルを使用すると、1年前に発生した古いデータの編集を、約60〜120分でマッピングできます
  3. 監査がオフの場合、scn_timeは行を返さないため、マッピングする別のテーブルを見つける必要があります。

クエリはsys.aud $を使用します。 [YOU_TABLE]を、挿入または更新の日付を見つける必要があるテーブルに置き換えます

-- get scn to date interval [begin..end] mapping from audit table      
with scn_time as
 (
     select sc sc_start, 
            lead(sc) over(order by sc) sc_end,
            start_time,
            lead(end_time) over(order by sc) end_time_sc
     from 
      (
        select n.ora_rowscn sc, 
        min( cast(from_tz(ntimestamp#,'00:00') at local as date) ) start_time,
        max( cast(from_tz(ntimestamp#,'00:00') at local as date) ) end_time
            from sys.aud$ n
            -- if audit log is big you need to select only a part of the table
            -- to make query faster
            --where ntimestamp# > sysdate - 365
           group by  n.ora_rowscn 
      ) order by sc 
  )
-- map scn from you table to scn_mapping  
select *
  from (
          select t.ora_rowscn sc, t.*
          from [YOU_TABLE] t
       ) table_inspect
 inner join scn_time s
    on (table_inspect.sc between s.sc_start and s.sc_end)
 -- to filter out bit intervals    
 where (end_time_sc-start_time) < 1

1年以上前に挿入された行が挿入されたときに、情報を復元する方法を使用しました。

3
Dmitry.M

UNDO_MANAGEMENTをAUTOに設定し、UNDO_RETENTIONを、最も長いクエリの期間をさかのぼる値に設定します。また、RETENTION GARANTEEを設定して、UNDOが上書きされないようにします。

Oracle 10gの場合、5日より長くフラッシュバックすることはできません。これはハードコードされた制限です。 Oracle 11gの場合、制限はありません。

2
xDBA