buffer cache —— buffer busy waits/read by other session

oracle提供非常精确、有效的row level lock机制,多个用户同时修改数据时,为了保护数据,以块为单位挂起锁的情况不会发生。但这不太正确。以块为单位的锁虽然不存在,但正因为oracle I/O以块为单位组成,所以块单位锁是必要的。假设row1、row2两个行位于同一个块内,两名用户(用户1、用户2)各自对row1、row2执行update,逻辑上两个被更新行之间不存在需要相互保护的数据。因为oracle提供row level lock机制,所以修改互相不用的行完全不成问题。但是若两个行位于同一个块内,因物理限制,修改块的操作不能同时完成。各用户为了修改行,即便以Exclusive模式已获得TX锁,但需要保障当前只有自己在修改块。此时需要获得的锁就称为buffer lock。如果没有获得buffer lock,与其它锁相同,需要一直等到获得锁。

获得buffer lock的模式有Shared模式和Exclusive模式。读取缓冲区的过程中需要以Shared模式模式获得锁,修改过程中则需要以Exclusive模式获得锁。欲获得buffer lock的会话之间没有共享性时(例如都想以Exclusive模式或以Shared模式模式读取过程中,另一个想要以Exclusive模式模式获得锁时),就会发生争用。

buffer lock与cache buffers chains锁存器、TX锁一起对缓冲区的修改起到同步化的作用。在抽象层次上,为了修改一个行,获得锁存器或锁的过程如下。
(1)为了查找要修改的行相应的块存在的位置(hash chain),请求cache buffers chains锁存器。
(2)对载入块的缓冲区请求buffer lock,并释放cache buffers chains锁存器。
(3)请求TX锁,修改相应行。若在次过程中,没有获得TX锁,则释放buffer lock并进入等待状态。之后重复过程(1)。
(4)修改相应(欲修改的)行后,释放buffer lock。

为了获得Buffer Lock而等待期间内,一般会等待buffer busy waits事件。buffer busy waits等待是最普通的等待现象中的一个,其原因也很多。从10G开始buffer busy waits等待事件分为buffer busy waits和read by other session两个了。其实两个等待事件都是想锁住同一个buffer block。

SQL> select event#,name,parameter1,parameter2,parameter3 from v$event_name where name = 'buffer busy waits';  

    EVENT# NAME 			  PARAMETER1	  PARAMETER2	  PARAMETER3
---------- ------------------------------ --------------- --------------- ---------------
	91 buffer busy waits		  file# 	  block#	  class#

SQL> select event#,name,parameter1,parameter2,parameter3 from v$event_name where name = 'read by other session'; 

    EVENT# NAME 			  PARAMETER1	  PARAMETER2	  PARAMETER3
---------- ------------------------------ --------------- --------------- ---------------
	94 read by other session	  file# 	  block#	  class#
这个等待事件包含三个参数:
file#:等待访问数据块所在的文件的id号。
block#:等待访问的数据块号。
class#:等待事件的类别。


1、select/select引起的read by other session

select/select 引起的buffer lock争用,发生在将相同块载入到内存的过程中,通过read by other session等待事件观察。(注意:如果数据块已经在内存中了,就不会发生争用了。)
请注意一点,发生read by other session等待时,同时发生db file sequential read、db file scattered read等待等I/O等待现象。read by other session等待在其属性上一直与物理I/O同时出现。因此以相同方式再次进行测试,就因为数据已位于高速缓存区,所以不发生物理I/O,自然read by other session等待以及db file sequential read、db file scattered read等待现象也会消失。要读取的块已经载入到SGA时,因为以Shared模式已经获得Buffer lock,所以不会发生Buffer lock争用。read by other session等待事件与db file sequential read、db file scattered read等待事件密切相关。
以前已经讲过Buffer lock只有Shared模式和Exclusive模式。读取位于SGA上的块时是以Shared模式获得Buffer lock的,所以不发生读取工作引起的Buffer lock争用。但是反生物理I/O后将新块载入到SGA需要创建新的缓冲区,因此最初创建缓存区的进程以Exclusive模式获得Buffer lock。这样其它想以Shared模式(这里既然发生了物理I/O,怎么还会有Shared模式获取Buffer lock的情况呢?发生了物理I/O不是都应该以Exclusive模式获取Buffer lock的吗?想了很久,才想明白了:例如两个会话session1、session2同时读取一个块,第一次session1读取的时候还没有缓存,会发生物理I/O,所以是以Exclusive模式获取Buffer lock,但是还没有释放Buffer lock。这时session2也读取,但这次是已经缓存了,所以发生逻辑I/O,session2想以Shared模式读取此块的会话需要等待Exclusive模式的Buffer lock释放,此时会发生read by other session等待。若session1和session2都是发生的逻辑I/O,而在获取Buffer lock发生争用,则发生buffer busy waits等待。)读取此块的会话需要等待Exclusive模式的Buffer lock释放,此时会发生read by other session等待。请留意,上述情况中,即便是读取工作时,因为创建新的缓存区,所以也会以Exclusive模式获得Buffer lock。

减少select/select引起的read by other session等待的方法,整理结果如下:
应该通过对sql进行优化,以便能以最少的I/O获得所需要的结果。
若SGSA大小(或高速缓冲区大小)比系统全局的I/O小,就不能只通过sql调优解决问题,还需要增加SGA物理大小。


2、select/update引起的buffer busy waits/read by other session

oracle的select操作基本上以一致性读取(consistent read)为基础。若实际应该读取的数据已经修改,则必须读取持有过去映象的CR块。这时若CR块不在当前的高速缓冲区上时,则应该从磁盘读取撤销块。若多个会话试图读取撤销块时,在将撤销块载入到内存上的过程中发生Buffer lock争用。


3、insert/insert引起的buffer busy waits

insert/insert 多个session同时对一个表执行insert操作时,载入相同块到内存中时引起的buffer lock争用。

4、update/update引起的buffer busy waits

update/update 虽然修改的是不同的行数据,但是多行数据可能存在同一个块上,修改不用的行而载入相同块到内存中时引起的buffer lock争用。发生buffer lock争用的根本原因就是不同的行位于同一个块,因此将不同行分散到不同块,这就是最普遍使用的解决方法。


减少buffer lock争用的方法,整理结果如下:

1)减少select/select引起的read by other session等待的最好方法是通过sql的最优化利用最少的I/O获得需要的结果。如果通过这个操作也不能解决问题,就应该检查SGA(高速缓冲区)大小适当与否。
2)select/update引起的read by other sessio与select/select引起的read by other session等待的解决方法相同
3)insert/insert引起的buffer busy waits等待,通过使用适当的段空间管理方法得以解决。oracle 9i以上的版本推荐使用ASSM。
4)update/update引起的buffer busy waits等待,可以通过采用避免对相同块同时执行update的方法得以解决。


查找热块方法

找到热块参数信息:

  1. SELECT p1 "file#", p2 "block#", p3 "class#"  
  2. FROM v$session_wait  
  3. WHERE event = 'read by other session';  

找到热块上所放的对象:
  1. SQL> SELECT relative_fno, owner, segment_name, segment_type  
  2. FROM dba_extents  
  3. WHERE file_id = &file  
  4. AND &block BETWEEN block_id AND block_id + blocks - 1; 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值