Question

We want to rename some sequences in our production database for certain reasons.

Is there a way to do this safely in production without having to first close all connections to the database?

It's fine if we get gaps in the ID sequence (e.g. it jumps from ID 123 to ID 200 or whatever) but we obviously don't want long locks causing delays/errors, don't want any risk of duplicate IDs and similar.

We're on PostgreSQL 9.5.21 on Heroku.

We've looked at the docs but are still uncertain about the consequences of running

ALTER SEQUENCE old_id_seq RENAME TO new_id_seq;
ALTER TABLE mytable ALTER COLUMN id SET DEFAULT nextval('new_id_seq');

in production. I guess one risk would be if stuff happens in mytable between those two commands. But what if we did something like this:

-- Starting at a much higher value than the currently highest ID.
CREATE SEQUENCE new_id_seq START 200;

ALTER TABLE mytable ALTER COLUMN id SET DEFAULT nextval('new_id_seq');

DROP SEQUENCE old_id_seq;

What are the risks of doing it that way?

Was it helpful?

Solution

  • If the sequence is used in the DEFAULT clause of the table column, it is enough to rename the sequence.

    That is because the DEFAULT clause is not stored as string, but as parsed expression tree (column adbin in catalog pg_attrdef). That expression tree does not contain the name of the sequence, but its object ID, which is unchanged by renaming the sequence. Tools like psql's \d re-construct a string from the parsed expression, so the DEFAULT clause will appear to reflect the renaming.

  • If the sequence name is used elsewhere, like in your client code or in a PostgreSQL function, you would have to change the name in that code. PostgreSQL functions are stored as strings (column prosrc in catalog pg_proc), so renaming a sequence can make a function that uses the sequence fail.

    In this case, you would have to suspend activity until you have changed the code and renamed the sequence if you want to avoid errors.

OTHER TIPS

I don't think the mentioned method is going to solve your problem. In both cases, PostgreSQL is going to acquire a lock on the table, and the application has to wait for the ALTER command to be finished.

ALTER SEQUENCE <sequence name> RENAME TO <new sequence name>

Above command should be fast and you don't need following

ALTER TABLE ALTER COLUMN SET DEFAULT nextval('new_id_seq');

After renaming the sequence. PostgreSQL internally knows the name has been changed.

Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top