Ana içeriğe geç

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:

/etc/mysql/mysql.conf.d/mysqld.cnf (Debian/Ubuntu) ya da /etc/my.cnf.d/*.cnf (RHEL ailesi)
[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 mysqldump ile yedek alındı
  • [ ] Büyük tablolar düşük trafikli bir saatte dönüştürüldü
  • [ ] default_storage_engine = InnoDB ayarlandı, sorun tekrar etmeyecek
  • [ ] Dönüşüm sonrası uygulama gerçekten çalışıyor (foreign key/transaction'a bağımlı kod varsa özellikle test edin)