Comment visualiser sont les ordres qui divergent des originaux dans DB Replay ?

Après avoir rejoué une charge avec DB Replay, il est probable que certaines requêtes divergent. Il se peut que ce soit à cause d’une erreur, ou dans le cas le plus probable, parce que le résultat d’une requête est différent entre la capture et le replay ; par exemple la requête ci-dessous ne ramènera jamais le même résultat :

select sid, serial# 
from gv$session
where username is not null
and username != 'SYS'

Est-ce grave ? Pas forcément mais encore faut-il être capable d’étudier ces cas…

Pour se faire, la vue DBA_WORKLOAD_REPLAY_DIVERGENCE donne le SQL_ID de ces ordres divergeants comme vous le voyez dans mon article précédent Comparer Capture et Replay de Real Application Testing « . Seulement le SQL_ID ne suffit pas, il vous faut le texte et les valeurs de bind. Alors comment faire ? Evidemment, vous pouvez interroger AWR, la shared pool ou le STS généré (en 11.2.0.2) mais ce n’est pas garanti que vous retrouverez l’information.

Ces données sont en fait dans les fichiers d’enregistrement et les procédures dbms_workload_replay.get_diverging_statement ou dbms_workload_replay.populate_diverging vous y donne accès simplement comme vous pouvez le voir ci-dessous :

set tab off
col sql_id format a15 new_value sql_id
col STREAM_ID format 999999999999999999999 new_value STREAM_ID
col CALL_COUNTER format 9999 new_value CALL_COUNTER

set tab off
select replay_id,
IS_QUERY_DATA_DIVERGENCE,
IS_DML_DATA_DIVERGENCE,
IS_ERROR_DIVERGENCE,
IS_THREAD_FAILURE,
STREAM_ID,
CALL_COUNTER,
SQL_ID
from DBA_WORKLOAD_REPLAY_DIVERGENCE
where replay_id=&&replay_id;

REPLAY_ID I I I I STREAM_ID CALL_COUNTER SQL_ID
--------- - - - - ---------------------- ------------ --------------
101 Y N N N 1597055482751614980 21 9mg7c4chxpjcw
101 Y N N N 1597055482751614984 21 9mg7c4chxpjcw
101 Y N N N 1597055482751614986 21 9mg7c4chxpjcw
101 Y N N N 1597055482751614988 21 9mg7c4chxpjcw
101 Y N N N 1597055482751614992 21 9mg7c4chxpjcw

var out clob
exec :out:=dbms_workload_replay.GET_DIVERGING_STATEMENT(101,1597055482751614988,21)
set long 10000
set longchunksize 10000
set head off
set lines 10000
print out

<replay_divergence_info>
<sql_id>9mg7c4chxpjcw</sql_id>
<sql_text>select *
from mydb
where dbname=&apos;RED&apos;</sql_text>
<full_sql_text>select *
from mydb
where dbname=&apos;RED&apos;</full_sql_text>
<binds/>
</replay_divergence_info>

set lines 120
set head on

Notes:
En fait, il n’est pas utilise d’utiliser dbms_workload_replay.populate_diverging puisque la procédure est appelée automatiquement par dbms_workload_replay.get_diverging_statement.
Pour les plus curieux, ces informations, une fois chargées sont disponibles dans les tables WRR$_REPLAY_SQL_TEXT et WRR$_REPLAY_SQL_BINDS d’AWR

Bug ou résultat attendu ?

Vous me direz, tout ça est dans la documentation alors pourquoi en parler ? Et bien parce que contrairement à ce que suggère la description de la procédure POPULATE_DIVERGENCE, si vous laissez la valeur NULL pour les paramètres stream_id et call_counter, au moins avec get_diverging_statement, vous avez une erreur pas vraiment explicite et pas le résultat que vous attendrez :

var out clob
exec :out:=dbms_workload_replay.GET_DIVERGING_STATEMENT(101,null,null)

*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at "SYS.DBMS_WORKLOAD_REPLAY", line 5831
ORA-06512: at line 1

Vous me direz, c’est assez facile à corriger et c’est peut-être contextuel à ma version 11.2.0.2 sans PSU ! Ca ne m’a empêché de perdre quelques longues minutes sur ce problème un peu stupide, j’en conviens.