1.

Oracle 19c COMMITの使い方: 暗黙コミット・自動確定・応答不明時の確認

▶

Oracle 19c: 確定・取消・結果不明を分ける

Oracle Database 19cでINSERT / UPDATE / DELETEを一つの業務単位として確定するための案内です。まず接続clientとtransactionの管理者を確認し、自動確定が有効な接続で「最後にROLLBACKすれば戻る」と考えないでください。OracleのBEGIN ... ENDはPL/SQLブロックであり、PostgreSQLのBEGINによるtransaction開始とは別です。

Oracle 19cの通常DMLについて、確定前の取消、COMMIT応答、応答不明時の照合と、別境界のDDL・XA・非同期確定を分ける模式図
模式図。通常DMLの未確定範囲と、確定済み・応答不明を区別します。DDLの暗黙確定、XA coordinatorの判断、非同期確定の永続化待機は別の境界で、実測結果や全障害での復旧保証を示す図ではありません。
  1. 変更前: SQL*PlusならSHOW AUTOCOMMITとSHOW EXITCOMMIT、JDBCならgetAutoCommit等で有効な接続条件を確認します。framework / pool管理の接続はそのtransaction APIに従います。複数DMLを一単位にする場合は開始前に自動確定と管理境界を整え、途中でDDLやautocommit切替を混ぜません。設定を切り替えても確定済みの変更は戻りません。
  2. 確定前: 対象の業務キー、更新件数、制約・業務結果を同じ接続で確認します。予定どおりなら管理APIのcommitまたはSQLのCOMMITへ進み、不一致・処理中止なら未確定の業務単位をROLLBACKします。0件更新は文として成功し得ます。文エラー後に残る変更を確認せずCOMMITへ進まないことが重要です。
  3. 成功応答あり: 通常の同期確定ならredoの永続化条件を満たして確定します。通常ROLLBACKでは取り消せません。OracleのCOMMIT WRITE NOWAITやPostgreSQLのsynchronous_commit=off等では成功報告と永続化完了を同一視できません。
  4. COMMIT応答不明: timeoutや通信断だけでは失敗と確定しません。同じ減算・加算を再送せず、要求ID・業務キー・接続先・エラーコードを秘密値抜きで記録し、同一transaction内の処理済み要求記録等、アプリが設計した正式な照合元を確認します。確認できれば成功処理か再試行の判断へ、確認できなければ保留・担当者確認へ進みます。新接続のROLLBACKや遅延replicaの0件だけで旧接続の未確定を証明することはできません。

境界を越える場合: Oracle 19cの構文的に妥当な通常DDLは、実行エラーでも先行DMLを実行前に確定し得ます。一方、XAのprepared / in-doubtは通常の利用者COMMITと異なり、coordinatorの決定・XID・参加者状態で解決します。通信失敗だけを理由に独断でXA ROLLBACKしません。冪等性は要求IDの採番だけで成立せず、一意制約や結果記録・同時実行制御を含む事前設計が必要です。

教材の範囲: 旧8コード枠を製品別比較として残し、各枠の直前で適用条件を説明しています。新旧SQLとdriver例は実機未実行です。以下のCOMMIT構文・DDL例外・client動作の訂正は公式資料との照合によるもので、未実行を理由に確定した構文差を曖昧にはしていません。

この記事の要点
  • COMMIT は現在のトランザクションを確定して終了する命令。成功応答と永続化の関係は製品・同期設定に依存する
  • COMMIT / COMMIT TRANSACTION / COMMIT WORK は製品別の表記。Oracle 19cでは COMMIT と COMMIT WORK が同義で、COMMIT TRANSACTION をOracleへ転用しない
  • Oracle 19c / MySQL 8.4の通常表DDLには暗黙COMMITがある。PostgreSQLの通常 CREATE TABLE は明示トランザクション内で取消可能。全DDL・一時表へ一律には広げない
  • 分散トランザクションの方式の一つがTwo-Phase Commit。XA対応リソースをcoordinatorが管理するが、SQL構文・設定・復旧手順は製品別
  • SET AUTOCOMMIT=0 はMySQLの接続設定。Oracleの利用者COMMIT、SQL*Plus設定、psql設定、driver API、frameworkの管理境界を区別する

COMMIT とは

ここではOracle Database 19cで、INSERT / UPDATE / DELETEによる一連の変更を利用者が確定する目的を中心に、他製品と比較します。COMMITは現在のトランザクションを終了し、savepointを消去してtransaction lockを解放します。未確定の通常DMLは自分の接続から確認し、確定前ならROLLBACKを選べます。ただしclientによる自動確定やDDLの境界を越えた変更は戻せません。他接続で見える時点は分離レベル・snapshotにも依存し、dirty readを許す製品設定へ「未確定変更は絶対に見えない」と一般化しません。

OracleのSQLに、PostgreSQLのBEGINと同じtransaction開始命令としてのBEGINはありません。OracleのBEGIN ... ENDはPL/SQLブロックです。ブロックの開始・正常終了だけで利用者のtransaction開始・確定を指示したことにはならず、内部のCOMMITやclientの自動確定を別に確認します。

基本構文

掲載例1の読み方: accounts等は教材用の表で、本番の口座へ試す手順ではありません。製品別の抜粋であり、枠全体を一括実行する例ではありません。Oracle部分はclientが自動確定しない前提で、UPDATEの対象・件数と業務結果を確認してからCOMMITかROLLBACKを選びます。SQL*PlusとJDBCでは既定動作も異なり、「Oracleだから常に自動確定OFF」ではありません。PostgreSQLでは明示transaction外の各文もtransactionとして実行され、成功すると確定します。driverがBEGINを送る場合はその境界に従います。MySQL部分はInnoDB等のtransaction対応表、SQL Server部分は入れ子でない単独transactionを想定します。枠内コメントの「標準SQL」はBEGINが全製品共通という意味ではなく、COMMIT WORKは単なる古い廃止構文でもありません。最後のCOMMIT WORKを再度送れば前の処理が成功する、という例ではありません。

-- 標準SQL / MySQL / PostgreSQL
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;             -- 確定

-- SQL Server
BEGIN TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT TRANSACTION; -- COMMIT TRAN でも可

-- Oracle
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
COMMIT;             -- BEGIN は不要、DML 開始時に暗黙開始

-- COMMIT WORK は標準SQLの古い書き方(同義)
COMMIT WORK;

明示 COMMIT と暗黙 COMMIT

種類発生条件例
明示 COMMIT利用者・アプリが現在のtransactionを確定。成功応答を確認するCOMMIT; またはdriverのcommit API。例外・切断だけでは確定失敗と断定しない
暗黙 COMMIT (DDL)Oracle 19cの構文的に妥当な通常DDLは実行前(実行エラーでも)、成功時は実行後にも確定。MySQLにも対象DDLの前後境界がある通常表のCREATE / ALTER / DROP / TRUNCATE等。PostgreSQLの通常 CREATE TABLE の取消や一時表の例外と区別する
暗黙 COMMIT (制御)client・終了手順に依存。「接続終了なら確定」ではないSQL*Plusの既定EXITは未確定分をCOMMIT(EXITCOMMIT ON)。AUTOCOMMITとは別設定。MySQLでautocommit無効の未確定transactionはsession終了時ROLLBACK
暗黙 COMMIT (管理)製品別の制御・管理文に依存MySQLのSET autocommit=1は0から1へ変えるときに確定。LOCK TABLESや新たなBEGIN / START TRANSACTIONも既存transactionの境界になり得る。全SET文やOracleへ一般化しない

DDL の暗黙コミットの落とし穴

掲載例2の注意: 前半のBEGINはMySQL用です。Oracle 19cで比較する際はこのBEGINを送らず、clientの自動確定を抑えた上でDMLを開始する形になります。通常 CREATE TABLE の前にstartが確定し、構文的に妥当なDDLなら既存名・権限等の実行エラーでも先行DMLが戻るとは限りません。SQL実行を続けた場合、Oracleで自動確定しないmidはROLLBACK対象ですが、MySQLでautocommit=1ならDDL後のmidも単独で成功時確定します。autocommit=0のInnoDBならmidは後続transactionで取消対象です。

掲載例2の対象: tmpは単なる表名で、一時表指定ではありません。MySQLのCREATE / DROP TEMPORARY TABLEは暗黙COMMITをしない一方、その定義操作自体は通常ROLLBACKで戻りません。Oracle 19cのprivate temporary tableも、transaction固有のON COMMIT DROP DEFINITIONの作成は暗黙COMMITなし、session固有のON COMMIT PRESERVE DEFINITIONの作成は暗黙COMMITあり、と分かれます。後半のPostgreSQLのBEGIN / CREATE TABLE / ROLLBACKは通常のCREATE TABLEを取り消す正しい比較です。CREATE DATABASEやCREATE INDEX CONCURRENTLYなどtransaction block内で使えない別のDDLへ拡張しません。atomic DDLの障害時整合性と、利用者がROLLBACKで取消可能かも別問題です。

BEGIN;
INSERT INTO logs(msg) VALUES ('start');
CREATE TABLE tmp (id INT);       -- ★ MySQL/Oracle ではここで暗黙 COMMIT
INSERT INTO logs(msg) VALUES ('mid');
ROLLBACK;                        -- もう start を消せない

-- PostgreSQL なら DDL もロールバック可能
BEGIN;
CREATE TABLE tmp (id INT);
ROLLBACK;                        -- tmp テーブルも消える

Autocommit と SET AUTOCOMMIT=0

掲載例3の注意: SET autocommit / @@autocommitはMySQL用で、接続内の設定です。InnoDBの未確定DMLを前提とし、非transaction表の更新まで戻せるわけではありません。psqlのバックスラッシュ設定はclientのメタコマンドで、PostgreSQLサーバーのSQLではありません。psqlのAUTOCOMMITは既定ON、OFFでは必要時にclientがBEGINを送ります。Oracle SQL*PlusのSET AUTOCOMMIT OFFは別構文のclient設定であり、終了時のEXITCOMMITとは独立です。SQL*PlusではSHOW AUTOCOMMITとSHOW EXITCOMMIT、driverではそのAPI・接続初期化を確認し、OFFのつもりで切断に任せず明示的に終了します。旧コメントの「別セッションからは見えない」はdirty readを許すREAD UNCOMMITTEDへは一般化できず、確定後も既存snapshotの読取りには直ちに反映されない場合があります。「ここで初めて永続化」も有効なredo同期設定に依存します。設定を変えても既に確定した変更は未確定へ戻りません。

-- MySQL
SELECT @@autocommit;             -- 1 (ON) / 0 (OFF)
SET autocommit = 0;              -- 明示 COMMIT モード

UPDATE accounts SET balance = 0 WHERE id = 1;
-- まだ COMMIT されていない。別セッションからは見えない
COMMIT;                          -- ここで初めて永続化

-- セッション内だけで OFF
SET SESSION autocommit = 0;

-- PostgreSQL の psql 対話モード
\set AUTOCOMMIT off

エラー時の自動ロールバック

文の失敗とtransaction全体の失敗は別です。Oracle 19cの通常のSQL文失敗はその文を取り消し、先に成功した文を自動で全て取り消すわけではありません。InnoDBの重複キーエラー(IGNOREなし)は文単位、deadlockはtransaction全体、lock wait timeoutは既定で文単位(innodb_rollback_on_timeoutにより全体取消もあり)です。エラーコードと接続状態を確認し、残った変更を誤ってCOMMITしないよう業務単位を終了します。

掲載例4の注意: PostgreSQL部分はidが主キーまたは一意制約であり、1行目が成功して2行目が重複エラーとなり、savepointへの復帰を行わない通常のtransaction blockを想定します。エラー後もclientが後続文を送る条件(psqlのON_ERROR_STOPがoff等)で、aborted状態でSELECTが拒否され、COMMITが取消になる流れはこの条件で成立します。エラー前のSAVEPOINTへROLLBACK TOすれば続行できる場合は別で、psqlのON_ERROR_ROLLBACKによる自動savepointも区別します。末尾のMySQLコメントは上記の重複キー等に限定し、全エラーへ一般化しません。OracleもPostgreSQLも必ず同じ失敗状態になる、という例ではありません。

-- PostgreSQL: 1つでもエラーが出るとトランザクションは ABORT 状態
BEGIN;
INSERT INTO users(id, name) VALUES (1, 'taro');
INSERT INTO users(id, name) VALUES (1, 'jiro');  -- 主キー重複エラー
SELECT 1;                        -- ERROR: current transaction is aborted
COMMIT;                          -- 実質 ROLLBACK

-- MySQL: エラーが出た文だけ無効。他の文は生きる
-- → 明示的に ROLLBACK 推奨

Two-Phase Commit (XA トランザクション)

Two-Phase Commitは複数の参加リソースを一つの確定判断で扱う方式です。coordinatorが参加branchの準備結果と最終決定を管理します。PREPAREは利用者への最終成功応答ではなく、未解決のprepared / in-doubt状態が残ることがあります。

掲載例5の注意: MySQL XAのSTART → END → PREPARE → COMMITという順序で二段階確定を進めます。ただし下記は1branchの概要で、固定のtx1を再利用する運用例でも全参加者を管理する完全な実装でもありません。「コミット可能性を保証」はprepared状態への移行を示し、全DBで既に確定済み・必ず短時間で完了という意味ではありません。「失敗時はXA ROLLBACK」を通信失敗後の無条件操作と読まないでください。coordinatorの決定・XID・参加者の状態を照合し、決定後の独断取消や再送を避けます。MySQLのXA RECOVERはprepared状態の照合用であり、一覧だけで業務成功を断定できません。Oracle 19cはOracle XA library / 対応driverをtransaction managerから利用し、このMySQL SQL列を直接使いません。PostgreSQLの二段階確定はPREPARE TRANSACTIONとCOMMIT PREPARED / ROLLBACK PREPAREDで、max_prepared_transactions等の設定と外部managerによる管理が必要です。JTAという名前だけではXA対応datasourceやcoordinatorが自動構成されるわけではありません。

-- MySQL XA (例)
XA START 'tx1';
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
XA END 'tx1';

XA PREPARE 'tx1';                -- 第1段階: コミット可能性を保証
-- 別のDBでも同様の PREPARE を実行
XA COMMIT 'tx1';                 -- 第2段階: 確定
-- 失敗時は XA ROLLBACK 'tx1';

-- Java EE / Spring の JTA で透明に利用可能

言語別 commit() メソッド

Java JDBC

掲載例6の注意: JDBC Connectionの既定auto-commitはtrueで、Oracle接続でもDBの利用者COMMITとこの既定を分けます。例はsetAutoCommit(false)で単独transactionを管理しますが、commitのSQLExceptionが「確定していない」とは限りません。catch内のrollbackも失敗し得て、確定済み処理を取り消す証明にはなりません。元の例外・要求IDを保持し成否を照合してから再試行を判断します。この旧例はexecuteUpdateの戻り件数を確認していないため、0件成功を業務成功にしない分岐も必要です。実装ではstatementのcloseや初期化失敗も扱い、pool / framework管理接続へ勝手なcommitや設定切替を追加しません。

Connection conn = DriverManager.getConnection(url, user, pass);
conn.setAutoCommit(false);       // 明示 COMMIT モード
try {
    PreparedStatement ps = conn.prepareStatement("UPDATE accounts SET balance = balance - ? WHERE id = ?");
    ps.setBigDecimal(1, new BigDecimal("100"));
    ps.setLong(2, 1L);
    ps.executeUpdate();
    conn.commit();               // 確定
} catch (SQLException e) {
    conn.rollback();             // 巻き戻し
    throw e;
} finally {
    conn.close();
}

PHP PDO

掲載例7の注意: PDOのbeginTransaction / commit / rollBackというAPI比較です。driverと表がtransactionをサポートする必要があり、MySQL / Oracleの通常DDLを途中へ混ぜると暗黙COMMITで取消境界が変わります。commitの失敗・通信断では成否不明を別に扱い、inTransaction等で残る状態を確認してrollbackの二次例外で元の障害を失わない実装にします。rollback成功やfalseの状態だけから、応答を失ったCOMMITの不成立を証明することはできません。

$pdo = new PDO($dsn, $user, $pass, [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
]);

$pdo->beginTransaction();
try {
    $pdo->prepare('UPDATE accounts SET balance = balance - ? WHERE id = ?')
        ->execute([100, 1]);
    $pdo->commit();              // 確定
} catch (\Throwable $e) {
    $pdo->rollBack();
    throw $e;
}

Python (psycopg2 / sqlite3 / mysql-connector)

掲載例8の注意: 見出しは複数driverの比較入口ですが、コード自体はpsycopg2専用です。autocommitは既定Falseで、必要時にdriverがtransactionを開始します。PostgreSQLサーバーの「明示block外の文は成功時確定」と矛盾しません。接続しただけでSQLのBEGINが全clientで不要になるわけでもありません。sqlite3 / mysql-connectorへパラメータ記法や既定設定をそのまま移植しません。commit応答不明とrollbackの二次失敗はJDBC / PDOと同様に分離し、二重減算を起こす無条件の再実行を避けます。

import psycopg2
conn = psycopg2.connect(dsn)
conn.autocommit = False          # 既定で False
cur = conn.cursor()
try:
    cur.execute("UPDATE accounts SET balance = balance - %s WHERE id = %s", (100, 1))
    conn.commit()                # 確定
except Exception:
    conn.rollback()
    raise
finally:
    cur.close()
    conn.close()

COMMIT のパフォーマンスチューニング

Oracle 19cではCOMMIT WRITEのWAIT / NOWAIT(応答時点)とIMMEDIATE / BATCH(redo書込み方式)を分けます。WAITは対応redoの永続化後に戻り、NOWAITでは成功応答後でも未書込み分を障害で失い得ます。句を省略した場合の有効なCOMMIT_WAIT / COMMIT_LOGGING設定も確認します。BATCHによるgroup commitは複数transactionのredoをまとめ得るため、行数・確定要求数と物理I/O回数は同じではありません。調査のために耐久性設定を緩めることは勧めません。

  • 毎行COMMITは確定要求・待機を増やす場合がありますが、1000行・1000transactionが物理fsync 1000回と一致するとは限りません。group commitやログ・storage設定、同時実行負荷を区別します
  • バッチCOMMITは要求回数を減らせる一方、lock保持・取消範囲・再試行単位も変えます。1000行は最適値ではなく、業務の原子性を優先して同条件の遅延・throughputを比較します。固定倍率や所要時間は保証しません
  • PostgreSQLのsynchronous_commit=offはcommit成功報告のWAL永続化待ちを省くもので、fsync=offとは異なります。直近の成功報告済みtransactionをクラッシュで失う可能性がありますが、損失窓を固定の秒数にはできません。fsync無効化は破損リスクも別に持ち、安易な代替策にしません
  • MySQLのinnodb_flush_log_at_trx_commitは1で各commit時にredoのwrite / flush、2ではcommit時writeと周期flush、0では周期write / flushが基本です。周期はtimeout設定・実スケジューリング等に依存し、0 / 2では未永続化transactionを障害で失い得ます。1でもstorageがflush要求を正しく満たすこと等が前提で、binlogのsync_binlogやreplica待機は別の設定です。「0が最速」「1なら全障害で無損失」とは保証しません

FAQ

Q: COMMIT 後にやっぱり巻き戻したい
A: 確定済みの変更を通常のROLLBACKで取り消すことはできません。補償更新、backupとログを使った復旧、製品固有の履歴・復旧機能等は別の操作です。同時更新・外部送信・採番まで完全に元通りになる保証はなく、対象範囲と復旧条件を確認します。

Q: COMMIT 中にDBクラッシュしたら?
A: WAL / REDO等は復旧の基盤ですが、ログの永続化条件・損傷・backupの有無によって結果は変わり、全障害からの復旧や一定時間での再開は保証できません。Oracleでもredo書込み後・成功応答前の障害ではclientが確定成否を判断できない場合があります。例外やtimeoutを「未確定」と読み替えて更新を無条件再送すると、成功済みの減算等を重ねる危険があります。

Q: AUTOCOMMIT は ON / OFF どちらが良い?
A: 単独文を確定したいか、複数文を一つの業務単位にするかで決めます。MySQLのsession変数、SQL*Plus / psqlのclient設定、JDBC / PDO / psycopg2のAPIは別物です。frameworkが管理している場合はその境界に従い、全アプリへ一律OFFやSQL文字列のSET AUTOCOMMIT=0を追加しません。

実務での確認手順: まずDB製品・版、接続client / driver、transactionの管理者、autocommit、DDLの混在と同期設定を既存の接続設定・記録から確認します。更新は業務キーと要求IDで追跡し、実更新件数・制約と業務結果を確定前に確認します。0件更新もSQL成功になり得るため、例外がないことだけで業務成功としません。取消を選ぶ場合は未確定の範囲を確認し、接続終了を取消手順の代わりにしません。

成功応答を失った場合: 同じ要求の再送を止め、要求ID・接続先・エラーコード・COMMIT送信の有無を秘密値抜きで保存します。接続が回復しても、新しい接続のROLLBACKで以前の接続を取り消すことはできません。業務キーと同一transactionで記録した処理済み要求、決済記録等の正式な照合元で結果を確認し、replicaの遅延や照合権限・同時処理も考慮します。記録がないことだけで未実行と断定せず、成否を確認できない間は保留・担当者確認へ進めます。冪等キーと一意制約等の再送設計は事前に整え、XAならcoordinatorの決定記録と参加branchを照合します。ここで示した掲載例はその仕組みを実装していません。

根拠と適用範囲

2026-10-27に一次公式資料で確認。中心はOracle Database 19c、比較はMySQL 8.4 / PostgreSQL 18、APIはJDBC Java SE 25 / PHP PDO / psycopg2です。仕様照合と実機実行は別で、全RU・driver・配備設定の保証ではありません。

子ページ

子ページはありません

同階層のページ
  1. COMMIT (トランザクション制御)
  2. ROLLBACK
  3. SAVEPOINT

最近更新/作成されたページ