ALTER PROCEDURE 不会清除执行计划缓存,需用 sp_recompile 标记重编译或通过 plan_handle 精准清除;直接 DBCC FREEPROCCACHE 风险高,生产环境应避免。

改完存储过程立刻执行,结果还是老样子——不是代码没改对,而是 SQL Server 正在复用缓存里的旧执行计划。
ALTER PROCEDURE 不会自动清缓存
SQL Server 编译并缓存存储过程的执行计划,后续调用默认复用。即使你用 ALTER PROCEDURE 更新了逻辑,只要原 plan_handle 还在 sys.dm_exec_cached_plans 里,就继续走旧路径。
- 验证方法:查
sys.dm_exec_procedure_stats,对比last_execution_time和你修改的时间,若明显滞后,说明缓存没刷新 - 常见现象:执行后返回数据、字段、甚至错误提示都和修改前一致,但
SELECT * FROM sys.procedures显示modify_date已更新 -
ALTER PROCEDURE只更新元数据和源码文本,不触发重编译,也不清理任何缓存项
优先用 sp_recompile 标记重编译
比直接清缓存更安全、副作用更小:它只标记目标存储过程为“下次执行时必须重编译”,不打断其他查询,也不引发 CPU 尖峰。
- 执行命令:
EXEC sp_recompile 'dbo.YourProcName' - 支持按表名调用(如
EXEC sp_recompile 'SalesOrderHeader'),会连带重编译所有引用该表的存储过程 - 重编译发生在下一次调用时,不影响当前连接或并发请求
- 生产环境首选方案;若仍无效,再考虑清除缓存
精准清除单个存储过程的缓存计划
避免误伤全局——DBCC FREEPROCCACHE 不加参数会清空所有数据库的所有计划,而 DBCC FLUSHPROCINDB 只能按库粒度清除。真正精准的方式是定位 plan_handle 后清除。
- 先查目标过程的缓存项:
SELECT plan_handle, cacheobjtype, objtype FROM sys.dm_exec_cached_plans cp CROSS APPLY sys.dm_exec_sql_text(cp.plan_handle) st WHERE st.objectid = OBJECT_ID('dbo.YourProcName') AND cp.objtype = 'Proc' - 再清除单个计划:
DBCC FREEPROCCACHE (0x060001002903DC0B4001B887000000000000000000000000)(把查到的plan_handle值填进去) - Azure SQL 和 SQL Server 2016+ 支持
WITH NO_INFOMSGS抑制输出,旧版本不识别该选项 - 注意:
sys.dm_exec_query_stats中的sql_handle对应语句级缓存,不能用于清除整个存储过程——必须用plan_handle
别在生产环境直接跑 DBCC FREEPROCCACHE
它会让所有查询首次执行变慢,并可能引发瞬时 CPU 高峰。真要清,得确认三件事:
- 当前负载低:检查
sys.dm_exec_requests是否有大量status = 'running'或长时间阻塞的会话 - 权限足够:需要
ALTER SERVER STATE,db_owner不够 - 确认是唯一解:比如已排除 SET 选项不一致(如
ANSI_NULLS ON/OFF)、统计信息陈旧、或跨库引用导致 objectid 为空等干扰因素
最易被忽略的是:缓存计划可能对应多个 plan_handle(比如不同 SET 上下文、不同参数类型隐式转换),只清一个不一定彻底——得结合 sys.dm_exec_cached_plans 多次验证是否还有残留。











