Ajouter astuce avec autotrace
-
29-09-2020 - |
Question
Je suis en train de faire un chemin d'insertion qui s'exécute avec succès.Lorsque j'essaie de traçage de l'exécution, j'ai l' ORA-12838: cannot read/modify an object after modifying it in parallel
.
SQL> insert into emp_big select * from emp_big_temp;
411843 rows created.
Elapsed: 00:00:00.89
Execution Plan
----------------------------------------------------------
Plan hash value: 3203427748
-----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | INSERT STATEMENT | | 357K| 45M| 1164 (1)| 00:00:14 |
| 1 | LOAD TABLE CONVENTIONAL | EMP_BIG | | | | |
| 2 | TABLE ACCESS FULL | EMP_BIG_TEMP | 357K| 45M| 1164 (1)| 00:00:14 |
-----------------------------------------------------------------------------------------
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
15 recursive calls
31909 db block gets
12829 consistent gets
0 physical reads
34685216 redo size
845 bytes sent via SQL*Net to client
802 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
411843 rows processed
SQL> rollback;
Rollback complete.
Elapsed: 00:00:00.18
SQL>
SQL> insert /*+ append */ into emp_big select * from emp_big_temp;
411843 rows created.
Elapsed: 00:00:00.18
Execution Plan
----------------------------------------------------------
ERROR:
ORA-12838: cannot read/modify an object after modifying it in parallel
SP2-0612: Error generating AUTOTRACE EXPLAIN report
Statistics
----------------------------------------------------------
0 recursive calls
4438 db block gets
4283 consistent gets
0 physical reads
7648 redo size
829 bytes sent via SQL*Net to client
816 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
411843 rows processed
Questions:
- Table
emp_big
a le degré de parallélisme est à 1, selonselect table_name, degree from user_tables
.Pourquoi Oracle de la force d'insertion parallèles? - Pourquoi ne l'aide
autotrace trace
causeORA-12838
?
La solution
Réponse à la sortie d'origine:
Ce n'est pas causé par traçage.Vous obtiendrez la même erreur, même sans traçage, tout en répétant le même chemin direct de l'insertion.Question d'un commit après la première insertion.
C'est documentée de la restriction: ORA-12700 à ORA-19400
ORA-12838:impossible de lire/modifier un objet après l'avoir modifié en parallèle
Cause: Dans la même transaction, une tentative a été faite pour ajouter ou lire instructions de modification sur une table après qu'il a été modifié en en parallèle ou directement en charge.Ce n'est pas permise.
Action:Réécrire la transaction, ou la diviser en deux opérations:un contenant la première modification et la deuxième contenant l'parallèle modification de l'opération.
Réponse à la nouvelle sortie, après la modification:
Ok, si vous avez un pas en arrière, et vous avez commencé une nouvelle transaction.Dans ce cas, traçage est vraiment le coupable, indirectement.La règle ci-dessus s'applique toujours, et que la description ci-dessus dit, même une lecture de référence sera la cause de l'erreur ci-dessus.Si le traçage est activé, il est implicitement fonctionne quelque chose comme ceci (après l'original de votre déclaration a été fini):
EXPLAIN PLAN SET STATEMENT_ID='PLUSxxxxxx' FOR insert /*+ append */ into emp_big select * from emp_big_temp;
Vous pouvez facilement vérifier cela en permettant à la errorstack trace de l'erreur 12838 (c'est bien dans un environnement sandbox pour cette courte démo, mais ce n'est pas comment je pourrais le faire sur une vraie base de données):
alter system set events '12838 trace name errorstack level 3';
Si je lance ce maintenant:
SQL> create table t1 as select * from dba_objects where 1=2;
Table created.
SQL> alter system set events '12838 trace name errorstack level 3';
System altered.
SQL> set autotrace on
SQL> insert /*+ append */ into t1 select * from dba_objects;
20079 rows created.
Execution Plan
----------------------------------------------------------
ERROR:
ORA-12838: cannot read/modify an object after modifying it in parallel
Je vais trouver l'erreur et un fichier de trace dans le journal des alertes.Le fichier de trace contient ceci:
dbkedDefDump(): Starting a non-incident diagnostic dump (flags=0x0, level=3, mask=0x0)
----- Error Stack Dump -----
ORA-12838: cannot read/modify an object after modifying it in parallel
----- Current SQL Statement for this session (sql_id=5x12x8czsd3t9) -----
EXPLAIN PLAN SET STATEMENT_ID='PLUS730007' FOR insert /*+ append */ into t1 select * from dba_objects
Et c'est ce qui provoque l'erreur, parce que c'est toujours la même transaction.Vous pouvez le tester, même sans traçage:
SQL> rollback;
Rollback complete.
SQL> set autotrace off
SQL> insert /*+ append */ into t1 select * from dba_objects;
20079 rows created.
SQL> explain plan for insert /*+ append */ into t1 select * from dba_objects;
explain plan for insert /*+ append */ into t1 select * from dba_objects
*
ERROR at line 1:
ORA-12838: cannot read/modify an object after modifying it in parallel
SQL> select count(*) from t1;
select count(*) from t1
*
ERROR at line 1:
ORA-12838: cannot read/modify an object after modifying it in parallel