1. 整体设计与落地思路拆解
1.1 为什么必须离线安装,离线安装到底难在哪
先说说我碰到的实际场景。接手一台新上架的Linux服务器,放在客户机房内网,安全策略非常严格,这台机器不能访问外网。客户要求部署Oracle数据库,作为生产系统核心库。线上环境无法用yum install直接拉依赖,也下载不了Oracle安装包,所有软件必须提前在能联网的机器上准备好,再用U盘或内网传输工具拷过去。这种场景在企业里太常见了,政府项目、银行项目、制造业内网,十有八九都是离线环境。
离线安装的难点本质上是三个:一是安装介质从哪来,二是系统的依赖库怎么补齐,三是安装过程中Oracle的图形界面用不了,必须靠静默配置文件来完成。很多新手第一次搞离线Oracle,不是卡在Oracle本身的安装,反而是卡在系统依赖装不齐,或者X11转发转发不了,图形界面打开一片空白。这些坑我都踩过,这篇就是把这套完整的流程走一遍,把会踩的坑提前标出来。
1.2 安装前的版本选型和整体流程规划
离线安装第一步不是找安装包,是确定Oracle版本。目前国内存量最多的还是Oracle 11g R2(11.2.0.4),虽然官方早已停止普通支持,但很多老业务系统跑在上面,稳定压倒一切。而2019年之后的机器,很多客户会指定装Oracle 19c,因为19c是12c/18c之后的长支持版本,技术路线相对干净。
不同版本对应的系统要求略有差异。11g R2建议配CentOS 7.x、RHEL 7.x,内核版本3.10以上。19c则建议RHEL 7.6以上或8.x,对glibc的要求也更高。我下面主要以Oracle 11.2.0.4 + CentOS 7.9这套组合来做整体讲解,因为这套装法最普遍,架构最典型。19c在安装思路上完全一致,就是依赖包列表和内核参数的初值略有差别,我会在对应章节里标出来。
整个离线安装的流程,我会按照下面这条线走:
- 准备好安装介质(Oracle的zip包)和依赖库的rpm包
- 在目标服务器上挂载系统镜像,配置本地YUM源,解决依赖库问题
- 调整内核参数、创建用户和目录结构
- 编写静默安装响应文件(responseFile),执行安装
- 用netca静默配置监听,用dbca静默建库
- 启动数据库并做基本验证
这套流程做下来,一台Oracle单机库从零到能建库跑SQL,熟练的话五六个小时就能搞定。第一次搞建议预留一整天,因为依赖和权限问题总是会在意想不到的地方冒出来。
2. 环境准备与离线依赖库补齐
2.1 离线依赖库准备的三种方案
先说依赖库的问题。Oracle安装时会调用系统命令和动态库,缺少任何一个都会在环境检查阶段报错,压根不让你继续。在线环境一条yum install -y就完事,离线环境就必须提前准备好rpm包。
我常用的有三种方案,按省事程度排序:
第一种,在有外网的同版本机器上用yumdownloader工具把相关依赖rpm全部拉下来,然后拷到目标机器安装。命令大概是:
mkdir /root/oracle-deps cd /root/oracle-deps yumdownloader --resolve --destdir=/root/oracle-deps binutils compat-libcap1 compat-libstdc++-33 gcc gcc-c++ glibc glibc-devel ksh libaio libaio-devel libgcc libstdc++ libstdc++-devel libXext libXtst libXau libXi libXrender make sysstat unixODBC unixODBC-devel--resolve参数会把依赖包一并下载,非常方便。注意目标机器的系统版本要一致,CentOS 7.9拉出来的rpm不能直接装到RedHat 8上,版本不匹配会报依赖冲突。
第二种,直接把系统安装镜像里的Packages目录整体拷到目标机器,然后配置成本地YUM源。这种方式相当于把整个系统软件仓库搬到了内网,后面装任何软件都能解决依赖,不只是Oracle需要的那几个包。
第三种,Oracle官方文档的依赖清单里有些包在CentOS默认镜像里本来就有,比如binutils、glibc这种基础包。如果目标机器上之前有别的应用,很可能已经装了一部分。所以装依赖之前先检查一遍,缺什么补什么,没必要无脑全部装一遍。
2.2 配置本地YUM源,让服务器可以离线“联网”
我自己最推荐的是第二种方案,把镜像Packages目录拷过去之后配置本地YUM源。这样以后在离线环境装任何软件都不用再折腾依赖,成本一次投入长期受益。
具体操作:先把系统ISO镜像挂载,或者把Packages目录通过U盘拷贝到/opt/centos-packages。然后新建一个repo文件:
mkdir -p /opt/centos-packages # 假设ISO已经挂载在 /mnt/iso cp -rp /mnt/iso/Packages/*.rpm /opt/centos-packages/ # 初始化createrepo的元数据(CentOS 7自带 createrepo,如果没有需要另行安装) createrepo /opt/centos-packages/然后写repo配置:
[local-repo] name=Local CentOS Repository baseurl=file:///opt/centos-packages enabled=1 gpgcheck=0执行yum clean all && yum makecache,之后就能用yum install正常安装本地仓库里的软件了。这里有个细节,CentOS 7.9镜像里包比较全,但有些Oracle需要的包,比如compat-libstdc++-33,在默认镜像里可能没有(它在AppStream或Extras里),这个时候还是要靠第一种方案从外网下载。
2.3 图形界面用不了?那就放弃图形界面
Oracle 11g和12c的安装程序,如果没有图形界面,默认会尝试调用X11连接。在离线服务器上,十有八九没有显示器也没有图形环境,哪怕用XShell的X11转发,也经常卡在半路。这是我第一次安装时浪费最多时间的地方。
后来我学乖了,全部用静默模式。静默安装本质上是一个Java程序读取你预先填好的响应文件,然后自动完成安装动作。整个过程只会在控制台打印日志,不需要任何图形交互。这不光解决了无图形界面的问题,还让安装过程可以完全脚本化,部署效率大幅提升。
Oracle的响应文件,在安装包解压后的response/目录里有模板,比如db_install.rsp。安装前把它拷贝出来,填好关键参数,然后通过-silent参数指定它,系统就会按配置走完整个安装流程。
3. 内核参数、用户与目录规划
3.1 内核参数调整,确保数据库运行的基础环境
Oracle数据库对Linux内核参数有硬性要求,不符合的话安装程序会在环境检查时直接给出警告或直接终止。建议在安装前就手工把参数改好,避免安装中途被打断。
编辑/etc/sysctl.conf,加入以下推荐参数(以11g为例):
fs.aio-max-nr = 1048576 fs.file-max = 6815744 kernel.semmsl = 250 kernel.semmns = 32000 kernel.semopm = 100 kernel.semmni = 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 vm.max_map_count = 655360改完执行sysctl -p使其生效。这里面我最常被人问到的就是kernel.sem四个值——semmsl、semmns、semopm、semmni分别表示每个信号量集合的最大信号量数、系统中信号量总数上限、每个信号量操作的最大次数和系统级信号量集合数。Oracle的进程间通信大量依赖信号量,如果配置过小,数据库启动时会报出ORA-27300之类的错误。
vm.max_map_count这个参数在Oracle 19c里尤其重要,因为数据库对内存映射区域的要求更高,默认的65530很容易不够用,导致实例无法启动,建议直接放宽到655360,不会有副作用,只是增加虚拟内存映射上限。
3.2 创建Oracle用户和环境变量
Oracle不允许直接用root来安装和运行数据库。官方建议是创建一个专门的oracle用户,归属oinstall和dba两个组。实际操作中我通常会一并创建好,因为后面建监听和建库都要用这个用户。
groupadd oinstall groupadd dba useradd -g oinstall -G dba oracle passwd oracle创建完成之后,通过id oracle确认一下用户组归属,确认没问题再往下走。
Oracle用户需要设置环境变量,主要是ORACLE_BASE、ORACLE_HOME、ORACLE_SID和PATH。这里有个容易弄混的地方,ORACLE_BASE是Oracle安装的根路径,ORACLE_HOME是具体版本软件的安装路径。按OFA(Optimal Flexible Architecture)规范来,我习惯将路径设置为:
export ORACLE_BASE=/u01/app/oracle export ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1 export ORACLE_SID=orcl export PATH=$ORACLE_HOME/bin:$PATH写入~/.bash_profile即可。注意如果安装的是Oracle 19c,ORACLE_HOME路径中版本数字会不同,但结构思路一样。还有一个小细节,Oracle 11g的ORACLE_HOME路径层级会比ORACLE_BASE多两层,这个在后续建库和打补丁时都会用到,路径别记错。
3.3 目录创建与权限设置
安装Oracle之前,需要把软件安装目录创建好,并且把属主改成oracle用户。这个操作看起来简单,但目录权限不对会导致安装程序无法写入,报OUI-10086之类的权限错误。
mkdir -p /u01/app/oracle chown -R oracle:oinstall /u01注意这里把/u01整层都授权给oracle:oinstall了,因为Oracle安装过程中会创建/u01/app/oraInventory以及/u01/app/oracle下的子目录。如果/u01是独立挂载的数据盘,还要确认挂载参数里没有noexec选项,否则安装程序在解压和运行二进制时会直接被系统拒绝。
3.4 检查系统资源限制
Oracle还要求对oracle用户设置进程数和文件描述符限制,编辑/etc/security/limits.conf:
oracle soft nproc 2047 oracle hard nproc 16384 oracle soft nofile 1024 oracle hard nofile 65536 oracle soft stack 10240同时还要确认/etc/pam.d/login中有session required pam_limits.so这一行(CentOS 7默认有)。这步不做的话,数据库启动时后台进程可能因为文件句柄耗尽而异常退出,日志里跟着就会出现ORA-12547: TNS:lost contact这类信息,很隐蔽。
4. 安装Oracle软件与静默配置
4.1 解压Oracle安装介质,准备响应文件
拿到linux.x64_11gR2_database_1of2.zip和linux.x64_11gR2_database_2of2.zip之后,两个包都要解压到同一个目录下(11g分两个包,19c只有一个)。解压后会出现一个database目录,里面就有runInstaller和response子目录。
unzip p13390677_112040_Linux-x86-64_1of7.zip unzip p13390677_112040_Linux-x86-64_2of7.zip解压完检查一下database目录的所有者。我遇到过一种情况,U盘和压缩包是从Windows传过来的,解压后文件所有者是root,如果不提前chown -R oracle:oinstall database,安装程序在写临时文件时会出现Permission denied。
然后把db_install.rsp拷贝出来备用:
cp database/response/db_install.rsp /home/oracle/ chown oracle:oinstall /home/oracle/db_install.rsp4.2 响应文件核心参数逐个解读
db_install.rsp里的参数非常多,大部分保持默认就好,但有几个是必须改的,直接决定安装结果。我列一下最核心的几个:
oracle.install.responseFileVersion=/oracle/install/rspfmt_dbinstall_response_schema_v11_2_0 oracle.install.option=INSTALL_DB_SWONLY ORACLE_HOSTNAME=你的主机名 UNIX_GROUP_NAME=oinstall INVENTORY_LOCATION=/u01/app/oraInventory ORACLE_HOME=/u01/app/oracle/product/11.2.0/dbhome_1 ORACLE_BASE=/u01/app/oracle oracle.install.db.InstallEdition=EE oracle.install.db.DBA_GROUP=dba oracle.install.db.OPER_GROUP=dba oracle.install.db.config.starterdb.type=GENERAL_PURPOSE oracle.install.db.config.starterdb.globalDBName=orcl oracle.install.db.config.starterdb.SID=orcl oracle.install.db.config.starterdb.memoryLimit=800 oracle.install.db.config.starterdb.password.ALL=你的数据库密码 DECLINE_SECURITY_UPDATES=true这里oracle.install.option=INSTALL_DB_SWONLY表示只装数据库软件,不建库。建库放到后面用dbca单独做,这样更可控,也符合生产环境的一般做法——软件和数据库实例分开管理。密码字段在11g的静默安装中如果不设置,安装到一半会卡住等交互,所以务必提前填好。
4.3 静默执行runInstaller
响应文件准备好之后,切换到oracle用户,进入database目录执行安装:
cd /home/oracle/database ./runInstaller -silent -responseFile /home/oracle/db_install.rsp电脑屏幕会开始滚动日志,整个安装过程大概20到40分钟,取决于磁盘速度和CPU性能。如果一切顺利,最后日志中会出现类似Successfully Setup Software的字样。
这里要提醒一下,即使静默安装正常结束,程序最后还是会提示你需要用root账号去执行两个脚本:orainstRoot.sh和root.sh。这两个脚本必须在安装结束后立刻执行,否则Oracle的初始化和权限设置不完整。
/u01/app/oraInventory/orainstRoot.sh /u01/app/oracle/product/11.2.0/dbhome_1/root.shroot.sh执行的时候会询问是否把Oracle的二进制链接到/usr/local/bin,问y即可。这是Oracle 11g很经典的一步,别跳过。
4.4 静默配置监听器和实例
软件装完之后,数据库还处于“没实例、没监听”的状态。下一步就是配置监听器。直接用netca静默模式跑一下:
netca -silent -responseFile $ORACLE_HOME/assistants/netca/netca.rspnetca会自动读取/etc/hosts里的主机名和IP信息,生成listener.ora文件。它默认监听的是1521端口。如果客户内网端口被占用了,之后可以手改$ORACLE_HOME/network/admin/listener.ora,把PORT换成空闲端口,然后重启监听。
监听启动后,用它来建库。建库用dbca静默模式,一次命令直接生成一个完整实例:
dbca -silent -createDatabase \ -templateName General_Purpose.dbc \ -gdbname orcl -sid orcl \ -responseFile NO_VALUE \ -characterSet AL32UTF8 \ -memoryPercentage 40 \ -emConfiguration NONE这里面-characterSet AL32UTF8是我个人的习惯,字符集一定要在建库前指定好,因为建库之后改字符集非常痛苦,不光是ALTER DATABASE一句命令的问题,还涉及到已有数据的转码风险。-memoryPercentage 40表示用服务器物理内存的40%来分配SGA和PGA,具体比例根据业务调整,一般OLTP系统给50%左右比较合适。
建库过程根据机器性能,大约需要10到30分钟。完成后日志中会出现Database creation complete,然后就可以用sqlplus / as sysdba连接验证了。
5. 常见问题与排查技巧实录
5.1 环境检查不通过,报依赖缺失
这是离线安装中被问得最多的一个问题。静默安装如果遇到环境不符合要求,默认会直接终止,日志里会明确提示缺失的软件包。比如最常见的是:
Checking for compat-libstdc++-33... not found Checking for libaio-devel... not found解决办法就是前面说的,提前把rpm包准备好,在安装Oracle之前rpm -ivh装好。这里有个技巧,如果yum本地源配好了,直接yum install -y compat-libstdc++-33 libaio-devel也是可以的,不需要手动一个个装。
如果不确定缺哪些包,可以先把Oracle安装包里的runInstaller用-prereqChecker参数跑一遍,它会只检查环境不安装软件,直接把缺少的依赖列出来:
./runInstaller -silent -responseFile /home/oracle/db_install.rsp -prereqChecker输出结果中Passed表示通过,Failed列出异常项。这个方式比猜要快得多。
5.2 磁盘空间不足或swap偏小
Oracle安装时会检查两个空间:一是/tmp目录,至少需要1GB以上可用空间,否则安装程序在解压临时文件时会报Not enough space;二是swap交换分区,11g建议至少2GB,如果内存2GB以下,swap至少要是内存的2倍。服务器配置比较老的情况下,swap不足是常见问题。扩容swap的办法:
dd if=/dev/zero of=/swapfile bs=1G count=4 chmod 600 /swapfile mkswap /swapfile swapon /swapfile echo "/swapfile swap swap defaults 0 0" >> /etc/fstab这个临时swap文件在生产环境不建议长期使用,速度不如独立swap分区,但作为安装期的应急手段完全够用。
5.3 监听服务启动失败
监听器是数据库对外连接的第一道关口,没它客户端根本连不进来。常见的监听启动失败原因有三个:一是listener.ora里的主机名解析不了,二是端口被占用,三是防火墙拦截。
排查思路很简单,先看监听状态:
lsnrctl status如果提示TNS-12545: Connect failed because target host or object does not exist,基本就是/etc/hosts的问题。确认主机名和IP对应关系:
hostname grep 主机名 /etc/hosts/etc/hosts里必须有本机IP和主机名的映射,否则监听器和数据库实例之间通信会异常。这个坑在DNS配置不当的内网环境中尤其常见。先把它抓好,再重启监听:
lsnrctl stop lsnrctl start防火墙方面,如果是CentOS 7默认使用firewalld,需要放行1521端口:
firewall-cmd --permanent --add-port=1521/tcp firewall-cmd --reload5.4 数据库实例启动报ORA-27102或ORA-00064
启动数据库的时候偶尔会碰到这类报错:
ORA-27102: out of memory Linux-x86_64 Error: 28: No space left on device如果你确定磁盘没有满,那多半是/dev/shm(共享内存)太小。Oracle 11g默认使用共享内存来管理SGA,如果/dev/shm的大小小于SGA的分配值,实例就无法启动。查看当前共享内存大小:
df -h /dev/shm默认情况下/dev/shm是物理内存的一半。解决办法要么调整SGA大小,让数据库在共享内存限制内运行,要么把共享内存挂载扩大。临时扩大:
mount -o remount,size=8G /dev/shm如果是虚拟机内存本来就小,更合理的方案是在初始化参数中把memory_target或sga_target调小。
5.5 远程客户端连不上数据库
如果监听和实例都正常,但远程客户端就是用SQL Developer或pl/sql连接不上,重点检查这几项:
lsnrctl services看是否有对应服务- 数据库是否处于
OPEN状态 - 防火墙是否放行1821端口(刚才提过)
sqlnet.ora里是否设置了TCP.INVITED_NODES之类的限制
有一种情况很隐蔽:数据库装好后,listener.ora里的HOST写成127.0.0.1而不是实际内网IP,导致远程客户端能到服务器,但监听只监听回环地址,连不上。遇到这种情况直接修改listener.ora,把HOST改成服务器实际IP或主机名,重启监听即可。
5.6 oracle用户环境下sqlplus中文乱码
对于需要UTF-8中文支持的环境,在/home/oracle/.bash_profile里加一行:
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8这个设置和数据库字符集要一致,否则从客户端查询中文字段会出现乱码。大部分公司项目建库时用的都是AL32UTF8,这一行建议从一开始就配好,免得后面被业务半路问起来。
6. 安装完成后的必要固化和后续扩展建议
6.1 把系统参数和配置固化到开机自启
Oracle数据库装好之后,服务器一旦重启,数据库实例和监听器不会自动起来,需要手工操作。生产环境不可能每次重启都人工去启库,所以这一步一定要做。
用root用户的systemctl创建一个服务,或者传统的方式在/etc/rc.local里加上:
su - oracle -c "/u01/app/oracle/product/11.2.0/dbhome_1/bin/lsnrctl start" su - oracle -c "/u01/app/oracle/product/11.2.0/dbhome_1/bin/dbstart $ORACLE_HOME"注意dbstart启动数据库依赖/etc/oratab文件。Oracle在安装的时候会生成这个文件,里面记录了orcl:/u01/app/oracle/product/11.2.0/dbhome_1:N,其中最后的标志符如果是N,dbstart就不会管这个实例。把它改成Y才能实现开机自动启库:
sed -i 's/dbhome_1:N/dbhome_1:Y/' /etc/oratab另外别忘了一提交修改/etc/rc.local后要给执行权限:
chmod +x /etc/rc.local6.2 补丁升级与后续运维的离线准备
Oracle 11.2.0.4之后有大量的PSU(补丁集更新),如果你在客户内网环境,绝对不能指望在线补丁。这类补丁也是通过OPatch工具离线打的,核心是提前准备好p6880880(这是OPatch工具本身)和其他补丁包,上传到服务器后按以下流程操作:
# 替换OPatch版本 unzip p6880880_112000_Linux-x86-64.zip -d $ORACLE_HOME # 检查补丁冲突 $ORACLE_HOME/OPatch/opatch prereq CheckConflictAgainstOHWithDetail -phBaseDir /home/oracle/patch/ # 打补丁 $ORACLE_HOME/OPatch/opatch apply /home/oracle/patch/实测下来,11g打补丁比19c要麻烦一点,主要在于需要重启数据库到migrate模式执行SQL脚本。这部分如果客户没强制要求,很少会有团队去主动打补丁。但如果在金融或者医疗行业,合规审计会查补丁情况,这个流程建议在部署文档里留一份备用。
6.3 备份策略的快速落地
离线环境同样要解决备份问题。最小可行方案是开启归档模式,配合每天的rman增量备份。作为刚装完库的初级固化,至少要把归档模式打开:
sqlplus / as sysdba shutdown immediate startup mount alter database archivelog; alter database open;然后写个简单的rman备份脚本,全库加归档日志备份到另一块磁盘或NFS挂载目录。这一步不一定在当天完成,但至少在交付给客户前要把备份通道验证跑通,别等数据丢了才想起这茬。
6.4 从11g升级到19c时的注意差异
如果你是为了新项目直接装19c,静默安装的思路完全一样,但有几处细节不同。第一,19c的runInstaller对glibc版本要求更高,建议CentOS 7.9以上或者直接用Rocky Linux 8;第二,19c安装包建议用LINUX.X64_193000_db_home.zip,解压后可以直接通过./runInstaller -silent安装,不再需要分成database目录;第三,19c的响应文件参数命名略有调整,但总体结构还是oracle.install.xx.xx的形式。内核参数里,vm.max_map_count必须放大到262144以上,这一点和11g不同,很容易被忽略。
另外19c默认使用CDB/PDB架构,如果还是习惯于11g的非容器数据库,可以在建库时指定-createAsContainerDatabase false,或者建好CDB后再创建独立的PDB。多租户架构对运维习惯的冲击不小,建议初次接触19c的朋友先建一个PDB练手,再上生产。
7. 我的经验总结
离线安装Oracle这件事,说难也难,说简单也简单。难在环境差异大,每台服务器的操作系统纯净度不一样,依赖缺失情况也不同;简单在于流程高度标准化,只要介质和依赖准备好了,静默安装基本一次过。我个人做了这么多套之后,最大的体会是——前期准备工作占整个安装过程70%的精力,真正执行安装的时间其实很短。
再分享一个小技巧:每做完一套环境,把rpm -qa的完整包列表和/etc/sysctl.conf、/etc/security/limits.conf这两个配置文件备份到一个文档里。下次做第二套时直接对照这个清单,缺失一目了然。这套"基线模板"的方法,我在批量交付项目时大大降低了翻车概率。
还有,第一次做的时候建议全程开着script命令记录终端日志,一旦安装失败,可以从日志里快速定位到底卡在哪一步,不用凭记忆排查。离线环境不像在线环境一样有个搜索引擎随时查答案,自己留下的记录就是最可靠的排查依据。