初识-Oracle的物理体系结构

143 阅读4分钟

在讲Oracle的物理体系结构之前,我们先来看一下Oracle的物理体系结构图,如下所示:

  • Oracle由实例Instance和数据库Database两部分组成,也就是上面的两个大方框;

  • 其中实例Instance是由共享内存区SGA(System Global Area)和一系列的后台进程组成。SGA被划分成共享池、数据缓存区和日志缓存区三部分,后台进程包括PMON、SMON、LCKn、RECO、CKPT、DBWR、LGWR和ARCH等进程;

  • 数据库Database是由数据文件、日志文件(归档日志文件)、参数文件和控制文件等组成,其中归档日志文件最终可能会被转移到新的存储介质,用于备份恢复使用;

  • 至于PGA(Program Global Area),它也是一块内存区,但是是私有的不是共享的,当用户发起查询或者更新等操作时,会先在PGA区进行预处理,然后进入实例由SGA和后台进程处理。PGA预处理包含如下三点:

    • 保存用户的连接信息,如会话属性、绑定变量等;

    • 保存用户的权限信息;

    • 如发起的指令需要排序,就会在PGA内存区进行排序,如果内存尺寸不够的话,超出部分在临时表空间排序;

    了解完这些之后,下面我们通过sql语句来分析其具体的执行流程,先来看一个查询语句:

drop table t purge;
//1、创建t表
create table t as select * from dba_objects;
//2、在object_id列上加索引
create index idx_object_id on t(object_id);
//3、set autotrace on:开启跟踪sql的执行计划和统计信息,
//set timing on:开启跟踪sql的执行时间
set autotrace on;
set linesize 1000;
set timing on;
//4、执行查询语句(先后执行两次)
select object_name from t where object_id=29;

第一次执行查询的输出信息:

第二次执行的输出信息:

通过观察两次的输出信息我们可以得知:

  • 第二次的执行时间相较于第一次的更短;

  • 第一次执行产生了52次递归调用,87次逻辑读和314次物理读。而第二次执行产生了0次递归调用,4次逻辑读和0次物理读;

    那么为什么两条一模一样的语句却产生了完全不同的结果,这一切都要归功于我们Oracle的物理体系了。

  • 首先,第一次执行时会在PGA内存区中保存用户的连接信息和权限信息等,这样第二次执行时就可以直接从PGA内存区中获取,避免物理读;

  • 在PGA中预处理之后,会给这条sql生成一个唯一的hash值,然后进入SGA内存区中,在这里会先用这个hash值去共享池中找是否已存在,如果没有的话,则需要对语句进行语法语义检查和解析执行计划等动作,完毕后将这些动作的“劳动成果”和唯一hash值绑定在一起并保存在共享池中,这样第二次执行就无需这些多余的动作了;

  • 经过共享池,接下来就是到数据缓存区中获取数据了,第一次执行数据缓存区中一般是没有需要的数据,需要从磁盘中获取并放到数据缓存区中,这样第二次执行就直接从数据缓存区中拿就行了,避免了物理读;

    查询语句讲完了,那更新语句(包含增加、删除和修改)的执行流程又是怎样的呢?比如下面这条更新语句:

update t set object_name = 'xxx' where object_id = 29;

    其实大体上更新和查询的流程是一样的,区别在于:磁盘中的数据拿过来放到数据缓冲区中后,对于查询而言,接下来就是将数据返回给前台的用户了,但是对于更新而言,Oracle还需要在数据缓冲区中完成对数据的修改。

    Oracle将数据修改完成后,不可能就这样放着它不管,肯定是需要将数据刷入到磁盘中,这样数据才能永久地保存下来。这个时候就需要启用我们的DBWR进程来完成这份工作了,它会将更新后的数据从内存刷入磁盘。

    OK,SGA中的共享池和数据缓存区都讲完了,还剩下一个日志缓存区,这个很好理解,就是为了将数据库相关的操作日志记录下来,因为数据库是保存数据的地方,一旦数据出现什么异常,那情况是非常严重的!日志缓存区会将操作日志记录下来,并借助LGWR这个进程将日志写入到日志文件当中,这样当出现异常时,可以借助这些日志文件进行恢复,保证数据的安全。不过日志文件也有写满的时候,这个时候Oracle会对第一个写入的文件进行覆盖重写,在此之前,Oracle会先启用ARCH进程将这个文件提前备份出去,被称为归档文件。