我在寻找一个很好的策略处理数据库的僵局从Java6应用程序;几个平行的线可能,可能写入同一表格在同一时间。该数据库(安格尔RDMBS)将随机杀死的一次会议如果检测到一个僵局。

这将是一个可以接受的技术来处理的僵局状况,给出的以下要求?

  • 总经过的时间应该保持 作为小型合理的可能性
  • 杀死一届会议将产生一个 重要的(可测量的)rollback
  • 时间线已经没有办法
    彼即的 战略应该是自主的

迄今为止,该战略的我有东西沿着这些线:

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);

它可以改进的任何方式?例如在等待一个固定的数额(数)秒钟。是有一个不同的战略,这将产生更好的结果?

注: 几个数据库水平的技术将用来确保僵局,在实践中,非常罕见的。此外,应用程序将试图避免调度线,写入同一表格在同一时间。局势上将只是一个"最坏情况方案"。

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

有帮助吗?

解决方案

一个常用的办法是某种形式的指数后关闭。而不是你 1000*attempts+random 方法,做出延迟的指数函数的数次尝试。这将确保最少的等待时间在第一个或两个尝试,它可能只是运气不好,你陷入僵局,但是给了你多大的延误之后,当时很明显,连接的真是拥挤。

当然,另一种办法是尽量安排你的数据库访问,以便僵局不太可能发生。但不知道什么是您的查询做(以及如何,并且当他们在执行),这是不可能的来说,如果可以做的

其他提示

这就是我们做到了。循环,并重新交易,直到它完成。

我们没有惹随机的延迟。

此外,我们做的承诺内 try 块和rollback在例外处理程序。

当你有多个可上锁的资源和多种并行的交易,僵局是不可避免的。这是一个合乎逻辑的结果的争锁。

如果你避免竞争锁(即,悲观的表级锁定),那么你也倾向于防止并发。如果你可以定义的交易不争的锁,可以避免僵局。同时访问的同样的表格,但是相当多的定义的僵局。

装载时,插入(特别是在一堆表)可以(通常)进行没有多少竞争问题。如果你的延迟建立的指数,那么就没有其他更新在该插入。

所以,你可能可以避免的放弃索引,改变本组织的一堆、装载与多个并行进程(或螺纹,它通常更快有多个进程),然后建立您的指标(和可能的重组表),可能可以避免僵局。

当做更新或删除,没有多少帮助。

如果你不需要有并发数据库的访问一个简单的解决办法可能是删除它,并使用一任务的处理队数据库的更新相反,serialising数据库的访问通过的队列。我知道,这将引入一个步元到应用程序,并因此将不被适用于大多数用户发起的应用程序或网上网的应用程序,但可能值得考虑的一批/脱机类型应用程序(我意识到很可能不回答你在寻找尽管).

有一个数据库,如安格尔,你总是会得到一些僵局,因此你必须假定任何插入、更新或删除会失败,有一个试的策略,在地方(如在例)。你应该设计数据库,这样,竞争是最大限度地减少和僵局只发生很少。如果你不断地获取交易失败的后甚至几个重试,然后这是一个迹象,表明你需要做一些主要数据库的重新设计(或转移到一个系统如Oracle在那里通常有可能设计应用程序,以避免僵局,通过适用的行级锁定).

这是怎么?

short attempts = 0;
boolean success = false;
long delayMs = 0;

Random random = new Random();
do {
try {
     synchronized(ClassName.class) {
         //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);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top