繁体   English   中英

IDbTransaction.Commit 在事务完成前返回

[英]IDbTransaction.Commit returns before transaction is complete

我有一个服务器(很少)动态创建数据库行以适应用户配置的数据模型。 在启动期间,服务器可能必须创建大约一千行以及对现有表的多个插入。

完成所有这些后,它会提交事务并向可能正在监听的任何人发送有关新数据模型的通知。 问题是,transaction.Commit() 似乎在数据库实际完成更改之前返回,因此如果客户端在发送通知后向服务器发出请求,客户端可能会得到一个空结果。 我的假设是等待 transaction.Commit() 将确保事务全部完成并提交。

客户端得到空结果的原因是,当不做 DDL 操作时,数据库使用快照隔离,所以很明显快照是在 DDL 操作完成之前(但在 transaction.commit 返回之后)拍摄的

操作顺序为:

  1. 开始交易
  2. 在数据库 (DDL) 中执行数千次操作
  3. 提交交易
  4. 发送有关更改的通知
  5. 客户端请求数据(快照隔离)
  6. 没有数据(交易前的状态)返回给客户端。

为什么 transaction.Commit() 在事务完成提交之前完成? 如何让服务器在继续发送通知之前等待事务完全完成?

编辑:清晰。

这是“快照隔离”的自然行为。 检查此链接: https : //www.sqlshack.com/snapshot-isolation-in-sql-server/

“当另一个会话读取相同的数据时,返回读取事务开始时数据的提交版本。”

您必须终止会话以便其他事务可以读取它。 或者将其更改为“已提交读”。

正如我们在评论中发现的那样,一个可能的原因是未决的外部事务。 文档中所述

在嵌套事务中使用时,内部事务的提交不会释放资源或使它们的修改永久化。 只有在提交外部事务时,数据修改才会永久化并释放资源。 @@TRANCOUNT 大于 1 时发出的每个 COMMIT TRANSACTION 只是将 @@TRANCOUNT 减 1。当 @@TRANCOUNT 最终减至 0 时,将提交整个外部事务。 由于数据库引擎会忽略 transaction_name,因此在存在未完成的内部事务时发出引用外部事务名称的 COMMIT TRANSACTION 只会将 @@TRANCOUNT 减 1。

因此,尽管Commit()已成功执行,但如果存在外部事务 - 在该外部事务也提交之前,不会将任何更改持久化到数据库中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM