如何以最少的停机时间将 rowversion 列添加到大表中

Mic*_*art 23 sql-server-2008 sql-server alter-table

使用 SQL Server 2008 及更高版本,我想向大表添加一个 rowversion 列,但是当我只是

ALTER TABLE [Tablename]
ADD Rowversion [Rowversion] NOT NULL
Run Code Online (Sandbox Code Playgroud)

然后该表无法更新太长时间。

我可以使用哪些策略来减少这种停机时间?我会考虑任何事情。当然越简单越好,但我会考虑任何策略。

我的想法是,作为最后的手段,我可​​以维护一个由触发器维护的副本临时表,然后将临时表 sp_rename 到原始表中。但我希望有更简单/更容易的东西。

Bre*_*zar 27

考虑创建一个具有相同架构和 rowversion 列的新表,并在两个表的顶部添加一个视图来合并所有。让人们使用视图,并针对基础表和视图编写替代触发器。

插入应该发送到新表,更新应该将数据移动到新表,删除应该应用于两个表。

然后在后台进行批量移动,一次将尽可能多的记录移动到新表中。在此过程中,您仍然可能会遇到并发问题,以及一些棘手的执行计划,但它可以让您在移动发生时保持在线状态。

理想情况下,您在周五下午开始该流程以尽量减少对最终用户的影响,并尽量在周一早上之前完成。一旦它就位,您可以将视图更改为仅指向新表,而繁琐的执行计划就会消失。理想情况下。

为避免在批量迁移数据时触发触发器,请查看触发器中已删除/插入的表中的行数,如果活动接近批处理中的行数,则跳过这些活动。


最后,Michael 决定跳过视图(而不是从原始表中删除)以获得更稳定的计划。权衡基本上是持有表格的两个副本。他把它变成了一系列的博客文章


小智 7

如果你有时间提前计划,有一个更简单的解决方案......(通常)

长锁几乎肯定是由存储层的页面拆分引起的。所以强迫他们按照你自己的时间表进行。

  1. 添加数据类型为 NULL 的临时列VARBINARY(8)
  2. 在数据库中查找可用的松弛时间以使用字段的有效值更新现有记录的批次。(0x0000000027F95A5B例如)
  3. 更新将强制进行必要的页面拆分并为表分配更多空间。
  4. 当你赶上时,删除临时列(不接触分配的存储)并添加 rowversion 列。
  5. 没有页面拆分,并且只需要足够长的时间来填充值的锁。

我已经成功地使用它在 10 分钟内将 rowversion 列添加到 150M 行表。

警告...如果您有一个包含大型 varchar 字段(尤其是varchar(max))的表,SQL Server 决定重建该表而不是重新使用新的可用空间。仍然试图找出解决这个问题的方法。