| Чем плох MySQL. | |
| От: | Maxim S. Shatskih mvp | ||
| Дата: | 16.07.07 16:06 | ||
| Оценка: | 45 (10) | ||
| MySQL может использовать один из двух основных низкоуровневых движков — InnoDB или MyISAM. InnoDB вроде как развитый. Только медленнее MyISAM раза в 2.5 — 3, а уж если сравнивать MySQL 4.0 c MSSQLServer 7 (делал такое году в 2004) на одинаковом железе — то Microsoft будет быстрее примерно втрое на паттерне "куча мелких апдейтов". В общем, не знаю, имеет ли смысл пользоваться InnoDB, что с ним стало в "пятерке", и решает ли он хотя бы часть из нижеперечисленных проблем MyISAM. Если да — то, возможно, имеет смысл даже простить такое уменьшение производительности. Теперь о MyISAM. 1. Только table-level locking. Чудовищные тормоза в апликации. Все ждут, пока кто-то один внесет изменения. Крайне забавно, например, для форумного движка со всеми сообщениями в одной таблице. 2. Отсутствие средства автовосстановления целостности по логу транзакций при старте базы. У MSSQLServer это было с рождения — с начала 90х. После крахов реально пропадают строки из таблиц. Лично видел. 3. Отсутствие полноценных средств бэкапа. Их всего два а) остановить демона, и скрутить базы в tgz б) mysqldump, который не бэкап, а экспорт в текст на языке SQL, и который — урааа! — накладывает лок длительностью во всю операцию. 4. Отвратительная имплементация ORDER BY, см. файл filesort.cc. Что они делают? выгружают ключи к результату (а то и сам результат) в _2 временных файла_, которые даже не являются MyISAMовскими таблицами. Аллоцируют временный буфер в памяти, нарезают его на кусочки, потом покусочечно читают туда первый временный файл, и пишут во второй, делая по ходу merge sort. В пределах кусочков используется qsort. Почему это отвратительно? ну, то, что файлы растут, что при работе с ними используются обычные кэширующие syscalls — это полбеды. Беда в другом. Беда в аллокации этого самого sort_buffer на каждый запрос с ORDER BY. Если юзерей у системы много, а размер буфера велик — то реально исчерпать все 3GB юзерского адресного пространства во FreeBSD и получить облом в malloc(). Более того, там явно стоит цикл вида "а если malloc обломался — то пробуем буфер в 2 раза меньше". Естественно, при такой нагрузке на heap malloc() начинает обламываться не только в filesort, но и в любом другом месте. И тут вступает в силу пятый пункт: 5. Некоторые обломы malloc() не проверяются в коде, и приводят к краху mysqld по сигналу 11. Что, в свою очередь по пункту 2 иногда приводит к исчезновению строк из таблиц. Как ORDER BY сделан в нормальных базах данных? SELECT INTO во временную таблицу с индексом, и потом SELECT уже из нее. Временная таблица создается в том же page cache, что и основная база данных, при этом у этих страниц ставится атрибут "слив на диск в последнюю очередь", что бережет disk IO. При исполнении ORDER BY не используется malloc() больших размеров. Да, можно уменьшить в конфиге параметр sort_buffer_size. И получить стабильные тормоза раза в 4 медленнее, зато практически без крахов. Насколько я понимаю, этот же движок сортировки используется и для InnoDB. В исходниках есть почти такой же код, который специфичен для MyISAM — но он используется в CREATE INDEX, а не в ORDER BY. Выводы: — при разработке приложений под MySQL нужно думать о том, как обойти эту проблему с ORDER BY, вплоть до выгрузки результата в таблицу (на деле временную) с индексом по атрибуту сортировки. — иначе — на единицах гигабайт базы и сотнях пользователей — крах за крахом. — обязательны "узкие композиты" при использовании таблиц с BLOBами, нужно добиваться того, чтобы EXPLAIN SELECT показывал Using index — т.е. полное неприкосновение к самой таблице с полным исполнением запроса по композиту. — возможно, имеет смысл на коленке сделанный table partitioning. Повторю еще раз — для приложений с ощутимой нагрузкой и ощутимыми размерами базы _нужно принимать специальные меры при разработке приложения, чтобы обойти MySQL misdesigns_. Занимайтесь LoveCraftом, а не WarCraftом! |