【发布时间】:2015-08-03 11:28:11
【问题描述】:
我熟悉使用 ADO (dbGo) 的 Microsoft SQL 服务器世界,并且我为该环境编写了许多应用程序。现在我有一个旧版 Delphi 7 应用程序,其中包含我必须维护的 Firebird 2.5 数据库。
但我发现如果 2 个客户端应用程序执行此操作:
SQLQuery.SQL.Text := 'Update mytable set field1 = 11 where keyfield = 99'
SQLQuery.Execute;
几乎在同一时间,第二个应用程序立即出现“死锁”错误。在 SQL Server 中,会有一个等待期
ADOConnection.Isolationlevel = ilCursorstability;
ADOConnection.CommandTimeout := 5;
在第二个客户端应用程序中引发任何异常之前。异常处理可能涉及在批处理过程中被视为非常不寻常的情况下的回滚。这是合理。 5 秒对于计算机处理时间来说是非常长的时间。
现在我在 Firebird 客户端上使用相同方法的尝试没有结果,因为“死锁”(实际上是正在使用的记录)立即发生。
如果无法将数据库引擎配置为等待一段时间来改善情况(释放记录锁),那么现在的责任必须落在客户端应用程序开发人员身上,他们必须编写极其缓慢的代码来克服在我看来的问题是火鸟的主要失败。
一旦检测到“死锁”,除非断开连接组件,否则条件不会清除
while rowsupdated = 0 and counter < 5 do
begin
try
rowsupdated := SQLQuery.Execute;
except
SQLConnection.Connected := False;
SQLConnection.Connected := True;
end;
Inc(Counter)
end;
当您在 Firebird 中没有任何实质性的锁容错时,如何使用 Delphi 中的 DBX 来制作强大的多用户表更新客户端?
【问题讨论】:
-
有一段时间没有使用 FirebirdSQL,但请记住,有一个 SELECT FOR UPDATE WITH LOCK 功能可以在 SQL 级别使用。结帐:firebirdsql.org/refdocs/langrefupd25-notes-withlock.html
-
DBExpress 到 Interbase 连接的 IsolationLevel 默认值为
ReadCommitted,相当于ilCursorstability。CommandTImeout不存在,但是有WaitOnLocks,默认为True,意思是指定一个事务在遇到与另一个事务的锁冲突时等待访问(根据文档)。这两个都在连接的参数中设置。 -
尽管我尝试以不同方式配置客户端,但它似乎默认为
nowait。请参阅下面我对@TOndrej 的问题。
标签: delphi firebird interbase dbexpress