DB2慢查询排查:系统临时表空间与LATCH争用根因
简介:这份DOC文档面向DB2数据库DBA与运维人员,取材于某银行真实性能案例,聚焦系统临时表空间TEMPSPACE1异常增大后引发的SQL执行变慢、活动会话升高等问题,适合有一定DB2基础、需要提升性能诊断能力的读者参考。压缩包内仅含1个doc文件,大小约607KB,内容集中,便于直接查阅。文档把现象确认、常规指标排查、LATCH等待分析、STACK收集与db2trc跟踪等线索串联起来,并讨论SQL优化、参数调整和临时对象清理等处理方向,可帮助读者理解临时表空间过大如何逐层影响查询性能。已有5903人学习,对希望积累银行级DB2排错思路和性能分析工具使用经验的DBA具有参考价值。
1. 从一次“指标全绿”的慢查询说起:被忽略的 DB2 系统临时表空间
一家金融机构的 DB2 数据库某天开始变慢,业务反馈集中在“提交变慢”,活动会话数从常年个位数频繁冲到 30 以上。运维按惯例把 CPU、内存、I/O、缓冲池命中率、锁等待过了一遍,每项都在正常区间,甚至可以说漂亮。这类排查最难受的地方就在这里:常规指标全绿,问题却真实存在。等把执行时间最长的语句拉出来逐条比对,才发现其中一部分语句的时间根本没花在读数据、等锁或者排序上,而是花在 LATCH 等待上;再往下追,真正卡住一切的是那个常年没人关注过的 DB2 系统临时表空间,它已经涨到 10G。这套从活动会话一路挖到表空间的路径,适合正在处理数据库性能问题的运维和开发,也适合把它当成一份完整性能分析案例来做方案设计的同学。
2. 排查链路设计:从活动会话到时间分布的取证顺序
性能排查真正难的地方通常不在于缺工具,而在于工具都用了一遍,结论却是散的。这次的处理过程之所以能收敛,是因为把六步取证串成了一条链:先确认现象是数据库侧的,再排除资源问题,再抓语句,再拆时间分布,最后才允许自己去动 SQL。顺序反了,很容易在第 4 步就一头扎进去优化语句,把时间耗在错误方向上。
2.1 先把活动会话拆到状态级
业务人员说“慢”只能当线索,不能当结论。真正让人开始紧张的是活动会话数。正常联机事务处理系统的活动会话数一般在 10 个以内,忙一些的系统二三十个也属正常,超过这个量级就该考虑扩容了;但如果一个平时只有几个会话的系统突然频繁冲到几十个,先别急着买硬件,先看状态构成。
活动会话的准确定义是“正在处理 SQL 请求的会话”,从编译到执行完成,中间会经历 Compiling、UOW Executing、Lock Waiting 等状态,COMMIT 也是一个语句,执行期间能看到 Commit Active,启用并发限制后排队中的会话是 Queued。这些状态都计入活动会话数;而一个事务里执行完一条语句、下一条还没开始,应用处于 UOW Waiting,不计入。
# 连接目标数据库,默认以 2 秒为间隔持续刷新 db2top -d OAPDB # 进入交互界面后: # d —— 查看 ActSess 汇总,观察总量趋势 # l —— 进入 SESSIONS 页面,逐个看会话处于什么状态 # D —— 查看 PACKAGE CACHE 中的动态 SQL # z —— 在 SQL 页面触发排序,输入 4 表示按平均执行时间倒序db2top的-d后面跟库名,进去后靠单字母指令切换视图。这次故障中,活动会话全部是 UOW Executing 状态——没有大面积的锁等待,说明会话不是被应用层或锁卡住,而是自己算得慢。这一步的价值在于把“数据库慢”这个模糊判断,收窄成“一批语句在并行执行且耗时异常”。
同时也要习惯用db2 LIST APPLICATIONS SHOW DETAIL做交叉核对,它给出的状态字段与 db2top 口径一致,适合在事后复盘时截图留证。
2.2 快速排除法:哪些指标必须看,哪些数据可以直接忽略
快速排除法的目的是尽快把“资源不够”这个可能性划掉,而不是把所有指标都研究一遍。CPU 利用率和操作系统内存用量在正常范围,缓冲池命中率正常,没有锁等待,四项平均读写时间——AvgPRdTime、AvgDRdTime、AvgPWrTime、AvgDWrTime——也都在正常区间,基本可以判定 I/O 不是瓶颈。
这里有两个容易误判的数据。一是 Deadlocks 显示 218,看着吓人,但这是累计值,从实例启动算起,不代表当前有死锁在影响性能;二是 SortOvf(排序溢出)为 10,偏高,但应用本身排序语句较多,有溢出属于可解释范围,不足以解释三十多个会话同时变慢。把这两个数当成“重点怀疑对象”,是很多排查走弯路的第一步。
还有一点:既然已经确认会话状态在数据库内部,网络故障、应用服务器负载这类方向就可以直接排除,不必再花时间。排除法的意义是缩小范围,不是面面俱到。
2.3 抓语句:缓存里的和执行窗口里的
确认是语句慢之后,要把具体的语句捞出来。db2top 的D视图能看到缓存中的动态 SQL,再输入z后会提示按哪一列排序,输入 4 即按平均执行时间倒序。这次看到最慢的几条平均执行时间接近 4 秒,但执行次数都很有限——典型的应用没走变量绑定、直接拼 SQL,每条语句对数据库来说都是全新的,缓存里自然积累不起来。
针对活动会话数高的情况,MON_CURRENT_SQL管理视图更直接,能看到当前正在跑的语句,动态、静态都在内:
-- 查看当前正在执行、且已运行时间较长的语句 SELECT COORD_MEMBER AS MEMBER, VARCHAR(SESSION_AUTH_ID, 10) AS USER, VARCHAR(CLIENT_APPLNAME, 10) AS APPNAME, ELAPSED_TIME_SEC AS ELAPSEDTIME, -- 已运行秒数 VARCHAR(ACTIVITY_STATE, 10) AS STATE, -- UOW Executing 等 TOTAL_CPU_TIME, ROWS_READ, ROWS_RETURNED, QUERY_COST_ESTIMATE, DIRECT_READS, DIRECT_WRITES, VARCHAR(STMT_TEXT, 2000) AS STMT_TEXT FROM SYSIBMADM.MON_CURRENT_SQL ORDER BY ELAPSED_TIME_SEC DESC;ELAPSED_TIME_SEC是语句从开始执行到查询时刻的秒数,不是完整执行时间,所以抓出来的值一定比语句真实耗时短,这属于正常现象。另一个注意点是:活动会话数高这个现象不是持续存在的,单次查询很可能抓不全,通常需要连跑几次,等峰值出现时再取结果。这次抓到接近 30 条,和监控上的活动会话数对得上。
2.4 拆时间分布:别只看总耗时,要看时间花在哪
知道哪些语句慢还不够,关键是搞清慢在哪里。MON_GET_PKG_CACHE_STMT表函数返回的字段极多,包含各类等待时间,可以算成占比,一眼看出时间去向:
-- 计算各语句平均执行时间,以及各类等待占总执行时间的百分比 SELECT MEMBER, NUM_EXECUTIONS, STMT_EXEC_TIME, DECIMAL((TOTAL_ACT_WAIT_TIME / DOUBLE(STMT_EXEC_TIME)) * 100, 5, 2) AS pct_wait, DECIMAL((POOL_READ_TIME / DOUBLE(STMT_EXEC_TIME)) * 100, 5, 2) AS pct_read, DECIMAL((LOCK_WAIT_TIME / DOUBLE(STMT_EXEC_TIME)) * 100, 5, 2) AS pct_lock, DECIMAL((LOG_DISK_WAIT_TIME / DOUBLE(STMT_EXEC_TIME)) * 100, 5, 2) AS pct_log, DECIMAL((TOTAL_SECTION_SORT_TIME / DOUBLE(STMT_EXEC_TIME)) * 100, 5, 2) AS pct_sort, CAST(FLOAT(STMT_EXEC_TIME) / FLOAT(NUM_EXECUTIONS) AS DECIMAL(10, 3)) AS AVG_EXEC_TIME, VARCHAR(STMT_TEXT, 500) AS STMT_TEXT FROM TABLE(MON_GET_PKG_CACHE_STMT(NULL, NULL, NULL, -2)) AS T WHERE NUM_EXECUTIONS > 1 AND STMT_EXEC_TIME > 0;STMT_EXEC_TIME是该语句累计执行时间,除以NUM_EXECUTIONS得到平均耗时,AVG_EXEC_TIME这一列才是可以直接和其他语句横向比较的值。表函数最后一个参数-2表示取当前成员上所有可用数据,前三个NULL分别对应 activity、package、member 过滤条件,不筛就全给。
结果里出现了很关键的一组:5 条以 with 开头的语句,平均执行时间 2 到 6 秒不等,PCT_WAIT全部在 95% 以上——也就是说时间几乎全花在等待上,而PCT_READ、PCT_LOCK、PCT_LOG、PCT_SORT都很低。等待的不是读、不是锁、不是日志、不是排序,那就只剩内部争用。在查询里再加一个TOTAL_EXTENDED_LATCH_WAIT_TIME,答案就浮出来了:这几条语句在等 LATCH。另外 5 条慢语句是调用存储过程的,从这个视图看不出内部分布,需要另找入口。
2.5 什么时候该停手:三个“没有变”帮你否掉优化 SQL 的方向
拿到结果后,常规动作是优化。当时也确实动了手:几个全表扫描的语句加索引就解决了,然后开始梳理那些又长又复杂的语句。
但这里必须踩一脚刹车。那些复杂长 SQL 不是最近才上线的,应用程序没有变更,数据库也没有变更,凭什么一个月前它跑得好好的,现在突然慢?加索引能解决的那几个语句,只能解释个别会话变慢,解释不了三十多个会话同时 UOW Executing。真正的问题一定是一个“最近才变化、又被所有人忽略”的因素。
这三个“没有变”——没有应用变更、没有数据库变更、慢语句逻辑没变——是判断方向的硬约束。反过来推,变化只能发生在数据库的运行状态里:某个对象的大小、某个内部结构的分布、某个后台动作的代价。顺着这个思路往下走,才轮到 LATCH 和 STACK 出场。
3. LATCH 与 STACK 取证:把内部函数名翻译成可判断的操作
3.1 pool_table_latch 是什么:从名字到机制的理解路径
产品文档里几乎找不到对 LATCH 的科普性说明,只有若干监控元素能间接反映它的存在,比如前面提到的TOTAL_EXTENDED_LATCH_WAIT_TIME。可以这么理解:LATCH 是数据库为保证多线程访问内部共享结构一致性而设的轻量锁。举个例子,内存里有个预取队列,处理用户请求的线程往里加任务,多个预取线程不停从里面取任务,为了协调这两方对队列的访问,每次访问前都要先拿到 LATCH,拿不到的就得等。
所以 LATCH 本身不是故障,它是正常机制;只有当某个持有者拿着 LATCH 干了一件特别久的事,后面排队的才会成串堵住。这次的情况正是如此:db2pd -latches第一次跑没看到异常,因为 LATCH 等待几秒就消散了,单次采样很容易错过。改成持续采样:
# 每 2 秒刷新一次 LATCH 情况并持续输出,便于捕捉瞬时争用 db2pd -d OAPDB -latches -rep 2-rep 2是重复间隔秒数,不加就只能看一瞬间的快照,这类瞬时现象必须靠连续采样。这次抓到了:EDU ID 11665 持有类型为pool_table_latch的 LATCH,同时 23 个 EDU 在等它。23 个等待者加上持有者,活动会话数至少 24,和监控曲线对得上。
到这一步只确认了“有争用”,还没确认“谁在争、争的是什么东西”。LATCH 的名字只有字面意义,pool_table指什么、为什么会持有这么久,靠猜没用。
3.2 收集 STACK 的命令参数与资源代价
既然瞬时状态抓不住现场,就换个思路:在抓现场的同时把每个线程当时的调用栈一起存下来。db2pd的-stack正是干这个的,它在收集栈的同时也会记录该 EDU 当时的 LATCH 和锁信息。
# 连续收集 10 次栈信息,每次间隔 3 秒,输出到指定目录 mkdir -p /tmp/stack0531 db2pd -d OAPDB -stack all dumpdir=/tmp/stack0531 -rep 3 10-stack all表示收集所有 EDU;dumpdir指定输出目录,不指定就默认落在诊断目录里,事后翻找很麻烦;-rep 3 10是每 3 秒一次、共 10 次,之所以要多次,是因为 LATCH 争用不是常态,单次采集大概率落空。
必须强调代价:-stack会挂起线程去抓栈,在生产库上是一次实打实的扰动,库越忙影响越明显。我一般的做法是控制次数、挑相对低峰、提前和业务打招呼,绝不在高峰期做长时间采集。抓完之后立刻确认有没有命中:
cd /tmp/stack0531 grep -l pool_table_latch *.stack.txt | head命中后直接看文件内容,能找到Holding Latch type和Waiting on latch type两类记录,地址相同,说明确实是同一把 LATCH。
3.3 读 STACK:靠函数名与调用关系反推操作类型
栈里全是内部函数名,第一眼确实劝退,但不需要读懂实现,只要能判断“这是在干什么活”。方法是看函数名、看调用链的层次,再结合对数据库架构的基本认知去猜。
持有者的栈里出现了sqlbSnapshotTablespace调用sqlbMonSMSGetContainerPages,再往下是sqlofindn2、__xstat64这类文件系统调用。字面翻译:对表空间做快照,具体动作是在监控 SMS 表空间时枚举容器、获取数据页信息,__xstat64说明它真的在跟操作系统要文件状态。这就解释了一个关键点——它在做一件跟文件数量、文件大小强相关的事。
等待者的栈里是sqldTableCreateTemp调用sqldInternalCreateTable,再调用sqlbGetSysTempDatapool,同一条链上还有sqldEvalDataPred、sqlriFetch。这条链的含义很明确:执行一条带谓词的查询,过程中需要创建内部临时表,于是去申请系统临时表空间。
两条栈拼起来,因果关系就成立了:某个后台动作在对表空间做快照,耗时过长,长时间持有pool_table_latch;而查询语句要建临时表、要用系统临时表空间,必须拿同一把 LATCH,于是成串排队。谁在频繁做快照?答案是数据库监控系统部署在服务器上的采集代理,它按周期采集表空间信息。
到这里还剩最后一环:快照为什么慢。快照慢,只能是因为它要处理的对象太大——而那个对象,正是 10G 的 TEMPSPACE1。
3.4 analyzestack:批量汇总栈文件的小工具
手工 grep 加肉眼比对,在十个文件内还行,几十上百个就撑不住了。产品安装目录的sqllib/pd下有个 Perl 脚本analyzestack,能把目录里所有栈文件按相同栈归并统计,顺带做 LATCH 分析。
# -d 指定比对时比较的函数层数,-i 指定栈文件目录,-l 开启 LATCH 分析 perl ~/sqllib/pd/analyzestack -d 50 -i /tmp/stack -l-d 50是比较深度,值越大越严格,栈要前 50 层都对上才算同一类;-i可以是目录也可以是若干个具体文件;-l打开 LATCH 分析。跑完会在当前目录生成LatchAnalysis.out和StackAnalysis.out两个文件,前者列出持有者与等待者的配对关系,后者是按栈归并后的统计,哪个栈出现次数最多一目了然。
需要提醒的是,这个脚本在文件头自己写明了按现状提供、不做担保,属于典型的“能用但别指望官方支持”的工具。生产环境用之前,先在测试环境跑一遍确认输出格式,别等到出事现场才发现参数不对。它解决的是归并统计这类体力活,判断还得自己做。
4. 根因确认与处置:TEMPSPACE1 从 10G 回落的两步动作
4.1 表空间体检:查看动作本身变慢就是信号
顺着“对象太大”这条线去查表空间,第一个异常不是数值,而是速度:db2 LIST TABLESPACES SHOW DETAIL要跑好几秒才出结果。一个查看元数据的命令慢成这样,本身就说明被查看的对象数量或规模已经失控。
# 查看表空间明细,重点关注 Total/Used pages 与容器数量 db2 "LIST TABLESPACES SHOW DETAIL"结果里 TEMPSPACE1 的信息是这样的:类型为系统管理空间(SMS),内容为系统临时数据,总页数 354661,页大小 32768 字节,区大小 32 页,预取大小 768 页,容器数 4,已用页等于总页数。粗算一下就是十个 GB 级别。正常情况下系统临时表空间应该非常小,涨到这个体量,说明里面堆了大量本该被回收的东西。
再去看容器目录,问题更直观:
# 统计临时表空间容器目录下遗留的 TDA 文件数量与占用 ls -al /db2data/.../NODE0000/OAP/T0000001/C0000003.TMP | head find /db2data/.../NODE0000/OAP/T0000001 -name "*.TDA" | wc -l目录里是一堆SQL04313.MEMBER0000.TDA、SQL04314.MEMBER0000.TDA这样的文件,每个 1MB 左右,时间戳集中在同一个时间点。这些是临时数据文件,按设计应该在用完后被清理,现在全都留着。
同时翻监控系统的表空间大小历史曲线,能看到某个时刻 TEMPSPACE1 从 0 直接跳到 10G。时间点非常集中,说明不是缓慢增长,而是一次事件造成。
4.2 TDA 文件残留:一个“按设计如此”的行为
查到这一步,去官方技术支持文档里搜,能搜到一条明确说明:SMS 临时表空间中的 TDA 文件可能不被删除,从而占满文件系统。关键在于它的定性——Work as Design,产品设计如此,不是缺陷。
这个定性会直接改变处置思路。既然不是缺陷,就别指望打补丁或者升级能解决,只能从运行态入手:想办法让这些文件被释放,并且在制度上防止它再次堆积。
至于为什么会堆积,回溯到那个时间点就清楚了:当时出现了一次并发尖峰,活动会话一度冲到 800 多个,大量语句同时使用临时表空间。数据库没崩,语句也都执行成功了,但留下了一堆 TDA 文件,成了后面踩到的雷。这类雷的特点是当时完全无感,几周后才以“系统变慢”的形式爆发,排查时极容易和业务变化、应用变更混淆。
4.3 处置动作与生效边界:为什么重启实例不管用
处置本身只有两步,但边界必须说清楚:
# 先停用数据库,再激活,强制释放残留的临时表空间 db2 deactivate db OAPDB db2 activate db OAPDB # 验证:表空间信息应立即恢复正常返回速度 db2 "LIST TABLESPACES SHOW DETAIL"必须是 deactivate/activate 这一对操作。只重启实例(db2stop / db2start)不管用,因为实例重启不一定触发数据库级的清理动作,残留文件会原样留着。这一点如果没搞清楚,很容易在维护窗口里白折腾一轮,然后得出“办法无效”的错误结论。
激活后立刻验证:表空间查询恢复正常速度,TEMPSPACE1 回到很小的体量,活动会话数回落到个位数,之前那批 3 到 6 秒的语句恢复到正常耗时。再挂上监控观察一段时间,确认曲线稳定,处置才算完成。
4.4 预防方案:监控、容量与变更窗口的三道闸
问题解决之后,真正有价值的是把这类问题挡在下次之前。我一般从三个地方下手。
第一道是监控口径。原来只监控表空间使用率,对系统临时表空间基本不看,因为“它反正会自己回收”。现在需要把 TEMPSPACE1 的大小和容器目录下的 TDA 文件数量都纳入采集,设阈值告警——正常应该维持在很小的量级,一旦出现数量级跃升,就是异常。
第二道是容量与类型的选择。系统临时表空间不是越大越好,SMS 类型下容器文件数量会随并发峰值增长,快照类操作遍历容器的成本也随之上升。规划时按真实峰值估算,留合理余量即可,不要图省事直接给一个巨大的初始值。
第三道是变更窗口。deactivate/activate 会断开所有连接,必须放在维护窗口做,并且要提前确认没有长事务在跑。把“并发尖峰之后检查临时表空间残留”写进重大活动后的巡检清单,比事后救火便宜得多。
4.5 用 db2trc 做一次小验证
结论是否可靠,最好能复现。db2trc可以抓取数据库运行中的函数调用,还支持在指定函数入口处暂停实例,让人从容取证。
# 打开跟踪,在指定函数入口处挂起,便于观察该函数被调用的时机 db2 CONNECT TO OAPDB db2trc on -crash DB2.SQLB.sqlbSMSGetContainerPages.entry -suspend # 复现表空间信息采集动作,观察是否精确停在该函数 db2trc off db2trc fmt db2trc.dmp db2trc.txt-crash后跟函数名限定跟踪范围,-suspend让实例在命中该函数时暂停。这个小实验验证了两件事:表空间信息查看确实会走到sqlbSMSGetContainerPages,也就是那个要枚举容器页、持有pool_table_latch的动作;同时对数据库监控采集与性能下降之间的关系有了确定性的证据,不再是靠推断。
5. 避坑清单:这类性能问题最容易翻车的五个地方
5.1 常规指标全绿就下“数据库没问题”的结论
现象是 CPU、内存、I/O、缓冲池、锁等待全部正常,于是排查转向应用或者网络,来回折腾几天没结果。
原因是这套指标只覆盖资源层,不覆盖内部争用。LATCH 等待既不吃 CPU,也不体现在锁等待上,普通监控里根本看不见。
解决办法是把“会话状态构成”和“语句时间分布”作为第二层检查固定下来。活动会话里如果 UOW Executing 占多数,而资源层又是绿的,就该往内部争用方向查,先看TOTAL_EXTENDED_LATCH_WAIT_TIME这个字段,成本很低。
5.2 盯着累计值指标做决策
看到 Deadlocks 两百多、SortOvf 有十个,立刻判断是锁和排序问题,动手调排序区、查死锁。
原因是累计值只反映历史总量,不能反映当前是否在发生。这两项在这次故障里都出现了,但都不是主因。
解决办法是养成区分“累计值”和“当前值”的习惯,判断前先问一句:这个数是什么时候开始累加的,最近有没有增量。有增量再看,没增量就放过。
5.3 LATCH 采样一次没抓到就放弃
db2pd -latches跑了一次,输出一切正常,于是认为 LATCH 没问题,转向别的方向。
原因是 LATCH 争用往往只持续几秒,瞬时快照的命中率很低。这次的问题里,等待会在几秒内消散。
解决办法是改成带-rep的连续采样,采样周期和持续时间按现象的出现频率定。这次用-rep 2连续观察,才第一次抓到 23 个等待者。另外,抓到的 LATCH 名称要记录下来,作为后续找栈的检索关键词。
5.4 生产库上长时间 dump 全量栈
为了多抓点信息,直接在业务高峰期跑长时间、多次数的-stack all,结果数据库响应进一步恶化,把性能问题变成了可用性问题。
原因是抓栈会暂停线程,线程越多、次数越密,扰动越大。忙库上这个代价会放大。
解决办法是三条纪律:挑低峰窗口;控制次数,通常 10 次以内够用;先小范围试一次确认能命中,再决定是否加量。同时提前准备好dumpdir,避免事后在一堆诊断文件里翻找。
5.5 处置后用“感觉快了”验收
做完 deactivate/activate,问了句业务说好了,就结单。过一段时间同样的问题再次出现,又从头查一遍。
原因是缺少可对比的量化口径,也缺少防复发措施。并发尖峰是会再来的。
解决办法是验收至少看四项:活动会话数曲线是否回到基线、慢语句平均执行时间是否恢复、TEMPSPACE1 大小和 TDA 文件数是否归零、表空间查询耗时是否正常。同时把并发尖峰后的巡检动作固化下来,别指望下次还能想起这次。
6. 验收与答辩:用五项指标证明问题真的解决了
这套东西讲给别人听的时候,最容易被打断的地方是“你怎么证明是临时表空间导致的,而不是同时段别的因素”。证据链要经得起这个追问,靠的不是结论本身,而是三条独立线索指向同一个对象。
第一条线索是会话状态:活动会话数从个位数涨到三十以上,且状态全部是执行中,没有锁等待,说明是算得慢而不是被卡住。第二条线索是语句时间分布:部分语句 95% 以上的时间在等待,而读、锁、日志、排序的占比都很低,把范围压缩到内部争用。第三条线索是 LATCH 加栈:持有者在做表空间快照、等待者在建临时表,两者争同一把pool_table_latch,而快照慢的原因是临时表空间有 10G。三条线索单独看都只是线索,合起来才构成因果。
验收口径建议做成一张对照表,答辩时直接摆出来,比口头描述有说服力:
| 验收项 | 故障期表现 | 恢复后目标 | 采集方式 |
|---|---|---|---|
| 活动会话数 | 频繁超过 30,峰值 800+ | 稳定在个位数 | db2top 的 ActSess 曲线 |
| 慢语句平均执行时间 | 2 到 6 秒 | 回到百毫秒级 | MON_GET_PKG_CACHE_STMT |
| LATCH 等待 | 单次采样 23 个等待者 | 无持续排队 | db2pd -latches -rep 2 |
| TEMPSPACE1 大小 | 约 10G,已用页等于总页 | 维持在很小量级 | LIST TABLESPACES SHOW DETAIL |
| 容器目录 TDA 文件 | 大量残留,时间戳集中 | 数量稳定不增长 | 目录文件计数巡检 |
答辩时还有一个加分点:主动讲自己走错的那一段。加索引解决了几条全表扫描,然后花了时间去优化那些又长又复杂的语句——方向是错的,因为应用没变更、库没变更、语句逻辑也没变,解释不了为什么现在才慢。把这段讲出来,比只讲正确路径更能说明你理解了排查的边界在哪里。评审的人真正想确认的,是你能不能在下一次遇到没见过的问题时,靠证据而不是靠运气收敛。
另外准备好两段可复现的命令,现场问就现场给:一段是db2pd -stack all dumpdir=... -rep 3 10,说明为什么要多次采集、代价在哪;一段是db2 deactivate db加db2 activate db,说明为什么只重启实例不行。这两处是最容易被追问细节的地方,答得利索,整份方案的可信度就立住了。
从那以后,我每次处理“指标全绿但系统就是慢”的问题,都会强制走一遍活动会话状态拆分和语句时间分布这两步,不管前面看起来多像应用问题——因为那次真的让我明白,最贵的不是工具不会用,而是方向错了还在努力。希望帮到你。
本文还有配套的精品资源,点击获取