SQL Serverで長時間開いたままのトランザクションを確認するSQL
公開日 2026-08-13 · 更新日 2026-08-13 · 最終検証日 2026-08-13
結論
長時間開いたままのトランザクションは、`sys.dm_tran_active_transactions` と `sys.dm_tran_session_transactions` を結合し、`transaction_begin_time` の古い順に並べれば特定できます。`sys.dm_exec_sessions` を足せば、どのログイン・どのアプリケーションが原因かまで分かります。特定用のSQLは参照専用ですが、`KILL` による強制終了はロールバックを伴う高リスク操作です。
この文書の適用条件
| 対象製品 | SQL Server / Amazon RDS for SQL Server / Azure SQL Managed Instance |
|---|---|
| 確認バージョン | SQL Server 2008 以降 |
| 適用環境 | オンプレミス、EC2、Amazon RDS、Azure |
| 必要権限 | 参照用SQLは VIEW SERVER STATE。`DBCC OPENTRAN` は sysadmin または db_owner。`KILL` は ALTER ANY CONNECTION(または processadmin / sysadmin) |
| 実行影響 | 参照用SQLは変更なし。`KILL` はセッションを強制終了し、未コミットのトランザクションをロールバックします |
| 再起動 | 不要 |
| 最終検証日 | 2026-08-13 |
そのまま実行できるコマンド
- 対象
- SQL Server 2008 以降 / Amazon RDS for SQL Server
- 権限
- VIEW SERVER STATE
- 変更作業
- なし(参照のみ)
- Production実行
- 可能
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: VIEW SERVER STATE
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SELECT
at.transaction_id,
at.name AS transaction_name,
at.transaction_begin_time,
DATEDIFF(SECOND, at.transaction_begin_time, GETDATE()) AS open_seconds,
at.transaction_type, -- 1:読み書き 2:読み取り専用 3:システム 4:分散
at.transaction_state, -- 2:アクティブ 3:終了(読み取り専用) 7:ロールバック中
st.session_id,
st.is_user_transaction,
st.open_transaction_count,
es.login_name,
es.host_name,
es.program_name,
es.status AS session_status,
es.last_request_start_time,
es.last_request_end_time,
ec.client_net_address,
ec.connect_time,
txt.text AS last_statement
FROM sys.dm_tran_active_transactions AS at
INNER JOIN sys.dm_tran_session_transactions AS st
ON at.transaction_id = st.transaction_id
LEFT JOIN sys.dm_exec_sessions AS es
ON st.session_id = es.session_id
LEFT JOIN sys.dm_exec_connections AS ec
ON st.session_id = ec.session_id
OUTER APPLY sys.dm_exec_sql_text(ec.most_recent_sql_handle) AS txt
WHERE st.is_user_transaction = 1
ORDER BY at.transaction_begin_time ASC;`CROSS APPLY sys.dm_exec_sql_text(...)` にすると、ハンドルが取得できないセッションが結果から落ちます。放置セッションの取りこぼしを避けるため、ここでは `OUTER APPLY` を使っています。`session_status` が sleeping で `open_transaction_count` が1以上のセッションが、典型的な「BEGIN TRAN 放置」です。
- 対象
- SQL Server 2008 以降 / Amazon RDS for SQL Server
- 権限
- VIEW SERVER STATE
- 変更作業
- なし(参照のみ)
- Production実行
- 可能
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: VIEW SERVER STATE
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SELECT TOP (1)
at.transaction_id,
at.transaction_begin_time,
DATEDIFF(SECOND, at.transaction_begin_time, GETDATE()) AS open_seconds,
st.session_id,
st.open_transaction_count,
es.login_name,
es.host_name,
es.program_name,
es.status AS session_status
FROM sys.dm_tran_active_transactions AS at
INNER JOIN sys.dm_tran_session_transactions AS st
ON at.transaction_id = st.transaction_id
LEFT JOIN sys.dm_exec_sessions AS es
ON st.session_id = es.session_id
WHERE st.is_user_transaction = 1
ORDER BY at.transaction_begin_time ASC;トランザクションログが解放されない(`log_reuse_wait_desc = ACTIVE_TRANSACTION`)ときに真っ先に必要になるのが、この「最古のトランザクション」です。これより後ろのログは切り捨てできません。
- 対象
- SQL Server 2008 以降 / Amazon RDS for SQL Server
- 権限
- VIEW SERVER STATE
- 変更作業
- なし(参照のみ)
- Production実行
- 可能
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: VIEW SERVER STATE
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SELECT
r.session_id,
r.status,
r.command,
r.blocking_session_id,
r.wait_type,
r.wait_time,
r.cpu_time,
r.total_elapsed_time,
r.open_transaction_count,
r.percent_complete, -- ROLLBACK など一部の操作で進捗率が入る
SUBSTRING(
t.text,
(r.statement_start_offset / 2) + 1,
((CASE r.statement_end_offset
WHEN -1 THEN DATALENGTH(t.text)
ELSE r.statement_end_offset
END - r.statement_start_offset) / 2) + 1
) AS running_statement
FROM sys.dm_exec_requests AS r
CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) AS t
WHERE r.session_id <> @@SPID
ORDER BY r.total_elapsed_time DESC;1つ目のクエリで拾ったセッションが「今も何かを実行しているのか、実行を終えてトランザクションだけ開いたままなのか」を切り分けます。`status` が running/suspended なら処理中、`sys.dm_exec_requests` に行が無ければ処理は終わっておりトランザクションだけが残っています。
- 対象
- SQL Server 2008 以降 / Amazon RDS for SQL Server
- 権限
- sysadmin 固定サーバーロール または db_owner 固定データベースロール
- 変更作業
- なし(参照のみ)
- Production実行
- 可能
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: sysadmin または db_owner
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
USE [SampleDB];
GO
DBCC OPENTRAN;対象データベースの最も古いアクティブトランザクションと、レプリケーション未配布トランザクションの情報を返します。開いたトランザクションが無い場合は「アクティブなオープン トランザクションはありません」という趣旨のメッセージが返ります。DMV より情報量は少ないですが、1文で状況を掴めます。
- 対象
- SQL Server 2008 以降 / Amazon RDS for SQL Server
- 権限
- ALTER ANY CONNECTION、または processadmin / sysadmin
- 変更作業
- あり(セッションを強制終了し、未コミットのトランザクションをロールバック)
- Production実行
- 原則不可。影響範囲を確認し、業務側の承認を得てから実行する
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: ALTER ANY CONNECTION / processadmin / sysadmin
-- 変更作業: あり(セッション強制終了 → 未コミットトランザクションのロールバック)
-- Production 実行: 原則不可。業務影響の確認と承認を得てから実行すること
-- 57 は前掲のクエリで特定した session_id に置き換える
KILL 57;
-- 既にロールバック中のセッションについて進捗率を確認する
KILL 57 WITH STATUSONLY;`KILL` はロールバックを開始するだけで、完了までの時間は元のトランザクションが行った変更量に比例します。長時間の更新を強制終了すると、ロールバックにそれ以上の時間がかかる場合があります。`WITH STATUSONLY` は既にロールバック中のセッションに対してのみ進捗を返します。
結果の読み方
| 列 | 意味 | 確認するポイント |
|---|---|---|
| transaction_begin_time | トランザクションの開始時刻 | 現在時刻との差が業務上ありえない長さになっていないか |
| open_seconds | 開いている秒数(算出値) | 数百秒〜数時間なら放置の可能性が高い |
| transaction_type | 1=読み書き / 2=読み取り専用 / 3=システム / 4=分散 | 1 と 4 はログ解放を阻害する。2 は影響が小さい |
| transaction_state | 2=アクティブ / 3=読み取り専用として終了 / 7=ロールバック中 | 7 が続く場合は既にロールバック処理中で、KILL を重ねても早くならない |
| open_transaction_count | そのセッションで開いているトランザクション数 | 2以上ならネストしたトランザクションが残っている |
| session_status | セッションの状態(running / sleeping など) | sleeping かつトランザクションが開いている状態が典型的な放置 |
| program_name / host_name / login_name | 接続元アプリケーション・ホスト・ログイン | どのアプリケーションが原因かを特定する。改修依頼先の判断材料になる |
| last_statement | その接続で最後に実行されたSQL | BEGIN TRAN の後にコミットが無いパターンかを確認する |
| blocking_session_id | ブロックしているセッションID | 0 以外ならブロッキングの連鎖を遡る |
こういう状況で使います
- トランザクションログが解放されず、`log_reuse_wait_desc` が ACTIVE_TRANSACTION のまま変わらない
- 特定テーブルへの更新が長時間ブロックされ、タイムアウトが多発する
- アプリケーションを再起動すると一時的に解消するが、しばらくすると再発する
- ロック待ちのセッションが積み上がり、接続数が上限に近づく
考えられる原因(可能性の高い順)
01
アプリケーションが BEGIN TRAN 後にコミット/ロールバックしていない
例外処理でコミットもロールバックも通らない経路があると、接続がプールに戻ってもトランザクションが残ります。`session_status` が sleeping なのにトランザクションが開いている状態で観測されます。
02
対話的なツールからトランザクションを開いたまま放置している
管理ツールで `BEGIN TRAN` を実行したまま画面を閉じずに離席するケースです。`program_name` で判別できます。
03
大量更新のロールバックが進行中
`transaction_state = 7` の場合、既にロールバック中です。この状態は待つ以外に短縮する手段がなく、`KILL` を重ねても速くなりません。
04
分散トランザクションが未解決のまま残っている
`transaction_type = 4` の分散トランザクションは、調整役(MS DTC)側の状態に依存します。データベース側の操作だけでは解消しない場合があります。
05
アプリケーション側のタイムアウトと DB 側の待機が噛み合っていない
クライアントがタイムアウトして処理を打ち切っても、サーバー側のトランザクションは自動では終わりません。接続が切れるまで残ります。
確認手順
- 1
開いているトランザクションを一覧化する
参照のみ1つ目のSQLを実行し、`open_seconds` の大きいものから確認します。
- 2
最古のトランザクションを特定する
参照のみログ解放が止まっている場合は、最古の1件が原因です。2つ目のSQLで絞り込みます。
- 3
処理中か放置かを切り分ける
参照のみ`sys.dm_exec_requests` に該当セッションの行があるかを確認します。行が無ければ処理は終わっており、トランザクションだけが残っています。
- 4
ブロッキングの連鎖を遡る
参照のみ`blocking_session_id` を辿り、連鎖の起点になっているセッションを特定します。起点以外を止めても解決しません。
- 5
接続元アプリケーションを特定する
参照のみ`program_name`、`host_name`、`client_net_address` から、どのアプリケーション・どのサーバーからの接続かを確認します。
- 6
同じ時間帯に再現するかを確認する
参照のみ定期バッチと同じ時刻に発生していないかを、実行履歴と突き合わせます。
対応方法
すぐに実施できる低リスクの対応
原因アプリケーション側でコミット/ロールバックを実行させる
低アプリケーションの正常な経路でトランザクションを終わらせるのが最も安全です。運用担当と連携して該当処理を完了させます。
ロールバック中かどうかを先に確認する
参照のみ`transaction_state = 7` なら既にロールバック中です。`KILL ... WITH STATUSONLY` で進捗率を確認し、完了を待ちます。追加の `KILL` は無意味です。
事前検討が必要な変更
アプリケーション側の例外処理を修正する
低try/finally 相当の構造でコミットまたはロールバックが必ず通るようにします。再発防止としては最も効果が確実な対応です。
トランザクションのスコープを短くする
低トランザクション内で外部API呼び出しやユーザー入力待ちを行わない設計に変更します。
長時間トランザクションの監視を追加する
参照のみ`open_seconds` が閾値を超えたセッションを検知して通知する仕組みを用意します。検知の閾値は業務の最長バッチ時間を基準に決めます。
SET XACT_ABORT の適用を検討する
中実行時エラーでトランザクションが中途半端に残る経路がある場合、`SET XACT_ABORT ON` の適用を検討します。既存処理の挙動が変わるため、検証環境での確認が必要です。
再起動・サービス影響を伴う変更
セッションを強制終了する(KILL)
高未コミットの変更はロールバックされます。ロールバックには元の処理と同等以上の時間がかかることがあり、その間もログは解放されません。業務側の承認を前提とした最終手段です。
分散トランザクションの手動解決
専門家レビュー必須未解決の分散トランザクションは調整役側の状態確認が必要です。データベース単独の判断で強制解決すると整合性を損なう可能性があるため、専門家の確認を前提とします。
!注意事項
- `KILL` は未コミットのトランザクションをロールバックします。ロールバック完了まではログも解放されず、テーブルのロックも保持されたままです。「止めればすぐ直る」とは限りません。
- `transaction_state = 7`(ロールバック中)のセッションに対して `KILL` を繰り返しても処理は早くなりません。`WITH STATUSONLY` で進捗を確認して待ちます。
- ブロッキングの連鎖では、起点のセッションを特定せずに末端を止めても状況は変わりません。`blocking_session_id` を必ず遡ってください。
- システムトランザクション(`transaction_type = 3`)や内部セッションを対象に `KILL` を実行しないでください。
- `sys.dm_exec_sql_text` が返すのはバッチ全体のテキストです。実行中のステートメントを見るには `statement_start_offset` / `statement_end_offset` で切り出す必要があります。
バージョン・環境による違い
これで解決しない場合に確認すること
ロック待ちの内訳
`sys.dm_tran_locks` で、どのリソースにどのモードのロックが掛かっているかを確認します。
アプリケーションの接続プール設定
接続がプールに戻る際にトランザクションがリセットされているか、プールの最大数と待機時間を確認します。
バッチジョブの実行履歴
`msdb.dbo.sysjobhistory` で、同時刻に稼働しているジョブの有無を確認します。
分離レベルの設定
既定より高い分離レベルを長時間保持していないか、アプリケーション側の設定を確認します。
この文書の根拠と限界
製品の公式ドキュメントに基づく説明
SQL Server の動的管理ビュー(`sys.dm_tran_active_transactions`、`sys.dm_tran_session_transactions`、`sys.dm_exec_sessions`、`sys.dm_exec_connections`、`sys.dm_exec_requests`)、動的管理関数 `sys.dm_exec_sql_text`、および `DBCC OPENTRAN` / `KILL` の公開仕様に基づく一般的な手順です。特定顧客の環境や実測値は含みません。
よくある質問
Productionで実行できますか?
一覧・特定に使う4つのSQL(`DBCC OPENTRAN` を含む)は参照専用で、本番環境で実行できます。`KILL` は未コミットのトランザクションをロールバックする変更操作のため、影響範囲の確認と業務側の承認を前提としてください。
AWS RDSでも使用できますか?
使用できます。本記事のDMVはすべて Amazon RDS for SQL Server で参照でき、`KILL` も実行できます。RDS が使用するシステムセッションを誤って対象にしないよう、`is_user_transaction = 1` で絞り込んでください。
どの権限が必要ですか?
参照用SQLには VIEW SERVER STATE が必要です。`DBCC OPENTRAN` は sysadmin または対象データベースの db_owner、`KILL` は ALTER ANY CONNECTION(または processadmin / sysadmin)が必要です。
KILLしても終わらないのはなぜですか?
`KILL` はロールバックを開始する命令であり、完了までの時間は元のトランザクションが変更したデータ量に依存します。`transaction_state = 7` はロールバック進行中を示し、この状態では待つのが唯一の対応です。
結果をどう判断しますか?
`open_seconds` が業務上の最長処理時間を明確に超えており、かつ `sys.dm_exec_requests` に該当セッションの行が無ければ「処理は終わっているのにトランザクションだけ残っている」状態です。これが対応対象になります。
この文書がカバーする質問
- BEGIN TRAN 放置セッションの検出
- SQL Serverで未コミットのトランザクションを探したい
- ログが解放されない原因のトランザクションを特定したい
- ブロッキングの起点セッションを見つけたい
リスク表示の意味
- 参照のみデータと設定を変更しません。
- 低影響は限定的ですが、権限と負荷の確認が必要です。
- 中性能・ロック・コストに影響する可能性があります。
- 高障害・データ損失・復旧作業が発生する可能性があります。
- 専門家レビュー必須本番適用前に別途レビューが必須です。
GIIPの対応範囲
放置トランザクションは、発生した瞬間には誰も気付かず、ログ枯渇やブロッキングとして表面化したときには既に業務が止まっている、という性質を持ちます。GIIP では複数のデータベースに対してトランザクションの開放時間を定期的に取得し、閾値を超えた時点でAIエージェントが該当セッションと接続元アプリケーションまで特定したうえで担当者に通知します。`KILL` のような影響の大きい操作は自動実行せず、判断と承認は人間が行う切り分けにしています。
執筆・技術検証
GIIP プロダクション運用チーム
大規模Webサービス、SQL Server、Oracle、AWS、Azureの設計・移行・運用に約30年従事。x12largeクラスのAWS RDS for SQL Server環境12セット、約12万テーブルのOracle環境、約3TBのTiDBからAurora MySQLへの移行を経験。現在も複数のクラウドデータベースと約30のWebサービスを、AIエージェントと人間の専門家が継続的に監視・運用しています。
RDS for SQL Serverでトランザクションログの使用率を確認する方法
ログ使用率を DBCC SQLPERF(LOGSPACE) と sys.dm_db_log_space_usage で確認し、解放されない理由を log_reuse_wait_desc で切り分ける参照専用手順です。
sql-serverSQL ServerでCXPACKET待機が多いときの原因と確認方法
sys.dm_os_wait_stats と sys.dm_os_waiting_tasks で CXPACKET を評価し、CXCONSUMER との区別を踏まえて並列度の見直しに進むための手順です。
sql-serverSQL Serverでテーブルごとの統計情報更新日時を確認するSQL
sys.stats と STATS_DATE で、テーブル・統計ごとの最終更新日時と更新後の変更行数を一覧化する参照専用SQLです。
monitoringサーバーとデータベースを24時間監視するときに設定する項目
24時間監視を設計する際の監視対象・しきい値の考え方・エスカレーション体制・外形監視の必要性を、層ごとに整理したチェックリストです。
関連サービス
長時間トランザクションの監視を設計する
同じ確認を複数の環境で継続する必要がある場合は、運用体制ごと相談できます。
長時間トランザクションの監視を設計する