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

SQL to Check for Long-Running Open Transactions in SQL Server

公開日 2026-08-13 · 更新日 2026-08-13 · 最終検証日 2026-08-13

結論

You can identify long-running open transactions by joining `sys.dm_tran_active_transactions` with `sys.dm_tran_session_transactions` and sorting by the oldest `transaction_begin_time`. Adding `sys.dm_exec_sessions` also reveals which login and application is responsible. The identification SQL is read-only, but forcibly terminating a session with `KILL` is a high-risk operation that triggers a rollback.

この文書の適用条件

対象製品SQL Server / Amazon RDS for SQL Server / Azure SQL Managed Instance
確認バージョンSQL Server 2008 and later
適用環境On-premises, EC2, Amazon RDS, Azure
必要権限The read-only SQL requires VIEW SERVER STATE. `DBCC OPENTRAN` requires sysadmin or db_owner. `KILL` requires ALTER ANY CONNECTION (or processadmin / sysadmin)
実行影響The read-only SQL makes no changes. `KILL` forcibly terminates a session and rolls back any uncommitted transaction
再起動Not required
最終検証日2026-08-13

そのまま実行できるコマンド

List of open transactions (start time, session, most recent SQL)参照のみ
対象
SQL Server 2008 and later / Amazon RDS for SQL Server
権限
VIEW SERVER STATE
変更作業
None (read-only)
Production実行
Safe to run
-- 対象: 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;

Using `CROSS APPLY sys.dm_exec_sql_text(...)` would drop sessions whose handle cannot be retrieved. To avoid missing any abandoned sessions, this uses `OUTER APPLY` instead. A session where `session_status` is sleeping and `open_transaction_count` is 1 or more is the typical "abandoned BEGIN TRAN" pattern.

Identify only the single oldest transaction参照のみ
対象
SQL Server 2008 and later / Amazon RDS for SQL Server
権限
VIEW SERVER STATE
変更作業
None (read-only)
Production実行
Safe to run
-- 対象: 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;

When the transaction log is not being released (`log_reuse_wait_desc = ACTIVE_TRANSACTION`), this "oldest transaction" is the very first thing you need. Log after this point cannot be truncated.

Currently executing statement and wait state (sys.dm_exec_requests)参照のみ
対象
SQL Server 2008 and later / Amazon RDS for SQL Server
権限
VIEW SERVER STATE
変更作業
None (read-only)
Production実行
Safe to run
-- 対象: 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;

Use this to determine whether a session found in the first query "is still executing something, or has finished executing and only has an open transaction left." If `status` is running/suspended, it is still processing; if `sys.dm_exec_requests` has no row for it, processing has finished and only the transaction remains.

Quick check of the target database's oldest transaction (DBCC OPENTRAN)参照のみ
対象
SQL Server 2008 and later / Amazon RDS for SQL Server
権限
sysadmin fixed server role or db_owner fixed database role
変更作業
None (read-only)
Production実行
Safe to run
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: sysadmin または db_owner
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
USE [SampleDB];
GO
DBCC OPENTRAN;

Returns information about the oldest active transaction in the target database, and any transactions not yet distributed by replication. If there is no open transaction, it returns a message to the effect of "no active open transactions." It carries less detail than the DMVs, but lets you grasp the situation with a single statement.

Forcibly terminate a session (last resort — requires approval)
対象
SQL Server 2008 and later / Amazon RDS for SQL Server
権限
ALTER ANY CONNECTION, or processadmin / sysadmin
変更作業
Yes (forcibly terminates the session and rolls back any uncommitted transaction)
Production実行
Not allowed as a rule. Confirm the scope of impact and obtain business sign-off before running
-- 対象: SQL Server 2008 以降 / Amazon RDS for SQL Server
-- 権限: ALTER ANY CONNECTION / processadmin / sysadmin
-- 変更作業: あり(セッション強制終了 → 未コミットトランザクションのロールバック)
-- Production 実行: 原則不可。業務影響の確認と承認を得てから実行すること
-- 57 は前掲のクエリで特定した session_id に置き換える
KILL 57;

-- 既にロールバック中のセッションについて進捗率を確認する
KILL 57 WITH STATUSONLY;

`KILL` only starts the rollback; the time to completion is proportional to the amount of change the original transaction made. Forcibly terminating a long-running update can make the rollback take even longer. `WITH STATUSONLY` only returns progress for a session already rolling back.

結果の読み方

意味確認するポイント
transaction_begin_timeTransaction start timeWhether the gap from the current time is implausibly long for the business process
open_secondsSeconds the transaction has been open (computed)Hundreds of seconds to hours strongly suggests it has been abandoned
transaction_type1 = read/write / 2 = read-only / 3 = system / 4 = distributed1 and 4 block log release; 2 has little impact
transaction_state2 = active / 3 = ended as read-only / 7 = rolling backIf it stays at 7, it is already rolling back — repeated KILLs won't speed that up
open_transaction_countNumber of open transactions on that session2 or more means nested transactions remain open
session_statusSession status (running / sleeping, etc.)Sleeping with an open transaction is the typical abandoned pattern
program_name / host_name / login_nameOriginating application, host, and loginIdentifies which application is responsible — useful for deciding who to route the fix to
last_statementThe last SQL executed on that connectionCheck for the pattern of a BEGIN TRAN with no matching commit
blocking_session_idID of the blocking sessionA nonzero value means you need to trace the blocking chain further

こういう状況で使います

  • The transaction log is not being released, and `log_reuse_wait_desc` stays fixed at ACTIVE_TRANSACTION
  • Updates to a specific table are blocked for long periods, causing frequent timeouts
  • Restarting the application temporarily resolves it, but it recurs after a while
  • Lock-waiting sessions pile up and the connection count approaches its limit

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

  1. 01

    The application does not commit or roll back after BEGIN TRAN

    If exception handling has a path where neither commit nor rollback is reached, the transaction remains open even after the connection returns to the pool. This shows up as `session_status` being sleeping while a transaction is still open.

  2. 02

    A transaction was left open from an interactive tool

    This happens when someone runs `BEGIN TRAN` in a management tool and walks away without closing the window. You can identify this by `program_name`.

  3. 03

    A rollback of a large update is in progress

    If `transaction_state = 7`, it is already rolling back. There is no way to shorten this state other than waiting — repeated `KILL`s will not speed it up.

  4. 04

    An unresolved distributed transaction remains open

    A distributed transaction (`transaction_type = 4`) depends on the state of the coordinator (MS DTC). Database-side operations alone may not resolve it.

  5. 05

    Application-side timeout and DB-side wait are out of sync

    Even if the client times out and abandons the operation, the server-side transaction does not end automatically — it remains until the connection is closed.

確認手順

  1. 1

    List open transactions

    参照のみ

    Run the first SQL and check entries with the largest `open_seconds` first.

  2. 2

    Identify the oldest transaction

    参照のみ

    If log release has stopped, the single oldest transaction is the cause. Narrow it down with the second SQL.

  3. 3

    Determine whether it is still processing or abandoned

    参照のみ

    Check whether `sys.dm_exec_requests` has a row for that session. No row means processing has finished and only the transaction remains.

  4. 4

    Trace the blocking chain

    参照のみ

    Follow `blocking_session_id` to identify the session at the root of the chain. Stopping anything other than the root will not resolve it.

  5. 5

    Identify the originating application

    参照のみ

    Use `program_name`, `host_name`, and `client_net_address` to determine which application and server the connection is coming from.

  6. 6

    Check whether it recurs at the same time of day

    参照のみ

    Cross-reference against execution history to see whether it coincides with a scheduled batch.

対応方法

すぐに実施できる低リスクの対応

  • Have the responsible application commit or roll back

    Ending the transaction through the application's normal code path is the safest option. Coordinate with the operations team to let that process complete.

  • Check first whether it is already rolling back

    参照のみ

    If `transaction_state = 7`, it is already rolling back. Check progress with `KILL ... WITH STATUSONLY` and wait for completion. An additional `KILL` accomplishes nothing.

事前検討が必要な変更

  • Fix the application's exception handling

    Use a try/finally-equivalent structure so a commit or rollback always runs. This is the most reliably effective fix to prevent recurrence.

  • Shorten the scope of the transaction

    Redesign the code so the transaction never spans an external API call or a wait for user input.

  • Add monitoring for long-running transactions

    参照のみ

    Set up detection and alerting for sessions where `open_seconds` exceeds a threshold, based on the longest legitimate batch duration.

  • Consider applying SET XACT_ABORT

    If there is a path where a runtime error leaves a transaction half-finished, consider applying `SET XACT_ABORT ON`. This changes the behavior of existing processing, so verify it in a test environment first.

再起動・サービス影響を伴う変更

  • Forcibly terminate the session (KILL)

    Uncommitted changes will be rolled back. The rollback can take as long as, or longer than, the original operation, and the log remains unreleased throughout. This is a last resort that requires business sign-off.

  • Manually resolve a distributed transaction

    専門家レビュー必須

    An unresolved distributed transaction requires checking the state on the coordinator side. Forcibly resolving it from the database side alone can break consistency, so this assumes expert review.

!注意事項

  • `KILL` rolls back an uncommitted transaction. The log is not released and table locks are not freed until the rollback completes — stopping it does not necessarily mean an immediate fix.
  • Repeating `KILL` against a session where `transaction_state = 7` (already rolling back) will not speed up the process. Check progress with `WITH STATUSONLY` and wait.
  • In a blocking chain, stopping the tail end without identifying the root session changes nothing. Always trace `blocking_session_id` back to its origin.
  • Do not run `KILL` against system transactions (`transaction_type = 3`) or internal sessions.
  • `sys.dm_exec_sql_text` returns the text of the entire batch. To see the statement currently executing, you need to extract it using `statement_start_offset` / `statement_end_offset`.

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

SQL Server 2008 and laterAll the DMVs used in this article (`sys.dm_tran_active_transactions`, `sys.dm_tran_session_transactions`, `sys.dm_exec_sessions`, `sys.dm_exec_connections`, `sys.dm_exec_requests`) are available.
Amazon RDS for SQL ServerThe read-only DMVs and `KILL` are available. However, since RDS-managed system sessions exist, filter on `is_user_transaction = 1` before judging.
Azure SQL DatabaseServer-scoped DMVs have restrictions. Whether you can get equivalent information at the database scope depends on the target service's specifications (verify before relying on this).

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

  • Breakdown of lock waits

    Check `sys.dm_tran_locks` to see which resource has which lock mode held against it.

  • The application's connection pool settings

    Check whether the transaction is reset when a connection returns to the pool, and the pool's max size and wait timeout.

  • Execution history of batch jobs

    Check `msdb.dbo.sysjobhistory` for any job running at the same time.

  • Isolation level settings

    Check the application-side configuration for whether a higher-than-default isolation level is being held for a long time.

この文書の根拠と限界

製品の公式ドキュメントに基づく説明

A general procedure based on the public specifications of SQL Server's dynamic management views (`sys.dm_tran_active_transactions`, `sys.dm_tran_session_transactions`, `sys.dm_exec_sessions`, `sys.dm_exec_connections`, `sys.dm_exec_requests`), the dynamic management function `sys.dm_exec_sql_text`, and `DBCC OPENTRAN` / `KILL`. It does not include any specific customer's environment or measured values.

よくある質問

Can this be run in production?

The four SQL statements used for listing and identification (including `DBCC OPENTRAN`) are read-only and can be run in production. `KILL` is a change operation that rolls back an uncommitted transaction, so it requires confirming the scope of impact and obtaining business sign-off first.

Does this work on AWS RDS?

Yes. Every DMV in this article can be queried on Amazon RDS for SQL Server, and `KILL` can also be run there. Filter on `is_user_transaction = 1` so you do not accidentally target a system session managed by RDS.

What permissions are required?

The read-only SQL requires VIEW SERVER STATE. `DBCC OPENTRAN` requires sysadmin or db_owner on the target database; `KILL` requires ALTER ANY CONNECTION (or processadmin / sysadmin).

Why does it not finish even after I run KILL?

`KILL` is a command that starts a rollback; the time to completion depends on how much data the original transaction changed. `transaction_state = 7` indicates a rollback in progress, and waiting is the only option in that state.

How should I interpret the results?

If `open_seconds` clearly exceeds the longest legitimate processing time for the business, and `sys.dm_exec_requests` has no row for that session, you are looking at a case where "processing has finished but the transaction is still open." That is what needs to be addressed.

この文書がカバーする質問

  • Detecting abandoned BEGIN TRAN sessions
  • I want to find uncommitted transactions in SQL Server
  • I want to identify the transaction preventing the log from being released
  • I want to find the originating session of a blocking chain

リスク表示の意味

  • 参照のみデータと設定を変更しません。
  • 影響は限定的ですが、権限と負荷の確認が必要です。
  • 性能・ロック・コストに影響する可能性があります。
  • 障害・データ損失・復旧作業が発生する可能性があります。
  • 専門家レビュー必須本番適用前に別途レビューが必須です。

GIIPの対応範囲

An abandoned transaction has the property that no one notices it the moment it happens — by the time it surfaces as log exhaustion or blocking, the business process has already stopped. At GIIP, we periodically pull transaction open-duration data across multiple databases, and once a threshold is crossed, an AI agent identifies the responsible session and originating application before notifying the person in charge. High-impact operations like `KILL` are never run automatically — judgment and approval remain a human responsibility.

執筆・技術検証

GIIP プロダクション運用チーム

大規模Webサービス、SQL Server、Oracle、AWS、Azureの設計・移行・運用に約30年従事。x12largeクラスのAWS RDS for SQL Server環境12セット、約12万テーブルのOracle環境、約3TBのTiDBからAurora MySQLへの移行を経験。現在も複数のクラウドデータベースと約30のWebサービスを、AIエージェントと人間の専門家が継続的に監視・運用しています。

関連するナレッジ

関連サービス

Design monitoring for long-running transactions

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

Design monitoring for long-running transactions

ナレッジベース一覧へ