游标是指向私有SQL区(private SQL area)及其关联的共享SQL区(shared SQL area)的句柄 (handle,一种允许程序访问某一资源的内存结构)。如图2-1所示,尽管句柄是客户端内存结构,但它指向了服务器进程的内存结构,转而指向存储在SGA中的内存结构,更确切地说是库缓存中的内存。
游标是指向私有SQL 区及其关联的共享SQL 区的句柄
私有SQL区存储诸如绑定变量值和查询执行状态信息等数据。从命名上就可以看出,私有SQL区属于具体的会话。用于存储私有SQL区的会话内存称作用户全局区(UGA)。
共享SQL区包含两个独立的结构,即所谓的父游标(parent cursor)和子游标(child cursor)。存储在父游标中的关键信息是与游标关联的SQL语句文本,简单来说就是进程将要执行的SQL语句。存储在子游标中的关键元素是执行环境和执行计划。这些元素指明了执行过程如何进行。一个共享SQL区可以用于多个会话,因此它存储在库缓存中。
注意在实践中,游标和私有/共享SQL区这两个术语可互换使用。
游标的生命周期
下面是处理游标过程中执行的步骤。
(1)打开游标:在会话的UGA中会分配一个用于打开游标的私有SQL区。同时还会分配一个引用私有SQL区的客户端句柄。注意此时还没有任何SQL语句与该游标相关联。
(2)解析游标:共享SQL区包含与该SQL语句解析后相关的表示形式及其执行计划(用来描述SQL引擎如何执行SQL语句),这些都是在SGA中生成和加载的,确切地说是在库缓存中。私有SQL区会进行更新,以存储一个对共享SQL区的引用。
(3)定义输出变量:如果SQL语句返回数据,则必须定义接收数据的变量。这不仅对查询是必要的,同样适用于使用了RETURNING条件的删除、插入和更新语句。
(4)绑定输入变量:如果SQL语句使用了绑定变量,则必须为绑定变量提供值。在绑定过程中不执行检查。如果传入了非法数据,在执行的时候会抛出一个运行时错误。
(5)执行游标:会在此阶段执行SQL语句。但是请注意,数据库引擎在这个阶段并不总是做些重要的事情。实际上,对于许多类型的查询,真正的处理过程都会推迟到获取阶段再做。
(6)获取游标:如果SQL语句有结果,就在这一步取回结果。尤其对查询而言,这一阶段会执行大部分的处理过程。查询的时候可能只取回结果集的一部分,换句话说,游标可能在获取全部数据之前就关闭了。
(7)关闭游标:与句柄和私有SQL区有关的资源被释放并可以供其他游标使用。库缓存中的共享SQL区则没有变化。它留在内存中希望以后可以被重用。
在实践中,会使用不同的优化技巧来加速处理过程。例如,绑定变量扫视需要将执行计划的生成推迟到绑定变量的值变成已知的时候。
解析执行的步骤如下。
(1)包含VPD谓词:如果使用了虚拟私有数据库(VPD,以前也称作行级别安全控制),并且解析的SQL语句其中的一张表激活了这个选项,那么由安全策略生成的谓词就会包含在WHERE条件中。
(2)检查语法、语义和访问权限:这一步不仅保证SQL语句是书写正确的,同时确保SQL语句引用的所有对象都存在,而且解析它的用户有相应的权限来访问这些对象。
(3)在共享SQL区存储父游标:只要可共享的父游标尚不可访问,库缓存中就会分配一些内存,新产生的父游标就存储在这里。
(4)生成执行计划:在这一阶段,查询优化器为解析的SQL语句产生执行计划.
(5)在共享SQL区存储子游标:此时会分配一些内存,可共享的子游标就存储在其中并与它的父游标进行关联。