您的位置:首页 > Web前端

通过案例学调优之--和 BUFFER CACHE 相关的主要 Latch

2015-03-31 12:09 381 查看
通过案例学调优之--和 BUFFER CACHE 相关的主要 Latch2.1、和 BUFFER CACHE 相关的主要 Latch 有:
Latch:cache buffers lru chain
Latch: cache buffers chains既然Latch是用来保护共享内存块不被并行破坏,那就了解BUFFER CACHE的相关原理,进
而得知什么时候需要用到这个 Latch,才能够有相应的解决方案。
2.2、BUFFER CACHE 是用来缓存数据块的地方,那么数据的查询和修改都要通过它来完成。
接下来就看看访问数据的流程是怎样的:


2.2.1当一个进程要访问数据时,首先要查找 BUFFER CACHE 看看数据是否已经存在?
(Y) 如果数据在 BUFFER CACHE 中存在,则根据数据的状态来判断是否可以直接访问
还是需要构造一致性读取?
(N) 如果数据在 BUFFER CACHE 中不存在,则需要从数据文件中读取数据块到 BUFFER
CACHE 中去。这个时候,需要查找在 BUFFER CACHE 中寻找足够的内存空间来读取相关的数
据。
2.2.2现在 BUFFER CACHE 那么大,一个 BUFFER 一个 BUFFER 的扫描过去是相当的消耗资源以及查
询的时间,那我们怎样才能快速地查到数据了?

可以看看下面关于 BUFFER CACHE 的示图:



这边我们先看下面几点:
1) 图中右边的有一块 Buffers Memory,其中每一块小格就是一个 Buffer(用来存放从数据文
件中读取的数据块 Block)。
2)  图中左边的有许多 Buffer Header 用虚线指向 Buffers Memory 中的相应的 Buffer。
3)  图中左边的有许多实线箭头,这些箭头(其实就是数据结构的链表结构中的指针)将不
同的 Buffer Header 连接成一条 Hash Chain,这边也就是 Cache Buffers Chain(双向链表)。
4)  另外,还有一个 Hash Bucket,其实这只是一个逻辑上的概念,即每一个 Hash Bucket 都
会有一条 Hash Chain 来将 Buffer Header(按照 HASH 算法分类后)连接起来,并由一个Cache Buffers Chains Latch 来进行管理其并发操作。
每当将一个Block读入到Buffer Cache的时候,首先会构造一个与之对应的Buffer Header,
然后根据 HASH 算法( Hash Bucket = MOD(Data Block Address, _DB_BLOCK_HASH_BUCKETS) ),
将 Buffer Header 放到对应的 Hash Bucket 的 Cache Buffers Chain 中去,并在 Buffer Header 中
存放如下信息:



5) 最后,在看看 Hash Latch,即 Cache Buffers Chains Latch,在 Oracle 8i 之前,对应每一个Hash Bucket,Oracle使用一个独立的Latch来维护。Oracle 8i开始,Oracle增加了Hash
Bucket 的数量,这样每个 Latch 需要维护多个 Bucket,由于每个 Hash Bucket 上的 Buffer
Header 数量大大减低,也使得 Latch 的性能反而提高。其中,BUFFER CACHE 中 Hash Bucket的个数由隐含参数_db_block_hash_buckets 决定,Cache Buffers Chains Latch 的个数由隐
含参数_db_block_hash_latches 决定。
2.2.3现在再回过头,看看怎样查找 BUFFER CACHE 看看数据是否已经存在?
(Y) 如果数据在 BUFFER CACHE 中存在的情况。
1) 根据要查找的数据块的 DBA 等信息,通过上面给的 HASH 算法( Hash Bucket = MOD(Data
Block Address, _DB_BLOCK_HASH_BUCKETS) ),得到该数据块所在的 Hash Bucket。
2) 定位到对应的 Hash Bucket 上,在该 Hash Bucket 对应的 Cache Buffers Chain 中加上 Cache
Buffers Chains Latch,然后从 Cache Buffers Chain 对应的第一个 Buffer Header 开始扫描查
找,直至之后一个。在这个扫描查找过程中,为防止对 Cache Buffers Chain 并发访问,
将一直持有 Cache Buffers Chains Latch。
在 Cache Buffers Chain 上查找的具体逻辑如下:




3)获得第 2)步中查到的可以直接访问的 Buffer Header 或者构造一致性读后的 Buffer
Header 中的 Buffer 地址到 Buffer Memory 来获得数据。
2.2.4 如果上面在Hash Chain中查找不到对应的Buffer Header的情况下,也就前面的问题的第二
种情况:

(N) 如果数据在 BUFFER CACHE 中不存在,则需要从数据文件中读取数据块到 BUFFER
CACHE 中去。这个时候,需要查找在 BUFFER CACHE 中寻找足够的内存空间来读取相关的数
据。
再看看前面给的 BUFFER CACHE 示例图:
可以看到 2 条链(LRU 和 LRUW),这 2 条分别将 Buffer Header 连接起来,和 Cache Buffers Chain类似。下面看看这 2 条链的作用:
1)LRU 表示 Least Recently Used,也就是指最近最少使用的 Buffer Header 链表。LRU 链表串
连起来的 Buffer Header 都指向可用数据块(Free Buffer)。
2)LRUW 则表示 Least Recently Used Write,也叫做 Dirty List,也就是脏数据块链表,LRUW串起来的都是修改过但是还没有写入数据文件的内存数据块所对应的 Buffer Header(Dirty
Buffer)。
3)一个 Buffer Header 要么在 LRU 上,要么在 LRUW 上,不能同时存在于这两个链表上。
所以,当前面查找数据在 BUFFER CACHE 中不存在的时候(即在 Hash Chain 中查找不到对应
的 Buffer Header 的情况下):
1) 就要扫描 LRU List 寻找 Free 的 Buffer,在扫描过程将持有 Cache Buffers Lru Chain Latch(其
Latch 数量由隐含参数_db_block_lru_latches 决定)。扫描过程中会把已经被修改过的
Buffer 移动到 LRUW 列表上。
2) 找到足够的 Buffer 后,将数据块 Block 读入到 Buffer Cache,构造一个与之对应的 Buffer
Header , 然 后 根 据 HASH 算 法 ( Hash Bucket = MOD(Data Block Address,
_DB_BLOCK_HASH_BUCKETS) ),将 Buffer Header 放到对应的 Hash Bucket 的 Cache Buffers
Chain 中去,并在 Buffer Header 中存放相关的信息。
2.3、总的在 BUFFER CACHE 中查找数据,可以简单的表示为下图:



2.4 通常有 2 中情况或导致 Latch 出现竞争:
1) 某一进程长时间的持有 Latch,导致其他进程不能正常的得到 Latch,只能等待。
2) 可能存在大量的 Latch 请求。
2.4.1如果出现 Cache Buffers Chains Latch 竞用严重,根据前面的原理,那么可能有如下原因:1)当多个会话重复访问一个或多个由同一个子Cache Buffers Chains Latch保护的块时热点块(可以关注 X$BH 中的 TCH 字段)。
2) 大量并发执行的低效 SQL。低效的 SQL 通常需要获取大量的逻辑读,而得到一次逻辑 IO
就得获得一次 Cache Buffers Chains Latch。
3) Hash Bucket 中存在长的 Cache Buffers Chains,导致查询数据时候,长时间持有 Latch。2.4.2
如果出现 Cache Buffers Lru Chain Latch 竞用严重,那么可能有如下原因:
1) 可能 BUFFER CACHE 分配的空间不够,导致读数据到 BUFFER CACHE 的时候,不断的扫描LRU List。
案例分析:
2.5、测试:模拟 Cache Buffers Chains Latch 竞用 
[code=jfx;toolbar:false">1、建立测试table,只有一条记录
14:10:47 SCOTT@ prod >select * from test;
         N
----------
        10

2、查看表存储的block信息        
14:10:50 SCOTT@ prod >select dbms_rowid.rowid_relative_fno(rowid) file#,dbms_rowid.rowid_block_number(rowid) block# from test;
     FILE#     BLOCK#
---------- ----------
         6        365

3、建立测试存储过程
14:16:29 SCOTT@ prod >create or replace procedure test_latch is
14:16:30   2     i number;
14:16:30   3    begin
14:16:30   4      loop
14:16:30   5       select n into i from test;
14:16:30   6    end loop;
14:16:30   7    end;
14:16:31   8  /
Procedure created.

4、建立session测试
14:17:14 SCOTT@ prod >select * from v$mystat where rownum=1;
       SID STATISTIC#      VALUE
---------- ---------- ----------
         1          0          0
 
5、执行procedure进行测试         
14:17:27 SCOTT@ prod >exec test_latch;

6、查看会话信息(event)
14:20:38 SYS@ prod > select sid,event,p1,p1raw,p1text,p2,p2text from v$session where sid=1
       SID EVENT                                  P1 P1RAW            P1TEXT                       P2 P2TEXT
---------- ------------------------------ ---------- ---------------- -------------------- ---------- --------------------
         1 SQL*Net message from client    1650815232 0000000062657100 driver id                     1 #bytes

7、在执行期间可以看到 Cache Buffers Lru Chain Latch 都是 Get 成功,不存在竞争 
14:21:13 SYS@ prod >select gets,misses,sleeps,spin_gets,wait_time from v$latch
14:21:49   2      where name='cache buffers chains';

      GETS     MISSES     SLEEPS  SPIN_GETS  WAIT_TIME
---------- ---------- ---------- ---------- ----------
  63272697          0          0          0          0

8、再建立另一个session,执行相同的任务
14:23:07 SYS@ prod >conn scott/tiger
Connected.
14:23:09 SCOTT@ prod >select * from v$mystat where rownum=1;

       SID STATISTIC#      VALUE
---------- ---------- ----------
        56          0          0

14:23:22 SCOTT@ prod >exec test_latch;
       
9、查看session event
1)可以看到出现latch: cache buffers chains等待事件。这就是2个session要同时访问同一
个 Block,这个时候在一个会话持有 Latch 的时候,另一个会话必须 Spin 等待获得 Latch。
2)同时也能看到 cursor: pin S等待事件。 

14:23:42 SYS@ prod >select sid,event,p1,p1raw,p1text,p2,p2text from v$session where sid in (1,56);
       SID EVENT                                  P1 P1RAW            P1TEXT                       P2 P2TEXT
---------- ------------------------------ ---------- ---------------- -------------------- ---------- --------------------
         1 latch: cache buffers chains     850140044 0000000032AC1B8C address                     150 number
        56 cursor: pin S                  3879408699 00000000E73B143B idn                       65536 value

14:24:34 SYS@ prod >/
       SID EVENT                                  P1 P1RAW            P1TEXT                       P2 P2TEXT
---------- ------------------------------ ---------- ---------------- -------------------- ---------- --------------------
         1 latch: cache buffers chains     850082532 0000000032AB3AE4 address                     150 number
        56 latch: cache buffers chains     850140044 0000000032AC1B8C address                     150 number

14:24:46 SYS@ prod >/
       SID EVENT                                  P1 P1RAW            P1TEXT                       P2 P2TEXT
---------- ------------------------------ ---------- ---------------- -------------------- ---------- --------------------
         1 latch: cache buffers chains     849991208 0000000032A9D628 address                     150 number
        56 latch: cache buffers chains     850231368 0000000032AD8048 address                     150 number
        
14:38:32 SYS@ prod >/

       SID EVENT                                  P1 P1RAW            P1TEXT                       P2 P2TEXT
---------- ------------------------------ ---------- ---------------- -------------------- ---------- --------------------
         1 cursor: pin S                  3879408699 00000000E73B143B idn                     3670016 value
        56 cursor: pin S                  3879408699 00000000E73B143B idn                       65536 value
10、这个时候可以看到 Cache Buffers Lru Chain Latch 都是 Get 出现严重的竞争,出现大量的Misses,Sleeps,Spin_gets:          
14:24:48 SYS@ prod >select gets,misses,sleeps,spin_gets,wait_time from v$latch
14:25:06   2  where name='cache buffers chains';
      GETS     MISSES     SLEEPS  SPIN_GETS  WAIT_TIME
---------- ---------- ---------- ---------- ----------
 111686729       2358       1293       1065    1043230
Elapsed: 00:00:00.00
14:25:18 SYS@ prod >/
      GETS     MISSES     SLEEPS  SPIN_GETS  WAIT_TIME
---------- ---------- ---------- ---------- ----------
 115457171       2667       1466       1202    1178935
Elapsed: 00:00:00.00
14:25:33 SYS@ prod >/
      GETS     MISSES     SLEEPS  SPIN_GETS  WAIT_TIME
---------- ---------- ---------- ---------- ----------
 115987352       2722       1497       1226    1204103
Elapsed: 00:00:00.00
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: