为了确保我正确创建和关闭数据库连接,我编写了以下代码。这是一个简单的 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
有什么想法吗,这个场景有什么问题吗?
如果您想了解更多关于我到底想做什么的背景信息,我有 blogged关于它在这里。
最佳答案
好的。发现问题了。
假设 - 连接关闭位发生在两个级别 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();
}
...
关于Java + Oracle 连接 - 完成少量后被拒绝,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12894193/