目次
1. はじめに
ADB-Sでは、Transparent Application Continuity(TAC) を有効化することで、
✅セッション切断時の自動再接続
✅未完了トランザクションの自動再実行
が可能になります。
ADB-SにおいてTACを有効化し、プロシージャを実行している途中に異常終了しても、自動でセッション再接続してトランザクション再実行されるかを検証してみました。
2. 本文
2.1【検証手順】
(1) トランザクションを発生させるプロシージャ作成
(2) TACが無効の状態で、プロシージャ実行している途中で疑似障害を発生させて挙動確認
(3) TACを有効の状態にして、プロシージャ実行している途中で疑似障害を発生させて挙動確認
2.2【検証手順詳細】
※本検証では、ADB上でtacuserとadminユーザーを作成し、tacuserでプロシージャ実行することでトランザクション発生させて、adminユーザーで疑似障害を発生させる。また、adminユーザーでTACを有効化させてでの検証もする。そのため、TeraTermを2つ起動させて、別々の端末でオペレーションをしています。
検証環境と前提
✅Autonomous AI Database Serverless(ADB-S)
✅利用ユーザー
tacuser:PL/SQL実行用
admin:疑似障害発生用
✅TeraTermを2セッション起動し、別端末として操作
(1) トランザクションを発生させるプロシージャ作成
■端末(teraterm)1より
tacuserユーザーでログイン
テスト環境作成する
-- スキーマ作成(テーブル/インデックス)
-- テスト用スキーマのオブジェクトを作成します
-- 口座テーブル(accounts) + 取引履歴テーブル(acct_txn) + インデックス(ix_acct_balance)
CREATE TABLE accounts (
acct_id NUMBER PRIMARY KEY,
cust_name VARCHAR2(100),
balance NUMBER,
updated_at TIMESTAMP
);
CREATE TABLE acct_txn (
txn_id NUMBER
GENERATED BY DEFAULT AS IDENTITY
PRIMARY KEY,
from_acct NUMBER,
to_acct NUMBER,
amount NUMBER,
created_at TIMESTAMP,
note VARCHAR2(200)
);
CREATE INDEX ix_acct_balance
ON accounts (balance);
-- 初期データ投入(l_rowsで件数を調整)(例: 100,000口座)
DECLARE
l_rows NUMBER := 100000;
BEGIN
INSERT /*+ APPEND */
INTO accounts (
acct_id,
cust_name,
balance,
updated_at
)
SELECT
LEVEL AS acct_id,
'CUST_' || TO_CHAR(LEVEL) AS cust_name,
TRUNC(DBMS_RANDOM.VALUE(1000, 100000)) AS balance, -- 初期残高
SYSTIMESTAMP AS updated_at
FROM
dual
CONNECT BY
LEVEL <= l_rows;
COMMIT;
END;
/
-- トランザクションを発生させるプロシージャ作成
-- 指定時間(秒)実行し、ランダムに送金、参照、更新、古い履歴の削除を行う
CREATE OR REPLACE PROCEDURE run_mixed_workload_nocommit(
p_seconds IN NUMBER DEFAULT 300
) IS
l_end_time TIMESTAMP := SYSTIMESTAMP + NUMTODSINTERVAL(p_seconds, 'SECOND');
l_from NUMBER;
l_to NUMBER;
l_amount NUMBER;
l_choice NUMBER;
l_cnt NUMBER := 0;
BEGIN
DBMS_APPLICATION_INFO.set_module(
module_name => 'TEST_WORKLOAD',
action_name => 'RUN'
);
WHILE SYSTIMESTAMP < l_end_time LOOP
l_choice := TRUNC(DBMS_RANDOM.value(1, 101)); -- 1..100
IF l_choice <= 55 THEN
------------------------------------------------------------------
-- 55%: 振替トランザクション(更新 + 履歴挿入)
------------------------------------------------------------------
l_from := TRUNC(DBMS_RANDOM.value(1, 100001));
l_to := TRUNC(DBMS_RANDOM.value(1, 100001));
IF l_from = l_to THEN
l_to := CASE WHEN l_to < 100000 THEN l_to + 1 ELSE 1 END;
END IF;
l_amount := TRUNC(DBMS_RANDOM.value(10, 1000));
-- 残高チェックしつつ行ロック(更新できたら SQL%ROWCOUNT=1)
UPDATE accounts
SET balance = balance - l_amount,
updated_at = SYSTIMESTAMP
WHERE acct_id = l_from
AND balance >= l_amount
RETURNING acct_id INTO l_from;
IF SQL%ROWCOUNT = 1 THEN
UPDATE accounts
SET balance = balance + l_amount,
updated_at = SYSTIMESTAMP
WHERE acct_id = l_to;
INSERT INTO acct_txn (
from_acct, to_acct, amount, created_at, note
) VALUES (
l_from, l_to, l_amount, SYSTIMESTAMP, 'transfer'
);
END IF;
ELSIF l_choice <= 85 THEN
------------------------------------------------------------------
-- 30%: 調査系 SELECT(インデックス活用やソートを誘発)
------------------------------------------------------------------
DECLARE
v_dummy NUMBER;
BEGIN
SELECT SUM(balance)
INTO v_dummy
FROM (
SELECT balance
FROM accounts
WHERE balance BETWEEN TRUNC(DBMS_RANDOM.value(100, 50000))
AND TRUNC(DBMS_RANDOM.value(50001, 100000))
ORDER BY balance DESC
)
WHERE ROWNUM <= 1000;
EXCEPTION
WHEN NO_DATA_FOUND THEN
NULL;
END;
ELSIF l_choice <= 95 THEN
------------------------------------------------------------------
-- 10%: ランダム更新(軽い更新)
------------------------------------------------------------------
UPDATE accounts
SET balance = balance + TRUNC(DBMS_RANDOM.value(-50, 50)),
updated_at = SYSTIMESTAMP
WHERE acct_id = TRUNC(DBMS_RANDOM.value(1, 100001))
AND ROWNUM = 1;
ELSE
------------------------------------------------------------------
-- 5%: 履歴のクリーンアップ(古い行を削除)
------------------------------------------------------------------
DELETE FROM acct_txn
WHERE created_at < SYSTIMESTAMP - INTERVAL '1' HOUR
AND ROWNUM <= 1000;
END IF;
l_cnt := l_cnt + 1;
END LOOP;
END;
/
(2) TACが無効の状態で、プロシージャ実行している途中で疑似障害を発生させて挙動確認
■端末(teraterm)2より
adminユーザーでログイン
TACが設定されていないことを確認
FAILOVER_TYPEが[NONE]であること
[oracle@adb-hol-dev-vcn ~]$ sqlplus admin/*******@inbetest005_tp
SQL> set pages 9999
SQL> set lines 200
SQL> col NAME for a60
SQL> col FAILOVER_TYPE for a10
SQL> SELECT name, failover_type FROM DBA_SERVICES;
NAME FAILOVER_TYPE
------------------------------------------------------------ ---------------
SYA6*******_INBETEST005_tp.adb.oraclecloud.com NONE
■端末(teraterm)1より
tacuserユーザーでログイン
プロシージャ実行前の環境確認
プロシージャ実行
[oracle@adb-hol-dev-vcn ~]$ sqlplus tacuser/*******@inbetest005_tp
SQL> select count(*) from acct_txn;
COUNT(*)
----------
0
SQL> BEGIN
2 run_mixed_workload_nocommit(300);
3 END;
4 /
■端末(teraterm)2より
tacuserユーザーで実行しているプロシージャを止める
SQL> col username for a10
SQL> col SERVICE_NAME for a50
SQL> col FAILED_OVER for a15
SQL> col MODULE for a15
SQL> select sid, serial#, username,service_name,failed_over,module
2 from v$session
3 where username = 'TACUSER' and module = 'TEST_WORKLOAD';
SID SERIAL# USERNAME SERVICE_NAME FAILED_OVER MODULE
---------- ---------- ---------- -------------------------------------------------- --------------- ---------------
41488 14541 TACUSER SYA6*******_INBETEST005_tp.adb.oraclecloud.com NO TEST_WORKLOAD
SQL> alter system kill session '41488,14541';
System altered.
■端末(teraterm)1より
プロシージャ実行エラーになる事を確認
SQL> BEGIN
2 run_mixed_workload_nocommit(300);
3 END;
4 /
BEGIN
*
ERROR at line 1:
ORA-00028: session has been terminated
ORA-06512: at "TACUSER.RUN_MIXED_WORKLOAD_NOCOMMIT", line 68
ORA-06512: at line 2
--> ORA-25403: could not reconnect
Help: https://docs.oracle.com/error-help/db/ora-00028/
SQL> exit
(3) TACを有効の状態にして、プロシージャ実行している途中で疑似障害を発生させて挙動確認
■端末(teraterm)2より
TACを設定する
FAILOVER_TYPEが[AUTO]であること
SQL> execute DBMS_APP_CONT_ADMIN.ENABLE_TAC('SYA6*******_INBETEST005_tp.adb.oraclecloud.com', 'AUTO', 1200);
SQL> SELECT name, failover_type FROM DBA_SERVICES;
NAME FAILOVER_TYPE
------------------------------------------------------------ ---------------
SYA6*******_INBETEST005_tp.adb.oraclecloud.com AUTO
■端末(teraterm)1より
再度、プロシージャ実行
[oracle@adb-hol-dev-vcn ~]$ sqlplus tacuser/*******@inbetest005_tp
SQL> BEGIN
2 run_mixed_workload_nocommit(300);
3 END;
4 /
■端末(teraterm)2より
tacuserユーザーで実行しているプロシージャを止める
SQL> select sid, serial#, username,service_name,failed_over,module
2 from v$session
3 where username = 'TACUSER' and module = 'TEST_WORKLOAD';
SID SERIAL# USERNAME SERVICE_NAME FAILED_OVER MODULE
---------- ---------- ---------- -------------------------------------------------- --------------- ---------------
28862 58903 TACUSER SYA6*******_INBETEST005_tp.adb.oraclecloud.com NO TEST_WORKLOAD
SQL>
SQL> alter system kill session '28862,58903';
System altered.
■端末(teraterm)1より
プロシージャ実行エラーにならずに、正常終了することを確認
SQL> BEGIN
2 run_mixed_workload_nocommit(300);
3 END;
4 /
PL/SQL procedure successfully completed.
SQL> select count(*) from acct_txn;
COUNT(*)
----------
138293
※ランダムアクセスなので、レコード件数は毎回かわる
■端末(teraterm)2より
tacuserユーザーで実行しているプロシージャのSIDとSERIAL#が変わっていることと、FAILED_OVER=YESになっていることを確認する。
このことから、セッションフェイルオーバー(再接続)が発生し、処理が継続(再実行)されたと判断できる。
SQL> select sid, serial#, username,service_name,failed_over,module
2 from v$session
3 where username = 'TACUSER' and module = 'TEST_WORKLOAD';
SID SERIAL# USERNAME SERVICE_NAME FAILED_OVER MODULE
---------- ---------- ---------- -------------------------------------------------- --------------- ---------------
32468 36191 TACUSER SYA6*******_INBETEST005_tp.adb.oraclecloud.com YES TEST_WORKLOAD
3. まとめ
Transparent Application Continuity(TAC)の有効化方法および疑似的な障害を発生させて、挙動確認の方法についてご紹介させて頂きました。
ADB-Sは週末にメンテナンス・ウィンドウが設定されており、セッションの瞬断が発生する場合があります(すぐに再接続可能)。
この瞬断の影響を避けるための対策としてもAC/TACをご活用いただけます。
AC/TACを有効化していると接続エラーを自動検知し接続先を切り替えトランザクションを再実行し何事もなかったかのように振る舞います。
つまり各種メンテナンス作業が行われようともアプリケーションに影響を与えずに業務を継続することができます。