Cache Buffer Chain(CBC) Latch解析

本文深入探讨了Oracle数据库中CBCLatch的工作原理及其产生的原因,包括如何通过模拟实验来观察CBCLatch等待现象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[+]

一.  原理

当一个数据块读入到sga中时,该块的块头(buffer header)地址存放在一个hash bucket的链表(hash chain)中。该内存结构由一系列cache buffer chains子latch保护(cbc latch)。对buffer cache中的块,要select或者update、insert、delete等,都得先获得cache buffer chains子latch,以保证对chain的排他访问。若在过程中发生争用,就会等待latch:cache buffer chains事件。

逻辑读的过程:

1.Oracle以每个块的文件号,块号和类型做hash运算,得到hash值。根据hash值,到hash表中取出指定块的内存地址。

2.获取CBC latch

3.根据hash值,搜索CBC链表

4.根据DBA找到BH(Buffer header)加buffer pin

5.加完buffer pin马上释放CBC latch

6.访问buffer开始fetch数据

7.获取CBC latch

8.释放buffer pin

9.释放CBC latch

二.产生原因

1.CBC latch保护不同的链表、不同BH,即同一latch下多个BUCKET被同时访问时(一个latch对应多个BUCKET)。

体现在实际情况通常为低效率的sql语句(逻辑读过高)。在某些环境中,应用程序打开执行相同的低效率sql的多个并发会话,这些病发会话都设法得到相同的数据集,每次执行都带有高buffer_gets。相反,较少的逻辑读则意味着较少的latch get操作,从而减少锁存器争用并改善性能。注意v$sql中buffer_gets/executions大的语句。

2.CBC latch保护同一链表下同一BH,即同一latch下同一BH被同时访问时(全表扫描时容易出现)

Hot Block:当多个会话重复访问一个或多个由同一个子cache buffer chains锁存器保护的块时,热块就会产生。即多个会话争用cache buffer chains子锁存器。

3.同时出现CBC latch和buffer busy waits的情况:已经有会话获取了buffer pin锁,此时会话1时获取了CBC latch,但是无法获得buffer pin锁,此时会话1出现buffer busy waits。如果有其他会话想要访问此CBC latch下的其他hash chain或者访问和会话1 相同的BH,就会出现CBC latch等待。

三.模拟产生CBC latch等待

测试表:

[sql]  view plain  copy
  1. SQL>  select rowid,  
  2.   2     dbms_rowid.rowid_row_number(rowid) rowid_rownum,  
  3.   3     dbms_rowid.rowid_relative_fno(rowid) file_id,  
  4.   4     dbms_rowid.rowid_block_number(rowid) block_id,test_buffer_busy.object_id from test_buffer_busy where rownum<3;  
  5.   
  6. ROWID              ROWID_ROWNUM    FILE_ID   BLOCK_ID  OBJECT_ID  
  7. ------------------ ------------ ---------- ---------- ----------  
  8. AAAVXOAAEAAAAw7AAA            0          4       3131         20  
  9. AAAVXOAAEAAAAw7AAB            1          4       3131         46  
session1:

[sql]  view plain  copy
  1. SQL> declare  
  2.   2  aa varchar2(100);  
  3.   3  begin  
  4.   4  for i in 1..1000000 loop  
  5.   5  select object_name into aa from test_buffer_busy where rowid='AAAVXOAAEAAAAw7AAA';  
  6.   6  end loop;  
  7.   7  end;  
  8.   8  /  
session2:

[sql]  view plain  copy
  1. SQL> declare  
  2.   2  begin  
  3.   3  for i in 1..1000000 loop  
  4.   4  update test_buffer_busy set status=15 where rowid='AAAVXOAAEAAAAw7AAB';  
  5.   5  end loop;  
  6.   6  commit;  
  7.   7  end;  
  8.   8  /  
sesison3:

[sql]  view plain  copy
  1. SQL> select sid ,event,total_waits from v$session_event  where sid in(1,17) and event like '%buffer%'  
  2.   2  ;  
  3.   
  4.        SID EVENT                                                            TOTAL_WAITS  
  5. ---------- ---------------------------------------------------------------- -----------  
  6.          1 latch: cache buffers chains                                               21  
  7.          1 buffer busy waits                                                         48  
  8.         17 latch: cache buffers chains                                                9  
  9.         17 log buffer space     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值