【问题标题】:Java MySQL possible to cause a deadlock?Java MySQL可能导致死锁吗?
【发布时间】:2015-12-18 19:18:11
【问题描述】:

我编写了一个 java 应用程序,其中不同的线程(每个线程都有一个使用连接池 c3p0 的连接对象)调用类似的方法。

伪代码:

void example(Connection connection) {
    connection.update("LOCK TABLES Test WRITE");
    resultSet = connection.query("SELECT * FROM Test WHERE Id = '5'");

    if (resultSet.next()) {
        connection.update("UPDATE Test SET Amount = '10' WHERE Id = '5'");
    } else {
        connection.update("INSERT INTO Test (Id, Amount) VALUES ('5', '10')");
    }

    connection.update("UNLOCK TABLES");
    connection.commit();
}

还有一些其他类似的方法可以锁定表,选择/更新/插入某些内容,然后解锁表。目的是防止竞争条件和死锁。

当我从不同的线程调用这样的方法时,是否可能导致 MySQL 死锁?如果是的话,你能给我一个例子吗(导致死锁的两个事务的时间)?我是一个有死锁的菜鸟,我想进入这个。

编辑:明确应该在方法中使用的连接是从调用该方法的线程传递的。

编辑:将 READ 替换为 WRITE

【问题讨论】:

  • 我假设“update()”和“query()”方法使用相同的连接(不是从池中获取新连接)。
  • @slambeth 是的,调用该方法的线程从池中获取连接对象并将其传递给该方法。该方法中的整个代码都使用此连接。自动提交为假。
  • @Jas 是的,我使用 InnoDB。

标签: java mysql multithreading transactions deadlock


【解决方案1】:

这里不能。由于没有复杂的逻辑,并且代码在更新后立即提交,因此必须始终有一个线程通过。即使在更复杂的场景中,它也可能需要我认为 MySql 不支持的最高序列化级别(可重复读取)。

【讨论】:

    【解决方案2】:

    这可能会造成死锁。实际上我不确定它是否会执行,因为您需要获取“写”锁,而不是“读”。

    【讨论】:

    • 你是对的,但我认为我必须同时阻止(READ 和 WRITE)以防止出现竞争条件。
    • 锁定类型指定不标识其他会话可以做什么,它标识“你”可以做什么。 “WRITE”是更高级别的锁——它允许你写,并完全阻止来自其他会话的访问:
    • 谢谢!我不知道(已编辑)。回到我的问题,该代码是否可能导致死锁?
    • 就像你编辑后写的那样简单......我不相信 - 但这只是你的伪代码。当涉及多个表时,它会变得更丑陋,和/或更新的表上存在尝试更新自身的触发器。
    • 该项目的 MySQL 部分与伪代码一样简单。实际上还有更多的表,但它们是独立的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多