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」など)の発音区別符号が含まれ、レコードのテキストから手動で削除すると、エラーは次のレコードに渡されますコピーにエラーがあると、このテーブルへのデータの挿入が停止するためです。そして、これを達成するために手動で1つずつ置き換えたいとは思いません。
しかし、UTF8ではこの種の問題が発生してはならないので、それはちょっと変です。
そもそもどうやってそこに着いたのかはわかりません。私はデータベースを移行しているだけで、データベースがLATIN1のようであったため、UTF8に不適切に変更されたと考えられます。
テーブル/データベースに無効なUTF8シーケンスがあるかどうかを確認する方法はありますか?または、これらの文字をUFT8に適用/再変換して、復元を実行するときに問題が発生しないようにする方法はありますか?
前もって感謝します。
インターネットを掘り下げてみると、これはかなり一般的な問題であることがわかりました。一般的な解決策は、プレーンテキスト形式のダンプを使用し、それをiconvにフィードしてエンコードを修正することです。
ここ はその詳細情報です。
「そもそも彼らがどうやってそこに着いたのか、私にはわかりません」
説明されているように発生する可能性があります ここ -これは8.4でエラーを生成します:
テキストタイプ(text、varchar(10)など)でテーブルを作成する場合、8進エスケープを使用して、そのフィールドに無効なバイトシーケンスを挿入できます。
たとえば、UTF8でエンコードされたデータベースがある場合は、次のことができます。
=> CREATE TABLE foo(t TEXT);
=> INSERT INTO foo VALUES(E '\ 377');
これで、テーブルをコピーした場合、結果のファイルをコピーして戻すことはできません。つまり、pg_dumpバックアップを復元できなくなります。データを戻す唯一の方法は、その値を再エスケープすることです。
これに関する良い投稿があります 優れたブログ 一般的な問題とそれらに対処するいくつかの方法について
プレーンテキストダンプでiconvを盲目的に実行することはお勧めしません。これは、有効な文字(中国語の文字など)を他の文字に変換する可能性があるためです。以下のコマンドを実行して、無効なUTF8文字を見つけることをお勧めします。
grep -naxv '.*' plain_text_dump.sql
次に、特定のデータに対してiconvを実行します。 詳細な手順ごとの説明については、このドキュメント を確認してください。
Unix/Linux環境で使用されているデフォルトのエンコーディングを使用している可能性があります。現在デフォルトのエンコーディングを確認するには、次のコマンドを実行します。
$ echo $LANG
en_US
この場合、コピーコマンドが依存するUTF-8エンコーディングではないことが明確にわかります。
これを修正するには、例のLANG変数を次のように設定します。
$ export LANG=en_US.UTF-8
注:これは現在のセッションでのみ使用できます。それを〜/ .bashrcなどに追加して、今後のシェルセッションの起動時に使用できるようにします。
次のリンクを参照して、ソースエンコーディングを特定し、それを目的のUTF-8エンコーディングに変換する手がかりを得ることができました。 Linuxのチェックとエンコードの変更
$ file -bi cabot.sql
text/plain; charset=utf-16le
$ iconv -f utf-16le -t utf-8 -o converted.sql cabot.sql
$ file -bi converted.sql
text/plain; charset=utf-8