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 |
そのまま実行できるコマンド
- 対象
- 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.
- 対象
- 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.
- 対象
- 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.
- 対象
- 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.
- 対象
- 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_time | Transaction start time | Whether the gap from the current time is implausibly long for the business process |
| open_seconds | Seconds the transaction has been open (computed) | Hundreds of seconds to hours strongly suggests it has been abandoned |
| transaction_type | 1 = read/write / 2 = read-only / 3 = system / 4 = distributed | 1 and 4 block log release; 2 has little impact |
| transaction_state | 2 = active / 3 = ended as read-only / 7 = rolling back | If it stays at 7, it is already rolling back — repeated KILLs won't speed that up |
| open_transaction_count | Number of open transactions on that session | 2 or more means nested transactions remain open |
| session_status | Session status (running / sleeping, etc.) | Sleeping with an open transaction is the typical abandoned pattern |
| program_name / host_name / login_name | Originating application, host, and login | Identifies which application is responsible — useful for deciding who to route the fix to |
| last_statement | The last SQL executed on that connection | Check for the pattern of a BEGIN TRAN with no matching commit |
| blocking_session_id | ID of the blocking session | A 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
考えられる原因(可能性の高い順)
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.
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`.
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.
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.
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
List open transactions
参照のみRun the first SQL and check entries with the largest `open_seconds` first.
- 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
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
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
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
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`.
バージョン・環境による違い
これで解決しない場合に確認すること
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エージェントと人間の専門家が継続的に監視・運用しています。
How to Check Transaction Log Usage on RDS for SQL Server
A read-only procedure that checks log usage with DBCC SQLPERF(LOGSPACE) and sys.dm_db_log_space_usage, and isolates the reason it is not being released using log_reuse_wait_desc.
sql-serverCauses and Checks for High CXPACKET Waits in SQL Server
A procedure for evaluating CXPACKET using sys.dm_os_wait_stats and sys.dm_os_waiting_tasks, distinguishing it from CXCONSUMER, and moving toward a review of the degree of parallelism.
sql-serverSQL to Check Statistics Last-Updated Time per Table in SQL Server
A read-only SQL script using sys.stats and STATS_DATE that lists the last-updated time and the number of rows modified since the last update, per table and statistic.
monitoringWhat to Configure When Monitoring Servers and Databases 24/7
A checklist, organized by layer, of what to monitor, how to think about thresholds, the escalation structure, and why synthetic monitoring is necessary when designing 24/7 monitoring.
関連サービス
Design monitoring for long-running transactions
同じ確認を複数の環境で継続する必要がある場合は、運用体制ごと相談できます。
Design monitoring for long-running transactions