SQL Server 2016 排序规则和内部表故障?

Tre*_*man 6 sql-server collation sql-server-2016

我的步骤:

  1. 安装了带有排序规则 SQL_Latin1_General_CP850_CI_AS 的 SQL 2016
  2. 将数据库还原到具有与数据库相同排序规则的暂存实例。(2012 年的原始备份)
  3. 运行> "C:\Program Files\Microsoft SQL Server\MSSQL13.STAGE\MSSQL\Binn\sqlservr.exe" -m -T4022 -T3659 -s"STAGE" -q"SQL_Latin1_General_CP1_CI_AS"
    这是为了将实例和所有数据库排序规则更改为 SQL_Latin1_General_CP1_CI_AS。(什么没有改变用户类型表)
  4. 运行查询

    Select i.name, c.collation_name,i.internal_type,i.internal_type_desc
    from sys.columns c inner join sys.internal_tables i on c.object_id=i.object_id
    WHERE c.collation_name <> 'SQL_Latin1_General_CP1_CI_AS'
    AND object_name(c.object_id) NOT LIKE 'sys%'
    AND object_name(c.object_id) NOT LIKE 'queue%'
    AND object_name(c.object_id) NOT LIKE 'file%'
    AND object_name(c.object_id) NOT LIKE 'spt%'
    AND object_name(c.object_id) NOT LIKE 'MSrep%'
    
    Run Code Online (Sandbox Code Playgroud)

    将返回带有旧排序规则的内部表。

    name         collation_name                  internal_type internal_type_desc
    sqlagent_jobs SQL_Latin1_General_CP850_CI_AS   220         CONTAINED_FEATURES
    
    Run Code Online (Sandbox Code Playgroud)

测试 2:

  1. 当实例排序规则设置为 SQL_Latin1_General_CP850_CI_AS 时,在 2016 年创建新数据库。
    新的数据库排序规则具有 SQL_Latin1_General_CP850_CI_AS。

  2. 运行此查询 where collat​​ion = SQL_Latin1_General_CP1_CI_AS

    Select i.name, c.collation_name,i.internal_type,i.internal_type_desc
    from sys.columns c inner join sys.internal_tables i on c.object_id=i.object_id
    WHERE c.collation_name = 'SQL_Latin1_General_CP1_CI_AS'
    AND object_name(c.object_id) NOT LIKE 'sys%'
    AND object_name(c.object_id) NOT LIKE 'queue%'
    AND object_name(c.object_id) NOT LIKE 'file%'
    AND object_name(c.object_id) NOT LIKE 'spt%'
    AND object_name(c.object_id) NOT LIKE 'MSrep%'
    
    Run Code Online (Sandbox Code Playgroud)

    这将返回与当前排序规则不匹配的结果。名称 collat​​ion_name internal_type internal_type_desc sqlagent_jobs SQL_Latin1_General_CP1_CI_AS 220 CONTAINED_FEATURES

我不认为应用程序会受到这个 internal_table 的影响。但仍然奇怪的是 internal_table 排序规则不匹配,在创建和将实例转换为新排序规则之后。

如果我执行相同的过程,但这次是在 2012 Staging 实例上。

  1. 使用排序规则 SQL_Latin1_General_CP850_CI_AS 将数据库恢复到 2012 暂存实例
  2. 冉> "C:\Program Files\Microsoft SQL Server\MSSQL11.STAGE12\MSSQL\Binn\sqlservr.exe" -m -T4022 -T3659 -s"STAGE" -q"SQL_Latin1_General_CP1_CI_AS"
  3. 修复用户类型表
  4. 备份转换后的数据库。
  5. 使用排序规则 SQL_Latin1_General_CP1_CI_AS 在 SQL 2016 上恢复数据库。
  6. 运行查询

    Select i.name, c.collation_name,i.internal_type,i.internal_type_desc
    from sys.columns c inner join sys.internal_tables i on c.object_id=i.object_id
    WHERE c.collation_name <> 'SQL_Latin1_General_CP1_CI_AS'
    AND object_name(c.object_id) NOT LIKE 'sys%'
    AND object_name(c.object_id) NOT LIKE 'queue%'
    AND object_name(c.object_id) NOT LIKE 'file%'
    AND object_name(c.object_id) NOT LIKE 'spt%'
    AND object_name(c.object_id) NOT LIKE 'MSrep%'
    
    Run Code Online (Sandbox Code Playgroud)

没有任何回报,因为我在 2012 年对其进行了转换。

如果有人可以解释发生了什么?这是一个错误吗?任何人都知道如何修复内部表格整理?

Sol*_*zky 5

我已经看了看内部表列的排序规则在大多数我的测试情况下,他们是所有无论是SQL_Latin1_General_CP1_CI_ASLatin1_General_BIN。有些实例是 SQL Server Express LocalDB,它们始终SQL_Latin1_General_CP1_CI_AS处于实例级别(不幸的是),但我Korean_100_CS_AS_KS_WS_SC在实例级别安装了 2017 Express,在实例级别安装了 2019 CTP 2.3 UTF8_BIN2。我将数据库恢复到 2019 年的实例(来自 CTP 2.2,而不是像您的情况那样的早期版本),French_100_CI_AS_SC_UTF8并带有 和 的排序规则French_100_CI_AS

我目前正在使用另一个SQL Server 2017年Express实例Estonian_100_CS_AS_SC在实例和DB水平,并使用该实例已更改-q选项很多说选项测试时间。它甚至有一个 Contained DB (containment_type = PARTIAL),并且内部表中的所有列都是SQL_Latin1_General_CP1_CI_ASLatin1_General_BIN,没有例外。

我不会担心这些列。它们显然都是希望保留其特定排序规则的 MS Shipped 对象。并且您永远不会有时间 100% 的排序规则是您为实例设置的。用于元数据的排序规则有自己的静态排序规则。排序规则来自系统目录视图中的表达式和具有显式排序规则集的函数等。您可以使用以下查询查看所有不是您将实例和数据库设置为的排序规则:

SELECT OBJECT_SCHEMA_NAME(col.[object_id]) AS [SchemaName],
       ISNULL(obj.[name], OBJECT_NAME(col.[object_id])) AS [ObjectName],
       col.[name] AS [ColumnName],
       col.[collation_name] AS [Collation],
       obj.[type_desc],
       ISNULL(obj.[is_ms_shipped],
              OBJECTPROPERTY(col.[object_id], 'IsMSShipped')) AS [IsMSShipped],
       col.[object_id]
FROM   sys.[all_columns] col
LEFT JOIN sys.[all_objects] obj
       ON obj.[object_id] = col.[object_id]
WHERE  col.[collation_name] IS NOT NULL
AND    col.[collation_name] NOT IN (
                         CONVERT([sysname], SERVERPROPERTY('collation')),
                         CONVERT([sysname], DATABASEPROPERTYEX(DB_NAME(), 'collation')))
ORDER BY [SchemaName], [ObjectName], [ColumnName];
Run Code Online (Sandbox Code Playgroud)

有些对象不在 中sys.all_objects,例如sys.pdw_nodes_partitions,这在object_id任何地方都是相同的(跨实例甚至 SQL Server 版本,但在 SQL Server 2012 中不存在):

SELECT OBJECT_SCHEMA_NAME(-1046288262) AS [SchemaName],
       OBJECT_NAME(-1046288262) AS [ObjectName],
       OBJECTPROPERTY(-1046288262, 'IsExecuted') AS [IsExecuted],
       OBJECTPROPERTY(-1046288262, 'IsView') AS [IsView],
       OBJECTPROPERTY(-1046288262, 'IsMSShipped') AS [IsMSShipped];
Run Code Online (Sandbox Code Playgroud)

不过,我不确定如何解释您在测试 1 中看到的结果。您说:

将返回带有旧排序规则的内部表。

根据我在本答案顶部的所有这些版本等中发现的所有内容,应该永远不可能将列输入sqlagent_jobsSQL_Latin1_General_CP1_CI_AS. 在创建这些内部表时,这可能是数据库升级过程的侥幸。SQL Server 2012 中不存在“CONTAINED_FEATURES”表,因此当您还原到 SQL Server 2016 时,必须在此时创建它们。您的 2016 年整理是SQL_Latin1_General_CP850_CI_AS,这是我目前看到的唯一联系。

我能够重现这个!!我从 SQL Server 2012 LocalDB 备份了一个数据库,该数据库的排序规则为Latin1_General_100_CS_AS_KS_SC. 然后我将其恢复到 SQL Server 2019(实例级排序规则为UTF8_BIN2)。检查内部表,我看到 3 个queue_messages_*表和filestream_tombstone_2073058421表(所有这些都存在于 SQL Server 2012 中)仍然有Latin1_General_BIN. 但是,sqlagent_*表和plan_persist_*表(在 SQL Server 2012 中都不存在),都有一个排序规则Latin1_General_100_CS_AS_KS_SC(与恢复的数据库相同)。

然后,我从 SQL Server 2014 LocalDB 备份了一个数据库,该数据库的排序规则为Latin1_General_100_CS_AS_KS_WS_SC. 然后我将其恢复到 SQL Server 2019(实例级排序规则为UTF8_BIN2)。检查内部表,我看到 3 个queue_messages_*表和filestream_tombstone_2073058421表(所有这些都存在于 SQL Server 2012 中)仍然有Latin1_General_BIN. 但是,这一次的sqlagent_*表(确实存在于 SQL Server 2014 中)的排序规则都是SQL_Latin1_General_CP1_CI_AS. 这些plan_persist_*表(SQL Server 2014 中仅存在 6 个中的 2 个),所有表的排序规则均为Latin1_General_100_CS_AS_KS_WS_SC(同样,与恢复的数据库相同)。

我将从 SQL Server 2012 恢复的 DB 的兼容模式更改为“SQL Server 2019 (150)”,但这并没有解决整理问题。

这显然是数据库升级过程的一个问题,与sqlservr.exe -q更改服务器上所有排序规则的方法无关(官方没有记录且不受支持,但我确实在此处记录了它:更改实例的排序规则,数据库,以及所有用户数据库中的所有列:可能出现什么问题?)。我已经通过几乎没有功能、甚至低于 2008-2010 年标准的报告站点 UserVoice 向 Microsoft 报告了这个错误:将数据库恢复到较新版本的 SQL Server 将创建缺失的内部表,并且排序不正确

关于测试 2:

排序规则 = SQL_Latin1_General_CP1_CI_AS

是的,预计这些内部表将使用旧的、应该已经删除的排序规则。

关于测试 3:

没有任何回报,因为我在 2012 年对其进行了转换。

不对。没有任何回报,因为:

  1. 您通过 过滤掉了 3 个队列表AND object_name(c.object_id) NOT LIKE 'queue%',而那些使用Latin1_General_BIN.
  2. 您通过 过滤掉了所有其他表WHERE c.collation_name <> 'SQL_Latin1_General_CP1_CI_AS'