【DB笔试面试865】序列cache值过小导致CPU利用率过高
♣
问题
序列cache值过小导致CPU利用率过高
♣
答案
1、故障环境如下表所示:
项目 |
source db |
---|---|
db 类型 |
RAC |
db version |
10.2.0.5.0 |
db 存储 |
ASM |
OS版本及kernel版本 |
AIX 64位 6.1.0.0 |
2、故障发生现象及报错信息
有一套数据库做测试的时候,CPU利用率很高,同事已经抓取了CPU和AWR的信息。发生问题的时间段是19点到23点,其中,nmon数据截图如下所示:
可以看到CPU的利用率是非常高的,下边来看看AWR中的数据:
从等待事件中可以很明显地看出“enq: SQ - contention”和“DFS lock handle”这两个等待事件异常。“Top 5 Timed Events”部分也是AWR报告中非常重要的部分,从这里可以看出等待事件排在前五位的是哪些事件,从而基本上就可以判断出性能瓶颈在什么地方。在这里,“enq: SQ - contention”等待了172254次,等待时间为69652秒,平均等待时间为69652/172254=404毫秒,等待类别为Configuration即配置上的等待问题。
3、有关序列等待的基础知识
根据AWR报告的内容,基本可以断定,只要解决了“enq: SQ - contention”和“DFS lock handle”这两个等待事件即可解决问题。其实,“enq: SQ - contention”、“row cache lock”、“DFS lock handle”和“enq: SV - contention”这4个等待事件都与Oracle的序列有关,如下所示:
SELECT *
FROM V$EVENT_NAME
WHERE NAME IN ('row cache lock','enq: SQ - contention','DFS lock handle','enq: SV - contention');
其中,PAREMETER1的值为“name|mode”或“type|mode”的事件为队列等待。在这类等待事件中,name代表队列的名称,type代表队列的类型,mode代表队列的模式。使用如下的SQL可以查询到锁的名称和请求的mode值:
SELECT CHR(BITAND(P1,-16777216)/16777215)||CHR(BITAND(P1, 16711680)/65535) "LOCK",
BITAND(P1, 65535) "MODE"
FROM V$SESSION_WAIT
WHERE EVENT IN ('enq: SQ - contention','DFS lock handle','enq: SV - contention');
其中,MODE值如下表所示:
模式代码 |
解释 |
---|---|
1 |
Null mode |
2 |
Sub-Share |
3 |
Sub-Exclusive |
4 |
Share |
5 |
Share/Sub-Exclusive |
6 |
Exclusive |
使用如下的SQL可以查询SQ和SV这两种锁的解释:
SELECT * FROM V$LOCK_TYPE D WHERE D.TYPE IN ('SV','SQ');
事实上,Oracle为了管理序列使用了如下表所示的三种锁:
在RAC上创建序列时,在赋予了CACHE属性的状态下,若没有赋予ORDER属性,则各节点将会把不同范围的序列值CACHE到内存上。比如,在拥有两个节点的RAC环境下,创建CACHE值为100的序列,则节点1使用1~100,节点2使用101~200。若两个节点之间都通过递增方式使用序列,则必须赋予ORDER属性。Oracle序列默认是NOORDER,如果设置为ORDER,那么在单实例环境没有影响,在RAC环境中,多实例实际缓存相同的序列,此时在多个实例并发取该序列的时候,会有短暂的资源竞争来在多实例之间进行同步。因此,性能相比NOORDER要差,所以RAC环境非必须的情况下不要使用ORDER,尤其要避免NOCACHE ORDER组合。
有一点必须要注意,当没有赋予CACHE属性时,不管ORDER属性使用与否或RAC环境与否,一直等待row cache lock事件。row cache lock是可以在全局范围内使用的锁,单实例环境或多实例环境同样可以发生。如果使用了CACHE,而此时DB崩溃了,那么序列会从CACHE值之后重新开始,在CACHE中没有使用的序列会被跳过,这样就会导致序列不连续。在创建序列时,CACHE的缺省值设定为较小的20。因此创建并发量多的序列时,CACHE值应该取1000以上的较大值。
另外,若一次性同时创建许多会话时,有时会发生enq: SQ - contention等待事件。其原因是VSESSION.AUDSID列值是利用序列创建的。Oracle在创建新的会话后,利用名为SYS.AUDSES的序列的NEXTVAL来创建AUDSID值。在Oracle 10g下SYS.AUDSES的CACHE值默认20,但在Oracle 11g下SYS.AUDSES的CACHE值默认为10000,通过如下的SQL可以查询:
SELECT * FROM DBA_SEQUENCES D WHERE D.SEQUENCE_NAME ='AUDSES$';
4、故障解决过程
首先查询出现问题时间段的ASH视图DBA_HIST_ACTIVE_SESS_HISTORY,通过该视图可以找到需要的序列名称。可以有多种查询方法:
SELECT D.SQL_ID, COUNT(1)
FROM DBA_HIST_ACTIVE_SESS_HISTORY D
WHERE D.SAMPLE_TIME BETWEEN TO_DATE('20160823170000', 'YYYYMMDDHH24MISS') AND
TO_DATE('20160823230000', 'YYYYMMDDHH24MISS')
AND D.EVENT = 'enq: SQ - contention'
GROUP BY D.SQL_ID;
可以看到SQL_ID为3jhvjgj7kbpmt的SQL最多,查看具体SQL内容:
SELECT * FROM V$SQL A WHERE A.SQL_ID IN ('3jhvjgj7kbpmt') ;
由此可以知道,产生等待的序列名称为ONLNID,另外,也可以从DBA_HIST_ACTIVE_SESS_HISTORY视图的P2值获取到序列的名称,SQL语句如下:
SELECT D.EVENT,
D.P1TEXT,
D.P1,
D.P2TEXT,
D.P2,
CHR(BITAND(P1, -16777216) / 16777215) ||
CHR(BITAND(P1, 16711680) / 65535) "Lock",
BITAND(P1, 65535) "Mode",
D.BLOCKING_SESSION,
D.BLOCKING_SESSION_STATUS,
D.BLOCKING_SESSION_SERIAL#,
D.SQL_ID,
TO_CHAR(D.SAMPLE_TIME, 'YYYYMMDDHH24MISS') SAMPLE_TIME,
D.*
FROM DBA_HIST_ACTIVE_SESS_HISTORY D
WHERE D.SAMPLE_TIME BETWEEN TO_DATE('20160823170000', 'YYYYMMDDHH24MISS') AND
TO_DATE('20160823230000', 'YYYYMMDDHH24MISS')
AND D.EVENT = 'enq: SQ - contention';
由以上的查询结果可知,序列的OBJECT_ID为47989,通过DBA_OBJECTS就可以查询到序列的名称了。另外,LOCK为SQ代表的是序列的CACHE锁(SEQUENCE CACHE),MODE为6代表EXCLUSIVE排它锁。
SELECT * FROM DBA_OBJECTS D WHERE D.object_id='47989';
知道了序列名称后,通过DBA_SEQUENCES视图就可以查询到序列的属性了:
SELECT * FROM DBA_SEQUENCES D WHERE D.sequence_name='ONLNID' ;
可以看到,该序列是NOORDER属性,CACHE值为默认的20,对于并发值很高的系统而言,该默认值太低,所以需要调整到1000。可以执行SQL语句“ALTER SEQUENCE ONLNID CACHE 1000;”调整其CACHE值即可解决该问题。
& 说明:
有关该案例的更多内容可以参考我的BLOG:http://blog.itpub.net/26736162/viewspace-2123996/、http://blog.itpub.net/26736162/viewspace-2139754/
本文选自《Oracle程序员面试笔试宝典》,作者:小麦苗
DB宝分享的IT资料:https://mp.weixin.qq.com/s/Iwsy-zkzwgs8nYkcMz29ag
● 本文作者:小麦苗,只专注于数据库的技术,更注重技术的运用
● 作者博客地址:http://blog.itpub.net/26736162/abstract/1/
● 本系列题目来源于作者的学习笔记,部分整理自网络,若有侵权或不当之处还请谅解
● 版权所有,欢迎分享本文,转载请保留出处
● QQ:646634621 QQ群:230161599、618766405
● 微信:lhrbestxh
● 微信公众号:DB宝
● 提供Oracle OCP、OCM、高可用(rac+dg+ogg)和MySQL最实用的技能培训
● 题目解答若有不当之处,还望各位朋友批评指正,共同进步
长按下图识别二维码或微信扫描下图二维码来关注小麦苗的微信公众号:DB宝,学习最实用的数据库技术。
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【Java8新特性】01 函数式接口和Lambda表达式你真的会了吗
- 只出现一次的元素
- 【排序】堆排序
- redis灵魂拷问:怎样搭建一个哨兵主从集群
- 是时候给你的鼠标指针更换样式换下风格体验了!如何卸载与安装鼠标指针?
- Linux设置虚拟内存
- SSM 单体框架 - 教育平台后台管理系统:接口文档
- java学习应用篇|使用环境变量做一些工具
- 【Java8新特性】06 新的日期和时间:LocalDate LocalTime LocalDateTime
- UNSAFE和Java 内存布局
- 【玩转Redis面试第1讲】Redis数据结构和常用命令速记
- SSM 单体框架 - 教育平台后台管理系统:课程模块
- 【玩转Redis面试第2讲】面试官再问Redis事务把这篇文章扔给他
- SSM 单体框架 - 教育平台后台管理系统:Maven 进阶使用
- SSM 单体框架 - 教育平台后台管理系统:广告和用户模块开发