web-dev-qa-db-ja.com

Oracle 10g:ora_rowscnを適切に使用してテーブル行の変更(つまり、挿入、更新、削除)を検出します。

テーブルのレコードが最後に更新、変更、または削除された時期を確認する調査の結果、ora_rowscnと呼ばれる疑似列が見つかりました。

まず、これを行います:

select max(ora_rowscn) from tablename;

番号を書き留めます。次に、挿入、更新、削除を行い、それぞれの前と後に最大値を確認します。変更のタイプごとに増加するように見えます。

なぜこれを行っているのか疑問に思われる場合は、エンティティのリストをC#Windowsサービスにキャッシュします。このサービスは2つの負荷分散サーバー上で実行されるため、実行中のそれぞれの個別のインスタンスがあります。サーバーAで更新が発生すると、サーバーBはそれを知る必要があります。私がやりたいのは、max(ora_rowscn)を変数にキャッシュすることです。アプリケーションがレコードを挿入、更新、または削除しようとするたびに、データベースから新しい最大値が取得されます。値が異なる場合、データベースから新しいリストを取得する必要があることは明らかです。

だから私の実際の質問はこれです:この値をインクリメントしないレコードの挿入、更新、または削除を引き起こす可能性があることを知っておくべき他の障害はありますか?

編集:誰かがora_rowscnをタグとして追加できますか?

6

この値が増加しないレコードの挿入、更新、または削除につながる可能性があることを知っておく必要がある他の障害はありますか?

ora_rowscn isalways行が変更されるとインクリメントされますが、デフォルトの構成では、インクリメントすることもできます 行は変更されません

テーブル全体でudatesを確認する必要がある場合、1つの方法は 監査を使用 です。一方、更新する行の競合のみをチェックする必要がある場合は、ora_rowscn with rowdependenciesが理想的です。

Max(ora_rowscn)を取得するには、毎回テーブル全体をスキャンする必要があります。毎回キャッシュ全体を更新する方が速い場合があります。

変更が行われたことと、変更内容を他のサービスに通知する方法が必要なようです。どのシステムが変更を消費する必要があるかを示す列を持つログテーブルを維持できます。列には、サービスごとに1つずつ、2つの関数ベースのインデックスを含めることができます。これにより、各インデックスには、消費する必要のあるエントリのみが含まれます。その後、消費されると、値をNULLにしてインデックスから削除できます。

または、Oracleの Advanced Queuing を使用することもできます。

6
Leigh Riffel

@Leigh Riffelが述べたように、max(ora_rowscn)を選択すると、テーブル全体がスキャンされます。代わりの方法は、タイムスタンプ列(この例ではsys_tsを呼び出します)を使用して、ステートメントの実行時に設定されます(これは、scnが生成/設定されたときのステートメントコミットメントとは異なります)。 sys_ts列のインデックスにより、最新のx(たとえば25)行を調べて、それらの行からのみ最大ora_rowscnを見つけることができます。

これを行う最も簡単な方法は、rownumを使用して結果を制限することです。

select *
from (select sys_ts, ora_rowscn
from table order by SYS_TS desc) where rownum < 25;

残念ながら、これによりテーブル全体がスキャンされます(少なくともOracle 11.2.0.3では)。これはOracleに報告されていますが、不具合ではないと判断されました(バグ17347125)。

同じ結果を効果的に実現するには、もう少し作業が必要です。

select b.sys_ts,b.ora_rowscn from
    (select rid from 
        (select rowid as rid from table order by sys_ts desc) 
    where rownum <= 25) a, table b
where a.rid = b.rowid;

[1]- http://www.Oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html

2
Brett Okken