Translate

vendredi 24 avril 2015

Oracle Data Guard Broker - DGMGRL - Standby


Bonjour

     Cette configuration vous sera utile dans le cas d'un environnement avec une base de données StandBy. Ceci va vous faciliter la vie énormément et on laissera au Broker de faire presque tout le travail de configuration entre les bases de données,

Une fois créée la base de données qui sera configurée comme StandBy, vous pouvez continuer avec la configuration du Broker, pour ce faire : 

Dans cet exemple :

  • TEST_P  ---­  Base de données Primaire 
  • TEST_S  ---­  Base de données StandBy 


Même si au début vos paramètres ne contiennent pas d'information pour la configuration de la BD StandBy

Sur le serveur où se trouve la bd primaire :

$ sqlplus / as sysdba
...
SQL> SHOW PARAMETER BROKER
NAME                    TYPE        VALUE
----------------------- ----------- ------------------------------
dg_broker_config_file1  string      
dg_broker_config_file2  string      
dg_broker_start         boolean     FALSE

SQL> show parameter log_archive_dest
NAME                    TYPE        VALUE
----------------------- ----------- ------------------------------
....
log_archive_dest_2      string             
....

Il faut s'assurer de modifier le paramètre ci-dessous sur les deux bases de données avant de continuer : 

ALTER SYSTEM SET DG_BROKER_START=TRUE SCOPE=BOTH SID='*' ;

Maintenant, on peut commencer la configuration du Broker :

$ dgmgrl
DGMGRL for Linux: Version 11.2.0.1.0 - 64bit Production
Copyright (c) 2000, 2009, Oracle. All rights reserved.

Welcome to DGMGRL, type "help" for information.
--Faire la connexion sur la BD Primaire
DGMGRL> connect sys@test_p
Password:
Connected.

--Créer la configuration du Broker
DGMGRL> CREATE CONFIGURATION EVTA AS PRIMARY DATABASE IS TEST_P CONNECT IDENTIFIER IS TEST_P ;
Configuration "evta" created with primary database "test_p"

--Ajouter la BD StandBy à la configuration
DGMGRL> ADD DATABASE TEST_S AS CONNECT IDENTIFIER IS TEST_S MAINTAINED AS PHYSICAL ;
Database "test_s" added

--Activer la configuration
DGMGRL> ENABLE CONFIGURATION ;
Enabled.

--Pour voir la configuration existante
DGMGRL> SHOW CONFIGURATION
Configuration - evta

 Protection Mode: MaxPerformance
 Databases:
test_p - Primary database
test_s - Physical standby database

Fast-Start Failover: DISABLED

Configuration Status:
SUCCESS


Si vous voulez placer votre base de données StandBy en mode Snapshot ...

DGMGRL> CONVERT DATABASE TEST_S TO SNAPSHOT STANDBY ;
Converting database "test_s" to a Snapshot Standby database, please wait...
Database "test_s" converted successfully
 

DGMGRL> SHOW CONFIGURATION
Configuration - evta

 Protection Mode: MaxPerformance
 Databases:
test_p - Primary database
test_s - Snapshot standby database

Fast-Start Failover: DISABLED

Configuration Status:
SUCCESS

Et voilà, en plus comme vous pouvez voir maintenant :

SQL> SHOW PARAMETER BROKER
NAME                    TYPE        VALUE
----------------------- ----------- ------------------------------
dg_broker_config_file1  string      /DISK2/oracle/product/11.2.0/d
                                    b_1/dbs/dr1TEST_P.dat
dg_broker_config_file2  string      /DISK2/oracle/product/11.2.0/d
                                    b_1/dbs/dr2TEST_P.dat
dg_broker_start         boolean     TRUE


SQL> show parameter log_archive_dest
NAME                    TYPE        VALUE
----------------------- ----------- ------------------------------
....
log_archive_dest_2      string      service="test_s", LGWR ASYNC N
                                    OAFFIRM delay=0 optional compr
                                    ession=disable max_failure=0 m
                                    ax_connections=1 reopen=300 db
                                    _unique_name="test_s" net_time
                                    out=30, valid_for=(all_logfile
                                    s,primary_role)
....


ORA-17628: Oracle error 19505



Si jamais vous avez ce message d'erreur lors d'un duplicate de base de données avec RMAN 

Ci-dessous j'ai reproduit le problème avec une petite base de données d'essai.


$ rman target sys@test_p auxiliary sys@test_s


Recovery Manager: Release 11.2.0.1.0 - Production on Thu Apr 23 21:36:37 2015
Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

target database Password:
connected to target database: TEST (DBID=2174328171)
auxiliary database Password:

connected to auxiliary database: TEST (not mounted)

RMAN> DUPLICATE TARGET DATABASE FOR STANDBY FROM ACTIVE DATABASE ;
...
...
...
Starting backup at 23-APR-2015 20:14:38
using channel ORA_DISK_1
channel ORA_DISK_1: starting datafile copy
copying standby control file
RMAN-00571: =======================================================
RMAN-00569: =============== ERROR MESSAGE STACK FOLLOWS ===========
RMAN-00571: =======================================================
RMAN-03002: failure of Duplicate Db command at 04/23/2015 20:14:46
RMAN-03015: error occurred in stored script Memory Script
RMAN-03009: failure of backup command on ORA_DISK_1 channel at 04/23/2015 20:14:46
ORA-17628: Oracle error 19505 returned by remote Oracle server



C'est presque sûr que le problème soit relié à un répertoire manquant.

Dans mon cas, j'ai regardé le spfile utilisé pour la base de données auxiliaire -celle à créer- et j'ai pu constater qu'un des répertoires des controlfile n'existait pas. 


$cat initTEST.ora

*.audit_file_dest='/DISK2/oracle/admin/TEST/adump'
*.audit_trail='db'
*.compatible='11.2.0.0.0'
*.control_files='/DISK2/oracle/oradata/TEST/control01.ctl','/DISK2/oracle/flash_recovery_area/TEST/control02.ctl'
*.db_block_size=8192
*.db_domain=''
*.db_flashback_retention_target=1440
*.db_name='TEST'
*.db_recovery_file_dest='/DISK2/oracle/flash_recovery_area'
*.db_recovery_file_dest_size=3145728000
*.db_unique_name='TEST_S'
*.diagnostic_dest='/DISK2/oracle'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=TESTXDB)'
*.log_archive_dest_1='LOCATION=/DISK2/oracle/archives/dest1'
*.log_archive_format='%t_%s_%r.arc'
*.memory_target=606076928
*.open_cursors=300
*.processes=150
*.remote_login_passwordfile='EXCLUSIVE'
*.undo_tablespace='UNDOTBS1'


Une fois ajouté le répertoire vous pouvez relancer le DUPLICATE et tout devrait bien fonctionner.


vendredi 17 avril 2015

Problèmes avec les applets de UCM 10g ou 11g

Bonjour

     Probablement vous avez déjà rencontré ce problème lors les constantes mises à jour de la version de java.
Après la version 7.41 de java la sécurité de java a été  renforcé et logiquement certaines classes java et les applets ne chargent pas s'ils n'ont pas été signés ou ajoutés dans la liste d'exception de java.

Juste pour vous montrer, lorsque une version récente est installé vous allez avoir une écran plus ou moins comme celle ci-dessous.




Lequel quelques secondes après montrera un avertissement comme :





Si jamais vous avez besoin de faire fonctionner les applets de UCM voici une des solutions.

Installez une version précédente à la version 7.41.
Dans mon cas je me suis retrouvé avec un client avec une version de Windows 8.1 de 64 bits. Pour le faire fonctionner il a fallu installer la version java mais celle de 32 bits parce qu'avec celle de 64 bits ne fonctionne pas.




Vous pouvez voir la version installé dans ce cas.



Une fois installé vous pouvez aller sur votre fureteur et relancer la connexion.





Il faut surtout pas mettre à jour le plugin, sinon la dernière version de java sera installée. Cliquez simplement sur "Executer cette fois" et les applets seront maintenant sur place.




Et voilà.








jeudi 16 avril 2015

UTL_FILE - ORA-06512 - ORA-29283


Il y a quelques jour un client m'est revenu avec un problème au moment de créer un fichier avec UTL_FILE, ci-dessous vous pouvez voir le script utilisé pour le test et le message d'erreur obtenu.
Version de Bd, 11.2.0.3 sous Solaris 5.10.


CONNECT COMPTEORACLE@MYBD

set serveroutput on ; 
declare
  fich utl_file.file_type;
begin
  fich := utl_file.fopen('REP_EVTA','monfichier.txt','W',32767);
  utl_file.put_line (fich,'Test');
  utl_file.fclose(fich);
  dbms_output.put_line ('Terminé');
 
exception
  when others then
    dbms_output.put_line ('Erreur : ' || sqlcode);
    dbms_output.put_line (substr(sqlerrm,1,200));
    utl_file.fclose_all;
end;
/

Erreur : -29283
ORA-29283: opération non valide sur le fichier
ORA-06512: à "SYS.UTL_FILE", ligne 536
ORA-29283: opération non valide sur le fichier


En regardant, il faut commencer par valider que l'utilisateur a vraiment les privilèges pour exécuter le UTL_FILE ou qu'au moins ils n'ont pas été révoqués du PUBLIC.

SELECT TABLE_NAME, PRIVILEGE, GRANTEE 
  FROM DBA_TAB_PRIVS 
 WHERE TABLE_NAME ='UTL_FILE' ;

TABLE_NAME       PRIVILEGE                        GRANTEE
---------------  -------------------------------- ----------------
UTL_FILE         EXECUTE                          PUBLIC
 
Jusqu'à ici tout est correct.

En suite, il faut valider que le compte "oracle" a les privilèges sur le répertoire "REP_EVTA"

SELECT TABLE_NAME, PRIVILEGE, GRANTEE 
  FROM DBA_TAB_PRIVS 
 WHERE GRANTEE= 'COMPTEORACLE' AND TABLE_NAME = 'EVTA' ;

TABLE_NAME        PRIVILEGE                 GRANTEE
----------------- ------------------------- --------------
REP_EVTA          EXECUTE                  
COMPTEORACLE 
REP_EVTA          READ                      COMPTEORACLE
REP_EVTA          WRITE                     COMPTEORACLE

Maintenant, validez si le répertoire physique existe et il est bel et bien accessible. Une recherche sur DBA_DIRECTORIES vous permettra de connaître le chemin du répertoire.

SELECT DIRECTORY_PATH 
  FROM DBA_DIRECTORIES 
 WHERE DIRECTORY_NAME='REP_EVTA' ;

DIRECTORY_PATH
--------------------------------------------------------
/chemin/sur/serveur/unix/repertoire


SQL> host ls -l /chemin/sur/serveur/unix/repertoire

-rw-rw-r--  1 2067     sql_group   13824 Oct  7  2014 fichier01.xls
-rw-rw-r--  1 2067    
sql_group   33871 Oct  2  2014 fichier02.csv
...


On voit que le répertoire est accessible et on peut même créer un fichier

SQL> host touch /chemin/sur/serveur/unix/repertoire/myfile.txt

SQL> host ls -l
/chemin/sur/serveur/unix/repertoire/myfile.txt
-rw-r--r-- 1 oracle oinstall 0 Apr 10 14:31
/chemin/.../repertoire/myfile.txt
 
Juste pour m'assurer, j'ai répété le même essai avec le compte "sys" mais sans passer par le Listener, soit directement avec un "sqlplus / as sysdba" et ma création a bien réussi cette fois.

      PL/SQL procedure successfully completed.

Pour vérifier, cette fois j'ai testé une autre fois avec "sys" mais en passant par le Listener, soit avec "sqlplus sys@MYDB as sysdba". Cette fois j'obtiens une autre fois l'erreur.

Erreur : -29283      
ORA-29283: opération non valide sur le fichier      
ORA-06512: à "SYS.UTL_FILE", ligne 536       
ORA-29283: opération non valide sur le fichier


C'est le moment d'aller regarder du côté OS et du "listener"


$ ps -ef | grep lsn | grep MYBD
 
grid 13777  1598 0  Jun 21 ? 190:23 /u01/.../bin/tnslsnr LSN_MYBD -inherit


Je vois qu'il a été reparti par le compte "grid", et cela peut expliquer le problème, pour vérifier, il faudrait regarder la définition du compte "grid"

$ id -a grid

uid=990(grid) gid=996(oinstall) groups=14(sysadmin),990(asmadmin),991(asmdba),992(asmoper),980(sql_group)


Si on remonte un niveau dans le répertoire

$ ls -l /chemin/sur/serveur/unix/

drwxrwx---   2 2067   sql_group   32K Apr 14 14:42 repertoire


Le répertoire appartient au même groupe, mais le "owner" est un compte qui n'existe pas sur le serveur.

$ is -a oracle
uid=991(oracle) gid=996(oinstall) groups=14(sysadmin)....980(sql_group)



Pour le compte "oracle"

$ umask
0022

Pour le compte "grid"

$ umask
0002


  • J'ai vérifié la dernière date où le listener a été reparti et il date d'il y a 3 mois, donc, pour m'assurer je repars le listener afin que le compte "grid" prenne en compte les groupes auquel il a été assigné. je modifié le umask avant de le repartie, mais malgré cela, je relance le test et même erreur.
  • En plus, j'ai pu constater que si je me connecte avec le compte "grid" et repars le listener avec "lsnrctl" et non pas avec "srvctl" -ce qu'on ne devrait pas faire mais qui a servi juste à mes tests-, le script est capable de créer le fichier. 

  • Donc, c'est clair que c'est un problème de privilèges.

À ce point-ci, on a deux possibles solutions :

  • Assigner comme "owner" du répertoire au compte propriétaire du processus "oracle", soit le configurer comme -idée suggérée par un collègue-. Bien sûr avec un chmod 777 au rpertoire avait démontré que cela fonctionnait mais cela serait moins sécurisant.
 drwxrwx---   2 oracle sql_group   32K Apr 14 14:42 repertoire


  • Suivre la note Oracle 1980622.1 qui demande un patch -qui existe seulement pour le moment pour Linux- et en plus de faire une modification au listener configuré auprès du srvctl
srvctl setenv listener -l LSN_MYBD -t ORA_RDBMS_UMASK=022

 Dans mon cas je ne peux pas appliquer ce patch parce que je suis sous Solaris. Donc la première alternative a aidé à corriger le problème.





lundi 6 avril 2015

(Tip) Identifier la version installée de UCM ?


Le "Tip" de la journée...

      Dès que nous avons des nouveaux clients il est important de pouvoir identifier et reconnaître les produits installés, si jamais vous avez un client qui a installé Oracle WebCenter et qui pour une raison inconnue il n'est pas capable de vous dire quelle est la version actuelle installée, vous pouvez faire la vérification par vous même...Bien sûr en ayant au moins les accès.




Ici vous pouvez voir la version installée, même la version de la base de données et la version de java configurée.

En plus, en faisant clic sur "Enabled Component Details" vous pouvez voir la version installée pour chaque composante






FK sans Indexes


Des fois lorsque vous faites des vérifications il est important de vérifier si les FK ont une indexe de renforcement créé afin d'éviter des problèmes de performance, voici un script qui peut vous être utile.

Bien sûr, après cette première vérification il faudrait valider si les colonnes ne font pas partie d'un autre index ou s'il y a d'autres raisons qui pourraient "justifier" un manque d'indexe.

Voici le script :

SELECT QRY.OWNER, QRY.TABLE_NAME, QRY.CONSTRAINT_NAME, QRY.INDEX_NAME, QRY.CONSCOLUMNS, QRY.INDCOLUMNS
  FROM (
    SELECT LIST_CONST.OWNER, LIST_CONST.TABLE_NAME, LIST_CONST.CONSTRAINT_NAME, LIST_IND.INDEX_NAME,
           LIST_CONST.CONSCOLUMNS, LIST_IND.INDCOLUMNS 
     FROM (SELECT BB.OWNER, BB.TABLE_NAME, BB.CONSTRAINT_NAME, 
                  LTRIM(MAX(SYS_CONNECT_BY_PATH(BB.COLUMN_NAME,',')) KEEP (DENSE_RANK LAST ORDER BY curr),',') AS CONSCOLUMNS 
            FROM (SELECT B.OWNER, B.TABLE_NAME, B.CONSTRAINT_NAME, C.COLUMN_NAME, C.POSITION, 
                         ROW_NUMBER() OVER (PARTITION BY B.CONSTRAINT_NAME ORDER BY C.POSITION)   AS CURR, 
                         ROW_NUMBER() OVER (PARTITION BY B.CONSTRAINT_NAME ORDER BY C.POSITION)-1 AS PREV 
                    FROM DBA_CONSTRAINTS B, DBA_CONS_COLUMNS C 
                   WHERE B.OWNER           = C.OWNER            AND 
                         B.CONSTRAINT_NAME = C.CONSTRAINT_NAME  AND 
                         B.CONSTRAINT_TYPE = 'R' 
                 ) BB 
            GROUP BY BB.OWNER, BB.TABLE_NAME, BB.CONSTRAINT_NAME 
            CONNECT BY PREV = PRIOR CURR AND BB.CONSTRAINT_NAME = PRIOR BB.CONSTRAINT_NAME 
            START WITH CURR = 1
           ) LIST_CONST, 
          (SELECT AA.TABLE_OWNER, AA.TABLE_NAME, AA.INDEX_NAME, 
                  LTRIM(MAX(SYS_CONNECT_BY_PATH(AA.COLUMN_NAME,',')) KEEP (DENSE_RANK LAST ORDER BY curr),',') AS INDCOLUMNS 
            FROM (SELECT A.TABLE_OWNER, A.TABLE_NAME, A.INDEX_NAME, A.COLUMN_NAME, A.COLUMN_POSITION, 
                         ROW_NUMBER() OVER (PARTITION BY A.INDEX_NAME ORDER BY A.COLUMN_POSITION)   AS CURR,
                         ROW_NUMBER() OVER (PARTITION BY A.INDEX_NAME ORDER BY A.COLUMN_POSITION)-1 AS PREV
                    FROM DBA_IND_COLUMNS A, DBA_INDEXES AA 
                   WHERE A.INDEX_OWNER = AA.OWNER        AND 
                         A.INDEX_NAME  = AA.INDEX_NAME 
                 ) AA 
            GROUP BY AA.TABLE_OWNER, AA.TABLE_NAME, AA.INDEX_NAME 
            CONNECT BY PREV = PRIOR CURR AND AA.INDEX_NAME = PRIOR AA.INDEX_NAME 
            START WITH CURR = 1 
           ) LIST_IND 
     WHERE LIST_IND.TABLE_OWNER (+)  = LIST_CONST.OWNER         AND 
           LIST_IND.TABLE_NAME  (+)  = LIST_CONST.TABLE_NAME    AND 
           LIST_IND.INDCOLUMNS  (+)  LIKE LIST_CONST.CONSCOLUMNS || '%' 
      ) QRY 
WHERE QRY.INDEX_NAME IS NULL 
ORDER BY QRY.OWNER, QRY.TABLE_NAME ;