Oracle Listener
Posted wandering-mind
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle Listener相关的知识,希望对你有一定的参考价值。
一、监听器功能
1)监听客户端请求:监听器作为独立进程运行在数据库服务器上,监听特定网络端口(默认1521)服务请求。
2)为客户端请求分配oracle Server Process:监听器不直接处理客户端发送过来的SQL命令,而是作为代理,将分配一个服务进程与客户端建立通信连接,由server process处理SQL命令并返回结果。
3)注册服务:通过注册过程实现监听器与数据库实例之间了联系,注册的过程就是告知监听器数据库实例名称和服务名,目前Oracle版本中,提供动态注册和静态注册两种方式。
4)故障转移failover: Failover是RAC容错的一个重要方面功能,当数据库实例发生崩溃时,监听器可以自动将请求转移到其它可用实例上。
5)负载均衡衡:在RAC架构中,当一个客户请求到来时,Oracle会根据当前RAC集群环境中所有实例的负载情况,避开负载较高的实例,将请求转移到负载较低的实例进行处理。
二、注册过程
注册的作用就是实现数据库实例名和服务名注册到运行的监听器程序中。
Figure 2-1 Example listener.ora File
LISTENER= (DESCRIPTION= (ADDRESS_LIST= (ADDRESS=(PROTOCOL=tcp)(HOST=sale-server)(PORT=1521)) (ADDRESS=(PROTOCOL=ipc)(KEY=extproc))))-- 静态注册部分 SID_LIST_LISTENER= (SID_LIST= (SID_DESC= (GLOBAL_DBNAME=sales.us.acme.com) (ORACLE_HOME=/oracle9i) (SID_NAME=sales)) (SID_DESC= (SID_NAME=plsextproc) (ORACLE_HOME=/oracle9i) (PROGRAM=extproc)))
2.1) 默认是动态注册的时候,只有PLSExtProc项目。SID_LIST里用来配置当前监听器静态注册的服务项目,其中,通过一个或多个SID_DESC进行配置。静态配置项目中,通过GLOBAL_NAME配置服务项目,通过SID_NAME指定数据库实例的名称,通过ORACLE_HOME配置Oracle数据库软件安装的基本目录。
2.2)动态注册由PMON后台进程周期(2分钟)发起注册。
-- 手工进行注册 alter system set LOCAL_LISTENER=‘(ADDRESS = (PROTOCOL = TCP)(HOST = 10.150.10.150)(PORT = 1521))‘; alter system register;
三、监听器信息
通过lsnrctl监听器控制程序与监听器进行交互和控制操作获取相对应信息。
注:
-- 这在10g及以后版本不是必要的安全检查条件,若想要取消此安全设置,可以在listener.ora文件中设置上LOCAL_OS_AUTHENTICATION_[listener name]=OFF
set password
监听器密码设置在ORACLE 9i版本中有效,在10g版本中,即使设置密码后,依然可以不用输入密码停止监听服务,因为In Oracle 10, the TNSListener is secure out of the box and there should not be a need to set a listener password as in older versions of the Oracle listener。
Oracle10g以后,设置Listener密码已经不是安全检查的必要条件了,因为默认在10g里面除了启动监听的用户之外,其它用户都无法停止Listener(还有另外一些lsnrctl的命令也同样被禁止了,比如trace, reload等),即使Listener没有设置密码。在默认情况下,启动Listener或者使用lsnrctl status命令查看监听状态,可以看到:Security ON: Password OR Local OS Authentication这表明Listener的安全机制使用了Password方式或者Local OS Authentication方式,在这种状态下,即使是设置了监听密码,对于启动监听的user来说,也仍然是不需要任何密码就可以停止监听的。
3.1)set 命令操作配置
参数 |
描叙 |
set password |
|
set rawmode |
设置rawmode |
set displaymode |
把lsnrctl工具的显示模式设置成RAW、COMPACT、NORMAL或VERBOSE |
set trc_file |
设置监听跟踪文件的名称 |
set trc_directory |
设置监听器跟踪目录的名称 |
set trc_level |
把跟踪级别设置为OFF、USER、ADMIN、SUPPORT模式 |
set log_file |
显示或设置日志文件 |
set log_directory |
设置日志目录位置 |
set log_status |
设置是否为该监听器打开日志特性 |
set current_listener |
设置当前监听器为指定监听器 |
set inbound_connect_timeout |
设置参数指定的时间,在几秒钟内为客户完成网络连接已经建立后,其连接请求的监听 |
set startup_waittime |
设置监听器等待响应lsnrctl 命令行工具中的一条STATUS命令的时间长度 |
set save_config_on_stop |
在退出lsnrctl工具时保存对listener.ora文件的修改 |
set dynamic_registration |
使用的DYNAMIC_REGISTRATION_listener_name的参数启用或禁用动态注册。当设置为on,听者接受动态登记;设置为关闭时,听者拒绝动态注册。静态注册不受影响 |
set enable_global_dynamic_endpoint |
四、监听器日志解析
1)日志格式:TIMESTAMP * CONNECT DATA [* PROTOCOL INFO] * EVENT [* SID] * RETURN CODE, 使用*进行内容分割。
2)监听日志截断,防止日志文件过大,一般不能超过2GB,超过会导致LISTENER监听器无法处理新的连接或是给写入、查看带来的一些性能问题。
Step 1:首先停止监听服务进程(tnslsnr)记录日志。
Step 2:将监听日志文件(listener.log)复制一份,以listener.log.yyyymmdd格式命名
Step 3:将监听日志文件(listener.log)清空。(如:mv命令等)
Step 4:开启监听服务进程(tnslsnr)记录日志
#!/bin/bash # 00 00 * * * /home/oracle/_cron/cls_oracle/cls_oracle.sh -d 31 > /home/oracle/_cron/cls_oracle/cls_oracle.sh.log 2>&1 # Script used to cleanup any Oracle environment. # # Cleans: audit_log_dest # background_dump_dest # core_dump_dest # user_dump_dest # # Rotates: Alert Logs # Listener Logs # # Scheduling: 00 00 * * * /home/oracle/_cron/cls_oracle/cls_oracle.sh -d 31 > /home/oracle/_cron/cls_oracle/cls_oracle.log 2>&1 # # Created By: Tommy Wang 2012-09-10 # # History: # RM="rm -f" RMDIR="rm -rf" LS="ls -l" MV="mv" TOUCH="touch" TESTTOUCH="echo touch" TESTMV="echo mv" TESTRM=$LS TESTRMDIR=$LS SUCCESS=0 FAILURE=1 TEST=0 HOSTNAME=`hostname` ORAENV="oraenv" TODAY=`date +%Y%m%d` ORIGPATH=/usr/local/bin:$PATH ORIGLD=$LD_LIBRARY_PATH export PATH=$ORIGPATH # Usage function. f_usage(){ echo "Usage: `basename $0` -d DAYS [-a DAYS] [-b DAYS] [-c DAYS] [-n DAYS] [-r DAYS] [-u DAYS] [-t] [-h]" echo " -d = Mandatory default number of days to keep log files that are not explicitly passed as parameters." echo " -a = Optional number of days to keep audit logs." echo " -b = Optional number of days to keep background dumps." echo " -c = Optional number of days to keep core dumps." echo " -n = Optional number of days to keep network log files." echo " -r = Optional number of days to keep clusterware log files." echo " -u = Optional number of days to keep user dumps." echo " -h = Optional help mode." echo " -t = Optional test mode. Does not delete any files." } if [ $# -lt 1 ]; then f_usage exit $FAILURE fi # Function used to check the validity of days. f_checkdays(){ if [ $1 -lt 1 ]; then echo "ERROR: Number of days is invalid." exit $FAILURE fi if [ $? -ne 0 ]; then echo "ERROR: Number of days is invalid." exit $FAILURE fi } # Function used to cut log files. f_cutlog(){ # Set name of log file. LOG_FILE=$1 CUT_FILE=${LOG_FILE}.${TODAY} FILESIZE=`ls -l $LOG_FILE | awk ‘{print $5}‘` # Cut the log file if it has not been cut today. if [ -f $CUT_FILE ]; then echo "Log Already Cut Today: $CUT_FILE" elif [ ! -f $LOG_FILE ]; then echo "Log File Does Not Exist: $LOG_FILE" elif [ $FILESIZE -eq 0 ]; then echo "Log File Has Zero Size: $LOG_FILE" else # Cut file. echo "Cutting Log File: $LOG_FILE" $MV $LOG_FILE $CUT_FILE $TOUCH $LOG_FILE fi } # Function used to delete log files. f_deletelog(){ # Set name of log file. CLEAN_LOG=$1 # Set time limit and confirm it is valid. CLEAN_DAYS=$2 f_checkdays $CLEAN_DAYS # Delete old log files if they exist. find $CLEAN_LOG.[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9] -type f -mtime +$CLEAN_DAYS -exec $RM {} \\; 2>/dev/null } # Function used to get database parameter values. f_getparameter(){ if [ -z "$1" ]; then return fi PARAMETER=$1 sqlplus -s /nolog <<EOF | awk -F= "/^a=/ {print \\$2}" set head off pagesize 0 feedback off linesize 200 whenever sqlerror exit 1 conn / as sysdba select ‘a=‘||value from v\\$parameter where name = ‘$PARAMETER‘; EOF } # Function to get unique list of directories. f_getuniq(){ if [ -z "$1" ]; then return fi ARRCNT=0 MATCH=N x=0 for e in `echo $1`; do if [ ${#ARRAY[*]} -gt 0 ]; then # See if the array element is a duplicate. while [ $x -lt ${#ARRAY[*]} ]; do if [ "$e" = "${ARRAY[$x]}" ]; then MATCH=Y fi done fi if [ "$MATCH" = "N" ]; then ARRAY[$ARRCNT]=$e ARRCNT=`expr $ARRCNT+1` fi x=`expr $x + 1` done echo ${ARRAY[*]} } # Parse the command line options. while getopts a:b:c:d:n:r:u:th OPT; do case $OPT in a) ADAYS=$OPTARG ;; b) BDAYS=$OPTARG ;; c) CDAYS=$OPTARG ;; d) DDAYS=$OPTARG ;; n) NDAYS=$OPTARG ;; r) RDAYS=$OPTARG ;; u) UDAYS=$OPTARG ;; t) TEST=1 ;; h) f_usage exit 0 ;; *) f_usage exit 2 ;; esac done shift $(($OPTIND - 1)) # Ensure the default number of days is passed. if [ -z "$DDAYS" ]; then echo "ERROR: The default days parameter is mandatory." f_usage exit $FAILURE fi f_checkdays $DDAYS echo "`basename $0` Started `date`." # Use test mode if specified. if [ $TEST -eq 1 ] then RM=$TESTRM RMDIR=$TESTRMDIR MV=$TESTMV TOUCH=$TESTTOUCH echo "Running in TEST mode." fi # Set the number of days to the default if not explicitly set. ADAYS=${ADAYS:-$DDAYS}; echo "Keeping audit logs for $ADAYS days."; f_checkdays $ADAYS BDAYS=${BDAYS:-$DDAYS}; echo "Keeping background logs for $BDAYS days."; f_checkdays $BDAYS CDAYS=${CDAYS:-$DDAYS}; echo "Keeping core dumps for $CDAYS days."; f_checkdays $CDAYS NDAYS=${NDAYS:-$DDAYS}; echo "Keeping network logs for $NDAYS days."; f_checkdays $NDAYS RDAYS=${RDAYS:-$DDAYS}; echo "Keeping clusterware logs for $RDAYS days."; f_checkdays $RDAYS UDAYS=${UDAYS:-$DDAYS}; echo "Keeping user logs for $UDAYS days."; f_checkdays $UDAYS # Check for the oratab file. if [ -f /var/opt/oracle/oratab ]; then ORATAB=/var/opt/oracle/oratab elif [ -f /etc/oratab ]; then ORATAB=/etc/oratab else echo "ERROR: Could not find oratab file." exit $FAILURE fi # Build list of distinct Oracle Home directories. OH=`egrep -i ":Y|:N" $ORATAB | grep -v "^#" | grep -v "\\*" | cut -d":" -f2 | sort | uniq` # Exit if there are not Oracle Home directories. if [ -z "$OH" ]; then echo "No Oracle Home directories to clean." exit $SUCCESS fi # Get the list of running databases. SIDS=`ps -e -o args | grep pmon | grep -v grep | awk -F_ ‘{print $3}‘ | sort` # Gather information for each running database. for ORACLE_SID in `echo $SIDS` do # Set the Oracle environment. ORAENV_ASK=NO export ORACLE_SID . $ORAENV if [ $? -ne 0 ]; then echo "Could not set Oracle environment for $ORACLE_SID." else export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$ORIGLD ORAENV_ASK=YES echo "ORACLE_SID: $ORACLE_SID" # Get the audit_dump_dest. ADUMPDEST=`f_getparameter audit_dump_dest` if [ ! -z "$ADUMPDEST" ] && [ -d "$ADUMPDEST" 2>/dev/null ]; then echo " Audit Dump Dest: $ADUMPDEST" ADUMPDIRS="$ADUMPDIRS $ADUMPDEST" fi # Get the background_dump_dest. BDUMPDEST=`f_getparameter background_dump_dest` echo " Background Dump Dest: $BDUMPDEST" if [ ! -z "$BDUMPDEST" ] && [ -d "$BDUMPDEST" ]; then BDUMPDIRS="$BDUMPDIRS $BDUMPDEST" fi # Get the core_dump_dest. CDUMPDEST=`f_getparameter core_dump_dest` echo " Core Dump Dest: $CDUMPDEST" if [ ! -z "$CDUMPDEST" ] && [ -d "$CDUMPDEST" ]; then CDUMPDIRS="$CDUMPDIRS $CDUMPDEST" fi # Get the user_dump_dest. UDUMPDEST=`f_getparameter user_dump_dest` echo " User Dump Dest: $UDUMPDEST" if [ ! -z "$UDUMPDEST" ] && [ -d "$UDUMPDEST" ]; then UDUMPDIRS="$UDUMPDIRS $UDUMPDEST" fi fi done # Do cleanup for each Oracle Home. for ORAHOME in `f_getuniq "$OH"` do # Get the standard audit directory if present. if [ -d $ORAHOME/rdbms/audit ]; then ADUMPDIRS="$ADUMPDIRS $ORAHOME/rdbms/audit" fi # Get the Cluster Ready Services Daemon (crsd) log directory if present. if [ -d $ORAHOME/log/$HOSTNAME/crsd ]; then CRSLOGDIRS="$CRSLOGDIRS $ORAHOME/log/$HOSTNAME/crsd" fi # Get the Oracle Cluster Registry (OCR) log directory if present. if [ -d $ORAHOME/log/$HOSTNAME/client ]; then OCRLOGDIRS="$OCRLOGDIRS $ORAHOME/log/$HOSTNAME/client" fi # Get the Cluster Synchronization Services (CSS) log directory if present. if [ -d $ORAHOME/log/$HOSTNAME/cssd ]; then CSSLOGDIRS="$CSSLOGDIRS $ORAHOME/log/$HOSTNAME/cssd" fi # Get the Event Manager (EVM) log directory if present. if [ -d $ORAHOME/log/$HOSTNAME/evmd ]; then EVMLOGDIRS="$EVMLOGDIRS $ORAHOME/log/$HOSTNAME/evmd" fi # Get the RACG log directory if present. if [ -d $ORAHOME/log/$HOSTNAME/racg ]; then RACGLOGDIRS="$RACGLOGDIRS $ORAHOME/log/$HOSTNAME/racg" fi done # Clean the audit_dump_dest directories. if [ ! -z "$ADUMPDIRS" ]; then for DIR in `f_getuniq "$ADUMPDIRS"`; do if [ -d $DIR ]; then echo "Cleaning Audit Dump Directory: $DIR" find $DIR -type f -name "*.aud" -mtime +$ADAYS -exec $RM {} \\; 2>/dev/null fi done fi # Clean the background_dump_dest directories. if [ ! -z "$BDUMPDIRS" ]; then for DIR in `f_getuniq "$BDUMPDIRS"`; do if [ -d $DIR ]; then echo "Cleaning Background Dump Destination Directory: $DIR" # Clean up old trace files. find $DIR -type f -name "*.tr[c,m]" -mtime +$BDAYS -exec $RM {} \\; 2>/dev/null find $DIR -type d -name "cdmp*" -mtime +$BDAYS -exec $RMDIR {} \\; 2>/dev/null fi if [ -d $DIR ]; then # Cut the alert log and clean old ones. for f in `find $DIR -type f -name "alert\\_*.log" ! -name "alert_[0-9A-Z]*.[0-9]*.log" 2>/dev/null`; do echo "Alert Log: $f" f_cutlog $f f_deletelog $f $BDAYS done fi done fi # Clean the core_dump_dest directories. if [ ! -z "$CDUMPDIRS" ]; then for DIR in `f_getuniq "$CDUMPDIRS"`; do if [ -d $DIR ]; then echo "Cleaning Core Dump Destination: $DIR" find $DIR -type d -name "core*" -mtime +$CDAYS -exec $RMDIR {} \\; 2>/dev/null fi done fi # Clean the user_dump_dest directories. if [ ! -z "$UDUMPDIRS" ]; then for DIR in `f_getuniq "$UDUMPDIRS"`; do if [ -d $DIR ]; then echo "Cleaning User Dump Destination: $DIR" find $DIR -type f -name "*.trc" -mtime +$UDAYS -exec $RM {} \\; 2>/dev/null fi done fi # Cluster Ready Services Daemon (crsd) Log Files for DIR in `f_getuniq "$CRSLOGDIRS $OCRLOGDIRS $CSSLOGDIRS $EVMLOGDIRS $RACGLOGDIRS"`; do if [ -d $DIR ]; then echo "Cleaning Clusterware Directory: $DIR" find $DIR -type f -name "*.log" -mtime +$RDAYS -exec $RM {} \\; 2>/dev/null fi done # Clean Listener Log Files. # Get the list of running listeners. It is assumed that if the listener is not running, the log file does not need to be cut. ps -e -o args | grep tnslsnr | grep -v grep | while read LSNR; do # Derive the lsnrctl path from the tnslsnr process path. TNSLSNR=`echo $LSNR | awk ‘{print $1}‘` ORACLE_PATH=`dirname $TNSLSNR` ORACLE_HOME=`dirname $ORACLE_PATH` PATH=$ORACLE_PATH:$ORIGPATH LD_LIBRARY_PATH=$ORACLE_HOME/lib:$ORIGLD LSNRCTL=$ORACLE_PATH/lsnrctl echo "Listener Control Command: $LSNRCTL" # Derive the listener name from the running process. LSNRNAME=`echo $LSNR | awk ‘{print $2}‘ | tr "[:upper:]" "[:lower:]"` echo "Listener Name: $LSNRNAME" # Get the listener version. LSNRVER=`$LSNRCTL version | grep "LSNRCTL" | grep "Version" | awk ‘{print $5}‘ | awk -F. ‘{print $1}‘` echo "Listener Version: $LSNRVER" # Get the TNS_ADMIN variable. echo "Initial TNS_ADMIN: $TNS_ADMIN" unset TNS_ADMIN TNS_ADMIN=`$LSNRCTL status $LSNRNAME | grep "Listener Parameter File" | awk ‘{print $4}‘` if [ ! -z $TNS_ADMIN ]; then export TNS_ADMIN=`dirname $TNS_ADMIN` else export TNS_ADMIN=$ORACLE_HOME/network/admin fi echo "Network Admin Directory: $TNS_ADMIN" # If the listener is 11g, get the diagnostic dest, etc... if [ $LSNRVER -ge 11 ]; then # Get the listener log file directory. LSNRDIAG=`$LSNRCTL<<EOF | grep log_directory | awk ‘{print $6}‘ set current_listener $LSNRNAME show log_directory EOF` echo "Listener Diagnostic Directory: $LSNRDIAG" # Get the listener trace file name. LSNRLOG=`lsnrctl<<EOF | grep trc_directory | awk ‘{print $6"/"$1".log"}‘ set current_listener $LSNRNAME show trc_directory EOF` echo "Listener Log File: $LSNRLOG" # If 10g or lower, do not use diagnostic dest. else # Get the listener log file location. LSNRLOG=`$LSNRCTL status $LSNRNAME | grep "Listener Log File" | awk ‘{print $4}‘` fi # See if the listener is logging. if [ -z "$LSNRLOG" ]; then echo "Listener Logging is OFF. Not rotating the listener log." # See if the listener log exists. elif [ ! -r "$LSNRLOG" ]; then echo "Listener Log Does Not Exist: $LSNRLOG" # See if the listener log has been cut today. elif [ -f $LSNRLOG.$TODAY ]; then echo "Listener Log Already Cut Today: $LSNRLOG.$TODAY" # Cut the listener log if the previous two conditions were not met. else # Remove old 11g+ listener log XML files. if [ ! -z "$LSNRDIAG" ] && [ -d "$LSNRDIAG" ]; then echo "Cleaning Listener Diagnostic Dest: $LSNRDIAG" find $LSNRDIAG -type f -name "log\\_[0-9]*.xml" -mtime +$NDAYS -exec $RM {} \\; 2>/dev/null fi # Disable logging. $LSNRCTL <<EOF set current_listener $LSNRNAME set log_status off EOF # Cut the listener log file. f_cutlog $LSNRLOG # Enable logging. $LSNRCTL <<EOF set current_listener $LSNRNAME set log_status on EOF # Delete old listener logs. f_deletelog $LSNRLOG $NDAYS fi done echo "`basename $0` Finished `date`." exit
五、sqlplus连接数据库实例方式,其它类似
5.1) sqlplus / as sysdba 操作系统认证,不需要数据库服务器启动listener,也不需要数据库服务器处于可用状态。比如我们想要启动数据库就可以用这种方式进入 sqlplus,然后通过startup命令来启动。 5.2) sqlplus username/password 连接本机数据库,不需要数据库服务器的listener进程,但是由于需要用户名密码的认证,因此需要数据库服务器处于可用状态才行。 5.3) sqlplus usernaem/[email protected] 通过网络连接,这是需要数据库服务器的listener处于监听状态。此时建立一个连接的大致步骤如下 a. 查询sqlnet.ora,看看名称的解析方式,默认是TNSNAME b. 查询tnsnames.ora文件,从里边找orcl的记录,并且找到数据库服务器的主机名或者IP,端口和service_name c. 如果服务器listener进程没有问题的话,建立与listener进程的连接。 d. 根据不同的服务器模式如专用服务器模式或者共享服务器模式,listener采取接下去的动作。默认是专用服务器模式,没有问题的话客户端 就连接上了数据库的server process。 e. 这时连接已经建立,可以操作数据库了。 5.4)sqlplus username/[email protected]//host:port/sid 用sqlplus远程连接oracle命令(例:sqlplus risenet/1@//192.168.130.99:1521/risenet)
以上是关于Oracle Listener的主要内容,如果未能解决你的问题,请参考以下文章
oracle的监听器listener 和 java web的监听器listener 的联系是啥?
连接oracle数据库出现:ORA-12505,TNS:listener does not currently know of SID given in connect descriptor(示例代码