Làm cách nào để giải quyết lỗi sao chép chuỗi byte không hợp lệ UTF8 khi khôi phục, khi cơ sở dữ liệu nguồn được mã hóa trong UTF8?


17

Tôi đã được giao nhiệm vụ di chuyển cơ sở dữ liệu PostgreSQL 8.2.x sang một máy chủ khác. Để thực hiện điều này, tôi đang sử dụng pgAdmin 1.12.2 (trên Ubuntu 11.04 bằng cách này) và sử dụng Sao lưu và Khôi phục bằng cách sử dụng định dạng tùy chỉnh / nén (.backup) và mã hóa UTF8.

Cơ sở dữ liệu ban đầu là trong UTF8, như vậy:

-- Database: favela

-- DROP DATABASE favela;

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

Tôi đang tạo cơ sở dữ liệu này chính xác như thế này trên máy chủ đích. Nhưng khi tôi khôi phục cơ sở dữ liệu từ tệp .backup bằng tùy chọn Khôi phục, nó sẽ cho tôi một số lỗi sau:

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

Khi tôi kiểm tra bản ghi nào đã gây ra lỗi này trong thực tế, một số trường vartext có các ký tự dấu phụ như ç (được sử dụng trong tiếng Bồ Đào Nha, ví dụ: "caça") và khi tôi xóa chúng khỏi văn bản trong bản ghi thì lỗi sẽ chuyển sang bản ghi tiếp theo có lỗi - vì khi sao chép có lỗi, nó sẽ dừng chèn dữ liệu trên bảng này. Và tôi không muốn thay thế chúng bằng tay từng cái một để thực hiện điều này.

Nhưng điều đó thật lạ vì với UTF8 không nên có loại vấn đề này, phải không?

Tôi không biết làm thế nào họ đến đó ngay từ đầu. Tôi chỉ di chuyển cơ sở dữ liệu và tôi cho rằng bằng cách nào đó cơ sở dữ liệu giống như trong LATIN1 và sau đó được thay đổi không chính xác thành UTF8.

Có cách nào để kiểm tra xem bảng / cơ sở dữ liệu có trình tự UTF8 không hợp lệ không? Hoặc có cách nào để thực thi / chuyển đổi các ký tự này thành UFT8 để tôi không gặp phải bất kỳ vấn đề nào khi thực hiện khôi phục không?

Cảm ơn trước.

Câu trả lời:


8

Tìm hiểu trên internet, tôi đã thấy rằng đây là một vấn đề khá phổ biến. Giải pháp phổ biến là sử dụng kết xuất định dạng văn bản đơn giản và cung cấp thông qua iconv để sửa mã hóa.

Dưới đây là thông tin thêm về điều đó.


sử dụng iconv để chuyển đổi sang UTF-32 loại bỏ các ký hiệu không hợp lệ và sau đó quay lại UTF-8, chuyển đổi UTF-8 sang UTF-8 sẽ không bắt được tất cả các điểm mã xấu. (ví dụ người thay thế mồ côi)
Jasen

7

"Tôi không biết làm thế nào họ đến đó ngay từ đầu"

Nó có thể xảy ra như được mô tả ở đây - mặc dù điều này tạo ra lỗi trên 8.4:

Nếu bạn tạo một bảng với bất kỳ loại văn bản nào (ví dụ văn bản, varchar (10), v.v.), thì bạn có thể chèn một chuỗi byte không hợp lệ vào trường đó bằng cách sử dụng thoát bát phân.

Ví dụ: nếu bạn có cơ sở dữ liệu được mã hóa UTF8, bạn có thể thực hiện:

=> TẠO BẢNG foo (t TEXT);

=> XÁC NHẬN VÀO GIÁ TRỊ foo (E '\ 377');

Bây giờ, nếu bạn sao chép bảng ra, bạn không thể sao chép tệp kết quả trở lại. Điều đó có nghĩa là các bản sao lưu pg_dump của bạn sẽ không thể khôi phục. Cách duy nhất để lấy lại dữ liệu của bạn là thoát lại giá trị đó.

Có một bài viết hay trên blog tuyệt vời này về các vấn đề chung và một số cách để giải quyết chúng


1

Có khả năng với mã hóa mặc định được sử dụng trong môi trường Unix / Linux của bạn. Để kiểm tra mã hóa nào hiện tại là mã mặc định, hãy thực hiện như sau:

$ echo $LANG
en_US

Trong trường hợp này, chúng ta có thể thấy rõ nó không phải là mã hóa UTF-8, là mã mà lệnh sao chép dựa vào.

Vì vậy, để khắc phục điều này, chúng ta chỉ cần đặt biến LANG trong ví dụ sau:

$ export LANG=en_US.UTF-8

Lưu ý: Điều này sẽ chỉ có sẵn cho phiên hiện tại. Thêm nó vào ~ / .bashrc hoặc tương tự để có sẵn khi khởi động bất kỳ phiên shell nào trong tương lai.

Tài liệu tham khảo


1

Tôi không khuyên bạn nên chạy iconv một cách mù quáng trên bãi chứa văn bản đơn giản vì nó có thể chuyển đổi các ký tự hợp lệ (ví dụ: ký tự Trung Quốc) sang một số ký tự khác. Tốt hơn là tìm ký tự UTF8 không hợp lệ bằng cách chạy bên dưới lệnh.

grep -naxv '.*' plain_text_dump.sql

và sau đó chạy iconv trên dữ liệu cụ thể. Kiểm tra tài liệu này để giải thích chi tiết từng bước .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.