как решить 'соединение все еще ждет результата' ошибка с em_mysql2 - PullRequest
5 голосов
/ 27 мая 2011

Я использую activerecord с em_mysql2 под Goliath (eventmachine). Самое странное происходит с моей моделью User. Когда я делаю 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 не был полностью поддерживаемой конфигурацией. (Хотя с того времени может быть достигнут некоторый прогресс)

1 Ответ

0 голосов
/ 07 ноября 2011

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

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

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

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

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

...