PostgreSQL 是否支持在线模式修改 (DDL)?

duk*_*ody 5 mysql postgresql concurrency ddl

MySQL 的最新版本(使用 InnoDB)支持许多没有独占锁定表的更改表查询

PostgreSQL 是否支持任何级别?也就是说,我可以在同时读取/写入行的同时从表中添加/删除列吗(即使性能下降)?

Cra*_*ger 7

TL;DR:不,除了一些基本情况。

PostgreSQL 9.5 中添加了一些针对 ALTER TABLE 的锁强度降低。但是,在 9.5 或更低版本中,您无法在没有排他锁的情况下执行需要全表重写的任何操作。

即使在旧版本中,某些操作,例如ALTER TABLE ... DROP COLUMNALTER TABLE ... ADD COLUMN ...不使用 aDEFAULT和 ,NOT NULL也可以使用非常短的排他锁来完成。查询不运行时需要片刻,但它几乎是瞬时的,因为不需要重写表。

有些事情可以优化,例如ALTER TABLE ... ADD COLUMN ... DEFAULT ... NOT NULL,通过在表元数据中存储旧行的默认值并在读取旧行时查找它。这尚未在 PostgreSQL 中实现。

理论上,PostgreSQL 可以使用其 MVCC 目录来支持您通过将新版本的行后台写入表中同时继续使用旧版本进行查询来描述的内容。我不知道有人试图这样做,它需要一些特殊处理,因为 PostgreSQL 的代码当前假定表行在任何给定时间只有一种可能的结构。

  • 据我了解,在 MySQL 中添加新列意味着创建表的临时副本,对其应用并发更改,然后将其放入旧的位置。相比之下,在 PostgreSQL 中添加新列实际上是对目录的更改 - 严格意义上不是在线,但如果小心完成,只会通过排他锁造成最小的干扰。所以,从实用的角度来看,postgres 已经存在了相当长的时间...... (2认同)
  • MySQL 5.6 可以做很多`ALTERs` _而无需_创建一个临时副本。 (2认同)

小智 5

正如Craig Ringer提到的,PostgreSQL 很早以前就开始支持一些无锁的 ALTER 操作。

但由于版本 11 ALTER TABLE ... ADD COLUMN ... DEFAULT ... NOT NULL还避免了表重写(以及长时间锁定),因此您可以在迁移中安全地使用它。

您可以在这篇文章中阅读更多相关信息:使用默认值快速创建列