
乍一看,重命名数据库中的实体似乎很容易。SQL是一个非常简单的’ALTER ... RENAME TO ...’那么会出什么问题呢?
事实证明很多。任何以前运行过生产数据库的人都会意识到,在学术环境之外,这实际上有点困难。问题不在于数据库本身,而在于数据库客户端。当重命名发生时,任何仍在旧名称下运行的内容都将立即中断,从而导致停机和对用户的重大影响。
另一种选择是暂时禁用所有客户端,然后进行重命名,事实上,在21世纪初,“我们要维护了”屏幕是很常见的,但在20世纪20年代,严肃的服务旨在永远不会停机。这对用户来说很烦人,如果一个服务正在做一些关键业务,那就很痛苦。
实际上,管理生产数据库最简单的方法是从不重命名任何东西,并接受一些名称不太理想的事实。我大胆地猜测,大多数商店都是这样经营的——人们通常更愿意酌情重新命名,但在实践中,这需要花费更多的时间、风险和精力。
代码
但对于模式狂热者(比如我自己)来说,这并不是一个令人满意的答案。我们想重命名一些东西,但也要做到零停机和零用户影响。幸运的是,Postgres相对容易地实现了这一点。
以下是一些用于重命名表的可复制/可粘贴迁移代码(在本例中,chainwheel -> sprocket):

通过部署后(在所有客户端轮换后)跟进:

详细信息
为什么这样做:
RENAME TO立即以新名称使表可用sprocket.
为了支持仍在旧名称下运行的程序,我们创建了一个视图,该视图使用表的旧名称chainwheel作为表的替代。
Postgres支持 updatable views,这意味着在有一些注意事项的情况下,视图可以支持针对其底层表的INSERT、UPDATE和DELETE操作。
Postgres支持事务DDL,因此RENAME TO和CREATE VIEW可以原子化地进行。对于其他数据库使用者来说,表从未被重命名过,但新视图还不可用。这是使更改成为可能而不会对用户产生影响的关键功能。
概念验证演示
我做了一个小演示项目,演示了即使在程序运行时重命名的安全性。
我们启动一个小应用程序,用它现有的名称读取和写入表格:

在运行时,迁移到新名称:

请注意应用程序如何继续愉快地运行:

然后,我们可以启动一个使用新名称的过程:

在现实生活中,这将是对原始应用程序的新部署,该应用程序的表引用从chainwheel更新到sprocket。在它联机并且清除了旧进程之后,我们将运行DROP VIEW chainwheel的后续迁移。
干净的工作空间
该演示继续展示了可更新视图如何对重命名有用,但不能保证保持可更新。如果原始表的模式被更改为需要不在视图中的列,比如添加了一个新的not NULL列,那么对视图的插入将开始失败。
为了避免生产问题,请确保始终完成重命名操作。执行重命名和创建视图,部署并重新启动针对数据库运行的代码,然后删除视图。不要让它在未来成为其他人的最终落脚点。
原文链接:
https://brandur.org/fragments/postgres-table-rename





