1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

オラクルAPEXのトランザクション処理(COMMIT、ROLLBACK)

Last updated at Posted at 2021-10-11

初めに

現代のウエブ開発には、無数の言語、ライブラリー、テクノロジがあります。UIデザインやユーザー・エクスペリエンス等、技術以外の知識も把握しなければならなりません。開発者は、エキスパートになるまで数年がかかってしまいます。

Oracle APEXとはロー・コード開発プラットフォームです。APEXで、簡単で、高速にアプリケーションをゼロから作成し、技術の詳細を気にせずビジネス課題に集中することだできます。一方、プラットフォームなので、普段開発者が管理できることはプラットフォームが管理を引き受けますので、行動が自動か、手動に行うことを把握しなければなりません。

データの保全することにトランザクション処理が重要なことなので、APEXのトランザクション処理を洗い出しましょう。

トランザクションとは?

データベースのトランザクションとは、複数のSQL文を1つの処理としてまとめてデータベースに反映させることです。

例えば、銀行のシステムに、あるアカウントから他のアカウントに振り込む行動を想像してください。一つだけじゃなくて、2つの変更が必要です:

  1. アカウントAの残高を減らす
  2. アカウントBの残高を増やす

以上の操作の中に、すべての操作を行わなければならなりません。だからSQL文を1つの処理としてまとめることになり、トランザクションと呼ばれます。

CommitとRollback

APEXのトランザクション処理を理解するには、まずcommitrollbackというSQLコマンドを理解しなければなりません。
このコマンドでトランザクションを終了することができます。

commitは、データの変更がまとめてデータベースに格納されます。
rollbackは、トランザクション内でのデータの変更がすべてキャンセルされます。

APEXのトランザクション

APEXのページには、「プロセス」と「動的アクション」でPL/SQL文を書くことができます。

「プロセス」と「動的アクション」もPL/SQL文を実行すると、トランザクションが開始されます。もちろん以上のcommitrollbackコマンドで、手動的にトランザクションを終了することができますが、自動的にcommitrollbackが実行されます。こういう場合はデータが案外な状態になってしまう恐れがありますので、注意が必要です。

APEXは、いつ自動的にコミットする?

APEXのトランザクション処理の情報はドキュメンテーションにはありませんので、調査で以下のタイミングで自動的にコミットすることを確認しました:

  1. COMMITを書く時
  2. 動的アクションのアクションの終了の時
  3. すべてのプロセスの終了の時(レンダリング前)
  4. すべてのプロセスの終了の時(ページ送信後)
  5. 一つのプロセスが終了し、セッション・ステートが更新された
  6. APEX_MAIL.PUSH_QUEUEの実行時

APEXは、いつ自動的にロールバックする?

エラーが処理中に発生したら、自動的にロールバックされる。どこまでロールバックするのは、最後のコミットの時まで。まだコミットしなかった場合はトランザクションの前の状態までロールバックします。

テストケースのセットアップ

自動commitrollbackを理解するため、テストケースで確認しましょう。

テストテーブル

テーブル名:「TEST_COMMIT_ROLLBACK」
image.png

テストプロシージャ

create or replace procedure "TCR_SIMPLE_UPDATE"
(in_value IN NUMBER,
in_value2 IN VARCHAR2)
is
begin
    update test_commit_rollback set value = in_value;
    update test_commit_rollback set value2 = in_value2;
end;

テストページ

APEXのページを作成し、以下のようなフォームリージョンを追加しました。
image.png

プロセス

プロセスは原則、全部のプロセスが終わった時にコミットする。複数のプロセスがあっても、自動コミットは一回だけです。

  • DBの状況:Value = 1, Value2 = a
  • ページ送信後、プロセスを2つ実行する
    • タイプ:PL/SQL実行
    TCR_SIMPLE_UPDATE(:P2_VALUE,:P2_VALUE2);
    
    • タイプ:PL/SQL実行
    ROLLBACK;
    
  • VALUEを2、VALUE2をbに更新する
  • image.png

結果:

  • VALUE = 1, VALUE2 = a
  • 最初までROLLBACKする。プロセス後コミットされないらしい。

プロセスの実行タイミングが違う場合もコミットは一回です。以下の例で、After Submitのタイミングじゃなくて、Processingのタイミングの後、コミットすることになります。

  • DBの状況:Value = 1, Value2 = a
  • 「After Submit」のタイミングに、プロセスを作成
    TCR_SIMPLE_UPDATE(2,'b');
    
  • 「Processing」のタイミングに、プロセスを作成
    TCR_SIMPLE_UPDATE(3,'c');
    ROLLBACK;
    
  • image.png

結果:

  • VALUE = 1, VALUE2 = a

※プロセスの実行順序はAfter Submit > Validation > Processing

セッション変更時のコミット

前に、「プロセスは原則、全部のプロセスが終わった時にコミットする」と書きましたが、例外があります。セッション・ステートを変更すると、コミットしてしまう場合があります。

セッション・ステート変更する操作

  1. PX_ITEM := ○○ (直接アイテムを兼行する)
  2. apex_util.set_session_state(PX_ITEM, 値)
  3. SELECT INTO :PX_ITEM
  4. RETURNING INTO :PX_ITEM
  5. Out変数をページアイテムに挿入する
  6. APEX Computation(計算)

例:別プロセスでセッション・ステートを変更する

  • ページ送信後、プロセスが実行する
    • DBの状況:Value = 1, Value2 = a
    • 「コード実行1」タイプ:PL/SQL実行
    TCR_SIMPLE_UPDATE(2,'b');
    
    • 「ステート変更1」タイプ:PL/SQL実行
    :P2_ITEM := 2;
    
    • 「コード実行2」タイプ:PL/SQL実行
    TCR_SIMPLE_UPDATE(3,'c');
    
    • 「ステート変更2」タイプ:PL/SQL実行
    :P2_ITEM := 3;
    
    • 「コード実行3」タイプ:PL/SQL実行
    ROLLBACK;
    

結果:

  • VALUE = 3, VALUE2 = c
  • 期待は、VALUE = 1, VALUE2 = aが、ステート変更後、コミットしてしまうことがあります。

例:別プロセスでセッション・ステートの値を変更しない

  • ページ送信後、プロセスが実行する
    • DBの状況:Value = 1, Value2 = a
    • 「コード実行1」タイプ:PL/SQL実行
    TCR_SIMPLE_UPDATE(2,'b');
    
    • 「ステート変更1」タイプ:PL/SQL実行
    :P2_ITEM := 2;
    
    • 「コード実行2」タイプ:PL/SQL実行
    TCR_SIMPLE_UPDATE(3,'c');
    
    • 「ステート変更2」タイプ:PL/SQL実行
    :P2_ITEM := 2; --以上と変更はなし
    
    • 「コード実行3」タイプ:PL/SQL実行
    ROLLBACK;
    

結果:

  • VALUE = 2, VALUE2 = b
  • 期待は、VALUE = 1, VALUE2 = aが、「ステート変更1」後、コミットしてしまうことがあります
  • 「ステート変更2」は、ステート変更使用としましたが、値は現在の値と同じなので、コミットは実行しません。

例:プロセス内

  • ページ送信後、プロセスが実行する
    • DBの状況:Value = 1, Value2 = a
    • 「コード実行」タイプ:PL/SQL実行
        TCR_SIMPLE_UPDATE(2,'b');
        :P2_ITEM := 2;
        TCR_SIMPLE_UPDATE(3,'c');
        :P2_ITEM := 3;
        ROLLBACK;

結果:

  • VALUE = 1, VALUE2 = a
  • コミットはプロセスが終わった時に実行します。コードをまとめて一つのプロセスで実行すると、コミットする機会はなさそうです。

動的アクション

動的アクションは、プロセスと違って、各アクションの後コミットされます。

  • DBの状況:Value = 1, Value2 = a
  • ボタンを押すと、動的アクションが実行する
    • タイプ:PL/SQL実行
    TCR_SIMPLE_UPDATE(2,'b');
    
    • タイプ:PL/SQL実行
    ROLLBACK;
    

結果:

  • VALUE = 2, VALUE2 = b
  • 最初のアクションが終了したからCOMMITします。

参照(英語版)

  1. Ted Struik Blog : Rollback & Commit
  2. How to make a deferred commit Q&A
  3. When is commit executed? Q&A
  4. Jeff Kemp Blog : Session State May or May Not Commit
  5. Implicit commits in APEX
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?