Czy Latin-1 powinien być używany na UTF-8, jeśli chodzi o konfigurację bazy danych?

65

Używamy MySQL w firmie, w której pracuję, i budujemy zarówno aplikacje klienckie, jak i wewnętrzne przy użyciu Ruby on Rails.

Kiedy zacząłem tu pracować, napotkałem problem, z którym nigdy wcześniej się nie spotkałem; baza danych na serwerze produkcyjnym jest ustawiona na Latin-1, co oznacza, że ​​klejnot MySQL zgłasza wyjątek za każdym razem, gdy użytkownik wprowadza dane, w których użytkownik kopiuje i wkleja znaki UTF-8.

Mój szef nazywa te „złe postacie”, ponieważ większość z nich to postacie, których nie można wydrukować, i mówi, że musimy je usunąć. Znalazłem kilka sposobów, aby to zrobić, ale ostatecznie znaleźliśmy się w sytuacji, w której potrzebna była postać UTF-8. Dodatkowo jest to trochę kłopotliwe, zwłaszcza, że ​​wydaje się, że jedynym rozwiązaniem, o jakim kiedykolwiek czytałem w tym temacie, jest ustawienie bazy danych na UTF-8 (ma to dla mnie sens).

Jedyny argument, który słyszałem za utrzymywaniem Latin-1, polega na tym, że zezwolenie na niedrukowalne znaki UTF-8 może zepsuć wyszukiwania tekstowe / pełnotekstowe w MySQL. Czy to naprawdę prawda?

Czy istnieją inne powody, dla których warto używać Latin-1 zamiast UTF-8? Rozumiem, że jest lepszy i staje się coraz bardziej wszechobecny.

Krukon
źródło
4
@jon LATIN-1 nie jest specyficzny dla języka angielskiego. Hiszpański jest tam doskonale zawarty, a także francuski, jeśli się nie mylę.
Darkhogg,
4
@Darkhog: Latin1 rzeczywiście nie jest specyficzny dla języka angielskiego, ale jest zasadniczo ograniczony do alfabetów zachodnioeuropejskich.
Bart van Ingen Schenau
16
Jedyną możliwą korzyścią z używania Latin 1 zamiast UTF-8 w nowoczesnym systemie jest sabotaż. Jest to oczywiście tylko korzyść dla sabotażysty i każdego, kto jest ich lojalny, a nie dla właścicieli lub twórców systemu.
Jon Hanna
13
Szkoda, że ​​twoja baza danych nie byłaby w stanie pomieścić symbolu Euro, a nawet mojego imienia (דותן).
dotancohen,
20
użytkownik „kopiuj i wkleja” znaki spoza alfabetu łacińskiego 1? nie traktuj jednorożca jako jakiejś nieistotnej frywolnej rzeczy, o którą dbają tylko psotni frajerzy. sporo z nas wpisać znaki, które nie zmieszczą się w Latin-1 w sposób regularny - Słyszę wiele osób zna języki pozaeuropejskie, nawet ♥
Eevee

Odpowiedzi:

131

Unicode jest z pewnością trudny, a kodowanie UTF-8 ma kilka niedogodnych właściwości. Jednak UTF-8 stał się de facto standardowym kodowaniem w Internecie, przewyższając ASCII, Latin-1, UCS-2 i UTF-16. Po prostu używaj UTF-8 wszędzie .

Najważniejszym powodem, dla którego powinieneś obsługiwać Unicode, jest to, że nie powinieneś przyjmować niepotrzebnych założeń dotyczących danych wejściowych użytkownika. Nie mam pojęcia, jaka jest twoja domena, ale takie rzeczy jak hebrajskie nazwy użytkownika, wpis na blogu o Chinach, komentarz do Emoji lub po prostu dobrze stylizowany tekst - na przykład „ten” - powinny być możliwe… Och, to były poprawne typograficznie znaki cudzysłowu ( “”zamiast ""), en-wide myślniki i wielokropek, które są znakami, które są wspólne w tekście angielskim, ale nie są obsługiwane przez ASCII lub Latin-1. Zatem nieobsługiwanie innych skryptów to nie tylko pieprzenie cię w innych kulturach, ale trzymanie się Latin-1 nawet nie pozwala ci pisać poprawnie po angielsku.

Pojęcie, że Unicode dopuszcza tylko „złe znaki”, jest błędne. Tak, tekst jest naprawdę skomplikowany, a Unicode nie ukryje go przed tobą. Twój szef może myśleć o skomponowanych postaciach, w których jeden podstawowy kodowy punkt, taki jak azmodyfikowany przez kolejne kodowe punkty, które np. Reprezentują znaki diakrytyczne, tworząc jeden znak wizualny, taki jak á. To tak naprawdę nie wchodzi w grę, gdy próbujesz wyszukiwać, jeśli wykonujesz jakąś normalizację. Na przykład, możesz zapisać cały tekst w formie NFC, która zwinie takie kompozycje do ich wstępnie złożonej formy, jeśli jest dostępna. Podczas wyszukiwania możesz również usunąć wszystkie znaki komponujące z tekstu, ale może to znacznie zmienić ich znaczenie w niektórych językach.

Unicode dodaje również wiele znaków niedrukowalnych - ale nawet ASCII ma ich mnóstwo. Czy obsłużysz NUL w środku łańcucha? Co powiesz na 0x1C, „separator plików”? Nigdy nie widziałem ich połowy . Latin-1 dodaje miękki łącznik, który wskazuje możliwości podziału słów, ale poza tym jest niewidoczny. Czy to również przerywa wyszukiwanie pełnotekstowe? Innymi słowy, nawet ASCII i Latin-1 pozwalają całkowicie przerwać wprowadzanie, jeśli założymy, że to tylko tekst do wydrukowania!

amon
źródło
8
Z perspektywy bazy danych niektóre z tych znaków nie są / nie powinny być dozwolone w polu typu tekstu (text / varchar / char / itp.). MySQL nie pozwalają znaki puste w tych typów danych, ale inne, takie jak bazy danych PostgreSQL nie. Powinieneś używać BLOB (MySQL) lub BYTEA (PostgreSQL), jeśli chcesz mieć możliwość przechowywania takich znaków.
cimmanon
15
„trzymanie się Latin-1 nie pozwala nawet pisać poprawnie po angielsku” To dobrze, bo inaczej unicode byłby odporny na jeszcze silniejsze. ;-)
Deduplicator
3
@ PaŭloEbermann Osadzone znaki NUL oznaczają, że dane są binarnymi blokami BLOB, a nie tylko ciągami znaków. NULs był dziwnym przykładem, ponieważ uważam, że UTF-8 unika kiedykolwiek używania \0bajtu jako części kodowania wielobajtowego, aby upewnić się, że kod nieświadomy UTF8 nie zatrzymuje się w środku łańcucha.
Peter Cordes
7
Wszystkie znaki Unicode można wydrukować - wystarczy poprawna czcionka :-)
James Anderson
4
@JamesAnderson czcionka byłaby wtedy niepoprawna i zepsuta. en.wikipedia.org/wiki/Unicode_control_characters
djechlin
62

Myślę, że poza kwestią techniczną twój szef może nie mieć czasu, aby być na bieżąco z aktualnymi standardami.

Ponieważ jego postawa nie jest całkowicie na lunch, po prostu przestarzała, szanuj jego pozycję podczas omawiania tej sprawy (i musisz pamiętać, aby dyskutować , a nie dyskutować) i starać się rozwiać obawy, jakie ma on w odniesieniu do UTF-8. Podejrzewam, że podstawowa kwestia nie jest kwestią techniczną i może wymagać pewnego poziomu negocjacji umiejętności miękkich.

Nelson
źródło
6
Nie mogłem zatwierdzić więcej. Właściwie żałuję, że w mojej własnej odpowiedzi całkowicie przeoczyłem „ludzką stronę”, która w tej kwestii może być najważniejsza. Chciałbym głosować więcej niż raz :-)
LSerni
2
dzwonienie do wszystkiego poza Latin-1 bad characteri myślenie, że non-printableto just out-dateddla ciebie?
njzk2
2
Prawdziwy problem brzmi: „Czy mamy do czynienia z problemem technicznym?” Nie wierzę, że szef OP poszedł do szkoły i został nauczony, czy też przeczytał jakiś podręcznik techniczny / czasopismo i doszedł do tego wniosku. Nie mam poczucia, że ​​to rozwiązanie jest ściśle techniczne. Jak na ironię komentarz pokazuje dokładnie sedno problemu; rozwiązanie tego problemu może być wyjątkowo obraźliwe, jeśli zostanie wykonane nieprawidłowo.
Nelson
49

Który z nas ma rację?

Pewnego razu twój szef był. Ale z biegiem czasu rzeczy się zmieniają. W dzisiejszych czasach jesteś (ale zanim pobiegniesz do swojego szefa, koniecznie przeczytaj również odpowiedź Nelsona ).

Stare wersje MySQL i stare wersje głównie wszystkiego radziły sobie znacznie lepiej ze starszymi Latin1 / ISO-8859-1 (5) niż UTF8.

Istnieje powód, dla którego UTF8 został stworzony, ewoluował i rozpowszechniany głównie wszędzie: jeśli odpowiednio wdrożony, działa znacznie lepiej . Istnieją pewne problemy z wydajnością i pamięcią wynikające z faktu, że znak Latin1 ma 8 bitów, podczas gdy znak UTF8 może mieć od 8 do 32 bitów. Więc przy planowaniu VARCHARmusisz wziąć to pod uwagę. A twoje procedury wyszukiwania będą odrobinę wolniejsze. Będą one w stanie zrobić więcej rzeczy (np wyszukiwań z czułością akcentującego lub bez . Nie można zrobić te w Latin1 bez szeroko zakrojonych prac), ale będzie się nieco więcej czasu.

Ale z drugiej strony, pamięć masowa jest tania , realistyczny narzut na rozmiary plików jest mniejszy niż 2-3%, moc obliczeniowa jest również tania i coraz tańsza zgodnie z prawem Moore'a; podczas gdy twój czas i oczekiwania klientów zdecydowanie nie są .

Być może będziesz musiał martwić się o narzędzia wyszukiwania itp., Jeśli to ty opracowałeś takie narzędzia. Ale prawdopodobnie nie jesteś. Państwo używać tych narzędzi; nawet te, które wczoraj nie były całkowicie zgodne z UTF8 (jak wcześniejszych MySQL-ów), są dzisiaj lub wkrótce będą (np. MySQL z obsługą utf8mb4).

Tak więc, starannie planując i wdrażając UTF8 we właściwy sposób ( nie rzucając go na Latin1 jako później), możesz mieć kod, który jest bardzo rozsądny na przyszłość , co, jeśli planujesz robić interesy z dowolnym krajem azjatyckim, jest bardzo dobrym Rzecz. A jeśli nie masz takich planów, inne osoby będą miały, a ci ludzie mogą być Twoimi klientami, dostawcami lub partnerami.

Więc kiedy zaczną wysyłać ci dane UTF8, będziesz musiał skonfigurować skomplikowany program do konwersji na i z Latin1 i radzenia sobie z nierozwiązywalnymi przypadkami.

Jeśli weźmiesz pod uwagę budżet, koszt kilku potyczek przeciwko złym ninja mojibake i rozważysz , że nie odejdą - jak już odkryłeś - wtedy zdasz sobie sprawę, że przejście na UTF8 jest nie tylko prostsze, ale będzie również tańsze .

LSerni
źródło
4

Niektóre sytuacje, w których ograniczenie zestawu znaków tylko do ASCII może mieć sens, dotyczą pól ograniczonego wyboru, np. Pól statusu, ponieważ ściśle kontrolujesz wartości, które mogą tam być, oraz klucz obcy / odniesienia do systemu zewnętrznego, ponieważ rzadko istnieją powody mają mieć tylko znaki alfanumeryczne i kilka symboli.

W przypadku innych tekstów wystarczy użyć UTF-8.

Lie Ryan
źródło
2
Czy MySQL nie ma wyliczeń?
raptortech97
2
A ponieważ ASCII jest podzbiorem UTF8, wystarczy użyć UTF8 nawet wtedy.
RemcoGerlich
@RemcoGerlich: Nie zgadzam się, że możesz do tego użyć UTF8. Moim zdaniem odwołania zewnętrzne nie są tekstem, ale nieprzejrzystą sekwencją bajtów. Nie mają zestawu znaków poza wygodą notacji. Jeśli sekwencja bajtów ma interpretację w pewnym zestawie znaków, jest to domena systemu zewnętrznego lub aplikacji, a nie baza danych.
Lie Ryan
3
@LieRyan: Rozumiem ten punkt, ale nie powinien to być ASCII, prawdopodobnie jakiś binarny format blob.
RemcoGerlich
3

Na początek odpowiedź nie ma znaczenia, jak skonfigurowany jest serwer . Kodowanie znaków w MySQL można skonfigurować dla każdej kolumny (oznacza to, że ta sama tabela może przechowywać znaki w wielu kodowaniach, łatwe). Tj. Mój serwer (i wiele starszych baz danych) jest domyślnie skonfigurowany dla cp1251 dla starych klientów, którzy nie mogą ustawić poprawnego sortowania po połączeniu (różni klienci sprzętowi), ale wszystkie główne produkcyjne bazy danych używają UTF-8.

Mówiąc o „zmarnowanej przestrzeni” - nie możesz realistycznie nazwać ważnych danych marnotrawstwem, prawda? Zwiększenie przestrzeni dyskowej będzie jednak różne w zależności od języka, w którym znajdują się Twoje dane. Od nieznacznego (mniej niż 1%) wzrostu, jeśli twoja strona jest głównie w języku angielskim i do 100%, jeśli jest dużo znaków przy użyciu znaków spoza zakresu ASCII . Co więcej, jeśli przeprowadzisz się na wschód. Późniejsze specyfikacje UTF-8 (tak zwane UTF8mb4) dopuszczają do 4 bajtów na punkt kodowy.

A dla „kto ma rację”… Prawda jest taka, że ​​jest to pytanie społeczne bardziej niż techniczne. Mogą istnieć uzasadnione powody określonych konfiguracji serwera, ale musisz znać implikacje. Ale jeśli mnie zapytasz, nie ma powodu, aby nie używać UTF-8. To jedyny rodzaj rządzenia wszystkimi tekstami na świecie.

AnrDaemon
źródło
MySQL spróbuje przekonwertować dane w kodowaniu bazy danych przed konwersją na kodowanie kolumnowe. Jeśli masz klienta utf8, bazę danych Latin1 i kolumnę utf8, dane tekstowe mogą zostać utracone.
Ivan Solntsev
Ivan, to zupełnie inne pytanie. Interakcja między klientem zestawu znaków, zestawem znaków serwera, połączeniem zestawu znaków, zestawem znaków jest długim artykułem w dokumentacji MySQL. W przypadku ustawień sortowania według kolumn „sortowanie bazy danych” to sortowanie kolumn i jest ono bezpośrednio konwertowane na wynik zestawu znaków, ignorując sortowanie bazy danych.
AnrDaemon
0

Wyjaśnij mu, że UTF-8 jest domyślnym ruchem sieciowym. I każdy użytkownik może wprowadzić dowolny prawidłowy znak Unicode w swojej przeglądarce.

O wiele łatwiej jest mieć utf-8 / unicode od przodu do końca, niż zajmować się wieloma i różnymi problemami wynikającymi z utf-8-> latin-1-> utf-8.

James Anderson
źródło