CPU_COUNT导致的LIBRARY CACHE问题
LIBRARY CACHE闩锁等待导致了系统数分钟的HANG住,什么原因呢?请到Oracle粉丝网阅读: http://www.oraclefans.cn/forum/showtopic.jsp?rootid=18377
介绍白鳝DBA工作中的一些案例
LIBRARY CACHE闩锁等待导致了系统数分钟的HANG住,什么原因呢?请到Oracle粉丝网阅读: http://www.oraclefans.cn/forum/showtopic.jsp?rootid=18377
| EVENT 19549和从损坏的备份集中恢复数据文件 | |||
|
|||
很多客户的数据库从9i升到10g 后都出现了性能问题,有些甚至比9i时下降超过50%。后来经过分析绝大多数都是和大量SQL使用了错误的执行计划有关。为什么10g 会出现这么严重的执行计划偏差呢?在9i的时代里,我们都自己编写分析脚本来对表和索引进行分析,在使用采样比例上,大家一般都比较保守,基本上都在20%以上。而10G提供了一个令人心动的技术就是自动分析,10g 数据库由于取消了RBO优化模式,缺省的优化器模式变为了ALL_ROWS,因此对分析数据的依赖程度更高,因此Oracle自带了一个标准的分析脚本,并且定期进行分析。不过随着这种新技术的使用,问题就出现了,oracle 的自动分析脚本往往只做很少量的采样,导致大量的表的评估信息出现严重偏差。最终很多客户选择了停止自动采集作业,改为手工分析。
以前在和一些Oracle的工程师讨论这个问题的时候,大家都觉得Oracle的AUTO SAMPLE是很不错的,是Oracle官方建议的,应该不会有问题,只有少量的系统需要调整,自定义采集作业脚本。今天我在整理以前的资料的时候,发现了一份METALINK的文档,发现这里的观点和我一直坚持的观点很近似。现在拿出来和大家共享。
全文参考:
昨天有一个朋友安装CRS的时候无法找到节点: $ ./cluvfy/runcluvfy.sh stage -post hwos -n node1,node2 -verbose Performing post-checks for hardware and operating system setup Checking node reachability... Check: Node reachability from node "node1" 碰到这个问题,首先我问他hostname是否就是Node1,node2,而且这两个地址是否正确的在/etc/hosts里定义了。他回答是这些都没错,然后我问他网卡的顺序是否正确,在HP-UX下有时候私网和公网的网卡在两台服务器上的设备名不对应,也可能会出一些莫名其妙的错误。经过确认都没问题。 检查hosts文件和services文件的属性,也都没问题,world有r的权限。看样子问题不是出在这些地方。那么下面该怎么处理呢?我建议他用tusc跟踪一下,看看能有什么发现。 很快在tusc里面我们发现了疑点: stat("/usr/sbin/ping", 0x742ff5e4) .................................................................... = 0 于是我让他执行一下/usr/sbin/ping node1 -n 1 -m 3 # ping node1 -n 1 ----node1 PING Statistics---- 这下子就很明确了,估计是HP-UX的补丁没有打全,经过检查,发现GOLDQPK11i 没有打,打了补丁后,测试一下/usr/sbin/ping node1 -n 1 -m 3 这个案例主要让大家学会如何通过TUSC去做深入的诊断,如果发现问题后胡乱的从网上去找解决方案,肯定是不行的。解决问题,思路最重要。
notice: JAVA_HOME not set in the environment.
Destination Node Reachable?
------------------------------------ ------------------------
node1 no
node2 no
Result: Node reachability check failed from node "node1".
access("/usr/sbin/ping", X_OK) ........................................................................ = 0
pipe() ................................................................................................ = 9 (10)
pipe() ................................................................................................ = 11 (12)
pipe() ................................................................................................ = 13 (14)
vfork() ............................................................ (returning as child ...) ......... , 2452
execve("/tmp/2437/jre/bin/HPUXChildWrapper", 0x1923d0, 0xf5230) ....................................... [entry]
argv[0] @ 0x192410: "/tmp/2437/jre/bin/HPUXChildWrapper"
argv[1] @ 0x742ff460: "9"
argv[2] @ 0x742ff470: "12"
argv[3] @ 0x742ff480: "14"
argv[4] @ 0xffffffffc1be1140:
argv[5] @ 0x742ff038: "/usr/sbin/ping"
argv[6] @ 0x192170: "node1"
argv[7] @ 0x192188: "-n"
argv[8] @ 0x1921a0: "1"
argv[9] @ 0x1921e8: "-m"
argv[10] @ 0x192200: "3"
env[0] @ 0x77ff00f2: "_=/tmp/2437/jre/bin/java"
env[1] @ 0x77ff010b: "MANPATH=/usr/share/man/%L:/usr/share/man:/usr/contrib/man/%L:/usr/contrib/man:/usr/local/man/%L:/usr/local/man:/opt/mx/share/man:/opt/upgrade/share/man/%L:/opt/upgrade/share/man:/opt/pd/share/man/%L:/opt/pd/share/man:/opt/pd/share/man/%L:/opt/pd/share/man:/opt/pd/share/man/%L:/opt/pd/share/man:/opt/resmon/share/man:/opt/gnome/man:/opt/openssl/man:/opt/openssl/prngd/man:/opt/wbem/share/man:/opt/hparray/share/man/%L:/opt/hparray/share/man:/opt/graphics/common/man:/usr/dt/share/man:/opt/samba/man:/opt/perl/man:/opt/ignite/share/man/%L:/opt/ignite/share/man:/opt/ssh/share/man"
env[2] @ 0x77ff034e: "SHLIB_PATH=/tmp/2437/jre/lib/PA_RISC2.0:/tmp/2437/jre/lib/PA_RISC2.0/server:/tmp/2437/jre/../lib/PA_RISC2.0:/tmp/2437/lib32:/tmp/2437/srvm/lib32:"
env[3] @ 0x77ff03e0: "PATH=/usr/bin:/usr/ccs/bin:/usr/contrib/bin:/opt/hparray/bin:/opt/nettladm/bin:/opt/upgrade/bin:/opt/fcms/bin:/opt/pd/bin:/opt/resmon/bin:/opt/gnome/bin:/usr/bin/X11:/usr/contrib/bin/X11:/opt/mozilla:/opt/wbem/bin:/opt/wbem/sbin:/opt/graphics/common/bin:/usr/sbin/diag/contrib:/opt/mx/bin:/opt/perl/bin:/opt/ssh/bin:."
env[4] @ 0x77ff051e: "COLUMNS=125"
env[5] @ 0x77ff052a: "ORACLE_BASE=/home/oracle/base"
env[6] @ 0x77ff0548: "EDITOR=vi"
env[7] @ 0x77ff0552: "LOGNAME=oracle"
env[8] @ 0x77ff0561: "CV_DESTLOC=/tmp"
env[9] @ 0x77ff0571: "ERASE=^H"
env[10] @ 0x77ff057a: "CV_JDKHOME=/tmp/2437/jre"
env[11] @ 0x77ff0593: "CRS_HOME=/home/oracle/crsHome"
env[12] @ 0x77ff05b1: "SHELL=/sbin/sh"
env[13] @ 0x77ff05c0: "HOME=/home/oracle"
env[14] @ 0x77ff05d2: "LD_LIBRARY_PATH=/tmp/2437/lib:"
env[15] @ 0x77ff05f1: "TERM=vt100"
env[16] @ 0x77ff05fc: "CV_HOME=/tmp/2437"
env[17] @ 0x77ff060e: "PWD=/home/oracle"
env[18] @ 0x77ff061f: "TZ=EAT-8"
env[19] @ 0x77ff0628: "LINES=47"
env[20] @ 0xffffffffc1be0fa8:
env[21] @ 0xffffffffc1be0fd0:
发现ping没有-m选项
PING node1: 64 byte packets
64 bytes from 192.168.1.150: icmp_seq=0. time=0. ms
1 packets transmitted, 1 packets received, 0% packet loss
round-trip (ms) min/avg/max = 0/0/0
# ping node1 -n 1 -m 3
Usage: ping [-oprv] [-i address] [-t ttl] host [-n count]
ping [-oprv] [-i address] [-t ttl] host packet-size [[-n] count]
,一切都OK了,于是再安装CRS,一切正常。
办粉丝网的目的是为大家提供一个开放的平台,交流技术,交换各自手中的好的技术资料。想来粉丝网也已经足足开通了2年了,这两个目的都没有达到。
首先是交流技术,到粉丝网来的朋友往往都是为了下载资料,而并没有多少技术交流。
其次是分享资料,粉丝网上有不少资料的确不错,大家也很喜欢。不过主动把资料上传到粉丝网上的人很少。很多DBA把手头的资料看的很宝贝,藏着掖着,哪怕自己看不懂也没人愿意拿出来交流。实际上老白觉得没有必要。与其在手里放着几年也难得看上一眼,还不如把资料上传,给更多的人共享,只有大家都愿意拿出自己的资料来交流,大家才能获得更多的资料。虽然老白尽力上传资料,不过老白的收藏还是有限的,没有大家的共同互动,资料交流就是一句空话。
不管大家对老白的观点是否赞同,老白还将继续上传资料给大家共享。
一大早过来就看了看昨天晚上录制的数据,快进了半天也没看到什么特殊的东西,干脆不看了,打电话问了几个昨天晚上做账务处理的人,大家都说比较正常,除了速度比上个月更慢了一些以外,没有性能下降特别多的模块。账务处理的速度每个月都是线性下降的,所以大家都觉得很正常,并没有什么特别的地方。既然大家都没觉得什么,昨天晚上录制的东西也就懒得去看了。不过看录像的时候突然发现这台安装OMS服务器的微机速度比我那台借来的老掉牙的笔记本快多了,干脆用这台电脑工作吧,用那台电脑起码降低1/3的工作效率。
由于优化的方案基本上都确定了,剩下的事情老于他们在做细化。SQL优化的工作有老熊帮忙,我也轻松了许多。前面几批提交的3、40个SQL的优化方案也分析的差不多了,大部分都已经由张工转发给了开发商。由于昨天电脑故障,今天我主要的工作还是在现有的电脑上安装相关的工具,拷贝相关的文件。
这几天系统虽然负载很重,不过这种情况已经持续了快一年了,所有的人也都没有感觉什么不适应的地方。中午快吃午饭的时候,张工突然打电话过来,说他们那边有一个数据库出现了ORA-4030错误。由于那套系统并不在我们合同范围之内,因此张工很委婉的问我有没有时间,帮她们看看。使用张工给我的账号密码登录到了系统里。发现报错的信息是:
ORA-04030: out of process memory when trying to allocate 2097192 bytes (joxcx callheap,ioc_allocate ufree)
Current SQL statement for this session:
call CRM_OPER.oper(:1,:2)
----- PL/SQL Call Stack -----
object line object
handle number name
c000000100da8108 0 package SYS.XMLNODECOVER
c000000100dada80 381 package body SYS.XMLDOM
c000000103a1d178 77 package body CRM.CRM_OPER
看到这个错误信息,首先我查看了一下ulimit,发现ulimit设置很正常,没有可能导致故障的设置。检查物理内存的使用情况,发现物理内存还有一些空闲,虽然不是很多,不过也就300多兆。SWAP区的使用率相当高,高达98%。从这一点上可以看出,不久前系统曾经出现过十分严重的换页现象。从CALL STACK中我们可以看出,这是CRM.CRM_OPER在调用XMLDOM包的时候报错。DOM操作是十分消耗内存的,这回报错的是一次申请2M的内存空间。看到DOM操作我的第一个反应就是是不是DOM对象使用后没有释放。于是马上找到CRM_OPER的代码进行分析,有一段代码引起了我的注意:
parser := xmlparser.newParser;
xmlparser.parseBuffer(parser,operInfo);
doc := xmlparser.getDocument(parser);
xmlparser.freeParser(parser);
虽然xmlparser被释放了,而Documentation对象DOC并没有释放。Doc是一个dom对象,如果不释放,DOM对象所占的空间将会随着调用的增加而叠加,最终导致物理内存被耗尽。为了证实这个猜测,首先编写一个测试程序:
create or replace procedure oper is
parser xmlparser.Parser;
doc sys.xmldom.DOMDocument;
operInfo varchar2(2000);
i integer;
begin
operInfo:='<?xml version="1.0" standalone="yes" ?>';
operInfo:=operInfo||'<QUERY_LIST>';
operInfo:=operInfo||'<LIB NAME="areasQueries" VER="2.2.0.7.0" REP_VER="0.0" MIN_INST_VER="2.1.0.4.1" INV_LOC="Queries21/areasQueries/2.2.0.7.0/areasQueries.jar"/>';
operInfo:=operInfo||'</QUERY_LIST>';
i:=0;
parser := xmlparser.newParser;
xmlparser.parseBuffer(parser,operInfo);
doc := xmlparser.getDocument(parser);
xmlparser.freeParser(parser);
-- xmldom.freeDocument(doc);
i:=i+1;
end;
/
分别进行2次测试,第一次不执行xmldom.freDocument(doc),第二次执行该语句。通过下面的方法调用:
declare
i integer;
begin
i:=0;
loop
oper;
i:=i+1;
exit when i>100;
end loop;
end;
/
每调用一次,通过下列语句检查PGA的情况:
select value, n.name|| '('||s.statistic#||')'
from v$sesstat s , v$statname n
where s.statistic# = n.statistic#
and n.name like '%ga memory%'
and sid= <sid of problem session>;
首先进行一次调用freeDocument的测试,查看UGA和PGA的使用情况。在调用前,结果是:
-------------------------------------
142476 session uga memory(15)
207940 session uga memory max(16)
710024 session pga memory(20)
1037704 session pga memory max(21)
第一次执行后的情况:
-------------------------------------
207940 session uga memory(15)
273404 session uga memory max(16)
8165056 session pga memory(20)
8165056 session pga memory max(21)
第二次执行后的情况:
-------------------------------------
207940 session uga memory(15)
273404 session uga memory max(16)
7882672 session pga memory(20)
10734088 session pga memory max(21)
可以看出随着调用次数的增长,PGA和UGA并没有明显的增长。下面修改一下测试程序,将freeDocument的部分去掉。没执行的时候PGA情况:
-------------------------------------
77012 session uga memory(15)
142476 session uga memory max(16)
776488 session pga memory(20)
842024 session pga memory max(21)
执行第一次后的情况:
-------------------------------------
142476 session uga memory(15)
207940 session uga memory max(16)
5188024 session pga memory(20)
5253560 session pga memory max(21)
执行第二次后的情况:
-------------------------------------
142476 session uga memory(15)
207940 session uga memory max(16)
5126608 session pga memory(20)
5253560 session pga memory max(21)
通过WINDOWS任务管理器观察ORACLE进程的物理内存情况可以得出类似的结果。就是如果释放DOM对象,PGA内存不会持续增长,如果不释放DOM对象,PGA内存会越占越多。通过WINDOWS任务管理器可以看出,执行200次存储过程,ORACLE进程的内存使用增加了200M。从上述测试中可以得出结论,由于没有释放DOCUMENT对象,导致了内存泄露。我把这个结果告诉了张工,他和开发人员确认了一下,确认这个模块是昨天下午才上线的一个应用调用的,程序员也确认不释放DOCUMENT对象是错误的。
处理完这个小故障,已经是中午的12点半了。办公室里除了老于其他人都去吃饭了。我急忙锁了屏幕,和老于下楼去吃饭。中午吃饭的时候,老于一直比较沉默,我问他是不是有什么心事。他说有点想家,老于家就是锦州的,原计划这个周末回家休息一下,由于6号要做实施,这个计划只能泡汤了。做DBA的,很多象老于那样,一年到头没有多长时间能够和家里人团聚。
ORA-4030一般来说是进程从操作系统申请内存的时候,操作系统无法分配内存引起的。一般来说ORA-4030可能是几方面原因引起:操作系统无法从物理内存和SWAP区分配内存给进程,或者进程受到了操作系统的某个限制条件的约束无法分配更多内存。还有可能就是碰到了某个ORACLE的BUG。
碰到出现ORA-4030,首先我们需要检查的是操作系统的物理内存和SWAP区是否满了。如果物理内存所剩无几,并且SWAP区接近或者达到100%,那么就是真正的内存不足了。一般情况下这种现象出现的较少,大多数ORA-4030是由于进程或者操作系统参数限制引起。
如果我们发现物理内存还有很多剩余,那么下一步需要检查的是oracle账户的ulimit参数。比如:
SUN OS:
/tmp/oralog>>> ulimit -a
time(seconds) unlimited
file(blocks) unlimited
data(kbytes) unlimited
stack(kbytes) 8192
coredump(blocks) unlimited
nofiles(descriptors) 256
vmemory(kbytes) unlimited
HP-UX:
$[/oracle]ulimit -a
time(seconds) unlimited
file(blocks) unlimited
data(kbytes) 1048576
stack(kbytes) 131072
memory(kbytes) unlimited
coredump(blocks) 4194303
nofiles(descriptors) 2048
AIX:
[/home/oracle9i]#ulimit -a
time(seconds) unlimited
file(blocks) unlimited
data(kbytes) unlimited
stack(kbytes) 65536
memory(kbytes) unlimited
coredump(blocks) 2097151
nofiles(descriptors) unlimited
其中的DATA,STACK,MEMORY等参数过小都可能引起ORA-4030。一般来说这些参数建议设置为-1(unlimited)。如果ulimit参数没有问题,那么也可能是其他操作系统内核参数引起。我们可以使用下面一个程序去测试一下,一个进程能够分配到的物理内存的大小:
/* mem.c */
#include <stdio.h>
#include <errno.h>
main()
{
long int i;
i = 1;
for(;;)
{
if (!malloc(1048576))
{
printf("malloc failed with error: %u at iteration %u\n", errno,i);
exit(-1);
Permalink
No Comments
早上8点多和小齐会合后一起来到浑南的省公司。老方本来也要来,被吉林的事情绊住了。昨天晚上我和老于都没睡好,老于的眼睛红红的,我也一直打着哈欠。看样子小齐也没睡好,脸色有点白。我开玩笑的说女孩子别有太多心思,老得快。可能大家心里都有些忐忑,这个玩笑也没有达到应有的效果。我打了个电话给小孙,问他昨天模块上线的情况以及现在系统的情况。小孙告诉我,昨天晚上他们原计划上线的14个模块,最终上线了6个,其他模块领导临时决定暂时不上了。因为新版本升级后,这几个模块要大改,目前上线意义不大。小孙不会监控系统,不过从应用那边看,几个服务器的性能都不错,和昨天的感受差不多。我让小孙和下面的营业厅联系联系,看看今天的系统情况,有事立即通知我。到了会议室,张工正在安排投影,我看他的笔记本通过无线连载DCN网上,就通过张工的笔记本连到服务器上,查看了3台服务器的状态,都比昨天的指标略好一些,看来昨天上线的6个模块表现还是不错。大家看到这个情况,心里踏实多了。
孙主任临时有点事,晚了10多分钟才到了会场。之前和张工他们聊了聊目前系统的情况,他们对优化的效果都感到比较满意。张工问我系统性能提升的比例大概有多少,是不是能够超过30%的预期。我说现在还没做评估,还不好说,不过以我的经验,超过1倍应该没问题,远远高于30%的预期。孙主任一到现场首先向我们表示祝贺,他来之前也让人和几个营业厅确认过了,今天系统状态十分好,好几个常用模块都比以前快很多。
今天的会议比较正式,首先老于向甲方汇报了到目前为止所做的优化,以及达到的效果。然后开发商也汇报了应用修改的情况,按照开发商的统计,他们对我们提出的应用修改,已经100%完成修改,超过90%的模块都已经上线,剩下没上线的是从业务角度考虑,准备在下一个小版本升级的时候一起做。
由于优化目的基本达到,因此这次小结会开得比较轻松,集团公司的领导也通过电话会议参加了讨论。会上大家一致同意本次优化到此为止,不再进行下一次微调。随后就是后续的一些安排。我明天就可以回家了,老于还要再观察几天,下周也可以撤离现场。在7月1号,大家回到沈阳,进行账期数据的收集,以便于完成最终的性能评估报告。7月7日-10日进行验收。随后安排一次北方公司的性能优化研讨会,在该研讨会上,以沈阳的案例,介绍系统性能优化的方法与技术,对北方公司的DBA进行一次全面的培训。在这段时间里,我们需要初步完成系统分析报告、性能评估报告、优化方案等正式文档。
会议结束后,我和老于先下楼,老于的烟瘾又犯了,出了门马上把烟点上。小齐还在和孙主任确认一些事情,我们在楼下等他。我也向老于要了一支烟点上,绷得很紧的神经终于松弛了下来。就这样结束了,心里放下了一块石头,反而觉得空落落的。
中午和小齐一起在北站旁边的新洪记吃了顿饭。心情高兴,多喝了几杯,下午就直接和老于一起回到酒店。想着下午到中街去买点沈阳土特产。老于建议晚上去刘老根大舞台看场二人转,就住在大舞台边上,一直也没心思去看,老于这个建议马上得到了我的响应。打了个电话给酒店前台,问问能不能帮助订票。忙了半天,买了两张200块的票,原价180的,黄牛还不算黑,不过是二楼的,离舞台比较远。
下午接到了万隆的李科的电话,问我有没有时间,帮他们的系统做一个调优,经费已经申请下来了,总共十五万,他们出一半,集成商出一半,合同可以随后走流程,只要我们尽快进场做就可以了。万隆的系统问题很大,集成商在做软件开发的时候底层设计存在问题,导致每年7、8、9三个月业务高峰期的时候年年会出问题。我一年前和李科讨论过,希望大家一起坐下来,把底层的应用架构和数据字典调整好,这样就可以一劳永逸的解决问题。当时我提出的价格就是十五万,不过当时他们觉得价格太贵,没地方出这笔经费,这件事就作罢了。没想到李科还记着这个事情,而且运作出了这个项目。经过一年的运行,我估计万隆的系统比一年前更加恶化了,这个优化项目活不好干,可能成为一个吃力不讨好的项目。而且沈阳的项目刚刚结束,我也想好好休息一下,不想连续去碰硬骨头,所以这个项目我的初步想法就是推掉。不过李科一副死缠烂打的架势,搞得我也不好彻底推掉,只是说先给我开个VPN,我先安排人上去看看,了解一下我们能不能搞定再做决定。
放下电话后,和南京的阿罗联系了一下,让他有空VPN上去看看系统的情况。我再三嘱咐阿罗,这个系统问题很大,我们还没决定是不是要接这个项目,因此登上去后,只能看,不能动任何的东西。并且这个系统十分关键,千万不能出问题,VPN账号不要透露给公司的其他人,只有他一个人知道就行了。
嘱咐完阿罗,老于的电话就进来了,两个人一起喝了点小酒就去刘老根大舞台看二人转去了。小时候也经常听二人转,不过今天看赵本山的弟子演出的二人转,还是感到十分过瘾。演出刚开始的时候报幕员说的赵本山今天也在沈阳,如果能安排的开,会亲自表演一个节目。虽然最后由于时间错不开,赵本山只是出面打了个招呼就走了,不过看到这么一场演出,感觉200块钱花的还是很值的。
据说扬州市政府要规范扬州炒饭,并且注册知识产权,不禁想起了近20年前的一件事。那时候还在南京读大学,大概是90年吧。一次和一个广东的同学一起烟花三月下扬州,到扬州游玩。中午的时候,广州的同学一定要拉我去吃扬州炒饭,据说他老豆对扬州炒饭情有独钟,偶尔会带上他到街坊的茶餐厅点上一份扬州炒饭解馋。既然到了扬州炒饭的老家,当然要尝尝最正宗的扬州炒饭了。不过我们在大街上问了好几家小餐馆,都没有卖这道菜的。后来以为可能扬州炒饭在扬州可能属于高档酒店的美食,也就没有过多的追究了。
毕业后到了深圳,发现大街小巷几乎每个餐馆都会提供这道扬州炒饭。价格便宜,2、3块钱一份,而且量又足。在广东,扬州炒饭是工薪阶层常吃的快餐之一,基本可以和桂林米粉有一拼。有一次和一个老广东一起工作,我就又想起了在扬州没有遇到卖扬州炒饭的地方的事情,问他是否知道扬州炒饭的来源。那老兄是家住西关的老广,偏爱美食,对各种美食掌故也是了如指掌。
据他所说,扬州炒饭实际上起源于香港,大约是清末民初的时候,香港有家扬州菜馆,推出了一道通过扬州名菜三鲜锅巴改良来的锅巴菜,起名叫扬州锅巴。一经推出就风靡香港。后来大三元的一个厨师就用扬州锅巴的材料(青豆、胡萝卜、火腿)加上鸡蛋,炒制炒饭,命名为扬州炒饭,其愿意是想借扬州锅巴来宣传自制的炒饭。后来扬州炒饭就名扬省港,甚至现在连扬州都为扬州炒饭编了一个和隋炀帝下扬州的故事。
其实淮扬菜偏咸偏甜,根本做不出扬州炒饭这样的菜式,整个江浙菜系里面也根本找不到炒饭这种传统小吃。炒饭本事一种家里冷饭利用的家常做法。很多家庭都经常将冷饭热一下再吃。讲究一点的人家就放点油盐炒一下,再讲究一点的就打上一个鸡蛋。而扬州炒饭说白了就是一种豪华版本的家常炒饭,里面加上火腿、青豆、胡萝卜等,其主要用途除了增加口感外,在感官上也可以刺激食欲。
在深圳过了差不多10年的单身生活,炒饭当然也是吃了不少,街头小餐馆或者茶餐厅的扬州炒饭往往过于油腻,而且随着地沟油的出现,对这种东西也不太敢于光顾了。不过偶尔嘴馋的时候,还是会自己下厨房炒制一下。久而久之,总结出了一套炒饭的秘诀。
炒制扬州炒饭的用料可以随意,根据喜好就行了。传统的扬州炒饭必须有青豆,或萝卜和火腿丁。如果没有火腿肉,也可以用超市里那种方腿、火腿肠替代。不过如果是真的火腿,最好泡过,蒸制过,生火腿不宜炒熟,并且会带有一点腥味。也可以准备一点鲜虾仁之类的东西,不过扬州炒饭的辅料不要用口味特别重或者味道特别霸道的,选择平和一点的辅料。另外一样辅料就是葱,蒜不是必须的,不过准备少许爆香还是不错的。
扬州炒饭的主料当然是米饭,米饭最好选用硬一点的,看到网上建议使用隔夜的米饭。其实也不一定非要隔夜,把米饭放到冰箱里冰一会也能起到脱水的作用。不过从根本上来说,煮饭的时候稍微偏硬一点是关键。
炒饭的技巧也十分重要,首先热油放蒜末爆香,低油要足,然后爆炒葱及辅料。等锅里的油温再次升起来后,再放入蛋液将鸡蛋和辅料一起炒熟,盛好待用。
然后就是炒制米饭。现在人喜欢少油,因此炒米饭的时候尽量少放油,甚至可以用刚才炒辅料的剩油来炒制米饭。将锅烧热,然后再放入米饭,米饭下锅前最好用筷子拨松。如果没有放油或者油很少,米饭下锅后开小火,用锅铲将米饭拨开,瘫在锅底,慢慢加热,除去水分。
这个时候如果家里有一些浓汤,比如炖肉剩下的汤,可以放入米饭中,以增加米饭的香味。不过加入汤的时候不能一次性加入,而要一点一点的加入。加一点就翻炒一下搅拌均匀,并且除去多余的水分。米饭炒好后就可以加入辅料以及盐和鸡精,一起翻炒几下,搅拌均匀就可以出锅了。
对于米饭的处理,还有一种比较讲究的做法是米饭下锅前先将部分蛋液倒入米饭中搅拌均匀,然后再去炒制,炒出来的米饭是金黄的,卖相十分好。不过蛋液不宜太多,否则必须用较多的油,而且火候不宜把握。
扬州炒饭是单身青年的方便食品,大家有兴趣也可以试试。多做几次,就能推陈出新,发扬广大了。真的十分感谢发明扬州炒饭的那个香港厨师。
有个客户的系统中某个模块突然变得十分慢,以前每小时处理1万必业务,今天每小时只能处理1000笔业务。大量的业务堆积,使客户感到十分头痛。从V$SESSION_WAIT看,存在大量的LATCH FREE等待,从STATSPACK报告上看:
Load Profile
~~~~~~~~~~~~ Per Second Per Transaction
--------------- ---------------
Redo size: 606,513.75 10,096.93
Logical reads: 263,689.83 4,389.77
Block changes: 3,438.74 57.25
Physical reads: 817.62 13.61
Physical writes: 319.30 5.32
User calls: 9,289.06 154.64
Parses: 2,764.50 46.02
Hard parses: 334.28 5.56
Sorts: 1,460.77 24.32
Logons: 3.53 0.06
Executes: 2,808.80 46.76
Transactions: 60.07
Instance Efficiency Percentages (Target 100%)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Buffer Nowait %: 97.29 Redo NoWait %: 100.00
Buffer Hit %: 99.75 In-memory Sort %: 100.00
Library Hit %: 93.44 Soft Parse %: 87.91
Execute to Parse %: 1.58 Latch Hit %: 88.50
Parse CPU to Parse Elapsd %: 74.96 % Non-Parse CPU: 88.71
Top 5 Timed Events
~~~~~~~~~~~~~~~~~~ % Total
Event Waits Time (s) Ela Time
-------------------------------------------- ------------ ----------- --------
latch free 44,261,551 122,352 46.29
CPU time 44,436 16.81
buffer busy global CR 24,549,325 29,212 11.05
db file sequential read 2,298,542 23,234 8.79
wait list latch free 810,305 17,562 6.64
-------------------------------------------------------------
LATCH FREE等待占了46.29%。经过检查,发现是ROW CACHE OBJECTS等待十分严重。初步怀疑在某张表上,客户在前一天晚上对这张表做了一些修改。询问应用开发部门,他们都不承认做了操作。从数据库上看,并没有多大的问题。通过HANGANALYZE看:
存在大量的HANG住现象:
Found 26 objects waiting for <cnode/sid/sess_srno/proc_ptr/ospid/wait_event>
<1/270/2196/0x47a8100/1259/No Wait>
Found 10 objects waiting for <cnode/sid/sess_srno/proc_ptr/ospid/wait_event>
<1/1238/35370/0x4784820/966/latch free>
Found 14 objects waiting for <cnode/sid/sess_srno/proc_ptr/ospid/wait_event>
<1/373/3688/0x47b9ae0/2253/No Wait>
Found 11 objects waiting for <cnode/sid/sess_srno/proc_ptr/ospid/wait_event>
<1/855/23311/0x47a76c0/1253/latch free>
Cycle 1 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/754/1937/0x47add40/1310/latch free>
-- <1/905/1505/0x47ac3a0/1302/latch free>
-- <1/71/1827/0x479e220/1161/latch free>
Cycle 2 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/1238/35370/0x4784820/966/latch free>
-- <1/125/2442/0x47b8660/1720/latch free>
-- <1/905/1505/0x47ac3a0/1302/latch free>
-- <1/71/1827/0x479e220/1161/latch free>
-- <1/508/4711/0x47ae780/1329/latch free>
-- <1/855/23311/0x47a76c0/1253/latch free>
-- <1/531/2223/0x47ab440/1286/latch free>
Cycle 3 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/508/4711/0x47ae780/1329/latch free>
-- <1/855/23311/0x47a76c0/1253/latch free>
Open chains found:
Chain 1 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/238/45371/0x47b90a0/2307/global cache cr request>
-- <1/508/4711/0x47ae780/1329/latch free>
-- <1/855/23311/0x47a76c0/1253/latch free>
-- <1/531/2223/0x47ab440/1286/latch free>
-- <1/1239/12911/0x47a71a0/1249/latch free>
-- <1/562/765/0x47ae260/1335/latch free>
-- <1/33/24430/0x47ac8c0/1298/latch free>
Chain 2 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/270/2196/0x47a8100/1259/No Wait>
-- <1/562/765/0x47ae260/1335/latch free>
-- <1/33/24430/0x47ac8c0/1298/latch free>
Chain 3 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/373/3688/0x47b9ae0/2253/No Wait>
-- <1/1239/12911/0x47a71a0/1249/latch free>
-- <1/562/765/0x47ae260/1335/latch free>
-- <1/33/24430/0x47ac8c0/1298/latch free>
Chain 4 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/927/2464/0x47b67a0/2112/No Wait>
-- <1/744/287/0x46f12a0/2057/latch free>
-- <1/460/1881/0x47afc00/1344/latch free>
-- <1/71/1827/0x479e220/1161/latch free>
-- <1/508/4711/0x47ae780/1329/latch free>
-- <1/855/23311/0x47a76c0/1253/latch free>
-- <1/531/2223/0x47ab440/1286/latch free>
-- <1/1239/12911/0x47a71a0/1249/latch free>
-- <1/562/765/0x47ae260/1335/latch free>
-- <1/33/24430/0x47ac8c0/1298/latch free>
Other chains found:
Chain 5 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/2/7/0x468a060/7842/No Wait>
Chain 6 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/40/55347/0x46958e0/2392/latch free>
Chain 7 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/113/8784/0x47a9aa0/1276/enqueue>
Chain 8 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/134/24816/0x47b7c20/1711/latch free>
-- <1/614/18700/0x47ba000/2353/latch free>
Chain 9 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/135/577/0x47a9060/1280/latch free>
-- <1/1191/36393/0x4762e00/706/latch free>
Chain 10 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
经过多次HANGANALYZE看到,目前的状态主要是比较慢,并不是真正的HANG住。过一段时间做的HANGANALYZE,BLOCKER和BLOCKED是不停变化的。
由于在另外一个地方做另外一个项目的支持,所以我也没有太多的时间协助客户做详细的分析。也就没有仔细阅读STATSPACK报告。不过以我的经验,这种情况往往和应用系统的某些变化有关。询问了开发部门,他们都说没有修改过数据字典,也没有异常的操作。这种回答也给了我很大的误导,当时把重点放到了ROW CACHE OBJECTS的分析上,重点放在了共享池方面。最后证明,这是极其错误的。
基于上述分析,首先决定针对共享池进行操作。刷新共享池,系统没有任何改善。无奈之下,客户只好重启服务器,服务器重启后,状态依然。看样子肯定是应用出了问题。回过头再分析STATSPACK报告,刚才一直萦绕在心头的一个问题终于又引起了我的注意:
Instance Efficiency Percentages (Target 100%)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Buffer Nowait %: 97.29 Redo NoWait %: 100.00
Buffer Hit %: 99.75 In-memory Sort %: 100.00
Library Hit %: 93.44 Soft Parse %: 87.91
Execute to Parse %: 1.58 Latch Hit %: 88.50
Parse CPU to Parse Elapsd %: 74.96 % Non-Parse CPU: 88.71
BUFFER BUSY WAIT等待十分严重。并且buffer busy global CR等待也十分严重。客户的系统虽然是RAC,但是两个节点之间共享的数据十分少,而且共享数据基本上遵循在某个节点上写操作的,在另外一个节点上尽可能不做写操作。这种情况下,buffer busy global CR不可能存在这么大的问题。一份HANGANALYZE的信息引起了我的注意:
Chain 1 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/523/25/0x772efc0/10816/buffer busy global CR>
-- <1/601/97/0x7747f80/11045/latch free>
-- <1/832/136/0x7788080/12069/latch free>
-- <1/820/374/0x778b8e0/12055/latch free>
-- <1/837/177/0x778ec20/12144/latch free>
-- <1/705/38/0x7768f60/11419/latch free>
-- <1/611/21/0x774ada0/11075/latch free>
-- <1/760/86/0x777b8a0/11724/latch free>
-- <1/600/7/0x7747540/11041/latch free>
-- <1/520/59/0x772db40/10818/latch free>
Chain 3 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/769/286/0x7782e80/11835/buffer busy global CR>
-- <1/738/33/0x7773880/11611/latch free>
-- <1/524/5/0x772eaa0/10812/latch free>
-- <1/845/46/0x7790ae0/12204/latch free>
-- <1/820/374/0x778b8e0/12055/latch free>
-- <1/837/177/0x778ec20/12144/latch free>
-- <1/705/38/0x7768f60/11419/latch free>
-- <1/611/21/0x774ada0/11075/latch free>
-- <1/760/86/0x777b8a0/11724/latch free>
-- <1/600/7/0x7747540/11041/latch free>
-- <1/520/59/0x772db40/10818/latch free>
Chain 7 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/825/255/0x778d280/12061/buffer busy global CR>
-- <1/777/9/0x777a940/11716/latch free>
-- <1/520/59/0x772db40/10818/latch free>
Chain 8 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/831/119/0x778cd60/12122/buffer busy global CR>
-- <1/845/46/0x7790ae0/12204/latch free>
-- <1/820/374/0x778b8e0/12055/latch free>
-- <1/837/177/0x778ec20/12144/latch free>
-- <1/705/38/0x7768f60/11419/latch free>
-- <1/611/21/0x774ada0/11075/latch free>
-- <1/760/86/0x777b8a0/11724/latch free>
-- <1/600/7/0x7747540/11041/latch free>
-- <1/520/59/0x772db40/10818/latch free>
Chain 10 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/842/108/0x77900a0/12176/buffer busy global CR>
-- <1/520/59/0x772db40/10818/latch free>
Chain 11 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/846/15/0x7791520/12190/global cache cr request>
-- <1/600/7/0x7747540/11041/latch free>
-- <1/520/59/0x772db40/10818/latch free>
Chain 12 : <cnode/sid/sess_srno/proc_ptr/ospid/wait_event> :
<1/867/46/0x7794860/12346/buffer busy global CR>
-- <1/823/175/0x77861c0/12028/latch free>
-- <1/741/3/0x77742c0/11601/latch free>
-- <1/783/32/0x7781f20/11807/latch free>
-- <1/520/59/0x772db40/10818/latch free>
通过检查v$segment_statistics和V$CR_BLOCK_TRANSFER,发现有一张表的CR BLOCK TRANSFER是最活跃的,而这张表就是这个业务出问题的那张表。我再次咨询了开发部门,提出了我的疑问,并把我找到的证据发给了他们。两个小时后,系统突然恢复正常。
由于关键业务系统白天营业时间停机,主管领导一定要搞清楚具体原因。在强大的政治攻势下,开发部门终于承认,早上在另外一个节点上对这张表的200万条记录进行UPDATE。UPDATE操作特别慢,几个小时后,他们杀掉了UPDATE的进程。
数据库出现:
Fri Nov 28 09:27:00 2008
Errors in file /home/oracle9i/admin/ora9i/udump/ora9i2_ora_6615.trc:
ORA-00600: internal error code, arguments: [kkxprpic8], [], [], [], [], [], [], []
这个ORA-600错误一般出现在9.2.0.8环境,查看日志信息:
ksedmp: internal or fatal error
ORA-00600: internal error code, arguments: [kkxprpic8], [], [], [], [], [], [], []
Current SQL statement for this session:
INSERT INTO TB_RM_MIN_NBR (MIN_ID, MIN, MIN_GRP, INPUT_STAFF, INPUT_DATE, USE_STATE, USE_STAFF, USE_SITE, SERV_ID) SELECT SQ_RM_MIN_
NBR_ID.NEXTVAL, IB_MIN, PG_CDMA_RM_NEW.TRAN_MIN_TO_MINGRP(IB_MIN_GRP), 'C_GJ', C_OPER_DATE, IB_MIN_STATE, NULL, 0, IB_SERV_ID FROM M
ID_CARD_PHONE_MIN_INFO M WHERE M.C_OPER_DATE = (SELECT MAX(N.C_OPER_DATE) FROM MID_CARD_PHONE_MIN_INFO N WHERE M.IB_MIN = N.IB_MIN G
ROUP BY IB_MIN HAVING COUNT(*) >= 1)
----- PL/SQL Call Stack -----
object line object
handle number name
c00000102dd6d620 1687 package body ZQIB.PG_CDMA_RM_NEW
c00000102dd6d620 1518 package body ZQIB.PG_CDMA_RM_NEW
c00000102dd6d620 28 package body ZQIB.PG_CDMA_RM_NEW
c00000104f5a74f8 1 anonymous block
在存储过程ZQIB.PG_CDMA_RM_NEW的时候报错。通过日志查看这个存储过程的信息:
DBA这个圈子比较保守,一般不愿意把自己的独门绝技传人。而我们做服务一直用一种开放的心态,对客户的要求有求必应。记得有一次给客户做一个巡检,结束后我把文档拷贝在U盘上交给客户,客户犹豫了半天,问我,你的那些脚本能不能留给我。我说在U盘里已经有这些脚本了,我们做完巡检,会把巡检过程全部记录日志,并且会把使用过的脚本全部提交给客户。
和江苏电信合作3年多了,一直和他们比较融洽,主要的原因就是我们从来不保守,客户需要什么资料我们会原封不动的提供。客户咨询什么问题,我们会以很详细的报告提交。我一直要求大家写报告的时候一定要清晰明了,没必要隐瞒什么。
我经常和客户说我们的服务理念,目前客户处于A点,我们处于B点,B点高于A点,而我们做服务的一个很重要的任务是使客户的技术从A点向B点迈进,而在这个时候,我们自己在从B点向C点前进。当客户达到B点的时候我们已经达到了C点,这个时候我们就可以帮助客户从B点向C点前进,而我们也向更高的目标前进。如果是这样一种情况,我们不会害怕客户提高了我们自己就没饭吃了。对于客户而言,我们永远是有价值的,可以帮助他们象更高的目标迈进。
如果做服务的,把自己的技术保护的死死的,那早晚是会做死的。保守就很难进步,时间长了,你的价值就会越来越低。所以我觉得以开放的心态来做服务,让客户在你的帮助下提高,才是根本之道。
这篇文章是我04年写的,现在修改一下发到博客上。
经常有人问我:"我们的系统有XX内存,怎么分配内存合适?"
我的回答是"不知道"。这是一个很无奈的答案,因为这个问题确实无解。每个系统都有不同的特性,如果使用一种通用的模式去分配内存,那么肯定是无法达到目的的。优化内存配置的时候,首先需要注意一些原则性的问题,更为准确的内存分配方法,需要根据科学的评估才能做出。以下几点是笔者在实际工作中总结的内存优化的基本原则:
第一,无论如何分配内存,绝对不能让系统存在较多的换页情况,最好的选择是让系统基本不存在换页。并且随时保留足够的空闲物理内存,以应对突发的业务高峰。宁可让你的DB CACHE命中率较低,也不要为了提高DB CACHE的命中率而过多的使用物理内存,导致物理内存换页。
第二,使用文件系统并不能给ORACLE数据库的IO性能带来好处,因此尽量使用裸设备,如果使用裸设备,SGA和PGA使用内存的总量可以高达70%,甚至更高,但是SGA、PGA、Oracle后台进程、Oracle前台进程、应用进程占用内存的总量一般不要超过系统物理内存总量的90%。上述的参考值仅仅提供参考,不能机械地说SGA和PGA不能占用超过物理内存的60%或者70%,而是要根据你的系统的实际情况进行调整。如果你的系统有很大的物理内存,那么这些指标值还可以更高,只要遵循系统不产生换页操作的原则,那么哪怕你使用了95%甚至更多的物理内存,那么你的配置也是合理的。在海量内存下,如果配置了很大的SGA,那么会消耗大量的CPU资源,因此如果数据库实际不需要使用那么多内存,配置过大的SGA会导致CPU资源的浪费。因此调整SGA的同时要考虑CPU的情况,如果CPU已经出现了瓶颈,加大SGA可能会带来更大的CPU压力。切忌在解决内存问题的同时带来新的性能故障。
第三,在内存允许的情况下,设置足够大的PGA空间,尽量避免硬盘排序。硬盘排序会造成IO压力增大和相应速度大幅度下降,因此在有条件的情况下,提高内存排序比例可以提高系统的性能。如果排序操作很大,而且物理内存也有限,那么产生部分硬盘排序也是正常的。但是如果系统中存在大量的multi-pass的硬盘排序,那么就应该加大PGA空间了。
第四,在一般情况下,共享池和各个数据块缓冲池的命中率尽量保持在95%以上(OLAP应用除外)。由于每个应用都有不同的特点,命中率指标不一定能够完全表现出数据缓冲池的实际情况,但是在大多数情况下,这个命中率具有一定的代表性。如果在使用多缓冲的情况下,总体的命中率指标超过95%不能证明数据库缓冲池没有问题。通过检查DEFAULT、KEEP、NK CACHE等的命中率情况,往往能够发现在整体命中率达标的情况下,个别缓冲区性能不佳的问题。
第五、在 Oracle 9i 之前,过大的 shared pool 会导致大量的管理开销,因此不能设置过大的 shared pool(这一点其实也不是绝对的,如果CPU足够强劲的话,一个超过4G的共享池并不一定就会带来性能问题) 。 Oracle 9i 改进了共享池的管理,并且采用了 subpool 机制,使大型共享池的性能得到了很大的改善。笔者曾经在 9i 数据库上使用过超过 5G 的共享池,没有发现由于共享池过大导致�性能问题。在一些移动公司的大型BOSS系统中,超过8GB的共享池也是十分常见的,我曾经见过一个有300G内存的系统,共享池配置了10GB。另外要注意的是,如果已经使用了很大的共享池,还是出现共享池不足的问题,那么调整应用比加大共享池更为有效,另外如果由于某种原因,共享池存在碎片问题,SUBPOOL可能成为一种负面的东西,这个时候禁止使用SUBPOOL会带来好的效果。如果存在较为严重的共享池碎片,那么PX MSG POOL可能会导致经常出现共享池无法分配的情况出现,这种情况下,将PX MSG POOL在LARGE POOL中分配,可以减轻共享池不足的现象,另外减少SESSION_CACHED_CURSORS也会起到好的效果。在一般情况下,过大的共享池是不正常的。过大的共享池也会带来加大 CPU 开销等问题,因此在适当的情况下加大共享池的大小,而不要片面调大共享池,在有些情况下,将 SQL 和 PL/SQL 对象 PIN 到共享池中可能比扩大共享池具有更好的效果。
第六、LOG BUFFER是一个环状的BUFFER,用于将SERVER进程中的REDO LOG信息写入REDO LOG BUFFER中,以便于LGWR将BUFFER的数据写入REDO LOG文件。对于log buffer的设置,过大的log buffer不能改善REDO LOG的性能。一般来说LOG BUFFER的大小在几百K到几兆之间。Oracle 9i的安装指南建议LOG BUFFER的大小是128K*CPU的数量。对于REDO LOG产生量特别大的系统,可以使用这个建议值的数倍。对于一些类似电信计费账务系统的REDO 产生量很大的系统,设置超过10M甚至30M的LOG BUFFER,可能对REDO的性能有帮助。判断LOG BUFFER是否存在性能问题,闩锁REDO SPACE ALLOCATION会存在一定的争用,另外统计值redo log space requests也会出现异常。对于LOG_BUFFER,还有一个最为常见的误区就是超过3M的LOG BUFFER是没有意义的。这个错误的论断出自于LOG BUFFER刷入LOG FILE的规则,其中一个是LOG BUFFER的数据超过1M,就会触发LGWR写,另外就是LOG BUFFER超过1/3就会触发LGWR写。这里就很容易产生一个错误的论断,就是反正超过1M的LOG BUFFER数据就会触发LGWR写,那么超过3M的LOG BUFFER就没有意义了。这个论断忽视了一个问题,就是LOG BUFFER是环状的,在LGWR想LOG FILE中写入数据的时候,LOG BUFFER的尾部还是可以写入REDO 数据的,因此大的LOG BUFFER在某些场合还是有意义的。
第七、一般来说,多数据缓冲池的使用会对系统的性能提高有益。由于缓冲池采用HASH链的方式进行管理,因此对于数据缓冲池很大的系统,管理单个大型缓冲池的开销要远大于管理多个较小缓冲池的开销。使用KEEP池、RECYCLE池以及NK缓冲池可以分散数据的分布,减少由于各种竞争带来的缓冲池的额外开销。
第八、通过工作缓冲(通过*_area_size参数设置)来减少SQL执行过程中使用临时表空间,可以提高SQL的响应速度,减少系统IO。如果是Oracle 9i以前的版本,通过设置合理的工作缓冲区参数,可以实现上述目标。在Oracle 9i以后的版本,可以通过PGA自动管理来管理这些缓冲区, PGA自动管理可以大大提高各种工作缓冲区的使用率,在最小程度占用系统物理内存的情况下,提高各类工作缓冲区的使用率。
第九、LARGE POOL是和SHARED POOL类似的缓冲池,不过只有特定的BUFFER才会在LARGE POOL里分配。第一种情况,在SHARED SERVER模式(旧版本称为MTS)下,UGA空间是从LARGE POOL中分配的;第二种情况,作为顺序文件IO的缓冲区,最典型的就是RMAN备份的时候分配LARGE POOL作为缓冲区,另外从ORACLE 8I开始,如果PARALLEL_AUTOMATIC_TUNING设置为TRUE,那么并行操作的缓冲区也从LARGE POOL里分配。如果没有使用SHARED SERVER,那么系统对LARGE POOL的使用量是很小的,保持50-80M的LARGE POOL就足够了
第十、JAVA POOL是另外一个缓冲池,主要是为ORACLE JVM提供缓冲。如果应用软件很少使用JAVA的存储过程等,那么JAVA POOL不需要设置很大。
第十一、过大的数据块缓冲会导致大量的BUFFER GET扫描,增加CPU的开销。同时维护大量的缓冲池也会带来额外的CPU开销。同样,过大的共享池会导致共享池管理开销的增大。因此片面追求提高命中率的做法是不足取的。按需分配各种缓冲区的大小,不要过度分配缓冲区是一个十分重要的原则。
第十二、9i以后支持的SGA动态调整技术可以为缓冲区动态调整提供了技术手段。DBA可以根据实际情况,随时对SGA的各种缓冲进行调整。
第十三、Oracle 10G提供了自动共享内存管理(ASMM),ASMM机制可以根据系统的状态自动调整共享内存的大小。如果系统不是很大,内存资源比较充分,而且DBA的管理水平不足的话,使用ASMM可以免除DBA这方面的维护工作,使系统保持在一个较好的运行水平上。如果系统种存在性能瓶颈,而且系统的内存资源存在竞争,那么就要慎用ASMM。
最近发的BLOG主要是从粉丝网的博客上搬过来的,我会逐渐把有价值的文章搬过来。最近比较忙,很久没有写新的案例了,请大家原谅。
前一阵子给客户处理一个故障,这个故障已经重复发生了多次,几乎半个月不到就会重现。在Metalink上开了个tar,由于很多日志缺失,Oracle方面也无法进行继续的分析。
我接到资料后,第一反应是存在BUG,但是随着我分析了几十个类似的BUG后,发现虽然在表象上很类似,但是没有一个真正吻合。通过经验,我将疑点放到了OS上,并提出了优化方案。由于日志方面的缺失,很多东西只能靠猜测。做过调整后,我在报告里提出,这个问题还没有完全定位,如果调整后2个月故障未重现,说明这次调整是成功的,但也不能说是彻底解决了这个问题。因此系统监控还要继续,开的tar也要继续跟进,也许Oracle那边会提出一些好的建议。
客户的系统是一个十分重要的系统,如果出现故障将会承受十分巨大的经济损失,还会导致大客户的流失。因此客户对我的这个结论并不放心。虽然已经过去了半个多月,故障没有重现,但是客户还是不放心,因此他们又找了一家公司协助诊断这个故障,那家公司很快给出了一个故障分析报告,在报告里,用十分肯定的口气确定了这个故障和2个BUG有关。建议客户按照BUG报告上的内容进行处理。
客户告诉我,说问题的原因找到了,北京一家公司,用了不到一天就定位了这个问题。我问他最终的结论是什么,客户就说了那2个BUG,我说你把报告给我看看,肯定有问题,因为这两个BUG我都分析过,其中一个第一时间我也怀疑是问题的根源,后来随着分析的深入被第一时间排除了。另外一个BUG在我们这个平台上根本不肯能存在,因为在我们的平台上根本没有这个模块。后来我也看了这份报告的部分章节,真是一把辛酸泪,满纸荒唐言。整个报告从格式、语气上来说都十分严谨,分析也是丝丝入扣,让人不得不信服。对于缺乏足够专业知识的客户来说,这种报告的杀伤力是巨大的,一切都是用十分肯定的口气,让人觉得十分的可信。我把报告中的疑点一点一点的和客户解释后,他觉得有种上当受骗的感觉。
无疑,那份报告在商业上是成功的,如果没有我的介入,可能这份报告会带来巨大的商业价值。而我写报告的习惯是问题的分析过程十分明晰,我会把我的观点一览无余的告诉客户,包括我无法确定的事实。对于客户来说,最希望的是听到好消息,对于坏消息,他们虽然愿意知道,但是坏消息总是会让他们的心里产生一定的阴影。但是无论如何,我的原则是让客户知道他们应该知道的,我不会隐瞒任何东西,我会把我没有把握的东西第一时间让客户知道,是或者不是或者可能是,我绝对不会乱用词汇,我想这也是一个DBA应有的道德。商业利益是应该建立在一定的道义基础上的,不能为了商业利益而采用欺骗的手段,让客户蒙受更大的损失。因为在第三方服务市场,客户最大的担心就是第三方的服务水平和服务能力。欺骗可以短期内获得商业价值,但是从长期来看,这种方式会导致客户对第三方服务失去信心,从而危及整个行业。我曾经代表原厂去为客户做过一次巡检。巡检结束后,给客户提出了一份详细的报告,客户看了以后告诉我,以前他们是第三方做的服务,做巡检后也发现不了什么问题,比较而言,原厂虽然贵一点,但是更有价值,他们今后将会选择原厂服务。听到这话我感觉很不是滋味,不到位的服务不仅仅意味着丢失一个客户,还可能丢失一个正在兴起的市场。和原厂相比,第三方服务有很多先天的不足,需要用我们更加到位的服务,才能在这个市场中获得一定的份额。
那个问题虽然我已经有了9成把握,但是由于大量的日志缺失,我确实无法100%定位问题,那么如果我在报告里不把疑问列出来,客户可能很放心的放松警惕,放弃了继续的系统进行监控,那么下一次故障发生的时候,客户失去了一次定位问题的机会,遭受更大的损失。
客户的一个9207 RAC因为ora-4031导致了宕机。分析4031问题,如果是事后,那么TRACE文件是最好的分析工具,我们来看4031 TRACE里各种对象的情况:
===============================
Memory Utilization of Subpool 1
===============================
Allocation Name Size
_________________________ __________
"free memory " 32773512
"miscellaneous " 15862600
"partitioning i " 0
"sim trace entries " 245760
"gcs resources " 21925568
"PL/SQL DIANA " 401496
"trigger defini " 0
"KQR M PO " 49688
"krvxrr " 253056
"trigger inform " 0
"FileOpenBlock " 6028960
"transaction " 470104
"fixed allocation callback" 376
"replication session stats" 269040
"ges enqueues " 4222088
"KGK heap " 552
"trigger source " 0
"PL/SQL MPCODE " 26448
"errors " 0
"pl/sql source " 0
"sim memory hea " 515944
"ges resources " 85367744
"dictionary cache " 1071104
"PL/SQL PPCODE " 0
"Temporary Tables State Ob" 209968
"parameters " 0
"db_block_hash_buckets " 3924384
"library cache " 2541616
"db_handles " 928000
"sql area " 157400
"sessions " 597584
"KGLS heap " 80272
"gcs shadows " 2519272
"branch " 316616
"event statistics per sess" 2507024
"Checkpoint queue " 1283200
"table definiti " 0
"partitioning d " 0
===============================
Memory Utilization of Subpool 2
===============================
Allocation Name Size
_________________________ __________
"free memory " 33796496
"miscellaneous " 17424112
"KGLS heap " 134008
"transaction " 405408
"trigger defini " 0
"errors " 0
"ges enqueues " 4138672
"PL/SQL MPCODE " 0
"Checkpoint queue " 1283200
"ksm_file2sga region " 370496
"KCL name table " 1471944
"PL/SQL DIANA " 0
"gcs resources " 5824744
"KCL extra lock elements " 691200
"sim memory hea " 515944
"trigger inform " 648
"parameters " 0
"session param values " 1577760
"ges resources " 85415480
"partitioning d " 0
"gcs shadows " 2517168
"ges regular msg buffers " 893048
"dictionary cache " 33792
"KQR S SO " 8192
"partitioning i " 0
"KQR M PO " 210328
"trigger source " 0
"library cache " 3063304
"processes " 1056000
"sql area " 795296
"sessions " 597584
"MTTR advisory " 179472
"event statistics per sess" 2518368
"fixed allocation callback" 424
"KGK heap " 6448
"table definiti " 0
"db_block_hash_buckets " 352256
"ges resource hash table " 2490368
===============================
Memory Utilization of Subpool 3
===============================
Allocation Name Size
_________________________ __________
"free memory " 28924264
"miscellaneous " 15446808
"KQR M PO " 135704
"gcs resources " 5824744
"parameters " 0
"KGLS heap " 16456
"ges big msg buffers " 3835688
"Checkpoint queue " 1283200
"trigger defini " 0
"PLS non-lib hp " 2088
"ges resources " 72820856
"KQR L PO " 131176
"PL/SQL MPCODE " 37392
"joxs heap init " 4240
"enqueue " 1646960
"gcs shadows " 18621616
"MTTR advisory " 149216
"KSXR receive buffers " 1034000
"table definiti " 0
"ges process array " 1057320
"trigger source " 0
"sim memory hea " 520184
"dictionary cache " 1065728
"db_block_hash_buckets " 3924400
"partitioning i " 0
"1M buffer " 1049600
"PL/SQL DIANA " 0
"library cache " 2219312
"partitioning d " 0
"sql area " 128528
"trigger inform " 0
"sessions " 600288
"event statistics per sess" 2507024
"ges enqueues " 4264344
"PL/SQL PPCODE " 0
"errors " 0
"fixed allocation callback" 336
"ktlbk state objects " 521528
===============================
Memory Utilization of Subpool 4
===============================
Allocation Name Size
_________________________ __________
"free memory " 35164632
"miscellaneous " 16038016
"fixed allocation callback" 376
"partitioning i " 0
"table definiti " 224
"KGLS heap " 197648
"KQR L PO " 343440
"gcs resources " 5822416
"PL/SQL MPCODE " 2488
"PX subheap " 41008
"ges reserved msg buffers " 2096008
"gcs resource hash table " 524288
"PL/SQL PPCODE " 0
"transaction " 404520
"gcs shadows " 2519272
"partitioning d " 0
"trigger inform " 0
"1M buffer " 1049600
"message pool freequeue " 324464
"KSXR pending messages que" 853952
"PL/SQL SOURCE " 0
"ges enqueues " 4100120
"dictionary cache " 2103808
"ges resources " 85545768
"enqueue resources " 535104
"trigger defini " 0
"errors " 0
"library cache " 3616560
"PL/SQL DIANA " 44672
"sql area " 691424
"sessions " 597584
"KQR M PO " 28232
"event statistics per sess" 2507024
"parameters " 0
"DML lock " 820368
"sim memory hea " 515944
"Checkpoint queue " 1283200
"trigger source " 0
服务器有16个CPU,因此共享池被分为4个子池。每个子池128M。从上面看,当时的空闲空间超过100M。在分配一个2268字节的对象的时候报错。说明共享池的碎片化十分严重。什么导致共享池的碎片呢?我们注意到一个对象:ges resources,在每个子池中总计超过300M。大多数共享池空间都被GES RESOURCES占用了。而GES RESOURCE是可以动态扩展的PERMENT OBJECT,每个资源占用484个字节。在RAC环境中,由于GES RESOURCE的大量动态扩展,会导致共享池中碎片大规模出现,最终导致系统不可用。在这个案例中,处理这个问题的方法很多,最简单的情况,是内存充足的情况下,直接加大共享池的大小就可以解决问题了。如果要找到GES RESOURCES为何如此巨大的原因,要复杂的多,要配合应用一起来分析。这里就不做讨论了。