如何以最少的停机时间将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语句,DROPVARBINARY(8)您刚才添加的列和填充,并添加TIMESTAMP NULL列。


如果TIMESTAMP要添加的是NOT NULLABLE

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

填充后,在背对背SQL语句中,添加和填充刚创建DROPBINARY(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.