我在这里有一个基本问题 - 我正在使用名为XpressMP
的新数据库。
我写了一个多线程程序,将大量记录插入数据库。在与数据库建立连接时,我注意到了一件最重要的事情:
在我的计划中,如果我使用下面的内容 -
class Task implements Runnable {
private Connection dbConnection = null;
private PreparedStatement preparedStatement = null;
//other stuff
@Override
public void run() {
try {
dbConnection = getDBConnection();
} finally {
if (preparedStatement != null) {
try {
preparedStatement.close();
preparedStatement = null;
} catch (SQLException e) {
}
}
if (dbConnection != null) {
try {
dbConnection.close();
dbConnection = null;
} catch (SQLException e) {
}
}
}
}
}
它工作正常,我正在关闭最后一个块中的每个连接。我可以向数据库插入更多行。
但是一旦我开始故意使用静态连接(我不应该这样做)多线程 -
class Task implements Runnable {
private static Connection dbConnection = null;
private static PreparedStatement preparedStatement = null;
//other stuff
@Override
public void run() {
try {
dbConnection = getDBConnection();
} finally {
if (preparedStatement != null) {
try {
preparedStatement.close();
preparedStatement = null;
} catch (SQLException e) {
}
}
if (dbConnection != null) {
try {
dbConnection.close();
dbConnection = null;
} catch (SQLException e) {
}
}
}
}
}
整个数据库都挂起。在重新启动数据库之前,我无法使用该数据库。这意味着我的JDBC驱动程序存在一些问题。我告诉DBA这个问题,他们正在与拥有该数据库的人交谈。
但我的问题是为什么它会挂起。出于什么原因?
答案 0 :(得分:1)
您正在各种线程之间共享一个对象引用变量...有时,创建一个连接对象,在它关闭之前(并将其引用设置为null),另一个线程启动,创建另一个对象并且永远不会关闭旧对象一。因此,该连接仍然存在,并且在某些时候,将打开太多连接并且您的DBMS可能会崩溃,从而引发一些错误,例如“太多连接”。问题不是你的驱动器,而是你的代码。请注意,某些线程也可能会关闭由另一个线程创建的连接!
我认为您没有看到正在抛出的异常,因为您在catch
外没有try
。当您尝试创建连接时,将抛出异常。尝试在那里放一个捕捉来显示堆栈跟踪。如果您的数据库检测到此问题,它将起作用(它可能会起作用)。
答案 1 :(得分:1)
JDBC不是线程安全的,因此您不应该并行使用多个线程中的一个Connection对象,无论它是否存储在静态字段中。一旦你这样做,一个线程可能会在其他线程的查询中发送它的查询,所以数据库将收到完整的垃圾,如果数据库不是坚如磐石,这个垃圾可能会破坏数据库