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

写入#temp的UPDATE语句在生产环境中突发挂起

分析与解决思路

哎,生产环境遇到这种突然挂起的问题确实闹心,明明单独跑查询返回0条记录,但一加上UPDATE就卡住,咱们来一步步拆解可能的原因和解决办法:

一、先排查锁阻塞问题

这是生产环境UPDATE挂起最常见的原因,哪怕没有符合条件的行,也可能因为其他事务持有锁导致进程等待:

  • 先找到当前UPDATE进程的会话ID,然后运行下面的SQL查看阻塞情况:
SELECT 
    blocking_session_id,
    session_id,
    command,
    wait_type,
    wait_time,
    resource_description
FROM sys.dm_exec_requests
WHERE session_id = <你的UPDATE进程ID>;

如果blocking_session_id不为0,说明这个进程被其他会话阻塞了,找到那个阻塞会话,看看是不是有长事务(比如未提交的修改、长时间运行的查询)占用了相关表的锁。

二、质疑NOLOCK带来的“假结果”

你单独跑查询时用了NOLOCK提示,这个提示会让查询读取未提交的数据,可能出现幻读或者脏读:

  • 试试不带NOLOCK重新跑查询,看看实际有没有符合条件的行:
SELECT STG.TRACKING_ID
FROM STAGE_TABLE STG
INNER JOIN STAGE_PRE_ACC PRE 
    ON PRE.ID=STG.ID AND PRE.CID=STG.CID 
WHERE PRE.STATUS = 'D' AND STG.ETLNBR < PRE.ETLNBR;

说不定你带NOLOCK查的时候没数据,但实际有其他事务正在修改PRE.STATUS为'D',导致UPDATE执行时试图锁定这些行,但被其他事务阻塞。

三、检查索引与执行计划

哪怕没有符合条件的行,如果表数据量大且没有合适的索引,UPDATE会做全表扫描,也可能导致长时间运行甚至挂起:

  • 查看UPDATE语句的执行计划,看看有没有全表扫描的情况,有没有索引缺失的警告。
  • 建议为关联和过滤字段创建索引,比如:
    • 在STAGE_PRE_ACC上建索引:CREATE NONCLUSTERED INDEX IX_PRE_STATUS_ID_CID_ETLNBR ON STAGE_PRE_ACC (STATUS, ID, CID, ETLNBR);
    • 在STAGE_TABLE上建索引:CREATE NONCLUSTERED INDEX IX_STG_ID_CID_ETLNBR ON STAGE_TABLE (ID, CID, ETLNBR);
      合适的索引能让数据库快速定位到符合条件的行,哪怕结果为空,也能快速结束扫描。

四、临时表的小概率问题

虽然临时表#TEMP是会话级的,但也可以试试改成表变量@TEMP,看看会不会有差异:

DECLARE @TEMP TABLE (TID INT); -- 根据实际字段类型调整
UPDATE STG SET STATUS = 'D' 
OUTPUT INSERTED.TRACKING_ID INTO @TEMP (TID) 
FROM STAGE_TABLE STG
INNER JOIN STAGE_PRE_ACC PRE 
    ON PRE.ID=STG.ID AND PRE.CID=STG.CID 
WHERE PRE.STATUS = 'D' AND STG.ETLNBR < PRE.ETLNBR;

五、其他排查点

  • 检查最近生产环境有没有做过 schema 变更(比如表结构修改、索引删除)。
  • 查看数据库的性能指标,比如CPU、IO是不是满了,导致进程无法正常执行。

内容的提问来源于stack exchange,提问作者Younus Mohammed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:30:01