ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
| この記事の要点 |
|
SAVEPOINT とは
SAVEPOINT は SQL 標準で定義されたトランザクション制御命令で、トランザクション内に名前付きの "チェックポイント" を作成します。エラー発生時に SAVEPOINT まで部分的にロールバックでき、その後の処理は継続可能です。
通常の ROLLBACK はトランザクション全体を巻き戻すのに対し、ROLLBACK TO SAVEPOINT は指定地点までの巻き戻しに留まります。これにより複雑な業務処理の一部だけをやり直すことができます。
基本構文
-- 設置
SAVEPOINT sp_name;
-- 巻き戻し(SAVEPOINT 自体は残り、再利用可能)
ROLLBACK TO SAVEPOINT sp_name;
ROLLBACK TO sp_name; -- SAVEPOINT 省略可(多くの DB)
-- 解放(明示的に SAVEPOINT を消す)
RELEASE SAVEPOINT sp_name;
典型的な使用例
3 段階の処理を行い、2 段階目がエラーでも 1 段階目は維持したいケース:
BEGIN;
-- 1段階目: 顧客登録
INSERT INTO customers (id, name) VALUES (1, 'Alice');
SAVEPOINT after_customer;
-- 2段階目: 任意の住所登録(エラー許容)
INSERT INTO addresses (customer_id, addr) VALUES (1, 'Tokyo');
-- もし制約違反やビジネスロジックで失敗したら
ROLLBACK TO after_customer;
-- → addresses への INSERT は消える、customers は残る
-- 3段階目: ポイント付与(必須)
INSERT INTO points (customer_id, point) VALUES (1, 100);
COMMIT;
-- → customers と points は確定、addresses は無し
ROLLBACK との違い
| 命令 | 巻き戻し範囲 | トランザクションは継続するか |
|---|---|---|
ROLLBACK | BEGIN 以降すべて | 終了する |
ROLLBACK TO SAVEPOINT sp | SAVEPOINT 以降のみ | 継続する(再 COMMIT 可能) |
COMMIT | 巻き戻し無し(確定) | 終了する |
RELEASE SAVEPOINT sp | 巻き戻し無し(SAVEPOINT 削除のみ) | 継続する |
ネストして使う
BEGIN;
INSERT INTO orders VALUES (1, 'A');
SAVEPOINT sp1;
INSERT INTO orders VALUES (2, 'B');
SAVEPOINT sp2;
INSERT INTO orders VALUES (3, 'C');
SAVEPOINT sp3;
INSERT INTO orders VALUES (4, 'D');
ROLLBACK TO sp3;
-- 4 のみ消える。1,2,3 は残る
ROLLBACK TO sp2;
-- 3 も消える。1,2 が残る(sp3 も自動消滅)
COMMIT;
-- 1, 2 が確定
注意: ROLLBACK TO sp2 を行うと、sp2 より後に作られた sp3 は自動的に消滅します。これは SQL 標準で規定された動作です。
DBMS 別の対応状況
| DBMS | 対応 | 特記事項 |
|---|---|---|
| PostgreSQL | 完全対応 | SQL 標準準拠。ROLLBACK TO sp 形式 OK |
| MySQL / MariaDB | 対応(InnoDB のみ) | MyISAM は不可。SAVEPOINT / ROLLBACK TO / RELEASE |
| Oracle | 完全対応 | SAVEPOINT / ROLLBACK TO SAVEPOINT。RELEASE は無し(自動管理) |
| SQL Server | 対応(独自構文) | SAVE TRANSACTION sp / ROLLBACK TRANSACTION sp |
| SQLite | 対応 | SQL 標準準拠 |
| DB2 | 対応 | SAVEPOINT sp ON ROLLBACK RETAIN CURSORS |
SQL Server の独自構文
-- SQL Server は SAVE TRANSACTION
BEGIN TRANSACTION;
INSERT INTO orders VALUES (1, 'A');
SAVE TRANSACTION sp1;
INSERT INTO orders VALUES (2, 'B');
ROLLBACK TRANSACTION sp1; -- sp1 以降ロールバック
COMMIT TRANSACTION;
エラーハンドリングとリトライ
外部 API 呼び出しや楽観ロックなど、失敗の可能性がある処理は SAVEPOINT を挟むと安全です:
BEGIN;
INSERT INTO orders (id, total) VALUES (100, 5000);
SAVEPOINT before_payment;
BEGIN
-- 外部決済 API 呼び出し(失敗するかもしれない)
PERFORM call_payment_api(100);
EXCEPTION WHEN OTHERS THEN
ROLLBACK TO before_payment;
-- 失敗時は order を「未払い」状態で残す
UPDATE orders SET status = 'PAYMENT_FAILED' WHERE id = 100;
END;
COMMIT;
フレームワークでの利用
Spring (Java) のネストトランザクション
@Service
public class OrderService {
@Transactional
public void placeOrder(Order o) {
customerService.register(o.getCustomer());
try {
inventoryService.reserve(o); // NESTED
} catch (StockException e) {
// 在庫不足 → reserve だけ巻き戻し、registerは生きる
log.warn("Stock failure, continue without reservation");
}
}
}
@Service
public class InventoryService {
// 親トランザクションに SAVEPOINT を作る
@Transactional(propagation = Propagation.NESTED)
public void reserve(Order o) { ... }
}
Spring は Propagation.NESTED 指定時に内部で Connection#setSavepoint() を呼び、SAVEPOINT ベースのネストを実現します。
Laravel (PHP) のネストトランザクション
DB::transaction(function () {
DB::table('customers')->insert([...]);
try {
// ネスト = 内部で SAVEPOINT 発行
DB::transaction(function () {
DB::table('addresses')->insert([...]);
});
} catch (Throwable $e) {
// addresses INSERT のみロールバック
Log::warning('addr failed but continue');
}
DB::table('points')->insert([...]);
});
よくあるトラブル
| 症状 | 原因 | 対処 |
|---|---|---|
ERROR: SAVEPOINT can only be used in transaction blocks | BEGIN していない | 事前に BEGIN; |
savepoint "sp" does not exist | 既に ROLLBACK で消滅した SAVEPOINT を参照 | 名前を見直し |
| 自動コミットモードで動かない | クライアントが auto-commit ON | SET autocommit = 0; |
| MySQL で MyISAM テーブル | 非トランザクションエンジン | InnoDB へ変換 |
FAQ
Q: SAVEPOINT を多用しても性能に影響しない?
A: 軽微な影響はあります。InnoDB / PostgreSQL ともに、各 SAVEPOINT で内部状態を記録するためメモリ消費が増えます。常識的な数(数十程度)なら問題ありません。
Q: 同じ名前の SAVEPOINT を再度 SAVEPOINT 文で作るとどうなる?
A: 多くの DB で古い SAVEPOINT が消滅し、新しい位置に作り直される動作になります(PostgreSQL は両方残る独自仕様)。挙動が DB によって違うので、名前は使い回さないのが安全です。
Q: COMMIT したら SAVEPOINT は?
A: トランザクション内のすべての SAVEPOINT はCOMMIT / ROLLBACK と同時に消滅します。トランザクションをまたぐ SAVEPOINT は存在しません。
ページの作成
親となるページを選択してください。
親ページに紐づくページを子ページといいます。
例: 親=スポーツ, 子1=サッカー, 子2=野球
子ページを親ページとして更に子ページを作成することも可能です。
例: 親=サッカー, 子=サッカーのルール
親ページはいつでも変更することが可能なのでとりあえず作ってみましょう!
子ページはありません
- COMMIT (トランザクション制御)
- ROLLBACK
- SAVEPOINT
人気ページ
- 1 Eclipseで「サーバーに追加または除去できるリソースがありません。」の原因と対処法
- 2 tomcat の起動 / 停止ログと catalina.log・catalina.out の違い
- 3 JavaScript base URL 取得方法|window.location.origin と SSR/Node.js 対応
- 4 YouTube Data API v3 エラー一覧|403/400/404 の主要原因と切り分け
- 5 Spring Frameworkのアノテーション一覧
- 6 Laravel エラー一覧|500/Blade/DB 接続/ルーティングの代表エラー
- 7 3Dグラフィックスとは|モデリング/レンダリング/主要ソフトウェア (Blender / Maya)
- 8 【Spring】@Valueアノテーションとは
- 9 CATALINA_HOME の確認方法 (Linux / Mac)
- 10 【Spring】@Autowiredアノテーションとは
最近更新/作成されたページ
- IPv6とは|128bitアドレス・コロン16進表記/::省略・リンクローカル・SLAAC・デュアルスタック NEW 2026-06-22 12:34:44
- VPNとは|暗号トンネル・サイト間/リモートアクセス・IPsec/SSL-VPN/WireGuardを解説 NEW 2026-06-22 12:19:10
- MAC アドレスフィルタリングの仕組みと限界 | ネットワーク入門 NEW 2026-06-22 12:19:10
- gRPC とは HTTP/2 + Protocol Buffers の高速 RPC | ネットワーク入門 NEW 2026-06-22 12:17:25
- WebRTC とは ブラウザ間 P2P の音声・映像・データ通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/2 とは 多重化・HPACK・バイナリフレーム | ネットワーク入門 NEW 2026-06-22 12:17:25
- Web通信プロトコル入門 HTTP/2・HTTP/3・WebSocket・gRPC・WebRTC | ネットワーク入門 NEW 2026-06-22 12:17:25
- HTTP/3 (QUIC) とは UDP ベースの低遅延 Web 通信 | ネットワーク入門 NEW 2026-06-22 12:17:25
- WebSocket とは 全二重リアルタイム通信 ws/wss | ネットワーク入門 NEW 2026-06-22 12:17:25
- 証明書と認証局(CA)とは|X.509・信頼チェーン・DV/OV/EV・失効(CRL/OCSP)を解説 NEW 2026-06-22 12:17:24
- ファイアウォールとは|パケットフィルタ・ステートフル・DMZ・次世代FW(L4/L7)を解説 NEW 2026-06-22 12:17:24
- iptables/nftablesとは|テーブル・チェーン・ルール例・永続化をLinux視点で解説 NEW 2026-06-22 12:17:24
- HAProxy とは frontend/backend と設定例 | ネットワーク入門 NEW 2026-06-22 12:17:24
- CDN とは エッジキャッシュ・TTL・Cloudflare/CloudFront | ネットワーク入門 NEW 2026-06-22 12:17:24
- TLS/SSLの仕組み|ハンドシェイク・暗号スイート・前方秘匿性・証明書検証をわかりやすく解説 NEW 2026-06-22 12:17:24
コメントを削除してもよろしいでしょうか?