Oracle 12C已经开始逐渐开始走上各客户的生产系统了,大家对12C的各种新特新是怎样理解的呢?通过读白皮书还是其他的官方文档?如果遇到问题了,我们如何一步一步定位到新特性上?今天我们迎来CESOUG成员海猫的分享,看看他对12C的新特性的认识。
正常情况下truncate一张表需要多长时间?
我们应该如何判定一个truncate操作的时间阈值?
如果truncate操作我们无法找到对应的SQL_ID,如何快速定位truncate操作存在的等待在哪?
如果操作过程中出现了我们意想不到的等待事件,我们如何精确严谨的定位问题所在?
如果是遇到了新特性,我们又如何理解新特性带来的好处和隐患?
我们不妨仔细阅读本篇,以上一切尽在此文中。
正准备背包下班,客户在办公室呼喊的我的名字说有一套上线数据库系统出现跑批慢的情况。一听到“跑批慢 ” 三个字,在去客户工位上的分分钟里,我的心里就职业病般的涌现出各种常见案例 :
+
+
可能是跑批里的某些SQL本身性能问题导致的
可能是跑批业务被其他会话阻塞了
可能系统的资源有瓶颈了
……
幻想的再多,不如实际调查,所谓没有调查就没有发言权
-----编辑自己说的名人名言
+
+
客户很专业,嗖嗖的就把我想要的信息一股脑的提供给我了:
1.从脚本来看,出现缓慢的不是什么大量复杂的增删改操作,就是一批整齐排队 truncate 语句;
2.在聆听客户的描述中,得知目前这些相关表的 truncate 操作需要 10 分钟左右,而业务超时阈值为 5 分钟;
看起来,客户上线前的测试还是没有做好 ! 也有可能客户心理预设本来 truncate 应该就在 5 分钟内完成,难道是 Oracle 让我们失望了吗?
我们看客户执行的 truncate 操作包括如下 :
看起来并没有什么特殊的地方。。。。查询了下,批量 truncate 的表中(将近 10 张表)记录数有上千行,也有上万、百万不等 。 相关表信息 :
二、确认问题
对于这种短时间内业务操作慢的情况,最有效诊断方法就是使用 ash dump 。客户似乎很了解我的套路,直接提供了 ash dump, 给我的诊断提供了很大的便利。
那么首先可以根据现有的 ash 快速定位 truncate 操作时的基本情况;根据客户提供的批量执行时间,可以直接定位到执行的 truncate 操作时的会话信息如下 :
很明显,我们看到 9x1qukh460yhp 就是客户执行的 truncate 操作。简单地对单条 truncate 语句统计执行时间,可确认如下 :
粗略估算,这个 truncate 语句大概执行了 1 分多钟的时间。
1 分钟?
1 分钟 ?
1 分钟?
……
Oracle 的单条 truncate 啥时候变得这么慢呢?不应该,不合理……满脑子问号,暂时存疑 。
继续看看还有什么线索, 我重新对问题时间段内的 truncate 操作的等待事件进行了分析如下:
从等待事件上来看,在 truncate 的时候大部分时间等待在 DFS lock handle 事件上; 至此,我心里大概有了很明确的诊断方向了。
也不再去考虑什么操作系统资源瓶颈, IO 慢等等乱七八糟的原因了,理都不理,还是老猫那句话:抓住重点不放,一心一意顺藤摸瓜,肯定可以找到问题的原因!!
注:很多时候,我们
DBA
排查一些老大难问题,在尚且不知根因的情况下,最好不要根据经验一个个去试,这不仅浪费时间,而且很容易让我们误入迷途。最好的办法就是用最有效的办法直奔主题。好比千军万马之中,最快结束战斗的办法不是跟千万小兵较量,而是擒贼先擒王,直取项上人头,岂不快哉?
三、思考思考
看到这,我们不妨一起来捋一捋这个案例的几个问题点:
+
+
1.truncate应该有多快
?
通常我们说
truncate
比
delete
要来的快,事实上是因为
truncate
操作只是需要修改相关
segment
中的几个关键的位图信息和段头信息,所以通常来说,我们认为
truncate
需要做的只是读取相关表
/
索引的几个关键块进行修改即可,这个操作应该是非常快的!
2.
DFS lock handle
等待是什么?
DFSlock handle
等待事件并不常见,通常在
RAC
环境中出现意味着当前存在着跨节点的调用(
Cross Instance Call
),即请求
RAC
中其他节点完成某些操作;
+
+
truncate 时出现大量 DFS lock handle 等待正常吗????
不确定!!对于任何等待事件,如果不对等待事件的具体信息进行分析,就判断其是否正常都是不负责的;所以这里想要定位问题,首先要定位出现 DFS lock handle 的原因。
各位看官注意啦!!下面就是一步步揭开等待事件 DFS lock handle 神秘的面纱的时刻 !(假装有音乐和鲜花~~)
四、等待事件分析
我们习惯分析各种 sharedpool 的 latch 等待、 library cache 等待,各种 IO 等待,各种 enq 锁等待,可是眼前突然出现一个较为陌生的等待事件 DFS lock handle ,你会怎么做呢?1. 百度、谷歌一把?2. 问问老前辈?3. 还是……? 哈哈,你想多了,当真正在银行生产环境处理故障的时候,身后一堆人围着,作为专业 DBA 人士,先别着急去网上找答案 。
这个时候, 方法论就尤为重要 。我们一定要有一套自己解决某些特定问题的一整套行之有效的方法、套路;而不是靠零零散散收集来的一些所谓的技巧、攻略;方法掌握了,一步步操作,很容易找到问题的源头。
想一想,不就是等待事件嘛, p1 , p2 , p3 通常是我们分析的重要入口 :
我们可以看到,比较熟悉的 type|mode ,还有 id1 、 id2 。这里问题时段的 DFS lock handle 等待事件的 p1 , p2 , p3 都是一致的,很有规律可循噢~~ p1 值按照我们的理解,应该包含了锁的类型和模式信息,而 p2 和 p3 是 id1 , id2 的意思;
上面这些信息有什么意义呢?这个时候就能看出你专不专业了。其实,我们可以从已有等待事件的解释文档来帮助计算出一些结果:
上面可以看到,通过 p1 值我们可以计算出这个锁的类型是 CI ,锁的模式是 5 ;
注:这个查询
type
的
sql
语句是不是靠死记硬背的呢?哈哈,我没那么厉害。对于这种,我一般都是用家中常备的小文档——
Oracle
官方文档;对于这种等待事件名称解释等等相关,我一般嗖嗖的直接看
reference,
基本上都能找到一些相关的解释;在
12c
的
reference
里有一章节
Descriptions of Common Wait Event Parameters
,里面就可以找到这个查询:
是不是感觉又学到一招呢?(窃喜……)
那么我们这里的 CI 锁又代表什么意义呢?这不难, Oracle 数据库里可以直接查询:
CI 代表的是 Cross-Instance Call Invocation 。根据提供的 description ,可以大概知道是跨实例的函数调用相关的锁。
搞清楚了锁的基本信息,接下来就要搞清楚持有这些锁到底做了什么?可以通过 ID1 的字段来可以了解到是在做什么操作时产生的该类调用,查询出来 id1 是 opcode ,就是 operation code ,所以肯定是一个操作代码。
这里代码 123 到底代表什么特别的意思呢 ? 此时只能借助相关文档的解释来帮助我们更好的理解 id1 和 id2 。
很显然这里已经告知 id1=123 代表 Nuke ILM file stats 。感觉离成功越来越近了……
Nuke ILM file stats 字面意思就是销毁 ILM 文件的统计信息,那么更深层的意思又是什么呢?或者说这样的操作为什么会在 truncate 的时候出现?难道有我们多年未知的天大的秘密在里面??
到这里各位可能需要捋一捋我们核查的路径了,看看我们都查了些什么:
+
+
通过ASH的sql_opname快速定位到相关的truncate操作;
通过该操作可以进一步定位到truncate过程中主要的等待事件是DFS lock handle;
通过等待事件的p1值可以换算出其等待的锁类型为CI,并了解到p2(ID1)值123意味着Nuke ILM file stats,而p3(ID2)值看起来并无特别用处;
+
+
到这里了解了这么多,我们该如何继续呢?再回到我们的问题,出现 DFS lock handle 等待正常吗?再具体一点出现跨节点调用实现 Nuke ILM file stats 的操作正常吗?我们该如何进一步确认?各位读者不妨也停顿一下,如果是你,你会如何进一步分析这个问题呢?
ILM ?
ILM ?
ILM ?
你是不是在想 ILM 到底是什么东东?
在笔者看来,问题查到这里,问题的关键词是 “Nuke ILM file stats” !这么一个看起来很神秘的缩写,后面却包含了几个问题 ?
什么是 ILM ?
看起来是 12c 的一个新特性。 对!记住我们目前的数据库是 12c 。这个很重要。既然是 12c ,肯定有很多我们还没有探知的新功能。
在这里, ORACLE 试图来帮助我们提供数据库中数据的全生命周期管理策略,策略的关键部分时Heat Map 和 ADO;如果是有这部分信息,那么 truncate 的时候关于 ILM 策略 ORACLE 会做什么呢?是记录 truncate 的相关信息还是销毁之前记录的 ILM 信息呢?从这里看似乎是要去销毁原有记录的 ILM 信息;但是我们继续了解 ILM 会发现:
可以看到,默认情况下 HEAT_MAP 特性是关闭的,那么我们的系统呢? 我们可以查看 heat_map 相关的参数及相关隐含参数如下:
可以看到当前,系统的 heat_map 的相关参数是关闭的; 当前的参数时关闭的,是不是以前曾经开启过,记录了相关的记录,但是却需要在 truncate 的时候来清理呢?我们进一步核查存储 HEAT_MAP 信息的段和相关的 ILM 策略,并未发现又相关的记录:
到了这里,我们新的疑惑又来了,在并未启用用 ILM 的情况下,并没有以往记录 ILM 信息的情况下, truncate 为什么会要去销毁 ILM file stats 呢?这个动作必要吗?即使有必要,需要等待这么长时间吗?是不是有那么点自相矛盾的意思?这样看来, ORACLE 本身在这个地方可能存在缺陷。成功的曙光近在咫尺了……
六、精确定位BUG
在了解了上述问题的各个关键点之后,我们就可以上 MOS 精确的查找 bug 了:
具体的 bug 描述如下:
通过描述,我们可以看到该问题只有在12c以后才存在,在12c引入ILM特性后,即使是没有启用heat_map特性,在truncate时oracle还是会去执行销毁ILM信息的动作,而从bug描述中的stack调用ktfs_imnuke_range来看,销毁操作是分段进行的,这个操作需要执行多次,具体的操作是试图将内层中的数据ILM数据刷入磁盘后一起删除,所以整个事件持续较长;
+
+
针对上述问题,oracle没有workaround,必须打上相应的patch或者升级到12.2来解决该问题;该补丁相应的做了两个事
:
通过判断当前是否开启了heat_map,如果未开启,则在truncate时不再调用相关销毁函数;
如果我们将heat_map参数从on调整到off状态,则会在修改参数时刻完成销毁所有ILM信息的动作,不再等到truncate是完成该动作。
+
+
综合上述信息,笔者再想到一个新的问题是:如果我们真的启用heat_map特性,制定相关策略,收集表的ILM信息,即使版本是12.2以上,那么truncate是否会不可避免的很慢?有兴趣的读者不妨测试一番,会有意外收获哦
~~~
七、解决方案与总结
针对上述问题,解决方案包括结果:
升级数据库版本到12.2
直接在当前数据库版本打
patch
:针对于这个
bug
,
Oracle
提供了单独的
one-off
的
patch
,可以考虑打上这个
patch
来解决这种问题
总结:
对于这个问题的分析,我们最终看到,12c提供了不少的新特性,事实上,从我们以往的经验来看,新特性总是意味着潜在的bug,如何在未了解新特性的情况下精确定位其中的bug,如何通过bug又反过来更深刻的理解新特性的意义,这是笔者希望从大家从本文中收获的,你get到了吗?
本文转载于中亦安图
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/31547066/viewspace-2283224/,如需转载,请注明出处,否则将追究法律责任。