Mysql+JDBC+Linux:executeQuery 在不应该返回空结果集时返回空结果集

发布于 2024-11-19 22:40:41 字数 2440 浏览 2 评论 0原文

我有以下代码:

public boolean updateDatabase(long houseValue, List<Users> userList)
{
    boolean result = false;
    Connection conn = null;
    PreparedStatement stmtUpdateUsers = null;
    PreparedStatement stmtQueryHouse = null;
    PreparedStatement  stmtUpdateHouse = null;
    ResultSet rs = null;

    String updateUsers = "UPDATE users SET money = ? WHERE username = ?";
    String queryHouse = "SELECT * FROM house WHERE house_id = ?";
    String updateHouse = "UPDATE house SET house_money = ? WHERE house_id = ?";

    try
    {
        conn = getConnectionPool().getConnection();
        conn.setAutoCommit(false);      

        stmtUpdateUsers = conn.prepareStatement(updateUsers);

        ...
        // Here is some code that updates Users table in a short loop
        ...

        stmtQueryHouse = conn.prepareStatement(queryHouse);
        stmtQueryHouse.setInt(1, 1); 
        rs = stmtQueryHouse.executeQuery();
        if(rs.next())
        {
            long houseMoney = rs.getLong("house_money");
            houseMoney += houseValue;

            stmtUpdateHouse = conn.prepareStatement(updateHouse);
            stmtUpdateHouse.setLong(1, houseMoney);
            stmtUpdateHouse.setInt(2, 1); 
            stmtUpdateHouse.executeUpdate();
        }
        else
        {               
            throw new SQLException("Failed to update house: unable to query house table");
        }

        conn.commit();
        result = true;
    }
    catch(SQLException e)
    {           
        logger.warn(getStackTrace(e));
        try{conn.rollback();}catch(SQLException excep)
        {
            logger.warn(getStackTrace(excep));
        }
    }
    finally
    {   
        DbUtils.closeQuietly(rs);
        DbUtils.closeQuietly(stmtQueryHouse);
        DbUtils.closeQuietly(stmtUpdateUsers);
        DbUtils.closeQuietly(stmtUpdateHouse);
        try { conn.setAutoCommit(true); } catch (SQLException e) { /* quiet */ }
        DbUtils.closeQuietly(conn);         
    }

    return result       
}

这个方法可以从多个线程调用,房子表只是一个保存总收入的单行表。它由不同的线程更新。

问题是 stmtQueryHouse.executeQuery() 返回空集,这种情况不应该发生,因为 house 表总是有(自数据库创建以来)一行被更新(只有 house_money 列被更新)。

当我在 Windows(JDBC 驱动程序 + mysql 5.5.13)上运行此代码时,它工作正常,但是当我在 CentOS(相同的 JDBC 驱动程序 + mysql 5.1.57)上运行它时,它经常返回空结果集(如果不是总是)。知道出了什么问题或者我如何检查问题出在哪里?也许我应该使用 select 进行更新,但是为什么它在 Windows 上有效而不在 Linux 上有效?我很感激任何帮助。提前致谢。

I have following code:

public boolean updateDatabase(long houseValue, List<Users> userList)
{
    boolean result = false;
    Connection conn = null;
    PreparedStatement stmtUpdateUsers = null;
    PreparedStatement stmtQueryHouse = null;
    PreparedStatement  stmtUpdateHouse = null;
    ResultSet rs = null;

    String updateUsers = "UPDATE users SET money = ? WHERE username = ?";
    String queryHouse = "SELECT * FROM house WHERE house_id = ?";
    String updateHouse = "UPDATE house SET house_money = ? WHERE house_id = ?";

    try
    {
        conn = getConnectionPool().getConnection();
        conn.setAutoCommit(false);      

        stmtUpdateUsers = conn.prepareStatement(updateUsers);

        ...
        // Here is some code that updates Users table in a short loop
        ...

        stmtQueryHouse = conn.prepareStatement(queryHouse);
        stmtQueryHouse.setInt(1, 1); 
        rs = stmtQueryHouse.executeQuery();
        if(rs.next())
        {
            long houseMoney = rs.getLong("house_money");
            houseMoney += houseValue;

            stmtUpdateHouse = conn.prepareStatement(updateHouse);
            stmtUpdateHouse.setLong(1, houseMoney);
            stmtUpdateHouse.setInt(2, 1); 
            stmtUpdateHouse.executeUpdate();
        }
        else
        {               
            throw new SQLException("Failed to update house: unable to query house table");
        }

        conn.commit();
        result = true;
    }
    catch(SQLException e)
    {           
        logger.warn(getStackTrace(e));
        try{conn.rollback();}catch(SQLException excep)
        {
            logger.warn(getStackTrace(excep));
        }
    }
    finally
    {   
        DbUtils.closeQuietly(rs);
        DbUtils.closeQuietly(stmtQueryHouse);
        DbUtils.closeQuietly(stmtUpdateUsers);
        DbUtils.closeQuietly(stmtUpdateHouse);
        try { conn.setAutoCommit(true); } catch (SQLException e) { /* quiet */ }
        DbUtils.closeQuietly(conn);         
    }

    return result       
}

This method can be called from multiple threads, house table is just a one row table which holds total earned money. It gets updated by different threads.

Problem is that stmtQueryHouse.executeQuery() returns empty set, and it should not happen, because house table always have (since database creation) one single row that gets updated (only house_money column is updated).

When I run this code on windows (JDBC driver + mysql 5.5.13) it works fine, but when I run it on CentOS (same JDBC driver + mysql 5.1.57) it returns empty result set very often (if not always). Any idea what is going wrong or how could I check where is the problem? Maybe I should use select for update, but then why it works on windows and not on linux? I appreciate any help. Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半世蒼涼 2024-11-26 22:40:41

查看mysql通用查询日志是否有错误?

我意识到这本身不是您的问题,但如果您有另一张表,每个房屋只有一行,那么在我看来,将 house_money 移动到您的主 中会更有意义房子

Look in the mysql general query log for any errors?

I realize this isnt your question per se, but if you have another table with just a single row for each House, it sounds to me that it would make more sense to move house_money into your main house table

情话已封尘 2024-11-26 22:40:41

我想说这一种方法做得太多了。

我将连接传递给三个单独的方法,并在所有方法之外管理事务。

我想知道是否有一种优化可以消除其中一项更新。

我想对所有这些进行批处理,这样我就不会为每个用户进行往返。随着用户数量的增加,它的性能会很差。

I'd say this one method is doing far too much.

I'd pass in the Connection to three separate methods and manage the transaction outside all of them.

I'd wonder if there's an optimization that would eliminate one of the UPDATES.

I'd want to batch all these so I didn't do a round trip for each and every user. It'll perform poorly as the # of users increases.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文