天天看点

《Oracle数据库管理与维护实战》—— 2.10 SQL语句的处理过程

本节书摘来自异步社区出版社《oracle数据库管理与维护实战》一书中的第2章,第2.10节,作者: 何伟娜 , 常建功,更多章节内容可以访问云栖社区“异步社区”公众号查看。

oracle数据库管理与维护实战

oracle数据库是关系数据库,oracle用sql语言对数据库进行操作。了解sql语句的处理过程,能更深一步地了解oracle的内部运行机制。

oracle中,所有的sql语句都分三个阶段进行处理:语法分析、执行、返回结果。无论何种工具(如:oracle form 、oracle reports),都要将语句传递到oracle进行处理。下面我们简单分析这三个阶段。

分析是处理sql语句的第一步,sql语句从用户进程送到服务器进程,服务器进程开始进行以下工作。

(1)语法分析。oracle采用自底向上的分析方法,检查语句是否符合语法规范,命名是否符合命名规范。语法分析是处理sql语句过程中最费时间且代价最高的。

例如前面提到的如下sql语句。

sql>select ename,sal from emp;

服务器进程会将其中的关键字select、from,表名emp,列名ename、sal分析出来等待语义分析。

(2)语义分析。语法分析通过,说明sql语句格式正确,但还不知道语句中的对象在数据中是否存在,当前用户是否有权限读写。语义分析的功能就是验证这些。它根据语法分析出来的各数据库对象,分别从数据字典中取出其定义和权限。

如前面例中的表名emp,先从数据字典中看是否有该表,如果有,就从数据字典中取出表emp的定义,查看当前用户是否有权限读,否则提示出错。

(3)视图转换,将涉及视图的查询语句转换为相应的对基表查询语句。

(4)表达式转换,将复杂的sql表达式转换为较简单的等效连接表达式。

(5)选择优化器。不同的优化器一般产生不同的“执行计划”。

(6)选择连接方式。oracle有三种连接方式,对多表连接,oracle可选择适当的连接方式。

(7)选择连接顺序。对多表连接,确定oracle选择哪一对表先连接,选择这两表中哪个表作为源数据表。

(8)选择数据的搜索路径。oracle根据以上条件选择合适的数据搜索路径,例如是选用全表搜索还是利用索引或是其他的方式。

(9)到sga中为该sql语句找到一个共享sql区。

如果在共享sql区中已有该sql语句的共享sql区,则oracle直接执行共享sql区内容,而不进行以上分析。

执行阶段执行已分析过的语句。如果sql语句会改变数据库,如update、delete语句,oracle先要将修改的行锁住,以防其他用户修改;如果sql语句不会改变数据库,则执行下一步的数据读。

oracle会先从数据库缓冲区中寻找是否有所要的数据块,如果有,就直接读或修改;否则从物理文件中读到数据库缓冲区。

对于select语句等需要返回结果的语句,还有返回结果阶段,将执行结果,如select后的所有数据行,返回给用户进程。如果查询需要排序,则oracle将排序的结果返回给用户。查询结果总是以表格形式出现,根据使用的内存大小不同,oracle可以一次取出一行数据,也可以一次取出一组。

在dml类型的sql语句中,select语句是数据库中最常使用的命令,图2-32列出了处理查询语句的具体步骤。

(1)创建游标(cursor)。游标可以是显式的,也可以是隐式的。

(2)分析语句。

(3)定义输出,指定位置、类型和结果集的数据类型,转换数据类型。

(4)捆绑变量,如果查询语句中有变量值,需取到变量的值。

(5)判断是否能并行查询。

(6)执行查询。

(7)以行方式取出数据。

(8)关闭游标。

《Oracle数据库管理与维护实战》—— 2.10 SQL语句的处理过程

select以外的其他语句和select执行过程稍有不同,其他语句不需返回结果,如图2-33所示。

(1)创建游标(cursor),使用隐式游标。

(3)捆绑变量,如果查询语句中有变量值,需取到变量的值。

(4)看是否能并行查询。

(5)执行语句。

(6)通知用户执行完成。

(7)关闭游标。

《Oracle数据库管理与维护实战》—— 2.10 SQL语句的处理过程

在介绍commit和rollback的处理之前,我们先讨论一个与数据库恢复有关的重要机制:系统改变号scn(system change number)。

scn是数据库中非常重要的一个数据结构。它定义数据库在某个确切时刻提交的版本。每当事物被提交时,它被赋予一个唯一标识事务的scn。scn提供oracle的内部时钟机制,可被看作逻辑时钟。这对于恢复操作是至关重要的,oracle只根据scn执行恢复。scn用来同步数据库,并且提供数据读的一致性。执行查询语句时,oracle在执行阶段就确定了当前scn,只有scn号小于或等于当前的scn号,数据块才能读取。对于较高的scn号,oracle就从回滚段中读取。

scn记录在控制文件、数据文件头部、块的头部以及重做日志文件中。对同一个事务,重做日志文件存了低的scn号和高的scn号。

每个事务提交时都会增加数据库系统的scn号。但查询开始时,oracle执行下述操作,为查询返回集产生一个读一致性数据集。

(1)系统查询时,oracle查看系统当前的scn,这里称为查询scn。

(2)在oracle查询时,它必须读数据块以建立查询返回集。对于要读的每一个数据块,oracle将查询scn与数据块头的scn相比较,然后做如下处理。如果数据块的scn等于或先于查询scn,oracle可以使用块中的数据创建查询结果集;如果数据块中的scn大于查询scn,oracle从系统回滚段读信息,即重新生成一个数据块。

图2-34展示了一个多版本返回与查询scn一致性的示意图。

《Oracle数据库管理与维护实战》—— 2.10 SQL语句的处理过程

数据库中涉及到事务时,经常会遇到提交(commit)操作。当用户发出提交命令commit后,处理commit的步骤如下。

(1)服务器进程先生成一个scn号,赋给回滚段(可参考2.6.4节看回滚段定义),在回滚段中作标志表示事务已提交。服务器进程将提交的记录和scn号存到重做日志缓冲区中,同时将数据库缓冲区作标志。

(2)lgwr进程将重做日志缓冲区中包含提交记录及scn号写到联机重做日志文件中。

(3)服务器进程解开对表和行的锁定。

(4)通知用户commit已经完成。

(5)服务器进程将事务标记为完成。

commit进行时,dbwr并不立刻写磁盘,oracle会延迟向数据文件中写已修改的数据。这就是所谓的“快速提交机制”。快速提交的优点有以下几个。

lgwr往日志文件上写是顺序写,比dbwr向数据文件中不同块写要快。

lgwr往日志文件上写的内容要比向数据文件上写的内容少。日志文件只需存变动的内容,而数据文件上要存整个数据块内容。

如果多个事务发数据库提交命令,lgwr会将这些提交信息一起往日志文件上写。

一般一个事务最多有一次写日志文件,除非重做日志文件写满。

事务的大小不会影响commit操作的时间。

如果事务没有提交,就可以回滚,也就是可以恢复到原先的状态。发生以下情况oracle会进行回滚。

用户发出rollback命令。

服务器异常结束。

dba停止会话。

以下是处理rollback的步骤。

(1)通过回滚段,恢复在事务中所做的所有修改。

(2)服务器进程释放所有的对表和行的锁定。

(3)服务器将事务标记为完成。