2

私の仕事は、プログラマーがデータベースでトリガーを作成、変更、置換、または削除したときに起動するトリガーを作成することです。テーブルと同様に作成した2つのデータテーブルに変更を記録し、それらに変更をSYS.trigger$加えたユーザーに関する追加情報を追加する必要があります。単純にするために、 GalaktikaまたはGalaxyという名前の ERP システムの既存の監査機能からロギングの原則をコピーしました。しかし、私は有名な問題に遭遇し、ORA-04089: no one can create triggers on system tablesそれに固執しました。

現在、データベースのルールに従ってトリガーを穏やかに変更する方法を探しています。元のコードは次のとおりです。

CREATE OR REPLACE TRIGGER MRK_AlTrigger$
   BEFORE DELETE OR INSERT OR UPDATE
   ON SYS.TRIGGER$
   REFERENCING NEW AS New OLD AS Old
   FOR EACH ROW
DECLARE
   Log_Rec   MRK_TRIGGERS_LOG_HEADER.NREC%TYPE;
BEGIN
   INSERT INTO MRK_TRIGGERS_LOG_HEADER (DATEOFCHANGE,
                                            USERCODE,
                                            OPERATION,
                                            OBJ#)
    VALUES (
              SYSDATE,
              UID,
              CASE
                 WHEN INSERTING THEN 0
                 WHEN UPDATING THEN 1
                 WHEN DELETING THEN 2
              END,
              CASE
                 WHEN INSERTING OR UPDATING THEN :new.OBJ#
                 ELSE :old.OBJ#
              END)
     RETURNING NRec
          INTO Log_Rec;

   IF INSERTING OR UPDATING
   THEN
      INSERT INTO MRK_TRIGGERS_LOG_SPECIF (LOGLINK,
                                               OBJ#,
                                               TYPE#,
                                               UPDATE$,
                                               INSERT$,
                                               DELETE$,
                                               BASEOBJECT,
                                               REFOLDNAME,
                                               REFNEWNAME,
                                               DEFINITION,
                                               WHENCLAUSE,
                                               ACTION#,
                                               ACTIONSIZE,
                                               ENABLED,
                                               PROPERTY,
                                               SYS_EVTS,
                                               NTTRIGCOL,
                                               NTTRIGATT,
                                               REFPRTNAME,
                                               ACTIONLINENO)
       VALUES (Log_Rec,
               :new.OBJ#,
               :new.TYPE#,
               :new.UPDATE$,
               :new.INSERT$,
               :new.DELETE$,
               :new.BASEOBJECT,
               :new.REFOLDNAME,
               :new.REFNEWNAME,
               :new.DEFINITION,
               :new.WHENCLAUSE,
               :new.ACTION#,
               :new.ACTIONSIZE,
               :new.ENABLED,
               :new.PROPERTY,
               :new.SYS_EVTS,
               :new.NTTRIGCOL,
               :new.NTTRIGATT,
               :new.REFPRTNAME,
               :new.ACTIONLINENO);
   END IF;
EXCEPTION
   WHEN OTHERS
   THEN
      -- Consider logging the error and then re-raise
      RAISE;
END MRK_AlTrigger$;
/

DDLも提供できますがMRK_TRIGGERS_LOG_HEADERMRK_TRIGGERS_LOG_SPECIF必要ないと思います。要約すると、ここに私が持っている質問があります:

  1. 上記のソースを構文に変更するにはどうすればよいCREATE OR REPLACE TRIGGER ON DATABASEですか?
  2. これを行う車輪を発明していますか?そのようなことを行う一般的な方法はありますか?(一部のテーブルにはロギング オプションがあることに気付きましたが、デバッグ目的であると考えてください)

どんな助けでも大歓迎です!

UPD:ソース管理に異なるバージョンのコードを保持し、DB にリビジョン番号のみを記録する方がよいという決定に (APC のおかげで) 至りましたが、これを自動的に行うことを夢見ています。

4

2 に答える 2

1

「私たちはプログラマーのきちんとした態度にアピールすることに絶望していたので、私の上司は、変更をログに記録するための強力で自動的な方法が必要であると要求しました。また、必要に応じて変更を迅速に元に戻す必要があります。」

つまり、政治的な問題に対する技術的な修正が必要です。これは動作しません。ただし、上司のサポートがあれば、解決できます。でもぐちゃぐちゃになります。

私はこのフェンスの両側にいて、開発者および開発 DBA として働いてきました。開発データベース (スキーマ、構成パラメーター、参照データなど) が管理されていない場合、それがどれほど悪いことになるかを苦い経験から知っています。開発者は今まさに飛んでいるように感じますが、スクリプト形式で行ったすべての変更を追跡しているわけではありません。そのため、それらの変更は元に戻すことも繰り返すこともできず、プロジェクトが UAT に到達すると、展開はおそらく失敗に終わります (ビールを買ってくれれば、いくつかの話をしましょう)。

じゃあ何をすればいいの?

特権アクセス

開発者から SYSDBA アカウントとアプリケーション スキーマ アカウントへのアクセスを取り消します。他のものとは別に、アプリケーションの一部が特権アクセスやハードコードされたパスワードに依存し始めることがありますが、それらは悪いことです。これらの違反を本番環境に含めたくありません。

開発者はこのようなアクセスに慣れているため、これは非常に人気がありません。だからこそ、上司のサポートが必要です。また、代わりのアプローチを用意する必要があるため、このアクションは最後まで残しておいてください。しかし、間違いなく、これはエンドゲームです。

ソース管理

データベース スキーマもソフトウェアです。これらは、アプリケーションの残りの部分と同様に、プログラムから構築されます。ソース コードのみが DDL であり、DML スクリプトは C# や Java ではありません。これらのスクリプトは、他のソース コードと同様に SVN で制御できます。

ソース管理でそれを整理する方法は? それは難しいかもしれません。したがって、スクリプトには次の 3 つのカテゴリがあることを認識してください。

  1. オブジェクトをデプロイするスキーマ スクリプト
  2. 参照データの挿入、システム パラメータの管理などを行う構成スクリプト
  3. 他のスクリプトを正しい順序で呼び出すスクリプトを作成する

スキーマ スクリプトの管理は、正しく行うのが最も難しいことです。オブジェクトごとに個別のスクリプトを使用することをお勧めします。また、テーブル、インデックス、および制約に対して個別のスクリプトを用意します。これは、すべてのテーブルを依存関係順に並べる必要なく構築できることを意味します。

取り扱い変更

誘惑は、単に CREATE TABLE ステートメント (または何でも) を制御することです。これは間違いです。実際には、スキーマへの変更は、まったく新しいオブジェクトを導入するのと同じように、列を追加、削除、または変更する可能性があります。CREATE TABLE ステートメントをベースラインとして保存し、その後の変更を ALTER TABLE ステートメントとして管理します。

CREATE TABLE および後続の ALTER TABLE コマンド用に 1 つのファイル、または個別のファイル? スクリプトが 1 つあれば安心です。テーブルが既に存在することを期待しているときに CREATE TABLE ステートメントが失敗してもかまいません。しかし、他の人が本番環境でスクリプトを実行する場合、これは混乱を招く可能性があります。したがって、ベースライン スクリプトを用意してから、変更を適用するための別のスクリプトを作成します。タイムボックスごとにオブジェクトごとに 1 つの変更スクリプトを使用するのが適切な妥協点です。

開発者からの変更は、

  • 変更を適用するためのテーブル スクリプトの変更
  • 変更を元に戻すためのミラー化されたテーブル変更スクリプト
  • その他のスクリプト (DML など)
  • 参照番号を変更します(SVNで使用します)

遅い時間にこれを紹介するので、外交的である必要があります。そのため、変更プロセスを軽くて使いやすいものにします。また、できるだけ早くスクリプトを確認して実行してください。応答性が高く、物事を迅速に行う場合、開発者は制限されたアクセスの下でイライラすることはありません。

そこへの行き方

まず、ベースラインを確立する必要があります。DBMS_METADATAのようなものは、現在のすべてのオブジェクトに対して CREATE ステートメントを提供します。それらを SVN で整理し、ビルド スクリプトを記述する必要があります。おもちゃのデータベースを作成して、これを正しく理解してください。

これには時間がかかる場合があるため、最新のステートメントが反映されるように DDL スクリプトを更新することを忘れないでください。現在非常に便利なスキーマ比較ツールにアクセスできる場合。

次に、構成を整理します。テーブルに参照データが含まれていることを既に知っていることを願っています。それ以外の場合は、開発者に尋ねてください。

おもちゃのデータベースで、データベースをザッピングしてゼロから構築する練習をします。冒険心があれば、Ant や Hudson などを使用してこれを自動化できますが、少なくとも SVN からビルドするにはいくつかのシェル スクリプトが必要です。

移行を行う

これは大きなものです。新しい体制を開発者に発表します。上司に会議に出席してもらいます。開発者がデータベースに変更を加える場合は、その旨を通知するように開発者に伝えてください。

その夜:

  1. Data Pump で完全なエクスポートを行う
  2. すべてのアプリケーション スキーマを削除します。
  3. SVN からアプリケーションをビルドする
  4. Data Pump を使用してデータを再ロードしますが、データ構造は再ロードしません
  5. 構造的な問題が発生しないことを願っています。しかし、開発者があなたに言わずに変更を加えた場合、あなたは知っているでしょう - そして彼らはテーブルにデータを持っていません.
  6. できるだけ早く SYSDBA アクセスを取り消すようにしてください。

開発者は、ALTER スクリプトを作成できるように、一連のスキーマにアクセスする必要があります。開発者には、テスト用のローカル パーソナル データベースやプライベート スキーマがないため、変更スクリプトをテストするために、おもちゃのデータベースにアクセスできるようにすることをお勧めします。または、Trash'n'Rebuild 演習を定期的に繰り返すことになるため、アプリケーション所有者のアクセス権を維持することもできます。彼らが変更を失うという考えに慣れると、彼らはナックルダウンして正しいことを始めます.

最後の言葉

明らかに、これは多くの漠然としたウインドバガリーであり、確かな詳細が欠けています. しかし、それはあなたのための政治です。

あとがき

昨日、私はUKOUG のイベントに参加し、Regdate のスマートなメンバーによるセッションに参加しました。彼らは、(たとえば)SVNとデータベースの間のインターフェースを提供するOracleのソース管理製品を持っています。上で概説したものとはかなり異なるアプローチをとります。しかし、彼らのアプローチは健全なものです。彼らのツールは多くのことを自動化し、現在の状況で大いに役立つと思います。私は実際にこの製品を使用していないことを強調しなければなりませんが、チェックする必要があると思います.28日間の無料試用版があります. もちろん、使うお金がなければ、これは役に立ちません。

于 2013-07-17T14:13:51.360 に答える
0

次のトリガー属性で必要な情報を見つけることができます

dictionary_obj_name 
dictionary_obj_owner
ora_sysevent

これが単純なON DATABASEトリガーです

CREATE OR REPLACE TRIGGER trigger_name
AFTER CREATE OR DROP  ON DATABASE
BEGIN
  IF dictionary_obj_type = 'TRIGGER'
  THEN 

    INSERT INTO log_table ( trg_name, trg_owner, trg_action) VALUES (dictionary_obj_name,dictionary_obj_owner, ora_sysevent);

  END IF;
END;
/ 
于 2013-07-11T14:25:39.230 に答える