场景 我们正在将我们的 SQL 资产升级到 SQL Server 2019,并设置了生产环境。
来自:SQL2008R2 Standard/Windows Server 2008R2 - 主服务器/辅助服务器(Windows 故障转移群集)和报告服务器(事务复制)。
至:SQL2019 Standard/Windows Server 2019 - 主服务器/辅助服务器(始终在线)和报告服务器(事务复制)
2008R2 的备份已于 2019 年恢复,兼容性级别设置为最新。Always-On 设置相对顺利,针对当前应用程序的初始测试显示兼容性没有问题。
问题纯粹在于设置事务复制。有 2 个数据库需要复制,每个发布一个以主数据库作为发布者和分发者。
问题 在报告服务器上的每个数据库的订阅初始化期间,它运行良好,直到它到达创建函数的地步并产生以下错误。
第一个数据库:
消息:选项“INLINE=ON”对此函数无效。检查文档以了解函数中 INLINE 选项支持的构造。命令文本: CREATE FUNCTION [dbo].[f_clienttels - 镜像复制 ce2d3663eb494f3589bd5000dad1bf1f](@ClientID [int]) RETURNS varchar WITH INLINE = ON, EXECUTE AS CALLER AS BEGIN ......
第二个数据库:
消息:为语句“CREATE/ALTER FUNCTION”指定了无效选项。关键字“with”附近的语法不正确。如果此语句是公用表表达式、xmlnamespaces 子句或更改跟踪上下文子句,则前面的语句必须以分号结束。')' 附近的语法不正确。命令文本:CREATE FUNCTION [dbo].[GetGroupAndDescendantGroupsSelective - Mirror Copy 46f329d5eed444428f45b052f07c7ea8](@GroupId [int]) RETURNS TABLE WITH INLINE = ON AS RETURN ( WITH GroupsCTE AS ( ........
它们都是不同的错误,但我相信两者都与“INLINE = ON”选项有关,这两个函数中都不存在此选项,如果您从订阅中删除这些文章,我们的函数都没有明确使用 inline 选项它只是在下一个函数上给出相同的错误(如果函数以 CTE 开头,则为 CTE 错误,如果不是,则为 INLINE=ON 错误)。
因此,似乎复制在复制之前将“WITH INLINE = ON”插入到函数中,然后在它所做的添加上出错。
我已将所有实例修补到最新的 CU4 更新 15.0.4033.1,在两台服务器上测试了这些功能(有效),验证了数据库中的所有功能/过程,一切都很好。在当前的 2008R2 环境中,我不得不在几个月前重新创建该出版物并且没有出现这些错误。作为目前的解决方法,我在订阅者处手动创建函数并从出版物中删除所有函数文章。
任何解决此问题的帮助将不胜感激,对此错误的唯一引用(来自第一个 DB)是提到它没有记录(下面的链接),我找不到任何其他论坛帖子提到它。
16203 – 选项“INLINE=ON”对此功能无效。检查文档以了解函数中 INLINE 选项支持的构造。
来自:Brent Ozar - SQL Server 2019 的 sys.messages 中的新增功能:更多未宣布的功能
我们与 Microsoft 没有有效的支持合同,但正试图通过提供许可证的供应商联系他们,因此如果他们回复我们,我将在此处提供更新。
如果需要,我可以提供更多信息。
请参阅本文对我有用的唯一解决方案是在升级到 SQL 2019 后删除并重新创建 UDF。
升级到 SQL 2019 后,Sys.sql_modules 中的 inline_Type 列将为 1。删除并重新创建 UDF 后,Inline_type 将为 0,并且复制初始化工作正常。
我在将包含一些标量 UDF 的发布从 SQL 2016 迁移到 SQL 2019 时遇到了这个问题。更改发布者数据库上的数据库设置并没有解决这个问题。由于订阅者包括旧版本的 SQL Server,因此在函数定义中添加“WITH INLINE=OFF”不是一个选项。所以我的解决方案是通过在函数定义中添加以下代码来强制 udf 不可内联:
如果您在 sys.sql_modules 上进行选择,is_inlineable 将显示为 0,并且快照脚本将成功生成。
作为对此的跟进,升级到 SQL Server 2019 CU9 将删除此解决方法。
格式的任何函数: Create function as return table select 1 x
使用 inline_type = 1 创建,然后复制会引发上述错误。
由于此功能,我们不得不回滚 CU9。
对延迟发布这些调查结果表示歉意,我花了一个多月的时间与 Microsoft 支持来回讨论这个问题(有一次他们告诉我,复制不是为了复制函数和存储过程而设计的,也不是为了修复它们而复制它们) ?!!),在我向他们发送了大量实验证据之后,他们最终承认这确实是一个错误。该错误实际上与 SQL 引擎中的数据库恢复/升级过程有关,而不是事务复制本身,因为它最初出现。
原因/调查
其根本原因是,当数据库从以前版本的 SQL(在我的情况下为 2008R2)恢复到新的 SQL 2019 实例时,默认情况下,它似乎会在sys.sqlmodules中标记inline_type = 1的函数(这表明在 GUI 的函数属性中为“标记为内联”)。该表中有一个名为inlinable的标志,在最初调查时它有点红鲱鱼,因为它似乎正在使用inline_type复制,即使在解决方法之后inlinable仍然是 true 并且不会阻碍复制。
我通过以下步骤得出了这个结论:
由于 inline_type 标志,此选项由复制自动应用。
或者
第二个错误的原因是因为它在复制代码中自动声明 INLINE = ON,导致当函数包含 CTE 时语法无效。
解决方法
唯一可行的解决方法是在还原/升级后重新创建所有功能,以便正确设置它们的标志。注意:并非所有函数都被错误地标记,一些合法地应该用inline_type = 1 标记,解决方法将正确设置这些,因此如果它们被以下脚本捕获也不会受到伤害。
我是通过一个快速而肮脏的 PowerShell(如下)完成的,一些类似问题的 Microsoft 文章建议sp_refreshsqlmodule这在第一个实例中对我不起作用,但我看不出任何不合逻辑的原因,所以它值得在第一个实例中尝试而不是这个。
最终决议
根本原因必须在 SQL 引擎/数据库恢复代码中修复,才能真正解决这个确切的场景。Microsoft 已确认此修复程序将在 SQL Server 2019 CU6 更新中实施。
当您必须等待 3 个月才能获得它时,我不确定我是否同意它被称为修补程序!
希望这对其他人有所帮助,也可以作为一个教训,当您联系 Microsoft 支持时,请准备好自己进行大量调查并将其发送给他们,这确实有助于加快流程。