火鸟强行消除僵局

时间:2012-10-09 10:16:52

标签: delphi deadlock firebird database-deadlocks

我正在使用Delphi IBQuery和IBTransaction组件使用此查询更新数据库中的所有记录:

UPDATE INVOICES SET BLK = 0;

当用户打开另一个客户端应用程序时,它会在某些记录上留下死锁(由用户打开)。

问题在于我的应用程序必须完成上面的查询。

是否有可能实施某种解决方案以强制删除死锁?例如一个SQL查询?

Firebird版本为2.1.2.18118 在Windows 7上运行

2 个答案:

答案 0 :(得分:5)

最好的选择是重构这些应用程序。

FB / IB的自然模式是两个并行交易。

  • #1 将是只读读取提交,永不关闭,它只会用于读取数据。

  • #2 将以短暂的突发方式打开/提交以实际应用更改。 “正在编辑”的任何数据本身都不会打开交易。

长期编辑事务通过阻止垃圾收集并强制它(和索引)包含大量虚假数据来影响数据库。

我不知道如果你能通过IBX + IBQuery +这样做,那么像TUpdateSQL这样的自定义更新查询是在bDE时代。第三方FB连接库通常支持双事务模式。

然而,这种方法强加了一个非常具体的模式,说明应用程序的设计方式,并使Firebird无法保证数据的一致性 - 这现在是您的应用程序的负担。评论带来了一个很好的链接:http://tech.groups.yahoo.com/group/firebird-support/message/94903


在现代Firebird中,如果您具有数据库管理员/所有者角色,则可以强行删除事务。阅读监控表。请注意,2.5.1中存在错误,因此您可能需要等待2.5.2版本。

但是,如果您强制回滚这些事务 - 应用程序将如何表现?用户仍然会编辑,只是突然发现他的大部分变化都丢失了。

PS。 http://www.sql.ru/forum/actualthread.aspx?tid=910920此代码使用mon$transactions将事务映射到连接,然后强制断开违规应用程序。如果直接delete from mon$transactions where...无法使用,那么这将是剩下的选项。

PPS。由于FB 2.1长时间交易应该每隔几分钟(甚至是r / o)更好地提交(和关闭)。原因是它们碰巧使用BLOB计算可能导致数据库无法控制的增长,只能通过事务结束重置。虽然这可能会触发重新读取所有db-aware控件,但是在没有像MIDAS ClientDataset这样的中间缓存的情况下处理事务,这可能仍然比数据库膨胀更好,在一些罕见的情况下报告速度非常快。

答案 1 :(得分:0)

我已经设法通过一些用户交互来决定问题。

首先,我正在检查用户是否正在编辑任何发票。

SELECT COUNT(*) FROM MON$RECORD_STATS WHERE MON$STAT_GROUP = 2 AND MON$RECORD_UPDATES <> 0

然后,如果在上述查询执行过程中发现任何锁定,我向用户显示一条消息“请关闭所有已打开的发票...”,然后创建 failed.sql 文件,如果用户刚刚终止我的应用程序,则必须执行该查询。

在我的应用程序的下一次启动时,我检查 failed.sql 文件是否存在,并尝试使用死锁检查再次执行它。

因此,我的应用程序对用户来说变得更加烦人,但它不会使任何无人值守的操作都会给用户带来挫折感。