In the previous post I wrote about strangely behaving V$SQL. For some reason there were duplicate rows leading to wrong results issue when running DBMS_XPLAN.DISPLAY_CURSOR for a particular child cursor. I tried to reproduce the issue using simple test case – and it was reproduced.
Here it is. I’m starting to execute a simple query against DUAL while constantly changing optimizer environment, forcing Oracle to build a new child cursor for each execution:
alter session set workarea_size_policy=manual; col curr_date new_value curr_date select to_char(sysdate, 'HH24MISS') curr_date from dual; set define on verify off begin for i in 1..100 loop execute immediate 'alter session set sort_area_size=' || to_char(100000 + i*1024); execute immediate 'select /* &&curr_date */ count(*) from dual'; end loop; end; / col sql_id new_value sql_id select sql_id, address from v$sqlarea where sql_text = 'select /* &&curr_date */ count(*) from dual'; clear columns select count(*) from v$sql_shared_cursor where sql_id = '&&sql_id'; @unshared &&sql_id
As expected, I’ve got 100 child cursors and 99 of them were created due to OPTIMIZER_MISMATCH:
SQL> select sql_id, address from v$sqlarea where sql_text = 'select /* &&curr_date */ count(*) from dual'; SQL_ID ADDRESS ------------- ---------------- 8ugq0vhq0z7pb 000007FF5D45C0B0 SQL> clear columns columns cleared SQL> select count(*) from v$sql_shared_cursor where sql_id = '&&sql_id'; COUNT(*) -------------------- 100 SQL> @unshared &&sql_id SQL_ID NONSHARED_REASON COUNT(*) ------------- ----------------------------- -------------------- 8ugq0vhq0z7pb OPTIMIZER_MISMATCH 99
Now let’s continue and see what will happen:
begin for i in 101..250 loop execute immediate 'alter session set sort_area_size=' || to_char(100000 + i*1024); execute immediate 'select /* &&curr_date */ count(*) from dual'; end loop; end; / select count(*) from v$sql_shared_cursor where sql_id = '&&sql_id'; select sum(cnt), avg(cnt), min(child_number), max(child_number) from (select child_number, count(*) cnt from v$sql where sql_id = '&&sql_id' group by child_number); select address, count(*) from v$sql where sql_id='&&sql_id' group by address; select sql_id, address from v$sqlarea where sql_text = 'select /* &&curr_date */ count(*) from dual'; @unshared &&sql_id select * from table(dbms_xplan.display_cursor('&&sql_id', 1));
SQL> select count(*) from v$sql_shared_cursor where sql_id = '&&sql_id'; COUNT(*) -------------------- 250 SQL> SQL> select sum(cnt), avg(cnt), min(child_number), max(child_number) 2 from (select child_number, count(*) cnt 3 from v$sql 4 where sql_id = '&&sql_id' 5 group by child_number); SUM(CNT) AVG(CNT) MIN(CHILD_NUMBER) MAX(CHILD_NUMBER) -------------------- -------------------- -------------------- -------------------- 250 2.5 0 99 SQL> SQL> select address, count(*) from v$sql where sql_id='&&sql_id' group by address; ADDRESS COUNT(*) ---------------- -------------------- 000007FF5D1E18A8 50 000007FF5D45C0B0 100 000007FF5D5BA268 100 SQL> select sql_id, address from v$sqlarea where sql_text = 'select /* &&curr_date */ count(*) from dual'; SQL_ID ADDRESS ------------- ---------------- 8ugq0vhq0z7pb 000007FF5D1E18A8 SQL> @unshared &&sql_id SQL_ID NONSHARED_REASON COUNT(*) ------------- ----------------------------- -------------------- 8ugq0vhq0z7pb OPTIMIZER_MISMATCH 249 SQL> select * from table(dbms_xplan.display_cursor('&&sql_id', 1)); PLAN_TABLE_OUTPUT ----------------------------------------------------------------------------------------------------------------------- SQL_ID 8ugq0vhq0z7pb, child number 1 ------------------------------------- An uncaught error happened in prepare_sql_statement : ORA-01422: exact fetch returns more than requested number of rows Plan hash value: 3910148636 ----------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ----------------------------------------------------------------- | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | ----------------------------------------------------------------- SQL_ID 8ugq0vhq0z7pb, child number 1 ------------------------------------- An uncaught error happened in prepare_sql_statement : ORA-01422: exact fetch returns more than requested number of rows Plan hash value: 3910148636 ----------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ----------------------------------------------------------------- | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | ----------------------------------------------------------------- SQL_ID 8ugq0vhq0z7pb, child number 1 ------------------------------------- An uncaught error happened in prepare_sql_statement : ORA-01422: exact fetch returns more than requested number of rows Plan hash value: 3910148636 ----------------------------------------------------------------- | Id | Operation | Name | Rows | Cost (%CPU)| Time | ----------------------------------------------------------------- | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 0 | SELECT STATEMENT | | | 2 (100)| | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 1 | SORT AGGREGATE | | 1 | | | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | | 2 | FAST DUAL | | 1 | 2 (0)| 00:00:01 | ----------------------------------------------------------------- 114 rows selected.
Bingo. After the point of 100 child cursors per parent, Oracle builds a new parent (V$SQL.ADDRESS holds its address) cursor, marking old parent and child cursors as obsolete. V$SQLAREA handles the situation well, but V$SQL doesn’t and that’s clearly a bug. The threshold point of when to build a new parent cursor is 100 by default and is controlled with a new hidden parameter _cursor_obsolete_threshold. I’ve tested setting this parameter to 150 and it worked as expected. Note that this bug-fix-improvement-again-bugs 10187168 claimed to be included into Patch Set Update 11.2.0.2.2 (and higher). I’ve tested 11.2.0.2.3 & 11.2.0.2.5 and it seems the improvement is not enabled by default and they act the old, pre-11.2.0.3 way; most likely the bug-fix have to be enabled explicitly with event 106001 in the 11.2.0.2 PSUs. I haven’t tested it though.
PS. If you have time and desire, please file a bug to Oracle.
Filed under: Oracle Tagged: 11.2.0.3, bug, dynamic views, shared cursors Image may be NSFW.
Clik here to view.
Clik here to view.
