6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ADB-SにおけるTransparent Application Continuity(TAC)の挙動確認

6
Last updated at Posted at 2026-01-23

目次

1.はじめに
2.本文
3.まとめ

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を有効化していると接続エラーを自動検知し接続先を切り替えトランザクションを再実行し何事もなかったかのように振る舞います。

つまり各種メンテナンス作業が行われようともアプリケーションに影響を与えずに業務を継続することができます。

6
3
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
6
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?