-
Notifications
You must be signed in to change notification settings - Fork 419
Cockroachdb unimplemented feature multiple active portals not supported #580
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
Comments
I have uploaded a minimal working example here: https://gist.github.com/nagylzs/acc716982f8a8213cbe5d6d6495e5387 |
Some more info: if I don't start a new transaction ( async with conn.transaction() ) then it works. |
Coud it be related to this issue from Cockroach cockroachdb/cockroach#42912? |
It could be. Then it would mean that fetchval or execute did not close the resultset before returning the result? (I'm guessing - these are the only two queries opened.) |
From my analysis, Cockroach is unable to implicitly close a result set (named also portal) in a transaction which it should do if it was respecting completely PSQL spec. As far as I understand, they are not willing to fix this anytime soon because it would require them to do a lot of refactoring and only a few clients are behaving like asyncpg. In this example:
I'm working on a fix (for asyncpg) |
@vaperce did you get a chance to patch asyncpg? |
Nope, didn't. Ended up this portal issue was not the only one with Cockroach, some fixes in asyncpg/introspection.py would have been required to make it fully working (not even sure it is possible), so I decided to stop the dev at this step. If you wanna continue it, please feel free to you use my work on the portals. |
Hi all, I work on cockroachdb. I tested with a bleeding edge version of cockroachdb (which will soon be released as v21.2-alpha). The issue reported in #580 (comment) no longer occurs. I think cockroachdb/cockroach#63677 might have improved the situation. Also, I ran the full asyncpg test suite against cockroachdb, and it went well:
The two failures are |
This is still an issue, tested with CockroachDB v21.2.5 and asyncpg 0.25.0 with a minimal test case:
Results in:
@rafiss anything you could think of to help this case? |
I have zeroed in on this to the fact that fetchrow/fetchval (and various other) functions set the row limit to 1 for these pgwire requests and CockroachDB handles it somehow incorrectly as setting the limit to 0 works around it completely without any visible issues and the queries will still only fetch a single result but the transaction will continue working. |
Hi, I'm also a maintainer for CockroachDB. The root cause of this is that Postgres permits leaving cursors open and beginning new cursors. CockroachDB does not. The problem here is that asyncpg doesn't explicitly close portals when it's done using them. The example code from @hifi is correct in Postgres, but it actually leads to cursor leakage: if you run this against Postgres, you won't get errors, but you will have leaked server-side cursors until you close your connection. This is bad for performance in Postgres, and just plain doesn't work in CockroachDB. I think the best solution would be for asyncpg to provide a cursor.close() method that permits explicit closure of cursors. A call like I believe this will improve performance in Postgres, and make the library compatible with CockroachDB. |
asyncpg uses an unnamed portal in
It doesn't, asyncpg closes prepared statements when the statement object is garbage collected. |
Thank you for the reply!
You're right, CockroachDB indeed doesn't do this properly. Thanks for calling that out, I missed that asyncpg uses the unnamed portal for this purpose. We will correct this error.
But what about cursors, which are connected to portals (different from prepared statements)? |
They also get closed on garbage collection. We can implement an explicit |
I could be missing something, but I was looking around at the code and I don't see where we ever invoke
I think that would be useful. It's good that they get closed when GC'd, but isn't it true then that the Postgres server will have to hold open the cursors for an arbitrary amount of time, depending on how the client happens to be behaving with respect to GC? I'm not familiar with how Python GC works, to be fair, but I would be nervous to tie server-side resources to client-side GC behavior. |
Hmm, you're right, this could be an issue. |
I believe since cockroachdb/cockroach#76792 (in v22.1.0), CockroachDB should implement that behavior. I'm not able to confirm at the moment. |
Actually I was mistaken above. However, I created cockroachdb/cockroach#83164, which should implement the correct unnamed portal behavior for the specific way that asyncpg uses them (sending a Prepare, then Describe, then Bind of an unnamed portal). A more general fix is complicated, but this one can at least be backported to existing CockroachDB versions. It still seems useful to implement the |
For the above code snippet by @hifi, one workaround that I noticed is that the error goes away by replace |
Example code:
The table_exists method looks like this:
This code is actually called from tornado.ioloop.IOLoop.current().run_sync so it is guaranteed that nothing else is running queries concurrently.
Here is the traceback that I'm getting:
The referenced issue tells that it is not possible to keep multiple queries open and fetch from them interleaved.
However, I'm not doing anything that should result in opening multiple queries and fetching from them that way. As far as I see, my code should not open a new query before closing the previous one.
I suspect that asyncpg itself forgot to close something in the background.
The text was updated successfully, but these errors were encountered: