DBAFAQ rejoint LAMI-DBA.COM

Afin de simplifier la co-rédaction d’un blog commun avec mon acolyte Laurent (laodba), le blog DBAFAQ fusionne avec le blog LAMI-DBA, pour réunir nos deux cerveaux en un seul et même blog !
DBAFAQ restera bien sur accessible en l’état, et conservera tous les articles, qui seront également repris sur LAMI-DBA.COM au fur et à mesure du temps, et les futurs articles y seront désormais rédigés et publiés.

@ bientot sur LAMI-DBA.COM

Mickael.

Publicités

ORACLE – Détecter et corriger la Corruption de données

Dans tous environnements, qu’ils soient en production ou non, nous ne sommes jamais à l’abri d’avoir des erreurs de corruption de données, qui peuvent impacter le fonctionnement d’une application compte tenu de datas qui pourraient être incohérentes.

Bien sur dans le cas d’indexes corrompus, le problème peut être rapidement résolu via une reconstruction de ce dernier, mais dans le cas d’une table, c’est tout de suite un peu plus compliqué..

Prennons l’exemple d’une erreur identifiée dans l’alert.log de la base :

Errors in file d:\bin\app\diag\rdbms\MYDB\MYDB\trace\MYDB_ora_4572.trc (incident=2859705):
ORA-01578: bloc de données ORACLE altéré (fichier # 5, bloc # 129165)
ORA-01110: fichier de données 5 : 'D:\WRK\ORACLE\ORADATA\MYDB\DATAFILE\O1_MF_DBMASTER_8GCJZHGT_.DBF'
ORA-26040: Le bloc de données a été chargé à l'aide de l'option NOLOGGING

Ici ce qu’il faut bien voir, en dehors du fichier trc, c’est que nous avons un bloc corrompu pour un fichier oracle, et la base n’est pas en archivelog .. ce qui ne laisse que peu d’option pour tenter de résoudre ce problème.

On lance un premier diagnostic avec l’utilitaire maintenant devenu commun « DBVerify » :

$ORACLE_HOME/bin/dbv file=D:\WRK\ORACLE\ORADATA\MYDB\DATAFILE\O1_MF_DBMASTER_8GCJZHGT_.DBF blocksize=8192 logfile=/tmp/dbv.log

Note : La valeur du blocksize est en fonction du paramétrage de l’instance pour ce tablespace (peut être 16k, 32k ..). Je préconise également de générer une log pour étudier le contenu en détail.

Résultat de l’execution de dbverify :

DBVERIFY - Début de vérification : FILE = D:\WRK\ORACLE\ORADATA\MYDB\DATAFILE\O1_MF_DBMASTER_8GCJZHGT_.DBF

DBVERIFY - Vérification terminée

Nbre de pages examinées : 139520
Nbre de pages traitées (Données) : 13144
Nbre de pages en échec (Données) : 0
Nbre de pages traitées (Index) : 6473
Nbre de pages en échec (Index) : 0
Nbre de pages traitées (Autre) : 116390
Nbre de pages traitées (Seg) : 0
Nbre de pages en échec (Seg) : 0
Nbre de pages vides : 3513
Nbre de pages marquées altérées : 169
Nbre de pages Influx : 0
Nbre de pages cryptées : 0
SCN de bloc le plus élevé : 352031051 (0.352031051)

On constate bel et bien une jolie corruption de datas ..

Si l’on identifie la table impactée (ou index), la commande ANALYZE TABLE VALIDATE STRUCTURE peut être pratique, pour identifier les lignes impactées, au travers de la vue INVALID_ROWS. On peut toujours, si l’on ne connait pas la table, générer un petit SQL pour analyser les tables du schéma impacté.

Vous allez me dire, oui mais je ne connais pas le schéma concerné ! Ok, alors voici une astuce simple :

SQL> select distinct owner from dba_tables where tablespace_name = (select tablespace_name from dba_data_files where file_name='&1');
OWNER
-----------------
MYSCHEMA

Nous avons notre schéma impacté par cette corruption, lançons donc un petit sql pour analyser les tables :

SQL> set lines 200
SQL> set pages 0
prompt On creer la vue INVALID_ROWS ..
SQL> @?/rdbms/admin/UTLVALID.SQL
Table crÚÚe.
SQL> spool /tmp/analyze.sql
SQL> select 'analyze table MYSCHEMA.'||table_name||' validate structurecascade;' from dba_tables where owner='MYSCHEMA';
SQL> spoo off
SQL> @/tmp/analyze.sql
Table analysÚe.
Table analysÚe.
Table analysÚe.
Table analysÚe.
...
...
SQL> select * from invalid_rows;
aucune ligne selectionee

Ah je n’ai aucune infos .. ma corruption porterait t’elle sur un autre type d’objet ??

Pour le découvrir, j’utilise notre ami RMAN, en lancant une vérification (VALIDATE) logique de notre fichier de données endomagé :

RMAN> backup validate check logical datafile 5;

ou

RMAN> VALIDATE check logical datafile 'D:\WRK\ORACLE\ORADATA\MYDB\DATAFILE\O1_MF_DBMASTER_8GCJZHGT_.DBF';

ou

RMAN> VALIDATE CHECK LOGICAL TABLESPACE MYTBS;

Cette instruction va lancer un « faux » backup. Autrement dit, il n’y aura pas de fichiers de sauvegarde de générés. Ce faux backup va nous permettre de découvrir les objets liés au bloc(s) oracle endommagés.

Demarrage de backup dans 24/09/15
utilisation du fichier de contr¶le de la base de donnÚes cible au lieu du catal
gue de rÚcupÚration
canal affectÚ : ORA_DISK_1
canal ORA_DISK_1 : SID=30 type d'unitÚ=DISK
canal ORA_DISK_1 : dÚmarrage de l'ensemble de sauvegarde de tous les fichiers d
donnÚes
canal ORA_DISK_1 : insertion du(des) fichier(s) de donnÚes dans l'ensemble de s
uvegarde
fichier de donnÚes en entrÚe, numÚro=00005, nom=D:\WRK\ORACLE\ORADATA\MYDB\DAT
FILE\O1_MF_DBMASTER_8GCJZHGT_.DBF
canal ORA_DISK_1 : ensemble de sauvegarde terminÚ, temps ÚcoulÚ : 00:00:03
Liste des fichiers de donnÚes
=================
File Status Marked Corrupt Empty Blocks Blocks Examined High SCN
---- ------ -------------- ------------ --------------- ----------
5 OK 169 3513 139520 352035662
Nom de fichier : D:\WRK\ORACLE\ORADATA\MYDB\DATAFILE\O1_MF_DBMASTER_8GCJZHGT
.DBF
Block Type Blocks Failing Blocks Processed
---------- -------------- ----------------
Data 0 13144
Index 0 6473
Other 0 116390

Fin de backup dans 24/09/15

plus globalement, si nous voulons scanner toute la base, la commande ci dessous peut être utilisée :

RMAN> BACKUP VALIDATE CHECK LOGICAL DATABASE ARCHIVELOG ALL ;

ou, dans le cas où nous aurions une DB en NOARCHIVELOG (ce qui est mon cas)

RMAN> BACKUP VALIDATE CHECK LOGICAL DATABASE;

 

Reprenons la log RMAN générée après notre exécution de VALIDATE CHECK LOGICAL. On s’aperçoit qu’aucun bloc n’est marqué FAILING. Qu’importe, il faut aller plus loin :

La requète SQL ci dessous permet d’avoir les informations pour identifier qui / quoi est corrompu :

SQL>COLUMN owner FORMAT A20
SQL>COLUMN segment_name FORMAT A30

SQL>SELECT DISTINCT owner, segment_name
FROM v$database_block_corruption dbc
JOIN dba_extents e ON dbc.file# = e.file_id AND dbc.block# BETWEEN e.block_id and e.block_id+e.blocks-1
ORDER BY 1,2;

OWNER SEGMENT_NAME
-------------------- ---------------------------
MYSCHEMA SYS_LOB0000062083C00008$$

Nous avons identifié le segment impacté, un BLOB.

Pour déterminer la table et colonne concernée par ce segment :

SQL> select table_name,column_name from dba_lobs where segment_name='SYS_LOB0000062083C00008$$' and owner='MYSCHEMA';

TABLE_NAME COLUMN_NAME
-------------- ---------------
MYTABLE VALUE

=> Nous avons maintenant isolé précisémment l’impact de la corruption de données.

Pour la résoudre, plusieurs solutions s’offrent à nous.

La méthode universelle, qui fonctionne avec une base en ARCHIVELOG ET NOARCHIVELOG, est de passer par un import de données (à partir d’un dump datant d’avant la corruption bien sur), en ayant au préalable supprimé et créer le Tablespace / fichier de données.

Pour le cas des bases en Archivelog, RMAN peut être utilisé via la notion de blockrecover.

Exemple

RMAN>connect target /
RMAN>BLOCKRECOVER DATAFILE 5 BLOCK 129165;
RMAN>BLOCKRECOVER CORRUPTION LIST RESTORE UNTIL TIME 'SYSDATE - 7';

Ces commandes permettent de récupérer via les sauvegardes RMAN, ainsi que via les archivelogs, le contenu du block endommagé. L’instruction BLOCKRECOVER CORRUPTION LIST RESTORE  permettant quant à elle de restaurer tous les blocs endommagés, qui sont référencés dans la « corruption list » (alimentée après un validate RMAN), le tout en utilisant un UNTIL TIME pour éviter de retrouver la corruption !

DBMS_REPAIR est également une alternative efficace, qui permet d’isoler les données endommagées par la corruption et de fixer les blocs corrompus de telle façon à ce qu’Oracle évite d’avoir à les réutiliser.
Il permet donc ET de détecter la corruption de données, ET de la réparer en « mettant de coté » les blocs endommagés.

Voici un exemple d’utilisation de ce package, qui nescessite l’utilisation de 2 tables spécifiques, l’une pour stocker la liste des blocs corrompus, et la seconde qui stocke les indexes liés à ces blocs (cas de blocs concernant une ou plusieurs tables)

SQL> BEGIN
DBMS_REPAIR.admin_tables (
table_name => 'REPAIR_TABLE',
table_type => DBMS_REPAIR.repair_table,
action => DBMS_REPAIR.create_action,
tablespace => 'SYSAUX');

DBMS_REPAIR.admin_tables (
table_name => 'ORPHAN_KEY_TABLE',
table_type => DBMS_REPAIR.orphan_table,
action => DBMS_REPAIR.create_action,
tablespace => 'SYSAUX');
END;
/

Nous pouvons maintenant vérifier la table impactée via la procédure CHECK_OBJECT :

SQL> SET SERVEROUTPUT ON
SQL> DECLARE
v_num_corrupt INT;
BEGIN
v_num_corrupt := 0;
DBMS_REPAIR.check_object (
schema_name => 'MYSCHEMA',
object_name => 'MYTABLE',
repair_table_name => 'REPAIR_TABLE',
corrupt_count => v_num_corrupt);
DBMS_OUTPUT.put_line('number corrupt: ' || TO_CHAR (v_num_corrupt));
END;
/

number corrupt: 1

-> Ici nous voyons un bloc corrompu de détecté. Nous pouvons donc interroger le contenu des colonnes CORRUPTION_DESCRIPTION et REPAIR_DESCRIPTION de la table REPAIR_TABLE pour en savoir plus sur la corruption identifiée.

Maintenant, nous avons vérifié la corruption, mais les blocs endommagés n’ont pas été fixés. La procédure FIX_CORRUPT_BLOCKS permet de fixer ces blocs, dans l’objectif que ces derniers ne soient pas utilisés par Oracle une fois que la corruption aura été résolue.

SQL> SET SERVEROUTPUT ON
SQL> DECLARE
v_num_fix INT;
BEGIN
v_num_fix := 0;
DBMS_REPAIR.fix_corrupt_blocks (
schema_name => 'MYSCHEMA',
object_name => 'MYTABLE',
object_type => Dbms_Repair.table_object,
repair_table_name => 'REPAIR_TABLE',
fix_count => v_num_fix);
DBMS_OUTPUT.put_line('num fix: ' || TO_CHAR(v_num_fix));
END;
/

num fix: 1

-> Le bloc est « fixé » et ne sera plus utilisé par oracle. Vérifions maintenant l’état des indexes qui pointeraient sur la table impactée, l’objectif étant d’identifier si des indexes doivent être reconstruits ou non :

SQL> declare
v_num_orphans INT;
begin
for myidx in ( select index_name from dba_indexes where owner='MYSCHEMA' and table_name='MYTABLE') LOOP
DBMS_REPAIR.dump_orphan_keys (
schema_name => 'MYSCHEMA',
object_name => myidx.index_name,
object_type => DBMS_REPAIR.index_object,
repair_table_name => 'REPAIR_TABLE',
orphan_table_name => 'ORPHAN_KEY_TABLE',
key_count => v_num_orphans);
DBMS_OUTPUT.put_line('orphan key count: ' || TO_CHAR(v_num_orphans));
end loop;
END;
/
orphan key count: 0

==> Dans ce cas d’exemple, je n’ai pas d’indexes qui sont à rebuilder, mais dans le cas où nous aurions des Orphan Key de détectés, un rebuild des indexes concernés est à réaliser.

Pour revenir au sujet des blocs qui ont été marqués / fixés comme corrompus via la procédure FIX_CORRUPT_BLOCKS, ces derniers sont automatiquement supprimés de la FREELIST, il convient alors de la reconstruire :

SQL> BEGIN
DBMS_REPAIR.rebuild_freelists (
schema_name => 'MYSCHEMA',
object_name => 'MYTABLE',
object_type => DBMS_REPAIR.table_object);
END;
/

Enfin, pour être certain que toutes instructions DML ne touchent pas aux blocs corrompus, la procédure SKIP_CORRUPT_BLOCKS doit être lancée :

SQL> BEGIN
DBMS_REPAIR.skip_corrupt_blocks (
schema_name => 'MYSCHEMA',
object_name => 'MYTABLE',
object_type => DBMS_REPAIR.table_object,
flags => DBMS_REPAIR.skip_flag);
END;
/

Et voila, nous avons vu comment détecter et réparer des erreurs de corruption de données, le tout à chaud sans arrêt de service.

Attention néanmoins car certaines actions peuvent impacter le fonctionnement des applications, je pense notamment à la partie « blockrecover » et à la partie « rebuild indexes », il conviendra donc d’être prudent sur ce type d’opérations 😉

Micka

Oracle Dataguard 11G Part #1 : Mise en place d’un Physical Dataguard

Après quelques temps d’inactivité, j’ai décidé de faire une série d’articles sur la technologie Oracle Dataguard 11G, afin de présenter les principales caractéristiques et la mise en place de ce mode de disponibilité.

Dans ces articles, nous verrons (dans l’ordre) :

Oracle Dataguard 11G Part #1 : Mise en place d’un Physical Dataguard
Oracle Dataguard 11G Part #2 : Comment changer le mode de protection de Dataguard ?
Oracle Dataguard 11G Part #3 : Gestion et supervision : Oracle Dataguard BROKER
Oracle Dataguard 11G Part #4 : Mise en place d’ACTIVE DATAGUARD
Oracle Dataguard 11G Part #5 : Mise en place d’un LOGICAL DATAGUARD
Oracle Dataguard 11G Part #6 : Restauration Rman d’une base Primaire : Les impacts

Bon, mais qu’est ce qu’un environnement DATAGUARD et à quoi cela peut il servir ?

Et bien c’est assez simple en fait. Un environnement Oracle DATAGUARD est un environnement pourvu d’une base de données dite principale (ou primary pour les intimes), et d’une base de secours sur un autre serveur (idéalement un autre datacenter / site) alimentée en temps rêel à partir des archivelogs de la base principale. Le mécanisme est entièrement automatique, y compris sa supervision.

Globalement, dans la plupart des cas de configuration, cette base de données de secours (standby pour les intimes) pourra être activée dès lors où la base de données principale ne sera plus opérationnelle, ou accessible. On nomme cela un PHYSICAL DATAGUARD. Cela permet d’avoir une continuité des opérations, qui seront redigirées vers le serveur et donc la base dite de secours / Standby.
Dans d’autres cas, plus rares de part mon expérience, cette base de données de secours pourra également être utilisée en parallèle de la base de données principale à des fins de tests, de récupération d’informations, de réglages ou autres. On nomme cela un LOGICAL DATAGUARD. Dans cette configuration, et à la différence de l’autre configuration PHYSICAL, cette base de secours est OPEN, alors que dans l’autre mode, elle serait uniquement MOUNTED en mode STANDBY (pour permettre l’application des archivelogs).

Vous l’avez compris, dans tous les cas, nous avons la notion d’archivelogs, lequels permettent d’alimenter la base de secours, qu’elle soit dans un mode PHYSICAL ou LOGICAL. Sans ce mode archivelog, il faut oublier tout mécanisme de disponibilité DATAGUARD, ou encore MANUAL Stanby

Pour la différence entre un environnement de secours DATAGUARD et MANUAL Standby, c’est simple également car d’un coté tout est géré par la mécanique dataguard Oracle (envoi d’archivelogs, application sur la base de secours, supervision via DGMGMRL) et de l’autre tout est à faire manuellement via pack de scripts OS / SQL.

Le petit plus de Dataguard, c’est du temps reel, alors qu’avec une configuration « Manual standby », cela sera lié à la planification qui sera mise en place pour l’envoie des archivelogs et leur application sur la base de secours.

D’un coté, une base de secours sera activée avec la dernière transaction datant d’avant panne / crash, de l’autre la base de secours sera activée avec une dernière transaction datant de la dernière application des archivelogs. Nous ne sommes donc pas, en mode Manual standby, en temps reel.

Evidemment, comme toute fonctionnalité « non défaut », Dataguard nécessite un licensing spécifique. Le fonctionnement DATAGUARD n’est disponible qu’en ENTERPRISE EDITION, et est une option supplémentaire payante.

Bon, passons maintenant à la partie technique. Je vais ici détailler la mise en place d’un PHYSICAL DATAGUARD

Le contexte technique, sur lequel je me base pour démarrer ce tuto, est le suivant :

  • 2 serveurs (VM) Oracle Linux 6 installés et configurés (accès réseau et autres), disposant de 60Go d’espace chacun (à adapter en fonction du contexte d’étude)
  • Moteurs oracle 11GR2 enterprise edition installés sur les deux serveurs
  • Base de données « primaire » UP sur le premier serveur, en mode Archivelog, nommée ici « MICKPRIM »
  • Listener Oracle UP sur les deux serveurs, en configuration statique :

Exemple pour le serveur « primaire » :

SID_LIST_LISTENER =
 (SID_LIST =
 (SID_DESC =
 (ORACLE_HOME = /oracle/product/11.2.0.4)
 (SID_NAME = MICKPRIM)
 ) )
LISTENER =
 (DESCRIPTION =
 (ADDRESS = (PROTOCOL = TCP)(HOST = srvoraprim)(PORT = 1521))
 )
ADR_BASE_LISTENER = /oracle

Exemple pour le serveur « secondaire / secours »

SID_LIST_LISTENER =
 (SID_LIST =
 (SID_DESC =
 (ORACLE_HOME = /oracle/product/11.2.0.4)
 (SID_NAME = MICKSTBY)
 ) )
LISTENER =
 (DESCRIPTION =
 (ADDRESS = (PROTOCOL = TCP)(HOST = srvorastby)(PORT = 1521))
 )
ADR_BASE_LISTENER = /oracle

 

Mais avant de démarrer d’emblée les actions, que représente un PHYSICAL DATAGUARD ?

Un Physical dataguard se base sur une base de données Standby (de secours) dont la structure est identique à la base de données Primary (principale).
Les archivelogs générées par la base primary seront directement appliquées sur la base standby.
Cette solution technique est couramment choisie. Elle permet notamment d’assurer une protection maximale en cas de crash de la base primaire.

Pour construire la base de secours « STANDBY », nous pourrons donc utiliser aisément notre ami RMAN, qui permet de réaliser (depuis la version 9i) un duplicate for standby, et plus particulièrement en 11G un duplicate for standby from active database.

Et oui, en 11g, grosse nouveauté (qui date un peu maintenant..) puisque nous pouvons construire une standby database à partir d’une base de données directement, au lieu d’utiliser un dernier backup rman (versions antérieures).

Je ne parlerais pas des versions 8i sur lesquelles j’ai eu à mettre en place un Physical dataguard dans une vie passée, c’était quelque peu moins efficace et rapide, et demandait pas mal de code et d’actions, mais le principe de fonctionnement et paramétrage reste globalement le même.

Mais avant la création de cette instance STANDBY, il faut préparer le terrain sur la base de données PRIMARY.

Première étape, très importante et obligatoire à toute configuration Standby, on s’assure que la base primary soit bien en force logging (ce qui sous entend de forcer la génération d’archivelog, même s’il y a des objets en Nologging)

SQL> select NAME,LOG_MODE,OPEN_MODE,DATABASE_ROLE,FORCE_LOGGING,DATAGUARD_BROKER,GUARD_STATUS,PROTECTION_MODE from v$database;

NAME LOG_MODE OPEN_MODE DATABASE_ROLE FOR DATAGUAR GUARD_S PROTECTION_MODE
--------- ------------ -------------------- ---------------- --- -------- ------- --------------------
MICKPRIM ARCHIVELOG READ WRITE PRIMARY NO DISABLED NONE MAXIMUM PERFORMANCE

=> Activation du Force Logging :

SQL> shutdown immediate ;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup mount ;
ORACLE instance started.

Total System Global Area 1068937216 bytes
Fixed Size 2260088 bytes
Variable Size 671089544 bytes
Database Buffers 390070272 bytes
Redo Buffers 5517312 bytes
Database mounted.
SQL> alter database force logging ;

Database altered.

SQL> alter database open;

Database altered.

SQL> select NAME,LOG_MODE,OPEN_MODE,DATABASE_ROLE,FORCE_LOGGING,DATAGUARD_BROKER,GUARD_STATUS,PROTECTION_MODE from v$database;

NAME LOG_MODE OPEN_MODE DATABASE_ROLE FOR DATAGUAR GUARD_S PROTECTION_MODE
--------- ------------ -------------------- ---------------- --- -------- ------- --------------------
MICKPRIM ARCHIVELOG READ WRITE PRIMARY YES DISABLED NONE MAXIMUM PERFORMANCE

SQL> select force_logging from v$database;

FORCE_LOGGING
---
YES

Ensuite, on vérifie que la base utilise bien un fichier de mot de passe et que le paramètre « REMOTE_LOGIN_PASSWORDFILE » soit bien à « EXCLUSIVE » :

SQL>show parameter remote_login_passwordfile

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
remote_login_passwordfile string EXCLUSIVE

[oracle@srvoraprim dbs]$ ls -l orapw*
-rw-r-----. 1 oracle dba 1536 Nov 7 10:46 orapwMICKPRIM

On vérifie le db_name et db_unique_name  de notre base :

SQL> sho parameter _name

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_name string MICKPRIM
db_unique_name string MICKPRIM

Dans mon cas, les 2 paramètres sont identiques. Sur la base Standby, le DB_NAME sera le même que la base primaire (ie MICKPRIM), mais la valeur de db_unique_name devra être différente (MICKSTBY).

De plus, la valeur de ce paramètre db_unique_name devra être indiquée dans la configuration dataguard « DG_CONFIG », pour les 2 bases. (cf plus bas où la configuration est indiquée).

On prépare maintenant les alias TNS qui seront utilisés aussi bien par RMAN (pour la mise en place de la database en Standby) que pour la fonctionnalité Dataguard.

Exemple :

MICKPRIM =
(DESCRIPTION =
 (ADDRESS_LIST =
 (ADDRESS = (PROTOCOL = TCP)(HOST = srvoraprim)(PORT = 1521))
 )
 (CONNECT_DATA =
 (SERVICE_NAME = MICKPRIM)(UR=A)
 )
)

MICKSTBY =
(DESCRIPTION =
 (ADDRESS_LIST =
 (ADDRESS = (PROTOCOL = TCP)(HOST = srvorastby)(PORT = 1521))
 )
 (CONNECT_DATA =
 (SERVICE_NAME = MICKSTBY)(UR=A)
 )
)

Bien sur, ce tnsnames devra être en place sur les 2 serveurs.

On vérifie ensuite que le TNSPING fonctionne bien entre les serveurs. Si cela ne passe pas, vérifier votre firewall et le service « iptables » (« service iptables status » à lancer en ROOT)

-> Sur le serveur dit primaire :

[oracle@srvoraprim ~]$ tnsping MICKSTBY

TNS Ping Utility for Linux: Version 11.2.0.4.0 - Production on 07-NOV-2016 14:49:40

Copyright (c) 1997, 2013, Oracle. All rights reserved.

Used parameter files:

Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = srvorastby)(PORT = 1521))) (CONNECT_DATA = (SERVICE_NAME = MICKSTBY)(UR=A)))
OK (30 msec)

-> Sur le serveur secondaire

[oracle@srvorastby ~]$ tnsping MICKPRIM

TNS Ping Utility for Linux: Version 11.2.0.4.0 - Production on 07-NOV-2016 14:49:52

Copyright (c) 1997, 2013, Oracle. All rights reserved.

Used parameter files:

Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = srvoraprim)(PORT = 1521))) (CONNECT_DATA = (SERVICE_NAME = MICKPRIM)(UR=A)))
OK (0 msec)

On passe maintenant à la configuration de Dataguard en lui même, sur l’instance Oracle PRIMAIRE.

Déjà, on sauvegarde le fichier de paramètre actuellement utilisé au cas où, puis on ajoute les paramètres liés à Dataguard qui sont :

LOG_ARCHIVE_CONFIG='DG_CONFIG=(MICKPRIM,MICKSTBY)'
LOG_ARCHIVE_DEST_1='location=/oradata/MICKPRIM/arch valid_for=(all_logfiles,all_roles) db_unique_name=MICKPRIM'
LOG_ARCHIVE_DEST_2='SERVICE=MICKSTBY NOAFFIRM ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=MICKSTBY'
LOG_ARCHIVE_DEST_STATE_2=ENABLE
LOG_ARCHIVE_MAX_PROCESSES=30
FAL_SERVER=MICKSTBY
FAL_CLIENT=MICKPRIM
STANDBY_FILE_MANAGEMENT=AUTO

Les 2 paramètres FAL_SERVER et FAL_CLIENT, configurés sur les 2 instances, serviront à réaliser des switchovers entre les bases (la base primaire devient standby, et vice versa).

Le paramètre STANDBY_FILE_MANAGEMENT quant à lui permet la gestion automatique des fichiers de base de données (datafiles). Autrement dit, si un datafile est crée / ajouté sur la base primaire, il sera automatiquement crée / ajouté sur l’instance standby.

Attention, ce paramètre ne peut être positionné en AUTO que lors d’une configuration DATAGUARD en tant que tel (donc enterprise edition + option..)

En ce qui concerne les 2 paramètres FAL_SERVER & FAL_CLIENT, iI n’est pas obligatoire de les indiquer pour le fonctionnement de dataguard, mais je le préconise cependant, le switchover pouvant s’avérer très utile en production.

Ce qui donne dans mon cas d’exmple:

*.audit_file_dest='/oracle/admin/MICKPRIM/adump'
*.audit_trail='db'
*.compatible='11.2.0.4.0'
*.control_files='/oradata/MICKPRIM/control01.ctl','/oradata/MICKPRIM/control02.ctl'
*.db_block_size=8192
*.db_domain=''
*.db_name='MICKPRIM'
*.diagnostic_dest='/oracle'
*.dispatchers='(PROTOCOL=TCP) (SERVICE=MICKPRIMXDB)'
*.LOG_ARCHIVE_CONFIG='DG_CONFIG=(MICKPRIM,MICKSTBY)'
*.LOG_ARCHIVE_DEST_1='location=/oradata/MICKPRIM/arch valid_for=(all_logfiles,all_roles) db_unique_name=MICKPRIM'
*.LOG_ARCHIVE_DEST_2='SERVICE=MICKSTBY NOAFFIRM ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=MICKSTBY'
*.LOG_ARCHIVE_DEST_STATE_2=ENABLE
*.LOG_ARCHIVE_MAX_PROCESSES=30
*.FAL_SERVER=MICKSTBY
*.FAL_CLIENT=MICKPRIM
*.STANDBY_FILE_MANAGEMENT=AUTO
*.log_archive_format='%t_%s_%r.arc'
*.memory_target=1073741824
*.open_cursors=300
*.processes=150
*.remote_login_passwordfile='EXCLUSIVE'
*.undo_tablespace='UNDOTBS1'

Une fois cette partie de configuration terminée, nous allons passer à la mise en place de la base Standby nommée MICKSTBY, via RMAN.

Pour cela, copier tout d’abord le fichier de mot de passe « orapw » sur le serveur de secours.

[oracle@srvoraprim dbs]$ scp orapwMICKPRIM oracle@srvorastby:/oracle/product/11.2.0.4/dbs/orapwMICKSTBY
orapwMICKSTBY 100% 1536 1.5KB/s 00:00

Se connecter sur le serveur de secours, et creer ensuite un fichier d’initialisation oracle init.ora pour la base standby, contenant uniquement le nom de la base :

[oracle@srvorastby dbs]$ echo "db_name=MICKSTBY" > $ORACLE_HOME/dbs/initMICKSTBY.ora

Par la suite, il est désormais possible de démarrer l’instance oracle avant la duplication RMAN.

=> Notez bien que je vais gérer via RMAN les modifications liées au SPFILE.

[oracle@srvorastby ~]$ rman

Recovery Manager: Release 11.2.0.4.0 - Production on Mon Nov 7 14:52:47 2016

Copyright (c) 1982, 2011, Oracle and/or its affiliates. All rights reserved.

RMAN> connect target sys/oracle@MICKPRIM

connected to target database: MICKPRIM (DBID=2500540110)

RMAN> connect auxiliary sys/oracle@MICKSTBY

connected to auxiliary database (not started)

RMAN> startup clone nomount ;

RMAN>run {

allocate channel c1 device type disk;
allocate auxiliary channel c2 device type disk;
duplicate target database for standby from active database
 SPFILE
 set audit_file_dest='/oracle/admin/MICKSTBY/adump'
 set control_files='/oradata/MICKSTBY/control01.ctl'
 set fal_server='MICKPRIM'
 set fal_client='MICKSTBY'
 set standby_file_management='AUTO'
 set db_file_name_convert='/oradata/MICKPRIM','/oradata/MICKSTBY'
 set log_file_name_convert='/oradata/MICKPRIM','/oradata/MICKSTBY'
 set log_archive_dest_1='location=/oradata/MICKSTBY/arch valid_for=(all_logfiles,all_roles) db_unique_name=MICKSTBY'
 set log_archive_dest_2='service=MICKPRIM valid_for=(online_logfiles,primary_role) db_unique_name=MICKPRIM'
 set log_archive_dest_state_1='enable'
 set log_archive_dest_state_2='defer'
 set db_unique_name='MICKSTBY';
 }
 
using target database control file instead of recovery catalog
allocated channel: c1
channel c1: SID=46 device type=DISK

allocated channel: c2
channel c2: SID=171 device type=DISK

Starting Duplicate Db at 08-NOV-16

contents of Memory Script:
{
 backup as copy reuse
 targetfile '/oracle/product/11.2.0.4/dbs/orapwMICKPRIM' auxiliary format
 '/oracle/product/11.2.0.4/dbs/orapwMICKSTBY' targetfile
 '/oracle/product/11.2.0.4/dbs/spfileMICKPRIM.ora' auxiliary format
 '/oracle/product/11.2.0.4/dbs/spfileMICKSTBY.ora' ;
 sql clone "alter system set spfile= ''/oracle/product/11.2.0.4/dbs/spfileMICKSTBY.ora''";
}
executing Memory Script

Starting backup at 08-NOV-16
Finished backup at 08-NOV-16

sql statement: alter system set spfile= ''/oracle/product/11.2.0.4/dbs/spfileMICKSTBY.ora''

contents of Memory Script:
{
 sql clone "alter system set audit_file_dest =
 ''/oracle/admin/MICKSTBY/adump'' comment=
 '''' scope=spfile";
 sql clone "alter system set control_files =
 ''/oradata/MICKSTBY/control01.ctl'' comment=
 '''' scope=spfile";
 sql clone "alter system set fal_server =
 ''MICKPRIM'' comment=
 '''' scope=spfile";
 sql clone "alter system set fal_client =
 ''MICKSTBY'' comment=
 '''' scope=spfile";
 sql clone "alter system set standby_file_management =
 ''AUTO'' comment=
 '''' scope=spfile";
 sql clone "alter system set db_file_name_convert =
 ''/oradata/MICKPRIM'', ''/oradata/MICKSTBY'' comment=
 '''' scope=spfile";
 sql clone "alter system set log_file_name_convert =
 ''/oradata/MICKPRIM'', ''/oradata/MICKSTBY'' comment=
 '''' scope=spfile";
 sql clone "alter system set log_archive_dest_1 =
 ''location=/oradata/MICKSTBY/arch valid_for=(all_logfiles,all_roles) db_unique_name=MICKSTBY'' comment=
 '''' scope=spfile";
 sql clone "alter system set log_archive_dest_2 =
 ''service=MICKPRIM valid_for=(online_logfiles,primary_role) db_unique_name=MICKPRIM'' comment=
 '''' scope=spfile";
 sql clone "alter system set log_archive_dest_state_1 =
 ''enable'' comment=
 '''' scope=spfile";
 sql clone "alter system set log_archive_dest_state_2 =
 ''defer'' comment=
 '''' scope=spfile";
 sql clone "alter system set db_unique_name =
 ''MICKSTBY'' comment=
 '''' scope=spfile";
 shutdown clone immediate;
 startup clone nomount;
}
executing Memory Script

sql statement: alter system set audit_file_dest = ''/oracle/admin/MICKSTBY/adump'' comment= '''' scope=spfile

sql statement: alter system set control_files = ''/oradata/MICKSTBY/control01.ctl'' comment= '''' scope=spfile

sql statement: alter system set fal_server = ''MICKPRIM'' comment= '''' scope=spfile

sql statement: alter system set fal_client = ''MICKSTBY'' comment= '''' scope=spfile

sql statement: alter system set standby_file_management = ''AUTO'' comment= '''' scope=spfile

sql statement: alter system set db_file_name_convert = ''/oradata/MICKPRIM'', ''/oradata/MICKSTBY'' comment= '''' scope=spfile

sql statement: alter system set log_file_name_convert = ''/oradata/MICKPRIM'', ''/oradata/MICKSTBY'' comment= '''' scope=spfile

sql statement: alter system set log_archive_dest_1 = ''location=/oradata/MICKSTBY/arch valid_for=(all_logfiles,all_roles) db_unique_name=MICKSTBY'' comment= '''' scope=spfile

sql statement: alter system set log_archive_dest_2 = ''service=MICKPRIM valid_for=(online_logfiles,primary_role) db_unique_name=MICKPRIM'' comment= '''' scope=spfile

sql statement: alter system set log_archive_dest_state_1 = ''enable'' comment= '''' scope=spfile

sql statement: alter system set log_archive_dest_state_2 = ''defer'' comment= '''' scope=spfile

sql statement: alter system set db_unique_name = ''MICKSTBY'' comment= '''' scope=spfile

Oracle instance shut down

connected to auxiliary database (not started)
Oracle instance started

Total System Global Area 1068937216 bytes

Fixed Size 2260088 bytes
Variable Size 671089544 bytes
Database Buffers 390070272 bytes
Redo Buffers 5517312 bytes
allocated channel: c2
channel c2: SID=133 device type=DISK

contents of Memory Script:
{
 backup as copy current controlfile for standby auxiliary format '/oradata/MICKSTBY/control01.ctl';
}
executing Memory Script

Starting backup at 08-NOV-16
channel c1: starting datafile copy
copying standby control file
output file name=/oracle/product/11.2.0.4/dbs/snapcf_MICKPRIM.f tag=TAG20161108T172056 RECID=3 STAMP=927393657
channel c1: datafile copy complete, elapsed time: 00:00:03
Finished backup at 08-NOV-16

contents of Memory Script:
{
 sql clone 'alter database mount standby database';
}
executing Memory Script

sql statement: alter database mount standby database

contents of Memory Script:
{
 set newname for tempfile 1 to
 "/oradata/MICKSTBY/temp01.dbf";
 switch clone tempfile all;
 set newname for datafile 1 to
 "/oradata/MICKSTBY/system01.dbf";
 set newname for datafile 2 to
 "/oradata/MICKSTBY/sysaux01.dbf";
 set newname for datafile 3 to
 "/oradata/MICKSTBY/undotbs01.dbf";
 set newname for datafile 4 to
 "/oradata/MICKSTBY/users01.dbf";
 backup as copy reuse
 datafile 1 auxiliary format
 "/oradata/MICKSTBY/system01.dbf" datafile
 2 auxiliary format
 "/oradata/MICKSTBY/sysaux01.dbf" datafile
 3 auxiliary format
 "/oradata/MICKSTBY/undotbs01.dbf" datafile
 4 auxiliary format
 "/oradata/MICKSTBY/users01.dbf" ;
 sql 'alter system archive log current';
}
executing Memory Script

executing command: SET NEWNAME

renamed tempfile 1 to /oradata/MICKSTBY/temp01.dbf in control file

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

Starting backup at 08-NOV-16
channel c1: starting datafile copy
input datafile file number=00001 name=/oradata/MICKPRIM/system01.dbf
output file name=/oradata/MICKSTBY/system01.dbf tag=TAG20161108T172106
channel c1: datafile copy complete, elapsed time: 00:00:55
channel c1: starting datafile copy
input datafile file number=00002 name=/oradata/MICKPRIM/sysaux01.dbf
output file name=/oradata/MICKSTBY/sysaux01.dbf tag=TAG20161108T172106
channel c1: datafile copy complete, elapsed time: 00:00:35
channel c1: starting datafile copy
input datafile file number=00003 name=/oradata/MICKPRIM/undotbs01.dbf
output file name=/oradata/MICKSTBY/undotbs01.dbf tag=TAG20161108T172106
channel c1: datafile copy complete, elapsed time: 00:00:15
channel c1: starting datafile copy
input datafile file number=00004 name=/oradata/MICKPRIM/users01.dbf
output file name=/oradata/MICKSTBY/users01.dbf tag=TAG20161108T172106
channel c1: datafile copy complete, elapsed time: 00:00:01
Finished backup at 08-NOV-16

sql statement: alter system archive log current

contents of Memory Script:
{
 switch clone datafile all;
}
executing Memory Script

datafile 1 switched to datafile copy
input datafile copy RECID=3 STAMP=927393773 file name=/oradata/MICKSTBY/system01.dbf
datafile 2 switched to datafile copy
input datafile copy RECID=4 STAMP=927393773 file name=/oradata/MICKSTBY/sysaux01.dbf
datafile 3 switched to datafile copy
input datafile copy RECID=5 STAMP=927393773 file name=/oradata/MICKSTBY/undotbs01.dbf
datafile 4 switched to datafile copy
input datafile copy RECID=6 STAMP=927393773 file name=/oradata/MICKSTBY/users01.dbf
Finished Duplicate Db at 08-NOV-16
released channel: c1
released channel: c2

Et voila, nous avons notre base de secours en mode STANDBY sur notre serveur. Vérifions donc la configuration de la base pour activer le mode DATAGUARD et de facto la synchronisation automatique via l’application des archivelogs.

Sur le serveur et base PRIMAIRE, on vérifie la base et on récupère le dernier numéro de séquence d’archivelog généré :

SQL> select status,instance_name,database_role from v$database,v$instance;

STATUS INSTANCE_NAME DATABASE_ROLE
------------ ---------------- ----------------
OPEN MICKPRIM PRIMARY

SQL> select max(sequence#) from v$archived_log;

MAX(SEQUENCE#)
--------------
 28

On fait la même vérification sur la standby :

SQL> select status,instance_name,database_role from v$database,v$instance;

STATUS INSTANCE_NAME DATABASE_ROLE
------------ ---------------- ----------------
MOUNTED MICKSTBY PHYSICAL STANDBY

SQL> select max(sequence#) from v$archived_log where applied='YES';

MAX(SEQUENCE#)
--------------
 28

Nous avons donc les 2 bases au même niveau de séquence. Essayons voir si des archivelogs de la base primaire seraient automatiquement appliquées sur la base Standby :

Sur la base primary :

SQL> select status,instance_name,database_role from v$database,v$instance;

STATUS INSTANCE_NAME DATABASE_ROLE
------------ ---------------- ----------------
OPEN MICKPRIM PRIMARY

SQL> alter system switch logfile ;

System altered.

SQL> /

System altered.
SQL> /

System altered.
...
...
...
SQL> /

System altered.

SQL> select max(sequence#) from v$archived_log;

MAX(SEQUENCE#)
--------------
 36

On vérifie directement sur la base Standby, sans aucune autre action, en vérifiant tout d’abord si le transfert des archivelogs c’est bien fait entre les 2 machines :

[oracle@srvorastby arch]$ ls -ltr /oradata/MICKSTBY/arch
total 112708

-rw-r-----. 1 oracle dba 169984 Nov 28 09:44 1_34_928484905.arc
-rw-r-----. 1 oracle dba 22016 Nov 28 09:44 1_35_928484905.arc
-rw-r-----. 1 oracle dba 28672 Nov 28 09:44 1_33_928484905.arc
-rw-r-----. 1 oracle dba 6958592 Nov 28 09:44 1_29_928484905.arc
-rw-r-----. 1 oracle dba 6540800 Nov 28 09:44 1_30_928484905.arc
-rw-r-----. 1 oracle dba 19219968 Nov 28 09:44 1_32_928484905.arc
-rw-r-----. 1 oracle dba 41263616 Nov 28 09:44 1_31_928484905.arc
-rw-r-----. 1 oracle dba 19968 Nov 28 09:44 1_36_928484905.arc
-rw-r-----. 1 oracle dba 52429312 Nov 28 09:48 1_37_928484905.arc

Nous avons bien nos archives, de la séquence 29 à 37, qui ont été transférées automatiquement. Vérifions maintenant l’application coté base :

[oracle@srvorastby arch]$ sqlplus / as sysdba

SQL*Plus: Release 11.2.0.4.0 Production on Tue Nov 8 17:45:14 2016

Copyright (c) 1982, 2013, Oracle. All rights reserved.

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options

SQL> select max(sequence#) from v$archived_log where applied='YES';

MAX(SEQUENCE#)
--------------
 28

=> Les archivelogs n’ont pas été appliquées à la base standby, ce qui est normal puisque nous n’avons pas activé l’application automatique des archivelogs. Qu’à cela ne tienne, j’active la synchronisation automatique :

SQL> alter database recover managed standby database disconnect from session;

Database altered.

SQL> select process,status,sequence# from v$managed_standby;

PROCESS STATUS SEQUENCE#
--------- ------------ ----------
RFS IDLE 0
RFS IDLE 0
RFS IDLE 39

PROCESS STATUS SEQUENCE#
--------- ------------ ----------
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
MRP0 APPLYING_LOG 30

Dans le contrôle ci dessus, que j’ai lancé directement après la commande de synchronisation, nous identifions deux processus importants pour le fonctionnement de Dataguard :
-> Le process RFS (remote file server) qui est en attente de la séquence 39 (Last séquence de la base primaire),

Dans sa définition la plus globale, le processus RFS récupère les informations des modifications qui ont eu lieu sur la base primaire (en interrogeant le processus LGWR), et les appliquent automatiquement en déclenchant le processus MRP dans les Standby redologs files.

-> Le process MRP (Managed Recovery Process) qui, quand à lui, est en charge de l’application des archivelogs reçues dans les STANDBY REDOLOGS FILES.

Qu’est ce dont ces standby redologs files ? Simple, ce sont des redologs similaires à des redologs normaux (Online Redo Log), sauf qu’ils sont utilisés uniquement pour enregistrer des données depuis une base distante.

Vérifions après quelques instant la base stanbdby,  qui a du appliquer toutes les archivelogs reçues de la base PRIMARY :

SQL> select max(sequence#) from v$archived_log where applied='YES';

MAX(SEQUENCE#)
--------------
 38

SQL> select process,status,sequence# from v$managed_standby;

PROCESS STATUS SEQUENCE#
--------- ------------ ----------
ARCH CONNECTED 0
ARCH CONNECTED 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 39
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
RFS IDLE 0
MRP0 WAIT_FOR_LOG 39

SQL> select DEST_NAME,RECOVERY_MODE,DATABASE_MODE,TYPE,STATUS,DESTINATION from v$archive_dest_status ;

DEST_NAME RECOVERY_MODE DATABASE_MODE STATUS DESTINATION
------------------------- ----------------------------------- --------------- --------- ------------------------------
LOG_ARCHIVE_DEST_1 MANAGED MOUNTED-STANDBY VALID /oradata/MICKSTBY/arch
LOG_ARCHIVE_DEST_2 IDLE UNKNOWN DEFERRED WITTPRDH

-> Les archivelogs ont bien été appliquées automatiquement et continueront à l’être, nous voyons bien que la base Standby est en « MANAGED » (ie : application des archives automatiquement gérée) !

Bon, nous avons bien toutes les archivelogs appliquées, et notre process MRP en waiting, preuve que la base STANDBY est en mode de d’application automatique des archivelogs dans les standby redologs files.

Et voilà, nous avons monté un mécanisme de Dataguard Physical, mis en place la synchronisation automatique, et vérifié que tout ce petit monde s’accorde correctement.

Mais qu’en est il si nous modifions le mode de protection de Dataguard ? Si nous passions en Maximum PROTECTION ou AVAILABILITY ?

Cela tombe bien, nous allons voir cela très prochainement dans le second article « Oracle Dataguard 11G Part #2 : Comment changer le mode de protection de Dataguard  »

Enjoy !

Micka

How to : Oracle ASM & Multipath : Ajout d’un disque SAN à un diskgroup sur Unix

Pour compléter l’article « How to : Oracle ASM – Ajout d’un disque SAN à un diskgroup sur Windows » , voici son homologue pour les environnements Unix. Ici, la méthode finale sous ASM reste quasi identique, il s’agit donc ici de d’indiquer comment repérer les devices MPATH pour les ajouter sous ASM.

En synthèse des opérations, on s’assure que le nouveau disque SAN soit bien visible depuis multiplath. Ensuite, une fois que le bon disque a été identifié parmi la liste ci dessus, on peut passer à la création des partitions.

Petit moyen simple, pour savoir si les disques « MPATH » sont utilisés ou non, on peut (si on est en gestion disques LVM) lancer la commande suivante :

pvdisplay |grep mpath

Cela permet d’isoler par déduction le disque SAN qui n’est pas encore utilisé par ORACLEASM.

Exemple de cas : J’ai déjà 2 disques SAN rattachés à mon serveur, et on m’en a ajouté un autre dont j’ignore la taille :

[root@SRV1 ~]# multipath -ll
mpathe (36005076802818c85780000000000004d) dm-2 IBM,2145
size=60G features='1 queue_if_no_path' hwhandler='0' wp=rw
|-+- policy='round-robin 0' prio=50 status=active
| |- 0:0:3:0 sdd 8:48 active ready running
| |- 1:0:1:0 sdn 8:208 active ready running
| |- 0:0:1:0 sdb 8:16 active ready running
| `- 1:0:2:0 sdt 65:48 active ready running
`-+- policy='round-robin 0' prio=10 status=enabled
 |- 0:0:2:0 sdc 8:32 active ready running
 |- 1:0:0:0 sdm 8:192 active ready running
 |- 0:0:0:0 sda 8:0 active ready running
 `- 1:0:3:0 sdu 65:64 active ready running
mpathg (3600507640081009790000000000000fd) dm-4 IBM,2145
size=100G features='0' hwhandler='0' wp=rw
|-+- policy='round-robin 0' prio=50 status=active
| |- 0:0:4:1 sdf 8:80 active ready running
| |- 1:0:4:1 sdw 65:96 active ready running
| |- 0:0:5:1 sdh 8:112 active ready running
| `- 1:0:5:1 sdy 65:128 active ready running
`-+- policy='round-robin 0' prio=10 status=enabled
 |- 0:0:7:1 sdl 8:176 active ready running
 |- 1:0:6:1 sdaa 65:160 active ready running
 |- 0:0:6:1 sdj 8:144 active ready running
 `- 1:0:7:1 sdac 65:192 active ready running
mpathf (3600507640081009790000000000000a0) dm-3 IBM,2145
size=200G features='1 queue_if_no_path' hwhandler='0' wp=rw
|-+- policy='round-robin 0' prio=50 status=active
| |- 0:0:4:0 sde 8:64 active ready running
| |- 1:0:4:0 sdv 65:80 active ready running
| |- 0:0:5:0 sdg 8:96 active ready running
| `- 1:0:5:0 sdx 65:112 active ready running
`-+- policy='round-robin 0' prio=10 status=enabled
 |- 0:0:6:0 sdi 8:128 active ready running
 |- 1:0:6:0 sdz 65:144 active ready running
 |- 0:0:7:0 sdk 8:160 active ready running
 `- 1:0:7:0 sdab 65:176 active ready running

Dans cette liste de 3 disques SAN, il me faut donc découvrir lequel n’est pas encore utilisé :

[root@SRV1 ~]# pvdisplay |grep mpathf
 PV Name /dev/mapper/mpathfp1
[root@SRV1 ~]# pvdisplay |grep mpathe
 PV Name /dev/mapper/mpathe
[root@SRV1 ~]# pvdisplay |grep mpathg
[root@SRV1 ~]#
[root@SRV1 ~]#

Hop j’ai un candidat, le MPATHG car les autres semblent dispose de partitions, et sont alloués à des VG :

[root@SRV1 ~]# pvdisplay |grep mpath
 PV Name /dev/mapper/mpathfp1
 PV Name /dev/mapper/mpathe
[root@SRV1 ~]# pvdisplay /dev/mapper/mpathfp1
 --- Physical volume ---
 PV Name /dev/mapper/mpathfp1
 VG Name datavg-san
 PV Size 200,00 GiB / not usable 1,34 MiB
 Allocatable yes
 PE Size 4,00 MiB
 Total PE 51199
 Free PE 15103
 Allocated PE 36096
 PV UUID 8k1Cgo-sf4E-tttd-ubFs-lvSJ-KukX-fdZdUR

[root@SRV1 ~]# pvdisplay /dev/mapper/mpathe
 --- Physical volume ---
 PV Name /dev/mapper/mpathe
 VG Name oraexport
 PV Size 60,00 GiB / not usable 4,00 MiB
 Allocatable yes
 PE Size 4,00 MiB
 Total PE 15359
 Free PE 511
 Allocated PE 14848
 PV UUID AGzG9E-Ew3P-oDmq-LSLr-rKbI-2ZCz-JzkYdO

Je suis donc sur que le device MPATHG est LE disque à prendre. Je créée donc mon disque ASM avec OracleASM, en vue de l’ajouter à mon groupe ASM existant :

[root@SRV1 ~]# oracleasm listdisks
VOL1
VOL2
[root@SRV1 ~]# oracleasm createdisk VOL3 /dev/mapper/mpathg
Writing disk header: done
Instantiating disk: done
[root@SRV1 ~]# oracleasm listdisks
VOL1
VOL2
VOL3

Mon disque étant ajouté et formaté ASM, je peux maintenant passer coté Oracle pour augmenter l’espace disque de mon groupe asm « DATA »

J’identifie déjà si mon disque ajouté est bien candidat « PROVISIONED » à être ajouté au groupe DATA :

SQL> col path for a40
SQL> set lines 200
SQL> SELECT MOUNT_STATUS,HEADER_STATUS,MODE_STATUS,STATE,TOTAL_MB,FREE_MB,NAME,PATH,LABEL FROM V$ASM_DISK;

MOUNT_S HEADER_STATU MODE_ST STATE TOTAL_MB FREE_MB NAME PATH LABEL
------- ------------ ------- -------- ---------- ---------- ------------------------------ ---------------------------------------- -------------------------------
CLOSED PROVISIONED ONLINE NORMAL 0 0 ORCL:VOL3 VOL3
CACHED MEMBER ONLINE NORMAL 139486 27206 VOL1 ORCL:VOL1 VOL1
CACHED MEMBER ONLINE NORMAL 139486 27216 VOL2 ORCL:VOL2 VOL2

C’est donc bien le cas, mon VOL3 est visible et prêt a être utilisé. Voyons également la notion de rebalance, car quand je vais ajouter mon disque il va y avoir une auto répartition des datas réalisés par ASM, et en fonction de la taille du disque ajouté il convient de faire quelques réglages, pour éviter que ca prenne un temps fou.

SQL> sho parameter asm_power_limit

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
asm_power_limit integer 1

La configuration est DEFAULT, ie les opérations ne vont pas « trop » solliciter les ressources machines / SAN (CPU / IO) pour ne pas impacter les performances, dans le cas où par exemple cette opération serait lancée en pleine journée.

Je le passe cependant à 4 pour que le REBALANCE soit plus rapide, la machine étant critique et le moindre risque est à éviter ..

SQL> alter diskgroup DATA add disk 'ORCL:VOL3' rebalance power 4;
alter diskgroup DATA add disk 'ORCL:VOL3' rebalance power 4;
*
ERROR at line 1:
ORA-15032: not all alterations performed
ORA-15038: disk '' mismatch on 'Sector Size' with target disk group [512] [4096]

Ah dommage … Le problème vient que la taille des secteurs de ma partition MPATHG est en 512 bytes au lieu de 4096. Dans cette situation je ne peux pas ajouter de disque de la sorte à mon diskgroup qui lui a été créée sur une base de taille de secteur de 4k.

[]<>/root[]:fdisk -l /dev/mapper/mpathg |grep "Sector"
Sector size (logical/physical): 512 bytes / 512 bytes

Il s’agit ici d’une particularité liée à la baie SAN, qui ne permet pas de forcer la taille de secteur.

Ne pouvant supprimer le groupe DATA pour le refaire avec le nouveau disque, je dois passer par la création d’un second diskgroup, qui servira pour les nouvelles databases. Attention, il ne sera pas possible d’agrandir (par exemple) un tablespace existant (sur le groupe de disque avec un sector size à 4096) sur ce nouveau groupe de disque. il faut en effet que la sector Size soit la même.

SQL> create diskgroup DATA2 external redundancy disk 'ORCL:VOL3' ;

Diskgroup created.


SQL> SELECT MOUNT_STATUS,HEADER_STATUS,MODE_STATUS,STATE,TOTAL_MB,FREE_MB,NAME,PATH,LABEL FROM V$ASM_DISK;

MOUNT_S HEADER_STATU MODE_ST STATE TOTAL_MB FREE_MB NAME PATH LABEL
------- ------------ ------- -------- ---------- ---------- ------------------------------ ---------------------------------------- -------------------------------
CACHED MEMBER ONLINE NORMAL 139486 30029 VOL1 ORCL:VOL1 VOL1
CACHED MEMBER ONLINE NORMAL 139486 30030 VOL2 ORCL:VOL2 VOL2
CACHED MEMBER ONLINE NORMAL 102400 102350 VOL3 ORCL:VOL3 VOL3


SQL> select NAME,SECTOR_SIZE,BLOCK_SIZE,ALLOCATION_UNIT_SIZE,STATE,TOTAL_MB,FREE_MB ,DATABASE_COMPATIBILITY,COMPATIBILITY from v$asm_diskgroup;

NAME SECTOR_SIZE BLOCK_SIZE ALLOCATION_UNIT_SIZE STATE TOTAL_MB FREE_MB DATABASE_C COMPATIBILITY
------------------------------ ----------- ---------- -------------------- ----------- ---------- ---------- ---------- ------------------------------------------------------------
DATA 4096 4096 1048576 MOUNTED 278972 59894 10.2.0.0.0 11.2.0.0.0
DATA2 512 4096 1048576 MOUNTED 102400 102350 10.1.0.0.0 10.1.0.0.0

Mais l’objectif est atteint, celui de voir comment intégrer un disque SAN géré par multipath à ASM 😉

Tips : Oracle RAC 11GR2 : DELETE NODE

Dans cet article nous allons voir comment retirer un NOEUD d’un Cluster Oracle RAC en release 11GR2.

Dans mon contexte technique, je suis sur un cluster Oracle à 2 Nodes, en Oracle linux 6, avec un node KO suite à un problème Hardware. Je vais donc retirer le node en question, en vue de le réintégrer par la suite une fois le problème corrigé.

Première étape, vérifier les serveurs qui sont connectés au RAC, et l’état du Cluster :

[]<>/root[]:/oracle/product/11.2.0/grid/bin/olsnodes -t
rac1 Pinned
rac2 Unpinned

[]<>/root[]:/oracle/product/11.2.0/grid/bin/crsctl status res -t

--------------------------------------------------------------------------------
NAME TARGET STATE SERVER STATE_DETAILS Local Resources
--------------------------------------------------------------------------------
ora.DATADG.dg ONLINE ONLINE rac1
ora.LISTENER.lsnr ONLINE ONLINE rac1
ora.OCR.dg ONLINE ONLINE rac1
ora.asm ONLINE ONLINE rac1 Started
ora.gsd OFFLINE OFFLINE rac1
ora.net1.network ONLINE ONLINE rac1
ora.ons ONLINE ONLINE rac1
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.LISTENER_SCAN1.lsnr 1 ONLINE ONLINE rac1
ora.LISTENER_SCAN2.lsnr 1 ONLINE ONLINE rac1
ora.LISTENER_SCAN3.lsnr 1 ONLINE ONLINE rac1
ora.cvu 1 ONLINE ONLINE rac1
ora.oc4j 1 ONLINE ONLINE rac1
ora.rac1.vip 1 ONLINE ONLINE rac1
ora.rac2.vip 1 ONLINE INTERMEDIATE rac1 FAILED OVER
ora.scan1.vip 1 ONLINE ONLINE rac1
ora.scan2.vip 1 ONLINE ONLINE rac1
ora.scan3.vip 1 ONLINE ONLINE rac1

Dans cet exemple, le second node est DOWN, les ressources cluster sont donc basculées sur le noeud principal nommé dans cet exemple « RAC1 ».

Note : Le serveur RAC2 n’étant pas connecté au cluster (Unpinned), il n’est pas nécessaire de lancer la commande « unpin », mais si cela avait été le cas (RAC2 en « Pinned« ), il aurait fallu faire :

[]<>/root[]:/oracle/product/11.2.0/grid/bin/crsctl unpin css -n rac2

On passe donc directement par la suppression du NODE RAC2 :

[]<>/root[]:/oracle/product/11.2.0/grid/bin/crsctl delete node -n rac2
 CRS-4661: Node rac2 successfully deleted.

On met à jour ensuite l’inventaire sur le noeud qui reste disponible (RAC1), cette fois avec le compte unix qui a installé le GRID (dans mon cas « oracle ») :

[rac1]<oracle>/home/oracle[+ASM1]:cd $GRID_HOME/
[rac1]<oracle>/oracle/product/11.2.0/grid[+ASM1]:cd oui/bin
[rac1]<oracle>/oracle/product/11.2.0/grid/oui/bin[+ASM1]:./runInstaller 
-updateNodeList ORACLE_HOME=$ORACLE_HOME "CLUSTER_NODES={rac1}" 
CRS=TRUE -local

 Starting Oracle Universal Installer...

Checking swap space: must be greater than 500 MB. Actual 15999 MB Passed
 The inventory pointer is located at /etc/oraInst.loc
 The inventory is located at /oracle/oraInventory
 'UpdateNodeList' was successful.

Une petite vérification :

[rac1]<oracle>/oracle/product/11.2.0/grid/oui/bin[+ASM1]:cluvfy stage -post 
nodedel -n rac2 -verbose

Performing post-checks for node removal

Checking CRS integrity...

Clusterware version consistency passed
 The Oracle Clusterware is healthy on node "rac1"

CRS integrity check passed
 Result:
 Node removal check passed

Post-check for node removal was successful.

Et enfin l’état des ressources cluster :

[rac1]<oracle>/oracle/product/11.2.0/grid/oui/bin[+ASM1]:crsctl stat res -t
 --------------------------------------------------------------------------------
 NAME TARGET STATE SERVER STATE_DETAILS
 --------------------------------------------------------------------------------
 Local Resources
 --------------------------------------------------------------------------------
 ora.DATADG.dg
 ONLINE ONLINE rac1
 ora.LISTENER.lsnr
 ONLINE ONLINE rac1
 ora.OCR.dg
 ONLINE ONLINE rac1
 ora.asm
 ONLINE ONLINE rac1 Started
 ora.gsd
 OFFLINE OFFLINE rac1
 ora.net1.network
 ONLINE ONLINE rac1
 ora.ons
 ONLINE ONLINE rac1
 --------------------------------------------------------------------------------
 Cluster Resources
 --------------------------------------------------------------------------------
 ora.LISTENER_SCAN1.lsnr
 1 ONLINE ONLINE rac1
 ora.LISTENER_SCAN2.lsnr
 1 ONLINE ONLINE rac1
 ora.LISTENER_SCAN3.lsnr
 1 ONLINE ONLINE rac1
 ora.cvu
 1 ONLINE ONLINE rac1
 ora.oc4j
 1 ONLINE ONLINE rac1
 ora.rac1.vip
 1 ONLINE ONLINE rac1
 ora.rac2.vip
 1 ONLINE INTERMEDIATE rac1 FAILED OVER
 ora.scan1.vip
 1 ONLINE ONLINE rac1
 ora.scan2.vip
 1 ONLINE ONLINE rac1
 ora.scan3.vip
 1 ONLINE ONLINE rac1

=> Il me reste la VIP du second node, je dois donc la supprimer :

[]<>/root[]:/oracle/product/11.2.0/grid/bin/crsctl delete resource ora.rac2.vip -f
[]<>/root[]:/oracle/product/11.2.0/grid/bin/crsctl stat res -t
 --------------------------------------------------------------------------------
 NAME TARGET STATE SERVER STATE_DETAILS
 --------------------------------------------------------------------------------
 Local Resources
 --------------------------------------------------------------------------------
 ora.DATADG.dg
 ONLINE ONLINE rac1
 ora.LISTENER.lsnr
 ONLINE ONLINE rac1
 ora.OCR.dg
 ONLINE ONLINE rac1
 ora.asm
 ONLINE ONLINE rac1 Started
 ora.gsd
 OFFLINE OFFLINE rac1
 ora.net1.network
 ONLINE ONLINE rac1
 ora.ons
 ONLINE ONLINE rac1
 --------------------------------------------------------------------------------
 Cluster Resources
 --------------------------------------------------------------------------------
 ora.LISTENER_SCAN1.lsnr
 1 ONLINE ONLINE rac1
 ora.LISTENER_SCAN2.lsnr
 1 ONLINE ONLINE rac1
 ora.LISTENER_SCAN3.lsnr
 1 ONLINE ONLINE rac1
 ora.cvu
 1 ONLINE ONLINE rac1
 ora.oc4j
 1 ONLINE ONLINE rac1
 ora.rac1.vip
 1 ONLINE ONLINE rac1
 ora.scan1.vip
 1 ONLINE ONLINE rac1
 ora.scan2.vip
 1 ONLINE ONLINE rac1
 ora.scan3.vip
 1 ONLINE ONLINE rac1

Le tour est joué, il ne reste maintenant qu’à ajouter le second node au Cluster une fois qu’il sera de nouveau UP, ce qui fera l’objet d’un futur article 😉

Micka

How To : Installation / déploiement d’un agent OEM 12c en SILENT MODE sur LINUX

Il peut arriver certaines fois qu’il soit nécessaire d’installer un agent OEM (Enterprise Manager) en mode silencieux, c’est à dire en ne passant pas par l’interface web du grid control, mais en le déployant depuis le serveur où il doit être installé.

Voyons cependant brièvement comment déployer un agent 12c depuis le Grid Control OEM, afin de permettre de comparer les deux méthodes.

Tout d’abord, le serveur, sur lequel l’agent sera déployé, doit respecter un certain nombre de prérequis.

Sur Linux, il faut en effet veiller à paramétrer correctement les autorisations de type sudo, compléter le fichier host (également sur le serveur OMS d’ailleurs) et disposer d’un emplacement dédié sur lequel l’agent pourra être déployé (un Filesystem de préférence)

Cf DOC pour davantage d’informations sur ces prérequis.

Attention : il est conseillé d’utiliser le FQDN (Fully Qualified Domain Name) des serveurs plutôt que le nom court.

Dans mon contexte, tous mes prérequis sont respectés, je passe directement sur la méthode pour déployer l’agent.

Sur la page d’accueil du grid control, aller sur

-> SETUP en haut à droite

-> cliquer sur ADD TARGET

-> cliquer ADD TARGETS MANUALY.

1

Note : Le mode « auto discovery result » ne peut être utilisé qu’une fois que l’agent ait été déployé, pour faciliter l’ajout des « targets » secondaires (bases / listener et autres)

=> Laisser le mode « Add Hosts Targets » de sélectionné, puis cliquer sur ADD HOST.

2

Cliquer ensuite sur ADD et indiquer les informations du serveur client (dans mon cas SRVCLNT.mydomain.com) puis cliquer sur NEXT.

3

4

Renseigner les informations liées au déploiement de l’agent : emplacement , port d’écoute et les CREDENTIALS pour que l’OMS puisse s’y connecter. Cliquer ensuite sur NEXT.

5

Une page de récapitulatif et de confirmation apparaît. Une fois les informations contrôlées, cliquer sur DEPLOY pour lancer la procédure de déploiement.

67

Il reste maintenant à patienter que le déploiement soit terminé

Passons maintenant à la seconde méthode, plus technique quant à elle, pour déployer l’agent en mode silencieux.

La première chose à faire est de se connecter à notre serveur OMS avec le user système qui gère l’OMS (dans mon cas le user est « oracle »), et de lancer l’utilitaire de gestion EMCLI, alternative non graphique à l’interface web du grid control.

Note : il faut disposer du password du compte SYSMAN.

[root@SRVOMS1.mydomain.com ~]# su - oracle
[oracle@SRVOMS1.mydomain.com ~]$ cat .envoms
export ORACLE_HOME=/oracle/oms/em/oms
export PATH=$ORACLE_HOME/bin:$PATH
set -o vi

[oracle@SRVOMS1.mydomain.com ~]$ . .envoms
[oracle@SRVOMS1.mydomain.com ~]$
[oracle@SRVOMS1.mydomain.com ~]$ emcli login -username=sysman
Enter password :

Login successful
[oracle@SRVOMS1.mydomain.com ~]$ emcli sync
Synchronized successfully

Il faut ensuite interroger la liste des agents que peut gérer l’OMS, à savoir que s’il manque un agent il peut être installé via les méthodes conventionnelles (via « self update » du grid control) .

[oracle@SRVOMS1.mydomain.com ~]$ emcli get_supported_platforms
-----------------------------------------------
Version = 12.1.0.5.0
Platform = Microsoft Windows x64 (64-bit)
-----------------------------------------------
Version = 12.1.0.5.0
Platform = Linux x86-64
-----------------------------------------------
Platforms list displayed successfully.

Dans mon cas, je souhaite déployer un agent Linux 64Bit, je vais donc faire générer un ZIP de l’agent Linux via la commande ci dessous :

[oracle@SRVOMS1.mydomain.com ~]$ emcli get_agentimage -destination=/oracle/soft_library/agent -platform="Linux x86-64" -version="12.1.0.5.0"
=== Partition Detail ===
Space free : 8 GB
Space required : 1 GB
Check the logs at /home/oracle/.emcli/get_agentimage_2017-01-17_15-41-51-PM.log
Downloading /oracle/soft_library/agent/12.1.0.5.0_AgentCore_226.zip
File saved as /oracle/soft_library/agent/12.1.0.5.0_AgentCore_226.zip
Downloading /oracle/soft_library/agent/12.1.0.5.0_PluginsOneoffs_226.zip
File saved as /oracle/soft_library/agent/12.1.0.5.0_PluginsOneoffs_226.zip
Downloading /oracle/soft_library/agent/unzip
File saved as /oracle/soft_library/agent/unzip
Agent Image Download completed successfully.

Ce ZIP peut maintenant être copié directement sur le serveur cible, où l’agent doit y être installé :

[oracle@SRVOMS1.mydomain.com agent]$ ls -ltr
total 251080
-rw-r--r-- 1 oracle dba 257102519 17 janv. 15:43 12.1.0.5.0_AgentCore_226.zip
[oracle@SRVOMS1.mydomain.com agent]$ scp 12.1.0.5.0_AgentCore_226.zip SRVCLNT.mydomain.com:/home/oracle/.
The authenticity of host 'SRVCLNT.mydomain.com (192.168.1.10)' can't be established.
RSA key fingerprint is dc:88:a3:b0:09:38:71:0a:04:78:22:e7:ce:81:c4:5d.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'SRVCLNT.mydomain.com,192.168.1.10' (RSA) to the list of known hosts.
oracle@SRVCLNT.mydomain.com's password:
12.1.0.5.0_AgentCore_226.zip 100% 245MB 4.6MB/s 00:53

On se connecte maintenant sur le serveur cible (« SRVCLNT.mydomain.com« ) pour passer à l’étape de configuration de l’installation, en décompressant tout d’abord l’archive qui a été envoyée précédemment.

[SRVCLNT.mydomain.com]<oracle>:cd /home/oracle
[SRVCLNT.mydomain.com]<oracle>:unzip 12.1.0.5.0_AgentCore_226.zip
Archive: 12.1.0.5.0_AgentCore_226.zip
inflating: unzip
inflating: agentDeploy.sh
inflating: agentimage.properties
inflating: agent.rsp
extracting: agentcoreimage.zip
extracting: 12.1.0.5.0_PluginsOneoffs_226.zip

Il faut ensuite configurer le fichier de « réponse » AGENT.RSP en fonction du contexte technique (Nom du serveur OMS, port et autres informations)

La partie à modifier étant :

#OMS_HOST=<Value Unspecified>
#EM_UPLOAD_PORT=<Value Unspecified>
#AGENT_REGISTRATION_PASSWORD=<Value Unspecified>
#AGENT_INSTANCE_HOME=<Value Unspecified>
#AGENT_PORT=<Value Unspecified>
b_startAgent=true
#ORACLE_HOSTNAME=<Value Unspecified>

Qui devient (dans mon cas) :

OMS_HOST=SRVOMS1.mydomain.com
EM_UPLOAD_PORT=4889
AGENT_REGISTRATION_PASSWORD=xxxxxxxxx
AGENT_INSTANCE_HOME=/agent12c/agt
AGENT_PORT=3872
b_startAgent=true
ORACLE_HOSTNAME=SRVCLNT.mydomain.com

Une fois ce fichier complété, il suffit maintenant de lancer l’installation.

Note : Veillez à remplacer le répertoire /home/oracle par votre répertoire où a été dézippé l’agent 

[SRVCLNT.mydomain.com]<oracle>:cd /home/oracle
[SRVCLNT.mydomain.com]<oracle>:./agentDeploy.sh AGENT_BASE_DIR=/agent12c/agt RESPONSE_FILE=/home/oracle/agent.rsp
Validating the OMS_HOST & EM_UPLOAD_PORT
Executing command : /agent12c/agt/core/12.1.0.5.0/jdk/bin/java -classpath /agent12c/agt/core/12.1.0.5.0/jlib/agentInstaller.jar:/agent12c/agt/core/12.1.0.5.0/oui/jlib/OraInstaller.jar oracle.sysman.agent.installer.AgentInstaller /agent12c/agt/core/12.1.0.5.0 /home/oracle /agent12c/agt AGENT_BASE_DIR=/agent12c/agt RESPONSE_FILE=/home/oracle/agent.rsp -prereq

Validation de l'hote et du port OMS avec l'URL : http://SRVOMS1.mydomain.com.localdomain.fr:4889/empbs/genwallet
Validation de l'hote et du port OMS avec l'URL : https://SRVOMS1.mydomain.com.localdomain.fr:4889/empbs/genwallet
Return status:0-oms http port is passed
Unzipping the agentcoreimage.zip to /agent12c/agt ....
12.1.0.5.0_PluginsOneoffs_226.zip
Executing command : /home/oracle/unzip -o /home/oracle/12.1.0.5.0_PluginsOneoffs_226.zip -d /agent12c/agt
Successfully unzipped /home/oracle/12.1.0.5.0_PluginsOneoffs_226.zip to /agent12c/agt !
Executing command : /agent12c/agt/core/12.1.0.5.0/jdk/bin/java -classpath /agent12c/agt/core/12.1.0.5.0/oui/jlib/OraInstaller.jar:/agent12c/agt/core/12.1.0.5.0/oui/jlib/xmlparserv2.jar:/agent12c/agt/core/12.1.0.5.0/oui/jlib/srvm.jar:/agent12c/agt/core/12.1.0.5.0/oui/jlib/emCfg.jar:/agent12c/agt/core/12.1.0.5.0/jlib/agentInstaller.jar:/agent12c/agt/core/12.1.0.5.0/oui/jlib/share.jar oracle.sysman.agent.installer.AgentInstaller /agent12c/agt/core/12.1.0.5.0 /home/oracle /agent12c/agt /agent12c/agt AGENT_BASE_DIR=/agent12c/agt


Exécution des prérequis pour l'installation de l'agent...
Exécution de la commande : /agent12c/agt/core/12.1.0.5.0/oui/bin/runInstaller -debug -ignoreSysPrereqs -prereqchecker -silent -ignoreSysPrereqs -waitForCompletion -prereqlogloc /agent12c/agt/core/12.1.0.5.0/cfgtoollogs/agentDeploy -entryPoint oracle.sysman.top.agent_Complete -detailedExitCodes PREREQ_CONFIG_LOCATION=/agent12c/agt/core/12.1.0.5.0/prereqs -J-DORACLE_HOSTNAME=SRVCLNT.mydomain.com.appclient.asp -J-DAGENT_PORT=3872 -J-DAGENT_BASE_DIR=/agent12c/agt
Les prérequis pour l'installation de l'agent ont été appliqués

Clonage du répertoire d'origine Oracle Home de l'agent...
Exécution de la commande : /agent12c/agt/core/12.1.0.5.0/oui/bin/runInstaller -debug -ignoreSysPrereqs -clone -forceClone -silent -waitForCompletion -nowait ORACLE_HOME=/agent12c/agt/core/12.1.0.5.0 -responseFile /home/oracle/agent.rsp AGENT_BASE_DIR=/agent12c/agt AGENT_BASE_DIR=/agent12c/agt RESPONSE_FILE=/home/oracle/agent.rsp -noconfig ORACLE_HOME_NAME=agent12c2 -force b_noUpgrade=true EMCTLCFG_MODE=NONE
Répertoire de base de l'agent cloné

Attachement du répertoire d'origine Oracle Home sbin...
Exécution de la commande : /agent12c/agt/core/12.1.0.5.0/oui/bin/runInstaller -debug -ignoreSysPrereqs -attachHome -waitForCompletion -nowait ORACLE_HOME=/agent12c/agt/sbin ORACLE_HOME_NAME=sbin12c2 -force
...
...

Une fois le déploiement réalisé, il reste une dernière action pour terminer l’installation, à savoir exécuter le ROOT.SH, depuis le compte ROOT du serveur :

[SRVCLNT.mydomain.com]<oracle>:sudo -i
[SRVCLNT.mydomain.com]<root>:/agent12c/agt/core/12.1.0.5.0/root.sh

Un dernier petit contrôle :

[SRVCLNT.mydomain.com]<oracle>:/agent12c/agt/core/12.1.0.5.0/bin/emctl status agent

Oracle Enterprise Manager Cloud Control 12c Release 5
Copyright (c) 1996, 2015 Oracle Corporation. All rights reserved.
---------------------------------------------------------------
Agent Version : 12.1.0.5.0
OMS Version : 12.1.0.5.0
Protocol Version : 12.1.0.1.0
Agent Home : /agent12c/agt
Agent Log Directory : /agent12c/agt/sysman/log
Agent Binaries : /agent12c/agt/core/12.1.0.5.0
Agent Process ID : 38659
Parent Process ID : 38597
Agent URL : https://SRVCLNT.mydomain.com:3872/emd/main/
Local Agent URL in NAT : https://SRVCLNT.mydomain.com:3872/emd/main/
Repository URL : https://SRVOMS1.mydomain.com:4903/empbs/upload
Started at : 2017-01-17 10:51:38
Started by user : oracle
Operating System : Linux version 3.10.0-514.el7.x86_64 (amd64)
Last Reload : (none)
Last successful upload : 2017-01-23 14:23:26
Last attempted upload : 2017-01-23 14:23:26
Total Megabytes of XML files uploaded so far : 6.21
Number of XML files pending upload : 0
Size of XML files pending upload(MB) : 0
Available disk space on upload filesystem : 62.75%
Collection Status : Collections enabled
Heartbeat Status : Ok
Last attempted heartbeat to OMS : 2017-01-23 14:28:57
Last successful heartbeat to OMS : 2017-01-23 14:28:57
Next scheduled heartbeat to OMS : 2017-01-23 14:29:58

---------------------------------------------------------------
Agent is Running and Ready

[SRVCLNT.mydomain.com]<oracle>:/agent12c/agt/core/12.1.0.5.0/bin/emctl upload agent
Oracle Enterprise Manager Cloud Control 12c Release 5
Copyright (c) 1996, 2015 Oracle Corporation. All rights reserved.
---------------------------------------------------------------
EMD upload completed successfully

[SRVCLNT.mydomain.com]<oracle>:/agent12c/agt/core/12.1.0.5.0/bin/emctl config agent listtargets
Oracle Enterprise Manager Cloud Control 12c Release 5
Copyright (c) 1996, 2015 Oracle Corporation. All rights reserved.
[SRVCLNT.mydomain.com, host]
[SRVCLNT.mydomain.com:3872, oracle_emd]
[SRVCLNT.mydomain.com:3872_proxy, oracle_emd_proxy]

Et voilà ! notre agent est installé, il est maintenant possible d’y ajouter d’autres cibles comme une base de données, un listener, un RAC etc..

Micka

 

 

How to : Oracle ASM – Ajout d’un disque SAN à un diskgroup sur Windows

Comme premier article de l’année, je me suis lancé dans un petit tuto pour montrer au mieux comment ajouter un nouvel espace de stockage SAN à un diskgroup ASM sur un environnement RAC 11G windows (à partir de 2008). Rien de bien complexe, mais cela reste des opérations courantes qui méritent d’avoir leur petit tuto 😉

Pour ce qui est du contexte technique, j’ai donc un cluster Oracle (sur machine physique) à deux noeuds, en 11.2.0.3 (Grid + RDBMS), sur un windows 2008R2.

L’objectif est d’ajouter un espace de stockage SAN de 250Go à mon diskgroup « DATA » utilisé par ASM, sans provoquer d’incident ou d’indisponibilité.

Attention :

Il faut s’assurer que le zoning soit bien réalisé depuis le SAN sur les 2 noeuds, sans accès EXCLUSIF, si si cela peu arriver …

=> Pour la petite note, l’accès « exclusif » se caractérise par le fait de réaliser des opérations sur un nouveau disque depuis un nœud du RAC, qui ne seraient pas propagées sur le ou les autres nœuds.

Tout d’abord, dès que l’espace SAN a été mappé sur les 2 serveurs, il faut s’assurer de la visibilité du disque depuis l’utilitaire DISKPART.

L’utilisation de cet utilitaire est préconisé par Oracle pour gérer les disques qui seront affectés à ASM, il faut en effet éviter d’utiliser le GUI « diskmgmt.msc » pour éviter des problèmes de FREEZE (que j’ai d’ailleurs rencontré quelques fois), qui feraient que le simple ajout -d’un disque devient une opération complexe pour ne pas dire d’autres mots.

On lance donc DISKPART depuis une commande dos sur l’un des noeuds du RAC, et on affiche l’ensemble des disques identifiés par le System pour ensuite s’occuper du nouvel espace ajouté.

Nota : il se peut que le nouveau disque ne soit pas visible sur les noeuds du cluster. Pas de panique, un RESCAN permet de rafraîchir le gestionnaire de disques Windows

1

Dans cette liste, on visualise 2 disques Offline qui sont à ajouter. Nous allons ajouter le disque 5 de 250Go à notre groupe de disque ASM « DATA ».

-> Toujours à travers DISKPART, on sélectionne le disque et débutons la création de 2 partitions en passant tout d’abord le disque ONLINE (la mise ONLINE du disque doit être réalisé sur l’ensemble des noeuds du RAC).

Note : Pour les stockages windows ASM, il faut avoir un disque ayant une partition ETENDUE puis LOGIQUE (soit à la taille globale du disque, ou non)

2

On créée la partition ETENDUE :

3

Ah … dommage . Le volume est en READ ONLY il est donc impossible de créer quoique ce soit dessus.

L’origine de ce problème est connu de Microsoft (KB), et fait référence à de nouvelles stratégies de groupes windows relatif à la gestion des disques SAN. En 2008 et 2008R2 les stratégies de groupes SAN attribuent le mode READ ONLY à tout nouveaux disques partagés SAN (mode VDS_SP_OFFLINE_SHARED) , alors que dans les versions plus récentes, le mode READ WRITE (VDS_SP_ONLINE) est le mode par défaut.

Les différentes stratégie de groupes SAN :

VDS_SP_ONLINE: All newly discovered disks are brought online and made read-write.
VDS_SP_OFFLINE_SHARED: All newly discovered disks that do not reside on a shared bus are brought online and made read-write.
VDS_SP_OFFLINE: All newly discovered disks remain offline and read-only.

Le contournement proposé est donc de modifier les attributs du disque, pour le forcer à être en READ WRITE via la commande « ATTRIBUTE DISK CLEAR READONLY« 

Qu’à cela ne tienne, passons le disque 5 en READ WRITE , et continuons la création de nos partitions.

5

=> Attention : Ceci est à faire sur l’ensemble des noeuds du cluster RAC.

Pour la création des deux partitions, il faut suivre les commandes ci dessous sauf pour la partition logique, dans le cas où une limite d’espace disque serait à fixer (ce qui n’est pas mon cas)

Création de la partition étendue :

CREATE PARTITITON EXTENDED

Création de la partition logique en utilisant tout l’espace disque de la partition étendue :

CREATE PARTITION LOGICAL 

Ou si une taille doit être spécifiée (exemple pour 10Go, la SIZE étant spécifiée en MB)

CREATE PARTITION LOGICAL SIZE=10000

Ce qui donne dans mon cas :

6

=> Après cette étape il faut s’assurer que les partitions soient BIEN VISIBLES des autres noeuds du cluster. Dans mon cas je vérifie sur mon second node toujours via DiskPart, après avoir fait en revanche un petit RESCAN pour rafraîchir le gestionnaire de disque.

7

Histoire d’être sur (car normalement depuis windows 2008 c’est du par défaut), on lance une commande « AUTOMOUNT ENABLE » pour être sur que le disque sera monté au prochain reboot.

23

Maintenant que cette étape est faite, il faut vérifier un point certes peu impactant mais qui peut être gênant pour oracle,  windows et les applications :

A chaque découverte de nouvelles partitions, Windows attribue AUTOMATIQUEMENT une nouvelle lettre de lecteur. En soi, pour des partitions classiques (primary) ce n’est pas bien grave, mais pour les partitions étendues (que va utiliser ASM) cela peut poser problème.

=> Il faut donc veiller à RETIRER la LETTRE qui a du être automatiquement ajoutée sur le second noeud (en effet, le nœud d’où a été créée la partition n’a quand à lui pas cette lettre d’automatiquement associée)

Après avoir cliqué droit sur la partition, puis sélectionné « Change drive letter and path » :

20

=> on remove !

21

On dit YES bien sur ..

22

Hop, plus de lettre, c’est tout bon, je peux maintenant passer à la partie Oracle, et plus particulièrement ASM, pour agrandir mon DISKGROUP existant avec cette nouvelle partition LOGIQUE précédemment créée.

La première action est, sous windows (et oui car pas besoin sous Unix) est de labelliser cette partition, pour être ensuite CANDIDATE sous ASM.

Pour cela, il faut lancer l’utilitaire ASMTOOL (disponible dans le répertoire d’installation du GRID CONTROL) soit en mode graphique ou en ligne de commande. Etant sous windows je ne vais pas me compliquer la vie, j’utilise la méthode graphique via ASMTOOLG :

8

On continue (NEXT) et on arrive sur la liste des partitions visibles par le system, et celles qui sont candidates à être formatées « ASM » :

9

La partition 1 du Disk5, qui est CANDIDATE, est bien celle qui a été précédemment créée.

Note :

Je garde le même PREFIX pour la labellisation ASM « DATA » puisque je vais procéder à une augmentation du diskgroup de ce même nom. Ceci étant j’aurais pu mettre « DATA2″ ou « TOTO », cela n’aurait pas empêché l’opération d’agrandissement, il s’agit plus de normes et conventions, autant les respecter alors 😉

Je sélectionne donc ma partition 1 du disk5, et lance la « labellisation » du disk en format ASM :

10

1112

 

Je peux enfin passer sous ASM pour agrandir mon diskgroup !

Mais faisons au préalable un petit état des lieux, pour avoir un état avant et après, et également identifier le disque ASM qui sera à ajouter.

13

14

J’ai donc bien d’identifié par ASM mon disque en statut PROVISIONED et non utilisé, qui peut être ajouté au diskgroup DATA, auquel cas je lance ma commande :

15

Tout juste une fois cette commande lancée, nous pouvons interroger les opérations de REBALANCE en cours sur le diskgroup DATA :

16

Tiens mais qu’est ce le REBALANCE au fait ?

->  A chaque ajout de disque (un ou plusieurs) au sein d’un même diskgroup, il y a des opérations de redistribution des données qui sont automatiquement réalisées par ASM, l’objectif étant que les données soient réparties au mieux à travers tous les disques qui composent le diskgroup.

Les opérations de REBALANCE se découpent en 3 phases :

1. Analyse des données à répartir : « PLANNING »
2. Ré-allocation des EXTENTS des fichiers de données : « File extents relocation »
3. Compactage : « Disk compacting »

Par défaut, le niveau de REBALANCE est fixé à 1 via le paramètre ASM_POWER_LIMIT

17

Ce qui signifie que les opérations ne vont pas « trop » solliciter les ressources machines / SAN (CPU / IO) pour ne pas impacter les performances, dans le cas où par exemple cette opération serait lancée en pleine journée.

Mais l’impact de laisser tel quel ce paramètre à sa valeur par défaut peut être majeur, puisque autant sur une base de 100G, répartir les données sur l’ensemble des disques va prendre un temps probablement acceptable, dans lequel peu de risques peuvent survenir, mais autant sur une base de quelques To, cela ne va pas être la même limonade…

Si l’opération met plusieurs heures à se réaliser, les facteurs risquent augmentent (risques de pannes disques, machines, coupure lien SAN, reboot et j’en passe) ce qui peut provoquer un doux bazar au sein des données stockées par ASM.

Il est donc important de vérifier le temps que va mettre ASM à effectuer ses opérations de réorganisation, pour adapter au mieux et éviter ainsi un certain nombres de risques.

La gestion de la REBALANCE est dynamique, nous pouvons augmenter ou diminuer ASM_POWER_LIMIT, via une commande du type « alter diskgroup MYDISK rebalance power 3;« , voyons donc ce que cela donne pour moi :

18

On voit que le temps estimé ne descend pas, c’est plutôt le contraire (et c’est normal car c’est la première phase de « Planning« ). Nous allons donc passer au niveau rebalance 4 :

19

Tout de suite, en montant le niveau de rebalance à 4, on divise par deux le temps nécessaire à la réorganisation des données.

24

Nous avons donc maintenant notre diskgroup DATA pleinement opérationnel avec ces 250 nouveaux Go !

Enjoy !

Micka