1

为了确保我正确地创建和关闭数据库连接,我编写了以下代码。这是一个简单的 java 代码,只有核心 java、Oracle 瘦客户端,连接到 Oracle 10g XE 实例。我曾期望这段代码可以毫无问题地运行——因为它只是创建和关闭连接(在一个线程中)——多次。但问题是在运行几次(20ish)后会引发错误。

编码:

public class TestConnection {
private final static Logger logger = LoggerFactory
        .getLogger(TestConnection.class);

@Rule
public ContiPerfRule i = new ContiPerfRule();

@Test
@PerfTest(invocations = 100, threads = 1)
@Required(max = 1200, average = 1000)
public void test() {

    Connection connection = null;
    try {
        // Load the JDBC driver
        String driverName = "oracle.jdbc.driver.OracleDriver";
        Class.forName(driverName);

        // Create a connection to the database
        String serverName = "127.0.0.1";
        String portNumber = "1521";
        String sid = "XE";
        String url = "jdbc:oracle:thin:@" + serverName + ":" + portNumber
                + ":" + sid;
        String username = "funngames";
        String password = "funngames";
        connection = DriverManager.getConnection(url, username, password);
        assertNotNull(connection);
        logger.debug("Connection made.");

    } catch (ClassNotFoundException e) {
        logger.debug(e.getMessage());
    } catch (SQLException e) {
        logger.debug(e.getMessage());
    } finally {
        if (connection != null) {
            try {
                connection.close();
                logger.debug("Connection broken.");
            } catch (SQLException e) {
                logger.debug(e.getMessage());
                fail("The connection could not be closed.");
            }
        }
    }
}

}

它抛出的错误是

ORA-12519, TNS:no appropriate service handler found

重要的是要注意,如果我只运行一次 - 而不是上面代码片段中显示的 100 次 - 它绝对可以正常工作。如果我运行它 100 次,它会运行几次(20 - 25 次),然后退出并出现上面显示的错误。例如,该片段显示许多连接已打开并已成功关闭,但之后立即开始抛出错误。

    foo.bar.database.TestConnection.test
16:39:17.854 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:17.854 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:17.869 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:17.869 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:17.885 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:17.885 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:17.901 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:17.901 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:17.916 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:17.916 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:17.932 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:17.932 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:17.948 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:17.948 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:17.979 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:17.979 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:17.994 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:17.994 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:18.010 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:18.010 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:18.026 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:18.026 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:18.041 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:18.041 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:18.057 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:18.057 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:18.073 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:18.073 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:18.088 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:18.088 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:18.104 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:18.104 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:18.119 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:18.119 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:18.135 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:18.135 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:18.151 [main] DEBUG foo.bar.database.TestConnection - Connection made.
16:39:18.151 [main] DEBUG foo.bar.database.TestConnection - Connection broken.
16:39:18.166 [main] DEBUG foo.bar.database.TestConnection - Listener refused the connection with the following error:
ORA-12519, TNS:no appropriate service handler found
The Connection descriptor used by the client was:
127.0.0.1:1521:XE

任何想法,这种情况有什么问题?

如果你想了解更多关于我到底想要做什么的背景信息,我已经在这里写了博客。

4

3 回答 3

1

行。发现了问题。

假设 - 连接关闭位发生在两个级别 1. java 代码 2. 数据库服务器。在我的代码中,java 位关闭连接的速度比数据库服务器能够关闭它们的速度更快(预计是因为它确实是数据库服务器在那里完成了大部分工作)。因此存在一些竞争条件,Java 代码假设先前的连接已关闭并试图创建一个新连接,而数据库服务器尚未能够关闭先前的连接。

证明 - 如果我让 java 代码在它设法关闭连接后稍等片刻,那么这段代码可以正常工作。我让这段修改过的 java 代码在循环中执行了 1000 次,它运行良好。将此与我报告此问题时的事实进行比较,代码在绊倒之前只会运行大约 20 到 25 次。

新代码(只是修改)...

...
finally {
if (connection != null) {
    try {
        connection.close();
        logger.debug("Connection broken.");
        Thread.sleep(1000);
    } catch (SQLException e) {
        logger.debug(e.getMessage());
        e.printStackTrace();
        fail("The connection could not be closed.");
    } catch (InterruptedException e) {
        logger.debug(e.getMessage());
        e.printStackTrace();

    }
...
于 2012-10-16T03:48:59.450 回答
0

我猜您的连接没有正确关闭,因为该错误意味着没有可用的侦听器来处理请求。您是否在日志中收到“连接中断”文本?

于 2012-10-15T11:06:27.533 回答
0

可能您的连接没有被关闭。我建议您让 java 为您完成关闭。现在有实现的AutoClosable接口Connection。它的详细信息在这里。试试这个,看看你是否仍然得到错误。如果可能,最好让 API 为您完成工作。

于 2012-10-15T11:10:55.050 回答