我想在大约1200万条记录的表格上运行以下内容。
ALTER TABLE t1
ADD c1 int NULL;
ALTER TABLE t2
ADD c2 bit NOT NULL
DEFAULT(0);
我已经在分段中完成了它并且时间似乎很好,但在我在生产中进行之前,我想知道在创建新列时锁定是如何工作的(特别是在指定默认值时)。那么,有人知道吗?整个表是否被锁定,或者在默认值插入期间逐行锁定行?还是会发生一些不同的事情?
答案 0 :(得分:9)
在SQL Server 11(Denali)之前,使用默认值添加非空列将在后台运行更新以填充新的默认值。因此,它将在1200万行更新期间锁定表。在SQL Server 11中已不再是这种情况,该列已在线添加且未进行更新,请参阅Online non-NULL with values column add in SQL Server 11。
在SQL Server 11和之前都在表上获取Sch-M锁以修改定义(添加新列元数据)。此锁与任何其他可能的访问(包括脏读)不兼容。不同之处在于持续时间:在SQL Server 11之前,此锁将保持数据大小操作(更新12M行)。在SQL Server 11中,锁仅用于简短的简要说明。在SQL Server 11之前的行更新中,不需要获取行锁,因为表上的Sch-M锁可以保证任何单个行都不会发生冲突。
答案 1 :(得分:5)
是的,它会锁定表格。
表作为一个整体,具有单个模式(一组列,具有关联的类型)。因此,至少,需要架构锁来更新表的定义。
尝试考虑事情是如何相反的 - 如果每一行都是单独更新的,那么任何并行查询将如何工作(特别是如果它们涉及新列)?
默认值仅在INSERT
和DDL语句期间有用 - 因此,如果为10,000,000行指定新的默认值,则必须将该默认值应用于所有这些行。
答案 2 :(得分:5)
是的,它会锁定。
DDL语句发出模式锁(see this link),这将阻止在操作完成之前访问该表。
没有办法解决这个问题,如果你仔细想想就行了。 SQL需要知道表中有多少字段,并且在此操作期间,某些行将具有比其他字段更多的字段。
另一种方法是使用正确的字段创建一个新表,插入,然后重命名表以将它们交换出来。
答案 3 :(得分:0)
我没有读过添加列时锁定机制的工作原理,但我几乎100%确定逐行是不可能的。
观察您在SQL Server管理器中执行这些类型的操作时使用拖放操作(我知道您不是在这里执行此操作,但这是一个公共论坛),因为某些更改具有破坏性(幸运的是,SQL Server 2008,at至少R2,在这里更安全,因为它告诉你“不能做”而不是只做它。)
但是,您可以在单个语句中运行两个列添加,并减少流失。