ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 探索系列——神人steve adams之著oracle8i interal service(十八)

探索系列——神人steve adams之著oracle8i interal service(十八)

原创 Linux操作系统 作者:wisdomone1 时间:2010-05-10 09:43:38 0 删除 编辑
内存
       

      好多性能问题皆与内存分配有关.oracle动态管理它的内存组件使得问题更为复杂多变.为了有效调节oracle,应该理解
内存的用途(用于什么)及如何管理这些内存.


sga
      sga连同基本的后台进程,就是一个oracle实例.从全局层次上来讲,它包含全局变量和数据结构,它从某种层次来讲,就是一个系统局域,包含可以被整个oracle实例访问的数据结构,而不仅仅是针对某个特定的进程.


sga areas
      sga包括4或5个主要的区域
         the fixed area 固定区域
         the variable area 可变区域或动态区域
         the database block buffers
         the log buffer
         the instance lock database(for parallel server instances)
如果从内存占用尺寸来讲,固定区域与log buffer就是微不足道或可以忽略掉



the fixed area
       包括数以千计的原子型变量,微小或细小的数据结构如:latches和指向sga其它区域的指针变量.这些变量的内容可以查询x$kxmfsv,得到它们的数据类型,大小,内存地址.这些变量含义很模糊,很少有人知道它们.
但是oracle资深员工通过联结x$ksmfsv和x$ksmmem得到高级诊断信息,可以监控这些变量的值,用来调查它们指向的数据结构内容.x$ksmmem对于sga每个内存地址有一条记录,同时它的很个非键列显示内存地址的内容.

固定区域的每个组件大小是固定的.也就是讲,它们不依赖于任何初始化参数的设定,或者其它的一些配置.所以对于每个变量的固定sga的偏移量是固定的,从而它的总体的大小也是固定的.


the variable area
       由large pool和共享池组成.大池所有内存是动态分配,然而共享池包含动态分配的内存和固定的内存.shared_pool_size实际上指定用于动态分配的共享池的近似大小,而非共享池本身的大小.共享池的固定内存部分包含,
一系列的数据结构如:buffer headers,进程,会话,事务队列,入队资源和锁,在钱rollback segment队列,以及记录统计的各种各样的队列.
       大多数队列的大小与一个或多个初始化参数有关.这些初始化参数改变必须要重启实例方可,因此固定内存队列的大小在每个实例的生命周期内是固定的.比如,process队列大小是由processes参数配置.如果这个队列的所有slots正在使用,然后尝试
在实例中分配更多的进程会失败,因为这个队列不能动态改变大小.
       对于一些固定内存的队列,这是(或它们是)一些x$表,以一行显示或展示每个队列element,它的某些结构成员以列方式显示.这些x$表有时叫固定表.因此这儿有它们对应的v$视图,不过它们只显示x$表中最有用的一些列,但仅仅显示代表目前在用的队列slots的记录.比如,
v$process视图是以x$ksupr固定表为基础,而x$ksupr以内存中的process array进程队列为基础.v$process不包含x$ksupr所有的行与列,x$ksupr也不显示sga进程结构所有的成员.

       the variable area的大小等于large_pool_size加上shared_pool_size,加上固定内存队列的大小.固定内存队列的大小,从理论上讲,根据这些初始化参数计算出来.但是,你应该知道根据这些参数计算队列大小的公式,每种队列element的大小,队列头的大小.同时在不同版本间有所变化的,而且与os有关.
你也要认识到每一个固定内存队列是在一个内存页范围上进行分配的,为了优化内存定位(地址定位)寻址,因此一些空间没有使用.幸运的是,基本上没有必要去精确计算固定内存的大小.如果你真的想得到这些信息,你用一个dummy sid启动一个测试实例,可以度量固定内存大小,不用加载一个数据库.




the database block buffers
       在sga存储数据库的数据块的sga buffers 拷贝区域.db_block_buffers表示缓冲区的数目,每个缓冲区大小为db_block_size.这个区域仅包含缓冲区数,没有它们的控制结构.对于每个缓冲区,在sga的可变区域有一个对应的buffer header.同样,工作集头,hash chain头,它们的latches驻存于sga的可变区域.因而,
你会发现sga的可变区域,对于sga database block buffers缓冲区数每四个缓冲区,将会以1k大小而改变.







the log buffer
       它的值由log_buffer控制.但是,如果尝试给它一个值小于它的最小值(所支持平台的4倍的数据库块大小),它将会静然加大大小.如果是在支持内存保护的os下,the log buffer会由两个保护页所包括(更为准确的是,内存保护单元),为了防止让错误oracle进程破坏log buffer.但是,log buffer相对于可变区域与database block buffers,是可以忽略的.
the log buffer从内部分为好多数据块的.每个log buffer block,在sga的可变区域皆有一个8 byte的头.



the instance lock database
       在并行服务器配置中,实例锁用于在多个实例间串行化访问共享的资源.这个区域维护这个实例感兴趣的相关资源,以及需要这些资源的进程及实例,目前正在持有的锁或者这些进程和实例发起的请求.这三个队列的大小由lm_ress,lm_procs,lm_locks来控制。实例锁数据库也包含消息缓冲区和其它结构.甚至在单实例数据库中也需要这种内存区域,但是这个大小可以忽略.
当在实例启动时报告这个组成和sga大小,这个区域目前不包含在oracle中;但是,通过在svrmgrl中用oradebug ipc查看dumps会发现它的身影.



overhead
       sga最后一个细小或微小区域是共享内存成本本身.这个区域包含正在使用的共享内存segment的信息,以及它们包含的sga区域及子区域.





shared memory
        在大多os中,sga是驻存于共享内存上.为了理解共享内存segments,你需要了解内存segment,也叫虚拟内存.

virtual memory addressing 虚拟内存定址
        今天虚拟内存定位技术很为流行,导致它的替代物直接内存定址基本仅仅是一个内存.如果你曾经在z80或8086 cpus
上进行过编程,你应该还记得直接内存定址.你必须知道可用的内存地址的精确位置,因此不用引用不存在的内存否则会破坏bios.
如果你要写一个大型的程序,大于可用的内存或地址空间,你必须把它分割为不同的节,便于载入或者切换到内存中(根据需要).
事实上,初期oracle二阶段架构设计就是源于这个问题.
        虚拟内存定址在程序代码与物理内存间引入一个抽象层.在每个指令执行前,所有引用的内存会动态从虚拟内存地址翻译为或转变为
物理内存地址.os维护数据结构,叫作页表page tables,为了支持虚拟到物理内存地址转变.为了优化地址转变,在每个cpu上缓存最近使用的
页表条目,这个缓存通常叫作tlb(translation lookaside buffer).为了更进一步优化地址转化,tlb查找会在硬件中实施.一个tlb miss必须
通过在主内存引用页表解决或处理.这个操作有一些情况下也是通过硬件来实施.如果硬件地址转变失败,cpu切换为一个特定的执行上下文,用于
确保为这个虚拟页分配一个物理内存页,如果有必要,从磁盘进行刷新.这个页表条目也被拷贝到tlb中.这种硬件地址转变失败叫作page faults
页故障--否则就是一个软或次级页故障.当处理了这个次级页故障后,cpu切换回用户模式然后重新开始当前的指令.但是,当一个主要的页故障处理完
后,用cpu time服务其它的进程.
        虚拟内存定址使得程序运行,不用全部的代码或数据都驻在物理内存中.这意味着相对不太活跃的虚拟页可以暂时从物理内存中移走如有必要.
如果这些页被修改后,它们必须保存在磁盘中一个临时的存储区域,叫作一个分页文件paging file或交换空间swap space.
把一个或一系列的不活跃的内存页写到磁盘的操作叫作一个页出page out,如果当引用一些页从而这些页再次被读入内存的对应操作叫作页入page in.
paging分页是虚拟内存管理的一个方面,允许一个大型程序可以执行。典型情况在任何情况下,每个时刻只有一部分虚拟内存页处于活跃状态.一个进程
正在使用的一系列的内存页叫作它的工作集working set.
        虚拟内存定址也让程序可以在物理内存的基本上所有位置上运行.这意味着同时会有许多程序和它们的数据存在,在它们之间可以快速切换.cpu time
不会浪费,当一个进程实行磁盘i/o或者等待用户输入,或处理一个页故障时.




memory access
        大量繁重的换页活动会对性能产生极大的影响,这个会在后面讨论.但是首先,一定要认识到地址转换本身和内存访问,除了分页paging, 也会极大影响性能.
主内存访问在cpu周期内是个很expensive的操作.内存操作比cpu操作处理在硬件时钟速度方面要慢好多,在每个内存访问之后,同时在每个内存bank可以服务相同cpu(或不同cpu)发起
的另一个内存访问,这儿会有一个必需的恢复时间部分.这就是为何现在的计算机制造商花费大把心思在cpu缓存技术上了.
不仅页表条目缓存中tlb上,部分用户内存(也叫缓存记录或缓存行cache lines)也会缓存在一个通用或普通的缓存中.采用这种复杂多变的机制维护主内存和cpu缓存(也叫缓存coherency 机制)
的一致性.缓存行会尽可能保存,为了最大限度cache hits,程序代码与数据因为它们不同的位置特征,从而有显著的区别.从os层次来讲,调度法则或算法会有偏向性地为要调度的进程分配
这些进程经常根据最常使用的cpu上分配一个时间片.这样设计为了减少硬件地址转变失败的可能性和cpu cache misses,因而减少了主内存访问.

       





process memory segments
      虚拟内存定址一个好处就是,进程可以使用一个更大的虚拟内存地址空间而不管物理内存是否可用.这使得进程内存从逻辑上根据不同的用途分割为不同的segments.这些segments可能映射到不连续的虚拟内存地址,这样就允许或考虑到以后的segment增长.oracle使用下面的segment types,通常
程序分为如下几种类型:
    
   program text
       这个文本segment包括程序本身的可执行机器代码,不含动态链接共享库.文本segments正常情况标记为只读,以便它们在运行相同程序的多个进程间共享.比如,所有的oracle进程执行相同的oracle binary,虽然是以不同的方式personalities.不管一个实例中运行多少个进程,不管在同一个服务器上
运行多少个实例,在物理内存中只有仅仅一个程序文本的拷贝
  
   intialized global data
       包含编译器进行初始化时包含的一些全局数据结构,比如用于trace输出的文本字符串.初始化数据从理论上可以修改,因此在运行相同程序的多个进程间不能共享.oracle很少使用这个segment
   uninitialized global data
       通常情况下叫作bss(根据符号启动的块)segment.包含静态分配的全局数据结构,这些结构是在运行时由进程本身进行初始化.oracle是最小限度使用这些bss segment.

   data heap
       进程在运行过程中通过malloc()及sbrk()系统调用,为了给进程动态分配内存.oracle作用它用于pga(process glabal area)
   execution stack
       只要一个函数被调用时,它的参数及返回上下文return context被推入pushed into执行堆栈中.返回上下文本质上就是一系列的cpu注册值,用于描述函数调用哪个时间点上进程的准确状态.当函数调用结束时,堆栈被弹出而且上下文传会继续以便继续从这个函数调用开始执行指令.这个堆栈也会在本地
         保存一份代码块.堆栈大小和函数调用嵌套深度有关,或者递归调用,以及参数的内存需要和本地变量有关.oracle堆栈空间条件是适度的,根据它的复杂度.
   shared libraries
       它是与位置有关的执行代码(可能是多个程序执行时需要它)的集合--特别是,系统调用函数的集合.通常情况下,标记为只读,在所有相互依赖的进程间共享,包含oracle进程.在调用一个共享库之前,进程必须首先打开这个共享库文件,通过mmap()系统调用把它是映射到它的地址空间.
       替代共享库的方法就是在程序文本segment中包含必需的系统调用函数.它适用于某些不支持共享库的os,或者它的实施或完成是有问题的.在大多os中,oracle使用系统调用函数的共享库,而不仅仅用于oracle服务器代码本身.但是,java  class库编译然后动态链接为共享库.
 

   shared memory segments
       共享内存允许相关或有关系的进程在内存中协同读写公用的数据结构.每个需要定位address一个共享内存segment的进程,必须首先把这个segment attach附加到它的虚拟地址空间.正常情况是以shmat()系统调用来完成.oracle的sga使用共享内存segment



在一个进程中虚拟地址空间,这些segment的位置是和不同的os有关.
 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/9240380/viewspace-662311/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
提供针对oracle初学者及进阶的数据库培训,欢迎大家咨询: 微信: wisdomone 微信公众号: lovedb 工作经历: 中国普天 北京科蓝 北京云和恩墨 北京神州新桥

注册时间:2008-04-04

  • 博文量
    2189
  • 访问量
    12690172