UDN-企业互联网技术人气社区

板块导航

浏览  : 1127
回复  : 0

[干货] 以"器"驭"道"—透过生活看oracle优化

[复制链接]
呵呵燕的头像 楼主
发表于 2016-11-25 22:53:15 | 显示全部楼层 |阅读模式
  ◤一个案例告诉你什么是行迁移?◢

  一切的开始就从oracle的两个比较容易混淆的术语讲起吧,说到行迁移(migration)and行链接(chain)很多有一定经验的dba也不一定能马上区分。

  ▪ 行迁移:当修改不是行链接的行时,当修改后的行长度大于修改前的行长度,并且该数据块中的空闲空间已经比较小而不能完全容纳该行的数据时,就会发生行迁移。

  ▪ 行链接:当第一次插入行时,由于行太长而不能容纳在一个数据块中时,就会发生行链接。

  是不是好难记?OK,先让我们看看生活中的某个真实场景

  A君换了个手机号码,要想让他所有的联系人都能及时联系到他有两种办法。

  Method 1:是通过新号码编辑条信息,告诉大家我换号了,并告知新号码。然后所有的联系人都会更新自己的通讯录。我想大多数人都遇到过这种情况吧。但是如果有一天,你超过十个的联系人发消息说换了新号,你会不会觉得更改通讯录的工作相当繁琐。

  Method 2:A不变更之前对外的号码,而是将这个号设成呼叫转移,将呼入这个旧号的来电全部转移到新号码上。这样一来他所有的联系人是不是可以在不更换号码的情况下最快的找到A了。

  其实第二种方式就是行迁移的全部了,这里的A就是数据库中的行数据,而rowid就是手机号了。

  Oracle设计行迁移的初衷就是为了以最小的代价(索引不需重建)实现行数据在块级别的变更。这本来是个高效率的想法,结果却在历代讲义中变成dba和开发人员避之不及的洪水猛兽了。读了前面这个故事,会不会对行迁移感到一些小爱。

  ◤这才是正确的诊断与改进◢

  我们可以再想象这样一个场景

  一对小夫妻结婚的时候是住在30平的小房里,开始也不觉得挤,但是当他们养了BABY后,房子太小住不下了。他们之后搬进了十公里之外的两室户了。然而搬家前已经有很多客人打算拜访了,很多正在路上。 但是小夫妻没有来得及通知所有认识他们的人新住址。为了避免客人们找不到他们而失望而归。他们在老房子门口贴了新房子的地址。这样好友到达时通过新房地址就能找到小夫妻了。

  第二个故事说完了,似乎没什么内容也不精彩,但在我看来,oracle的诊断思想、方法论却可以通过这个故事体现出来。

  我们思考下这个故事具体都有哪些环节:(将过程细化)

  ▪ 先将整个过程细化,具体环节就出来了:

  1.客人去找小夫妻

  2.小夫妻因为房子小已经搬家

  3.新家距离老房子较远

  4.老房子存在的价值

  ▪ 接下来找到细节中的矛盾:

  找细化项主要矛盾(开销最大的部分)

  ▪ 依次分析各细化项的开销:

  1. 客人能否找到小夫妻

  2. 小夫妻搬家的开销

  3. 客人找到老房子后通过地址找到十公里外小夫妻的开销

  4. 老房子空置后的开销

  找到主要矛盾后,如果能够相应解决,就能达到目的。

  接着考虑怎么优化改进,从而解决问题。

  客人已经在路上了,目前没有比这个更紧急的事情了,所以在门前贴新地址的确是最有效的解决办法,但是这是个临时办法,不能长久使用。因为成本实在太高。

  1. 客人得根据原地址先到老房子,然后在绕路去十公里外的新地址。这里的高成本体现在客人访问路径被拉长。如果能直接去新房地址则效率更高。

  2. 老房子存在的成本,房价飙升,老房子很贵啊,而现在老房子存在的价值仅仅是提供新房地址,实在太浪费了。

  综上所述,在使用临时办法之后,我们必须要找到降低成本开销,更高效的方法。

  很明显我们可以在客人走后,告诉其新地址,然后卖掉老的空房即可。转化到oracle中,我们首先考虑的就是任何更改是否会对生产有影响。在生产期间(客户拜访阶段)最关键的是可用性而并非性能。接下来我们可以重建表和索引(让数据库知道新块数据的直接地址)。

  我们对开销考虑全面了吗?

  不管是临时办法还是变更地址,搬家成本和时间成本都比较高,为什么不能开始就考虑到需求呢。如果我们知道一对小夫妻未来是有很大可能有小孩的,为什么不能初始就分配一套两室户呢。(反之如果开始知道是一对老夫妻,则生育几率则会小很多)。

  在oracle当中,我们就可以根据表的特性(将来是否会有大量DML操作)设置较大的pctfree参数,预留出更多的增长空间。

  到此问题圆满解决了,冷静思考生活中的小事,总结出了诊断问题和解决问题的方法论如下:

  诊断思想->过程细化->找到细化项主要矛盾->改进优化->理解需求->避开矛盾从其他路径完成需求

  ◤“道”与“器”◢

  上述总结的一套流程某个案例故事演绎推理出来,任何事物都可以多角度看待剖析。我们还可以将解决问题的事情分成意识(非技术能力)和技能(技术能力)两部分。在我们看来,这就是troubleshooting和优化的两大法宝。

a.png


  存在即是合理,问题的产生一定有其两面性,怎么独立思考,把握全局都属于意识类,和具体的技术能力无关。笔者做开发的时候,曾经听到有同事常说sql中exist比in效率高。不管与否,我只想说,如果存在这个假设,那oracle为什么还要保留in呢。生活中也好,oracle中也好,任何事物没有fast=true的开关。意识需要通过大量实践和对每次事件深入思考去培养。

  当然技术也不是一生下来就会的,必须经历过训练学习才能掌握。两者都很重要。两者的关系好似“道”与“器”。道是形而上的东西,是别人无法教授的,只能靠自己感悟;器是有形的东西,很容易获得,也最容易使人从中受益。我们在如饥似渴地阅读,认真地参与实践之外,其实更应该多花些时间来思考一些形而上的东西。而这些东西可能就在你身边,在生活中的细小处。

  ◤应用案例◢

  故事结束了,和大家分享下工作中的诊断案例吧

  某期货公司生产系统出现故障,在中午12点15分到20分这段时间内 产生大量as积压,严重影响交易。情况紧急,需要立即着手调查,该怎么处理呢?

  根据总结的“一套流程”,我们自然想到,这套流程主要分为诊断和改进优化两个环节,由于现在还不明确问题出在该数据库的哪个模块?因此进入诊断环节是必要的,然后根据诊断定位出来的具体问题,再进行具体的优化。

  调用oracle工具,先通过ash工具精细的找到12点15分到20分这段时间,数据库在经历什么等待。再使用awr工具查找12点至1点之间数据库整体状态。

9.png


  ▪ 将过程细化:

  1. 那个时间段的library cache pin, library cache load lock 等待严重.

  2. 有大量row cache objects等待事件

  3. 大量db file sequential read等待事件

8.png


  Library cache pin 事件是用来管理library cache的并发访问的, pin一个object会引起相应的heap被载入内存中,如果客户端需要修改或检测这个object它就必须在锁住后取得一个pin. 当一个session对SQL语句进行硬解析的时候,这个session就必须获得librarycache lock,这样其他session就不能够访问或者更改这个SQL所引用的对象。

  Row cache objectslatch的争夺也就意味着数据字典的争夺。从block(阻塞)等待中library cache pin/lock也是占大头。

7.png


  说明有大概会话因为这个等待事件被锁了。

  通过等待事件名在google中查询,就可以知道数据库大概的情况了,以上部分我认为都属于技能类,也就是“器”的部分。

  ▪ 接下来找到细节中的矛盾:找细化项主要矛盾

  1. 经查排在前几位的由于library cache pin而等待的语句皆为风控模块的语句 ,他们有个共同点就是都没有使用绑定变量,并且执行频率很高 并发很高。没有绑定变量意味着sql语句为硬解析。

  2. latch: row cache objects等待事件,那么会导致CPU很高,主机和数据库响应都很慢。

  3. 有大量db file sequential read等待事件。说明当时逻辑读很厉害

  我们来理一下思路,从各项矛盾来看数据库是因为风控语句没有使用绑定变量,大量硬解析,导致library cache pin,library cache lock。这两样消耗大量CPU资源引起应用层面AS积压。

  这个解释很通顺(当时客户也认同),OK 问题找到了,风控模块有问题,我们找风控人员吧。但问题真的找到了吗?大家仔细想想,风控模块上线已经很久了,即使有大量硬解析,为什么偏偏是这个时间点突然爆发。

  我始终相信世界上没有无缘无故的爱与恨。一定是有什么东西触发了他们。从事件来看仅仅1,2就得到了结论。那3呢,有大量db file sequential read等待事件。此时数据库除了有library cache锁,还经历着大强度的读操作。根据线索找到这句语句

6.png



  原来这是再查一年的历史持仓。(hisholdsinfo表非常大)

  通过数据库理论知识可知,oracle为了提升读速度,是先将数据读入内存的db_cache区,而数据库SGA共享全局内存区域中包含为提升读查询的db_cache区,为sql解析提供场所的librarycache区等,而他们之间大小是根据数据库负载情况动态调整的,如果sql解析量大,则librarycache会抢占db_cache区域,反之亦然。

  至此整个问题链就清晰了,一年持仓查询导致大量的逻辑读,db_cache区从而抢占了librarycache区的空间,而librarycache区域的减小使得本来风控硬解析的空间不够,而产生大量library cache锁等待。

  知道了原理和过程,调优和改进则变得更加简单自如。

  1. 我们将历史查询功能as指向到了灾备查询库。

  2. 设置了librarycache空间的最小值,不管怎么抢占至少保留这个最小值。

  Alter system set shared_pool_size=2500M scope=both

  3. 更改风控语句,让其改成使用绑定变量的形式 进一步减少硬解析的可能。从而减少系统资源消耗。

  ◤总结◢

  生活中总会遇到形形色色的问题,其实技术来自于生活,解决问题的方法也在身边。培养独立思考的能力,养成由浅至深全面观察事物的意识。

  技能是和意识是紧密联系的,比如 10046 TRACE诊断工具包的使用和学习;比如执行计划的查看与分析;比如理解索引的原理;比如知道如何使用并行的命令。

  最终达到以"器"驭"道",至上而下看待解决问题。我想这才是我们客服工程人员的精髓吧。

原文作者:余毅 来源:开发者头条

相关帖子

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关于我们
联系我们
  • 电话:010-86393388
  • 邮件:udn@yonyou.com
  • 地址:北京市海淀区北清路68号
移动客户端下载
关注我们
  • 微信公众号:yonyouudn
  • 扫描右侧二维码关注我们
  • 专注企业互联网的技术社区
版权所有:用友网络科技股份有限公司82041 京ICP备05007539号-11 京公网网备安1101080209224 Powered by Discuz!
快速回复 返回列表 返回顶部