
当使用 cx_Oracle 的 executemany() 插入数据突然卡住(而 SQL Developer 中操作正常),极可能是目标表中存在未提交的行级锁,导致 Python 进程阻塞等待锁释放。
当使用 cx_oracle 的 `executemany()` 插入数据突然卡住(而 sql developer 中操作正常),极可能是目标表中存在未提交的行级锁,导致 python 进程阻塞等待锁释放。
在 Oracle 数据库中,DML 操作(如 INSERT、UPDATE、DELETE)会自动加行级锁,且该锁会持续到事务显式执行 COMMIT 或 ROLLBACK 为止。若你或其他人在 SQL Developer、另一个 Python 脚本或任何客户端中执行了修改同一张表(尤其是相同主键/唯一键值)的 DML 语句但未提交,后续的 executemany() 就会因等待锁而长时间挂起——表面看是“卡死”,实则是阻塞等待,而非程序崩溃或网络故障。
✅ 快速诊断与解决步骤:
-
检查活跃会话锁:在 SQL Developer 或其他具备 DBA 权限的工具中运行以下查询,定位阻塞源:
SELECT blocking_session, sid, serial#, username, osuser, machine, program, sql_id, event, blocking_session_status FROM v$session WHERE blocking_session IS NOT NULL OR sid IN ( SELECT blocking_session FROM v$session WHERE blocking_session IS NOT NULL );
-
立即释放锁(推荐优先尝试):
- 若确认是自己打开的 SQL Developer 窗口执行了未提交的 UPDATE/INSERT,请直接在该会话中执行:
COMMIT; -- 或 ROLLBACK; 若需撤销变更
- 执行后,原 Python 脚本通常会在数秒内继续执行并完成。
- 若确认是自己打开的 SQL Developer 窗口执行了未提交的 UPDATE/INSERT,请直接在该会话中执行:
-
强制清理(谨慎使用):
若无法定位或联系到持有锁的用户,且环境允许(如开发/测试库),可由 DBA 或授权用户终止对应会话:ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;
⚠️ 注意:务必确认 sid 和 serial# 对应的是闲置或可中断会话,避免影响生产任务。
? 预防性最佳实践:
- 在所有数据库交互脚本中,明确管理事务边界:
try: cursor.executemany(query, data) connection.commit() # 及时提交,释放锁 print("Data inserted successfully.") except cx_Oracle.DatabaseError as exc: error, = exc.args print(f"Oracle Error {error.code}: {error.message}") connection.rollback() # 关键!异常时回滚,避免残留锁 finally: cursor.close() connection.close() - 避免在交互式工具(如 SQL Developer)中长期保持未提交的 DML;养成“改完即提”习惯。
- 对大批量插入,考虑分批次提交(如每 1000 行 commit() 一次),平衡性能与锁持有时间。
总结:cx_Oracle 插入变慢并非驱动或代码缺陷,而是 Oracle 事务锁机制的典型表现。核心思路是——找锁、释锁、防锁。通过监控 v$session 定位源头,配合及时 COMMIT/ROLLBACK,即可高效恢复插入性能。











