簡體   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