问题描述
我想放下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
解决方法
据我了解,问题与Firebird如何缓存某些元数据有关,这可能导致保留存在锁,这将防止对象的删除。另外,有可能-这是一个猜测! -Firebird ADO.net提供程序保留已准备好插入语句的语句句柄,这也将导致保留存在锁。
在Firebird核心开发人员中,在WAIT事务中执行(可选地具有超时)被认为是一种适当的解决方法。
作为参考,请参阅以下票证:
- CORE-3766 - Transaction can`t change metadata if it is run in no_wait and there is another connect that once had queried these metadata
- CORE-6382 - Triggers accessing a table prevent concurrent DDL command from dropping that table
在某些情况下,从Firebird ClassicServer或Firebird SuperClassic切换到Firebird SuperServer也可以防止此问题。
但是,如果您需要更深入的说明,可能值得在firebird-devel邮件列表中提出这个问题。