标题里这个“基于 centOS 11.2.0.4”,其实是把两个东西写在一起了:操作系统是 CentOS 7.x,数据库是 Oracle 11.2.0.4。这套组合在现在的生产环境里还大量存在,尤其是在政企和传统制造业的信息系统里,稳定性优先,升级意愿低。但 CentOS 7 的时代红利正在消退,新机器上装 11.2.0.4 也一年比一年难,依赖包、内核参数、glibc 版本,每一步都可能让你卡在 OUI 的图形界面里进退两难。
静默安装的意义在于:不用 X Window、不用人工盯着进度条、不用一台一台重复点“下一步”。配合一个写好的响应文件和 shell 脚本,一台机器从裸机到数据库可连接,半小时内搞定,剩下时间只需要喝水盯日志。这篇文章不打算讲那些照着 Oracle 官方文档抄的废话,而是把我实际批量部署时用的脚本、踩过的坑、以及为什么这么写的逻辑一次性铺开,适合刚入门的 DBA,也适合那些被分配了“装一套 Oracle 测试库”任务的运维同学。
1. 环境规划:先想清楚,别急着下载
1.1 系统版本匹配,CentOS 7 才是省心的选择
Oracle 11.2.0.4 官方认证的操作系统是 RHEL 6 和 RHEL 7,CentOS 7 因为和 RHEL 7 同源,所以是社区里最主流的部署环境。CentOS 8 或者 Stream 8/9 不是不能跑,而是坑太多:glibc 版本新了,Oracle 自带的很多二进制没有跟着适配;libnsl 和 libaio 这些老库要么改名要么被拆分;11.2 的 OUI 在识别系统发行版时也会直接报 “操作系统版本不支持”。我个人建议,如果是正经交付,优先选 CentOS 7.9 的 2009 镜像,这是这个系列最后一个版本,生命周期长,软件源里的依赖包也齐全。
如果你手里只有 CentOS 8 的机器,想硬装 11.2.0.4,也不是完全没救,核心思路是补齐缺失的兼容库、绕过 OUI 的发行版检测、以及把内核参数手工调到位。但这样做出来的环境,打补丁和做灾备时会有很多意想不到的兼容问题,运维成本不低。所以下面的方案默认基于 CentOS 7.9,其他的版本请自己对照调整。
1.2 用户、目录与安装介质
安装 Oracle 不能直接用 root 跑,必须要建专用用户。规范一点的命名是oracle,属于主组oinstall、辅组dba。为什么要分两个组?因为在真实的多实例环境里,oinstall 管理 Inventory(安装清单),dba 负责数据库操作权限,如果以后要做 ASM 或者 RAC,还会有asmadmin、asmdba这些组,现在把组规划好,后面省得改权限。
目录结构我习惯用经典的 OFA 规范:
mkdir -p /u01/app/oracle/product/11.2.0/dbhome_1 mkdir -p /u01/app/oraInventory chown -R oracle:oinstall /u01/app chmod -R 775 /u01/app安装介质需要准备好两个 zip 包:p13390677_112040_Linux-x86-64_1of7.zip和2of7.zip。把它们解压到同一个 database 目录下。注意有些下载站只提供其中一个分卷,缺了第二卷解压时会报 “not a valid zip file” 或者缺少 runInstaller 文件,这是新手最容易踩的第一个坑。
另外,Oracle 的补丁包下载入口是 My Oracle Support,没有账号的话,在 Oracle 官网的软件交付云也能找到 11.2.0.4 的基础介质。补丁下载页面搜索时优先用补丁号或季度 Bundle Patch 的名称,比按关键字搜索精准得多。
1.3 内核参数、依赖包与 /etc/hosts
系统参数这部分,网上的教程一大把,但我劝你不要照着任何一篇旧文章直接复制,因为 CentOS 7 默认的sysctl.conf和早期版本差异不小。我用的是下面这一组,实测过多次,别改,直接覆盖:
cat >> /etc/sysctl.conf <<'EOF' fs.aio-max-nr = 1048576 fs.file-max = 6815744 kernel.shmall = 2097152 kernel.shmmax = 536870912 kernel.shmmni = 4096 kernel.sem = 250 32000 100 128 net.ipv4.ip_local_port_range = 9000 65500 net.core.rmem_default = 262144 net.core.rmem_max = 4194304 net.core.wmem_default = 262144 net.core.wmem_max = 1048576 EOF sysctl -p这里重点解释两个参数:kernel.shmmax是单个共享内存段的最大字节数,11.2 官方要求最小 536870912(512 MB),我见过有些人为了省事直接设成物理内存的一半大小,其实在生产上是可以的,但如果 SGA 配得比 shmmax 还大,数据库启动时会报 ORA-27102,所以宁可保持官方最小值或者干脆设成物理内存的 60% 以上,别让它成为瓶颈。kernel.sem四个值对应 semmsl、semmns、semopm、semmni,11.2 的官方最低要求是 250 32000 100 128,这个值不能只改第一个,否则并发进程多了很容易出现 “semget: No space left on device” 的奇葩报错。
Oracle 用户还需要修改资源限制,标准配置是:
cat >> /etc/security/limits.conf <<'EOF' oracle soft nproc 2047 oracle hard nproc 16384 oracle soft nofile 1024 oracle hard nofile 65536 oracle soft stack 10240 EOF依赖包方面,CentOS 7 的默认最小化安装缺很多库。Oracle 官方文档列了一长串 RPM,里面有几个是必须装且不能少的,我用一条命令装齐:
yum install -y binutils compat-libcap1 compat-libstdc++-33 gcc gcc-c++ glibc glibc-devel ksh libaio libaio-devel libgcc libstdc++ libstdc++-devel libXext libXtst libX11 libXau libXi make sysstat unixODBC unixODBC-devel这里有个很容易被忽略的问题:glibc-devel不装,后面root.sh执行 relink 时会出现一堆 “gcc: 致命错误:没有输入文件” 之类的诡异错误,而它偏偏不属于“缺少 Oracle 命令”那一类,排查起来非常费时间。ksh也很关键,Oracle 内部很多脚本用 ksh 而不是 bash,缺了会在 DBCA 建库时直接报ins_ctx相关错误。装完所有的 RPM 后,rpm -q验证一遍,别 yum 说成功就完事,有些包会被系统已有的版本覆盖。
还有一个非常基础但总有人忘的:/etc/hosts要把主机名解析配好。CentOS 7 安装完以后,默认的主机名可能是localhost.localdomain,Oracle 11.2 的 OUI 和监听都会做主机名反解,如果 hosts 里没有对应记录,静默安装会卡在 “Listener configuration” 或者 OUI 的 “Check for network” 阶段很久。正确的做法是先把主机名固定住:
hostnamectl set-hostname oracledb echo "192.168.1.10 oracledb" >> /etc/hosts这个动作看着无关紧要,却是很多安装超时问题的根源。
2. 静默安装响应文件才是核心
2.1 db_install.rsp 关键参数逐项解读
静默安装的本质,是把图形安装界面里那些交互问题,提前用响应文件回答掉。Oracle 自带的响应文件模板在解压目录的database/response/db_install.rsp。不建议直接改模板,建议复制一份到 oracle 用户目录下再改,避免权限问题。
最核心的几个参数,按我的实践经验逐个说:
oracle.install.option=INSTALL_DB_SWONLY这个参数决定了只安装数据库软件,不建库。选择 SWONLY 的好处是:把“装软件”和“建库”两个动作分开,出问题的时候定位范围小。建库我用后面的 DBCA 单独做,这样脚本每一步都可以独立重跑。
UNIX_GROUP_NAME=oinstall INVENTORY_LOCATION=/u01/app/oraInventory SELECTED_LANGUAGES=en,en_US ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1 ORACLE_BASE=/u01/app/oracleORACLE_HOME 这个路径建议直接写成 /u01 下,而不是默认的 /home/oracle/product。后续打补丁、跑 root.sh、或者使用 opatch 时,路径越短越不容易出问题。
安装版本和组相关的参数:
oracle.install.db.InstallEdition=EE oracle.install.db.DBA_GROUP=dba oracle.install.db.OPER_GROUP=dba oracle.install.db.OSDBA_GROUP=dba oracle.install.db.OSOPER_GROUP=oper如果你不需要单独的操作员角色,也可以把 OPER_GROUP 也设置成 dba,省得建组。但这里要留意,Oracle 11.2 的 oper 组如果不存在,runInstaller 会直接报错,所以要么建好 oper 组,要么全部写 dba,二选一,不要留空。
安全更新相关:
DECLINE_SECURITY_UPDATES=true这个参数以前很多人不理解为什么必须设成 true。因为如果你的机器没有配置 My Oracle Support 的账号邮箱,或者无法访问外网,OUI 在图形界面里会强制要求填写邮件接收安全更新信息。设为 true 就是告诉 OUI 我不需要在线接收更新,避免网络验证卡住安装。生产环境的安全更新后续都是通过手动下载补丁完成的,这点并不冲突。
模板里还有一些 starterdb 相关的参数,因为我们选的是 SWONLY,那些直接删掉或者留空,不要被模板里的注释误导。一个经典的错误是:明明选了 INSTALL_DB_SWONLY,还在响应文件里填了oracle.install.db.config.starterdb.password,结果 OUI 报参数冲突,安装中止。
完整可用的响应文件内容其实不长,核心就上面这几项。我习惯把响应文件放在/home/oracle/db_install.rsp,并且改完以后用chown oracle:oinstall保证属主正确。
2.2 执行 runInstaller 与 root.sh 的正确顺序
响应文件准备好后,切换到 oracle 用户执行:
su - oracle cd /tmp/database ./runInstaller -silent -responseFile /home/oracle/db_install.rsp -ignorePrereq-ignorePrereq这个参数,很多人纠结要不要加。我的观点是:CentOS 7 上跑 11.2.0.4,几乎必然会在“操作系统平台”这个预检查上出警告,因为 OUI 内部的认证列表只认 RHEL,不认 CentOS。加-ignorePrereq可以跳过检查,但如果你的依赖包真的没装齐,它也会一并跳过,导致后面编译报错。所以更稳妥的做法是先手动把依赖包检查好,再加这个参数跳过发行版识别;如果你有耐心,可以设置环境变量CV_ASSUME_DISTID=RHEL7来让 OUI 认为自己是在 RHEL7 上安装,效果一样,但不会跳过真正的包检查。
安装过程大约需要 15 到 25 分钟,取决于磁盘速度和 CPU。终端会打印日志路径和进度,看到 “Successfully executed” 之类字样说明软件部分安装完成。这时候先别急着建库,有一个步骤是必须手动做的:以 root 用户执行$ORACLE_HOME/root.sh。这个脚本会创建/etc/oratab、配置环境变量、relink 可执行文件。忘记执行 root.sh 的后果是:DBCA 建库时总有权限报错,监听也起不来,而且错误信息五花八门,特别误导人。
执行前先看一眼 root.sh 有没有可执行权限,用 bash 强制运行更稳妥:
sudo bash /u01/app/oracle/product/11.2.0/dbhome_1/root.shroot.sh 运行完后,安装环节基本结束。我习惯顺手检查一下安装日志里有没有 WARNING,比如机制类的告警可以忽略,但跟 “make” 或 “link” 相关的错误必须处理,否则后面打补丁时会爆发。日志目录在/u01/app/oraInventory/logs下,按时间戳找最新的那一份。
3. 静默建库、监听与初始化参数
3.1 用 DBCA 一行命令完成建库
软件装好后,下一步是建库。比起再写一遍建库响应文件,我更推荐直接用 DBCA 的命令行参数,可读性好,参数清晰,出错了也容易定位。Oracle 11.2 的 DBCA 支持-silent模式,配合-createDatabase参数一行搞定:
su - oracle dbca -silent -createDatabase \ -templateName General_Purpose.dbc \ -gdbname orcl \ -sid orcl \ -characterSet AL32UTF8 \ -memoryPercentage 30 \ -emConfiguration NONE \ -datafileDestination /u01/app/oracle/oradata \ -recoveryAreaDestination /u01/app/oracle/fast_recovery_area \ -storageType FS \ -sysPassword Oracle123 \ -systemPassword Oracle123 \ -sampleSchema true几个参数的注意点:
-characterSet AL32UTF8是字符集选项。如果不能确定业务以后是否需要存中文,直接用 AL32UTF8 是最稳妥的,虽然比 ZHS16GBK 浪费一点空间,但兼容性最好。如果在响应文件里漏了这个参数,DBCA 会按系统默认创建一个 US7ASCII 的库,等业务上线再改字符集就是灾难级别的操作。
-memoryPercentage 30表示把宿主机物理内存的 30% 分给 SGA+PGA。如果机器是 16G 内存,这里就会配到 4.8G 左右,不要贪多,数据库后面还要留内存给操作系统和文件缓存。需要精确控制时,可以改用-memorySize参数指定具体 MB 数。
-sampleSchema true可选,如果你要的是干净的生产库,建议设 false,省得里面多出一堆演示表。
DBCA 建库过程中,会调用 Oracle 内部的sql.bsq脚本创建数据字典,这个过程比较耗时,20 分钟左右。期间不要中断,否则再次建库时会因为残留的临时文件而失败。如果中途报错,先清理/u01/app/oracle/admin下对应的目录再重跑。
建完后用ps -ef | grep pmon确认实例进程存在,然后连接测试:
sqlplus / as sysdba select status from v$instance;3.2 监听配置与默认端口修改
Oracle 安装软件时不会自动配置监听,除非你手动跑过 netca。静默场景下,用 netca 一行命令最省事:
netca -silent -responsefile $ORACLE_HOME/network/install/netca.rsp这条命令会按照默认规则在本机监听 1521 端口,监听名称 LISTENER。很多教程会漏掉这一步,直接建完库就试图从客户端连接,结果报ORA-12541: TNS-无监听程序,其实不是库有问题,而是根本没有监听进程。务必在 DBCA 建库前把监听配好,这样建库时 DBCA 才能自动把实例注册到监听。
如果要修改默认监听端口,比如业务要求不能占 1521,最简单的做法是直接编辑$ORACLE_HOME/network/admin/listener.ora:
LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = oracledb)(PORT = 1522)) ) )改完执行:
lsnrctl reload然后确认监听状态:
lsnrctl status LISTENER这里有一个容易踩的坑:如果你改了监听端口,tnsnames.ora里的端口也要同步改,否则客户端连接时仍然是走默认的 1521。服务端连接测试倒是无所谓,因为本地 sqlplus 走的是 BEQUEATH 协议,压根不经过监听。但客户端、应用连接串里的host:1521/orcl就会连不到。
3.3 建库后值得顺手落地的安全参数
建库只是开始,等保测评和公司安全策略通常对数据库实例有不少要求。我这里列几个常见的调整项,用 sys 账号执行:
alter system set audit_trail=DB scope=spfile; alter system set audit_sys_operations=TRUE scope=spfile; alter profile default limit FAILED_LOGIN_ATTEMPTS 5; alter profile default limit PASSWORD_LIFE_TIME 90; alter profile default limit PASSWORD_GRACE_TIME 7; alter profile default limit PASSWORD_REUSE_TIME 180; alter system set resource_limit=TRUE scope=both;解释一下为什么是这些参数:audit_trail=DB是把审计日志写入数据库内部的审计表,而不是写操作系统文件,这样等保检查时可以直接查询dba_audit_trail;audit_sys_operations=TRUE表示对 sysdba/sysoper 这种管理员操作也记审计,这条在很多检查项里是必选项。密码策略设置主要是防止弱口令和长期不改密。resource_limit=TRUE的作用是让 profile 中关于会话资源限制的配置真正生效,特别是配合 FAILED_LOGIN_ATTEMPTS 使用。
注意audit_trail是静态参数,改完需要重启实例才生效。如果不想重启,也可以把审计初始化参数保持默认,等业务维护窗口再改,但千万不要为了应付检查直接改完不重启,那样审计不会启用,反而在测评时露馅。
4. 补丁应用:OJVM 与 PSU 的常见操作
4.1 为什么 11.2.0.4 特别关注 OJVM
Oracle 11.2.0.4 的数据库内置了一个 Java VM 组件,这个组件在代码中主要负责 PL/SQL 的 Java 存储过程、以及部分 Oracle 特性如 XDK 和 ORB。这个 Java 虚拟机因为历史原因,安全漏洞频率很高,几乎是每季度安全公告的常客,所以有专门的 OJVM 补丁包,与普通的 Database PSU / BP 分开发布。
很多企业装完 11.2.0.4 后就不管了,等安全扫描扫出一堆 CVE,再回头找补丁,发现版本已经隔了大半年。因此我建议的节奏是:安装完数据库软件后,直接把当季最新的 Database Proactive Bundle Patch 和对应的 OJVM 补丁一起下载,打完了再做建库和业务部署,这样生产环境的初始安全基线是干净的。补丁下载路径在 My Oracle Support 的 Patch 搜索里,输入补丁号或选择产品 “Oracle Database” + 版本 11.2.0.4 + 平台 Linux x86-64,就能看到当季的推荐补丁集。
OJVM 补丁的命名一般是p???????_112040_Linux-x86-64.zip,安装前一定要看补丁包里的 README,因为 11.2 的 OJVM 补丁在不同小版本上,要求的前置补丁可能不同。最稳妥的做法是在执行opatch apply前,先用opatch lsinventory检查当前环境的补丁基线,确认 OPatch 工具本身的版本也满足要求。OPatch 版本太老,打新补丁时会有OPatch version mismatch的提示,解决办法就是去补丁页下载最新版本的 OPatch 工具,替换到$ORACLE_HOME/OPatch目录。
4.2 opatch 打补丁的标准流程
假设你已经下载好了补丁包,比如 OJVM 补丁p34044356_112040_Linux-x86-64.zip,把它传到服务器上,解压到/tmp/patch目录。打补丁的全过程我建议按这个顺序:
su - oracle cd $ORACLE_HOME/OPatch ./opatch lsinventory确认当前补丁情况后,解除补丁文件权限,然后:
cd /tmp/patch $ORACLE_HOME/OPatch/opatch apply .如果应用的补丁是 OJVM 类,opatch 应用过程会 relink 数据库软件中与 Java 相关的可执行文件,耗时 10 分钟左右。这期间不要并发执行其他安装操作,也不要用kill -9中断 opatch,否则会导致$ORACLE_HOME下的二进制文件处于不完整状态,后续只能通过重新解压介质恢复,非常麻烦。
opatch apply 完成后,还要做数据库侧的脚本操作。不同类型的补丁要求不同,OJVM 补丁一般会要求你关闭数据库实例,以 startup upgrade 模式启动,然后执行补丁包中指定的 SQL 脚本,最后重启实例。具体执行哪些脚本,严格以 README 为准,不要凭记忆照搬别的补丁流程。如果漏了 SQL 脚本,补丁状态在dba_registry里可能显示无效,安全扫描依然会报警。
打完补丁后,重启监听和实例,再次检查:
sqlplus / as sysdba select comp_name, version, status from dba_registry;凡是状态不是VALID的组件,都要回过去查原因。这一步是验收的关键,因为 opatch 显示 “OPatch succeeded” 只代表文件层和应用层成功了,不代表数据库内部组件升级成功。
5. 一套可复制的静默安装脚本
5.1 脚本完整内容与使用说明
把前面所有步骤串成一个脚本,才是“静默安装脚本”的真正价值。下面是精简版的脚本骨架,按顺序执行,注释标明了每一步的作用:
#!/bin/bash # 一键静默安装 Oracle 11.2.0.4 on CentOS 7.9 # 使用方法:root 用户执行,准备安装介质后手动改下面变量 ORACLE_BASE=/u01/app/oracle ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1 INVENTORY_DIR=/u01/app/oraInventory SOFTWARE_DIR=/root/software # 存放 zip 包的目录 RESP_FILE=/home/oracle/db_install.rsp # 预先准备好的响应文件 SID=orcl SYSPASS=Oracle123 SYSTEMPASS=Oracle123 set -e echo "================ 1. 安装依赖包 ================" yum install -y binutils compat-libcap1 compat-libstdc++-33 \ gcc gcc-c++ glibc glibc-devel ksh libaio libaio-devel \ libgcc libstdc++ libstdc++-devel libXext libXtst libX11 \ libXau libXi make sysstat unixODBC unixODBC-devel echo "================ 2. 修改内核参数 ================" cat >> /etc/sysctl.conf <<'EOF' fs.aio-max-nr = 1048576 fs.file-max = 6815744 kernel.shmall = 2097152 kernel.shmmax = 536870912 kernel.shmmni = 4096 kernel.sem = 250 32000 100 128 net.ipv4.ip_local_port_range = 9000 65500 net.core.rmem_default = 262144 net.core.rmem_max = 4194304 net.core.wmem_default = 262144 net.core.wmem_max = 1048576 EOF sysctl -p echo "================ 3. 创建用户与目录 ================" groupadd -g 54321 oinstall groupadd -g 54322 dba useradd -u 54321 -g oinstall -G dba oracle mkdir -p $ORACLE_HOME $INVENTORY_DIR chown -R oracle:oinstall /u01/app chmod -R 775 /u01/app echo "================ 4. 配置 limits 和 hosts ================" cat >> /etc/security/limits.conf <<'EOF' oracle soft nproc 2047 oracle hard nproc 16384 oracle soft nofile 1024 oracle hard nofile 65536 oracle soft stack 10240 EOF # 注意:把替换成你的真实 IP echo "192.168.1.10 oracledb" >> /etc/hosts hostnamectl set-hostname oracledb echo "================ 5. 解压安装介质 ================" cd $SOFTWARE_DIR unzip -q p13390677_112040_Linux-x86-64_1of7.zip unzip -q p13390677_112040_Linux-x86-64_2of7.zip chown -R oracle:oinstall /root/software/database echo "================ 6. 静默安装数据库软件 ================" su - oracle -c "cd $SOFTWARE_DIR/database && ./runInstaller -silent -responseFile $RESP_FILE -ignorePrereq" bash $ORACLE_HOME/root.sh echo "================ 7. 静默配置监听 ================" su - oracle -c "netca -silent -responsefile $ORACLE_HOME/network/install/netca.rsp" echo "================ 8. 静默建库 ================" su - oracle -c "dbca -silent -createDatabase -templateName General_Purpose.dbc -gdbname $SID -sid $SID -characterSet AL32UTF8 -memoryPercentage 30 -emConfiguration NONE -datafileDestination $ORACLE_BASE/oradata -recoveryAreaDestination $ORACLE_BASE/fast_recovery_area -storageType FS -sysPassword $SYSPASS -systemPassword $SYSTEMPASS -sampleSchema false" echo "================ 9. 验证 ================" su - oracle -c "sqlplus / as sysdba <<'EOF' select status from v\$instance; EOF"这个脚本不是万能的,它在设计上假设你已经把db_install.rsp根据上一节的内容准备好了,并且放在了/home/oracle下。如果有密码策略更严格的环境,记得把SYSPASS、SYSTEMPASS按规则改掉,别用脚本里默认的弱口令。
5.2 安装现场最容易翻车的三个地方
脚本写好后,批量执行时反而不会在“技术难点”上出问题,真正翻车往往在小细节。
第一个翻车点是set -e。这行虽然能让脚本在任一环节失败时立即退出,但 Oracle 的安装日志里很多非致命错误也是通过非 0 返回码表现的,比如 root.sh 在某些环境下即使执行成功,也可能返回非 0。所以我在关键步骤后没有完全依赖返回值,而是加了人工日志检查点。如果你拿到脚本要改,千万别全局加set -e后就不管了,至少要在 runInstaller 和 dbca 之后,主动tail一下日志再决定是否继续。
第二个容易翻车的点是磁盘空间。CentOS 7 默认的/分区一般只有 50G,装完系统、解压两个 zip 包、再加上数据库软件和建库文件,很容易把根分区塞满。安装介质解压前先用df -h /tmp和df -h /u01看一下,如果空间不足,要么把软件目录放到一个独立的大分区,要么先清理 yum 缓存。不然 runInstaller 会在写文件时突然中断,错误信息居然还是 “磁盘空间不足” 但后续日志可能直接卡死,很难看。
第三个翻车点是 sudo 和 su 的交互。脚本里用su - oracle -c执行命令,但 Oracle 的环境变量ORACLE_HOME、PATH还没有写入~oracle/.bash_profile时,DBCA 和 netca 是找不到dbca命令的。所以在脚本正式跑之前,先手动在/home/oracle/.bash_profile里把下面两行加上,否则脚本第 8 步必然失败:
export ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1 export PATH=$ORACLE_HOME/bin:$PATH export ORACLE_SID=orcl这三个点看起来都不算技术难题,但它们的特点是:一旦出问题,定位成本高、重跑成本更高。批量部署时先把一台机器跑到全流程结束,再铺开剩下的机器。
6. 常见报错与排查速查
6.1 监听起不来与 ORA-12518
监听起不来是最常见的安装后问题。先区分类型:lsnrctl status报TNS-12545: Connect failed because target host or object does not exist时,基本都是 listener.ora 里的 HOST 写成了无法解析的主机名。CentOS 7 的/etc/hosts如果只有localhost,而监听写的是完整主机名,就会这样。解决办法是把/etc/hosts里的 IP 和主机名对应关系补齐,然后lsnrctl reload。
如果是客户端连接时报ORA-12518: TNS:listener could not hand off client connection,这个我专门展开讲一下。它最典型的原因是数据库实例的processes参数被耗尽了。11.2 默认的 processes 是 150,听起来不少,但生产库跑起来后,连接池、定时任务、DBA 运维连接,很快就逼近上限。检查方法:
select count(*) from v$process; show parameter processes;如果两者相等或者接近,就要调大 processes:
alter system set processes=300 scope=spfile; shutdown immediate; startup;这个参数虽然是动态参数,但设置后要重启才生效。另外,监听日志恢复区空间满也会导致连接被拒,但报的错通常是别的提示,所以排查顺序建议是:先看监听状态、再看 processes、最后看磁盘。
还有一种情况是操作系统层面的进程数限制,如果你改了limits.conf里的 nproc=16384,但当前 ssh 会话没有重新登录,ulimit 还是旧的 1024,高并发连接时会有大量连接失败。这属于“无头冤案”,排查三遍 SQL 都找不到问题,实际上是最基础的 ulimit。
6.2 SQL*Plus 登录卡顿的真实原因
另一个高频问题是:sqlplus 连上数据库要等几十秒,但连上以后一切正常。这个问题在 CentOS 7 上尤其常见,根源几乎都是 DNS 反向解析。
Oracle 在客户端建立连接、服务端验证身份时,都会尝试把客户端 IP 反解成主机名。如果sqlnet.ora里没有把验证方式限制住,系统就会走 DNS 查询,DNS 超时或没有 PTR 记录时,表现就是登录慢。处理手段是在$ORACLE_HOME/network/admin/sqlnet.ora里加:
SQLNET.INBOUND_CONNECT_TIMEOUT=10 SQLNET.RECV_TIMEOUT=10 SQLNET.SEND_TIMEOUT=10这几个参数可以避免客户端建立连接后长时间无响应导致服务进程挂死。但要注意,光加超时并不能解决 DNS 反解本身。如果服务器本身没有内网 DNS,最直接的办法是让tnanames.ora和listener.ora里都用 IP 而不是主机名,同时确保客户端连接串里也写 IP。
另外,监听日志文件如果长期不轮转,文件体积涨到几十个 GB,lsnrctl每次读写日志都会卡顿,数据库登录也就跟着慢。这个问题在运维中会被忽略,日志本身只增不减,应用连接偶尔超时都被误判为网络问题。我的习惯是给监听日志单独建目录,然后让 log.xml 每天轮转一次,可以通过设置log_status=ON的 listener.ora 参数和LOGGING的级别来控制。
6.3 补丁、扩容与运维小技巧
补丁应用完成后,如果安全扫描还报 Java 相关漏洞,先确认opatch lsinventory的补丁列表包含了 OJVM 补丁,再看dba_registry的组件是否 VALID。两个状态缺一个都不算数。如果发现 OJVM 补丁明明打了但注册表里还显示版本旧,大概率是漏执行了 SQL 脚本,或者执行脚本后没有重启数据库,重新按 README 走一遍即可。
集群磁盘空间不足是另一个需要提一下的运维场景。CentOS 7 的根分区扩容,如果当初用了 LVM,可以这样扩展:先vgextend把新磁盘加进卷组,再lvextend -L +20G /dev/mapper/centos-root,最后xfs_growfs /让文件系统识别新空间。Oracle 数据文件所在的分区同样适用这套逻辑。千万不要在文件系统层直接resize2fs,CentOS 7 默认是 xfs,resize2fs 不适用于它。
再补充两个数据库日常使用的小技巧。判断一个字段是否“像数字”,Oracle 没有内置 is_number 函数,可以用正则:
select case when regexp_like(col, '^[+-]?[0-9]*\.?[0-9]+$') then '数字' else '非数字' end as flag from dual;这种方式比to_number(col)套decode靠谱得多,因为to_number遇到非法字符会直接抛 ORA-01722,不会友好地返回一个空值。
Python 连接 Oracle 这块,以前主流是 cx_Oracle,现在推荐用新版python-oracledb,接口几乎一致:
import oracledb conn = oracledb.connect(user="scott", password="tiger", dsn="192.168.1.10:1521/orcl") cur = conn.cursor() cur.execute("select sysdate from dual") print(cur.fetchone())如果遇到DPI-1047之类的错误,多半是缺 Oracle Instant Client 的库,把 Instant Client 解压路径加入LD_LIBRARY_PATH即可。
这些内容看着零散,但都是安装完数据库后最常被问到的方向。文章写到这,安装、建库、打补丁、排查、运维的闭环已经基本完整了。我个人在实际操作中的体会是:静默安装脚本最值钱的部分不是那几行命令,而是把顺序固定下来、把参数显式调好、把每一步的日志留清楚。只要有一台机器能从头跑到尾,后面的机器就只是复制粘贴的问题。真要遇到环境差异,就回到第 6 节的速查表逐项比对,问题一般不会卡超过半小时。如果还想在这个脚本上继续扩展,下一步可以让它支持自动化巡检、补丁基线校验,甚至对接外部的交付平台,这些以后有机会再写。