MySQL/MariaDB'de storage engine: InnoDB'ye geçiş#
MySQL kurulumunu bu sayfada anlatmıyoruz - onun için Linux Yönetimi Kitabı'ndaki MySQL kurulum sayfasına bakın. Burada dar ama sık karşılaşılan bir soru var: bir tablo (ya da eski bir veritabanının tamamı) hâlâ MyISAM'da, ve InnoDB'ye geçmeniz gerekiyor.
Neden InnoDB#
MySQL 5.5'ten beri varsayılan storage engine InnoDB'dir - MyISAM'ı hâlâ görüyorsanız, o tablo muhtemelen çok eski bir sürümde oluşturulmuş ya da eski bir yedekten geri yüklenmiş demektir. Fark önemsiz değil:
| MyISAM | InnoDB | |
|---|---|---|
| Transaction (COMMIT/ROLLBACK) | Yok | Var |
| Kilitlenme | Tablo seviyesinde | Satır seviyesinde |
| Çökme sonrası kurtarma | Zayıf, sık tablo bozulması | Otomatik (crash recovery) |
| Foreign key | Desteklemez | Destekler |
| Full-text index | Var (eski MySQL'in tek sebebiydi) | MySQL 5.6+'dan beri var |
Full-text arama tek gerekçenizse artık InnoDB'de de var - MyISAM'da kalmanın çoğu zaman bir sebebi yok.
Mevcut durumu kontrol edin#
SELECT table_schema, table_name, engine
FROM information_schema.tables
WHERE table_schema NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
AND engine != 'InnoDB';
Bu sorgu, sisteminizde InnoDB dışında bir engine kullanan her tabloyu listeler.
Tek tabloyu dönüştürün#
ALTER TABLE veritabani.tablo_adi ENGINE=InnoDB;
Küçük tablolarda anında biter. Büyük tablolarda ALTER TABLE tabloyu yeniden yazar ve süre tablo boyutuyla orantılı büyür - kilitlenme derecesi ise MySQL/MariaDB sürümüne ve desteklenen ALGORITHM/LOCK seçeneklerine bağlıdır: ALGORITHM=COPY tabloyu baştan yeniden kurar ve genelde daha güçlü kilitleme ister, desteklendiği durumlarda ALGORITHM=INPLACE + LOCK=NONE eşzamanlı yazmalara izin verebilir.
Kilitlenmeyi varsaymadan önce kontrol edin
Yazmaların dönüşüm boyunca beklediğini ya da kesintisiz sürdüğünü varsaymayın - kendi sürümünüzde hangi ALGORITHM/LOCK seçeneklerinin desteklendiğini önceden doğrulayın (EXPLAIN ya da ALTER TABLE ... ALGORITHM=INPLACE, LOCK=NONE ile deneyin) ve işlem sürerken metadata lock'ları izleyin. Milyonlarca satırlık bir tabloda, native işlem kilitleme ihtiyacınızı karşılamıyorsa düşük trafikli bir saatte yapın ya da pt-online-schema-change (Percona Toolkit) gibi çevrimiçi bir araç kullanın.
Tüm veritabanını dönüştürün#
Tek tek yazmak yerine, information_schema'dan ALTER TABLE komutlarını üretip çalıştırabilirsiniz:
mysql -N -e "SELECT CONCAT('ALTER TABLE \`', REPLACE(table_schema, '\`', '\`\`'), '\`.\`', REPLACE(table_name, '\`', '\`\`'), '\` ENGINE=InnoDB;')
FROM information_schema.tables
WHERE table_schema='veritabani_adi' AND engine != 'InnoDB';" | mysql veritabani_adi
Tırnak içine alma (backtick) rastgele değil: rezerve kelime, boşluk ya da tire içeren bir tablo/veritabanı adı tırnaksız ALTER TABLE cümlesini geçersiz kılar ve üretilen script o satırda durur - kalan tablolar sessizce dönüştürülmeden kalır.
Dönüştürmeden önce yedek alın
ALTER TABLE ENGINE= geri alınamaz bir işlemdir - dönüşüm sırasında bir şey ters giderse elinizde ne eski ne yeni format kalır. mysqldump ile yedek almadan büyük bir dönüşüme başlamayın.
mysqldump veritabani_adi > /opt/yedek/oncesi-$(date +%F).sql
Yeni tabloları varsayılan olarak InnoDB yapın#
Sunucu genelinde varsayılan engine'i ayarlayıp bu sorunu bir daha yaşamayın:
[mysqld]
default_storage_engine = InnoDB
sudo systemctl restart mysql # ya da mariadb
Morpheus ile
"veritabanı X'te InnoDB olmayan tabloları listele"
"tablo Y'yi InnoDB'ye dönüştür, önce yedek al"
Morpheus sorguyu çalıştırır, sonucu size gösterir ve onayınızla dönüşümü uygular - ama büyük bir dönüşümden önce yedek almayı atlamaz.
Kontrol listesi#
- [ ] Dönüştürmeden önce
mysqldumpile yedek alındı - [ ] Büyük tablolar düşük trafikli bir saatte dönüştürüldü
- [ ]
default_storage_engine = InnoDBayarlandı, sorun tekrar etmeyecek - [ ] Dönüşüm sonrası uygulama gerçekten çalışıyor (foreign key/transaction'a bağımlı kod varsa özellikle test edin)