Данная тема создана по мотивам
данной темыОпишу проблему. В некоторых случаях, когда количество авторизующихся пользователей большое (это абстрактно, конечно, все зависит от технических средств провайдера) возникают тупняки в авторизации (невозможности подключиться или пропадает авторизация).
Практически всегда в этом виновны так называемые дедлоки (deadlocks) в базе данных. Если коротко, то в базе данных есть механизм локов, это не что-то плохое, он предназначен для сохранения консистентности базы данных. Но бывают ситуации, когда локи "превращаются" в мертвые и записи в БД долго остаются заблокированными, что приводит к тупнякам.
Почему это происходит? С одной стороны, в этом есть вина движка mysql, с другой стороны нужно менять sql запросы так, чтобы они не приводили к дедлокам. Однако, не всегда это возможно. Более того, не всегда можно понять почему, черт возьми, этот запрос привел к дедлокам.
Одним из проблемных sql был запрос на создание/продление авторизации. Есть таблица auth_now, которая хранит текущие авторизации. Когда приходит запрос от Радиуса "такой-то перец авторизован", то процедура NoDeny пытается создать запись в таблице auth_now, а если она там уже есть, то пытается заапдейтить (обновить актуальные данные).
В mysql есть механизм для выполнения этих действий как единого целого (а нам для корректности и безглючности именно это и нужно) - INSERT ... ON DUPLICATE KEY UPDATE - либо вставляем, либо обновляем если запись есть.
Вот этот запрос приводил к дедлокам. Если честно, я не вижу логики почему. Вернее, я вижу косвенную причину, хотя и не понимаю, почему она возникает. Короче. Судя по логам, проблема возникает на конфликте поля Id. Вероятно, когда insert откатывается, идет попытка отката поля id, а оно заблокировано.
Что такое поле id? Оно есть практически во всех таблицах и нужно для того, чтобы как-то идентифицировать запись, грубо говоря номер строки. Это поле автинкрементное и при вставке любой записи оно становится +1. В общем, поле нужное. Практически всегда.
Я обратил внимание, что NoDeny нет никакой необходимости нумеровать записи в таблице авторизации. Да, поле теоретически полезное, но оно никак не используется. А проблема именно в нем. Поэтому я пришел к чисто Сталлинскому решению: нет поля, нет проблемы. И предложил удалить это поле автору топика в начале данного.
И судя по его данным, все получилось. Повторюсь, что нужно сделать:
alter table auth_now drop id;