oracle / python-oracledb

Python driver for Oracle Database conforming to the Python DB API 2.0 specification. This is the renamed, new major release of cx_Oracle

Home Page:https://oracle.github.io/python-oracledb

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Concurrent open of connections don't work on 2.2.0 and 2.2.1 also (operation takes forever)

golubovai opened this issue · comments

  1. What versions are you using?

Oracle Database 19c

platform.platform: Windows-10-10.0.19045-SP0
sys.maxsize > 2**32: True
platform.python_version: 3.12.3

oracledb.version: 2.2.0

  1. Is it an error or a hang or a crash?
    It is a hang.

  2. What error(s) or behavior you are seeing?

If many connections open semultaneously then await on AsyncConnection freezes forever.

  1. Does your application call init_oracle_client()?
    No, it's Thin mode.
  1. Include a runnable Python script that shows the problem.
import oracledb
import asyncio

oracledb.defaults.config_dir = ' '
u = ' '
p = ' '

async def c(u, p, dsn):
    print('start')
    connection = await oracledb.connect_async(user=u,
                                              password=p,
                                              dsn=dsn)
    print('end')


async def main():
    asyncio.create_task(c(u, p, ' '))
    asyncio.create_task(c(u, p, ' '))
    await asyncio.sleep(3)

if __name__ ==  '__main__':
    asyncio.run(main())

Addition of Async.Lock synchronization solves the problem.

import oracledb
import asyncio

oracledb.defaults.config_dir = ' '
u = ' '
p = ' '

async def c(u, p, dsn, l):
    print('start')
    async with l:
        connection = await oracledb.connect_async(user=u,
                                                  password=p,
                                                  dsn=dsn)
    print('end')


async def main():
    l = asyncio.Lock()
    asyncio.create_task(c(u, p, ' ', l))
    asyncio.create_task(c(u, p, ' ', l))
    await asyncio.sleep(3)

if __name__ ==  '__main__':
    asyncio.run(main())

Thanks for the logging the issue.

I have pushed a patch that corrects this issue. If you are able to build from source you can verify that it works for you, too.

I can confirm that the error has been fixed. The test case works and the complex application also works.

@golubovai (and others) we'd love to get feedback on the asyncio support and understand what it lets you do that you couldn't before. Drop us a line!

just ran into to the same issue after switching to connect_async, built from source, works as expected, no hangups on await connect_async. But... I can't (ideally) build from source/vendor on production servers... would it be possible to include this in next release? Would be greatly appreciated!

@cjbj, my use case for this is as follows:

  • Automating a password change procedure across 20+ Oracle PeopleSoft environments & minimizing the time it takes
    • There is a lot of IO-bound tasks like shutting down and restarting all the domains, data-mover stuff, etc.
    • In between shutdown/restart, I need to run some SQL to affect the password change
    • My idea is to async/await everything IO-bound that I can, including database calls

real metrics: running a single update DML SQL sequentially across 20 environments takes ~8s with hot cache, while async version takes only ~0.7s.

would it be possible to include this in next release? Would be greatly appreciated!

Yes, it will be included in the upcoming release, which should be fairly soon!

This issue was corrected in version 2.3.0, which was just released.