java - `SELECT ... FOR UPDATE`锁什么时候释放?

标签 java mysql jdbc locking

我正在开发一个允许多个用户访问一个数据库 (MySQL) 的程序,并且在不同时间我得到一个 SQLException: Lock wait timeout exceeded .

使用以下方法创建连接:

conn = DriverManager.getConnection(connString, username, password);
conn.setAutoCommit(false);

所有调用都通过这段代码:

try { 
    saveRecordInternal(record);
    conn.commit();
} catch (Exception ex) {
    conn.rollback();
    throw ex;
}

在哪里saveRecordInternal有一些内部逻辑,保存给定的记录。一路上的某个地方是我怀疑是问题的方法:

private long getNextIndex() throws Exception {
    String query = "SELECT max(IDX) FROM MyTable FOR UPDATE";
    PreparedStatement stmt = conn.prepareStatement(query);

    ResultSet rs = stmt.executeQuery();
    if (rs.next()) {
        return (rs.getLong("IDX") + 1);
    } else {
        return 1;
    }
}

此方法由 saveRecordInternal 调用如果需要,在它运行的某个地方。 由于目前我无法控制的原因,我不能使用自动增量索引,而且无论如何,某些内部程序逻辑需要要插入的索引。

我假设有 conn.commit()conn.rollback() called 足以释放锁,但显然不是。所以我的问题是 - 我应该使用 stmt.close()rs.close()里面getNextIndex ?是在提交或回滚事务之前释放锁,还是只是确保在调用 conn.commit() 时确实释放了锁?或 conn.rollback()

我还有什么遗漏/做错了吗?

编辑:在发生锁定时,所有连接的客户端似乎都有响应,当前没有任何查询正在进行,但关闭所有连接的客户端确实可以解决问题。这让我认为即使事务(据说?)通过提交或回滚结束,锁也会以某种方式保留下来。

最佳答案

即使不关闭 StatementResultSet 是个坏主意,但该函数似乎并不对您收到的错误负责。函数 getNextIndex() 正在创建本地 StatementResultSet 但没有关闭它。在那里关闭它们或在 saveRecordInternal() 中创建那些 StatementResultSet 对象并作为参数传递,如果在起点创建并重用则更好一次又一次。最后,在不再需要时关闭它们(按以下顺序 - ResultSet、Statement、Connection)。

错误只是意味着某个数据库对象(Connection、Table、Row 等)上存在锁,而另一个线程/进程同时需要它但不得不等待(已经锁定)但由于时间超过等待超时预期的等待。

引用,How to Avoid Lock wait timeout exceeded exception.?了解更多关于这个问题。

总而言之,这是您的环境特定问题,需要在您的机器上调试并打开大量日志记录。

希望对您有所帮助!!

关于java - `SELECT ... FOR UPDATE`锁什么时候释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34448811/

相关文章:

java - 如何将类对象转换为通用对象类型?

mysql - 本月总和与之前的差异[mysql]

java - 使用 ColdFusion 和 Oracle 瘦客户端的数据库连接加密和完整性

java - 如何使用 JDBC 驱动程序和 SSL 连接连接到 Sybase ASE

java - Java中获取类的正则表达式

java - 使用 for 循环更新总和(例如 spaces = spaces + 2)

使用 Hamcrest 进行 Java Junit 测试 : cannot create compositional Matcher

PHP比较两个表的结果

php - 动态过程语句错误

multithreading - servlet/jdbc的正确设计和并发问题