web-dev-qa-db-ja.com

トランザクション内のテーブル構造を変更しますか?

Oracle(およびおそらく他の場所)では、ALTER TABLEステートメントを実行すると、現在のトランザクションで暗黙的なコミットが実行されます。

次の方法でスキーマを変更する必要があるツール(Javaで記述)があります。

  • 列を追加する
  • 一部の列を削除する
  • 新しいスキーマレイアウトで説明テーブルを更新する

記述されたツールは、現在のスキーマレイアウトをユーザーに表示し、ユーザーがそれを変更できるようにします。 (基本的には、カスタムの「属性」列をいくつかのテーブルに追加または削除します)満足すると、彼は変更を適用できます。

注:基本的なスキーマレイアウト、および一部を変更するためにALTER TABLEが必要であるという事実は、標準で事前定義されており、他のツールが機能しなくなるため、変更することはできません。

今問題は、これらの変更を単一のトランザクションで実行できないことです。なぜなら、私の知る限り、トランザクション内で複数のALTER TABLEステートメントを実行することは不可能だからです。

変更の適用中に問題が発生した場合、初期状態に「ロールバック」するにはどのオプションが必要ですか?

注:ここで誰かがRESTORE POINT + FLASHBACKを提案しました-これをこの(Java)ツールから呼び出すのは良い考えですか? (ツールを使用する必要がある一部のサイトでは、データベースインスタンスを完全に制御していません。)

注:Oracle 10g2以降

4
Martin

DDLは暗黙的にコミットするため、変更を「ロールバック」する唯一の方法は、a_horse_with_no_nameが示すように、逆の操作を作成し、それを適用して変更を元に戻すことです。

ただし、そのようなロールバックの作成は必ずしも簡単ではありません。タイプの変更(varchar2(10)-> varchar2(50)、number-> varchar2)の間にデータをテーブルに書き込むことができ、これをロールバックする場合、に戻ったときに新しいデータが有効であることを確認する必要があります。元のタイプ(またはいくつかの変換を実行)。大きなテーブルで列を削除すると、時間がかかり、大量のREDOが生成される可能性があることに注意してください。

これらの変更の結果として、データベース上のストアドプロシージャや他のアプリケーションの依存関係を無効にすることにも注意する必要があります。

この場合、フラッシュバックオプションは役に立ちません。テーブルにDDL変更を加えたら、フラッシュバックを使用してテーブルを以前の状態に復元することはできません。そうしようとすると、エラーが発生します。

ORA-01466:データを読み取れません-テーブル定義が変更されました

データベース全体をフラッシュバックするのはやり過ぎであり、Javaアプリからも不可能です。この操作を完了するには、データベースをシャットダウンしてからマウントする必要があります。

これはすべて、ツールの目的に関する疑問を引き起こします。ユーザーがテーブルを編集するためのGUIだけが必要な場合は、Oracle SQL Data Modelerなどでこれを実行し、DDLスクリプトを生成できます。次に、これらを検証、テストし、適切なロールバックを構築してデータベースに適用できます。 (本番)データベースの構造の変更は慎重に行い、すべての変更が有効であることを確認するためにテストする必要があります!

5
Chris Saxon

私が考えることができる唯一の方法(トランザクションDDLをサポートするDBMSへの移行を除く)は、実際の変更をロールバックする対応するステートメントを作成する独自の「DDLトランザクション」処理を記述することです。

列をドロップするだけで、ADD COLUMNを「ロールバック」するのは簡単です。 DROP COLUMNをロールバックするには、列の名前を変更してから、すべてが正常に完了した後で、名前を変更したすべての列を削除するのが唯一の選択肢です。 「仮想ドロップ」をロールバックするには、列の名前を元の名前に戻すだけです。

別の代替案は、テーブルを変更する前にテーブルのコピーを作成することです。 CREATE TABLE backup_table AS SELECT * FROM original_tableを使用します(ただし、テーブルが非常に大きい場合、これは明らかに良い解決策ではありません)

フラッシュバックデータの可用性に依存できないため、フラッシュバックの使用はおそらくあまり信頼できません。 保証フラッシュバック時間のデフォルト値は15分です。ただし、DBAはより小さな値を自由に選択できます。

Oracleは、11gR2で主にオンラインでアプリケーションスキーマをアップグレードするための機能 Edition-Based Redefinition を追加しました。おそらく、これを使用して目標を達成できます。

2
Todd Pierce

Oracle DDLステートメントは暗黙的にコミットします。それはonlyで動作するDBMSです。

Oracleの "FlashBack Table"は、テーブルを以前の特定の時点に巻き戻すことができますが、そのテーブルへの構造(つまりDDL)の変更全体で機能しませんです。

"フラッシュバックデータベース"は別のメカニズムを使用しますが、データベース全体を変更前の状態に戻します。これは許可されていない場合があります。

他の誰も言及していない別のオプションはmonolith --DBMS_REDEFINITIONです。
これはオラクル社が提供する巨大なパッケージであり、これらすべてを管理し、テーブルの変更を透過的かつシームレスにして、サービスの中断をほとんど回避します。それは大きくて複雑ですが、それに慣れるために投資する価値があるかもしれません。

1
Phill W.

テーブルの一時セットにすべての変更を加えます。

すべてが正常に完了すると、実際のテーブルへのすべての変更が適用されます。

1
Jimbo

クライアントが列を追加していると思う場所に構造を追加するほうがよいと思いますが、実際には、テーブルにレコードを追加するだけです。例: "Table_Column_DEF"。次に、デフォルトのテーブルと「Table_Column_DEF」の間のリンクテーブルのみが必要です。ここには値も格納されます。

この方法を使用すると、クライアントは必要な列を追加でき、これを1つのトランザクションで実行できます。ロールバック、フラッシュバックなどのメリットがあります。もちろん、考慮すべきいくつかのトレードオフがあります。

1)値の列:

  • 可能なデータ型ごとに1つの値の列があり、すべてをvarchar2、clob、またはblobに格納します。
  • 可能なすべてのデータ型の値列...

2)パフォーマンス

3)クエリ:これを動的に構築する必要があります。すべての「Table_Column_DEF」レコードをループし、「select(select Value_Int from LinkTable where ...)Value_Int、... from ...」を使用してそれらを追加します