SQL Server 更新了只读文件组上的记录?

too*_*uto 8 sql-server filegroups partitioning

我的数据仓库中有一个非常大的数据库,我们在其中实施了分区来管理维护和备份。某个时间的记录最终会每月迁移一次到只读文件组。

有时,我们的 ETL 过程会尝试更新已迁移到存档的旧记录,但我们预计这些会失败。但是,我至少有两个最近的示例,其中测试中的记录即使在我们的测试环境(查询sys.partition_functionssys.partition_range_values)中似乎位于只读文件组的分区中也会更新。

生产中的相同记录在尝试更新记录时会导致预期的失败。到目前为止,我们已经两次发现更新在生产中失败但在测试中成功(从来没有相反)。

相关环境事实:

  • SQL Server 2012 SP3 CU3(内部版本 11.0.6537.0)
  • 测试是开发版,生产是企业版
  • 可以按要求提供其他人:现在严重难倒...

更新 2016-08-19

以某种方式在一夜之间更新了新记录。确认它在只读文件组中。发现我可以更新同时插入的记录(即也在只读文件组的同一分区上)。我在同一分区上识别了一条记录,并且能够多次更新该记录。尝试更新夜间更新的记录会导致预期的失败。

更新 2016-08-11

在只读分区上的测试中的夜间处理期间继续发生更新。尝试从进程更新相同的记录失败。在以之前更新记录的用户身份登录时尝试更新相同的记录失败。我也无法通过更新夜间流程尚未触及的类似记录来复制该问题。

更新 2016-08-04

今天发现它不仅限于单个表,因为我发现在使用相同分区方案的不同表上又发生了相同的行为。

更新 2016-08-03

运行该脚本这个MSDN脚本证实了我使用肯德拉小的分区助手的意见时得到ph.FilegroupDetailph.ObjectDetail该演示。有问题的记录位于分区 #2(有问题的记录的分区列值为 2015-03-18)

Filegroup     Low Boundary     UpperBoundary
Archive  (RO) NULL             1900-01-01
Archive  (RO) 1900-01-01       2015-04-01
ActiveFG (RW) 2015-04-01       2015-07-01
ActiveFG (RW) 2015-07-01       2015-10-01
ActiveFG (RW) 2015-10-01       2015-01-01
ActiveFG (RW) 2016-01-01       2016-04-01
ActiveFG (RW) 2016-04-01       2016-07-01
ActiveFG (RW) 2016-07-01       2016-10-01
ActiveFG (RW) 2016-10-01       2017-01-01
ActiveFG (RW) 2017-01-01       2115-01-01
ActiveFG (RW) 2115-01-01       NULL
Run Code Online (Sandbox Code Playgroud)

将表放在分区上的代码(没有其他索引)

ALTER TABLE [dbo].[TABLE_NAME] ADD  CONSTRAINT [pk_TABLE_NAME] PRIMARY KEY CLUSTERED 
(
    [ETL_VERS_START_DTM] ASC,
    [ACCT_NO] ASC,
    [ACCT_TYPE] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON ps_SmallTablesDate(ETL_VERS_START_DTM)
Run Code Online (Sandbox Code Playgroud)

应该失败的更新语句(通过 Informatica):

UPDATE TABLE_NAME SET ETL_JOB_SEQ_NUM = ?, ETL_IUD_CD = ?, ETL_UPD_DTM = ?, ETL_DEL_DTM = ? WHERE ETL_VERS_START_DTM = ? AND ACCT_NO = ? AND ACCT_TYPE = ?
ETL_VERS_START_DTM (ETL_VERS_START_DTM:Date:): "03/17/2015 23:30:02.140000000"
ETL_JOB_SEQ_NUM (ETL_JOB_SEQ_NUM:Int:): "1173651"
ETL_IUD_CD (ETL_IUD_CD:Char.1:): "D"
ETL_UPD_DTM (ETL_UPD_DTM:Date:): "08/02/2016 02:32:45.000000000"
ETL_DEL_DTM (ETL_DEL_DTM:Date:): "08/02/2016 00:10:03.567000000"
ACCT_NO (ACCT_NO:Char.12:): "1234567890"
ACCT_TYPE (ACCT_TYPE:Char.3:): "OLN"
Run Code Online (Sandbox Code Playgroud)

更新 2017-02-21

因此,经过这么长时间,我们发现以某种方式将最旧的活动分区合并到存档中时,磁盘上的一部分记录并未从活动文件组移动到存档文件组。以下查询显示分区 2 中的记录已映射到 ActiveFG,同时检查实际分区方案显示这些相同的记录应通过分区功能分类到存档文件组中。

SELECT  OBJECT_NAME(P.[object_id]) ,
    P.index_id ,
    P.partition_number ,
    F.name ,
    F.filegroup_guid
FROM    sys.allocation_units AU
    JOIN sys.partitions P ON P.partition_id = AU.container_id
    JOIN sys.filegroups F ON F.data_space_id = AU.data_space_id
WHERE   P.partition_number IN ( 1, 2, 3 )
    AND P.[object_id] = OBJECT_ID('TABLE_NAME')
ORDER BY P.partition_number;
Run Code Online (Sandbox Code Playgroud)

我撤消了实际使用的数据库中的所有分区,并保留了一个版本,该版本已损坏以使用 Microsoft 票证。我需要和我们的 DW 团队一起修改分区计划,但我承认我很害怕再次尝试。

Microsoft 无法复制此行为,因此此时已对票证进行了处理。他们似乎准备不理会它并假设它在 2014/2016 年不存在?他们似乎无法在他们的实验室中复制它,尽管我有能力让它继续存在于数据库中,即使我在我的系统中从备份中恢复它。

Bre*_*zar 1

我有件事要坦白。

有一次,当我年轻的时候,我构建了一个 ETL 流程,首先将只读文件组更改为读写,执行 ETL 工作,然后将它们设置回只读。

所以万一你有一个像我一样邪恶的同事(我还年轻,我需要钱),你可以通过以下方式进行测试:

  1. 更改只读文件组的名称 - 这样,如果有人使用硬编码脚本按名称更改文件组,他们的脚本将失败,您将抓住罪魁祸首。或者,更难一些:

  2. 使用 Profiler 或扩展事件来跟踪执行 ALTER DATABASE 操作的任何人。