2016-05-30 4 views
1

У меня есть несколько таблиц InnoDB и скрипт, который запускает транзакцию. В рамках этой транзакции обновляются разные строки одной таблицы, другие строки будут вставлены в другую таблицу, и выполняется множество выборок. Это должно произойти надежно, поэтому я использую транзакцию по умолчанию с REPEATABLE READ как уровень изоляции. Эта транзакция может занять некоторое время.Как избежать блокировки выборок, если транзакция продолжается?

Теперь, когда другие скрипты (запросы веб-страниц) выполняются одновременно, некоторые из них выбирают в базе данных. К сожалению, эти выбирают до тех пор, пока транзакция не закончится, поскольку они читаются из тех же таблиц. Выбранными данными могут быть обновленные данные транзакции, но могут быть и другими данными.

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

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

Должен ли я

  • использование 'FOR UPDATE' или 'LOCK IN SHARE MODE' с выбирает в сделке?
  • использовать другой уровень изоляции?
  • положить чтение также в сделке?
  • сделать что-то другое?

Я думаю, что это очень распространенное требование, но пока я не нашел простой ответ.

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

+0

@iLikeMySql Что значит? Я просто вижу, что выбор за пределами транзакции ожидает завершения транзакции. В транзакции используются инструкции UPDATE, INSERT и SELECT. – robsch

ответ

0

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

Это не имеет ничего общего с действиями MySQL, я думаю. На самом деле это зависание запросов PHP. То есть, когда первый вызов PHP запустил длительную транзакцию, дальнейшие вызовы PHP на другие страницы повесили. И причина, по которой они повесили, заключалась в том, что сеанс был заблокирован по первому запросу! session_start() больше не работал. Просто, когда первый запрос завершен (или приурочен), дальнейшие запросы будут работать снова.

Поскольку вызов PHP с длинной транзакцией не нужно ничего записывать в сеанс, я просто закрываю сеанс с session_write_close() в этом вызове. Теперь дальнейшие запросы больше не зависают.

This был подсказкой для меня.

Вывод: выбор базы данных не был заблокирован.

Смежные вопросы