我想我在某处读到在 postgres 数据库上运行
ALTER TABLE foo ADD COLUMN baz text
不会导致读或写锁定。设置默认值会导致锁定,但允许空默认值可防止锁定。
不过,我在文档中找不到这个。任何人都可以指出一个地方,明确说明这是真的还是假的?
不同类型的锁以及它们的使用时间在文档中提到 表级锁。例如,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
。
关于锁持有多久,一旦获得:
添加新的空列将锁定表非常非常短的时间,因为不需要重写磁盘上的所有数据。虽然添加具有默认值的列需要 PostgreSQL 为所有行创建新版本并将它们存储在磁盘上。在此期间,桌子将被锁定。
因此,当您需要向大表添加具有默认值的列时,建议先添加空值,然后小部分更新所有行。这样,您将避免磁盘上的高负载,并允许 autovacuum 完成其工作,这样您就不会最终使表大小加倍。
http://www.postgresql.org/docs/current/static/sql-altertable.html#AEN57290
“添加具有非空默认值的列或更改现有列的类型将需要重写整个表和索引。”
因此文档仅指定何时不重写表。 总会有一个锁,但它会很短,以防表不被重写。
设置默认值会导致锁定,但允许空默认值会防止锁定。
其他答案已经过时了。从 Postgres 11 开始,添加具有默认值(空或其他)的列不需要重写表。它只会锁定表几毫秒,因此本质上不会锁定全部。添加具有默认值的列现在是一种快速且廉价的操作!