概念
概念:Oracle网络服务在服务端是通过监听器的进程来实现的,在oracle中,最常见的连接方式是专用连接
服务器进程与用户进程为一一对应的关系,一旦用户进程中断,其对应的服务器进程也被终止。
监听:用户连接监听,监听知道数据库在什么位置,他们之间没有长连接,监听和数据库之间没有必然联系,但是相互之间可以找到,他们之间没有长连接,监听只做一件事情就是在建立连接的时候起作用,负责转发。
建立连接的大致过程
1、客户端发起连接:通过在客户端提供用户名、密码、以及连接字符串等信息,建立与监听器的连接。连接字符串位于客户端的文件里面,文件名字是tnsnames.ora,根据安装的客户端不同,放置在不同的目录里面。
监听把用户的连接请求转发给instance,实例会为这个连接启动一个Server Process, 同时会把Server Process的地址告诉监听,监听告诉客户端,然后客户端直接发起对Server Process的请求,同时把用户名和密码给Server Process,Server Process会验证,Server Process通过客户端输入的连接字符串,去到tnsnames.ora 里去找到host和端口,判断输入的端口和ip是否正确,如果正确则和监听建立连接。
2、客户端一旦与监听器建立连接,则在客户端生成用户进程,同时监听器会判断客户端所请求的服务名是否是自己所管理的服务名。
判断SERVICE_NAME是否正确:监听知道数据库在什么位置,监听会根据客户端输入的连接字符串信息找到tnsnames.ora文件里的SERVICE_NAME,检查SERVICE_NAME是否根自己所管理的服务名匹配(show parameter service),一旦匹配。建立成功连接,此时和监听没有任何关系。
例:如果客户端传过来的连接字符串不包含服务名,报错
如果请求的服务名不是自己管理的,报错并中断
如果请求的服务名是自己管理的,监听器就在数据库服务器上创建服务器进程
3、监听器在创建服务器进程以后,会将用户进程与服务器进程建立连接,之后,监听器退出与客户端的连接
4、服务器进程根据用户进程提供的用户名和密码到数据字典里判断是否正确
5、如果用户名和密码不匹配,报错,如果匹配,则分配PGA,并生成session
动态注册与静态注册
我们前面在配置listener的时候,并没有涉及到服务名的问题,客户端将服务名传给监听器以后,监听器的服务名来自何处?
1、动态注册
数据库实例里的PMON进程,将当前实例的服务名注册到同一台服务器上的,默认的,并在1521端口上监听的监听器(就是名为LISTENER的监听器),当前实例的服务名由初始化参数service_name决定。
SQL> show parameter service
NAME TYPE
------------------------------------ --------------------------------
VALUE
------------------------------
service_names string
jfdb
手工启用动态注册:
show parameter local_listener;
SQL> show parameter servrice_name;
SQL> show parameter service
NAME TYPE
------------------------------------ --------------------------------
VALUE
------------------------------
service_names string
jfdb
SQL> show parameter local_listener;
NAME TYPE
------------------------------------ --------------------------------
VALUE
------------------------------
local_listener string
(ADDRESS = (PROTOCOL =TCP)(HOS
T =jfdb)(PORT = 1523))
SQL> alter system set local_listener= '(ADDRESS = (PROTOCOL =TCP)(HOS
T =jfdb)(PORT = 1523))'; 2
System altered.
修改了这个参数以后 很快服务名就注册过来了
[oracle@jfdb admin]$ lsnrctl status
LSNRCTL for Linux: Version 11.2.0.4.0 - Production on 08-AUG-2022 14:56:19
Copyright (c) 1991, 2013, Oracle. All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=jfdb)(PORT=1523)))
STATUS of the LISTENER
------------------------
Alias LISTENER
Version TNSLSNR for Linux: Version 11.2.0.4.0 - Production
Start Date 08-AUG-2022 14:05:41
Uptime 0 days 0 hr. 50 min. 37 sec
Trace Level off
Security ON: Local OS Authentication
SNMP OFF
Listener Parameter File /u01/app/oracle/product/11.2.0/network/admin/listener.ora
Listener Log File /u01/app/oracle/diag/tnslsnr/jfdb/listener/alert/log.xml
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=jfdb)(PORT=1523)))
Services Summary...
Service "jfdb" has 1 instance(s).
Instance "jfdb", status READY, has 1 handler(s) for this service...
The command completed successfully
静态注册:静态注册在监听启动的时候,立刻就将服务名注册到监听里去。
vim listener.ora
SID_LIST_LISTENER=
(SID_LIST=
(SID_DESC=
(GLOBAL_DBNAME=jfdb)
(ORACLE_HOME=/u01/app/oracle/product/11.2.0)
(SID_NAME=jfdb)
)
)
重启监听
lnsrctl stop
lnsrctl start
查看监听状态: status UNKNOWN是正常的 因为是手动注册的,所以数据库不知道有服务有没有注册到监听里去。
lnsrctl status
[oracle@jfdb admin]$ lsnrctl status
LSNRCTL for Linux: Version 11.2.0.4.0 - Production on 08-AUG-2022 16:48:00
Copyright (c) 1991, 2013, Oracle. All rights reserved.
Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=jfdb)(PORT=1523)))
STATUS of the LISTENER
------------------------
Alias LISTENER
Version TNSLSNR for Linux: Version 11.2.0.4.0 - Production
Start Date 08-AUG-2022 16:47:42
Uptime 0 days 0 hr. 0 min. 18 sec
Trace Level off
Security ON: Local OS Authentication
SNMP OFF
Listener Parameter File /u01/app/oracle/product/11.2.0/network/admin/listener.ora
Listener Log File /u01/app/oracle/diag/tnslsnr/jfdb/listener/alert/log.xml
Listening Endpoints Summary...
(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=jfdb)(PORT=1523)))
Services Summary...
Service "jfdb" has 1 instance(s).
Instance "jfdb", status UNKNOWN, has 1 handler(s) for this service...
The command completed successfully
配置tnsnames.ora
vim tnsnames.ora
JFDB =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.13.129)(PORT = 1523))
)
(CONNECT_DATA =
(SERVICE_NAME = jfdb)
)
)
通过sqlplus连接
创建用户测试
SQL> create user test identified by test;
User created.
SQL> alter user test identified by 123456;
User altered.
SQL> grant connect, resource to test;
Grant succeeded.
SQL> commit;
Commit complete.
[oracle@jfdb admin]$ sqlplus test/123456@jfdb
SQL*Plus: Release 11.2.0.4.0 Production on Mon Aug 8 18:14:07 2022
Copyright (c) 1982, 2013, Oracle. All rights reserved.
Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options
SQL>
监听的三大文件
监听的所有文件的位于$ORACLE_HOME/network/admin/下
listener.ora: 服务端文件、配置监听 位置
tnsname.ora:配置文件是一个用于解析名称的客户端文件,客户端通过连接字符串解析主机名+端口+服务吗是否正确。
sqlnet.ora: 配置访问白名单、黑名单。
service_name
服务名(service_name)是可以更改的,例:从其它环境克隆过来的数据,服务名不相等的需要更改,然后重启服务,以及监听。
修改pdb名字
sqlplus / as sysdba
alter pluggable database SZPROD close;
alter pluggable database SZPROD open restricted;
SQL> select name, open_mode, restricted from v$pdbs;
NAME OPEN_MODE RES
-------------------- ---------- ---
PDB$SEED READ ONLY NO
SZPROD READ WRITE YES
alter session set container=SZPROD;
alter pluggable database rename global_name to SZUAT;
alter pluggable database close immediate;
alter pluggable database open;
alter pluggable database SZUAT save state;
alter session set container=SZUAT;
exec dbms_service.create_service('ebs_SZUAT','ebs_SZUAT');
exec dbms_service.delete_service('ebs_SZPROD');
exec dbms_service.start_service('ebs_SZUAT');
查看数据库的名字:
数据库名:show parameter name
实例名:show parameter instance
服务名:show parameter service,其中服务名可以修改
问题一:
TNS-12537: TNS:connection closed
TNS-12560: TNS: protocol adapter error
TNS-00507: Connection closed
Linux Error: 29: Illegal seek
解决方案
切换到oracle 用户,执行:$ORACLE_HOME/bin/relink,问题解决。
问题二:
从报错来看,很模糊,报错信息就只告诉我们说是名称解析失败。那么这个名称解析失败我们通常会理解为/etc/hosts解析,/etc/resolve.conf 里DNS解析,TNS 里面的主机用的是名称和IP解析失败导致。当然这些都会导致这个报错;但是仅仅这些原因是远远不够的,我们一起来揭秘吧:
1、/etc/hosts 错误导致
解决处理:
是因为地址解析出现异常导致,检查地址信息,主机名是否对应正确。
2、/etc/resolv.conf错误导致
解决办法:
/etc/resolv.conf文件主要由domain, search, nameserver,sortlist这四行内容组成,有任何一条记录不存在或配置不争取都将导致TNS-03505;通常建议的解决办法是配置正确的 DNS 信息或删除无用的配置。
3、tnsname.ora文件所属用户和权限导致
解决办法:
DBLink环境或一台主机装多个不同版本数据库环境的环境下常见。
4、tnsname.ora手工修改后的格式问题(空格,括号,全角)
解决处理:
这是因为没有顶格写,tnsname.ora文件格式错误导致的问题都好处理,这个ora-03505有的时候就不太容易发现,一定要注意顶格写,报错非常不清晰。
5、tnsnames.ora文件名称错误导致
解决办法:
tnsnames.ora 而不是tnsname.ora;修改为正确的tns文件名称即可;tnsnames.ora
6、windows 环境下后缀问题导致
解决办法:
sqlnet.ora文件和“tnsnames.ora”文件图标有差异,这是因为该文件是手动创建的,因为OS上没有显示文件扩展名,实际上名称是一个tnsnames.ora.txt的记事本文件,在显示文件扩展名称的方式下,去除tnsnames.ora.txt文件的.txt后缀,再次在客户机上tnsping orcl成功。
7、SQLNet 配置问题
NAMES.DEFAULT_DOMAIN = WORLD
解决办法:
删除NAMES.DEFAULT_DOMAIN行,因为在访问数据库的时候,会在tns别名后面加上".domain"。
备注:
Oracle的tnsping测试程序,在通讯时使用TCP协议。TCP 是面向连接的OSI传输层协议。面向连接的协议在初始建立连接的阶段需要进行初始的序列号的交换,这就是我们通常所指的三次握手。即tnsping测试程序在与listener进行通讯时会产生三次握手现象。
tnsping命令后,会执行oracle 网络别名(即网络服务名,主机连接字符串)的解析工作。这个解析工作会在本地的tnsnames.ora文件或ORACLE的命令服务器或ORACLE LDAP(目录服务)中进行。解析的目的是得到目标listener所在的机器名(IP地址)和listener侦听的端口号。
listener的机器名与端口号,就可以打开一个到目标机器与端口的TCP连接。为了打开这个TCP连接,listener的机器名必须被解析为ip地址(当然这只有在解析出的listener的连接地址为机器名时才这样做),然后TCP/IP执行三次握手来完成这次连接。
Tnsping工具然后就发送一个Oracle TNS 连接包给Oracle Listener,Listener然后就回应一个TNS 拒绝包(Refuse packet),在两个机器间的TCP/IP连接就结束了。从oracle 网络别名的解析到结束TCP/IP连接之间的总的耗费的时间就显示在tnsping命令的输出中。
问题三:
旧环境生产监听后,启动监听报TNS-12557 or TNS-12555: TNS:Permission Denied之类错误
问题原因
在系统/var/tmp/.oracle文件有问题,是些旧的临时文件
解决方案
stop lsnrctl
rm -rf /var/tmp/.oracle
直接删掉,然后重启监听