pg_restore:[アーカイバ(db)]クエリを実行できませんでした:エラー:スキーマ "public"は既に存在します


17

pg_dump / pg_restoreを使用してPostgreSQLデータベースをバックアップおよび復元していますが、pg_restoreからいくつかのエラーメッセージ(およびゼロ以外の終了ステータス)を取得しています。私は非常にシンプルなベースケース(以下に概説)を試しましたが、まだこれらのエラーが発生しました:

pg_restore:[アーカイバ(db)] TOC処理中のエラー:
pg_restore:[archiver(db)] TOCエントリ5からのエラー。2615 2200 SCHEMAパブリックポストグレス
pg_restore:[アーカイバ(db)]クエリを実行できませんでした:エラー:スキーマ "public"は既に存在します
    コマンドは:CREATE SCHEMA public;

再現する手順:

  1. 新鮮なバニラUbuntu 14.04ディストリビューションをインストールします(このVagrantボックスで Vagrantを使用しています)。
  2. PostgreSQL 9.3をインストールし、LinuxユーザーからのPostgreSQLユーザー「postgres」としてローカル接続を許可するように設定します。
  3. テストデータベースを作成します。私はただやっている:

    vagrant @ vagrant-ubuntu-trusty-64:〜$ psql --username = postgres postgres
    psql(9.3.5)
    ヘルプを表示するには「help」と入力します。
    
    postgres =#データベースmydbを作成;
    データベース作成
    postgres =#\ q
    vagrant @ vagrant-ubuntu-trusty-64:〜$ psql --username = postgres mydb
    psql(9.3.5)
    ヘルプを表示するには「help」と入力します。
    
    mydb =#create table data(entry bigint);
    テーブルを作成
    mydb =#データ値に挿入(1);
    挿入0 1
    mydb =#データ値に挿入(2);
    挿入0 1
    mydb =#データ値に挿入(3);
    挿入0 1
    mydb =#\ q
    
  4. 次のようにデータベースのバックアップを作成します。

    PGPASSWORD = "postgres" pg_dump --dbname = mydb --username = postgres --format = custom> pg_backup.dump
  5. mydbのデータテーブルからいくつかの行を削除して、データが正常に復元されたかどうかを確認できるようにします。

  6. 以下を使用してデータベースを復元します。

    PGPASSWORD = "postgres" pg_restore --clean --create --dbname = postgres --username = postgres pg_backup.dump

データは復元されますが、手順6のpg_restoreコマンドはステータス1で終了し、次の出力を表示します。

pg_restore:[アーカイバ(db)] TOC処理中のエラー:
pg_restore:[archiver(db)] TOCエントリ5からのエラー。2615 2200 SCHEMAパブリックポストグレス
pg_restore:[アーカイバ(db)]クエリを実行できませんでした:エラー:スキーマ "public"は既に存在します
    コマンドは:CREATE SCHEMA public;



警告:復元時に無視されるエラー:1

このコマンドをプログラムで実行しており、終了ステータスを使用して復元が失敗したかどうかを判断する必要があるため、これを無視することはできません。最初は、この問題がデータベースをパブリック(デフォルトのスキーマ)にしたためかどうか疑問に思いました。私--createは、データが復元される前にpg_restoreによるオプションの結果としてパブリックが作成されると推論しました(これは私のテーブルがある場所なので、スキーマを作成しようとする可能性があります)が、テーブルで上記の手順を試したとき異なるスキーマでは、結果は同じで、エラーメッセージは同じでした。

私は何か間違っていますか?このエラーが表示されるのはなぜですか?

回答:


16

エラーは無害ですが、それを取り除くには、次のようにこの復元を2つのコマンドに分割する必要があると思います。

dropdb -U postgres mydb && \
 pg_restore --create --dbname=postgres --username=postgres pg_backup.dump

--cleanpg_restore のオプションはあまり見かけませんが、実際には重要な問題が発生します。

9.1までのバージョン

pg_restoreオプション--create--cleanpg_restoreオプションの組み合わせは、以前のバージョンの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は逆になります。

とにかく、このシーケンスは、エラーの発生させpublic作成しているため、既存のスキーマmydbからtemplate0すでにそれを輸入しています(正常です、それはテンプレートデータベースのポイントですが)。

このケースがによって自動的に処理されない理由はわかりませんpg_restore。管理者がtemplate0の目的をカスタマイズおよび/または変更することを決定したpublic場合、これが行われることを想定していない場合でも、望ましくない副作用を引き起こす可能性があります。


9.6を使用していますが、指定--createcleanずに問題を解決することはできません。
セリン

6

私の場合、理由は、9.6でpg_restore作成されたダンプをpg_dumpPostgreSQLクラスター9.6 に復元するためにpostgresql-contribバージョン11.2から使用していたためです。

pg_restore9.6 にダウングレードした後、このschema "public" already existsエラーはなくなり、復元プロセスは以前と同じように機能しました。


しかし、pg_restore 9.6を使用してpostgres 11.2データベースにダンプを復元しましたか?
マリアーノルイス

@MarianoRuiz私の元の答えは明確だと思います:「pg_dump 9.6によって作成されたダンプをPostgreSQLクラスター9.6に復元するためにpostgresql-contribバージョン11.2のpg_restoreを使用していました。」あなたの質問に:いいえ、私はしませんでした。私のpg_restoreは11.2でしたが、pgクラスターは9.6でした
Lu Liu
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.