Python使用cx_Oracle执行Oracle MERGE语句长时间无响应如何解决?
cx_Oracle执行MERGE语句无响应排查方案
1. 优先排查锁阻塞
绝大多数跨客户端执行SQL卡住的场景都是锁冲突导致:
- 用DBA权限账号登录Oracle执行以下SQL,查询是否存在阻塞会话:
SELECT s1.username || '@' || s1.machine || ' (SID=' || s1.sid || ') 阻塞 ' || s2.username || '@' || s2.machine || ' (SID=' || s2.sid || ')' AS block_relation FROM v$lock l1 JOIN v$session s1 ON l1.sid = s1.sid JOIN v$lock l2 ON l1.id1 = l2.id1 AND l1.id2 = l2.id2 JOIN v$session s2 ON l2.sid = s2.sid WHERE l1.block = 1 AND l2.request > 0;
- 如果查询到对应Python会话被阻塞,确认阻塞会话的操作是否可以终止,提交/回滚阻塞会话的事务,或者执行
ALTER SYSTEM KILL SESSION 'SID,SERIAL#'清理异常阻塞会话即可。
2. 验证执行计划一致性
不同客户端的会话参数差异可能导致执行计划不同,出现SQL Developer执行快、Python执行慢的情况:
- 先查询Python会话对应的SQL_ID:
SELECT sid, serial#, sql_id, status FROM v$session WHERE username = '你的数据库账号' AND program LIKE '%python%';
- 用SQL_ID查询实际执行计划:
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('替换为实际SQL_ID', 0, 'ALLSTATS LAST'));
- 和SQL Developer中执行MERGE的执行计划对比,若存在差异,先更新两张表的统计信息再重试:
EXEC DBMS_STATS.GATHER_TABLE_STATS('ASBODS_SDDM_SCHEMA', 'EULA_DATA'); EXEC DBMS_STATS.GATHER_TABLE_STATS('ASBODS_SDDM_SCHEMA', 'EULA_STG_DATA');
3. 大数据量分批优化
如果EULA_STG_DATA表数据量较大,全量MERGE本身就是长耗时操作:
- 先在Linux服务器上用sqlplus直接执行相同MERGE语句,确认是否是cx_Oracle层的问题
- 拆分MERGE逻辑,按
MASTER_METER_NBR范围、日期字段等维度拆分SQL,每次处理部分数据,避免单条SQL执行时间过长 - 可以给cx_Oracle连接添加超时配置(Oracle 18c及以上版本支持),避免进程无限挂起:
con = cx_Oracle.connect('username/pwd@server', encoding="UTF-8", nencoding="UTF-8") con.call_timeout = 300000 # 单位为毫秒,此处设置5分钟超时
4. 冗余代码优化
你当前代码的finally块中重复执行了con.commit(),属于冗余操作,虽然不影响执行逻辑,但建议删除,避免异常场景下提交脏数据。
内容的提问来源于stack exchange,提问作者William
相关产品推荐
相关产品推荐

