Wyjaśnij, w jaki sposób Wordpress działa z zestawem znaków MySQL i zestawieniem znaków na niskim poziomie


10

Jak sugeruje tytuł pytania, chcę zrozumieć, jak Wordpress działa z zestawami znaków MySQL i opcjami sortowania. Jak pokażę poniżej, rzeczy nie mają dla mnie większego sensu ...

Zainstalowałem Wordpress, postępując zgodnie z instrukcjami na stronie instalacji:

https://codex.wordpress.org/Installing_WordPress

W ramach instrukcji podążyłem za ich radą ręcznego tworzenia bazy danych MySQL w wierszu poleceń, a mianowicie poleceń:

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

Ponadto, zgodnie z instrukcją, edytowałem plik „wp-config.php”, aby użyć zestawu znaków UTF-8:

define( 'DB_CHARSET', 'utf8' );

... i pozostawił ustawienie sortowania puste:

define( 'DB_COLLATE', '' );

Tutaj zaczyna się zabawa ...

  1. Jeśli wprowadzę znak, który nie jest częścią MySQL UTF-8, ale jest częścią UTF-8 MB4, taki jak 𝌆, w poście, wyświetla się poprawnie na renderowanej stronie. Spodziewałbym się, że tak się nie stanie, ponieważ nie ustawiłem zestawu znaków na UTF-8 MB4, ale bardziej ograniczonego UTF-8 (zgodnie z definicją MySQL, oczywiście nie tak ogólnie rozumianą).

  2. Jeśli zbadam ten problem w MySQL w wierszu poleceń, staje się dziwniejszy. Jeśli uruchomię show variables like 'char%';, otrzymam tę odpowiedź:

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

Spodziewałbym się, że zestaw znaków bazy danych to UTF-8, a nie latin1.

  1. Jeśli uruchomię polecenie show variables like 'collation%';, wynikiem będzie:

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

Jest to nawet dziwniejsze, z oczywistych powodów (nie spodziewałbym się domyślnego sortowania latin1_swedish_ci w bazie danych UTF-8).

  1. Wreszcie, jeśli uruchomię show full columns from mywpdatabase.wp_posts;, wiersze wyjściowe, w których wartość nie jest równa NULL, pokazują sortowanie jako:

| post_content_filtered | longtext | utf8mb4_unicode_ci |

Moje pytanie - w jaki sposób można to wyjaśnić? Dlaczego moja Wordpress poprawnie instaluje renderowanie znaków UTF-8 MB4, kiedy baza danych jest zdefiniowana jako UTF-8 w konfiguracji? I dlaczego baza danych jest wyświetlana w MySQL jako łaciński, szwedzki zestaw, zamiast UTF-8? Jak to możliwe, że pomimo tego wszystkie pola w tabeli to utf8mb4_unicode_ci? Bardzo pomocne byłoby wyjaśnienie niskiego poziomu, w jaki Wordpress współpracuje z MySQL. Dziękuję Ci!

Odpowiedzi:


11

Istnieją dwa definicje w wp-config.php witryny WordPress:

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

Jest kilka rzeczy, które najczęściej są źle rozumiane. Nazwy stałych w tych definicjach mogą sugerować, że są one powiązane z samą bazą danych. Oni nie są. Są one powiązane z tabelami w bazie danych.

Tworzenie baz danych jest całkowicie niezależne od tworzenia tabel. WordPress nie tworzy bazy danych i nie dba o domyślny zestaw znaków i sortowanie bazy danych, o ile może łączyć się z bazą danych.

Wartość „utf8” w pierwszym zdefiniowaniu oznacza najmniej ograniczony zestaw znaków z rodziny „utf8”, którym jest albo „utf8”, albo „utf8mb4”.

Jeśli pozostawisz powyższe definicje bez zmian, przed próbą zainstalowania strony internetowej, to tak, jakbyś powiedział WordPressowi, aby dokonał własnych wyborów dotyczących zestawu znaków i zestawiania tabel w bazie danych, które są obsługiwane przez MySQL (w zależności od wersji MySQL) i są najmniejsze.

Oto rzeczy, które analizuje WordPress w celu ustalenia swoich wyborów podczas instalacji:

  • Wersja MySQL
  • sortowanie bazy danych (w wp-config.php)

Na podstawie wersji MySQL WordPress decyduje, z której grupy rodziny utf8 korzystać. Są dwa, wyróżniające się nazwami: utf8 i utf8mb4 . Zestawy znaków z grupy utf8 umożliwiają przechowywanie maksymalnie 3-bajtowych znaków. Zestawy znaków z grupy utf8mb4 umożliwiają przechowywanie maksymalnie 4-bajtowych znaków.

Teraz WordPress sprawdza wartość definicji DB_COLLATE . Jeśli pusty, użyje najmniejszego sortowania z wybranej rodziny utf8 , w przeciwnym razie użyje określonej wartości.

Przykłady

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

Jeśli MySQL nie obsługuje utf8mb4 (starsze wersje), zestaw znaków tabel będzie utf8, a zestawienie będzie utf8_general_ci . W przeciwnym razie możemy spodziewać się odpowiednio utf8mb4 i utf8mb4_unicode_520_ci lub utf8mb4_unicode_ci (zależne od wersji MySQL).

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

Starsza wersja MySQL - utf8 i utf8_polish_ci . Nowsza wersja MySQL - utf8mb4 i utf8mb4_polish_ci ( sufiks _polish_ci jest honorowany)

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

Dowolna wersja MySQL - cp1250 i cp1250_polish_ci .

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

Dowolna wersja MySQL - błąd (niedopasowanie zestawu znaków i sortowania)

Podsumowanie

W większości przypadków pozostawienie wartości definicji, wyjaśnionych powyżej, bez zmian, jest dobrym wyborem. Ale jeśli chcesz, aby zestawianie tabel pasowało do języka Twojej witryny, możesz odpowiednio zmodyfikować wartość DB_COLLATE-Define (na przykład - utf8mb4_polish_ci ).

Uwaga: to wyjaśnia, dlaczego znak 𝌆 został poprawnie zapisany i pobrany. Po prostu zestaw znaków w tabelach należał do grupy utf8mb4 , a nie utf8 .


1
Dziękujemy za wyjaśnienie, w jaki sposób Wordpress ustawia zestawianie, ale nie zająłeś się resztą punktów. Dlaczego, jeśli zdefiniowano zestaw znaków UTF-8, MySQL pokazuje bazę danych jako latin1? I dlaczego pokazuje sortowanie bazy danych jako szwedzkie? Ponadto wydaje się, że mylisz zestaw znaków i zestawianie. Sortowanie określa tylko porządek, zasady porównywania, a nie zestaw znaków. Dlatego bez względu na zastosowane sortowanie, jeśli UTF-8 jest zestawem znaków, znaki poza nim (zgodnie z definicją w węższym sensie MySQL) nie powinny renderować.
X-Mann

Zaktualizuję moją odpowiedź, aby jaśniej wyjaśnić proces.
Frank P. Walentynowicz

1
Dziękuję za aktualizację! Zaakceptowałem twoją odpowiedź, teraz wszystko jest jasne. Problem dotyczy MySQL i mojego braku wiedzy w tym zakresie - nie wiedziałem, że tabele mogą używać szerszego zestawu znaków niż sama baza danych. Te nowe informacje uspokoiły mnie. Nie muszę zmieniać domyślnego zestawu znaków w MySQL, Wordpress zajmuje się nim na poziomie tabeli.
X-Mann

Zapraszamy. Cieszę się, że to pomogło.
Frank P. Walentynowicz
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.