
简介某银行DB2数据库因系统临时表空间异常增大而严重影响SQL执行性能的真实案例浓缩为一份doc技术复盘文档。文档面向DBA及数据库性能调优人员完整梳理了从监控到ACTIVE SESSION异常、常规资源排查无果到最终定位TEMPSPACE1达10GB的排障链条并展开临时表空间过大引发I/O下降、内存压力、LATCH竞争、磁盘排序增多等问题的机理。其中还详细介绍了如何借助db2top观察活动会话状态、利用db2pd和db2trc收集LATCH与堆栈信息、通过STACK分析定位SQL等操作要点以及优化SQL、调整排序参数、清理临时对象等实战处理手段。整个排障过程层次清晰从初步判断到根因确认均可直接对照操作。压缩包内为1个doc文件大小约607KB轻量易读目前已有5899人学习适合希望掌握DB2性能问题分析方法的运维人员。1. 系统临时表空间“过大”性能差的不一定是空间本身某个系统的批量任务结束后临时表空间使用率从20%飙到95%系统响应明显变慢重启数据库后使用率回落到个位数但磁盘占用却一直没有下降过两天同样的场景又出现一次。这个标题里的“过大”其实是两类问题一类是临时空间在运行时段被大量SQL占满另一类是表空间本身的物理配置或历史峰值把容量撑大了。前者往往不影响日常运行但后者会直接拖垮业务。这篇文章按一份外委交付文档该有的顺序展开先讲清楚系统临时表空间在DB2里到底在承载什么再给出一套从SQL定位到参数调整、再到空间收缩的排查路径最后把这些经验固化成可复用的巡检习惯。适合负责DB2运维的一线DBA也适合给刚接手这类系统的团队成员做参考。2. 系统临时表空间在 DB2 里到底装了什么三类写入者与三种“过大”2.1 临时表空间承载的中间结果排序、哈希连接与维护操作系统临时表空间System Temporary Tablespace不是给用户表放数据的地方它是数据库执行中间态操作时的暂存区和交换区。DB2在执行 ORDER BY、GROUP BY、DISTINCT、UNION 等需要排序的算子时如果数据量超过了每个排序操作可用的内存上限 SORTHEAP超出的部分就溢出到系统临时表空间。这也是绝大多数“临时空间打满”场景的来源。需要留意的是临时空间使用率高不一定代表SQL写得有问题也可能只是执行计划临时偏向了排序连接反过来一条看起来很小的查询如果统计信息过期优化器选错了连接方法同样会把临时空间瞬间打满。第二类写入者是哈希连接Hash Join。当两个表做等值连接且行数差异较大、连接列选择性不理想时优化器会选择在内存里构建哈希表构建表和探测过程中产生的溢出段、哈希桶都可能落到临时表空间。在多分区数据库环境里数据重分布Redistribute也会把中间结果写入临时表空间用量往往呈锯齿状变化。第三类是维护操作REORG、CREATE INDEX、LOAD 等过程需要在临时表空间生成临时对象这些对象在语句结束时自动清理但如果维护作业异常中断对象就可能滞留一段时间。临时对象在 SQL 语句结束后会立即释放所以正常情况下使用率是快速回落而不是缓慢回收。理解这一点很关键一个健康的临时表空间曲线应该是“日常很低高峰短暂冲高随后马上回落”。如果回落很慢或者高峰持续时间超出语句本身的执行时间说明有对象没有被正确释放问题就不单纯是排序量大小了。2.2 三类“过大”现象对应的判断命令把“过大”拆成三类配置过大、使用率过高、对象滞留不释放。配置过大指的是表空间初始分配很大或因为历史上的一次峰值触发自动扩展后文件系统里占用的空间没有再收回。它的特点是使用率低但磁盘占用高。使用率过高则是业务高峰段持续超过 85%或直接出现临时空间不足的错误这类是动态的需要定位高峰时段的会话和语句。对象滞留不释放是使用率长时间不回落或数据库里出现大量以临时表命名的对象。先查容量和当前使用率区分三类情况SELECT TBSP_NAME, TBSP_TYPE, CAST(TBSP_TOTAL_SIZE_KB / 1024 / 1024 AS DECIMAL(10,2)) AS TOTAL_GB, CAST(TBSP_USED_SIZE_KB / 1024 / 1024 AS DECIMAL(10,2)) AS USED_GB, CAST(TBSP_USABLE_SIZE_KB / 1024 / 1024 AS DECIMAL(10,2)) AS USABLE_GB, DECIMAL(TBSP_USED_SIZE_KB * 100.0 / NULLIF(TBSP_USABLE_SIZE_KB, 0), 5, 1) AS USED_PCT FROM SYSIBMADM.MON_TBSP_UTILIZATION WHERE TBSP_TYPE SYSTEM TEMPORARYTBSP_TOTAL_SIZE_KB 表示该表空间当前从存储分配的总容量单位 KBTBSP_USED_SIZE_KB 是实际有数据占用的容量TBSP_USABLE_SIZE_KB 是当前扩展策略下可以继续使用的逻辑容量。对于自动扩展的 DMS 表空间TOTAL 与 USABLE 的差异体现了扩展余量。如果你更关心已分配容量的占用率把分母换成 TBSP_TOTAL_SIZE_KB 即可。这里 USED_PCT 超过 90% 时要结合时间点判断是业务高峰导致的还是常态性使用。判断对象滞留用 db2pd 查看临时表空间上的对象状态db2pd -d dbname -tcbstats重点关注 T 开头的临时对象状态如果它们长时间处于活跃或等待状态说明释放被阻塞。判断排序溢出用快照中的 Sort overflows 字段db2 get snapshot for database on dbname | grep -E Sort overflows|Sort heap allocatedSort overflows 大于 0 是正常的但如果连续多次采样都在持续增长说明排序内存明显不够。Sort heap allocated 显示当前所有排序操作累计使用的内存可以和 SORTHEAP 的配置做对比判断是不是内存配置过小。2.3 把现场证据整理成外委交付文档的三层记录外委交付文档的核心不是技术结论而是决策过程。我写这类材料时会按三层结构记录现象层记录时间窗口、使用率曲线、错误日志和告警记录根因层记录通过哪条 SQL 定位、当时的执行计划、统计信息最后更新时间、锁记录变更层记录参数或 SQL 的改动内容、生效时间、后续观察周期的曲线。这三层记录的目的是让一个多月后接手的人不需要重新跑一遍排查流程就能直接开始验证。记录层应包含的内容用途现象层时间窗口、使用率曲线、错误日志、告警记录还原故障现场根因层定位 SQL、执行计划、统计信息时间、锁记录支撑根因判断变更层参数前后值、SQL 改动、生效时间、观察周期验证效果与回滚依据实际操作中我会额外做一张时间线表格把每个高峰时刻的 Top SQL 文本、临时空间峰值、是否触发过空间不足告警列在一起。这样接手的人能一眼看出规律是每天固定时段还是只在月末批量出现是同一类 SQL还是每次都不同。证据之间的关联比单个指标的绝对值更有判断价值。3. 从高耗 SQL 到参数调整临时表空间问题的完整处理路径3.1 用监控视图定位最耗临时空间的会话与 SQL 文本先跑一条查询看当前有哪些活动在消耗临时空间SELECT ACTIVITY_ID, ACTIVITY_STATE, APPL_ID, CAST(TEMP_TABLE_SPACE_TOP_KB / 1024 AS BIGINT) AS TEMP_TOP_MB, CAST(SORT_TOP_KB / 1024 AS BIGINT) AS SORT_TOP_MB, SUBSTR(STMT_TEXT, 1, 200) AS STMT FROM TABLE(MON_GET_ACTIVITY(NULL, -2)) AS T WHERE TEMP_TABLE_SPACE_TOP_KB 102400 ORDER BY TEMP_TABLE_SPACE_TOP_KB DESC FETCH FIRST 10 ROWS ONLYTEMP_TABLE_SPACE_TOP_KB 是该活动在监控周期内临时表空间使用量的峰值102400 对应 100MB 的过滤线这个阈值根据自己的业务调整。SORT_TOP_KB 是排序相关临时空间峰值两个字段一起看能判断消耗来源。MON_GET_ACTIVITY 的第一个参数填写 NULL 表示不过滤活动 ID第二个参数 -2 表示当前实例的所有成员具体发行版的参数名称略有差异但这条语句在主流 DB2 版本上都能跑。如果上述查询返回空说明当前没有瞬时高峰活动需要抓历史数据。可以查 package cache 里累计临时空间消耗最多的语句SELECT SUBSTR(STMT_TEXT, 1, 100) AS STMT, NUM_EXECUTIONS, POOL_TEMP_TABLE_SPACE_TOP_KB, POOL_SORT_TOP_KB FROM TABLE(MON_GET_PKG_CACHE_STMT(D, NULL, NULL, -2)) AS T ORDER BY POOL_TEMP_TABLE_SPACE_TOP_KB DESC FETCH FIRST 10 ROWS ONLYNUM_EXECUTIONS 能帮你区分“跑得多”和“单次耗得多”。出现次数少但峰值极高的通常是批量或月末任务出现次数多且每次峰值都不低的属于常规查询需要重点治理。拿到 SQL 后下一步是看执行计划。常见做法是用 db2expln 生成文本计划重点看有没有 HSJOIN 节点、有没有独立的 SORT 节点以及各节点的行数估算是否和实际相差很远。行数估算差一个数量级以上优先怀疑统计信息过期。3.2 排序内存参数怎么调SHEAPTHRES_SHR 与 SORTHEAP先把当前值取出来db2 get db cfg for dbname | grep -iE SHEAPTHRES_SHR|SORTHEAP两个参数的单位都是 4K 页。SORTHEAP 是单个排序操作的内存上限SHEAPTHRES_SHR 是所有并发共享排序操作累计的软上限。超过软上限后新的排序操作会被限制在更保守的内存范围内强制走溢出路径。调整顺序建议是先动 SHEAPTHRES_SHR后动 SORTHEAP。把 SHEAPTHRES_SHR 从 AUTOMATIC 改为固定值或者按现有值上调 50%然后观察 Sort overflows 是否明显下降db2 update db cfg for dbname using SHEAPTHRES_SHR 12000不要一上来就调大 SORTHEAP。调大 SORTHEAP 意味着单个排序可以占更多内存但也意味着并发场景下内存总量更不可控可能引发操作系统换页性能反而更差。判断标准始终是 Sort overflows 和临时空间峰值溢出高、临时空间高优先加共享阈值溢出低、临时空间高要去看是不是哈希连接而不是继续加内存。还有一个常见误用把 SHEAPTHRES_SHR 当成硬限制实际上它是软阈值DB2 在超过阈值后不会直接拒绝排序而是降低新排序的内存授予。针对哈希连接根治手段往往是统计信息。执行一次 RUNSTATS让优化器拿到最新的行数和分布信息db2 runstats on table schema.tablename with distribution and detailed indexes all统计信息更新后重新绑定或让语句自然重新优化。实践中大量“临时空间莫名其妙打满”的场景在 RUNSTATS 之后消失因为优化器把连接顺序和连接方法换掉了。这是成本最低的一步应该放在调参数之前做。3.3 收缩物理占用DMS 自动扩展表空间的 REDUCE 操作与前提如果最终判断是“物理配置过大”才考虑收缩。DMS 表空间在自动扩展机制下只增不减历史上一次峰值会在磁盘上留下长期占用这是标题里“过大”最常对应的物理表现。收缩命令ALTER TABLESPACE TEMPSPACE1 REDUCE TO 20G执行前先确认三点当前已用空间低于目标值否则命令会失败没有正在运行的、依赖该临时表空间的批量作业否则收缩过程会等待目标值预留至少 30% 余量不要卡在使用率上。REDUCE 本质是把文件系统容量重写到目标大小所以磁盘 I/O 和文件系统剩余空间都需要检查。很多 DBA 在监控页面上看到占用率高就急着收缩结果刚缩完下一个业务高峰又触发自动扩展空间白白来回折腾。需要特别说明一点SMSSystem Managed Space临时表空间没有容量配额的概念它直接使用文件系统目录不存在“缩小”操作。如果在 SMS 环境下出现“过大”的诉求实际要做的是评估临时数据所在目录的清理策略而不是执行表空间级别的收缩。不少管理员把 DMS 的 REDUCE 命令直接拿过来跑报错之后还在纠结语法其实是表空间类型用错了。4. 避坑指南临时表空间排查中常见的五个误判4.1 空间打满但根因在锁等待而不是空间本身现象临时表空间使用率长时间在 90% 以上数据库整体响应变慢但抓到的活动 SQL 都是简单短查询。原因某个长事务占用了临时表空间里的临时对象之后没有提交后续所有排序请求只能排队或共享剩余空间。锁等待和临时空间满在监控图上非常像都是等待时间升高、表空间使用率升高。解决用 db2pd -locks 找出锁持有者确认后通知业务提交或终止该会话。会话结束后临时对象释放使用率会在几秒内回落。排查临时表空间问题时应该先看锁再看空间这个顺序不能反。4.2 调大 SORTHEAP 后临时空间占用反而更高现象为了降低临时空间使用率把 SORTHEAP 从 4096 调到 8192运行一天后发现 Sort overflows 确实下降了但临时空间峰值反而更高了。原因SORTHEAP 变大后单个排序在内存里能容纳的数据更多但整体并发排序的总内存上限并没有同步变导致多个大排序同时在内存中运行总内存超限后部分排序在更晚的阶段才溢出。峰值出现得更晚但在监控图上表现为更高的临时空间使用。解决如果并发排序是常态调整的重点应该是 SHEAPTHRES_SHR 和并发控制而不是单排序内存。回退 SORTHEAP观察 SHEAPTHRES_SHR 调整后的曲线。这条血泪经验在调整排序内存时几乎必踩。4.3 重启后使用率回落就认为问题已经解决现象数据库重启后临时表空间使用率回落到个位数告警消失团队认为故障已排除。原因临时表空间是非持久化的重启会清空所有临时对象但触发峰值的 SQL 和执行计划并没有变下次业务高峰会再次打满。解决依靠快照和监控 SQL 在重启前把 Top SQL 和临时空间曲线保存下来。重启只是恢复业务不能作为故障结论。后续一个完整业务周期内没有再次出现高峰才有资格判定为已解决。4.4 REDUCE 命令执行成功但磁盘占用没有变化现象ALTER TABLESPACE REDUCE TO 执行成功没有报错但文件系统层面看到的占用空间并没有减少。原因这是 DMS 自动扩展表空间的常见现象。REDUCE 只影响表空间逻辑容量当表空间存储使用的是预先分配的容器文件且文件系统不支持稀疏文件时物理占用不会立即变化另外如果收缩目标大于当前文件系统上实际分配的簇大小命令会执行但效果不明显。解决确认是否真的需要物理层面回收很多场景下只缩逻辑容量就可以满足审查要求。如果必须回收物理空间需要配合文件系统层面的操作或迁移表空间数据。不要为了监控页面好看而在高 I/O 时段反复执行 REDUCE它会拖慢业务。4.5 只看使用率百分比忽略临时空间的 I/O 延迟现象临时表空间使用率只有 30%但 SQL 执行极慢系统监控工具显示临时表空间 I/O 等待持续居高。原因排序溢出产生的临时写入是典型的随机小 I/O无论使用率多低只要排序溢出量变大磁盘延迟就会被放大。此时问题在 I/O 能力不在空间容量。解决把 Sort overflows 和临时表空间 I/O 延迟纳入监控。延迟高时考虑把临时表空间迁移到更快存储或通过 SHEAPTHRES_SHR 降低溢出频率。空间使用率这个指标只能回答“够不够用”回答不了“够不够快”。5. 把排查沉淀成巡检脚本一周一张临时表空间健康卡临时表空间问题有一个特点大部分时间隐藏只在特定业务窗口暴露。单靠故障时排查很难建立“正常值”的参考系。我习惯的做法是写一个小巡检脚本每天定时采集临时表空间的容量、使用率、排序溢出以及当时的 Top 临时空间语句存成文本日志。脚本本身不长#!/bin/bash DBNAME$1 THRESHOLD_MB100 { echo $(date %Y-%m-%d %H:%M:%S) db2 connect to $DBNAME /dev/null 21 db2 -x SELECT TBSP_NAME, CAST(TBSP_USED_SIZE_KB/1024/1024 AS DECIMAL(10,2)) AS USED_GB, CAST(TBSP_USABLE_SIZE_KB/1024/1024 AS DECIMAL(10,2)) AS USABLE_GB, DECIMAL(TBSP_USED_SIZE_KB*100.0/NULLIF(TBSP_USABLE_SIZE_KB,0),5,1) AS USED_PCT FROM SYSIBMADM.MON_TBSP_UTILIZATION WHERE TBSP_TYPESYSTEM TEMPORARY db2 -x SELECT APPL_ID, CAST(TEMP_TABLE_SPACE_TOP_KB/1024 AS BIGINT) FROM TABLE(MON_GET_ACTIVITY(NULL,-2)) WHERE TEMP_TABLE_SPACE_TOP_KB/1024 $THRESHOLD_MB ORDER BY TEMP_TABLE_SPACE_TOP_KB DESC FETCH FIRST 5 ROWS ONLY db2 terminate /dev/null 21 } /home/db2inst1/temp_tbsp_health_$(date %Y%m).log把这个脚本放进 crontab 每小时执行一次连续跑一个月就能得到曲线的基线。基线的价值在于下次再报“临时表空间过大”翻出历史日志对比一下当下时段的值是偏离还是正常波动。如果发现使用率曲线每周都在同一个业务窗口准时变高说明对应的批量作业就是根因源头。脚本里的阈值和周期都要按自己的环境调重点不是监控频率而是把每一次告警出现前后的 Top 语句留下来。我在接手这类系统时第一步永远是先看历史曲线和 Top 语句的留存而不是急着改参数——因为改参数只能缓解症状留存下来的证据才能定位根因。临时表空间的排查没什么玄学把每一次高峰的证据攒下来问题就会从“灵异事件”变成“可复现的已知问题”。希望帮到你。本文还有配套的精品资源点击获取