我在.NET 4.0下使用Npgsql 2.0.11来修改PostgreSQL 9.0数据库。该程序在一次交易中对数据库进行了许多修改。
在提交之前,我运行SELECT语句,有时会失败(例如,超时)。我吞下了异常并继续进行交易。没有错误,所以看起来好像一切正常,但实际上数据库根本没有修改过!
我的猜测是失败的SELECT回滚整个事务。我可以阻止这种情况(即,事务仍然提交)或至少检测到这种情况并抛出异常,因此用户知道提交失败了吗?
我知道在这个特定的情况下我可以在事务之外移动SELECT,但我更关心的是解决这个问题。提交不提交是一个非常严重的问题,我想确保它不被发现。
答案 0 :(得分:7)
我对Npgsql一无所知,但我可以谈谈PostgreSQL的行为。当PostgreSQL事务中发生任何错误时,事务将被标记为 invalid ,直到它被关闭。 (他们的术语是“中止”,我认为这是误导性的。)此外,这是恕我直言,如果你COMMIT
无效的交易,它“成功”,但效果与ROLLBACK
相同。您可以在psql
REPL中观察到这一点;它将打印ROLLBACK
以响应您的COMMIT
命令,但不会发出错误信号。
您可以在最终SAVEPOINT
之前创建SELECT
。如果失败,则ROLLBACK
为保存点名称;这将使您退出无效状态,并允许您提交事务的前一部分。
答案 1 :(得分:0)
我最后编写了一个小包装器方法,尝试在提交之前执行一个简单的语句作为事务的一部分,这有效地检测问题。
public static void CommitTransaction(NpgsqlConnection conn, NpgsqlTransaction tran)
{
using (var command = new NpgsqlCommand("SELECT 1", conn, tran))
{
try
{
command.ExecuteScalar();
}
catch (NpgsqlException ex)
{
if (ex.Code == "25P02")
throw new Exception("The transaction is invalid...");
throw;
}
}
tran.Commit();
}
修复是 Morg。或 Ryan Culpepper 的答案:要么在事务之外运行语句,要么事先创建一个SAVEPOINT并向它创建ROLLBACK出错了。
答案 2 :(得分:-1)
在交易中出现问题,但交易完成对交易不是很正确吗?
所以基本上,如果它可能会失败并且您不关心它,请不要将它放在交易中,而不要让它失败。
使用交易,因为它们意图使用,您不会有任何问题;)