解决一则row cache lock引起的性能故障

转载的文章地址:http://www.oracleonlinux.cn/2012/06/row-cache-lock-performance-tuning/

此文章写的很好,非常详细的解说了cache引起的性能故障。

收到紧急邮件:说某客户生产系统在今天早上9:30左右,生产环境整个系统操作响应很慢,查询一票单子可能要耗时半分钟,有时候登录界面也卡住很久才响应。

       这是一套10.2.0.5.0的双节点RAC数据库,平时系统运行较为正常,现在突然变慢。好了,对于我这个优化菜鸟来讲,还是从AWR报告入手。下面给出分析步骤和解决办法:

1   从报告头中看到,在数据库出现性能问题的一个小时内,DB Time达到240分钟,(DB Time)/Elapsed=3.93,说明数据库应该是存在问题的。

 

Snap IdSnap TimeSessionsCursors/Session
Begin Snap:1063805-6月 -12 09:00:00545.8
End Snap:1063905-6月 -12 10:01:031025.8
Elapsed:61.04 (mins)61.04 (mins)61.04 (mins)
DB Time: 

 

 

 

 

 

2   从报告的Load Profile节,看到用户的每秒调用高达680次,说明肯定存在问题了。

Load Profile

 

Per SecondPer Transaction
Redo size:12,939.466,115.60
Logical reads:67,323.1831,819.06
Block changes:53.2225.15
Physical reads:1.020.48
Physical writes:4.722.23
User calls:679.70321.25
Parses:90.4942.77
Hard parses:0.350.16
Sorts:1.940.92
Logons:0.080.04
Executes:316.75149.71
Transactions:2.12

3   继续分析报告,从Top 5中看到排在第一的等待事件是row cache lock,并且该等待事件的平均等待达到2128ms。

ROW CACHE LOCK等待事件是一个共享池相关的等待事件,是由于对于字典缓冲的访问造成的。通常直接的解决办可以通过调大共享池来解决,但是,并非在所有场景下都凑效。

Top 5 Timed Events

 

EventWaitsTime(s)Avg Wait(ms)% Total Call TimeWait Class
row cache lock2,7365,8222,12840.4Concurrency
CPU time4,30529.9
gc cr block busy2,2932,6331,14818.3Cluster
gc buffer busy1,5691,0966987.6Cluster
enq: TX - row lock contention2,0299984926.9Application

4    继续分析,发现基于时间的统计信息中,加载序列sequence的耗时排在了第二位。

Time Model Statistics

  • Total time in database user-calls (DB Time): 14406.5s
  • Statistics including the word "background" measure background process time, and so do not contribute to the DB time statistic
  • Ordered by % or DB time desc, Statistic name

 

Statistic NameTime (s)% of DB Time
sql execute elapsed time14,188.0198.48
sequence load elapsed time6,900.8347.90
DB CPU4,304.5929.88
PL/SQL execution elapsed time20.640.14
parse time elapsed10.250.07
hard parse elapsed time6.000.04
PL/SQL compilation elapsed time1.170.01
hard parse (sharing criteria) elapsed time1.070.01
repeated bind elapsed time0.800.01
hard parse (bind mismatch) elapsed time0.640.00
connection management call elapsed time0.310.00
failed parse elapsed time0.000.00
DB time14,406.50
background elapsed time2,115.75
background cpu time20.52

5     看到最耗时的竟然是一条再简单不过的SQL语句,SELECT SEQ_NEWID.NEXTVAL FROM DUAL,取序列的值,竟然会如此的耗时?

SQL ordered by Elapsed Time

  • Resources reported for PL/SQL code includes the resources used by all SQL statements called by the code.
  • % Total DB Time is the Elapsed Time of the SQL statement divided into the Total Database Time multiplied by 100
  • Total DB Time (s): 14,406
  • Captured SQL account for 223.8% of Total

 

Elapsed Time (s)CPU Time (s)ExecutionsElap per Exec (s)% Total DB TimeSQL IdSQL ModuleSQL Text
6,910028124.5947.961gd7ancd2px8mFC.EdiService.Import.exeSELECT SEQ_NEWID.NEXTVAL FROM ...

6    再看字典缓冲区的统计信息:取序列值一共287次,就失败了43.9%,看来的确是取序列值的地方出现问题,也就解释了为什么上一步骤中的分许出的那条SQL会如此耗时,因为差不多有一半的情况下都没有取到序列的值。

Dictionary Cache Stats

  • "Pct Misses" should be very low (< 2% in most cases)
  • "Final Usage" is the number of cache entries being used

 

CacheGet RequestsPct MissScan ReqsFinal UsageMod ReqsPctMiss
dc_awr_control651.54011
dc_database_links3040.00001
dc_global_oids1550.000024
dc_histogram_data74,7040.25005,612
dc_histogram_defs71,4000.26004,945
dc_object_ids29,3980.01001,136
dc_objects3,9120.2300860
dc_profiles1500.00001
dc_rollback_segments17,7890.100056
dc_segments8,9270.0604896
dc_sequences28743.9002793
dc_tablespace_quotas250.00002
dc_tablespaces8,9540.000025
dc_usernames1,0820.00008
dc_users13,9910.000031
outstanding_alerts32677.9102354

7   到此,解决问题的基本思路已经出来了,通过将序列缓存到内存中,基本可以解决问题。通过查看生产系统上的该序列的信息,发现创建序列的语句如下:

1

2

3

4

5

6

7

-- Create sequence

create sequence SEQ_NEWID

minvalue 1000

maxvalue 9999

start with 1000

increment by 1

nocache;

8   调整序列,使之cache到内存中,alter sequence SEQ_NEWID cache 3000;

/*

sequence cache介绍

CACHE的主要用途是
在获取第一次的sequence时,预先创建出一部分sequence并存放在缓存中

例如:
CREATE SEQUENCE
SEQ_UNIQUEKEY AS INT
START WITH 1
INCREMENT BY 1
MINVALUE 1
MAXVALUE 99999999
CYCLE
CACHE 300
ORDER;

当创建成功时,在缓存中已经存在了1~300号sequence,每次执行NEXTVAL时,都会使用缓存中的seq。当seq增加到300时,下一次的NEXTVAL命令就会重新产生301~600号seq并存放于缓存。

若,当前连接中断,并重新连接数据库时,NEXTVAL命令取得的值就是在缓存中的最小值。
例如:
NEXTVAL.......(执行100次,下次seq为101)
执行,commit,disconnect命令断开连接(或者发生异常,强制commit)
则,下次连接到数据库后,执行NEXTVAL命令取得的seq就为301,101~300号自动作废。

 

但是因为数据库是rac环境,如果调整为cache,如果应用对序列有顺序要求的这种,调整就会有问题。

比如cache 40,

instance 1 使用1-40

instance 2使用41-80

和开发问过应用对序列顺序要求后,确认应用对sequence的顺序没有太大依赖,所以可以调整sequence的cache。

*/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: library cache lock是Oracle数据库中的一种锁,用于保护共享池中的共享内存区域,以确保多个会话不会同时修改同一块内存。当一个会话正在修改共享池中的某个内存区域时,其他会话需要等待该锁释放后才能访问该内存区域。如果该锁被长时间持有,可能会导致其他会话的性能下降。因此,需要对该锁进行优化和监控。 ### 回答2: library cache lock(库缓存锁)是Oracle数据库中的一种锁机制,用于在共享池(Shared Pool)中保护和管理库缓存(Library Cache)中的共享内存结构。 库缓存是Oracle数据库中存储SQL语句执行计划、存储过程以及其它重要对象的内存区域。在并发环境下,多个会话(Session)可能同时请求某一对象的执行计划或存储过程,为了避免冲突和数据不一致性,需要通过库缓存锁来进行协调。 当一个会话请求某一对象的执行计划或存储过程时,数据库会先检查库缓存中是否已经有该对象的锁。如果该对象的锁已经存在,会话就需要等待,直到之前的会话释放锁。如果该对象的锁不存在,数据库会为当前会话创建一个库缓存锁。当一个会话对某一对象的执行计划或存储过程进行修改时,会话首先获得该对象的库缓存锁,然后可以对该对象进行修改。 库缓存锁的粒度非常细,可以是数据库级别、模式级别、对象级别甚至是子对象级别的。库缓存锁的管理是自动的,由Oracle数据库内部自动分配和释放。 库缓存锁的存在可以保证多个会话在并发访问数据库时的数据一致性和资源的安全性。但是,如果过多的会话同时请求同一个对象的锁,也可能导致性能瓶颈和资源竞争,从而影响数据库的性能和响应速度。 为了减少库缓存锁的竞争,可以通过优化SQL语句、增加共享池大小、调整并发连接数等方式来提高数据库的性能性能。同时,也可以使用Enable Row-level Locking(启用行级锁)的方式来减少库缓存锁的使用。 ### 回答3: library cache lock是Oracle数据库中的一种锁定机制,用于保护共享SQL和PL/SQL对象在库缓存中的访问。 在Oracle数据库中,库缓存是用于存储数据库的共享SQL和PL/SQL对象的重要组件。它包含了解析树、执行计划、存储过程等重要对象的定义和元数据。多个会话可以同时访问共享的库缓存对象,但在某些情况下,需要使用库缓存锁来保护对象的访问和修改。 当一个会话需要对一个共享的库缓存对象进行修改时,它会请求一个library cache lock。这个锁会阻塞其他会话对同一个对象的修改,直到持有锁的会话完成修改操作并释放锁。这种机制能够确保在并发访问的情况下,库缓存对象的一致性和正确性。 库缓存锁是Oracle数据库中的一种共享锁,意味着它可以被多个会话同时持有。它可以阻止其他会话对同一个对象的并发修改,但不会阻止读取操作。这种锁是为了避免并发访问造成的竞争条件和冲突,确保库缓存中的共享对象的正确性。 库缓存锁是通过Oracle数据库的内部机制自动管理的,用户不需要手动操作。当会话需要修改一个库缓存对象时,数据库会自动分配和管理合适的锁。在执行完修改操作后,会话会自动释放锁,以便其他会话能够继续访问和修改对象。 总之,library cache lock是Oracle数据库中用于保护共享SQL和PL/SQL对象在库缓存中访问的锁定机制。它确保了对象的并发访问的一致性和正确性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值