Java 生成序列号遇到死锁

Java 生成序列号遇到死锁,java,db2,deadlock,Java,Db2,Deadlock,我们需要为我们的交易生成序列号。当并发用户试图同时预订事务时,我们遇到了sqlcode=-911、sqlstate=40001、sqlerrmc=2(死锁)。当前发生死锁是因为它正在读取和更新同一条记录。我们如何设计它以防止死锁?围绕这个问题有很多方法,有些方法性能不如其他方法 如果所有对象都锁定在同一层次序列中,则可以防止死锁。[ 但是,完全防止死锁的问题解决方案的性能通常不如简单地回滚事务并重试。您需要测试您的解决方案 如果您正在寻找一种数据端解决方案,一种老式的(可能性能不佳)方法是通过建

我们需要为我们的交易生成序列号。当并发用户试图同时预订事务时,我们遇到了sqlcode=-911、sqlstate=40001、sqlerrmc=2(死锁)。当前发生死锁是因为它正在读取和更新同一条记录。我们如何设计它以防止死锁?

围绕这个问题有很多方法,有些方法性能不如其他方法

如果所有对象都锁定在同一层次序列中,则可以防止死锁。[

但是,完全防止死锁的问题解决方案的性能通常不如简单地回滚事务并重试。您需要测试您的解决方案

如果您正在寻找一种数据端解决方案,一种老式的(可能性能不佳)方法是通过建立严格的锁序列来强制获取新事务ID

一个快速的ish解决方案(在发布到生产环境之前在负载下测试!)可以是使用
事务
边界,并让一个控制行充当网守。下面是一个愚蠢的示例,演示了基本技术。 它没有错误检查,回收重影ID的代码不在本示例的范围内:

DECLARE @NewID INTEGER;
BEGIN TRANSACTION;
UPDATE [TABLE] SET [LOCKFLAG] = CURRENT_TIMESTAMP WHERE [ROW_ID] = 0;
SELECT @NewID = MAX([ROW_ID])+1 FROM [TABLE];
INSERT INTO [TABLE] ([ROW_ID]) VALUES (@NewID);
UPDATE [TABLE] SET [LOCKFLAG] = NULL WHERE [ROW_ID] = 0;
COMMIT TRANSACTION;
我们的想法是让这个原子的、单线程的、序列化的操作在持续时间上非常非常短——只做安全地保留ID和避免干扰所需的事情

通过第一步更新第0行,如果所有ID请求都符合此标准,则竞争用户只需在第一步后排队

一旦你保留了你的ID,你可以去做你想做的事情,你可以使用一个新的事务来更新你创建的行

您需要涵盖后续步骤决定回滚的情况,因为表中现在会有一个重影行。您需要一种方法来回收这些重影行;可以使用多种简单的解决方案。

创建一个包含单个数据行的“种子”表。 此“种子”表行保存“下一个顺序”值

当您希望使用“Next Sequential”值插入新的业务数据行时,请执行以下步骤

1) 。在“种子”表上打开一个光标进行更新,并获取当前行。这使您可以独占控制种子值。 2) 。您将使用此获取的行作为“下一个值”…但是在这样做之前 3) 。增加获取的“下一个值”并提交更新。此提交将关闭光标并使用新的“下一个值”释放种子行


您现在可以自由使用“下一个价值”.

请提供更多信息,说明到底是什么导致了死锁,调用代码是什么,数据库设计是什么?目前没有什么可以做的。在这种情况下,通常要做的就是捕获异常并重试。另一种方法是在数据库表中创建事务,让数据库本身生成primary键。您可以使用Synchronized关键字防止死锁。Synchronized块确保只有在当前线程成功进入对象的监视器后,才会调用作为对象成员的方法。一旦线程在实例上输入任何同步方法,其他线程就不能输入任何其他同步方法。O您可能遇到过描述此方法的其他名称:高水位线、序列ID表和主事务表。++Hector用于更有效地使用流程专用表。不确定光标是否比简单事务边界更有效,但您可以同时使用这两个名称来查看在您的环境中工作的情况。Ive u在许多企业生产系统中使用了游标更新方法。这种方法以有序的方式排队请求“下一个值”,我看到它在大型机z/OS DB2上支持非常高的TPS 100->1000。非常好。我想我会增加我个人的“额外时间”要做的事情列表尝试在这两种技术之间进行性能比较。因为,知道很好,玩起来很有趣。:-)