Trzy miejsca, w których MySQL potrzebuje kodowania
- Kolumna lub tabela: zestaw znaków, w którym zapisane są dane, np.
utf8mb4,latin2lubcp1250. - Połączenie: zestaw znaków, w którym klient i serwer ze sobą rozmawiają – ustawiasz go przez
SET NAMES utf8mb4albo w ustawieniach połączenia. - Plik: kodowanie, w którym czytany jest import lub zapisywany eksport – w phpMyAdmin w polu Zestaw znaków pliku.
Jeśli te trzy ustawienia się nie zgadzają, polskie litery się psują. Najczęstszy przypadek: tekst w UTF-8 zapisany przez połączenie latin1 do kolumny latin1. W aplikacji wszystko wygląda dobrze, ale phpMyAdmin i eksport pokazują Ä… i Ĺ‚.
Przed
"1","Zbigniew Wójcik","ul. Gdańska 12","Kraków"
Po
"1","Zbigniew Wójcik","ul. Gdańska 12","Kraków"
Sprawdź zestawy znaków
SHOW VARIABLES LIKE 'character_set%';pokazuje ustawienia serwera i połączenia.SHOW CREATE TABLE klienci;pokazuje zestaw znaków tabeli i jej kolumn.SELECT nazwisko, HEX(nazwisko) FROM klienci LIMIT 5;pokazuje prawdziwe bajty: w kolumnieutf8mb4C3B3toó, aC383C2B3to już zepsuteó.
Napraw eksport lub zrzut bazy
- Wyeksportuj tabelę w phpMyAdmin jako SQL lub CSV – albo poleceniem
mysqldump --default-character-set=utf8mb4. - Przeciągnij plik do pola powyżej. Mojibuster naprawia tylko zepsute miejsca, poprawne znaki zostają bez zmian.
- Sprawdź naprawione miejsca w sekcji Co zostało zmienione? i pobierz plik.
- Zaimportuj go do tabeli z
utf8mb4i w oknie importu wybierz zestaw znakówutf-8. - Najpierw przetestuj to na kopii, zanim podmienisz prawdziwą tabelę.
Eksport nigdy nie opuszcza Twojego komputera – a przy danych klientów to ma znaczenie. Jeśli teksty w bazie są zepsute w kilku warstwach naraz, zajrzyj na stronę co to jest mojibake.
Usuń przyczynę
- Nowe tabele twórz z
DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci. Do polskiego sortowania możesz użyć teżutf8mb4_polish_ci. - Ustaw w aplikacji połączenie
utf8mb4, w PHP np. przezcharset=utf8mb4w DSN dla PDO. - Jeśli bajty UTF-8 leżą w kolumnie
latin1, nie konwertuj jej wprost przezCONVERT TO– zakodujesz je drugi raz i powstanie tekst zakodowany podwójnie. Bezpieczna droga prowadzi przez typ binarny: najpierwMODIFY nazwisko VARBINARY(255), potemMODIFY nazwisko VARCHAR(255) CHARACTER SET utf8mb4. - Jeśli MySQL zamienia litery na
?, kolumna lub połączenie nie potrafią ich zapisać. To, co tak już zapisano, jest utracone – więcej w artykule co to jest mojibake.
Najczęstsze pytania
Dlaczego w aplikacji wszystko wygląda dobrze, a w phpMyAdmin nie?
Bo aplikacja i baza robią ten sam błąd dwa razy: aplikacja zapisuje UTF-8 przez połączenie latin1 i tak samo je odczytuje. phpMyAdmin łączy się poprawnie, więc pokazuje to, co naprawdę jest w bazie.
Jakiego porównywania (collation) użyć?
utf8mb4_unicode_ci pasuje do większości aplikacji, a od MySQL 8 domyślne jest utf8mb4_0900_ai_ci. Ważniejszy jest zestaw znaków utf8mb4 – nie utf8, który w MySQL nie zapisze emoji.
Czy to działa także z MariaDB?
Tak. MariaDB obsługuje zestawy znaków jak MySQL, a polecenia są takie same.
Jak duży może być zrzut bazy?
Do 100 MB na plik. Większe bazy eksportuj tabela po tabeli.