Pg_dump/pg_restoreを使用してPostgreSQLデータベースをバックアップおよび復元していますが、pg_restoreからいくつかのエラーメッセージ(およびゼロ以外の終了ステータス)が返されます。私は非常に単純な基本ケース(以下に概説)を試しましたが、それでもこれらのエラーが発生しました:
pg_restore:[archiver(db)] TOCの処理中にエラーが発生しました: pg_restore:[archiver(db)] TOCエントリ5からのエラー。 2615 2200 SCHEMA public postgres pg_restore:[archiver(db)] couldn run query:ERROR:schema "public" already exists Command was:CREATE SCHEMA public;
再現する手順:
テストデータベースを作成します。私はただやっています:
vagrant @ vagrant-ubuntu-trusty-64:〜$ psql --username = postgres postgres psql(9.3.5) ヘルプとして「help」と入力してください。 postgres =#create database mydb; CREATE DATABASE postgres =#\ q vagrant @ vagrant-ubuntu-trusty-64:〜$ psql- -username = postgres mydb psql(9.3.5) ヘルプを表示するには「help」と入力します。 mydb =#create table data(entry bigint); CREATE TABLE mydb =#insert into data values(1); INSERT 0 1 mydb =#insert into data values(2); INSERT 0 1 mydb =#insert into data values(3); INSERT 0 1 mydb =#\ q
次のようにデータベースのバックアップを作成します。
PGPASSWORD = "postgres" pg_dump --dbname = mydb --username = postgres --format = custom> pg_backup.dump
Mydbのデータテーブルからいくつかの行を削除して、データが正常に復元されたかどうかを確認できるようにします。
以下を使用してデータベースを復元します。
PGPASSWORD = "postgres" pg_restore --clean --create --dbname = postgres --username = postgres pg_backup.dump
データは復元されますが、手順6のpg_restoreコマンドはステータス1
で終了し、次の出力を示します。
pg_restore:[archiver(db)] TOCの処理中にエラーが発生しました: pg_restore:[archiver(db)] TOCエントリ5からのエラー。 2615 2200 SCHEMA public postgres pg_restore:[archiver(db)] couldn run query:ERROR:schema "public" already exists Command was:CREATE SCHEMA public; 警告:復元時に無視されたエラー:1
このコマンドをプログラムで実行していて、終了ステータスを使用して復元が失敗したかどうかを判断する必要があるため、これを無視することはできません。最初、この問題の原因はデータベースをパブリック(デフォルトのスキーマ)に配置したためかと思いました。データが復元される前にpg_restoreによって--create
オプションの結果としてpublicが作成されると推論しました(おそらくテーブルがそこにあるため、スキーマも作成しようとする可能性があります)。テーブルを別のスキーマで使用する上記の手順では、結果は同じで、エラーメッセージは同じでした。
私は何か間違ったことをしていますか?このエラーが表示されるのはなぜですか?
エラーは無害ですが、それを取り除くには、次のように、この復元を2つのコマンドに分割する必要があると思います。
dropdb -U postgres mydb && \
pg_restore --create --dbname=postgres --username=postgres pg_backup.dump
Pg_restoreの--clean
オプションは多くのようには見えませんが、実際には重要な問題を引き起こします。
バージョン9.1まで
Pg_restoreオプションの--create
と--clean
の組み合わせは、以前のPGバージョン(9.1まで)ではエラーでした。 (9.1マンページを引用して)確かにいくつかの矛盾があります:
--cleanデータベースオブジェクトを再作成する前にクリーン(ドロップ)します。
そして
--create復元する前にデータベースを作成します。
新しいデータベースの内部をクリーンアップするポイントは何ですか?
バージョン9.2以降
組み合わせは受け入れられ、ドキュメントには次のように記載されています(9.3マンページを引用):
--cleanデータベースオブジェクトを再作成する前にクリーンアップ(ドロップ)します。 (これにより、宛先データベースにオブジェクトが存在しなかった場合、問題のないエラーメッセージが生成されることがあります。)
--create復元する前にデータベースを作成します。 --cleanも指定されている場合は、接続する前にターゲットデータベースを削除して再作成します。
両方を一緒にすると、復元中にこの種のシーケンスが発生します。
DROP DATABASE mydb;
...
CREATE DATABASE mydb WITH TEMPLATE = template0... [other options]
...
CREATE SCHEMA public;
...
CREATE TABLE...
個々のオブジェクトごとにDROP
はなく、最初はDROP DATABASE
のみです。 --create
を使用しない場合、これは逆になります。
とにかく、template0
からpublic
を作成するとすでにインポートされているため、このシーケンスは既存のmydb
スキーマのエラーを発生させます(これは通常、テンプレートデータベースのポイントです)。
このケースがpg_restore
によって自動的に処理されない理由がわかりません。管理者がtemplate0
をカスタマイズしたり、public
の目的を変更したりすると、予期しない副作用が発生する可能性があります。
私の場合、理由は、postgresql-contribバージョン11.2のpg_restore
を使用して、pg_dump
9.6で作成されたダンプをPostgreSQLクラスター9.6に復元していたためです。
pg_restore
を9.6にダウングレードした後、このschema "public" already exists
エラーはなくなり、復元プロセスは以前と同様に機能しました。
復元にはパブリックスキーマが含まれ、データベースも作成されます。したがって、データベースを作成した後にスキーマを削除して、復元でエラーなしでスキーマを作成できるようにします。
注:以下では、-h -U -pがデフォルトで、PGPASSWORDまたは.pgpassが設定されていると想定しています。
psql << XENDX
drop database if exists DB_NAME;
create database DB_NAME;
/c DB_NAME;
drop schema if exists public;
create schema public;
XENX
pg_restore -d DB_NAME FILE_CREATED_WITH_pg_dump
私はそれを解決しました:
の中に db.sql
ファイル
drop database if exists DB_name;
create database DB_name;
drop schema if exists public;
create schema public;
\q
その後
PGPASSWOD=DB_pass psql -U DB_user -h 127.0.0.1 < db.sql
その後
PGPASSWOD=DB_pass pg_restore -h 127.0.0.1 \
-U DB_user -d DB_name --create --no-acl --no-owner DB_dump_FILE
私のpg_restoreバージョンは11.6です