SQL Server トランザクションの基本と実務活用を理解しよう
トランザクションは、複数の処理を「ひとまとまりの1単位」として扱い、すべて成功した場合はCOMMIT、失敗した場合はROLLBACKで取り消す仕組みです。
大量データ更新・在庫引当・銀行処理など、実務システムでは欠かせない重要な概念です。
SQL Server のトランザクション設計では、以下のACID特性を満たすことが基本となります。
- Atomicity(原子性): 全処理が成功するか、すべて取り消されるか
- Consistency(一貫性): 常に整合性の取れた状態に保つ
- Isolation(独立性): 他の処理と干渉せず実行される
- Durability(永続性): COMMIT後の変更は永続的に保存される
目次
トランザクションとは
トランザクションは、複数 SQL を「不可分の1セット」として扱うことで整合性を維持する仕組みです。
在庫処理、決済、履歴登録など、複数の更新がセットで成立すべき業務では必須となります。
BEGIN TRANSACTION;
UPDATE dbo.Stock
SET Quantity = Quantity - 1
WHERE ProductId = 1001;
INSERT INTO dbo.OrderHistory (ProductId, OrderDate)
VALUES (1001, GETDATE());
COMMIT;
トランザクションの基本構文
BEGIN TRANSACTION;
-- 複数の SQL を安全に実行
UPDATE dbo.Employees
SET Salary = Salary * 1.1
WHERE DepartmentId = 10;
DELETE FROM dbo.Logs
WHERE CreatedAt < '2025-01-01';
-- 正常終了
COMMIT;
-- エラー時は明示的に ROLLBACK
ROLLBACK;
SQL Serverでは、例外処理を明確にするために、TRY...CATCH構文を使った実装が強く推奨されます。
エラーハンドリング(TRY...CATCH)
実務では、トランザクション中にエラーが発生した場合、必ずROLLBACKし、ログに記録する構成が必須です。
TRY...CATCHの基本構造
BEGIN TRY
BEGIN TRANSACTION;
-- メイン処理
UPDATE dbo.Employees
SET Salary = Salary * 1.05
WHERE DepartmentId = 8;
COMMIT;
END TRY
BEGIN CATCH
ROLLBACK;
-- エラー詳細取得
SELECT ERROR_MESSAGE(), ERROR_LINE(), ERROR_NUMBER(), ERROR_PROCEDURE();
END CATCH;
ログテーブルへの記録(実務で最も一般的な形式)
BEGIN TRY
BEGIN TRANSACTION;
-- 処理
UPDATE dbo.Stock
SET Quantity = Quantity - 5
WHERE ProductId = 3001;
COMMIT;
END TRY
BEGIN CATCH
ROLLBACK;
INSERT INTO dbo.ErrorLog
(ErrorMessage, ErrorLine, ErrorProcedure, LoggedAt)
VALUES
(ERROR_MESSAGE(), ERROR_LINE(), ERROR_PROCEDURE(), GETDATE());
-- SQL Server 2012 以降は THROW を推奨
THROW;
END CATCH;
SQL Server 2012 以前では THROW が使えず、RAISERROR を利用する必要があります。
ロールバックできない操作
以下の操作は ROLLBACK できず即時確定(Auto-Commit) となる場合があります。
- CREATE(TABLE / VIEW / INDEX など)
- DROP(特に DROP DATABASE は完全不可逆)
- ALTER DATABASE の一部操作
- TRUNCATE TABLE(ログを書かないため取り消し不可)
DDLは基本的にトランザクションと相性が悪いため、構造変更はメンテナンス時間に行うべきです。
実務でのベストプラクティス
- ① トランザクションは短く保つ
長時間ロックにより他処理がブロックされる。 - ② TRY...CATCH で必ず ROLLBACK 保証
ログ出力と再スロー(THROW)で原因追跡を容易にする。 - ③ 不要な SELECT をトランザクション内に含めない
参照系もロックを保持し、競合が増える。 - ④ 大量更新時はバッチ分割を検討
ログ肥大化・ロック保持時間増加のリスク。 - ⑤ ネストトランザクションに注意
SQL Serverではネストしても実際には1つとして扱われる。
SQL Server バージョン依存の注意点
SQL Server のトランザクション動作には、いくつかバージョン依存の注意点があります。
① SQL Server 2012 以前は THROW が使えない
THROW は 2012 以降で導入。それ以前は RAISERROR を使用。
② SQL Server 2016 以降:TempDB の最適化
TempDB のマルチファイル最適化により、トランザクション中の一時テーブル利用でロック競合が減少。
③ SQL Server 2019:バッチモード最適化
大量データ処理のクエリが高速化され、大規模トランザクションの待機時間が短縮されるケースがある。
④ メモリ最適化テーブル(Hekaton)はロック動作が異なる
In-Memory OLTP を利用する場合、従来のロック方式とは異なるため、更新頻度の高いテーブルに有利。
実務で異なるバージョンを跨ぐシステムでは、特にこの章の内容を押さえておくとトラブルを避けやすくなります。
実務での利用ケース
🔹 説明ベースの例
- 銀行システム:入金と引き落としを同時に処理
- 在庫管理:在庫更新と注文履歴を同時確定
- 給与計算:対象社員の給与アップを一括実行
実務課題と回答例
課題1:在庫更新と履歴登録を1セットで実行せよ
BEGIN TRY
BEGIN TRANSACTION;
UPDATE dbo.Stock
SET Quantity = Quantity - 1
WHERE ProductId = 2001;
INSERT INTO dbo.OrderHistory (ProductId, OrderDate)
VALUES (2001, GETDATE());
COMMIT;
END TRY
BEGIN CATCH
ROLLBACK;
SELECT ERROR_MESSAGE();
END CATCH;
課題2:給与10%アップをトランザクションで安全に実行せよ
BEGIN TRY
BEGIN TRANSACTION;
UPDATE dbo.Employees
SET Salary = Salary * 1.1
WHERE DepartmentId = 5;
COMMIT;
END TRY
BEGIN CATCH
ROLLBACK;
SELECT ERROR_MESSAGE();
END CATCH;
課題3:ログ削除と管理テーブル更新を1セットで処理せよ
BEGIN TRY
BEGIN TRANSACTION;
DELETE FROM dbo.Logs
WHERE CreatedAt < DATEADD(DAY, -30, GETDATE());
UPDATE dbo.Settings
SET UpdatedAt = GETDATE()
WHERE Id = 1;
COMMIT;
END TRY
BEGIN CATCH
ROLLBACK;
SELECT ERROR_MESSAGE();
END CATCH;
まとめ
トランザクションは、SQL Serverの整合性と信頼性を支える最重要機能です。
- BEGIN → COMMIT / ROLLBACK の流れを理解する
- TRY...CATCH とログ記録で安全に運用する
- DDL は原則ROLLBACK不可であることを理解する
- バージョン依存の挙動を把握し、最適な設計をする
参考リンク

補足:トランザクションの設計には、「整合性」「ロック競合」「実行計画」「ログ肥大化」など複数の観点が必要です。実務で問題が出やすい箇所を理解しておくことで、安定したシステム運用に大きく寄与します。
※2025/11/13 更新
0 件のコメント:
コメントを投稿