Linux下Oracle实例与监听器启停管理:原理、命令与常见坑
开头在Linux服务器上折腾Oracle数据库绕不开三件事启动数据库实例、关掉数据库实例、管好监听器。这三件事看着就是几条命令的事但我见过太多同事在这上面吃亏——要么把startup敲成了start要么数据库还没起来就急着启动监听结果应用连不上还一头雾水。更常见的是刚接触Oracle的人根本分不清“数据库服务”和“监听器”到底谁管谁遇到ORA-12541就以为数据库挂了实际上是监听没起来。今天我就把Linux下Oracle服务和监听的启停、状态查看、常见坑一次性讲透从原理到命令从单机环境到日常运维姿势全部给你捋顺。这篇文章适合刚接手Linux Oracle环境的运维、开发也适合那些一直靠复制粘贴命令但没搞懂原理的同学。我会先讲清楚实例和监听器的关系再分别给出标准操作流程最后聊一堆我实际踩过的坑。你跟着走一遍基本就能独立搞定这摊事了。1. Oracle服务和监听的管理逻辑先别急着敲命令1.1 数据库实例和监听器不是同一个东西很多人习惯把“启动Oracle”理解为一条命令搞定其实Oracle的运行分成两个完全独立的组成部分实例Instance由SGA内存结构和一堆后台进程组成是数据库干活的地方。通过sqlplus / as sysdba进去执行startup启动的是实例并挂载/打开数据库。监听器Listener一个独立进程端口默认1521负责接受客户端的连接请求然后把连接转发给对应的实例。它不属于实例的一部分而是单独的tnslsnr进程。举个生活化的例子实例像一个营业中的柜台监听器是门口的取号机。取号机停机了顾客不知道找哪个柜台柜台打烊了取号机还在派号但业务办不了。在Linux上这两个进程的管理命令完全独立实例用sqlplus的startup/shutdown监听器用lsnrctl。而且有个关键细节监听器进程是由oracle用户启动的数据库实例也是由oracle用户启动的。如果你用root去操作或者环境变量没配对极容易报权限错误或找不到命令。所以第一步要把自己切换成Oracle的安装用户通常是oracle或者确保ORACLE_HOME、ORACLE_SID、PATH这几个环境变量是对的。1.2 环境变量没配好命令都找不到在Linux下你执行sqlplus、lsnrctl这些命令本质是去$ORACLE_HOME/bin下面找二进制文件。如果环境变量没配置最常见的就是-bash: sqlplus: command not found或者提示ORACLE_SID未设置连实例都连不上。我建议的做法是在Oracle用户的家目录下的~/.bash_profile里固定配置好以下内容export ORACLE_BASE/u01/app/oracle export ORACLE_HOME$ORACLE_BASE/product/11.2.0/dbhome_1 export ORACLE_SIDorcl export PATH$ORACLE_HOME/bin:$PATH export LD_LIBRARY_PATH$ORACLE_HOME/lib:$LD_LIBRARY_PATHORACLE_SID是你实例的名字通常安装时取的orcl或者orclcdb。如果环境变量配置不对即使切换到了oracle用户执行lsnrctl status也会乱套。所以拿到一个新环境第一件事就是看环境变量echo $ORACLE_HOME echo $ORACLE_SID which sqlplus确认这三个都正常再进行后续操作。这也是我接手任何Oracle服务器时的第一个动作能省掉很多莫名奇妙的报错。提示如果环境变量是临时的可以执行source ~/.bash_profile立即生效不用重新登录。2. Linux下启动和关闭Oracle数据库实例2.1 启动数据库实例的完整姿势启动实例分三步先以sysdba身份进入再执行startup最后确认状态。最常见的正确操作是# 切换到oracle用户 su - oracle # 进入sqlplus sqlplus / as sysdba这里强调一下/ as sysdba是操作系统认证只要当前用户是oracle或者dba组里的用户就可以免密登录。这句话写全了是sqlplus username/password as sysdba但我们在Linux服务器本机上用/相当于空用户配合操作系统组认证是最常用的方式。进入sqlplus后先查一下当前实例状态SQL select status from v$instance;如果返回的是OPEN说明数据库已经运行如果没有返回或者连接时提示实例未启动就执行SQL startup正常情况下Oracle会经历启动实例分配SGA启动后台进程装载数据库读取控制文件打开数据库检查数据文件、在线日志看到Database opened.就完成了。有些生产库可能因为参数或数据文件问题需要特殊启动但绝大多数单机环境一条startup就够了。如果你启动时需要限制访问比如维护时不想让业务连进来可以SQL startup restrict; -- 这样只有具备RESTRICTED SESSION权限的用户能连进来启动之后直接退出sqlplusSQL exit此时可以用操作系统进程确认ps -ef | grep smon实例的SMON后台进程是标志看到类似ora_smon_orcl就说明实例进程起来了。如果这一进程在但业务不可用那大概率是监听的问题往下看。2.2 关闭数据库实例的N种方式和区别关闭实例的命令也是进入sqlplus后执行shutdown但参数不同风险完全不同。我把几种方式列成表格你对照着选关闭方式命令行为使用场景normalshutdown normal等待所有会话主动断开后才关闭几乎不用等半天等不完transactionalshutdown transactional等待当前事务完成然后强制断开会话适合短事务业务等待可控immediateshutdown immediate当前正在执行的SQL立即终止回滚未提交事务然后关闭默认推荐日常维护用这个没毛病abortshutdown abort直接杀掉实例进程不做任何回滚应急、实例卡死才用启动后需要实例自动恢复我平时90%的场景都是用shutdown immediatesqlplus / as sysdba SQL shutdown immediate;执行后Oracle会先处理当前未提交的事务然后关闭数据库、卸载数据库最后停止实例。这个过程一般几秒到几分钟如果出现大量活动事务可能稍久。执行完看到ORACLE instance shut down.就成功了。要特别注意生产环境千万不要动不动就用shutdown abort。这个操作相当于直接拉闸断电所有没写盘的东西全部丢失下一次startup的时候Oracle会自己做实例恢复前滚回滚恢复时间长短取决于当时脏数据块多少。我之前见过一个同事每次有问题就abort结果恢复时间比正常关闭慢好几倍而且有概率损坏数据文件概率极低但在生产上承受不起。还有一种比较细腻的方式SQL shutdown transactional;它会先阻止新事务然后等待当前事务完成最后断开会话并关闭。如果事务持续很长时间这个命令会等很久所以如果没有特殊要求还是immediate适合大多数场景。2.3 只启动到mount态的妙用有时候我们不想完全打开数据库比如要做数据文件重命名、控制文件备份、表空间改名这些操作需要在mount态完成。所以启动也可以按阶段来SQL startup nomount; -- 只启动实例没有真实数据库可查 SQL startup mount; -- 挂载控制文件不打开数据文件 SQL startup open; -- 完整打开一条命令startup相当于nomount - mount - open。分阶段启动的好处在于你能在验证每一步成功后再继续也方便恢复场景下操作。我遇到过的一种情况是某次掉电后数据库起不来报控制文件损坏后来通过重新指定控制文件路径并在nomount状态下执行恢复才救回来。如果只会敲startup没有报错理解这种场景基本没得救。另外很多Oracle环境装了gridASM数据库实例的启动要用srvctl来管但在单机非RAC普通文件系统上直接用sqlplus管理就够了。RAC或者12c以后的多租户环境的启停命令更复杂比如CDB和PDB但基础原理一个样startup后还要alter pluggable database all open;等这里不展开。3. Oracle监听器的启动、关闭与状态查看3.1 lsnrctl命令监听器的控制台监听器由另一个命令家族管理叫lsnrctl。最常用的五条lsnrctl start lsnrctl stop lsnrctl status lsnrctl services lsnrctl reload启动监听lsnrctl start正常情况下会看到类似输出... Listening on: (DESCRIPTION(ADDRESS(PROTOCOLtcp)(HOST... Listening on: ... Listening endpoint summary... The command completed successfully说明监听已启动默认端口1521。如果想启动指定名字的监听系统里可以有多个监听器名字自定义用lsnrctl start LISTENER监听器的名字就是listener.ora里配置的名字默认叫LISTENER。在Linux里监听器进程名是tnslsnr确认是否启动ps -ef | grep tnslsnr关闭监听lsnrctl stop查看状态lsnrctl status这个命令最实用它会列出监听的端口、主机名、服务名以及每个服务对应的实例状态。比如看到Service orcl has 1 instance(s). Instance orcl, status READY就说明监听器已经知道了orcl实例并且实例处于READY状态可以正常接客。如果实例状态是UNKNOWN表示监听器里通过静态注册方式记录了实例而不是动态注册。UNKNOWN状态也可以连但一般依赖静态配置。READY才是动态注册的最佳状态。还有一个命令是lsnrctl services它比status更详细显示了每个服务名对应的实例、处理程序DEDICATED或SHARED以及连接数lsnrctl services3.2 监听配置文件listener.ora全解析监听器的所有配置都在$ORACLE_HOME/network/admin/listener.ora这个文件里。一个最简单但完整的文件长这样LISTENER (DESCRIPTION_LIST (DESCRIPTION (ADDRESS (PROTOCOL TCP)(HOST your_host_ip)(PORT 1521)) (ADDRESS (PROTOCOL IPC)(KEY EXTPROC1521)) ) )生产环境还会配静态注册段SID_LIST_LISTENER (SID_LIST (SID_DESC (GLOBAL_DBNAME orcl) (ORACLE_HOME /u01/app/oracle/product/11.2.0/dbhome_1) (SID_NAME orcl) ) )HOST这里要特别注意如果写成了localhost或环回地址远程客户端就永远连不上。必须写能被其他机器访问到的IP或主机名。如果你不确定写什么可以用hostname -i查看本机IP或者干脆写成0.0.0.0监听所有网卡但这样不太安全生产上建议明确IP。好多“监听无法启动”的案例都是文件里配了错误的HOST或者端口被占用。在改配置之前先备份原文件改完后用lsnrctl reload热加载没必要重启监听reload只会重读配置不断当前连接。# 修改配置后执行 lsnrctl reload3.3 查看监听日志和状态排查监听器的运行日志默认写在$ORACLE_HOME/network/log/listener.log里面记录了所有客户端连接尝试、连接成功/失败、监听启停时间。排查问题时直接看这个日志比瞎猜有用得多tail -f $ORACLE_HOME/network/log/listener.log里面常见的记录格式timestamp * service_update * orcl * 12516或者连接报错TNS-12541: TNS:no listener TNS-12514: TNS:listener does not currently know of service requested in connect descriptor当监听启动失败时除了看日志先检查端口占用netstat -tlnp | grep 1521如果端口被其他进程占用了就必须先处理占用进程再启动监听。还有一种典型的坑服务器的/etc/hosts里把主机名解析到了127.0.0.1导致监听器绑定IP失败报TNS-12545: Connect failed because target host or object does not exist。这个要单独排查把主机名对应真实IP加进/etc/hosts。4. 启停顺序、开机自启与实战问题排查4.1 正确的启停顺序少走弯路在Linux下启动时应该先启动监听器再启动数据库实例还是反过来这里先说结论启动顺序先启动数据库实例再启动监听器。原因动态注册机制会由实例的PMON进程向监听器“报告”自己的服务名。如果你先启动监听后启动数据库PMON会在几秒到几十秒内自动注册也没太大问题。但如果先起监听再起库刚起监听的几十秒内客户端可能报“无监听”之后就好了。反之如果库没起来监听器虽然能接收请求但响应不了服务。所以最稳妥的做法是先startup库待库状态变成OPEN后再执行lsnrctl start。关闭顺序先关闭监听器再关闭数据库实例。先断开监听让新连接无法进来然后执行shutdown immediate处理掉已有业务。这样可以避免在关闭过程中还有新会话试图接入从而避免各种诡异的等待和超时。这也是生产变更的标准操作。我写了个简化顺序1. su - oracle 2. sqlplus / as sysdba 3. SQL startup; 4. SQL exit 5. lsnrctl start 6. lsnrctl status关闭1. lsnrctl stop 2. sqlplus / as sysdba 3. SQL shutdown immediate; 4. SQL exit 5. ps -ef | grep smon # 确认进程消失4.2 用dbstart和dbshut实现开机自启如果每次机器重启都要手动敲命令太费劲。Oracle自带dbstart和dbshut脚本放在$ORACLE_HOME/bin目录下。要设置开机自启改/etc/oratab文件# 编辑 /etc/oratab找到这行 orcl:/u01/app/oracle/product/11.2.0/dbhome_1:N # 把最后的 N 改成 Y orcl:/u01/app/oracle/product/11.2.0/dbhome_1:Y然后就可以手动测试$ORACLE_HOME/bin/dbstart $ORACLE_HOMEdbstart会自动读取/etc/oratab中标记为Y的实例执行startup。dbshut同理执行shutdown。注意dbstart只处理数据库实例不处理监听器。监听器的自启要么通过集成到系统服务里要么在/etc/rc.d/rc.local里写一行su - oracle -c /u01/app/oracle/product/11.2.0/dbhome_1/bin/lsnrctl start或者写个简单的systemd service单元但这里更推荐保守的做法rc.local简单可靠。有些新系统默认rc.local权限不足需要先赋权chmod x /etc/rc.d/rc.local如果你有较新版本的Oracle也可以用systemctl自定义服务来管理但传统脚本方式仍然广泛运行在生产环境而且更透明。4.3 常见问题排查实录下面几个坑是我在不同环境里真实遇到过的全部列出来按频率排序问题1监听启动报TNS-12541或TNS-12545现象执行lsnrctl start后报错TNS-12541: TNS:no listener或者连接时报TNS-12545: Connect failed because target host or object does not exist。排查检查listener.ora里的HOST配置是否为服务器真实可访问的IP或主机名。查看/etc/hosts确认主机名解析指向真实IP而不是127.0.0.1。检查端口1521是否被占用netstat -tlnp | grep 1521。看$ORACLE_HOME/network/log/listener.log的报错详情。我遇到最多的是/etc/hosts里主机名被解析到127.0.0.1监听器启动时绑定到回环地址外部怎么连都连不上。解决办法是给/etc/hosts加上一行真实IP和主机名映射。问题2ORA-12514: listener does not currently know of service现象应用连接报ORA-12514但监听状态是正常的。原因实例没有向监听器动态注册或者注册失败。常见于数据库刚启动不到几秒PMON还没来得及注册也可能是SERVICE_NAME配置错误。解决等1030秒再lsnrctl status看看有没有出现对应服务。如果一直不注册执行alter system register;手动触发PMON注册。在listener.ora里加静态注册SID_LIST效果立竿见影。SQL alter system register;问题3lsnrctl命令找不到一看就是环境变量没配好。确认which lsnrctl是否有结果。没有就按前面说的配置PATH$ORACLE_HOME/bin。问题4shutdown immediate卡住不动大多是会话没断干净或者有长事务在回滚。可以先shutdown abort应急再startup让实例自己恢复。但记住这只在万不得已才用。生产环境如果频繁出现要检查是哪个会话一直占用通常用select sid, serial#, status from v$session;查活跃会话而不是一味强关。问题5启动时报ORA-01034或ORA-27101一般是共享内存或信号量问题确认/dev/shm空间是否充足kernel.sem参数是否合理。在虚拟机里很多小配置的Oracle都会遇到这个坑最简单的排查看df -h /dev/shm是不是只有几十MB。如果太小可以挂载大一点的tmpfsmount -o remount,size2G /dev/shm但这只是临时的要持久化得改/etc/fstab。4.4 把启停过程脚本化防手滑每天手动敲这些命令万一哪天在窗口打错字把shutdown abort当成shutdown immediate敲了就够你喝一壶。所以我建议把启停流程写成shell脚本固定在服务器上输入一个参数就能启动或关闭。我自己的脚本大概长这样供参考#!/bin/bash # oracle_service.sh start|stop|status ORACLE_USERoracle ORACLE_HOME/u01/app/oracle/product/11.2.0/dbhome_1 case $1 in start) su - $ORACLE_USER -c $ORACLE_HOME/bin/sqlplus / as sysdba EOF startup; EOF su - $ORACLE_USER -c $ORACLE_HOME/bin/lsnrctl start ;; stop) su - $ORACLE_USER -c $ORACLE_HOME/bin/lsnrctl stop su - $ORACLE_USER -c $ORACLE_HOME/bin/sqlplus / as sysdba EOF shutdown immediate; EOF ;; status) su - $ORACLE_USER -c $ORACLE_HOME/bin/lsnrctl status su - $ORACLE_USER -c $ORACLE_HOME/bin/sqlplus / as sysdba EOF select status from v\\$instance; EOF ;; *) echo Usage: $0 {start|stop|status} exit 1 ;; esac注意脚本里v$instance的$要转义否则会被shell吃掉。这个脚本做得很糙但能用。更完善的可以加日志和状态检查比如等监听状态出现READY再返回成功。总之多一层脚本就少一次手误的机会。5. 写在最后的一点个人体会我在Linux下管Oracle这些年最深的体会是启停Oracle这件事真正的难点从来不是命令本身而是对状态的理解。数据库实例有没有起来监听器有没有起来实例有没有注册到监听器这三个是“三座大山”缺一个业务就连不上。所以每次重启完我习惯性地做三步检查ps -ef | grep smon lsnrctl status sqlplus -L user/passhost:1521/orcl EOF select 1 from dual; EOF三步全过才算真正“服务可用”。最后再分享一个小技巧如果你只想测试实例能不能连接不需要登服务器直接用客户端连接字符串测比如tnsping orcl或者sqlplus system/password//localhost:1521/orcl能连上说明数据库和监听都正常连不上就按本文的思路分层排查。管好Linux下的Oracle说到底就是理清实例、监听、网络这三层关系然后勤看日志。这些经验都是用一次次的故障换来的你要是记住了至少能少踩一半的坑。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →