我申请这个blog是为了督促自己,把自己平时的一些想法和思考结果保留下来。 本博客所有内容均为原创,如有转载请注明作者和出处

长时间latch free等待——记一次系统异常的诊断过程

上一篇 / 下一篇  2007-03-24 00:00:00 / 个人分类:ORACLE

今天发现一个报表数据库中SQL运行异常,简单记录一下问题的诊断和解决过程。


uQ#jM*cB&J@0

问题是在检查ALERT文件时发现的,一个过程运行时间太长而出现了ORA-1555错误。

错误信息:

ORA-01555 caused by SQL statement below (Query Duration=38751 sec, SCN: 0x0000.fe5b584a):
:o` Qu6F&f!{ `bY/w0INSERT INTO MAN_ORDER_ITEM (ITPUB个人空间pr,x6@2jg*cu*_
ID,ITPUB个人空间x { F[N:~4e
REQUEST_QTY,ITPUB个人空间}$h.^GG3E/?
SALER_ID,ITPUB个人空间s/AVZ ` Y"Mze
PRODUCT_ID,
,o(M,q!K:a,k0UNIT_PRICE,ITPUB个人空间0]HJJ [V^ Z"L
CREATE_DATE,
.B]0d,@1d7U4?0ANSWER_DATE,ITPUB个人空间7P{RWZ j0?sk
BUYER_IDITPUB个人空间0J UvY1~&J*O)Z``u4C
)
2J9f2I9U9}W0SELECTITPUB个人空间G:KSc&VF [ a
A.RECORD_ID,ITPUB个人空间f/^3`h:|kT(~1O*G4O x
A.REQUEST_QTY,ITPUB个人空间5uh:w$hc??
A.SALER_ORGID,ITPUB个人空间TcV{7RnNS1R
A.PRODUCT_ID,ITPUB个人空间6t8Bk/i.M&h:b
A.UNIT_PRICE,ITPUB个人空间5Rc0n"e,Q-WxX0Dw
A.CREATE_DATE,
QK3K-~7{~y5D"]0NULL,ITPUB个人空间 s3bP;xq{m;E
A.BUYER_ORGIDITPUB个人空间 Sn@`4z5\\3t(t
FROM ORD_ORDER_ITEM A
J9_k [H;YhgzY8u0WHERE A.CREATE_DATE >= TO_DATE('2004-01-01 0:0:0', 'YYYY-MM-DD HH24:MI:SS')
x*^?uK h0AND A.CREATE_DATE < TRUNC(SYSDATE)
@ zP1i ?3@Y0AND EXISTS (SELECT 1 FROM MAN_PRODUCT WHERE ID = A.PRODUCT_ID)ITPUB个人空间X Dv#A4f4ni*UK
AND EXISTS (SELECT 1 FROM MAN_DEALER WHERE ID = A.SALER_ORGID)ITPUB个人空间0J5k4F*i}7yC*vO[
AND EXISTS (SELECT 1 FROM MAN_BUYER WHERE ID = A.BUYER_ORGID)

由于这是个JOB调用,在失败后JOB会自动重试,于是从DBA_JOBS_RUNNING中查看相关的JOBSESSION信息。

SQL> SELECT SID, JOB FROM DBA_JOBS_RUNNING;

SID JOB
W:]Cp W*x0---------- ----------ITPUB个人空间 ?"ca0`L.TQG0U5a z,Q
70 208

检查这个SESSION目录在执行什么SQL

SQL> SELECT SQL_TEXT FROM V$SQL SQL, V$SESSION S
XO%d)Bp5l02 WHERE SQL.HASH_VALUE = S.SQL_HASH_VALUE
U9Jh"X byCZ*uzJ03 AND SQL.ADDRESS = S.SQL_ADDRESSITPUB个人空间}0r LtE)]!zi(T0Hv
4 AND S.SID = 70;

SQL_TEXT
Fi0D,x)de*H|7z0------------------------------------------------------------------------------ITPUB个人空间 D+R0Q(p ~.c)X
INSERT INTO MAN_ORDER_ITEM ( ID, REQUEST_QTY, SALER_ID, PRODUCT_ID, UNIT_PRICE, CREATE_DATE, ANSWER_DATE,
(_*G8x+nt y-}3X0BUYER_ID ) SELECT A.RECORD_ID, A.REQUEST_QTY, A.SALER_ORGID, A.PRODUCT_ID, A.UNIT_PRICE, A.CREATE_DATE,
"P1K[ r`!?A ^fDM0NULL, A.BUYER_ORGID FROM ORD_ORDER_ITEM A WHERE A.CREATE_DATE >= TO_DATE('2004-01-01 0:0:0', 'YYYY-MM-DD HH24:MI:S
Ar-{+YF,R#OC0S') AND A.CREATE_DATE < TRUNC(SYSDATE) AND EXISTS (SELECT 1 FROM MAN_PRODUCT WHERE ID = A.PRODUCT_ID) AND EXISTS (SEL
-VBc~5[*BdWw"H$l0ECT 1 FROM MAN_DEALER WHERE ID = A.SALER_ORGID) AND EXISTS (SELECT 1 FROM MAN_BUYER WHERE ID = A.BUYER_ORGID)

SQL上看,就是刚才失败的那个SQL语句,那么看看SESSION在等待什么:

SQL> SELECT SID, EVENT, P1TEXT, P1RAW, P2TEXT, P2, SECONDS_IN_WAIT FROM V$SESSION_WAIT
4_+cyfC a"B8].n02 WHERE SID = 70;

SID EVENT P1TEXT P1RAW P2TEXT P2 SECONDS_IN_WAIT
+p WW'}n/wQ0------- -------------- -------- ---------------- ------- ----- ---------------ITPUB个人空间uzh u2H-\J
70 latch free address 00000004125AB718 number 98 330

通过观察发现,Session的等待事件一直是LATCH FREE。第一个感觉是可能和其他的进程产生了争用。

查询一下Oracle等待的具体latch的类型。

SQL> SELECT LATCH#, NAME FROM V$LATCH WHERE LATCH# = 98;

LATCH# NAME
q/mbq"D6H%q&?-A0---------- ----------------------------------------------------------------
ukddv4f7UE6Z w098 cache buffers chains

而查询V$LOCKV$LATCHHOLDER视图,发现没有其他的进程对JOB运行构成影响:

SQL> SELECT SID, TYPE, ID1, ID2, LMODE, REQUEST, CTIME, BLOCKITPUB个人空间*A i6w)FnQl,C~
2 FROM V$LOCKITPUB个人空间9x1Q:\^2l7J
3 WHERE SID > 8;

SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK
rSVEz;`k0S0---------- -- ---------- ---------- ---------- ---------- ---------- ----------
a/q&EE0y(d-{B070 TM 35258 0 3 0 12072 0ITPUB个人空间4Uhj/}Iq0_^
70 JQ 0 208 6 0 12155 0

SQL> SELECT * FROM V$LATCHHOLDER;

no rows selected

SQL> SELECT * FROM V$LATCHHOLDER;

no rows selected

SQL> SELECT * FROM V$LATCHHOLDER;

no rows selected

SQL> SELECT * FROM V$LATCHHOLDER;

PID SID LADDR NAME
BN0D%gw0---------- ---------- ---------------- ------------------------------
4Q,i`2J"i6_2ta015 70 0000000412564D98 cache buffers chains

SQL> SELECT * FROM V$LATCHHOLDER;

no rows selected

可以看到,并没有其他对象影响JOB进程。

由于等待事件是LATCH FREE,怀疑和系统本身的问题有关。

通过下面的脚本可以看到,目前正在等待的这个子LATCH的信息:

SQL> SELECT ADDR, LATCH#, CHILD#, NAME FROM V$LATCH_CHILDRENITPUB个人空间D u pQ9_eBB5M;Y
2 WHERE ADDR IN (SELECT P1RAW FROM V$SESSION_WAIT WHERE SID = 70);

ADDR LATCH# CHILD# NAMEITPUB个人空间i5wC3I'?
---------------- ---------- ---------- ---------------------------------------
"Jf$t^s7lit |00000000412550518 98 327 cache buffers chains

观察LATCH_MISSES的信息:

SQL> COL PARENT_NAME FORMAT A20ITPUB个人空间D*m i6H0q
SQL> COL WHERE FORMAT A35ITPUB个人空间{T!{O;L&PQ
SQL> SELECT *
_|Y T"T2j8X[02 FROM ITPUB个人空间b(HG[*no
3 (ITPUB个人空间!Q;C8h7yO8^[
4 SELECT PARENT_NAME, "WHERE", SLEEP_COUNT, WTR_SLP_COUNT, LONGHOLD_COUNT ITPUB个人空间-^at#|&z6`0PYI?
5 FROM V$LATCH_MISSES
@)DK:o*]"n$iJ5v p06 WHERE PARENT_NAME = 'cache buffers chains'
D` t p#Fk JDH4a07 ORDER BY SLEEP_COUNT + WTR_SLP_COUNT + LONGHOLD_COUNT DESCITPUB个人空间t-u q;Y&?#wb$~
8 )
#P9l@Br3l]4Xc\6rAF09 WHERE ROWNUM < 20;

PARENT_NAME WHERE SLEEP_COUNT WTR_SLP_COUNT LONGHOLD_COUNT
[.g%Z.^gEJ0-------------------- ------------------------------- ----------- ------------- --------------ITPUB个人空间%~8T`"|!_V t
cache buffers chains kcbgtcr: kslbegin excl 1202658 884364 906374ITPUB个人空间XF*~/i,a1NY-z*x)V b
cache buffers chains kcbrls: kslbegin 480030 852471 335799ITPUB个人空间'}aX)T"c9~ Hd9D$l
cache buffers chains kcbzwb 95994 90482 84373ITPUB个人空间O7@4c8v8q
cache buffers chains kcbgtcr: kslbegin shared 89385 84911 62640
\ AglT2f'E#o%^0cache buffers chains kcbgtcr: fast path 69352 113120 51014
\f WO'k(N0cache buffers chains kcbchg: kslbegin: bufs not pinned 86476 51934 58687ITPUB个人空间m\"L l5V~
cache buffers chains kcbzsc 76224 55 75045
e6VjqaOZ0cache buffers chains kcbbxsv 37425 8306 35681
$JW @p%^9j Fz U0cache buffers chains kcbchg: kslbegin: call CR func 1337 20943 745ITPUB个人空间*TdH,? y
cache buffers chains kcbzib: finish free bufs 685 18544 432ITPUB个人空间O`#f(I })t$B(s
cache buffers chains kcbcge 168 8767 107ITPUB个人空间xvy#q.a
cache buffers chains kcbgcur: kslbegin 344 4974 203ITPUB个人空间6P F!mj(MM&T}!e
cache buffers chains kcbget: pin buffer 542 4508 383ITPUB个人空间wHf!TRs Av6@)m
cache buffers chains kcbgtcr 2400 395 1769
_iZB y ^C0cache buffers chains kcbbic1 14 4015 11
SrY*s"E%nU0cache buffers chains kcbzgb: scan from tail. nowait 2048 0 1896ITPUB个人空间D5oW os l
cache buffers chains kcbbic2 38 2920 32ITPUB个人空间3U-v{ v0}lPC S*?*y
cache buffers chains kcbzib: multi-block read: nowait 1502 0 970
:V*T,j9e:L0cache buffers chains kcbnew 497 331 289

19 rows selected.

感觉问题和热点块有关,那么看看到底是哪些块出现的问题:

SQL> SELECT OBJ, OBJECT_NAME, TCH, TIMITPUB个人空间e*k6i],o$Ej:aI
2 FROM X$BH A, DBA_OBJECTS BITPUB个人空间 R(P4h)}~
3 WHERE HLADDR IN (SELECT P1RAW FROM V$SESSION_WAIT WHERE SID = 70)
E~6[?W/aB,oS04 AND A.OBJ = B.DATA_OBJECT_ID;

OBJ OBJECT_NAME TCH TIM
(S'E{-Y-Csaf0---------- ------------------------------ ---------- ----------
K-G%vy:tBuQ0109 I_OBJAUTH2 0 0
mut ^_qA045761 STATS$SQLTEXT_PK 1 1174381376
&?9a0OV]F%t}fwi~0.
D+@#_1V@"K$}$R0.ITPUB个人空间,^$@h(y%b ?r-iIm
.
.c#f\!z)c j#W@_5]062275 ORD_ORDER_ITEM_ZJ 1 1174380112ITPUB个人空间l g.Ag2E
62275 ORD_ORDER_ITEM_ZJ 1 1174380085ITPUB个人空间:Up Kx@T
62275 ORD_ORDER_ITEM_ZJ 1 1174380088
Vd a0?h Z-Jp062275 ORD_ORDER_ITEM_ZJ 1 1174380097ITPUB个人空间7C]v#q [y-_#w
62275 ORD_ORDER_ITEM_ZJ 1 1174380100ITPUB个人空间5hDX O pg A`b
62275 ORD_ORDER_ITEM_ZJ 1 1174380103.ITPUB个人空间-bE+U3~lV%e
.
hdB3@;[F;x;g0.ITPUB个人空间4B HG-Q([
.
:f$K.ZBE7@k!Lq0200403 ORD_ORDER_ITEM 6 1174381870
K.t{&n3J0200403 ORD_ORDER_ITEM 6 1174381871ITPUB个人空间5b r~x'C:]
200403 ORD_ORDER_ITEM 6 1174381870ITPUB个人空间,uRdKO5xO
200403 ORD_ORDER_ITEM 6 1174381870
!ZW[ s ^2vd*] u A0200403 ORD_ORDER_ITEM 6 1174381871ITPUB个人空间e ]CQB3m OLE9o
200403 ORD_ORDER_ITEM 6 1174381870ITPUB个人空间"V"~n]G[7v
200403 ORD_ORDER_ITEM 6 1174381870ITPUB个人空间+T+Gn!qu*cx
200403 ORD_ORDER_ITEM 6 1174381871ITPUB个人空间oS._ m,c]~
200403 ORD_ORDER_ITEM 6 1174381871
:` C X0g!wN0200403 ORD_ORDER_ITEM 6 1174381871ITPUB个人空间t^3n UW'e.Dt
200403 ORD_ORDER_ITEM 6 1174381870
A'_k6K8a4t]7Z)QJ8d0200403 ORD_ORDER_ITEM 6 1174381870
h)T4~E9}8Yc%z0.
t7M V+~A9w Nk3MeN0.ITPUB个人空间^nIT(J;M
.
RK(`.ko-k$x?1}p062275 ORD_ORDER_ITEM_ZJ 678 1174381878ITPUB个人空间bkv;c.VtKw
62275 ORD_ORDER_ITEM_ZJ 1 1174380060
OA0h3WgG@-h`\ z062275 ORD_ORDER_ITEM_ZJ 1 1174380091ITPUB个人空间j8O![u]3k
62126 ORD_ORDER_ITEM_CEN 0 0
Q1n&V Q:CS$PU5J062126 ORD_ORDER_ITEM_CEN 0 0
4@,Z qW6iTP9qT1O062126 ORD_ORDER_ITEM_CEN 0 0
S(O;`#^$HB'V062126 ORD_ORDER_ITEM_CEN 0 0ITPUB个人空间}|7VF2g2X t
45772 STATS$UNDOSTAT 0 0ITPUB个人空间G;azEw
45772 STATS$UNDOSTAT 0 0

125 rows selected.

从这些热点块的所属对象来看,大部分都是那个长时间运行的SQL访问的。难道转了一个大圈,结果是执行计划的问题?

检查该SQL的执行计划:

SQL> EXPLAIN PLAN FOR
juxio4l02 INSERT INTO MAN_ORDER_ITEM (
S^"k8f p S7t03 ID,
;A.h+Jv)K}6lp&YU04 REQUEST_QTY, ITPUB个人空间 @Mr1Z3H5\F3f-d
5 SALER_ID, ITPUB个人空间"?}R:{G a,@_,b`E
6 PRODUCT_ID, ITPUB个人空间(LE;G9C7e$^)J4j
7 UNIT_PRICE,
@b.C+eDq B? y/@:Q2y08 CREATE_DATE,
2Y+W&J$_H}jTp0KNg09 ANSWER_DATE,
4i'^6cy0Zi0v8Du010 BUYER_ID ITPUB个人空间|!C9F"TM
11 )
*mRy~gLk012 SELECT ITPUB个人空间5T,fz l;K
13 A.RECORD_ID,
4N@1hm/j014 A.REQUEST_QTY,ITPUB个人空间N'Qr-eW wb
15 A.SALER_ORGID,
B-S!Y?D _016 A.PRODUCT_ID,
x9uAu L017 A.UNIT_PRICE,
)e)JG hywm018 A.CREATE_DATE,
M#[3m!UC7IHq!i5{019 NULL,ITPUB个人空间sA(bOz.Hz w
20 A.BUYER_ORGID
x_ iv#\Q5m9yLt021 FROM ORD_ORDER_ITEM A ITPUB个人空间&g g@}i E7P
22 WHERE A.CREATE_DATE >= TO_DATE('2004-01-01 0:0:0', 'YYYY-MM-DD HH24:MI:SS')ITPUB个人空间 tM&W(J-C"~&EsU
23 AND A.CREATE_DATE < TRUNC(SYSDATE)
,N&hz _i9X({}Bq024 AND EXISTS (SELECT 1 FROM MAN_PRODUCT WHERE ID = A.PRODUCT_ID)ITPUB个人空间n\'[HHuE$m"C
25 AND EXISTS (SELECT 1 FROM MAN_DEALER WHERE ID = A.SALER_ORGID)ITPUB个人空间d/Qe ^0r"Hd2NkF
26 AND EXISTS (SELECT 1 FROM MAN_BUYER WHERE ID = A.BUYER_ORGID)
%T.v0ToVi027 ;

Explained.

SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());

PLAN_TABLE_OUTPUT
)PS%CrQ XI zL0------------------------------------------------------------------------------------------------------------------------

-------------------------------------------------------------------------------------------------ITPUB个人空间a,eU%_yS g
| Id | Operation | Name | Rows | Bytes | Cost |
W`-@.? U'R0-------------------------------------------------------------------------------------------------ITPUB个人空间i0d;a:r"S
| 0 | INSERT STATEMENT | | 1 | 212 | 37 |ITPUB个人空间 m%DK1k/hH a`$d q
|* 1 | FILTER | | | | |
EBN@ ?D0| 2 | NESTED LOOPS | | 1 | 212 | 37 |
d{h5m4S+afg0| 3 | MERGE JOIN CARTESIAN | | 1 | 76 | 12 |ITPUB个人空间Wx_:qdf"M
| 4 | MERGE JOIN CARTESIAN | | 1 | 51 | 9 |
[%P0Wh6k5T"O(w:B0| 5 | SORT UNIQUE | | | | |
z&o.o5|/Lm.{*\u0| 6 | INDEX FAST FULL SCAN | PK_MAN_PRODUCT | 1 | 26 | 3 |
A'F$Oa3b"?_1N0| 7 | BUFFER SORT | | 8138 | 198K| 6 |ITPUB个人空间 e$w(IM)EiI'AH
| 8 | SORT UNIQUE | | | | |ITPUB个人空间e H(\,C#U'l
| 9 | INDEX FAST FULL SCAN | PK_MAN_BUYER | 8138 | 198K| 3 |
._3g K7\KD0| 10 | BUFFER SORT | | 14238 | 347K| 9 |ITPUB个人空间'M*d/K S'SRE"{!N
| 11 | SORT UNIQUE | | | | |ITPUB个人空间5@d"ee2_-uRJ a
| 12 | INDEX FAST FULL SCAN | PK_MAN_DEALER | 14238 | 347K| 3 |
,PT-U4K7xtzmk0|* 13 | VIEW | ORD_ORDER_ITEM | 1 | 136 | 37 |ITPUB个人空间%lq"t!]*A{/t
| 14 | UNION-ALL PARTITION | | | | |ITPUB个人空间Qh(q2qK!J3H8g
|* 15 | FILTER | | | | |
/^$m%pt D k0|* 16 | TABLE ACCESS BY INDEX ROWID| ORD_ORDER_ITEM_CEN | 1 | 116 | 14 |ITPUB个人空间 jZ*}9_0Ba
| 17 | AND-EQUAL | | | | |
Pn ] R0{-v0|* 18 | INDEX RANGE SCAN | TU_ORD_ORD_ITEM_PRODUCT_ID | | | |
%e~ k{;N1f0|* 19 | INDEX RANGE SCAN | TU_ORD_ORDER_ITEM_SALER | | | |
t*JVv%VrO#kx0|* 20 | FILTER | | | | |ITPUB个人空间}S9d N7i0Ze o&D+Hn
|* 21 | TABLE ACCESS BY INDEX ROWID| ORD_ORDER_ITEM_ZJ | 1 | 116 | 2 |
.zy9B1grR1?0|* 22 | INDEX RANGE SCAN | TU_ORD_ORD_ITEM_PRODUCT_ID1 | 179 | | 1 |
)J+O~RT:e{l[G0-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
N ?I:db-w5}0---------------------------------------------------

1 - filter(TRUNC(SYSDATE@!)>TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') AND
7K\!O tE]r&RpK0TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss')<TRUNC(SYSDATE@!))ITPUB个人空间,T4`~ Y M:[
13 - filter("MAN_PRODUCT"."ID"="A"."PRODUCT_ID" AND "MAN_DEALER"."ID"="A"."SALER_ORGID" ANDITPUB个人空间*V9RF2RmR
"MAN_BUYER"."ID"="A"."BUYER_ORGID")
8tE L{mM4]015 - filter(TRUNC(SYSDATE@!)>TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') ANDITPUB个人空间`ci"k+~L.@1g^
TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss')<TRUNC(SYSDATE@!))ITPUB个人空间/Jk%q$X6o~H.o7P_v7x'z
16 - filter("ORD_ORDER_ITEM_CEN"."BUYER_ORGID"="MAN_BUYER"."ID" ANDITPUB个人空间HF i(Mx2f
"ORD_ORDER_ITEM_CEN"."SALER_ORGID"="MAN_DEALER"."ID" ANDITPUB个人空间 }-A'},N,rTj hxV O
"ORD_ORDER_ITEM_CEN"."PRODUCT_ID"="MAN_PRODUCT"."ID" ANDITPUB个人空间1P7p,J#T&g^
"ORD_ORDER_ITEM_CEN"."CREATE_DATE">=TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') AND
}u1uL$f{0"ORD_ORDER_ITEM_CEN"."CREATE_DATE"<TRUNC(SYSDATE@!))
8MU0w)`~3|W7E$Ph018 - access("ORD_ORDER_ITEM_CEN"."PRODUCT_ID"="MAN_PRODUCT"."ID")ITPUB个人空间.}vTZ_FZ
19 - access("ORD_ORDER_ITEM_CEN"."SALER_ORGID"="MAN_DEALER"."ID")ITPUB个人空间+wcob4x2J\
20 - filter(TRUNC(SYSDATE@!)>TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') AND
#C'C1v$rpW zv0TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss')<TRUNC(SYSDATE@!))
SC+KD#v.lV-Z021 - filter("ORD_ORDER_ITEM_ZJ"."BUYER_ORGID"="MAN_BUYER"."ID" ANDITPUB个人空间];D%nS \6O1@-O N
"ORD_ORDER_ITEM_ZJ"."SALER_ORGID"="MAN_DEALER"."ID" AND
zbo"Cr4G0"ORD_ORDER_ITEM_ZJ"."CREATE_DATE">=TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') AND
5r u1g_$O+JIE0"ORD_ORDER_ITEM_ZJ"."CREATE_DATE"<TRUNC(SYSDATE@!))
/[5Eyb@M pP022 - access("ORD_ORDER_ITEM_ZJ"."PRODUCT_ID"="MAN_PRODUCT"."ID")

Note: cpu costing is off

54 rows selected.

晕倒,怎么会产生一个这样的执行计划。不看别的,只看上面两个MERGE JOIN CARTESIAN就已经足够了。

这下总算明白系统中为什么拼命在等待LATCH FREE了。Oracle按照这个执行计划执行,不知道需要多大的内存来容纳中间结果集,所以只能不停的将中间结果装入内存,然后清空内存,一直不断的持续这个过程。

明白了系统目前的运行状况,那么Oracle为什么会产生这种恐怖的执行计划呢?从执行计划信息上看,使用的CBOOracle不会无缘无故采用这种执行计划的。

首先怀疑的是统计信息出现了偏差。

SQL> SELECT TABLE_NAME, NUM_ROWS FROM USER_TABLESITPUB个人空间 tc7T$V}Z0q
2 WHERE TABLE_NAME IN ('MAN_PRODUCT', 'MAN_BUYER', 'MAN_DEALER');

TABLE_NAME NUM_ROWS
juY7l9W_"gM-c0------------------------------ ----------
Wu&v N)E'z's:g0MAN_BUYER 8138
1dIN7D,J Q*Ur0MAN_DEALER 14238
p-RUz,y`Y#X@0MAN_PRODUCT 0

SQL> SELECT COUNT(*) FROM MAN_PRODUCT;

COUNT(*)ITPUB个人空间)E+C-ty;VvW\
----------ITPUB个人空间$y)t1W*zyBW6I@
91750

已经很明显了,MAN_PRODUCT的统计信息有误。正是由于Oracle认为MAN_PRODUCT的记录为0,所以选择了MERGE JOIN的方式,这样可以最迅速的得到最终的结果——0条记录。但是MAN_PRODUCT的记录数实际上并不为0,而是有将近10万的记录。这就是导致问题产生的真正原因。

其实问题到这里并没有完。Oracle产生错误的统计信息也是有原因的。首先这个脚本会首先清空相关表的数据,然后重新生成。而在前一次执行这个过程的时候,中途失败了。导致MAN_PRODUCT表中没有数据。而每周运行一次的收集统计信息的JOBMAN_PRODUCT表的0记录的统计信息记录了下来。

再次运行脚本的时候,虽然将记录写入到MAN_PRODUCT表中,但是统计信息并没有更新,因此导致了这个问题。

了解了问题的产生原因,解决起来就十分容易了,收集MAN_PRODUCT表的统计信息并检查执行计划,杀掉运行中JOB,重新启动JOB就可以了。

SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'MAN_PRODUCT', CASCADE => TRUE)

PL/SQL procedure successfully completed.

SQL> EXPLAIN PLAN FOR
a;r3CBKIpo02 INSERT INTO MAN_ORDER_ITEM (
pS/T$n|`;i03 ID, ITPUB个人空间J[b6]jZ
4 REQUEST_QTY,
!UI#Pc7e{6vt05 SALER_ID, ITPUB个人空间 b6CW5q2H
6 PRODUCT_ID, ITPUB个人空间z;W*u'vj6noW
7 UNIT_PRICE, ITPUB个人空间| ~Eq p j^Q
8 CREATE_DATE,
/U.`*w't.F)|"l(o09 ANSWER_DATE,
?|pqU)f,f$|8A*|P-k010 BUYER_ID ITPUB个人空间K K.HJ3h
11 )ITPUB个人空间?1Uc^(K$Ov }
12 SELECT
:fsD+B6o({013 A.RECORD_ID,ITPUB个人空间Ee-B;|*g2H#\
14 A.REQUEST_QTY,
3d*z\yf5b015 A.SALER_ORGID,
+}a*mO @U1[016 A.PRODUCT_ID,ITPUB个人空间'TFVtko nP
17 A.UNIT_PRICE,ITPUB个人空间@:DNK%io1k
18 A.CREATE_DATE,ITPUB个人空间#u H5y}&{5X,c
19 NULL,ITPUB个人空间9y-U)Vm(f'z&ep.il"wg(C
20 A.BUYER_ORGID
/X2F @ tm021 FROM ORD_ORDER_ITEM A ITPUB个人空间)N$?P9?,]k
22 WHERE A.CREATE_DATE >= TO_DATE('2004-01-01 0:0:0', 'YYYY-MM-DD HH24:MI:SS')
Iy(iYg$A6j Si023 AND A.CREATE_DATE < TRUNC(SYSDATE)
,P.Q/mV@024 AND EXISTS (SELECT 1 FROM MAN_PRODUCT WHERE ID = A.PRODUCT_ID)ITPUB个人空间 t q0q`W%T!Y
25 AND EXISTS (SELECT 1 FROM MAN_DEALER WHERE ID = A.SALER_ORGID)ITPUB个人空间 kSR9m*wtXD\
26 AND EXISTS (SELECT 1 FROM MAN_BUYER WHERE ID = A.BUYER_ORGID)
,AQ$J|1lD*BEn027 ;

Explained.

SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());

PLAN_TABLE_OUTPUT
9x C5a,m#I_0----------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------
\u5@9yN*D^*^0| Id | Operation | Name | Rows | Bytes |TempSpc| Cost |ITPUB个人空间T8} chD`#Z` @Z+q0H
--------------------------------------------------------------------------------------------------------------ITPUB个人空间W Un2T(Q5S y
| 0 | INSERT STATEMENT | | 32977 | 6795K| | 72667 |ITPUB个人空间W-t*{hL!jz0X
|* 1 | FILTER | | | | | |ITPUB个人空间-\.KeP4RfE+R&C%u`@+I
| 2 | NESTED LOOPS SEMI | | 32977 | 6795K| | 72667 |ITPUB个人空间A b7C/rl7f
| 3 | NESTED LOOPS SEMI | | 32977 | 5989K| | 72667 |ITPUB个人空间L-b|2y+tHy
|* 4 | HASH JOIN SEMI | | 32977 | 5184K| 4768K| 72667 |ITPUB个人空间%h+S'{%|L*^
| 5 | VIEW | ORD_ORDER_ITEM | 32977 | 4379K| | 72502 |
8}h-Eo!^5z0| 6 | UNION-ALL | | | | | |
"@w'S+E#r}"dl0|* 7 | FILTER | | | | | |ITPUB个人空间&N0UO[e
| 8 | TABLE ACCESS BY INDEX ROWID| ORD_ORDER_ITEM_CEN | 5797K| 641M| | 479 |
sQ%^4f?}zb0|* 9 | INDEX RANGE SCAN | TU_ORD_ORDER_ITEM_CREATE_DATE | 5797K| | | 16 |
3u"l+QR;i1F$`Q'Y4I0|* 10 | FILTER | | | | | |ITPUB个人空间/C]6m;~p
| 11 | TABLE ACCESS BY INDEX ROWID| ORD_ORDER_ITEM_ZJ | 2464K| 272M| | 643 |ITPUB个人空间 G9p,h\}u7Z1@
|* 12 | INDEX RANGE SCAN | TU_ORD_ORDER_ITEM_CREATE_DATE1 | 2464K| | | 21 |ITPUB个人空间T3M*NB*|(t.w
| 13 | INDEX FAST FULL SCAN | PK_MAN_PRODUCT | 91750 | 2239K| | 39 |
T`E1GS*F}0|* 14 | INDEX UNIQUE SCAN | PK_MAN_BUYER | 8138 | 198K| | |ITPUB个人空间q)el$xj{)M+F,s,d
|* 15 | INDEX UNIQUE SCAN | PK_MAN_DEALER | 14238 | 347K| | |
w$y w;w3iZl0---------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):ITPUB个人空间i.k2IA{W9o
---------------------------------------------------

1 - filter(TRUNC(SYSDATE@!)>TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') AND
-ILhI;vq*d%w0Qp3?2j!Y0TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss')<TRUNC(SYSDATE@!))ITPUB个人空间+b.[;?(xW*zB;@8d
4 - access("MAN_PRODUCT"."ID"="A"."PRODUCT_ID")ITPUB个人空间M*q;JT)Jr
7 - filter(TRUNC(SYSDATE@!)>TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') ANDITPUB个人空间X-J;p `B] f d*f Q3lx
TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss')<TRUNC(SYSDATE@!))
aA-o[D L09 - access("ORD_ORDER_ITEM_CEN"."CREATE_DATE">=TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') ANDITPUB个人空间F s1j^N x o
"ORD_ORDER_ITEM_CEN"."CREATE_DATE"<TRUNC(SYSDATE@!))ITPUB个人空间]or4jZ
10 - filter(TRUNC(SYSDATE@!)>TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') AND
O;XBO-m5JUu0TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss')<TRUNC(SYSDATE@!))ITPUB个人空间*Y(I1i#W u6I^b*w
12 - access("ORD_ORDER_ITEM_ZJ"."CREATE_DATE">=TO_DATE('2004-01-01 00:00:00', 'yyyy-mm-dd hh24:mi:ss') ANDITPUB个人空间n(Qi8_wuuV K0b
"ORD_ORDER_ITEM_ZJ"."CREATE_DATE"<TRUNC(SYSDATE@!))
(uQ1Opv sC014 - access("MAN_BUYER"."ID"="A"."BUYER_ORGID")ITPUB个人空间3]1xf;u)r)z
15 - access("MAN_DEALER"."ID"="A"."SALER_ORGID")

Note: cpu costing is off

40 rows selected.

SQL> SELECT SPID FROM V$PROCESS WHERE ADDR IN (SELECT PADDR FROM V$SESSION WHERE SID = 70);

SPID
M:EV7}2S0------------ITPUB个人空间\d.NS M fj
27488

找到JOB运行的操作系统进程,然后通过操作系统命令kill -9来杀掉进程。JOB运行的会话很难通过ALTER SYSTEM KILL SESSION语句来杀掉,因此选择使用操作系统命令的方式。

SQL> hostITPUB个人空间c0Q0f;~/[xmy+?
$ ps -ef|grep 27488ITPUB个人空间"b``+BY ]
oracle 28672 28671 0 18:07:20 pts/2 0:00 grep 27488ITPUB个人空间 I5o5`+h+p1Pz
oracle 27488 1 13 12:46:56 ? 317:21 ora_j000_repdb01
F}&C H5x t X{ s0$ kill -9 27488ITPUB个人空间-WD4{8i'[z(B,{|
$ exit

检查SESSIONJOB状态,确认JOB重新启动。

至此,问题解决。其实当时发现问题的时候,有两条路可以选择,一方面从系统运行的情况入手,也就是这篇文章中选择的方式。另一方面是直接从SQL语句入手,先检查执行计划。

由于这个SQL以前过多次,都是正常的,所以没有想到执行计划会发生那么大的变化。因此,一直从第一方面着手来诊断问题。所幸殊途同归,虽然绕了一个大圈子,最终还是找到问题的所在。


TAG:

 

评分:0

我来说两句

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

Open Toolbar