我有一个数据库,它将遇到 Basecamp 在 11 月著名的整数耗尽问题。我有几个月的时间来弄清楚该怎么做。
迁移此列类型是否有无需停机的主动解决方案?如果是这样,那是什么?如果不是,是否只是消耗停机时间并尽可能迁移色谱柱?
这篇文章是否足够,假设我现在有几天/几周的时间来执行迁移,然后在我用完 id 时被迫这样做?
对于所有事务都很短的 pre-v10 数据库的另一种解决方案:
向表中添加一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
。这已经足够好了,您以后可以在不中断的情况下对其进行验证。
如果有外键约束,事情会变得有点复杂。您必须删除这些并NOT VALID
为新列创建外键。
创建旧表的副本,但修改了 ID 字段。接下来在旧表上创建一个触发器,将新数据插入两个表。最后将数据从旧表复制到新表(如果它是顺序的,最好通过 id 区分预触发数据和后触发数据)。完成后切换表并删除旧表。
这显然需要两倍的空间(和复制时间),但可以在没有任何停机时间的情况下工作。