
去年为了把一个老进销存系统搬到新服务器上我在Linux下安装Oracle 11g前后折腾了三次第一次卡在依赖包第二次挂在共享内存参数第三次软件装好了远程连接又报ORA-12514。这篇东西就是基于这几次完整过程整理出来的适合第一次在Linux上装Oracle 11g、或者装到一半被各种报错拦住的人。它会尽量解释每个关键步骤为什么这么做而不是只丢给你一堆命令。如果你已经有基础也可以直接从故障排查那部分开始看。1. 先想清楚为什么还在装Oracle 11g又该让它跑在哪种Linux上1.1 老系统对11g的依赖比想象中顽固不少人会问Oracle都出到19c、23ai了为什么还要装11g我接手的老进销存系统就是典型例子。项目里大量SQL用着旧式写法比如()外连接、隐式类型转换、老版本JDBC驱动以及一批在11g上跑得又快又稳、换到12c及以上就出现执行计划变化的查询。业务方不可能停下来改代码数据库版本自然被钉死。另外很多企业内网还有老旧的C/S架构客户端安装时硬编码了连接串和驱动版本只认11g的服务名规则。这种情况下与其冒着业务兼容性风险升库不如老老实实在一台新Linux服务器上把11g装好。项目里我选择的是11.2.0.4这是11g最后一个大补丁集版本修复了大量已知问题也是业界实际使用最多的11g版本。1.2 操作系统选型红帽系是11g的舒适区Oracle 11g的官方安装脚本和依赖检查主要面向Red Hat Enterprise Linux和CentOS。我强烈建议使用CentOS 7.9或RHEL 7.9这类系统原因很现实11.2.0.4的预安装检查、runInstaller、root.sh这些脚本都是按红帽系目录和包管理方式设计的在CentOS 7上基本不用改。网上能查到的依赖包清单、报错解决思路绝大多数也是针对RHEL/CentOS的。如果你非要在Debian或Ubuntu上装理论可行但会遇到glibc版本、包名不同、compat-libstdc缺失等一堆额外问题后续打补丁和跑root脚本也会更折腾。至于内核版本CentOS 7自带的3.10内核和11g的IPC机制配合得很好。不要为了尝鲜去换新内核我见过有人升级内核后数据库启动出现ORA-27102的案例排查半天最后发现是共享内存行为变了。选一个稳定、被广泛验证的组合才是装数据库该有的心态。2. 装之前打好地基依赖包、内核参数和用户目录2.1 硬件和目录规划安装Oracle 11g前先确认系统资源。内存最低2GB4GB以上才舒服。官方文档写的是1GB最低要求但如果你真的用1GB内存装后面启动实例、跑dbca建库都会非常痛苦。交换分区也值得认真规划。按Oracle官方建议物理内存在2GB到8GB之间时swap一般等于物理内存大小8GB以上时swap可以适当小一些。我习惯给8GB内存的机器分配8GB swap足够应付大部分场景。目录方面最容易忽视的是/tmp。安装程序在解压、运行runInstaller时需要临时写文件至少留出1GB到2GB空间。装完后Oracle软件加数据文件往往超过10GB所以安装目录建议独立分区或至少有20GB可用空间别和系统盘挤在一起。2.2 依赖包一条yum命令解决八成问题Oracle 11g在CentOS 7上的依赖包很多是32位兼容库少了任何一个预检查就会报错。我推荐把这串包一次装齐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 \ elfutils-libelf-devel这里面compat-libstdc-33是很多CentOS 7用户容易漏掉的它提供老版本C标准库Oracle的安装程序和部分组件在编译链接时需要它。CentOS 7的base源里一般有直接yum装即可。安装完成后用ldconfig -p | grep libaio快速确认关键库已经存在避免后面安装时突然报缺库。2.3 内核参数与limits现在不改起库时哭Oracle 11g对共享内存、信号量等系统参数有硬性要求。最稳妥的做法是装数据库前就把/etc/sysctl.conf改好然后sysctl -p生效。下面是我常用的参数按8GB内存机器给的值参数值作用kernel.shmmax4294967296单个共享内存段最大字节数建议等于或略大于SGAkernel.shmall1048576共享内存总页数按shmmax除以页大小4KB计算kernel.shmmni4096共享内存段数量下限kernel.sem250 32000 100 128信号量参数第一项决定每个进程可用的信号量数fs.file-max6815744系统级文件句柄上限fs.aio-max-nr1048576异步I/O请求上限数据库高并发写入时需要net.ipv4.ip_local_port_range9000 65500本地可用端口范围影响大量连接时的端口分配net.core.rmem_default/rmem_max262144 / 4194304TCP接收缓冲区net.core.wmem_default/wmem_max262144 / 1048576TCP发送缓冲区关于kernel.shmmax我自己的理解是Oracle的SGA会尝试分配一个共享内存段如果这个段的受限大小比SGA还小实例启动就会报共享内存不足。所以“物理内存的一半左右”是个相对稳妥的取值如果你的SGA明确设置了比如8GB那就把shmmax至少设成8GB以上。接着改/etc/security/limits.conf追加oracle soft nproc 2047 oracle hard nproc 16384 oracle soft nofile 1024 oracle hard nofile 65536 oracle soft stack 10240 oracle hard stack 32768nofile控制进程能打开的文件数量nproc控制用户进程数量stack是栈大小。很多“数据库连接数一多就报错”的问题根源其实是nofile不够这一步一定要做。2.4 oracle用户和目录权限Oracle官方建议用专门的操作系统用户运行数据库软件不要用root。创建用户和组groupadd oinstall groupadd dba useradd -g oinstall -G dba oracle passwd oracle然后建目录并授权。我把Oracle Base放在/u01/app/oraclemkdir -p /u01/app/oracle chown -R oracle:oinstall /u01/app chmod -R 775 /u01/app为什么不用root直接装一方面Oracle安装脚本会检查当前用户另一方面数据库进程如果以root运行任何一个漏洞都可能让攻击者直接拿到系统最高权限。这个习惯后面所有数据库操作都适用。3. 上传解压与静默安装runInstaller全流程3.1 安装包上传与解压乱码安装包是那两个经典的zip文件linux.x64_11gR2_database_1of2.zip和linux.x64_11gR2_database_2of2.zip。下载后先校验MD5或SHA256网上教程很多不用我多说。上传到服务器后有人习惯在Windows里先解压再传到Linux我强烈不建议这么做一方面可能丢失Unix权限位另一方面会莫名其妙多出很多垃圾文件。直接在Linux上解压就好。有同学会遇到“Linux解压Windows传来的zip文件名乱码”的问题。这是因为Windows的zip用GBK编码记录文件名Linux的unzip默认按UTF-8解码。解决方法是如果你的unzip支持-O参数unzip -O CP936 linux.x64_11gR2_database_1of2.zip如果不支持可以改用Python处理文件名或者干脆只解压不关注文件名乱码。实际上Oracle安装包解压后的核心目录结构是英文的乱码通常只影响个别说明文档不影响安装。真正需要注意的是两个zip解压后会自动合并到同一个database目录所以第一个解压完第二个直接解压到同一位置即可。3.2 db_install.rsp最关键的几项配置解压后安装模板在database/response/db_install.rsp。silent模式安装就是靠这个文件告诉安装程序“装什么、装到哪、按什么权限装”。我通常只改几个关键项其他保持默认oracle.install.optionINSTALL_DB_SWONLY UNIX_GROUP_NAMEoinstall INVENTORY_LOCATION/u01/app/oraInventory SELECTED_LANGUAGESen,zh_CN ORACLE_HOME/u01/app/oracle/product/11.2.0/dbhome_1 ORACLE_BASE/u01/app/oracle oracle.install.db.InstallEditionEE oracle.install.db.DBA_GROUPdba oracle.install.db.OPER_GROUPdba oracle.install.db.BACKUPDBA_GROUPdba oracle.install.db.DGDBA_GROUPdba oracle.install.db.KMDBA_GROUPdba DECLINE_SECURITY_UPDATEStrue重点解释几个oracle.install.optionINSTALL_DB_SWONLY只装数据库软件不建库。这样后续用dbca单独建库每个环节出问题都能单独排查比一次性“软件建库”好定位得多。ORACLE_HOME要和后续所有环境变量保持一致我习惯用dbhome_1这个目录名识别度高。DECLINE_SECURITY_UPDATEStrue不配置My Oracle Support账号时必须设为true否则安装程序会一直等待在线配置。3.3 执行runInstaller先切换到oracle用户把解压目录属主改好chown -R oracle:oinstall /u01/software/database su - oracle cd /u01/software/database然后执行./runInstaller -silent -responseFile /u01/software/database/response/db_install.rsp -ignorePrereq-ignorePrereq是跳过预检查仅当某些非关键项不满足时才建议加。如果你系统配置按前面步骤都做好了其实可以不加。安装日志默认写在/u01/app/oraInventory/logs/和$ORACLE_BASE/cfgtoollogs/下面。如果卡住或报错第一件事就是去翻installActions*.log比盯着终端输出有效得多。安装顺利的话最后会提示你用root执行两个脚本/u01/app/oraInventory/orainstRoot.sh /u01/app/oracle/product/11.2.0/dbhome_1/root.shroot.sh执行时会问localhost/bin目录直接回车用默认值即可。这两个脚本的作用是修正一些需要root权限的文件属性和链接不执行的话后面dbca和启动监听会非常麻烦。3.4 静默安装中常见的三类中断我实际遇到过的安装中断大致分三类第一类是预检查失败日志里明确写着缺少某个包或参数不达标。解决方案是补装依赖包、改sysctl然后重新跑runInstaller。第二类是磁盘空间不足尤其是/tmp目录不够。清理/tmp或用TMPDIR环境变量指到别的分区再重跑。第三类是编译agent时报错比如Error in invoking target agent nmhs。这类错误看着吓人大部分时候是系统缺了某个编译相关库最常见的是libaio-devel和sysstat没装。确认这两个包在后再重跑。4. 监听和实例netca与dbca的正确用法4.1 有图形界面和纯命令行两种路线如果服务器有图形桌面或你能通过X11转发打开窗口直接执行netca网络配置助手和dbca数据库配置助手是最省力的。但很多Linux服务器是纯命令行环境所以我这里主要讲静默方式。先设置好oracle用户的环境变量编辑~/.bash_profileexport ORACLE_BASE/u01/app/oracle export ORACLE_HOME$ORACLE_BASE/product/11.2.0/dbhome_1 export ORACLE_SIDorcl export PATH$PATH:$ORACLE_HOME/bin export LD_LIBRARY_PATH$ORACLE_HOME/libexport ORACLE_SIDorcl这行特别重要。很多人在安装后执行sqlplus / as sysdba结果显示“无法连接到空闲例程”就是因为当前shell里SID没设置或与实例名不一致。4.2 配置监听netca静默方式在oracle用户下执行$ORACLE_HOME/bin/netca /silent /responsefile $ORACLE_HOME/network/install/netca.rsp执行完用lsnrctl status验证监听有没有起来。如果没起来先看$ORACLE_HOME/network/log/listener.log。这里有个值得记住的坑listener.ora里监听地址的HOST不要写成127.0.0.1否则只能本机连接。默认配置一般会用当前主机名那就要保证/etc/hosts里主机名解析到了正确的内网IP否则远程客户端会连不上。4.3 dbca静默建库监听配好后用dbca静默方式创建数据库。命令较长我用的是$ORACLE_HOME/bin/dbca -silent -createDatabase \ -templateName General_Purpose.dbc \ -gdbname orcl \ -sid orcl \ -sysPassword Oracle11g#123 \ -systemPassword Oracle11g#123 \ -datafileDestination /u01/app/oracle/oradata \ -characterSet AL32UTF8 \ -nationalCharacterSet AL16UTF16 \ -memoryPercentage 30 \ -emConfiguration NONE \ -storageType FS参数解释一下-templateName用的是General_Purpose.dbc通用模板适合大多数业务。模板文件在$ORACLE_HOME/assistants/dbca/templates/下面。-memoryPercentage 30表示数据库用机器物理内存的30%作为内存目标可以根据业务和机器大小调整。-emConfiguration NONE是不装Enterprise Manager省资源也避免端口占用的麻烦。对大多数内网系统EM不是必需品。-datafileDestination建议放在单独分区或目录方便以后备份维护。建库过程会在最后阶段自动启动实例通常需要几分钟。看到Database creation complete基本就成功了。4.4 字符集选择AL32UTF8还是ZHS16GBK网上关于Oracle字符集的争论非常多我给一个直接可用的建议新系统一律选AL32UTF8。ZHS16GBK的中文占用2字节看似比AL32UTF8的3字节省空间但它只能表示简体中文和常用符号遇到多语言、Emoji等情况就抓瞎。更重要的是后期做数据迁移、跨库同步、升级到新版本时UTF8字符集是默认选项GBK转UTF8的代价远高于一开始选UTF8。只有一种情况可以考虑ZHS16GBK老库的数据必须和另一个GBK字符集的系统做字符级完全一致的对接且业务方明确要求不能有任何字符转换。这种场景属于“历史包袱”不是技术选型问题。5. 装完不等于跑起来验证、自启与日常操作5.1 第一次启动数据库的正确顺序建库完成后实例默认是启动状态。但后来如果手动关过库再启动时建议按这个顺序lsnrctl start sqlplus / as sysdba在SQL*Plus里执行startup观察有没有报错。正常应该看到“Database opened”。关闭数据库则反过来先关实例再关监听shutdown immediate;监听停止用lsnrctl stop。shutdown immediate会回滚未提交事务并断开连接在线业务环境适用如果只是开发机shutdown abort更快但启动时要做好介质恢复准备我不建议养成随手abort的习惯。5.2 修改密码与远程连接验证刚建完库system和sys的密码是你传参时指定的但最好还是登录后显式改一次ALTER USER system IDENTIFIED BY NewPass123;很多教程喜欢把Oracle自带测试账号scott解锁ALTER USER scott IDENTIFIED BY tiger ACCOUNT UNLOCK;远程连接的客户端连接串长这样jdbc:oracle:thin:192.168.1.100:1521/orcl其中orcl是服务名不是SID这点容易被搞混。连接前先在服务器本机执行lsnrctl status看到服务名orcl出现在输出里远程连接才有可能成功。防火墙和SELinux也是远程连接失败的重灾区。CentOS 7执行firewall-cmd --permanent --add-port1521/tcp firewall-cmd --reload查看SELinux状态用getenforce如果是Enforcing且没打磨规则可以先临时setenforce 0测试确认是SELinux拦截后再决定是放行还是保持关闭不要在排查问题时忽略掉它。5.3 开机自启两种方案Linux重启后数据库不会自动起来需要配置。第一步都是修改/etc/oratab把实例那一行末尾的N改成Yorcl:/u01/app/oracle/product/11.2.0/dbhome_1:Y第一种做法是在/etc/rc.d/rc.local里加一行su - oracle -c /u01/app/oracle/product/11.2.0/dbhome_1/bin/dbstart /u01/app/oracle/product/11.2.0/dbhome_1注意CentOS 7里rc.local默认没有执行权限需要chmod x /etc/rc.d/rc.local。第二种做法是用systemd管理新建/etc/systemd/system/oracle.service[Unit] DescriptionOracle Database Afternetwork.target [Service] Useroracle Groupoinstall Typeforking ExecStart/u01/app/oracle/product/11.2.0/dbhome_1/bin/dbstart /u01/app/oracle/product/11.2.0/dbhome_1 ExecStop/u01/app/oracle/product/11.2.0/dbhome_1/bin/dbshut /u01/app/oracle/product/11.2.0/dbhome_1 [Install] WantedBymulti-user.target然后systemctl daemon-reload systemctl enable oracle两种方式我都试过rc.local简单直接systemd则能通过systemctl status oracle查状态更直观。如果一台机器上有多个实例dbstart配合oratab里多个Y标志一次全启动反而比写多条systemd配置省事。6. 高频故障完整排查链路从报错表象挖到根因6.1 ORA-01078 / LRM-00109instanc参数文件找不到现象登录SQL*Plus后执行startup报ORA-01078: failure in processing system parameters LRM-00109: could not open parameter file /u01/app/oracle/product/11.2.0/dbhome_1/dbs/initorcl.ora排查链路我建议这样走先看$ORACLE_SID有没有设置用echo $ORACLE_SID确认。如果为空说明环境变量丢了先补export ORACLE_SIDorcl再试。再检查$ORACLE_HOME/dbs目录下有没有spfileorcl.ora。如果没有说明DBCA建库时spfile没有成功生成常见原因是建库中途中止、磁盘写入失败、或者内存参数配得过大导致实例启动失败。解决方法是先找到模板参数文件复制为initorcl.oracp $ORACLE_HOME/dbs/init.ora $ORACLE_HOME/dbs/initorcl.ora然后启动时用pfile指定startup pfile$ORACLE_HOME/dbs/initorcl.ora。能起来后执行CREATE SPFILE FROM PFILE$ORACLE_HOME/dbs/initorcl.ora;让后续启动默认加载spfile。这个问题的根因往往不是参数文件本身而是前面某个环节静默失败了。务必同步检查$ORACLE_BASE/cfgtoollogs/dbca/orcl下的建库日志把根因找出来。6.2 ORA-12514监听器找不到服务现象客户端连接时报ORA-12514: TNS:listener does not currently know of service requested in connect descriptor我最开始看到这个报错很慌其实排查链路很清晰。第一步在数据库服务器上执行lsnrctl status看输出里有没有类似orcl的服务条目。如果没有说明监听起来了但数据库没有成功把自己注册上去。第二步进数据库检查实例状态SELECT status FROM v$instance;如果实例是open那就是动态注册失败。动态注册需要数据库感知到监听的存在最直接的办法是ALTER SYSTEM SET LOCAL_LISTENER(ADDRESS(PROTOCOLTCP)(HOST192.168.1.100)(PORT1521)); ALTER SYSTEM REGISTER;这里的HOST要写客户端能访问到的IP别写localhost。第三步再执行lsnrctl services这时通常能看到服务条目了。如果还不行检查listener.ora里端口是不是真的在1521或者连接串里写的服务名到底叫什么。曾有同事连不上就是因为lsnrctl services里显示的服务名是ORCL连接串却写成了orcl.world一字之差卡了半小时。6.3 ORA-27102共享内存启动失败现象startup时报ORA-27102: out of memory Linux-x86_64 Error: 12: Cannot allocate memory这个报错非常误导人第一反应以为是物理内存不够。实际上大部分情况是kernel.shmmax或kernel.shmall设置得比SGA还小导致共享内存分配失败。排查链路查看SGA大小最直接的是看参数文件里的sga_target比如设了4GB然后执行sysctl kernel.shmmax看当前值如果shmmax只有1GB分配4GB SGA当然失败。修复方式是把/etc/sysctl.conf里的kernel.shmmax调大比如4GB以上kernel.shmall同步调整为shmmax / 4096然后sysctl -p生效重启数据库。如果改完还报错看看/dev/shm大小df -h /dev/shmOracle 11g如果使用AMM内存管理会把部分内存段放到/dev/shm这个目录默认只有物理内存的一半不够时同样会报错。可以在/etc/fstab里显式调大tmpfs /dev/shm tmpfs defaults,size4G 0 0再重新挂载mount -o remount /dev/shm最后提醒一句在数据库启动问题里报错信息只是线索不是答案。ORA-27102背后可能是shmmax、shmall、/dev/shm、hugepages四类原因按链路一个个排除比盯着一个报错字面反复试要快得多。总结印象装完这套Oracle 11g我最深的体会是数据库安装最费时间的不是命令本身而是“你以为装完了”之后那一连串的验证和排错。每次换一台新机器重装我都会把lsnrctl status、sqlplus / as sysdba、远程连接、冷启动这四个动作重新走一遍确认无误才算交付。建议你用一台测试虚拟机把从依赖包到建库的完整流程先跑通再上生产。毕竟在内网生产服务器上一边翻日志一边装数据库压力比现在大得多多踩几轮坑之后你会感谢自己提前做过测试。