如何在生产PostgreSQL上向表中添加一列,同时实现零停机



此处https://stackoverflow.com/a/53016193/10894456是为Oracle 11g提供的答案,我的问题是一样的:

添加具有默认值的非null列的最佳方法是什么在生产oracle数据库中,当该表包含一百万记录,它是现场直播。如果我们做这个列,它会创建锁吗创建,添加默认值并使其在单个中不为null陈述

但对于PostgreSQL?

这个先前的答案基本上回答了您的查询。

将相关PostgreSQL文档与上述答案中提到的AlterTableGetLockLevel的PostgreSQL源代码交叉引用表明,ALTER TABLE ... ADD COLUMN将始终获得ACCESS EXCLUSIVE表锁,从而在ADD COLUMN操作期间阻止任何其他事务访问该表。对于任何ADD COLUMN变体,都可以获得相同的独占锁;即,添加NULL列(带或不带DEFAULT(或使用默认值的NOT NULL都无关紧要。

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

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

我应该补充一点,对于PostgreSQL 11和更高版本,ALTER TABLE文档注意到,只有非易失性DEFAULT说明符才能避免表重写:

当使用ADD column添加列并指定非易失性DEFAULT时,将在语句时评估默认值,并将结果存储在表的元数据中。该值将用于所有现有行的列。如果未指定DEFAULT,则使用NULL。在这两种情况下都不需要重写表。

添加具有volatile DEFAULT[…]的列将需要重写整个表及其索引。[…]对于大型表,表和/或索引重建可能需要花费大量时间;并且将临时需要多达两倍的磁盘空间。

最新更新