ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 第6 章、解释与锁有关的等待事件

第6 章、解释与锁有关的等待事件

原创 Linux操作系统 作者:红叶DBA 时间:2011-02-28 13:14:03 0 删除 编辑

章、解释与锁有关的等待事件

Oracle 通过Latch Lock 串行化对SGA 数据结构和数据库对象的访问,这是ACID Atomicity 原子性、Consistency 一致性、Isolation 隔离性、Durability 持久性)中的I(隔离性),在这种情况下,为了完整性必须牺牲并发性。

多个进程竞争串行化资源通常表现为latch free enqueue buffer busy wait 等待事件。

1、   Latch free 等待事件:

l  关键思想:

1)         锁存器只应用于SGA 中的内存结构,他们不会应用于数据库对象,他们的存在是为了保护各种内存结构不会由于并发访问而遭到破坏。

2)      Oracle 等待获得锁存器所采取的动作依赖于进程竞争的锁存器类型。

3)      Oracle 10g 之前的Latch free 代表所有的锁存器等待事件,10g 之后常见的锁存器被单独取出,具有单独的等待事件。

l  锁存器是简单的锁设备,他们是由部分组成的内存元素:PID (进程ID )、内存地址、长度。

l  存在中类型的锁存器:父锁存器、子锁存器和单独的锁存器,v$latch_parent 包含父锁存器,v$latch_children 包含子锁存器,v$latch 包含单独的锁存器和父、子锁存器的合计统计。

l  在获得锁存器后,要修改受保护的数据之前,进程将恢复信息写到锁存器恢复区中,以便PMON 知道在获得锁存器的进程死亡时需要清除什么。

l  离开锁存器的唯一方式是GET 成功,进程在Get 几次尝试中没有获得锁存器时,就会通知PMON 检查锁存器,如果以前持有该锁存器的进程死亡,那么就由PMON 清除并释放锁存器。

l  除了依靠_spin_count 参数来修改spin 次数外,还可以单独修改某个latch spin 次数:

1)         x$ksllclass (内核服务锁定锁存器类)中查看每个锁存器类的spin 值:

Select indx,spin,yield,waittime from x$ksllclass;

2)      v$latchname 查看要修改的锁存器的编号:

select latch# from v$latchname where name= cache buffer chains ;

3)      修改一个没有使用过的latch 类,在init 文件中添加:

_latch_class_1= 10000 

_latch_classes= latch#:1 

4)      查看latch 所属的类:select a.kslldnam,b.kslltnum,b.class_ksllt from x$kslld a,x$ksllt b where a.kslldadr=b.addr and b.class_ksllt>0;

l  V$system_event.total_waits 记录了以愿意等待模式没有获取到latch  的次数,此值应该和sleeps 的总和相等,但由于sleeps 统计只在get 操作完成后才统计,所以total_waits>=sleeps 

l  Shared pool 锁存器和library cache 锁存器

u  Oracle 9i 开始,有7shared pool 锁存器保护每个shared pool,还可以通过_kghdsidx_count 来修改子共享池的数量。library cache 也有自己的锁存器,其数量通常为大于cpu_count 的最小质数,可以通过_kgl_latch_count 参数修改。

u  过多的硬解析会导致shared pool library cache 中的锁存器竞争,这通常和没有使用绑定变量有关。

u  如果在不同模式中拥有相同的对象,那么就有可能造成锁存器的争用,因为相同的SQL 中引用的对象的模式不同,那么就具有不同的child_number Oracle SQL 解析匹配时,必须持续持有锁存器,然后一一扫描匹配,消耗时间。

l  Cache buffer chains 锁存器

u  Oracle 9i 开始,cache buffer chains 锁存器可以只读共享,这样就可以减少一部分的争用,但是无法消除争用。

u  有两个隐藏参数:_db_block_hash_buckets _db_block_hash_latches ,分别控制散列桶数量和散列锁存器数量。

u  每个逻辑读都需要一个latch get 和一个CPU latch get 的唯一方法是获得锁存器,在某一个时刻,只能有一个进程拥有cache buffer 链。所以SQL 优化过程中必须要减小SQL 语句的逻辑读。

u  减少热块的主要思想是将热块散列到不同的cache buffers chains 锁存器所覆盖的存储桶,方法有:

1)         通过rowid 删除一些行,并重新插入。

2)      输出表,使用较大的pctfree 并输入表,这是以空间为代价的。

3)      最小化每个行中的记录数,records_per_block 参数修改表。

4)      对于索引,可以使用较高的pctfree ,但这种方法可能增加索引的高度。

5)      考虑减少块大小。

u  查看每个散列锁存器管理的块数:Select hladdr,count(*) from x$bh group by hladdr having count(*)>10;

如果一个散列链中的块数超过了10 个,就认为是长散列链。

l  Cache buffers lru chain 锁存器

u  LRU LRUW CKPT-Q 链表也连接到缓冲区头,LRU 保存通常缓冲区,LRUW 包含脏缓冲区,二者是相互排斥的。他们统一称为工作集(working set )。每个工作集有一个锁存器保护,所以工作集的数量由cache buffers lru chain 数量决定。

u  x$kcbwds (内核高速缓冲区工作集描述符)视图可以查看工作集情况:

Select set_id,set_latch from x$kcbwds order by set_id;

也可以从v$latch_children 中查找name= cache buffer lru chain 得到。

u  隐含参数_db_block_lru_latches 可以改变LRU chains 锁存器的数量:默认是cpu_count ,如果db_write_processes>4 那么就是db_write_processes * cpu_count 

l  Row cache objects 锁存器

u  针对行高速缓存的调整非常有限,可以从v$rowcache 中查看每个数据字典的统计信息。常见的解决方案是增大shared pool size 

2、Enqueue 等待事件:

l  排队:用作动词时,他表示将一个锁请求放入队列的动作;用作名词时,表示一个特殊的锁,例如TX 排队。排队资源是受排队锁影响的数据库资源,可从v$resource x$ksqrs (内核服务排队资源)中查看,受隐含参数_enqueue_resources 控制,v$resource_limit 提供了利用率统计。

l  排队锁:从视图v$enqueue_lock x$ksqeq (内核服务排队对象)中查看,受_enqueue_locks 控制,TX 锁和TM 锁可能不在此视图中,因为Oracle 使用不同的结构来管理TX TM 排队,可以从x$ktadm (内核事务访问定义DML 锁)中查询,v$lock 则显示了所有的锁信息。

l  Enqueue hash chains 锁存器:散列存储桶:排队散列链=1 

l  Enqueue 锁存器的数量默认等于cpu_count ,可以通过隐含参数_enqueue_hash_chain_latches 调整。排队散列表的长度来源于sessions 初始化参数=sessions-10 *2+55 ,可以通过_enqueue_hash 参数调整。

l  转储排队结构到一个追踪文件:

alter session set event  immediate trace name enqueue level 3 ;

l  enqueue 事件P1 参数包含了排队的type mode 

select sid,event, chr(bitand(p1,-167777216)/16776215)|| chr(bitand(p1, 16711680)/65535) type,mod(p1,16) mode from v$session_wait where event= enqueue ;

l  进程可以获得中模式的排队锁,编号从0~6 

0:无。

1:空锁(Null

2:行共享锁(Row-Share RS ),也称为子共享锁(SubShare lock SS 

3:行独占锁(Row-Exclusive RX ),也称为子独占锁(SubExclusive lock SX 

4:共享锁(Share 

5:共享行独占锁(Share Row Exclusive SRX ),也称为共享子独占锁(Share-SubExclusive lock SSX 

6:独占锁(Exclusive 

l   兼容

     2 兼容

     3 兼容

     4兼容

     5兼容

     6兼容

l  可以从v$enqueue_stat 查看enqueue 等待事件的实例级统计信息。

l  几种常见的enqueue 等待:

1)         模式中的TX enqueue 等待:enq: TX - row lock contention

enq 此等待发生在一个事务尝试修改被另一个事务锁定的行时,

2)      模式中的TX enqueue 通常是有以下原因引起的:1ITL 不足;、唯一键实施、、位映射索引条目。

3)      模式中的TX enqueue 等待:enq: TX - allocate ITL entry

u  当一个块中所有的ITL 都在使用,并且pctfree 中没有空间分配新的ITL 时,就会有严重的ITL 争用。9i 以后,每个表中至少ITL,即使dba_tables 中显示一个也是个。

u  Oracle 9i 开始,Oracle 会跟踪ITL 等待的数量并记录在v$segment_statistics 视图中,statistic_name= ITL waits 

4)      模式中的TX enqueue 等待:enq: TX - row lock contention

发生在多个会话并发的将相同的键值插入具有唯一索引的表中时。

5)      模式中的TX enqueue 等待:enq: TX - index contention

6)      ST enqueue 等待:ST 锁的争用表明有多个获得会话在字典管理的表空间中执行空间的分配和释放。

7)      模式中的TM enqueue 等待:通常是由于外键未加索引引起的。

3、Buffer busy wait 等待事件:

l  关键思想:

1)         Oracle 必须在读取或修改缓冲区内容之前,pin 住相关的块,在同一时刻,只能有一个进程pin 住一个块。

2)      Buffer busy waits 表明读/读、读/写、写/写争用。

3)      P3 参数在10g 之前表示原因码,在10g 之后表示块类,原因码中比较常见的是130 1013 )和220 1016 )。130 表示多个进程同时访问一个不在缓冲区里的块,此时只有第一个进程调用系统IO ,剩余的进程在此事件上等待;220 表示多个进程尝试并发修改同一个块中的不同行,但在同一时刻一个块只能被一个进程pin 住。

l  视图x$kcbwait 是视图v$waitstat 的基视图,

l  视图x$kcnfwait 根据数据文件来跟踪buffer busy waits 等待,其中indx 表示file#

l  视图x$kcbwds 通过保护LRU LRUW lru chain 锁存器来跟踪buffer busy waits 

l  视图x$ksolsfts v$segment_statistics 视图的基视图,通过跟踪段信息来跟踪buffer busy waits ,其中有一列fts_smtp 记录了争对特定段更新值(fts_staval )的最近时间。

l  在以上视图中的buffer busy waits 的值可能存在不一致的情况,原因有:

1)         底层的内存结构不被保护,在内存结构的同步中破坏了计数。

2)      Oracle 内核在不同位置调用buffer busy waits ,有些位置并不是添加实际等待数量,而是固定添加一个大数字(如100 )。

3)      针对这些内存结构没有一致读取。

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24465008/viewspace-688093/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2010-08-19

  • 博文量
    54
  • 访问量
    69835