2017-07-19 183 views
1

用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的问题是它永远不能用于生产。我认为应该有一些方法可以更便宜地获得相同的价值。

如何在代码中执行此操作,以便在生产中监控此值?

+1

您可以查询Oracle数据库以获取源自该程序的连接的总连接数。例如:select count(*) from gv $ session where machine ='XXXXX' and username ='YYYYY' and program ='ZZZZZ'; – ivanzg

+0

您只需要一些特定的值来唯一标识这些连接,例如源自它的机器 - >“server.123.local.com”,连接进入数据库的数据库用户名以及可能的程序名称,如“clientprogram1 “或其他属性。 – ivanzg

回答

2

试图找到哪些地方连接未关闭是一项艰巨的任务。

如果您离开程序并忘记关闭连接,那么最后执行的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 
; 
1

您可以在“gv $ session”视图上查询Oracle DB以获取所需的信息。通过对该视图的查询,您可以每10-15分钟循环监视一次数据库,以获取此程序的连接数量。

实施例以下查询:

select count(*) 
from gv$session 
where machine = 'XXXXX' 
and username = 'YYYYY' 
and program = 'ZZZZZ'; 

你只需要唯一地标识例如像机从该连接源于这些连接值。

此外,查询非常轻,不会增加性能开销。

相关问题