Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2767087
  • 博文数量: 389
  • 博客积分: 4177
  • 博客等级: 上校
  • 技术积分: 4773
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-16 23:29
文章分类

全部博文(389)

分类: Oracle

2013-09-06 19:54:28

                                                     观察Oracle latch的内存值
     oracle通过设置某个内存的地址(实际上是一个变量),来判断某个latch是否可以得到,然后接着执行相关代码。

创建一个表
SQL> create table t1(a int); --create table
SQL> insert into values(10);  --insert value
SQL>commit;

接下来得到该表行的数据块地址和文件号
SQL> select dbms_rowid.rowid_block_number(rowid),dbms_rowid.rowid_relative_fno(rowid) from t1;
 
DBMS_ROWID.ROWID_BLOCK_NUMBER( DBMS_ROWID.ROWID_RELATIVE_FNO(
------------------------------ ------------------------------
                         99025                              1

SQL> select count(*) from t1;  --执行一个select 操作


从buffe cache得到保护该块的latch address

SQL> select file#,dbablk,hladdr from x$bh where file#=1 and dbablk=99025;
 
     FILE#     DBABLK HLADDR
---------- ---------- ----------------
         1      99025 000000008108BBE8

可以看到保护当前buffer的chains buffer chain latch的地址为0x 000000008108BBE8

SQL> oradebug peek 0x000000008108BBE8 16;
[08108BBE8, 08108BBF8) = 00000000 00000000 000A5656 000000CB
从这个值可以判断当前全是0,表示当前没有会话持有该latch,其他会话可以读取这个buffer。

假设我不断的使用一个循环该得到该latch呢,那这个值一定会被置,另外的会话就会在CBC上等待,结果真是这样的吗?接着往下看

SQL>   declare
  2    i int;
  3    b int;
  4      begin
  5      for i in 1..10000000
  6           loop
  7            select count(*) into b from t1;
  8           end loop;
  9 
 10     end;
 11  /

SQL> oradebug peek 0x000000008108BBE8 16;
[08108BBE8, 08108BBF8) = 00000000 00000000 0017418B 000000CB

事实上进行只读的时候,cbc不会被设置,我们把这种方式也叫只读CBC,这是oracle为了增加buffer的并发而改进的一种方式,只是第三个值会一直增加.
当多个会话执行之前的plsql代码段的时候,也不会以独占的方式去持有cbc,这样就可以保证多个会话的并发访问.

会话1.
SQL>  declare
  2    i int;
  3    b int;
  4      begin
  5      for i in 1..10000000
  6           loop
  7            select count(*) into b from t1;
  8           end loop;
  9 
 10     end;
 11  /

会话2
SQL>  declare
  2    i int;
  3    b int;
  4      begin
  5      for i in 1..10000000
  6           loop
  7            select count(*) into b from t1;
  8           end loop;
  9 
 10     end;
 11  /

会话3,

SQL> select event,sid from v$session_wait where wait_class<>'Idle';
 
EVENT                                                                   SID
---------------------------------------------------------------- ----------
 
返回空

再次观察 CBC内存的地址,

SQL> oradebug peek 0x000000008108BBE8 16;
[08108BBE8, 08108BBF8) = 00000000 00000000 00284C24 000000CB

与我们之前的假设一致

如果我们手动来更改内存的地址,看会话会等待什么内容呢?

首先在会话1,查看当前的sid

SQL> select distinct sid from v$mystat;

       SID
----------
       267

在会话2上面,更改latch address的内容,模拟以exclusive的方式来占用CBC
SQL> oradebug poke 0x000000008108BBE8 8 0xffffffffffffffff;
BEFORE: [08108BBE8, 08108BBF0) = 00000000 00000000
AFTER:  [08108BBE8, 08108BBF0) = FFFFFFFF FFFFFFFF

在会话1上,再次执行

SQL>select count(*) from t1;

会话被hang住


在会话2上执行查询

SQL> select event,p1 from v$session where sid=267;

EVENT                                   P1
---------------------------------------   -------------------------
latch: cache buffers chains                  2164833256
可以看到会话1一直在CBC上等待,被hang住了.P1的地址为latch的地址.

 实验通过cbc来实现的,其他的latch的地址,可以通过v$latchholder可以得到当前持有latch的会话和latch的内存地址信息.

阅读(3742) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~