Por favor, explique cómo funciona Wordpress con el conjunto de caracteres MySQL y la clasificación en un nivel bajo

10

Como sugiere el título de la pregunta, estoy tratando de entender cómo funciona Wordpress con los juegos de caracteres MySQL y las opciones de clasificación. Como mostraré a continuación, las cosas no tienen mucho sentido para mí ...

Instalé Wordpress siguiendo las instrucciones en su página de instalación:

https://codex.wordpress.org/Installing_WordPress

Como parte de las instrucciones, seguí sus consejos para la creación manual de la base de datos MySQL en la línea de comandos, a saber, los comandos:

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

Además, según las instrucciones, edité el archivo "wp-config.php" para usar el juego de caracteres UTF-8:

define( 'DB_CHARSET', 'utf8' );

... y dejó la configuración de colación en blanco:

define( 'DB_COLLATE', '' );

Aquí es donde comienza la diversión ...

  1. Si ingreso un carácter que no es parte de MySQL UTF-8, pero es parte de UTF-8 MB4, como 𝌆, en una publicación, se muestra correctamente en la página representada. Hubiera esperado que esto no suceda, ya que no he configurado el juego de caracteres en UTF-8 MB4, pero el UTF-8 más restringido (como lo define MySQL, por supuesto, no como se entiende generalmente).

  2. Si investigo el problema en MySQL en la línea de comandos, se vuelve más extraño. Si corro show variables like 'char%';, obtengo esta respuesta:

    +--------------------------+----------------------------+
    | 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/ |
    +--------------------------+----------------------------+
    

Hubiera esperado que el conjunto de caracteres de la base de datos sea UTF-8, no latin1.

  1. Si ejecuto el comando show variables like 'collation%';, el resultado es:

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

Eso es aún más extraño, por razones obvias (no habría esperado la clasificación latin1_swedish_ci predeterminada en una base de datos UTF-8).

  1. Finalmente, si ejecuto show full columns from mywpdatabase.wp_posts;, las líneas de salida, donde el valor no es NULL, muestran que la intercalación es:

| post_content_filtered | longtext | utf8mb4_unicode_ci |

Mi pregunta entonces: ¿cómo se puede explicar esto? ¿Por qué mi instalación de Wordpress representa correctamente los caracteres UTF-8 MB4, cuando la base de datos se define como UTF-8 en la configuración? ¿Y por qué la base de datos se muestra en MySQL como latin1, colación sueca, en lugar de UTF-8? ¿Y cómo es que, a pesar de todo esto, los campos individuales en la tabla son utf8mb4_unicode_ci? Una explicación de bajo nivel de la forma en que Wordpress funciona con MySQL sería muy útil. ¡Gracias!

X-Mann
fuente

Respuestas:

11

Hay dos definiciones en wp-config.php del sitio web de WordPress:

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

Hay varias cosas que comúnmente se malinterpretan. Los nombres de las constantes en esas definiciones pueden sugerir que están relacionados con la base de datos en sí. No son. Están relacionados con tablas dentro de la base de datos.

La creación de la base de datos es totalmente independiente de la creación de la tabla. WordPress no crea una base de datos y no le importa el conjunto de caracteres y la clasificación predeterminados de la base de datos, siempre que pueda conectarse a la base de datos.

El valor 'utf8' en el primer medio de definición, el conjunto de caracteres menos restringido de la familia 'utf8', que es 'utf8' o 'utf8mb4'.

Si deja las definiciones anteriores sin cambios, antes de intentar instalar su sitio web, es como decirle a WordPress que tome sus propias decisiones, en relación con el conjunto de caracteres y la clasificación de las tablas de la base de datos, que son compatibles con MySQL (dependiendo de la versión de MySQL) y son menos limitantes.

Las siguientes son las cosas que WordPress analiza para determinar sus opciones, durante la instalación:

  • Versión de MySQL
  • cotejo de la base de datos (en wp-config.php)

Basado en la versión de MySQL, WordPress decide qué grupo de la familia utf8 usar. Hay dos, distinguidos por sus nombres: utf8 y utf8mb4 . Los juegos de caracteres del grupo utf8 permiten el almacenamiento de un máximo de 3 bytes de caracteres largos. Los juegos de caracteres del grupo utf8mb4 permiten almacenar caracteres de un máximo de 4 bytes de longitud.

Ahora, WordPress verifica el valor de DB_COLLATE define. Si está vacío, usará la colación menos limitante de la familia utf8 elegida ; de lo contrario, usará el valor especificado.

Ejemplos

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

Si MySQL no admite utf8mb4 (versiones anteriores), el conjunto de caracteres de las tablas será utf8 y la clasificación será utf8_general_ci . De lo contrario, podemos esperar utf8mb4 y utf8mb4_unicode_520_ci , o utf8mb4_unicode_ci (depende de la versión de MySQL), respectivamente.

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

Versión anterior de MySQL: utf8 y utf8_polish_ci . Versión MySQL más nueva: utf8mb4 y utf8mb4_polish_ci (se respeta el sufijo _polish_ci )

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

Cualquier versión de MySQL: cp1250 y cp1250_polish_ci .

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

Cualquier versión de MySQL: error (falta de coincidencia del conjunto de caracteres y la clasificación)

Resumen

En la mayoría de los casos, dejar los valores de define, explicados anteriormente, sin cambios, es una buena opción. Pero, si desea que la clasificación de tablas coincida con el idioma de su sitio web, puede modificar el valor de DB_COLLATE define, apropiadamente (por ejemplo, utf8mb4_polish_ci ).

Nota: eso explica por qué el carácter 𝌆 se almacenó y recuperó correctamente. Simplemente, su conjunto de caracteres de tablas pertenecía al grupo utf8mb4 , no utf8 .

Frank P. Walentynowicz
fuente
1
Gracias por explicar cómo Wordpress establece la intercalación, pero no ha abordado el resto de los puntos. ¿Por qué, si se define el juego de caracteres UTF-8, MySQL muestra la base de datos como latin1? ¿Y por qué muestra la clasificación de la base de datos como sueca? Además, parece ser confuso conjunto de caracteres y cotejo. La clasificación solo define el orden, las reglas de comparación, no el conjunto de caracteres. Por lo tanto, no importa qué intercalación se use, si UTF-8 es el conjunto de caracteres, los caracteres que están fuera de él (como se define en el sentido más estricto de MySQL) no deberían procesarse.
X-Mann
Actualizaré mi respuesta, para explicar más claramente el proceso.
Frank P. Walentynowicz
1
¡Gracias por la actualización! He aceptado tu respuesta, todo está claro ahora. El problema es con MySQL y mi falta de experiencia en él: no sabía que las tablas pueden usar un conjunto de caracteres más amplio que la base de datos en sí. Esta nueva información me ha tranquilizado. No necesito cambiar el juego de caracteres predeterminado en MySQL, Wordpress se encarga de ello a nivel de tabla.
X-Mann
De nada. Me alegra que haya ayudado.
Frank P. Walentynowicz