没有必胜的秘籍,没有方程式遵循~~ 要赢~~只有全身心的投入!

晶晶实验二十一:一个简单4031例子的引申:

上一篇 / 下一篇  2008-03-26 07:51:47 / 个人分类:晶晶oracle实验系列

查看( 880 ) / 评论( 32 )
一个简单4031例子的引申:
w2rV"cSq-\%ap-U0 ITPUB个人空间(p.S.b`:AI9W
内存,像来是兵家必争之地。内存,像来也是一个注定要多事的地方。内存的管理,稍有不甚,即会内存泄露。就算不泄露,如果应用大量占用内存而不释放,再大也嫌少的内存将会迅速告磬。在Oracle中,常用的内存组件中,最容易出问题的,就是共享池了。共享池内存不足后,会报出一个ORA-04031错误,下面就处理这个错误方面的问题,说一下简单的例子,请ITPUB中的坛友补充。
2e)|3p7_R0 ITPUB个人空间A/x1i&DL.?s-^ c
   开发人员说在测试环境中,有一个应用运行后不久就会报出4031错误,因为是9.2.0.1的系统,我设置了如下参数:
+w \d\]0 alter system set events '4031 trace name errorstack level 3';ITPUB个人空间']H{]-x?.Akr0M
ITPUB个人空间,l wN O7a0INGf%P
又运行一遍应用。果然,运行不久后,又报出了4031错误,查看DUMP文件,报出错误的语句是:ITPUB个人空间]1Andz

R?~,H)l"A8c)^{0 select id from t3 where myid=XXXX
}-c;TExtf0 ITPUB个人空间 ^)b`4c(@3H iB.T2S
并且,在DUMP文件中发现大量select COL from TABLE where COL=1、select COL from TABLE where COL=2,直到COL=XXXX的语句,至此,这例4031错误已经真相大白,开发人员没有使用绑定变量,并且打开的游标没有关闭。打开源代码看了一下,果然有一段循环不停的打开游标、执行查询,好,错误的原因到此,水落石出。开发人员说,一开始先报了一个01000,超出游标数,他将open_cursor设为6000后,就报出了4031错误。ITPUB个人空间Hc7t'i](LQ(~

*t3U"sA S$f*W0 这是一个非常简单的例子,下面我来模拟一下:ITPUB个人空间/f0u J/ISu8q+P
步1:修改打开游标数:ITPUB个人空间N;PmXD ]j"P x+^ Z6Ql
alter system set open_cursors=5000;ITPUB个人空间%A1V#V!W}r

L5n(u"YpO1V0 步2:跟踪错误堆栈:
s@S[ ]-T;Me0 alter system set events '4031 trace name errorstack level 3';ITPUB个人空间 N$vj'WC&UaI1Z2W E
ITPUB个人空间1zhD!?3K$l&dN5Lz
步3:执行下如下ITPUB个人空间9x*g$~Po;C
declare
;o/p.C'K&`#Nj]HR0 msql varchar2(500);ITPUB个人空间#t H;w2|'g }+G
mcur number;
zJ*v(f.~D~0 mstat number;
+j2fB w6n1NJ&B0 jg varchar2(4000);
zvP7[mz"A;b0 beginITPUB个人空间F8E;OSg"S~X
  for i in 1..2000 loopITPUB个人空间sC m2C!R:k
     mcur:=dbms_sql.open_cursor;
?3[ t#\.g1Q P S$I#b3h.H0      msql:='select id from t3 where myid='||to_char(i);
{~5q&|.Q${0      dbms_sql.parse(mcur,msql,dbms_sql.native);
M)f,p0M T0      dbms_sql.define_column(mcur,1,jg,4000);ITPUB个人空间M,yg8J9^@&uG
     mstat:=dbms_sql.execute(mcur);
Y)sq9\'y$nag0    end loop;
6Q e+T'NW `O"C0    dbms_sql.close_cursor(mcur);
I pvv&b$i$h0 end;ITPUB个人空间hzW~ RK
/ITPUB个人空间'k4Y5r0Ewm+n-u
ITPUB个人空间%e)yq*t8`d2C2u
第 1 行出现错误:
/hR O8n9_!J:x0 ORA-04031: 无法分配 1272 字节的共享内存 ("shared pool","select id from t3 where myid...","Typecheck heap","kkotp : kkoiqd")
kj.grd:]R0c0 ORA-06512: 在"SYS.DBMS_SYS_SQL", line 826ITPUB个人空间"e8M ~+A M%V j7`
ORA-06512: 在"SYS.DBMS_SQL", line 32
m h;V6wN6}-m0 ORA-06512: 在line 12ITPUB个人空间J5M n4KH2B\9Y6K*^5\:H

U)hB PI$H8jW0 步4:查看跟踪文件:ITPUB个人空间*y%tIS{v
在跟踪文件的开始,有如下内容:ITPUB个人空间1x*b}5P(ef-{De
ksedmp: internal or fatal errorITPUB个人空间:n?~;LqA0cE%_%ea
ORA-04031: 无法分配 1272 字节的共享内存 ("shared pool","select id from t3 where myid...","Typecheck heap","kkotp : kkoiqd")
e1WaF/Eq-Q0 Current SQL statement for this session:ITPUB个人空间5J2AV?^2_~@N
select id from t3 where myid=944 ITPUB个人空间3tb R6`4M
ITPUB个人空间3l.C9AB hC)Z,`
这已经显示出来了引发错误的语句:select id from t3 where myid=944 ,再向下查看,可以发现大量的select id from t3 where myid=XXX语句。
O7t v2\5E,o/o0 ITPUB个人空间9m4zuh+L+G9J'[
下面,再深入的想一下,如果上面的匿名过程并不是执行到将共享池内存占尽才被迫终止,而是执行多少次后,不关闭游标正常终止,在此会话退出前,游标在共享池中的部分内存,将不会被释放。而此时共享池自由内存已经被占用的差不多了,有其他的编写正确的过程、SQL语句执行时,由于无法取得足够的共享池内存,将会报出4031错误。此时,虽然我们可以看到引发4031错误的语句,但此语句并不是造成错误的真正原因,原凶另有其人。对于这样的情况,该如何找到真正的原凶呢?比如说,将上面的匿名过程改为:
#Lr5QA9X5V]G0 declare
2HCTq%n.N |9V0 msql varchar2(500);ITPUB个人空间*B*C4z7J n)d k
mcur number;
1i;~lQM0 mstat number;
'f2X*U&TI/T F.R0 jg varchar2(4000);ITPUB个人空间-R~&c])AB(q._
beginITPUB个人空间dmv$_ v'n/d#{
                         --上面例子中,循环执行到944次被中断,这次我将循环次数改为850,ITPUB个人空间2c#o Gq7RK(D[t+_
  for i in 1..850 loop   --即可以消耗大量内存,又不会报出4031错误。ITPUB个人空间gQZ3w:?3m5bR)if qI6e
     mcur:=dbms_sql.open_cursor;ITPUB个人空间tuT.GS*}+mW
     msql:='select id from t3 where myid='||to_char(i);  ITPUB个人空间$F EmA0Zxx
     dbms_sql.parse(mcur,msql,dbms_sql.native);
z7o4v.R+f%ud0      dbms_sql.define_column(mcur,1,jg,4000);
`DDQD3xV|K0      mstat:=dbms_sql.execute(mcur);
9AM6^8T!X0    end loop;
arHP\~0    dbms_sql.close_cursor(mcur);
,yzec9vt^Z0 end;
R6s#Y t)Q Hb M9q0 /
B&j&FcOm@0 ITPUB个人空间%T.L Pz m/l8G
上面的过程可以正常执行完毕(如果在测试中仍会报出4031,可以将循环次数再缩小一些),这时,共享池的自由内存应该已经不多了。另开一些会话,随便运行一些消耗共享池的语句,不一会,4031出现了:
3ANEg~I0 ksedmp: internal or fatal error
P&Z0jaX)t0E0 ORA-04031: 无法分配 4088 字节的共享内存 ("shared pool","STATSPACK","PL/SQL MPCODE","BAMIMA: Bam Buffer")ITPUB个人空间 p:{#e%d'J;I/Y)A \
Current SQL statement for this session:ITPUB个人空间BCSDJ
DECLARE job BINARY_INTEGER := :job; next_date DATE := :mydate;  broken BOOLEAN := FALSE; BEGIN statspack.snap; :mydate := next_date; IF broken THEN :b := 1; ELSE :b := 0; END IF; END;
`-q0N^r0
0l I{ JPmJ0 引发4031的语句是STATSPACK,但,真正的原凶不是它。ITPUB个人空间.qS"~-fH1P ~!`o
好了,下面我用一个脚本,试验一下该如何定位问题的原凶。ITPUB个人空间0f.l1w0\ G7T$O3l
ITPUB个人空间/z3I.h1~6M8[
步1:准备基本的记录共享池状态的表:
)R2u-J \:j&R{:wol@0 create table jj_ksmsp as select * from x$ksmsp where 0=1;
uXt*N2x+c&X0 alter table jj_ksmsp add(id number);
r,E*^W#s0 create table jj_sqlarea as select * from v$sqlarea where 0=1;ITPUB个人空间j4_mC T;a"_ _F
alter table jj_sqlarea add(id number);
E0SP ? b+R Cp x0
j%]\I-^xRP0 var id number;ITPUB个人空间*a"`;O`!b xn^"D
exec :id:=1;ITPUB个人空间m{ j!B4g]
ITPUB个人空间n#S Z!r0im&i
步2:ITPUB个人空间+p3h ~/HI"y7AY#W
建立一个脚本 my_shared_stat.sql:
rGE'F9My)TU6~0
a0_&W5yY6k0 insert into jj_ksmsp select x$ksmsp.*,:id from x$ksmsp;ITPUB个人空间R~&[`X~
insert into jj_sqlarea select v$sqlarea.*,:id from v$sqlarea;ITPUB个人空间{ v8I P9l ?m} x{
exec :id:=:id+1ITPUB个人空间8][wnM$W-{E^"C3u
commit;ITPUB个人空间m8kK_F\ h[-k
ITPUB个人空间]#^z1e YT8o
步3:在于步1同一会话中,每隔一段时间运行此脚本my_shared_stat.sqlITPUB个人空间 y)o#v@p m0K(X{
ITPUB个人空间&JJ/P|&C6M
步4:随便的在其他会话中做些操作
F@M(N3Ia uLaW0
+P/b5^;uR/L#w*d,L0 步5:在任一会话中,运行如下匿名过程:ITPUB个人空间x+k;b6{-PA g
declare
Yv9~%H1dU:e#S0 msql varchar2(500);
h'xC(b4}*t0 mcur number;ITPUB个人空间,] v.BB6L'eX?2b*B)i
mstat number;
0\:v]4Xp6b:w`#n!{0 jg varchar2(4000);
7Pu$I uOL4G#w&n0 begin
"V b f5o1Eu0                          --上面例子中,循环执行到944次被中断,这次我将循环次数改为850,ITPUB个人空间AL#iJ/@7Cl p
  for i in 1..850 loop   --即可以消耗大量内存,又不会报出4031错误。
8q!J_:P1y0      mcur:=dbms_sql.open_cursor;ITPUB个人空间 A}W\;@@6z`2K p
     msql:='select id from t3 where myid='||to_char(i);  ITPUB个人空间O_ n^I)NO7` K
     dbms_sql.parse(mcur,msql,dbms_sql.native);ITPUB个人空间\:C\8~~2a/S
     dbms_sql.define_column(mcur,1,jg,4000);ITPUB个人空间 @%X#M#w Tb
     mstat:=dbms_sql.execute(mcur);
[;S1y Q&c vDC0    end loop;ITPUB个人空间N9IdA&E*f~
   dbms_sql.close_cursor(mcur);
4z/Ma"X4y3`ut0 end;ITPUB个人空间;\ Qsee%au
/ITPUB个人空间^\om#X8Z(\&T:_f
在此步骤中,循环的次数要根据自己共享池的大小而定,目的是既要让此过程消耗共享池内存,又不至于用尽共享池内存。ITPUB个人空间 ^WF2WK4I3} }s

4X CU4A8j#r0 步6:继续随便的在其他会话中做些操作,看什么时候会出现4031错误,
3}F|QRT"^]0 我是在执行Statspack抓取快照时,出现的4031。
u$G3tcIm M0 sid=16 pid=15> exec statspack.snapITPUB个人空间w f:X"UL"@#Sg0Q1v
BEGIN statspack.snap; END;ITPUB个人空间:oKu-`^:K(E

m TF(w ~'~0 *
-C5|*um Qb&Y9R0 第 1 行出现错误:ITPUB个人空间oUH:oJ3q*AT$@h%?
ORA-04031: 无法分配 2196 字节的共享内存 ("shared pool","STATS$SNAPSHOT","KGLS heap","KGLS MEM BLOCK")ITPUB个人空间 a O"t5r&Q1xFwG
ORA-06512: 在"PERFSTAT.STATSPACK", line 1361ITPUB个人空间%NI/v5y3X0_En
ORA-06512: 在"PERFSTAT.STATSPACK", line 2442
/|hso3T!~0 ORA-06512: 在"PERFSTAT.STATSPACK", line 91
)^u_8Z.Gn3k*v0 ORA-06512: 在line 1ITPUB个人空间3nN [Sql

ZqV+\,M ni0 select sharable_mem,persistent_mem,runtime_mem, executions  ,substr(sql_text,1,60) from (select * from jj_sqlarea order by sharable_mem desc) where rownum<=30 and id=&id;
a%M |$O1rI8iWp0
k2d'Pl*XZ9@)s0 步7:分析原因:
0Mpc nP0 建立如下脚本,名为show_ksmsp.sql:
h mXMk?;X0 select ksmchcom, decode(round(ksmchsiz/1000),0,'0-1K', 1,'1-2K', 2,'2-3K',3,'3-4K',
r*h.o\7i~| w0 4,'4-5K',5,'5-6k',6,'6-7k',7,'7-8k',8,
s AIt2uXhRcs0 '8-9k', 9,'9-10k','> 10K') "size",ITPUB个人空间8U&[_(gx*w0y
count(*),ksmchcls Status, sum(ksmchsiz) BytesITPUB个人空间5u&nuL1w%F} a Z
from jj_ksmspITPUB个人空间:L ub;F @ sY
where KSMCHCOM = 'free memory' and id=&id
[tTmno]B3D$V0 group by ksmchidx, ksmchcls,
NY1l!cwlV-b2V0 'sga heap('||KSMCHIDX||',0)',ksmchcom, ksmchcls,decode(round(ksmchsiz/1000),0,'0-1K',ITPUB个人空间m#j,WL{p ?
1,'1-2K', 2,'2-3K', 3,'3-4K',4,'4-5K',5,'5-6k',6,
N,l-b:me3b0 '6-7k',7,'7-8k',8,'8-9k', 9,'9-10k','> 10K');
}:tJ0w$c0
OqD-L jLR\a0 依次运行:
7Q7vE'r hy8R8V0 idle> @show_ksmsp
U;[ Nx$s-a[Um0e0 输入 id 的值:  1ITPUB个人空间%L!k3W*u#j$Z-b1o

/e*qm(L ^S5[ b z0 KSMCHCOM         size    COUNT(*) STATUS        BYTES
|'x$Ss?F3D0 ---------------- ----- ---------- -------- ----------
lA$S?$V\ YV0 free memory      0-1K          90 free           5088
:{TP_B*E:r I0 free memory      1-2K           1 free           1324ITPUB个人空间K(E h7]d1Q
free memory      > 10K          2 free        6318988ITPUB个人空间x3[0oH,Tm
id为1时的资料,Free memory大于10K的Chunk有两个,共6M多字节。ITPUB个人空间&D |BM*Y'C)D

4]1VuK"`0 idle> @show_ksmsp
A XW!enzQ1X-c0 输入 id 的值:  2ITPUB个人空间 U$n MatD
原值    6:  where KSMCHCOM = 'free memory' and id=&id
7g(M+EtoR0 新值    6:  where KSMCHCOM = 'free memory' and id=2ITPUB个人空间/s5y!c1m| Ra\
KSMCHCOM         size    COUNT(*) STATUS        BYTES
N$s3f+PP,SUE0 ---------------- ----- ---------- -------- ----------
8d*K3g$nd7V4c8dk0 free memory      0-1K         106 free           5972
_D:J^R| CJ0 free memory      3-4K           1 free           2988ITPUB个人空间wum cS @%Z2qv
free memory      > 10K          2 free        5730568ITPUB个人空间B'K#io2K
id为2时的资料,Free memory大于10K的Chunk有两个,共5M多字节。
VW:U3n0| H![|0 ITPUB个人空间;~0|%LP-n@.Z ~[
idle> @show_ksmsp
F l$k7q!B!D4a3f$t0 输入 id 的值:  3ITPUB个人空间2A)DRxD1f#u0M
KSMCHCOM         size    COUNT(*) STATUS        BYTES
}bL6];Rs Agf$fj0 ---------------- ----- ---------- -------- ----------
wGPsmV$R!s Qq0 free memory      0-1K         527 free          26348
l#sHWFu7P"L}0 free memory      2-3K           2 free           4052ITPUB个人空间T7^X!fS6A
free memory      3-4K           1 free           3408
NNZg`2e%H0 free memory      4-5K           1 free           3556ITPUB个人空间s5K![)@v
free memory      > 10K          1 free          17052ITPUB个人空间`yT&xkr,^i
id为3时的资料,Free memory大于10K的Chunk只剩1个,也就是17K左右。1K之下的Chunk则有527个。这时,已经开始有碎片了。
1O&jw\CD|xC c0
l*] \zj*| M7[br0 idle> @show_ksmspITPUB个人空间D@*tCZ0P
输入 id 的值:  4ITPUB个人空间@ x nV)W V.r4h
KSMCHCOM         size    COUNT(*) STATUS        BYTES
8S-d*W^`?}(g0 ---------------- ----- ---------- -------- ----------
&PeI~0^HKy0 free memory      0-1K         524 free          26256ITPUB个人空间1? U;?]Xy
free memory      1-2K          11 free           6568
9n(H"o'S.G^y#k+[0 free memory      > 10K          5 R-free       429700ITPUB个人空间,s HVKb dK"n|
id为4时的资料,Free memory大于10K的Chunk已经没有了,只剩下0-1K、和1-2K。
?8@#SXb5H0
Z8u.^];T t9WC:Q0 好了,不用再看下去了,问题应该是发生在ID为3或4时。在JJ_SQLAREA中查看ID为3的行:ITPUB个人空间v3ou+|}PX1Mt
步8:查找原凶:
z[6a Dj2o0 先显示ID为3时,前10条占用内存最多SQL声明:ITPUB个人空间 Wi`q6PAbl#Qa
select  VERSION_COUNT,PARSE_CALLS,executions , MEM,
iOaH!K0 round(mem/(select sum(sharable_mem+persistent_mem+runtime_mem) from jj_sqlareaITPUB个人空间 P!pbP(`%W
  where id=3)*100,2) "Mem%", substr(sql_text,1,150)
%cU"|};f'o%gR1l0 from (select jj_sqlarea.*,sharable_mem+persistent_mem+runtime_mem MEM from jj_sqlarea
$UDx)Y J4X0   order by mem desc)  where rownum<=&sl and id=3;
A x)E~9m(W*[0 输入 sl 的值:  10ITPUB个人空间d2LH*a%AzhN,T;a;W
ITPUB个人空间r s_/u[
VERSION_COUNT PARSE_CALLS EXECUTIONS        MEM       Mem% SUBSTR(SQL_TEXT,1,150)
4U w{;V!^0 ------------- ----------- ---------- ---------- ---------- --------------------------------------------------------
2z'i~ @1Ll e-H R(Z)K$s0             1           3          2      91318       1.07 insert into jj_sqlarea select v$sqlarea.*,:id from v$sql
DW8M6f {o4d0             1           1          1      82958        .98 select 'sid='||a.sid||' pid='||b.pid SID from v$sessionITPUB个人空间-bzr(RQ7e/@-`
            1           1          1      51594        .61 select OPEN_MODE from v$database
h9m7JMY&p0             3           5         30      47967        .56 select value$ from sys.props$ where name = :1
'M7|c`9w1h:k'Bp0             1           1          1      42644         .5 select tc.type#,tc.intcol#,tc.position#,c.type#, c.lengtITPUB个人空间p~ [[:V-c)f
            2          12         41      41439        .49 select i.obj#,i.ts#,i.file#,i.block#,i.intcols,i.type#,iITPUB个人空间} P"Iz,km9?7A
            1           3          3      35620        .42 insert into jj_ksmsp select x$ksmsp.*,:id from x$ksmsp
P2z:b@r,G*f0             1           1          1      31049        .37 select baseobject,type#,update$,insert$,delete$,refnewna
#IFe3H'e?4](m0             1           1          1      28772        .34 select o.owner#,o.obj#,decode(o.linkname,null, decode(u.ITPUB个人空间5| IY[,E4fv2v
            2          12         40      27017        .32 select ts#,file#,block#,nvl(bobj#,0),nvl(tab#,0),intcols已选择10行。ITPUB个人空间)C4b(J!VTGw
ITPUB个人空间 Gl)JR)K&f+{p5h
ID为3时,占用内存最多的SQL声明,是我自己的向JJ_SQLAREA中收集数据的脚本,它也只不过占用了所有SQL声明内存总量的1.07%。再看下面的这些SQL,并不能发现什么异常,扩大显示范围,显示前100条:
&{w2qY7Z-Q0 VERSION_COUNT PARSE_CALLS EXECUTIONS        MEM       Mem% SUBSTR(SQL_TEXT,1,150)
0i#SX"z0Nb/P*~k0 ------------- ----------- ---------- ---------- ---------- ------------------------------------------ITPUB个人空间D9wU,q~ \`#x5V2J
                     (省略部分内容...............)
2YB@qa'A;l(v6s-A^0             1           1          1       8930        .11 select id from t3 where myid=433ITPUB个人空间AIrzR-Y6x?
            1           1          1       8930        .11 select id from t3 where myid=547
6hLQ]#w0             1           1          1       8930        .11 select id from t3 where myid=604ITPUB个人空间XI}$Q?,XkAD({
            1           1          1       8930        .11 select id from t3 where myid=661
$ps0gLW1E5J%Y0             1           1          1       8930        .11 select id from t3 where myid=490ITPUB个人空间4YF'uwt4}(s)t
            1           1          1       8886         .1 select id from t3 where myid=554
?/b}{V9| X0             1           1          1       8862         .1 select id from t3 where myid=403
!l&V hr8H!YD2Q0             1           1          1       8862         .1 select id from t3 where myid=480ITPUB个人空间|r%F d/M[O
            1           1          1       8862         .1 select id from t3 where myid=475ITPUB个人空间"O[ H0N#N/}x0c
            1           1          1       8862         .1 select id from t3 where myid=470
"wWlI%a7C7G;k0             1           1          1       8862         .1 select id from t3 where myid=465
#slM0P;v-x0             1           1          1       8862         .1 select id from t3 where myid=460
b;^Gv8KtX3e0                      (省略部分内容...............)
|Y-~"DP ? x$V0 ITPUB个人空间"{7Ax!m9u.V6N1Y
发现大量硬解析,好了,原凶终于浮出水面。ITPUB个人空间}U+]$ci^'|)tt h:K
ITPUB个人空间'b-Om8D1F.bD ]A
总结一下,此处,查看某条语句是否占用过多的共享池内存,或是否有大量相似的SQL语句,是找到问题的一般途径。
hc,?"d.Dfz@d:H0 很多时候,“原凶”可能是Oracle的Bug。因此,如果真出现了4031,还要对引发共享池内存泄露的BUG有所了解。
5tDm n y{0 还有一些4031,是不可再现的,重启数据库后,再也没有出现过。这种情况最是让人揪心,好像你的数据库中有了一颗定时炸弹。ITPUB个人空间z}9I*fof1J
ITPUB个人空间 m4[)V)U?)P,D
对于可再现的4031,我上面的例子中脚本,只是一个非常简单的例子,真的要想找出原凶,还可以收集更多的视图中的资料,将收集资料的脚本my_shared_stat.sql,设为一个定时执行的自动任务。当然也可以使用STATSPACK,不过STATSPACK收集的资料过多,有些对4031是没用的,我觉得如果要想让收集频率更高一些的话,可以自己设计脚本,有针对性的收集一些视图的资料。这样收集资料的脚本需要做的工作更少,完成的速度更快,收集的频率也可以更高。ITPUB个人空间 w koi$c

'j{!e!NQ8p1VD0 上面例子中,我的脚本只是测试用的,因此,统计的信息并不全面,在出现4031时,还应该关注的视图有ITPUB个人空间yl0URb~q!sb!Y
V$SHARED_POOL_RESERVEDITPUB个人空间 B?E ^)h+DB N
v$sgastat
Gjq2aww0 V$SQL_SHARED_MEMORY
w}r4^Dh+vs0 x$kghluITPUB个人空间Rb"E-o~6j
x$ksmlruITPUB个人空间"K!q*C~6[%O&bNM
v$resource_limit
L4i P.k| R0 ITPUB个人空间gb{2pG0I
可以用于4031的跟踪事件还有:ITPUB个人空间VJ Aa ]3LC@
alter system set events '4031 trace name heapdump level 2';
3Lh)G3e` J(gz0 alter system set events 'immediate trace name library_cache level 11';
v"b_d,Z0
giMT/t,k0 对于可重现的4031,使用statspack在比较大的时间粒度下,持续的收集资料,找出引发4031出现的时段,在再相应的时段中,用自己的脚本,以比较高的频率(比较细的时间粒度)收集有针对性的资料,对于发现错误的原凶,也很有帮助。另外,对你所使用的数据库版本4031方面的BUG要有所了解,很多4031问题,都是由BUG引发的。ITPUB个人空间C"LQ|~K

sO.v1^$_3hRZx&U*G0 [ 本帖最后由 晶晶小妹 于 2008-3-26 07:55 编辑 ]

TAG:

DBA 足迹 jimhou 发布于2008-03-26 08:27:55

dhs0227的个人空间 dhs0227 发布于2008-03-26 08:39:03

bluemoon0083发布于2008-03-26 08:48:07
不错顶一下
Oracle的琐碎生活 yuxuan 发布于2008-03-26 09:00:15
很详细,学习
vepeta发布于2008-03-26 09:15:34
学习!
mustapha的个人空间 mustapha 发布于2008-03-26 09:22:18
分析的很清晰,支持
fikong2005的个人空间 fikong2005 发布于2008-03-26 09:37:11
先顶再看
rollingpig的个人空间 rollingpig 发布于2008-03-26 09:38:12
hehe
(W~O'k0Lq;z`#Nz|space.itpub.net这个procedure ,当年我写过,就是为了向开发说明 shared_pool再大,也不能开太大的open cursors. 当然,为了速度我只parse 而不执行。
t M3Br#Uespace.itpub.net[php]&m!wW,mY:@&cW
@

for i in 1..850 loop   --即可以消耗大量内存,又不会报出4031错误。ITPUB个人空间M$DU#A:DX:J;i1H
     mcur:=dbms_sql.open_cursor;ITPUB个人空间#b `4t:W!~0A8B)ja
     msql:='select id from t3 where myid='||to_char(i);  ITPUB个人空间"yaG8a_G0z!g7k
     dbms_sql.parse(mcur,msql,dbms_sql.native);
r!h/r;i3H)uoracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net   end loop;
3qTbW'O
?d
   dbms_sql.close_cursor(mcur);
XQeh?space.itpub.netend;
y)bc7[i e`sGITPUB个人空间..,Rr6]+r3nGi
.(v0u!Y6l*[
[/php]5X6xWzU
yZ-f:]
N){

另外,找元凶的更好方法是看 v$open_cursor+V$sqlArea group by SIDITPUB个人空间+NyK.RVg`
[php]$n|9M Y;DK*x K{
select /*+ordered use_hash(c s) no_merge(s) no_merge(c) */
m GQoD4]v$`U;q L3_#Iisid,sum(sharable_mem)/1024/1024 from I#o7t_5d~;M.y_
v$open_cursor c , v$sqlarea s
d@(?9`
i}a k X5h
@%X"U#coracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net
where c.hash_value =s.hash_valueq}0\0w\
group by c.sid
Nd,u^`W bTt2akorder by 2 descITPUB个人空间_(@APl5i0j7?
...ITPUB个人空间;~B
Cru P

...oracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net(m.FL4Sd/y&c`J
[/php]
)v;Q$J X7r        gworacle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.netspace.itpub.netX] AOT'@
立刻就可以找出占用大量share pool memory的SID%Oi-Dyoo.w]
然后需要的话再select * from v$open_cursor where sid = .. 看到具体语句
*I7iF"N(@8i"bITPUB个人空间u[5s,eNPQ
[ 本帖最后由 rollingpig 于 2008-3-26 09:40 编辑 ]
Alienovo的个人空间 Alienovo 发布于2008-03-26 09:47:50
不错  学习一下
wangfans的个人空间 wangfans 发布于2008-03-26 10:00:02
学习
jieyancai发布于2008-03-26 10:04:26
透过现象看本质,强!
五“宅”一生发布于2008-03-26 10:39:56
学习,支持晶晶!
paul oracle my love paulyibinyi 发布于2008-03-26 11:26:45
不错
john_77发布于2008-03-26 11:29:22
学习了
cyt2005发布于2008-03-26 11:44:27

QUOTE:

原帖由 rollingpig 于 2008-3-26 09:38 发表
8N:wI:x&LIR.Bhehe
"sm0x}*p!d7_r_这个procedure ,当年我写过,就是为了向开发说明 shared_pool再大,也不能开太大的open cursors. 当然,为了速度我只parse 而不执行。
`[TA2XR'z#k$^[php]space.itpub.net^ | Uj o$Um
for i in 1..850 loop   --即可以消耗大量内存,又不会报出4031错误。ITPUB个人空间i0l7H.j5B#GoE
     mcur:=dbms_sql.open_cursor;
iP\?1E5n0fspace.itpub.net     msql:='select id from t3 where myid='||to_char(i);  oracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net7kI.MU0lw
     dbms_sql.parse(mcur,msql,dbms_sql.native);
?`y+e:a%f5g;h+voracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net   end loop;ITPUB个人空间5O#dT$B'[$WR
   dbms_sql.close_cursor(mcur);
$u'DS~ i*Tend;
)L;N]3D1mf
m6w
..
ZB-vT$Q7R
l3kjITPUB个人空间
.VR%He-L5b1W
[/php]
Kw2?&|qoracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net另外,找元凶的更好方法是看 v$open_cursor+V$sqlArea group by SID
1p9@8~TF        g[php]space.itpub.netmL*ff(W8X)y,cqeD
select /*+ordered use_hash(c s) no_merge(s) no_merge(c) */ s:qu m8Bs O
sid,sum(sharable_mem)/1024/1024 from ITPUB个人空间
c8S(zG
X
j
^

v$open_cursor c , v$sqlarea sITPUB个人空间I&x-kE
`XL

where c.hash_value =s.hash_value Hzz"Ga6O~
group by c.sidITPUB个人空间'l!t3VC.s(k3PL#o+W K
order by 2 desc&P*N2x Z,@){:E
...oracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net;H"{l M`SF
...
_N_%oL yITPUB个人空间[/php]
aS
VS"}1[Aspace.itpub.net
ITPUB个人空间n6ytS
xe

立刻就可以找出占用大量share pool memory的SID
Asj#Qq.A5dITPUB个人空间然后需要的话再select * from v$open_cursor where sid = .. 看到具体语句
ITPUB个人空间~RI
N0]K-p5E5^

space.itpub.net| RRe(KZ N`

'AW2F'sjI5G'ioracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net+EuR)zPEK
斑竹使问题由繁入简
feng_xin的个人空间 feng_xin 发布于2008-03-26 11:48:22

QUOTE:

原帖由 rollingpig 于 2008-3-26 09:38 发表
H ?+^^
{.G7j8e
hehe RXv1Do*L8^!Y
这个procedure ,当年我写过,就是为了向开发说明 shared_pool再大,也不能开太大的open cursors. 当然,为了速度我只parse 而不执行。O+v        ~v[g-q
[php]
:f6^Zm}/k{g&Mfor i in 1..850 loop   --即可以消耗大量内存,又不会报出4031错误。`E#_]#y&H}]
     mcur:=dbms_sql.open_cursor;ITPUB个人空间 ZM        UwTGI4X
     msql:='select id from t3 where myid='||to_char(i);  
*pl[pX     dbms_sql.parse(mcur,msql,dbms_sql.native);
1w%iYQf1i_(Uz   end loop;
R:@X6uy};n@n3gd   dbms_sql.close_cursor(mcur);
/Z{hv1SITPUB个人空间end;oracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net \j@LdB
..
6N)\
i:y9zspace.itpub.net
.
@#d~%\7BbUoracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net[/php]Fz&F&G+jz7\
另外,找元凶的更好方法是看 v$open_cursor+V$sqlArea group by SIDspace.itpub.netDIj!VO1E3D2a
[php]ITPUB个人空间]ab
Bw"h0i ?8P9P

select /*+ordered use_hash(c s) no_merge(s) no_merge(c) */
[(Cz'H2Msid,sum(sharable_mem)/1024/1024 from Pr ~@7ZB
v$open_cursor c , v$sqlarea s
7j K!BU'k        QK{where c.hash_value =s.hash_valueoracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net c8X*xI&i-A4HpC
group by c.sid
7zc$y
g0iUoracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net
order by 2 descspace.itpub.net_wC `8@
...S4cT1p+H3\%c\        N
...
!z-he4x.} UA[/php]
AC&K:Jf#u9UNITPUB个人空间space.itpub.netSGOp?&i
DOd

立刻就可以找出占用大量share pool memory的SIDoracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net/F_w0~/LD4[i_
然后需要的话再select * from v$open_cursor where sid = .. 看到具体语句
oracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.netP(WEZ'a

f$dCb1rE        z"d-]qspace.itpub.net ITPUB个人空间-q5{
u;pwc8`-xt/n;R



ZcJH        S6xoracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net
4031的错误大部分是未绑定变量SQL语句引起的。排除bug后,就要从v$sqlarea与v$open_cursor中找出元凶sql语句。D%i.TcT
doHW I


:[5sv)qDE元凶有两种:
7z        InF*\*Kioracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net1, 未绑定变量并且大量执行的sql, 这种sql就是晶晶模拟出来的现象。可以通过如下SQL语句抓出来。
\/PD;bwFN0Ioracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net先找出sql:

CODE:

select count(*), sum(sharable_mem),substr(sql_text,50) from v$sqlarea group by substr(sql_text,50) order by 1,2;substr取的字符的个数,根据应用进行调整。
I5Todb2FAoracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.net"G1YduR)Al
然后根据找出的SQL确定是哪个应用执行的

CODE:

select sid,sharable_mem,s.sql_text from v$open_cursor c , v$sqlarea s where c.hash_value =s.hash_value and s.sql_text like 'xxxxxxxx%'2, 单条SQL需要大量内存空间,如果内存里有空间但是是由很多小空间碎片组成的话,当执行这个占用内存大的单条sql时,由于不能分配空间,而产生4031错误。这种sql一般来说都是够长够复杂的sql. 可以通过如下SQL语句抓出来。V0j|NK5p3v
先找出sql

CODE:

select sid,s.sharable_mem,s.sql_text,s.ADDRESS,s.HASH_VALUE from v$open_cursor c , v$sqlarea s where c.hash_value =s.hash_value order by sharable_mem;通常sql_text不能把sql显示完整,用如下查询找出完整的sql.

CODE:

select a.address,a.hash_value,a.piece,a.sql_text,a.command_type from v$sqltext a,
(select sid,s.sharable_mem,s.sql_text,s.ADDRESS,s.HASH_VALUE from v$open_cursor c , v$sqlarea s where c.hash_value =s.hash_value and s.sharable_mem>xxxxx) b
where a.address=b.address and a.hash_value=b.hash_value
order by 1,2,3;

guyuanli发布于2008-03-26 11:53:04
学习了,支持晶晶!
qsxing发布于2008-03-26 12:16:42
学习了....
isongshu发布于2008-03-26 12:31:21
学习一下
jiangjh62发布于2008-03-26 13:39:09
3Q ,很不错
晶晶小妹的个人空间 晶晶小妹 发布于2008-03-26 18:19:21

QUOTE:

原帖由 rollingpig 于 2008-3-26 09:38 发表
}9?Im*LITPUB个人空间hehe
xORX&DI;U这个procedure ,当年我写过,就是为了向开发说明 shared_pool再大,也不能开太大的open cursors. 当然,为了速度我只parse 而不执行。
0Y3t;]@[[php]oracle,db2,sqlserver,sybase,mysql,erp,scm,sap,java,.neth
YHb8L

for i in 1..850 loop   --即可以消耗大量内存,又不会报出4031错误。ITPUB个人空间/^@5Nx R3n:o#]1b
     mcur:=dbms_sql.open_cursor;space.itpub.net~&a?f n'a`U
     msql:='select id from t3 where myid='||to_char(i);          Y} ?p"F#W:ul
     dbms_sql.parse(mcur,msql,dbms_sql.native);space.itpub.net3XLJ`xcj~
   end loop;space.itpub.net4d*r+b TClt
   dbms_sql.close_cursor(mcur);"El` X:Nn3w w(v
end;ITPUB个人空间9d?bFW        _
..space.itpub.netk/OP$L6m~w*o1r
.2G
`5SGs-S!TS

[/php]
E8Q|[Z0g(X另外,找元凶的更好方法是看 v$open_cursor+V$sqlArea group by SIDITPUB个人空间L^YO\7I&e
[php]
k0W(En/P,r#q)Rselect /*+ordered use_hash(c s) no_merge(s) no_merge(c) */0@)l:HCYRNfWx
sid,sum(sharable_mem)/1024/1024 from
)cN9{Liv$open_cursor c , v$sqlarea sITPUB个人空间s5[6T:o/j
where c.hash_value =s.hash_value
bpP2lF2V:]
U~space.itpub.net
group by c.sidspace.itpub.netU]j6l#wx)y!Z
WS

order by 2 descL
D*KgO4P;S

...
!~
p,J\_8uIIrN
...
lP1Ykce

[/php]
Mi,Jg0Vd4Q
yW"xf8hy uo
yspace.itpub.net
立刻就可以找出占用大量share pool memory的SIDLak6{/K0G9D:K
然后需要的话再select * from v$open_cursor where sid = .. 看到具体语句

A n^3Z7X:j7yITPUB个人空间
3nN        xbr

i5I3pY-ST!SPM2W老大补充的好,大家还有什么好意见补充一下,我写个专门“抓元凶”的脚本,也方便一下初学者。
DragonBill的个人空间 DragonBill 发布于2008-03-26 18:39:02

liyongdong发布于2008-03-27 11:14:14
支持
louis_xu的个人空间 louis_xu 发布于2008-03-27 12:22:48
小妹有日子没操刀了space.itpub.netX9G[|8P(I0d B
我顶
eagle_fan发布于2008-03-27 12:46:54
select substr(sql_text,1,40),count(*) from v$sql group by substr(sql_text,1,40) having count(*)>1000
wsny的个人空间-Thunder Ping wsny 发布于2008-03-27 13:04:06
小妹的开发团队的技术挺落后啊。
*u;a+i*NI
r
}5J?
其实现在OR mapping的工具的存在,基本上可以避免绑定变量的问题了。
idoi发布于2008-03-27 13:32:33
顶,学习
leeking1105发布于2008-03-28 17:33:31

haorman zuohao_lu 发布于2008-03-28 18:16:36
学习
congya发布于2008-03-28 19:27:09
学习一下,十分好呀!
我来说两句

(可选)

日历

« 2008-11-22  
      1
2345678
9101112131415
16171819202122
23242526272829
30      

数据统计

  • 访问量: 38807
  • 日志数: 31
  • 图片数: 4
  • 建立时间: 2008-02-15
  • 更新时间: 2008-05-29

RSS订阅

Open Toolbar