当只有一个事务写入数据库时,什么可以触发Firebird上的死锁消息?
我正在构建一个2.1应用程序,它的后端是用Delphi2010编写的,它位于FireBird2.1数据库之上。我得到一个并发更新错误,我无法理解。也许有人可以帮我调试这个问题,或者解释可能导致消息的场景。
我正在尝试对单个记录上的单个字段进行更新。
UPDATE USERS SET passwdhash=? WHERE (RECID=?)我所看到的信息是标准的:
deadlock
update conflicts with concurrent update
concurrent transaction number is 659718
deadlock
Error Code: 16我明白它告诉了我什么,但我不明白为什么我在这里看到它,因为我不知道并发的更新。
这是我调查的事。
我启动了我的应用服务器并检查了这个查询的结果:
SELECT
A.MON$ATTACHMENT_ID,
A.MON$USER,
A.MON$REMOTE_ADDRESS,
A.MON$REMOTE_PROCESS,
T.MON$STATE,
T.MON$TIMESTAMP,
T.MON$TOP_TRANSACTION,
T.MON$OLDEST_TRANSACTION,
T.MON$OLDEST_ACTIVE,
T.MON$ISOLATION_MODE
FROM MON$ATTACHMENTS A
LEFT OUTER JOIN MON$TRANSACTIONS T
ON (T.MON$ATTACHMENT_ID = A.MON$ATTACHMENT_ID)结果显示了许多连接,但其中只有一个在MON$TRANSACTION字段中有非NULL。这个连接是我从IBExperts用来查询监视器表的连接。
我是否正确地认为,没有活动事务的连接可以被忽略为没有造成僵局的原因?
接下来,我在行上放置一个断点,在我的应用服务器中提交UPDATE语句,并执行触发它的请求。当断点停止应用程序时,我将重新运行上面的Monitor-query。
这一次,我可以看到另一个事务正在活动,正如我所期望的那样:

然后,我让我的appserver执行更新并获取错误消息,如上面所示。
当只有一个写入事务时,什么可以触发死锁消息?或者还有更多,而我误解了输出?关于如何调试这一点,还有其他建议吗?
发布于 2015-02-28 13:04:35
Firebird使用MVCC (多版本并发控制)作为其事务模型。其中一个特性是--取决于事务隔离--您只会看到在事务启动时提交的最后版本(一致性和并发性隔离级别),或者在语句启动时提交的版本(读提交)。对记录的更改将创建记录的新版本,只有在其他活动事务被提交(然后仅用于已提交的读事务)时,该记录才会变得可见。
作为一项基本规则,只能有一个未提交的记录版本。因此,对于其中一个事务,两个事务更新相同记录的尝试都将失败。由于历史原因,这些类型的错误被归为死锁错误族,即使它实际上不是正常并发白话中的死锁。
根据您的事务隔离,此规则实际上具有更多的限制性:对于一致性和并发级别,也不可能有新的提交版本的记录对您的事务不可见。
我猜对你来说发生了这样的事:
(注意,步骤1+3和步骤2的顺序可能不同(如1,3,2,2,1,3))
步骤5失败,因为在步骤3中创建的新版本在事务2中不可见。如果已使用read提交,则步骤5将成功,因为此时新版本对事务是可见的。
https://stackoverflow.com/questions/28746317
复制相似问题