暂无图片
暂无图片
12
暂无图片
暂无图片
暂无图片

Oracle 数据库启动过程之 nomount 详解

原创 Lucifer三思而后行 2024-08-27
1291

大家好,这里是 Lucifer三思而后行,专注于提升数据库运维效率。

目录

前言

作为一名 DBA,应该都玩过 Oracle 数据库,最熟悉的操作应该就是开关库了:

-- 开库 SQL> startup -- 关库 SQL> shutdown immediate

但是执行这两个命令,数据库到底做了什么?相信很多人都没有研究过,本系列打算详解一下 Oracle 数据库的启动和关闭过程,静心看完,相信一定可以帮助大家更加深入了解 Oracle 数据库。

介绍

Oracle 数据库启动分为三个阶段:

  • nomount:读取参数文件,启动实例,分配 SGA,启动部分进程。
  • mount:实例启动后读取控制文件,挂载数据库。
  • open:读取数据文件和日志文件,启动数据库。

本文先讲数据库的第一个启动阶段:nomount 阶段,我这里演示环境是 11GR2 数据库。

nomount 阶段

nomount 阶段是数据库启动的第一个阶段,需要参数文件,会启动一个实例,在这个过程中会分配内存区域 SGA 以及启动一些后台进程。

参数文件

参数文件分为:

  • init<SID>.ora
  • spfile.ora
  • spfile<SID>.ora

单实例数据库存放在 $ORACLE_HOME/dbs 目录下,启动默认的查找顺序为:spfile<SID>.ora ---> spfile.ora ---> init<SID>.ora

可以发现当前数据库优先使用的是 spfile<SID>.ora 方式启动:

[oracle@rhel6:/home/oracle]$ cd $ORACLE_HOME/dbs [oracle@rhel6:/u01/app/oracle/product/11.2.0/db/dbs]$ ll -rw-rw----. 1 oracle oinstall 1544 Aug 26 22:57 hc_lucifer.dat -rw-r--r-- 1 oracle oinstall 2084 Jul 26 22:20 initlucifer.ora -rw-r--r--. 1 oracle oinstall 2851 May 15 2009 init.ora -rw-r-----. 1 oracle oinstall 24 Jul 10 18:43 lkLUCIFER -rw-r-----. 1 oracle oinstall 1536 Aug 19 21:50 orapwlucifer -rw-r----- 1 oracle oinstall 9781248 Aug 23 02:00 snapcf_lucifer.f -rw-r-----. 1 oracle oinstall 5632 Aug 26 13:27 spfilelucifer.ora

验证一下,启动数据库实例:

-- 不指定参数文件,启动到 mnount 状态 SQL> startup nomount ORACLE instance started. Total System Global Area 4275781632 bytes Fixed Size 2260088 bytes Variable Size 2801795976 bytes Database Buffers 1459617792 bytes Redo Buffers 12107776 bytes -- 查看实例的状态为 STARTED SQL> select status from v$instance; STATUS ------------------------------------ STARTED -- 查看 spfile 参数 SQL> show parameter spfile NAME TYPE VALUE ------------------------------------ --------------------------------- ------------------------------ spfile string /u01/app/oracle/product/11.2.0/db/dbs/spfilelucifer.ora

可以看到默认启动的参数文件是 spfilelucifer.ora,此时查看 alert 日志中参数文件相关的部分:

## 也可以看到是使用参数文件:/u01/app/oracle/product/11.2.0/db/dbs/spfilelucifer.ora,并且读取了参数文件中非系统默认的参数配置 Using parameter settings in server-side spfile /u01/app/oracle/product/11.2.0/db/dbs/spfilelucifer.ora System parameters with non-default values: processes = 2000 resource_limit = TRUE event = "28401 trace name context forever,level 1" event = "10949 trace name context forever,level 1" sga_max_size = 4G streams_pool_size = 1312M resource_manager_plan = "force:" sga_target = 4G _memory_imm_mode_without_autosga= FALSE control_files = "/oradata/lucifer/control01.ctl" control_files = "/u01/app/oracle/fast_recovery_area/lucifer/control02.ctl" control_file_record_keep_time= 31 db_block_size = 8192 compatible = "11.2.0.4.0" log_archive_dest_1 = "location=/oradata/archivelog" log_archive_format = "%t_%s_%r.dbf" _use_adaptive_log_file_sync= "FALSE" db_files = 5000 db_create_file_dest = "/oradata" db_recovery_file_dest = "/u01/app/oracle/fast_recovery_area" db_recovery_file_dest_size= 5532M enable_goldengate_replication= TRUE _datafile_write_errors_crash_instance= FALSE _cleanup_rollback_entries= 2000 undo_tablespace = "UNDOTBS1" _undo_autotune = FALSE undo_retention = 10800 _partition_large_extents = "FALSE" _index_partition_large_extents= "FALSE" sec_case_sensitive_logon = FALSE remote_login_passwordfile= "EXCLUSIVE" db_domain = "" dispatchers = "(PROTOCOL=TCP) (SERVICE=luciferXDB)" session_cached_cursors = 300 parallel_max_servers = 64 _PX_use_large_pool = TRUE audit_file_dest = "/u01/app/oracle/admin/lucifer/adump" audit_trail = "NONE" db_name = "lucifer" open_cursors = 1000 _optimizer_null_aware_antijoin= FALSE _b_tree_bitmap_plans = FALSE _optimizer_extended_cursor_sharing= "NONE" _optimizer_extended_cursor_sharing_rel= "NONE" _optimizer_adaptive_cursor_sharing= FALSE pga_aggregate_target = 1256M deferred_segment_creation= FALSE _optimizer_use_feedback = FALSE enable_ddl_logging = TRUE diagnostic_dest = "/u01/app/oracle"

所以,数据库实例启动的第一步就是找到参数文件,并且读取参数配置。

分配 SGA

通过第一步读取参数文件配置,可以获取到内存相关配置,包括 SGA 相关参数:

sga_max_size = 4G streams_pool_size = 1312M sga_target = 4G

在启动数据库实例过程中会输出以下信息:

Total System Global Area 4275781632 bytes Fixed Size 2260088 bytes Variable Size 2801795976 bytes Database Buffers 1459617792 bytes Redo Buffers 12107776 bytes

以上这些提示信息分别是什么意思呢?大家如果知道 SGA 有哪些组件,应该一下就能明白:

参考 11GR2 官方文档 Database Concepts:Memory Architecture

下面就详解一下启动数据库实例时输出的每一行的意思:

-- 这个是可分配的总 SGA 大小 Total System Global Area 4275781632 bytes -- 可以通过查询 select sum(value) from v$sga; 或者 select sum(bytes) from v$sgastat; -- 注意:以上两个 SQL 在 11G 查询出来的结果值有出入,在 19C 查出来是一模一样 -- 11GR2 SQL> select sum(value) from v$sga; SUM(VALUE) ---------- 4275781632 SQL> select sum(bytes) from v$sgastat; SUM(BYTES) ---------- 4275780728 -- 19C SQL> select sum(value) from v$sga; SUM(VALUE) ---------- 5318374384 SQL> select sum(bytes) from v$sgastat; SUM(BYTES) ---------- 5318374384 -- Fixed SGA Size 包含数据库和实例的状态信息等通用信息,后台进程需要访问这部分信息,用于进程之间传递信息,不存储用户数据,大小由 Oracle 数据库设置,无法手动更改,大小可能会因版本而异。 Fixed Size 2260088 bytes -- 可以通过查询 select * from v$sgainfo where name = 'Fixed SGA Size'; SQL> select * from v$sgainfo where name = 'Fixed SGA Size'; NAME BYTES RESIZEABL -------------------- ---------- --------- Fixed SGA Size 2260088 No -- Variable size 包括 Shared Pool Size、Java Pool Size、Large Pool Size 和 Streams Pool Size。 Variable Size 2801795976 bytes -- 可以通过查询 select * from v$sgainfo where name in ('Shared Pool Size','Java Pool Size','Large Pool Size','Streams Pool Size'); SQL> select * from v$sgainfo where name in ('Shared Pool Size','Java Pool Size','Large Pool Size','Streams Pool Size'); NAME BYTES RESIZEABL -------------------- ---------- --------- Shared Pool Size 587202560 Yes Large Pool Size 805306368 Yes Java Pool Size 33554432 Yes Streams Pool Size 1375731712 Yes -- 注意:这个 SQL 总和在 11G 查询出来的结果跟 Variable Size 的值有出入,在 19C 查出来是一模一样 SQL> select sum(bytes) from v$sgainfo where name in ('Shared Pool Size','Java Pool Size','Large Pool Size','Streams Pool Size'); SUM(BYTES) ---------- 2801795072 -- Buffer Cache Size,数据库缓冲区缓存,也称为缓冲区高速缓存,是存储从数据文件读取的数据块副本的内存区域。 Database Buffers 1459617792 bytes -- 可以通过查询 select * from v$sgainfo where name = 'Buffer Cache Size'; SQL> select * from v$sgainfo where name = 'Buffer Cache Size'; NAME BYTES RESIZEABL -------------------- ---------- --------- Buffer Cache Size 1459617792 Yes -- Redo Buffers,重做日志缓冲区是 SGA 中的一个循环缓冲区,用于存储数据库所做更改的重做记录。 Redo Buffers 12107776 bytes -- 可以通过查询 select * from v$sgainfo where name = 'Redo Buffers'; SQL> select * from v$sgainfo where name = 'Redo Buffers'; NAME BYTES RESIZEABL -------------------- ---------- --------- Redo Buffers 12107776 No

以上 SGA 组件内存分配的相关信息可以从 v$sgainfo 中查看:

SQL> select * from v$sgainfo; NAME BYTES RESIZEABL ---------------------------------------- ---------- --------- Fixed SGA Size 2260088 No Redo Buffers 12107776 No Buffer Cache Size 1459617792 Yes Shared Pool Size 587202560 Yes Large Pool Size 805306368 Yes Java Pool Size 33554432 Yes Streams Pool Size 1375731712 Yes Shared IO Pool Size 0 Yes Granule Size 16777216 No Maximum SGA Size 4275781632 No Startup overhead in Shared Pool 498329672 No Free SGA Memory Available 0

这部分内容无法从 alert 日志中获取相关信息,所以直接打印在 sqlplus 启动过程中,也可以通过 show sga 查看:

SQL> show sga Total System Global Area 4275781632 bytes Fixed Size 2260088 bytes Variable Size 2801795976 bytes Database Buffers 1459617792 bytes Redo Buffers 12107776 bytes

上面是将数据库层面的 SGA 内存分配,其实在操作系统层面也可以看出个大概:

## 开启实例前 [oracle@rhel6:/home/oracle]$ ipcs -a ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 0 root 644 80 2 0x00000000 32769 root 644 16384 2 0x00000000 65538 root 644 280 2 ## 可以看到,当数据库实例启动到 nomount 后,多了 3 个 oracle 用户的共享内存段 ## nattch 表示当前附加到这个共享内存段的进程数 ## oracle 用户 key 的值 0x00000000 的 bytes 之和为 4294967296,也就是 SGA 的大小为 4G,其中 33554432 代表的是 Java Pool Size,4261412864 是其他组件的总和。 [oracle@rhel6:/home/oracle]$ ipcs -m ------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 0 root 644 80 2 0x00000000 32769 root 644 16384 2 0x00000000 65538 root 644 280 2 0x00000000 917507 oracle 640 33554432 17 0x00000000 950276 oracle 640 4261412864 17 0x467a6680 983045 oracle 640 2097152 17

注意:上面的输出中,关于共享内存段的列的意思如下:

key:共享内存段的键值,用于标识。
shmid:共享内存段的ID。
owner:共享内存段的所有者。
perms:共享内存段的权限,通常以4位八进制数表示。
bytes:共享内存段的大小,单位是字节。
nattch:当前附加到这个共享内存段的进程数。
status:共享内存段的状态,可能包含额外的信息或为空。

综上发现,数据库实例启动的第二步是分配 SGA 组件内存。

启动进程

查看进程启动情况:

-- 数据库实例启动前,没有 lucifer 实例相关的后台进程 SQL> ! env | grep ORACLE_SID ORACLE_SID=lucifer SQL> ! ps -ef|grep -v grep|grep lucifer -- 数据库实例启动到 nomount 后,启动进程如下 SQL> ! ps -ef|grep -v grep|grep lucifer -- 后台进程 oracle 57755 1 0 16:56 ? 00:00:00 ora_pmon_lucifer oracle 57757 1 0 16:56 ? 00:00:00 ora_psp0_lucifer oracle 57759 1 2 16:57 ? 00:00:40 ora_vktm_lucifer oracle 57763 1 0 16:57 ? 00:00:00 ora_gen0_lucifer oracle 57765 1 0 16:57 ? 00:00:00 ora_diag_lucifer oracle 57767 1 0 16:57 ? 00:00:00 ora_dbrm_lucifer oracle 57769 1 0 16:57 ? 00:00:06 ora_dia0_lucifer oracle 57771 1 0 16:57 ? 00:00:00 ora_mman_lucifer oracle 57773 1 0 16:57 ? 00:00:00 ora_dbw0_lucifer oracle 57775 1 0 16:57 ? 00:00:00 ora_lgwr_lucifer oracle 57777 1 0 16:57 ? 00:00:00 ora_ckpt_lucifer oracle 57779 1 0 16:57 ? 00:00:00 ora_smon_lucifer oracle 57781 1 0 16:57 ? 00:00:00 ora_reco_lucifer oracle 57783 1 0 16:57 ? 00:00:00 ora_mmon_lucifer oracle 57785 1 0 16:57 ? 00:00:03 ora_mmnl_lucifer oracle 57787 1 0 16:57 ? 00:00:00 ora_d000_lucifer oracle 57789 1 0 16:57 ? 00:00:00 ora_s000_lucifer -- 前台进程,也就是当前连接的会话 oracle 61552 61551 0 17:29 ? 00:00:00 oraclelucifer (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq))) -- 这里可以看到 ora_ 后台进程数为 17 个,与 ipcs -m 看到的 nattch 的数量相符 SQL> ! ps -ef|grep -v grep|grep ora_|wc -l 17

可以看到当 Oracle 启动到 nomount 状态后,有以下后台进程被启动:

  • pmon(Process Monitor):监视其他后台进程,并在服务器或调度程序进程异常终止时执行进程恢复。
  • psp0(Process Spawner Process):初始实例启动后生成 Oracle 后台进程。
  • vktm(Virtual Keeper of Time Process):提供一个秒级更新的数据库时钟,减少数据库和操作系统的交互。
  • gen0(General Task Execution Process):为数据库提供了一个执行通用任务的进程,进程的主要目标是分担进程中某些可能造成阻塞的处理过程,并将他们放在后台完成。
  • diag(Diagnostic Capture Process):数据库诊断进程,负责维护管理各种用于诊断的转储文件,并执行 oradebug 命令。
  • dbrm(Database Resource Manager Process):数据库资源管理进程,负责设置资源计划和其他的资源管理的工作。
  • dia0(Diagnostic Process):数据库诊断进程,负责检测 Oracle 数据库中的挂起(hang)和死锁的处理。
  • mman(Memory Manager Process):实现共享内存自动管理。
  • dbw0(Database Writer Process):数据库写入程序,主要职责是将数据块写入磁盘,还负责处理检查点、文件打开同步以及块写入记录的日志记录。
  • lgwr(Log Writer Process):日志写入程序,将重做日志条目按顺序写入重做日志文件。
  • ckpt(Checkpoint Process):在检查点处发出 DBWn 信号并更新数据库的所有数据文件和控制文件以指示最近的检查点。
  • smon(System Monitor Process):执行关键任务(如实例恢复和死事务恢复)以及维护任务(如临时空间回收、数据字典清理和撤消表空间管理)。
  • reco(Recoverer Process):解决由于分布式数据库中的网络或系统故障而挂起的分布式事务。
  • mmon(Manageability Monitor Process):MMON 执行许多与可管理性相关的任务,包括获取自动工作负载存储库快照和执行自动数据库诊断监视器分析。
  • mmnl(Manageability Monitor Lite Process):是 AWR 新增的进程,主要作用是将 AWR 数据从内存中刷新到表中。
  • d000(Dispatcher Process):允许用户进程共享有限的服务器进程(SERVER PROCESS)。
  • s000(Shared Server Process):负责与用户进程通信,并与 Oracle 交互,以代表相关的用户进程执行任务。

注意:以上后台进程具体可参考官方文档:Background Processes

查看数据库 alert 日志中与进程启动相关的信息:

## 启动后台进程,一共 17个 Mon Aug 26 16:56:59 2024 PMON started with pid=2, OS id=57755 Mon Aug 26 16:56:59 2024 PSP0 started with pid=3, OS id=57757 Mon Aug 26 16:57:00 2024 VKTM started with pid=4, OS id=57759 at elevated priority VKTM running at (1)millisec precision with DBRM quantum (100)ms Mon Aug 26 16:57:00 2024 GEN0 started with pid=5, OS id=57763 Mon Aug 26 16:57:00 2024 DIAG started with pid=6, OS id=57765 Mon Aug 26 16:57:00 2024 DBRM started with pid=7, OS id=57767 Mon Aug 26 16:57:00 2024 DIA0 started with pid=8, OS id=57769 Mon Aug 26 16:57:00 2024 MMAN started with pid=9, OS id=57771 Mon Aug 26 16:57:00 2024 DBW0 started with pid=10, OS id=57773 Mon Aug 26 16:57:00 2024 LGWR started with pid=11, OS id=57775 Mon Aug 26 16:57:00 2024 CKPT started with pid=12, OS id=57777 Mon Aug 26 16:57:00 2024 SMON started with pid=13, OS id=57779 Mon Aug 26 16:57:00 2024 RECO started with pid=14, OS id=57781 Mon Aug 26 16:57:00 2024 MMON started with pid=15, OS id=57783 Mon Aug 26 16:57:00 2024 MMNL started with pid=16, OS id=57785

可以发现,数据库实例启动的第三步是启动进程。

总结

综上所述,可以总结出 nomount 阶段的启动过程大致如下:

  1. 查找参数文件,搜索顺序为:spfile<SID>.ora ---> spfile.ora ---> init<SID>.ora
  2. 读取参数文件,并启动数据库实例
  3. 分配 SGA 内存段
  4. 启动后台进程和前台进程

在这个阶段,不涉及控制文件以及数据文件,只需要参数文件即可,通常用于数据库创建、控制文件重建、特定的备份恢复等。


往期精彩文章推荐

Oracle RAC 修改系统时区避坑指南(深挖篇)
Ubuntu 22.04 一键安装 Oracle 11G RAC
使用 dbops 快速部署 MySQL 数据库
Oracle RAC 启动顺序,你真的了解吗?
达梦数据库一键安装脚本(免费)一篇文章让你彻底掌握 Python 🔥
一篇文章让你彻底掌握 Python
一篇文章让你彻底掌握 Shell 🔥
Oracle 监控 EMCC 13.5 安装部署超详细教程 🔥
Oracle 一键巡检自动生成 Word 报告 🔥
Oracle一键安装脚本的 21 个疑问与解答 🔥
Oracle一键巡检脚本的 21 个疑问与解答 🔥
全网首发:Oracle 23ai 一键安装脚本 🔥
Oracle 19C 最新 RU 补丁 19.24 ,一键安装! 🔥
Oracle Linux 6 一键安装 Oracle 11GR2 RAC
Oracle Linux 7.9 一键安装 Oracle 19C
Oracle Linux 8.9 一键安装 Oracle 19C RAC
Oracle Linux 9.4(aarch64) 一键安装 Oracle 19C 🔥
openEuler 20.03 LTS SP4 一键安装 Oracle 19C 🔥
openEuler 22.03 LTS SP4 一键安装 Oracle 19C RAC
RHEL 7.9 一键安装 Oracle 19C 19.23 RAC
Redhat 8.4 一键安装 Oracle 11GR2
RedHat 9.4(aarch64) 一键安装 Oracle 19C
龙蜥 Anolis 7.9 一键安装 Oracle 19C 19.23
龙蜥 Anolis OS 8.8 一键安装 Oracle 19C
SUSE 15 SP5 一键安装 Oracle 19C
统信 UOS V20 1070(a) 一键安装 Oracle 11GR2
Ubuntu 22.04 一键安装 Oracle 19C
Ubuntu 14.04 一键安装 Oracle 19C
银河麒麟 Kylin V10 SP3 一键安装 Oracle 19C 🔥
银河麒麟 Kylin V10 SP3 一键安装 Oracle 11GR2 RAC
Oracle DataGuard GAP 修复手册 🔥
优化 Oracle:最佳实践与开发规范
DBA 必备:Linux 软件源配置全攻略 🔥
Linux 一键配置时钟同步全攻略 🔥
Starwind 配置 ISCSI 共享存储
SUSE 15 SP3 安装 Oracle 19C RAC 数据库
达梦 8 数据库安装手册 🔥
Oracle 12CR2 RAC 安装避坑宝典
Linux7 安装 Oracle 19C RAC 详细图文教程 🔥
Oracle ADG 搭建 RAC to Single 详细教程
Oracle DataGuard GAP 修复手册 🔥
Oracle 分区表之在线重定义
AutoUpgrade 快速升级 Oracle 数据库
Oracle 数据库巡检命令手册 🔥
Oracle 数据坏块的 N 种修复方式 🔥
数据库 SQL 开发入门教程
超全 Linux 基础命令总结 🔥
VMware 虚拟机安装 Linux 系统
Linux 安装 MySQL 详细教程
教你玩转 SQLPLUS,工作效率提升 200%


感谢您的阅读,这里是 Lucifer三思而后行,欢迎 点赞+关注,我会持续分享数据库知识、运维技巧。

最后修改时间:2024-08-27 13:48:00
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论