繁体   English   中英

间歇性的java慢查询到MySQL

[英]intermitten java slow query to MySQL

在我的应用程序服务器,用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;
}

您没有使用连接池,因此java服务器将继续连接和断开mysql。 表中有很多行吗? 还有其他一些线程会继续插入吗?

我强烈建议使用正确的JDBC连接池而不是DriverManager ,后者的缺点是每次需要时都会创建一个新连接,没有池。 通常,与数据库建立连接是一项冗长的操作。

除此之外,您的代码存在缺陷,imho,如果出现异常,您的连接仍会保持打开状态,您应该关闭ResultSetPreparedStatement以及连接。 优选地,在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);
}

您应该理想地设置DataSource并使用它来获取连接,而不是设置dbConfigString

public void setDataSource(DataSource ds) {
    this.ds=ds;
}

public void getDBConnection() throws SQLException {
    return ds.getConnection();
}

这样你就可以注入一个像Commons DBCPHikariCP这样的连接池。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM