IDbTransaction.Commit returns 交易完成前
IDbTransaction.Commit returns before transaction is complete
我有一台服务器(很少)动态创建数据库行以适应用户配置的数据模型。在启动期间,服务器可能必须创建大约一千行以及向现有表中进行多次插入。
完成所有这些后,它会提交事务并向可能正在收听的任何人发送有关新数据模型的通知。问题是,transaction.Commit() 在数据库实际完成更改之前出现在 return,因此如果客户端在发送通知后向服务器发出请求,客户端可能得到一个空的结果。我的假设是等待 transaction.Commit() 将确保事务全部完成并提交。
客户端得到空结果的原因是当不进行 DDL 操作时,数据库正在使用快照隔离,所以很明显快照是在 DDL 操作完成之前拍摄的(但在 transaction.commit returned)
运算顺序为:
- 开始交易
- 在数据库中执行数千次操作 (DDL)
- 提交交易
- 发送有关更改的通知
- 客户端请求数据(快照隔离)
- 没有数据(交易前的状态)return发送给客户端。
为什么 transaction.Commit() 在事务完成提交之前完成?如何让服务器等待事务完全完成后再继续发送通知?
编辑:清晰度。
这是 'Snapshot Isolation' 的自然行为。检查此 link:
https://www.sqlshack.com/snapshot-isolation-in-sql-server/
“当另一个会话读取相同的数据时,将返回读取事务开始时数据的提交版本。”
您必须终止会话,其他事务才能读取它。或者改成'Read Committed'.
正如我们在评论中发现的那样,一个可能的原因是待处理的外部交易。如documentation所述:
When used in nested transactions, commits of the inner transactions
don't free resources or make their modifications permanent. The data
modifications are made permanent and resources freed only when the
outer transaction is committed. Each COMMIT TRANSACTION issued when
@@TRANCOUNT is greater than one simply decrements @@TRANCOUNT by 1.
When @@TRANCOUNT is finally decremented to 0, the entire outer
transaction is committed. Because transaction_name is ignored by the
Database Engine, issuing a COMMIT TRANSACTION referencing the name of
an outer transaction when there are outstanding inner transactions
only decrements @@TRANCOUNT by 1.
因此,尽管 Commit()
已成功执行,但如果存在外部事务 - 在该外部事务也提交之前,不会将任何更改持久保存到数据库中。
我有一台服务器(很少)动态创建数据库行以适应用户配置的数据模型。在启动期间,服务器可能必须创建大约一千行以及向现有表中进行多次插入。
完成所有这些后,它会提交事务并向可能正在收听的任何人发送有关新数据模型的通知。问题是,transaction.Commit() 在数据库实际完成更改之前出现在 return,因此如果客户端在发送通知后向服务器发出请求,客户端可能得到一个空的结果。我的假设是等待 transaction.Commit() 将确保事务全部完成并提交。
客户端得到空结果的原因是当不进行 DDL 操作时,数据库正在使用快照隔离,所以很明显快照是在 DDL 操作完成之前拍摄的(但在 transaction.commit returned)
运算顺序为:
- 开始交易
- 在数据库中执行数千次操作 (DDL)
- 提交交易
- 发送有关更改的通知
- 客户端请求数据(快照隔离)
- 没有数据(交易前的状态)return发送给客户端。
为什么 transaction.Commit() 在事务完成提交之前完成?如何让服务器等待事务完全完成后再继续发送通知?
编辑:清晰度。
这是 'Snapshot Isolation' 的自然行为。检查此 link: https://www.sqlshack.com/snapshot-isolation-in-sql-server/
“当另一个会话读取相同的数据时,将返回读取事务开始时数据的提交版本。”
您必须终止会话,其他事务才能读取它。或者改成'Read Committed'.
正如我们在评论中发现的那样,一个可能的原因是待处理的外部交易。如documentation所述:
When used in nested transactions, commits of the inner transactions don't free resources or make their modifications permanent. The data modifications are made permanent and resources freed only when the outer transaction is committed. Each COMMIT TRANSACTION issued when @@TRANCOUNT is greater than one simply decrements @@TRANCOUNT by 1. When @@TRANCOUNT is finally decremented to 0, the entire outer transaction is committed. Because transaction_name is ignored by the Database Engine, issuing a COMMIT TRANSACTION referencing the name of an outer transaction when there are outstanding inner transactions only decrements @@TRANCOUNT by 1.
因此,尽管 Commit()
已成功执行,但如果存在外部事务 - 在该外部事务也提交之前,不会将任何更改持久保存到数据库中。