提问者:小点点

DbUpdateConcycyException和40001 postgres代码有什么区别?


我有两个事务。首先,我选择一个实体,进行验证,将客户端文件提供的上传到S3,然后使用有关S3文件的信息更新此实体。第二个事务只是删除此实体。现在,假设有人调用了第一个事务并立即调用了第二个事务。第二个将进行得更快,第一个将抛出DbUpdateConcycyException,因为所选实体在更新查询时不再存在。

当我的事务有IsolationLevel. ReadCommed时,我得到DbUpdateConcurrency cyException。但是如果我设置IsolationLevel.Serializable它会抛出带有40001 postgres代码的InvalidOperationException。有人能解释为什么我会得到不同的错误,因为在我看来结果应该是相同的,因为更新不存在的实体调用的两个错误?


共1个答案

匿名用户

40001错误对应于SQLSTATEserialization_failure(参见错误代码表)。

它是由数据库引擎以可序列化隔离级别生成的,当它检测到存在并发事务并且该事务可能产生了如果并发事务已串行运行则无法获得的结果时。当使用IsolationLevel. ReadCommed时,不可能获得此错误,因为选择此隔离级别恰恰意味着客户端不希望由数据库执行这些隔离检查。

另一方面,DbUpdateConcycyException可能不是由数据库引擎生成的。它是由实体框架生成的。数据库本身可以使用UPDATE更新零行,它不是SQL级别的错误。

我认为,如果数据库首先出错,则会出现序列化失败,如果数据库没有出错,则会出现DbUpdateConcycyException错误,但按分层顺序排列的第二层(EF)会出错。

在可序列化隔离级别处理序列化失败的典型方法是客户端在收到40001错误时重试事务。重试的事务将有一个新的数据视图,希望能通过(否则,在重试时循环)。

在较小的隔离级别(如读提交)处理并发的典型方法是在访问对象之前显式锁定它们以强制对并发事务进行序列化。