Oracle在buffer cache内存管理中利用hash table来提高进程检索数据的速度,一般来说oracle利用hash算法将buffer cache分割成不同的hash bucket,每hash bucket都会有一个hash链(cache buffers chains)来管理buffer cache中的每一个buffer,那么这些buffer的header就是存放在这个cache buffers chains上面的,因此进程根据pid的hash算法,来访问某一个hash bucket中的buffer header时,首先要获得每一个hash bucket中cache buffers chains的一个latch,也就是我们所谓的闩。latch其实就是一种非常低级的串行化设备,和锁的数据结构有着截然不同的特点,只所以说他是低级的,就是因为相比锁来讲他的获得和释放都非常的快。同时latch的存在会使的我们的共享设备在进程并发访问的情况下对其进行数据结构的保护。
下面来做个实验就是,让一个block很热,从而观察cache buffers chains上面latch的竞争。
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
PL/SQL Release 9.2.0.8.0 - Production
CORE 9.2.0.8.0 Production
TNS for 32-bit Windows: Version 9.2.0.8.0 - Production
NLSRTL Version 9.2.0.8.0 - Production
SQL> select file_name from dba_data_files;
FILE_NAME
----------------------------------------------------------------------
D:\ORACLE\ORA92\ICMNLSDB\SYSTEM01.DBF
D:\ORACLE\ORA92\ICMNLSDB\UNDOTBS01.DBF
D:\ORACLE\ORA92\ICMNLSDB\INDX01.DBF
D:\ORACLE\ORA92\ICMNLSDB\TOOLS01.DBF
D:\ORACLE\ORA92\ICMNLSDB\USERS01.DBF
SQL> create tablespace assm
2 datafile 'D:\ORACLE\ORA92\ICMNLSDB\assm.dbf' size 10M
3 extent management local uniform. size 1M
4 segment space management auto;
表空间已创建。
SQL> create table t
2 (id number,
3 name char(10)) tablespace assm;
表已创建。
SQL> insert into t values (1,'A');
已创建 1 行。
SQL> commit;
提交完成。
SQL> select id,rowid from t;
ID ROWID
---------- ------------------
1 AAAGP5AAGAAAAAXAAA
这里我们只插入一行的数据,然后频繁的针对这个block进行并发访问,导致这个block header所在的cache buffers chains上的latch产生竞争。
创建测试脚本
SQL> create or replace procedure latch_test
2 as
3 cursor my_cursor is select id from t where rowid='AAAGP5AAGAAAAAXAAA';
4 t_result number(5);
5 begin
6 for i in 1..700000 loop
7 open my_cursor;
8 fetch my_cursor into t_result;
9 close my_cursor;
10 end loop;
11 end;
12 /
过程已创建。
在3个session上面同时运行测试脚本,并进行监控:
运行脚本之前......
SQL> select sid,event,time_waited,time_waited_micro,total_timeouts,total_waits
2 from v$session_event
3 where sid in (7,8,9) and event like '%latch%';
未选定行
SQL> select misses,gets,sleeps,spin_gets,sleep1,sleep2,sleep3,sleep4
2 from v$latch where name='cache buffers chains';
MISSES GETS SLEEPS SPIN_GETS SLEEP1 SLEEP2 SLEEP3
---------- ---------- ---------- ---------- ---------- ---------- ----------
SLEEP4
----------
0 8241 0 0 0 0 0
0
开始在3个不同的session同时运行脚本......
继续观察
SQL> select sid,event,time_waited,time_waited_micro,total_timeouts,total_waits
2 from v$session_event
3 where sid in (8,9,10) and event like '%latch%';
SID EVENT
---------- ----------------------------------------------------------------
TIME_WAITED TIME_WAITED_MICRO TOTAL_TIMEOUTS TOTAL_WAITS
----------- ----------------- -------------- -----------
8 latch free
84 838857 15 24
9 latch free
80 803321 15 28
10 latch free
101 1011249 17 30
这里出现了三个等待事件,正好是我们在运行脚本时的三个session 8,9,10。
SQL> select misses,gets,sleeps,spin_gets,sleep1,sleep2,sleep3,sleep4
2 from v$latch where name='cache buffers chains';
MISSES GETS SLEEPS SPIN_GETS SLEEP1 SLEEP2 SLEEP3
---------- ---------- ---------- ---------- ---------- ---------- ----------
SLEEP4
----------
78 4209205 81 0 75 3 0
0
因为三个session都在并发的去争夺同一个cache buffer chains上的latch,从而会导致latch的竞争。
如果是单读一个session对block进行访问,我们可以只看到这个latch被gets.而竞争消失。
SQL> /
MISSES GETS SLEEPS SPIN_GETS SLEEP1 SLEEP2 SLEEP3
---------- ---------- ---------- ---------- ---------- ---------- ----------
SLEEP4
----------
78 5609271 81 0 75 3 0
参考这个
http://space.itpub.net/13095417/viewspace-172809
记录一下sleeps和sleep 1,2,3,4的关系:
sleeps=sleep1*1 + sleep2 * 2 + sleep3 * 3 + ........
v$latch的字段描述
gets 以愿意等待模式请求闩,并获得的次数.
misses 以愿意等待模式请求闩,自旋或睡眠后获得的次数.
sleeps 以愿意等待模式请求闩,睡眠的次数.
spin_gets 第一次自旋即成功获得闩的次数.
sleep1 睡眠一次后获得闩的次数.
sleep2 睡眠两次后获得闩的次数.
sleep3 睡眠三次后获得闩的次数.
sleep4 睡眠四次以上获得闩的次数.
下面来做个实验就是,让一个block很热,从而观察cache buffers chains上面latch的竞争。
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
PL/SQL Release 9.2.0.8.0 - Production
CORE 9.2.0.8.0 Production
TNS for 32-bit Windows: Version 9.2.0.8.0 - Production
NLSRTL Version 9.2.0.8.0 - Production
SQL> select file_name from dba_data_files;
FILE_NAME
----------------------------------------------------------------------
D:\ORACLE\ORA92\ICMNLSDB\SYSTEM01.DBF
D:\ORACLE\ORA92\ICMNLSDB\UNDOTBS01.DBF
D:\ORACLE\ORA92\ICMNLSDB\INDX01.DBF
D:\ORACLE\ORA92\ICMNLSDB\TOOLS01.DBF
D:\ORACLE\ORA92\ICMNLSDB\USERS01.DBF
SQL> create tablespace assm
2 datafile 'D:\ORACLE\ORA92\ICMNLSDB\assm.dbf' size 10M
3 extent management local uniform. size 1M
4 segment space management auto;
表空间已创建。
SQL> create table t
2 (id number,
3 name char(10)) tablespace assm;
表已创建。
SQL> insert into t values (1,'A');
已创建 1 行。
SQL> commit;
提交完成。
SQL> select id,rowid from t;
ID ROWID
---------- ------------------
1 AAAGP5AAGAAAAAXAAA
这里我们只插入一行的数据,然后频繁的针对这个block进行并发访问,导致这个block header所在的cache buffers chains上的latch产生竞争。
创建测试脚本
SQL> create or replace procedure latch_test
2 as
3 cursor my_cursor is select id from t where rowid='AAAGP5AAGAAAAAXAAA';
4 t_result number(5);
5 begin
6 for i in 1..700000 loop
7 open my_cursor;
8 fetch my_cursor into t_result;
9 close my_cursor;
10 end loop;
11 end;
12 /
过程已创建。
在3个session上面同时运行测试脚本,并进行监控:
运行脚本之前......
SQL> select sid,event,time_waited,time_waited_micro,total_timeouts,total_waits
2 from v$session_event
3 where sid in (7,8,9) and event like '%latch%';
未选定行
SQL> select misses,gets,sleeps,spin_gets,sleep1,sleep2,sleep3,sleep4
2 from v$latch where name='cache buffers chains';
MISSES GETS SLEEPS SPIN_GETS SLEEP1 SLEEP2 SLEEP3
---------- ---------- ---------- ---------- ---------- ---------- ----------
SLEEP4
----------
0 8241 0 0 0 0 0
0
开始在3个不同的session同时运行脚本......
继续观察
SQL> select sid,event,time_waited,time_waited_micro,total_timeouts,total_waits
2 from v$session_event
3 where sid in (8,9,10) and event like '%latch%';
SID EVENT
---------- ----------------------------------------------------------------
TIME_WAITED TIME_WAITED_MICRO TOTAL_TIMEOUTS TOTAL_WAITS
----------- ----------------- -------------- -----------
8 latch free
84 838857 15 24
9 latch free
80 803321 15 28
10 latch free
101 1011249 17 30
这里出现了三个等待事件,正好是我们在运行脚本时的三个session 8,9,10。
SQL> select misses,gets,sleeps,spin_gets,sleep1,sleep2,sleep3,sleep4
2 from v$latch where name='cache buffers chains';
MISSES GETS SLEEPS SPIN_GETS SLEEP1 SLEEP2 SLEEP3
---------- ---------- ---------- ---------- ---------- ---------- ----------
SLEEP4
----------
78 4209205 81 0 75 3 0
0
因为三个session都在并发的去争夺同一个cache buffer chains上的latch,从而会导致latch的竞争。
如果是单读一个session对block进行访问,我们可以只看到这个latch被gets.而竞争消失。
SQL> /
MISSES GETS SLEEPS SPIN_GETS SLEEP1 SLEEP2 SLEEP3
---------- ---------- ---------- ---------- ---------- ---------- ----------
SLEEP4
----------
78 5609271 81 0 75 3 0
参考这个
http://space.itpub.net/13095417/viewspace-172809
记录一下sleeps和sleep 1,2,3,4的关系:
sleeps=sleep1*1 + sleep2 * 2 + sleep3 * 3 + ........
v$latch的字段描述
gets 以愿意等待模式请求闩,并获得的次数.
misses 以愿意等待模式请求闩,自旋或睡眠后获得的次数.
sleeps 以愿意等待模式请求闩,睡眠的次数.
spin_gets 第一次自旋即成功获得闩的次数.
sleep1 睡眠一次后获得闩的次数.
sleep2 睡眠两次后获得闩的次数.
sleep3 睡眠三次后获得闩的次数.
sleep4 睡眠四次以上获得闩的次数.
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/12361284/viewspace-201610/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/12361284/viewspace-201610/