Merhaba arkadaşlar, bugün sizlere MySQL veya MariaDB sunucularınızda karakter setini `utf8mb4`'e nasıl geçireceğinizi ve bu geçiş sırasında karşılaşabileceğiniz uyumluluk sorunlarını nasıl çözeceğinizi adım adım anlatacağım. Bu geçiş, emoji'leri (
) ve tüm dünya dillerindeki karakterleri (örneğin, bazı nadir Çince karakterler) sorunsuzca saklamanızı sağlar. Eski `utf8` karakter seti, sadece 3 byte'lık karakterleri desteklediği için bu tür karakterlerde sorun yaşatabiliyordu. Benim yönettiğim tüm sunucularda artık standart olarak `utf8mb4` kullanıyorum.
Neden UTF8MB4? Temel Farklar
`utf8` (MySQL'in tanımıyla) aslında "utf8mb3" anlamına gelir ve maksimum 3 byte'lık karakterleri destekler. `utf8mb4` ise tam 4 byte'lık UTF-8 Unicode kodlamasını destekler. Bu ekstra 1 byte, emoji'ler ve BMP (Temel Çok Dilli Düzlem) dışındaki karakterler için hayati önem taşır. Geçiş yapmazsanız, bu karakterler veritabanınıza "?" gibi bozuk karakterler olarak kaydedilir veya hata alırsınız.
Mevcut Durumunuzu Kontrol Edin
İşe, sunucunuzdaki ve veritabanlarınızdaki mevcut karakter seti ve collation (karşılaştırma) ayarlarını kontrol ederek başlayalım. Aşağıdaki komutları yönetim konsolunuzdan (mysql veya mariadb komut satırı) çalıştırabilirsiniz.
Çıktıda `character_set_server` ve `collation_server` değerlerini, ayrıca tablo ve sütunlarınızın `CHARSET` ve `COLLATE` bilgilerini not alın. Eğer `utf8` veya `latin1` gibi bir şey görüyorsanız, geçişe hazırsınız demektir.
Sunucu ve Veritabanı Seviyesinde Geçiş
Öncelikle, yeni oluşturulacak veritabanları ve tablolar için varsayılanı değiştirelim. Bu işlem mevcut veritabanlarını ve tabloları ETKİLEMEZ, sadece yeniler için geçerlidir. Ana konfigürasyon dosyasını (/etc/mysql/my.cnf veya /etc/mysql/mariadb.conf.d/50-server.cnf) düzenleyin.
Dosyayı kaydettikten sonra MySQL/MariaDB servisini yeniden başlatın: `
` (veya mariadb).
Şimdi, mevcut bir veritabanının varsayılan karakter setini değiştirelim. Bu işlem, o veritabanı içinde YENİ oluşturulacak tabloların varsayılanını değiştirir.
EN KRİTİK ADIM: Mevcut Tablo ve Sütunları Dönüştürme
Bu adım, mevcut verilerinizi dönüştüreceği için MUTLAKA ÖNCE BİR YEDEK ALIN! Aşağıdaki komut, belirli bir veritabanındaki TÜM tabloların karakter setini ve collation'unu dönüştürmek için dinamik bir SQL üretir. Bu komutu çalıştırmak yerine, ürettiği ALTER TABLE komutlarını kontrol edip teker teker çalıştırmak daha güvenli olabilir.
Çıktıdaki `ALTER TABLE` komutlarını kopyalayıp çalıştırabilirsiniz. Bu komut, tablonun kendisini, tüm sütunlarını ve indekslerini dönüştürür. Büyük tablolarda bu işlem uzun sürebilir ve sunucu yükünü artırabilir. Bu nedenle trafiğin az olduğu bir saatte yapmanızı şiddetle tavsiye ederim.
Karşılaşabileceğiniz Sorunlar ve Çözümleri
1. "Specified key was too long" Hatası:
`utf8mb4`, bir karakter için maksimum 4 byte kullanır. `utf8`'de 255 karakterlik bir VARCHAR sütunu 255 3 = 765 byte yer kaplarken, `utf8mb4`'te 255 4 = 1020 byte kaplar. MySQL'in InnoDB motoru için indeks uzunluğu limiti 767 byte'dır (eski sürümlerde). Bu nedenle, üzerinde indeks bulunan uzun VARCHAR veya TEXT sütunlarınız varsa bu hatayı alırsınız.
Çözüm: İndeks uzunluğunu sınırlayın (prefix index).
Veya, MariaDB 10.2.2 / MySQL 5.7.7 ve sonrasında `innodb_large_prefix` ayarını etkinleştirip `innodb_default_row_format`'ı `DYNAMIC` veya `COMPRESSED` yaparak bu limiti 3072 byte'a çıkarabilirsiniz.
2. Bağlantı ve İstemci Uyumluluk Sorunları:
Uygulamanızın bağlantı dizesinde veya sorgularında karakter seti belirtilmemiş olabilir. PHP (PDO/MySQLi), Python, Java gibi dillerde bağlantı kurduktan hemen sonra `SET NAMES 'utf8mb4'` sorgusunu çalıştırmalısınız.
PHP (PDO) Örneği:
Son Kontroller ve Test
Her şey tamamlandığında, tüm ayarların doğru şekilde güncellendiğini kontrol edin.
Eğer emoji'yi sorunsuz görüyorsanız, geçiş başarılı demektir!
Umarım bu rehber faydalı olmuştur arkadaşlar. Bu işlem biraz teknik detay içeriyor ama özellikle modern web uygulamaları ve çok dilli içerikler için artık bir zorunluluk. Benim sunucu migrasyonlarında uyguladığım standart prosedür bu şekilde. Siz bu konfigürasyonu kendi sunucularınızda nasıl yapıyorsunuz? Farklı bir yönteminiz veya eklemek istediğiniz bir püf noktası var mı? Ya da takıldığınız bir yer olursa aşağı
`utf8` (MySQL'in tanımıyla) aslında "utf8mb3" anlamına gelir ve maksimum 3 byte'lık karakterleri destekler. `utf8mb4` ise tam 4 byte'lık UTF-8 Unicode kodlamasını destekler. Bu ekstra 1 byte, emoji'ler ve BMP (Temel Çok Dilli Düzlem) dışındaki karakterler için hayati önem taşır. Geçiş yapmazsanız, bu karakterler veritabanınıza "?" gibi bozuk karakterler olarak kaydedilir veya hata alırsınız.
İşe, sunucunuzdaki ve veritabanlarınızdaki mevcut karakter seti ve collation (karşılaştırma) ayarlarını kontrol ederek başlayalım. Aşağıdaki komutları yönetim konsolunuzdan (mysql veya mariadb komut satırı) çalıştırabilirsiniz.
SQL:
-- Sunucu genelindeki varsayılan ayarları göster
SHOW VARIABLES LIKE 'character_set_server';
SHOW VARIABLES LIKE 'collation_server';
-- Belirli bir veritabanının ayarlarını kontrol et (ÖRNEK_DB yerine kendi DB adınızı yazın)
SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME = 'ÖRNEK_DB';
-- Bir tablonun ayarlarını kontrol et (ÖRNEK_TABLO yerine kendi tablo adınızı yazın)
SHOW CREATE TABLE ÖRNEK_TABLO;
Çıktıda `character_set_server` ve `collation_server` değerlerini, ayrıca tablo ve sütunlarınızın `CHARSET` ve `COLLATE` bilgilerini not alın. Eğer `utf8` veya `latin1` gibi bir şey görüyorsanız, geçişe hazırsınız demektir.
Öncelikle, yeni oluşturulacak veritabanları ve tablolar için varsayılanı değiştirelim. Bu işlem mevcut veritabanlarını ve tabloları ETKİLEMEZ, sadece yeniler için geçerlidir. Ana konfigürasyon dosyasını (/etc/mysql/my.cnf veya /etc/mysql/mariadb.conf.d/50-server.cnf) düzenleyin.
INI:
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
init_connect = 'SET NAMES utf8mb4'
Dosyayı kaydettikten sonra MySQL/MariaDB servisini yeniden başlatın: `
Bash:
sudo systemctl restart mysql
Şimdi, mevcut bir veritabanının varsayılan karakter setini değiştirelim. Bu işlem, o veritabanı içinde YENİ oluşturulacak tabloların varsayılanını değiştirir.
SQL:
ALTER DATABASE ÖRNEK_DB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
Bu adım, mevcut verilerinizi dönüştüreceği için MUTLAKA ÖNCE BİR YEDEK ALIN! Aşağıdaki komut, belirli bir veritabanındaki TÜM tabloların karakter setini ve collation'unu dönüştürmek için dinamik bir SQL üretir. Bu komutu çalıştırmak yerine, ürettiği ALTER TABLE komutlarını kontrol edip teker teker çalıştırmak daha güvenli olabilir.
SQL:
SELECT CONCAT('ALTER TABLE `', TABLE_NAME, '` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'ÖRNEK_DB'
AND TABLE_COLLATION NOT LIKE 'utf8mb4%';
Çıktıdaki `ALTER TABLE` komutlarını kopyalayıp çalıştırabilirsiniz. Bu komut, tablonun kendisini, tüm sütunlarını ve indekslerini dönüştürür. Büyük tablolarda bu işlem uzun sürebilir ve sunucu yükünü artırabilir. Bu nedenle trafiğin az olduğu bir saatte yapmanızı şiddetle tavsiye ederim.
1. "Specified key was too long" Hatası:
`utf8mb4`, bir karakter için maksimum 4 byte kullanır. `utf8`'de 255 karakterlik bir VARCHAR sütunu 255 3 = 765 byte yer kaplarken, `utf8mb4`'te 255 4 = 1020 byte kaplar. MySQL'in InnoDB motoru için indeks uzunluğu limiti 767 byte'dır (eski sürümlerde). Bu nedenle, üzerinde indeks bulunan uzun VARCHAR veya TEXT sütunlarınız varsa bu hatayı alırsınız.
Çözüm: İndeks uzunluğunu sınırlayın (prefix index).
SQL:
-- Örnek: 191 karakterden sonrasını indeksleme
ALTER TABLE forum_mesajlari DROP INDEX mesaj_indeksi;
ALTER TABLE forum_mesajlari ADD INDEX mesaj_indeksi (mesaj(191));
Veya, MariaDB 10.2.2 / MySQL 5.7.7 ve sonrasında `innodb_large_prefix` ayarını etkinleştirip `innodb_default_row_format`'ı `DYNAMIC` veya `COMPRESSED` yaparak bu limiti 3072 byte'a çıkarabilirsiniz.
2. Bağlantı ve İstemci Uyumluluk Sorunları:
Uygulamanızın bağlantı dizesinde veya sorgularında karakter seti belirtilmemiş olabilir. PHP (PDO/MySQLi), Python, Java gibi dillerde bağlantı kurduktan hemen sonra `SET NAMES 'utf8mb4'` sorgusunu çalıştırmalısınız.
PHP (PDO) Örneği:
PHP:
$pdo = new PDO('mysql:host=localhost;dbname=ÖRNEK_DB;charset=utf8mb4', 'kullanici', 'sifre');
Her şey tamamlandığında, tüm ayarların doğru şekilde güncellendiğini kontrol edin.
SQL:
-- Tüm tablolarınızın durumunu özetle
SELECT TABLE_NAME, TABLE_COLLATION
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'ÖRNEK_DB';
-- Örnek bir emoji veya özel karakter ekleyerek test edin
UPDATE test_tablom SET yorum = 'Merhaba Dünya! 😊 ✅' WHERE id = 1;
SELECT FROM test_tablom WHERE id = 1;
Eğer emoji'yi sorunsuz görüyorsanız, geçiş başarılı demektir!
Umarım bu rehber faydalı olmuştur arkadaşlar. Bu işlem biraz teknik detay içeriyor ama özellikle modern web uygulamaları ve çok dilli içerikler için artık bir zorunluluk. Benim sunucu migrasyonlarında uyguladığım standart prosedür bu şekilde. Siz bu konfigürasyonu kendi sunucularınızda nasıl yapıyorsunuz? Farklı bir yönteminiz veya eklemek istediğiniz bir püf noktası var mı? Ya da takıldığınız bir yer olursa aşağı