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

时间:2022-07-19 18:29:36

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。

  1. SQL> select event#,name,parameter1,parameter2,parameter3 from v$event_name where name = 'buffer busy waits';
  2. EVENT# NAME               PARAMETER1      PARAMETER2      PARAMETER3
  3. ---------- ------------------------------ --------------- --------------- ---------------
  4. 91 buffer busy waits          file#       block#      class#
  5. SQL> select event#,name,parameter1,parameter2,parameter3 from v$event_name where name = 'read by other session';
  6. EVENT# NAME               PARAMETER1      PARAMETER2      PARAMETER3
  7. ---------- ------------------------------ --------------- --------------- ---------------
  8. 94 read by other session      file#       block#      class#
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#:等待事件的类别。

When informationis requested from the database, Oracle will first read the data from disk intothe database buffer cache. If two or more sessions request the sameinformation, the first session will read the data into the buffer cache whileother sessions wait. In previous versions this wait was classified under the"buffer busy waits" event. However, in Oracle 10.1 and higher thiswait time is now broken out into the "read by other session" waitevent. Excessive waits for this event are typically due to several processesrepeatedly reading the same blocks, e.g. many sessions scanning the same indexor performing full table scans on the same table. Tuning this issue is a matterof finding and eliminating this contention.

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的方法得以解决。

转载:http://blog.csdn.net/zq9017197/article/details/7971014