- Buffer Cache 我们常说的数据库高速缓存,虽然我一直不明白要冠以高速之名
- Default Pool 默认的缓冲池,大小由DB_CACHE_SIZE决定
- Keep Pool 持久的缓冲池,大小由DB_KEEP_CACHE_SIZE决定
- Non standard pool 非标准块标准池,大小由DB_nK_cache_size决定
- Recycle pool 回收池,大小由db_recycle_cache_size决定
- Shared Pool 共享池,大小由shared_pool_size决定
- Library cache 俗称的库缓存
- Row cache 行缓存,也叫字典缓存
- Java Pool java池,大小由Java_pool_size决定
- Large Pool 大池,大小由Large_pool_size决定
- Fixed SGA 固定的SGA区域,包含了Oracle内部的数据结构,一般被存放在第一个granule中
- 个别组件如shared pool、default buffer pool的大小存在最优值,但组件之间无法交换内存
- 在9i中就提供了多种内存建议(advisor),但都要求人工手动干预
- 无法适应工作负载存在变化的环境
- 往往会导致内存浪费,没有用到实处
- 若设置不当,引发著名的ORA-04031错误的可能性大大提高
- 全自动的共享内存管理
- 无需再配置每一个内存组件大小参数
- 仅使用一个参数sga_target驱动
- 有效利用所有可用的内存,极大程度上减少内存浪费
- 对比MSMM其内存管理模式:
- 更加动态
- 更加灵活
- 并具备适应性
- 易于使用
- 一定程度上增强了性能,因为内存分配更为合理了
- 当某个组件急需更多内存时可以有效提供,因此可以一定程度避免ORA-04031的发生
SQL> show parameter sga NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ lock_sga boolean FALSE pre_page_sga boolean FALSE sga_max_size big integer 2000M sga_target big integer 2000M SQL> show parameter sga_target NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ sga_target big integer 2000M SQL> alter system set statistics_level=BASIC; alter system set statistics_level=BASIC * ERROR at line 1: ORA-02097: parameter cannot be modified because specified value is invalid ORA-00830: cannot set statistics_level to BASIC with auto-tune SGA enabled如果使用了server parameter file即spfile的话,ASMM会在实例shutdown之前将当前实际的内存组件大小(Oracle认为这是最优的,但实际上可能不是)保存到spfile中,如果你使用strings命令打印过spfile的内容的可以发现一些以双下划线开头的参数,如:
G10R2.__db_cache_size=973078528 G10R2.__java_pool_size=16777216 G10R2.__large_pool_size=16777216 G10R2.__shared_pool_size=1006632960 G10R2.__streams_pool_size=67108864这些在spfile保存的组件大小会在下次启动时被沿用,以达到将已经实践得出的"最佳值"记住的目的,这样下次就不用从头再"学习"了。 在ASMM的内存交换模型中存在三类组件
- 可调优组件(tunable):可调优组件是那些大小可以随之变化且若过小仅损害少量性能。buffer cache就是一个经典的例子,cache过小的情况下应用程序仍能正常运行,但带来的代价是更多的 IO。注意可调优组件同时存在一个下限。举例来说共享池由库缓存Library cache和其他一些 subheap子堆组成,那么共享池就存在一个下限要保证至少能放下某个一个时刻并行打开的游标(open cursors)以及负担其他共享池client的运行时内存分配需求。类似的buffer cache也存在一个下限,该下限至少要大于并行被pin住的buffer的总和(虽然这部分很小)
- 不可调组件(Un-tunable):不可调组件是那些存在最小下限的内存组件,这个最小下限足够让应用程序正常运行,超过这个上限并不会带来额外的性能收益。在这类组件中large pool是一个典型。
- 固定大小组件(Fixed Size):自动调优框架之外的组件,一般为固定大小。这些组件的大小仅在手动调整时改变。例如非标准块大小的高速缓冲池
- 首先在该granule的尾部生成新的granule header
- 针对剩下的chunk判定在该granule中是否还有未使用的buffer header
- 如果有,那么将chunk中的内存转换为一个数据块。否则将之转换为一个metadata块
- 重复以2-4步骤,直到该granule被转换完
- MMAN后台进程找到一块属于buffer cache的合适granule
- MMAN将看中的granule置入quiesce列表中(Moving 1 granule from inuse to quiesce list of DEFAULT buffer cache for an immediate req)
- DBWR将负责写出置入quiesced列表中granule里面的脏buffer(dirty buffer)
- MMAN将为shared pool调用消费回调函数(consume callback),granule中free的chunk都会被shared pool消费(consume)掉,并对共享池新的内存分配可用。从这里开始该granule变成一个shared granule共享内存颗粒,注意不要认为这个时候该granule的空间全部属于共享池了,实际上有部分pin住的buffer及其Metadata(上述的buffer header和LE)的空间仍被buffer cache占用着
- 最终该granule将完整的转移给shared pool,这时此granule不再是一个shared共享的
- _enabled_shared_pool_duration:该参数控制是否启用10g中特有的shared pool duration特性,当我们设置sga_target为0时该参数为false;同时在10.2.0.5前若cursor_space_for_time设置为true时该参数也为false,不过在10.2.0.5以后cursor_space_for_time参数被废弃
- _memory_broker_shrink_heaps:若该参数设置为0那么Oracle不会去收缩shared pool或java pool,当该参数大于0,会在shrink request失败后等待该参数指定秒数时间后再次申请
- _memory_management_tracing: 该参数控制针对MMON和MMAN后台进程包括内存建议(advisor)和内存代理(Memory Broker)决议的相关trace的级别;针对ORA-04031的诊断可以设置为36,设置为8启用针对启动期间组件大小的trace,设置为23启动针对Memory Broker decision的跟踪,设置为32将转储cache resize的细节;该参数的具体级别如下:
Level | Contents |
0x01 | Enables statistics tracing |
0x02 | Enables policy tracing |
0x04 | Enables transfer of granules tracing |
0x08 | Enables startup tracing |
0x10 | Enables tuning tracing |
0x20 | Enables cache tracing |
接下来我们通过设置_memory_management_tracing隐藏参数和DUMP_TRANSFER_OPS转储来实地了解一次完整的内存转移,和不完整的内存转移。以下演示的完整trace文件可以从这里下载mman_trace、transfer_ops_dump。
SQL> alter system set "_memory_management_tracing"=63;
System altered
Operation make shared pool grow and buffer cache shrink!!!..............
以下为一个完整granule转移的过程,包括了对default buffer pool的resize操作:
AUTO SGA: Request 0xdc9c2628 after pre-processing, ret=0 /* 这里的0xdc9c2628是前台进程的addr */ AUTO SGA: IMMEDIATE, FG request 0xdc9c2628 /* 这里可以看到前台进程的Immediate立即申请 */ AUTO SGA: Receiver of memory is shared pool, size=16, state=3, flg=0 /* 此次申请的收益人是shared pool,共享池,其大小为16个granule,处于grow状态 */ AUTO SGA: Donor of memory is DEFAULT buffer cache, size=106, state=4, flg=0 /* 此处的捐献者是Default buffer cache,高速缓存,其大小为106个granule,处于shrink状态 */ AUTO SGA: Memory requested=3896, remaining=3896 /* 这里immeidate request所要求的空间是3896 bytes */ AUTO SGA: Memory received=0, minreq=3896, gransz=16777216 /* 这里没有free的granule,所以received为0,gransz为granule的大小 */ AUTO SGA: Request 0xdc9c2628 status is INACTIVE /* 因为没有空的内存颗粒,先将申请置于inactive状态 */ AUTO SGA: Init bef rsz for request 0xdc9c2628 /* 为相关申请初始化before-process大小调整 */ AUTO SGA: Set rq dc9c2628 status to PENDING /* 将request置于pending状态 */ AUTO SGA: 0xca000000 rem=3896, rcvd=16777216, 105, 16777216, 17 /* 返回起始地址为0xca000000的16M大小granule */ AUTO SGA: Returning 4 from kmgs_process for request dc9c2628 AUTO SGA: Process req dc9c2628 ret 4, 1, a AUTO SGA: Resize done for pool DEFAULT, 8192 /* 完成对default pool的resize */ AUTO SGA: Init aft rsz for request 0xdc9c2628 AUTO SGA: Request 0xdc9c2628 after processing AUTO SGA: IMMEDIATE, FG request 0x7fff917964a0 AUTO SGA: Receiver of memory is shared pool, size=17, state=0, flg=0 AUTO SGA: Donor of memory is DEFAULT buffer cache, size=105, state=0, flg=0 AUTO SGA: Memory requested=3896, remaining=0 AUTO SGA: Memory received=16777216, minreq=3896, gransz=16777216 AUTO SGA: Request 0x7fff917964a0 status is COMPLETE /* shared pool成功收到16M的granule */ AUTO SGA: activated granule 0xca000000 of shared pool以下为一个partial granule不完全内存颗粒的转移过程trace:
AUTO SGA: Request 0xdc9c2628 after pre-processing, ret=0
AUTO SGA: IMMEDIATE, FG request 0xdc9c2628
AUTO SGA: Receiver of memory is shared pool, size=82, state=3, flg=1
AUTO SGA: Donor of memory is DEFAULT buffer cache, size=36, state=4, flg=1
/* 此处的受益者仍为shared pool,而捐献者是default buffer cache */
AUTO SGA: Memory requested=4120, remaining=4120
AUTO SGA: Memory received=0, minreq=4120, gransz=16777216
AUTO SGA: Request 0xdc9c2628 status is INACTIVE
AUTO SGA: Init bef rsz for request 0xdc9c2628
AUTO SGA: Set rq dc9c2628 status to PENDING
AUTO SGA: Moving granule 0x93000000 of DEFAULT buffer cache to activate list
AUTO SGA: Moving 1 granule 0x8c000000 from inuse to quiesce list of DEFAULT buffer cache for an immediate req
/* 以上将buffer cache中起始地址为0x8c000000的granule从使用中列表inuse list,
移动到静默列表quiesce list中 */
AUTO SGA: Returning 0 from kmgs_process for request dc9c2628
AUTO SGA: Process req dc9c2628 ret 0, 1, 20a
AUTO SGA: activated granule 0x93000000 of DEFAULT buffer cache
AUTO SGA: NOT_FREE for imm req for gran 0x8c000000
/ * 等待dbwr写出0x8c000000 granule中所有的dirty buffer */
AUTO SGA: Returning 0 from kmgs_process for request dc9c2628
AUTO SGA: Process req dc9c2628 ret 0, 1, 20a
AUTO SGA: NOT_FREE for imm req for gran 0x8c000000
AUTO SGA: Returning 0 from kmgs_process for request dc9c2628
AUTO SGA: Process req dc9c2628 ret 0, 1, 20a
AUTO SGA: NOT_FREE for imm req for gran 0x8c000000
AUTO SGA: Returning 0 from kmgs_process for request dc9c2628
AUTO SGA: Process req dc9c2628 ret 0, 1, 20a
AUTO SGA: NOT_FREE for imm req for gran 0x8c000000
AUTO SGA: Returning 0 from kmgs_process for request dc9c2628
AUTO SGA: Process req dc9c2628 ret 0, 1, 20a
AUTO SGA: NOT_FREE for imm req for gran 0x8c000000
AUTO SGA: Returning 0 from kmgs_process for request dc9c2628
AUTO SGA: Process req dc9c2628 ret 0, 1, 20a
AUTO SGA: NOT_FREE for imm req for gran 0x8c000000
.........................................
AUTO SGA: Rcv shared pool consuming 8192 from 0x8c000000 in granule 0x8c000000; owner is DEFAULT buffer cache
AUTO SGA: Rcv shared pool consuming 90112 from 0x8c002000 in granule 0x8c000000; owner is DEFAULT buffer cache
AUTO SGA: Rcv shared pool consuming 24576 from 0x8c01a000 in granule 0x8c000000; owner is DEFAULT buffer cache
AUTO SGA: Rcv shared pool consuming 65536 from 0x8c022000 in granule 0x8c000000; owner is DEFAULT buffer cache
AUTO SGA: Rcv shared pool consuming 131072 from 0x8c034000 in granule 0x8c000000; owner is DEFAULT buffer cache
AUTO SGA: Rcv shared pool consuming 286720 from 0x8c056000 in granule 0x8c000000; owner is DEFAULT buffer cache
AUTO SGA: Rcv shared pool consuming 98304 from 0x8c09e000 in granule 0x8c000000; owner is DEFAULT buffer cache
AUTO SGA: Rcv shared pool consuming 106496 from 0x8c0b8000 in granule 0x8c000000; owner is DEFAULT buffer cache
.....................
/* 以上shared pool开始消费0x8c000000 granule中的chunk,
但此granule的owner暂时仍为default buffer cache */
AUTO SGA: Imm xfer 0x8c000000 from quiesce list of DEFAULT buffer cache to partial inuse list of shared pool
/* 以上将0x8c000000 granule从default buffer cache的静默列表转移到shared pool的不完整inuse list */
AUTO SGA: Returning 4 from kmgs_process for request dc9c2628
AUTO SGA: Process req dc9c2628 ret 4, 1, 20a
AUTO SGA: Init aft rsz for request 0xdc9c2628
AUTO SGA: Request 0xdc9c2628 after processing
AUTO SGA: IMMEDIATE, FG request 0x7fffe9bcd0e0
AUTO SGA: Receiver of memory is shared pool, size=83, state=0, flg=1
AUTO SGA: Donor of memory is DEFAULT buffer cache, size=35, state=0, flg=1
AUTO SGA: Memory requested=4120, remaining=0
AUTO SGA: Memory received=14934016, minreq=4120, gransz=16777216
AUTO SGA: Request 0x7fffe9bcd0e0 status is COMPLETE
/* 以上一个partial transfer完成 */
对应于以上partial transfer我们可以通过DUMP_TRANSFER_OPS来了解该0x8c000000 partial granule的实际使用情况,如:
SQL> oradebug setmypid; Statement processed. SQL> oradebug dump DUMP_TRANSFER_OPS 1; Statement processed. SQL> oradebug tracefile_name; /s01/admin/G10R2/udump/g10r2_ora_21482.trc =======================trace content============================== GRANULE SIZE is 16777216 COMPONENT NAME : shared pool Number of granules in partially inuse list (listid 4) is 23 Granule addr is 0x8c000000 Granule owner is DEFAULT buffer cache /* 该0x8c000000 granule在shared pool的partially inuse list, 但这里它的owner仍为default buffer cache */ Granule 0x8c000000 dump from owner perspective gptr = 0x8c000000, num buf hdrs = 1989, num buffers = 156, ghdr = 0x8cffe000 / * 可以看到该granule的granule header地址位于0x8cffe000, 其中共有156个buffer block,1989个buffer header */ /* 以下granule中具体的内容,实际既包含了buffer cache也有shared pool chunk */ BH:0x8cf76018 BA:(nil) st:11 flg:20000 BH:0x8cf76128 BA:(nil) st:11 flg:20000 BH:0x8cf76238 BA:(nil) st:11 flg:20000 BH:0x8cf76348 BA:(nil) st:11 flg:20000 BH:0x8cf76458 BA:(nil) st:11 flg:20000 BH:0x8cf76568 BA:(nil) st:11 flg:20000 BH:0x8cf76678 BA:(nil) st:11 flg:20000 BH:0x8cf76788 BA:(nil) st:11 flg:20000 BH:0x8cf76898 BA:(nil) st:11 flg:20000 BH:0x8cf769a8 BA:(nil) st:11 flg:20000 BH:0x8cf76ab8 BA:(nil) st:11 flg:20000 BH:0x8cf76bc8 BA:(nil) st:11 flg:20000 BH:0x8cf76cd8 BA:0x8c018000 st:1 flg:622202 ............... Address 0x8cf30000 to 0x8cf74000 not in cache Address 0x8cf74000 to 0x8d000000 in cache Granule 0x8c000000 dump from receivers perspective Dumping layout Address 0x8c000000 to 0x8c018000 in sga heap(1,3) (idx=1, dur=4) Address 0x8c018000 to 0x8c01a000 not in this pool Address 0x8c01a000 to 0x8c020000 in sga heap(1,3) (idx=1, dur=4) Address 0x8c020000 to 0x8c022000 not in this pool Address 0x8c022000 to 0x8c032000 in sga heap(1,3) (idx=1, dur=4) Address 0x8c032000 to 0x8c034000 not in this pool Address 0x8c034000 to 0x8c054000 in sga heap(1,3) (idx=1, dur=4) Address 0x8c054000 to 0x8c056000 not in this pool Address 0x8c056000 to 0x8c09c000 in sga heap(1,3) (idx=1, dur=4) Address 0x8c09c000 to 0x8c09e000 not in this pool Address 0x8c09e000 to 0x8c0b6000 in sga heap(1,3) (idx=1, dur=4) Address 0x8c0b6000 to 0x8c0b8000 not in this pool Address 0x8c0b8000 to 0x8c0d2000 in sga heap(1,3) (idx=1, dur=4)以上可以看到该granule真的是一个shared granule共享内存颗粒,其中不仅包含了部分buffer block,还包含了1号shared subpool共享池子池的durtaion为4的chunk,duration=4即execution duration;这类duration的chunk一般有着较短的生命周期,当其extent被置于quiesce list静默列表时将很有可能变得足够free。execution duration是共享池中唯一能可靠转移的,因此唯有该类duration所在的extent(一般来说一个extent占用一个granule)可以用来收缩。 以下我们列出一些有助于诊断ASMM问题的动态性能视图,仅供参考:
V$SGAINFO Displays summary information about the system global area (SGA).
V$SGA Displays size information about the SGA, including the sizes of different SGA components, the granule size, and free memory.
V$SGASTAT Displays detailed information about the SGA.
V$SGA_DYNAMIC_COMPONENTS Displays information about the dynamic SGA components. This view summarizes information based on all completed SGA resize operations since instance startup.
V$SGA_DYNAMIC_FREE_MEMORY Displays information about the amount of SGA memory available for future dynamic SGA resize operations.
V$SGA_RESIZE_OPS Displays information about the last 400 completed SGA resize operations.
V$SGA_CURRENT_RESIZE_OPS Displays information about SGA resize operations that are currently in progress. A resize operation is an enlargement or reduction of a dynamic SGA component.
V$SGA_TARGET_ADVICE Displays information that helps you tune SGA_TARGET.
近期内会写一篇介绍shared pool duration的文章,作为对这篇的补充。 待修订!!