it-swarm.asia

كيفية حل أخطاء نسخ تسلسل بايت UTF8 غير صالحة عند الاستعادة ، عندما يتم ترميز قاعدة البيانات المصدر في UTF8؟

تم تكليفي بمهمة ترحيل قاعدة بيانات 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;

أنا أقوم بإنشاء قاعدة البيانات هذه تمامًا على هذا الخادم الوجهة. ولكن عندما أستعيد قاعدة البيانات من ملف النسخ الاحتياطي باستخدام خيار الاستعادة ، يعطيني بعض هذه الأخطاء:

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 حتى لا أواجه أي مشاكل عند تنفيذ الاستعادة؟

شكرا مقدما.

17
pedrosanta

أثناء البحث في الإنترنت ، رأيت أن هذه مشكلة شائعة جدًا. الحل الشائع هو استخدام تفريغ تنسيق النص العادي وإطعامه من خلال iconv لتصحيح الترميز.

هنا هو مزيد من المعلومات حول ذلك.

8
Richard

"لا أعرف كيف وصلوا إلى هناك في المقام الأول"

يمكن أن يحدث كما هو موضح هنا - على الرغم من أن هذا يولد خطأ في 8.4:

إذا قمت بإنشاء جدول بأي نوع نص (أي نص ، varchar (10) ، وما إلى ذلك) ، فيمكنك إدراج تسلسل بايت غير صالح في هذا الحقل باستخدام هروب ثماني.

على سبيل المثال ، إذا كانت لديك قاعدة بيانات مشفرة باستخدام UTF8 ، يمكنك القيام بما يلي:

=> إنشاء جدول foo (t TEXT) ؛

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

الآن ، إذا نسخت الجدول ، فلا يمكنك نسخ الملف الناتج مرة أخرى. وهذا يعني أن النسخ الاحتياطية pg_dump لن تتمكن من الاستعادة. الطريقة الوحيدة لاستعادة بياناتك هي إعادة الهروب من هذه القيمة.

هناك منشور جيد على هذا مدونة ممتازة حول القضايا العامة وبعض الطرق للتعامل معها

7
Jack says try topanswers.xyz

لا أوصي بتشغيل iconv بشكل أعمى على تفريغ النص العادي لأنه قد يحول الأحرف الصالحة (مثل الأحرف الصينية) إلى بعض الأحرف الأخرى. من الأفضل العثور على حرف UTF8 غير صالح عن طريق تشغيل الأمر أدناه.

grep -naxv '.*' plain_text_dump.sql

ثم قم بتشغيل iconv على بيانات معينة. تحقق هذا المستند للحصول على شرح مفصل خطوة بخطوة .

1
Nijil

من المحتمل أن يكون مع الترميز الافتراضي المستخدم في بيئة Unix/Linux الخاصة بك. للتحقق من الترميز الافتراضي الحالي ، نفّذ ما يلي:

$ echo $LANG
en_US

في هذه الحالة ، يمكننا أن نرى بوضوح أنه ليس ترميز UTF-8 ، الذي يعتمد عليه أمر النسخ.

لإصلاح ذلك ، قمنا فقط بتعيين متغير LANG على سبيل المثال لما يلي:

$ export LANG=en_US.UTF-8

ملاحظة: لن يكون هذا متاحًا إلا للدورة الحالية. أضفه إلى ~/.bashrc أو ما شابه لإتاحته عند بدء تشغيل أي جلسة Shell مستقبلية.

المرجع

1
arulraj.net

لقد أشرت إلى الرابط التالي الذي أعطاني أدلة لتحديد ترميز المصدر ثم تحويله إلى ترميز 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
0
Biswajit Barman