首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

Oracle 開放游標診斷:查詢 V$OPEN_CURSOR 定位洩漏 SQL

     編輯:關於SqlServer

Java 應用若未正確關閉 Statement/ResultSet,易導致 ORA-01000: maximum open cursors exceeded。透過動態效能視圖 V$MYSTAT、V$OPEN_CURSOR 可快速定位洩漏的 SQL 文本。

診斷三步驟

  1. 統計當前 Session 開啟游標數:
    SELECT a.value, a.sid
    FROM v$mystat a, v$statname b
    WHERE a.statistic# = b.statistic#
      AND b.name = 'opened cursors current';
  2. 依 SID 查詢開啟游標對應的 SQL 文本:
    SELECT sql_text
    FROM V$OPEN_CURSOR
    WHERE sid = :sid;
  3. 在程式碼中搜尋該 SQL,補上 rs.close()、stmt.close()。

Java 程式碼自動檢測範例

try {
  String qry = "SELECT a.value, b.name, a.sid FROM v$mystat a, v$statname b " +
               "WHERE a.statistic# = b.statistic# AND b.name = 'opened cursors current'";
  Statement stmt = conn.createStatement();
  ResultSet rs = stmt.executeQuery(qry);
  if (rs.next()) {
    long openCursors = rs.getLong(1);
    int sid = rs.getInt(3);
    if (openCursors > 1) { // 正常應為 1 (僅此查詢)
      // 查詢具體 SQL
      Statement stmt2 = conn.createStatement();
      ResultSet rs2 = stmt2.executeQuery(
        "SELECT sql_text FROM V$OPEN_CURSOR WHERE sid = " + sid);
      while (rs2.next()) {
        System.out.println("Leaked SQL: " + rs2.getString(1));
      }
      rs2.close(); stmt2.close();
      throw new Exception("Cursor leak detected, open=" + openCursors);
    }
  }
  rs.close(); stmt.close();
} catch (Exception e) { e.printStackTrace(); }

最佳實踐

  • 所有 JDBC 資源 (Connection, Statement, ResultSet) 必須在 finally 區塊或 try-with-resources (Java 7+) 中關閉。
  • 連線池設定 maxOpenPreparedStatements 限制預編譯語句快取數量。
  • 定期監控 V$SYSSTAT 的 opened cursors current 總量,設定告警閾值。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved