はじめに
RDBMS は、ロックの競合が発生した場合に「先着順(first-come, first-served)」で処理され、先にロックを取得したトランザクションが完了するまで、後続のトランザクションは待ち続けます。ビジネス上の優先度がどれだけ高くても、先にロックを取った低優先度の処理が完了するまで待つ必要があります。
Oracle Database 26ai で導入された Priority Transactions(優先度付きトランザクション) は、この仕組みを「ビジネス優先度に基づくモデル」へと転換します。高優先度のトランザクションがロック競合でブロックされた場合、設定した待機時間を超えると、ブロックしている低優先度のトランザクションを自動的にロールバックして、高優先度の処理を優先的に完了させることができます。
この機能はセッションレベルで優先度を設定するだけで利用できます。
トランザクションの優先度レベルは以下の 3 段階です。
| 優先度 | 値 | 説明 |
|---|---|---|
| 高 | HIGH |
デフォルト値。このレベルのトランザクションはロールバックされません。LOW または MEDIUM のブロッカーをロールバックできます。 |
| 中 | MEDIUM |
LOW のブロッカーのみロールバックできます。 |
| 低 | LOW |
他のトランザクションをロールバックすることはできません。 |
ロールバックのルールをまとめると以下のようになります。
| 待機側(Waiter) | ブロック側(Blocker) | ロールバックされるか? |
|---|---|---|
| HIGH | LOW | される |
| HIGH | MEDIUM | される |
| HIGH | HIGH | されない |
| MEDIUM | LOW | される |
| MEDIUM | MEDIUM | されない |
| MEDIUM | HIGH | されない |
| LOW | HIGH/MEDIUM/LOW | されない |
ROLLBACK モードを使って HIGH 優先度と LOW 優先度の競合シナリオを試してみました。
事前準備
- Oracle Database 26ai 以降が稼働していること
- DBA 権限または SYSDBA 権限を持つユーザーでログインできること(
ALTER SYSTEM実行のため) - テスト用の接続セッションを複数同時に開けること(SQL*Plus、SQL Developer、SQLcl など)
手順
Step 1: 動作モードと待機時間パラメータの設定
まず DBA 権限のあるユーザーで接続し、システムレベルのパラメータを設定します。
priority_txns_mode は以下の 2 つのモードをサポートしています。
| モード | 説明 |
|---|---|
ROLLBACK |
実際にブロッカーのトランザクションをロールバックします |
TRACK |
シミュレーションモード。実際のロールバックは行わず、統計のみ記録します |
最初は TRACK モードで動作確認してから ROLLBACK モードに切り替えることを推奨されますが、動作確認のため最初から ROLLBACK モードで設定してみます。
-- HIGH 優先度トランザクションの待機時間を 15 秒に設定
ALTER SYSTEM SET priority_txns_high_wait_target = 15;
-- MEDIUM 優先度トランザクションの待機時間を設定する場合
-- ALTER SYSTEM SET priority_txns_medium_wait_target = <秒数>;
-- モードを ROLLBACK に設定(実際にロールバックが発生します)
ALTER SYSTEM SET "priority_txns_mode" = "ROLLBACK";
Step 2: テスト用テーブルとデータの作成
動作確認用のテーブルとデータを作成します。
-- テスト用テーブルの作成
CREATE TABLE orders (
order_id NUMBER PRIMARY KEY,
status VARCHAR2(20)
);
-- テストデータの挿入
INSERT INTO orders VALUES (1, 'PENDING');
INSERT INTO orders VALUES (2, 'PENDING');
COMMIT;
-- データ確認
SELECT * FROM orders;
ORDER_ID STATUS
---------- --------------------
1 PENDING
2 PENDING
Step 3: LOW 優先度セッションでロックを取得する(セッション 1)
新しいセッションとしてデータベースに接続し、LOW 優先度を設定してから UPDATE を実行し COMMIT しません。これにより order_id = 1 の行ロックが保持された状態になります。
-- セッション 1:LOW 優先度を設定
ALTER SESSION SET txn_priority = LOW;
-- order_id = 1 の行を更新(コミットしない)
UPDATE orders SET status = 'PROCESSING' WHERE order_id = 1;
-- この時点では COMMIT しない
Step 4: HIGH 優先度セッションで同じ行を更新(セッション 2)
別のセッションとしてデータベースに接続し、HIGH 優先度を設定してから同じ行を更新します。セッション 1 がロックを保持しているため、最初は待機状態になります。
-- セッション 2:HIGH 優先度を設定
ALTER SESSION SET txn_priority = HIGH;
-- order_id = 1 の同じ行を更新(セッション 1 のロックにより待機が発生)
UPDATE orders SET status = 'COMPLETED' WHERE order_id = 1;
priority_txns_high_wait_target で設定した待機時間(本手順では 15 秒)が経過すると、セッション 1(LOW 優先度)のトランザクションが自動的にロールバックされ、セッション 2(HIGH 優先度)の UPDATE が完了します。
セッション 1 ではロールバックされたことがメッセージされます
SQL> SELECT * FROM orders;
SELECT * FROM orders
*
ERROR at line 1:
ORA-63302: Transaction must roll back
ORA-63300: Transaction is automatically rolled back since it is blocking a
higher priority transaction from another session.
Help: https://docs.oracle.com/error-help/db/ora-63302/
Step 5: V$TRANSACTION でトランザクション優先度を確認
V$TRANSACTION ビューには TXN_PRIORITY と PRIORITY_TXNS_WAIT_TARGET の 2 列が追加されています。競合が発生している間に以下のクエリを実行することで、各トランザクションの優先度と待機ターゲットを確認できます。
SELECT xid,
xidusn,
xidslot,
xidsqn,
txn_priority,
priority_txns_wait_target,
status
FROM v$transaction;
XID XIDUSN XIDSLOT XIDSQN TXN_PRI
---------------- ---------- ---------- ---------- -------
PRIORITY_TXNS_WAIT_TARGET STATUS
------------------------- ----------------
0A002100142D0000 10 33 11540 HIGH
15 ACTIVE
Step 6: V$SYSSTAT で統計を確認
Priority Transactions の動作状況は V$SYSSTAT で統計として確認できます。
ROLLBACK モードの場合の統計確認:
SELECT name, value
FROM v$sysstat
WHERE name LIKE '%txns rollback%';
NAME VALUE
---------------------------------------------------------------- ----------
txns rollback priority_txns_high_wait_target 1
txns rollback priority_txns_medium_wait_target 0
TRACK モードの場合の統計確認SQL
SELECT name, value
FROM v$sysstat
WHERE name LIKE '%txns track mode%';
注意: アラートログにもロールバックが発生したセッションとトランザクションの詳細が記録されます。本番環境では定期的にアラートログを確認することを推奨します。
Step 7: 結果の確認
セッション 2 の UPDATE が完了した後、テーブルのデータを確認します。
SELECT * FROM orders;
ORDER_ID STATUS
---------- --------------------
1 COMPLETED
2 PENDING
order_id = 1 の status が 'COMPLETED' になっていれば、HIGH 優先度トランザクションが正しく優先処理されたことが確認できます。
制限事項
| 制限・注意事項 | 詳細 |
|---|---|
| HIGH 優先度は常に保護される | HIGH 優先度のトランザクション自身はいかなる状況でもロールバックされません |
| LOW 優先度はロールバックをトリガーできない | LOW 優先度のトランザクションは他のトランザクションのロールバックをトリガーできません |
| MEDIUM の待機対象は LOW のみ | MEDIUM 優先度は LOW のブロッカーのみロールバックでき、HIGH や同じ MEDIUM はロールバックできません |
| ROLLBACK モードはデータ損失のリスクあり | ロールバックされたトランザクションの変更は失われます。アプリケーション側でリトライ処理を実装する必要があります |
おわりに
今回の検証で確認できたポイントをまとめます。
- セッションレベルで
ALTER SESSION SET txn_priority = HIGH/MEDIUM/LOWを設定するだけで、ビジネス優先度に基づくトランザクション制御が実現できます。 -
priority_txns_high_wait_targetパラメータで待機時間を秒単位で細かく制御できます。 -
TRACKモードを使うことで、本番環境への影響を与えずに事前にシミュレーションと統計確認ができます。 -
V$TRANSACTIONとV$SYSSTATを使って、優先度情報とロールバック統計をリアルタイムに監視できます。 - アラートログへの記録により、ロールバックが発生したトランザクションの追跡調査が容易になります。