DBAplus社群 | 2016-04-14 20:31html
1概述算法
Oracle发展这么多年,提供了多种的内存管理方式,从最先SGA、PGA手工管理,到9I版本出现的PGA的自动管理,到10G版本出现的SGA自动管理(ASMM),再到11G版本出现的memory自动管理(AMM),Oracle基本是在朝着智能化、傻瓜化、自动化的方向稳步前进着,对于初学Oracle的DBA来讲,看到这些不一样的内存管理方式必定内心有着不一样程度的疑惑,例如:数据库
Oracle有这么多内存分配的管理方式,我该使用哪种?是使用11G版本推出的AMM管理方式,仍是使用10G版本出现的ASMM管理方式?或者干脆使用最旧的手工方式管理内存?缓存
我该为个人实例SGA,PGA分别设置多大呢?安全
我该为buffer cache,shared pool分配多大的内存空间?服务器
什么状况下我该使用大页?为何大页这个词最近几年这么容易听到?微信
有没有一些简单粗暴的算法来搞定这一切?session
写这篇文章的初衷也来源于上面这些很是正常的疑问,若是这篇文章能给有这些疑惑的DBA朋友一些指导和帮助,那肉丝我也就真的功莫大焉了。多线程
2Memory构成架构
在一个运行着Oracle数据库的专用服务器上,内存基本上被如下内容所占用:
Kernel Memory
OS Page Table
文件系统Cache
SGA
PGA
Oracle进程
其余进程(RMAN,非Oracle的进程等等)
严格来讲OS Page Table也算是Kernel Memory部分的内容,因为本文后面会重点讲大页的内容,所以把OS Page Table这部分在图中独立了出来,以引发读者注意。必需要强调,Oracle不该该使用掉主机上的全部内存,过量的内存分配会诱发操做系统SWAP的产生,致使Oracle性能严重下降,在RAC环境下,内存不足还很是容易致使RAC节点的驱逐。对于Oracle两大块内存:SGA和PGA,DBA必定要仔细根据系统特色、业务使用特色作好规划和设计,以防出现OS内存不够用的状况。
3内存自动化发展历程
咱们首先了解一下Oracle内存发展的历程,基本上Oracle的内存管理在版本的演进过程当中沿着愈来愈智能化、自动化、傻瓜化的方向前进。接触过MYSQL等数据库的DBA朋友应该比较清楚,这些数据库基本上都还须要DBA去决定每一个内存组件的大小,而Oracle已经从9I版本开始就迈向智能化、自动化的过程了。下图是Oracle内存管理的一个演进图:
4PGA 自动管理
Oracle是多进程的架构,这点区别于MYSQL,MYSQL是单进程多线程的架构,Oracle会为每个用户链接建立一个独立的操做系统进程来为用户提供服务,这个进程叫作服务器进程或者影子进程,它像是用户的一个代理,来操做数据文件或者SGA内存,因为服务器进程的代码是Oracle公司开发的,因此Oracle公司彻底相信这些进程或代码是安全的,所以这些进程能够直接操做数据文件和SGA内存,这些进程接受用户进程发送的指令,并完成相关的操做,并根据须要来给用户进程返回结果。
因为服务器进程是操做系统上的一个进程,所以它自己须要占用一些操做系统内存,除此以外,进程在对数据进行读取、排序、hash过程当中,也会占用必定量的内存,在Oracle 9I版本以前,对于服务器进程的内存管理是由一些参数去控制的,如下参数表明每个服务器进程可使用的不一样区域的内存大小(都是进程的私有内存区域):
SORT_AREA_SIZE
HASH_AREA_SIZE
BITMAP_MERGE_AREA_SIZE
CREATE_BITMAP_AREA_SIZE
例如,SORT_AREA_SIZE控制了每个进程可用的排序区大小,HASH_AREA_SIZE参数控制了每个进程可用的hash区大小,这些参数都有默认值,可是默认值是否合适,须要打上一个大大的问号,由于不一样的任务对于PGA内存的不一样区域有不一样的要求,例如,若是是作排序操做,就对排序区内存要求较大,而对hash区没任何的要求。固然若是默认值不合适,DBA能够手工调整这些区域的大小。
Oracle 9I版本出现了PGA的自动管理,再也不须要像9I以前版本须要设置一系列参数来控制PGA的使用,只须要设置PGA_AGGREGATE_TARGET为一个值,就能够控制全部的服务器进程的PGA使用量,至于每一个服务器进程使用了多少排序区,hash区,都交给Oracle去控制。
通常状况下对于PGA的大量使用有以下几种操做:
hash 对于hash join操做,hash桶所占用的内存就在进程的私有PGA内存中,而不是在共享内存SGA中,若是使用PGA手工管理的话,能够经过HASH_AREA_SIZE参数来动态调整会话进行hash操做可以使用的内存量。
sort 对于排序操做,例如查询语句里的order by、建立索引的排序操做等占用的内存也在PGA中,若是使用PGA手工管理,能够经过SORT_AREA_SIZE参数动态调整会话排序操做可使用的内存量。
parallel 并行操做简直能够说是PGA内存的杀手,每个并行进程都能使用到最多2G的PGA内存,固然Oracle会确保全部的并行slave使用的PGA内存不能超过PGA_AGGREGATE_TARGET的一半。
如今Oracle的版本已经出到了12C,PGA的自动管理已经发展了不少个年头,若是是我的,也应该是一个很是成熟的小伙子了,甚至是位大叔了,绝大部分数据库操做彻底不必再去手工调整PGA的一些参数。
不过,咱们依然能从互联网上、论坛上看到有不少DBA对这种手工调整PGA的技术崇拜有加(我之前也是),确实在一些状况下,经过手工调整PGA的相关内存区,能够达到加速排序等一些操做的目的,可是若是须要操做的数据量很是的大,那这种调整每每是费时费力,甚至是徒劳的,由于对于一个进程的私有PGA内存来讲,像sort,hash等P区域的内存分配是有限制的,如今11GR2的版本对于每一个进程的PGA内存最大限制默认是2个G,且排序区可使用的只有1个G,若是你的排序等操做须要的内存远远不止1,2个G,那么这种优化就很是的徒劳,甚至还可能变慢(肉丝亲身遭遇过变慢的案例)。
是否使用PGA自动管理由参数WORKAREA_SIZE_POLICY控制,它的值能够为auto和manual,顾名思义,auto为PGA自动管理,manual为PGA手工管理,回到9I以前的使用方式。
这里肉丝提供几个你们可能会感兴趣的隐含参数,好比我上面提到了每一个进程最大能使用的PGA不能超过2个G,经过修改隐含参数能够突破这个限制。>肉丝在这里警惕各位,这些参数若是要在生产环境使用,请在你的数据库版本下作好测试(包括相同的OS及版本)。
如下为11GR2版本的状况,其余版本并未作测试:
_PGA_MAX_SIZE 每一个进程的PGA的最大内存大小。默认值为:2147483648,2个G,单位为B。
_SMM_MAX_SIZE 每一个进程的工做区的大小,默认值为1/2 _PGA_MAX_SIZE,1048576 ,单位KB,1GB,排序区、hash区都属于工做区的范围。64位系统下真实使用的排序区内存不能超过4GB。
_SMM_PX_MAX_SIZE 全部并行查询的SLAVE进程可以用到的PGA总量。默认值为 1/2 pga_aggregate_target,单位为KB,RAC环境下,每一个节点均可以用到这么多内存。
以上所有为动态参数,能够在session/system级别来在线修改。
上面的参数调整后,必定要设置对应的pga_aggregate_target,不然以上调整可能会不起做用,建议设置为修改后的_SMM_PX_MAX_SIZE的值的两倍。
默认状况下,每一个进程使用的排序区不能超过1G。由参数_SMM_MAX_SIZE(单位KB)控制,默认为_PGA_MAX_SIZE(单位B)的一半。例如,并行度20建立索引,总共可使用的排序区大小为20*1G=20G,可是同时还受参数_SMM_PX_MAX_SIZE的控制,全部的slave占用的内存不能超过_SMM_PX_MAX_SIZE的值(单位为KB),默认为pga_aggregate_target的一半。同时64位系统下,每一个进程可使用的排序空间不能超过4个G。因此即便把_SMM_MAX_SIZE调整大于4个G也没有用。_SMM_PX_MAX_SIZE,全部并行查询的SLAVE进程可以用到的PGA总量。每一个RAC 节点均可以用到这么多,限制的是本节点全部并行slave可以消耗的PGA。
如何为PGA_AGGREGATE_TARGET设置一个合理的值?
PGA_AGGREGATE_TARGET的设定常常是一个摸索的过程,这里给出官方的一个分配指导原则
上面公式中的TOTAL_MEM * 80%表明着Oracle可使用的全部内存为操做系统的80%,再根据不一样类型业务的特色,OLTP系统,能够在此基础上分配20%的内存给PGA,DSS分析型系统,能够给出剩余内存的50%。这个只是一个指导的意见,具体状况要具体分析。例如,你的OLTP系统上有成千上万个链接,那么你能够粗略的按照每一个进程占用10M的内存来大致的计算一下PGA须要占用的内存空间,再者,假如你的系统不但链接数很是多,并且活跃的链接数也很是的多,那么你能够按照每一个进程至少12M的内存来进行估算,更为重要的,系统中假如存在很是多的临时性的计算任务,那么要为PGA预留的内存就更多了。 例如,并行度设置为5建立索引,每一个并行进程占用的PGA内存接近1个G:
因此你在为系统规划PGA内存时不要忘了这些临时性任务须要占用的内存。他们多是很大的一块哦。
该为数据库分配多少的PGA内存,除了把链接数的多少这个指标做为一个考量因素外,还须要关注活跃链接数的多少,这是由于不少系统链接数虽然很是的多,可是去数据库里一统计发现,绝大部分的链接已经几个小时甚至几天都没活跃过了,这每每是应用程序的链接池不加以管理的结果(也多是其余缘由)。对于不活跃的链接,Oracle每一个进程的PGA占用不会太大,按照10M计算是个合理安全的值。AIX下能够大一些,按照每一个15M-20M计算。
这里再提供一种估算每一个空闲的服务器进程占用OS内存的方法。 首先经过操做系统命令free -m查看一下当前OS剩余的内存,69590M
再次查看剩余的操做系统内存,经过没建立链接以前的剩余内存减去建立完2000个链接以后的剩余内存能够估算出每一个进程占用的内存大约为(59332-44548)/ 2000=7M
读者须要牢记,减小的7M内存中,绝大部分都是进程自己占用的,只有1-2M的内存是PGA占用的。所以上面给你们推荐的值是10-12M,也就是给进程预留出一些PGA的内存来。
确认一个空闲进程占用的真正PGA内存有多大,能够经过v$process视图中PGA_ALLOC_MEM字段来得到,以下:只有1.49M。可是就像上面已经提到的,这个进程从操做系统层面看却占用了7M左右的内存。
pga_aggregate_target参数指定的值并非一个硬限制,直到Oracle 12C才提供了一个参数来强制限制PGA的使用量。若是读者不知道该为本身系统的PGA设置一个什么样的值,能够经过视图v$pgastat中的maximumPGAallocated,totalPGAallocated值做为参考,前者表明自实例启动以来最大的PGA使用峰值,后者表明当前PGA的使用量,不过这个视图最大的缺点是不能看到各个时间段的PGA整体使用状况,这里肉丝给你们提供一个更好的视图来做为参考vsysmetric_history
上面查询的输出表明了各个时间段的,PGA内存的使用量,结果集并无彻底列出来,读者能够根据PGA各个时间段的使用量来更加精准的去为本身系统的PGA如何作设定作决策。设定PGA的过程是一个按部就班的过程。再次强调,一个进程占用的内存除了PGA以外,进程自己也会占用内存,这点上面咱们已经讨论过。
按照Oracle 2015年OOW上的一份PPT提到,12C以前版本,PGA最多可用的内存可达到PGA_AGGREGATE_TARGET设定值的三倍,这里你听一下就好了,没必要当真。
若是生产环境真的遭遇了PGA严重使用过量的状况,能够经过Event 10261 来限制某个/全部进程PGA的使用,level后面值的单位为KB。
一旦进程超出PGA的设定配额,会被后台进程杀掉并报错,不一样的版本可能报错的信息不同:
For 11.2.0.4 and 12.1.0.1+, ORA-10260
For 11.1 - 11.2.0.3, ORA-600 [723]
12C PGA_AGGREGATE_LIMIT
12C以前的版本对于PGA的使用限制并无一个硬限制,这个可能会致使一些问题,好比不加以限制后可能会致使OS SWAP的问题,一旦出现SWAP会致使Oracle性能的急剧降低,甚至致使DOWN机,我曾经遭遇过的一个案例是出现SWAP后,LGWR进程自己的内存出现了SWAP,数据库系统的表现是几乎彻底HANG死,最后没办法只能重启解决问题。
对于这个新特性的使用是经过参数PGA_AGGREGATE_LIMIT来限制PGA的使用上线,它是一个推导参数,在使用ASMM状况下,取如下的最大值
2GB
200% PGA_AGGREGATE_TARGET
3MB* PROCESSES
在使用AMM状况下,肉丝还未找到PGA_AGGREGATE_LIMIT取值的规律,若是你知道,请告诉我哦。
5MSMM
10G前SGA的管理是经过手工设置一系列的参数来实现的,例如重要的参数有如下几个:
buffer_cache_size
shared_pool_size
large_pool_size
stream_pool_size
log_buffer
SGA是一大块内存的统称,由上面列出的组件组成,10G以前的版本,DBA须要对SGA的各个内存区域进行手工设置,这可能对一个DBA无形中要求变得很是的高,须要了解业务,了解热点数据量,了解SQL的使用方式,是否存在大量不一样文本的SQL等等来决策来给每一个区域分配多少内存。使用过这个版本的DBA基本都遭遇过一个经典的报错:ORA-04031,通常是因为shared pool内存不够致使,这个不够的缘由可能有不少,共享池内存的严重碎片化,大量的硬解析,巨大的PL/SQL文本等等均可能会致使这个问题。下面咱们来看下,手工管理SGA状况下,如何考虑为buffer cache和shared pool这两个最重要的内存组件分配内存。
Buffer Cache
Buffer Cache俗称数据块高速缓存,是用来缓存数据块的拷贝的,Oracle经过改进后的LRU算法以期待这些数据块后续被高效的重用。服务器进程从磁盘读入的数据就放在这块内存中,修改数据时,也是在这个区域对数据进行修改。并无一个给buffer cache分配内存的黄金法则,仍是要根据操做系统的内存大小,业务的热点数据量、业务的类型等因素来决定给buffer cache分配多大的内存大小。咱们先看下如何决定整个SGA的大小,对于SGA的分配原则,官方建议以下:
上面的公式格式跟PGA的公式大同小异,刨去20%内存给操做系统以后,分为了避免同的系统类型,基本上是OLTP系统,大部分的内存给buffer cache,DSS类的系统,buffer cache没那么重要,能够给到50%甚至更低。 至于SGA中多少能够分配给buffer_cache,要看实际状况。DBA能够经过查看buffer cache的命中率来粗略了解是否给buffer cache分配了足够的内存。可是熟悉个人朋友都知道,我是OWI方法论的践行者,对于命中率的崇拜在Oracle里已然不该该再存在,可是命中率做为一种性能诊断的辅助手段依然具备它的价值。若是系统的SQL都足够优化后,命中率不高,必定程度上意味着可能buffer cache给小了或者你的业务访问的数据很是的离散,热点数量太少。
这里肉丝给出的优化思路是自顶向下,命中率低是一个表象,最上层的应用是否是调用了大量不须要调用的SQL,这些SQL是否是缺乏索引,SQL都足够优化后,DBA是否是考虑加大buffer cache来提高性能,加大以后仍是不行,是否是要考虑增长系统内存来进一步提升buffer cache的大小,最后是否是须要为数据库多加几个盘或者使用SSD来提升性能。
采用自顶向下的分析方法有利于真正发现问题所在并且以最低的代价解决问题,若是仅仅是一个SQL因为缺乏索引而致使整个数据库系统缓慢,DBA直接就去加盘扩容IO,那么最终会发现花费了这么大的代价,治标不治本,问题依然没有解决。上面给出的公式并不适用于全部状况,特别是OLTP系统,若是进程数很是的多,那么须要进一步下降SGA占用内存的比例,以预留出更多内存给PGA使用。
Shared Pool
Oracle占用量最大的两块内存除了buffer cache区就是Shared Pool的内存了,它的结构很是的复杂,并且因为要缓存SQL代码这种非标准大小的文本,常常会产生大量的碎片化内存,shared pool整体上包含了两大部分,一块是library cache区,用来缓存SQL、PL/SQL代码,保存它们的执行计划,提升SQL的解析效率,若是你的应用代码历来不使用绑定变量,那么这一块的内存对你来讲是一个很大的负担,可是Oracle里是没法关闭library cache区的,所以对于OLTP系统,请确保SQL都使用了绑定变量。第二大块区域是row cache区,用来缓存数据库的数据字典,因为保存在里面的信息是以行的形式存在,所以叫row cache。
对于这一块的内存,依据数据库中元信息(metadata)的多少而决定,若是数据库中有几十万的对象,那么这一块的内存就会占用比较大,同时表上的不少列都有直方图信息,也会致使这一区的内存占用比较大。在一个稳定的系统中,这一区域的内存基本上是静态的,Oracle中几乎没有操做会频繁修改row cache区。有个例外状况是没有cache属性的sequence,若是这种sequence调用频繁,就会触发频繁的修改sequence的属性值,进而可能会产生row cache lock的一些等待,优化的办法是为每个sequence设置足够的cache值。 >若是应用程序没有使用绑定变量,并且难以修改,能够经过设置cursor_sharing为force来尝试解决问题。
这里肉丝再讲一个亲身经历的案例,老DBA嘛,可能技能已经很少,但故事仍是有的,曾经帮一位客户解决了一个free buffer waits的案例,这个等待事件的出现通常说明buffer cache太小,或者全表扫描、写入操做比较多、写脏数据比较慢,从AWR报告看,free buffer waits排在TOP EVENT的第一名,占用的DB TIME已达到了百分之七八十,并且从awr报告中发现客户的shared pool内存占用已经达到了接近50G,而分析数据库一个月以前的AWR报告,shared pool的内存只有3个G左右的大小,基本上能够认定为shared pool内存占用过大,而致使buffer cache不够用,进而出现了free buffer waits等待事件,通过跟客户沟通后知道,之前一直比较稳定,最近作过的大的变动是给数据库使用了oracle 的flahcache,经过MOS上搜索flashcache关键字最终发现,在11.2.0.4,Oracle RAC若是使用了flash cache,那么会在shared pool 中分配额外的内存存放GCS资源。多出的内存为:208 bytes * the total number of (flash) buffer blocks。由于这里提醒广大DBA朋友,若是你打算使用Oracle的FlashCache那么请为它预留出足够的shared pool内存。
7ASMM
10G 版本Oracle推出了ASMM,自动SGA管理,它的出现必定程度上帮助DBA解决了管理SGA的问题,经过设置参数sga_target为非0值来启用ASMM。可是在10GR1,包括10GR2的早期版本,ASMM还不够成熟存在比较多的BUG,致使了比较多的问题,因此当时DBA在一些核心的生产环境,仍是沿用了9I时候的手工SGA管理。自动SGA管理,再也不须要为每一个内存组件设定值,固然若是你设置sga_target的同时,设置了db_cache_size这些参数,那么db_cache_size这些参数值会做为最小值要求。
若是sga_target设置为0,memory_target也为0,则回归到传统的MSMM管理。经过使用ASMM能够很大程度上解决上面提到的ORA-04031的错误。在使用了ASMM后,去查看spfile文件,会发现多了一些双下划线打头的内存参数如__db_cache_size,这些内存参数是Oracle实例运行过程当中动态产生固化到spfile中的,若是实例运行的时间足够长,这些参数的值被固话后,至关于有了一个基于自身环境的最佳实践参数,数据库实例重启后,会沿用固化在spfile中的这些参数值。 > 11G版本即便sga_target设置为0,memory_target也设置为0,也可能会发现SGA的pool之间Granule的移动,这是11G的新Linux特性,经过参数_memory_imm_mode_without_autosga来控制。 >
Granule
ASMM技术的实现,内部是经过Granule在内存组件之间移动来实现。这里对Granule作一点解释,Oracle 10G引入的自动共享内存管理,目的是为了解决下面的问题,“我应该把db_cache_size设置为多大?我应该把shared_pool_size设置多大?那么10G之后,Oracle给出的答案是,“你不用再考虑这个问题了,我经过算法帮你搞定“。
简单来讲,就是经过比较经过增长数据块缓存减小的磁盘IO时间与经过增长共享池优化而节省的时间,经过比对,来得出是否须要在二者间来移动内存。为了让内存在db_cache_size和shared_pool_size之间高效移动,Oracle在9I版本中从新构建了SGA,也就是使用固定大小的内存块-Granule,Granule会随着操做系统、Oracle版本以及SGA大小的不一样而不一样,读者能够经过以下的SQL语句来查看当前实例的Granule的大小:
in Oracle Database 11.2.0.2 indicates that the granule size increases from 64MB to 128MB when the SGA_TARGET parameter is set to 1 byte greater than 32G, and jumps to 256MB when the SGA_TARGET parameter is set to 1 byte greater than 64G. A granule size of 32MB is possible when the SGA_TARGET was set to a value between 8G + 1 byte to 16G.
8AMM
有了PGA的自动管理,SGA的自动管理,Oracle 这个强迫症患者终于在11G这个版本推出了AMM,自动内存管理,因为使用了AMM后就不能使用大页,所以这个功能其实一直没被普遍使用,经过这个功能DBA只须要设置memory_target一个参数就能够完成整个数据库实例内存的配置,就像ASMM致使了一些双下划线隐含参数的产生,AMM一样致使了一些双下划线隐含参数的产生,例如:__pga_aggregate_target,__sga_target。
并且在11.2.0.2版本以前,DBCA建库默认就是AMM管理(有些时候Oracle胆子真的是很大),11.2.0.3之后开始DBCA建库时会检测操做系统内存大小,大于4G内存默认为ASMM,小于4G内存默认为AMM。一样若是你设置AMM后,也设置了SGA_TARGET等参数,那么这些参数会做为最小值要求。
AMM最大的问题是不能使用大页内存。关于使用大页的重要性会在本文后面部分详细介绍。 >Doc 749851.1 > > Doc 1453227.1.
11G后因为出现了AMM,若是你作DBA时间足够长,你必定遇到过下面这个错误
这个错误给人莫名其妙的感受,“MEMORY_TARGET特性不被支持”,其实不是特性不被支持,这是因为AMM使用的是操做系统的共享内存文件系统,位于/dev/shm下,若是配置的内存文件系统比较小,小于了memory_target的值就会报错,通常在Linux主流的操做系统上,这个内存共享文件系统的值是内存大小的一半,若是读者遭遇了这个问题,要不去调小memory_target的参数值,要不经过以下办法去修改这个共享内存文件系统的大小:
这里指出一点,11G ASM默认会使用AMM,官方强烈建议不要修改这个默认行为。ASM里要求MEMORY_TARGET的最小值为256M。若是设置了低于256M的值,Oracle会自动增长内存到256M。 对于ASM的发布版:11.2.0.3/11.2.0.4/12.1,Oracle强烈建议把memory_target设置为1536M,这个值被证实在绝大部分的环境里都是足够的。
使用了ASM后,数据库实例的shared_pool内存须要从新评估计算,以下公式是在正常shared pool的基础上须要额外增长的大小:
若是ASM磁盘组是external redundancy,须要在2MB基础上,每100G的空间,增长1MB。
若是ASM磁盘组是normal redundancy,须要在4MB基础上,每50G的空间,增长1MB。
若是ASM磁盘组是high redundancy,须要在6MB基础上,每33G的空间,增长1MB。
ASM & Shared Pool (ORA-4031) (文档 ID 437924.1)
9大页
对于类Linux系统,CPU必须把虚拟地址转换程物理内存地址才能真正访问内存。为了提升这个转换效率,CPU会缓存最近的虚拟内存地址和物理内存地址的映射关系,并保存在一个由CPU维护的映射表中,为了尽可能提升内存的访问速度,须要在映射表中保存尽可能多的映射关系。这个映射表在Linux中每一个进程都要持有一份,若是映射表太大,就会大大下降CPU的TLB命中率,主流的Linux操做系统,默认页的大小是4K,对于大内存来讲,这会产生很是多的page table entries,上面已经提到,Linux下页表不是共享的,每一个进程都有本身的页表,如今随便一个主机的内存都配置的是几十个G,几百个G,甚至上T,若是在上面跑Oracle不使用大页,基本上是找死,由于Oracle是多进程架构的,每个链接都是一个独占的进程,大内存+多进程+不使用大页=灾难,肉丝在8年的DBA生涯里,至少帮助不下5个客户处理过因为没有使用大页而致使的系统故障,而这5个客户都是近三四年遇到的,为何大页这个词提早个三五年并无被频繁提起,而当下,大页这个词在各类技术大会,最佳实践中成为热门词汇?
这是由于最近几年是Linux系统被大量普及应用的几年,也是大内存遍地开花的几年,并且如今一个数据库系统动不动就是几百上千个链接,这些都促成了大页被愈来愈多的被关注到。
大页的好处
咱们来看一下使用了大页的好处:
少的page table entries,减小页表内存
pin住SGA,没有page out
提升TLB命中率,减小内核cpu消耗
在没有使用大页的系统上,常常可能会发现几十上百G的页表,严重状况下,系统CPU的sys部分的消耗很是大,这些都是没使用大页的状况下的一些症状。
大页的特色/缺点
要预先分配
不够灵活,甚至须要重启主机
若是分配过多,会形成浪费,不能被其余程序使用。
大页的分配方法
经过在文件/etc/sysctl.cnf中增长vm.nr_hugepages参数来为大页设定一个合理的值,值的单位为2MB。或者经过echo 一个值到/proc/sys/vm/nr_hugepages中也能够临时性的对大页进行设定。 至于应该为大页设定多大的值,这个要根据系统SGA的配置来定,通常建议大页的总占用量大于系统上全部SGA总和+2GB。
HugePages on Oracle Linux 64-bit (文档 ID 361468.1),AIX页表共享,通常不用设置大页。
大页的原理
如下的内容是基于32位的系统,4K的内存页大小作出的计算: 1)目录表,用来存放页表的位置,共包含1024个目录entry,每一个目录entry指向一个页表位置,每一个目录entry,4b大小,目录表共4b*1024=4K大小 2)页表,用来存放物理地址页的起始地址,每一个页表entry也是4b大小,每一个页表共1024个页表entry,所以一个页表的大小也是4K,共1024个页表,所以页表的最大大小是1024*4K=4M大小 3)每一个页表entry指向的是4K的物理内存页,所以页表一共能够指向的物理内存大小为:1024(页表数)*1024(每一个页表的entry数)*4K(一个页表entry表明的页大小)=4G 4)操做系统将虚拟地址映射为物理地址时,将虚拟地址的31-22这10位用于从目录表中索引到1024个页表中的一个,将虚拟地址的12-21这10位用于从页表中索引到1024个页表entry中的一个。从这个页表entry中得到物理内存页的起始地址,而后将虚拟地址的0-12位用做4KB内存页中的偏移量,那么物理内存页起始地址加上偏移量就是进出所须要访问的物理内存地址。
因为32位操做系统不会出现4M的页表,由于一个进程不能使用到4GB的内存空间,有些空间被保留使用,好比用来作操做系统内核的内存。并且页表entry的建立出如今进程访问到一块内存的时候,而不是一开始就建立。
页表内存计算
在32位系统下,一个进程访问1GB的内存,会产生1M的页表,若是是在64位系统,将会增大到2M。 很容易推算,若是一个SGA设置为60G,有1500个Oracle用户进程,64位Linux的系统上,最大的页表占用内存为:60*2*1500/1024=175G,是的,你没看错,是175G!可是实际状况看到的页表占用可能没有这么大,打个百分之四五十的折扣,这是由于只有服务器进程访问到SGA的特定区域后,进程才须要把这一块对应的页表项加入到本身的页表中。
11.2.0.3版本
11.2.0.3版本以前,若是分配的大页数量不足,那么Oracle启动过程当中不会使用大页,转而使用小页,可是在11.2.0.3版本后,Oracle在启动时一样会尝试使用大页,若是大页的数量不够,那么会把当前配置的大页使用完,不够的部分再从小页中去获取,这一行为其实是经过Oracle的一个参数来控制USE_LARGE_PAGES,后面会对这个参数作详细解释。经过数据库实例的alert文件能够清楚的看到这一状况的发生:
Total Shared Global Region in Large Pages = 1024 MB (85%),表明只有85%的SGA被放在了大页中。RECOMMENDATION部分,建议你至少增长89个大页来让SGA彻底放到大页中。
USE_LARGE_PAGES
这个参数用来控制数据库实例启动时,对于大页内存的使用行为。有3个值在11.2.0.3版本以前,11.2.0.3版本多了一个值auto:
true 默认值,尽量使用大页,有可能有一些页在大页中,有一些在小页中,这种状况下经过操做系统命令ipcs -ma可能会看到内存分段(内存分段可能有多重状况都会致使,例如开启numa也可能会致使内存分段)
false 不使用大页
only 选项表明强制使用大页,不然没法启动
auto (11.2.0.3)在实例启动时,经过后台进程dism echo xxx > /proc/sys/vm/nr_hugepages 来尽量的使用大页
如下代码为在参数设置为auto状况下alert的输出:
能够看到启动实例过程当中,优先启动了DISM进程,经过这个进程来自动完成大页的配置。$Oracle_HOME/bin/oradism的权限也是root权限,由于若是是grid权限不能完成大页的配置echo xxx > /proc/sys/vm/nr_hugepages。
Transparent Hugepage
从RedHat6, RedHat7, OL6, OL7 SLES11 和 UEK2 kernels开始transparent hugepage被默认开启,它容许大页作动态的分配,而不是系统启动后就分配好,根据Oracle MOS DOC:1557478.1,transparent hugepage致使了不少的问题,建议将其关闭 查看是否启用了transparent hugepage cat /sys/kernel/mm/transparent_hugepage/enabled [always] never []内的值是当前启用的值,上面的输出说明启用了transparent hugepage。 能够经过 /etc/grub.conf 文件来关闭transparent hugepage。
经过增长关键字transparent_hugepage=never来说transparent hugepage关闭。 也能够经过开机启动后,echo相应的值到对应的文件来动态关闭transparent hugepage。
OS层面查看大页使用状况
cat /proc/meminfo
HugePages_Total: 43000
HugePages_Free: 29493
HugePages_Rsvd: 23550
Hugepagesize: 2048 kB
HugePages_Total为所分配的页面数目,和Hugepagesize相乘后获得所分配的内存大小。43000*2/1024大约为84GB。
HugePages_Free为历来没有被使用过的Hugepages数目。即便Oracle sga已经分配了这部份内存,可是若是没有实际写入,那么看到的仍是Free的。这是很容易误解的地方。
HugePages_Rsvd为已经被分配预留可是尚未使用的page数目。在Oracle刚刚启动时,大部份内存应该都是Reserved而且Free的,随着Oracle SGA的使用,Reserved和Free都会不断的下降。
HugePages_Free – HugePages_Rsvd 这部分是没有被使用到的内存,若是没有其余的Oracle instance,这部份内存也许永远都不会被使用到,也就是被浪费了。在该系统上有11.5GB的内存被浪费了。
10最佳实践
对于Oracle来讲,这是一个最佳实践泛滥的时代,全部的最佳实践其实都有特定的应用场景,而不是放之四海皆准,可是当今信息爆炸时代(数据库种类爆炸时代),不少DBA没有那么多的耐心去专一学习一门数据库,只是拿来主义从网上找出一些最佳实践来,无论三七二十一就用到本身的环境中(甚至是生产环境中),必定程度上来讲,崇拜最佳实践是懒惰的结果。
针对于Oracle的内存分配方式,肉丝给你们推荐在核心系统上:
1.使用手工的SGA管理,这种管理方式已经很是的成熟,可是这种方式对DBA要求较高,必定程度上须要了解业务特色。
2.若是第一种方法你感受到比较难,那么使用ASMM,可是为buffer cache,shared pool设定最小值的方式,这种方式是我很是推荐的方式。
至于AMM这种内存分配方式,因为不能使用大页,建议不要去用。
具体到内存如何分配,针对是OLTP场景,仍是OLAP场景,有着不一样的内存分配原则,即便是OLTP场景,针对进程数的多少,并发数的多少,SQL语句的特色,都会致使产生不一样的内存分配方法。做为DBA要掌握基本的Oracle内存使用原理,而后根据实际状况去根据业务自身特色分配内存。
无论是OLTP系统或者OLAP系统,通常都建议至少为操做系统预留出20%的内存空间,这些内存空间用于kernal、page table以及一些其余的进程须要,例如rman备份,文件系统缓存。这个也是Oracle官方的建议。
把这一部分的内存刨去后,针对OLTP系统,能够考虑先尝试预留出20%的内存给PGA使用,80%的内存给SGA使用。若是系统上进程数比较多,特别是同时活跃的进程数比较多,须要给PGA预留出更多的内存,能够按照每一个进程12M的PGA占用进行计算。
针对OLAP系统,刨去操做系统的预留内存后,能够考虑预留出50%的内存给PGA使用,50%的内存给SGA使用。毕竟在纯OLAP下,buffer cache其实不须要那么大的内存空间。
SGA、PGA分配好后,要考虑到是否须要为buffer cache、shared pool来手工设定一个值,就像上文已经提到过的,能够参考buffer cache 的命中率,Library Hit的命中率做为一个辅助参考.若是命中率较低,有多是内存分配的不够合理。
固然你还须要借助于像AWR报告这样的工具,根据SQL的执行计划等内容来进一步的作诊断,好比命中率低的缘由可能不是分配的buffer cache小,而是存在大量的低效的全表扫描,进而致使命中率低,这样的话,须要优化的就是SQL,而不是继续加大buffer cache。再好比,若是你发现Library cache Hit比较低,可能并非shared pool比较小,还多是系统的SQL存在大量未使用绑定变量的状况,致使硬解析太重。
优化常常是个系统工程,不能一蹴而就,特别像Oracle是一个很庞大的复杂系统,对于问题的出现,更是要仔细推敲,不能轻易的下结论。随着作DBA时间愈来愈长,你也会愈来愈懂TOM的一句话:It depends。
About Me
....................................................................................................................................................
本文来自于微信公众号转载文章,如有侵权,请联系小麦苗及时删除
ITPUB BLOG:http://blog.itpub.net/26736162
QQ:642808185 若加QQ请注明您所正在读的文章标题
【版权全部,文章容许转载,但须以连接方式注明源地址,不然追究法律责任】
....................................................................................................................................................