首页 / 资讯中心 / 文章详情

DB2指标全绿却变慢:LATCH争用与TEMPSPACE1残留

DB2指标全绿却变慢:LATCH争用与TEMPSPACE1残留 ★ FEATURED ARTICLE
简介一份聚焦 DB2 数据库性能排障的实战案例文档面向已有一定 DB2 运维基础、需要处理 SQL 执行变慢与活动会话激增问题的 DBA 和数据库工程师。内容以某银行业务系统真实故障为线索从常规 CPU、内存、I/O、锁等待与缓冲池命中率排查切入逐步追到系统临时表空间 TEMPSPACE1 异常增大这一根因并展开其引发资源消耗、内存压力、LATCH 竞争和磁盘排序开销的作用链路。文档还涉及 db2top 观察 ACTIVE SESSION、LATCH 等待分析、STACK 收集、db2trc 暂停实例等诊断手段以及 SQL 优化、参数调整和临时对象清理等处置思路适合用作性能问题定位与复盘参考。包内为 1 个 doc 文件约 607KB篇幅集中、便于检索关键命令与分析路径。目前已有 5903 人学习可作为 DB2 临时表空间相关故障排查的案例型资料。1. 业务变慢 ACTIVE SESSION 冲到 50别急着一上来就加索引DB2 数据库突然变慢ACTIVE SESSION 从平时的个位数涨到 50 以上翻遍 CPU、内存、I/O 和锁等待却全部显示正常——这类 DB2 性能问题最磨人的地方就在这里所有常规指标都在告诉你「没事」。我最早遇到时把执行时间长的 SQL 挨个加索引、拆复杂查询折腾大半天ACTIVE SESSION 一点没降。真正的元凶是系统临时表空间 TEMPSPACE1 涨到了 10G一个平时几乎没人关心的对象靠残留的 TDA 文件把pool_table_latch拖成了瓶颈。这篇复盘适合正在被「指标全绿但系统就是慢」卡住的 DBA 和运维从现象一路走到根因、命令和预防。2. 常规排查全绿之后ACTIVE SESSION 高但 CPU/IO/锁都正常怎么破这一章解决的是最容易走偏的一段路。系统响应变慢、业务方陆续反馈同时监控频繁捕捉到 ACTIVE SESSION 超过 50第一反应通常是「数据库出问题了」然后按部就班查 CPU、内存、I/O、LOCK WAIT、缓冲池命中率。问题在于这些检查全部正常的时候很多人会开始怀疑监控、怀疑网络、怀疑应用反而错过了真正的线索。2.1 db2top 上 ActSess 和四个读写时间指标怎么读先确认「慢」是客观事实而不是体感。ACTIVE SESSION 数量是一个很硬的指标它统计的是当前正在处理 SQL 请求的会话数从编译到执行完成这个区间里的会话都算包括 Compiling、UOW Executing、Lock Waiting、Commit Active以及启用了 WLM 并发限制后排队中的 Queued 状态。而一个事务里执行完一条语句、下一条还没开始的 UOW Waiting 状态不计入。这个区分很关键因为它决定了你看到的高数字到底是在「干活」还是在「等活」。# 连到目标库进入 db2top 主界面 db2top -d OAPDB # 主界面按 d看 ActSess 曲线默认 2 秒刷新一次 # 按 l小写 L进入 SESSIONS 页面看这些会话具体卡在什么状态-d后面跟数据库名。进入后按dActSess 指标会以默认 2 秒的间隔持续刷新你能直观看到它是尖峰还是持续高位。接着按l进入会话页本次故障里所有活动会话都停在 UOW Executing——说明它们不是被锁挡住而是真的在执行只是执行得慢。这个细节排除了锁等待方向也排除了应用连接池打满的可能。另一种统计方式是对db2 LIST APPLICATIONS SHOW DETAIL的结果按状态过滤计数适合写进巡检脚本。一般的 OLTP 系统 ACTIVE SESSION 通常在 10 个以内较繁忙的系统二三十个也算正常再高就该考虑扩容了。但如果一个平时只有几个会话的系统突然频繁冲到几十只有两种解释业务量真的涨了或者出现了性能问题导致单条 SQL 执行时间变长。和业务负责人确认访问量没有增加之后方向就锁死在第二种。这里不要偷懒跳过确认业务量这一步否则后面所有分析都建立在错误前提上。确认是数据库自身问题后快速排除法要一次做完。CPU 利用率在正常区间操作系统内存使用正常db2top 界面上 HitRatio 正常没有 LOCK WAIT右下角四个平均时间指标 AvgPRdTime平均物理读时间、AvgDRdTime平均直接读时间、AvgPWrTime平均物理写时间、AvgDWrTime平均直接写时间都看不出异常I/O 这一路也基本排除。界面上 Deadlocks 显示 218但那是累计值不代表当前有死锁在影响性能SortOvf排序溢出显示 10略微偏高考虑到业务 SQL 里有大量排序先记下来但不作为主攻方向。既然已经确认是数据库自身问题网络故障这条线也不用再花时间。2.2 MON_CURRENT_SQL 抓现场语句为什么要连抓几次指标正常不等于语句正常下一步必须抓到真实的慢语句。db2top 里按D可以看 PACKAGE CACHE 中的动态 SQL在这个界面再按z上方会提示Column number for descending sort:输入4回车结果就按 Avg ExecTime 降序排。当时排在最前面的几条语句平均执行时间接近 4 秒但 Num Execution 都只有寥寥几次。这个组合非常说明问题不是某一条 SQL 特别慢而是几乎每条 SQL 对 DB2 来说都是新语句——应用没用变量绑定直接把参数拼进 SQL 文本导致硬编译反复发生缓存里全是「一次性」语句。想看当前这一刻到底在跑什么用 MON_CURRENT_SQL 管理视图最直接动态 SQL 和静态 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, 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是语句「已经跑了多久」抓取时语句往往还没结束所以这个值只会小于等于完整执行时间不能拿来当性能基线。二是这个视图是瞬时快照一次抓取很可能只看到几条短语句必须根据情况连续执行多次才能碰上 ACTIVE SESSION 真正高涨的时刻。当时反复抓了几轮每次都稳定看到接近 30 条语句在跑和监控上的数字对得上这就算把现场固定住了。VARCHAR(STMT_TEXT,2000)的 2000 是截断长度语句很长时只保留前 2000 字符够用来识别语句类型和主要表ORDER BY那行是排序依据想优先看 CPU 消耗就换成TOTAL_CPU_TIME DESC。2.3 MON_GET_PKG_CACHE_STMT 把执行时间拆成等待、读、锁、排序抓到语句只是第一步真正有用的是知道时间花在哪。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)) WHERE NUM_EXECUTIONS 1 AND STMT_EXEC_TIME 0 ORDER BY AVG_EXEC_TIME DESC;表函数的四个参数依次是成员号NULL 表示所有成员、活动指标阈值NULL 表示不过滤、动作NULL、语句类型-2 表示所有语句。WHERE NUM_EXECUTIONS 1是为了滤掉只执行过一次的语句避免硬解析产生的海量一次性条目淹没有效信息。把STMT_EXEC_TIME当分母之前要先确认它大于 0否则除零会直接报错。结果里能看到这些语句的平均执行时间在 2 到 6 秒之间对 OLTP 系统来说这已经是很难接受的水平并发一上来 ACTIVE SESSION 立刻堆高。关键发现在于其中有 5 条以with开头的语句PCT_WAIT超过 95%——执行时间几乎全花在等待上但PCT_READ、PCT_LOCK、PCT_LOG、PCT_SORT都不高说明等的是别的东西。这时候回头往查询里加一个TOTAL_EXTENDED_LATCH_WAIT_TIME字段答案就浮出来了它们等的是 LATCH。到这一步很容易犯一个错立刻动手改 SQL。当时确实先通过加索引解决了几个全表扫描的语句接着去啃那些逻辑复杂的长 SQL但冷静下来一想这些长 SQL 早就上线了最近既没有应用变更也没有数据库变更怎么可能突然变慢。这个反问救了后面所有的时间——剩下的问题不在 SQL 文本里。3. LATCH 抓不到现场db2pd -latches 单次采样为什么总显示「无异常」已经知道有语句在等 LATCH下一步是把它抓个正着。这里最容易翻车的地方是第一次跑db2pd -latches发现结果干干净净就判断「LATCH 没问题」然后掉头回去继续改 SQL。这个误判太常见了值得单独拆开讲。3.1 pool_table_latch 到底是什么为什么文档里查不到DB2 的 LATCH 机制可以简单理解为数据库内部的一种轻量锁目的是保证多个线程访问内部共享结构时的一致性。举个具体例子DB2 内存里有个 PREFETCH QUEUE 结构处理用户请求的 EDU 需要预取时会往队列里加任务多个 PREFETCHER EDU 不停地从队列里取任务为了让这两类线程不踩踏每次访问前都得先拿到一个 LATCH拿不到的就得等释放。它跟用户层面的行锁、表锁不是一回事影响的是数据库内部线程之间的协作效率。pool_table_latch就更冷门了。它的名字看上去像跟表池有关但实际含义从字面猜不出来而且 DB2 官方文档里找不到任何对 LATCH 的介绍性内容更没有哪里解释某个具体 LATCH 名的场景。这意味着遇到这类等待靠查文档是不行的只能靠现场证据反推谁拿着、拿了多久、拿的时候在执行什么函数。理解了这一点排查思路就变了。从「等多久」转向「谁拿着、在干什么」。3.2 -rep 2 持续采样才抓得到间歇阻塞问题的核心在于间歇性。这个 LATCH 等待持续几秒就会消失下一次什么时候出现没有规律。在最初那次快速排除中已经跑过一次db2pd -latches结果毫无异常——但那只是一瞬间的快照恰好错过了阻塞窗口。# 每 2 秒采一次 LATCH 状态持续输出到屏幕CtrlC 结束 db2pd -d OAPDB -latches -rep 2-rep 2是关键参数表示每隔 2 秒重复执行一次并持续输出不加这个参数就退化成单次采样。间隔不能设太大因为 LATCH 等待窗口可能只有几秒也不能设太小采样本身有开销而且频繁输出会刷屏到看不清。2 秒是个比较稳妥的起点如果怀疑的窗口更短可以降到 1 秒。这个命令建议挂在一个独立终端里跑上十几分钟覆盖业务高峰。改成持续采样之后异常就露出来了每隔一段不固定的时间结果里会集中出现一批 LATCH 等待。其中一次快照显示EDU ID 11665 作为 Holder 拿着类型为pool_table_latch的 LATCH而 ID 2877、2981 等共 23 个 EDU 排在后面等同一个 LATCH。3.3 一个 Holder 拖住 23 个 Waiter 意味着什么这个数字要跟 ACTIVE SESSION 对上一个操作阻塞了 23 个操作光这一个 LATCH 就能让 ACTIVE SESSION 至少达到 24。前面监控里看到的「频繁超过 30」终于有了合理解释——不是业务变忙而是一个内部操作把一大批查询挡在了门外。这里有个容易忽略的判定逻辑如果你在 LATCH 快照里看到 Holder 和 Waiter 数量接近 1 比 N而且 N 会随着 ACTIVE SESSION 波动基本可以确认这就是主因而不是并发导致的偶发现象。反过来如果每次看到的 Holder 都不同、Waiter 只有一两个那更可能是正常的瞬时竞争不必深挖。但新的难点来了LATCH WAIT 几秒就消失等你看到快照再想去抓 Holder 和 Waiter 当前在执行什么窗口早就关了。这也是为什么很多人卡在这一步就放弃——现象看到了原因抓不到。常规监控手段在这里失效必须换一种能在极短窗口内固定证据的方法。4. 从 STACK 到根因TEMPSPACE1 涨到 10GTDA 文件残留怎么清这一章是整个排查里信息密度最高的部分。思路是把「LATCH 快照」和「线程调用栈」绑在一起看既然抓不到操作内容那就让数据库自己把每个 EDU 正在执行的函数调用链打出来栈里同时带着该 EDU 当时的 LATCH 持有或等待信息。4.1 db2pd -stack 的收集参数怎么配# 建一个专门的目录存结果避免和诊断目录里的历史文件混在一起 mkdir -p /tmp/stack0531 cd /tmp/stack0531 # 每 3 秒收集一次全部 EDU 的 STACK连续收 10 次 db2pd -d OAPDB -stack all dumpdir/tmp/stack0531 -rep 3 10三个参数各有用途。-stack all表示收集所有 EDU 的栈不做筛选因为事先并不知道哪个 EDU 会是 Holder。dumpdir指定输出目录不指定的话结果默认落在 DIAGPATH 下和历史诊断文件混在一起很难分辨。-rep 3 10表示每 3 秒一轮、共 10 轮之所以要重复收集就是因为 LATCH 等待不是持续存在的单次收集大概率扑空。10 轮覆盖 30 秒通常能撞上一次阻塞窗口撞不上就把轮次加大。注意生产库繁忙时段收集 STACK 会明显消耗系统资源对数据库性能有可感知的影响务必评估后再执行尽量避开业务峰值。4.2 grep 验证抓没抓到 pool_table_latch收集完不要急着逐个文件翻先用 grep 确认这批结果里有没有目标 LATCH。# 在结果目录里检索所有 stack 文件看是否捕获到目标 LATCH cd /tmp/stack0531 grep -l pool_table_latch *.stack.txt grep pool_table_latch *.stack.txt | head -20-l只列出命中的文件名能快速判断这批结果有没有价值不加-l则输出具体行方便看是 Holding 还是 Waiting。命中结果里会同时出现两类行Holding Latch type: (SQLO_LT_SQLB_PTBL__pool_table_latch)和Waiting on latch type: (SQLO_LT_SQLB_PTBL__pool_table_latch)后面的 Address 是同一个地址说明它们争的是同一把锁。如果一条都没命中说明收集窗口没有覆盖到阻塞时刻直接重收不要在空结果上做分析。4.3 读 Holder 与 Waiter 的函数调用链找到命中文件后进到对应 EDU 的栈文件里看调用链。函数名是 C 修饰名看着吓人但关键字面意思加上 DB2 架构常识足够判断操作类型。Holder 的栈里能看到这样的调用关系sqlbSnapshotTablespace调sqlbMonSMSGetContainerPages再往下是sqlbMonSMSGetContainerPages调SQLB_FIND_BUF::next最终落到sqlofindn2、__xstat64这类文件系统调用。直白地说这个 EDU 在对表空间做快照而且是在逐个获取 SMS 表空间容器的数据页信息一路走到了操作系统的 stat 调用。文件系统调用是有 IO 开销的容器数量越多、目录里文件越多这一趟就越慢——它拿着pool_table_latch的整段时间里别人全都得等。再看 Waiter 的栈调用关系是sqldTableCreateTemp→sqldInternalCreateTable→sqlbGetSysTempDatapool往上还有sqldEvalDataPred、sqlriFetch、sqlrita。翻译过来就是正在执行一条查询语句语句里需要创建内部临时表于是去系统临时表空间申请数据页卡在了获取 LATCH 这一步。两条栈拼在一起因果链就完整了表空间快照操作耗时过长长时间持有pool_table_latch需要建内部临时表的查询排在后面全部堵住堵住的会话计入 ACTIVE SESSION业务侧表现为响应变慢。那为什么会有频繁的表空间快照因为数据库监控系统在每台服务器上部署了采集代理会定期拉取表空间信息。这个动作平时无害只有在它变慢的时候才成为问题。所以下一个问题自然是快照为什么变慢。4.4 analyzestack 汇总以及 TEMPSPACE1 的 354661 个页手工翻几十个栈文件效率太低DB2 安装目录里带了一个 Perl 脚本可以批量汇总。# -d 指定对比时比较的函数个数-i 指定 stack 文件目录-l 开启 LATCH 分析 perl ~/sqllib/pd/analyzestack -d 50 -i /tmp/stack0531 -l脚本会生成LatchAnalysis.out和StackAnalysis.out两个结果文件前者汇总 LATCH 的 Holder 与 Waiter 对应关系后者把相同调用链的栈归并统计出现次数最多的栈排在最前面——这比逐个看文件高效得多。-d的取值影响栈对比的粒度值越大越严格50 是个常用起点-i既可以是目录也可以是多个具体文件路径。这个脚本没有官方支持声明用法只能靠-help自己摸索但作为辅助分析工具足够好用。顺着「SMS 表空间容器」这条线索去查表空间发现db2 LIST TABLESPACES SHOW DETAIL本身就要跑好几秒才出结果——这个反直觉的信号当时没人留意其实已经是答案正常情况下这个命令是秒回的。db2 LIST TABLESPACES SHOW DETAIL结果里 TEMPSPACE1 的信息很扎眼Tablespace ID 为 1Type 是 System managed spaceContents 是 System Temporary dataTotal pages 达到 354661Page size 是 32768 字节Extent size 32 页Prefetch size 768 页Number of containers 为 4。按页数乘页大小算下来就是 10G 量级。而系统临时表空间在正常状态下应该非常小涨到 10G 说明有东西没被回收。进到容器目录看文件就明白了目录里堆着大量SQL0xxxx.MEMBER0000.TDA文件单个 1048576 字节还有个别是 32768 字节。TDA 是临时数据文件正常情况下用完即删现在却留在了表空间里。翻监控系统的表空间大小历史曲线能看到某个时间点 TEMPSPACE1 从 0 直接暴涨到 10G再对照那个时间点的会话监控当时有过一次 ACTIVE SESSION 冲到 800 多的尖峰——大量 SQL 同时使用临时表空间数据库没崩、语句也都成功了但留下了一堆没清理的 TDA 文件成了后来踩到的雷。4.5 deactivate/activate 才是解药官方技术说明里对这个现象有明确描述SMS 临时表空间中的 TDA 文件可能残留并占满文件系统这属于设计行为Work as Design不是 bug。这句话解释了两件事为什么没有报错、为什么文件不会自己消失。解决办法是把数据库彻底停用再启用让临时表空间重建。# 先确认没有活动连接force 会强制断开生产环境务必在维护窗口执行 db2 force applications all # 停用数据库释放所有临时表空间和残留 TDA 文件 db2 deactivate db OAPDB # 重新启用 db2 activate db OAPDB # 验证页数应恢复到很小的量级 db2 LIST TABLESPACES SHOW DETAILforce applications all会中断所有连接必须在维护窗口做并且提前通知应用方。deactivate和activate是一对前者释放数据库级别的资源后者重新拉起。执行完之后再查 TEMPSPACE1页数回落到很小的量级LIST TABLESPACES SHOW DETAIL恢复秒回之前那个「命令本身变慢」的异常信号也消失了。注意必须是 deactivate/activate 数据库只重启数据库实例无法释放这些残留的临时表空间文件这一步走错会白等一次维护窗口。处理完继续观察一段时间ACTIVE SESSION 回到个位数业务侧反馈的响应变慢也消失了。到这里问题闭环但根因层面还有一件事没做——为什么快照会慢到拿住 LATCH 不放。容器里的文件数量是直接因素而文件数量又是上一次 800 并发尖峰留下的。也就是说真正的预防点在容量规划和临时表空间的使用规范上而不是等它涨到 10G 再清。顺带说一个验证手段可以用 db2trc 对DB2.SQLB.sqlbSMSGetContainerPages.entry做入口挂起追踪让实例在进入这个函数时暂停从而从容地抓取现场信息。这个手法适合在测试环境复现问题时用生产环境要非常谨慎。5. 排查避坑清单这五条踩过的坑别再踩这一章全是血泪经验。同样的现象走错一步就可能多花半天甚至误判方向下面五条按「现象 → 原因 → 解决」写清楚。5.1 只重启实例TDA 文件一个没少现象执行了实例级重启服务恢复了但LIST TABLESPACES SHOW DETAIL还是慢TEMPSPACE1 的页数没有下降过一段时间性能问题原样复现。原因残留的 TDA 文件属于数据库级资源实例重启不会触发临时表空间的清理流程文件继续躺在容器目录里。很多人默认「重启治百病」在这个场景里完全不成立。解决改用db2 deactivate db dbname再db2 activate db dbname执行前用db2 force applications all清掉连接。判断是否真的清干净不看服务状态看 TEMPSPACE1 的 Total pages 有没有回落。5.2 单次 db2pd -latches 没异常就排除了 LATCH现象跑了一次db2pd -latches输出里没有任何等待于是判断「不是 LATCH 问题」回头继续改 SQL改了两天没效果。原因LATCH 等待是间歇性的持续几秒就消失单次采样命中阻塞窗口的概率很低。这次故障里第一次采样就是干净的真正的异常是改成持续采样之后才暴露的。解决一律带-rep参数采样间隔 1 到 2 秒连续跑十几分钟覆盖业务高峰。判断标准不是「有没有出现过等待」而是「有没有出现过 1 个 Holder 拖住多个 Waiter 的集中阻塞」。5.3 生产库长时间收 STACK 把系统拖垮现象为了抓到间歇性问题在生产库上连续收集 STACK 半个多小时结果数据库更慢了业务方直接打来电话。原因收集 STACK 需要挂起线程读取调用栈本身就有明显的资源开销EDU 数量多的时候开销叠加得很厉害。收得越久、轮次越多对业务的影响越大。解决先在小压力时段试跑一轮确认命令参数没问题正式收集控制在几十秒到几分钟用-rep 3 10这种有限轮次而不是无限循环。收完立刻停止不要挂着不管。测试环境能复现的就别在生产上硬抓。5.4 监控代理定期 SNAPSHOT 放大 LATCH 竞争现象问题解决后过了一段时间又有苗头ACTIVE SESSION 偶发抬升但业务量并没有变化。原因数据库监控系统在每台服务器上都有采集代理会定期对表空间做快照。这个动作平时无害一旦临时表空间里堆了大量文件快照耗时就会从毫秒级涨到秒级持有pool_table_latch的时间同步变长把后台采集变成了前台阻塞。解决把表空间大小纳入日常巡检对 TEMPSPACE1 设置阈值告警一旦超过预期量级就排查是否有并发尖峰残留。同时评估监控采集频率对表空间这类元数据采集不必追求高频降低无谓的快照次数。5.5 先改 SQL 加索引方向一开始就偏了现象看到慢 SQL 就加索引、拆查询、改写逻辑改完MON_GET_PKG_CACHE_STMT一看PCT_WAIT还是 95% 以上执行时间没降。原因慢的根因不在执行计划而在 LATCH 等待。加索引优化的是数据访问路径对内部轻量锁的争用毫无帮助。而且当时那些复杂长 SQL 早就上线了近期没有任何变更本就不该是怀疑对象。解决先用MON_GET_PKG_CACHE_STMT把时间拆开看清是花在读、锁、日志、排序还是别的等待上再决定优化方向。等待时间占比极高且四项常规等待都不高时直接转向 LATCH 排查不要在 SQL 上继续消耗时间。6. 快速定位这类问题的顺序与验证方法把这次的路径压缩成一套可复用的顺序遇到「指标全绿但系统就是慢」时照着走能少绕很多弯。核心原则是先确认现象客观存在再用排除法砍掉大方向最后在剩下的方向里做深度取证每一步都要有明确的判据不能凭感觉跳步。顺序观察对象关键命令判据1会话数量与状态db2top -d db按d看 ActSess按l看状态会话数远超历史水位且集中在 UOW Executing2资源与等待db2top 界面 HitRatio、LOCK WAIT、四个 IO 时间指标全部正常排除 CPU/内存/IO/锁3语句时间构成MON_GET_PKG_CACHE_STMT算各项等待百分比等待占比 90% 以上且非常规等待4LATCH 争用db2pd -latches -rep 2持续采样出现 1 个 Holder 对多个 Waiter 的集中阻塞5栈与 LATCH 对应db2pd -stack all dumpdir... -rep 3 10grep 命中同一 LATCH 地址的 Holding 与 Waiting6表空间体量db2 LIST TABLESPACES SHOW DETAIL命令本身变慢临时表空间页数异常偏大7修复验证db2 deactivate/db2 activate页数回落ACTIVE SESSION 回到个位数几个实操上的细节值得单独记一下。第三步做完之后如果发现等待占比高但四项常规等待都低不要再犹豫直接进第四步这是最强的转向信号。第四步的采样一定要持续单次采样在这个场景里没有任何参考价值。第五步收完栈先 grep 再分析命中不了就重收别在空结果上推演。第六步有个很隐蔽的判断点LIST TABLESPACES SHOW DETAIL本身变慢就是异常正常情况它应该是秒回的这个信号比页数更早出现。验证环节容易被草率处理。清完临时表空间之后别只看一次命令输出就收工要连续观察一到两个业务高峰确认 ACTIVE SESSION 没有再冲到几十、MON_GET_PKG_CACHE_STMT里那些with开头语句的PCT_WAIT回到正常区间、监控代理的表空间快照耗时恢复正常。三样都对上才算真的修完。从那以后我每次遇到「常规指标全绿但会话数异常」的反馈都会强制把 LATCH 持续采样和临时表空间体检加进排查清单不再默认「指标正常就等于没问题」。临时表空间这种平时没人看的对象往往藏着最贵的坑。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站