11月03日,由Oracle 资深DBA彭小波老师在“DBA+东北群”进行了一次关于“无处不在的等待”的线上主题分享。小编特别整理出其中精华内容,供大家学习交流。
嘉宾简介
“DBA+社群”东北联合发起人。从事Oracle 数据库技术十余年,ACOUG核心成员,Oracle用户组年轻专家。现就职于某金融保险公司,曾服务于航天、航空、机车、大型制造行业数据库的维护以及系统开发,擅长Oracle数据库架构规划、SQL优化、OWI方面性能的优化。
内容摘要
ORACLE的等待事件是DBA洞察数据库问题的一个窗口。然而,说数据库出了问题都会触发一系列的等待事件,如何追根溯源找到问题所在,是我们每个DBA的目标。那么今天小波老师给大家分享他是怎样通过等待事件发现问题的。
演讲实录
数据库性能优化是一个神秘而又古老的话题,之所以说神秘是因为,一个困扰大家的SQL,在DBA的调整后,性能能提升百倍,甚至千倍。在外行看来,就像魔术师变魔术一样。古老是因为,当我们使用接触数据库那天起,甚至一些Oracle业界的技术大牛都在一直在孜孜不倦的研究数据库性能优化,如果想做个出色的DBA,数据库性能优化会伴随着我们整个职业生涯。
我想用一句话概括数据库优化,优化是数据库体系结构的延续,数据库的结构和运行的机制决定了数据库的优化模式,所以说数据库的体系是优化的基石。当你把数据库体系结构学明白了,优化是水到渠成。反过来,我们通过优化数据库,进一步的深入学习数据库的体系结构。
从这张图上我们看到数据库优化的主要方向大致分四部分(注:这里不讲主机,网络,存储等方面的优化):
资源的优化
实例的优化
SQL的优化
数据库的优化
Oracle社区中也提供了一个监控主机性能方面的一个小工具,OS Watcher。关于OS Watcher的使用我们可以参考MOS文档 ID 1614397.1。数据库各个方面都有优化的余地,主要有上面写的四大部分。其中SQL优化又是重中之重。
优化数据库的主要步骤:
1.设立优化目标和优化的方向。
2.采集数据库的信息。
3.修改数据库的配置。(注:这里不是指简单的修改数据库参数)
4.再次采集数据库信息。
那么,我们用现实生活中的例子来说明。
请你想一下你到医院看病的情况:
医生问你哪里不舒服,在数据库中就是确定优化的方向。医生给你测量体温,在数据库中就是收据数据库的信息。医生根据你的体温判断你发烧了,在数据库中就是根据收集的信息判断数据库问题所在。医生给你吃退烧药,在数据库中就是修改数据库配置。医生再次测量体温,达到预期效果,在数据库中就是达到了我们的优化指标。
优化是无止境的,达到预期就可以,用户能接受就可以。数据库有优化的向导(ADDM,STA,SPA),做的就是我上面写的事情。向导是死的,我们人是活的,千万不能刻舟求剑。我们要根据自己的实际情况来变化。
在Oracle9i及之前,我们已经拥有了很多很好用的性能分析工具,比如,statspack,sql_trace、set event 10046&10053等等。这些工具能够帮助DBA很快的定位性能问题。但这些工具都只给出一些统计数据,然后再由DBA们根据自己的经验进行优化。那能不能由机器自动在统计数据的基础上给出优化建议呢?
Oracle10g中就推出了新的优化诊断工具:数据库自动诊断监视工具(Automatic Database Diagnostic Monitor ADDM)和SQL优化建议工具(SQL Tuning Advisor STA)。这两个工具的配合使用,能使DBA节省大量优化时间,也大大减少了系统宕机的危险。简单点说,ADDM就是收集相关的统计数据到自动工作量知识库(Automatic Workload Repository AWR)中,而STA则根据这些统计数据,给出优化建议。
在Oracle 9i以前,当一个系统出现了明显的性能问题时,首先做一个statspack快照,等30分钟,再做一次。分析报告,在top 5 events里面发现’ cursor: xx wait ’事件。根据经验,这个事件可能是因为shared pool 中 cursor 的版本数变得过多,过多的硬/软分析,过多的无效/重新加载,加载了大量的对象,shared pool 大小不合适,资源的持有者被 OS 或者 Resource Manager 从 CPU 上移除内存的操作系统管理(例如 Linux x86-64 上非常大的 SGA,而没有实施 Hugepage),代码缺陷等等引起的。
根据这些经验,我们需要逐个来定位排除,比如查看语句的查询计划、查看user_tables的last_analysed字段,检查热块等等步骤来最后定位出原因,并给出优化建议。但是,有了STA以后,它就可以根据ADDM采集到的数据直接给出优化建议,甚至给出优化后的语句。
Why is my sql Slow,给我们引出了一个问题,为什么我们的SQL会慢哪?当这个问题迎面而来的时候,我想当大家会给出有各种答案。服务器资源不足,应用程序复杂多变,网络原因,SQL写的不好,数据库本身的问题,等等......
那么我想说的是,SQL慢,70%,80%是由于SQL写的不好。SQL的问题。不过,不完全是SQL问题,要具体问题具体分析,分析后才能给出正确的答案。
如果SQL写的不好,SQL慢,会引起大量等待时间,一条SQL慢有时甚至能拖垮整个数据库,导致数据库宕机。
最初Oracle 7.0中有104个等待事件,Oracle 8.0中有140个等待事件,Oracle 8i中有220个等待事件,Oracle 9i中有400个等待事件,Oracle 10g中有800个等待事件,随着版本的提升等待事件一路攀升。这也意味着oracle正向准确报告性能问题发展,性能问题更加细粒度化,当发现等待事件时能快速的定位问题。
这是一个典型三层架构的应用系统。它讲解了一个用户请求业务的整个流程。首先当用户在应用端发出请求,经过网络,到达应用,应用在经过网络,请求数据库查询数据。反反复复大约经历10个步骤才把数据返回给最终用户。Response Time = Service Time + Wait Time,每个环节都存在影响性能的因素。只要降低工作时间和等待时间,响应时间自然随之降低,有些问题只要降低工作时间,等待时间自然也会降低,但是有些时候,不能降低工作时间,这是只有降低等待时间一种方法。
从这里引入我们今天的主题,《无处不在的等待》,在Oracle世界里,Oracle是一个巨大的同步机,许多进程可以同时使用同一个资源,如果没有保护资源的精确的同步机制,资源的一致性将遭到破坏。Oracle利用Latch和Lock这两种同步机制保护资源。
一、产生的背景:
Oracle为了将物理IO最小化,把最近使用过的数据块保持在内存中。为了管理这些内存,oracle 使用如图的结构,Hash Chain的结构,Hash Chain位于共享池中,使用典型内存结构Bucket->Chain->Header结构进行管理。Hash Chain结构的起点是Hash表,Hash表由多个hash bucket组成,块地址 是由file#+block#组成的,当扫描块时使用Hash函数进行hash运算,使用hash值查找hash bucket,具有相同hash值的buffer haeder在hash bucket上以chain形式链接。
Buffer header有指向实际缓冲区的指针。注意:Hash Chain结构是在共享池中,而实际缓冲区信息存储在高速缓冲区中。Hash Chain结构利用cache buffers chain Latch来保护。当进程扫描特定的数据块时,必须获得相应数据块所在Hash Chain管理的cache buffers chain Latch。基本上一个进程获得仅有的一个cache buffers chain Latch,一个cache buffers chain Latch管理多个Hash Chain。
当多个进程同时检索Buffer Cache时,获得cache buffers chain Latch的过程中发生争用,就会产生cache buffers chain Latch等待事件。
使用SQL语句可以获得hash_latches,hash_buckets数量,因此一个锁存器保护Bucket数量是1048576/32768=32个。
SQL> select x.ksppinm name,
2 y.ksppstvl value,
3 y.ksppstdf isdefault,
4 decode(bitand(y.ksppstvf, 7),
5 1,
6 'MODIFIED',
7 4,
'SYSTEM_MOD', 8
9 'FALSE') ismod,
10 decode(bitand(y.ksppstvf, 2), 2, 'TRUE', 'FALSE') isadj
11 from sys.x$ksppi x, sys.x$ksppcv y
12 where x.inst_id = userenv('Instance')
13 and y.inst_id = userenv('Instance')
14 and x.indx = y.indx
15 and x.ksppinm like '
