一個ResultSet的 Bug教訓

昨天在測試的時候,經常出現一個異常:Error setting up static cursor cache 網上說這是因爲一個進程所持有的File Descriptor 過多引起的。我查了一個下午,發現是由於微軟提供的SQL Server JDBC驅動引起的,但是確實是我們自己編碼的失誤,沒有關閉一些相應的資源。

在系統中,錯誤隱藏很深,我試驗了多次,終於重現了錯誤,代碼如下:
        try
        {
            Connection conn = ........ //注意,該連接可能是從連接池中獲取的
            DatabaseMetaData dbm = conn.getMetaData();

            //得到信息源中的所有的表的
            for (int i = 0; i < 100; i++)
            {
                long start = System.currentTimeMillis();

                //得到信息源中的所有的表的
                ResultSet rs = dbm.getTables(null, null, null, new String[]
                                             {"TABLE"});
                while (rs.next())
                {
                    String tableName = rs.getString(3); //得到表的名稱
                    ResultSet rs1 = dbm.getColumns(null, null, tableName, null);

                    while (rs1.next())
                    {
                        rs1.getString(4);
                    }
                   
                    ResultSet rs2 = dbm.getImportedKeys(null, null, tableName);
                    while (rs2.next())
                    {
                        rs2.getString(4);
                    }
                   
                    ResultSet rs3 = dbm.getExportedKeys(null, null, tableName);
                    while (rs3.next())
                    {
                        rs3.getString(8);
                    }
                   
                    ResultSet rs4 = dbm.getPrimaryKeys(null, null, tableName);
                    while (rs4.next())
                    {
                        rs4.getString(4);
                    }                   

                }
               
                long end = System.currentTimeMillis();
                System.out.println(">>>>"+i+": " + (end - start));


            }
            conn.close(); //這裏的close方法,並不真正的關閉連接,只是把它放到了  緩衝池中
        }
        catch (SQLException e)
        {
            e.printStackTrace();

        }
 }
上述代碼獲取一個數據庫的所有表,表的主鍵、外鍵等信息,在我機器上for循環每到第58次就會出現錯誤。原因如下:
SQLServer JDBC爲了獲得這些數據,會使用大量臨時文件(在java.io.tmpdir指定的目錄中),但是如果不關閉ResuletSet的話(例如上面的代碼),JDBC就不會釋放這些文件的Hanlder, 所以當獲取數據庫Schema次數較多時,,當前的進程會持有大量的文件Hanlder, 這時候,JDBC就會拋出"Error setting up static cursor cache"的異常。
所以ResultSet如果不用的話,一定要記着關閉,否則後患無窮

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章