从死锁中恢复

Recovery from deadlock

我有一个 2 线程进程从 MySQL table 访问数据。 由于 MySQL 有可能,我有时会陷入僵局。

现在,我准备好的是: 在死锁的情况下,只需将所有行更新回它们以前的状态,然后重新启动进程。

但我怀疑出了点问题,因为在一个案例中我想更新 1300 左右的数据,但在死锁后计数显示为 1700 左右。

所以,一些数据可能通过调用进程的第二个实例被处理了两次。

我应该在重新启动进程之前杀死所有 运行 线程吗?

编辑:

我正在使用 InnoDB 并在 id 上创建索引。 线程应该获取限制为 500 且带有已处理标志 'N' 的任何行并处理它们,然后将各个行更新为 'Y'.

我还更新了一个进程 ID,以指示哪个线程应该对哪些行执行操作。

我仍然在 resultset.updaterow()

上陷入僵局

Table:

create table Mail(
id integer not null auto_increment primary key,
from_eaddress varchar(50) not null,
to_address varchar(50) not null,
process_flg varchar(1) not null,
process_id varchar(50) default null,
time_stamp datetime default null,
index(id)
) engine=InnoDB;

最后这是我的工作代码: https://github.com/codezero10/MailQueue/tree/master

这似乎是一个交易问题。在访问信息之前,您必须在 program/controller 中使用必要的逻辑。如果您尝试访问正在使用的行,您总是(不是有时)会看到此错误。有时会因为两个线程不能同时访问而产生,但这是不正确的行为

注意:现代 RDBMS 自行管理其内存。因此,您需要实施一种预防算法,例如 Mutual exclusión

我遇到了一个 mysql 死锁问题,概述如下:

我最终发现的内容在我自己的回答中得到了解释

简而言之,这些表没有以最佳方式索引,这意味着查询 运行 比它们本来可以的慢得多(而且长 运行 查询更有可能导致死锁)。添加适当的索引完全消除了死锁问题。

我遇到的死锁问题与事务有关。

我所做的是将我的 Update 语句包装在一个事务块中,然后死锁就消失了。

        conn.setAutoCommit(false);// start transaction
        conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); 
        String sql2="update EmailQueue set process_flg='Y' where id="+id;
        //getting deadlocks here
        stmt=conn.createStatement();
        stmt.executeUpdate(sql2);
        conn.commit();// complete transaction
        conn.setAutoCommit(true);