我正在维护一个旧软件(Firebird 2.5和C#.net)。最近,我们收到许多“死锁更新与并发更新冲突”错误。我检查了交易设置。它没有设置等待超时选项:
public override IDbTransaction BeginTransaction(IDbConnection conn)
{
FbTransaction trans = null;
if (conn.State != ConnectionState.Open)
conn.Open();
FbTransactionOptions op = new FbTransactionOptions();
op.TransactionBehavior = FbTransactionBehavior.ReadCommitted | FbTransactionBehavior.RecVersion;
trans = ((FbConnection)conn).BeginTransaction(op);
return trans;
}
那么,为什么我们会超时?它不应该等待一个事务提交以提交下一个事务吗?
答案 0 :(得分:1)
当多个事务要修改同一行时,发生“死锁更新与并发更新冲突”。只有一个更新程序才能真正更改行并提交。只要第一个事务尚未提交,第二个事务中的更新就会等待(无限期或直到配置的超时)。第一个事务提交后,第二个事务中的更新将以该错误结束(如果相反,第一个事务已回滚,则第二个事务将继续)。
如果最近开始发生这种情况,则需要确定发生了什么变化。是否有其他工具也开始写入数据库,用户数量是否增加,是否升级了某些内容(例如Firebird或Firebird ado.net提供程序版本等),是否进行了更改,导致长时间运行的事务执行了更新? ?
将需要更改您的应用程序代码,以自动重试此错误。另外,请确保您的交易时间不是太长(交易时间越长,发生此类错误的机会就越大)。此外,您可以尝试将事务行为从FbTransactionBehavior.RecVersion
更改为FbTransactionBehavior.NoRecVersion
,但是在读取当前由并发事务更新的记录时可能会导致等待,并且如果发生以下情况,它实际上会增加更新冲突的发生记录是由具有新交易ID的交易更新(并提交)的。
另请参见http://www.firebirdfaq.org/faq151/,Transactions in Firebird: ACID, Isolation levels, Deadlocks, and Resolution of update conflicts和Transaction Statements。