向postgres表添加空列是否会导致锁定?

时间:2013-10-22 17:59:29

标签: postgresql alter-table

我想我在某处看到在postgres数据库上运行ALTER TABLE foo ADD COLUMN baz text不会导致读或写锁定。设置默认值会导致锁定,但允许空默认值会阻止锁定。

但是,我在文档中找不到这个。任何人都可以指出一个明确地说,如果这是真的吗?

3 个答案:

答案 0 :(得分:22)

在文档中提到了不同类型的锁以及何时使用它们 Table-level Locks。例如,Postgres 11的ALTER TABLE可能会获得SHARE UPDATE EXCLUSIVESHARE ROW EXCLUSIVEACCESS EXCLUSIVE锁定。

Postgres 9.1到9.3声称支持上述三个中的两个但实际上是forced Access Exclusive for all variants of this command。此限制为lifted in Postgres 9.4,但 ADD COLUMN仍设计为ACCESS EXCLUSIVE

检查源代码很容易,因为在各种情况下,有一个专门用于建立此命令所需锁定级别的函数:AlterTableGetLockLevel中的src/backend/commands/tablecmds.c


关于锁定持续时间,一旦获得:

  • 当列的默认值为NULL时,列的添加应该非常快,因为它不需要表重写:它只是目录中的更新。
  • 当列具有非NULL默认值时,它取决于PostgreSQL版本:版本11或更新版本,没有立即重写所有行,因此它应该与NULL情况一样快。但是对于10或更高版本,该表完全被重写,因此根据表的大小,它可能非常昂贵。

答案 1 :(得分:22)

添加新的空列将在非常短的时间内锁定表,因为无需重写磁盘上的所有数据。添加具有默认值的列需要PostgreSQL创建所有行的新版本并将其存储在磁盘上。在此期间,表格将被锁定。

因此,当您需要将具有默认值的列添加到大表时,建议先添加空值,然后以小部分更新所有行。这样你就可以避免磁盘上的高负载,并允许autovacuum完成它的工作,所以你最终不会使表大小加倍。

答案 2 :(得分:12)

http://www.postgresql.org/docs/current/static/sql-altertable.html#AEN57290

“添加具有非null默认值的列或更改现有列的类型将需要重写整个表和索引。”

因此,文档仅指定何时不重写表。 总会有锁,但如果不重写表,它将会很短。