In this 7th episode of the series of articles about why my execution plan has not been shared, I will deep dive into the AUTO_CHECK_MISMATCH. Before I start, I wanted, first, to remind you that I actually already explained this reason in part 5 of the same series. I have, in fact, demonstrated in that part, that the implementation of a RLS (Row Level Security) was the ingredient of this reason. But what I missed at that time was that this reason was accompanied by a piece of information that is not at all innocent and that I overlooked:
<ChildNode>
<ChildNumber>0</ChildNumber>
<ID>37</ID>
<reason>Authorization Check failed(9)</reason>
<size>0x0</size>
<details>row_level_access_control_mismatch</details>
</ChildNode>
The number (9) that appears in
<reason>Authorization Check failed(9)</reason>
is not trivial. Indeed, 9 refer to a Row Level Security rule that is causing a new execution plan optimisation.
So, in the same vein as for the different values of Optimizermismatch() that goes hand in hand with the OPTIMIZER_MODE_MISMATCH explained in part 4
• Optimizermismatch(1)
• Optimizermismatch(2)
• Optimizermismatch(3)
• Optimizermismatch(4) → points to a px_mismatch for serial plan (not clear)
• Optimizermismatch(5)
• Optimizermismatch(6)
• Optimizermismatch(7)
• Optimizermismatch(8)
• Optimizermismatch(9)
• Optimizermismatch(10) → optimizer mode (first_rows, all_rows) mismatch
• Optimizermismatch(11)
• Optimizermismatch(12) → optimizer parameter mismatch
• Optimizermismatch(13) → cardinality feedback
It looks like Oracle has also used the same philosophy to differentiate the root-causes for AUTO_CHECK_MISMATCH using the Authorization Check failed() tag:
• Authorization Check failed(1)
• Authorization Check failed(2)
• Authorization Check failed(3)
• Authorization Check failed(4) → we are going to see in this blog post
• Authorization Check failed(5)
• Authorization Check failed(6)
• Authorization Check failed(7)
• Authorization Check failed(8)
• Authorization Check failed(9) → VPD and Row Level Security
Let’s start by trying to explain what we should think about when we see this double information
- AUTO CHECK MISMTACH
- Authorization Check failed(4)
To simulate this situation, I will simply execute a query in two different schemas. I will start with the c##mhouri schema followed by the c##test schema. This will lead us to see that the optimized execution plan in the first schema cannot be shared in the second. The reason for this hard parse is, as you may have guessed, Authorization Check failed(4)
SQL> show user
USER is "C##MHOURI"
SQL> create table t1 as select rownum n1 from dual connect by level <=10;
Table created.
SQL> select count(1) from t1;
COUNT(1)
----------
10
SQL> @xpsimp
SQL_ID a2d8wpfzju8fr, child number 0
-------------------------------------
select count(1) from t1
Plan hash value: 3724264953
-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | 3 (100)| |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T1 | 10 | 3 (0)| 00:00:01 |
-------------------------------------------------------------------
SQL> show user
USER is "C##TEST"
SQL> create table t1 as select rownum n1 from dual connect by level <=10;
Table created.
SQL> select count(1) from t1;
COUNT(1)
----------
10
SQL> @xpsimp
SQL_ID a2d8wpfzju8fr, child number 1
-------------------------------------
select count(1) from t1
Plan hash value: 3724264953
-------------------------------------------------------------------
| Id | Operation | Name | Rows | Cost (%CPU)| Time |
-------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | 3 (100)| |
| 1 | SORT AGGREGATE | | 1 | | |
| 2 | TABLE ACCESS FULL| T1 | 10 | 3 (0)| 00:00:01 |
-------------------------------------------------------------------
14 rows selected.
SQL> @nonshared a2d8wpfzju8fr
Show why existing SQL child cursors were not reused (V$SQL_SHARED_CURSOR)...
SQL_ID : a2d8wpfzju8fr
ADDRESS : 0000000064C9EED0
CHILD_ADDRESS : 0000000064BC2640
CHILD_NUMBER : 0
REASON : <ChildNode><ChildNumber>0</ChildNumber><ID>36</ID>
<reason>Authorization Check failed(4)</reason> ---> here
<size>5x4</size<translation_table_position>0
</translation_table_position><original_handle>
2141856400</original_handle><temp_handle>
2147116632</temp_handle><schema>107</schema>
<synonym_object_number>0</synonym_object_number>
</ChildNode>
CON_ID : 1
-----------------
SQL_ID : a2d8wpfzju8fr
ADDRESS : 0000000064C9EED0
CHILD_ADDRESS : 00000000696A23A0
CHILD_NUMBER : 1
AUTH_CHECK_MISMATCH : Y
TRANSLATION_MISMATCH : Y
REASON :
CON_ID : 1
-----------------
PL/SQL procedure successfully completed.
As a conclusion, I can say that for the moment I managed to decipher two reasons among at least 9 that can generate a hard parse identified by AUTO_CHECK_MISMATCH
• Authorization Check failed(4) → query using same objects but for different user schemas
• Authorization Check failed(9) → VPD and Row Level Security
I hope to be able to explain the other 7 Authorization Check failed() that remain
Salut Mohammed,
ce post est tres interessant et instructif.
Mon approche aurait ete :
« when my not-shared execution plan is a problem »
Peut-etre dans un prochain post 🙂
Merci pour le partage.
Comment by mlaiti — August 2, 2021 @ 5:06 pm |
Hello Majda,
Pour réponder à ta question ” When my not-shared execution plan is a problem” je dirai que, très souvent, on cherche à avoir un plan d’execution stable avec un temps d’exécution stable et une consommation I/O constante. Autant que faire se peut, on préfère donc s’en tenir à ce plan plutôt que d’avoir des surprises désagréables lorsqu’Oracle change de plan. Et lorsqu’une requête switch d’un “bon” plan à un “mauvais” plan, on cherche toujours à comprendre la raison de ce “swicth”. CQFD tous ses articles.
Ceci dit, parfois on ne voudrait pas que le plan soit partagé. Et on essaie de forcer une optimisation à chaque execution comme dans le cas PoepleSoft expliqué dans cet article : https://hourim.wordpress.com/2019/07/30/global-temporary-table-private-statistics/
Bien Cordialement
Comment by hourim — August 3, 2021 @ 7:54 am |
Hello Mohamed Houri,
Thank you for sharing this post. We pretty much see stuff from our application. High version count and the reason are :
1) Optimizer mismatch(12)
2) Authorization Check failed(4)
03Optimizer mismatch(12)2×476 -575108365 0 036Authorization Check failed(4)5x40370409768529430904111003Optimizer mismatch(12)2×476 -575108365 0 036Authorization Check failed(4)5×405349806324625937441400
The database has more than 100 schemas with same table and column names across each schema. The queries run from users are textually same and have same hash values and sql_ids.
The other thing i noticed the shared pool is getting bigger and bigger (sql area) and stealing memory from buffer cache, that i belive is due to this high version count.
I am curious if this can be fixed from database or its just application design that create so high version count or just expected behaviour?.
Regards
Ahmed
Comment by Ahmed — February 22, 2022 @ 1:46 pm |
Ahmed,
From the database point of view, you can limit the damage by changing the value of the hidden parameter _cursor_obsolete_threshold. Set it to 1024 for example (if you are in 19c)
Best regards
Mohamed
Comment by hourim — February 22, 2022 @ 3:42 pm |
Thank you for the reply..
Yeh this has been changed to value 1024 a month ago.
Comment by Ahmed — February 22, 2022 @ 3:52 pm |
Hi Mohamed,
I couldn’t find the explanation for number 7 which is reported in error of Authorization Check failed(7)
Also if you could give short summarize of all the Authorization Check failed reasons specific with numbers ?
Comment by Bala — February 8, 2024 @ 4:42 pm |