第一章 Oracle 的体系结构
<h1>Oracle 的体系结构</h1>
<h2>1.1 Oracle 引入复杂的体系结构的原因:管理内存资源</h2>
<ul>
<li>内存是宝贵的稀有资源,引入复杂的体系结构对其进行有效管理。</li>
<li>储存使用到内存与外存,内存外存的区别应该了解。</li>
</ul>
<h2>1.2 Oracle 数据库中常用的术语</h2>
<ul>
<li>进程</li>
<li>后台进程</li>
<li>前台进程</li>
<li>缓冲区</li>
<li>主机</li>
<li>服务器</li>
<li>客户机</li>
</ul>
<h2>1.3 Oracle 数据库管理系统的体系结构</h2>
<ul>
<li>Oracle服务器、其他关键文件、用户进程、服务器进程
Oracle服务器
Oracle实例
Oracle数据库</li>
<li>服务器中的一些结构并不在处理SQL语句时使用,而是为了改进数据库系统的效率或数据的恢复等而设计</li>
</ul>
<h2>1.4 Oracle 服务器</h2>
<ul>
<li>一台机种可以装多个Oracle 服务器,一般只装一个</li>
<li>Oracle 服务器=实例(instance)+数据库(database)</li>
<li>Oracle服务器3种安装方式
基于主机方式
客户端-服务器(client-server)两层模型方式
客户端-应用服务器-服务器(client-application server-server)三层模型方式</li>
</ul>
<h2>1.5 Oracle实例</h2>
<ul>
<li>Oracle 实例是访问数据库的机制,由内存结构和一些后台进程组成。</li>
<li>内存结构:系统全局区(System Global Area,SGA)。系统全局区是实例最基本的部件之一。</li>
<li>5个必需的后台进程,任何一个没启动实例都自动关闭。
SMON、PMON、DBWR、LGWR、CKPT。除此之后的进程都是可选的。</li>
<li>一个实例只能操作一个数据库,一个数据库可以有多个实例。</li>
<li>系统全局区包含以下几个内存结构:
共享池(shared pool)
数据库高速缓冲区(database buffer cache)
重做日志缓冲区(redo log buffer)
一些其他结构(锁、统计数据等)</li>
</ul>
<h2>1.6 Oracle 数据库</h2>
<ul>
<li>数据集合,Oracle 把这些数据作为一个完整的单位来处理。</li>
<li>Oracle 数据库也称为物理(外存)结构,为数据库信息提供了真正的物理存储,由三部分组成:
控制文件(control files):包含了维护和校验数据库一致性所需的信息。
重做日志文件(redo log files):包含了当系统崩溃后进行恢复所需记录的变化信息。
数据文件(data files):包含了数据库真正的数据。</li>
</ul>
<h2>1.7 Oracle 其他关键文件</h2>
<ul>
<li>这些关键文件不属于数据库
初始化参数文件(parameter files):定义了实例的特性,如系统全局区中一些内存结构的大小、DBWR的个数。
密码文件(password files):包含了数据库管理员、操作员用户在启动和关闭实例时所需的密码。
归档重做日志文件(archived redo log files):是重做日志文件的脱机备份。在系统崩溃后恢复时可能需要这些文件。</li>
</ul>
<h2>1.8 建立与Oracle 实例的连接</h2>
<ul>
<li>启动Oracle 实例命令:startup;意味着SGP生成、五个后台进程运行。</li>
<li>由用户进程向 Oracle 服务器 的服务进程发起连接,账号、密码验证通过即会话开始;用户退出或者非正常终止连接会话结束。</li>
<li>用户进程与服务进程是一一对应关系,</li>
<li>连接:一个用户进程与一个Oracle 数据库实例之间的通信路径。</li>
<li>会话:代表的是一个当前用户登录该数据库实例的状态。</li>
</ul>
<h2>1.9 各种不同的连接方式</h2>
<ul>
<li>对应三种安装方式,有三种联接
基于主机方式:用户进程与Oracle 服务器之间的通信路径是通过操作系统内部进程通信机制来建立。
客户端-服务器(client-server)两层模型方式:通过网络协议(如TCP/IP)来完成。
客户端-应用服务器-服务器(client-application server-server)三层模型方式:个人计算机通过网络到应用\网络服务器通信,再网络通信到数据库计算机。</li>
</ul>
<h2>1.10 服务器进程</h2>
<ul>
<li>Oracle 创建一个服务器进程同时要为其分配一个内存区,该内存区称为程序全局区(PGA)。
PGA 是私有的内存区,不能共享,且只属于一个服务器进程。
随着进程创建而分配,进程终止而被回收。</li>
<li>程序全局区(PGA)包括以下结构:
排序区(sort area):
游标状态区(Curso):用于指示会话当前所使用的SQL语句处理状态。作用减少I/O将磁盘操作变成内存操作。
会话信息区(session information):
堆栈区(stack space):</li>
<li>共享服务器进程或者多线程服务器进程,以上前三个结构都将存在于SGA中,如果有large pool,它他将存在large pool 中,否则存在共享池中。</li>
</ul>
<h2>1.11 Oracle 执行SQL查询语句的步骤</h2>
<ul>
<li>分三步走:编译(parse)、执行(execute)、提取数据(fetch)</li>
</ul>
<h2>1.12 共享池</h2>
<ul>
<li>SGA中共享池由库高速缓存(library cache)和数据字典高速缓存(data dictionary)两部分组成。</li>
<li>服务器进程将sql语句正文和编译后的代码及执行计划存放于此。第二次执行在共享池中找相同的正文或者执行计划,而不再编译。</li>
<li>高速缓存包含共享SQL区和共享PL/SQL区,12c还可以缓存执行结果。</li>
<li>Oracle 是使用LRU 的队列或者算法来实现对库高速缓存的管理的。</li>
<li>库高速缓存越大,使用过的sql缓存就越多,但不能直接设置library cache的大小,只能通过设置共享池的大小间接地设置libary chace的大小。</li>
<li>数据字典高速缓存,服务器进程把数据文件、表、索引、列、用户等信息放入数据字典缓存区,这部分重用率也高,所以也要设置大,但是也是要间接设置。</li>
<li>9i之前设置共享池大小是修改参数文件的SHARED_POOL_SIZE的值,要重启Oracle 数据库。之前的版本如下:
<code>SQL>alter system set SHARED_POOL_SIZE=250M;</code> 来修改。</li>
<li>共享池足够大且SQL语句满足,也不一定使用内存中的缓存。
如:当用户修改了某个对象的定义,使用这个对象的共享池中的所有代码Oracle 将视其无法,必须重新编译。</li>
</ul>
<h2>1.13 数据库高速缓冲区(database buffer cache)</h2>
<ul>
<li>sql读数据:先在数据库高速缓冲区(database buffer cache)中搜索数据,如没有再进行磁盘操作把数据文件中的数据读读到数据库高速缓冲区。
所以为了能够共享数据库中的数据,数据库高速缓冲区要足够大。Oracle 使用LRU队列和算法来实现对数据库高速缓冲区进行管理。</li>
<li>决定数据库高速缓冲区大小的因素:database buffer cache的大小等于DB_BLOCK_SIZE与DB_BLOCK_BUFFERS的乘积。
DB_BLOCK_SIZE:数据块大小,内存与外存一致的。创建数据库时设定,修改要重建数据库。
DB_BLOCK_BUFFERS:内存缓冲区的个数。修改要重启数据库生效。
DB_CACHE_SIZE:9i后引入的动态参数,数据库运行时可以动态地改变该参数。
命令:<code>SQL>alter system set DB_CACHE_SIZE=250M;</code></li>
</ul>
<h2>1.14 内存缓冲区顾问(v$db_cache_advice)</h2>
<ul>
<li>作用:工具,用来帮助获得高速数据库高速缓冲区统计信息。共三种状态。
ON:打开,占内存、CPU
READY:关闭,占内存,不占CPU
OFF:关闭,不占内存,不占CPU</li>
<li>查看状态
<code>select id,name,block_size,advice_status from v$db_cache_advice ;</code></li>
<li>修改状态(参数是一个动态参数)
<code>alter system set db_cache_advice=off;</code></li>
</ul>
<h2>1.15 重做日志缓冲区(redo log buffer)</h2>
<ul>
<li>主要目的是数据恢复。使用任何DDL、DML操作改变数据之前(写数据入数据库高速缓冲区之前),先写入重做日志缓冲区(恢复所需要的信息)。</li>
<li>执行update 语句的步骤:
1、如果数据和回滚数据不在数据库高速缓冲区中,则Oracle 服务进程将把他们从数据文件中读到数据库高速缓冲区中。
2、Oracle 服务器进程在要修改的数据行上加锁(行一级的锁,而且是在内存的数据行上加锁)。
3、Oracle 服务器进程将数据变化信息和回滚所需要的信息都记录在重做日志缓冲区中。
4、Oracle 服务器进程将回滚所需的原始值和对数据所做的修改都写入数据库高速缓冲区。之后数据库高速缓冲区中的数据被称为脏数据,因为与内存中的数据是不同的了。</li>
</ul>
<h2>1.16 大池、java池和Streams池</h2>
<ul>
<li>large pool;java pool;streams pool 是三个可选的内存缓冲区。
large pool 提高效率,没有队列,I/O操作和备份/恢复操作时可能使用该区。
通过设置LARGE_POOL_SIZE的值来配置large pool的大小。</li>
<li>java pool 的目的是能够编译java 语言的命令。
通过设置JAVA_POOL_SIZE的值来配置java pool 的大小,单位是字节(bytes)</li>
<li>Streams pool 是由Oracle Streams 使用的,以存储捕获和应用所需的信息。</li>
</ul>
<h2>1.17 内存缓冲区大小的设定</h2>
<ul>
<li>9i之前的版本只能通过设置初始化文件中的一些参数间接地设置SGA(系统全局区)的大小,如DB_BLOCK_BUFFER、LOG_BUFFER、SHARED_POOL_SIZE等。是静态参数,修改后要重启数据库。</li>
<li>9i后SGA为动态参数,如数据库高速缓冲区、共享池可以动态增加或者减少,Oracle 分配和回收内存的基本单位是区组。</li>
<li>SGA中至少包括三个区组:SGA固定区组(重做日志缓冲区)、数据库高速缓冲区、共享池。</li>
<li>12c,当SGA尺寸小于或者等于1GB,区组大小是4MB;SGA大于1GB,区组大小就为16MB。</li>
<li>通过alter system set 命令分配和回收区组。但总内存大小不能超过参数SGA_MAX_SIZE所设定值。 </li>
</ul>
<h2>1.18 内存缓冲区信息的获取</h2>
<ul>
<li>使用如下命令获得参数SGA_MAX_SIZE:
<pre><code>SQL> show parameter sga_max_size ;
NAME TYPE VALUE
sga_max_size big integer 800M</code></pre></li>
<li>获取SGA的相关信息
<code>show sga</code></li>
<li>利用数据字典v$parameter 查看更多参数。
<code>select name,type,value from v$parameter where name='sga_max_size';</code></li>
</ul>
<h2>1.19 重做日志写进程及快速提交(LGWR)</h2>
<ul>
<li>重做日志写进程(LOG writer,LGWR)负责将重做日志缓冲区的记录顺序地写到重做日志文件中。要清楚commit的工作原理才能理解LGWR操作原理。</li>
<li>commit顺序:重做日志缓冲区-重做日志缓冲区提交到重做日志文件(用于恢复)-提示用户提交在成功-数据库高速缓冲区(解锁,数据可能还没真实写到数据文件中,由DBWR进程负责)。</li>
<li>重做日志写进程(LGWR)在以下情况将重做日志缓冲区的记录写到重做日志文件(外存)中:
当某个事务被提交时
当重做日志缓冲区中所存的记录已超过缓冲区容量的1/3
在DBWR将数据库高速缓冲区中修改过的数据写到数据文件之前(如果有需要)
每3秒</li>
</ul>
<h2>1.20 数据库写进程(DBWR/DBWn)</h2>
<ul>
<li>减少I/O量(LGWR)</li>
<li>减少I/O次数(DBWR/DBWn)</li>
<li>由参数 DB_WRITER_PROCESSES 决定写进程的个数,或者启动时说明写进程的个数。
<code>select name,type,value from v$parameter where name='db_writer_processes';</code>
<pre><code>SQL> show parameter DB_WRITER_PROCESSES
NAME TYPE VALUE
db_writer_processes integer 1</code></pre></li>
<li>数据库写进程负责将数据库高速缓冲区中的脏缓冲区中的数据写到数据文件中。</li>
<li>并不是数据库高速缓冲区中的数据一有变化就写,而是积累到足够多数据后一次写一大批量内存数据块到数据文件上。</li>
<li>以下事件之一发生时把数据库高速缓冲区中的数据写到数据文件上:
当脏缓冲区的数量超过所设定的限额。
当所设定的时间间隔已到。
当有进程需要数据库高速缓冲区却找不到空闲的缓冲区时。
当校验(检查)点发生时。
当某个表被删除(drop)或被截断(truncate)时。
当某个表空间被设置为只读状态(read only)时。
当使用类似于alter tablespace user begin backup 的命令对某个表空间进行联机备份时。
当某个表空间被设置为脱机状态(offline)或重新设置为正常状态(normal)时等。</li>
</ul>
<h2>1.21 系统监督进程(SMON)</h2>
<ul>
<li>突然断电类异常,提交的数据还没来得及真正被写到数据文件中就丢失,数据库重新开启时,SMON将自动地执行Oracle 实例恢复工作。步骤:
执行前滚(roll forward):将已经写到重做日志文件中但还没写数据文件中的数据写到数据文件中(根据SCN识别)。
打开数据库:数据文件可能还有部分没提交的数据,这样安排主要是提高系统的效率。
回滚没有提交的事务(数据)。除SMON进程外,服务器进程(server processes)也可以进行回滚没有提交的事务,只能回滚它加锁的行。</li>
<li>SMON还执行如下的磁盘空间维护工作:
回收或者合并数据文件中相连的空闲区
释放临时段(执行SQL时用作排序的磁盘区),将它们还给临时文件以作为空闲区使用。</li>
</ul>
<h2>1.22 进程监督进程(PMON)</h2>
<ul>
<li>当没有正常退出Oracle 的情况下重启了PC,由PMON负责如下事务:
回滚用户当前的事务。
释放用户所加的所有表一级和行一级的锁。
释放用户所有的其他资源等。</li>
</ul>
<h2>1.23 校验(检查)点和校验点进程(CKPT)</h2>
<ul>
<li>为提交效率和保证数据的一致性,引入了一个称为校验点的事件。在DBWR进程把SGA中所有已经改变了的数据库高速缓冲区中的数据写到数据文上时产生。</li>
<li>校验事件发生时,Oracle 要将校验码写到数据文件的文件头中。还将校验点号码、重做日志序列号、归档日志名称和最低和最高的SCN写入控制文件中。</li>
<li>校验点能加快实例的恢复速度,但是会影响性能,两者之中要衡量。</li>
</ul>
<h2>1.24 归档日志进程(ARCH/ARCn)</h2>
<ul>
<li>可选进程中最重要的一个,数据文件丢失或者损坏,如果要进行完全恢复,Oracle 数据库应运行在归档方式。</li>
<li>重做日志文件是分组的,循环写,有覆盖的情况。</li>
<li>归档日志可以看做是重做日志文件的备份,是脱机的。</li>
<li>查看后台进程:
<code>select pid,username,program from v$process where background = '1' order by program ;</code></li>
<li>RECO 后台进程是用于分布式数据库。</li>
</ul>
<h2>1.25 小结</h2>
<ul>
<li>什么时候数据库中的数据是一致的,什么时候是不一致的?</li>
<li>SGA和后台进程有关的问题点到OCP考试中的20%。</li>
</ul>
<h2>1.26 你应该掌握的内容</h2>