因为如今pg的版本,修改int到bigint仍然须要rewrite表,会致使表阻塞,没法使用。但能够考虑其余方式来作。
此问题是排查现网pg使用序列的状况时遇到的。
因为int的最大值只有21亿左右,并且自增列多为主键,当达到最大值时,数据就会没法插入。通常状况是修改类型为bigint,但直接作会锁表,影响现网使用。
这里分两块来看:
一、分区表(修改序列):
对于分区表能够直接修改序列为循环形式,并且最大值设置为int的最大值,由于单个分区表不多会将int值用完。sql
alter sequence seq_name MAXVALUE 2147483647 CYCLE;
注意这里适用于按日或按月分区的表,对于hash分区表,只能修改字段类型。 oop
二、非分区表(修改成bigint)spa
因为建立表时,可能使用的是serial,因此此时就须要新建一个序列,否则字段id在删除时,以前的序列也会跟着一同被删除。
下面的步骤中要注意,添加主键约束部分,若是new_id上没有not null约束,则此时会进行全表扫描检查有无not null的记录。虽然pg检查记录是否为not null的操做比较快,但这一步仍是会锁较长时间(看记录数多少而定)。code
alter table table_name add column new_id bigint; ---循环更新new_id do language plpgsql $$ declare i int; begin for i in 0..1000 loop update table_name set new_id = id where id >= min(id)+ (max(id)-min(id))/1000*i and id< min(id) + max(id)-min(id))/1000*(i+1); end loop; end $$; create unique index CONCURRENTLY on table_name(new_id);
BEGIN; ALTER TABLE table_name DROP CONSTRAINT table_name_pkey; CREATE SEQUENCE table_name_new_id_seq; ALTER TABLE table_name ALTER COLUMN new_id SET DEFAULT nextval('table_name_new_id_seq'::regclass); UPDATE table_name SET new_id = id WHERE new_id IS NULL; ALTER TABLE table_name ADD CONSTRAINT table_name_pkey PRIMARY KEY USING INDEX table_name_pk_idx; ALTER TABLE table_name DROP COLUMN id; ALTER TABLE table_name RENAME COLUMN new_id to id; ALTER SEQUENCE table_name_new_id_seq RENAME TO table_name_id_seq; SELECT setval('table_name_id_seq', (SELECT max(id) FROM table_name)); COMMIT;
还有能够经过修改数据字典来实现一样操做的,不过不推荐使用,有可能引发元数据损坏。blog