oracle listener也是oracle中非常重要的进程,其作用就不阐述了,当listener进程异常时,应用连接oracle数据库将受到非常大的影响。
监听工作原理:
- 首先客户端向监听进程发起数据库连接请求。这个过程又分为两个步骤:
a) 通过三次握手机制建立 TCP 连接。这一步一般来说比较快,只是在客户端操作系统与监听所在操作系统内核之间的交互过程,不涉及到监听进程。
b) 监听进程接受客户端的连接。在客户端发起数据库连接请求这一过程中,如果监听进程太忙,则在建立 TCP 连接之后,需要等待一段时间,监听进程才能真正地接受连接请求,监听进程接受连接将使用操作系统调用 accept。
- 监听进程 fork 一个子进程,这里我们称为“监听子进程 1”,然后等待子进程退出。在这一步中,如果子进程退出之前所耗的时间越长,那么监听等待的时间也越长,在这个等待过程 中监听不能做任何其他动作。如果子进程异常,不能退出,监听进程将 Hang 住。在一个连接频繁的系统上,我们使用 ps –ef | grep tnslsnr 命令看到的父进程不为 1 的 tnslsnr 进程, 就是这样的子进程。
- 监听子进程 1 fork 一个子进程,这里我们称为“子进程 2”。
- 监听子进程 1 完成工作,立即结束。监听进程然后又会一直等待,这里是等待 Oracle Server Process 发送数据过来。
- 子进程 2 执行系统调用 exec,调用的是 oracle 这个可执行文件,这样这个子进程 2 就变更 为 Oracle Server Process。也就是说,Server Process 与“子进程 2”具有相同的进程号。 Server Process 进行一些初始化操作。
- Server Process 向监听进程传递一些特定的数据,包括进程号等,典型的数据是“N T P 0 1 9 1 9 0”,这里 19190 为进程号,每个字符用空格分开。
- 监听进程向 Server Process 发送客户端的连接串数据,这个数据用于 Server Process 验证客户端。然后监听进程向 listener.log 写入日志。这个时候,监听进程的工作就完成了,继续处理下一个连接请求。监听进程能工作到这一步,表明监听并没有被挂起。
- Server Process 向客户端发送数据,对客户端的连接进行响应。
- 客户端与 Server Process 之间进行交互,完成连接过程,然后再提交SQL执行真正的工作等等。
如何诊断listener进程:
一般来说监听进程挂起主要有几种可能:
- 进程陷入某个死循环,这种情况下进程的 CPU 占用率会比较高。
- 进程在网络 IO 和磁盘 IO 上被阻塞。
- 进程在等待子进程或线程结束。
- 进程在等待信号量、互斥量等。
以上几种可能的情况,通过收集进程的 call stack、CPU 使用、system call 等信息可以深入的诊断出现问题的根本原因。
检查监听进程的内存使用:
1 2 3 4 |
Solaris pmap -x <listener_pid> AIX (5.2 +) procmap <listener_pid> HPUX export UNIX95=1;ps -e -o pid, ruser, vsz, args | grep tnslsnr Linux cat /proc/<listener_pid>/status或 pmap <listener_pid>或者pidstat |
检查监听进程的cpu使用:
1 2 3 |
linux top/pidstat aix topas HPUX glance |
查看监听进程的 call stack:
1 2 3 4 5 |
Solaris pstack <listener_pid> AIX (pre 5.2) 输入: dbx -a <listener_pid>然后在出现的提示符下输入: where AIX (5.2 and higher) procstack <listener_pid> HPUX 输入: gdb $ORACLE_HOME/bin/tnslsnr <listener_pid>然后在出现的提示符下输入: where Linux 输入: gdb $ORACLE_HOME/bin/tnslsnr <listener_pid>然后在出现的提示符下输入: where |
跟踪监听进程:
1 2 3 4 |
Solaris truss -rall -wall -p <listener_pid> -o <输出文件> HP-UX tusc -T hires -afp <listener_pid> -o <输出文件> IBM AIX 5.2+ truss -aefp <listener_pid> -o <输出文件> -d Linux strace -fp <listener_pid> -o <输出文件> -ttt |