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


21

使用SQL Server 2008和更高版本时,我想将rowversion列添加到大型表中,但是当我只是

ALTER TABLE [Tablename]
ADD Rowversion [Rowversion] NOT NULL

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

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

我的想法是,作为最后的选择,我可以维护一个由触发器维护的副本登台表,然后将登台表sp_rename重命名为原始表。但我希望有一些更简单/更轻松的方法。

Answers:


26

考虑使用相同的架构以及rowversion列创建一个新表,并在两个表之间添加一个视图,该视图将全部合并。让人们使用视图,并针对基础表和视图编写触发器。

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

然后在后台进行批处理移动,一次将尽可能多的记录移动到新表中。在进行此操作时,您仍然会遇到并发问题,还有一些令人难以置信的执行计划,但是它使您可以在移动发生时保持在线状态。

理想情况下,您应在星期五的下午开始该过程,以最大程度地减少对最终用户的影响,并尝试在星期一早晨之前完成此过程。放置到位后,您可以将视图更改为仅指向新表,并且奇特的执行计划将消失。理想地。

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


最后,Michael决定跳过该视图(而不是从原始表中删除)以获取更稳定的计划。折衷方案基本上是持有两张桌子。他把它变成了一系列博客文章。


7

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

长锁几乎可以肯定是由存储层的页面拆分引起的。因此,请按自己的时间表进行操作。

  1. 添加数据类型为NULL的临时列VARBINARY(8)。
  2. 在数据库中查找可用的空闲时间,以使用该字段的有效值更新现有记录的批次。(0x0000000027F95A5B例如)
  3. 更新将强制进行必要的页面拆分,并为表分配更多空间。
  4. 当您陷入困境时,请删除临时列(不要触摸已分配的存储)并添加rowversion列。
  5. 没有页面拆分,仅需要足够长的锁即可填充值。

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

注意...如果您的表具有较大的varchar字段(尤其是varchar(max)),则SQL Server决定重新构建该表,而不是重新使用新的可用空间。仍在尝试找出解决该问题的方法。


有趣的是,我想我没有说明问题中“太长”的含义。如果对于您的情况而言,> 30分钟太长并且可以容忍10分钟,则此解决方案将起作用。我的方案涉及尝试实现零停机时间或更确切地说是小于10秒,这是由Brent的答案实现的。
— Michael J Swart,2015年

1

如果TIMESTAMP要添加的是NULLABLE:

  1. 添加一VARBINARY(8)列
  2. 填充数据。

它被填充后,在背靠背的SQL语句,DROP在VARBINARY(8)您刚才添加的列和填充,并添加TIMESTAMP NULL列。


如果TIMESTAMP要添加的是NOT NULLABLE:

  1. 添加一BINARY(8)列
  2. 填充数据。

填充后,在背对背SQL语句中,添加和填充刚创建DROP的BINARY(8)列和ADD THE TIMESTAMP NOT NULL列。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.