游标是cursor的中文翻译,那么到底什么是cursor呢?Oracle Concept中是这样描述的:
When an application issues a SQL statement, the application makes a parse call to the
database to prepare the statement for execution. The parse call opens or creates acursor, which is a handle for the session-specific private SQL area that holds a parsed
SQL statement and other processing information. The cursor and private SQL area are
in the PGA.
如果上述很多的专业术语把你搞晕了,那你可以简单的理解成,一个sql语句就会对应到一个游标。
游标分类:
a2dk8bdn0ujx7 select * from emp 1 1 2 SCOTT
只有文本完全相同,才能共享父游标。哪怕是语句的语义、环境等有完全相同,sql文本稍微不同都不行。例如如下sql
select * from emp;
select * from emp;
select * from Emp;
那么当父游标相同,有多个子游标时,我们如何知道是何原因导致不共享子游标呢?
SELECT *
FROM v$sql_shared_cursor
WHERE sql_id = 'a2dk8bdn0ujx7'
这个表中会有什么*MISMATCH的字段,如果该值为Y,就表示是因为这个字段指示的内容不一致导致不能共享子游标。
游标的生命周期:
(1)打开游标(dbms_sql.open_cursor)
Open cursor: A memory structure for the cursor is allocated in the server-side private memory of the server process associated with the session, the user global area (UGA). Note that no SQL statement isassociated with the cursor yet.
系统会在UGA中分配相关的内存结构,就是获得游标句柄的过程,这时的游标还未和sql语句有关联;
(2)解析游标(dbms_sql.parse)
Parse cursor: A SQL statement is associated with the cursor. Its parsed representation that includes the execution plan (which describes how the SQL engine will execute the SQL statement) is loaded in the shared pool, specifically, in the library cache. The structure in the UGA is updated to store a pointer to the location of the shareable cursor in the library cache. The next section will describe parsing in more detail.
有一条sql与游标相关联,并将执行解析过后的执行计划放在library cache(SGA的shared pool下)中,UGA中生成指向这个共享游标的指针;即session cursor 指向shared cursor。 一个session cursor 只能指向一个shared cursor,而一个shared cursor 可以指向多个session cursor。
(3)定义输出变量(dbms_sql.define_column)
Define output variables: If the SQL statement returns data, the variables receiving it must be defined. This is necessary not only for queries but also for DELETE, INSERT, and UPDATE statements that use the RETURNING clause.
如果sql语句返回数据,必须定义接收数据的变量,对delete,update,insert来说是returning;
(4)绑定输入变量(dbms_sql.bind_variable/bind_array)
Bind input variables: If the SQL statement uses bind variables, their values must be provided. No check is performed during the binding. If invalid data is passed, a runtime error will be raised during the execution.
绑定过程是不做检查的;
(5)执行游标(dbms_sql.execute)
Execute cursor: The SQL statement is executed. But becareful, because the database engine doesn’t always do anything significant during this phase. In fact, for many types of queries, the real processing isusually delayed to the fetch phase.
这步数据库引擎其实不做什么重要事情,而对大多数sql语句来说,真正处理过程是到fetch获取数据阶段;
(6)获取游标(dbms_sql.fetch_rows)
Fetch cursor: If the SQL statement returns data, this step retrieves it. Especially for queries, this step is where most of theprocessing is performed. In the case of queries, rows might be partiallyfetched. In other words, the cursor might be closed before fetching all therows.
真正的处理过程,有返回数据的话,必须提供输出变量(dbms_sql.column_value);
(7)关闭游标(dbms_sql.close_cursor)
Close cursor: The resources associated with the cursorin the UGA are freed and consequently made available for other cursors. The shareable cursor in the library cache is not removed. It remains there in the hope of being reused in the future.
释放UGA中相关资源,库缓存中共享游标不会被清除。
当游标被关闭后,还可以继续缓存在内存中,参数SESSION_CACHED_CURSORS定义当前Session已经关闭并被缓存的游标的最大数量,即单个session中同时能cache住的soft closed session cursor的最大数量。