正德厚生,臻于至善

Oracle row cache lock 之sequence

select distinct event, p1, p1text
from v$active_session_history ash
where ash.event = 'row cache lock'
and ash.sample_time > to_date('2023-05-26 00:00:00','yyyy-mm-dd hh24:mi:ss') 
and ash.sample_time < to_date('2023-05-27 00:00:00','yyyy-mm-dd hh24:mi:ss')
;
select session_id,sql_id,blocking_session,event,machine 
from dba_hist_active_sess_history
where event='row cache lock'
and sample_time >= to_date('2023-05-23 10:00:00','yyyy-mm-dd hh24:mi:ss') 
and sample_time <= to_date('2023-05-23 11:00:00','yyyy-mm-dd hh24:mi:ss')
;
select sql_id,count(*)
from dba_hist_active_sess_history
where event='row cache lock'
and sample_time >= to_date('2023-05-25 00:00:00','yyyy-mm-dd hh24:mi:ss') 
and sample_time <= to_date('2023-05-26 00:00:00','yyyy-mm-dd hh24:mi:ss')
group by sql_id
order by 2 desc;

https://blog.csdn.net/weixin_29326909/article/details/116325672

今天遇到一个生产库产生大量row cache lock,以下是相应步骤:

1 查询当时P1的情况
select INSTANCE_NUMBER, p1, count(*) cnt
  from dba_hist_active_sess_history
 where event = 'row cache lock'
   and SAMPLE_TIME >=
       to_date('2023-05-24 10:00:00','yyyy-mm-dd hh24:mi:ss')
   and SAMPLE_TIME <=
       to_date('2023-05-24 11:00:00','yyyy-mm-dd hh24:mi:ss')
 group by INSTANCE_NUMBER, p1
 order by cnt;

2 根据第一步查询的P1,代入到下面cache#,这里查询出来的结果是13,dc_sequences
select inst_id, cache#,type,gets,parameter from gv$rowcache where cache# in (?) order by gets;

3 查询当时用户会话量情况
select INSTANCE_NUMBER, USER_ID, count(*) cnt
  from dba_hist_active_sess_history
 where SAMPLE_TIME >=
       to_date('2023-05-24 10:00:00','yyyy-mm-dd hh24:mi:ss')
   and SAMPLE_TIME <=
       to_date('2023-05-24 11:00:00','yyyy-mm-dd hh24:mi:ss')
 group by INSTANCE_NUMBER, USER_ID
 order by 1, cnt;

4 查询对应SQL的情况
select INSTANCE_NUMBER,
       SAMPLE_TIME,
       event,
       sql_opname,
       sql_id,
       count(*) cnt
  from dba_hist_active_sess_history
 where SAMPLE_TIME >=
       to_date('2023-05-24 10:00:00','yyyy-mm-dd hh24:mi:ss')
   and SAMPLE_TIME <=
       to_date('2023-05-24 11:00:00','yyyy-mm-dd hh24:mi:ss')
 group by INSTANCE_NUMBER, SAMPLE_TIME, event, sql_opname, sql_id
 order by 2, 1;

5 查询对应节点更详细的会话信息
select INSTANCE_NUMBER,
       SAMPLE_TIME,
       session_id,
       BLOCKING_SESSION,
       current_obj#,
       user_id,
       event,
       sql_id,
       P1
  from dba_hist_active_sess_history
 where SAMPLE_TIME >=
       to_date('2023-05-24 10:00:00','yyyy-mm-dd hh24:mi:ss')
   and SAMPLE_TIME <=
       to_date('2023-05-24 11:00:00','yyyy-mm-dd hh24:mi:ss')
   and INSTANCE_NUMBER = 2
   and event = 'row cache lock';

最后定位是一个高频INSERT 语句引用SEQUENCE引起的,而这个序列是NOCAHE,改成cache恢复正常
0dupf1d2nntjz	8569
0dupf1d2nntjz select FND_SOA_REQUEST_S.nextval from dual
alter sequence APPLSYS.FND_SOA_REQUEST_S cache 1000;

P1 = cache - ID of the dictionary cache
P2 =  mode - Mode held
P3 =  request - Mode requested

https://blog.csdn.net/weixin_39760368/article/details/111819665

Oracle Sequence 性能优化
定义Sequence是很简单的,如果最大程度利用默认值的话,我们只需要定义sequence对象的名字即可。在序列Sequence对象的定义中,Cache是一个可选择的参数。默认的Sequence对象是有cache选项的,默认取值为20。这个默认值对于大多数情况下都是够用的。 除非那种每秒上万次的select。 所以具体情况要具体对待。 对于哪些大并发的系统,最好设置在100以上。像移动的BOSS系统,以1000为单位。

SEQUENCE创建基本语法:
CREATE SEQUENCE [schema.]sequence
[INCREMENT BY integer]
[START WITH integer]
[MAXVALUE integer | NOMAXVALUE]
[MINVALUE integer | NOMINVALUE]
[CYCLE | NOCYCLE]
[CACHE integer | NOCACHE]
[ORDER | NOORDER]

eg:
CREATE SEQUENCE emp_seq
INCREMENT BY 1-- 每次加几个
START WITH 1-- 从1开始计数
NOMAXVALUE-- 不设置最大值
NOCYCLE-- 一直累加,不循环 CACHE N / NOCACHE --其中n代表一个整数,默认值为20。

如果指定CACHE值,Oracle就可以预先在内存里面放置一些Sequence,这样存取的快些。cache里面的取完后,Oracle自动再取一组到cache。使用cache或许会跳号, 比如数据库突然不正常down掉(shutdown abort),cache中的Sequence就会丢失。举个例子:比如你的sequence中cache 100,那当你sequence取到90时突然断电,那么在你重启数据库后,sequence的值将从101开始。

如果指定NOCACHE值,Oracle就不会预先在内存里面存放Sequence,当然这也就可以避免数据库不正常down掉的sequence丢失。不过会产生一些问题:创建nocache sequence在高并发访问时,容易导致row cache lock等待事件,主要原因是每次获取nextval时都需要修改rowcache中的字典信息。使用nocache sequence,还会导致如下问题:

由于每次修改字典信息都需要commit,可能导致log file sync等待,nocache sequence在RAC环境下,会对基于sequence生成的列创建的索引造成实例间大量索引块争用
基于以上问题,避免创建nocache sequence。

再来看看sequence相关保护机制:
row cache lock:在调用sequence.nextval情况下需要修改数据字典时发生,对应row cache lock事件
SQ lock:在内存缓存(并非rowcache)上获取sequence.nextval时发生,对应enq:SQ-contention事件
SV lock:RAC环境下获取cache+order属性的sequence.nextval时发生,对应DFS lock handle事件

什么情况下使用cache什么时间上使用nocache?
个人感觉应该尽量使用cache,因为现在的数据库很多都是在高并发的情况下运行的,首先这样可以搞性能,并且也不会产生row cache lock等待事件。可能有些人会担心数据库不正常的down掉会产生序列号间断,但这也是很少的情况。当然如果你的业务要求是绝不能产生间断的序列号,那就要使用nochache了。

序列的并发访问 :
序列总是在数据库中生成唯一值,即使当多个用户并发地引用同一序列时也没有可察觉的等待或锁定。当多个用户使用 NEXTVAL 来增长序列时,每个用户生成一个其他用户不可见的唯一值。
当多个用户并发地增加同一序列时,每个用户看到的值是有差异的。例如,一个用户可能从一个序列生成一组值,如 1、4、6 和 8,而另一个用户并发地从同一序列生成值 2、3、5 和 7。

假如在创建sequence时,有意不选用cache选项,有2点需要注意:
1. 访问效率降低,没有cache功能的sequence取值将无法直接访问内存
2. 不论是nocache还是cache , 每次访问nextval的过程都是不可逆的,在同一session中,在执行一系列dml和sequence的操作后,用户执行rollback,希望将操作回滚,但是sequence此时就显得异常顽固,用掉的nextval将无法被重现。当下一次试图读取nextval时,sequence的指针又移动到下一位了。

还有sequence不属于某个表,也不属于某个字段,sequence仅仅属于某个用户。
其实在创建了sequence后,每个表都可以使用这个sequence,但是这样会引起应用的很多麻烦,因此,建议每个表都使用一个sequence。
关于Sequence order 参数的说明:
序参数:oracle默认是NOORDER,如果设置为ORDER;在单实例环境没有影响,在RAC环境此时,多实例实际缓存相同的序列,此时在多个实例并发取该序列的时候,会有短暂的资源竞争来在多实例之间进行同步。因次性能相比noorder要差,所以RAC环境非必须的情况下不要使用ORDER,尤其要避免NOCACHE ORDER组合。
order确保按照请求次序递增生成序列数字,在RAC环境中建议使用该选项。noorder不保证按请求次序生成,默认是noorder。
Cache参数对Sequence的使用带来什么好处?如果不设置,会有什么问题 ?
1、Sequence Cache简析
简单的说,Cache 就是Oracle每次向Sequence进行请求时,分配出的独立数字数量。例如,当我们使用.nextval获取一个 独立值时,Oracle需要将sequence对象的数据字典信息更新。如果我们设置cache为10,那么第一次请求nextval的时候,就更新数据 字典信息增加10,取出的10个号放在Oracle服务器的缓存中。
在以后每次请求nextval的时候,Oracle就从服务器缓存中去获取序列值。而不需要更新数据字典信息。只有在分配到缓存的10个数字都已经分配完,或者因为缓存刷新操作剩余数字被清理的情况下,才会再次调用sequence分配机制,再次分出cache个数字。
在cache问题上,我们经常会疑惑为什么我们sequence生成的数字序列会“跳号”。这种跳号现象实际上就是因为cache的数字在缓存中因为各种原因被flush出,这样才导致生成的数字序列不连续。
注意:在有cache的情况下,sequence只能保证每次获取到的数字都是唯一、递增的,从来没有保证过数字的连续性。
如果我们不设置cache,也就是不启用序列数字缓存机制,有什么缺点呢?
1、过多的Redo Log生成
a),对nocache的序列对象而言,每次操作都会有600左右的redo log生成。
b),对cache的sequence对象而言,redo size生成的频率显然是低得多(到达cahce size最大值时才会创建redo log)。
设置cache之后,Oracle似乎不用为每次的nextval进行数据字典修改,生成redo log记录。只有cache在内存中使用结束之后,才会进行获取。
在实际的生产环境中,我们对redo size无必要的生成是要尽力避免的。首先,过多的redo log生成,容易造成online redo log的写入量增加,切换频繁。第二,redo size和nocache的使用,可能是伴随着频繁的commit动作,进而是频繁的log buffer写入online log file的过程。同时归档量增加。同时,在进行恢复的时候,也要消耗更多的时间。
所以,设置cache可以有效减少redo log的大小。
说明:如果我们处在一个高并发的情况下,系统频繁的多会话请求sequence取值。如果我们的sequence没有设置cache,那么每次都要更新数据字典,都要进行commit操作。多个会话还会出现该sequence记录的争用,出现等待事件row lock contention。
在RAC环境下,cache和noorder选项的作用更大。在RAC中,多个实例争用情况会让sequence设计的不合理效果放大。所以,在没有特殊情况下,还是设置合理的cache值,减少系统潜在性能瓶颈。

http://blog.csdn.net/cymm_liu/article/details/7451009

赞(0) 打赏
未经允许不得转载:徐万新之路 » Oracle row cache lock 之sequence

评论 抢沙发

联系我们

觉得文章有用就打赏一下文章作者

支付宝扫一扫

微信扫一扫

登录

找回密码

注册