处理JDBC可能出现的死锁的最佳方法

时间:2019-05-07 13:24:59

标签: java mysql sql jdbc database-deadlocks

因此,我最近发现了deadlocks的存在。尽管我从来没有一个人,但我知道这可能是测试环境之外的一个问题,许多用户同时访问。

我学到了一些技巧,以使它发生的次数更少,但并非永远不会发生,因此我担心正确处理该问题。因此,假设我们正在通过JDBC访问数据库。

documentationofficial examples中,我都没有找到处理死锁的引用,因为它们只是回滚(或打印和异常,如果不可能的话):

} catch (SQLException e ) {
        JDBCTutorialUtilities.printSQLException(e);
        if (con != null) {
            try {
                System.err.print("Transaction is being rolled back");
                con.rollback();
            } catch(SQLException excep) {
                JDBCTutorialUtilities.printSQLException(excep);
            }
        }
    }

据我了解,阅读文档时,如果executeUpdate()方法发现死锁,它将不会以任何方式再次尝试。

搜索不同的解决方案时,我发现了this approach,它将整个过程包装成一个带有计数器的循环,并在每次尝试之间进行睡眠

所以,我的目的是:

  1. 除了抛出异常外,JDBC是否还以任何方式处理死锁?任何语言的图书馆都(至少可以选择)重试查询吗?
  2. 在具有JDBC实现的对死块敏感的情况下,您将如何处理呢?
  3. 您是否在自定义数据库访问方法中防止这种情况?另外,您是否拥有它们?还是每次访问数据库时都使用默认行?
  4. 当所需的行被解锁时,为什么数据库引擎不重新启动受害者查询?

编辑:我在MySQL documentation上找到了这个

  

如果由于死锁而失败,则始终准备重新发出事务。死锁并不危险。再试一次。

建议在应用程序代码上进行处理。

有什么想法吗?预先谢谢你。

1 个答案:

答案 0 :(得分:1)

尽管缓解死锁可能有一定价值,但在设计良好的系统中死锁应该非常少见。您提到了学习一些避免方法的提示,但这是我自己的列表:

  • 在许多系统中,在更新其子表之前,您始终首先锁定顶级对象/实体。例如,一个订单处理系统可能有许多不同的表来保存数据,但是您总是会尝试首先锁定顶级订单实体。
  • 更一般而言,如果所有访问数据库的代码始终以相同的顺序锁定实体,则不会发生死锁。 (例如,如果一个连接按该顺序锁定表A和C的行,而另一个连接按顺序锁定A,B和C,则无论这些锁定的时间如何,都不会发生死锁。)
  • 系统还可以消除大多数锁定。例如,如果数据 被附加而不是被编辑,则不需要锁定。
  • 在NoSQL数据库中,所有相关数据通常都保存在一个对象中。不需要锁定,数据库甚至可能不支持锁定。

如果允许用户对数据库进行临时写访问,那么您当然无法控制导致死锁的因素。但是我从未见过允许它使用的严肃系统。

因此,不必担心响应死锁,而应将所有精力都花在完全避免死锁上。当您看到死锁时,您会在系统中发现允许死锁发生的错误。