当前位置:首页 > 问答 > 正文

Oracle运维 数据库管理 Linux下的Oracle启动脚本编写与优化

Oracle运维实战:Linux下启动脚本编写与优化指南

【2025年8月行业动态】根据最新发布的数据库管理趋势报告,全球仍有超过65%的企业级数据库运行在Oracle平台上,其中近40%部署在Linux环境中,随着Oracle 23c的逐步普及,自动化运维和脚本优化成为DBA日常工作的核心技能之一。

为什么需要定制Oracle启动脚本?

老张是我们公司的资深DBA,上周五半夜被叫起来处理数据库宕机问题,原来服务器意外重启后,Oracle没跟着起来,导致早高峰业务系统全线瘫痪,这种事情其实完全可以通过规范的启动脚本避免。

标准Linux安装的Oracle自带启动脚本通常存放在/etc/init.d目录下,比如dbora,但这些通用脚本往往存在几个问题:

  1. 启动顺序控制不精确
  2. 缺少完善的状态检测
  3. 日志记录过于简单
  4. 资源分配不够灵活

手把手编写基础启动脚本

我们先从最基础的脚本开始,用vim新建一个/usr/local/bin/ora_start.sh

#!/bin/bash
# Oracle启动脚本v1.0
# 创建日期:2025-08-15
ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1
ORACLE_OWNER=oracle
SID=ORCL
case "$1" in
start)
    echo -n "Starting Oracle: "
    su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/lsnrctl start"
    su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/dbstart $ORACLE_HOME"
    touch /var/lock/subsys/oracle
    echo "OK"
    ;;
stop)
    echo -n "Shutting down Oracle: "
    su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/dbshut $ORACLE_HOME"
    su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/lsnrctl stop"
    rm -f /var/lock/subsys/oracle
    echo "OK"
    ;;
restart)
    $0 stop
    $0 start
    ;;
*)
    echo "Usage: $0 {start|stop|restart}"
    exit 1
esac
exit 0

给脚本执行权限:

chmod 750 /usr/local/bin/ora_start.sh
chown oracle:oinstall /usr/local/bin/ora_start.sh

这个基础版本已经能应付简单场景,但离生产环境要求还差得远。

生产级脚本优化技巧

1 添加资源限制

在启动前设置合理的系统参数:

Oracle运维 数据库管理 Linux下的Oracle启动脚本编写与优化

# 在start部分添加
ulimit -u 16384 -n 65536
sysctl -w kernel.shmall=2097152 >/dev/null
sysctl -w kernel.shmmax=2147483648 >/dev/null

2 完善的日志记录

LOG_FILE=/var/log/oracle_start.log
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') $1" | tee -a $LOG_FILE
}
# 使用时替换原来的echo
log_message "Starting Oracle Listener..."

3 状态检测机制

check_oracle_status() {
    pmon_count=$(ps -ef | grep -v grep | grep ora_pmon_$SID | wc -l)
    [ $pmon_count -eq 1 ] && return 0 || return 1
}
# 在启动后添加检查
sleep 5  # 等待启动完成
if check_oracle_status; then
    log_message "Oracle started successfully"
else
    log_message "ERROR: Oracle failed to start!"
    exit 1
fi

4 依赖服务检查

check_required_services() {
    # 检查ASM是否运行
    if [ -f /etc/oracle/asm.conf ]; then
        asm_status=$(crsctl check has)
        [ "$asm_status" != "CRS-4638" ] && {
            log_message "ASM not running, starting ASM first..."
            /etc/init.d/init.ohasd start
            sleep 10
        }
    fi
    # 检查共享内存是否足够
    shm_avail=$(df -k /dev/shm | awk 'NR==2 {print $4}')
    [ $shm_avail -lt 1048576 ] && {
        log_message "WARNING: /dev/shm has only ${shm_avail}KB free"
    }
}

Systemd服务集成(适用于较新Linux版本)

现在主流Linux发行版都转向systemd,我们可以创建更专业的服务单元:

# /etc/systemd/system/oracle.service
[Unit]
Description=Oracle Database Service
After=syslog.target network.target
[Service]
Type=forking
Environment=ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1
Environment=ORACLE_SID=ORCL
ExecStart=/usr/local/bin/ora_start.sh start
ExecStop=/usr/local/bin/ora_start.sh stop
User=oracle
Group=oinstall
TimeoutSec=300
[Install]
WantedBy=multi-user.target

启用服务:

systemctl daemon-reload
systemctl enable oracle

常见问题排错指南

  1. ORA-00845 MEMORY_TARGET错误 检查/dev/shm大小,在启动脚本中添加:

    mount -o remount,size=8G /dev/shm
  2. 监听器启动慢 添加DNS超时设置:

    echo "NAMES.DIRECTORY_PATH= (TNSNAMES, EZCONNECT)" >> $ORACLE_HOME/network/admin/sqlnet.ora
  3. 权限问题 确保脚本中所有Oracle路径的权限正确:

    chown -R oracle:oinstall /u01/app/oracle

性能优化建议

  1. 并行启动组件:使用&让监听器和数据库实例并行启动

    su - oracle -c "$ORACLE_HOME/bin/lsnrctl start &"
    su - oracle -c "$ORACLE_HOME/bin/dbstart $ORACLE_HOME &"
    wait
  2. 内存预热:对于频繁重启的环境,可以在启动后执行:

    Oracle运维 数据库管理 Linux下的Oracle启动脚本编写与优化

    sqlplus / as sysdba <<EOF
    @?/rdbms/admin/utlrp.sql
    exit
    EOF
  3. 启动超时控制:在systemd单元中添加TimeoutStartSec=600防止误判

安全加固措施

  1. 脚本文件权限设置:

    chmod 750 /usr/local/bin/ora_*.sh
    chown root:oinstall /usr/local/bin/ora_*.sh
  2. 密码安全处理:

    # 使用Oracle Wallet替代明文密码
    mkstore -wrl $ORACLE_HOME/wallet -create
    mkstore -wrl $ORACLE_HOME/wallet -createCredential ORCL sys password
  3. 日志文件保护:

    chmod 640 /var/log/oracle_*.log
    chown oracle:oinstall /var/log/oracle_*.log

最终优化版脚本示例

以下是综合了所有优化点的生产环境脚本框架:

#!/bin/bash
# Oracle智能启动脚本v3.2
# 配置区
ORACLE_HOME=/u01/app/oracle/product/19.0.0/dbhome_1
ORACLE_OWNER=oracle
SID=ORCL
LOG_FILE=/var/log/oracle_control.log
LOCK_FILE=/var/lock/subsys/oracle
# 初始化日志
init_log() {
    [ ! -d $(dirname $LOG_FILE) ] && mkdir -p $(dirname $LOG_FILE)
    exec 3>&1 4>&2
    exec 1>>$LOG_FILE 2>&1
    echo "====== $(date '+%Y-%m-%d %H:%M:%S') $1 ======"
}
# 状态检查
check_status() {
    # 简化版状态检查逻辑
    if pgrep -u $ORACLE_OWNER ora_pmon_$SID >/dev/null; then
        return 0
    else
        return 1
    fi
}
# 资源检查
check_resources() {
    # 内存检查
    local mem_free=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
    [ $mem_free -lt 1048576 ] && {
        echo "WARNING: Only ${mem_free}KB memory available"
        return 1
    }
    return 0
}
case "$1" in
start)
    init_log "Start Request"
    if check_status; then
        echo "Oracle is already running"
        exit 0
    fi
    check_resources || exit 1
    echo "Setting system parameters..."
    ulimit -u 16384 -n 65536
    sysctl -w kernel.shmall=2097152 >/dev/null
    echo "Starting Oracle components..."
    su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/lsnrctl start" &
    su - $ORACLE_OWNER -c "$ORACLE_HOME/bin/dbstart $ORACLE_HOME" &
    wait
    sleep 3
    if check_status; then
        touch $LOCK_FILE
        echo "Startup completed successfully"
        exit 0
    else
        echo "ERROR: Startup failed!"
        exit 1
    fi
    ;;
stop)
    # 类似逻辑的停止处理
    ;;
status)
    check_status && echo "Running" || echo "Stopped"
    ;;
*)
    echo "Usage: $0 {start|stop|restart|status}"
    exit 1
esac
exit 0

维护建议

  1. 定期检查:每月验证脚本功能,特别是升级系统或Oracle版本后
  2. 版本控制:将脚本纳入Git等版本控制系统
  3. 文档记录:维护README文件记录特殊配置项
  4. 监控集成:将启动日志接入现有监控系统

好的启动脚本应该像优秀的DBA一样——平时默默无闻,关键时刻从不掉链子,花点时间优化你的启动脚本,它能帮你省下无数个被电话吵醒的深夜。

发表评论