在我的应用程序服务器中,用JAVA编写,我有以下症状:
每小时一次或两次,对MySQL的查询非常慢(8-10秒/查询)。
我的服务器查询2个不同的数据库服务器,它们都有这种症状,但不是同时出现。
为了消除网络原因,我运行网络监视器,并报告应用服务器和数据库服务器之间的网络是好的。而且,我的app服务器有4个线程,只有1个线程有慢查询,其他3个仍然查询良好。
在两台数据库服务器上,我将连接超时设置为10秒,有些查询超时(> 10秒),有些查询不会超时但速度慢(查询时间超过1秒,通常为8秒-9秒)。
1奇怪的是,尽管客户端的查询速度很慢,但数据库服务器端的查询日志并不慢(我的查询速度慢,查询时间为1秒)。
以下是我用来连接数据库的代码:
public boolean checkSession(String sessionId) {
Connection conn = null;
conn = getDBConnection();
if(conn == null)
return false;
try {
PreparedStatement stm = conn.prepareStatement("SELECT uid FROM sessions WHERE sid=?");
stm.setString(1, sessionId);
ResultSet rs = stm.executeQuery();
if(rs.next()){
if(rs.getInt("uid") == tamtayId){
conn.close();
return true;
}
}
conn.close();
return false;
} catch (SQLException e1) {
e1.printStackTrace();
}
return false;
}
public void setDbConfigString(String str){
conStr = str;
}
public Connection getDBConnection(){
Connection conn = null;
try{
conn = DriverManager.getConnection(conStr);
}
catch (Exception e) {
e.printStackTrace();
}
return conn;
}
答案 0 :(得分:1)
您没有使用连接池,因此java服务器将继续连接和断开mysql。 表中有很多行吗?还有其他一些线程会继续插入吗?
答案 1 :(得分:1)
我强烈建议使用正确的JDBC连接池而不是DriverManager
,后者的缺点是每次需要时都会创建一个新连接,没有池。通常,与数据库建立连接是一项冗长的操作。
除此之外,您的代码存在缺陷,imho,如果出现异常,您的连接仍会保持打开状态,您应该关闭ResultSet
和PreparedStatement
以及连接。优选地在finally
块中。
我建议重写代码如下。
public boolean checkSession(String sessionId) {
Connection conn = getDBConnection()
PreparedStatement stm = null;
ResultSet rs = null;
boolean val = false;
try {
if (conn != null) {
stm = conn.prepareStatement("SELECT uid FROM sessions WHERE sid=?");
stm.setString(1, sessionId);
rs = stm.executeQuery();
if(rs.next()){
val = rs.getInt("uid") == tamtayId;
}
}
} catch (SQLException e1) {
e1.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {}
}
if (stm != null) {
try {
stm.close();
} catch (SQLException e) {}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {}
}
}
return val;
}
public void setDbConfigString(String str){
conStr = str;
}
public Connection getDBConnection() throws SQLException {
return DriverManager.getConnection(conStr);
}
您应该理想地设置dbConfigString
并使用它来获取连接,而不是设置DataSource
。
public void setDataSource(DataSource ds) {
this.ds=ds;
}
public void getDBConnection() throws SQLException {
return ds.getConnection();
}
这样您就可以注入一个合适的连接池,如Commons DBCP或HikariCP。