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

问题描述 投票:0回答:4

我想我在某处读到在 postgres 数据库上运行

ALTER TABLE foo ADD COLUMN baz text
不会导致读或写锁定。设置默认值会导致锁定,但允许空默认值可防止锁定。

不过,我在文档中找不到这个。任何人都可以指出一个地方,明确说明这是真的还是假的?

postgresql alter-table
4个回答
61
投票

不同类型的锁以及它们的使用时间在文档中提到 表级锁。例如,Postgres 11 的

ALTER TABLE
可能会获取
SHARE UPDATE EXCLUSIVE
SHARE ROW EXCLUSIVE
ACCESS EXCLUSIVE
锁。

Postgres 9.1 到 9.3 声称支持上述三个中的两个,但实际上强制

Access Exclusive
此命令的所有变体。此限制在 Postgres 9.4 中已被 取消,但
ADD COLUMN
仍按设计保留为
ACCESS EXCLUSIVE

查看源代码很容易,因为有一个函数专门用于建立该命令在各种情况下所需的锁定级别:

AlterTableGetLockLevel
in
src/backend/commands/tablecmds.c


关于锁持有多久,一旦获得:

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

37
投票

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

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


13
投票

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

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

因此文档仅指定何时不重写表。 总会有一个锁,但它会很短,以防表不被重写。


0
投票

设置默认值会导致锁定,但允许空默认值会防止锁定。

其他答案已经过时了。从 Postgres 11 开始,添加具有默认值(空或其他)的列不需要重写表。它只会锁定表几毫秒,因此本质上不会锁定全部。添加具有默认值的列现在是一种快速且廉价的操作!

© www.soinside.com 2019 - 2024. All rights reserved.