最近项目上用户反馈查询一个报表半天跑不出来,提示“无法分配临时段”。我跑去数据库一看,临时表空间使用率100%。但奇怪的是,查了一圈,当前并没有大查询在运行。我想着是不是有会话没释放?就把所有会话都杀掉了。结果等了十几分钟,再一看,临时空间还是100%,一点没降。没办法,只能重启实例。问题暂时解决了,但我心里一直记着这事。
两周后,用户又找过来了,同样的报错,同样的症状。这次我意识到:不是偶然,肯定有更深的原因。
1、首先查看临时表空间是不是真的满了,执行:
SELECT
TOTAL_SIZE,
USED_SIZE,
(USED_SIZE/TOTAL_SIZE)*100 USED_PERCENT
FROM V$TEMPSPACE;
结果显示USED_SIZE确实接近TOTAL_SIZE,使用率98%,是真的满了。
2、再找找谁在占用
既然满了,肯定有会话在占用。我查了V$SESSIONS:
SELECT
SESS_ID,
SQL_TEXT,
TEMP_SPACE_USED/1024/1024 AS TEMP_USED_MB
FROM V$SESSIONS
WHERE TEMP_SPACE_USED > 0
ORDER BY TEMP_SPACE_USED DESC;
发现有几个会话占用了几百MB的临时空间,但SQL_TEXT字段是空的——说明这些会话已经没在跑SQL了,却还占着空间不释放。
我试着把这些会话杀掉:
SP_CLOSE_SESSION('会话ID');
杀掉后等了十几分钟,再看临时空间使用率,还是98%,一点没降。
这下真的懵了,会话都杀光了,空间怎么还不释放?
3、更深层次机制分析
实在没辙,我去求助了产品人员,说是有些老版本的达梦库,在临时空间回收的机制上可能和现在不太一样。
为了验证这个猜测,我在测试环境做了个试验:
1) 跑个大查询,让临时空间涨上去
2) 杀掉会话
3) 观察临时空间是否释放
结果和我生产环境一样——空间确实不释放。
我又找了个新一点的环境(V8.1.4.7),同样的操作,空间能正常释放。
这下我心里大概有数了:不同版本的行为确实不太一样,老版本遇到这种情况可能需要重启,新版本就好很多。
1、短期内添加监控,别等业务报错。比如写一个监控脚本,表空间超过阈值就告警。这样至少能在问题出现时第一时间知道,不用等业务报错。
#!/bin/bash
THRESHOLD=85 # 使用率超过85%告警
USED=$(disql -S SYSDBA/SYSDBA <<EOF
SELECT ROUND((USED_SIZE/TOTAL_SIZE)*100, 2) FROM V\$TEMPSPACE;
EOF
)
if [ $(echo "$USED > $THRESHOLD" | bc) -eq 1 ]; then
echo "临时表空间使用率已达 $USED%" | mail -s "告警:临时空间使用率过高" dba@company.com
fi
然后通过V$SYSTEM_LARGE_MEM_SQLS视图查出哪些sql占用临时空间较多,在这些sql上做性能优化,比如添加索引、该sql等。尽量减少临时空间的使用。
SELECT * FROM V$SYSTEM_LARGE_MEM_SQLS
ORDER BY MEM_USED_BY_KB DESC
LIMIT 10;
如果监控告警了,空间真的满了,业务又等不了,只能选业务低峰期重启实例。这是最后的手段,但至少是个退路。
2、长期来看,需要升级数据版本
把版本升级列入了后续的工作计划,等业务窗口合适的时候操作。
1、某些老版本的达梦库,SQL执行完并不是临时空间就释放了。
临时段的释放是“逻辑释放”,空间会被标记为“可重用”,但不一定立即归还给操作系统。这在大多数情况下没问题,但在某些场景下,会导致空间持续占用。
2、临时表空间不足会直接报“临时空间不足”
达梦的报错信息是-6403: 无法分配临时段。我第一次看到这个报错时,先去查了数据文件、表空间是不是满了,绕了一圈才发现是临时表空间的问题。
3、 日常监控真的不能少
临时表空间使用率建议设置告警阈值,不要等业务报错才发现。
4、版本差异要注意
不同版本的行为可能不一样,遇到问题可以先看看版本。
5、优化SQL才是根本
临时空间暴涨往往是因为SQL执行计划有问题,找到这些SQL并优化,比单纯扩容更有效。
6、该升级就升级
如果发现新版本确实解决了老问题,可以考虑升级。
文章
阅读量
获赞
