ソースデータベースがUTF8でエンコードされている場合、復元時にUTF8の無効なバイトシーケンスコピーエラーを解決する方法


17

PostgreSQL 8.2.xデータベースを別のサーバーに移行するタスクが与えられました。これを行うには、pgAdmin 1.12.2(ちなみにUbuntu 11.04)を使用し、カスタム/圧縮形式(.backup)とUTF8エンコードを使用したバックアップと復元を使用しています。

元のデータベースは、次のようにUTF8です。

-- Database: favela

-- DROP DATABASE favela;

CREATE DATABASE favela
  WITH OWNER = favela
       ENCODING = 'UTF8'
       TABLESPACE = favela
       CONNECTION LIMIT = -1;

移行先サーバーで、このようなデータベースを作成しています。しかし、復元オプションを使用して.backupファイルからデータベースを復元すると、次のエラーのいくつかが表示されます。

pg_restore: restoring data for table "arena"
pg_restore: [archiver (db)] Error while PROCESSING TOC:
pg_restore: [archiver (db)] Error from TOC entry 2173; 0 35500 TABLE DATA arena favela
pg_restore: [archiver (db)] COPY failed: ERROR:  invalid byte sequence for encoding "UTF8": 0xe3a709
HINT:  This error can also happen if the byte sequence does not match the encoding expected by the server, which is controlled by "client_encoding".
CONTEXT:  COPY arena, line 62

実際にどのレコードがこのエラーをトリガーしたかを確認すると、vartextフィールドにはç(ポルトガル語で使用される「caça」など)のような発音区別記号があります。コピーにエラーがあると、このテーブルへのデータの挿入が停止するためです。そして、これを達成するためにそれらを一つ一つ手動で置き換えたくありません。

しかし、UTF8ではこの種の問題はないはずですから、ちょっと奇妙ですよね?

そもそも彼らがどうやってそこに着いたのか分かりません。私はデータベースを移行するだけです。データベースはどういうわけかLATIN1のようで、その後UTF8に不適切に変更されたと思います。

テーブル/データベースに無効なUTF8シーケンスがあるかどうかを確認する方法はありますか?または、これらの文字を強制的にUFT8に変換または再変換して、復元の実行時に問題が発生しないようにする方法はありますか?

前もって感謝します。

回答:


8

インターネットを調べてみると、これはかなり一般的な問題であることがわかりました。一般的な解決策は、プレーンテキスト形式のダンプを使用し、それをiconvにフィードしてエンコードを修正することです。

その詳細についてはこちらをご覧ください。


iconvを使用してUTF-32に変換し、無効なシンボルを破棄してからUTF-8に戻します。UTF-8からUTF-8への変換は、すべての不良コードポイントをキャッチしません。(例:孤児の代理)
-Jasen

7

「そもそも彼らがどうやってそこに着いたのかわかりません」

ここで説明さているように発生する可能性があります -これは8.4でエラーを生成します:

任意のテキストタイプ(つまり、text、varchar(10)など)でテーブルを作成する場合、8進エスケープを使用してそのフィールドに無効なバイトシーケンスを挿入できます。

たとえば、UTF8でエンコードされたデータベースがある場合、次のことができます。

=> CREATE TABLE foo(t TEXT);

=> foo VALUES(E '\ 377');に挿入します。

これで、テーブルをコピーすると、結果のファイルをコピーして戻すことはできません。つまり、pg_dumpバックアップを復元することはできません。データを取り戻す唯一の方法は、その値を再エスケープすることです。

この優れたブログには、一般的な問題とそれらに対処するいくつかの方法についての良い投稿があります


1

Unix / Linux環境で使用されているデフォルトのエンコーディングを使用している可能性があります。現在どのエンコードがデフォルトのエンコードであるかを確認するには、次を実行します。

$ echo $LANG
en_US

この場合、コピーコマンドが依存するUTF-8エンコーディングではないことがはっきりとわかります。

したがって、これを修正するには、例のLANG変数を次のように設定するだけです。

$ export LANG=en_US.UTF-8

注:これは、現在のセッションでのみ使用できます。〜/ .bashrcなどに追加して、将来のシェルセッションの起動時に使用できるようにします。

参照


1

有効な文字(例:中国語文字)を他の文字に変換する可能性があるため、プレーンテキストダンプで盲目的にiconvを実行することはお勧めしません。以下のコマンドを実行して、無効なUTF8文字を見つけることをお勧めします。

grep -naxv '.*' plain_text_dump.sql

次に、特定のデータでiconvを実行します。詳細な手順ごとの説明については、このドキュメントを参照してください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.