将 PostgreSQL 中的列类型 VARCHAR 更改为 TEXT 而无需锁定 table

Change column type VARCHAR to TEXT in PostgreSQL without lock table

我有一个 "Parent Table" 并且按年份分区 table 有很多列,现在我需要将列 VARCHAR(32) 更改为 TEXT 因为我们需要更大的长度灵活性.

所以我会更改父级,它们也会更改所有分区。

但是 table 对此列有 2 个唯一索引和 1 个索引。

此查询锁定 table:

ALTER TABLE my_schema.my_table
ALTER COLUMN column_need_change TYPE VARCHAR(64) USING 
column_need_change :: VARCHAR(64);

还有这个:

ALTER TABLE my_schema.my_table
ALTER COLUMN column_need_change TYPE TEXT USING column_need_change :: TEXT;

我看到了这个解决方案:

UPDATE pg_attribute SET atttypmod = 64+4
WHERE attrelid = 'my_schema.my_table'::regclass
AND attname = 'column_need_change ';

但我不喜欢这个解决方案。

如何在没有锁定的情况下将 VARCHAR(32) 类型更改为 TEXT table,我需要在更新之间继续推送 table 中的一些数据。

我的 Postgresql 版本:9.6

编辑:

这是我最终采用的解决方案:

ALTER TABLE my_schema.my_table
ALTER COLUMN column_need_change TYPE TEXT USING column_need_change :: TEXT;

查询锁定我的 table 之间:1m 52s 548ms 260 万行,但没问题。

受支持且安全的变体是使用 ALTER TABLE。这将 而不是 重写 table,因为 varchartext 具有相同的磁盘表示,所以它会在瞬间完成一旦获得 ACCESS EXCLUSIVE table 锁。

如果您的交易很短,您只会在 ALTER TABLE 等待所有之前的交易完成时遇到短暂的停顿。

乱用系统目录很危险,风险自负。

可能逃脱

UPDATE pg_attribute
SET atttypmod = -1,
    atttypid  = 25
WHERE attrelid = 'my_schema.my_table'::regclass
  AND attname = 'column_need_change';

但如果它破坏了某些东西,你可以保留碎片……