MySQL зберігає дані через рушії зберігання (storage engines). Один сервер може мати таблиці на різних рушіях. Від MySQL 5.5 рушій за замовчуванням - InnoDB, а MyISAM лишився спадщиною.
Що дає InnoDB:
- Транзакції (ACID).
COMMIT,ROLLBACK, відновлення після збою. У MyISAM транзакцій немає взагалі:DB::transaction()у Laravel на MyISAM-таблиці нічого не відкотить. - Блокування рядків. Два запити, що оновлюють різні рядки однієї таблиці, не заважають один одному. MyISAM блокує всю таблицю на кожен запис - під навантаженням на запис усі запити стають у чергу.
- Узгоджене читання (MVCC). Читачі не чекають на записувачів:
SELECTбачить знімок даних, а не блокується через чужийUPDATE. - Зовнішні ключі. MyISAM синтаксис
FOREIGN KEYприймає, але ігнорує. - Стійкість до збоїв. Після аварійного вимкнення InnoDB відновлюється за журналом повтору (redo log). MyISAM-таблиці після збою часто доводиться «лагодити» (
REPAIR TABLE) з ризиком втратити дані. - Кластерний індекс. Рядки фізично впорядковані за первинним ключем, тож пошук за ним дуже дешевий.
Чим MyISAM колись приваблював і чому це вже неактуально:
- точний
COUNT(*)без умов миттєво (лічильник у метаданих) - InnoDB рахує рядки, бо через MVCC різні транзакції бачать різну кількість; - повнотекстовий пошук - InnoDB має його від 5.6;
- менший розмір на диску - різниця не варта втрати транзакцій.
Як перевірити й перевести:
SELECT table_name, engine FROM information_schema.tables
WHERE table_schema = DATABASE() AND engine <> 'InnoDB';
ALTER TABLE legacy_logs ENGINE = InnoDB;
ALTER ... ENGINE перебудовує таблицю повністю, тож на великих таблицях це варто планувати.
Інші рушії мають вузьке застосування: MEMORY для тимчасових даних (зникають при перезапуску), ARCHIVE для рідко читаних логів, CSV для обміну. Для таблиць застосунку відповідь майже завжди одна - InnoDB.