作者:IT168黄血成 来源:IT168   酷勤网收集 2008-10-03

摘要
  从trace文件中提取sql语句包括两个步骤:首先要找到sql语句本身,然后找到sql语句可能用到的绑定变量的值。

从trace文件中提取sql语句包括两个步骤:
首先要找到sql语句本身,然后找到sql语句可能用到的绑定变量的值。
本文假设你已经找到了报错的trace文件。

 第一步:查找sql语句

跳到"Current cursor:"那行(在"*** Cursor Dump ***"部分的开始处)。记下和当前cursor关联的数字(详情参考下文例子)。
如果当前的游标数字是0,表示当前没有sql语句。在这种情况下,最好是在trace文件前面的Call Stack Trace部分看看,这里告诉我们发生错误时正在做什么。一般情况下,oracle技术支持在处理问题的时候,会查看trace文件。
如果当前游标是个非0数值,在trace文件后面的部分查找以"Cursor n"开头的行,n表示你要找的游标号,从10.2及其以后的版本开始,查找"Cursor#n"开头的行。找到后,在下一行,你会看到"cursor name:",sql语句就在其后。

注意:
通常情况下,你通过查找"Current SQL statement for this session:"就能很快定位该sql,一般会在trace文件的前面部分。
如果sql语句没有用到绑定变量(例如. ":b1", ":b2", 等。),第二步可以不看了。

 第二步:查找绑定变量的值
如果sql语句使用了绑定变量,根据游标中的sql语句,你就能定位特定的文本部分,和每个绑定变量的值关联。文本的每部分以"bind x:"开头,其中的x的范围是0 到 n-1,其中的n代表绑定变量个数。
在sql语句和绑定变量之间可能会有大量的内存dump,可以忽略这些信息。
每个绑定变量会有很多属性列表,下面是我们感兴趣的一部分列表:
a.) dty 指数据类型,常见的值为:
1 VARCHAR2 or NVARCHAR2
2 NUMBER
8 LONG
11 ROWID
12 DATE
23 RAW
24 LONG RAW
96 CHAR
112 CLOB or NCLOB
113 BLOB
114 BFILE
b.) mxl 指最大长度,即变量占用的最大字节数,dty=2 and mxl=22 表示NUMBER(22)列
c.) scl 指位数 (对NUMBER列而言)
d.) pre 指小数点位数(对NUMBER列而言)
e.) value 指绑定变量的值

将游标dump中的绑定变量的值和sql语句中绑定变量的值直接对应:
:b1 ~ bind 0
:b2 ~ bind 1
:b3 ~ bind 2
以此类推………

绑定变量可以称为:1, :2,等,或者:a1, :a2等。最关键的是,在sql语句中的排列顺序和变量的dump部分的排列要完全一致。
现在你应该能找到绑定变量(包括长度,数值长度,精度)以及对应的值。

例子

下面我们举例说明在trace文件中如何提取sql语句。
特别注意:
如果使用字面值替代绑定变量,会导致优化器选择不同的查询路径,从而使得问题可能不会再现。
Example 1: 
 

******************** Cursor Dump ************************
Current cursor: 2, pgadep: 1
Cursor Dump:
----------------------------------------
我们查找cursor 2:
----------------------------------------
Cursor 2 (20139ad0): CURFETCH curiob: 2013bca4
curflg:
7 curpar: 20139ab0
curusr:
0 curses 587a250c
cursor name: select text from view$ where rowid=:1
child pin: 50a5b650, child lock: 50a5a628,
parent lock: 50a5a844
xscflg:
20141466, parent handle: 4f348490, xscfl2: 400
nxt:
2.0x0000006c nxt: 1.0x000001d8
Cursor
frame allocation
dump:
frm:
-------- Comment -------- Size Seg Off
bhp size: 52/560
bind
0: dty=11 mxl=16(16) mal=00
scl
=00 pre=00 oacflg=18 oacfl2=1 size=16
offset
=0
bfp
=2013e9f4 bln=16 avl=16 flg=05
value
=0000138C.0046.0004

当前SQL 语句:
select text from view$ where rowid=:1
绑定变量转换成:
:
1 ~ bind 0 - ROWID (dty=11), value = 0000138C.0046.0004
因此我们得到下面的原始sql语句:
select text from view$ where rowid=0000138C.0046.0004

Example 2:
 

******************** Cursor Dump ************************
Current cursor: 11, pgadep: 1
Cursor Dump:
----------------------------------------
查找cursor 11:
----------------------------------------
Cursor 11 (202cb9f0): CURBOUND curiob: 202f8b04
curflg: dd curpar:
0 curusr: 0 curses 30047c7c
cursor name: SELECT LOCKID FROM DBMS_LOCK_ALLOCATED WHERE NAME =
:b1
FOR UPDATE
child pin:
0, child lock: 300dc9b4, parent lock: 301730b8
xscflg:
1151421, parent handle: 3025b4dc
bind
0: dty=1 mxl=32(00) mal=00 scl=00 pre=00 oacflg=01
No bind buffers allocated
----------------------------------------
当前SQL 语句:
SELECT LOCKID FROM DBMS_LOCK_ALLOCATED WHERE NAME = :b1 FOR UPDATE
绑定变量:b1是VARCHAR2(
32) 类型(dty=1, mxl=32), 但是在dump的那个时刻没有给变量赋值("No bind buffers allocated").  

Example 3:
 

******************** Cursor Dump ************************
Current cursor: 2, pgadep: 0
Cursor Dump:
----------------------------------------
...
----------------------------------------
Cursor 2 (20140444): CURNULL curiob: 0
curflg:
44 curpar: 0 curusr: 0 curses 701dc94c
----------------------------------------
在这种情况下,当dump 的时候并没有sql被执行  

Example 4: 
 

******************** Cursor Dump ************************
Current cursor: 1, pgadep: 0
pgactx: ccf361c0
ctxcbk:
0 ctxqbc: 0 ctxrws: 0
Cursor Dump:
----------------------------------------
Cursor 1 (400d9478): CURBOUND curiob:
400e43d8
curflg: 4c curpar:
0 curusr: 0 curses d5348f80
cursor name: BEGIN myparser.convert('/tmp','workflow000_2.log',2);
END;
child pin: d14a4d70, child lock: d1589968, parent lock: d14c64a0
xscflg:
100064, parent handle: d083f1c0, xscfl2: 4040408

nxt:
1.0x000000a8
Cursor frame allocation dump:
frm:
-------- Comment -------- Size Seg Off
--
--------------------------------------
没有用到绑定变量,所以,sql语句就是PL/SQL块:
BEGIN myparser.convert('/tmp','workflow000_2.log',2); END;

 

分类: 数据库开发 数据仓库 Web技术

上一篇:Oracle数据库:db link与read only   下一篇:MySQL Replication(复制)基本原理