问题背景:
用户通过监听TNS连接一套Oracle11G的RAC数据库,提示报错ORA-12537: TNS:connection closed,而通过。
问题分析:
客户端会话通过监听TCP/IP连接数据库初始化的过程。
1. 客户端会话通过IP,PORT,SERVICE_NAME发起连接,先进行客户端服务器与监听服务器之间的网络TCP/IP三次握手连接。
2. 网络通过之后,监听进程才开始接收这个连接,进入监听进程工作步骤。
3. 监听进程会先fork一个子进程A,再通过这个子进程A fork一个专用的数据库服务进程B以接收客户端的连接会话,之后子进程A会退出。
4. 接下来,服务进程B会通过execve函数执行oracle程序,重新初始化这个服务进程。
5. 初始化完之后,服务进程B会与监听进程进行交互,发送自己的进程号NTP等进程信息给监听进程,监听进程也会将客户端的会话登陆信息发送给服务进程B,之后监听进程就完成自己的工作,进入下一个连接的处理。
6. 服务进程B会对登录信息进行验证,并与客户端进行响应。
7. 客户端登陆信息验证通过后,服务进程B与客户端会话开始进行交互,响应客户端的发送请求。
ORA-12537: TNS:connection closed通常发生在步骤3-6,从数据库服务进程的生成到与客户端的会话响应过程中,数据库服务进程或是客户端的连接出现异常都会导致客户端会话返回连接已关闭的报错。
检查监听的listener日志,可以看到报错信息,其中有操作系统的管道错误Linux Error: 32: Broken pipe,以及TNS的连接丢失报错。
TNS-12518: TNS:listener could not hand off client connection
TNS-12547: TNS:lost contact
TNS-12560: TNS:protocol adapter error
TNS-00517: Lost contact
Linux Error: 32: Broken pipe
通过strace对监听进程7184进行跟踪,跟踪过程生成了3个子进程23883,23884,23885。
[root@rac1 ~]# strace -fr -o /tmp/output.txt -p 7184
Process 7184 attached with 3 threads
Process 23883 attached
Process 23884 attached
Process 23885 attached
分析strace监听的输出日志,一开始主要的步骤为接收客户端的连接信息以及fork子进程23883,子进程23883之后再fork数据库的服务进程23884。
之后,服务进程23884通过execve函数执行oracle程序,重新初始化进程。到这里都没有发现问题。
继续往下看,在初始化进程的过程中,看到通过函数shmat(393226, 0, 0)去申请共享内存的访问提示权限不足Permission denied的报错。这里的393226是共享内存的标识符shmid。
往前翻,可以看到进程通过shmget(0xa429f390, 4096, 0)函数去获取共享内存地址0xa429f390的相关标识符。
这个地址可以通过ipcs查到是属于oracle用户下的共享内存段。
到最后,服务进程23884退出,没有与监听进程通信,监听进程也poll监测也返回POLLERR管道关闭,与之前监听返回的报错Linux Error: 32: Broken pipe一致。
通过分析strace的日志,我们可以确认连接丢失是由于服务进程execve函数执行oracle程序,重新初始化进程没有权限去操作oracle用户下的共享内存等文件所导致。权限不足的原因很有可能是$ORACLE_HOME/bin/oracle的权限有问题,进一步检查发现oracle执行程序并没有设置suid权限(u+s),当前为rwxr-s--x,正确应该为rwsr-s--x。由于监听是在grid用户下启动,所以如果没有设置suid权限,在执行oracle程序时grid用户将没有oracle下的执行权限,会导致对数据库的操作报权限不足。
问题解决:
这里我们通过beq协议方式,即进程间采用直接通信,不通过监听连接的方式,进一步oracle程序权限的作用。
在grid用户下的tnsnames.ora文件里面配置beq协议的连接串。
testbeq=
(DESCRIPTION =
(ADDRESS =
(PROTOCOL = BEQ)
(PROGRAM = /u01/app/oracle/product/11.2.0/db_1/bin/oracle)
(ARGV0 = oracletest1)
(ARGS = '(DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=BEQ)))')
(ENVS='ORACLE_HOME=/u01/app/oracle/product/11.2.0/db_1,ORACLE_SID=test1')
)
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = test)
)
)
当oracle程序的权限为rwxr-s--x时,grid用户使用beq方式连接会出现ORA-12547: TNS:lost contact连接丢失的报错。
[grid@rac1 admin]$ sqlplus test/oracle@testbeq
SQL*Plus: Release 11.2.0.4.0 Production on Sat May 11 10:50:57 2024
Copyright (c) 1982, 2013, Oracle. All rights reserved.
ERROR:
ORA-12547: TNS:lost contact
Enter user-name:
将oracle的程序修改为6751,即rwsr-s--x。
[oracle@rac1 ~]$ chmod 6751 /u01/app/oracle/product/11.2.0/db_1/bin/oracle
[oracle@rac1 ~]$ ls -l /u01/app/oracle/product/11.2.0/db_1/bin/oracle
-rwsr-s--x 1 oracle asmadmin 243233900 Mar 6 16:54 /u01/app/oracle/product/11.2.0/db_1/bin/oracle
grid用户再次使用beq方式连接,这一次可以成功。
[grid@rac1 ~]$ sqlplus test/oracle@testbeq
SQL*Plus: Release 11.2.0.4.0 Production on Sat May 11 10:52:56 2024
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, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options
SQL>
通过tns连接也恢复正常。
[oracle@rac1 admin]$ sqlplus test/oracle@test
SQL*Plus: Release 11.2.0.4.0 Production on Sat May 11 10:53:12 2024
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, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options
SQL>
Tip:欢迎关注公众号:勇敢牛牛的笔记,超100+的原创内容,每周不定期更新数据库技术文章。