Npgsql 如何处理失败的事务?

Posted

技术标签:

【中文标题】Npgsql 如何处理失败的事务?【英文标题】:How does Npgsql handle failed transactions? 【发布时间】:2019-08-21 06:43:36 【问题描述】:

在 ASP.NET 应用程序 (C#) 中,我们使用 Postgres 作为后端,使用 Npgsql 作为数据提供者。几天前,我们遇到了严重的数据丢失问题。我在代码中进行了调查,发现代码如下:

    var transaction = connection.BeginTransaction();
    //some crud operation here  
    transaction.Commit()

有人坚持 Npgsql 会自己处理异常,并且会自动回滚事务,以防事务期间出现问题。

在我看来这是相当乐观的,代码应该被包装在一个 try and catch 块中并显式调用事务回滚:

 var transaction = connection.BeginTransaction();
 try
    
        //some crud operation here        
        transaction.Commit
    catch(Exception ex)
    
        transaction.Rollback();
    

错了吗?

此外,事务回滚是否总是有效?我在某处读到它只有在引发 Postgres 异常时才会起作用,比如在格式错误的 sql 的情况下,但在其他类型的异常情况下它将不起作用。有人也可以澄清这一点吗?

【问题讨论】:

【参考方案1】:

另一种方式可能是:

using( var tx = connection.BeginTransaction())

    .. do som database stuff ..

    tx.Commit();

对未提交的事务进行处理会导致回滚。并且资源被释放了!

【讨论】:

【参考方案2】:

如果发生错误,PostgreSQL 将自动中止事务,但不会回滚。

只有当你完成交易

    断开连接

    COMMITROLLBACK 结束事务(在两种情况 情况下都会回滚)

在错误和事务结束之间的连接上发送的所有语句都将被忽略。

所以是的,您应该使用 try / catch 阻止和回滚。

ROLLBACK 将始终完全撤消当前事务,无论是否出现错误。

【讨论】:

嗨,谢谢。但是如果在事务期间抛出 .NET IO 异常会发生什么。 using 子句会以任何方式回滚事务,还是我需要调用显式回滚()? 如果错误来自数据库,则事务中止但尚未回滚。如果异常来自 .NET,则事务仍处于活动状态(除非提供者中止它)。在这两种情况下,您都需要显式回滚来结束事务。 知道了!非常感谢!

以上是关于Npgsql 如何处理失败的事务?的主要内容,如果未能解决你的问题,请参考以下文章

如何处理SQL Server事务复制中的大事务操作

您通常如何处理数据库事务日志?

如何处理 jdbc 事务中的父键约束?

你们公司是如何处理分布式事务的?

清洁架构 - 如何处理数据库事务?

如何处理 Spring 集成流的事务(Java DSL)