Исправление «Превышено время ожидания блокировки; попробуйте перезапустить транзакцию» для «зависшей» таблицы Mysql? - PullRequest
112 голосов
/ 04 мая 2010

Из сценария я тысячи раз отправлял запрос в мою локальную базу данных:

update some_table set some_column = some_value

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

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

Lock wait timeout exceeded; try restarting transaction

Это таблица innodb, поэтому застрявшая транзакция, вероятно, неявная. Как я могу исправить эту таблицу и удалить застрявшую транзакцию из нее?

Ответы [ 12 ]

128 голосов
/ 31 мая 2013

У меня была похожая проблема, и я решил ее, проверив работающие потоки. Чтобы увидеть запущенные потоки, используйте следующую команду в интерфейсе командной строки mysql:

SHOW PROCESSLIST;

Его также можно отправить из phpMyAdmin, если у вас нет доступа к интерфейсу командной строки mysql.
Это отобразит список потоков с соответствующими идентификаторами и временем выполнения, так что вы можете УБИТЬ потоки, выполнение которых занимает слишком много времени. В phpMyAdmin у вас будет кнопка для остановки потоков с помощью KILL, если вы используете интерфейс командной строки, просто используйте команду KILL, за которой следует идентификатор потока, как в следующем примере:

KILL 115;

Это прервет соединение для соответствующего потока.

41 голосов
/ 01 марта 2016

Вы можете проверить текущие транзакции с помощью

SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`

Ваша транзакция должна быть одной из первых, потому что она самая старая в списке. Теперь просто возьмите значение из trx_mysql_thread_id и отправьте ему команду KILL:

KILL 1234;

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

31 голосов
/ 10 августа 2014

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

Правда, вероятно, есть какой-то способ оптимизировать ваши запросы или вашу БД, но попробуйте эти 2 запросадля работы вокруг исправить.

Запустите это:

SET GLOBAL innodb_lock_wait_timeout = 5000; 

А затем это:

SET innodb_lock_wait_timeout = 5000; 
29 голосов
/ 14 ноября 2016

Проверка статуса InnoDB для блокировок

SHOW ENGINE InnoDB STATUS;

Проверка открытых таблиц MySQL

SHOW OPEN TABLES WHERE In_use > 0;

Проверка ожидающих транзакций InnoDB

SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`; 

Проверка зависимости блокировки - что блокирует, что

SELECT * FROM `information_schema`.`innodb_locks`;

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

Основная причина проблемы также может быть в вашем коде - пожалуйста, проверьте соответствующие функции, особенно для аннотаций, если вы используете JPA, например Hibernate.

Например, как описано здесь , неправильное использование следующей аннотации может вызвать блокировки в базе данных:

@Transactional(propagation = Propagation.REQUIRES_NEW) 
7 голосов
/ 04 марта 2013

Перезапустите MySQL, все работает нормально.

НО помните, что если такой запрос застрял, то где-то возникает проблема:

  • в вашем запросе (неуместный символ, декартово произведение, ...)
  • очень много записей для редактирования
  • сложные соединения или тесты (MD5, подстроки, LIKE %...% и т. Д.)
  • проблема структуры данных
  • модель внешнего ключа (блокировка цепи / петли)
  • неверно проиндексированные данные

Как сказал @syedrakib, он работает, но это не долговременное решение для производства.

Осторожно: перезапуск может повлиять на ваши данные в несогласованном состоянии.

Кроме того, вы можете проверить, как MySQL обрабатывает ваш запрос, с помощью ключевого слова EXPLAIN и посмотреть, возможно ли там что-то ускорить запрос (индексы, сложные тесты, ...).

5 голосов
/ 10 июня 2014

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

Решение: закройте соединение или установите AutoCommit (true) [в соответствии с вашим дизайном], чтобы снять блокировку.

3 голосов
/ 25 апреля 2012

Перейти к процессам в MySQL.

Итак, вы видите, что задание все еще работает.

Завершите определенный процесс или дождитесь его завершения.

1 голос
/ 05 апреля 2012

У меня была эта проблема при попытке удалить определенную группу записей (используя MS Access 2007 с подключением ODBC к MySQL на веб-сервере). Обычно я удаляю определенные записи из MySQL, а затем заменяю их обновленными (каскадное удаление нескольких связанных записей, это упрощает удаление всех связанных записей для удаления одной записи).

Я попытался выполнить операции, доступные в phpMyAdmin для таблицы (оптимизация, очистка и т. Д.), Но при попытке сбросить мне было необходимо разрешение RELOAD Поскольку моя база данных находится на веб-сервере, я не смог перезапустить базу данных. Восстановление из резервной копии не было возможным.

Я попытался выполнить запрос на удаление для этой группы записей в cPanel mySQL access в Интернете. Получил то же сообщение об ошибке.

Мое решение: я использовал бесплатный MySQL Query Browser от Sun (Oracle) (который я ранее установил на своем компьютере) и запустил там запрос на удаление. Это сработало сразу, проблема решена. Затем я смог снова выполнить эту функцию, используя скрипт Access, используя соединение ODBC Access to MySQL.

0 голосов
/ 09 апреля 2018

Исправлено, Убедитесь, что в запросе не указан несоответствующий тип данных. У меня была проблема, когда я пытался «данные агента браузера пользователя» в «VARCHAR (255)» и имел проблему с этой блокировкой, однако, когда я изменил ее на «TEXT (255)», он исправил ее. Так что скорее всего это неверное совпадение типа данных

0 голосов
/ 16 марта 2012

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

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