症状
假设你使用 Microsoft SQL Server中的 WITH DTC_SUPPORT = PER_DB 子句创建可用性组。 尝试在事务或系统存储过程(如 sp_executesql)中执行 SAVE TRANSACTION 语句时,将收到以下错误消息之一:
注意
消息 627,级别 16,状态 0,行 LineNumber
不能在分布式事务中使用 SAVE TRANSACTION。
消息 12324,级别 16,状态 100,行 行号
内存优化表不支持 (DTC) 的分布式事务。
错误:3933,严重性:16,状态:1。
无法将事务升级为分布式事务,因为此事务中有一个活动的保存点。
原因
当 Always On 可用性组中的数据库启用 WITH DTC_SUPPORT = PER_DB 时,只要事务涉及多个数据库,事务就会在 SQL Server 2016 SP2 和 SQL Server 2017 中提升为 MSDTC 事务。 MSDTC 事务存在限制,例如无法使用保存点、无法使用内存优化表。
在某些情况下,发生跨数据库事务并不是因为用户具有涉及两个用户数据库的事务,而是因为事务涉及当前数据库和系统数据库 (master、tempdb、模型、系统资源数据库) 。 由于系统资源数据库实际上是只读的,因此,如果跨数据库事务涉及系统资源数据库而非其他系统数据库,则无需升级到 MSDTC 事务。
解决方法
如果系统资源数据库和属于已启用 PER_DB DTC 的可用性组中的用户数据库涉及同一 SQL Server 实例中的跨数据库事务,则此知识库中引入的修补程序将跳过升级到 MSDTC 事务。
因此,如果上面列出的错误的原始原因是涉及系统资源数据库的跨数据库事务,则此修补程序将解决该问题。 有时,用户可能会看到具有相同基本原因的上面列出的错误。 下面列出了此修补程序适用的条件:
- 数据库是已启用 WITH DTC_SUPPORT = PER_DB 的 Always On 可用性组的一部分。
- 跨数据库事务涉及此数据库和同一 SQL Server 实例中的系统资源数据库。
- 在跨数据库事务中,使用了 SAVE TRANSACTION 或涉及内存优化表。
如果没有此修复程序,此类事务将失败并出现上面列出的错误。 使用此修补程序后,此类事务应继续进行。
注: 此修补程序解决了涉及系统资源数据库的跨数据库事务,但任何涉及用户数据库并包含 SAVE TRANSACTION 语句的跨数据库事务仍将失败,必须重写。
此问题已在 SQL Server 的累积更新中进行了修复:
关于 SQL Server 的累积更新:
SQL Server 的每个新累积更新都包含上一个累积更新中包含的所有修补程序和所有安全修补程序。 查看 SQL Server 的最新累积更新:
详细信息
有关 DTC_SUPPORT = PER_DB、内存优化表、 SAVE TRANSACTION 的其他信息,请参阅以下链接。
同一 SQL Server 实例中的数据库事务将此部分链接到 https://learn.microsoft.com/en-us/sql/database-engine/availability-groups/windows/transactions-always-on-availability-and-database-mirroring?view=sql-server-2017#sql-server-2016-sp1-and-before-support-for-cross-database-transactions-within-the-same-sql-server-instance
内存优化表将 此部分链接到 https://learn.microsoft.com/en-us/sql/relational-databases/in-memory-oltp/transactions-with-memory-optimized-tables?view=sql-server-2017#limitations
保存交易 将此部分链接到 https://learn.microsoft.com/en-us/sql/t-sql/language-elements/save-transaction-transact-sql?view=sql-server-2017#remarks
状态
Microsoft 已确认在 "适用于" 部分中所列的 Microsoft 产品中存在问题。
参考资料
了解 Microsoft 用于描述软件更新的 术语 。