Как mysql может съесть всю оперативную память

Dec 13, 2011 18:55

Оказывается mysql легко уронить. Для этого не обязательно использовать малоизвестные уязвимости. Достаточно послать "правильный" SQL запрос. Главные особенности - размер и ветвистость.


Например что-то вроде:

SELECT DISTINCT B.ID as ID
FROM b_sale_basket B
WHERE
((((B.FUSER_ID = 1 ))))
AND ((
(B.PRODUCT_ID IS NULL OR NOT (B.PRODUCT_ID = 1)) AND
(B.PRODUCT_ID IS NULL OR NOT (B.PRODUCT_ID = 2)) AND
...
(B.PRODUCT_ID IS NULL OR NOT (B.PRODUCT_ID = 24999)) AND
(B.PRODUCT_ID IS NULL OR NOT (B.PRODUCT_ID = 25000)) AND
))
AND ((((B.LID = 's1'))))
AND ((((B.ORDER_ID IS NULL) OR (B.ORDER_ID = 0))))

В итоге получается размер около 1,5 Мб.
Как получился такой запрос не важно (на совести кодеров).
Наша задача защитить mysql от этого безобразия.
Сделать это просто - нужно уменьшить допустимый размер запроса хотя бы до 512 Кб. А лучше до 256 Кб.

В настройках my.cnf пропишем:

[mysqld]
max_allowed_packet = 512K

[mysqldump]
net_buffer_length = 512K

И перезапустим.

Кстати, сейчас арендуем сервер на scalaxy. Обычно хватает 2-3 Гб оперативки. Но когда возник этот жуткий запрос не хватало даже 16 Гб. Система постоянно убивала mysql так как возникала нехватка памяти (mysql съедал 15 Гб):

mysqld invoked oom-killer
...
Killed process 27833 (mysqld)
Оказывается есть еще много других способов навредить работе mysql.

Но там нет моего случая - пришлось разбираться самому.
Мне помог журнал mysql:

general_log_file = /var/log/mysql/mysql.log
Будьте осторожны - не включайте его постоянно. Только во время отладки:

SET @@global.general_log = 'ON';

mysql, oom, out of memory

Previous post Next post
Up