使用多个连接时无法删除 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 事务中执行(可选择超时)是一种合适的解决方法。
供参考,请参阅以下门票:
- 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 也可以防止出现此问题。
但是,如果您想要更多 in-depth 的解释,可能值得在 firebird-devel 邮件列表中提出这个问题。
我想安全地放下 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 事务中执行(可选择超时)是一种合适的解决方法。
供参考,请参阅以下门票:
- 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 也可以防止出现此问题。
但是,如果您想要更多 in-depth 的解释,可能值得在 firebird-devel 邮件列表中提出这个问题。