检测Oracle连接泄漏的最佳方法是什么?
问题描述:
用C#Oracle客户端编写的一个程序,事实证明它有“连接泄漏”,它没有关闭所有的数据库连接,所以一段时间后它不能再连接到数据库,因为打开的连接太多。检测Oracle连接泄漏的最佳方法是什么?
我写了下面的辅助功能(相当广阔):
private static int tryFindConnCount(){
var connstk = new Stack<Oracle.ManagedDataAccess.Client.OracleConnection>();
try
{
for (var i = 0; i < 10000; ++i)
{
var conn = new Oracle.ManagedDataAccess.Client.OracleConnection(
myDatabaseConnection);
conn.Open();
connstk.Push(conn);
}
}
catch(Exception e)
{
foreach (var conn in connstk)
{
conn.Close();
}
}
return connstk.Count;
}
这里是一个测试用例的代码,使用上面:
var co = tryFindConnCount();
CodeThatMayLeakConnection();
var cn = tryFindConnCount();
Assert.That(cn, Is.EqaulTo(co));
它帮助我识别至少一个的情况下有连接泄漏。
tryFindConnCount
的问题是它永远不能用于生产。我认为应该有一些方法可以更便宜地获得相同的价值。
如何在代码中执行此操作,以便在生产中监控此值?
答
试图找到哪些地方连接未关闭是一项艰巨的任务。
如果您离开程序并忘记关闭连接,那么最后执行的SQL存储在v $ session(gv $ session for RAC)的列SQL_ID中。您可以在v $ session中搜索空闲/死机会话。然后,您可以使用v $ sql来查找可能会告诉您更多关于上次完成操作的SQL文本。通过这个,你可能会得到一个提示在哪里搜索你的代码。
select a.sid, a.username, a.program, a.machine, a.sql_id, b.sql_fulltext
from v$session a, v$sql b
where b.sql_id(+) = a.sql_id
and a.username is not null -- filter system processes, maybe filter more stuff
;
答
您可以在“gv $ session”视图上查询Oracle DB以获取所需的信息。通过对该视图的查询,您可以每10-15分钟循环监视一次数据库,以获取此程序的连接数量。
实施例以下查询:
select count(*)
from gv$session
where machine = 'XXXXX'
and username = 'YYYYY'
and program = 'ZZZZZ';
你只需要唯一地标识例如像机从该连接源于这些连接值。
此外,查询非常轻,不会增加性能开销。
您可以查询Oracle数据库以获取源自该程序的连接的总连接数。例如:select count(*) from gv $ session where machine ='XXXXX' and username ='YYYYY' and program ='ZZZZZ'; – ivanzg
您只需要一些特定的值来唯一标识这些连接,例如源自它的机器 - >“server.123.local.com”,连接进入数据库的数据库用户名以及可能的程序名称,如“clientprogram1 “或其他属性。 – ivanzg