从死锁中恢复

时间:2015-04-16 06:19:16

标签: java mysql deadlock database-deadlocks

我有一个2线程进程从MySQL表访问数据。 正如MySQL可能的那样,我有时会陷入僵局。

现在,我所做的是: 在死锁的情况下,只需将所有行更新回其先前的状态,然后重新启动该过程。

但我怀疑,出现了问题,因为在一个案例中我想要更新1300-ish数据,在死锁之后,计数显示为1700-ish。

因此,可能通过调用该进程的第二个实例来处理一些数据两次。

我应该在重新启动进程之前终止所有正在运行的线程吗?

编辑:

我正在使用在id上创建索引的InnoDB。 线程应该获得限制500中的任何行,并且处理标志“N”在那里并处理它们然后将各个行更新为“Y”。

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

我仍然在resultset.updaterow()

上陷入僵局

表:

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

3 个答案:

答案 0 :(得分:1)

这似乎是一个交易问题。在访问信息之前,必须在程序/控制器中使用必要的逻辑。如果您尝试访问正在使用的行,您始终(有时不会)会看到此错误。有时会产生它,因为两个线程无法同时访问,但这是一种不正确的行为

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

答案 1 :(得分:0)

我遇到了这里概述的mysql死锁问题: What are 'best practices' for dealing with transient database errors in a highly concurrent Rails system?

我最终找到的内容在我自己的答案中解释{。{3}}。

简而言之,这些表没有以最佳方式编制索引,这意味着查询运行速度要慢得多(并且长时间运行的查询会使死锁更有可能)。添加正确的索引完全消除了死锁问题。

答案 2 :(得分:0)

我遇到的死锁问题与交易有关。

我所做的是将我的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);