MySQL'de utf8 adında, UTF-8 olmayan bir karakter kümesi vardır. Karakter başına en çok üç bayt saklar; oysa her emoji ve bazı seyrek karakterler dört ister. İçinde böyle bir karakter geçen metin ya geri çevrilir ya da tam o noktada sessizce kesilir — bir yorumun bir paragraftan sonrasının yok olmasının sebebi budur.

Her yerde utf8mb4 kullanın

ALTER DATABASE shop CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE comments CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

Bağlantıda da: gözden kaçan yarısı burasıdır

// PDO
new PDO('mysql:host=localhost;dbname=shop;charset=utf8mb4', $u, $p);
; my.cnf
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
latin1 bir bağlantı üzerinden okunan utf8mb4 bir tablo, bozuk metin döndürür ve geriye bozuk metin yazar. Tablo doğrudur, bağlantı değildir, veri de yolda bozulur. İkisini de ayarlayın.

Hangi harmanlama

  • utf8mb4_unicode_ci — diller arasında Unicode kurallarına göre sıralar ve karşılaştırır. Güvenli varsayılan.
  • utf8mb4_0900_ai_ci — MySQL 8'in varsayılanı, daha yeni Unicode, biraz daha hızlı.
  • utf8mb4_bin — baytların tam kendisi. Belirteçler ve özetler için kullanın, adlar için asla.

Karşılaştırmayı harmanlama belirler. Büyük-küçük harf ayırmayan bir harmanlamada WHERE name = 'ali' ifadesi Ali ile de eşleşir — bir aramada genellikle istediğiniz budur, bir API anahtarında ise değildir.

Hâlâ yanlış olanı bulun

SELECT table_name, table_collation
  FROM information_schema.tables
 WHERE table_schema = 'shop' AND table_collation NOT LIKE 'utf8mb4%';

SELECT table_name, column_name, character_set_name
  FROM information_schema.columns
 WHERE table_schema = 'shop' AND character_set_name IS NOT NULL
   AND character_set_name <> 'utf8mb4';

Sütunlar, tablolardan ayrı olarak dönüştürülür. utf8mb4 diye tanımlanmış bir tablo, yıllar öncesinden kalma latin1 sütunlar taşıyor olabilir — bozulanlar da işte onlardır.

Dönüştürmeden önce yedek alın. Her satırı yeniden yazar, büyük bir tabloda zaman alabilir ve eski sürümlerde dizin boyutu sınırları arada bir canınızı yakar.