一个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如果不用的话,一定要记着关闭,否则后患无穷

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