!
!
!
!
!
!
!
!

Les notions du mois de décembre 2000

!

Les groupes de ressources (06/12/2000)

ORA-1555 snapshot is too old (05/12/2000)

Les transactions discrètes (04/12/2000)

Modifier le stockage d'un index (04/12/2000)

Renommer les répertoires pour une standby database (04/12/2000)

Une des nouveautés d’oracle 8i est l’apparition des RESOURCE GROUPS. Un objet de ce type permet de stipuler un taux d’utilisation du CPU pour un groupe d’utilisateurs. Pour utiliser les groupes de ressources, le DBA doit instaurer un PLAN de RESSOURCES. De cette maniere le DBA peut octroyer des ressources (à plusieurs niveaux).

Création d’un plan de ressources
Les grandes lignes de la création d’un plan sont montrées dans le tableau suivant :

         Action                                                               Comment faire? 
        1 Octroyer des privilèges à l’administrateur de plan dbms_resource_manager_privs.grant_system_privilege
        2 Création de PENDING AREA                                dbms_resource_manager.create_pending_area
        3 Création du PLAN MAP 
        4 Création de TOP LEVEL PLAN                              dbms_resource_manager.create_plan
        5 Création de sous PLANS                                     dbms_resource_manager.create_plan
        6 Création de groupes et sous-groupes                  dbms_resource_manager.create_consumer_group
        7 Création de directives                                        dbms_resource_manager.create_plan_directive
        8 Validation de PENDING AREA                              dbms_resource_manager.validate_pending_area
        9 Si validation non achevée, 4 
        10 Soumission de PENDING AREA                          dbms_resource_manager.submit_pending_area
        11 Octroyer des groupes obtenus aux utilisateurs avec
                                                               dbms_resource_manager_privs.grant_switch_consumer_group, 
                                                               dbms_resource_manager.set_initial_consumer_group, 
                                                               dbms_resource_manager.switch_consumer_group_for_user, 
                                                               dbms_resource_manager.switch_consumer_group_for_sess
L’exemple ci-après alloue des ressources à deux groupes d’utilisateurs, BATCH et TP qui seront intégrés dans un plan d’allocation (simple) de ressources nommé UTILISATEURS.

        SQL> set serveroutput on
        SQL> execute dbms_resource_manager.create_pending_area;
        PL/SQL procedure successfully completed.
        SQL> --
        SQL> execute dbms_resource_manager.delete_plan -
        > 	    (plan=>'UTILISATEURS') ;
        PL/SQL procedure successfully completed.
        SQL> execute dbms_resource_manager.delete_consumer_group -
        > 	    (consumer_group=>'BATCH') ;
        PL/SQL procedure successfully completed.
        SQL> execute dbms_resource_manager.delete_consumer_group -
        > 	    (consumer_group=>'TP') ;
        PL/SQL procedure successfully completed.
        SQL> --
        SQL> --
        SQL> execute dbms_resource_manager.create_plan -
        > 	    (plan=>'UTILISATEURS', comment=>'jour ou nuit') ;
        PL/SQL procedure successfully completed.
        SQL> --
        SQL> execute dbms_resource_manager.create_consumer_group -
        > 	    (consumer_group=>'TP', comment=>'Saisie');
        PL/SQL procedure successfully completed.
        SQL> execute dbms_resource_manager.create_consumer_group -
        > 	    (consumer_group=>'BATCH', comment=>'Batch');
        PL/SQL procedure successfully completed.
        SQL> --
        SQL> execute dbms_resource_manager.create_plan_directive -
        > 	    (plan => 'UTILISATEURS', group_or_subplan => 'BATCH', -
        > 	    comment => 'utilisateurs de nuit', cpu_p1 => 20, cpu_p2 => 0, -
        > 	    parallel_degree_limit_p1 => 4 );
        PL/SQL procedure successfully completed.
        SQL> execute dbms_resource_manager.create_plan_directive -
        > 	    (plan => 'UTILISATEURS', group_or_subplan => 'TP', -
        > 	    comment => 'utilisateurs de nuit', cpu_p1 => 75, cpu_p2 => 0, -
        > 	    parallel_degree_limit_p1 => 0 );
        PL/SQL procedure successfully completed.
        SQL> execute dbms_resource_manager.create_plan_directive -
        > 	    (plan => 'UTILISATEURS', group_or_subplan => 'OTHER_GROUPS', -
        > 	    comment => 'Others', cpu_p1 => 5, cpu_p2 => 0, -
        > 	    parallel_degree_limit_p1 => 0 );
        PL/SQL procedure successfully completed.
        SQL> --
        SQL> execute dbms_resource_manager.validate_pending_area;
        PL/SQL procedure successfully completed.
        SQL> --
        SQL> execute dbms_resource_manager.submit_pending_area;
        PL/SQL procedure successfully completed.
        SQL> --
        SQL> execute DBMS_RESOURCE_MANAGER_PRIVS.GRANT_SWITCH_CONSUMER_GROUP -
        > 	     ( 'ANP', 'TP', FALSE)
        PL/SQL procedure successfully completed.
        SQL> --
        SQL> execute dbms_resource_manager.set_initial_consumer_group -
        > 	    (user=>'ANP', consumer_group=>'TP');
        PL/SQL procedure successfully completed.
        SQL> spool off
        Le package dbms_resource_manager fournit une pléiade de procédures qui
        implémente ces options. La documentation du package se trouve dans 
        Oracle8i Supplied PL/SQL Packages Reference, un regard peut
        être jeté dans le commentaires trouvés dans rdbms/admin/dbmsrmad.sql.
        Administrer les plans de ressources
        Plusieurs vues permettent de vérifier les objets nécessaires aux plans de ressources. 
        Un listing global des
        résultats est présenté ensuite.
        DBA_RSRC_PLANS
        Les plans de ressources et leurs statuts
        SQL> select plan, status from dba_rsrc_plans;
        PLAN            STATUS 
        --------------- ------ 
        UTILISATEURS    ACTIVE 
        SYSTEM_PLAN     ACTIVE 
        DBA_RSRC_PLAN_DIRECTIVES
Détails des directives de plans des ressources
SQL> select plan, group_or_subplan, cpu_p1, cpu_p2,
2 parallel_degree_limit_p1, status
3 from dba_rsrc_plan_directives
4 order by plan;

        PLAN            Sous Plan       CPU_P1 CPU_P2 Parallel STATUS 
        --------------- --------------- ------ ------ -------- ------ 
        SYSTEM_PLAN     SYS_GROUP          100      0        0 ACTIVE 
        SYSTEM_PLAN     OTHER_GROUPS         0    100        0 ACTIVE 
        SYSTEM_PLAN     LOW_GROUP            0      0        0 ACTIVE 
        UTILISATEURS    BATCH               20      0        4 ACTIVE 
        UTILISATEURS    TP                  75      0        0 ACTIVE 
        UTILISATEURS    OTHER_GROUPS         5      0        0 ACTIVE 

        DBA_RSRC_CONSUMER_GROUPS
        

Les groupes de consommateurs de ressources
SQL> select consumer_group, status, mandatory from dba_rsrc_consumer_groups;

        CONSUMER_GROUP                 STATUS MAN 
        ------------------------------ ------ --- 
        TP                             ACTIVE NO 
        BATCH                          ACTIVE NO 
        OTHER_GROUPS                   ACTIVE YES 
        DEFAULT_CONSUMER_GROUP         ACTIVE YES 
        SYS_GROUP                      ACTIVE NO 
        LOW_GROUP                      ACTIVE NO 
        DBA_RSRC_CONSUMER_GROUPS_PRIVS

Les privileges des groupes de consommateurs de ressources
SQL> select * from dba_rsrc_consumer_group_privs;
        GRANTEE    GRANTED_GROUP                  GRA INI 
        ---------- ------------------------------ --- --- 
        ANP        TP                             NO  YES 
        PUBLIC     DEFAULT_CONSUMER_GROUP         YES YES 
        PUBLIC     LOW_GROUP                      NO  NO 
        SYSTEM     SYS_GROUP                      NO  YES 

La vue DBA_USERS contient une colonne (INITIAL_RSRC_CONSUMER_GROUP) qui montre l’appartenence initiale de l’utilisateur. Les vues dynamiques V$RSRC_CONSUMER_GROUP et V$RSRC_PLAN montrent des informations actuelles. V$SESSION est enrichie d’une nouvelle colonne, RESOURCE_CONSUMER_GROUP.

 

ORA-1555 snapshot is too old

Lors d'une lecture consistante Oracle peut ne plus trouver les informations nécessaires dans le rollback segment parce que le bloc en question était marqué libre et une autre transaction l’a utilisé. Il existe deux causes fondamentales de cette erreur, a) l'information du rollback segment elle-même est effacée ou b) l'information du header est effacée. Dans les deux cas, la solution immédiate est d’augmenter la taille du rollback segment, de diminuer le nombre de commits ou ajouter des rollback segments, pour tarder l’écrasement d’un bloc libéré. Dans le deuxième cas (b), forcer le delayed cleanout plus tôt en demandant un full table scan (SELECT * FROM LATABLE;) D’autres causes possibles sont la relecture d'un bloc dans une transaction discrète ou le shrink d'un rollback segment. Bien que les solutions proposées sont valables, il faut comprendre qu’elle ne garantissent pas la résolution du problème. La réelle solution est d’éviter de permettre à des transactions qui durent longtemps (BATCH) de partager les mêmes données avec des transactions qui durent très peu (OLTP).

Il est possible de ne pas utiliser les rollback segments grâce aux transactions discrètes, lors des activités très rapides et qui modifient peu de blocs de données. Les transactions qui se prêtent à être discrétisées sont celles qui 
· Modifient quelques blocs uniquement 
· Ne modifient plus d’une fois les données dans un bloc pendant la meme transaction 
· Ne modifient pas les données lues par d’autres transactions de longue durée 
· Ne nécessitent pas la relecture des données modifiées 
· Ne modifient pas des champs de type LONG 
· Ne sont pas distribuées 
Lors d’une transaction discrète (discrete transaction), toutes les modifications dans les blocs de données sont différées jusqu’au commit. Les entrées redo sont générées, mais ne sont pas écrites dans le buffer redo log avant le commit. Assez bizarre, une transaction discrète ne voit pas ses propres modifications puisque les modifications sont rendues visibles uniquement lors de la validation (COMMIT). C’est cette cécité qui rend impossible pendant la même transaction la mise à jour d'un couple table parent/table enfant Les transactions discrètes peuvent apporter des gains spectaculaires de performances dues au fait qu’aucune écriture dans les rollback n’est effectuée. Le revers de la médaille est qu’elles doivent se conformer aux conditions draconiennes énumérées plus haut. Le danger à éviter est l’accès aux données modifiés pendant une transaction discrète par d’autres transactions. Comme il n’y a pas d’image avant, les autres transactions risquent de se heurter du message ‘snapshot is too old’ ! Nous signalons à Oracle le début d’une transaction discrète avec DBMS_TRANSACTION.BEGIN_DISCRETE_TRANSACTION; Ceci est rendu possible si le paramètre DISCRETE_TRANSACTIONS_ENABLED est TRUE (avant 8.1.3). S’il est FALSE, l’appel à la procédure précédente échoue et la transaction est manipulée comme d’habitude, avec allocation de rollback segment. Normalement, vous devriez utiliser les transactions discrètes dans des blocs PL/SQL, gérer les exceptions (toute exception provoque l’erreur DISCRETE_TRANSACTION_FAILED ou CONSISTENT_READ_FAILURE), et dans le cas d’une exception provoquer rollback et recommencer la transaction. Le fait de provoquer rollback arrête la transaction discrète et commence une autre, normale. L’erreur CONSISTENT_READ_FAILURE est générée lors de la rencontre des données modifiées par de transactions qui ne gênèrent pas de rollback : create index, une autre transaction discrète ou direct load. Elle est présente depuis 8.1.6.

Q. Lors de l'implémentation d'une standby database, j'ai un problème avec le paramètre DB_FILE_ NAME_CONVERT:  j'ai des fichiers de la base de production qui ont comme racines : /dbf1/...., /dbf2/.... que je voudrais changer en /dbf3/..., /dbf4/...

A. Il n'est pas possible de renommer les fichiers automatiquement. Oracle sait faire un renommage de type '/vieux' en '/nouv' avec db_file_name_convert = '/vieux', '/nouv' et renommera /vieux/dbf1 en /nouv/dbf1, etc. Dans la situation présentée, faire un alter database rename '/dbf1/..' to '/dbf3..'; etc

Modifier le stockage d'un index

Q. Comment modifier le stockage d'un index ?

A. Ca dépend de la version d'Oracle employée.Comme d'habitude ! Quelle version d'Oracle ?

En 8i, alter index toto rebuild online tablespace blahblah; ceci a l'avantage que vous ne perdez à aucun moment les contraintes.
Avant 8i, il va falloir désactiver les contraintes et les recréer avec la bonne syntaxe pour que les index utilisent le bon tablespace. Plus de détails :-)

SQL> connect anp/anp@idba
Connected.
SQL> drop table k;
Table dropped.
SQL> create table k (c1 number, c2 number, c3 varchar2(45));
Table created.
SQL> create unique index kidxc2 on k(c2);
Index created.
SQL> select index_name, tablespace_name,index_type, table_name, uniqueness
from user_indexes where table_name = 'K';
INDEX_NAME TABLESPACE INDEX_TYPE TABLE_NAME UNIQUENES
---------- ---------- ---------- ---------- ---------
KIDXC2 USER1 NORMAL K UNIQUE

SQL> -- en 8i
SQL> alter index kidxc2 rebuild online tablespace tools1;
Index altered.
SQL> select index_name, tablespace_name,index_type, table_name, uniqueness
from user_indexes where table_name = 'K';
INDEX_NAME TABLESPACE INDEX_TYPE TABLE_NAME UNIQUENES
---------- ---------- ---------- ---------- ---------
KIDXC2 TOOLS1 NORMAL K UNIQUE

SQL> -- autres
SQL> drop index kidxc2;
--Si pas de contraintes, ca marche !
Index dropped.
SQL> create unique index kidxc2 on k(c2);
Index created.
SQL> select index_name, tablespace_name,index_type, table_name, uniqueness
from user_indexes where table_name = 'K';
INDEX_NAME TABLESPACE INDEX_TYPE TABLE_NAME UNIQUENES
---------- ---------- ---------- ---------- ---------
KIDXC2 USER1 NORMAL K UNIQUE
SQL> -- une contrainte
SQL> alter table k add (constraint kidxc2 primary key (c2));
Table altered.
SQL> -- ca ne marchera pas à cause de la contrainte
SQL> drop index kidxc2;
drop index kidxc2
*
ERROR at line 1:
ORA-02429: cannot drop index used for enforcement of unique/primary key

SQL> -- liberons
SQL> alter table k disable primary key;
Table altered.
SQL> -- l'index a disparu
SQL> select index_name, tablespace_name,index_type, table_name, uniqueness
from user_indexes where table_name = 'K';
no rows selected

SQL> -- le recreer dans un autre tablespace (l'index) en remettant la
contrainte
SQL> alter table k enable primary key USING INDEX TABLESPACE tools1 STORAGE
(INITIAL 65536)PCTFREE 10;
Table altered.
SQL> select index_name, tablespace_name,index_type, table_name, uniqueness
from user_indexes where table_name = 'K';
INDEX_NAME TABLESPACE INDEX_TYPE TABLE_NAME UNIQUENES
---------- ---------- ---------- ---------- ---------
KIDXC2 TOOLS1 NORMAL K UNIQUE
SQL> -- tout baigne !
SQL> spool off


 


Copyright © 1998-2012 Radu Caulea, TAFORA MAJ 19/05/2012 !
Commentaires et suggestions radu[CHEZ]tafora.fr