客户端连不上是因为新主库未注册原service_names,仅动态注册db_unique_name对应的服务名,导致非默认服务名连接报ORA-12516;需手动执行ALTER SYSTEM SET service_names=...和ALTER SYSTEM REGISTER。
为什么切换后客户端连不上,不是网络或密码问题?
容灾切换(switchover)完成后,主库变备库、备库升主库,但客户端连接仍指向旧的 service_names 或旧监听注册的服务名,而新主库默认只动态注册了 db_unique_name 对应的 service(如 jiekexu),其他自定义 service(如 test、scott)不会自动注册——这直接导致用非默认 service 连接时抛出 ora-12516。这不是监听没启、端口不通,也不是密码错,而是服务名在监听器里根本“不存在”。
tnsnames.ora 里加 CONNECT_TIMEOUT 和 RETRY_COUNT 真的有用吗?
没用。这两个参数控制的是客户端发起连接请求时的**单次尝试行为**(比如超时多久、重试几次),但解决不了核心问题:目标 service 根本没在监听器中注册。即使你设了 RETRY_COUNT=10,每次连的还是那个不存在的服务名,结果只会重复报 ORA-12516 十次。
真正该做的是让新主库主动把需要的服务名注册进监听器,而不是靠客户端硬扛重试。
怎么让新主库注册多个 service_names?
必须手动干预,分两步走:
- 确认新主库当前注册的服务:
lsnrctl status查看输出里Services Summary部分,只看到db_unique_name对应的 service,说明没注册成功 - 在新主库上执行:
ALTER SYSTEM SET service_names='jiekexu,test,orcl,scott' SCOPE=BOTH; - 强制重新注册到监听器:
ALTER SYSTEM REGISTER;(注意:不是重启监听,这个命令会立刻触发 PMON 向监听器推送当前service_names) - 再跑一遍
lsnrctl status,确认test、orcl等 service 已出现在列表中
如果 service_names 值含空格或特殊字符,必须用单引号包裹;修改后不需重启数据库,但 SCOPE=BOTH 要求实例处于 OPEN 状态。
切换脚本里漏掉这一步,等于白切
很多团队把 Switchover 当成纯数据库操作,只关注 ALTER DATABASE COMMIT TO SWITCHOVER 和 STARTUP MOUNT 这类语句,却忘了新主库启动后,它的服务注册行为是独立于角色切换逻辑的。Oracle 不会自动继承原主库的 service_names 设置——哪怕两个库的 spfile 完全一样,新主库启动时读取的是自己控制文件里的 db_unique_name,注册的 service 默认就是它。
最稳妥的做法,是在 Switchover 脚本末尾明确加上 ALTER SYSTEM SET service_names=... 和 ALTER SYSTEM REGISTER;,并用 lsnrctl status | grep -i "your_service" 做断言校验。少这一行,应用层就卡在连接池初始化阶段,谁都救不了。











