giip
SES案件登録
SQL Serverトランザクションロック障害対応ログファイル

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)参照のみ
対象
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 放置」です。

最も古いトランザクションを1件だけ特定する参照のみ
対象
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`)ときに真っ先に必要になるのが、この「最古のトランザクション」です。これより後ろのログは切り捨てできません。

現在実行中のステートメントと待機状況(sys.dm_exec_requests)参照のみ
対象
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` に行が無ければ処理は終わっておりトランザクションだけが残っています。

対象データベースの最古トランザクションを簡易確認する(DBCC OPENTRAN)参照のみ
対象
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_type1=読み書き / 2=読み取り専用 / 3=システム / 4=分散1 と 4 はログ解放を阻害する。2 は影響が小さい
transaction_state2=アクティブ / 3=読み取り専用として終了 / 7=ロールバック中7 が続く場合は既にロールバック処理中で、KILL を重ねても早くならない
open_transaction_countそのセッションで開いているトランザクション数2以上ならネストしたトランザクションが残っている
session_statusセッションの状態(running / sleeping など)sleeping かつトランザクションが開いている状態が典型的な放置
program_name / host_name / login_name接続元アプリケーション・ホスト・ログインどのアプリケーションが原因かを特定する。改修依頼先の判断材料になる
last_statementその接続で最後に実行されたSQLBEGIN TRAN の後にコミットが無いパターンかを確認する
blocking_session_idブロックしているセッションID0 以外ならブロッキングの連鎖を遡る

こういう状況で使います

  • トランザクションログが解放されず、`log_reuse_wait_desc` が ACTIVE_TRANSACTION のまま変わらない
  • 特定テーブルへの更新が長時間ブロックされ、タイムアウトが多発する
  • アプリケーションを再起動すると一時的に解消するが、しばらくすると再発する
  • ロック待ちのセッションが積み上がり、接続数が上限に近づく

考えられる原因(可能性の高い順)

  1. 01

    アプリケーションが BEGIN TRAN 後にコミット/ロールバックしていない

    例外処理でコミットもロールバックも通らない経路があると、接続がプールに戻ってもトランザクションが残ります。`session_status` が sleeping なのにトランザクションが開いている状態で観測されます。

  2. 02

    対話的なツールからトランザクションを開いたまま放置している

    管理ツールで `BEGIN TRAN` を実行したまま画面を閉じずに離席するケースです。`program_name` で判別できます。

  3. 03

    大量更新のロールバックが進行中

    `transaction_state = 7` の場合、既にロールバック中です。この状態は待つ以外に短縮する手段がなく、`KILL` を重ねても速くなりません。

  4. 04

    分散トランザクションが未解決のまま残っている

    `transaction_type = 4` の分散トランザクションは、調整役(MS DTC)側の状態に依存します。データベース側の操作だけでは解消しない場合があります。

  5. 05

    アプリケーション側のタイムアウトと DB 側の待機が噛み合っていない

    クライアントがタイムアウトして処理を打ち切っても、サーバー側のトランザクションは自動では終わりません。接続が切れるまで残ります。

確認手順

  1. 1

    開いているトランザクションを一覧化する

    参照のみ

    1つ目のSQLを実行し、`open_seconds` の大きいものから確認します。

  2. 2

    最古のトランザクションを特定する

    参照のみ

    ログ解放が止まっている場合は、最古の1件が原因です。2つ目のSQLで絞り込みます。

  3. 3

    処理中か放置かを切り分ける

    参照のみ

    `sys.dm_exec_requests` に該当セッションの行があるかを確認します。行が無ければ処理は終わっており、トランザクションだけが残っています。

  4. 4

    ブロッキングの連鎖を遡る

    参照のみ

    `blocking_session_id` を辿り、連鎖の起点になっているセッションを特定します。起点以外を止めても解決しません。

  5. 5

    接続元アプリケーションを特定する

    参照のみ

    `program_name`、`host_name`、`client_net_address` から、どのアプリケーション・どのサーバーからの接続かを確認します。

  6. 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` で切り出す必要があります。

バージョン・環境による違い

SQL Server 2008 以降本記事で使用するDMV(`sys.dm_tran_active_transactions`、`sys.dm_tran_session_transactions`、`sys.dm_exec_sessions`、`sys.dm_exec_connections`、`sys.dm_exec_requests`)はいずれも利用できます。
Amazon RDS for SQL Server参照系DMVと `KILL` は使用できます。ただし RDS 側で管理されるシステムセッションが存在するため、`is_user_transaction = 1` で絞り込んでから判断してください。
Azure SQL DatabaseサーバースコープのDMVには制限があります。データベーススコープで同等の情報を取得できるかは、対象サービスの仕様を確認してください(要確認)。

これで解決しない場合に確認すること

  • ロック待ちの内訳

    `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エージェントと人間の専門家が継続的に監視・運用しています。

関連するナレッジ

関連サービス

長時間トランザクションの監視を設計する

同じ確認を複数の環境で継続する必要がある場合は、運用体制ごと相談できます。

長時間トランザクションの監視を設計する

ナレッジベース一覧へ