Bagaimana mengatasi kesalahan salin urutan byte UTF8 tidak valid pada pemulihan, ketika sumber database dikodekan dalam UTF8?

17

Saya diberi tugas untuk memigrasi database PostgreSQL 8.2.x ke server lain. Untuk melakukan ini saya menggunakan pgAdmin 1.12.2 (pada Ubuntu 11,04 by the way) dan menggunakan Backup dan Restore menggunakan format kustom / kompres (.backup) dan pengkodean UTF8.

Database asli ada di UTF8, seperti:

-- Database: favela

-- DROP DATABASE favela;

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

Saya membuat database ini persis seperti ini di server tujuan. Tetapi ketika saya mengembalikan database dari file .backup menggunakan opsi Restore itu memberi saya beberapa kesalahan ini:

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

Ketika saya memeriksa catatan mana yang memicu kesalahan ini pada kenyataannya beberapa bidang vartext memiliki karakter diakritik seperti ç (digunakan dalam bahasa Portugis, misalnya, "caça"), dan ketika saya menghapusnya secara manual dari teks dalam catatan, kesalahan berlanjut ke catatan berikutnya yang memiliki mereka - karena ketika salinan memiliki kesalahan itu berhenti memasukkan data pada tabel ini. Dan saya tidak ingin menggantinya secara manual satu per satu untuk mencapai ini.

Tapi ini agak aneh karena dengan UTF8 seharusnya tidak ada masalah seperti ini, kan?

Saya tidak tahu bagaimana mereka sampai di sana. Saya hanya memigrasi database, dan saya kira entah bagaimana database seperti di LATIN1 dan kemudian diubah menjadi UTF8.

Apakah ada cara untuk memeriksa apakah tabel / database memiliki urutan UTF8 yang tidak valid? Atau cara apa pun untuk memaksakan / mengubah karakter ini ke UFT8 jadi saya tidak mengalami masalah ketika saya menjalankan pengembalian?

Terima kasih sebelumnya.

pedrosanta
sumber

Jawaban:

8

Menggali di internet, saya telah melihat bahwa ini adalah masalah yang cukup umum. Solusi umum adalah dengan menggunakan dump format teks biasa dan memberi makan melalui iconv untuk memperbaiki pengkodean.

Berikut ini informasi lebih lanjut tentang itu.

Richard
sumber
gunakan ikonv untuk mengkonversi ke UTF-32 membuang simbol yang tidak valid dan kemudian kembali ke UTF-8, konversi UTF-8 ke UTF-8 tidak akan menangkap semua poin kode buruk. (mis. pengganti yatim piatu)
Jasen
7

"Aku tidak tahu bagaimana mereka sampai di sana."

Itu bisa terjadi seperti yang dijelaskan di sini - meskipun ini menghasilkan kesalahan pada 8.4:

Jika Anda membuat tabel dengan jenis teks apa pun (yaitu teks, varchar (10), dll.), Maka Anda dapat menyisipkan urutan byte yang tidak valid ke dalam bidang tersebut menggunakan oktal escapes.

Misalnya, jika Anda memiliki basis data yang disandikan UTF8, Anda dapat melakukan:

=> CREATE TABLE foo (t TEXT);

=> INSERT INTO foo VALUES (E '\ 377');

Sekarang, jika Anda SALINAN tabel keluar, Anda tidak bisa SALINAN file yang dihasilkan kembali. Itu berarti cadangan pg_dump Anda tidak akan dapat mengembalikan. Satu-satunya cara untuk mendapatkan kembali data Anda adalah melepaskan diri dari nilai itu.

Ada posting yang bagus di blog yang luar biasa ini tentang masalah-masalah umum dan beberapa cara untuk mengatasinya

Jack Douglas
sumber
1

Kemungkinan dengan encoding default yang digunakan di lingkungan Unix / Linux Anda. Untuk memeriksa pengkodean mana yang saat ini menjadi default, jalankan yang berikut ini:

$ echo $LANG
en_US

Dalam hal ini, kita dapat dengan jelas melihat bahwa ini bukan pengkodean UTF-8, yang menjadi sandaran perintah salin.

Jadi untuk memperbaiki ini, kita hanya mengatur variabel LANG dalam contoh sebagai berikut:

$ export LANG=en_US.UTF-8

Catatan: Ini hanya akan tersedia untuk sesi saat ini. Tambahkan ke ~ / .bashrc atau yang serupa agar tersedia pada saat memulai setiap sesi shell di masa depan.

Referensi

arulraj.net
sumber
1

Saya tidak merekomendasikan menjalankan iconv secara membabi buta pada dump teks biasa karena dapat mengkonversi karakter yang valid (misalnya: karakter Cina) ke beberapa karakter lain. Lebih baik untuk menemukan karakter UTF8 yang tidak valid dengan menjalankan perintah di bawah ini.

grep -naxv '.*' plain_text_dump.sql

dan kemudian jalankan ikonv pada data tertentu. Periksa dokumen ini untuk penjelasan langkah demi langkah yang terperinci .

Nijil
sumber