Latin-1 dovrebbe essere usato su UTF-8 quando si tratta di configurazione del database?


65

Stiamo usando MySQL presso l'azienda per cui lavoro e realizziamo applicazioni interne e rivolte al cliente utilizzando Ruby on Rails.

Quando ho iniziato a lavorare qui, ho riscontrato un problema che non avevo mai riscontrato prima; il database sul server di produzione è impostato su Latin-1, il che significa che la gemma di MySQL genera un'eccezione ogni volta che c'è un input dell'utente in cui l'utente copia e incolla i caratteri UTF-8.

Il mio capo chiama questi "personaggi cattivi" poiché la maggior parte di essi sono personaggi non stampabili e afferma che dobbiamo eliminarli. Ho trovato alcuni modi per farlo, ma alla fine siamo finiti in una circostanza in cui era necessario un personaggio UTF-8. Inoltre è un po 'una seccatura, soprattutto perché sembra che l'unica soluzione di cui abbia mai letto per questo problema sia semplicemente impostare il database su UTF-8 (ha senso per me).

L'unico argomento che ho sentito per essere rimasto fedele a Latin-1 è che consentire caratteri UTF-8 non stampabili può confondere le ricerche di testo / testo completo in MySQL. È davvero vero?

Ci sono altri motivi per cui si dovrebbe usare Latin-1 su UTF-8? Comprendo che è superiore e diventa sempre più onnipresente.


4
@jon LATIN-1 non è specifico per l'inglese. Lo spagnolo è contenuto perfettamente lì, così come il francese se non sbaglio.
Darkhogg,

4
@Darkhog: Latin1 non è in effetti specifico per l'inglese, ma è essenzialmente limitato agli alfabeti dell'Europa occidentale.
Bart van Ingen Schenau,

16
L'unico vantaggio possibile derivante dall'uso di Latin 1 anziché UTF-8 in un sistema moderno è il sabotaggio. Questo ovviamente è solo un vantaggio per il sabotatore, e per chiunque sia fedele, non per i proprietari o gli sviluppatori del sistema.
Jon Hanna,

13
Peccato che il tuo database non sia in grado di contenere il simbolo dell'euro o il mio nome (דותן).
dotancohen,

20
caratteri "latin-1" utente "copia e incolla"? non considerare l'unicode come qualcosa di irrilevante e frivolo a cui solo i nerd dispettosi si preoccupano. molti di noi scrivono personaggi che non si adattano regolarmente al latino-1 - sento molte persone che parlano lingue non europee, anche ♥
Eevee,

Risposte:


130

Unicode è certamente difficile e la codifica UTF-8 ha un paio di proprietà scomode. Tuttavia, UTF-8 è diventata la codifica standard di fatto sul web, superando ASCII, Latin-1, UCS-2 e UTF-16. Basta usare UTF-8 in tutto il mondo .

Il motivo più importante per cui dovresti supportare Unicode è che non dovresti fare ipotesi non necessarie sull'input dell'utente. Non ho idea di quale sia il tuo dominio, ma cose come nomi utente ebraici, un post sul blog sulla Cina, un commento con Emoji o un testo semplicemente ben disegnato - come "questo" - dovrebbero essere possibili ... Oh, quelle erano virgolette tipograficamente corrette ( “”anziché ""), trattini a livello e puntini di sospensione, che sono caratteri comuni nel testo inglese, ma non supportati da ASCII o Latin-1. Quindi non supportare altri script non è solo un grosso problema per altre culture, ma attenersi al latino-1 non ti consente nemmeno di scrivere un inglese corretto.

L'idea che Unicode consenta solo "caratteri cattivi" è sbagliata. Sì, il testo è davvero complicato e Unicode non te lo nasconderà. Il tuo capo potrebbe pensare a personaggi composti, in cui un punto di codice base come aè modificato da punti di codice successivi che, ad esempio, rappresentano segni diacritici per formare un carattere visivo come á. Questo non ti ostacola quando provi a fare ricerche se fai qualche tipo di normalizzazione. Ad esempio, è possibile memorizzare tutto il testo nel modulo NFC che comprime tali composizioni nella loro forma precomposta, se disponibile. Durante la ricerca, puoi anche rimuovere dal testo tutti i caratteri che compongono, ma ciò potrebbe cambiare sostanzialmente il loro significato in alcune lingue.

Unicode aggiunge anche molti caratteri non stampabili, ma anche ASCII ne ha molti. Gestirai un NUL nel mezzo di una stringa? Che ne dici di 0x1C, un "File Separator"? Non ho mai visto la metà di quelli . Latin-1 aggiunge un trattino morbido che indica opportunità di interruzione di parole, ma è altrimenti invisibile. Ciò interrompe anche la tua ricerca full-text? In altre parole, anche ASCII e Latin-1 ti consentono di interrompere completamente l'input se pensi che sia tutto solo testo stampabile!


8
Dal punto di vista del database, alcuni di questi caratteri non sono / non dovrebbero essere consentiti in un campo del tipo di testo (testo / varchar / char / ecc.). MySQL non consente caratteri nulli in questi tipi di dati, ma anche altri database come PostgreSQL non lo fanno. Dovresti usare BLOB (MySQL) o BYTEA (PostgreSQL) se vuoi essere in grado di memorizzare tali personaggi.
cimmanon,

15
"attenersi al latino-1 non ti permette nemmeno di scrivere un inglese corretto" Questa è una buona cosa, altrimenti l'unicode sarebbe resistito ancora più forte. ;-)
Deduplicatore

3
@ PaŭloEbermann I caratteri NUL incorporati indicano che i tuoi dati sono un BLOB binario, non solo una stringa. NULs è stato uno strano esempio, poiché credo che UTF-8 eviti di usare mai un \0byte come parte di una codifica multi-byte, per assicurarsi che il codice non compatibile con UTF8 non si fermi nel mezzo di una stringa.
Peter Cordes,

7
Tutti i caratteri Unicode sono stampabili - hai solo bisogno del carattere corretto :-)
James Anderson

4
@JamesAnderson il carattere sarebbe quindi sbagliato e rotto. en.wikipedia.org/wiki/Unicode_control_characters
djechlin

62

Penso che al di là della domanda tecnica, il tuo capo potrebbe non avere il tempo di tenersi aggiornato sugli standard attuali.

Dal momento che la sua posizione non è completamente fuori a pranzo, appena superata, rispetta la sua posizione quando discute di questo argomento (e devi ricordarti di discutere , non di discutere) e provare a elaborare le preoccupazioni che ha riguardo all'UTF-8. Sospetto che il problema di fondo non sia un problema tecnico e potrebbe richiedere un certo livello di negoziazione delle competenze trasversali.


6
Non potrei approvare di più. In realtà mi dispiace che nella mia risposta abbia completamente ignorato il "lato umano", che in questo numero potrebbe essere fondamentale. Vorrei poter votare più di una volta :-)
LSerni

2
chiamando tutto al di fuori del latin-1 bad charactere di pensare questi sono non-printableè just out-datedper te?
njzk2,

2
Il vero problema è: "È un problema tecnico di cui ci stiamo occupando?" Non credo che il capo dell'OP sia andato a scuola e gli sia stato insegnato questo, o abbia letto un manuale tecnico / giornale e sia giunto a questa conclusione. Non ho la sensazione che la soluzione sia strettamente una soluzione tecnica. Ironia della sorte, il commento mostra esattamente il cuore del problema; affrontare questo problema può essere estremamente offensivo se fatto in modo improprio.
Nelson,

49

Chi di noi ha ragione?

C'era una volta il tuo capo. Ma col passare del tempo, le cose cambiano. Oggi lo sei (ma prima di correre dal tuo capo, assicurati di leggere anche la risposta di Nelson ).

Le vecchie versioni di MySQL e le vecchie versioni di quasi tutto , gestivano molto meglio il vecchio Latin1 / ISO-8859-1 (5) rispetto a UTF8.

C'è un motivo per cui UTF8 è stato creato, evoluto e spinto principalmente ovunque: se correttamente implementato, funziona molto meglio . Esistono alcuni problemi di prestazioni e archiviazione derivanti dal fatto che un carattere Latin1 è 8 bit, mentre un carattere UTF8 può essere lungo da 8 a 32 bit. Quindi, quando pianifichi, VARCHARdevi tenerne conto. E le tue routine di ricerca saranno un po 'più lente. Essi saranno in grado di fare più cose (ad esempio ricerche con sensibilità accento o senza . Non può fare quelle in Latin1 senza vasto lavoro), ma sarà prendere un po 'più di tempo.

D'altra parte, l'archiviazione è economica , l' overhead realistico sulle dimensioni dei file è inferiore al 2-3%, anche la potenza di elaborazione è economica e diventa più economica in accordo con la Legge di Moore; mentre il tuo tempo e le aspettative dei tuoi clienti sicuramente non lo sono .

Potresti doverti preoccupare degli strumenti di ricerca, ecc. Se fossi tu a sviluppare tali strumenti. Ma probabilmente non lo sei. Si utilizzano questi strumenti; anche quelli che ieri non erano completamente conformi a UTF8 (come non lo erano i precedenti MySQL), lo sono oggi, o lo saranno presto (ad es. MySQL con supporto utf8mb4).

Quindi, pianificando e implementando attentamente UTF8 nel modo giusto ( non schiacciandolo su Latin1 come ripensamento) puoi avere un codice che è ragionevolmente a prova di futuro , che, se hai intenzione di fare affari con qualsiasi paese asiatico, è un ottimo Cosa. E se non hai tali piani, lo faranno altre persone e quelle persone potrebbero essere i tuoi clienti, fornitori o partner.

Quindi, quando iniziano a inviarti i dati UTF8, dovrai impostare una cosa complicata da convertire in avanti e indietro in Latin1 e gestire casi irrisolvibili.

Quando si tiene conto del budget del costo di diverse schermaglie contro i malvagi ninja mojibake e si considera che non andranno via - come hai già scoperto - allora ti renderai conto che andare UTF8 non è solo più semplice, sarà anche più economico .


4

Alcune situazioni in cui limitare il set di caratteri solo a ASCII può avere senso è per campi a scelta limitata, ad esempio campi di stato, perché si controllano rigorosamente i valori che possono essere presenti e la chiave esterna / i riferimenti al sistema esterno, perché raramente ci sono motivi per loro di avere tutt'altro che caratteri alfanumerici e alcuni simboli.

Per qualsiasi altro testo, basta usare UTF-8.


2
MySQL non ha enumerazioni?
raptortech97,

2
E poiché ASCII è un sottoinsieme di UTF8, usa UTF8 anche allora.
RemcoGerlich,

@RemcoGerlich: non sono d'accordo sul fatto che potresti usare UTF8 per quelli. A mio avviso, i riferimenti esterni non sono testo ma sequenza opaca di byte. Non hanno set di caratteri se non per comodità notazionale. Se la sequenza di byte ha un'interpretazione in un determinato set di caratteri, vale a dire il dominio del sistema esterno o dell'applicazione, non quello del database.
Sdraiati Ryan il

3
@LieRyan: vedo quel punto, ma poi non dovrebbe essere nemmeno ASCII, probabilmente un formato BLOB binario o giù di lì.
RemcoGerlich,

3

Per iniziare con la risposta, non importa come è configurato il tuo server . La codifica dei caratteri in MySQL potrebbe essere configurata per colonna (significa che la stessa tabella potrebbe contenere caratteri in più codifiche, facile). Vale a dire il mio server (e un certo numero di database legacy in esso) è configurato per cp1251 per impostazione predefinita per i vecchi client che non sono in grado di impostare le regole di confronto corrette al momento della connessione (client hardware diversi), ma i database principali in produzione utilizzano tutti UTF-8.

Parlando di "spazio sprecato" - non puoi realisticamente chiamare uno spreco di dati importanti, vero? L'aumento dello spazio di archiviazione, tuttavia, sarà diverso a seconda della lingua in cui si trovano i tuoi dati. Dall'aumento insignificante (meno dell'1%) se il tuo sito è principalmente in inglese e fino al 100%, se è matto usando caratteri al di fuori dell'intervallo ASCII . E ancora di più, se ti sposti più a est. Le specifiche successive UTF-8 (il cosiddetto UTF8mb4) consentono fino a 4 byte per punto di codice.

E a "chi ha ragione" ... La verità è che questa è una domanda sociale più che tecnica. Potrebbero esserci validi motivi per specifiche configurazioni del server, ma è necessario conoscere le implicazioni. Ma se me lo chiedi, non c'è motivo di non usare UTF-8. È l'unico tipo a governare tutti i testi del mondo.


MySQL proverà a convertire i dati nella codifica del database prima di convertirli in codifica di colonna. Se si dispone di client utf8, database latin1 e columnt utf8, i dati di testo possono andare persi.
Ivan Solntsev,

Ivan, questa è una domanda completamente diversa. L'interazione tra client-set-caratteri, set-caratteri-server, connessione-set-caratteri, risultati-set-caratteri è un lungo articolo nella documentazione di MySQL. E nel caso delle impostazioni di confronto per colonna, "confronto tra database" è il confronto tra colonne e viene direttamente convertito in risultato del set di caratteri, ignorando le regole di confronto del database.
AnrDaemon,

0

Spiegagli semplicemente che UTF-8 è l'impostazione predefinita per il traffico web. E qualsiasi utente può inserire qualsiasi carattere Unicode valido nel proprio browser.

È molto più semplice avere utf-8 / unicode da front-end a back-end piuttosto che affrontare i molti e vari problemi che derivano da utf-8-> latino-1-> utf-8.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.