NULL yok, ancak “UTF8” kodlaması için geçersiz bayt dizisi: 0x00


12

Son 8 saatimi 'mysqldump --compatible = postgresql' çıktısını PostgreSQL 8.4.9'a aktarmaya çalışarak geçirdim ve burada ve başka bir yerde bu özel sorun hakkında zaten en az 20 farklı konu okudum, ancak gerçek kullanılabilir cevap çalışır.

MySQL 5.1.52 verisi dökümü:

mysqldump -u root -p --compatible=postgresql --no-create-info --no-create-db --default-character-set=utf8 --skip-lock-tables rt3 > foo

Hedef olarak PostgreSQL 8.4.9 sunucusu

Verileri 'psql -U rt_user -f foo' ile yüklemek bildiriyor (bunların çoğu, bir örnek):

psql:foo:29: ERROR:  invalid byte sequence for encoding "UTF8": 0x00
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".

Aşağıdakilere göre, girdi dosyasında NULL (0x00) karakter yok.

database-dumps:rcf-temp1# sed 's/\x0/ /g' < foo > nonulls
database-dumps:rcf-temp1# sum foo nonulls
04730 2545610 foo
04730 2545610 nonulls
database-dumps:rcf-temp1# rm nonulls

Benzer şekilde, Perl ile yapılan bir başka kontrolde NULL gösterilmez:

database-dumps:rcf-temp1# perl -ne '/\000/ and print;' foo
database-dumps:rcf-temp1#

Hata "HINT" olarak, 'client_encoding' 'UTF8' ayarlamak için mümkün olan her yolu denedim ve başarılı ama sorunumu çözmek için hiçbir etkisi yoktur.

database-dumps:rcf-temp1# psql -U rt_user --variable=client_encoding=utf-8 -c "SHOW client_encoding;" rt3
 client_encoding
-----------------
 UTF8
(1 row)

database-dumps:rcf-temp1#

Mükemmel, yine de:

database-dumps:rcf-temp1# psql -U rt_user -f foo --variable=client_encoding=utf-8 rt3
...
psql:foo:29: ERROR:  invalid byte sequence for encoding "UTF8": 0x00
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".
...

"Hoyle göre" doğru cevabı engellemek, duymak harika olurdu ve bu nadiren referans verilen veriler için ASCII olmayan karakterleri korumayı gerçekten umursamadığımı bilmek, ne önerileriniz var?

Güncelleme: İçe aktarım sırasında aynı döküm dosyasının yalnızca ASCII sürümüyle aynı hatayı alıyorum. Gerçekten akıl almaz:

database-dumps:rcf-temp1# # convert any non-ASCII character to a space
database-dumps:rcf-temp1# perl -i.bk -pe 's/[^[:ascii:]]/ /g;' mysql5-dump.sql
database-dumps:rcf-temp1# sum mysql5-dump.sql mysql5-dump.sql.bk
41053 2545611 mysql5-dump.sql
50145 2545611 mysql5-dump.sql.bk
database-dumps:rcf-temp1# cmp mysql5-dump.sql mysql5-dump.sql.bk
mysql5-dump.sql mysql5-dump.sql.bk differ: byte 1304850, line 30
database-dumps:rcf-temp1# # GOOD!
database-dumps:rcf-temp1# psql -U postgres -f mysql5-dump.sql --variable=client_encoding=utf-8 rt3
...
INSERT 0 416
psql:mysql5-dump.sql:30: ERROR:  invalid byte sequence for encoding "UTF8": 0x00
HINT:  This error can also happen if the byte sequence does not match the encod.
INSERT 0 455
INSERT 0 424
INSERT 0 483
INSERT 0 447
INSERT 0 503
psql:mysql5-dump.sql:36: ERROR:  invalid byte sequence for encoding "UTF8": 0x00
HINT:  This error can also happen if the byte sequence does not match the encod.
INSERT 0 502
INSERT 0 507
INSERT 0 318
INSERT 0 284
psql:mysql5-dump.sql:41: ERROR:  invalid byte sequence for encoding "UTF8": 0x00
HINT:  This error can also happen if the byte sequence does not match the encod.
INSERT 0 382
INSERT 0 419
INSERT 0 247
psql:mysql5-dump.sql:45: ERROR:  invalid byte sequence for encoding "UTF8": 0x00
HINT:  This error can also happen if the byte sequence does not match the encod.
INSERT 0 267
INSERT 0 348
^C

Söz konusu tablolardan biri şu şekilde tanımlanmıştır:

                                        Table "public.attachments"
     Column      |            Type             |                        Modifie
-----------------+-----------------------------+--------------------------------
 id              | integer                     | not null default nextval('atta)
 transactionid   | integer                     | not null
 parent          | integer                     | not null default 0
 messageid       | character varying(160)      |
 subject         | character varying(255)      |
 filename        | character varying(255)      |
 contenttype     | character varying(80)       |
 contentencoding | character varying(80)       |
 content         | text                        |
 headers         | text                        |
 creator         | integer                     | not null default 0
 created         | timestamp without time zone |
Indexes:
    "attachments_pkey" PRIMARY KEY, btree (id)
    "attachments1" btree (parent)
    "attachments2" btree (transactionid)
    "attachments3" btree (parent, transactionid)

DB şemasının herhangi bir parçası için türü değiştirme özgürlüğüm yok. Aksi takdirde, yazılımın gelecekteki yükseltmelerini bozabilir .

Muhtemel sorun sütunu, 'metin' türündeki 'içerik' dir (belki de diğer tablolardaki diğerleri). Önceki araştırmalardan bildiğim gibi, PostgreSQL 'metin' değerlerinde NULL değerine izin vermeyecektir. Bununla birlikte, lütfen hem sed hem de Perl'in NULL karakter göstermediği yerlere bakın ve daha sonra aşağıya tüm döküm dosyasından tüm ASCII olmayan karakterleri soyduğum ama yine de barfs.


2
Döküm dosyanızın 29. satırı neye benziyor? Bunun gibi bir şey head -29 foo | tail -1 | cat -vişe yarayabilir.
mu çok kısa

Etkilenen tablonun tanımı nedir ve rahatsız edici çizgi neye benziyor?
tscho

~ 1MB şirket verisi. Tabii ki nereye gittiğini anlıyorum. İşte bu düşünce çizgisinin sonu (lütfen gist
jblaine

tscho: Belirtildiği gibi, bu hata satırı bu hatalardan yüzlerce tanesidir.
jblaine

Yanıtlar:


3

Bu karakter / metin alanlarından biri veya daha fazlası içeriği için 0x00 olabilir.

Takip etmeyi dene:

SELECT * FROM rt3 where some_text_field = 0x00 LIMIT 1;

Bu herhangi bir satır döndürürse, bu karakter / metin alanlarını aşağıdakilerle güncellemeyi deneyin:

UPDATE rt3 SET some_text_field = '' WHERE some_text_field = 0x00;

Daha sonra başka bir MYSQLDUMP ... (ve PostgreSQL içe aktarma yöntemi) deneyin.


Bu, kullanmam gereken gerçi karakterleri bulmama yardımcı oldu colname LIKE concat('%', 0x00, '%'). Bunları serileştirilmiş PHP dizileri içeren alanlarda buldum.
cimmanon

5

MySQL 5.0.51 ve Postgres 9.3.4.0 sürümünü kullanırken de aynı sorunu yaşadım. Daniel Vérité'nin "postgresql kipindeki mysqldump'ın boş baytları dizelerde \ 0 olarak atacağını"

Tabii ki bir grep sonunda NULL karakterleri ortaya çıkardı.

grep \\\\0 dump.sql

NULL karakterleri aşağıdaki komutu kullanarak değiştirdim

sed -i BAK 's/\\0//g' dump.sql

Postgres daha sonra başarıyla dump.sql yükleyebildi


4

Bu hatayı dosyada NULL bayt veya ascii olmayan bir karakter olmadan alabilirsiniz. Bir utf8 veritabanındaki örnek:

select E'ab\0cd';

getirecek:

HATA: "UTF8" kodlaması için geçersiz bayt dizisi: 0x00 İPUCU: Bu hata, bayt dizisi "client_encoding" tarafından denetlenen sunucu tarafından beklenen kodlamayla eşleşmezse de oluşabilir.

postgresql modundaki mysqldump, boş baytları dizelerde \ 0 olarak atar, bu nedenle muhtemelen bu karakter dizisini aramak istersiniz.


0

Böyle bir sorunu yarı hatırlıyorum. Ben şeması geçirerek sonra csv olarak veri damping ve csv dosyasından veri yükleme sona erdi düşünüyorum. CSV dosyasını güncellemek zorunda kaldım (sed veya unixtodos gibi unix araçları kullanarak) veya içe aktarma adımında hata olan bazı öğeleri düzeltmek için açık ofis calc (excell) kullanarak - açmak ve yeniden kaydetmek kadar basit olabilir dosya.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.