今天遇到一位网友,配置的dblink无法使用,报错:
ORA-12514: TNS: 监听进程不能解析在连接描述符中给出的 SERVICE_NAME
其创建dblink的语句是:
create
public
database
link
nems
connect
to
heuser
identified
by
mypasswd
using
'
nems_123.456.78.99
'
;
其tnsnames.ora的配置是:
NEMS_123
.456.78.99
=
(
DESCRIPTION
=
(
ADDRESS_LIST
=
(
ADDRESS
=
(
PROTOCOL
=
TCP
)(
HOST
=
123.456.78.99
)(
PORT
=
1521
))
)
(
CONNECT_DATA
=
(
SERVER
=
DEDICATED
)
(
SERVICE_NAME
=
NEMS
)
)
)
通过tnsping和sqlplus手工登录来进行检查,比较奇怪的是tnsping能ping通,但是用通过这个tns用sqlplus登录则报错:
[
oracle
@
buptnu
admin
]$
tnsping
nems_123
.456.78.99
TNS
Ping
Utility
for
Linux
:
Version
9.2.0.4.0
-
Production
on
25
-
JUL
-
2007
13
:
37
:
00
Copyright
(
c
)
1997
Oracle
Corporation
.
All
rights
reserved
.
Used
parameter
files
: /
ora1
/
oracle
/
product
/
9.2.0
/
network
/
admin
/
sqlnet
.
ora
Used
TNSNAMES
adapter
to
resolve
the
alias
Attempting
to
contact
(
DESCRIPTION
=
(
ADDRESS_LIST
=
(
ADDRESS
=
(
PROTOCOL
=
TCP
)(
HOST
=
123.456.78.99
)(
PORT
=
1521
)))
(
CONNECT_DATA
=
(
SERVER
=
DEDICATED
)
(
SERVICE_NAME
=
NEMS
)))
OK
(
90
msec
)
--以上
tnsping
能通
--但是通过
sqlplus
user
/
mypasswd
@
NEMS_123
.456.78.99
就报错:
SQL
>
select
sysdbatate
from
dual
@
nems
;
select
sysdate
from
dual
@
nems
*
ERROR
at
line
1
:
ORA
-
12514
:
TNS
:
listener
could
not
resolve
SERVICE_NAME
given
in
connect
descriptor
既然tnsping能ping通,应该说明网络没有问题,但是从tnsnames.ora的配置上来看也没有错误——如果有错误,tnsping应该也会ping不到。
继续到远程数据库检查,检查listener提供的服务名:
LSNRCTL
>
services
Connecting
to
(
ADDRESS
=
(
PROTOCOL
=
tcp
)(
PORT
=
1521
))
Services
Summary
...
Service
"
nemsXDB
"
has
1
instance
(
s
)
.
Instance
"
nems
"
,
status
READY
,
has
1
handler
(
s
)
for
this
service
...
Handler
(
s
)
:
"
D000
"
established
:
291
refused
:
0
current
:
50
max
:
972
state
:
ready
DISPATCHER
<
machine
:
buptdes
,
pid
:
13465
>
(
ADDRESS
=
(
PROTOCOL
=
tcp
)(
HOST
=
buptdes
)(
PORT
=
36252
))
Service
"
nunems
"
has
1
instance
(
s
)
.
Instance
"
nems
"
,
status
READY
,
has
1
handler
(
s
)
for
this
service
...
Handler
(
s
)
:
"
DEDICATED
"
established
:
30421
refused
:
0
state
:
ready
LOCAL
SERVER
The
command
completed
successfully
在这里,我们只看到了listener提供的2个服务:一个叫nemsXDB,一个叫nunems。并没有看到在tnsnames.ora中配置的”SERVICE_NAME = NEMS”
因此把tnsnames.ora中的SERVICE_NAME = NEMS改成SERVICE_NAME = nunems:
NEMS_123
.456.78.99
=
(
DESCRIPTION
=
(
ADDRESS_LIST
=
(
ADDRESS
=
(
PROTOCOL
=
TCP
)(
HOST
=
123.456.78.99
)(
PORT
=
1521
))
)
(
CONNECT_DATA
=
(
SERVER
=
DEDICATED
)
(
SERVICE_NAME
=
nunems
)
)
)
测试sqplus也能正常登录了,且dblink也能正常使用了。
所以,上面我们碰到的问题,因为能根据实例名NEMS去找到了相应的主机,故tnsping能通,但是根据tns没有找到相应的服务名,所有在建立连接的时候报错了。
在这里,提一下比较容易弄混淆的概念,服务名、实例名和数据库名:
(1)服务名(service_names):指listener提供的对外的服务名,客户端可以通过配置tnsnmaes.ora连进行连接, tnsnmaes.ora文件中的service_name要等于服务器端listener所注册的服务名,服务名可以通过输入lsnrctl后,在输入 service查看,一般的service_name在listener.ora文件中配置(静态注册),或者当没有listener.ora文件时,在 初始化文件中配置instance_name和service_names这2个参数进行动态注册。但是无论采用那种注册方式,都可以通过lsnrctl -sevice来检查。
(2)实例名(instance_name):oracle启动instance后,即启动oracle的内存进程,这个内存进程的名称。在 unix或者linux环境可以通过ps -ef |grep ora_看到启动的进程。instance_name由环境变量决定,一个只装oracle软件,没有建库的实例(即没有初始化文件,没有控制文件,没有 数据文件,没有redolog),可以用rman来启动,启动后select instance_name from v$instance;这个时候我们可以看到instance_name和在环境变量里面配置的ORACLE_SID是同样的名称。(注:正是由于这个原 因,我们一般说的SID就是instance_name,但是需要注意的是,实际上instance_name不等于ORACLE_SID。前者是数据库 层面的概念,后者是操作系统中环境变量的设置。)
(3)数据库名(db_name):这个是在数据库创建的时候确定的:
CREATE DATABASE db_name
CONTROLFILE REUSE
MAXINSTANCES 32
MAXLOGHISTORY 0
……
一旦确定,不能更改。
该信息存在于初始化文件,控制文件等地方(估计数据文件中也有,因为之前试过想通过改初始化文件、控制文件、环境变量来改变数据库名称,但是均有报错,估计在数据文件中已经保存了该信息。)