脑洞大开!使用Perf深入研究Oracle内部(有彩蛋)
本文根据DBAplus社群第112期线上分享整理而成,文末还有好书送哦~
袁伟翔
新炬网络高级专家
长期服务于运营商,精通Oracle数据库故障诊断,内核技术
拥有10多年的数据库开发运维经验
主题简介:
Perf简介
Perf基本使用
Perf和Oracle如何结合进行深入研究
Perf生成火焰图
一、Perf简介
Perf是用来进行软件性能分析的工具,使用Perf,可以帮我们解决一些性能问题。例如:程序运行很慢,占用CPU 100%,需要知道是程序的哪一个函数占用的CPU最高?可以以此来定位问题的根源。
运行环境:
这里介绍的Perf是运行在Oracle Linux Server Release 7.2上,内核版本4.1.12
Perf的版本:
Perf version 4.1.12-94.3.5.el6uek.x86_64
运行Perf list,可以看到现在Perf主要分为以下几类:
Hardware event,Software event,Hardware cache event,Raw hardware event descriptor,Hardware breakpoint,Tracepoint event等等。
Hardware event、Hardware cache event硬件这类的诊断依赖于PMU(performance monitoring unit),一般处理器厂商都会在硬件中加入了 PMU 单元, PMU可以让我们对某种硬件事件设置counter,一旦发生这种事件,处理器就会统计该事件发生的次数。一旦发生的次数超过设置的counter,便会产生中断,Software event是内核产生的事件,例如CPU时钟、上下文切换等。
Tracepoint event,是内核中静态tracepoint所触发的事件,只有2.6.3x以上的内核才可用。
二、Perf基本使用
介绍完基本概念,来看看Perf是怎么使用的。
1、Perf Top
Perf的top和linux的top工具类似,实时打印采样函数,默认的采样事件是循环的。这里Perf显示了大部分消耗cpu-time高的函数。
当然,如果想要继续分析下去,还可以按s,再输入函数名,如图所示,我输入了函数e1000_watchdog,显示下面具体的code地址及原子操作。这里的ja和mov都是汇编语言的一些操作,ja是判断两个无符号数之间的大小关系然后跳转,mov是数据传送指令。
2、Perf Record
Perf Record的作用是记录一段时间内系统或者进程的性能事件。这里用一个Oracle操作来做例子。首先打开2个session,会话1是登录到Oracle,查到它的spid:2794。
那我们就在session2这边监控2794这个进程。使用perf record –e cpu-clock –p 2794。
这里需要说明一下-e,这个就是我们前面介绍的事件,可以通过Perf list查看,这里我们选择了cpu-clock计数器。
这边监控打开之后,我们切换到session 1,随便执行一条SQL操作。
然后回到session 2,按ctrl + c终止监控。运行perf report,就能看到刚刚监控的结果了。如下所示:
这里显示刚刚整个SQL操作,最消耗CPU的是内核_raw_spin_unlock_irqrestore函数。
有了上述两个基本操作,可以帮助我们研究那些莫名其妙CPU过高的问题,分析出具体是哪个函数导致的,甚至这个函数的相关原子操作都可以能被我们看到。因为Oracle是不开源的,所以我们发现是那个函数异常了,就只能上Mos上搜索。
例如:刚刚看到的有一个叫kghalf的函数,我们上去搜索一番,你看在这个函数上面果然存在这一个bug,不过这里版本对不上。
是不是很强大?在我们没有头绪的时候,通过Perf top或者Perf record往往能帮我们找到一些线索。
三、结合Perf和Oracle进行深入研究
前面介绍的都是Perf的一些基本用法,后面我们来介绍一下它怎么和Oracle结合起来,做一些动态追踪技术。动态追踪技术主要使用的是探针,下面我们来介绍一个例子。
Perf和10046等待事件跟踪
这里首先要介绍一下Oracle内核的三个函数:kskthbwt、kskthewt、kews_update_wait_time。
这三个函数,分别是内核服务编译线程开始等待,内核服务编译线程结束等待,内核事件更新等待事件的等待时间。需要注意的是,这里涉及到汇编语言的原理知识,如段地址和寄存器,还有偏移量。如果大家需要深入研究,建议看一下计算机书籍编译原理和深入理解计算机系统。
X86-64架构下有16个64位的寄存器,其中%rdi、%rsi用作传递函数参数,分别对应第1个参数、第2个参数。图中RDI代表着等待时间(微秒),RDS代表的等待事件的number。
这里需要对这三个函数设置探针。
对上述三个函数设置完探针之后,我们运行perf probe –l就能看到我们设置的探针。你如果觉得设置有问题,可以运行perf probe –del进行删除。设置完成之后,我们就可以做10046追踪了。
运行完成出现下列结果:
上图我们能够看到探针做的一些事情。会话2794等待事件0x162,等待时间ox553df61f78f21,然后下一个等待事件0x93,等待时间0x553df61f7938d。这些数据不是很直观,我们需要对其格式化一下。等待事件的这些编号需要从视图v$event_name获取。
通过下列脚本格式化后,输出结果如下:
当然还有很多函数可以做探针来进行学习和研究,大家可以通过Github来获取各种函数的意义及参数。例如函数opiprs就是硬解析,而kksParseCursor则代表了软解析。如果你想知道Oracle数据库都有哪些函数,可以运行命令nm -D $ORACLE_HOME/bin/oracle,你可以看到10多万行的信息。绝大多数的函数都是非公开的,我们可以通过MOS获取到一些信息,然后还可以通过oradebug doc获取到一些信息?如果有精力,也可以使用gdb来慢慢调试。
https://github.com/LucaCanali/Linux_tracing_scripts/tree/master/Perf_probes
四、Perf和火焰图
火焰图可以一针见血地指出程序的性能瓶颈,指出问题之所在。而Oracle上我们能做的火焰图一般有下面几种。
1、基于执行计划的火焰图。不仅仅有执行计划的信息,还有执行函数的信息,可以清楚帮助我们分析SQL语句的瓶颈。
2、基于逻辑I/O的火焰图。不仅仅有执行计划的信息,还有执行I/O函数的信息,清晰明了。
3、基于物理I/O的火焰图,同上。
4、基于系统负载的火焰图。它可以帮助我们直观地查看到系统最耗费资源的地方,快速定位问题。
要生成这些图表,需要我们下载一些工具。
Flame Graphs
https://github.com/brendangregg/FlameGraph.
到这里下载最新的版本example.zip
os_explain
http://blog.tanelpoder.com/files/scripts/tools/unix/os_explain
使用方法:
Session1:找出OSPID,并运行SQL语句,先让数据缓存到内存当中;
Session2:运行perf record 进行数据采集
perf record -a -g -F100000 -p pid
Session1:再次运行SQL语句
Session 2:按CTRL-C停止采集
Perf的数据有了,下面就是生成图了
当然,每一种图的执行方法不一样。详细可以参考:
http://externaltable.blogspot.com/2014/05/flame-graphs-for-oracle.html
Q1:Perf与Oracle结合使用,有没有要改什么配置或者参数的地方?
A1:如果你只是基本使用,查一些性能问题,用三个功能perf stat top record。不需要做什么配置。如果要搞探针,你可能还需要重新编译到内核开启一些功能。否则内核不支持。不同版本的Oracle使用方法不同。
Q2:Perf支持哪些平台?比如Solaris支持吗?
A2:基本都在Linux下使用,和Linux内核代码一起发布。Solaris上有大名鼎鼎的Dtrace。
Q3:有点深奥,袁老师是怎么想到Perf 可以与Oracle结合一起使用的呢?听下来,修改函数和添加探针,会不会对自身软件有影响?
A3:Perf主要是可以解决一些未知性能的问题。运行Perf top和Perf record可以帮助我们定位函数级别的问题。使用起来非常简单。Oracle自身也有很多函数,经常需要我们做error stack。所以结合起来使用定位一些函数CPU高的问题很合适。至于探针这些操作是很复杂,只适合学习研究。在实际操作中我们还是以top和record分析性能为主。
Q4:可以加到监控里面做分析吗?
A4:可以搞脚本,加到监控里面。
回听直播请戳 https://m.qlchat.com/topic/details?topicId=270000405021818
密码:112
好书相送
在本文微信订阅号(dbaplus)评论区留下足以引起共鸣的真知灼见,并在本文发布后的隔天中午12点成为点赞数最多的1名,可获得以下Oracle好书一本~
特别鸣谢图灵教育为活动提供图书赞助。
◆ 近期热文 ◆