MySQL "Specified key was too long" — 3072 Bayt Sınırı Nereden Geliyor?
3072 bayt indeks sınırının nedeni, utf8mb4 çarpanı, prefix indeks ve bileşik indekslerde toplam boyut hesabı.
Operasyonel Doğrulama & Güvenilirlik Standardı
Hata mesajı semptomdur, kök neden değildir. Sunucuyu yeniden başlatmadan veya rastgele ayar değiştirmeden önce aşağıdaki "Nedeni ayırt eden tek sorgu"yu çalıştırarak gerçek senaryoyu netleştirin.
▸Belirti
ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytesBu hata neredeyse her zaman utf8mb4 karakter seti + uzun varchar birleşiminden kaynaklanır. Hesaplama basittir ancak şema tasarımlarında sıklıkla gözden kaçar:
| Karakter Seti | Karakter Başına Bayt | 3072 Bayt / Karakter Sınırı |
|---|---|---|
latin1 | 1 bayt | 3.072 karakter |
utf8mb3 (utf8) | 3 bayt | 1.024 karakter |
utf8mb4 | 4 bayt | 768 karakter |
Dolayısıyla varchar(768) olan utf8mb4 bir kolon tek başına 3.072 baytlık sınırı doldurur. Bileşik (composite) indekslerde ise tüm kolonların toplam bayt değeri hesaplanır: İki adet varchar(500) utf8mb4 kolon = 1000 × 4 = 4.000 bayt eder ve Error 1071 fırlatılır.
▸Nedeni Doğrulayan Sorgular
SELECT @@innodb_default_row_format;
SHOW TABLE STATUS LIKE 'uygulamalar'; -- Row_format sütununu inceleyin
SELECT column_name, column_type, character_set_name, character_maximum_length
FROM information_schema.columns
WHERE table_schema = DATABASE() AND table_name = 'uygulamalar';Row_format değeri COMPACT veya REDUNDANT ise sınır 3.072 değil 767 bayttır; hata mesajında da "max key length is 767 bytes" yazar. MySQL 8.0 ve sonrasında varsayılan format DYNAMIC'tir ve eski innodb_large_prefix değişkeni tamamen kaldırılmıştır.▸Çözüm Yolları
1. Prefix İndeks (En Hızlı Çözüm)
ALTER TABLE uygulamalar ADD INDEX idx_ad (ad(191));191 karakter, utf8mb4'te 764 bayt tutar ve eski 767 sınırına da sığan klasik standarttır.
UNIQUE kısıtında kullanırsanız yalnızca ön ek tekilliğini garanti eder; "Ali Veli" ve "Ali Veli2" gibi değerler çakışabilir. Tam tekillik gerekiyorsa 3. yöntemi kullanın.2. Kolonu Kısaltın ve Satır Formatını Güncelleyin
ALTER TABLE uygulamalar ROW_FORMAT = DYNAMIC;
ALTER TABLE uygulamalar MODIFY ad VARCHAR(500) NOT NULL;3. Tam Tekillik Gerekiyorsa → Üretilmiş Kolon + SHA-256 Hash
ALTER TABLE uygulamalar
ADD COLUMN ad_hash BINARY(32) GENERATED ALWAYS AS (UNHEX(SHA2(ad, 256))) STORED,
ADD UNIQUE INDEX uk_ad_hash (ad_hash);Sabit 32 bayt kaplar, 3.072 sınırına hiç yaklaşmaz ve tüm metin üzerinden kusursuz tekillik sağlar.
4. utf8mb3'e Geri Dönmeyin!
utf8mb3'e dönmek sınırı geçici olarak çözer gibi görünür ancak emoji ve 4 baytlık özel karakter desteğini yok eder; bu durum kısa süre sonra MySQL Error 1366: Incorrect string value (H-25) olarak geri döner.
▸Ortak Karşılaştırma: MySQL vs. PostgreSQL İndeks Boyut Sınırları
| Mimari Kriter | MySQL InnoDB (DYNAMIC) | PostgreSQL (B-Tree) |
|---|---|---|
| Azami Anahtar Boyutu | 3.072 bayt | 2.704 bayt (8 KB / 3) |
| Karakter Sınırı (utf8mb4) | 768 karakter | ~676 karakter |
| Sınır Aşım Kodu | Error 1071 (42000) | index row size exceeds maximum |
| Kardeş Rehber | Bu Rehber (H-22) | PostgreSQL Hata Rehberi (H-21) |
▸Bunu Bir Daha Yaşamamak İçin
Yeni tablo tasarlarken bileşik indekslerin toplam bayt hacmini önceden hesaplayın: her varchar(n) için n × 4. Toplam 3.000 baytı aşıyorsa tasarımı revize edin. Ayrıca H-25'teki utf8mb4 dönüşümünü planlarken mevcut tüm indekslerin boyutlarını yeniden hesaplayın; utf8mb3 ile sınırda çalışan indeksler dönüşüm sonrası patlayacaktır.
- •Kardeş Rehber (PostgreSQL): PostgreSQL index row size exceeds maximum
- •İlişkili Hata (MySQL): MySQL Error 1366: Incorrect string value (utf8mb4 / emoji)
- •Veritabanı Hub: MySQL Üretim Mimarisi Rehberi
Diğer Veritabanı Hata Teşhisleri
Kriz anında başvurabileceğiniz diğer doğrulanmış hata rehberleri.
MySQL ERROR 1045 Access denied: root Şifresi Sıfırlama Rehberi
MySQL 1045 hatasının dört nedeni, "using password: YES/NO" ayrımının anlamı ve kilitli kalınca --init-file ile güvenli şifre sıfırlama.
MySQL Deadlock ERROR 1213: Grafiği Okuma ve Kalıcı Önleme
MySQL 1213 deadlock hatasının nedeni, LATEST DETECTED DEADLOCK çıktısını okuma, gap lock kaynaklı kilitlenmeler ve uygulama tarafında retry tasarımı.
MySQL Lock wait timeout exceeded: Bloklayan İşlemi Bulma
1205 lock wait timeout hatasında bloklayan işlemi performance_schema ile bulma, KILL kararını verme ve kilidi kalıcı olarak azaltma yöntemleri.