При решении проблем, возникающих при рассылке сообщений о запланированных задачах на работе, при поиске и решении проблем, собирайте и систематизируйте соответствующие блоги о проблемах и записывайте их здесь, чтобы в будущем можно было столкнуться с теми же проблемами для удобства.
сценарий проблемы
Сценарий возникновения проблемы:
- Когда очередь сообщений обрабатывает сообщения, операции вставки и обновления выполняются с одними и теми же данными в одной и той же транзакции;
- Несколько серверов работают с одной и той же базой данных;
- Мгновенный феномен высокого параллелизма;
Данные часто автоматически откатываются после обновления или добавления данных, общий отчет операций с таблицейLock wait timeout exceeded
и долгое время нет ответа
Анализ проблемы
Анализ причин
MySql Lock wait timeout exceeded
Я полагаю, что все знакомы с этой проблемой, но многие люди не очень понимают ее причину и способы ее решения. Во многих случаях поиск и устранение проблемы остается на усмотрение администратора баз данных. Далее мы сосредоточимся на этой проблеме.
Существует множество ситуаций, в которых Mysql вызывает блокировки, вот некоторые из них:
- Если операция DML выполняется без фиксации, операция удаления заблокирует таблицу.
- Вставляйте и обновляйте одни и те же данные в одной и той же транзакции.
- Неправильно спроектированные индексы таблиц приводят к взаимоблокировкам в базе данных.
- Длинные транзакции, блокировка DDL, а затем блокировка всех последующих операций над той же таблицей.
Но разница в томLock wait timeout exceeded
иDead Lock
это не то же самое.
-
Lock wait timeout exceeded
: транзакция после подтверждения ожидает, пока ранее обработанная транзакция освободит блокировку, но когда ожидание превысит время ожидания блокировки mysql, будет возбуждено это исключение. -
Dead Lock
: две транзакции ждут друг друга, чтобы снять блокировку одного и того же ресурса, что приводит к бесконечному циклу, который вызовет это исключение.
Еще одна вещь, которую следует отметить, это то, чтоinnodb_lock_wait_timeout
иlock_wait_timeout
Тоже разные.
-
innodb_lock_wait_timeout
: время ожидания для блокировок на уровне строк операций innodb dml. -
lock_wait_timeout
: Время ожидания операции блокировки структуры данных ddl.
Итак, как проверить конкретное значение innodb_lock_wait_timeout:
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout'
Как изменить значение тайм-аута ожидания блокировки внутреннего узла, объем изменения параметра включает сеанс и глобальный, и поддерживает динамическое изменение, есть два способа изменения:
метод первый:
Измените следующим утверждением
set innodb_lock_wait_timeout=100;
set global innodb_lock_wait_timeout=100;
ps Обратите внимание, что модификация global не влияет на текущий поток и вступает в силу только при установлении нового соединения.
Способ второй:
Изменить файл параметров/etc/my.cnf
innodb_lock_wait_timeout = 50
ps. innodb_lock_wait_timeout
Относится к максимальному времени ожидания транзакции для получения ресурсов.Если ресурс не будет выделен по истечении этого времени, он вернет сбой приложения, когда ожидание блокировки превысит установленное время, будет сообщено о следующей ошибке;ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
. Единицей времени его параметров являются секунды, минимум может быть установлен на 1 с (как правило, не так уж и мало), максимум может быть установлен на 1073741824 секунды, значение по умолчанию 50 с во время установки (настройка параметра по умолчанию).
Сводка причин
- В случае высокого параллелизма транзакции Spring вызывают взаимоблокировку базы данных, а последующие операции завершаются тайм-аутом и вызывают исключения.
- База данных Mysql принимает режим InnoDB. Параметр по умолчанию: innodb_lock_wait_timeout устанавливает время ожидания блокировки на 50 с. Как только блокировка базы данных превысит это время, будет сообщено об ошибке.
Решение
- Экстренный метод:
show full processlist;
kill
Отбросьте рассматриваемый процесс.ps.Иногда через processlist невозможно увидеть, где находится ожидающая блокировка.Когда обе транзакции находятся в стадии фиксации, это не может быть отражено в processlist. - Радикальный метод:
select * from information_schema.innodb_trx;
Посмотрите, какие транзакции занимают ресурсы таблицы.ps. С помощью этого метода вам нужно иметь некоторое представление о innodb, чтобы иметь дело с - Увеличьте время ожидания блокировки, то есть увеличьте значение параметра следующего элемента конфигурации, единица измерения – секунда (с)
innodb_lock_wait_timeout=500
- Оптимизируйте хранимые процедуры и транзакции, чтобы избежать длительного ожидания
Звучит просто, найти и убить его, но на самом деле это не так просто, как кажется. Когда возникает проблема, нам нужно проанализировать причину проблемы и найти бизнес-код через причину. Могут быть проблемы в некоторых местах, чтобы избежать проблем в будущем Столкнулся с той же проблемой.
Расширенная информация
Справочная информация
- Время ожидания блокировки истекло. Это вызвано тем, что текущая транзакция ожидает освобождения ресурсов блокировки другими транзакциями. Вы можете найти таблицы и операторы, конкурирующие за ресурсы блокировки, оптимизировать SQL, создать индексы и т. д. Если это все еще не работает, вы можете соответствующим образом уменьшить количество одновременных потоков.
- Истечение времени ожидания транзакции во время ожидания блокировки таблицы Предполагается, что таблица заблокирована другим процессом и не была освобождена. Вы можете использовать SHOW INNODB STATUS/G;, чтобы увидеть ситуацию с блокировкой.
- Найдите решение и добавьте: TransactionDeadLockDetectionTimeOut=10000 (установлено на 10 секунд) по умолчанию 1200 (1,2 секунды)
- InnoDB автоматически обнаружит взаимоблокировку и откатится назад или завершит ситуацию взаимоблокировки.
InnoDB automatically detects transaction deadlocks and rolls back a transaction or transactions to break the deadlock. InnoDB tries to pick small transactions to roll back, where the size of a transaction is determined by the number of rows inserted, updated, or deleted.
Если параметр innodb_table_locks=1 и autocommit=0, InnoDB будет обращать внимание на взаимоблокировки таблиц и блокировки на уровне строк на уровне MySQL. Кроме того, InnoDB не обнаруживает взаимоблокировки с помощью команды MySQL Lock Tables и других механизмов хранения. Вы должны установить innodb_lock_wait_timeout, чтобы исправить эту ситуацию. innodb_lock_wait_timeout — это тайм-аут для Innodb, чтобы отказаться от блокировок на уровне строк.
Объяснение таблиц Innodb_*
Mysql
изInnoDB
Механизм хранения поддерживает транзакции, и транзакция не активируется после ее открытия.Commit
. В результате ресурс занят надолго.При вытеснении ресурса другими транзакциями вытеснение не выполняется из-за блокировки предыдущей транзакции! таким образом появляютсяLock wait timeout exceeded
Следующие таблицы представляют собой таблицы информации о транзакциях и блокировках innodb.Понимание этих таблиц может помочь вам обнаружить проблему.
-
innodb_trx
## Все текущие транзакции -
innodb_locks
## Текущая блокировка -
innodb_lock_waits
## Соответствие ожидания блокировки
следующая параinnodb_trx
Каждое поле таблицы поясняется:
trx_id:事务ID。
trx_state:事务状态,有以下几种状态:RUNNING、LOCK WAIT、ROLLING BACK 和 COMMITTING。
trx_started:事务开始时间。
trx_requested_lock_id:事务当前正在等待锁的标识,可以和 INNODB_LOCKS 表 JOIN 以得到更多详细信息。
trx_wait_started:事务开始等待的时间。
trx_weight:事务的权重。
trx_mysql_thread_id:事务线程 ID,可以和 PROCESSLIST 表 JOIN。
trx_query:事务正在执行的 SQL 语句。
trx_operation_state:事务当前操作状态。
trx_tables_in_use:当前事务执行的 SQL 中使用的表的个数。
trx_tables_locked:当前执行 SQL 的行锁数量。
trx_lock_structs:事务保留的锁数量。
trx_lock_memory_bytes:事务锁住的内存大小,单位为 BYTES。
trx_rows_locked:事务锁住的记录数。包含标记为 DELETED,并且已经保存到磁盘但对事务不可见的行。
trx_rows_modified:事务更改的行数。
trx_concurrency_tickets:事务并发票数。
trx_isolation_level:当前事务的隔离级别。
trx_unique_checks:是否打开唯一性检查的标识。
trx_foreign_key_checks:是否打开外键检查的标识。
trx_last_foreign_key_error:最后一次的外键错误信息。
trx_adaptive_hash_latched:自适应散列索引是否被当前事务锁住的标识。
trx_adaptive_hash_timeout:是否立刻放弃为自适应散列索引搜索 LATCH 的标识。
следующая параinnodb_locks
Каждое поле таблицы поясняется:
lock_id:锁 ID。
lock_trx_id:拥有锁的事务 ID。可以和 INNODB_TRX 表 JOIN 得到事务的详细信息。
lock_mode:锁的模式。有如下锁类型:行级锁包括:S、X、IS、IX,分别代表:共享锁、排它锁、意向共享锁、意向排它锁。表级锁包括:S_GAP、X_GAP、IS_GAP、IX_GAP 和 AUTO_INC,分别代表共享间隙锁、排它间隙锁、意向共享间隙锁、意向排它间隙锁和自动递增锁。
lock_type:锁的类型。RECORD 代表行级锁,TABLE 代表表级锁。
lock_table:被锁定的或者包含锁定记录的表的名称。
lock_index:当 LOCK_TYPE=’RECORD’ 时,表示索引的名称;否则为 NULL。
lock_space:当 LOCK_TYPE=’RECORD’ 时,表示锁定行的表空间 ID;否则为 NULL。
lock_page:当 LOCK_TYPE=’RECORD’ 时,表示锁定行的页号;否则为 NULL。
lock_rec:当 LOCK_TYPE=’RECORD’ 时,表示一堆页面中锁定行的数量,亦即被锁定的记录号;否则为 NULL。
lock_data:当 LOCK_TYPE=’RECORD’ 时,表示锁定行的主键;否则为NULL。
следующая параinnodb_lock_waits
Каждое поле таблицы поясняется:
requesting_trx_id:请求事务的 ID。
requested_lock_id:事务所等待的锁定的 ID。可以和 INNODB_LOCKS 表 JOIN。
blocking_trx_id:阻塞事务的 ID。
blocking_lock_id:某一事务的锁的 ID,该事务阻塞了另一事务的运行。可以和 INNODB_LOCKS 表 JOIN。
Шаги обработки ожидания блокировки
- Просмотр таблицы innodb_lock_waits напрямую
SELECT * FROM innodb_lock_waits;
- Таблица innodb_locks объединяется с таблицей innodb_lock_waits:
SELECT * FROM innodb_locks WHERE lock_trx_id IN (SELECT blocking_trx_id FROM innodb_lock_waits);
- Таблица innodb_locks ПРИСОЕДИНЯЙТЕСЬ к таблице innodb_lock_waits:
SELECT innodb_locks.* FROM innodb_locks JOIN innodb_lock_waits ON (innodb_locks.lock_trx_id = innodb_lock_waits.blocking_trx_id);
- Запросите таблицу innodb_trx:
SELECT trx_id, trx_requested_lock_id, trx_mysql_thread_id, trx_query FROM innodb_trx WHERE trx_state = 'LOCK WAIT';
- trx_mysql_thread_id убивает идентификатор потока транзакции
SHOW ENGINE INNODB STATUS ;
SHOW PROCESSLIST ;
Имея соответствующую информацию, полученную с помощью описанного выше метода, мы можем получить идентификатор потока, ожидающего блокировки, а затем отключить его. KILL убивает поток, ожидающий блокировки.
kill ID;