ORA-28040是客户端与服务端TLS认证协议不匹配所致,须在数据库服务器$ORACLE_HOME/network/admin/sqlnet.ora中配置SQLNET.ALLOWED_LOGON_VERSION_SERVER=11或12a并重启监听器,JDBC还需ojdbc8+驱动及JVM启用TLSv1.2。

必须先分清是协议不兼容、OCI库不匹配,还是时区/认证等衍生问题——直接改 SQLNET.ALLOWED_LOGON_VERSION_SERVER 或换驱动,大概率踩坑。
ORA-28040:协议握手失败,只改服务端 sqlnet.ora
错误本质是客户端(如 11g sql*plus、旧版 Navicat、ojdbc6)用 TLS 1.0 以下协议发起连接,而 Oracle 12c+ 服务端默认拒绝。这不是密码错,也不是监听没起,是“话还没说上就拉黑了”。
- 改服务端
$ORACLE_HOME/network/admin/sqlnet.ora,加一行:SQLNET.ALLOWED_LOGON_VERSION_SERVER=11(兼容 11g 客户端),或=12a(强制 TLS 1.2,需客户端支持) - 别碰
SQLNET.ALLOWED_LOGON_VERSION(无 _SERVER 后缀)——12.1+ 已废弃,设了也不生效 - 改完必须重启监听器:
lsnrctl stop && lsnrctl start,否则零效果 - JDBC 场景额外注意:
ojdbc8.jar以上 + JVM 加-Dhttps.protocols=TLSv1.2,否则驱动可能仍走老协议
ORA-12578 / UnsatisfiedLinkError:JDBC 驱动和 OCI 库版本对不上
ojdbc8.jar 会尝试加载 libclntsh.so.19.1,但你机器上只有 12c 的 libclntsh.so.12.1,符号找不到,直接崩溃。这不是驱动下载错了,是本地 OCI 库没配对。
- 检查实际加载的 OCI 库:启动 Java 时加
-Doracle.jdbc.Trace=true,搜日志里oci library关键字 - 优先级顺序:JVM
-Djava.library.path=/path/to/instantclient_19_14> 环境变量LD_LIBRARY_PATH(Linux)或PATH(Windows)> 默认路径 - Windows 下多个 Oracle 客户端共存时,用
depends.exe查oci.dll实际加载来源,避免 PATH 里混着 11g 和 19c 的 bin 目录 - 实在对不齐?设
oracle.jdbc.thinLogonVersion=8强制走 Thin 模式(但丢掉 FAN、AQ、高级连接池功能,性能降 15%~30%)
ORA-01882:客户端时区名解析失败,不是 serverTimezone 参数的问题
服务端 DBTIMEZONE 是 Asia/Shanghai,但客户端 TZ 环境变量是空、CST 或老版 timezlrg.dat 文件里没有这个地区名,驱动一查就报错。MySQL 风格的 serverTimezone=GMT%2B8 在 Oracle JDBC 里完全无效。
- Linux/macOS:连库前执行
export TZ=Asia/Shanghai,别信系统默认值(尤其 Docker 容器) - JDBC 连接串必须加
oracle.jdbc.timezoneAsRegion=true,否则驱动把Asia/Shanghai当缩写查表,必挂 - 检查客户端
$ORACLE_HOME/oracore/zoneinfo/timezlrg.dat时间戳,和数据库服务端同路径文件比对;不一致就从服务端拷一份过去 - 注册表项
HKEY_LOCAL_MACHINE\SOFTWARE\Oracle\KEY_*下的ora_tzmap.xml和timezlrg.dat也得同步,Windows 客户端常在这里栽跟头
真正卡住人的从来不是单个参数怎么填,而是日志里看不到的隐性依赖:监听器没重启、JVM 参数被父进程覆盖、java.library.path 路径里混着两个 instantclient 版本、或者 timezlrg.dat 文件权限不对导致读失败——这些都得逐层验证,不能靠猜。


















