Faut-il utiliser Latin-1 sur UTF-8 pour la configuration de la base de données?

65

Nous utilisons MySQL dans l'entreprise pour laquelle je travaille et nous construisons des applications internes et internes avec Ruby on Rails.

Quand j'ai commencé à travailler ici, j'ai rencontré un problème que je n'avais jamais rencontré auparavant. la base de données sur le serveur de production est définie sur Latin-1, ce qui signifie que la gem MySQL lève une exception chaque fois que l'utilisateur entre et copie / colle les caractères UTF-8.

Mon patron appelle ces "mauvais caractères", car la plupart d'entre eux sont des caractères non imprimables, et dit qu'il faut les éliminer. J'ai trouvé plusieurs façons de faire cela, mais nous avons fini par nous retrouver dans une situation où un personnage UTF-8 était nécessaire. De plus, c'est un peu fastidieux, d'autant plus qu'il semble que la seule solution à propos de ce problème que j'ai jamais lue est de simplement définir la base de données sur UTF-8 (ce qui me semble logique).

Le seul argument que j'ai entendu pour rester avec Latin-1 est que permettre des caractères UTF-8 non imprimables peut gâcher les recherches texte / texte intégral dans MySQL. Est-ce vraiment vrai?

Y a-t-il d'autres raisons pour lesquelles on devrait utiliser Latin-1 par rapport à UTF-8? Si j'ai bien compris, il est supérieur et devient de plus en plus omniprésent.

Ravenstine
la source
4
@jon LATIN-1 n'est pas spécifique à l'anglais. L'espagnol y est parfaitement contenu, ainsi que le français si je ne me trompe pas.
Darkhogg
4
@Darkhog: Latin1 n'est certes pas spécifique à l'anglais, mais il est essentiellement limité aux alphabets d'Europe occidentale.
Bart van Ingen Schenau le
16
Le sabotage est le seul avantage possible de l'utilisation de Latin 1 plutôt que UTF-8 dans un système moderne. Bien sûr, cela n’est un avantage que pour le saboteur et ses fidèles, et non pour les propriétaires ou les développeurs du système.
Jon Hanna
13
Dommage que votre base de données ne puisse contenir le symbole de l’euro, ni même mon nom (ותן).
dotancohen
20
l'utilisateur "copie et colle" des caractères non-latin-1? ne traitez pas unicode comme une chose frivole non pertinente qui ne concerne que les nerds espiègles. nous sommes nombreux à taper des caractères qui ne rentrent pas dans le latin-1 de façon régulière - j'entends beaucoup de gens parler des langues non européennes, même ♥
Eevee

Réponses:

130

Unicode est certainement difficile, et le codage UTF-8 a quelques propriétés gênantes. Cependant, UTF-8 est devenu le codage standard de facto sur le Web, surpassant les normes ASCII, Latin-1, UCS-2 et UTF-16. Utilisez simplement le format UTF-8 partout .

La raison la plus importante pour laquelle vous devriez prendre en charge Unicode est que vous ne devez pas faire de suppositions inutiles concernant les entrées de l'utilisateur. Je n'ai aucune idée de ce qu'est votre domaine, mais des choses comme les noms d'utilisateur hébreux, un article de blog sur la Chine, un commentaire avec Emoji, ou simplement un texte bien stylé - comme «ceci» - devraient être possibles… Oh, ce sont des guillemets typographiquement corrects ( “”plutôt que ""), des tirets étendus et des points de suspension, qui sont des caractères communs dans le texte anglais, mais non pris en charge par ASCII ou Latin-1. Donc, ne pas prendre en charge d’autres scripts n’est pas simplement un fardeau pour d’autres cultures, mais rester fidèle à Latin-1 ne vous permet même pas d’écrire un anglais correct.

La notion selon laquelle Unicode n'autorise que les «mauvais caractères» est fausse. Oui, le texte est vraiment compliqué et Unicode ne vous le cachera pas. Votre patron pense peut-être aux caractères composés, où un point de code de base, tel que amodifié par des points de code ultérieurs, représentant par exemple des signes diacritiques pour former un seul caractère visuel tel que á. Cela ne vous gêne pas vraiment lorsque vous essayez de faire des recherches si vous effectuez une sorte de normalisation. Par exemple, vous pouvez stocker tout le texte sous la forme NFC qui réduit ces compositions dans leur forme précomposée, le cas échéant. Lorsque vous effectuez une recherche, vous pouvez également supprimer tous les caractères du texte, mais cela risque de modifier considérablement leur signification dans certaines langues.

Unicode ajoute également beaucoup de caractères non imprimables - mais même ASCII en a des tonnes. Voulez-vous gérer un NUL au milieu d'une chaîne? Que diriez-vous de 0x1C, un "séparateur de fichiers"? Je n'ai jamais vu la moitié de ceux-ci . Latin-1 ajoute un trait d'union doux qui indique les opportunités de saut de mot, mais est autrement invisible. Cela rompt-il également votre recherche en texte intégral? En d'autres termes, même ASCII et Latin-1 vous permettent de casser complètement votre saisie si vous supposez qu'il ne s'agit que de texte imprimable!

Amon
la source
8
Du point de vue de la base de données, certains de ces caractères ne sont pas / ne devraient pas être autorisés dans un champ de type texte (text / varchar / char / etc.). MySQL ne permet des caractères nuls dans ces types de données, mais d' autres bases de données comme PostgreSQL ne le font pas. Vous êtes censé utiliser BLOB (MySQL) ou BYTEA (PostgreSQL) si vous voulez pouvoir stocker de tels caractères.
Cimmanon
15
"s'en tenir à Latin-1 ne vous permet même pas d'écrire un anglais correct" C'est une bonne chose, sinon unicode résisterait encore plus fort. ;-)
Déduplicateur
3
@ PaŭloEbermann Les caractères NUL incorporés signifient que vos données sont un blob binaire, pas seulement une chaîne. NULs était un exemple étrange, car je pense qu'UTF-8 évite d'utiliser un \0octet dans le cadre d'un codage sur plusieurs octets, afin de s'assurer que le code non compatible UTF8 ne s'arrête pas au milieu d'une chaîne.
Peter Cordes
7
Tous les caractères unicode sont imprimables - vous avez juste besoin de la police correcte :-)
James Anderson
4
@ JamesAnderson, la police serait alors fausse et cassée. en.wikipedia.org/wiki/Unicode_control_characters
djechlin le
62

Je pense qu'au-delà de la question technique, votre patron n'a peut-être pas le temps de se tenir au courant des normes en vigueur.

Étant donné que sa position n’est pas tout à fait au goût du jour, mais qu’elle est dépassée, respectez sa position lorsqu’il discute de cette question (et vous devez vous rappeler de discuter , et non d’argumenter), et essayez de résoudre ses préoccupations concernant UTF-8. Je soupçonne que le problème sous-jacent n'est pas un problème technique et peut nécessiter un certain niveau de négociation de compétences non techniques.

Nelson
la source
6
Je ne pouvais pas approuver plus. En fait, je regrette que dans ma propre réponse, j'ai complètement négligé le "côté humain", qui dans ce numéro pourrait bien être primordial. J'aimerai pouvoir voter plus d'une fois :-)
LSerni, le
2
appeler tout ce qui est en dehors de latin-1 bad characteret y penser, non-printablec’est just out-datedpour vous?
njzk2
2
Le vrai problème est: "Est-ce un problème technique?" Je ne crois pas que le patron de l'OP soit allé à l'école et qu'il l'ait appris, ou qu'il ait lu un manuel / journal technique et soit parvenu à cette conclusion. Je n'ai pas l'impression que la solution est strictement technique. Ironiquement, le commentaire montre exactement le coeur du problème; S'attaquer à ce problème peut être extrêmement choquant s'il est mal fait.
Nelson
49

Lequel d'entre nous a raison?

Il était une fois votre patron. Mais avec le temps, les choses changent. De nos jours, vous l'êtes (mais avant de courir vers votre patron, assurez-vous de lire la réponse de Nelson également ).

Les anciennes versions de MySQL, et les anciennes versions de presque tout , traitaient beaucoup mieux de l’ancien Latin1 / ISO-8859-1 (5) que de l’UDT8.

Il y a une raison pour laquelle UTF8 a été créé, développé et poussé presque partout: s'il est correctement implémenté, cela fonctionne beaucoup mieux . Certains problèmes de performances et de stockage découlent du fait qu'un caractère Latin1 fait 8 bits, tandis qu'un caractère UTF8 peut comporter de 8 à 32 bits. Donc, lors de la planification, VARCHARvous devez en tenir compte. Et vos routines de recherche seront un peu plus lentes. Ils seront capables de faire plus de choses (par exemple, des recherches avec ou sans sensibilité accentuée . Ne ​​peuvent pas faire celles de Latin1 sans travail considérable), mais cela prendra un peu plus de temps.

Par contre, le stockage est bon marché , les frais généraux réalistes sur la taille des fichiers sont inférieurs à 2 à 3%, la puissance de calcul est également bon marché et devient moins chère, conformément à la loi de Moore; alors que votre temps et les attentes de vos clients ne le sont certainement pas .

Vous pourriez avoir à vous soucier des outils de recherche, etc. si vous étiez le seul à développer de tels outils. Mais vous ne l'êtes probablement pas. Vous utilisez ces outils; Même ceux qui n'étaient pas totalement conformes à la norme UTF8 hier (comme ce n'était pas le cas avec les précédents MySQL) le sont aujourd'hui ou le seront bientôt (par exemple, MySQL avec le support utf8mb4).

Ainsi, en planifiant avec soin et en mettant en œuvre correctement UTF8 ( sans le réappliquer après coup sur Latin1), vous pouvez obtenir un code très raisonnablement évolutif , qui, si vous envisagez de faire des affaires avec n’importe quel pays asiatique, est très bon. Chose. Et si vous n'avez pas de tels plans, d'autres personnes en auront, et ces personnes pourraient être vos clients, fournisseurs ou partenaires.

Ainsi, quand ils commenceront à vous envoyer des données UTF8, vous devrez configurer un truc compliqué pour effectuer la conversion aller-retour vers Latin1 et traiter les cas insolubles.

Si vous prenez en compte dans le budget le coût de plusieurs escarmouches contre les ninjas diaboliques mojibake , et considérez qu’elles ne vont pas disparaître - comme vous l’avez déjà découvert - vous réaliserez alors que passer au format UTF8 n’est pas seulement plus simple, il sera également plus simple. moins cher aussi.

LSerni
la source
4

Certaines situations dans lesquelles restreindre le jeu de caractères uniquement à ASCII peuvent avoir un sens peuvent concerner des champs à choix limité, tels que les champs de statut, car vous contrôlez strictement les valeurs pouvant être présentes, et les clés étrangères / références au système externe, car il existe rarement des raisons de le faire. qu’ils aient autre chose que des caractères alphanumériques et quelques symboles.

Pour tout autre texte, utilisez simplement UTF-8.

Lie Ryan
la source
2
MySQL n'a pas d'énums?
raptortech97
2
Et puisque l’ASCII est un sous-ensemble de UTF8, n’utilisez que UTF8.
RemcoGerlich
@RemcoGerlich: Je ne suis pas d'accord pour dire que vous pourriez utiliser UTF8 pour ces applications. À mon avis, les références externes ne sont pas du texte, mais une séquence d'octets opaque. Ils n'ont pas de jeu de caractères sauf pour la commodité de la notation. Si la séquence d'octets a une interprétation dans un certain jeu de caractères, il s'agit du domaine du système externe ou de l'application, et non du domaine de la base de données.
Lie Ryan
3
@LieRyan: Je vois ce point, mais alors cela ne devrait pas être non plus en ASCII, probablement un format de blob binaire ou autre.
RemcoGerlich
3

Pour commencer avec la réponse, peu importe la configuration de votre serveur . Le codage de caractères dans MySQL peut être configuré par colonne (moyen, même table pouvant contenir des caractères dans plusieurs codages, facile). Par exemple, mon serveur (et un certain nombre de bases de données existantes) est configuré par défaut pour cp1251 pour les anciens clients qui ne peuvent pas définir le classement correct lors de la connexion (différents clients matériels), mais les bases de données principales en production utilisent toutes UTF-8.

En parlant de "gaspillage d'espace", vous ne pouvez pas appeler de manière réaliste des données importantes, pas vrai? L'augmentation de l'espace de stockage sera toutefois différente en fonction de la langue dans laquelle vos données sont stockées. Augmentation insignifiante (moins de 1%) si votre site est principalement en anglais et jusqu'à 100%, s'il utilise des caractères ne relevant pas de la plage ASCII. . Et plus encore, si vous vous déplacez vers l’est. Les spécifications ultérieures UTF-8 (appelées UTF8mb4) autorisent jusqu'à 4 octets par point de code.

Et à qui a raison… La vérité, c’est une question sociale plus que technique. Il peut exister des raisons valables pour des configurations de serveur spécifiques, mais vous devez en connaître les implications. Mais si vous me demandez, il n'y a aucune raison de ne pas utiliser UTF-8. C'est le genre à gouverner tous les textes du monde.

AnrDaemon
la source
MySQL essaiera de convertir les données en encodage de base de données avant de les convertir en encodage de colonne. Si vous avez le client utf8, la base de données latin1 et la colonne utf8, les données texte peuvent être perdues.
Ivan Solntsev
Ivan, c'est une question totalement différente. L'interaction entre les jeux de caractères client, serveur de jeux de caractères, connexion de jeux de caractères et résultats de jeux de caractères est un long article de la documentation MySQL. Et dans le cas des paramètres de classement par colonne, "classement de base de données" est un classement de colonne et il est directement converti en résultat de jeu de caractères, en ignorant le classement de base de données.
AnrDaemon
0

Expliquez-lui simplement que UTF-8 est la valeur par défaut du trafic Web. Et tout utilisateur peut entrer n’importe quel caractère unicode valide dans son navigateur.

Il est simplement beaucoup plus facile d'avoir utf-8 / unicode du début à la fin, plutôt que de traiter des problèmes nombreux et variés qui résultent de utf-8-> latin-1-> utf-8.

James Anderson
la source