使用多个连接时无法删除 Firebird table

Cannot drop Firebird table when using multiple connections

我想安全地放下 Firebird table。我有 3 个事务,一个要重新创建 table,一个要对 table 做一些事情(只是插入一行以保持简单),最后一个要删除 table。 如果所有这些 txns 都是使用单个连接执行的,那么这些工作就可以了。如果我使用不同的连接,则 drop 命令失败并显示

lock conflict on no wait transaction unsuccessful metadata update object TABLE "DEMO" is in use

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.dll7.5.0.0

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

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

供参考,请参阅以下门票:

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

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