首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >多线程-避免和处理数据库死锁

多线程-避免和处理数据库死锁
EN

Stack Overflow用户
提问于 2009-12-08 11:09:38
回答 5查看 7.2K关注 0票数 6

我正在寻找一种处理Java 6应用程序中的数据库死锁的好策略;几个并行线程可能同时写入同一个表。如果检测到死锁,数据库(Ingres )将随机关闭其中一个会话。

考虑到以下要求,处理死锁情况的可接受技术是什么?

总时间应保持为合理的possible

  • killing,会话将导致大量(可测量的)回滚

  • 时间线程无法

相互沟通,即策略应该是自主的

到目前为止,我想出的策略是这样的:

代码语言:javascript
复制
short attempts = 0;
boolean success = false;
long delayMs = 0;

Random random = new Random();
do {
    try {
        //insert loads of records in table 'x'
        success = true;
    } catch (ConcurrencyFailureException e) {
        attempts++;
        success = false;
        delayMs = 1000*attempts+random.nextInt(1000*attempts);

        try {
                Thread.sleep(delayMs);
            } catch (InterruptedException ie) {
        }
    }
} while (!success);

它还能有任何改进吗?例如等待固定数量(魔法数)的秒。有没有不同的策略能产生更好的效果?

注:几种数据库级技术将用于确保死锁在实践中非常罕见。此外,应用程序将试图避免调度同时写入同一表的线程。上述情况只是“最坏的情况”。

注释:插入记录的表被组织为堆分区表,没有索引;每个线程将在自己的分区中插入记录。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-12-08 11:19:07

一种常用的方法是某种形式的指数后退.与其使用1000*attempts+random,不如将延迟作为尝试次数的指数函数。这确保了在第一次或两次尝试中延迟最小,可能只是运气不好而陷入僵局,但当连接明显拥堵时,延迟会更大。

当然,另一种方法是尝试安排数据库访问,这样死锁就不会发生。但是,如果不知道查询是做什么的(以及它们是如何执行的,以及它们何时执行),就不可能知道是否可以这样做。

票数 11
EN

Stack Overflow用户

发布于 2009-12-08 11:17:39

我们就是这样做的。循环并重试事务,直到事务完成为止。

我们没有随意拖延。

另外,我们在try块中执行提交,在异常处理程序中执行回滚操作。

当您拥有多个可锁定资源和多个并发事务时,死锁是不可避免的。这是锁争用的逻辑结果。

如果您避免了锁的争用(即悲观的表级锁定),那么您也倾向于防止并发性。如果可以定义不争锁的事务,则可以避免死锁。但是,并发访问相同的表几乎就是死锁的定义。

在加载时,插入(特别是堆表中的插入)可以(通常)并行进行,不会出现许多争用问题。如果延迟构建索引,则在插入期间没有其他更新。

因此,您可以通过删除索引、将组织更改为堆、装载多个并发进程(或线程,通常有多个进程更快)、然后构建索引(并可能重新组织表)来避免死锁。

在进行更新或删除时,帮助不大。

票数 1
EN

Stack Overflow用户

发布于 2009-12-08 11:18:10

如果不需要并发访问数据库,那么一个简单的解决方案可能是删除数据库并使用任务处理队列来更新数据库,通过队列序列化对数据库的访问。我意识到这将为您的应用程序引入一个异步元素,因此不适合大多数用户启动的应用程序或在线web应用程序,但对于批处理/脱机类型的应用程序可能值得考虑(虽然我意识到可能不是您想要的答案)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1866287

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档