MySQL InnoDB数据库死锁的应对

根据How to Cope with Deadlocks的解释:

   InnoDB uses automatic row-level locking. You can get deadlocks even in the case of transactions
   that just insert or delete a single row. That is because these operations are not really “atomic”;
   they automatically set locks on the (possibly several) index records of the row inserted or deleted.

以前在数据库领域积累的经验:为了避免数据死锁,尽量按照一致的顺序修改多张表。在此,该经验似乎无法奏效。当前MetaSeeker服务器的并发访问量很高,很容易观察到仅仅修改一条记录就引发死锁的情形。为了应对死锁,主要采用三个措施:

  1. Java应用层并发控制,对一些没有必要并发的情形使用适当的synchronized操作符进行控制
  2. Working around MySQL error “Deadlock found when trying to get lock; try restarting transaction”所述,用try...catch检测死锁,如果发生,则重新提交
  3. 为特殊情形准备一张作为信号灯(semaphore,信号量)的表,每个事务开头先修改该表,实际上,将事务顺序化了。

下面是监视死锁的Java代码片断

    } catch (SQLException e) {
      String sqlState = e.getSQLState();
      if ("40001".equals(sqlState)) {
      ....
      }
  }