当优化器解析不是DDL的新SQL语句时,数据库将分配一个新的共享SQL区域。所需的内存量取决于语句的复杂性。
数据库可以从共享池中删除共享SQL区域,即使该区域对应于已长时间未使用的打开游标。如果以后使用打开的游标运行其语句,则数据库将重新解析该语句并分配一个新的共享SQL区域。数据库不会删除正在执行语句或行未完全获取的游标。
由于对相关架构对象或优化器统计信息的更改,共享的SQL区域可能变得无效。Oracle数据库使用两种技术来管理游标的生命周期:无效和滚动无效。
本节包含以下主题:
也可以看看:
Oracle Database Concepts概述了共享池中的内存分配
20.1.4.1游标标记为无效
如果将共享的SQL区域标记为无效,则数据库可以将其与有效的游标(已使用一段时间)一起从共享池中删除。
在某些情况下,数据库必须执行与共享池中的无效共享SQL区域关联的语句。在这种情况下,数据库将在执行之前对语句进行硬解析。
满足以下条件时,数据库立即将依赖的共享SQL区域标记为无效:
DBMS_STATS
当NO_INVALIDATE
参数为时,收集表,表集群或索引的统计信息FALSE
。- SQL语句引用一个架构对象,该对象随后会被使用立即光标失效(默认)的DDL语句修改。
您可以在
ALTER TABLE ... IMMEDIATE VALIDATION
和等语句上手动指定立即无效ALTER INDEX ... IMMEDIATE VALIDATION
,
或在会话或系统级别将CURSOR_INVALIDATION
初始化参数设置为IMMEDIATE
。注意:
使用该
DEFERRED VALIDATION
子句的DDL语句将覆盖初始化参数的IMMEDIATE
设置CURSOR_INVALIDATION
。
(注对SQL中的对象,单独授予grant 也会导至游标失效)
当满足上述条件时,数据库将在下次执行时重新解析受影响的语句。
当数据库使游标无效时,该V$SQL.INVALIDATIONS
值增加(例如,从0
到1
),并V$SQL.OBJECT_STATUS
显示INVALID_UNAUTH
。
示例20-10通过设置NO_INVALIDATE = FALSE强制光标无效
本示例以用户sh
身份登录,该用户已被授予管理员特权。该示例进行查询sales
,然后使用收集该表的统计信息NO_INVALIDATE=FALSE
。然后,将V$SQL.INVALIDATIONS
值从变化0
到1
用于光标,表明数据库标记光标为无效。
SQL> SELECT COUNT(*) FROM sales; COUNT(*) ---------- 918843 SQL> SELECT PREV_SQL_ID SQL_ID FROM V$SESSION WHERE SID = SYS_CONTEXT('userenv', 'SID'); SQL_ID ------------- 1y17j786c7jbh SQL> SELECT CHILD_NUMBER, EXECUTIONS, 2 PARSE_CALLS, INVALIDATIONS, OBJECT_STATUS 3 FROM V$SQL WHERE SQL_ID = '1y17j786c7jbh'; CHILD_NUMBER EXECUTIONS PARSE_CALLS INVALIDATIONS OBJECT_STATUS ------------ ---------- ----------- ------------- ------------- 0 1 1 0 VALID SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(null,'sales',no_invalidate => FALSE); PL/SQL procedure successfully completed. SQL> SELECT CHILD_NUMBER, EXECUTIONS, 2 PARSE_CALLS, INVALIDATIONS, OBJECT_STATUS 3 FROM V$SQL WHERE SQL_ID = '1y17j786c7jbh'; CHILD_NUMBER EXECUTIONS PARSE_CALLS INVALIDATIONS OBJECT_STATUS ------------ ---------- ----------- ------------- -------------- 0 1 1 1 INVALID_UNAUTH
复制
也可以看看:
- “ 关于优化器初始化参数 ”
- Oracle Database SQL语言参考,以了解更多信息
ALTER TABLE ... IMMEDIATE VALIDATION
以及其他允许立即验证的DDL语句 - Oracle数据库参考更多地了解
V$SQL
和V$SQLAREA
动态视图 - Oracle数据库参考,以了解有关
CURSOR_INVALIDATION
初始化参数的 更多信息
20.1.4.2游标标记为滚动无效
当游标被标记为滚动无效(V$SQL.IS_ROLLING_INVALID
is Y
)时,数据库将在较长的时间内逐渐执行硬解析。
注意:
当V$SQL.IS_ROLLING_REFRESH_INVALID
为时Y
,基础对象已更改,但是不需要重新编译游标。数据库更新游标中的元数据。
滚动无效的目的
由于硬解析的急剧增加会显着降低性能,因此滚动无效(也称为延迟无效)对于同时使许多游标无效的工作负载很有用。数据库为每个无效游标分配一个随机生成的时间段。同时失效的SQL区域通常具有不同的时间段。
仅当时间段到期后执行访问游标的查询时,才会进行硬解析。这样,数据库可以随时间分散硬解析的开销。
注意:
如果将并行SQL语句标记为滚动无效,则无论时间段是否到期,数据库都会在下一次执行时执行硬解析。在Oracle Real Application Clusters(Oracle RAC)环境中,此技术可确保并行执行服务器的执行计划与查询协调器之间的一致性。
滚动失效的一个比喻可能是逐渐更换破旧的办公家具。公司没有一次更换所有家具,而是要花费大量的财务费用,而是为每件家具分配了不同的有效期。在一年的时间里,一块一直保持使用状态直到被更换为止,这时会产生成本。
递延无效的规范
默认情况下,DDL指定访问对象的语句使用立即游标无效。例如,如果创建表或索引,则引用该表或索引的游标将使用立即无效。
如果DDL语句支持延迟的游标无效,则可以使用诸如的语句来覆盖默认行为ALTER TABLE ... DEFERRED INVALIDATION
。选项取决于DDL语句。例如,ALTER INDEX
仅DEFERRED INVALIDATION
当还指定UNUSABLE
或REBUILD
选项时才支持。
DDL的替代方法是在会话或系统级别将CURSOR_INVALIDATION
初始化参数设置为DEFERRED
。使用该IMMEDIATE INVALIDATION
子句的DDL语句将覆盖初始化参数的DEFERRED
设置CURSOR_INVALIDATION
。
发生滚动无效时
如果DEFERRED INVALIDATION
由于DDL或初始化参数设置而将属性应用于对象,则访问该对象的语句可能会遭受延迟的失效。在下列情况之一中,数据库将共享的SQL区域标记为滚动无效:
DBMS_STATS
NO_INVALIDATE
参数设置为时,将收集表,表集群或索引的统计信息DBMS_STATS.AUTO_INVALIDATE
。这是默认设置。DEFERRED INVALIDATION
在不阻止使用延期无效的情况下,发出以下声明之一:ALTER TABLE
在分区表上ALTER TABLE ... PARALLEL
ALTER INDEX ... UNUSABLE
ALTER INDEX ... REBUILD
CREATE INDEX
DROP INDEX
TRUNCATE TABLE
在分区表上
DDL语句的一个子集,需要立即游标无效的DML(
INSERT
,UPDATE
,DELETE
或MERGE
),但不能SELECT
发言。与特定DDL语句和受影响的游标有关的许多因素决定了Oracle数据库是否使用延迟失效。
也可以看看:
- “ 关于优化器初始化参数 ”
- Oracle数据库SQL语言参考,以了解有关
ALTER TABLE ... DEFERRED INVALIDATION
允许延迟失效的其他信息以及其他DDL语句 - Oracle数据库参考更多地了解
V$SQL
和V$SQLAREA
动态视图 - Oracle数据库参考,以了解有关
CURSOR_INVALIDATION
初始化参数的 更多信息