1. 项目背景与整体思路拆解
1.1 为什么到今天还有人折腾 CentOS 7 上的 Oracle 11g
先说个现实:CentOS 7 早已进入生命周期尾期,Oracle 11g 也已经是“爷爷辈”的数据库版本,但这两样组合起来,仍然是很多生产环境里跑得最稳的底座。我接触过的存量业务系统里,凡是核心交易、报表统计、ERP 这类不能随便动的库,十有八九跑在 Oracle 11g 上。系统不敢动,数据库也不敢动,最后只能在这个组合下面持续做运维和扩容。
这个标题看起来只是“装个数据库”,但实际操作中涉及的东西远不止一条安装命令。Linux 内核参数、用户权限、依赖包、监听配置、字符集选择、内存分配、开机自启、备份策略,每一步都藏着一堆“没踩过坑就不知道”的细节。写这篇文章的目的,就是把我在 CentOS 7 上安装和使用 Oracle 11g 的全过程拆开讲清楚,适合三类人看:刚入行需要搭一套 Oracle 环境练手的 DBA,负责存量系统的运维开发,以及想搞明白“为什么装了老出问题”的测试工程师。
1.2 整体安装链路与方案选型
先把整个安装链路摆出来,心里有个全局地图再动手,比闷头敲命令稳得多:
- 系统准备:确认 CentOS 7 版本、内存、磁盘、Swap
- 依赖包安装:把 Oracle 需要的系统库全部装齐
- 用户与目录规划:创建 oracle 用户、管理组,规划软件安装目录
- 内核参数调整:修改共享内存、信号量、文件句柄等参数
- 资源限制配置:调整 limits.conf,防止进程被杀
- 安装数据库软件:用 runInstaller 执行图形或静默安装
- 配置监听:用 netca 创建 listener
- 创建实例:用 dbca 建库
- 运维接入:配置环境变量、开机自启、备份策略
方案选型上,我主推静默安装。原因很实在:很多服务器在机房或者云上,根本没有图形桌面,用 X11 转发做图形安装,延迟高、容易中断,而且 Oracle 的图形安装界面在远程环境下经常出现渲染问题。静默安装通过响应文件传参,整个过程不依赖图形界面,日志输出清晰,出问题也好排查。等你需要批量部署多台同样配置的机器时,响应文件可以直接复用,效率提升非常明显。当然,如果你手头正好有一台带桌面环境的机器,或者用 VNC 连过去也没问题,图形安装依然是最适合入门的方式,因为所有选项都有默认值和说明,不容易漏配。
2. 安装前的环境准备与系统侧调优
2.1 版本兼容性与硬件规划
Oracle 11g 版本很多,但现阶段装生产环境,我不建议用 11.2.0.1 或 11.2.0.2,尽量选 11.2.0.4,也就是 11gR2 的最后一个 Patch Set,Bug 修复最全,稳定性最好。CentOS 7 的内核默认是 3.10,Oracle 11g 官方文档里对 Linux 内核版本要求比较宽泛,3.10 内核运行 11g 是没问题的,但在安装过程中仍需要做不少适配。
硬件规划上,我给一个经过实际验证的最低参考:
| 项目 | 最低要求 | 推荐配置 | 备注 |
|---|---|---|---|
| CPU | 1 核 | 4 核以上 | 编译和建库阶段吃 CPU |
| 内存 | 2 GB | 4 GB 以上 | 内存太小 SGA 没法分配 |
| Swap | 2 GB | 内存的 1~1.5 倍 | 内存不足时兜底 |
| /tmp | 2 GB | 5 GB 以上 | 安装阶段解压和临时文件 |
| /u01 | 10 GB | 20 GB 以上 | 建议单独分区,避免根分区被撑爆 |
| 系统盘 | 20 GB | 40 GB 以上 | 日志和系统文件增长 |
很多人栽在内存上。2GB 内存装 Oracle 11g 能装,但跑起来很吃力,SGA 给到 800MB 左右就到顶了,稍微来点并发就会触发内存交换。有条件的话,4GB 内存是起步线。
2.2 依赖包安装与缺包排查
这是最容易出问题的第一道关。Oracle 11g 的安装程序在启动阶段会检查一批系统动态库,缺一个就直接报错退出。CentOS 7 下我一般用这一组命令装齐大部分依赖:
yum -y install binutils compat-libcap1 compat-libstdc++-33 \ gcc gcc-c++ glibc glibc-devel ksh libaio libaio-devel \ libX11 libXau libXi libXt libXrender libXtst libXext \ libstdc++ libstdc++-devel make sysstat unixODBC unixODBC-devel \ elfutils-libelf elfutils-libelf-devel这里面有几个需要特别说明的坑。
第一个是compat-libstdc++-33。这个老兼容库在 CentOS 7 默认仓库里不一定能直接装到,如果 yum 提示找不到软件包,需要去镜像仓库里找对应的 rpm 包手动安装。安装的时候注意选对 64 位版本:
rpm -ivh compat-libstdc++-33-3.2.3-69.el7.x86_64.rpm第二个是ksh。Oracle 11g 官方安装文档里点名要求pdksh,但 CentOS 7 没有这个包,用ksh替代就行,Oracle 11g 是认ksh的。如果不放心,可以安装完数据库后检查一下,运行ls -l /bin/ksh,确保链接存在。
第三个是libaio-devel。这个包是异步 I/O 库的开发版,很多新手会漏,安装过程中可能不报错,但建库时容易出ora-27121: unable to determine size of shared memory segment之类的问题。
装完以后,用下面的命令逐个核对关键库是否就位:
rpm -q binutils glibc ksh libaio libaio-devel sysstat unixODBC如果某个包显示没有安装,就针对性补齐。这一步能够拦住一半以上的安装失败。
2.3 用户、组和目录规划
Oracle 数据库不允许用 root 用户直接运行安装程序,必须要建独立的操作系统用户。原因很直接:数据库进程需要被系统管控,权限过大反而危险,而且 Oracle 内部有一套自己的权限体系,要求操作系统用户和组做对应映射。
执行如下:
groupadd oinstall groupadd dba useradd -g oinstall -G dba oracle passwd oracle说明一下这两个组的分工:oinstall是 Oracle 软件所有者主组,dba组负责数据库管理操作。这里有个常见的理解误区,dba组不是只能建一个,如果你希望不止一个人能管理数据库,可以把多个用户都加入dba组,这样他们都能以 SYSDBA 身份连库。
目录规划遵循 OFA(Oracle Flexible Architecture)标准,这个标准的好处是同一台机器上装多套 Oracle 环境时,目录彼此不冲突,升级和备份也清晰。按下面的规划建立目录:
mkdir -p /u01/app/oracle mkdir -p /u01/app/oracle/product/11.2.0/dbhome_1 chown -R oracle:oinstall /u01 chmod -R 775 /u01这里的/u01/app/oracle就是ORACLE_BASE,/u01/app/oracle/product/11.2.0/dbhome_1是ORACLE_HOME。目录权限要给到oracle用户,否则安装程序没有写权限,会在 Inventory 初始化阶段直接失败。
2.4 内核参数与资源限制调整
Oracle 依赖操作系统的共享内存和信号量机制,这部分参数不调,就算软件装好了,实例也未必能正常启动。我见过太多人跳过了这一步,最后建库时报ORA-27102: out of memory,才回头去改内核参数。
编辑/etc/sysctl.conf,追加以下内容:
kernel.semmsl = 32000 kernel.semmns = 32000 kernel.semopm = 100 kernel.semmni = 128 kernel.shmall = 1048576 kernel.shmmax = 2147483648 kernel.shmmni = 4096 fs.file-max = 6815744 fs.aio-max-nr = 1048576 net.core.rmem_default = 262144 net.core.rmem_max = 4194304 net.core.wmem_default = 262144 net.core.wmem_max = 1048586 vm.min_free_kbytes = 524288改完执行sysctl -p让参数立即生效。
这里把两个最核心的参数单独讲讲,因为很多人是照抄数值,根本不理解含义。
kernel.shmmax是单个共享内存段的最大字节数。Oracle 的 SGA 是一大块共享内存,如果这个值小于 SGA 需求,实例会启动失败。官方建议值一般是物理内存的一半,举例:4GB 内存的主机,按字节算就是 4 * 1024 * 1024 * 1024 / 2 = 2147483648,也就是 2GB。这也是我在配置里写2147483648的原因。
kernel.shmall是共享内存页的总数,单位是页,不是字节。Linux 默认内存页大小通常是 4096 字节,可以用getconf PAGESIZE确认。4GB 内存换算成页数:
4 * 1024 * 1024 * 1024 / 4096 = 1048576这就是配置里1048576的来历。如果你机器是 8GB 内存,shmall要翻倍改成2097152,shmmax改成4294967296。算清楚参数,比死记硬背数值靠谱得多。
接下来是资源限制。编辑/etc/security/limits.conf,追加:
oracle soft nproc 2047 oracle hard nproc 16384 oracle soft nofile 1024 oracle hard nofile 65536 oracle soft stack 10240这些限制作用分别是:nproc控制最大进程数,nofile控制最大文件句柄数,stack控制栈大小。数据库实例会开启大量进程和文件句柄,如果nofile不够,运行时会报ORA-12547: TNS:lost contact一类的连接异常。
2.5 SELinux、防火墙与其它环境坑
CentOS 7 默认开启 SELinux,这对 Oracle 是不友好的。最省事的方案是把 SELinux 设为 permissive 模式,也就是不拦截但记录告警,既能保证安装顺利,又保留了审计能力。
setenforce 0 sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config注意setenforce 0只对当前会话生效,重启后以配置文件为准,所以两行都要执行。
防火墙方面,如果开启了 firewalld,需要放行 Oracle 的监听端口:
firewall-cmd --permanent --add-port=1521/tcp firewall-cmd --reload还有一个容易忽略的点是/etc/hosts。Oracle 安装过程中会做主机名解析,如果/etc/hosts里没有本机的主机名映射,安装会卡在“检查主机名”这一步。确保里面有类似这样的一行:
127.0.0.1 localhost localhost.localdomain <本机IP> db-server3. Oracle 11g 安装核心流程实操
3.1 安装介质获取与校验
Oracle 11g 的官方安装包是两组 zip 文件,体积都不小,一组是安装主程序,另一组是补充模块。从官方渠道下载需要注册账号,企业内部通常由 DBA 统一保管安装介质。拿到压缩包后,上传到服务器并做完整性校验。
Linux 下用 md5sum 校验:
md5sum linux.x64_11gR2_database_1of2.zip linux.x64_11gR2_database_2of2.zip把计算出来的 MD5 值与官方发布值比对,不一致就重新下载。这一步别省,我遇到过安装包在传输过程中损坏,解压报错,排查了半天才发现是文件不完整。
3.2 静默安装:响应文件与执行过程
解压两组安装包:
mkdir /oracle_install unzip linux.x64_11gR2_database_1of2.zip -d /oracle_install unzip linux.x64_11gR2_database_2of2.zip -d /oracle_install解压完成后,进入database目录,可以看到响应文件的模板目录:
cd /oracle_install/database/response我用的是db_install.rsp这个模板,复制出来修改:
cp db_install.rsp /oracle_install/db_install_my.rsp chown oracle:oinstall /oracle_install/db_install_my.rsp关键是修改以下几项,其它项目保持默认即可:
oracle.install.responseFileVersion=/oracle/install/rspfmt_dbinstall_response_schema_v11_2_0 oracle.install.option=INSTALL_DB_SWONLY ORACLE_HOSTNAME=db-server UNIX_GROUP_NAME=oinstall INVENTORY_LOCATION=/u01/app/oraInventory SELECTED_LANGUAGES=en,zh_CN 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 DECLINE_SECURITY_UPDATES=true解释几个关键项。INSTALL_DB_SWONLY表示只安装数据库软件,不建库,建库放到后面单独用 dbca 做,这样责任边界清晰,出问题好定位。INVENTORY_LOCATION是 Oracle 产品的统一清单目录,记录装了哪些组件,未来做 patch 和卸载都靠它。DECLINE_SECURITY_UPDATES=true必须配,否则安装程序会尝试连接 Oracle 的更新服务,在无外网环境下会卡很久。
切换到 oracle 用户执行安装:
su - oracle cd /oracle_install/database ./runInstaller -silent -responseFile /oracle_install/db_install_my.rsp执行后终端会进入等待状态,不要 Ctrl-C,静默安装通常需要 10 到 30 分钟,具体看机器性能。日志会写到:
/u01/app/oraInventory/logs/可以用tail -f跟踪日志,也可以打开installActions*.log看进度和错误。
安装过程结束后,按照日志里的提示,用 root 用户执行两个脚本:
/u01/app/oraInventory/orainstRoot.sh /u01/app/oracle/product/11.2.0/dbhome_1/root.sh执行root.sh时会询问 local bin 目录路径,直接回车用默认值即可。这两个脚本的作用是修正 Inventory 目录的属主权限和注册系统级环境信息,漏执行会导致后续 patch 和卸载异常。
3.3 监听配置:netca 与 listener.ora
软件装好后先配监听。监听器是客户端连接数据库的入口,相当于一栋大楼的前台,客户端先找前台,前台再带你找具体房间,这里的“房间”就是具体的 SID。
静默配置监听用 netca:
su - oracle $ORACLE_HOME/bin/netca /silent /responsefile $ORACLE_HOME/assistants/netca/netca.rsp执行成功后,监听默认监听 1521 端口。查看状态:
$ORACLE_HOME/bin/lsnrctl status正常会显示Listening Endpoints Summary...,端口 1521,状态显示READY。
如果希望监听配置固定,也可以直接改$ORACLE_HOME/network/admin/listener.ora,典型内容:
LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = db-server)(PORT = 1521)) ) )改完重启监听:
$ORACLE_HOME/bin/lsnrctl stop $ORACLE_HOME/bin/lsnrctl start注意HOST参数不要填localhost,否则远程客户端会连不上。这个参数正确写法是主机名或者对外 IP。
3.4 数据库实例创建:dbca 建库实操
监听就绪后就到了最关键的一步:建库实例。用 dbca 静默建库是最高效的方式,一次把数据库名字、SID、字符集、系统口令全部定好。
我常用的静默建库命令:
su - oracle $ORACLE_HOME/bin/dbca -silent -createDatabase \ -templateName General_Purpose.dbc \ -gdbName orcl \ -sid orcl \ -responseFile NO_VALUE \ -characterSet AL32UTF8 \ -memoryPercentage 40 \ -emConfiguration NONE \ -sysPassword Oracle123 \ -systemPassword Oracle123参数说明:
templateName:建库模板。General_Purpose.dbc是通用模板,包含 system、sysaux、undo、temp 等基础表空间,适合绝大多数场景。gdbName和sid:数据库名与实例名,这里是 orcl。characterSet:字符集,推荐 AL32UTF8,原因后面单独讲。memoryPercentage:内存分配给 Oracle 的百分比,40% 是比较均衡的值。4GB 内存的机器,Oracle 能拿到 1.6GB,SGA 和 PGA 会自动分配。emConfiguration:企业管控配置,生产环境一般不用,设为 NONE 跳过。sysPassword/systemPassword:超级管理员口令,长度必须满足复杂度要求,Oracle 会校验,太简单会被拒。
建库过程需要几分钟,结束时日志会提示数据库创建成功,并给出实例的初始化相关文件路径。
建库完成后,立刻验证:
sqlplus / as sysdba SQL> select name, open_mode from v$database; SQL> select status from v$instance;能看到orcl处于READ WRITE状态、实例状态为OPEN,整个安装链路就通了。
3.5 字符集选型的关键决策
数据库字符集这一步,是很多人后期痛苦的根源,所以单独拿出来重点讲。
AL32UTF8是 Oracle 的 UTF-8 实现,能覆盖几乎所有语言的字符,多语言系统互通性最好。代价是中文亚洲字符在 UTF-8 下面比 GBK 占用更多存储空间,比如一个汉字 GBK 存 2 字节,UTF-8 存 3 字节。
如果你的业务只在国内跑,历史系统也用 GBK,那么选ZHS16GBK更省空间。但如果是新系统,我强烈建议直接上 AL32UTF8。原因很简单:字符集一旦建库定好,想修改非常麻烦,通常只能重建库或者做数据泵迁移,那种痛苦远大于多出来的几十 GB 存储空间。
字符集选择还会影响连接客户端。客户端的NLS_LANG环境变量要和数据库字符集保持一致,否则插入中文时会出现乱码。
4. 使用阶段的运维要点与性能优化
4.1 内存配置:SGA 与 PGA
实例建好了,下一个问题就是内存配多少。Oracle 的内存分为两大块:SGA(系统全局区)和 PGA(进程全局区)。SGA 是实例启动时分配的一块共享内存,所有会话都能访问,缓存数据块、SQL 解析结果都在里面;PGA 是每个服务进程私有的内存区域,排序、哈希连接这些操作主要用 PGA。
查看当前配置:
show parameter sga; show parameter pga; show parameter memory;11g 默认启用了 AMM(Automatic Memory Management),也就是用一个memory_target参数控制总内存,SGA 和 PGA 在运行时动态调整。但如果主机物理内存比较小,比如只有 2GB 或 4GB,AMM 反而容易引起内存抖动,因为系统内存不足时,Oracle 会自动把内存从 SGA 挪到 PGA,频繁调整反而带来性能波动。这种情况下,我更倾向于固定 SGA 和 PGA 的经验值。
以 4GB 内存、总配额 1.6GB 为例:
alter system set sga_max_size=1024M scope=spfile; alter system set sga_target=1024M scope=spfile; alter system set pga_aggregate_target=512M scope=spfile;scope=spfile表示修改持久化到服务器参数文件,重启实例后生效。
配置的时候遵循一个简单原则:OLTP 在线交易类业务,SGA 占大头,最好占到 70% 以上;偏统计报表的 DW 类业务,PGA 要给足,排序操作慢了会直接拖慢整个报表。
4.2 表空间管理与日常巡检
Oracle 实例日常运维绕不开表空间管理。表空间是逻辑存储容器,底下一个或多个数据文件。最常见的故障是表空间满了,应用直接报错,业务中断。
日常巡检用这几条 SQL 就够了:
-- 查看表空间使用率 select t.tablespace_name, round((t.total_size - f.free_size) / t.total_size * 100, 2) as used_pct from (select tablespace_name, sum(bytes) total_size from dba_data_files group by tablespace_name) t, (select tablespace_name, sum(bytes) free_size from dba_free_space group by tablespace_name) f where t.tablespace_name = f.tablespace_name;数据文件是否自动扩展:
select tablespace_name, file_name, autoextensible, maxbytes from dba_data_files;生产环境我一般把核心业务表空间做到 10GB 起步,并打开自动扩展,但设置maxbytes上限,防止极端情况下写爆磁盘。数据文件可以手动增加:
alter tablespace users add datafile '/u01/app/oracle/oradata/orcl/users02.dbf' size 2G autoextend on next 512M maxsize 8G;这里有个规划技巧,数据文件不要全堆在一个磁盘分区里,尤其是把数据文件和归档日志文件放同一块物理盘,I/O 竞争会很严重。有条件就把日志文件和数据文件分盘存放。
4.3 服务启停与开机自启脚本
Oracle 不像 MySQL 那样在 systemd 里有现成服务,需要自己维护启停。我长期在用的方式是把启动和关闭各写成一个脚本,再配置开机自启。
启动脚本/u01/scripts/ora_start.sh:
#!/bin/bash export ORACLE_BASE=/u01/app/oracle export ORACLE_HOME=$ORACLE_BASE/product/11.2.0/dbhome_1 export ORACLE_SID=orcl export PATH=$PATH:$ORACLE_HOME/bin $ORACLE_HOME/bin/lsnrctl start $ORACLE_HOME/bin/sqlplus / as sysdba <<EOF startup EOF关闭脚本/u01/scripts/ora_stop.sh:
#!/bin/bash export ORACLE_BASE=/u01/app/oracle export ORACLE_HOME=$ORACLE_BASE/product/11.2.0/dbhome_1 export ORACLE_SID=orcl export PATH=$PATH:$ORACLE_HOME/bin $ORACLE_HOME/bin/sqlplus / as sysdba <<EOF shutdown immediate EOF $ORACLE_HOME/bin/lsnrctl stop生产环境千万别用shutdown abort做日常关闭,那是异常情况才用的,会触发实例恢复流程,启动时间会拉长。正常操作用shutdown immediate,等 Oracle 把事务回滚和清理做完再退出。
把脚本交给 root 通过 rc.local 执行开机自启:
echo "/u01/scripts/ora_start.sh" >> /etc/rc.local chmod +x /etc/rc.local /u01/scripts/ora_start.sh /u01/scripts/ora_stop.sh4.4 备份策略:expdp 与 RMAN 搭配
数据库投入使用后,备份就是头等大事。我常用的备份策略是把逻辑备份和物理备份结合起来。物理备份出问题可以用逻辑备份兜底;逻辑备份迁移方便,物理备份恢复速度更快。
逻辑备份用expdp,适合做表级、schema 级的定期导出:
expdp oracle/oracle@orcl schemas=scott directory=DATA_PUMP_DIR dumpfile=scott_$(date +%Y%m%d).dmp logfile=expdp_scott.log配合 crontab 做每日导出:
0 2 * * * su - oracle -c "/u01/scripts/backup_dp.sh" > /dev/null 2>&1物理备份用 RMAN,核心脚本:
rman target / <<EOF backup database plus archivelog delete input; delete obsolete; EOFdelete input的作用是备份成功的归档日志直接删除,避免归档堆积占满磁盘。delete obsolete清理超出保留策略的旧备份。备份保留策略我一般设置为恢复窗口 7 天,既能覆盖日常故障,又不会让备份体积无限膨胀。
无论选哪种备份,都要定期做恢复演练。只备份不验证,等于没备份,这个教训我在生产事故里见到太多次了。
5. 常见问题与排查技巧实录
5.1 依赖缺失与运行时报错
先列一个最常见的报错清单,都是我实际遇到过的。
| 报错信息 | 本质原因 | 解决方法 |
|---|---|---|
libaio.so.1: cannot open shared object file | libaio 库缺失 | yum 安装 libaio libaio-devel |
compat-libstdc++-33 not found | 旧版 C++ 兼容库缺失 | 手动安装对应 rpm 包 |
ORA-12547: TNS:lost contact | 环境变量或库文件权限问题 | 确认 ORACLE_HOME 环境变量、检查 oracle 用户环境 |
ORA-27102: out of memory | 内核共享内存参数不够 | 调大 kernel.shmmax/shmmall |
ORA-01034: ORACLE not available | 实例未启动或参数文件损坏 | 查 alert 日志,确认实例状态 |
ORA-12505: TNS:listener does not currently know SID | 监听未识别实例 | 让实例注册监听或用静态监听配置 |
在这些问题里,ORA-01034是最容易被误判的。刚装完数据库,执行sqlplus / as sysdba后想看数据却报这个错,其实不是数据库坏了,而是实例压根没启动过。解决办法是用 sysdba 登录后执行startup。如果startup依然失败,立刻看告警日志:
tail -200 $ORACLE_BASE/diag/rdbms/orcl/orcl/alert_log日志里会有更底层的错误信息,定位精度远高于在终端猜。
5.2 监听相关的经典故障
监听问题在安装后的客户端连接阶段集中爆发,典型场景是:SQL*Plus 本机可以登录,远程客户端却报ORA-12514或ORA-12505。
原因基本是动态服务注册没有正常完成。实例刚启动时,PMON 进程会主动向监听注册服务名,但如果监听配置里的 HOST 是localhost,注册就会绑到回环地址上,导致外部客户端通过 IP 访问时找不到服务。
解决思路分两步。第一步,在listener.ora里把 HOST 改成对外地址或主机名;第二步,确认命名方式里能解析到服务名。最省事的应急办法是使用静态监听,在listener.ora里追加一段服务名注册:
SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (GLOBAL_DBNAME = orcl) (ORACLE_HOME = /u01/app/oracle/product/11.2.0/dbhome_1) (SID_NAME = orcl) ) )配置后重启监听,lsnrctl status在Services Summary下能看到 orcl 实例,客户端连接问题就解决了。
5.3 实例启动失败与共享内存调整
还有一个高频故障发生在给数据库加内存之后。你调大了 SGA,重启实例,结果 Oracle 起不来了,报错ORA-27102: out of memory。
这事的根因通常不是 Linux 内存不足,而是共享内存内核参数没跟上。SGA 是一块共享内存段,它的最大值不能超过kernel.shmaxx;同时系统允许的共享内存页总数受kernel.shmall限制,SGA 需要的内存页超过了这个总量,照样起不来。
解决办法很简单,回到 2.4 节的参数,按新 SGA 大小重新计算并修改:
sysctl -w kernel.shmmax=4294967296 sysctl -w kernel.shmall=2097152 sysctl -p再把 SGA 改成合理值:
alter system set sga_target=2G scope=spfile; alter system set sga_max_size=2G scope=spfile;重启实例验证。记住一个原则:先改内核参数,再改数据库参数,顺序反了照样报错。
5.4 中文乱码与字符集问题
实例一切正常,应用插入中文后查出来是乱码,这个问题几乎每个刚上手的人都会碰到。
排查分三步。第一步看数据库字符集:
select userenv('language') from dual;第二步看客户端环境变量:
echo $NLS_LANG第三步看数据库实际存储字节,用dump函数:
select dump(column_name) from table_name where rownum=1;常见原因是客户端NLS_LANG设置成了AMERICAN_AMERICA.US7ASCII,导致应用传输的编码和数据库编码不一致。解决办法是在客户端机器或应用服务器上统一设置:
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8如果客户端系统本身是 GBK 编码,可以设成:
export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK绕开乱码问题最好的办法,还是从建库开始就统一 UTF 字符集,客户端全部配置对齐,后患最少。
5.5 我的避坑清单
按照踩坑概率从高到低,整理一份清单:
- 缺依赖包:安装程序报错前,先把
rpm -q检查跑一遍,尤其是 libaio、ksh、compat-libstdc++-33。 - 内核参数乱填:
shmmax和shmall单位不同,前者是字节,后者是页,算错结果天差地别。 - 忘记改 SELinux:安装过程各种
permission denied,查一圈才发现是 SELinux 拦截。 - 用 root 跑安装:安装程序虽然会提示禁止,但总有人为了省事切换 root 执行,最后 Inventory 权限全乱。
/etc/hosts缺主机名:安装和建库阶段莫名卡死,其实是主机名解析阻塞。- 字符集拍脑袋选:建库后再想改字符集,折腾程度是重新建库的好几倍。
- 备份从不恢复验证:备份脚本写了三年,灾难恢复时发现备份文件早就损坏,全部白干。
- 数据文件和归档日志同盘:I/O 竞争严重,高峰期数据库性能断崖式下跌。
6. 写在最后的个人体会
我经手过很多次 CentOS 7 上装 Oracle 11g 的部署,说实话,这套流程本身并不复杂,真正决定成败的是前期准备工作。依赖包、内核参数、SELinux、目录权限,任何一步草率处理,后面都要花更大的代价去排查。很多人在安装失败后反复折腾 runInstaller,却忽略了报错前的系统检查输出,这是本末倒置。
另外一个体会是,数据库装好不是终点,而是运维的起点。SGA 怎么配、备份怎么做、自启脚本怎么写,这些和安装同等重要。尤其对于还在学习阶段的朋友,我建议每装完一套环境,都顺手把恢复演练做一遍,在虚拟机里模拟一次数据文件损坏并完整恢复,这对理解 Oracle 的工作原理比看十遍文档都有效。
真到了生产环境,请时刻记住两条底线:数据库目录独立分区,备份做定时验证。做到这两点,这套旧组合的稳定性足以让你在很长时间里睡得安稳。