lru oracle,oracle cache buffer lru chain(1)

oracle cache buffer lru chain(一)

今天是2013-09-09,这个月 我要 做一个大事情,就是把oracle内存结构研究好,这是第一篇笔记。

oracle database buffer cache:

一、

1)buffer cache定义:

数据缓存区是copy的数据块信息存在buffercache中sga的一个块区域。所有的客户端进程都能够并发的访问实例来共享这buffer

cache。

2)buffer cache实现的目标:

1、优化磁盘的物理读写

2、在buffer cache中保持频繁访问,延迟写入磁盘。

3)buffer状态

数据库使用内部算法来管理buffer cache,没个buffer存在如下情况之一。

1、unused

这种buffer是可以使用的,因为它从来没有被使用或是当前已经使用过了的。这种状态的buffer是最容易被使用的。

2、clean

这种缓冲区是最近使用的并且包含数据块的读一致性。这种数据块包含数据但是是干净的,所以没有必要进行检查点。数据库可以对它进行pin然后重新使用它

3、dirty

这种数据缓冲区包含被编辑的数据块,并且这些数据块还没有被写入磁盘。数据库必须对它进行checkpoint之后,然后再重新使用它。

Every buffer has an access mode: pinned orfree (unpinned). A buffer is "pinned" in the cache so that it doesnot age out of memory while a user session accesses it. Multiple sessionscannot modify a pinned

buffer at the same time.

The database uses a sophisticated algorithmto make buffer access efficient. Pointers to dirty and nondirty buffers existon the same least recently used (LRU) list, which has a hot end and cold end. Acold

buffer is one that has not been recently used. A hot buffer is frequentlyaccessed and has been recently used.

4)buffer write情况

数据库使用dbwn进程来完成数据从buffer cache写入到datafile中。该进程个数可以通过db_writer_processes参数进行设置。

另外在dbwn进程在执行写的条件有如下:

1)当服务今次那个不能够发现clean请求的buffer的时候,将会执行写操作,这个也受一个隐含参数控制:

SQL> select kvitval,kvittag,kvitdsc fromx$kvit  where kvittag='kcbfsp';

KVITVAL KVITTAG                                                         KVITDSC

-------------------------------------- ----------------------------

40 kcbfsp                                                          Max percentage of LRU list foreground can scan for free

SQL>

还有就是dirty lru达到一定值的时候,需要进行写出操作,这个值也收一个隐含参数控制:

SQL>  select kvitval,kvittag,kvitdsc fromx$kvit  where kvittag='kcbldq';

KVITVAL KVITTAG                                                         KVITDSC

------------------------------------------------------------------

25 kcbldq                                                          large dirty queue if kcbclw reaches this

SQL>

2、在完成检查点之前需要写出buffercache。

5)buffer读的情况

对于oracle clean或是unused buffer的数量很少的时候,那么数据库就会执行删除的操作。这种机制取决于flash cache是否启动了

注意:数据库的smart flash cache只能在solaris和oracle enterprise linux中使用。

flash cache没有启动:

数据库就会重新使用clean的buffer,或是覆盖之后进行使用。如果覆盖之后的数据过会又被使用,那么只能进行物理的读写操作,把数据文件的信息重新读取到buffer中。

flash cahce启动:

当dbwn进程能够把clean buffer的body写入到flash cache中,然后再内存中重新使用buffer,这时候数据库会保持原先的数据header存在于内存中的lru链中,数据存在flash

cache中。当这个buffer在此被使用的时候,就会从flash cache进行读取而不是进行物理的读写操作,从而提高了效率。

对于lru链的学习,参考:http://yeshaochen.blog.51cto.com/3155801/913342(灰常经典)

当一个客户端请求数据的时候,来看一下服务进程执行过程:

1)  首先服务进程搜索全部buffercache,如果找到了,那么就进行逻辑读取信息返回给client

2)  服务进程搜索在flashcache lru list中的buffer header信息。

如果找到了buffer header,那么就会执行最优化的把信息从flash cache中读取到memory cache。

3)  如果服务进程没有找到需要的buffer信息,那么就会进行如下两部:

1、  执行物理读取数据文件信息,把数据块copy到内存中

2、  在buffer中执行逻辑读取然后返回给用户信息

另外在来看一下flash cache这一部分知识,请查看联机手册:

http://docs.oracle.com/cd/E11882_01/server.112/e25494/memory.htm#BABHEDBH

二、

在oracle的内存中存在很多list进行管理,转储一下buffer然后查看一下具体情况:

对于内存转储有如下等级;

Level  1:包含buffer headers信息

Level  2:包含buffer headers和buffer概要信息

Level  3:包含buffer headers和完整的buffer内容转储

Level  4:level 1+ latch转储+LRU队列

Level  5:level4 + buffer概要信息转储

Level  6和level   7:level4+完整的buffer内存转储

Level  8:level4+显示users/waiters信息

Level  9:level5 +显示users/waiters信息

Level  10:level 6+显示users/waiters信息:

Eg:

SQL> alter system set events 'immediatetrace name buffer level 4';

System altered.

注意:转储的等级越高,trace文件就越大,内容就越详细,但是注意:max_dump_file_size参数的设置为没有限制大小,不要在现网中进行很高等级的buffer cache转储操作。

查看信息:

Dump of buffer cache at level 4 fortsn=2147483647, rdba=0

(WS) size: 0 (0) wsid: 1 state: 0 pool: 1

(WS_REPL_LIST) main_prev: 0x76e40858 main_next: 0x76e40858 aux_prev:0x76e40868 aux_next: 0x76e40868

curnum: 0 auxnum: 0

cold: 76e40858 hbmax: 0 hbufs: 0

(WS_WRITE_LIST) main_prev: 0x76e40888 main_next: 0x76e40888 aux_prev:0x76e40898 aux_next: 0x76e40898

curnum: 0 auxnum: 0

(WS_XOBJ_LIST) main_prev: 0x76e408b8 main_next: 0x76e408b8 aux_prev:0x76e408c8 aux_next: 0x76e408c8

curnum: 0 auxnum: 0

(WS_XRNG_LIST) main_prev: 0x76e408e8 main_next: 0x76e408e8 aux_prev:0x76e408f8 aux_next: 0x76e408f8

curnum: 0 auxnum: 0

(WS_REQ_LIST) main_prev: 0x76e40918 main_next: 0x76e40918 aux_prev:0x76e40928 aux_next: 0x76e40928

curnum: 0 auxnum: 0

(WS_L2WRT_LIST) main_prev: 0x76e40948 main_next: 0x76e40948 aux_prev:0x76e40958 aux_next: 0x76e40958

curnum: 0 auxnum: 0

(WS_L2REPL_LIST) main_prev: 0x76e40978 main_next: 0x76e40978 aux_prev:0x76e40988 aux_next: 0x76e40988

curnum: 0 auxnum: 0

(WS_L2KEEP_LIST) main_prev: 0x76e409a8 main_next: 0x76e409a8 aux_prev:0x76e409b8 aux_next: 0x76e409b8

curnum: 0auxnum: 0

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

MAIN RPL_LSTQueue header (NEXT_DIRECTION)[NULL]

MAIN RPL_LSTQueue header (PREV_DIRECTION)[NULL]

AUXILIARYRPL_LST Queue header (NEXT_DIRECTION)[NULL]

AUXILIARYRPL_LST Queue header (PREV_DIRECTION)[NULL]

MAIN WRT_LSTQueue header (NEXT_DIRECTION)[NULL]

MAIN WRT_LSTQueue header (PREV_DIRECTION)[NULL]

AUXILIARYWRT_LST Queue header (NEXT_DIRECTION)[NULL]

AUXILIARYWRT_LST Queue header (PREV_DIRECTION)[NULL]

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

MAIN RPL_LSTQueue header (NEXT_DIRECTION)[0x687fb9d0,0x6c3f5610]

0x687fb8e8=>0x687fba18=>0x687fbb48=>0x687fbc78=>0x687fbda8=>0x687fbed8=>0x687fc008=>0x687fc138

0x687fc268=>0x687fc5f8=>0x687fc398=>0x687fc4c8=>0x68bed748=>0x68bed878=>0x68bed9a8=>0x68bedad8

0x68bedc08=>0x68bedd38=>0x68bede68=>0x68bedf98=>0x68bee0c8=>0x68bee1f8=>0x68bee328=>0x68bee458

0x68bee588=>0x68bee6b8=>0x68bee7e8=>0x68bee918=>0x68beea48=>0x68fec318=>0x68fec448=>0x68fec578

0x68fec6a8=>0x68fec7d8=>0x68fec908=>0x68feca38=>0x68fecb68=>0x68fecc98=>0x68fecdc8=>0x68fecef8

0x68fed028=>0x68fed158=>0x68fed288=>0x68fed3b8=>0x68fed4e8=>0x68fed618=>0x693eaee8=>0x693eb018

0x693eb148=>0x693eb278=>0x693eb3a8=>0x693eb4d8=>0x693eb608=>0x693eb738=>0x693eb868=>0x693eb998

0x693ebac8=>0x693ebbf8=>0x693ebd28=>0x693ebe58=>0x693ebf88=>0x693ec0b8=>0x693ec1e8=>0x697e9ab8

0x697e9be8=>0x697e9d18=>0x697e9e48=>0x697e9f78=>0x697ea0a8=>0x697ea1d8=>0x697ea308=>0x697ea438

0x697ea568=>0x697ea698=>0x697ea7c8=>0x697ea8f8=>0x697eaa28=>0x697eab58=>0x697eac88=>0x697eadb8

0x69be8688=>0x69be87b8=>0x69be88e8=>0x69be8a18=>0x69be8b48=>0x69be8c78=>0x69be8da8=>0x69be8ed8

0x69be9008=>0x69be9138=>0x69be9268=>0x69be9398=>0x69be94c8=>0x69be95f8=>0x69be9728=>0x69be9858

0x69be9988=>0x69fe7258=>0x69fe7388=>0x69fe74b8=>0x69fe75e8=>0x69fe7718=>0x69fe7848=>0x69fe7978

0x69fe7aa8=>0x69fe7bd8=>0x69fe7d08=>0x69fe7e38=>0x69fe7f68=>0x69fe8098=>0x69fe81c8=>0x69fe82f8

0x69fe8428=>0x69fe8558=>0x6a3e5e28=>0x6a3e5f58=>0x6a3e6088=>0x6a3e61b8=>0x6a3e62e8=>0x6a3e6418

0x6a3e6548=>0x6a3e6678=>0x6a3e67a8=>0x6a3e68d8=>0x6a3e6a08=>0x6a3e6b38=>0x6a3e6c68=>0x6a3e6d98

0x6a3e6ec8=>0x6a3e6ff8=>0x6a3e7128=>0x6a7e49f8=>0x6a7e4b28=>0x6a7e4c58=>0x6a7e4d88=>0x6a7e4eb8

0x6a7e4fe8=>0x6a7e5118=>0x6a7e5248=>0x6a7e5378=>0x6a7e54a8=>0x6a7e55d8=>0x6a7e5708=>0x6a7e5968

0x6a7e5838=>0x6a7e5a98=>0x6a7e5bc8=>0x6a7e5cf8=>0x6abe35c8=>0x6abe36f8=>0x6abe3828=>0x6abe3958

0x6abe3a88=>0x6abe3bb8=>0x6abe3ce8=>0x6abe3e18=>0x6abe3f48=>0x6abe4078=>0x6abe41a8=>0x6abe42d8

0x6abe4408=>0x6abe4538=>0x6abe4668=>0x6abe4798=>0x6abe48c8=>0x6afe2198=>0x6afe22c8=>0x6afe23f8

0x6afe2528=>0x6afe2658=>0x6afe2788=>0x6afe28b8=>0x6afe29e8=>0x6afe2b18=>0x6afe2c48=>0x6afe2d78

0x6afe2ea8=>0x6afe2fd8=>0x6afe3108=>0x6afe3238=>0x6afe3368=>0x6afe3498=>0x6b3fa128=>0x6b3fa258

0x6b3fa388=>0x6b3fa4b8=>0x6b3fa5e8=>0x6b3fa718=>0x6b3fa848=>0x6b3fa978=>0x6b3faaa8=>0x6b3fabd8

0x6b3fad08=>0x6b3fae38=>0x6b3faf68=>0x6b3fb098=>0x6b3fb1c8=>0x6b3fb2f8=>0x6b3fb428=>0x6b7f8cf8

0x6b7f8e28=>0x6b7f8f58=>0x6dbe10f8=>0x6b7f9088=>0x6b7f91b8=>0x6b7f92e8=>0x6b7f9418=>0x6b7f9548

0x6b7f9678=>0x6b7f97a8=>0x6b7f98d8=>0x6b7f9a08=>0x6b7f9b38=>0x6b7f9c68=>0x6b7f9d98=>0x6b7f9ec8

0x6b7f9ff8=>0x6bbf78c8=>0x6bbf79f8=>0x6dbe0d68=>0x6bbf7b28=>0x6bbf7c58=>0x6bbf7d88=>0x6bbf7eb8

0x6bbf7fe8=>0x6d3f0468=>0x6bbf8118=>0x6bbf8248=>0x6bbf8378=>0x6bbf84a8=>0x6bbf85d8=>0x6bbf8708

0x6bbf8838=>0x6bbf8968=>0x6bbf8a98=>0x6bbf8bc8=>0x6bff6498=>0x6bff65c8=>0x6bff66f8=>0x6bff6828

0x6bff6958=>0x6bff6a88=>0x6bff6bb8=>0x6bff6ce8=>0x6bff6e18=>0x6bff6f48=>0x6bff7078=>0x6bff71a8

0x6bff72d8=>0x6bff7408=>0x6bff7538=>0x6bff7668=>0x6cbf2f28=>0x6bff7798=>0x6c3f5068=>0x6c3f5198

0x6c3f52c8=>0x6c3f53f8=>0x6c3f5788=>0x6c3f5c48=>0x6c3f6108=>0x6c7f3d68=>0x6c7f3e98=>0x6c7f3fc8

0x6c7f4ba8=>0x6cbf2808=>0x6cbf32b8=>0x6d7ef888=>0x6cbf3648=>0x6cff1898=>0x6cff1af8=>0x6cff1c28

0x6cff1d58=>0x6cff1e88=>0x6cff1fb8=>0x6cff20e8=>0x6cff2218=>0x6cff2348=>0x6cff2478=>0x6cff25a8

0x6cff26d8=>0x6d3effa8=>0x6d3f00d8=>0x6d3f0208=>0x6d3f0338=>0x6d3f0598=>0x6d3f06c8=>0x6d3f07f8

0x6d3f0928=>0x6d3f0a58=>0x6d3f0b88=>0x6d3f0cb8=>0x6d3f0de8=>0x6d3f0f18=>0x6d3f1048=>0x6d3f1178

0x6d3f12a8=>0x6d7eeb78=>0x6d7eeca8=>0x6d7eedd8=>0x6d7eef08=>0x6d7ef038=>0x6d7ef168=>0x6d7ef298

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

CHAIN: 0 LOC:0x76d3bd50 HEAD: [NULL]

CHAIN: 1 LOC:0x76d3bd60 HEAD: [NULL]

CHAIN: 2 LOC:0x76d3bd70 HEAD: [0x6c7fa698,0x6c7fa698]

BH (0x6c7fa5e8) file#: 1 rdba: 0x0040fc5c(1/64604) class: 1 ba: 0x6c7a0000

set: 75 pool 3 bsz: 8192 bsi: 0 sflg: 2pwc: 14,28

dbwrid: 14 obj: 2 objn: 4 tsn: 0 afn: 1hint: f

hash: [0x76d3bd70,0x76d3bd70] lru:[0x6c7fa5a0,0x6c7fa800]

lru-flags: debug_dump moved_to_tail

ckptq: [NULL] fileq: [NULL] objq:[0x6c7fa828,0x6c7fa5c8]

st: XCURRENT md: NULL tch: 1

flags: only_sequential_access

LRBA: [0x0.0.0] LSCN: [0x0.0] HSCN:[0xffff.ffffffff] HSUB: [65535]

cr pin refcnt: 0 sh pin refcnt: 0

。。。。。。。。。。。。。。。。。。。。。。。

Ws:就是工作集,oracle把所有链表按照功能不同分为很多ws,每个ws都有一个wsid这就是工作集编号。另外还可以看到有AUXILIARY,这是在数据库初始化的时候分配buffer到该链表,然后数据库搜free

memory就在这个链表开始,把分配空间的链表内容在放到main

链表上,从而搜索空位置在auxiliary list开始,dbwr搜索dirty list从main链开始,提高了效率。我们熟知的checkpoint

queue存在于shared pool中

SQL> select* from v$sgastat where name like '%Checkpoint%';

POOL         NAME                            BYTES

-------------------------------------- ----------

sharedpool  Checkpoint queue              6159360

SQL>

另外没个链表都被latch保护,常见的就是cachebuffer lru chain。

在此先看一下v$latch视图。

Latch请求分为两类:

1.             一类为:willing-to-wait,也就是说,请求latch如果请求不到,那么先歇会,到达一定时间在去请求,直到请求到该latch。在misses字段记录了请求失败的次数,失败一次该值加1.

2.             另一类为:immedate,也就是说当进行latch请求的时候,请求道最好,如果请求不到那么程序会继续下去,immedate_misses记录了该请求失败的次数。

另外还有spin_gets,也就是说,当在willing-to-wait模式下,第一次请求latch失败,但是在之后请求都成功的次数。

Wait_time;请求latch等待的时间。单位为:微妙(inmicroseconds)

Sleeps:Number oftimes a willing-to-wait latch request resulted in a session sleeping whilewaiting for the latch,成功获取latch前sleep多少次。

好了,我们可以通过v$latch视图确认,是否buffercache存在latch竞争问题:

Eg:

SQL> setlinesize 200

SQL> r

1* selectname,gets,misses,sleeps,immediate_gets,immediate_misses,wait_time from v$latchwhere name like '%cache buffer%'

NAME                                                                   GETS     MISSES    SLEEPS IMMEDIATE_GETS IMMEDIATE_MISSES WAIT_TIME

-------------------------------------- ---------- ---------- -------------- ---------------- ----------

cache bufferslru chain                                                9863          0          0          21850                0          0

cache bufferschains                                                426674          0          0         138947                0          0

cache bufferhandles                                                   984          0          0              0                0          0

SQL>

可以看到有三个latch,一个为cachebuffer lru chain,一个为cache buffers chains另一为cache

bufferhandles;

先看第一个:

当用户进程需要读取数据到buffercache的时候,就需要扫描lru list,但是这个buffer cache是共享的,因此必须有一个latch进行保护,因此就需要锁定内存结构,防止并发修改破坏数据,对于数据库的访问,buffer的存取就需要多次方位lru

list,从而会产生cache buffer lru chain的竞争。

另外对于该latch

还有很多子latch,可以通过v$latch_children查看:

Eg:

SQL> selectname,gets,misses,sleeps,immediate_gets,immediate_misses,spin_gets,wait_timefrom v$latch_children where name like '%cache buffers lru chain%';

NAME                                                                  GETS     MISSES     SLEEPS IMMEDIATE_GETS IMMEDIATE_MISSES  SPIN_GETS WAIT_TIME

-------------------------------------- ---------- ---------- -------------- ---------------- --------------------

cache bufferslru chain                                                  0          0          0              0                0          0          0

cache bufferslru chain                                                 12          0          0              3                0          0          0

cache bufferslru chain                                                  0          0          0              0                0          0          0

cache bufferslru chain                                                 12          0          0              3                0          0          0

cache bufferslru chain                                                  0          0          0              0                0          0          0

cache bufferslru chain                                                 12          0          0              3                0          0          0

cache bufferslru chain                                                  0          0          0              0                0          0          0

cache bufferslru chain                                                  12          0          0              3                0          0          0

cache bufferslru chain                                                  0          0          0              0                0          0          0

cache bufferslru chain                                                 12          0          0              3                0          0          0

cache bufferslru chain                                                  0          0          0              0                0          0          0

对于子latch的数量受一个隐含参数控制:

Eg:

SQL>@getpar.sql

Enter value forpar: block_lru_latches

KSPPINM                                           KSPPSTVL             KSPPDESC

---------------------------------- ------------------------

_db_block_lru_latches                              240                  number of lru latches

SQL>

对于,这种竞争我们采用如下办法解决:

1)  修改buffercache大小,减小物理读的次数

2)  调整_db_block_lru_latches的个数,增加latch个数

3)  优化sql语句减少读取lrulist的次数

4)设置oracle多缓冲池技术,一个是recycle池另一个是keep池,以此来减少数据老化和全表扫描对default buffer 的压力。

你可能感兴趣的:(lru,oracle)