-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cache issues #148
base: master
Are you sure you want to change the base?
Cache issues #148
Conversation
…xir-ecto#146)"" This reverts commit 919eabe.
Yeah, I think we need to wait for more general feedback before we can merge it, for sure! |
I looked into this more and did a bunch of testing and feel like I know what's going on. It looks like the MyXQL cache and the Ecto cache are becoming out of sync. I'll give you my spiel in 2 parts:
Based on what I'm going to say below, I believe this PR solves the issue. But of course you guys should do whatever you feel is best. The main culprits are:
Here is an example sequence that might happen when the same query is called concurrently before it has been cached in Ecto:
I ran the test below on 0.6.0 and printed out the Ecto/MyXQL refs when
If I run the same test on the changes in this PR, the Postgrex compares by ref and gets around it by updating the Ecto cache when the ref changes (https://github.com/elixir-ecto/ecto_sql/blob/master/lib/ecto/adapters/postgres/connection.ex#L101). But when I made MyXQL update the Ecto cache and ran the test, it seems like if the requests come too fast without a lull you can be perpetually out of sync. This can happen if one of the processes doesn't get to update the MyXQL cache and the Ecto cache before another execution begins:
If I run this modified test where there is a lull before the last query I get a cache hit:
If you made it through all this, thank you for listening :) |
Thank you @greg-rychlewski, i think the analysis is on point. I am not sure what is the solution though. We can probably keep one of the two commits, but I will ship 0.6.1 first without them to have a more stable base. |
We had a problem "ER_MAX_PREPARED_STMT_COUNT_REACHED" with code like this:
but when I changed the code to:
The problem went away.. This was on MySQL 5.6.24-72.2-log |
If you guys still want to keep the cache changes from the 2 reverted commits, this branch could be tested by the affected people. Though if you'd rather just get rid of them I completely understand. The first 2 commits here are the revert of the reverts and the last is the fix.
Since the test suite passes and I can't replicate the issues locally, I really feel like it's a multi-node setup issue. To summarize from #147:In multi-node setups prepared statements with the same name can be saved with different refs. If it was prepared on one node then executed on another it will be re-prepared and the next time it's executed on the original node, the refs won't match and it will be re-prepared again.Before the cache change commit, executions would check for the name and not the ref. So each node would only be able to re-prepare an existing statement once.Though there are still some complications with multi-node set-ups for re-preparing statements with the same name but a different query. But that happens with or without the reverted commits.Edit: actually thinking more about the multi-node setup. I think it's important for cache names too be able to be re-prepared. Say you have 2 nodes both with the same prepared query cached on them. Then this sequence happens:1. Close the prepared statement on node 12. Re-prepare a new statement with the same name on node 2. It's still in the cache so the old one will be picked up and returned.
So always closing the old statements on re-prepare circumvents that issue.^ don't believe this is correct anymore. i gave a detailed comment below of what i believe the issue is, with tests