如何在减少膨胀或 ALTER (ing) 表的同时最小化访问独占表锁?

joa*_*olo 7 postgresql optimization maintenance online-operations postgresql-9.6

在某些情况下,我被告知不要对生产中的表执行 VACUUM FULL(或 CLUSTER),因为这将独占锁定它的时间比预期的要长。这同样适用于几个 ALTER TABLE 操作(例如更改几个列的类型)。

提出的替代方案始终是执行以下操作:

 CREATE TABLE new_table AS SELECT * FROM old_table ;
 -- recreate all indices and constraints
 ALTER TABLE old_table RENAME TO going_to_drop_table ;
 ALTER TABLE new_table RENAME TO old_table ;
 DROP TABLE going_to_drop_table ;
Run Code Online (Sandbox Code Playgroud)

这适用于没有依赖关系的场景old_table(意味着没有任何依赖它的视图,也没有任何外键约束、函数等),并且old_table没有任何插入或更新。但在大多数数据库中,这将是一个例外,而不是规则。

有没有办法在不丢失依赖关系的情况下进行这样的“表交换”?

[为了完整起见:我对如何为 PostgreSQL 9.5 或 9.6 做这件事特别感兴趣]


研究到现在(关于根本原因):

  1. 是否可以在 Postgres 中异步运行 VACUUM FULL?=> pg_repack。注意事项:在 Windows 上可能不容易实现,未使用 postgresql 9.6 进行测试。看起来是最有希望的选择。
  2. pg_reorg: 类似于 pg_repack(是它的基础)=> 自 postgresql 9.4 以来似乎没有更新,并且它主要被pg_repack.
  3. 来自 OmniTI 的基于 bash 的旧工具,由Reduce Bloat of table without long/exclusive Locks引用=> 看起来不是最新的。
  4. 清理 PostgreSQL Bloat =>(对于我感兴趣的内容),基本上建议vacuumdb使用--jobs=njobs. 看起来是一种加速真空的方法,也是一种实际的可能性。我不喜欢文档中的句子“请注意,如果并行处理某些系统目录,将此模式与 -f (FULL) 选项一起使用可能会导致死锁失败。”
  5. pgcompact来自pgtoolkit => 不知道这是否是最新的。它基于Reducing bloat without locked,看起来很安全。
  6. Safe Operations For High Volume PostgreSQL:一个很好的解决方法集合,可以最大限度地减少表锁定。感谢@hruske 的评论。

哪个是避免与 ALTER TABLE ALTER COLUMN ...、CLUSTER 或 VACUUM FULL 相关联的排他锁的最佳方法?