vendredi 6 novembre 2015

Les hints de jointure et du parallélisme


Les hints de jointure :
  • LEADING : Permet de spécifier la table menante dans une jointure                                             select /*+leading (cmd cli) */ cli.noclient,nom, cmd.datecommande                              from clients cli,cmd                                                                        where cli.noclient=cmd.noclient                                                              and cli.noclient between 100000 and 100020 ;
  • ORDERED:  Permet de spécifier que les jointures doivent être faites dans l’ordre d’apparition dans la clause FROM.
  • USE_NL,NO_USE_NL: Force ou interdit une jointure par boucles imbriquées (Nested Loop).
  • USE_NL_WITH_INDEX: Force une jointure par boucles imbriquées seulement si unindex est présent sur la table jointe. Ce hint sera sans effet si l’index disparaît ou est invalidé. En effet, l’impossibilité d’utiliser un index pourrait avoir des conséquences désastreuses en termes de performances : une boucle imbriquée sur une grosse table non indexée a des performances catastrophiques car elle provoque un parcours complet de la table pour chaque valeur de la table menante.
  • USE_MERGE, NO_USE_MERGE. Force ou interdit une jointure par Sorted Merge.
  • USE_HASH, NO_USE_HASH. Force ou interdit une jointure par table de hachage.

Les hints de parallélisme :

  • PARALLEL(table_alias , degré //): Permet de spécifier un niveau de parallélisme pour les accès à une table.
  • NO_PARALLEL (table_alias):  Permet de désactiver le parallélisme pour les accès à une table.
  • PARALLEL_index (table_alias , idx,degré):  Permet de spécifier un niveau de parallélisme sur les Index Scan.
  • NO_PARALLEL_index (table_alias):  Permet de désactiver le parallélisme sur les Index Scan.

Les hints Access Path

il existe différents types de hints Access Path :


  • Full (table_alias). Permet de forcer un parcours complet d’une table au lieu d’utiliser un index.
  • Index (table_alias Nom_index). Permet de forcer l’utilisation d’un index en particulier lors de l’accès à une table. Ce hint est le plus utilisé car il empêche l’optimiseur d’écarter, à tort, un index s’il y a des erreurs d’estimation des cardinalités:                                                                                 select /*+index(TAB IDX_COL1) */  * from MYTABLE TAB where id >500000;
  • No_Index (table_alias Nom_index). Interdit l’utilisation d’un index particulier lors de l’accès à une table : select /*+no_index(TAB IDX_COL1) */  * from MYTABLE TAB where id >500000;
  • Index_FFS (table_alias Nom_index). Permet de forcer un Fast Full Scan sur un index.
  • No_Index_FFS (table_alias Nom_index). Interdit un Fast Full Scan sur un index.
  • Index_SS (table_alias Nom_index). Permet de forcer un Skip Scan sur un index.
  • No_Index_SS (table_alias Nom_index). Interdit un Skip Scan sur un index.
  • Index_RS (table_alias Nom_index). Permet de forcer un Range Scan sur un index (n’apparaît pas dans la documentation officielle).
  • INDEX_COMBINE(table_alias Nom_index1 Nom_index2 …). Force une combinaison de type bitmap de plusieurs index B*Tree.
  • INDEX_JOIN (table_alias Nom_index1 Nom_index2 …). Force une combinaison par jointure de plusieurs index.

Migration vers Exadata

La migration de vos bases de données vers une machine Exadata :




Vous avez votre machine Exadata et vous avez terminé la phase de mise en place et de configuration. Vous devez maintenant passer à l’essentiel et migrer vos bases de données vers votre nouvelle machine. Cette action est l’aboutissement de toute un travail et une étape très attendu par votre entreprise. Alors comment faire?

Globalement il y a deux catégories de migration :
·         Migration logique
·         Migration Physique
Il y a certainement des facteurs liés à votre contexte qui font que l’une des deux catégories soit plus adapté : Par exemple le temps d’indisponibilité.
La migration logique consiste à extraire les données de la base de données d’origine et les charger dans la base cible. La migration physique elle consiste à faire une copie bloc par bloc.
Les caractéristique de la base à migrer influence sur la stratégie à adopter. En effet sur Exadata la méthode d’accès aux données à son importance :
Dans un contexte OLTP par exemple on va plutôt avoir des petite transaction et le besoin d’accéder à une quantité limité de blocs dans toutes les tables. En revanche dans une base de type Data Warehouse on accède a une grande quantité de données et la base est optimisé pour les full scan. Exadata utilise les caches flash au niveau des cellules de stockage pour améliorer les performances d’un environnement OLTP. Pour un environnement Data Warehouse il va plus utiliser Smart Scan technologie pour optimiser les full scan. Quelle différence entre les deux catégories de Migration :

Migration Logique :
La migration logique peu importe la technologie utilisée consiste à extraire des objets d’une bases de données source et les charger dans une base de données cible.  Plus fastidieuse que la migration physique elle donne beaucoup plus de possibilités d’opérer des changements. Voici une liste non exhaustive des avantages de la migration logique dans le contexte Exadata:
·         Changement de plateforme: Les données sont automatiquement adaptés à la taille de bloc de la base de données cible. La conversion de Big-endiane vers Little-endiane est automatique. La compression HCC (Exadata hybrid columnar compression) peut être configuré avant le chargement des données : sur la base cible on compresse une table avec HCC et on charge les données à partir de la table d’origine. Les  données seront ainsi compressées lors du chargement.
·         La taille des Extent :  Les tables, indexes et partitions cible peuvent être définies avec une taille d’extent optimisée pour le type de bases : plus grande pour les Data Warehouse et plus petite pour OLTP.
·         Filtre des objets à migrer : Les objets de la base d’origine qui ne sont plus utilisés peuvent être ignorés durant la migration.
·         Fusionner des bases de données : sur les serveurs ou nous avons un grand nombre de bases de données on peut dans la mesure du possible fusionner plusieurs bases dans une seule sur Exadata et optimiser ainsi l’utilisation de la SGA.
Pour la migration logique nous avons généralement deux techniques :
1.       Extraction/chargement: les outils utilisés sont Data pump, Import/Export et create table as (select …) ou Insert as (select…) via un @DBLINK.
2.       Réplication : faire une réplication de la base à migrer sur un serveur de base de données sur la machine Exadata. Quand on souhaite finaliser la migration on arrête la réplication on redirige les applications clients vers la base cible. Les outils utilisés sont: Oracle Dataguard (Logical standby), Oracle Goldengate.


A suivre…

vendredi 30 octobre 2015

Reverse Index

Ce sont des index B*Tree qui indexent les valeurs miroirs ou inverses (par exemple, le nom
"FRED" devient "DERF"). La syntaxe est identique, il faut juste spécifier le mot clé REVERSE à la fin de l’instruction :

Create index  Nom_Index on  NomTable (<col1>[,<col2>,…]) REVERSE

Le but de ce type d’index est d’éviter que deux valeurs qui se suivent dans leur ordre naturel se retrouvent dans la même feuille. L’objectif est ici de s’organiser pour avoir un mauvais Clustering Factor. Mais alors dans quel intérêt ?

Imaginez une table dont la clé est un numéro séquentiel et qu’il y ait de nombreuses insertions en parallèle. On se retrouve alors avec plusieurs requêtes qui vont vouloir mettre à jour la même feuille d’index. Or, cette opération ne peut pas être faite par deux requêtes simultanément donc cela aurait pour effet de bloquer chacune d’elles le temps que la précédente ait terminé la mise à jour de la feuille d’index. Avec un index reverse, elles vont mettre à jour des feuilles d’index différentes et ainsi elles ne se gêneront pas. Cela permet donc de réduire la contention d’accès en écriture des feuilles d’index, ce qui sera intéressant sur des requêtes parallèles, particulièrement en environnement Oracle RAC. Cependant, ce type d’index montre des limites car il n’est utilisable que sur des conditions de type égalité (=), ce qui signifie qu’il ne fonctionnera pas pour des opérations Index Range Scan.

Clustering Factor

Clustering Factor ou en français Le facteur de foisonnement :

Clustering Factor établit le nombre de liens qu’il y a entre l’ensemble des feuilles de l’index et les blocs dans le tas. Il permet d’estimer si le fait que plusieurs valeurs se trouvent dans une même feuille d’index nécessitera plutôt peu de lecture de blocs différents dans le tas ou plutôt beaucoup.
Les données relatives au Clustering Factor sont disponibles dans la dictionnaire et on y accède par la requête suivante :

select t.INDEX_NAME,
       t.LEAF_BLOCKS,
       t.DISTINCT_KEYS,
       t.CLUSTERING_FACTOR
from sys.user_ind_statistics t 
where index_name like '%CLIENT%';


INDEX_NAME  LEAF_BLOCKS   DISTINCT_KEYS    CLUSTERING_FACTOR
-------------------- --------- -----------  -------------- ---------- -------------------------------
PK_CLIENTS                 94                 45000                            759
IS_CLIENTS_VILLE     130               1096                               43479


Clustering_Factor/Leaf_Blocks donne le nombre de liens qu’il y a en moyenne
entre une feuille et des blocs de données dans le tas : un ratio inférieur ou égal à 3
est excellent. Par contre, lorsque Clustering_Factor tend vers le nombre d’enregistrements, alors le Clustering Factor est considéré comme mauvais. Prenons deux cas pour illustrer le Clustering Factor :

Premier cas : L’index de clé primaire sur la colonne Nocmd de la table des commandes cmd. Si on suppose que les numéros de commandes sont créés séquentiellement, de façon ordonnée et jamais supprimés, le tas sera globalement dans le même ordre que l’index. Si l’index retourne plusieurs RowID depuis un même bloc (ce qui est caractéristique d’un prédicat sur une partie de clé ou sur un intervalle), alors il est probable que ces RowID désignent le même bloc ou peu de blocs différents dans le tas (puisque, généralement, il y aura plus de blocs dans le tas que de blocs d’index). Dans ce cas, le Clustering Factor sera bon.

Second cas:  Un index sur la colonne Ville dans la table des clients. Si on suppose que les clients n’agissent pas de façon concertée ou dirigée, alors ils seront mis dans le tas dans l’ordre suivant lequel ils ont passé leur première commande mais ils seront normalement dans des villes différentes. Donc, le fait de rechercher tous les clients situés à "Toulouse" retournera, depuis une ou plusieurs pages consécutives de l’index, des RowID qui désigneront des blocs qui seront probablement
sans aucun point commun. Dans ce cas, le facteur de foisonnement sera mauvais.

Un bon Clustering Factor permettra d’avoir de meilleures performances lors d’une opération Index Range Scan puisque, pour chaque feuille d’index, il y aura peu de blocs de données à charger depuis le tas. Pour les autres types d’accès, l’impact sera généralement faible. Un mauvais Clustering Factor aura pour effet de considérer un Index Range Scan moins intéressant.

In-Mermory Parallel Execution

In-Mermory Parallel Execution utilise une agrégation des mémoires disponibles pour éliminer au maximum le besoin des IO physique pour les opération parallélisées.  Autrement dit Oracle peut prendre la décision de placer en mémoire un objet(une table) sur lequel les exécutions parallèle sont autorisées. Pour une architecture en RAC il reparti les fragment de la table dans les différents Buffer Cache des instances actives du cluster. Cette répartition ou mapping permet à Oracle de déterminer le buffer cache utile pour trouver un ensemble de données nécessaires pour répondre à une requête et ainsi réduire le besoin d'I/O physique. Cette technique est rendu possible par le quantité importante de mémoire disponible dans les nouvelles infrastructures. Pour bénéficier de l'option  In-Mermory Parallel Execution il faut que le paramètre d'initialisation PARALLEL_DEGREE_POLICY soit configuré à AUTO (valeur par défaut MANUEL)

  

dimanche 4 octobre 2015

INDEX VIRTUEL


Un index virtuel est un index que l'on déclare sans qu'il ne soit physiquement créé.  Une simulation d'un index. En effet dans bien des cas et principalement dans les environnements de prod on peut vouloir tester un index pour voir s'il améliore les performances sans impacter la production
Avec une consommation cpu, IO et stockage.

Considérons la requête suivante :

SQL> EXPLAIN PLAN FOR
2 SELECT * FROM sh.sales WHERE quantity_sold > 10000
3 /

Explained.

SQL> SELECT *
2 FROM TABLE (DBMS_XPLAN.display (NULL, NULL, 'BASIC +COST'))
3 /
--------------------------------------------------
| Id | Operation | Name | Cost (%CPU)|
--------------------------------------------------
| 0 | SELECT STATEMENT | | 441 (12)|
| 1 | PARTITION RANGE ALL| | 441 (12)|
| 2 | TABLE ACCESS FULL | SALES | 441 (12)|
-------------------------------------------------


Nous avons un table access full sur la table SALES.  On peut se poser la question si un index serai pas plus performant.

SQL> ALTER SESSION SET "_use_nosegment_indexes"=TRUE;

Session altered.

SQL> CREATE INDEX sh.sales_vi1 ON sh.sales(quantity_sold) NOSEGMENT;

Index created.

L'option NOSEGMENT indique qu'il s'agit d'un index virtuel.

On execute de nouveau la requête :

SQL> EXPLAIN PLAN FOR
2 SELECT * FROM sh.sales WHERE quantity_sold > 10000;

Explained.

SQL> SELECT *
2 FROM TABLE (DBMS_XPLAN.display (NULL, NULL, 'BASIC +COST'));

| Id | Operation | Name | Cost (%CPU)|
---------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 (0)|
| 1 | TABLE ACCESS BY GLOBAL INDEX ROWID| SALES | 3 (0)|
| 2 | INDEX RANGE SCAN | SALES_VI1 | 2 (0)|
---------------------------------------------------------------------

On peut voir dans le plan d'exécution l'utilisation de l'index et l'optimisation qu'il apporte : le coût passe de 441 to 3 on peut donc conseiller la création d'un tel index ou le créer physiquement.




vendredi 2 octobre 2015

EXADATA Offloading/SmartScan


Dans cet article nous allons parler de la notion "Exadata offloading ou SmartScan". Offloading peut éventuellement être traduit par déporter ou déléguer un travail.

La notion du offloading est la recette miracle permettant de faire la différence entre Exadata et toute autre plateforme utilisée pour faire tourner des bases de données Oracle. On parle de offloading pour décrire l'action qui consiste à déplacer les traitements en principe réalisés par le serveur de base de données vers la couche stockage (cellule). L'objectif n'est pas uniquement un transfert de charge des serveurs bases de données aux serveurs de stockage pour reduire la consommation de CPU. L'objectif principal est la réduction de la quantité des données retournées aux serveurs de base de données. Il est à noter que l'importante quantité de données retournées aux serveurs de base de données par la couche stockage représente un des principaux goulot d'étranglement des bases de données.

On parle d'Offloading ou de SmartScan. Cependant le SmartScan fait plus référence aux améliorations apportées par Exadata aux traitements SQL. Le terme Offloading est lui plus générique et fait référence en plus à d'autres aspects par exemple l'impact sur la sauvegarde et restauration.

Pour illustrer l'importance de l'Exadata Offloading on prend un exemple on ne peut plus simple:
Une requête SQL qui récupère un champ dans une ligne dans une table et pour couronner le tout, elle filtre sur le Rowid de la ligne. Dans une architecture non Exadata un minimum d'un bloc devra être chargé en mémoire.
En supposant que la table enregistre en moyenne 50 lignes par bloc. Cela implique que nous allons transférer 49 lignes inutilement au serveur de base de données. Vous pouvez alors imaginer le cas des énormes quantités de données inutiles transmises aux serveurs de base de données et du temps nécessaire pour les transmettre. Exadata à été conçu principalement pour résoudre cette problématique via le Offloading qui a pour principal objectif de réduire la quantité de données retournée par la couche stockage aux serveurs de base de données.

Exadata implemente dans sa couche software des algorithmes permettant de tirer le meilleur profit de la couche hardware. Pour tester l'impact du Offloading je vais modifier le paramètre cell_offload_processing et ensuite interroger une table TAB d'une taille de 385 millions de lignes :

SYS@SU14> alter session set cell_offload_processing=false;
Session altered.
Elapsed: 00:00:00.06

SYS@SU14> select count(*) from TAB where col1 < 0;

COUNT(*)
----------
2 1 row selected.

Elapsed: 00:00:51.09

Je modifie de nouveau le paramètre cell_offload_processing pour activer le Offloading  :

SYS@SU14> alter session set cell_offload_processing=true;

Session altered.

Elapsed: 00:00:00.07

SYS@SU14> select count(*) from TAB where col1 < 0;

COUNT(*)
----------
2 1 row selected.

Elapsed: 00:00:00.15

On peut voir l'amélioration du temps d'exécution de la requête.

Je parlerai prochainement des mécanismes qui sont derrière le SmartScan.


lundi 28 septembre 2015

Reconstruction des index

Le problème :
ORA-01502: index 'idx_bd' or partition of such index is in unusable state 


lister les indexes invalides :

SELECT owner, index_name, tablespace_name
FROM   dba_indexes
WHERE  status = 'UNUSABLE';

On peut aussi voir les indexes de partitions :

SELECT index_owner, index_name, partition_name, tablespace_name
FROM   dba_ind_PARTITIONS
WHERE  status = 'UNUSABLE';

Générer le scripts pour reconstruire les indexes :

SELECT 'alter index '||owner||'.'||index_name||' rebuild tablespace '||tablespace_name ||';'
FROM   dba_indexes
WHERE  status = 'UNUSABLE';


Générer le scripts pour reconstruire les indexes de partition :

SELECT 'alter index '||owner||'.'||index_name ||' rebuild partition '||PARTITION_NAME||' TABLESPACE '||tablespace_name ||';'
FROM   dba_ind_partitions
WHERE  status = 'UNUSABLE';


alter index MON_IDX  rebuild tablespace INDX;

jeudi 24 septembre 2015

EXADATA

Introduction à Exadata

Cet article tente de présenter de manière simple la machine Exadata :


Exadata est une solution intégrée oracle combinant une couche hardware et une couche software fournissant une plateforme pour faire fonctionner des bases de données Oracle. 

On peut voir Exadata comme une couche de stockage et une couche de bases de données reliées via un réseau InfiniBand. Le réseau InfiniBand est caractérisé par une très grande bande passante et une faible latence. La couche base de données est formée de multiple serveurs Sun sur lesquels tournent des bases Oracle 11gR2. Les serveurs de bases de données sont généralement configurés en RAC clusters. Les bases de données utilisent ASM pour la gestion du stockages. Les serveurs de stockage eux aussi sont formés de multiples serveurs Sun. Chaque serveur de stockage contient 12 disques et sur lequel tourne le logiciel oracle storage server(cellsrv). La communication entre différentes couches est effectué via iDB (protocole réseau) implémenté par InfiniBand.
Pour information iDB est utilisé pour interroger les données via des requêtes envoyées à cellsrv accompagnées de metadata sur ces requêtes. Dans certains cas cellsrv utilise ces metadata pour traiter les données avant de les retransmettre à la couche base de données. Ce traitement effectué par cellsrv est appelé Smart Scan.

Les composants Exadata


Voici une vue de la machine Exadata en mode full Rack:

La machine Exadata

Serveur de stockage (cells):

Cell Services(cellsrv) est le système installé sur les serveurs de stockage ou storage cells. C'est un programme multi threads qui offre le service I/O pour répondre au requêtes envoyées par les serveurs de bases de données. En fonction des requêtes, celle-ci peuvent être exécutées en retournant les données déjà traitées au serveur de bases de données ou en retournant l'ensemble des blocks. Pour information cellsrv implemente oracle ressource manager pour là gestion des ressources.


mardi 22 septembre 2015

Supervision requêtes consommatrices.

SI on souhaite mettre en place  une supervision simple pour détecter les requêtes consommatrices et candidates au tuning alors voici une fonction simple pour cela :


  • la fonction pourra être schedulé dans un job
  • Elle devra permettre d'exclure des user que nous voulons pas superviser comme SYS et SYSTEM par exemple.
  • déterminer le seuil (en seconde) d'alerte pour qualifier de long une exécution.
  • la fonction de supervision devra loger dans une table temporaire. Les requêtes longues avec une rétention de 30 jours. 
  • on pourra recevoir un mail avec le reporting sur les requêtes capturées.
    • un seul mail sera envoyé par heure s'il s'agit du même user et de la même requête.
    • pour les sessions parallèle on envoi un unique mail. 
  • La supervision  est compatible avec le RAC.
  1. création de la table qui va contenir les requêtes capturées :
dba_long_sqlstat:


  CREATE TABLE "SYS"."DBA_LONG_SQLSTAT"
   (     "INST_ID" NUMBER,
         "USERNAME" VARCHAR2(30 BYTE),
         "OSUSER" VARCHAR2(30 BYTE),
         "MACHINE" VARCHAR2(64 BYTE),
         "PROGRAM" VARCHAR2(48 BYTE),
         "SQL_ID" VARCHAR2(13 BYTE),
         "LAST_CALL_ET" NUMBER,
         "SQL_TEXT" CLOB
   );


dba_hist_long_sqlstat(table d'historisation):



 CREATE TABLE "SYS"."DBA_HIST_LONG_SQLSTAT"
   (     "CAPTURE_TIMESTAMP" DATE DEFAULT SYSDATE,
         "INST_ID" NUMBER,
         "USERNAME" VARCHAR2(30 BYTE),
         "OSUSER" VARCHAR2(30 BYTE),
         "MACHINE" VARCHAR2(64 BYTE),
         "PROGRAM" VARCHAR2(48 BYTE),
         "SQL_ID" VARCHAR2(13 BYTE),
         "LAST_CALL_ET" NUMBER,
         "SQL_TEXT" CLOB
   );

création de la procédure :

create or replace procedure long_running_sql
is
v_db_name v$parameter.value%type;
crlf VARCHAR2(2):= CHR( 13 ) || CHR( 10 );

begin

   dbms_utility.exec_ddl_statement('truncate table dba_long_sqlstat');

insert into dba_long_sqlstat
select
s.inst_id, s.username, s.osuser, s.machine, s.program, s.sql_id,l_et,st.sql_fulltext
from
(
select distinct inst_id, username, osuser, machine, program, sql_id, max(last_call_et) as l_et
from gv$session
where
username is not null and
username not in ('SYS','SYSTEM','DBSNMP') and
status='ACTIVE'
and last_call_et > 180
group by
inst_id, username, osuser, machine, program, sql_id
) s
left outer join gv$sql st
on s.sql_id = st.sql_id;
commit;

select value into v_db_name from v$parameter where name = 'db_name';


for rec in
(
select * FROM dba_long_sqlstat WHERE ROWID IN
         (SELECT MAX(ROWID) FROM
                 (SELECT inst_id, username, osuser, machine, program, sql_id, last_call_et, sql_text
                  FROM   (
                          SELECT inst_id, username, osuser, machine, program, sql_id, last_call_et, sql_text, rank() over (partition by sql_id order by last_call_et desc) rnk
                          FROM dba_long_sqlstat
                          where sql_id not in (select sql_id from dba_hist_long_sqlstat where capture_timestamp between TRUNC(SYSDATE, 'HH24') and sysdate)
                          )
                 WHERE rnk = 1
                 )
         group by sql_id)
)
loop

declare
  v_from      varchar2(80) :=  v_db_name;
  v_recipient varchar2(80) := 'xxxx@gmail.com';
  v_subject   varchar2(80) := 'long running sql on '||v_db_name;
  v_mail_host varchar2(30) := 'localhost';
  v_mail_conn utl_smtp.connection;
  crlf        varchar2(2)  := chr(13)||chr(10);
begin
 v_mail_conn := utl_smtp.open_connection(v_mail_host,25);
 utl_smtp.helo(v_mail_conn, v_mail_host);
 utl_smtp.mail(v_mail_conn, v_from);
 utl_smtp.rcpt(v_mail_conn, v_recipient);
 utl_smtp.data(v_mail_conn, 'Content-Type: text/html;' || crlf ||
                          'To: '     || v_recipient || crlf ||
                          'Subject: '|| v_subject || crlf ||
                          'The following sql is running for '||  rec.last_call_et || ' seconds in database '|| v_db_name ||'<br><br></html>' ||
                          'DB User: '|| '<html><font color="darkblue">'|| rec.username || '</font><br></html>' ||
                          'On Instance: '|| '<html><font color="darkblue">'|| rec.inst_id || '</font><br></html>' ||
                          'OS User: '|| '<html><font color="darkblue">'|| rec.osuser || '</font><br></html>' ||
                          'Source Machine: '|| '<html><font color="darkblue">'|| rec.machine || '</font><br></html>' ||
                          'Program: '|| '<html><font color="darkblue">'|| rec.program || '</font><br><br></html>' ||
                          'SQL ID: '|| '<html><font color="red">'|| rec.sql_id || '</font><br><br></html>' ||
                          '<html><body><font face="courier" size="1" color="maroon">'|| rec.sql_text ||'</font></body></html>');
  utl_smtp.quit(v_mail_conn);
  end;

end loop;

insert into dba_hist_long_sqlstat(
 inst_id,
 username,
 osuser,
 machine,
 program,
 sql_id,
 last_call_et,
 sql_text)
select * from dba_long_sqlstat;

delete from dba_hist_long_sqlstat where capture_timestamp < (sysdate - 30);
commit;

end long_running_sql ;

2.Scheduler le job selon notre besoin:

Par exemple pour tourner toute les 2 minutes en semaine et dans la plage horaire pertinente pour nous. 

BEGIN
  DBMS_SCHEDULER.create_job (
    job_name        => 'long_running_sql_check_job',
    job_type        => 'PLSQL_BLOCK',
    job_action      => 'BEGIN long_running_sql; END;',
    start_date      => SYSTIMESTAMP,
    repeat_interval => 'FREQ=MINUTELY;INTERVAL=2;BYHOUR=12,13,14,15,16,17,18,19,20,21,22;BYDAY=MON,TUE,WED,THU,FRI',
    end_date        => NULL,
    enabled         => TRUE,
    comments        => 'sup requêtes en semaine ');
END;

Pour tester on peut se connecter bien évidemment avec un user qui n'est pas exclu de la supervision et on execute :

BEGIN
  DBMS_LOCK.sleep(seconds => 500);
END;
/

A tester bien évidemment avant de le mettre en production. 

Architecture Oracle 12c




















lundi 21 septembre 2015

RMAN-20011

RMAN-20011: target database incarnation is not current in recovery catalog


en exécutant le crosscheck j'ai l'erreur suivante :


RMAN> crosscheck archivelog all;

RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of crosscheck command at 09/21/2015 17:06:56
RMAN-12010: automatic channel allocation initialization failed
RMAN-06004: ORACLE error from recovery catalog database: RMAN-20011: target database incarnation is not current in recovery catalog

RMAN>  list incarnation of database;


RMAN> show all ;

RMAN configuration parameters are:
RMAN-00571: ===========================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===============
RMAN-00571: ===========================================================
RMAN-03002: failure of show command at 09/21/2015 17:10:56
RMAN-06004: ORACLE error from recovery catalog database: RMAN-20011: target database incarnation is not current in recovery catalog


SOLUTION

Option 1 - Reset PROD to Previous Incarnation
OR
Option 2 - Re-register PROD with the Recovery Catalog
Finally change the cloned db's DBID:
    Note 224266.1 How to Change the DBID and the DBNAME by using NID


Option 1 - Reset PROD to Previous Incarnation
 A. Check the latest incarnation key for production database in rc_database_incarnation
SQL> select DBID, NAME, DBINC_KEY, RESETLOGS_CHANGE#, RESETLOGS_TIME 
       from RC_DATABASE_INCARNATION
      where dbid=2284119847;

      ==> Check the DBINC_KEY corresponding to the current incarnation of PROD database


B. Connect to the Production Database with RMAN
Be aware that database needs to be in "MOUNT" status to be able to reset the incarnation
$ rman catalog <un/pw@catalog_db> target /
RMAN>
RMAN> reset database to incarnation <dbinc_key>;  
RMAN> resync catalog;
RMAN> list incarnation;   # => Now the production DB incarnation should be the current one and
                          #    the error RMAN-20011 should not raise  anymore

Option 2 - Re-Register PROD with the Recovery Catalog
Warning: Once a database is uregistered from the recovery catalog all backup information will be coming from the controlfile. Therefore you may lose some bakcup information!! If you have other backups that needs to be added to the recovery catalog you must recatalog them afterwards. 
A. Take a backup of the recovery catalog database/schema
B. Confirm the backups you currently have in the controlfile vs recovery catalog. Run the following in both nocatalog and catalog mode:
RMAN> list backup summary;
  
C. Connect to the clone database and recovery catalog and unregister the database:
RMAN> unregister database;
  
D. Connect to prod and the recovery catalog and register the prod database:
RMAN> register database;
RMAN> list incarnation of database;
RMAN> list backup summary;
E. Recatalog any additional backuppieces:
If on disk:
RMAN> catalog start with 'location of the backuppieces'; 

If on tape:
    HOW TO CATALOG TAPE BACKUP PIECES (Doc ID 550082.1)


Dans mon cas (base de test) comme je peux me permettre de le faire :-)   j'ai fait :
  •  unregister database;
  •  register database;


et ensuite j'ai lancé un full  backup de la base.