Проблема странных блокировок в MySQL - PullRequest
1 голос
/ 19 июня 2010

Довольно часто мой Сервер зависает, и MySQL показывает следующий список процессов:

Процесс 1: Время: 24 Пользователь: Статус работника: Заблокировано Информация: ЗАБЛОКИРОВАТЬ СТОЛЫ tRatings WRITE, tUsers WRITE

Процесс2: Время: 24 Пользователь: Статус рабочего: Обновление информации: ОБНОВЛЕНИЕ ПАРАМЕТРОВ УСТАНОВКИ fGender = '1' ГДЕ fID = 232049

Процесс 3: Время: 24 Пользователь: Статус рабочего: Заблокировано Информация: ЗАБЛОКИРОВАТЬ ТАБЛИЦЫ tClients READ,tUsers uA READ, tUsers a READ, tNexts READ

Все таблицы являются InnoDB, и я использую явные LOCK TABLES для предотвращения возникновения тупиковых ситуаций InnoDB.

Моя проблема в том, что я вообще ничего не понимаючто здесь не так!Может кто-нибудь объяснить, почему он просто не выполняет операцию за другим?Вместо этого все для процесса ничего не делают (в этом примере) 24 секунды.

Спасибо,

Jo

1 Ответ

1 голос
/ 19 июня 2010

Довольно часто мой Сервер зависает [...] Все таблицы являются InnoDB, и я использую явное LOCK TABLES, чтобы предотвратить возникновение тупиков InnoDB.

Вы не предотвращаете взаимоблокировки. Вы предотвращаете автоматическое обнаружение взаимоблокировки. Позвольте мне объяснить:

Взаимная блокировка возникает, когда два (или более) процесса конкурируют за один и тот же ресурс, но в другом порядке. Например:

  • Процесс А нуждается в ресурсе 2, затем в ресурсе 1. Он успешно захватывает ресурс 2 ...
  • Но тогда есть переключение контекста! Процесс B приходит и захватывает ресурс 1, а затем пытается захватить ресурс 2, но не может, потому что A зарезервировал его (либо в транзакции, либо в блокировке), поэтому B переводится в режим удержания.
  • Переключение контекста! A приходит снова и пытается захватить ресурс 1, но он удерживается процессом B.
  • А сейчас ожидает на B, B теперь ждет на A. Это тупик.

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

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

Прекратить использование LOCK TABLES.

Начните использовать транзакции в тех областях кода, где вам нужна целостность транзакций. не добавляйте их везде.

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

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

Наконец, другая альтернатива - вообще не использовать транзакции или блокировки. Вы не имеете дело с деньгами? Похоже, вы имеете дело с пользователями и рейтингами. Это довольно тривиальные данные. Никто не будет беспокоиться или замечать, если в текущем рейтинге отсутствует голос, который был зарегистрирован в доли секунды после того, как кто-то сделал что-то, что вызывает пересчет рейтинга.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...