-
Notifications
You must be signed in to change notification settings - Fork 86
ORA-22922 in async LOB reading from cursor #500
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 tried your test with and without the type handler and did not have any difficulties. This was on Linux with a 23ai database. I can ask internally for someone to try with 19c on Windows. Note that python-oracledb does have the |
I have tested on two other instances of Oracle 19 and on one instance of Oracle 21, and I reproduced the error in all my tests. I noticed that the count of successfully read rows was different, but the fetch was terminated with ORA-22922 anyway. Did you run the test-case with 25 rows in dataset or the tests with both variants (25 and 1000 rows) pass on Oracle 23? |
I ran both scenarios with 23ai and was unable to replicate. Someone else internally ran with 19c and was able to replicate. I will do some more investigation. If you are able to confirm that 23ai works for you, that would be appreciated. |
Unfortunately, I don’t have an Oracle 23 instance available to reproduce the issue. |
I was able to get access to a 19c database myself and can confirm the problem exists there. The workaround, however, is very straightforward: oracledb.defaults.fetch_lobs = False This also dramatically increases the performance! I suspect something to do with lifetime of the LOB -- since asyncio handles such things considerably differently -- but I will look into it further. I would strongly recommend avoiding its use even if this problem is resolved, however! |
I discovered the source of the issue and why 23ai database succeeds whereas 19c database fails. Responses from the database are sent in packets of SDU size (default is 8,192 bytes). If a response requires more than one packet the client does not know when the response is complete except by parsing the response. For synchronous mode this is not a problem as when the end of a packet is reached without receiving the entire response the client waits until the next packet arrives and continues parsing. For asynchronous mode packets are received asynchronously and a parse is attempted. If not all of the packets have been received, the attempt is discarded and another attempt is made when more packets have been received. (If you're wondering why the parsing functions are not asynchronous themselves, that is explained by the fact that database responses may consist of many thousands of component parts, each of which may be split across a packet boundary and using asynchronous functions would dramatically reduce the performance of the driver). With Oracle Database 23ai, the database sends a flag with each packet indicating if this packet is the final packet in the response. The asynchronous client is then able to make use of that and avoid the reparsing. The logic that currently runs for reparsing is creating the LOB objects and then destroying them during the subsequent reparse needed. If you ensure that the response fits within a single packet the "problem" goes away (in your scenario, setting arraysize to 10 does this). TLDR; I hope to have a patch for this issue shortly. Nevertheless, avoid LOBS for improved performance anyway! :-) |
The real summary is that this is all more efficient with Oracle Database 23ai, so you should looking at upgrading when possible! |
I have pushed a patch that should correct this issue and have initated a build from which you can download pre-built development wheels once it completes. You can also build from source if you prefer. If you can test your scenario and confirm the patch works as expected, that would be appreciated! |
Uh oh!
There was an error while loading. Please reload this page.
What versions are you using?
Python 3.9.13 (Windows, Oracle Linux 8)
Database: Oracle 19c
oracledb: 3.1.0, 3.1.1
Is it an error or a hang or a crash?
DatabaseError with ORA-22922
What error(s) or behavior you are seeing?
I have observed the error "ORA-22922: nonexistent LOB value" after reading around 100 LOB objects. If lobAutoload is configured (refCursor.outputtypehandler = _connection_lobautoload_handler) I fetched the async cursor well.
I noticed that the issue is present only for the async version in oracledb module, sync version works well, my old code based on cx_Oracle + cx_Oracle_async also works well with this case.
Does your application call init_oracle_client()?
no
Include a runnable Python script that shows the problem.
The text was updated successfully, but these errors were encountered: