Oracle数据库的本地命名解析依赖一个名为tnsnames.ora的纯文本文件。它把用户容易记忆的连接名(如ORCL)映射到底层的网络地址、协议、端口和服务名。如果这个文件里某个括号没配对、空格位置不对,或者服务名写错,客户端就会提示ORA-12154或ORA-12514等错误,而这些错误与数据库本身是否正常通常没有关系。理解tnsnames.ora连接描述的语法,是排查连接问题的第一步。

tnsnames.ora文件的作用与存放位置
tnsnames.ora属于Oracle Net配置文件的一部分,通常与sqlnet.ora、listener.ora放在同一目录。在Windows系统中,默认路径为ORACLE_HOME\network\admin;在Linux或Unix系统中,常见路径为$ORACLE_HOME/network/admin。如果设置了TNS_ADMIN环境变量,Oracle会优先从该变量指定的目录读取tnsnames.ora,这一点在多版本客户端共存时非常实用。
文件加载顺序值得注意。Oracle客户端解析连接名时,会先查找本地命名方法中的tnsnames.ora,如果找不到匹配项,再根据sqlnet.ora中的NAMES.DIRECTORY_PATH配置依次尝试其他解析方法。因此,把tnsnames.ora放在正确位置并且保证文件编码为纯文本(建议UTF-8或ASCII)是基础前提。修改文件后无需重启数据库或监听器,客户端下次连接时自动重新读取。
实际工作中,有些人把tnsnames.ora放在用户目录下,结果服务端能连而客户端连不上,就是因为客户端读取的路径不同。建议统一使用TNS_ADMIN变量指向存放所有Oracle网络配置文件的目录,避免多份文件内容不一致造成混乱。
连接描述符的语法逐一拆解
一个典型的tnsnames.ora条目由连接标识、等号和连接描述符组成,整体结构如下:
连接名 =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 主机地址)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = 服务名)
)
)
连接名通常对应应用连接串中的服务名或网络服务名,可以自定义,但要避免与保留字冲突。DESCRIPTION是连接描述符的根节点,必须包含一个或多个ADDRESS以及一个CONNECT_DATA。ADDRESS负责指定网络路径,常见的协议有TCP、TCPS、IPC等;HOST填写数据库服务器的主机名或IP地址,PORT默认1521。如果使用IPv6地址,HOST需要用方括号包裹,例如[2001:db8::1]。
CONNECT_DATA内部可以包含SERVER参数指定专用服务器(DEDICATED)或共享服务器(SHARED),以及SERVICE_NAME或SID来标识要连接的具体数据库服务。从Oracle 8i开始推荐使用SERVICE_NAME而不是SID,因为服务名可以对应一个或多个实例,更适合RAC环境。此外,还可以用FAILOVER_MODE、LOAD_BALANCE等参数实现故障转移和负载均衡,下文会给出示例。
语法中有两个容易忽视的细节:一是括号必须成对出现,二是各个描述项之间用空格分隔而不是逗号。例如(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.100)(PORT = 1521))中,ADDRESS后面紧跟多个用括号包裹的属性对,它们之间没有逗号。如果写成(PROTOCOL = TCP),(HOST = ...)就会报错。很多初学者会沿用编程语言的逗号习惯,导致解析失败。
典型配置示例:单实例、RAC与故障转移
单实例配置是最基础的情况,只需要一个ADDRESS和一个CONNECT_DATA。如下所示:
ORCL =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.100)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = orcl.local)
)
)
在这个配置中,连接名ORCL可以在客户端通过sqlplus user/password@ORCL或JDBC URL中的jdbc:oracle:thin:@ORCL来引用。注意JDBC Thin驱动可以直接使用完整的连接描述字符串,而如果只写连接名,则依赖tnsnames.ora解析。
RAC环境需要列出多个节点地址,并启用负载均衡和故障转移。常见的写法是在DESCRIPTION内部使用ADDRESS_LIST包裹多个ADDRESS,或者直接在DESCRIPTION下写两个ADDRESS,同时加入LOAD_BALANCE和FAILOVER参数。
RACDB =
(DESCRIPTION =
(LOAD_BALANCE = ON)
(FAILOVER = ON)
(ADDRESS = (PROTOCOL = TCP)(HOST = rac1.ipipp.com)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = rac2.ipipp.com)(PORT = 1521))
(CONNECT_DATA =
(SERVICE_NAME = racdb.ipipp.com)
)
)
其中LOAD_BALANCE决定客户端在多个地址之间随机选择或顺序选择,FAILOVER决定当一个地址不可用时是否尝试下一个地址。不过要注意,这里的FAILOVER属于连接时的故障转移,与CONNECT_DATA内部的FAILOVER_MODE(透明应用故障转移TAF)不同。TAF可以配置在CONNECT_DATA中,指定当连接中断后自动切换到备用节点并恢复查询或会话。
下面是一个带TAF的RAC配置示例:
RACTAF =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = rac1.ipipp.com)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = rac2.ipipp.com)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = racdb.ipipp.com)
(FAILOVER_MODE =
(TYPE = SELECT)
(METHOD = BASIC)
(RETRIES = 10)
(DELAY = 2)
)
)
)
这样配置后,如果连接到的实例发生故障,Oracle Net会自动在备用节点上重新建立连接,并尝试恢复正在进行的选择操作。不过TAF只对SELECT语句有效,对事务中的DML操作无法自动恢复,需要应用层配合处理。
常见格式错误与排查方法
tnsnames.ora的解析器对格式非常敏感,任何多余的空格、缺失的括号或错误的关键字都会导致连接失败。最常见的错误之一是括号不匹配。可以使用文本编辑器的括号匹配功能逐层检查,或者把整个条目复制到支持语法高亮的编辑器中观察颜色变化。另一个高频错误是关键字拼写错误,例如把DESCRIPTION写成DISCRIPTION,或者把SERVICE_NAME写成SERVICE,这些都不会被解析器忽略。
修改tnsnames.ora后,建议先用tnsping 连接名命令验证配置是否生效。tnsping只测试网络服务名的解析和到监听器的可达性,并不真正登录数据库,但它能快速定位是解析问题还是认证问题。如果tnsping返回TNS-03505,说明无法解析该名称;如果返回OK并显示耗时,说明tnsnames.ora配置基本正确。此外,还可以使用sqlplus /nolog然后执行conn username/password@连接名来完整测试登录过程。
如果tnsping报错ORA-12154,可以检查以下几点:文件是否位于正确的TNS_ADMIN目录;连接名是否与tnsnames.ora条目的第一行完全一致,区分大小写;文件是否被其他进程锁定或编码是否异常。有时Linux环境下文件写完忘记保存为UTF-8,导致解析失败。还有一个容易被忽视的问题是,tnsnames.ora中如果包含注释,需要使用#号开头,解析器会忽略整行,但注释不能与代码写在同一行且位于代码之后,否则可能破坏括号配对。
对于复杂环境,建议维护一份标准的tnsnames.ora模板,通过版本控制分发到所有客户端,避免手工复制粘贴造成的格式错误。同时,可以利用Oracle提供的lsnrctl status查看监听器实际注册的服务名,确保tnsnames.ora中的SERVICE_NAME与监听器中的服务名一致。很多连接失败的根源就是服务名不匹配。
Oracle数据库tnsnames.ora连接描述修改时间:2026-10-05 05:03:45