特定の理由 のために、本番データベースの一部のシーケンスの名前を変更します。
最初にデータベースへのすべての接続を閉じる必要なしに、本番環境でこれを安全に行う方法はありますか?
IDシーケンスにギャップが生じても問題ありません(たとえば、ID 123からID 200にジャンプするなど)。ただし、長いロックが遅延やエラーの原因になることは望ましくなく、IDが重複するなどのリスクはありません。
HerokuのPostgreSQL 9.5.21を使用しています。
the docs を確認しましたが、実行の結果についてはまだ不確かです
ALTER SEQUENCE old_id_seq RENAME TO new_id_seq;
ALTER TABLE mytable ALTER COLUMN id SET DEFAULT nextval('new_id_seq');
生産中。これら2つのコマンドの間でmytable
に問題が発生した場合、1つのリスクが発生すると思います。しかし、次のようなことをしたらどうなるでしょうか。
-- 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;
そのようにすることのリスクは何ですか?
シーケンスがテーブル列のDEFAULT
句で使用されている場合は、シーケンスの名前を変更するだけで十分です。
これは、DEFAULT
句がnotであるので、文字列として格納されますが、解析された式ツリー(列adbin
in catalog pg_attrdef
)。その式ツリーにはシーケンスの名前は含まれていませんが、そのオブジェクトIDはシーケンスの名前を変更しても変更されません。 psql
のような\d
解析された式から文字列を再構築するため、DEFAULT
句は名前の変更を反映して表示されます。
シーケンス名がクライアントコードやPostgreSQL関数などの他の場所で使用されている場合、そのコードで名前を変更する必要があります。 PostgreSQL関数は文字列として保存されます(列prosrc
カタログpg_proc
)、シーケンスの名前を変更すると、シーケンスを使用する関数が失敗する可能性があります。
この場合、エラーを回避するには、コードを変更してシーケンスの名前を変更するまでアクティビティを一時停止する必要があります。
上記の方法で問題が解決されるとは思いません。どちらの場合も、PostgreSQLはテーブルのロックを取得するため、アプリケーションはALTERコマンドが完了するまで待機する必要があります。
ALTER SEQUENCE <sequence name> RENAME TO <new sequence name>
上記のコマンドは高速でなければならず、以下を実行する必要はありません
ALTER TABLE ALTER COLUMN SET DEFAULT nextval('new_id_seq');
シーケンスの名前を変更した後。 PostgreSQLは内部的に名前が変更されたことを認識しています。