Как стать автором
Обновить

Комментарии 25

А если у меня запросы намеренно блокируют друг друга? И что значит «Некоторые запросы делают lock-и, блокирующие другие запросы»? Вы имеете в виду GET_LOCK()?
Тогда механизм не подойдет.
Вообще, несколько странно, если в высоконагруженной системе намеренно предусматриваются запросы блокирующие другие на длительное время.
Т.е. если есть намеренная блокировка, например бэкапера или генератора кэша — то здесь мы получим пару «подвисших до лучших времен» запросов.

Но если у нас есть намеренная блокировка запросов сотен клиентов, то либо система не очень хорошо спроектирована,
либо это весьма специфическая область, для которой да — подход обозначенный в статье не применим.
> «Некоторые запросы делают lock-и, блокирующие другие запросы»? Вы имеете в виду GET_LOCK()?
Не важно — либо явно лочат командой, либо лочат таблицу за счет долгой выборки из этой таблицы
Тему вы выбрали хорошую, но администраторы используют подобные решения и есть готовые реализации, к примеру mk-kill c рекоммендациями по использованию на MySQL Diary
Интересная утилита.
Правда, на первый взгляд, она сама не поддерживает сложную логику,
как например «Убить все запросы старше 3 секунд, если в системе обнаружено 15 запросов, висящих дольше 30 секунд»
Безусловно, эту логику можно реализовать в bash скрипте
В статье больше предлагается не скрипт как непосредственный инструмент, а бизнес-логика
Администратор может реализовать приведенный псевдо-код в виде schedule routine, php-скрипта, bash использующего mk-kill и т.п.
как например «Убить все запросы старше 3 секунд, если в системе обнаружено 15 запросов, висящих дольше 30 секунд»
Я не спец, но как-то так видимо:
/usr/bin/mk-kill --daemonize --interval 3 --any-busy-time 30 --query-count 15
Это будет убивать каждые 3 секунды все запросы висящие больше 30 секунд, если таковых накопится 15 штук.

И в принципе это решение, вполне неплохое.

Но если подойти к проблеме более детально, то при пике нагрузки обычно случается примерно такое:
1. Появилось 100 запросов за 10 секунд и они повесили друг друга
2. Следующие 20 секунд еще 200 запросов к ним «присоеденились». Теперь у нас 300 взаимоблокирующих запросов
3. Через 30 секунд с начала этой ситуации мы убьем только 100 старших (т.к. только они попадут под условие «старше 30 секунд»)
Но к этому времени у нас уже будет 100 20-секундных и 100 10-секнудных запросов — итого 200 тяжелых запросов, которые «не дают продохнуть» базе данных
Имхо, такое бездумное убийство запросов — не выход. Если уж у вас возникнет такая ситуация, как вы описали, то тут скорее нужно задуматься о правильности архитектуры вашей системы и поисках решений по ее улучшению.
Абсолючно верно Алексей замечает. Это тоже самое, что каждый день пить анальгин от головной боли — на следующий день она заболит снова.
Абсолютно верно: > задуматься о правильности архитектуры вашей системы и поисках решений по ее улучшению.

Собственно
> Скрипт полезен в системах, где применяется методология разработки не ставящая целью «преждевременную» оптимизацию всех возможных участков системы,
а где первичная оптимизация производится в очевидных bottleneck-ах, и последующая — в выявляемых в процессе эксплуатации системы.

Шаг (2) алгоритма преследует эту цель
Лучше уж сразу потратить время на разработку нормальной системы, чем понаписать непонятно что, а потом править и фиксить все косяки и убивать запросы при этом.

> первичная оптимизация производится в очевидных bottleneck-ах, и последующая — в выявляемых в процессе эксплуатации системы.

Если вы собираетесь выявлять подобные проблемы в процессе эксплуатации, то думаю ваша система долго не протянет.
Согласен с тем, что в неаджайловых методологиях разработки такие скрипты лучше не применять.

Это для методологии Lean software development
Независимо от того какая методология испольщуется, если у вас есть проблема, то можно её решать, а можно ставить костыли/сметать мусор под ковёр. Ни одна методология не ставит своей целью писать плохой софт.
Возможно, я вас не точно понял, но… :)

Правильно ли, что если у вас всплывает проблема (без багов никто не пишет, это аксиома — правильно?), то вы предлагаете на выбор:
1. Моментально ее решить (пусть хоть в субботу ночью)
2. Не обращать внимание на то, что пока вы будете решать проблему, продакшн будет хромать
3. Выключить продакшн, чтобы пока что как бы не было видно, что у вас баг? :)
Хотя, возможно, у этой утилиты есть ключ «убить вообще все запросы», если достигнуто указанное условие.
Тогда да — она, чуть более грубо, но будет решать ситуацию, связанную с взаимоблокировками.
А выделение в очередь запросов и приоритеты не лучшее ли решение?
А это российский подход такой: прибить, а потом разбираться.
Вообще-то не российский, а берет он свои истоки в Японии (lean production) :)
Ну и доработан американцами (Lean software development):
ru.wikipedia.org/wiki/Бережливая_разработка_программного_обеспечения

Указанное:
> Скрипт полезен в системах, где применяется методология разработки не ставящая целью «преждевременную» оптимизацию всех возможных участков системы,
а где первичная оптимизация производится в очевидных bottleneck-ах, и последующая — в выявляемых в процессе эксплуатации системы.

Продиктовано принципом:
> Предельно отсроченное принятие решений. Решение следует принимать не на основе предположений и прогнозов, а после открытия существенных фактов.

Согласен с тем, что, скажем, в неаджайловых методологиях разработки такие скрипты лучше не применять.
Излагаете красиво, я так не умею {ушёл работать}.
> SELECT @dangerous_queries_count:=COUNT(0) FROM information_schema.processlist
WHERE COMMAND != 'Sleep' AND TIME>@dangerous_query_duration

Соединения в статусе Sleep могут запросто быть причиной блокировок. Особенно если вы исполльзуете autocommit=OFF и InnoDB
Да, согласен. Если имеем такую конфигурацию БД или SLEEP() внутри транзакций, может понадобится дополнительная логика для работы со Sleep-соединениями.
Но бездумно убивать Sleep-запросы нельзя, например их могут создавать «долгоиграющие» php-скрипты выполняющие энкодинг видео и держащие соединение с БД.
Не нужно там никаких sleep внутри транзакций. Достаточно сделать

BEGIN;
UPDATE foo SET bar='baz';


и забыть как таблицв foo будет заблокирована для записи.

> Но бездумно убивать Sleep-запросы нельзя, например их могут создавать «долгоиграющие» php-скрипты выполняющие энкодинг видео и держащие соединение с БД.
ответить

Бездумно никакие запросы убивать нельзя
Зарегистрируйтесь на Хабре , чтобы оставить комментарий

Публикации