В MySQL обнаружен тупик (InnoDB) - PullRequest
0 голосов
/ 13 ноября 2010

Я часто получаю следующую ошибку при выполнении определенного запроса в моей базе данных (все таблицы используют механизм хранения InnoDB): «Обнаружен тупик при попытке получить блокировку; попробуйте перезапустить транзакцию»запрос DELETE FROM sessions WHERE userid != 0 AND lastactivity < 1289594761 AND admin = 1 AND userid NOT IN (SELECT userid FROM users WHERE (userflags & 1048576))

Ошибки начали возникать, когда я добавил часть NOT IN в свой оператор WHERE.Почему это вызывает проблемы и что я могу сделать, чтобы предотвратить это?

Ответы [ 2 ]

2 голосов
/ 13 ноября 2010

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

Опция & на userflags делает подзапрос нерасширяемым. Слова-флажки обычно не являются хорошим дизайном схемы, поскольку они требуют вычислений, которые побеждают индексацию. Если вы часто выполняете битовое тестирование, лучше использовать отдельные столбцы с небольшими типами данных (например, TINYINT).

Если ваша схема работает так, как она выглядит, вы можете сделать это, используя простой JOIN, который обычно работает лучше, чем подзапросы:

DELETE sessions
FROM sessions
JOIN users ON users.userid=sessions.userid
WHERE sessions.lastactivity<1289594761 AND admin=1
AND (users.userflags&1048576)=0

(присоединяется к DELETE - расширение не-ANSI SQL в MySQL.)

2 голосов
/ 13 ноября 2010

Простым решением было бы разделить это на два последовательных запроса. То есть.,:

ВЫБЕРИТЕ ИДЕНТИФИКАТОР в #tmptable ОТ ГДЕ WHERE (userflags & 1048576);

УДАЛИТЬ ИЗ СЕССИЙ, ГДЕ ИДЕНТИФИКАТОР! = 0 И ЛАСТАКТИВНОСТЬ <1289594761 И ИДЕНТИФИКАТОР = 1 И ИДЕНТИФИКАТОР НЕ ВХОДИТ (выберите ИД пользователя из #tmptable); </p>

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

...