Почему SELECT ожидает блокировки? - PullRequest
1 голос
/ 18 марта 2019

В моем приложении проблема заключается в том, что иногда операторы SELECT сталкиваются с исключением java.sql.SQLException: Lock wait timeout exceeded; try restarting transaction. К сожалению, я не могу создать пример, так как обстоятельства очень сложные. Так что вопрос касается общего понимания.

Немного справочной информации: я использую MySQL (InnoDB) с уровнем изоляции READ_COMMITED.

На самом деле я не понимаю, как SELECT может работать с тайм-аутом блокировки с этой настройкой. Я думал, что SELECT никогда не заблокируется, поскольку он просто вернет последнее зафиксированное состояние (управляемое MySQL). В любом случае, в зависимости от происходящего это кажется неправильным. Так как же это на самом деле?

Я уже читал это https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html, но это не дало мне понять. Нет SELECT ... FOR UPDATE или что-то подобное используется.

Ответы [ 2 ]

1 голос
/ 18 марта 2019

Чтобы ускорить запросы в БД, несколько транзакций могут быть выполнены одновременно.Например, если кто-то запускает запрос на выборку по таблице для заработной платы сотрудников компании (каждый сотрудник идентифицируется по идентификатору), а другой меняет фамилию того, кто, например, женился, вы можете выполнить оба запроса одновременновремя, потому что они не мешают.

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

Чтобы предотвратить непредвиденные результаты в транзакциях SQL, транзакции следуют за ACID-модель , что означает атомарность, согласованность, изоляцию и долговечность (дополнительную информацию читайте wikipedia ).

Допустим, транзакция 1 начинает что-то вычислять, а затем хочет записать результатыв таблицу А. Перед записью он блокирует все операторы SELECT в таблице А. В противном случае это будет противоречить требованию изоляции.Потому что если транзакция 2 начнется, пока 1 все еще пишет, результаты 2 зависят от того, куда 1 уже записана, а где нет.

Теперь она может даже создать dead-lock .Например, прежде чем транзакция 1 сможет записать последнее поле в таблице A, она все равно должна что-то записать в таблицу B, но транзакция 2 уже заблокировала таблицу B для безопасного чтения из нее после того, как она прочитала из A, и теперь у вас есть тупик.2 хочет прочитать из A, который заблокирован 1, поэтому он ждет 1, чтобы завершить, но 1 ждет 2, чтобы разблокировать таблицу B, чтобы завершить сам.

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

Так что это может быть чтение для вашего оператора select, чтобы получить превышение времени ожидания блокировки.

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

1 голос
/ 18 марта 2019

Вероятно, это связано с вашей базой данных.Обычно такого рода проблемы возникают с той стороны, а не со стороны программирования, которая к нему обращается. По моему опыту работы с базами данных, эти проблемы обычно связаны с этим.В конце концов, сторона программирования - это просто «иди и возьми это для меня в этом дБ».

Я нашел это без особых усилий.

Это в основном объясняет, что:

Lock wait timeout обычно происходит, когда транзакция ожидает строки (ей) данных для обновления, которые уже заблокированыпо какой-то другой транзакции.

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

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

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