不能直接当应用层缓存用,但同一连接内可用本地临时表(#tmp)跳过重复查询;其生命周期限于当前会话,随连接结束自动销毁,需显式建表、避免全局临时表,并手动管理失效逻辑。

SQL Server 里 tempdb 临时表真能当缓存用?
不能直接当应用层缓存用,但配合存储过程+本地临时表(#tmp),确实能在**同一连接内多次调用时跳过重复查询**。关键在于:它只对当前会话有效,且生命周期随连接结束自动销毁。
常见错误现象:Invalid object name '#cache'——下一次调用存储过程时临时表已不存在;或者误以为多个用户共用同一个 #tmp,结果数据串了。
- 使用场景:报表类存储过程,需先查主表再关联多张维度表,且每次调用参数变化不大(如按天/按区域)
-
#tmp表结构必须显式定义(不能靠SELECT INTO隐式创建),否则下次执行可能因字段类型不一致报错 - 别用
##tmp(全局临时表),它会在所有会话间共享,极易引发并发脏读或删除冲突
PostgreSQL 怎么模拟“存储过程级缓存”?
PG 没有真正的存储过程级变量缓存机制,但可以用 CREATE TEMP TABLE + ON COMMIT PRESERVE ROWS 实现类似效果,前提是调用方在一个事务里多次执行该函数。
性能影响明显:首次执行建表+填充,后续直接 SELECT FROM temp_table,IO 和执行计划都省了;但如果事务太长,temp 表会一直占内存,尤其大数据量时容易触发 temp_buffers 不足告警。
- 必须在函数开头加
CREATE TEMP TABLE IF NOT EXISTS ... ON COMMIT PRESERVE ROWS - 填充前先
TRUNCATE,否则重复调用会累积数据 - 不能依赖
pg_tempschema 下的对象名做跨函数通信——每个会话的pg_temp是隔离的
MySQL 存储过程中用 @variable 缓存单值靠谱吗?
只适合缓存标量(比如配置项 ID、默认状态码),不适合结果集。因为 @variable 是会话级的,但存储过程退出后值不会自动清空,下次调用可能拿到上一次的残留值。
容易踩的坑:SET @cache_id = (SELECT id FROM config WHERE key = 'default_mode'); 如果子查询没结果,@cache_id 变成 NULL,后续用它做 WHERE id = @cache_id 就全漏了——MySQL 中 NULL = anything 永远为 FALSE。
- 每次使用前加判断:
IF @cache_id IS NULL THEN ... END IF; - 不要在循环里反复赋值又不重置,容易内存泄漏(虽然小,但积少成多)
- 别和
PREPARE/EXECUTE混用——动态 SQL 里引用@variable是可以的,但调试极难,出错信息不带变量上下文
缓存失效逻辑怎么写才不翻车?
没人帮你自动失效。所谓“缓存”,本质是你自己在存储过程中加的一层 if-else 判断 + 临时结构复用,失效完全靠人工控制时机。
最常被忽略的点:缓存内容依赖外部表数据,但你没监听这些表的变更。结果就是缓存永远不更新,业务查到的是三天前的统计值。
- 简单方案:加时间戳字段,在临时表里存
last_updated DATETIME,每次读前比对源表MAX(updated_at) - 复杂但可靠:用
sp_addextendedproperty(SQL Server)或COMMENT ON FUNCTION(PG)把缓存策略写进元数据,方便 DBA 审计 - 绝对禁止:把缓存逻辑写死在应用代码里调用存储过程——这会让数据库层失去对缓存生命周期的掌控权

















