- データベース
current transaction is abortedの原因と直し方
ERROR: current transaction is aborted, commands ignored until end of transaction block は、同じトランザクションの中で、すでに別のエラーが起きているときに出るエラーです。 PostgreSQL は、トランザクションの中で1つでもエラーが起きると、そのトランザクションを「失敗した状態」にし、ROLLBACK するまでほかの SQL をすべて受け付けません。
このエラーそのものは原因ではありません。本当の原因は、その前に出たエラーです。
| 手順 | やること |
|---|---|
| 1 | このエラーより前に出たエラー(ログ・例外)を探す。それが本当の原因 |
| 2 | 失敗したトランザクションを ROLLBACK する |
| 3 | 1件の失敗で全体を止めたくないなら、SAVEPOINT を使う |
確認環境:PostgreSQL 16.15、psql、Python 3.11(psycopg 3.3.6)、Java 21(PostgreSQL JDBC 42.7.2)、比較に MySQL 8.0.46(確認日 2026年10月11日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「current transaction is abortedの原因と直し方」
再現:psql で、途中の INSERT が失敗する
txdemo=> BEGIN;
BEGIN
txdemo=> INSERT INTO item VALUES (1, 'ぶどう', 300); ← id=1 はすでにある
ERROR: duplicate key value violates unique constraint "item_pkey"
DETAIL: Key (id)=(1) already exists.
txdemo=> SELECT 1; ← 何を実行しても
ERROR: current transaction is aborted, commands ignored until end of transaction block
txdemo=> COMMIT;
ROLLBACK ← COMMIT が ROLLBACK になった
最初の duplicate key が本当の原因で、そのあとの SQL は、SELECT 1 のような何の問題もない SQL でもすべてこのエラーになります。COMMIT を実行すると、応答が ROLLBACK になり、トランザクションの中で成功していた INSERT も含めて、すべて取り消されました。
本当の原因の探し方
| 方法 | 内容 |
|---|---|
| アプリのログで、このエラーの直前の例外を探す | 例外を catch してログを出さずに続けていると、最初のエラーが見つからない |
| PostgreSQL のサーバーのログ | 最初のエラーの SQL と内容が残る(ERROR: duplicate key ...) |
pg_stat_activity の state |
失敗したまま止まっている接続は idle in transaction (aborted) |
SELECT pid, state, left(query, 40) FROM pg_stat_activity WHERE usename = 'tx';
-- idle in transaction (aborted) | INSERT INTO item VALUES ($1, $2, 100)
query の列には、その接続が最後に実行した SQLが出ます。失敗の原因になった SQL の手がかりになります。
危険:例外を握りつぶすと、commit が成功に見えて何も保存されない
アプリで、エラーをログに出さずに処理を続けると、もっと見つけにくい形になりました。
Python(psycopg)
for i, name in [(6, "a"), (1, "dup"), (7, "b")]:
try:
cur.execute("INSERT INTO item VALUES (%s, %s, 100)", (i, name))
except psycopg.Error as e:
print("握りつぶした:", type(e).__name__)
conn.commit()
握りつぶした: UniqueViolation ← id=1 の本当のエラー
握りつぶした: InFailedSqlTransaction ← id=7 はこのエラーで入らなかった
commit: ok ← 例外にならない
id 6,7 の件数: 0 ← 成功したはずの id=6 も保存されていない
Java(JDBC)
id=6: ok
id=1: 23505 ERROR: duplicate key value violates unique constraint "item_pkey"
id=7: 25P02 ERROR: current transaction is aborted, commands ignored until end of transaction block
commit: ok ← 例外にならない
(保存された件数)0
Python も Java も、commit() は例外を出さずに終わり、実際には何も保存されていませんでした。 確認環境の psycopg 3.3.6 と PostgreSQL JDBC 42.7.2 では、どちらも同じ結果です。「エラーの行だけ飛ばして、残りは保存されたはず」と思い込みやすく、データが黙って消える形の不具合になります。
MySQL では動きが違う
同じ処理を MySQL(PyMySQL)で実行すると、id=1 だけが 1062(重複)で失敗し、id=6 と id=7 は保存されました。MySQL では、トランザクションの中でエラーになった文だけが失敗し、続きの SQL は実行できます。MySQL から PostgreSQL に移したアプリで、このエラーに初めて出会うことがよくあります。
直し方1:エラーが起きたら ROLLBACK して、やり直す
1件でも失敗したら全体を取り消してよい処理(振り込み・注文の確定など)は、エラーを受け取ったら ROLLBACK し、例外を呼び出し元に伝えます。握りつぶさないことが一番の対策です。
try:
with conn.transaction(): # 例外が起きたら自動で ROLLBACK
cur.execute(...)
cur.execute(...)
except psycopg.Error:
logger.exception("登録に失敗") # 最初のエラーを必ずログに残す
raise
直し方2:1件ずつ SAVEPOINT(失敗した行だけ飛ばす)
取り込みのように、失敗した行だけ飛ばして残りは保存したいときは、1件ごとに SAVEPOINT を置き、失敗したらその地点まで戻します(PostgreSQL 公式ドキュメントの SAVEPOINT の使い方)。
SQL(psql)
BEGIN;
INSERT INTO item VALUES (4, 'なし', 120);
SAVEPOINT sp1;
INSERT INTO item VALUES (1, 'ぶどう', 300); -- 失敗
ROLLBACK TO SAVEPOINT sp1; -- この1件だけ取り消す
INSERT INTO item VALUES (5, 'かき', 150);
COMMIT; -- 4 と 5 が保存された
Python(psycopg 3)
with conn.transaction():
for i, name in rows:
try:
with conn.transaction(): # 入れ子にすると SAVEPOINT になる
cur.execute("INSERT INTO item VALUES (%s, %s, 100)", (i, name))
except psycopg.errors.UniqueViolation as e:
print(f"id={i}: スキップ({e.diag.message_detail})")
id=6: ok
id=1: スキップ(Key (id)=(1) already exists.)
id=7: ok
保存された: [(6,), (7,)]
Java(JDBC)
for (int id : ids) {
Savepoint sp = con.setSavepoint();
try (PreparedStatement ps = con.prepareStatement("INSERT INTO item VALUES (?, 'x', 100)")) {
ps.setInt(1, id);
ps.executeUpdate();
con.releaseSavepoint(sp);
} catch (SQLException e) {
con.rollback(sp); // この1件だけ取り消す
log.warn("id=" + id + " をスキップ: " + e.getSQLState());
}
}
con.commit(); // 6 と 7 が保存された
PostgreSQL JDBC には、接続 URL に autosave=always を付けると、SQL ごとに自動で SAVEPOINT を置く設定もあります。確認環境でも、付けると id=6・7 が保存されました。ただし、すべての SQL に SAVEPOINT が増えるので、必要な処理に絞って使います。
psql で作業するとき:ON_ERROR_ROLLBACK
psql で手作業をしていて、打ち間違い1つでトランザクション全体が止まるのを避けたいときは、次の設定が便利です。
\set ON_ERROR_ROLLBACK interactive
BEGIN;
INSERT INTO item VALUES (2, 'みかん', 80); -- INSERT 0 1
INSERT INTO item VALUES (1, 'ぶどう', 300); -- ERROR: duplicate key ...(この文だけ取り消し)
INSERT INTO item VALUES (3, 'もも', 250); -- INSERT 0 1(続けられる)
COMMIT; -- COMMIT(2 と 3 が保存された)
interactive にすると、手で打っているときだけ有効になります。確認環境でも、同じ SQL をファイルから流し込んだときは有効にならず、通常どおり current transaction is aborted で止まり、COMMIT は ROLLBACK になりました。スクリプトでは、エラーで止まるほうが安全です。上の例は \set ON_ERROR_ROLLBACK on で確かめた結果です。
確認の手順(チェックリスト)
| 順番 | 確認すること | 方法 |
|---|---|---|
| 1 | 直前のエラー | アプリのログ・サーバーのログで、このエラーの前の ERROR を探す |
| 2 | 例外を握りつぶしていないか | except: pass・catch でログを出さずに続けている箇所 |
| 3 | commit で本当に保存されたか | 件数を数えて確かめる(commit は成功に見える) |
| 4 | 全体を取り消す処理か | 取り消すなら ROLLBACK して例外を伝える |
| 5 | 失敗した行だけ飛ばす処理か | SAVEPOINT(psycopg は conn.transaction() の入れ子、JDBC は setSavepoint) |
| 6 | 止まっている接続 | pg_stat_activity の idle in transaction (aborted) |
よくある質問
Q. 自動コミット(autocommit)にすれば出ませんか。 A. 出なくなります。1文ごとに確定するので、失敗した文だけが失敗します。ただし、複数の更新をまとめて取り消すことはできなくなるため、まとめて成功・失敗させたい処理には使いません。
Q. SQLSTATE は何ですか。
A. このエラーは 25P02 です。Java では getSQLState()、psycopg では InFailedSqlTransaction の例外として受け取れます。この SQLSTATE を見たら、ログをさかのぼって最初のエラーを探す、と覚えておきます。
まとめ
- トランザクションの中で先にエラーが起きると、以降の SQL はすべてこのエラー。本当の原因は直前のエラー
- psql の COMMIT は ROLLBACK になる。成功していた更新も消える
- Python(psycopg)と Java(JDBC)では commit が例外にならず、何も保存されなかった。握りつぶしは危険
- MySQL はエラーの文だけ失敗する。MySQL から移したアプリで出会いやすい
- 全体を取り消すなら ROLLBACK して例外を伝える、行だけ飛ばすなら SAVEPOINT
- 手作業の psql は
\set ON_ERROR_ROLLBACK interactive
参考・出典
確認日はいずれも 2026年10月11日です。
- PostgreSQL 16 Documentation「SAVEPOINT」:https://www.postgresql.org/docs/16/sql-savepoint.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「current transaction is abortedの原因と直し方」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。