首页 > 解决方案 > firebird - 死锁更新与并发更新冲突

问题描述

我正在维护一个旧软件(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;
}

那么,为什么我们会超时?它不应该等待一个事务被提交来提交下一个事务吗?

标签: firebirddeadlockfirebird2.5

解决方案


当多个事务想要修改同一行时,会发生“死锁更新与并发更新冲突”。只有一个更新程序可以真正更改行并提交。只要第一个事务尚未提交,第二个事务中的更新就会等待(无限期或直到配置的超时)。一旦第一个事务提交,第二个事务中的更新就会以这个错误结束(如果第一个事务已经回滚,第二个事务会继续)。

如果这种情况最近开始发生,您需要确定发生了什么变化。另一个工具是否也开始写入数据库,用户数量是否增加,您是否升级了某些东西(例如 Firebird,或 Firebird ado.net 提供程序版本等),您是否进行了更改,导致长时间运行的事务执行更新?

您的应用程序代码将需要更改以自动重试此错误。还要确保您的事务在时间上不会太“长”(事务越长,发生此类错误的可能性就越大)。此外,您可以尝试将事务行为从 更改FbTransactionBehavior.RecVersionFbTransactionBehavior.NoRecVersion,但这可能会在读取当前由并发事务更新的记录时引入等待,并且如果记录由具有较新交易 ID 的交易。

另请参阅http://www.firebirdfaq.org/faq151/,Firebird中的事务:ACID、隔离级别、死锁和解决更新冲突事务语句


推荐阅读