如何通过Python线程池结合cx_Oracle提速?会话池调用存储过程卡顿怎么办?
为什么线程池调用数据库存储过程没提速?
你遇到的问题核心原因在于数据库连接的线程安全性和复用方式:
- 当用
multiprocessing.dummy处理网络请求时,每个线程的IO操作(urlopen)是独立的,而且Python的GIL会在IO阻塞时释放,多个线程可以真正并行发起请求,所以能看到明显提速。 - 但你的数据库代码里,所有线程共用了同一个全局数据库连接。哪怕设置了
threaded=True,Oracle的单个连接在同一时间只能处理一个请求——多个线程会排队等待这个连接释放,本质还是串行执行,自然看不到提速效果。
优化方案:使用数据库会话池(SessionPool)
正确的做法是用Oracle官方提供的SessionPool管理多个数据库连接,让线程池里的每个线程都能获取独立连接并行执行存储过程。针对你的代码,调整如下:
from multiprocessing.dummy import Pool as ThreadPool import cx_Oracle as ora import configparser config = configparser.ConfigParser() config.read('configuration.ini') conf = config['sample_config'] dsn = ora.makedsn(conf['ip'], conf['port'], sid=conf['sid']) # 初始化会话池:连接数和线程池大小对应,threaded=True支持多线程 db_pool = ora.SessionPool( user=conf['user'], password=conf['password'], dsn=dsn, min=1, max=4, increment=1, threaded=True ) def test_function(params): # 每个线程从会话池获取独立连接 conn = db_pool.acquire() try: cursor = conn.cursor() # 调用存储过程 cursor.callproc('Sample_PKG.my_procedure', keywordParameters=params) # 存储过程涉及DML操作时,必须手动提交事务 conn.commit() except Exception as e: # 异常时回滚事务,避免资源占用 conn.rollback() raise e finally: # 必须关闭cursor,并将连接释放回会话池 cursor.close() db_pool.release(conn) dicts = [{'a': 'b'}, {'a': 'c'}] # 你的参数列表 pool = ThreadPool(4) pool.map(test_function, dicts) pool.close() pool.join() # 程序结束时关闭会话池 db_pool.close()
关于会话池调用存储过程卡顿的问题
你之前的测试代码卡顿,大概率是因为事务未正确处理或者资源未释放:
- 事务未提交/回滚:Oracle默认不会自动提交事务,如果存储过程包含插入、更新等DML操作,未提交的事务会一直占用连接资源,导致后续请求阻塞。
- 资源未正确释放:没有关闭cursor或者没有将连接释放回会话池,导致连接被占用,新请求无法获取连接而卡顿。
按照上面优化后的代码,在finally块里确保关闭cursor并释放连接,同时在成功时提交、异常时回滚,就能解决卡顿问题。另外,也可以检查下存储过程本身是否存在锁表、执行效率低的问题——不过你替换成select 1 from dual正常,说明核心问题还是代码层面的资源管理。
内容的提问来源于stack exchange,提问作者Greenev
相关产品推荐
相关产品推荐

