我有一个数据库,该数据库将体验11月著名的Basecamp面对的integer exhaustion problem。我有几个月要弄清楚该怎么办。
是否存在无需停机的主动解决方案来迁移此列类型?如果是这样,那是什么?如果不是,那么我可以只吃顿停机时间并迁移色谱柱吗?
this article sufficient是不是假设我有几天/几周的时间要执行迁移,现在又要立即,当我用完ID之前,我被迫执行迁移?
答案 0 :(得分:3)
使用逻辑复制,您可以在主数据库和备用数据库中拥有不同的数据类型。
使用pg_dump -s
复制架构,更改副本上的数据类型,然后开始逻辑复制。
所有数据复制完毕后,切换应用程序以使用备用数据库。
要实现零停机时间,应用程序必须能够重新连接并重试,但这在这种情况下始终是必需的。
为此,您需要PostgreSQL v10或更高版本,并且您的数据库不应修改架构,因为不会复制DDL。
答案 1 :(得分:2)
创建旧表的副本,但ID字段已修改。接下来,在旧表上创建一个触发器,该触发器将新数据插入两个表中。最后,将数据从旧表复制到新表中(如果是连续的,最好通过id将前触发数据和后触发数据区分开来)。完成后,切换表并删除旧表。
这显然需要两倍的空间(和复制时间),但可以在没有任何停机时间的情况下工作。
答案 2 :(得分:1)
针对所有交易都很短的v10之前版本的数据库的另一种解决方案:
向表中添加var output = Array(Math.max(...input.map(arr => arr.length))).fill().map((_,i) => i)
.map(i => input.map(arr => arr[i] ))
.flat().filter(el => el !== undefined)
列。
创建一个bigint
触发器,该触发器将在添加或更新行时设置新列。
运行一系列更新,将新列从旧列设置为BEFORE
。使这些批次短一些,这样您就不会锁定太长时间,也不会死锁太多。确保这些事务以IS NULL
运行,因此它们不会触发触发器。
所有行都更新后,在新列上创建唯一索引session_replication_role = replica
。
为您刚创建的索引添加唯一约束CONCURRENTLY
。那会很快。
执行切换:
USING
那会很快。
您的新列未设置BEGIN;
ALTER TABLE ... DROP oldcol;
ALTER TABLE ... ALTER newcol RENAME TO oldcol;
COMMIT;
。没有长期的侵入性锁,就无法做到这一点。但是您可以添加检查约束NOT NULL
并创建IS NOT NULL
。这样就足够了,您以后可以在不中断的情况下对其进行验证。
如果有外键约束,事情会变得更加复杂。您必须删除它们并为新列创建NOT VALID
外键。