web-dev-qa-db-fra.com

MySQL et le classement à un niveau.

Comme le titre de la question le suggère, je cherche à comprendre comment Wordpress fonctionne avec les jeux de caractères et les options de classement MySQL. Comme je vais le montrer ci-dessous, les choses n'ont pas beaucoup de sens pour moi ...

J'ai installé Wordpress en suivant les instructions sur leur page d'installation:

https://codex.wordpress.org/Installing_WordPress

Dans le cadre des instructions, j'ai suivi leurs conseils pour la création manuelle de la base de données MySQL sur la ligne de commande, à savoir les commandes:

mysql> CREATE DATABASE databasename;
Query OK, 1 row affected (0.00 sec)

mysql> GRANT ALL PRIVILEGES ON databasename.* TO "wordpressusername"@"hostname"
-> IDENTIFIED BY "password";
Query OK, 0 rows affected (0.00 sec)

mysql> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.01 sec)

mysql> EXIT

De plus, conformément aux instructions, j'ai modifié le fichier "wp-config.php" pour utiliser le jeu de caractères UTF-8:

define( 'DB_CHARSET', 'utf8' );

... et laissé le paramètre de classement vide:

define( 'DB_COLLATE', '' );

C'est ici que commence le plaisir ...

  1. Si j'entre un caractère qui ne fait pas partie de MySQL UTF-8, mais qui fait partie de UTF-8 MB4, tel que ????, dans un article, il apparaît correctement sur la page rendue. Je me serais attendu à ce que cela ne se produise pas, car je n'ai pas défini le jeu de caractères sur UTF-8 MB4, mais sur le plus restreint UTF-8 (tel que défini par MySQL bien sûr, pas tel que compris généralement).

  2. Si j'examine le problème dans MySQL sur la ligne de commande, cela devient plus étrange. Si je lance show variables like 'char%';, j'obtiens cette réponse:

    +--------------------------+----------------------------+
    | Variable_name            | Value                      |
    +--------------------------+----------------------------+
    | character_set_client     | utf8                       |
    | character_set_connection | utf8                       |
    | character_set_database   | latin1                     |
    | character_set_filesystem | binary                     |
    | character_set_results    | utf8                       |
    | character_set_server     | latin1                     |
    | character_set_system     | utf8                       |
    | character_sets_dir       | /usr/share/mysql/charsets/ |
    +--------------------------+----------------------------+
    

Je m'attendais à ce que le jeu de caractères de la base de données soit UTF-8, pas latin1.

  1. Si j'exécute la commande show variables like 'collation%';, le résultat est le suivant:

    +----------------------+-------------------+
    | Variable_name        | Value             |
    +----------------------+-------------------+
    | collation_connection | utf8_general_ci   |
    | collation_database   | latin1_swedish_ci |
    | collation_server     | latin1_swedish_ci |
    +----------------------+-------------------+
    

C'est encore plus étrange, pour des raisons évidentes (je ne m'attendais pas au classement par défaut latin1_swedish_ci dans une base de données UTF-8).

  1. Enfin, si j'exécute show full columns from mywpdatabase.wp_posts;, les lignes de sortie, où la valeur n'est pas NULL, indiquent que le classement est:

| post_content_filtered | longtext | utf8mb4_unicode_ci |

Ma question alors - comment cela peut-il être expliqué? Pourquoi mon installation Wordpress rend-elle correctement le rendu des caractères UTF-8 MB4, lorsque la base de données est définie comme UTF-8 dans la configuration? Et pourquoi la base de données présente-t-elle dans MySQL le latin1, classement suédois, au lieu de UTF-8? Et comment se fait-il que malgré tout cela, les champs individuels de la table sont utf8mb4_unicode_ci? Une explication de bas niveau de la façon dont Wordpress fonctionne avec MySQL serait très utile. Je vous remercie!

9
X-Mann

Wp-config.php définit deux sites Web:

define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');

Il y a plusieurs choses qui sont le plus souvent mal comprises. Les noms des constantes dans ces définitions pourraient suggérer qu’elles sont liées à la base de données elle-même. Ils ne sont pas. Ils sont liés aux tables de la base de données.

La création de base de données est totalement indépendante de la création de table. WordPress ne crée pas de base de données et ne se soucie pas du jeu de caractères et du classement par défaut de la base de données, dans la mesure où il peut se connecter à la base de données.

La valeur "utf8" dans la première définition signifie le jeu de caractères le moins restreint de la famille "utf8", qui est "utf8" ou "utf8mb4".

Si vous laissez les définitions ci-dessus inchangées, avant d'essayer d'installer votre site Web, cela revient à dire à WordPress de faire ses propres choix en ce qui concerne le jeu de caractères et le classement des tables de la base de données, qui sont pris en charge par MySQL (en fonction de la version de MySQL) et sont moins restrictifs.

Voici ce que WordPress analyse pour déterminer ses choix lors de l’installation:

  • La version de MySQL
  • classement de la base de données (dans wp-config.php)

Sur la base de la version de MySQL, WordPress décide quel groupe de utf8 famille utiliser. Il y en a deux, distingués par leurs noms: utf8 et utf8mb4 . Les jeux de caractères de utf8 group permettent de stocker un maximum de 3 octets de caractères. Les jeux de caractères de utf8mb4 group permettent de stocker un maximum de 4 octets de caractères.

Maintenant, WordPress vérifie la valeur de DB_COLLATE define. S'il est vide, il utilisera le classement le moins restrictif choisi utf8 family, sinon il utilisera la valeur spécifiée.

Exemples

define('DB_CHARSET', 'utf8');
define('DB_COLLATE', '');

Si MySQL ne supporte pas utf8mb4 (versions antérieures), le jeu de caractères des tables sera utf8 et le classement sera utf8_general_ci . Sinon, nous pouvons nous attendre à utf8mb4 et utf8mb4_unicode_520_ci ou utf8mb4_unicode_ci , respectivement (version dépendante de MySQL).

define('DB_CHARSET', 'utf8');
define('DB_COLLATE', 'utf8_polish_ci');

Ancienne version de MySQL - utf8 et utf8_polish_ci . Nouvelle version de MySQL - utf8mb4 et utf8mb4_polish_ci ( _polish_ci le suffixe est respecté)

define('DB_CHARSET', 'cp1250');
define('DB_COLLATE', 'cp1250_polish_ci');

Toute version de MySQL - cp1250 et cp1250_polish_ci .

define('DB_CHARSET', 'cp1250');
define('DB_COLLATE', 'utf8_general_ci');

Toute version de MySQL - erreur (non concordance entre le jeu de caractères et le classement)

Résumé

Dans la plupart des cas, laisser les valeurs de définit, expliquées ci-dessus, inchangées, est un bon choix. Toutefois, si vous souhaitez que le classement des tables corresponde à la langue de votre site Web, vous pouvez modifier la valeur de DB_COLLATE define de manière appropriée (par exemple - utf8mb4_polish_ci ).

Note: ça explique pourquoi le personnage ???? a été stocké et récupéré correctement. Simplement, votre jeu de caractères de tables appartenait à utf8mb4 groupe, pas utf8 .

10