关注点:
1.Session Cursor与Session是一一对应的,不同Session的Session Cursor之间没法共享,这与Shared Cursor有本质区别。
2.Session Cursor是有生命周期的,每个Session Cursor在使用的过程中都至少会经历一次Open、Parse、Bind、Execute、Fetch和Close中的一个或多个阶段,用过的Session Cursor不一定会缓存在对应的Session的PGA中,取决于参数SESSION_CACHED_CURSORS的值是否大于0。
3.既然Session Cursor是以哈希表的方式缓存在PGA中,意味着Oracle会通过相关的哈希运算来存储和访问在当前Session的PGA中的对应Session Cursor。这种访问机制实际上和Shared Cursor是一样的,即可以简单地认为Oracle是根据目标SQL的SQL文本的哈希值去PGA中的相应Hash Bucket中找匹配的Session Cursor。
Oracle在解析和执行目标SQL时,会先去当前的Session的PGA中找是否存在匹配的缓存Session Cursor。当Oracle第一次解析和执行目标SQL时(硬解析),当前Session的PGA中肯定不存在匹配Session Cursor,这时Oracle会新生成一个Session Cursor和一对Shared Cursor(即Parent Cursor和Child Cursor),这其中的Shared Cursor会存储,能被所有Session共享、重用(比如标上SQL的解析树、执行计划等),而Session Cursor则会经历一次Open、Parse、Bind、Execute、Fetch和Close中的一个或多个阶段。
对于Oracle 11g之前的版本,在缓存Session Cursor的哈希表的对应Hash Bucket中,Oracle会存储目标SQL对应的Parent Cursor的库缓存对象句柄地址,这意味着Oracle已经建立了目标SQL的Session Cursor与其Parent Cursor之间的联系,即Oracle可以通过Session Cursor找到对应的Parent Current,进而就可以找到对应Child Cursor中目标SQL的解析树和执行计划,然后Oracle就可以按照这个解析树和执行计划来执行目标SQL了。
查看Session Cursor Dump的方法:
当前会话:
alter session set events ‘immediate trace name ERRORSTACK level 3’
alter session set events ‘immediate trace name ERRORSTACK off’
指定会话:
oradebug setospid xxx;
oradebug event immediate trace name ERRORSTACK level 3;
oradebug event immediate trace name ERRORSTACK off;
oradebug tracefile_name;
一个Session Cursor只能对应一个Shared Cursor,而一个Shared Cursor却可以同时对应多个Session Cursor。
当目标SQL以硬解析的方式解析和执行完毕后,这个目标SQL所对应的Shared Cursor就已经缓存在库缓存中,它所对应的Session Cursor也使用完毕,这时会出现两种情况:
1.参数session_cached_cursors=0,Session Cursor会正常执行Close操作。这样,当SQL重复执行时(软解析),此时可以找到匹配的Shared Cursor,但找不到匹配的Session Cursor(因为之前硬解析时对应的Session Cursor已经被Close了),这意味着Oracle必须为该SQL新生成一个Session Cursor,并且该Session Cursor还会再经历一次Open、Parse、Bind、Execute、Fetch和Close中的一个或多个阶段。
2.参数session_cached_cursor>0,不会对Session Cursor执行Close操作,而是将其标记为Soft Closed,同时将其缓存在当前Session的PGA中。这样做的好处是当目标SQL被重复执行时,此时Shared Cursor和Session Cursor就能找到匹配记录了,意味着Oracle已经不需要为该SQL再新生成一个Session Cursor,而是只需要从当前Session 的PGA中将之前已经被标记为Soft Closed的匹配Session Cursor直接拿过来用就可以了。
显然,和软解析相比,此时Oracle就省掉了Open一个新的Session Cursor所需要耗费的资源和时间。另外,Close一个现有的Session Cursor也不需要做了(只需要将其标记为Soft Closed,同时将其缓存在当前Session的PGA中就可以了).
当然,剩下的Parse、Bind、Execute、Fetch还是需要做的,这个过程就是所谓的“软软解析”。
总结:
无论是硬解析、软解析、软软解析,Oracle在解析和执行目标SQL时,始终会先去当前session的PGA中寻找是否存在匹配的缓存Session Cursor。
如果在当前Session的PGA中找不到匹配的缓存Session Cursor,Oracle就会去库缓存中找是否存在匹配的Parent Cursor。如果找不到,Oracle就会新生成个Session Cursor和一对Shared Cursor;如果找到了匹配的Parent Cursor,但找不到匹配的Child Cursor,Oracle就会新生成一个Session Cursor和一个Child Cursor(这个Child Cursor会被挂到之前找到的匹配Parent Cursor下)。无论哪一种情况,这两个过程对应的都是硬解析。




