ORA-01013是客户端主动中断信号,非数据库错误;需从调用链下游向上游排查,重点检查setQueryTimeout()覆盖、ODBC启用查询超时、锁等待及连接池配置。

ORA-01013 不是数据库报错,而是客户端主动中断的信号 —— 排查必须从调用链下游往上游倒推,否则永远在猜。
Java应用里setQueryTimeout()设为0不等于禁用超时
很多人以为 statement.setQueryTimeout(0) 就万事大吉,但 Oracle JDBC 驱动(如 ojdbc8)默认行为是“用驱动内置超时”,而某些连接池(Druid、WebSphere、Hikari 的拦截器)会覆盖这个值。更关键的是:setQueryTimeout() 只作用于当前 CallableStatement 或 PreparedStatement 的 execute() 调用,对存储过程内部的 EXECUTE IMMEDIATE 动态 SQL 无效。
实操建议:
- 显式在 JDBC URL 中加参数:
jdbc:oracle:thin:@host:1521/orcl?oracle.jdbc.ReadTimeout=0&oracle.jdbc.SocketTimeout=0 - 若用 Spring Boot + Hikari,
spring.datasource.hikari.connection-timeout=0仅控制获取连接,不影响语句执行;真正要关语句超时,得在CallableStatement创建后立刻调用setQueryTimeout(0),且确认没被 Druid 的FilterChain拦截重写 - 检查是否用了
@Transactional(timeout = ...),JTA 容器(如 WebLogic)的全局事务超时会强制中断,和 JDBC 层无关
ODBC 数据源的Enable Query Timeout常被忽略
哪怕你的 Java 应用没设任何超时,只要它底层走的是 Windows ODBC DSN(比如通过 UCP、旧版 JDBC-ODBC 桥、或某些报表工具间接调用),而该 DSN 在 odbcad32.exe 里勾选了 Enable Query Timeout,就会在默认 60 秒后触发 ORA-01013。这是现场最常复现又最难想到的点。
立即学习“Java免费学习笔记(深入)”;
实操建议:
- 打开对应位数的 ODBC 管理器(64 位系统:C:\Windows\SysWOW64\odbcad32.exe 配 32 位驱动;C:\Windows\system32\odbcad32.exe 配 64 位)
- 选中目标 Oracle DSN → Configure → Advanced → 取消勾选
Enable Query Timeout - 或直接在连接字符串末尾加
;QTO=F(如DSN=ORCL;UID=scott;PWD=tiger;QTO=F) - 改完必须重启调用该 DSN 的进程(Excel、Power BI、VB 程序等),否则缓存连接不会刷新
锁等待和未提交事务才是偶发的根本诱因
ORA-01013 偶发,往往不是因为“慢”,而是因为“卡住”——比如前一个事务更新了某条记录但没 COMMIT,当前查询/更新在等行锁释放,表面看是超时,实际是阻塞。这种问题在并发压测或定时任务场景下特别明显,日志里看不到锁信息,只看到 ORA-01013。
实操建议:
- 出问题时立刻查
v$session和v$lock:SELECT sid, serial#, blocking_session, sql_id, event FROM v$session WHERE event LIKE 'enq:%' OR state = 'WAITING' - 重点看
event是不是enq: TX - row lock contention或SQL*Net message from client(说明客户端在等响应,服务端卡住了) - 检查应用代码:是否有忘记
commit()或rollback()的分支?是否有长事务包裹了不该包的操作(如文件读写、HTTP 调用)? - 避免在存储过程中用
DBMS_OUTPUT.PUT_LINE输出大量内容,尤其在循环里 —— 它会显著拖慢执行,且无法被超时机制感知
Druid 连接池的maxWait和removeAbandonedOnBorrow可能掩盖真实问题
Druid 1.1.x 版本(如 1.1.9)在连接借出超时时,会抛出带 ORA-01013 的异常,但根源可能是连接被其他线程长时间占用未归还,而非 SQL 执行慢。这时候堆栈里出现 FilterChainImpl.preparedStatement_execute 多层嵌套,容易误判为 JDBC 层问题。
实操建议:
- 开启 Druid 的 remove-abandoned 日志:
druid.removeAbandonedOnBorrow=true+druid.logAbandoned=true,看是否真有连接泄漏 - 调低
maxWait(如设为 5000ms),让问题更快暴露,而不是让线程无限等待 - 确认 Druid 是否启用了
statFilter,它的监控数据能帮你定位哪类 SQL 耗时突增(注意:它统计的是从借连接到归还的总时间,含网络、锁等待、GC 等)
真正难排查的从来不是“哪里设了超时”,而是“为什么这条 SQL 在某些时刻突然变慢”。ORA-01013 是个提示符,不是病灶 —— 它背后藏着锁、连接池配置、ODBC 驱动开关、甚至 NLS_LANG 字符集不一致引发的隐式转换。每次偶发,都得当新问题重新 trace,不能依赖“上次这么改就好了”。


















