Довольно часто мой Сервер зависает [...] Все таблицы являются InnoDB, и я использую явное LOCK TABLES
, чтобы предотвратить возникновение тупиков InnoDB.
Вы не предотвращаете взаимоблокировки. Вы предотвращаете автоматическое обнаружение взаимоблокировки. Позвольте мне объяснить:
Взаимная блокировка возникает, когда два (или более) процесса конкурируют за один и тот же ресурс, но в другом порядке. Например:
- Процесс А нуждается в ресурсе 2, затем в ресурсе 1. Он успешно захватывает ресурс 2 ...
- Но тогда есть переключение контекста! Процесс B приходит и захватывает ресурс 1, а затем пытается захватить ресурс 2, но не может, потому что A зарезервировал его (либо в транзакции, либо в блокировке), поэтому B переводится в режим удержания.
- Переключение контекста! A приходит снова и пытается захватить ресурс 1, но он удерживается процессом B.
- А сейчас ожидает на B, B теперь ждет на A. Это тупик.
Когда это происходит внутри транзакции, ядро базы данных может обнаружить возникновение взаимоблокировки и разорвать одно из ответственных соединений, позволяя другому продолжить работу.
Когда вы используете LOCK TABLES
, вы не разрешаете ядру базы данных выполнять обнаружение взаимоблокировок, поэтому взаимоблокировка сохраняется до тех пор, пока вы не включите вручную и не убьете один из заблокированных процессов. Хуже того, LOCK TABLES
также может предотвратить чтение, что может привести к полной остановке всего приложения.
Прекратить использование LOCK TABLES
.
Начните использовать транзакции в тех областях кода, где вам нужна целостность транзакций. не добавляйте их везде.
Если вы получаете взаимоблокировки, есть вероятность, что у вас есть разные пути кода, которые выполняют связанные операции со связанными битами данных в другом порядке, или вы не используете транзакции в нужных местах.
Есть и другие альтернативы. Один из них состоит в том, чтобы спроектировать подпрограммы базы данных таким образом, чтобы они определяли, когда произошла взаимоблокировка, и начинали повторное воспроизведение событий, необходимых для продолжения. Другими словами, вы должны выполнить откат, перезапустить транзакцию и попытаться сделать то же самое снова. Скорее всего, к тому времени условия, которые приводят к тупику, уже решены, поэтому вы можете быть в порядке. К сожалению, другие процессы, связанные с тупиком, могли изменить некоторые данные, с которыми вы работали, поэтому перезапуск может быть немного сложным.
Наконец, другая альтернатива - вообще не использовать транзакции или блокировки. Вы не имеете дело с деньгами? Похоже, вы имеете дело с пользователями и рейтингами. Это довольно тривиальные данные. Никто не будет беспокоиться или замечать, если в текущем рейтинге отсутствует голос, который был зарегистрирован в доли секунды после того, как кто-то сделал что-то, что вызывает пересчет рейтинга.