1. はじめに
Oracle Autonomous AI Database(旧称 Autonomous Database、以下 ADB)には、本番のワークロードを記録して別の環境で流し直す Real Application Testing(ワークロードの Capture / Replay) が、DBMS_CLOUD_ADMIN のプロシージャとして用意されています。本番に近い負荷でパッチやバージョンアップの影響を事前に試せる、というものです。
半年ほど前にこの機能を触った記事を書いたのですが1、そのときは DBMS_CLOUD_ADMIN.PREPARE_REPLAY がうまく動かず、「手動で準備」していました。
今回はそれをやり直してみました。最近 SQLcl MCP や OCI CLI を使って Claude にデータベース操作をやらせる検証を続けてきた延長で、「同じ手順を、クローン作成からリプレイまでエージェント越しに最後まで通せるか」 を実機で試しました。結論から書くと、最後まで通り、前回つまずいた所についても原因の見当がつきました。
結論を先に箇条書きで出します。
- キャプチャ → リフレッシュ可能クローンで
PREPARE_REPLAY→REPLAY_WORKLOADまで完走できた。リプレイ後のクローン側テーブルはソースと完全に一致した(492 行) - 一連の操作は SQLcl MCP(DB 操作)と OCI CLI(クローン作成・削除)の組み合わせで、ツール越しに通せた
-
今回つまずいたのは、クローンの読み取り専用ではなく「セッションの NLS(日本語ロケール)」だった。
DBMS_CLOUD_ADMINのキャプチャ/リプレイ系は内部で日付文字列を解釈するため、日本語環境のままだとORA-01843: 無効な月で落ちる(前回の不調も同じ NLS が原因の可能性が高いと見ています) -
PREPARE_REPLAYはリフレッシュ可能クローン上で実行するプロシージャで、クローンをキャプチャ開始時刻まで進めてソースから切り離し、読み書き可能にする。切り離し(再起動を伴う)には体感で 10 分ほどかかった
今回の検証ゴール
| # | 検証項目 |
|---|---|
| 1 | キャプチャ → クローンで PREPARE_REPLAY → REPLAY を完走できるか |
| 2 | 一連の操作をエージェント(SQLcl MCP + OCI CLI)で回せるか |
| 3 | PREPARE_REPLAY はどこで何をするプロシージャなのか |
2. 検証環境
| 項目 | 内容 |
|---|---|
| クライアント | Windows 11 Pro / WSL2(Ubuntu) + OCI CLI 3.86 |
| ソース DB | Oracle Autonomous AI Database (ATP, Serverless) 23.26.2.2.0(26ai) |
| クローン | リフレッシュ可能クローン ADBCLONE01(MANUAL リフレッシュ) |
| DB 操作 | SQLcl MCP |
DB 側の操作はすべて SQLcl の MCP サーバ経由で実行しました。クローンの作成・状態確認・削除といった OCI のコントロールプレーン操作は、SQL からは行えないので OCI CLI を使います。「DB 内のことは SQLcl MCP、DB の外側(インスタンスの作成・削除)は OCI CLI」という役割分担です。
3. 仕組みの整理(先に押さえておくと迷わない点)
手順に入る前に、公式ドキュメントで分かる「ハマりどころに直結する仕様」を 3 つだけ整理します。
3.1. リプレイにはリフレッシュ可能クローンが要る
ワークロードはソース DB でキャプチャしますが、リプレイはソースではなく、ソースの「リフレッシュ可能クローン」に対して行います2。リフレッシュ可能クローンは、ソースの状態を継続的に取り込める読み取り専用のコピーです。これを使うことで「キャプチャ開始時点のデータ状態」をクローン上に再現し、そのクローンに対してキャプチャした操作をリプレイできます。
3.2. PREPARE_REPLAY はリフレッシュ可能クローンを「切り離す」
DBMS_CLOUD_ADMIN.PREPARE_REPLAY(capture_name) は、公式の説明では「リフレッシュ可能クローンをキャプチャ開始時刻まで進めて、そのうえで切り離す(disconnecting)」処理です3。切り離すとクローンはソースからの取り込みをやめ、独立した読み書き可能な DB になります。これが済んで初めて、記録した書き込みをリプレイできる状態になります。
つまり PREPARE_REPLAY は読み取り専用のリフレッシュ可能クローン上で実行するのが正しく、プロシージャ自身がクローンを読み書き可能へ切り替えます。前回これが動かなかったとき「クローンが読み取り専用だから書き込みに失敗したのでは」と考えましたが、実際にはそこではありませんでした(理由は 5 章)。
3.3. クローンはキャプチャ開始より前に作る
リフレッシュ可能クローンは、作成した時刻より後の時点にしかリフレッシュできません4。PREPARE_REPLAY はクローンをキャプチャ開始時刻まで進めるので、その時刻がクローン作成時刻より後である必要があります。したがってクローンはキャプチャを始める前に作っておくのが条件になります。過去に取ったキャプチャを、今から作るクローンでリプレイすることはできません。
全体の流れは次のとおりです。
4. 手順と実施
4.1. リフレッシュ可能クローンを作る(OCI CLI)
ソースの OCID とコンパートメントを指定して、クローンを 1 台作成します。
oci db autonomous-database create-refreshable-clone \
--compartment-id "$COMP_OCID" \
--source-id "$SOURCE_OCID" \
--db-name ADBCLONE01 \
--display-name "adbtest02-replay-clone" \
--compute-model ECPU \
--compute-count 2 \
--data-storage-size-in-gbs 80 \
--license-model LICENSE_INCLUDED \
--is-mtls-connection-required true \
--refreshable-mode MANUAL
リフレッシュ方式は MANUAL を選びました。AUTOMATIC だと auto-refresh-point-lag-in-seconds(ソースに対する遅れ秒数)が必須で、しかも自動リフレッシュの最小間隔が 1 時間です。今回は PREPARE_REPLAY 自身がクローンをキャプチャ開始時刻まで進めてくれるので、自動リフレッシュに任せる必要がなく、パラメータの少ない MANUAL の方が扱いが簡単でした。
リフレッシュ可能クローンの ADMIN パスワードはソースから引き継がれるため、作成時に --admin-password を指定する必要はありません。後でクローンに接続するときは、ソースと同じ ADMIN パスワードを使います。
数分で PROVISIONING から AVAILABLE になりました。
4.2. ソースでキャプチャ(ここで ORA-01843 に遭遇)
ソース adbtest02 に ADMIN で接続し、キャプチャを開始します。
BEGIN
DBMS_CLOUD_ADMIN.START_WORKLOAD_CAPTURE(capture_name => 'REPLAYTEST01');
END;
/
開始できたことを確認します。start_scn を控えておくと、後でクローンがこの時点まで進んだか確認できます。
SELECT id, name, status, start_scn FROM dba_workload_captures WHERE name='REPLAYTEST01';
-- 31 REPLAYTEST01 IN PROGRESS 49836393090012
続いて、リプレイ対象となるワークロードを SCOTT で流します。キャプチャは DB 全体の操作を記録するので、別ユーザーのセッションで動かしても捕捉されます。内容はテーブル作成と、投入 500 行 → 更新 100 行 → 削除 10 行 → 追加 2 行で、最終的に 492 行になる単純なものです(全文は src/workload.sql)。
CREATE TABLE replay_demo (id NUMBER PRIMARY KEY, val VARCHAR2(100), ts TIMESTAMP DEFAULT SYSTIMESTAMP);
-- 500 件 INSERT → MOD(id,5)=0 を UPDATE(100件に _upd 付与) → MOD(id,50)=0 を DELETE(10件) → 2 件 INSERT
ソース側の最終状態は次のとおりで、これがあとでクローンと一致すれば成功です。
| 指標 | 値 |
|---|---|
| 行数 | 492 |
| min / max id | 1 / 1002 |
| id=5 の val | row_5_upd |
_upd を含む行数 |
90 |
ADMIN に戻ってキャプチャを終了します。ところがここで失敗しました。
BEGIN
DBMS_CLOUD_ADMIN.FINISH_WORKLOAD_CAPTURE;
END;
/
-- ORA-20000: ORA-01843: 無効な月が指定されました。
-- ORA-06512: "C##CLOUD$SERVICE.DBMS_CLOUD$PDBCS_260529_0", 行2305
ORA-01843: 無効な月 は、日付文字列を解釈するときに月名が読めなかったときのエラーです。プロシージャが内部で日付を組み立てる際、セッションの言語設定(日本語ロケール)と月名の表記が噛み合わずに落ちていました。セッションの NLS を英語系に明示してから実行し直すと、今度は通りました。
ALTER SESSION SET NLS_LANGUAGE = 'AMERICAN';
ALTER SESSION SET NLS_TERRITORY = 'AMERICA';
ALTER SESSION SET NLS_DATE_LANGUAGE = 'AMERICAN';
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
BEGIN
DBMS_CLOUD_ADMIN.FINISH_WORKLOAD_CAPTURE;
END;
/
-- PL/SQL procedure successfully completed.
キャプチャは COMPLETED になりました。所要 111 秒、記録された呼び出しは 161 件です。
SELECT id, name, status, duration_secs, user_calls FROM dba_workload_captures WHERE name='REPLAYTEST01';
-- 31 REPLAYTEST01 COMPLETED 111 161
4.3. クローンで PREPARE_REPLAY(切り離しに約10分)
クローンは別の DB なので、SQLcl の名前付き接続を別途用意します。generate-wallet でクローンのウォレットを取得し、ADMIN(パスワードはソースと同じ)で名前付き接続 adbclone01_admin を作りました。
接続するとアクセスモードが READ ONLY で、リフレッシュ可能クローンらしい状態です。ここで NLS を設定したうえで PREPARE_REPLAY を実行します。前回ここで止まった処理です。
-- NLS を AMERICAN 系に設定(4.2 と同じ4行)してから
BEGIN
DBMS_CLOUD_ADMIN.PREPARE_REPLAY(capture_name => 'REPLAYTEST01');
END;
/
-- PL/SQL procedure successfully completed.
正常に終わりました。直後に OCI 側でクローンの状態を見ると、is-refreshable-clone が True から False に変わっており、クローンがソースから切り離されたことが分かります。lifecycle-state は STARTING で、読み書き可能モードへの再起動中でした。
oci db autonomous-database get --autonomous-database-id "$CLONE_OCID" \
--query 'data.{state:"lifecycle-state",refreshable:"is-refreshable-clone",openmode:"open-mode"}' --output table
# refreshable=False / state=STARTING → 数分後 open-mode=READ_WRITE
ワークリクエストを見ると Disconnect Refreshable Autonomous Database が 100% SUCCEEDED になっていました。open-mode が READ_WRITE に変わるまで、また STARTING ラベルが落ち着くまでは、体感で 10 分ほどかかりました。PREPARE_REPLAY は単なる SQL ではなく、インスタンスの切り離しと再起動を伴う処理だと考えておくとよさそうです。
4.4. クローンで REPLAY_WORKLOAD とデータ一致の検証
クローンが読み書き可能になったので接続し直します。リプレイ前に確認しておくと、SCOTT.REPLAY_DEMO はまだ存在しません。テーブルを作ったのはキャプチャ開始より後で、クローンはキャプチャ開始時点の状態に揃えられているので、その時点ではまだこのテーブルが無いわけです。クローンが狙った時点に合っている裏付けになります。
SELECT COUNT(*) FROM all_tables WHERE owner='SCOTT' AND table_name='REPLAY_DEMO'; -- 0
NLS を設定してから REPLAY_WORKLOAD を実行します。
-- NLS を AMERICAN 系に設定してから
BEGIN
DBMS_CLOUD_ADMIN.REPLAY_WORKLOAD(
capture_name => 'REPLAYTEST01',
replay_name => 'REPLAYRUN01');
END;
/
-- PL/SQL procedure successfully completed.
リプレイはバックグラウンドで進みます。進行は DBA_CAPTURE_REPLAY_STATUS で見られ、PREPARING REPLAY から STARTING REPLAY へと進みました。しばらくすると SCOTT.REPLAY_DEMO が現れ、記録した DML が適用されていきます。
最終的に、クローン側のテーブルはソースと完全に一致しました。
| 指標 | ソース | クローン(リプレイ後) |
|---|---|---|
| 行数 | 492 | 492 |
| min / max id | 1 / 1002 | 1 / 1002 |
| id=5 の val | row_5_upd |
row_5_upd |
_upd を含む行数 |
90 | 90 |
| MOD(id,50)=0 の残存 | 0 | 0 |
SELECT COUNT(*) cnt, MIN(id) min_id, MAX(id) max_id FROM scott.replay_demo; -- 492 / 1 / 1002
SELECT val FROM scott.replay_demo WHERE id = 5; -- row_5_upd
キャプチャした一連の操作(テーブル作成・投入・更新・削除・追加)が、そのままクローン上で再現されたことが確認できました。
5. つまずきと回避策
実際に詰まった点と回避策をまとめます。
5.1. 日本語ロケールだと ORA-01843 で落ちる(最重要)
FINISH_WORKLOAD_CAPTURE / PREPARE_REPLAY / REPLAY_WORKLOAD は内部で日付文字列を解釈するため、セッションが日本語ロケールのままだと ORA-01843: 無効な月 を返して落ちます。呼び出す前に、毎回このセッション設定を効かせるのが回避策です。
ALTER SESSION SET NLS_LANGUAGE = 'AMERICAN';
ALTER SESSION SET NLS_TERRITORY = 'AMERICA';
ALTER SESSION SET NLS_DATE_LANGUAGE = 'AMERICAN';
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
NLS はセッション単位の設定なので、接続し直すたびにリセットされます。ソースでのキャプチャ、クローンでの PREPARE_REPLAY、クローンでの REPLAY はそれぞれ別セッションになりがちなので、各セッションで毎回設定するのが確実です。
5.2. クローンはキャプチャ開始より前に作る
3.3 のとおり、リフレッシュ可能クローンは作成時刻より後にしかリフレッシュできません。過去のキャプチャを今から作るクローンでリプレイすることはできないので、新規にキャプチャを取り直しました。
5.3. PREPARE_REPLAY の切り離しは時間がかかる
PREPARE_REPLAY はクローンの切り離しと読み書きモードへの再起動を伴い、lifecycle-state が STARTING のまま体感 10 分ほど続きました。open-mode が READ_WRITE になったかどうかを OCI CLI で見ながら待つと、状況を把握しやすいです。
5.4. ステータスビューは ADB だと一部が空
進行状況は DBA_CAPTURE_REPLAY_STATUS の state 列で追えました。一方、オンプレでよく使う DBA_WORKLOAD_REPLAYS は、今回の環境では行が出ませんでした。リプレイの成否は、ステータス表示だけに頼らずリプレイ後のデータがソースと一致するかで確認するのが確実です。
6. 考察
6.1. 前回動かなかった本当の原因
前回 PREPARE_REPLAY が動かなかったとき、私はクローンが読み取り専用であることを疑いました。しかし今回、読み取り専用のクローン上で PREPARE_REPLAY はそのまま成功しました。PREPARE_REPLAY は読み取り専用のリフレッシュ可能クローンを前提に動き、自身でクローンを読み書きへ切り替えるプロシージャだからです。
実際に落ちたのは日付解釈の ORA-01843 で、これは NLS を英語系にすれば解消しました。前回の不調も、原因はクローンの状態ではなくセッションの NLS だった可能性が高いと考えられます。DBMS_CLOUD_ADMIN のワークロード系プロシージャを日本語環境で叩くときは、まず NLS を疑うのがよさそうです。
6.2. エージェントで回すときのポイント
今回は DB の中身を SQLcl MCP、インスタンスの作成・削除を OCI CLI、という二つを使い分けて回しました。Capture/Replay は「DB 内の操作」と「DB の外側の操作(クローンの作成・切り離し・削除)」が混ざる作業なので、この役割分担は自然でした。
一点だけ手間だったのは、クローンが別 DB なので接続を別に用意するところです。リフレッシュ可能クローンはソースと同じ ADMIN パスワードを引き継ぎますが、接続文字列とウォレットは別物なので、SQLcl の名前付き接続を別途作る必要がありました。ここだけはウォレット取得と接続作成という人手の段取りが残ります。
6.3. 本番ワークロードに広げるときの注意
今回のワークロードは 492 行・161 呼び出しの小さなもので、リプレイのパイプラインが通ることの確認が目的でした。本番に近い負荷で意味のある比較をするなら、キャプチャ時間・同時実行・処理の偏りを本番に寄せる必要があります。なお、リプレイの出発点となるデータ状態は、PREPARE_REPLAY がクローンをキャプチャ開始時刻まで進めることで担保されます。クローンはその時点のコピーなので、ここがずれる心配は基本的にありません。実際、リプレイ前のクローンには SCOTT.REPLAY_DEMO がまだ無く(キャプチャ開始後に作ったテーブルなので)、クローンがちょうどキャプチャ開始時点に揃っていることを確認できました。
7. まとめ
| # | 検証項目 | 結論 |
|---|---|---|
| 1 | キャプチャ → クローンで PREPARE_REPLAY → REPLAY を完走できるか | 完走できた。リプレイ後のクローンはソースと完全一致(492 行) |
| 2 | 一連をエージェント(SQLcl MCP + OCI CLI)で回せるか | 回せた。DB 内は SQLcl MCP、クローン作成・削除は OCI CLI |
| 3 | PREPARE_REPLAY はどこで何をするのか | リフレッシュ可能クローン上で実行し、クローンをキャプチャ開始時刻まで進めてソースから切り離す(read-only → read-write) |
DBMS_CLOUD_ADMIN.PREPARE_REPLAY は、リフレッシュ可能クローンを使う正しい手順と、日本語環境での NLS 設定さえ押さえれば、そのまま動きました。前回「手動で準備した」と書いた部分は、今回の結果で解消できたことになります。
-
Live Workload Capture Replay between Autonomous AI Databases(ターゲットはリフレッシュ可能クローンであること) ↩
-
Summary of DBMS_CLOUD_ADMIN Subprograms(PREPARE_REPLAY / START_WORKLOAD_CAPTURE / FINISH_WORKLOAD_CAPTURE / REPLAY_WORKLOAD の説明) ↩
-
Create a Refreshable Clone for an Autonomous AI Database Instance ↩