Получение «Превышено время ожидания блокировки; попробуйте перезапустить транзакцию», даже если я не использую транзакцию - PullRequest
217 голосов
/ 29 апреля 2011

Я выполняю следующую инструкцию MySQL UPDATE:

mysql> update customer set account_import_id = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

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

В таблице 406 733 строки.

Ответы [ 17 ]

277 голосов
/ 12 августа 2014

Как принудительно разблокировать заблокированные таблицы в MySQL:

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

Это хакерское решение, и правильное решение - исправить приложение, вызвавшее блокировки. Однако, когда на кону доллары, быстрый удар заставит все двигаться снова.

1) Введите MySQL

mysql -u your_user -p

2) Посмотрим список заблокированных таблиц

mysql> show open tables where in_use>0;

3) Давайте посмотрим список текущих процессов, один из них блокирует ваши таблицы

mysql> show processlist;

4) Убить один из этих процессов

mysql> kill <put_process_id_here>;
181 голосов
/ 30 апреля 2011

Вы используете транзакцию; autocommit не отключает транзакции, он просто автоматически фиксирует их в конце оператора.

Происходит следующее: какой-то другой поток слишком долго удерживает блокировку записи (вы обновляете каждую запись в таблице!), И время вашего потока истекло.

Вы можете увидеть более подробную информацию о событии, выдав

SHOW ENGINE INNODB STATUS

после события (в редакторе sql). Идеально делать это на тихой тестовой машине.

86 голосов
/ 16 ноября 2012
mysql> set innodb_lock_wait_timeout=100

Query OK, 0 rows affected (0.02 sec)

mysql> show variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 100   |
+--------------------------+-------+

Теперь снова активируйте блокировку. У вас есть 100 секунд, чтобы выдать SHOW ENGINE INNODB STATUS\G в базу данных и посмотреть, какая другая транзакция блокирует вашу.

62 голосов
/ 06 марта 2013

Посмотрите, правильно ли настроена ваша база данных. Особенно изоляция транзакций. Не стоит увеличивать переменную innodb_lock_wait_timeout.

Проверьте уровень изоляции транзакции базы данных в mysql cli:

mysql> SELECT @@GLOBAL.transaction_isolation, @@transaction_isolation, @@session.transaction_isolation;
+-----------------------+-----------------+------------------------+
| @@GLOBAL.tx_isolation | @@tx_isolation  | @@session.tx_isolation |
+-----------------------+-----------------+------------------------+
| REPEATABLE-READ       | REPEATABLE-READ | REPEATABLE-READ        |
+-----------------------+-----------------+------------------------+
1 row in set (0.00 sec)

Вы можете получить улучшения, изменяя уровень изоляции, используя оракул, такой как READ COMMITTED, вместо REPEATABLE READ (InnoDB Defaults)

mysql> SET tx_isolation = 'READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL tx_isolation = 'READ-COMMITTED';
Query OK, 0 rows affected (0.00 sec)

mysql> 

Также попробуйте использовать SELECT FOR UPDATE только в случае необходимости.

16 голосов
/ 16 марта 2016

Ни одно из предложенных решений не сработало для меня, но это сработало.

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

SHOW PROCESSLIST;

Как только вы обнаружите процесс блокировки, найдите его id и выполните:

KILL {id};

Повторно запустите ваш начальный запрос.1010 *

12 голосов
/ 30 апреля 2011

100% с тем, что сказал MarkR.autocommit делает каждый оператор транзакцией одного оператора.

SHOW ENGINE INNODB STATUS должен дать вам некоторые подсказки относительно причины тупика.Внимательно посмотрите на свой медленный журнал запросов, чтобы увидеть, что еще запрашивает таблицу, и попробуйте удалить все, что делает полный просмотр таблицы.Блокировка на уровне строк работает хорошо, но не тогда, когда вы пытаетесь заблокировать все строки!

5 голосов
/ 29 апреля 2011

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

2 голосов
/ 29 июля 2015

Количество строк невелико ... Создайте индекс для account_import_id, если это не первичный ключ.

CREATE INDEX idx_customer_account_import_id ON customer (account_import_id);
1 голос
/ 23 января 2015

Убедитесь, что в таблицах базы данных используется механизм хранения InnoDB и уровень изоляции транзакций READ-COMMITTED.

Вы можете проверить это с помощью SELECT @@ GLOBAL.tx_isolation, @@ tx_isolation;на консоли mysql.

Если он не установлен как READ-COMMITTED, вы должны установить его.Перед установкой убедитесь, что у вас есть привилегии SUPER в mysql.

Вы можете получить помощь от http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html.

Установив это, я думаю, ваша проблема будет решена.


Возможно, вы также захотите убедиться, что вы не пытаетесь обновить это сразу в двух процессах.Пользователи (@tala) сталкивались с подобными сообщениями об ошибках в этом контексте, возможно, еще раз проверьте, что ...

0 голосов
/ 10 апреля 2019

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

Я отключил autocommit, а затем он работал, просто добавив COMMIT в конце предложения SQL. Насколько я понял, это освобождает буфер по битам вместо ожидания в конце команды.

Чтобы привести пример OP, это должно сработать:

mysql> set autocommit=0;

mysql> update customer set account_import_id = 1; commit;

Не забудьте снова активировать autocommit, если вы хотите оставить конфигурацию MySQL, как раньше.

mysql> set autocommit=1;

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