如何解决“连接仍在等待结果” em_mysql2 错误

发布于 2024-11-10 10:14:40 字数 879 浏览 12 评论 0原文

我在 Goliath (eventmachine) 下将 activerecord 与 em_mysql2 一起使用。最奇怪的事情发生在我的用户模型上。当我第一次向 /users 发送 POST 时,一切正常,按预期查找。当我执行第二次 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 操作上? Active Record 是否以某种方式存储用于执行 Model.save 并重新使用它的数据库连接?

编辑:

当我写这个问题时,我不知何故没有提到我正在使用 ActiveRecord 作为 ORM。我也没有提到我正在异步向 Mongo 数据库发送请求以获取用户身份验证信息。

我的解决方案:

事实证明,只有当 Mongo 的响应早于 MySQL 的响应返回时,才会发生此错误,这导致 MySQL 响应被不同的 Fiber 拾取提出请求的人。由于我使用的 MySQL2 光纤实现使用光纤的 objectID 来管理连接,这似乎导致了问题。

ActiveRecord + MySql2 + Fibers + Goliath 中的总体连接池不是完全受支持的配置。 (不过从那时起可能会有一些进展)

I'm using activerecord with em_mysql2 under Goliath (eventmachine). The oddest thing is happening with my User model. When I do a POST to /users the first time, it all works just find as expected. When I do a second POST I get an error.

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

This doesn't happen for any other of my models or routes. I would assume that if the db connection is in a messed up state that I would see the same error on other requests but nope - all the other DB update and GET requests seem to work just fine.

Does anyone understand how it is that this could only happen for my Users model and only for a User.save action? Does active record somehow store the DB connection that it used for doing a Model.save and re-use it?

EDIT:

I somehow failed to mention when I wrote this question that I was using ActiveRecord as the ORM. I also failed to mention that I was asynchronously sending a request to a Mongo database to fetch the user authentication information.

My solution:

It turns out that the only time this error would occur was when the response from Mongo came back before the response from MySQL, which caused the MySQL response to be picked up by a different Fiber than the one that made the request. Since the MySQL2 fiber implementation I was using used the objectID of the fiber to manage the connections, that seems to have caused the issue.

Overall connection pooling in ActiveRecord + MySql2 + Fibers + Goliath wasn't a fully supported config. (There may be some progress since that time though)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜唯美灬不弃 2024-11-17 10:14:40

使用连接池,它带有em-synchrony。此处仅使用一个连接会失败,因为请求来自 Goliath,而 MySQL 查询仍在等待结果,因为单个连接上不能有多个活动查询。

像这样包装连接:

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

池确保请求等待,直到连接可用(如果所有连接都在使用中)。

不过,连接池的大小需要调整,具体取决于您的数据库可以处理的内容以及您期望的流量。我一开始提供了 5-10 左右的服务,但这是一个相对较低的流量服务,至少在开始时是这样。这让我们的联系问题消失了。

Use a connection pool, which comes with em-synchrony. Using only one connection fails here because requests come in from Goliath while a MySQL query is still waiting for a result, as you can't have multiple active queries on a single connection.

Wrap the connection like this instead:

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

The pool makes sure that requests wait until a connection becomes available, should all connections be in use.

The size of the connection pool needs to be tuned though, depending on what your database can handle and how much traffic you're expecting. I started out with something around 5-10 but it was a relatively low traffic service, at least in the beginning. That made our connection woes go away.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文