我想学习如何跟踪Oracle客户端并查看提交的SQL查询。
我首先将这些行添加到客户机的sqlnet中。ora文件:
TRACE_LEVEL_CLIENT=16
TRACE_FILE_CLIENT=sqlnet.trc
TRACE_DIRECTORY_CLIENT=c:temp
LOG_DIRECTORY_CLIENT=c:temp
TRACE_UNIQUE_CLIENT=TRUE
TRACE_TIMESTAMP_CLIENT=TRUE
DIAG_ADR_ENABLED=OFF
然后我使用SQL*Plus登录到同一个客户端的数据库。我提交了两个查询:
select * from all_tables where table_name = 'ADDRESS';
select * from all_users where username like 'AB%';
然后退出SQL*Plus。跟踪文件在c:temp
中创建。该文件大约有4000行长。我可以清楚地看到我的两个SQL语句。格式读起来很痛苦,因为它们只是十六进制转储:
(10632) [29-AUG-2016 17:08:40:240] nsbasic_bsd: 00 00 31 73 65 6C 65 63 |..1selec|
(10632) [29-AUG-2016 17:08:40:240] nsbasic_bsd: 74 20 2A 20 66 72 6F 6D |t.*.from|
(10632) [29-AUG-2016 17:08:40:240] nsbasic_bsd: 20 61 6C 6C 5F 75 73 65 |.all_use|
(10632) [29-AUG-2016 17:08:40:240] nsbasic_bsd: 72 73 20 77 68 65 72 65 |rs.where|
(10632) [29-AUG-2016 17:08:40:240] nsbasic_bsd: 20 75 73 65 72 6E 61 6D |.usernam|
(10632) [29-AUG-2016 17:08:40:240] nsbasic_bsd: 65 20 6C 69 6B 65 20 27 |e.like.'|
(10632) [29-AUG-2016 17:08:40:240] nsbasic_bsd: 41 42 25 27 01 00 00 00 |AB%'....|
我的研究使我相信tkprof
是获得跟踪文件的可读报告的方法。我尝试了以下操作:
tkprof c:tempsqlnet_10632.trc report.txt
但是这给了我一个相当无意义的文件:
0 session in tracefile
0 user SQL statements in trace file.
0 internal SQL statements in trace file.
0 SQL statements in trace file.
0 unique SQL statements in trace file.
4361 lines in trace file.
0 elapsed seconds in trace file.
理想情况下,我希望看到一个报告,在这种情况下,它显示了客户端提交的易于阅读的SQL文本(包括我手动输入的两个文本),按照提交的顺序。我的思路对吗?我错过了什么?如果我没有在正确的轨道上,我应该做些什么来跟踪客户端提交的SQL呢?
注意:我使用12c客户端。我不能访问数据库服务器
仅供参考,Oracle提供了trcasst
实用程序来执行此操作:
$ORACLE_HOME/bin/trcasst client_Tract_file.trc > client_Tract_file.txt
tkprof实用程序用于从10046跟踪文件生成报告。
这些跟踪文件显示数据库操作。
这里有一篇很好的文章可以让你开始:SQL trace 10046
tkprof对sqlnet跟踪文件根本没用。
对于sqlnet跟踪文件,您可能希望使用transast实用程序。
虽然传输很有用,但是如果您真的想知道发生了什么,您需要对文件本身有一些了解。
下面是一些很好的参考资料,可以帮助您开始理解sqlnet跟踪文件:
Oracle Net Services的跟踪错误信息
如果您可以访问My Oracle Support,下面的注释将是非常宝贵的:
SQLNET PACKET STRUCTURE: NS PACKET HEADER (Doc ID 1007807.6)检查Oracle Net, Net8, SQLNet跟踪文件(Doc ID 156485.1)
第二篇文章附带了一个PDF,其中解释了很多。
11g - 19c的文档都说明您应该在sqlnet.ora中设置以下内容:
diag_adr_enabled=off
如果你想要精确的时间戳,那么这样做:
diag_adr_enabled=on
这是一个错误,我希望看到在Oracle 20c发布时修复。
这不是我希望得到的答案,但我需要完成并继续前进,所以我编写了一个快速而肮脏的Windows控制台应用程序(c#):
static void Main(string[] args)
{
using (var sr = new StreamReader(args[0]))
{
var line = string.Empty;
var parsingSqlHex = false;
var timestamp = string.Empty;
var parsedSql = string.Empty;
var patternStart = @"nsbasic_bsd: packet dump";
var patternTimeStamp = @"[d{2}-[A-Z]{3}-d{4} (dd:){3}d{3}]";
var patternHex = @"nsbasic_bsd: ([0-9A-F][0-9A-F] ){8}";
var patternEnd = @"nsbasic_bsd: exit (0)$";
while (line != null)
{
if (Regex.IsMatch(line, patternStart))
{
timestamp = Regex.Match(line, patternTimeStamp).Value;
parsingSqlHex = true;
}
else if (parsingSqlHex)
{
if (Regex.IsMatch(line, patternEnd))
{
if (!string.IsNullOrEmpty(parsedSql))
{
Console.WriteLine(timestamp);
Console.WriteLine(parsedSql + "rn");
}
parsedSql = string.Empty;
parsingSqlHex = false;
}
else if (Regex.IsMatch(line, patternHex))
{
parsedSql += HexToString(line.Substring(line.Length - 35, 23));
}
}
line = sr.ReadLine();
}
}
}
static string HexToString(string hexValues)
{
var hexCodeArray = hexValues.Split(" ".ToCharArray());
var n = 0;
var s = string.Empty;
for (var i = 0; i < hexCodeArray.Length; i++)
{
n = Convert.ToInt32(hexCodeArray[i], 16);
if (n > 31 && n < 127) s += Convert.ToChar(Convert.ToUInt32(hexCodeArray[i], 16));
}
return s;
}
我用它来解析我的跟踪文件,像这样:
OracleTraceParser.exe c:temptrace.txt > report.txt
然后我的report.txt文件有一些奇怪的字符在这里和那里,但仍然给了我我想要的:
[30-AUG-2016 13:50:51:534]
i^qx(SELECT DECODE('A','A','1','2') FROM DUAL
[30-AUG-2016 13:50:51:534]
i
[30-AUG-2016 13:51:05:003]
^a5select * from all_tables where table_name = 'ADDRESS'
[30-AUG-2016 13:51:21:081]
i^a1select * from all_users where username like 'AB%'