如何在零停机时间的情况下向生产 PostgreSQL 上的 table 添加列?

How to add a column to a table on production PostgreSQL with zero downtime?

这里 是为 Oracle 11g 提供的答案, 我的问题是一样的:

What is the best approach to add a not null column with default value in production oracle database when that table contain one million records and it is live. Does it create any locks if we do the column creation , adding default value and making it as not null in a single statement?

但是对于 PostgreSQL 呢?

This prior answer 基本上回答了您的问题。

交叉引用上述答案中提到的 relevant PostgreSQL doc with the PostgreSQL sourcecode for AlterTableGetLockLevel 表明 ALTER TABLE ... ADD COLUMN 将始终获得 ACCESS EXCLUSIVE table 锁,从而阻止任何其他事务访问 table 在 ADD COLUMN 操作期间。 对于任何 ADD COLUMN 变体,都会获得相同的独占锁; IE。添加 NULL 列(带或不带 DEFAULT)或使用默认值 NOT NULL 都没有关系。

但是,如上面链接的答案中所述,添加没有 DEFAULTNULL 列应该非常快,因为此操作只是更新目录。

相比之下,添加带有 DEFAULT 说明符的列需要在 PostgreSQL 10 或更低版本中重写整个 table。 这个操作很可能会在你的 1M 记录上花费相当长的时间table。 根据链接的答案,PostgreSQL >= 11 不需要这样的重写来添加这样的列,因此应该更类似于 no-DEFAULT 的情况。

我应该补充一点,对于 PostgreSQL 11 及更高版本,ALTER TABLE docs 请注意 table 重写仅针对非易失性 DEFAULT 说明符避免:

When a column is added with ADD COLUMN and a non-volatile DEFAULT is specified, the default is evaluated at the time of the statement and the result stored in the table's metadata. That value will be used for the column for all existing rows. If no DEFAULT is specified, NULL is used. In neither case is a rewrite of the table required.

Adding a column with a volatile DEFAULT [...] will require the entire table and its indexes to be rewritten. [...] Table and/or index rebuilds may take a significant amount of time for a large table; and will temporarily require as much as double the disk space.