2011-07-20 50 views
3

我想在大约1200万条记录的表上运行以下内容。在SQL Server 2008中添加列锁表锁定?

ALTER TABLE t1 
ADD c1 int NULL; 
ALTER TABLE t2 
ADD c2 bit NOT NULL 
DEFAULT(0); 

我在分期完成它和时机似乎很好,但我在生产做之前,我想知道在新列的创建(指定一个默认值特别是当对表锁定的工作方式)。那么,有人知道吗?整个表是否被锁定,或者在默认值插入过程中行被逐个锁定?还是做了不同的事情呢?

+0

http://stackoverflow.com/questions/1703597/lock-escalation-whats-happening-here – Jacob

回答

4

是的,它会锁定表格。

整体而言,表格具有单一架构(一组列和相关类型)。因此,至少为,将需要架构锁来更新表的定义。


去想想事情会如何运作反之 - 如果每行被单独更新,如何将任何并行查询工作(特别是如果他们参与新列)?


和默认值时INSERT和DDL语句唯一有用的 - 所以,如果你指定一个新的默认10,000,000行,该默认值必须适用于所有这些行。

+0

“默认值仅在INSERT和DDL语句中有用” - 关于引用操作ON ** UPDATE ** SET DEFAULT并开启** DELETE ** SET DEFAULT? ;) – onedaywhen

+0

我知道它会在更新表的* definition *的时候锁定,但是当它更新时每个行的默认值会保持锁定状态?更新表格定义非常快,大概2秒钟。使用默认值更新每一行的地方没有那么近,所以这是出现性能问题的地方,如果有的话。 – Eli

+0

如果该列将不为空,则只需添加一个默认值即可。 – HLGEM

4

是的,它会锁定。

DDL语句发出一个Schema Lock (see this link)这将阻止访问表,直到操作完成。

有没有真正解决这个问题的方法,如果你仔细想想,这是有道理的。 SQL需要知道表中有多少个字段,并且在此操作期间,某些行的字段将比其他字段更多。

另一种方法是用正确的字段创建一个新表,插入,然后重命名表以将它们交换出来。

0

我还没有看到添加列时锁机制是如何工作的,但我几乎100%肯定行是不可能的。

当你在SQL Server管理器中用拖放操作(我知道你在这里没有这样做,但是这是一个公共论坛)时要注意,因为有些更改是破坏性的(幸运的是,SQL Server 2008,至少R2,在这里更安全,因为它告诉你“不能做”而不是仅仅做它)。

但是,您可以在单个语句中同时运行两列添加,并减少流失。

8

在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锁确保在任何单独的行上不会发生任何冲突。

+0

虽然我的猜测是Denali现在不会帮助他,但我会为您提供有关新版本的+1的相关信息。 –

+1

+1 - 从内部人员的角度来看,总是很好 – JNK