web-dev-qa-db-ja.com

Oracle:スキーマ内の最後の更新(任意のテーブル)のタイムスタンプを見つける方法は?

Oracleデータベーススキーマがあります(データは非常に小さいですが、それでも約10〜15個のテーブル)。一種の構成(ルーティングテーブル)が含まれています。

このスキーマを時々ポーリングする必要があるアプリケーションがあります。通知は使用されません。

スキーマ内のデータが更新されなかった場合、アプリケーションは現在のメモリ内バージョンを使用する必要があります。

テーブルに更新があった場合、アプリケーションはすべてのテーブルをメモリにリロードする必要があります。

指定されたキーポイント(時間またはトランザクションID)以降のスキーマ全体の更新をチェックする最も効果的な方法は何ですか

OracleがスキーマごとにトランザクションIDを保持していると思います。次に、そのようなIDを照会し、次のポーリングで比較するために保持する方法があるはずです。

私はこのような疑似列が行レベルに存在するこの質問を見つけました:

Oracleテーブルが最後に更新された日時を確認する方法

スキーマレベルでも同様のことがあると思います。

誰かが私を正しい方向に向けてくれませんか?

9

私はOracleのそのような機能を知りません。 下記参照。

私が思いつくことができる最善の解決策は、1行のテーブルまたは context を現在の日付/時刻で更新するトリガーを各テーブルに作成することです。このようなトリガーは、テーブルレベル(行レベルではなく)にある可能性があるため、ほとんどのトリガーほどオーバーヘッドがかかりません。

ちなみに、1つのトランザクションが複数のスキーマに影響を与える可能性があるため、OracleはスキーマごとにトランザクションIDを保持できません。 V $ビューを使用して、影響を受けたオブジェクトまでトランザクションを追跡することは可能かもしれませんが、それは簡単ではなく、ほぼ確実にトリガースキームよりもパフォーマンスが低下します。

10gを使用している場合、Oracleのフラッシュバック機能を使用してこの情報を取得できることがわかります。ただし、フラッシュバックを有効にする必要があります(これにより、独自のオーバーヘッドが発生します)。クエリが途方もなく遅くなります(おそらく、この用途を意図していないためです)。

select max(commit_timestamp) 
from FLASHBACK_TRANSACTION_QUERY 
where table_owner = 'YOUR_SCHEMA' 
      and operation in ('INSERT','UPDATE','DELETE','MERGE') 

「最終更新」テーブルでのロックの問題を回避するために、次のような自律トランザクションを使用するプロシージャにその更新を配置することをお勧めします。

create or replace procedure log_last_update as
pragma autonomous_transaction;
begin
   update last_update set update_date = greatest(sysdate,update_date);
   commit;
end log_last_update;

これにより、アプリケーションがある程度シリアル化されます。このプロシージャを呼び出す必要がある各ステートメントは、前のステートメントが終了するまで待機する必要があります。 「最後に更新された」テーブルは、トリガーをアクティブ化した更新がロールバックされても、その更新が保持されるため、同期が取れなくなる可能性があります。最後に、特に長いトランザクションがある場合、アプリケーションはトランザクションが完了する前に新しい日付/時刻を取得し、目的を果たせなくなる可能性があります。これについて考えれば考えるほど、悪い考えのように思えます。


これらの問題を回避するためのより良い解決策は、トリガーから行を挿入することです。これはテーブルをロックしないため、シリアル化は行われず、挿入を非同期で行う必要がないため、実際のデータと共にロールバックできます(そして、データも表示されます)。アプリケーションは最大値を取得します。これは、テーブルにインデックスが付けられている場合は非常に高速です(実際、このテーブルはインデックス構成テーブルの理想的な候補です)。唯一の欠点は、定期的に実行されるジョブで古い値をクリーンアップする必要があるため、大きくなりすぎないことです。

12
Allan

dbms_stats.gather_table_statsも役立つ可能性があります: http://forums.Oracle.com/forums/thread.jspa?threadID=60761 ==

   4. Statistics is considered to be stale, when the change is over 10% of current rows. 
   (As of 11g, this value can be customized per objects. Cool feature)


    .
    . 
    .

exec dbms_stats.gather_table_stats(user, 'T_STAT');

select * from sys.dba_tab_modifications where table_name = 'T_STAT';
No row selected

select stale_stats from sys.dba_tab_statistics where table_name = 'T_STAT';
NO

insert into t_stat select rownum from all_objects where rownum <= 20;

select * from sys.dba_tab_modifications where table_name = 'T_STAT';
No rows selected <-- Oops
select stale_stats from sys.dba_tab_statistics where table_name = 'T_STAT';
NO  <-- Oops

exec dbms_stats.flush_database_monitoring_info;

select * from sys.dba_tab_modifications where table_name = 'T_STAT';
TABLE_OWNER TABLE_NAME  PARTITION_NAME  SUBPARTITION_NAME   INSERTS UPDATES DELETES TIMESTAMP   TRUNCATED   DROP_SEGMENTS
UKJA        T_STAT      20  0   0   2008-01-18 PM 11:30:19  NO  0

select stale_stats from sys.dba_tab_statistics where table_name = 'T_STAT';
YES
3
Tim