首页 > 解决方案 > 使用多个连接时无法删除 Firebird 表

问题描述

我想安全地删除 Firebird 表。我有 3 个事务,一个用于重新创建表,一个用于对表执行某些操作(只需插入一行以保持简单),最后一个用于删除表。如果所有这些 txns 都是使用单个连接执行的,那么这些工作。如果我使用不同的连接,则 drop 命令失败

无等待事务上的锁冲突不成功的元数据更新对象表“DEMO”正在使用中

private static void Test() {
        using var conn1 = new FbConnection(ConnectionString);
        using var conn2 = new FbConnection(ConnectionString);
        using var conn3 = new FbConnection(ConnectionString);
        conn1.Open();
        conn2.Open();
        conn3.Open();
        ExecuteTxn(conn1, cmd => {
            cmd.CommandText = "recreate table demo (id int primary key)";
            cmd.ExecuteNonQuery();
        });
        ExecuteTxn(conn2, cmd => {
            cmd.CommandText = "insert into demo (id) values (1)";
            cmd.ExecuteNonQuery();
        });            
        ExecuteTxn(conn3, cmd => {
            cmd.CommandText = "drop table demo";
            cmd.ExecuteNonQuery();
        });            
    }

    private static void ExecuteTxn(FbConnection conn, Action<FbCommand> todo) {
        using (var txn = conn.BeginTransaction())
        using (var cmd = conn.CreateCommand()) {
            cmd.Transaction = txn;
            todo(cmd);
            txn.Commit();
        }
    }

我意识到将交易选项更改为

txn = conn.BeginTransaction(new FbTransactionOptions { TransactionBehavior = FbTransactionBehavior.Wait }))

似乎有帮助。但我不确定这是正确的做法还是只是巧合......

使用 Firebird 3.0.6,FirebirdSql.Data.FirebirdClient.dll 7.5.0.0

标签: ado.netfirebirdfirebird-3.0

解决方案


据我了解,问题与 Firebird 如何缓存某些元数据有关,这可能会导致保留存在锁,从而阻止删除对象。此外,这是可能的 - 这是一个猜测!- Firebird ADO.net 提供程序保留准备好插入语句的语句句柄,这也将导致保留存在锁。

Firebird 核心开发人员认为在 WAIT 事务中执行(可选超时)是一种合适的解决方法。

如需参考,请参阅以下门票:

在某些情况下,从 Firebird ClassicServer 或 Firebird SuperClassic 切换到 Firebird SuperServer 也可以防止这个问题。

但是,如果您想要更深入的解释,可能值得在 firebird-devel 邮件列表中提出这个问题。


推荐阅读