Какой запрос вызывает взаимоблокировку, обнаруженную при попытке получить блокировку; попробуйте перезапустить транзакцию

#php #mysql #deadlock

#php #mysql #взаимоблокировка

Вопрос:

Я не могу понять, какой запрос вызывает Deadlock found when trying to get lock; try restarting transaction . Моя оболочка для mysql имеет следующие строки

 if (mysql_errno($this->conn) == 1213) {
  $this->bug_log(0,"Deadlock. SQL:".$this->sql);
}
  

где bug_log выполняется запись в файл.

Файл журнала ошибок не содержит ошибок взаимоблокировки, но /var/log/mysqld.log содержит несколько записей:

 111016  3:00:02 [ERROR] /usr/libexec/mysqld: Deadlock found when trying to get lock; try restarting transaction
111016  3:00:02 [ERROR] /usr/libexec/mysqld: Sort aborted
111016  3:00:02 [ERROR] /usr/libexec/mysqld: Deadlock found when trying to get lock; try restarting transaction
111016  3:00:02 [ERROR] /usr/libexec/mysqld: Sort aborted
111016  3:00:02 [ERROR] /usr/libexec/mysqld: Deadlock found when trying to get lock; try restarting transaction
111016  3:00:02 [ERROR] /usr/libexec/mysqld: Sort aborted
  

Как я могу отследить это?

Ответ №1:

Обновление с предложением WHERE, которое не является уникальным столбцом, приведет к взаимоблокировке, если другая транзакция ожидает завершения текущей транзакции. Вот быстрый тест:

 CREATE TABLE test (pk int PRIMARY KEY, a int);
INSERT INTO test VALUES (0, 0);
INSERT INTO test VALUES (1, 0);
  

Сеанс 1

 BEGIN;
SELECT a FROM test WHERE pk=0 FOR UPDATE;
  

Сессия 2

 BEGIN;
SELECT a FROM test WHERE pk=0 FOR UPDATE;
  

(Сеанс 2 теперь заблокирован)

Сеанс 1

 UPDATE test SET a=1 WHERE a>0;
  

В сеансе 2 мы получаем сообщение об ошибке

 ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
  

Если в предложении WHERE обновления мы используем только столбец pk, ошибка не возникает.

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

1. Что значит «использовать только столбец pk»? Это то, что вы делаете в своем примере, не так ли?

2. нет — в предложении WHERE обновления у меня есть «a> 0». Если я напишу там «pk = 0» (или что-нибудь, что использует только уникальные столбцы), я не получу сообщение об ошибке.

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

Ответ №2:

Я видел, как это происходило при одном или нескольких из следующих условий:

  1. Объединение одной и той же таблицы несколько раз в запросе (САМОСОЕДИНЕНИЕ)
  2. При использовании транзакций, содержащих запросы, которые одновременно обрабатывают одну и ту же таблицу несколькими способами
  3. При использовании транзакций и использовании той же таблицы, что и САМОСОЕДИНЕНИЕ или подзапрос

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

http://en.wikipedia.org/wiki/Deadlock

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

1. У меня есть вложенный запрос, но не для self. Как может быть, что это вызывает взаимоблокировку каждый раз?

2. Вы используете транзакции? Это также может привести к тому, что две транзакции работают с одной и той же таблицей, но с разными ключевыми словами. Например UPDATE TABLE ... WHERE group_id=X AND user_id=Y , и UPDATE TABLE ... WHERE user_id=Y AND group_id=X предполагая, что это разные ключи. Вы можете видеть, что если бы они выполнялись одновременно, они заблокировали бы другой индекс для возврата другого запроса, что привело бы к взаимоблокировке. Я бы проверил ваши запросы и убедился, что они записаны в том же порядке при работе с любыми ИНДЕКСАМИ.

3. может быть, но как мне найти другой запрос? В настоящее время я отслеживал этот запрос на предмет взаимоблокировки: UPDATE players SET chatban = chatban - 1 WHERE recent=1 and chatban > 0 как это может быть?

4. Найдите все остальные запросы с помощью проигрывателей и сравните запросы. Возможно, вы выбираете тот, ГДЕ chatban> 0 И recent= 1, что может вызвать это.