You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

含DROP TABLE的代码导致DBCC SHRINKFILE超时阻塞的排查求助

排查DROP TABLE导致DBCC SHRINKFILE阻塞的步骤
  • 检查NHibernate事务的显式提交逻辑
    NHibernate默认会为修改类操作(包括DDL如DROP TABLE)启动隐式事务,若任务代码中未显式提交事务,该事务会持续持有锁。

    • 确认执行DROP TABLE的代码块是否用using包裹事务并完成提交:
      using (var session = SessionFactory.OpenSession())
      using (var tx = session.BeginTransaction())
      {
          session.CreateSQLQuery("DROP TABLE TargetTable").ExecuteUpdate();
          tx.Commit(); // 必须显式提交,否则事务会挂起
      }
      
    • 排查是否存在FlushMode设置为Auto或Always导致的隐式事务未提交情况,可在执行DDL后强制调用session.Flush()和事务提交。
  • 验证Hangfire任务的事务活跃状态
    在DROP TABLE执行后、DBCC SHRINKFILE执行前,添加代码查询当前会话的事务状态:

    • 通过NHibernate API检查:session.Transaction.IsActive,若返回true说明事务未提交。
    • 通过SQL查询系统视图确认:
      SELECT t.transaction_id, t.session_id, t.transaction_begin_time
      FROM sys.dm_tran_session_transactions t
      JOIN sys.dm_exec_sessions s ON t.session_id = s.session_id
      WHERE s.program_name LIKE '%Hangfire%' -- 匹配Hangfire的会话标识
      

    对比SSMS执行时的结果,SSMS默认自动提交模式,DROP TABLE后事务会立即结束。

  • 分析锁持有情况
    当任务执行到DROP TABLE后暂停(可临时加延迟),立即执行以下查询查看锁状态:

    SELECT request_session_id, resource_type, request_mode, resource_description
    FROM sys.dm_tran_locks
    WHERE request_session_id = (SELECT @@SPID FROM [当前Hangfire任务的数据库连接])
    

    若存在SCH_M模式的锁(DROP TABLE会申请该锁)且未释放,说明事务未提交,这会直接阻塞DBCC SHRINKFILE(收缩需要文件级的锁,与SCH_M锁冲突)。

  • 排查Hangfire的Session/连接复用问题
    确认Hangfire任务是否复用了全局的NHibernate Session或数据库连接:

    • 若任务使用共享Session,之前的操作可能残留未提交的事务,导致DROP TABLE被加入同一事务,锁无法释放。
    • 确保每个Hangfire任务都创建独立的Session实例,执行完成后显式关闭:session.Close()或用using自动释放。
  • 绕过NHibernate事务执行DDL
    尝试直接用ADO.NET连接执行DROP TABLE,绕过NHibernate的事务管理,验证是否还会阻塞:

    using (var conn = new SqlConnection("你的连接字符串"))
    {
        conn.Open();
        using (var cmd = new SqlCommand("DROP TABLE TargetTable", conn))
        {
            cmd.ExecuteNonQuery();
        }
    }
    

    若此方式下SHRINKFILE不再阻塞,说明问题出在NHibernate的事务管理逻辑上。

  • 检查异常处理中的事务回滚
    排查任务代码的try-catch块,确保异常发生时事务被正确回滚:

    using (var session = SessionFactory.OpenSession())
    using (var tx = session.BeginTransaction())
    {
        try
        {
            session.CreateSQLQuery("DROP TABLE TargetTable").ExecuteUpdate();
            // 其他操作
            tx.Commit();
        }
        catch (Exception ex)
        {
            tx.Rollback(); // 异常时必须回滚,避免事务挂起
            throw;
        }
    }
    

    若异常发生后未回滚,事务会持续持有锁,导致后续SHRINKFILE阻塞。

内容的提问来源于stack exchange,提问作者Staša Sekulić

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 04:41:02