RedHat 7.9 上 Oracle 11gR2 单机一键安装实战指南

RedHat 7.9 上 Oracle 11gR2 单机一键安装实战指南
1. 项目概述为什么在 RedHat 7.9 上搞 Oracle 11gR2 单机“一键安装”不是偷懒而是刚需你是不是也经历过——花一整天配环境结果卡在ora-28547: connection to server failed, probable oracle net admin error这个报错上反复检查listener.ora和tnsnames.ora删了重写、改了再试最后发现是/etc/hosts里少了一行127.0.0.1 localhost.localdomain localhost或者刚解压完linux.x64_11gR2_database.ziprunInstaller一跑就弹出Error in invoking target agent nmhs of makefile查半天才知道是缺libaio-devel和ksh而yum install -y ksh在 RHEL 7.9 的默认源里根本找不到包这些不是个别现象而是 Oracle 11gR2 在 RedHat 7.9 上部署时几乎必踩的“标准流程”。RedHat 7.9 作为企业级长期支持版本内核3.10.0、glibc2.17、systemd 架构与 Oracle 11gR22009年发布原生适配 RHEL 5/6存在天然代际断层。官方早已停止对 11gR2 的主流支持但大量老系统、财务软件比如你搜到的 a9财务管理单机u盘版、教学实验、历史数据迁移场景仍强依赖它。这时候“一键安装”不是图省事而是把三年运维踩过的坑、五次重装验证过的参数、八套不同硬件环境调优过的内核参数全部固化成可复用、可审计、可回滚的脚本逻辑。它解决的不是“能不能装”而是“能不能在 20 分钟内让一个没碰过 Oracle 的 Linux 新手在一台干净的 RHEL 7.9 虚拟机上得到一个监听正常、实例可连、sqlplus / as sysdba能进、SELECT SYSDATE FROM DUAL;能跑通的最小可用单机环境”。关键词RedHat、Oracle 11GR2、单机、一键安装每一个都指向明确约束操作系统锁定为 RHEL 7.9非 CentOS 或 AlmaLinux数据库版本锁定为 11.2.0.4这是 11gR2 最终补丁集必须用部署形态限定为单机无 RAC、无 Data Guard交付目标是“开箱即用”的最小可行实例。这不是 Docker 容器化那种轻量封装而是对传统 Oracle 安装全流程的深度自动化重构——从内核参数预调优、用户组创建、目录结构初始化、静默响应文件生成、到监听器与数据库实例的自动注册与启动全部由 Shell 脚本驱动且每一步都带校验和日志回溯。我试过用 Ansible 做但 Shell 更直接、更可控、更易调试我也试过用 VirtualBox 打包 OVA但客户要的是“在他们自己的物理服务器上跑”所以脚本必须能适应不同磁盘布局、不同网络配置。这个项目的核心价值从来不是炫技而是把 Oracle 安装这件反人类的事变成一件可预测、可复制、可交付的工程动作。2. 整体设计思路与方案选型为什么不用图形界面、不走 Oracle Universal Installer 交互流程2.1 放弃图形化安装器的底层逻辑Oracle 官方推荐的图形化安装方式OUI在 RHEL 7.9 上本身就是个陷阱。它依赖 X11 转发而生产环境服务器通常关闭 GUI它需要手动点击“下一步”无法集成到 CI/CD 流水线最致命的是它的错误提示极其模糊——比如Error in invoking target irman ioracle实际原因可能是gcc版本过高RHEL 7.9 默认 gcc 4.8.5而 11gR2 认证最高只到 4.4也可能是libstdc版本不匹配OUI 不会告诉你具体是哪个.so文件缺失。我们选择彻底绕过 OUI全程使用 Oracle 提供的静默安装模式Silent Mode。这要求我们精确构造response file响应文件而这个文件不是随便填几个值就能用的。比如oracle.install.db.config.starterdb.globalDBName字段如果填orcl安装后实例名SID默认也是orcl但很多老应用硬编码了ORCL全大写而 Linux 文件系统区分大小写$ORACLE_HOME/dbs/initORCL.ora和initorcl.ora是两个文件稍不注意就导致ORA-01078: failure in processing system parameters。所以我们的响应文件模板里所有涉及名称的字段globalDBName、sid、sysPassword、systemPassword都强制小写并在脚本中加入校验if [[ $ORACLE_SID ! ${ORACLE_SID,,} ]]; then echo SID must be lowercase; exit 1; fi。这种细节OUI 图形界面根本不会提醒你。2.2 为什么坚持用 Shell 脚本而非容器或虚拟机镜像你可能看到热词里有“下载 docker 安装oracle 11g r2 所需的tar”但 Docker 对 Oracle 11gR2 的支持非常脆弱。Oracle 官方从未认证过 Docker 容器运行 11gR2其内存管理SGA/PGA严重依赖宿主机内核的shmmax和shmall参数而 Docker 的--shm-size只能控制/dev/shm大小无法修改内核参数。实测下来当容器内sga_target设为 1G宿主机kernel.shmmax6871947673664G时Oracle 实例能启动但一旦宿主机shmmax被其他进程占用变小就会报ORA-27102: out of memory。而我们的 Shell 脚本在安装前第一件事就是检查并设置内核参数echo kernel.shmmax 68719476736 /etc/sysctl.conf sysctl -p。同样虚拟机镜像如 OVA看似方便但它把整个 OS 环境打包固化无法适应客户现场千差万别的磁盘命名/dev/sdb1vs/dev/nvme0n1p1、网卡名eth0vsens192、SELinux 状态enforcingvspermissive。我们的脚本在开头就做三件事lsblk获取磁盘信息、ip link show获取网卡名、getenforce检查 SELinux然后动态生成/etc/fstab挂载点和监听器配置。这才是真正面向生产环境的设计。2.3 “单机”定义的严格边界与技术取舍标题里的“单机”二字决定了我们不做任何高可用或分布式扩展。这意味着不配置 ASMASM 是 Oracle 自己的卷管理器对单机纯属杀鸡用牛刀。我们直接使用文件系统FS存储db_create_file_dest指向/u01/app/oracle/oradata所有数据文件、控制文件、重做日志都放这里。这样CREATE TABLESPACE语句无需指定DATAFILE DATA直接DATAFILE /u01/app/oracle/oradata/orcl/users01.dbf兼容性最好。不启用归档模式archive log list显示No。虽然归档对备份很重要但 11gR2 单机最常见的用途是开发测试开启归档会额外占用磁盘并增加log_archive_dest_1配置复杂度。我们的脚本默认LOG_MODENOARCHIVELOG如果用户需要只需改一行sed -i s/NOARCHIVELOG/ARCHIVELOG/g response/db_install.rsp。监听器仅绑定本地回环listener.ora中HOST localhost而非HOST $(hostname -i)。因为 RHEL 7.9 的hostname -i可能返回 IPv6 地址或多个 IP导致监听器启动失败。我们只要求sqlplus system/oraclelocalhost:1521/orcl能连外部网络访问由客户自己通过防火墙策略放开不越界。2.4 一键脚本的分层架构从 OS 层到 DB 层的四道关卡整个脚本不是一坨大泥球而是清晰分为四层每层失败都独立退出并打印错误码OS Pre-check Layer检查uname -r是否为3.10.0-*el7*getconf LONG_BIT是否为 64free -g | awk NR2{print $2}是否 ≥2内存df -h /u01 | awk NR2{print $4} | sed s/G//是否 ≥15磁盘空闲。任一不满足echo OS check failed: kernel version mismatch exit 101。Package User Layeryum install -y binutils compat-libcap1 gcc-c glibc-devel ksh libaio-devel make sysstat unixODBC-devel。特别注意kshRHEL 7.9 默认源无此包必须先yum install -y epel-release yum install -y ksh。用户创建用groupadd -g 54321 oinstall groupadd -g 54322 dba useradd -u 54321 -g oinstall -G dba oracleUID/GID 强制固定避免与客户现有用户冲突。Oracle Home Response Layer解压database/到/u01/app/oracle/product/11.2.0/db_1用sed动态生成db_install.rsp关键字段如oracle.install.optionINSTALL_DB_SWONLY只装软件不建库、DECLINE_SECURITY_UPDATEStrue跳过安全更新检查否则静默安装会卡住。DB Creation Post-config LayerrunInstaller -silent -responseFile /tmp/db_install.rsp后用dbca -silent -createDatabase建库最后执行cat /tmp/post_db.sql | sqlplus / as sysdba运行后置 SQL如创建scott用户、解锁hr用户。每一层都有set -e出错即停和echo [INFO] Layer X completed日志。3. 核心细节解析与实操要点那些官网文档绝不会写的魔鬼参数3.1 内核参数调优不是照抄/etc/sysctl.conf而是动态计算Oracle 11gR2 对共享内存的要求是硬性的。kernel.shmmax必须 ≥ SGA_MAX_SIZE而kernel.shmall必须 ≥ SGA_MAX_SIZE / PAGE_SIZE。RHEL 7.9 的默认PAGE_SIZE是 4096 字节。假设我们计划 SGA 为 2G2147483648 字节那么kernel.shmmax至少为2147483648kernel.shmall至少为2147483648 / 4096 524288但直接设死值不灵活。我们的脚本会先grep MemTotal /proc/meminfo | awk {print $2}获取总内存KB然后按 60% 计算 SGA 目标值TOTAL_MEM_KB$(grep MemTotal /proc/meminfo | awk {print $2}); SGA_KB$((TOTAL_MEM_KB * 60 / 100))。再据此推导shmmax和shmallSHMMAX$((SGA_KB * 1024)) SHMALL$((SHMMAX / 4096)) echo kernel.shmmax $SHMMAX /etc/sysctl.conf echo kernel.shmall $SHMALL /etc/sysctl.conf注意shmall的单位是“页”不是字节。很多教程直接写kernel.shmall 2097152这是按 8G 内存算的如果你的机器只有 4G这个值就过大反而触发内核警告。必须动态计算。3.2 用户资源限制limits.conf里的数字不是拍脑袋定的/etc/security/limits.conf中oracle soft nofile 1024和oracle hard nofile 65536是常见配置但nofile打开文件数只是冰山一角。Oracle 进程还需要大量nproc进程数和stack栈大小。11gR2 文档要求stack至少 10240 KB但 RHEL 7.9 默认是 8192 KB。我们的脚本会写入oracle soft nproc 2047 oracle hard nproc 16384 oracle soft stack 10240 oracle hard stack 32768 oracle soft memlock 32768 oracle hard memlock 32768其中memlock是关键。Oracle 启动时会尝试mlock()锁定 SGA 内存防止被 swap。如果memlock太小startup就会报ORA-27102: out of memory。32768单位是 KB即 32MB足够锁住 2G SGA 的页表项。这个值不能设为unlimited否则 systemd 会忽略它。3.3 响应文件db_install.rsp的 7 个必填字段与 3 个隐藏陷阱Oracle 的响应文件有上百个字段但对单机静默安装以下 7 个是绝对核心缺一不可oracle.install.optionINSTALL_DB_SWONLY只装软件ORACLE_HOSTNAMElocalhost必须是localhost不能是127.0.0.1否则 OUI 解析失败UNIX_GROUP_NAMEoinstallINVENTORY_LOCATION/u01/app/oraInventorySELECTED_LANGUAGESen,zh_CN中英文双语避免字符集问题ORACLE_HOME/u01/app/oracle/product/11.2.0/db_1ORACLE_BASE/u01/app/oracle三个隐藏陷阱陷阱1DECLINE_SECURITY_UPDATES。如果设为false安装程序会尝试连接 Oracle 服务器检查更新超时后卡住 300 秒。必须设为true。陷阱2SECURITY_UPDATES_VIA_MYORACLESUPPORTfalse。与上一条配套否则仍会尝试连接。陷阱3oracle.installer.autoupdates.optionSKIP_UPDATES。跳过自动更新检查三重保险。我们的脚本用cat /tmp/db_install.rsp EOF生成确保每个字段独占一行无空格缩进因为 OUI 对格式极其敏感。3.4 数据库创建脚本dbca.rsp的字符集与内存参数黄金组合dbca -silent -createDatabase的响应文件比安装文件更难搞。关键字段GDBNAMEorcl全局数据库名SIDorcl实例名必须与 GDBNAME 一致TEMPLATENAMEGeneral_Purpose.dbc模板名必须是$ORACLE_HOME/assistants/dbca/templates/下真实存在的文件名SYSPASSWORDoracleSYS 密码明文但脚本执行完立即rm -f /tmp/dbca.rspSYSTEMPASSWORDoracleDATAFILEDESTINATION/u01/app/oracle/oradataRECOVERYAREADESTINATION/u01/app/oracle/fast_recovery_areaCHARACTERSETAL32UTF8强烈推荐兼容中文NATIONALCHARACTERSETAL16UTF16MEMORYPERCENTAGE40内存百分比不是绝对值注意MEMORYPERCENTAGE40表示将 40% 的物理内存分配给 SGAPGA。这比硬编码SGA_TARGET2G更健壮因为脚本会先free -m | awk NR2{print $2}获取内存 MB 数再计算SGA_TARGET$((MEM_MB * 40 / 100))然后写入init.ora。很多教程直接写死sga_target2G在 8G 内存机器上没问题但在 32G 机器上就浪费了 24G 内存。4. 实操过程与核心环节实现从空白 RHEL 7.9 到SELECT SYSDATE FROM DUAL的完整流水线4.1 环境准备5 分钟搞定一台干净的 RHEL 7.9 虚拟机我们以 VirtualBox 为例但步骤适用于任何平台。下载rhel-server-7.9-x86_64-dvd.iso注意不是boot.iso新建虚拟机内存至少 4096 MB2G 给 Oracle2G 给 OS硬盘动态分配至少 40 GB/u01需要 20G网络NAT 模式即可确保能ping www.oracle.com用于yum update安装时选择“Minimal Install”不要选“Server with GUI”。安装完成后第一件事是sudo su -切换 root执行# 关闭防火墙单机开发环境简化网络配置 systemctl stop firewalld systemctl disable firewalld # 关闭 SELinux避免 Permission denied 报错 sed -i s/SELINUXenforcing/SELINUXdisabled/g /etc/selinux/config setenforce 0 # 更新系统 yum update -y # 安装基础工具 yum install -y wget vim net-tools bash-completion # 创建 Oracle 安装目录 mkdir -p /u01/app/oracle/product/11.2.0/db_1 mkdir -p /u01/app/oracle/oradata mkdir -p /u01/app/oracle/fast_recovery_area chown -R oracle:oinstall /u01 chmod -R 775 /u01提示chown -R oracle:oinstall /u01必须在创建用户前执行不顺序错了。正确顺序是先useradd创建用户再chown。否则/u01所有者是 rootoracle用户无法写入。这是新手最常犯的错误。4.2 下载与解压 Oracle 11gR2 安装包避开官网的“下载陷阱”Oracle 官网下载 11gR2 需要 Oracle 账号且链接极深。更麻烦的是官网提供的是linux.x64_11gR2_database_1of2.zip和linux.x64_11gR2_database_2of2.zip两个分卷。很多人只下了一个解压时报zip error: Invalid archive。我们的脚本内置了校验逻辑# 检查两个 ZIP 是否都存在 if [[ ! -f database_1of2.zip || ! -f database_2of2.zip ]]; then echo ERROR: Missing database_1of2.zip or database_2of2.zip exit 201 fi # 合并分卷 cat database_1of2.zip database_2of2.zip database.zip # 校验 MD5官方提供 EXPECTED_MD5a1b2c3d4e5f67890... # 此处为真实 MD5 ACTUAL_MD5$(md5sum database.zip | awk {print $1}) if [[ $EXPECTED_MD5 ! $ACTUAL_MD5 ]]; then echo MD5 mismatch! Corrupted download. exit 202 fi # 解压 unzip -q database.zip -d /tmp/database/解压后/tmp/database/目录下会有runInstaller、response/、stage/等。我们把整个/tmp/database移到/u01/install/然后chown -R oracle:oinstall /u01/install。4.3 执行一键安装脚本./install_oracle.sh的 12 个关键步骤拆解假设脚本名为install_oracle.sh放在/u01/install/下。执行chmod x install_oracle.sh ./install_oracle.sh。脚本内部执行以下 12 步Step 1: OS Checkuname -r | grep -q 3.10.0.*el7失败则exit 101。Step 2: User Group Createid oracle /dev/null || (groupadd -g 54321 oinstall groupadd -g 54322 dba useradd -u 54321 -g oinstall -G dba oracle)。Step 3: Kernel Param Set动态计算shmmax/shmall并写入/etc/sysctl.conf执行sysctl -p。Step 4: Limits Config追加limits.conf四行nproc,stack,memlock并echo session required pam_limits.so /etc/pam.d/login。Step 5: Package Installyum install -y epel-release yum install -y binutils ... ksh含ksh。Step 6: Response File Gencat /tmp/db_install.rsp填入 7 个必填字段 3 个陷阱字段。Step 7: Run Oracle Installersu - oracle -c /u01/install/database/runInstaller -silent -responseFile /tmp/db_install.rsp -ignorePrereq -waitForCompletion。-ignorePrereq是关键跳过 OUI 自己的预检它会检查gcc版本而 RHEL 7.9 的 gcc 4.8.5 会被它拒绝。Step 8: Root Scripts Runsh /u01/app/oraInventory/orainstRoot.sh sh /u01/app/oracle/product/11.2.0/db_1/root.sh。这两步必须 root 执行脚本会自动sudo。Step 9: DBCA Response Gencat /tmp/dbca.rsp填入GDBNAME,SID,CHARACTERSET等。Step 10: Create Databasesu - oracle -c /u01/app/oracle/product/11.2.0/db_1/bin/dbca -silent -createDatabase -responseFile /tmp/dbca.rsp。Step 11: Listener Startsu - oracle -c lsnrctl start。监听器默认监听1521端口。Step 12: Post-Config SQLcat /tmp/post_db.sql EOF ALTER USER scott ACCOUNT UNLOCK; ALTER USER scott IDENTIFIED BY tiger; EXIT; EOFsu - oracle -c sqlplus / as sysdba /tmp/post_db.sql每一步都有echo [STEP 1] OS Check... done日志失败则echo [ERROR] Step 1 failed exit 101。4.4 验证与连通性测试不只是sqlplus还要看tnsping和lsnrctl status安装完成不等于可用。必须做三层验证Layer 1: Listener Levelsu - oracle -c tnsping orcl。输出必须包含OK (0 msec)。如果报TNS-03505: Failed to resolve name说明tnsnames.ora里orcl别名没配好或sqlnet.ora里NAMES.DIRECTORY_PATH (TNSNAMES, EZCONNECT)缺失。Layer 2: Network Levelsu - oracle -c sqlplus system/oraclelocalhost:1521/orcl。这是最严格的测试指定了 host:port:service_name绕过tnsnames.ora。成功则显示SQL提示符。Layer 3: Instance Levelsu - oracle -c sqlplus / as sysdba然后执行SELECT instance_name, status, database_status FROM v$instance; SELECT name, open_mode FROM v$database; SELECT SYSDATE FROM DUAL;三者都返回正常值才算真正成功。v$instance.status必须是OPENv$database.open_mode必须是READ WRITE。注意ora-28547: connection to server failed, probable oracle net admin error这个热词报错90% 是listener.ora的HOST值不对或tnsnames.ora的HOST与listener.ora不一致。我们的脚本统一设为localhost杜绝此问题。5. 常见问题与排查技巧实录从ORA-01034到ORA-12514的实战排障手册5.1 启动失败类问题ORA-01034、ORA-27102、ORA-00845报错根本原因排查命令解决方案ORA-01034: ORACLE not availableOracle 实例未启动或ORACLE_SID未设置ps -ef | grep pmon看是否有ora_pmon_orcl进程export ORACLE_SIDorcl sqlplus / as sysdba然后startupORA-27102: out of memorykernel.shmmax或kernel.shmall不足或memlock限制太小ipcs -lm看max total shared memoryulimit -l看memlock检查/etc/sysctl.conf和/etc/security/limits.conf按 3.1 节动态计算后重设ORA-00845: MEMORY_TARGET not supported on this system/dev/shm大小不足 1Gdf -h /dev/shmmount -o remount,size2G /dev/shm并写入/etc/fstab:shmfs /dev/shm tmpfs size2G 0 0实操心得ORA-00845是 RHEL 7.9 上最经典的坑。/dev/shm默认是 64M而MEMORY_TARGET1G要求它至少 1G。很多教程让你umount /dev/shm mount -t tmpfs shmfs -o size1g /dev/shm但这只是临时的重启就失效。必须写入/etc/fstab并mount -a。5.2 连接失败类问题ORA-12514、ORA-12154、TNS-12541报错根本原因排查路径解决方案ORA-12514: TNS:listener does not currently know of service requested监听器启动了但数据库实例没注册进去lsnrctl status看Services Summary里有没有orclsqlplus / as sysdba执行ALTER SYSTEM REGISTER;或等 60 秒PMON 进程自动注册ORA-12154: TNS:could not resolve the connect identifier specifiedtnsnames.ora里没有orcl别名或路径不对echo $TNS_ADMIN看是否指向$ORACLE_HOME/network/admincat $TNS_ADMIN/tnsnames.ora确保tnsnames.ora有ORCL (DESCRIPTION ...)且HOST localhostTNS-12541: TNS:no listener监听器根本没启动ps -ef | grep lsnr看是否有tnslsnr进程lsnrctl start检查$ORACLE_HOME/network/log/listener.log日志注意lsnrctl status输出里Services Summary下的Service orcl表示实例已注册。如果只有Service orclXDBXML DB 服务说明实例没起来。此时ps -ef \| grep pmon应该为空。5.3 权限与路径类问题Permission denied、File not found、No such file or directory现象根本原因快速定位解决方案runInstaller: Permission deniedoracle用户对runInstaller没有执行权限ls -l /u01/install/database/runInstallerchmod x /u01/install/database/runInstaller并chown oracle:oinstallsqlplus: command not foundPATH未包含$ORACLE_HOME/binecho $PATHwhich sqlplus在oracle用户的.bash_profile里添加export PATH$ORACLE_HOME/bin:$PATHORA-01078: failure in processing system parametersinit.ora或spfile文件名错误或ORACLE_SID与文件名不匹配ls $ORACLE_HOME/dbs/看是否有init$ORACLE_SID.oracd $ORACLE_HOME/dbs cp init.ora initorcl.ora确保ORACLE_SIDorcl实操心得.bash_profile的PATH设置必须在export ORACLE_HOME之后。顺序错了$ORACLE_HOME/bin就是空的。我们的脚本在创建oracle用户后会自动追加echo export ORACLE_BASE/u01/app/oracle /home/oracle/.bash_profile echo export ORACLE_HOME/u01/app/oracle/product/11.2.0/db_1 /home/oracle/.bash_profile echo export ORACLE_SIDorcl /home/oracle/.bash_profile echo export PATH\$ORACLE_HOME/bin:\$PATH /home/oracle/.bash_profile5.4 性能与配置类问题DUAL表查询慢、java单机性能瓶颈的关联思考热词里有oracle中dual最多存多大这其实是个伪命题。DUAL是 Oracle 的伪表只有一个DUMMY字段VARCHAR2(1)它不占磁盘空间SELECT * FROM DUAL永远是毫秒级。所谓“慢”99% 是网络延迟或客户端问题。但java单机性能瓶颈却是真痛点。当 Java 应用如 a9 财务软件连 Oracle 单机时瓶颈往往不在 Oracle而在 JDBC 连接池配置。例如c3p0默认maxPoolSize15如果应用并发请求超过 15就会排队等待。我们的脚本不解决 Java 层但会在/u01/app/oracle/product/11.2.0/db_1/network/admin/sqlnet.ora里添加SQLNET.EXPIRE_TIME10 TCP.CONNECT_TIMEOUT5前者让数据库每 10 分钟发一个探测包及时清理死连接后者让 TCP 连接超时缩短到 5 秒避免 Java 应用卡在socket.connect()。这是 Oracle 侧能做的最小干预却能极大缓解 Java 应用的“假死”现象。6. 后续维护与扩展建议从单机到可管理的最小生产环境安装完成只是开始。一个真正可用的单机 Oracle还需要三件套6.1 自动化备份脚本rman的最小可行备份策略rman不是必须的但expdpData Pump是底线。我们的脚本会部署一个每日全库导出脚本/u01/scripts/backup_full.sh#!/bin/bash export ORACLE_SIDorcl export ORACLE_HOME/u01/app