как решить ошибку «соединение все еще ожидает результата» с помощью em_mysql2

Я использую activerecord с em_mysql2 под Goliath (eventmachine). Самое странное происходит с моей моделью пользователя. Когда я делаю POST для /users в первый раз, все работает, как и ожидалось. Когда я делаю второй POST, я получаю сообщение об ошибке.

Mysql2::Error: This connection is still waiting for a result, try again once you have the result: INSERT INTO `users` (... and so on ...)

Этого не происходит ни с одной из моих моделей или маршрутов. Я бы предположил, что если соединение с БД находится в испорченном состоянии, я увижу ту же ошибку в других запросах, но нет - все остальные запросы на обновление БД и запросы GET работают нормально.

Кто-нибудь понимает, как это могло случиться только для моей модели Users и только для действия User.save? Сохраняет ли активная запись какое-то соединение с БД, которое она использовала для выполнения Model.save, и повторно использует его?

ИЗМЕНИТЬ:

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

Мое решение:

Оказывается, эта ошибка могла возникнуть только в том случае, когда ответ от Mongo вернулся раньше, чем ответ от MySQL, что привело к тому, что ответ MySQL был получен другим волокном, а не тем, который сделал запрос. Поскольку реализация волокна MySQL2, которую я использовал, использовала objectID волокна для управления соединениями, это, похоже, вызвало проблему.

Общий пул соединений в ActiveRecord + MySql2 + Fibers + Goliath не был полностью поддерживаемой конфигурацией. (Хотя с тех пор может быть некоторый прогресс)


person radixhound    schedule 26.05.2011    source источник


Ответы (1)


Используйте пул соединений, который поставляется с em-synchrony. Использование только одного соединения здесь не работает, потому что запросы приходят от Голиафа, в то время как запрос MySQL все еще ожидает результата, поскольку вы не можете иметь несколько активных запросов на одном соединении.

Вместо этого оберните соединение следующим образом:

db = EventMachine::Synchrony::ConnectionPool.new(size: 2) do
  Mysql2::EM::Client.new
end

Пул гарантирует, что запросы ждут, пока соединение не станет доступным, если все соединения используются.

Однако размер пула соединений необходимо настроить в зависимости от того, что может обрабатывать ваша база данных, и ожидаемого объема трафика. Я начал с чего-то около 5-10, но это была услуга с относительно низким трафиком, по крайней мере, в начале. Это заставило наши проблемы со связью уйти.

person roidrage    schedule 06.11.2011
comment
Спасибо! Как правило, это разумный ответ на вопрос. К сожалению, я не могу проверить его правильность в настоящее время, так как я перешел в другой проект. Если кто-то еще может подтвердить, я бы с удовольствием принял ответ.. О! Вы используете АктивРекорд? - person radixhound; 16.11.2011
comment
Нет, не через ActiveRecord, а через Sequel. Там довольно похожая история, поэтому я подозреваю, что решение такое же. - person roidrage; 16.11.2011
comment
Я собираюсь принять этот ответ, так как он соответствует правильным направлениям. Я делал какую-то ошибку с волокнами запроса и пулом соединений, несмотря ни на что. :-) - person radixhound; 21.07.2012