开发应用程序并在其背后操作数据库集群时,会遇到一个意想不到的问题是实践与理论、开发环境与生产之间的差异。这种不匹配的一个完美例子就是更改列类型。
关于如何在 PostgreSQL(以及其他符合 SQL 标准的系统)中更改列类型的常规知识是:

这显然是语义上正确的方式,但是在适当的情况下,您可能会遇到相当不愉快的意外。
问题
让我们创建一个示例表并演示您可能观察到的孤立行为。让我们从 1000 万行开始(这实际上只是整个数据世界中的一小部分)。
我们将 id 类型从 INT 改为 BIGINT。

然后... 21 秒后,您就得到了更改。请注意,这是一个小表,其中大约有 600 MB 的数据。如果您要面对 100 倍于这个数量的情况怎么办?让我们看看幕后发生了什么。
PostgreSQL 必须做的事情
更改数据类型(以及您可能会遇到的许多其他操作)并非易事,PostgreSQL 引擎必须执行多项任务:
如您所见,执行一些可能被理解为常规表维护的操作涉及很多内容。修改的数据的大小、磁盘 I/O 和容量以及一般系统拥塞都会发挥作用。
但真正的问题并没有就此结束。如果我们谈论的是任何类型的严肃生产部署,你必须考虑更多的事情:
如您所见,更改列数据类型并不像看起来那么简单。当前的 CI/CD 实践通常使软件开发人员能够非常轻松地提交数据库迁移并将其推广到生产环境,但几分钟后他们就会发现自己处于生产事件之中。虽然暂存部署可能会有所帮助,但它不能保证与生产具有相同的特征(无论是由于负载水平还是资金限制)。
因此,问题在于(我会重复一遍),修改的数据量的规模、系统的整体拥塞程度、 I/O 容量以及目标表在应用程序设计中的重要性。
归根结底,这转化为完成迁移所需的 总时间 ,以及您的企业可以或可能无法承受的独特限制。解决该问题最简单的方法是将计划维护安排在流量较低的时段并完成它。
如何安全地更改 PostgreSQL 列类型
如果您需要重写数百 GB 甚至 TB 的数据,并且无法承受超过最低限度的停机时间,该怎么办?让我们探索如何正确更改列类型。
让我们先从 坏消息 开始——你无法避免重写整个表,这将在此过程中生成大量 WAL 文件。这是必然的,你必须计划如何管理它。
好消息: 您可以将潜在的停机时间分散到比处理数据所需的更长的时间段。具体要求和限制将根据各个业务需求而有所不同,因此仔细规划至关重要。
完整的迁移可以概括为以下一系列步骤:
order_id
最终会得到新列
new_order_id
。
设置一个触发器
,在有新数据进入时更新新列。这可确保迁移期间的所有新数据都将填充新列。
实现一个函数或逻辑,以便随着时间的
推移批量将
值从旧列迁移到新列。批次的大小和时间应与您的业务/环境的运营约束相一致。
迁移旧值:
根据您的约束、数据大小和 I/O 功能,此过程可能需要数小时到数周甚至更长时间。虽然在终端会话中运行的 SQL 或 PL/pgSQL 函数(考虑使用 tmux)可能足以完成较短的迁移,但更长的迁移可能需要更复杂的方法。仅此主题就可以成为单独的博客文章或指南的好主题。
迁移完成后,
创建反映新列的约束和索引
。注意潜在的锁定问题,尤其是当该字段是任何外键的一部分时。
此时,您已准备好执行切换本身。如果您可以验证所有行都已正确填充新列,那么是时候接受最困难的部分了。如果可能的话,在一个事务中或更短的计划停机时间内完成
删除旧列
。此操作通常只会短暂锁定表。
删除旧列后,
重命名新列
。此步骤完成了大部分迁移过程。
考虑重新启动所有依赖于更改的表的应用程序是一种很好的做法,因为某些工具(ORM......我正在看你)可能会缓存 OID 并且不能很好地处理更改。
就是这样 - 但事实并非如此。删除列只会删除引用,数据本身将物理保留在磁盘上。这是您可能需要执行的场景
VACUUM FULL
- 这可能会锁定表并完全重写它 - 可能会破坏并发迁移的目的。这让我们回到了促使我撰写本指南的原始文章 - [[The Bloat Busters:pg_repack vs pg_squeeze]] 是必经之路。强烈建议提前准备并熟悉这些工具。
结论
虽然更改 PostgreSQL 中的列类型可能像发出 ALTER TABLE 命令一样简单,但对于所有参与其中的人来说,了解与之相关的复杂性非常重要。无论您是请求更改的软件开发人员、审核人员,还是在没有仔细规划的情况下将此类更改部署到生产环境时负责解决事件的个人,深入了解此过程都至关重要。此外,掌握这一特定变化使您能够轻松地将洞察力投射到其他可能代价高昂的操作上。
编辑推荐:
下一篇:
相关推荐
-
雷神推出 MIX PRO II 迷你主机:基于 Ultra 200H,玻璃上盖 + ARGB 灯效
2 月 9 日消息,雷神 (THUNDEROBOT) 现已宣布推出基于英
-
制造商 Musnap 推出彩色墨水屏电纸书 Ocean C:支持手写笔、第三方安卓应用
2 月 10 日消息,制造商 Musnap 现已在海外推出一款 Oce
热文推荐
- 如何不改变 PostgreSQL 列类型
如何不改变 PostgreSQL 列类型
26-03-14 - 让PostgreSQL拥抱全局临时表功能
让PostgreSQL拥抱全局临时表功能
26-03-14 - 打破认知幻像:你写的SQL是否如你心意?
打破认知幻像:你写的SQL是否如你心意?
26-03-14 - 在 PostgreSQL 中强制执行连接顺序#postgresql认证
在 PostgreSQL 中强制执行连接顺序#postgresql认证
26-03-14 - 某大会的影响力正在扩大,吞噬了整个数据库世界!
某大会的影响力正在扩大,吞噬了整个数据库世界!
26-03-14 - 解密 PostgreSQL 加密:初学者指南#postgresql认证
解密 PostgreSQL 加密:初学者指南#postgresql认证
26-03-14 - 两个令人兴奋的 PostgreSQL 特性可改善 NULL 处理#PG认证
- 使用预加载库优化 PostgreSQL 函数#postgresql认证
使用预加载库优化 PostgreSQL 函数#postgresql认证
26-03-14 - 使用 pgbadger 自动填充准备好的语句占位符
使用 pgbadger 自动填充准备好的语句占位符
26-03-14 - RockyLinux部署流水线实战指南(从零搭建CI/CD自动化部署流程)
