SQL Server 2008中通过DBCC OPENTRAN和会话查询事务

本文介绍如何使用DBCC OPENTRAN命令在SQL Server 2008中查找最早活动的事务,以及利用动态管理视图(DMV)来进一步分析这些事务的状态和相关信息。

SQL Server 2008中SQL应用系列--目录索引

无论是有意无意,如果事务在数据库中保持打开,则它会阻塞其他进程对修改后的数据进行操作。同样,对事务日志进行备份也只会截断不活动事务的那部分事务日志,所以打开的事务会导致日志变多(甚至达到物理限制),直到事务被提交或回滚。

要找到最早的活动事务,可以使用DBCC OPENTRAN命令。详细用法见MSDN:http://msdn.microsoft.com/zh-cn/library/ms182792.aspx

给出一个示例:

 

执行结果:

 

结果显示了最早活动日志的相关信息,包括服务器进程ID、用户ID、和事务的开始时间。关键是SPID和Start Time。
拥有这些信息后,可以使用动态管理视图(DMV)来检验正在执行的T-SQL,以及在必要时关闭这个过程
DBCC OPENTRAN对于孤立连接(在数据库中是打开的,但与应用程序或客户端已经断开的连接)是非常有用的,并能帮助我们找出遗漏了COMMIT或ROLLBACK的事务。该命令也返回在指定数据库内存在最早的活动事务和最早的分布式和非分布式复制事务。如果没有活动事务,则显示信息性消息,而不返回会话级数据。

我们看一个实例:

 

这是一个未提交的事务,在另一个查询窗口执行如下:

 

执行结果:

返回会话ID后,可以通过sys.dm_exec_connections和sys.dm_exec_sql_text来挖掘最近执行的查询的详细信息。

 

这个查询返回最后执行的语句。也可以使用sys.dm_exec_requests。

因为也从sys.dm_tran_session_transactions的第一个查询中得知事务ID,所以可以使用sys.dm_tran_active_transactions来了解更多事务本身的内容

 

 

小结:这里演示了使用DMV 排除故障和调查长时间的活动事务的一般技巧。基本步骤如下:
1、查询sys.dm_tran_session_transactions获取会话ID和事务ID之间的映射。
2、查询sys.dm_exec_connectionssys.dm_exec_sql_text查找会话最新执行的命令(most_recent_sql_Handle列)
3、最后,查询sys.dm_tran_active_transactions确定事务被打开了多少时间、事务的类型和事务的状态。

使用这个技巧可以回到应用程序去查明调用的被抛弃的事务(打开但从未提交)以及那些运行时间太长或对于应用程序来说是不必要的不恰当事务。

 

邀月注:本文版权由邀月和优快云共同所有,转载请注明出处。
助人等于自助!   3w@live.cn

 

 

<think>我们已知用户执行了`DBCC OPENTRAN(tempdb)`显示没有打开的事务,但tempdb仍然增长过快。根据引用内容之前的分析,我们需要从其他方面排查。 可能原因: 1. **版本存储问题**:虽然`DBCC OPENTRAN`没有显示活动事务,但版本存储可能因为长时间运行的快照事务而累积。注意,`DBCC OPENTRAN`可能无法显示所有版本存储相关的事务状态。 2. **日志文件设置不当**:tempdb的日志文件在达到70%使用率时才会触发检查点,如果日志文件初始设置过大,可能导致空间无法及时回收。 3. **系统缓存未释放**:SQL Server缓存了IAM页,导致空间无法释放。 4. **用户对象过度使用**:临时变量或查询操作(如排序、哈希连接)占用了大量空间。 根据引用[1][3],即使没有活动事务,版本存储区也可能因为快照事务的保留而占用空间。引用[2]提到了通过`DBCC FREESYSTEMCACHE`释放缓存来收缩tempdb的方法。引用[4]则指出tempdb的并发分配可能导致系统争用,但这不是空间增长的原因,而是性能问题。 因此,我们重点排查以下方向: 步骤1:检查版本存储区的使用情况 步骤2:检查tempdb日志文件大小空间使用情况 步骤3:检查用户对象内部对象占用的空间 步骤4:释放系统缓存并尝试收缩(注意:生产环境收缩需谨慎) 具体操作: 1. **检查版本存储区**: 使用以下查询查看版本存储区的使用情况: ```sql SELECT DB_NAME(database_id) as DatabaseName, reserved_page_count, reserved_space_kb FROM sys.dm_tran_version_store_space_usage WHERE database_id = DB_ID('tempdb'); -- 注意:版本存储区在tempdb中,但这里database_id指的是原始数据库 -- 但是,这个DMV从SQL Server 2016开始提供,如果版本存储区很大,说明有数据库启用了快照隔离并且有大量版本存储。 ``` 另外,检查是否有长时间运行的快照事务(即使没有活动事务,也可能有未完成的快照事务): ```sql SELECT transaction_id, transaction_sequence_num, commit_sequence_num, is_snapshot, elapsed_time_seconds FROM sys.dm_tran_active_snapshot_database_transactions ORDER BY elapsed_time_seconds DESC; ``` 2. **检查tempdb文件使用情况**: ```sql -- 查看tempdb数据文件日志文件的空间使用 SELECT name, type_desc, size/128.0 as CurrentSizeMB, FILEPROPERTY(name, 'SpaceUsed')/128.0 as UsedSpaceMB, growths = growth/128 FROM tempdb.sys.database_files; ``` 如果日志文件(type_desc='LOG')的UsedSpaceMB远小于CurrentSizeMB,但日志文件很大,那么可能是因为日志文件初始设置过大,导致没有达到70%的使用率而无法触发检查点。这时可以考虑在非高峰时段收缩日志文件。 3. **检查用户对象内部对象**: ```sql -- 查看tempdb的空间使用情况 SELECT SUM(user_object_reserved_page_count) * 8 / 1024.0 AS user_objects_MB, SUM(internal_object_reserved_page_count) * 8 / 1024.0 AS internal_objects_MB, SUM(version_store_reserved_page_count) * 8 / 1024.0 AS version_store_MB, SUM(unallocated_extent_page_count) * 8 / 1024.0 AS free_space_MB FROM sys.dm_db_file_space_usage; ``` 根据结果,可以判断是用户对象、内部对象还是版本存储占用了大量空间。 4. **释放系统缓存并收缩**(如果确定需要收缩): 如果发现是系统缓存导致无法收缩,可以尝试以下操作(注意:释放系统缓存可能会影响性能,生产环境需谨慎): ```sql USE tempdb; DBCC FREESYSTEMCACHE ('ALL'); -- 然后收缩文件 DBCC SHRINKFILE (N'templog', 500); -- 收缩日志文件到500MB DBCC SHRINKFILE (N'tempdev', 1024); -- 收缩数据文件到1024MB ``` 5. **检查当前占用tempdb的会话**: ```sql -- 查看当前会话的tempdb使用情况 SELECT session_id, internal_objects_alloc_page_count * 8 / 1024 as internal_objects_MB, user_objects_alloc_page_count * 8 / 1024 as user_objects_MB FROM sys.dm_db_session_space_usage WHERE (internal_objects_alloc_page_count > 0 OR user_objects_alloc_page_count > 0); ``` 6. **检查任务级分配**(可能更精确): ```sql SELECT session_id, SUM(internal_objects_alloc_page_count) * 8 / 1024 as internal_objects_MB, SUM(user_objects_alloc_page_count) * 8 / 1024 as user_objects_MB FROM sys.dm_db_task_space_usage GROUP BY session_id HAVING (SUM(internal_objects_alloc_page_count) > 0 OR SUM(user_objects_alloc_page_count) > 0); ``` 综合以上排查,我们可以确定tempdb增长的主要原因,并采取相应措施。 注意:在解决问题后,应持续监控tempdb的增长情况,并考虑优化应用程序,减少对tempdb的过大使用。 如果版本存储是问题所在,需要检查哪些数据库启用了快照隔离,并优化事务(避免长时间运行的事务)。如果是用户对象或内部对象,需要检查相关的查询(如使用临时、排序、哈希连接等),并优化查询或调整索引。 最后,如果增长过快是由于日志文件设置过大,那么调整日志文件初始大小为合理值(例如初始500MB,按100MB增长)可以避免空间无法回收的问题。 根据引用[2],我们还可以在收缩前尝试释放缓存,这样可能有助于收缩。 由于用户已经排除了活动事务(通过DBCC OPENTRAN),我们应重点考虑版本存储、日志文件设置系统缓存。 总结原因: 1. **版本存储**:即使没有活动事务,也可能因为快照事务的保留策略而占用空间(引用[1])。 2. **日志文件设置过大**:导致日志空间无法及时重用(引用[2]中提到tempdb日志重用机制)。 3. **系统缓存**:未释放的缓存阻止了空间回收(引用[2])。 因此,请按照上述步骤逐一排查。 注意:在SQL Server中,tempdb的日志文件数据文件是分开的,所以需要分别检查。 如果以上方法都无法解决,可能需要进一步分析具体的查询系统负载。 </think> ### TempDB 增长过快的原因分析(无活动事务时) 虽然 `DBCC OPENTRAN(tempdb)` 显示无活动事务,但 TempDB 仍可能快速增长的常见原因如下: #### 1. **版本存储区堆积**(主要嫌疑)[^1][^3] 即使没有活动事务,**行版本控制机制**仍可能在 TempDB 中保留数据版本: - 当数据库启用 `READ_COMMITTED_SNAPSHOT` 或 `SNAPSHOT_ISOLATION` 时 - **长时间运行的查询**会阻止版本清理(即使事务已提交) - **未提交的只读事务**也可能阻塞版本回收 ```sql -- 检查版本存储区使用情况 SELECT DB_NAME(database_id) AS SourceDB, reserved_page_count * 8 / 1024.0 AS VersionStore_MB FROM sys.dm_tran_version_store_space_usage WHERE reserved_page_count > 0; ``` #### 2. **日志文件设置过大**(关键因素)[^2] TempDB 日志文件重用规则特殊: - **重用条件**:日志使用率 > 70% 时才触发检查点 - **典型问题**:初始日志文件设置过大(如 100GB),导致空间无法回收 ```sql -- 检查日志空间使用率 USE tempdb; SELECT name, size/128.0 AS Size_MB, FILEPROPERTY(name, 'SpaceUsed')/128.0 AS Used_MB, (FILEPROPERTY(name, 'SpaceUsed') * 1.0 / size) * 100 AS Usage_Percent FROM sys.database_files WHERE type = 1; -- 日志文件 ``` #### 3. **系统缓存未释放** [^2] SQL Server 缓存 IAM 页可能阻碍空间回收: ```sql -- 检查缓存状态 SELECT * FROM sys.dm_os_memory_cache_entries WHERE type = 'CACHESTORE_TEMPTABLES'; -- 解决方案:释放缓存后收缩 DBCC FREESYSTEMCACHE ('ALL'); DBCC SHRINKFILE (N'templog', 500); -- 缩至500MB ``` #### 4. **用户对象未释放** 临时对象可能因连接中断未清理: ```sql -- 查看占用空间的会话 SELECT session_id, user_objects_MB = (user_objects_alloc_page_count * 8) / 1024.0, internal_objects_MB = (internal_objects_alloc_page_count * 8) / 1024.0 FROM sys.dm_db_session_space_usage WHERE user_objects_alloc_page_count > 0 OR internal_objects_alloc_page_count > 0; ``` #### 5. **并发分配瓶颈**(间接影响)[^4] 虽然不直接导致增长,但会加剧问题: - 高频创建/删除临时导致系统页(SGAM/PFS)争用 - 现为空间回收延迟而非实际增长 --- ### 排查流程图 ```mermaid graph TD A[TempDB增长但无活动事务] --> B{日志使用率<70%?} B -- 是 --> C[收缩日志文件] B -- 否 --> D{版本存储>0?} D -- 是 --> E[检查快照隔离事务] D -- 否 --> F{缓存占用高?} F -- 是 --> G[DBCC FREESYSTEMCACHE] F -- 否 --> H[分析用户对象] ``` > **紧急处理建议**: > 1. 立即收缩过大的日志文件: > ```sql > USE tempdb; > DBCC SHRINKFILE (templog, 500); -- 替换实际文件名 > ``` > 2. 检查版本存储保留策略: > ```sql > SELECT snapshot_isolation_state_desc FROM sys.databases > WHERE name NOT IN ('master','tempdb'); > ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值