# Fichier: python_cheats/cheatsheets/ASM.txt
# Oracle ASM (Automatic Storage Management) - Guide Complet pour Grands Débutants
# Configuration Ultra-détaillée Détaillée avec Deux Utilisateurs sur Ubuntu

[OK] INTRODUCTION : QU'EST-CE QU'ASM ?

"""
┌────────────────────────────────────────────────────────────────────────┐
│                    BIENVENUE DANS LE MONDE D'ASM !                     │
└────────────────────────────────────────────────────────────────────────┘

ASM = Automatic Storage Management
-> Système de gestion de stockage INTÉGRÉ à Oracle
-> Remplace le système de fichiers traditionnel pour les bases Oracle
-> Gère les disques et les fichiers automatiquement
-> Optimise les performances et la disponibilité

ANALOGIE SIMPLE :
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Imagine que tu as plusieurs disques durs chez toi :
- Disque 1 : 100 GB
- Disque 2 : 200 GB
- Disque 3 : 150 GB

SANS ASM (gestion traditionnelle) :
[X] Tu dois décider manuellement où mettre chaque fichier
[X] "Fichier A va sur Disque 1, Fichier B sur Disque 2..."
[X] Si un disque se remplit, tu dois DÉPLACER des fichiers (galère !)
[X] Pas de redondance automatique
[X] Difficile d'optimiser les performances

AVEC ASM (gestion automatique) :
[OK] ASM voit les 3 disques comme un SEUL GRAND POOL de stockage (450 GB)
[OK] Tu dis juste : "Je veux stocker ce fichier"
[OK] ASM choisit AUTOMATIQUEMENT où le mettre
[OK] ASM ÉQUILIBRE les données sur tous les disques (performance !)
[OK] ASM peut créer des COPIES automatiques sur plusieurs disques (sécurité !)
[OK] Si tu ajoutes un 4ème disque, ASM RÉÉQUILIBRE automatiquement

C'EST EXACTEMENT COMME UN GESTIONNAIRE DE BIBLIOTHÈQUE INTELLIGENT !
-> Tu lui donnes des livres (fichiers)
-> Il les range intelligemment sur les étagères (disques)
-> Il optimise l'espace et la sécurité
-> Tu n'as plus à te soucier des détails !
"""

# === POURQUOI UTILISER ASM ? ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│                   AVANTAGES D'ASM vs SYSTÈME DE FICHIERS               │
└────────────────────────────────────────────────────────────────────────┘

1. PERFORMANCE [RAPIDE]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Système de fichiers traditionnel (ext4, XFS) :
-> Les fichiers sont stockés séquentiellement sur UN SEUL disque
-> Un gros fichier de 10 GB est sur un seul disque
-> Performance limitée par la vitesse d'UN SEUL disque

ASM (Automatic Storage Management) :
-> Les fichiers sont DÉCOUPÉS en morceaux (extents)
-> Chaque morceau est RÉPARTI sur PLUSIEURS disques
-> Lecture/écriture en PARALLÈLE sur tous les disques
-> Performance MULTIPLIÉE par le nombre de disques !

Exemple concret :
Fichier de 10 GB sur 5 disques
-> Système classique : lit 10 GB sur 1 disque = 100 MB/s = 100 secondes
-> ASM : lit 2 GB sur chacun des 5 disques en parallèle = 5×100 MB/s = 20 secondes
-> RÉSULTAT : 5x PLUS RAPIDE ! [RAPIDE]


2. HAUTE DISPONIBILITÉ [SECURITE]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Système de fichiers traditionnel :
-> Si un disque MEURT, tu PERDS toutes les données dessus
-> Il faut restaurer depuis une sauvegarde (long, perte de données récentes)

ASM avec REDONDANCE :
-> Chaque morceau de fichier est COPIÉ sur 2 ou 3 disques différents
-> Si un disque MEURT, ASM utilise automatiquement la copie sur un autre disque
-> Base de données continue de FONCTIONNER sans interruption ! [OK]
-> ASM RECONSTRUIT automatiquement les données sur un disque de spare

Exemple :
Tu as 5 disques + 1 disque de spare
-> Disque 3 tombe en panne à 14h30
-> ASM détecte la panne INSTANTANÉMENT
-> ASM bascule automatiquement sur les copies (pas d'interruption)
-> ASM commence à reconstruire sur le disque de spare
-> En 1-2 heures, tout est restauré
-> AUCUNE perte de données ! AUCUNE interruption !


3. GESTION SIMPLIFIÉE [OBJECTIF]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Système de fichiers traditionnel :
-> Tu dois créer des partitions manuellement
-> Tu dois créer des systèmes de fichiers (mkfs)
-> Tu dois monter les partitions (/etc/fstab)
-> Tu dois étendre manuellement si l'espace manque
-> Tu dois gérer les permissions
-> Tu dois équilibrer les données manuellement

ASM :
-> Tu présentes les disques bruts (raw devices) à ASM
-> ASM gère TOUT automatiquement
-> Plus besoin de partitions ni de systèmes de fichiers
-> Ajout d'un disque ? Une seule commande !
-> ASM rééquilibre automatiquement
-> Gestion unifiée via ASMCMD ou SQL


4. SCALABILITÉ ILLIMITÉE [HAUSSE]
━━━━━━────────────────────────────────────────────────────────────────────────
Système de fichiers traditionnel :
-> Limité par la taille du système de fichiers
-> Étendre un système de fichiers = opération risquée
-> Difficile de combiner plusieurs disques

ASM :
-> Ajoute des disques À CHAUD (sans arrêter la base)
-> Pas de limite pratique (jusqu'à des pétaoctets)
-> Rééquilibrage automatique en arrière-plan
-> Zero downtime !


5. OPTIMISATION I/O AUTOMATIQUE [RAPIDE]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
ASM connaît Oracle de l'intérieur :
-> Optimise le placement des données selon leur type
-> Met les fichiers de contrôle sur les disques les plus rapides
-> Répartit les redo logs pour maximiser la bande passante
-> Striping intelligent (découpage optimisé)


TABLEAU COMPARATIF :
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌──────────────────────┬─────────────────────┬─────────────────────┐
│   Caractéristique    │  Système Fichiers   │         ASM         │
├──────────────────────┼─────────────────────┼─────────────────────┤
│ Performance I/O      │ Limitée (1 disque)  │ Parallèle (N disques)│
│ Redondance           │ Manuelle (RAID)     │ Automatique         │
│ Ajout de disques     │ Complexe            │ Simple (à chaud)    │
│ Rééquilibrage        │ Manuel              │ Automatique         │
│ Gestion              │ Plusieurs outils    │ Unifiée (ASMCMD)    │
│ Optimisation Oracle  │ Aucune              │ Native              │
│ Scalabilité          │ Limitée             │ Illimitée           │
│ Complexité setup     │ Moyenne             │ Élevée (au début)   │
│ Maintenance          │ Manuelle            │ Automatique         │
└──────────────────────┴─────────────────────┴─────────────────────┘
"""


[OK] PARTIE 1 : ARCHITECTURE ASM - COMPRENDRE LES CONCEPTS

# === COMPOSANTS PRINCIPAUX D'ASM ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│                      ARCHITECTURE ASM COMPLÈTE                         │
└────────────────────────────────────────────────────────────────────────┘

                        ┌──────────────────────────┐
                        │   INSTANCE DATABASE      │
                        │       (ORCL)             │
                        │  ┌────────────────────┐  │
                        │  │  SGA + Processus   │  │
                        │  └────────────────────┘  │
                        └──────────┬───────────────┘
                                   │
                                   │ Accès aux fichiers
                                   │ (datafiles, redo, control)
                                   v
                        ┌──────────────────────────┐
                        │   INSTANCE ASM           │
                        │      (+ASM)              │
                        │  ┌────────────────────┐  │
                        │  │  SGA + Processus   │  │
                        │  │  - RBAL (Rebalance)│  │
                        │  │  - ARBn (Rebal wkr)│  │
                        │  │  - ASMB (ASM Bgr)  │  │
                        │  └────────────────────┘  │
                        └──────────┬───────────────┘
                                   │
                                   │ Gère les disques
                                   │
                   ┌───────────────┼───────────────┐
                   │               │               │
                   v               v               v
          ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
          │ DISK GROUP 1 │ │ DISK GROUP 2 │ │ DISK GROUP 3 │
          │    (DATA)    │ │    (FRA)     │ │   (REDO)     │
          └──────┬───────┘ └──────┬───────┘ └──────┬───────┘
                 │                │                │
        ┌────────┼────────┐      │         ┌──────┴──────┐
        │        │        │      │         │             │
        v        v        v      v         v             v
    ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐     ┌──────┐
    │ /dev/│ │ /dev/│ │ /dev/│ │ /dev/│ │ /dev/│     │ /dev/│
    │ sdb  │ │ sdc  │ │ sdd  │ │ sde  │ │ sdf  │     │ sdg  │
    └──────┘ └──────┘ └──────┘ └──────┘ └──────┘     └──────┘
    Disque   Disque   Disque   Disque   Disque      Disque
      1        2        3        4        5           6


EXPLICATION DE CHAQUE NIVEAU :
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

1. INSTANCE DATABASE (ORCL)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-> C'est ta BASE DE DONNÉES Oracle normale
-> Nom typique : ORCL, PROD, TEST, etc.
-> Elle contient :
   - Tables
   - Index
   - Données des utilisateurs
   - Redo logs
   - Control files
   - Etc.

-> ELLE NE GÈRE PAS les disques directement !
-> Elle demande à ASM : "Je veux créer un fichier de 1 GB"
-> ASM répond : "OK, je m'en occupe !"


2. INSTANCE ASM (+ASM)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-> C'est une INSTANCE ORACLE SPÉCIALE dédiée à la gestion du stockage
-> Nom : toujours +ASM (ou +ASM1, +ASM2 pour RAC)
-> Elle tourne EN PARALLÈLE de l'instance database
-> Elle démarre AVANT l'instance database

RÔLES :
[OK] Découvre les disques disponibles
[OK] Organise les disques en DISK GROUPS
[OK] Gère l'allocation des fichiers
[OK] Fait le rééquilibrage automatique
[OK] Surveille l'état des disques
[OK] Gère la redondance (mirroring)

PROCESSUS IMPORTANTS :
- RBAL (Rebalancer) : Coordonne le rééquilibrage
- ARB0-ARB9 (Rebalance Workers) : Font le rééquilibrage effectif
- ASMB (ASM Background) : Communication avec l'instance database

IMPORTANT :
-> L'instance ASM est LÉGÈRE (utilise peu de mémoire)
-> Elle ne contient PAS de données utilisateurs
-> Elle contient seulement des métadonnées (où sont les fichiers)


3. DISK GROUPS (Groupes de Disques)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-> Un disk group = POOL de disques regroupés logiquement
-> C'est l'équivalent d'un système de fichiers, mais géré par ASM

POURQUOI PLUSIEURS DISK GROUPS ?
-> Séparer les types de données selon leurs besoins

DISK GROUPS TYPIQUES :

a) DATA (Données principales)
   -> Contient : datafiles, tempfiles
   -> Redondance : HIGH ou NORMAL
   -> Performance : importante
   -> Disques : SSD rapides
   
b) FRA (Fast Recovery Area)
   -> Contient : sauvegardes, archived redo logs, flashback logs
   -> Redondance : NORMAL ou EXTERNAL
   -> Performance : moyenne
   -> Disques : SAS ou SATA (moins chers)

c) REDO (Journaux de transactions)
   -> Contient : redo logs, control files
   -> Redondance : HIGH (CRITIQUE !)
   -> Performance : ULTRA importante (écriture synchrone)
   -> Disques : SSD ultra-rapides

TU PEUX créer autant de disk groups que tu veux !


4. DISQUES PHYSIQUES (ASM Disks)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-> Les VRAIS disques durs (HDD/SSD)
-> Présentés à ASM comme RAW DEVICES (périphériques bruts)
-> Format : /dev/sdb, /dev/sdc, /dev/mapper/asm_disk1, etc.

IMPORTANT :
-> ASM accède DIRECTEMENT au disque (pas de système de fichiers)
-> Pas besoin de mkfs.ext4, mkfs.xfs, etc.
-> ASM écrit ses propres métadonnées sur le disque


FLUX DE DONNÉES COMPLET :
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Exemple : INSERT INTO clients VALUES (...);

1. Utilisateur exécute INSERT
   v
2. Instance Database (ORCL) écrit dans le Buffer Cache (RAM)
   v
3. DBWn (Database Writer) doit écrire sur disque
   v
4. ORCL demande à ASM : "Écris ce bloc dans +DATA/ORCL/datafile/users01.dbf"
   v
5. Instance ASM reçoit la demande
   v
6. ASM consulte ses métadonnées :
   "users01.dbf extent 42 est sur disque /dev/sdb offset 123456789"
   v
7. ASM écrit DIRECTEMENT sur /dev/sdb
   v
8. Si redondance NORMAL : ASM écrit AUSSI sur /dev/sdc (copie miroir)
   v
9. ASM confirme l'écriture à ORCL
   v
10. ORCL confirme le COMMIT à l'utilisateur

TOUT ÇA SE PASSE EN QUELQUES MILLISECONDES ! [RAPIDE]
"""

# === CONCEPTS CLÉS D'ASM ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│                        CONCEPTS ESSENTIELS ASM                         │
└────────────────────────────────────────────────────────────────────────┘

1. ALLOCATION UNIT (AU)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-> Plus petite unité d'allocation dans ASM
-> Taille par défaut : 1 MB (modifiable : 1, 2, 4, 8, 16, 32, 64 MB)
-> Équivalent d'un "bloc" dans un système de fichiers

Exemple :
Tu crées un fichier de 10 MB
-> ASM alloue 10 AU de 1 MB chacune
-> Ces 10 AU peuvent être sur différents disques

ANALOGIE :
-> AU = briques de construction
-> Fichier = maison construite avec ces briques
-> ASM = maçon qui place intelligemment les briques sur différents terrains


2. EXTENT (Ensemble d'AU)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-> Groupe d'AU contigus
-> Les fichiers grandissent par EXTENTS

Quand un fichier grandit :
1er extent : 1 AU = 1 MB
2ème extent : 4 AU = 4 MB
3ème extent : 8 AU = 8 MB
...
20ème extent : 64 AU = 64 MB (maximum)

Ensuite, tous les extents font 64 AU


3. STRIPING (Répartition des données)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-> ASM DÉCOUPE les fichiers en morceaux
-> Chaque morceau va sur un disque différent
-> GOAL : Lire/écrire en PARALLÈLE sur tous les disques

Striping = découpage en fines tranches

DEUX TYPES :

a) FINE STRIPING (Striping fin)
   -> Taille : 128 KB (fixe)
   -> Utilisé pour : fichiers nécessitant beaucoup d'I/O aléatoires
   -> Exemple : datafiles
   -> Avantage : Maximise le parallélisme

b) COARSE STRIPING (Striping large)
   -> Taille : 1 AU (1 MB par défaut)
   -> Utilisé pour : fichiers avec I/O séquentiels
   -> Exemple : archived redo logs, backups
   -> Avantage : Réduit la fragmentation

ASM CHOISIT AUTOMATIQUEMENT le type selon le type de fichier !

EXEMPLE CONCRET :
Fichier de 10 MB avec FINE STRIPING (128 KB) sur 4 disques

Fichier découpé en : 10 MB / 128 KB = 80 morceaux

Répartition :
/dev/sdb : morceaux 0, 4, 8, 12, 16, 20, ... (20 morceaux)
/dev/sdc : morceaux 1, 5, 9, 13, 17, 21, ... (20 morceaux)
/dev/sdd : morceaux 2, 6, 10, 14, 18, 22, ... (20 morceaux)
/dev/sde : morceaux 3, 7, 11, 15, 19, 23, ... (20 morceaux)

Lecture du fichier :
-> Les 4 disques lisent EN MÊME TEMPS
-> Performance × 4 ! [RAPIDE]


4. REDUNDANCY (Redondance / Mirroring)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-> ASM peut DUPLIQUER les données sur plusieurs disques
-> Protection contre la panne de disque

TROIS NIVEAUX :

a) EXTERNAL (Pas de redondance ASM)
   ┌─────────────────────────────────────────────────────┐
   │ Données stockées UNE SEULE FOIS                     │
   │ ┌─────────────┐                                     │
   │ │  Fichier A  │ -> /dev/sdb                          │
   │ └─────────────┘                                     │
   │                                                     │
   │ Avantage : Utilise 100% de l'espace disponible     │
   │ Inconvénient : Aucune protection si disque meurt   │
   │ Usage : Quand tu as déjà un RAID matériel          │
   └─────────────────────────────────────────────────────┘

b) NORMAL (Mirroring à 2 copies)
   ┌─────────────────────────────────────────────────────┐
   │ Données stockées DEUX FOIS sur disques différents   │
   │ ┌─────────────┐       ┌─────────────┐              │
   │ │  Fichier A  │  ───-> │  Copie 1    │ -> /dev/sdb   │
   │ └─────────────┘       └─────────────┘              │
   │                       ┌─────────────┐              │
   │                  ───-> │  Copie 2    │ -> /dev/sdc   │
   │                       └─────────────┘              │
   │                                                     │
   │ Avantage : Résiste à la perte d'1 disque           │
   │ Inconvénient : Utilise 2× l'espace                 │
   │ Usage : Configuration STANDARD recommandée         │
   └─────────────────────────────────────────────────────┘

c) HIGH (Mirroring à 3 copies)
   ┌─────────────────────────────────────────────────────┐
   │ Données stockées TROIS FOIS sur disques différents  │
   │ ┌─────────────┐       ┌─────────────┐              │
   │ │  Fichier A  │  ───-> │  Copie 1    │ -> /dev/sdb   │
   │ └─────────────┘       └─────────────┘              │
   │                       ┌─────────────┐              │
   │                  ───-> │  Copie 2    │ -> /dev/sdc   │
   │                       └─────────────┘              │
   │                       ┌─────────────┐              │
   │                  ───-> │  Copie 3    │ -> /dev/sdd   │
   │                       └─────────────┘              │
   │                                                     │
   │ Avantage : Résiste à la perte de 2 disques         │
   │ Inconvénient : Utilise 3× l'espace                 │
   │ Usage : Données ULTRA-CRITIQUES (redo logs)        │
   └─────────────────────────────────────────────────────┘

CALCUL DE L'ESPACE UTILISABLE :

Tu as 5 disques de 100 GB chacun = 500 GB total

EXTERNAL : 500 GB utilisables (100%)
NORMAL : 250 GB utilisables (50%)
HIGH : 166 GB utilisables (33%)


5. FAILURE GROUPS (Groupes de Défaillance)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-> Permet de grouper des disques qui PEUVENT TOMBER ENSEMBLE
-> ASM ne mettra JAMAIS deux copies sur des disques du même failure group

EXEMPLE D'UTILITÉ :
Tu as un serveur avec 2 contrôleurs disque :
- Contrôleur A : gère /dev/sdb, /dev/sdc, /dev/sdd
- Contrôleur B : gère /dev/sde, /dev/sdf, /dev/sdg

Si le contrôleur A MEURT :
-> Tous les disques A sont perdus
-> Mais si les COPIES sont sur les disques B, pas de problème ! [OK]

Configuration :
Failure Group 1 : /dev/sdb, /dev/sdc, /dev/sdd (contrôleur A)
Failure Group 2 : /dev/sde, /dev/sdf, /dev/sdg (contrôleur B)

ASM garantit :
-> Copie 1 du fichier : sur un disque du groupe 1
-> Copie 2 du fichier : sur un disque du groupe 2
-> Jamais les deux copies sur le même groupe !


6. REBALANCE (Rééquilibrage Automatique)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-> Processus automatique de redistribution des données
-> Déclenché quand :
   [OK] Tu AJOUTES un disque au disk group
   [OK] Tu SUPPRIMES un disque du disk group
   [OK] Un disque TOMBE EN PANNE

AVANT RÉÉQUILIBRAGE :
Disk Group avec 3 disques de 100 GB

/dev/sdb : 90 GB utilisés (90% plein) [FACE_WITH_OPEN_MOUTH_AND_COLD_SWEAT]
/dev/sdc : 50 GB utilisés (50% plein)
/dev/sdd : 40 GB utilisés (40% plein)

-> DÉSÉQUILIBRE ! sdb est surchargé

APRÈS AJOUT D'UN 4ÈME DISQUE + RÉÉQUILIBRAGE :
/dev/sdb : 60 GB utilisés (60% plein) [OK]
/dev/sdc : 60 GB utilisés (60% plein) [OK]
/dev/sdd : 60 GB utilisés (60% plein) [OK]
/dev/sde : 60 GB utilisés (60% plein) [OK] (nouveau disque)

-> ÉQUILIBRE PARFAIT ! Même charge sur tous les disques

COMMENT ÇA MARCHE ?
1. Tu ajoutes le disque : ALTER DISKGROUP data ADD DISK '/dev/sde';
2. ASM calcule la distribution optimale
3. Processus RBAL coordonne le rééquilibrage
4. Processus ARB0-ARB9 DÉPLACENT les données
5. Rééquilibrage se fait EN ARRIÈRE-PLAN
6. Base de données continue de FONCTIONNER normalement
7. Quand terminé, nouveau disque pleinement intégré

CONTRÔLE DE LA VITESSE :
ASM_POWER_LIMIT = 1 à 11
-> 1 = lent (priorité aux requêtes utilisateurs)
-> 11 = rapide (priorité au rééquilibrage)


7. ASM FILES (Fichiers ASM)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
-> Les fichiers dans ASM ont des noms SPÉCIAUX
-> Format : +DISKGROUP/DATABASE/FILETYPE/FILE.XXX.YYY

Exemple :
+DATA/ORCL/DATAFILE/users.256.123456789

Décomposition :
+DATA : Nom du disk group
ORCL : Nom de la base de données
DATAFILE : Type de fichier
users.256.123456789 : Nom du fichier (généré par ASM)

ALIAS :
Tu PEUX créer des alias pour rendre les noms plus lisibles :
+DATA/ORCL/DATAFILE/users01.dbf

TYPES DE FICHIERS SUPPORTÉS :
[OK] DATAFILE (fichiers de données)
[OK] TEMPFILE (fichiers temporaires)
[OK] CONTROLFILE (fichiers de contrôle)
[OK] ONLINELOG (redo logs)
[OK] ARCHIVELOG (redo logs archivés)
[OK] BACKUPSET (sauvegardes RMAN)
[OK] FLASHBACK (flashback logs)
[OK] DATAGUARDCONFIG (configuration Data Guard)
[OK] Et plus encore...
"""


[OK] PARTIE 2 : CONFIGURATION SYSTÈME - PRÉREQUIS SUR UBUNTU

# === PRÉPARATION DES UTILISATEURS ET GROUPES ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│         CONFIGURATION DEUX UTILISATEURS : oracle ET grid              │
└────────────────────────────────────────────────────────────────────────┘

POURQUOI DEUX UTILISATEURS ?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Dans une installation ASM professionnelle :
-> Utilisateur 'grid' : possède le logiciel ASM (Grid Infrastructure)
-> Utilisateur 'oracle' : possède le logiciel Database

POURQUOI SÉPARER ?
[OK] Sécurité : séparation des responsabilités
[OK] RAC : obligatoire pour Oracle Real Application Clusters
[OK] Best Practice Oracle : recommandé même en standalone
[OK] Maintenance : mise à jour indépendante de Grid et Database

ANALOGIE :
-> 'grid' = Gestionnaire d'immeuble (gère les locaux)
-> 'oracle' = Locataire (utilise les locaux)

GROUPES UNIX NÉCESSAIRES :
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Pour l'utilisateur 'grid' :
- oinstall : Groupe propriétaire de l'inventaire Oracle
- asmadmin : Administration ASM
- asmdba : Accès ASM depuis les databases
- asmoper : Opérations ASM limitées

Pour l'utilisateur 'oracle' :
- oinstall : Même inventaire
- dba : Administration des databases
- oper : Opérations limitées sur databases
- asmdba : Accès aux disk groups ASM
- backupdba : Opérations de backup
- dgdba : Data Guard
- kmdba : Encryption Key Management
"""

# ÉTAPE 1 : CRÉATION DES GROUPES
sudo groupadd -g 54321 oinstall
sudo groupadd -g 54322 dba
sudo groupadd -g 54323 oper
sudo groupadd -g 54324 backupdba
sudo groupadd -g 54325 dgdba
sudo groupadd -g 54326 kmdba
sudo groupadd -g 54327 asmdba
sudo groupadd -g 54328 asmoper
sudo groupadd -g 54329 asmadmin

# Vérification des groupes créés
cat /etc/group | grep -E "oinstall|dba|oper|asm"

# Sortie attendue :
# oinstall:x:54321:
# dba:x:54322:
# oper:x:54323:
# backupdba:x:54324:
# dgdba:x:54325:
# kmdba:x:54326:
# asmdba:x:54327:
# asmoper:x:54328:
# asmadmin:x:54329:

# ÉTAPE 2 : CRÉATION DE L'UTILISATEUR 'grid'
sudo useradd -u 54331 -g oinstall -G asmadmin,asmdba,asmoper \
    -d /home/grid -s /bin/bash -c "Grid Infrastructure Owner" grid

# Explication des options :
# -u 54331 : UID (User ID) fixe
# -g oinstall : Groupe primaire
# -G asmadmin,asmdba,asmoper : Groupes secondaires
# -d /home/grid : Répertoire home
# -s /bin/bash : Shell
# -c "..." : Commentaire
# grid : nom de l'utilisateur

# Définir un mot de passe
sudo passwd grid
# Entrer : grid123 (exemple, utiliser un mot de passe fort en production !)

# ÉTAPE 3 : CRÉATION DE L'UTILISATEUR 'oracle'
sudo useradd -u 54321 -g oinstall -G dba,asmdba,oper,backupdba,dgdba,kmdba \
    -d /home/oracle -s /bin/bash -c "Oracle Database Owner" oracle

# Définir un mot de passe
sudo passwd oracle
# Entrer : oracle123 (exemple, utiliser un mot de passe fort en production !)

# ÉTAPE 4 : VÉRIFICATION DES UTILISATEURS
id grid
# Sortie attendue :
# uid=54331(grid) gid=54321(oinstall) groups=54321(oinstall),54327(asmdba),54328(asmoper),54329(asmadmin)

id oracle
# Sortie attendue :
# uid=54321(oracle) gid=54321(oinstall) groups=54321(oinstall),54322(dba),54323(oper),54324(backupdba),54325(dgdba),54326(kmdba),54327(asmdba)


# === CRÉATION DE LA STRUCTURE DE RÉPERTOIRES ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│                    ARBORESCENCE DES RÉPERTOIRES                        │
└────────────────────────────────────────────────────────────────────────┘

/u01/                                <- Base de l'arborescence Oracle
├── app/
│   ├── grid/                        <- Home de l'utilisateur grid
│   │   ├── product/
│   │   │   └── 19.3.0/
│   │   │       └── grid/            <- GRID_HOME (logiciel ASM)
│   │   │           ├── bin/
│   │   │           ├── lib/
│   │   │           ├── network/
│   │   │           └── ...
│   │   └── admin/
│   │       └── +ASM/                <- Admin ASM
│   │           ├── adump/           <- Audit logs
│   │           ├── dpdump/
│   │           └── pfile/
│   │
│   ├── oracle/                      <- Home de l'utilisateur oracle
│   │   ├── product/
│   │   │   └── 19.3.0/
│   │   │       └── dbhome_1/        <- ORACLE_HOME (logiciel Database)
│   │   │           ├── bin/
│   │   │           ├── dbs/
│   │   │           ├── network/
│   │   │           └── ...
│   │   └── admin/
│   │       └── ORCL/                <- Admin de la base ORCL
│   │           ├── adump/
│   │           ├── dpdump/
│   │           └── pfile/
│   │
│   └── oraInventory/                <- Inventaire Oracle (commun)
│       ├── ContentsXML/
│       └── logs/
│
├── oradata/                         <- Données sur filesystem (optionnel)
│   └── ORCL/
│       └── (vide si tout sur ASM)
│
└── stage/                           <- Zone de staging pour installations
    ├── grid/
    └── database/


/u02/                                <- Disques ASM (optionnel, peut être /dev/*)
└── asmdisks/
    ├── disk1.img
    ├── disk2.img
    └── ...
"""

# ÉTAPE 5 : CRÉATION DES RÉPERTOIRES
sudo mkdir -p /u01/app/grid
sudo mkdir -p /u01/app/19.3.0/grid
sudo mkdir -p /u01/app/oracle
sudo mkdir -p /u01/app/oracle/product/19.3.0/dbhome_1
sudo mkdir -p /u01/app/oraInventory
sudo mkdir -p /u01/stage

# Permissions sur /u01/app
sudo chown -R grid:oinstall /u01/app/grid
sudo chown -R grid:oinstall /u01/app/19.3.0
sudo chown -R oracle:oinstall /u01/app/oracle
sudo chown -R grid:oinstall /u01/app/oraInventory
sudo chmod -R 775 /u01/app

# Vérification
ls -l /u01/app/
# Sortie attendue :
# drwxrwxr-x 3 grid   oinstall 4096 ... 19.3.0
# drwxrwxr-x 3 grid   oinstall 4096 ... grid
# drwxrwxr-x 3 oracle oinstall 4096 ... oracle
# drwxrwxr-x 2 grid   oinstall 4096 ... oraInventory


# === CONFIGURATION DES LIMITES SYSTÈME ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│                LIMITES SYSTÈME REQUISES PAR ORACLE                     │
└────────────────────────────────────────────────────────────────────────┘

Oracle nécessite des limites système élevées pour :
[OK] Ouvrir beaucoup de fichiers simultanément
[OK] Gérer de nombreux processus
[OK] Allouer de la mémoire partagée
[OK] Créer des segments mémoire de grande taille
"""

# ÉTAPE 6 : CONFIGURER LES LIMITES DANS /etc/security/limits.conf
sudo tee -a /etc/security/limits.conf > /dev/null <<'EOF'

# Limites pour l'utilisateur grid (ASM)
grid soft nofile 1024
grid hard nofile 65536
grid soft nproc 2047
grid hard nproc 16384
grid soft stack 10240
grid hard stack 32768
grid soft memlock unlimited
grid hard memlock unlimited

# Limites pour l'utilisateur oracle (Database)
oracle soft nofile 1024
oracle hard nofile 65536
oracle soft nproc 2047
oracle hard nproc 16384
oracle soft stack 10240
oracle hard stack 32768
oracle soft memlock unlimited
oracle hard memlock unlimited
EOF

# Explication des paramètres :
# nofile : nombre de fichiers ouverts (file descriptors)
# nproc : nombre de processus
# stack : taille de la pile (stack)
# memlock : mémoire verrouillée en RAM

# Vérification
tail -20 /etc/security/limits.conf

# ÉTAPE 7 : CONFIGURER LES PARAMÈTRES KERNEL
sudo tee -a /etc/sysctl.conf > /dev/null <<'EOF'

# Paramètres kernel pour Oracle
fs.aio-max-nr = 1048576
fs.file-max = 6815744
kernel.shmall = 2097152
kernel.shmmax = 4398046511104
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
net.ipv4.ip_local_port_range = 9000 65500
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048576
vm.swappiness = 10
vm.dirty_background_ratio = 3
vm.dirty_ratio = 15
vm.dirty_expire_centisecs = 500
vm.dirty_writeback_centisecs = 100
EOF

# Explication détaillée :
"""
fs.aio-max-nr = 1048576
-> Nombre maximum d'opérations I/O asynchrones en cours
-> Oracle utilise intensivement l'I/O asynchrone

fs.file-max = 6815744
-> Nombre maximum de file descriptors pour tout le système
-> Oracle ouvre beaucoup de fichiers simultanément

kernel.shmall = 2097152
-> Nombre total de pages de mémoire partagée disponibles
-> En pages (1 page = 4 KB sur x86_64)
-> 2097152 × 4 KB = 8 GB de mémoire partagée

kernel.shmmax = 4398046511104
-> Taille maximum d'un segment de mémoire partagée unique
-> 4398046511104 bytes = 4 TB
-> SGA (System Global Area) utilise la mémoire partagée

kernel.shmmni = 4096
-> Nombre maximum de segments de mémoire partagée dans le système

kernel.sem = 250 32000 100 128
-> Paramètres des sémaphores (synchronisation de processus)
-> 250 : SEMMSL (sémaphores max par tableau)
-> 32000 : SEMMNS (sémaphores max dans le système)
-> 100 : SEMOPM (opérations max par appel semop)
-> 128 : SEMMNI (tableaux de sémaphores max)

net.ipv4.ip_local_port_range = 9000 65500
-> Plage de ports pour connexions sortantes
-> Évite les conflits avec les ports Oracle (1521, etc.)

net.core.rmem_default = 262144
net.core.rmem_max = 4194304
-> Taille des buffers de réception réseau
-> Important pour les connexions client/serveur

net.core.wmem_default = 262144
net.core.wmem_max = 1048576
-> Taille des buffers d'envoi réseau

vm.swappiness = 10
-> Agressivité du swap (0-100)
-> 10 = utiliser le swap seulement en dernier recours
-> Oracle préfère garder la SGA en RAM

vm.dirty_background_ratio = 3
-> % de RAM avec des pages sales avant flush en arrière-plan
-> 3% = flush agressif pour libérer la RAM

vm.dirty_ratio = 15
-> % de RAM avec des pages sales avant blocage des écritures
-> 15% = point où les processus sont bloqués jusqu'au flush

vm.dirty_expire_centisecs = 500
-> Temps avant qu'une page sale soit considérée expirée (5 secondes)

vm.dirty_writeback_centisecs = 100
-> Fréquence de réveil du processus de flush (1 seconde)
"""

# Appliquer les paramètres immédiatement
sudo sysctl -p

# Vérification
sysctl kernel.shmmax
sysctl kernel.shmall
sysctl vm.swappiness


# === INSTALLATION DES PAQUETS NÉCESSAIRES ===

# ÉTAPE 8 : INSTALLER LES DÉPENDANCES
sudo apt update
sudo apt install -y \
    build-essential \
    libaio1 \
    libaio-dev \
    unixodbc \
    unixodbc-dev \
    sysstat \
    gcc \
    make \
    binutils \
    libcap-dev \
    libstdc++6 \
    libgcc1 \
    libc6 \
    libx11-6 \
    libxext6 \
    libxrender1 \
    libxtst6 \
    libxi6 \
    ksh \
    lsb-release \
    net-tools \
    nfs-common \
    smartmontools \
    xauth \
    xterm

# Explication des paquets clés :
"""
libaio1, libaio-dev
-> Bibliothèques d'I/O asynchrones
-> OBLIGATOIRES pour Oracle

unixodbc, unixodbc-dev
-> Connectivité ODBC

sysstat
-> Outils de monitoring système (sar, iostat, etc.)

ksh
-> Korn Shell, utilisé par certains scripts Oracle

smartmontools
-> Monitoring des disques (SMART)
-> Utile pour surveiller la santé des disques ASM
"""


# === CONFIGURATION DES VARIABLES D'ENVIRONNEMENT ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│              VARIABLES D'ENVIRONNEMENT POUR GRID ET ORACLE             │
└────────────────────────────────────────────────────────────────────────┘

Chaque utilisateur a besoin de variables spécifiques pour :
[OK] Localiser le logiciel Oracle/Grid
[OK] Définir les chemins de bibliothèques
[OK] Configurer l'environnement d'exécution
"""

# ÉTAPE 9 : CONFIGURER .bash_profile POUR L'UTILISATEUR 'grid'
sudo su - grid

cat > ~/.bash_profile <<'EOF'
# .bash_profile pour l'utilisateur grid (Grid Infrastructure / ASM)

# Identification Oracle
export ORACLE_SID=+ASM
export ORACLE_BASE=/u01/app/grid
export ORACLE_HOME=/u01/app/19.3.0/grid
export GRID_HOME=$ORACLE_HOME

# Inventaire Oracle
export INVENTORY_LOCATION=/u01/app/oraInventory

# Paths
export PATH=$ORACLE_HOME/bin:$PATH
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH

# Locale
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
export NLS_DATE_FORMAT='DD-MON-YYYY HH24:MI:SS'

# Autres paramètres
export TEMP=/tmp
export TMPDIR=/tmp

# Aliases pratiques
alias asmcmd='$ORACLE_HOME/bin/asmcmd'
alias sqlplus='$ORACLE_HOME/bin/sqlplus'
alias gridctl='$ORACLE_HOME/bin/crsctl'

# Prompt personnalisé
export PS1='[\u@\h:\w(+ASM)]$ '

echo "Environment set for Grid Infrastructure (+ASM)"
echo "ORACLE_HOME: $ORACLE_HOME"
echo "ORACLE_SID: $ORACLE_SID"
EOF

# Recharger le profil
source ~/.bash_profile

# Sortie de la session grid
exit


# ÉTAPE 10 : CONFIGURER .bash_profile POUR L'UTILISATEUR 'oracle'
sudo su - oracle

cat > ~/.bash_profile <<'EOF'
# .bash_profile pour l'utilisateur oracle (Database)

# Identification Oracle
export ORACLE_SID=ORCL
export ORACLE_BASE=/u01/app/oracle
export ORACLE_HOME=$ORACLE_BASE/product/19.3.0/dbhome_1

# Inventaire Oracle (partagé avec grid)
export INVENTORY_LOCATION=/u01/app/oraInventory

# Paths
export PATH=$ORACLE_HOME/bin:$PATH
export LD_LIBRARY_PATH=$ORACLE_HOME/lib:$LD_LIBRARY_PATH

# Locale
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8
export NLS_DATE_FORMAT='DD-MON-YYYY HH24:MI:SS'

# Autres paramètres
export TEMP=/tmp
export TMPDIR=/tmp

# Aliases pratiques
alias sqlplus='$ORACLE_HOME/bin/sqlplus'
alias rman='$ORACLE_HOME/bin/rman'
alias lsnrctl='$ORACLE_HOME/bin/lsnrctl'

# Prompt personnalisé
export PS1='[\u@\h:\w($ORACLE_SID)]$ '

echo "Environment set for Oracle Database ($ORACLE_SID)"
echo "ORACLE_HOME: $ORACLE_HOME"
echo "ORACLE_SID: $ORACLE_SID"
EOF

# Recharger le profil
source ~/.bash_profile

# Sortie de la session oracle
exit


[OK] PARTIE 3 : PRÉPARATION DES DISQUES POUR ASM

# === CRÉATION DES DISQUES (SIMULATION AVEC LOOP DEVICES) ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│              PRÉPARATION DES DISQUES POUR ASM                          │
└────────────────────────────────────────────────────────────────────────┘

SCÉNARIOS POSSIBLES :
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

1. DISQUES PHYSIQUES RÉELS
   -> Tu as de vrais disques durs/SSD : /dev/sdb, /dev/sdc, etc.
   -> Idéal pour production
   -> Ce guide utilise cette approche

2. PARTITIONS
   -> Tu partitionnes un gros disque en plusieurs partitions
   -> /dev/sda5, /dev/sda6, etc.
   -> OK pour test, mais pas optimal en production

3. FICHIERS LOOP (simulation)
   -> Tu crées des fichiers et les montes comme des disques
   -> Parfait pour apprentissage sur VM
   -> Performance limitée

DANS CE GUIDE : On utilise des DISQUES PHYSIQUES RÉELS (/dev/sdX)
Si tu n'en as pas, on montrera aussi la méthode LOOP DEVICE
"""

# === MÉTHODE 1 : UTILISATION DE DISQUES PHYSIQUES RÉELS ===

"""
PRÉREQUIS : Tu as ajouté des disques à ton serveur/VM

Exemple : 6 disques de 20 GB chacun
/dev/sdb : 20 GB
/dev/sdc : 20 GB
/dev/sdd : 20 GB
/dev/sde : 20 GB
/dev/sdf : 20 GB
/dev/sdg : 20 GB

[ATTENTION] ATTENTION : Les disques doivent être VIERGES (pas de données importantes)
ASM va prendre le contrôle TOTAL des disques !
"""

# ÉTAPE 11 : VÉRIFIER LES DISQUES DISPONIBLES
lsblk

# Sortie typique :
"""
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda      8:0    0   50G  0 disk 
├─sda1   8:1    0    1M  0 part 
├─sda2   8:2    0    1G  0 part /boot
└─sda3   8:3    0   49G  0 part /
sdb      8:16   0   20G  0 disk            <- Disque pour ASM
sdc      8:32   0   20G  0 disk            <- Disque pour ASM
sdd      8:48   0   20G  0 disk            <- Disque pour ASM
sde      8:64   0   20G  0 disk            <- Disque pour ASM
sdf      8:80   0   20G  0 disk            <- Disque pour ASM
sdg      8:96   0   20G  0 disk            <- Disque pour ASM
"""

# Vérifier qu'aucun disque n'est monté ou utilisé
sudo fdisk -l /dev/sdb
sudo fdisk -l /dev/sdc
# ... etc pour tous les disques

# S'assurer qu'il n'y a PAS de partitions
# Si des partitions existent, les supprimer :
sudo parted /dev/sdb --script mklabel gpt  # Efface tout et crée une table GPT vierge
sudo parted /dev/sdc --script mklabel gpt
sudo parted /dev/sdd --script mklabel gpt
sudo parted /dev/sde --script mklabel gpt
sudo parted /dev/sdf --script mklabel gpt
sudo parted /dev/sdg --script mklabel gpt


# === MÉTHODE 2 : CRÉATION DE LOOP DEVICES (SIMULATION) ===

"""
Si tu n'as pas de disques physiques, tu peux SIMULER avec des fichiers
"""

# Créer un répertoire pour stocker les fichiers
sudo mkdir -p /u02/asmdisks

# Créer 6 fichiers de 20 GB chacun
sudo dd if=/dev/zero of=/u02/asmdisks/asm_disk1.img bs=1M count=20480
sudo dd if=/dev/zero of=/u02/asmdisks/asm_disk2.img bs=1M count=20480
sudo dd if=/dev/zero of=/u02/asmdisks/asm_disk3.img bs=1M count=20480
sudo dd if=/dev/zero of=/u02/asmdisks/asm_disk4.img bs=1M count=20480
sudo dd if=/dev/zero of=/u02/asmdisks/asm_disk5.img bs=1M count=20480
sudo dd if=/dev/zero of=/u02/asmdisks/asm_disk6.img bs=1M count=20480

# Associer les fichiers à des loop devices
sudo losetup /dev/loop10 /u02/asmdisks/asm_disk1.img
sudo losetup /dev/loop11 /u02/asmdisks/asm_disk2.img
sudo losetup /dev/loop12 /u02/asmdisks/asm_disk3.img
sudo losetup /dev/loop13 /u02/asmdisks/asm_disk4.img
sudo losetup /dev/loop14 /u02/asmdisks/asm_disk5.img
sudo losetup /dev/loop15 /u02/asmdisks/asm_disk6.img

# Vérifier
losetup -a

# Rendre persistant au reboot (ajouter à /etc/rc.local)
sudo tee -a /etc/rc.local > /dev/null <<'EOF'
losetup /dev/loop10 /u02/asmdisks/asm_disk1.img
losetup /dev/loop11 /u02/asmdisks/asm_disk2.img
losetup /dev/loop12 /u02/asmdisks/asm_disk3.img
losetup /dev/loop13 /u02/asmdisks/asm_disk4.img
losetup /dev/loop14 /u02/asmdisks/asm_disk5.img
losetup /dev/loop15 /u02/asmdisks/asm_disk6.img
EOF

sudo chmod +x /etc/rc.local


# === CONFIGURATION DES RÈGLES UDEV (IMPORTANT !) ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│                    POURQUOI UDEV EST NÉCESSAIRE ?                      │
└────────────────────────────────────────────────────────────────────────┘

PROBLÈME :
-> Les noms de périphériques Linux (/dev/sdb, /dev/sdc) peuvent CHANGER
-> Au reboot, /dev/sdb peut devenir /dev/sdc
-> ASM ne pourra plus trouver ses disques ! [X]

SOLUTION : UDEV
-> Créer des noms PERSISTANTS pour les disques ASM
-> Exemple : /dev/oracleasm/disk1, /dev/oracleasm/disk2
-> Ces noms ne changent JAMAIS, même après reboot [OK]

COMMENT UDEV FONCTIONNE ?
-> UDEV détecte les disques par leurs attributs uniques (UUID, serial, etc.)
-> UDEV crée des liens symboliques avec des noms personnalisés
-> ASM utilise ces noms persistants
"""

# ÉTAPE 12 : IDENTIFIER LES ATTRIBUTS DES DISQUES

# Pour chaque disque, récupérer son UUID ou Serial Number
sudo udevadm info --query=all --name=/dev/sdb | grep -E "ID_SERIAL|ID_WWN"
sudo udevadm info --query=all --name=/dev/sdc | grep -E "ID_SERIAL|ID_WWN"
# ... etc

# Exemple de sortie :
# E: ID_SERIAL=WD-WCAZU1234567
# E: ID_WWN=0x50014ee2b1234567

# Alternative : utiliser le device path
udevadm info --query=path --name=/dev/sdb


# ÉTAPE 13 : CRÉER LES RÈGLES UDEV

# Méthode avec WWN (World Wide Name) - RECOMMANDÉ
sudo tee /etc/udev/rules.d/99-oracle-asmdevices.rules > /dev/null <<'EOF'
# Règles UDEV pour les disques Oracle ASM
# Format : KERNEL=="sd?", ENV{ID_WWN}=="<WWN>", SYMLINK+="oracleasm/diskX", OWNER="grid", GROUP="asmadmin", MODE="0660"

# Disque 1
KERNEL=="sd?", ENV{ID_WWN}=="0x50014ee2b1234567", SYMLINK+="oracleasm/disk1", OWNER="grid", GROUP="asmadmin", MODE="0660"

# Disque 2
KERNEL=="sd?", ENV{ID_WWN}=="0x50014ee2b1234568", SYMLINK+="oracleasm/disk2", OWNER="grid", GROUP="asmadmin", MODE="0660"

# Disque 3
KERNEL=="sd?", ENV{ID_WWN}=="0x50014ee2b1234569", SYMLINK+="oracleasm/disk3", OWNER="grid", GROUP="asmadmin", MODE="0660"

# Disque 4
KERNEL=="sd?", ENV{ID_WWN}=="0x50014ee2b1234570", SYMLINK+="oracleasm/disk4", OWNER="grid", GROUP="asmadmin", MODE="0660"

# Disque 5
KERNEL=="sd?", ENV{ID_WWN}=="0x50014ee2b1234571", SYMLINK+="oracleasm/disk5", OWNER="grid", GROUP="asmadmin", MODE="0660"

# Disque 6
KERNEL=="sd?", ENV{ID_WWN}=="0x50014ee2b1234572", SYMLINK+="oracleasm/disk6", OWNER="grid", GROUP="asmadmin", MODE="0660"
EOF

# [ATTENTION] REMPLACER LES WWN PAR LES VRAIS WWN DE TES DISQUES !

# Méthode alternative avec le chemin du device (moins fiable)
sudo tee /etc/udev/rules.d/99-oracle-asmdevices.rules > /dev/null <<'EOF'
# Règles UDEV pour les disques Oracle ASM (basées sur les noms de devices)

KERNEL=="sdb", SYMLINK+="oracleasm/disk1", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="sdc", SYMLINK+="oracleasm/disk2", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="sdd", SYMLINK+="oracleasm/disk3", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="sde", SYMLINK+="oracleasm/disk4", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="sdf", SYMLINK+="oracleasm/disk5", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="sdg", SYMLINK+="oracleasm/disk6", OWNER="grid", GROUP="asmadmin", MODE="0660"
EOF

# Pour les loop devices (si tu utilises la méthode simulation)
sudo tee /etc/udev/rules.d/99-oracle-asmdevices.rules > /dev/null <<'EOF'
# Règles UDEV pour les loop devices ASM

KERNEL=="loop10", SYMLINK+="oracleasm/disk1", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="loop11", SYMLINK+="oracleasm/disk2", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="loop12", SYMLINK+="oracleasm/disk3", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="loop13", SYMLINK+="oracleasm/disk4", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="loop14", SYMLINK+="oracleasm/disk5", OWNER="grid", GROUP="asmadmin", MODE="0660"
KERNEL=="loop15", SYMLINK+="oracleasm/disk6", OWNER="grid", GROUP="asmadmin", MODE="0660"
EOF


# ÉTAPE 14 : RECHARGER LES RÈGLES UDEV
sudo udevadm control --reload-rules
sudo udevadm trigger

# Vérifier que les liens symboliques sont créés
ls -l /dev/oracleasm/

# Sortie attendue :
"""
total 0
lrwxrwxrwx 1 root root 6 Dec 19 10:00 disk1 -> ../sdb
lrwxrwxrwx 1 root root 6 Dec 19 10:00 disk2 -> ../sdc
lrwxrwxrwx 1 root root 6 Dec 19 10:00 disk3 -> ../sdd
lrwxrwxrwx 1 root root 6 Dec 19 10:00 disk4 -> ../sde
lrwxrwxrwx 1 root root 6 Dec 19 10:00 disk5 -> ../sdf
lrwxrwxrwx 1 root root 6 Dec 19 10:00 disk6 -> ../sdg
"""

# Vérifier les permissions
ls -l /dev/oracleasm/disk1

# Sortie attendue :
# lrwxrwxrwx 1 root root 6 Dec 19 10:00 /dev/oracleasm/disk1 -> ../sdb

ls -l /dev/sdb

# Sortie attendue :
# brw-rw---- 1 grid asmadmin 8, 16 Dec 19 10:00 /dev/sdb
#            ^     ^          ^  ^
#          owner group      major minor


[OK] PARTIE 4 : INSTALLATION DE GRID INFRASTRUCTURE (ASM)

# === TÉLÉCHARGEMENT DU LOGICIEL ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│              TÉLÉCHARGEMENT ORACLE GRID INFRASTRUCTURE                 │
└────────────────────────────────────────────────────────────────────────┘

1. Aller sur https://www.oracle.com/database/technologies/oracle19c-linux-downloads.html
2. Télécharger "Oracle Database 19c Grid Infrastructure (19.3) for Linux x86-64"
3. Fichier : LINUX.X64_193000_grid_home.zip (~3 GB)
4. Transférer sur le serveur dans /u01/stage/grid/
"""

# ÉTAPE 15 : PRÉPARER LE LOGICIEL (en tant que root)
sudo mkdir -p /u01/stage/grid
sudo chown grid:oinstall /u01/stage/grid

# Transférer le fichier (via scp, sftp, ou copier depuis un montage)
# Exemple :
# scp LINUX.X64_193000_grid_home.zip user@server:/u01/stage/grid/

# Décompresser DIRECTEMENT dans GRID_HOME (IMPORTANT !)
sudo su - grid
cd /u01/app/19.3.0/grid
unzip /u01/stage/grid/LINUX.X64_193000_grid_home.zip

# [ATTENTION] NE PAS extraire dans un répertoire temporaire puis copier !
# Grid Infrastructure DOIT être extrait directement dans GRID_HOME

# Vérifier
ls -l /u01/app/19.3.0/grid/
# Tu dois voir : bin/ lib/ network/ install/ etc.


# === INSTALLATION SILENCIEUSE DE GRID INFRASTRUCTURE ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│              INSTALLATION GRID INFRASTRUCTURE (MODE SILENT)            │
└────────────────────────────────────────────────────────────────────────┘

Oracle propose deux modes d'installation :
1. GUI (graphique) : nécessite X Window
2. SILENT (silencieux) : via fichier de réponse (response file)

On utilise le mode SILENT car :
[OK] Reproductible (script)
[OK] Pas besoin d'interface graphique
[OK] Idéal pour automatisation
"""

# ÉTAPE 16 : CRÉER LE FICHIER DE RÉPONSE (RESPONSE FILE)
sudo su - grid

cat > /u01/stage/grid/grid_install.rsp <<'EOF'
####################################################################
## Copyright(c) Oracle Corporation 1998,2019. All rights reserved.##
##                                                                ##
## Response file for Grid Infrastructure Installation            ##
####################################################################

oracle.install.responseFileVersion=/oracle/install/rspfmt_crsinstall_response_schema_v19.0.0
oracle.install.option=HA_CONFIG

# Inventory Location
INVENTORY_LOCATION=/u01/app/oraInventory

# Oracle Base
ORACLE_BASE=/u01/app/grid

# ASM Password (for SYS and ASMSNMP)
# [ATTENTION] CHANGER CE MOT DE PASSE EN PRODUCTION !
oracle.install.asm.SYSASMPassword=Oracle123
oracle.install.asm.monitorPassword=Oracle123

# Disk Groups
oracle.install.asm.diskGroup.name=DATA
oracle.install.asm.diskGroup.redundancy=NORMAL
oracle.install.asm.diskGroup.AUSize=1
oracle.install.asm.diskGroup.disks=/dev/oracleasm/disk1,/dev/oracleasm/disk2,/dev/oracleasm/disk3,/dev/oracleasm/disk4
oracle.install.asm.diskGroup.diskDiscoveryString=/dev/oracleasm/*

# Optional : créer un second disk group pour FRA
oracle.install.asm.configureAFD=false

# Groupes Unix
oracle.install.asm.OSDBA=asmdba
oracle.install.asm.OSOPER=asmoper
oracle.install.asm.OSASM=asmadmin

# Ne pas configurer automatiquement GNS, MGMTDB, etc. (standalone)
oracle.install.crs.config.gpnp.configureGNS=false
oracle.install.crs.config.autoConfigureClusterNodeVIP=false
oracle.install.asm.configureGIMRDataDG=false

# Root scripts
oracle.install.config.executeRootScripts=false
EOF

# Explication des paramètres clés :
"""
oracle.install.option=HA_CONFIG
-> Configuration Haute Disponibilité (includes ASM)
-> Autres options : CRS_CONFIG (pour RAC), UPGRADE

ORACLE_BASE=/u01/app/grid
-> Répertoire de base pour Grid Infrastructure

oracle.install.asm.SYSASMPassword=Oracle123
-> Mot de passe pour le compte SYSASM
-> SYSASM = super-admin d'ASM (équivalent de SYS pour database)

oracle.install.asm.diskGroup.name=DATA
-> Nom du premier disk group à créer automatiquement

oracle.install.asm.diskGroup.redundancy=NORMAL
-> Niveau de redondance : EXTERNAL, NORMAL, ou HIGH

oracle.install.asm.diskGroup.disks=/dev/oracleasm/disk1,...
-> Liste des disques à inclure dans le disk group

oracle.install.asm.diskGroup.diskDiscoveryString=/dev/oracleasm/*
-> Pattern de recherche pour découvrir les disques ASM
-> ASM scannera tous les devices matching ce pattern

oracle.install.asm.OSDBA=asmdba
-> Groupe Unix pour le rôle OSDBA d'ASM
"""


# ÉTAPE 17 : LANCER L'INSTALLATION
sudo su - grid
cd /u01/app/19.3.0/grid

./gridSetup.sh -silent -responseFile /u01/stage/grid/grid_install.rsp

# L'installation va durer 20-40 minutes
# Tu verras des messages de progression

# À UN MOMENT, l'installeur va demander d'exécuter des scripts en tant que root :
"""
As a root user, execute the following script(s):
        1. /u01/app/oraInventory/orainstRoot.sh
        2. /u01/app/19.3.0/grid/root.sh

Execute /u01/app/oraInventory/orainstRoot.sh on the following nodes: 
[server1]
Execute /u01/app/19.3.0/grid/root.sh on the following nodes: 
[server1]
"""

# OUVRIR UNE NOUVELLE FENÊTRE TERMINAL (en tant que root)
sudo /u01/app/oraInventory/orainstRoot.sh

# Sortie attendue :
"""
Changing permissions of /u01/app/oraInventory.
Adding read,write permissions for group.
Removing read,write,execute permissions for world.

Changing groupname of /u01/app/oraInventory to oinstall.
The execution of the script is complete.
"""

# Puis exécuter le second script
sudo /u01/app/19.3.0/grid/root.sh

# Ce script va :
# 1. Configurer les permissions
# 2. Créer les liens symboliques
# 3. Démarrer l'instance ASM
# 4. Créer le disk group DATA

# Sortie typique (extraits) :
"""
Performing root user operation.

The following environment variables are set as:
    ORACLE_OWNER= grid
    ORACLE_HOME=  /u01/app/19.3.0/grid

Entries will be added to the /etc/oratab file as needed by
Database Configuration Assistant when a database is created
Finished running generic part of root script.
Now product-specific root actions will be performed.

Relinking oracle with rac_on option
Using configuration parameter file: /u01/app/19.3.0/grid/crs/install/crsconfig_params
The log of current session can be found at:
  /u01/app/grid/crsdata/server1/crsconfig/rootcrs_server1_2024-12-19_10-30-00AM.log

2024/12/19 10:30:15 CLSRSC-594: Executing installation step 1 of 19: 'SetupTFA'.
...
2024/12/19 10:35:45 CLSRSC-343: Successfully created ASM disk group 'DATA'.
...
2024/12/19 10:40:12 CLSRSC-325: Configure Oracle Grid Infrastructure for a Standalone Server completed successfully.
"""

# IMPORTANT : Attendre que le script se termine COMPLÈTEMENT
# Peut prendre 10-20 minutes

# Une fois terminé, revenir à la fenêtre d'installation grid
# Appuyer sur Enter pour continuer

# L'installation se terminera avec un message de succès


# ÉTAPE 18 : VÉRIFIER L'INSTALLATION

# Vérifier l'état d'ASM
sudo su - grid
crsctl stat res -t

# Sortie attendue :
"""
--------------------------------------------------------------------------------
Name           Target  State        Server                   State details       
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.DATA.dg
               ONLINE  ONLINE       server1                  STABLE
ora.LISTENER.lsnr
               ONLINE  ONLINE       server1                  STABLE
ora.asm
               ONLINE  ONLINE       server1                  Started,STABLE
ora.ons
               OFFLINE OFFLINE      server1                  STABLE
--------------------------------------------------------------------------------
"""

# Vérifier que l'instance ASM est démarrée
ps -ef | grep asm_pmon
# Tu dois voir : grid ... asm_pmon_+ASM

# Se connecter à ASM
sqlplus / as sysasm

# Dans SQL*Plus :
SQL> SELECT instance_name, status FROM v$instance;

# Sortie :
"""
INSTANCE_NAME    STATUS
---------------- ------------
+ASM             OPEN
"""

# Vérifier les disk groups
SQL> SELECT name, state, type, total_mb, free_mb FROM v$asm_diskgroup;

# Sortie :
"""
NAME       STATE    TYPE      TOTAL_MB   FREE_MB
---------- -------- --------- ---------- ----------
DATA       MOUNTED  NORMAL    81920      81800
"""

# Vérifier les disques
SQL> SELECT path, name, header_status, mode_status, state, total_mb, free_mb 
     FROM v$asm_disk 
     ORDER BY group_number, disk_number;

# Sortie :
"""
PATH                    NAME       HEADER_STATUS MODE_STATUS STATE     TOTAL_MB  FREE_MB
----------------------- ---------- ------------- ----------- --------- --------- ---------
/dev/oracleasm/disk1    DATA_0000  MEMBER        ONLINE      NORMAL    20480     20400
/dev/oracleasm/disk2    DATA_0001  MEMBER        ONLINE      NORMAL    20480     20400
/dev/oracleasm/disk3    DATA_0002  MEMBER        ONLINE      NORMAL    20480     20400
/dev/oracleasm/disk4    DATA_0003  MEMBER        ONLINE      NORMAL    20480     20400
"""

# Quitter SQL*Plus
SQL> EXIT


[OK] PARTIE 5 : GESTION DES DISK GROUPS

# === CRÉATION D'UN SECOND DISK GROUP (FRA) ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│              CRÉATION D'UN DISK GROUP SUPPLÉMENTAIRE                   │
└────────────────────────────────────────────────────────────────────────┘

Nous allons créer un disk group "FRA" (Fast Recovery Area)
pour stocker les sauvegardes et archived redo logs
"""

# ÉTAPE 19 : CRÉER LE DISK GROUP FRA (en tant que grid)
sudo su - grid

sqlplus / as sysasm

SQL> CREATE DISKGROUP FRA NORMAL REDUNDANCY
     DISK '/dev/oracleasm/disk5',
          '/dev/oracleasm/disk6'
     ATTRIBUTE 'compatible.asm' = '19.0',
               'compatible.rdbms' = '19.0',
               'au_size' = '1M';

# Explication :
"""
FRA
-> Nom du disk group

NORMAL REDUNDANCY
-> Mirroring 2-way (2 copies)

DISK '/dev/oracleasm/disk5', '/dev/oracleasm/disk6'
-> Les 2 disques restants

ATTRIBUTE 'compatible.asm' = '19.0'
-> Niveau de compatibilité ASM (Oracle 19c)

'compatible.rdbms' = '19.0'
-> Niveau de compatibilité Database

'au_size' = '1M'
-> Taille des Allocation Units (1 MB)
"""

# Sortie :
"""
Diskgroup created.
"""

# Vérifier
SQL> SELECT name, state, type, total_mb, free_mb FROM v$asm_diskgroup;

"""
NAME       STATE    TYPE      TOTAL_MB   FREE_MB
---------- -------- --------- ---------- ----------
DATA       MOUNTED  NORMAL    81920      81800
FRA        MOUNTED  NORMAL    40960      40920
"""

SQL> EXIT


# === AJOUT DE DISQUES À UN DISK GROUP EXISTANT ===

"""
Supposons que tu veux ajouter des disques au disk group DATA
pour augmenter sa capacité
"""

# Ajouter un disque
sqlplus / as sysasm

SQL> ALTER DISKGROUP DATA ADD DISK '/dev/oracleasm/disk7';

# ASM va automatiquement :
# 1. Intégrer le nouveau disque
# 2. Commencer le RÉÉQUILIBRAGE en arrière-plan
# 3. Redistribuer les données sur tous les disques

# Suivre la progression du rééquilibrage
SQL> SELECT group_number, operation, state, power, actual, sofar, est_work, est_rate, est_minutes
     FROM v$asm_operation;

"""
GROUP_NUMBER OPERATION  STATE      POWER     ACTUAL      SOFAR   EST_WORK   EST_RATE EST_MINUTES
------------ ---------- ---------- --------- ---------- -------- ---------- ---------- -----------
           1 REBAL      RUN                1          1      1200      3000        150           12
"""

# Interpréter :
"""
GROUP_NUMBER : 1 = disk group DATA
OPERATION : REBAL = Rebalance
STATE : RUN = en cours
POWER : 1 = vitesse de rééquilibrage (1-11)
SOFAR : 1200 = MB déjà rééquilibrés
EST_WORK : 3000 = MB total à rééquilibrer
EST_RATE : 150 = MB/minute
EST_MINUTES : 12 = temps restant estimé
"""

# Une fois terminé, plus aucune ligne dans v$asm_operation

# Vérifier que le disque est intégré
SQL> SELECT name, path, state, total_mb, free_mb FROM v$asm_disk WHERE group_number = 1;


# === SUPPRESSION D'UN DISQUE (MAINTENANCE) ===

"""
Si un disque est défaillant ou que tu veux le remplacer
"""

# Identifier le disque à supprimer
SQL> SELECT disk_number, name, path, state FROM v$asm_disk WHERE group_number = 1;

"""
DISK_NUMBER NAME       PATH                     STATE
----------- ---------- ------------------------ ------
          0 DATA_0000  /dev/oracleasm/disk1     NORMAL
          1 DATA_0001  /dev/oracleasm/disk2     NORMAL
          2 DATA_0002  /dev/oracleasm/disk3     NORMAL
          3 DATA_0003  /dev/oracleasm/disk4     NORMAL
"""

# Supprimer le disque DATA_0003
SQL> ALTER DISKGROUP DATA DROP DISK DATA_0003;

# ASM va :
# 1. Marquer le disque comme "DROPPING"
# 2. Copier les données vers les autres disques
# 3. Retirer le disque du disk group

# Suivre la progression
SQL> SELECT name, state FROM v$asm_disk WHERE name = 'DATA_0003';

# États possibles :
# NORMAL -> En service
# DROPPING -> En cours de suppression
# (le disque disparaît de v$asm_disk une fois la suppression terminée)

# [ATTENTION] NE PAS forcer l'arrêt pendant une opération DROP !


# === MODIFICATION DES ATTRIBUTS D'UN DISK GROUP ===

# Changer la taille des AU (Allocation Units)
# [ATTENTION] Possible seulement à la création, PAS après !

# Changer le niveau de compatibilité (ATTENTION : irréversible !)
SQL> ALTER DISKGROUP DATA SET ATTRIBUTE 'compatible.asm' = '19.0';

# Changer la politique de redondance
# [ATTENTION] Impossible de changer EXTERNAL <-> NORMAL <-> HIGH
# Il faut recréer le disk group


[OK] PARTIE 6 : UTILISATION D'ASMCMD

# === INTRODUCTION À ASMCMD ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│                      ASMCMD - L'OUTIL DE GESTION ASM                   │
└────────────────────────────────────────────────────────────────────────┘

ASMCMD = Utilitaire en ligne de commande pour gérer ASM
-> Alternative à SQL*Plus
-> Interface plus intuitive (type Unix)
-> Commandes similaires à bash : ls, cd, pwd, cp, rm, etc.
"""

# ÉTAPE 20 : LANCER ASMCMD (en tant que grid)
sudo su - grid
asmcmd

# Prompt :
"""
ASMCMD>
"""

# === COMMANDES DE NAVIGATION ===

# Lister les disk groups (équivalent de 'ls /')
ASMCMD> lsdg

# Sortie :
"""
State    Type    Rebal  Sector  Logical_Sector  Block       AU  Total_MB  Free_MB  Req_mir_free_MB  Usable_file_MB  Offline_disks  Voting_files  Name
MOUNTED  NORMAL  N         512             512   4096  1048576     81920    81800            20480           30660              0             N  DATA/
MOUNTED  NORMAL  N         512             512   4096  1048576     40960    40920            10240           15340              0             N  FRA/
"""

# Aller dans un disk group (équivalent de 'cd')
ASMCMD> cd +DATA

# Afficher le répertoire courant (équivalent de 'pwd')
ASMCMD> pwd
# +DATA

# Lister le contenu (équivalent de 'ls')
ASMCMD> ls
# ORCL/
# (vide si aucune database n'est créée encore)


# === COMMANDES DE GESTION DES FICHIERS ===

# Une fois qu'une database est créée sur ASM, tu verras :
ASMCMD> cd +DATA/ORCL
ASMCMD> ls
"""
CONTROLFILE/
DATAFILE/
ONLINELOG/
PARAMETERFILE/
TEMPFILE/
"""

ASMCMD> cd DATAFILE
ASMCMD> ls
"""
SYSTEM.256.1234567890
SYSAUX.257.1234567891
UNDOTBS1.258.1234567892
USERS.259.1234567893
"""

# Afficher les détails d'un fichier (équivalent de 'ls -l')
ASMCMD> ls -l
"""
Type      Redund  Striped  Time             Sys  Name
DATAFILE  MIRROR  COARSE   DEC 19 11:00:00  Y    SYSTEM.256.1234567890
DATAFILE  MIRROR  COARSE   DEC 19 11:00:00  Y    SYSAUX.257.1234567891
DATAFILE  MIRROR  COARSE   DEC 19 11:00:00  Y    UNDOTBS1.258.1234567892
DATAFILE  MIRROR  COARSE   DEC 19 11:00:00  N    USERS.259.1234567893
"""

# Afficher l'espace utilisé par un fichier
ASMCMD> du SYSTEM.256.1234567890
"""
Used_MB      Mirror_used_MB
    800                1600
"""
# 800 MB de données réelles
# 1600 MB utilisés (avec mirroring NORMAL)


# === COMMANDES DE GESTION DES DISK GROUPS ===

# Lister tous les disques
ASMCMD> lsdsk
"""
Path
/dev/oracleasm/disk1
/dev/oracleasm/disk2
/dev/oracleasm/disk3
/dev/oracleasm/disk4
/dev/oracleasm/disk5
/dev/oracleasm/disk6
"""

# Afficher les détails des disques
ASMCMD> lsdsk -k
"""
Total_MB  Free_MB  OS_MB  Name         Failgroup  Path
   20480    20400  20480  DATA_0000    DATA_0000  /dev/oracleasm/disk1
   20480    20400  20480  DATA_0001    DATA_0001  /dev/oracleasm/disk2
   20480    20400  20480  DATA_0002    DATA_0002  /dev/oracleasm/disk3
   20480    20400  20480  DATA_0003    DATA_0003  /dev/oracleasm/disk4
   20480    20460  20480  FRA_0000     FRA_0000   /dev/oracleasm/disk5
   20480    20460  20480  FRA_0001     FRA_0001   /dev/oracleasm/disk6
"""

# Afficher les templates (types de fichiers)
ASMCMD> lstmpl +DATA
"""
Name                     Stripe         Redundancy
ARCHIVELOG               COARSE         MIRROR
AUTOBACKUP               COARSE         MIRROR
BACKUPSET                COARSE         MIRROR
CONTROLFILE              FINE           HIGH
DATAFILE                 COARSE         MIRROR
ONLINELOG                FINE           MIRROR
PARAMETERFILE            COARSE         MIRROR
TEMPFILE                 COARSE         MIRROR
"""


# === COMMANDES DE COPIE ET SUPPRESSION ===

# Copier un fichier depuis le filesystem vers ASM
ASMCMD> cp /tmp/init.ora +DATA/ORCL/init.ora

# Copier depuis ASM vers le filesystem
ASMCMD> cp +DATA/ORCL/init.ora /tmp/init_backup.ora

# Supprimer un fichier ASM
ASMCMD> rm +DATA/ORCL/old_datafile.dbf

# [ATTENTION] ATTENTION : suppression DÉFINITIVE, pas de corbeille !


# === COMMANDES D'INFORMATION ===

# Afficher l'état d'ASM
ASMCMD> showclustermode
# ASM cluster : Flex mode

# Afficher la version d'ASM
ASMCMD> showversion
# 19.0.0.0.0

# Afficher les clients connectés à ASM
ASMCMD> lsct
"""
DB_Name  Status     Software_Version  Compatible_version  Instance_Name
ORCL     CONNECTED  19.0.0.0.0        19.0.0.0.0          ORCL
"""

# Afficher les opérations en cours (rééquilibrage, etc.)
ASMCMD> lsop

# Suite du fichier: python_cheats/cheatsheets/ASM.txt
# Oracle ASM (Automatic Storage Management) - Suite de la Configuration

"""
Sortie :
GROUP      OPERATION   STATE  POWER  ACTUAL  EST_WORK  EST_RATE  EST_MINUTES
1          REBAL       RUN    1      1       1000      50        20
"""

# Quitter ASMCMD
ASMCMD> exit


[OK] PARTIE 7 : INSTALLATION DE LA BASE DE DONNÉES AVEC ASM

# === INSTALLATION DU LOGICIEL DATABASE ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│           INSTALLATION ORACLE DATABASE 19c (UTILISATEUR oracle)        │
└────────────────────────────────────────────────────────────────────────┘

Maintenant que Grid Infrastructure (ASM) est installé et fonctionne,
nous allons installer le logiciel Oracle Database.

IMPORTANT : L'installation se fait avec l'utilisateur 'oracle', PAS 'grid' !
"""

# ÉTAPE 21 : TÉLÉCHARGER LE LOGICIEL DATABASE

"""
1. Aller sur https://www.oracle.com/database/technologies/oracle19c-linux-downloads.html
2. Télécharger "Oracle Database 19c (19.3) for Linux x86-64"
3. Fichier : LINUX.X64_193000_db_home.zip (~3 GB)
4. Transférer sur le serveur dans /u01/stage/database/
"""

# Préparer le répertoire (en tant que root)
sudo mkdir -p /u01/stage/database
sudo chown oracle:oinstall /u01/stage/database

# Basculer vers l'utilisateur oracle
sudo su - oracle

# Décompresser DIRECTEMENT dans ORACLE_HOME
cd $ORACLE_HOME
unzip /u01/stage/database/LINUX.X64_193000_db_home.zip

# Vérifier
ls -l $ORACLE_HOME/
# Tu dois voir : bin/ lib/ network/ install/ etc.


# ÉTAPE 22 : CRÉER LE FICHIER DE RÉPONSE POUR DATABASE

cat > /u01/stage/database/db_install.rsp <<'EOF'
####################################################################
## Copyright(c) Oracle Corporation 1998,2019. All rights reserved.##
##                                                                ##
## Response file for Oracle Database 19c Installation            ##
####################################################################

oracle.install.responseFileVersion=/oracle/install/rspfmt_dbinstall_response_schema_v19.0.0

# Type d'installation : SOFTWARE_ONLY (on créera la base après)
oracle.install.option=INSTALL_DB_SWONLY

# Informations système
UNIX_GROUP_NAME=oinstall

# Inventaire
INVENTORY_LOCATION=/u01/app/oraInventory

# Oracle Home
ORACLE_HOME=/u01/app/oracle/product/19.3.0/dbhome_1

# Oracle Base
ORACLE_BASE=/u01/app/oracle

# Type d'édition : EE = Enterprise Edition, SE2 = Standard Edition 2
oracle.install.db.InstallEdition=EE

# Groupes Unix
oracle.install.db.OSDBA_GROUP=dba
oracle.install.db.OSOPER_GROUP=oper
oracle.install.db.OSBACKUPDBA_GROUP=backupdba
oracle.install.db.OSDGDBA_GROUP=dgdba
oracle.install.db.OSKMDBA_GROUP=kmdba
oracle.install.db.OSRACDBA_GROUP=dba

# Ne pas exécuter automatiquement les scripts root
oracle.install.db.rootconfig.executeRootScript=false

# Pas de configuration automatique
oracle.install.db.config.starterdb.type=GENERAL_PURPOSE
oracle.install.db.ConfigureAsContainerDB=false
EOF


# ÉTAPE 23 : LANCER L'INSTALLATION DATABASE

cd $ORACLE_HOME

./runInstaller -silent -responseFile /u01/stage/database/db_install.rsp

# L'installation va durer 10-20 minutes

# À UN MOMENT, l'installeur va demander d'exécuter le script root :
"""
As a root user, execute the following script(s):
        1. /u01/app/oracle/product/19.3.0/dbhome_1/root.sh
"""

# OUVRIR UNE NOUVELLE FENÊTRE TERMINAL (en tant que root)
sudo /u01/app/oracle/product/19.3.0/dbhome_1/root.sh

# Sortie attendue :
"""
Check /u01/app/oracle/product/19.3.0/dbhome_1/install/root_server1_2024-12-19_12-00-00-123456789.log for the output of root script
"""

# Revenir à la fenêtre d'installation et appuyer sur Enter


# === CRÉATION D'UNE BASE DE DONNÉES SUR ASM ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│              CRÉATION DATABASE AVEC DBCA (Database Configuration       │
│                           Assistant)                                   │
└────────────────────────────────────────────────────────────────────────┘

DBCA = Outil Oracle pour créer/configurer des bases de données
Modes disponibles :
1. GUI (graphique)
2. SILENT (avec fichier de réponse)

On utilise SILENT pour automatisation et reproductibilité
"""

# ÉTAPE 24 : CRÉER LE FICHIER DE RÉPONSE DBCA

sudo su - oracle

cat > /u01/stage/database/dbca_create.rsp <<'EOF'
####################################################################
## Copyright(c) Oracle Corporation 1998,2019. All rights reserved.##
##                                                                ##
## Response file for DBCA (Database Creation)                    ##
####################################################################

responseFileVersion=/oracle/assistants/rspfmt_dbca_response_schema_v19.0.0

# Type d'opération : createDatabase
gdbName=ORCL
sid=ORCL
databaseConfigType=SI
createAsContainerDatabase=false

# Méthode de stockage : ASM
storageType=ASM

# Disk Group pour les fichiers de données
diskGroupName=+DATA

# Disk Group pour Fast Recovery Area (sauvegardes, archives)
recoveryGroupName=+FRA

# Type de base de données
templateName=General_Purpose.dbc

# Mots de passe
# [ATTENTION] CHANGER CES MOTS DE PASSE EN PRODUCTION !
sysPassword=Oracle123
systemPassword=Oracle123

# Mémoire
# SGA = System Global Area (cache, buffers)
# PGA = Program Global Area (mémoire privée des sessions)
totalMemory=2048
# 2048 MB = 2 GB total (SGA + PGA)

# Nombre de processus parallèles
processes=300

# Character Set
characterSet=AL32UTF8
nationalCharacterSet=AL16UTF16

# Listener
listeners=LISTENER

# Options de base de données
sampleSchema=false
automaticMemoryManagement=false
# On préfère la gestion manuelle pour plus de contrôle

# Tailles des fichiers
# Ces valeurs sont des suggestions, DBCA les ajustera selon besoin
datafileDestination=+DATA
recoveryAreaDestination=+FRA
recoveryAreaSize=10240
# 10240 MB = 10 GB pour Fast Recovery Area

# Types de fichiers
# SYSTEM, SYSAUX, UNDO, TEMP, USERS
# DBCA créera automatiquement ces tablespaces

# Options avancées
initParams=db_block_size=8192,processes=300,undo_management=AUTO,undo_tablespace=UNDOTBS1,db_recovery_file_dest_size=10G,db_recovery_file_dest=+FRA

# Ne pas ouvrir automatiquement la base après création
# (nous le ferons manuellement pour vérification)
createListener=false

EOF


# ÉTAPE 25 : LANCER LA CRÉATION DE LA BASE

# Vérifier que ASM est bien démarré
crsctl stat res -t | grep asm

# Sortie attendue :
"""
ora.asm
               ONLINE  ONLINE       server1                  Started,STABLE
"""

# Créer la base de données
dbca -silent -createDatabase -responseFile /u01/stage/database/dbca_create.rsp

# [ATTENTION] Cette opération prend 20-40 minutes
# DBCA va :
# 1. Créer les fichiers de contrôle sur +DATA
# 2. Créer les datafiles (SYSTEM, SYSAUX, UNDO, TEMP, USERS) sur +DATA
# 3. Créer les redo logs sur +DATA
# 4. Initialiser le dictionnaire de données
# 5. Configurer les paramètres d'initialisation
# 6. Démarrer la base de données

# Pendant l'exécution, tu verras :
"""
Prepare for db operation
7% complete
Copying database files
27% complete
Creating and starting Oracle instance
29% complete
31% complete
35% complete
37% complete
40% complete
Creating cluster database views
41% complete
53% complete
Completing Database Creation
57% complete
59% complete
60% complete
Creating Pluggable Databases
64% complete
80% complete
Executing Post Configuration Actions
100% complete
Database creation complete. For details check the logfiles at:
 /u01/app/oracle/cfgtoollogs/dbca/ORCL.
Database Information:
Global Database Name:ORCL
System Identifier(SID):ORCL
Look at the log file "/u01/app/oracle/cfgtoollogs/dbca/ORCL/ORCL.log" for further details.
"""


# ÉTAPE 26 : VÉRIFIER LA CRÉATION DE LA BASE

# Vérifier que l'instance est démarrée
ps -ef | grep pmon
# Tu dois voir : oracle ... ora_pmon_ORCL

# Se connecter à la base
sqlplus / as sysdba

# Vérifier l'état de la base
SQL> SELECT instance_name, status, database_status FROM v$instance;

# Sortie :
"""
INSTANCE_NAME    STATUS       DATABASE_STATUS
---------------- ------------ -----------------
ORCL             OPEN         ACTIVE
"""

# Vérifier les tablespaces
SQL> SELECT tablespace_name, contents, extent_management, segment_space_management 
     FROM dba_tablespaces;

# Sortie :
"""
TABLESPACE_NAME      CONTENTS  EXTENT_MANAGEMENT SEGMENT_SPACE_MANAGEMENT
-------------------- --------- ----------------- ------------------------
SYSTEM               PERMANENT LOCAL             MANUAL
SYSAUX               PERMANENT LOCAL             AUTO
UNDOTBS1             UNDO      LOCAL             MANUAL
TEMP                 TEMPORARY LOCAL             MANUAL
USERS                PERMANENT LOCAL             AUTO
"""

# Vérifier les datafiles (sur ASM)
SQL> SELECT file_name, tablespace_name, bytes/1024/1024 AS size_mb 
     FROM dba_data_files 
     ORDER BY tablespace_name;

# Sortie :
"""
FILE_NAME                                          TABLESPACE_NAME    SIZE_MB
-------------------------------------------------- ------------------ --------
+DATA/ORCL/DATAFILE/system.256.1234567890          SYSTEM             800
+DATA/ORCL/DATAFILE/sysaux.257.1234567891          SYSAUX             600
+DATA/ORCL/DATAFILE/undotbs1.258.1234567892        UNDOTBS1           100
+DATA/ORCL/DATAFILE/users.259.1234567893           USERS              5
"""

# Vérifier les fichiers de contrôle
SQL> SELECT name FROM v$controlfile;

# Sortie :
"""
NAME
----------------------------------------------------
+DATA/ORCL/CONTROLFILE/current.260.1234567894
+FRA/ORCL/CONTROLFILE/current.256.1234567895
"""

# Vérifier les redo logs
SQL> SELECT group#, thread#, bytes/1024/1024 AS size_mb, members, status 
     FROM v$log;

# Sortie :
"""
    GROUP#    THREAD#    SIZE_MB    MEMBERS STATUS
---------- ---------- ---------- ---------- ----------------
         1          1        200          1 CURRENT
         2          1        200          1 INACTIVE
         3          1        200          1 INACTIVE
"""

SQL> SELECT member FROM v$logfile;

# Sortie :
"""
MEMBER
----------------------------------------------------
+DATA/ORCL/ONLINELOG/group_1.261.1234567896
+DATA/ORCL/ONLINELOG/group_2.262.1234567897
+DATA/ORCL/ONLINELOG/group_3.263.1234567898
"""

SQL> EXIT


# ÉTAPE 27 : VÉRIFIER LES FICHIERS DANS ASMCMD

sudo su - grid
asmcmd

ASMCMD> cd +DATA/ORCL
ASMCMD> ls
"""
CONTROLFILE/
DATAFILE/
ONLINELOG/
PARAMETERFILE/
TEMPFILE/
"""

ASMCMD> cd DATAFILE
ASMCMD> ls -l
"""
Type      Redund  Striped  Time             Sys  Name
DATAFILE  MIRROR  COARSE   DEC 19 13:00:00  Y    SYSTEM.256.1234567890
DATAFILE  MIRROR  COARSE   DEC 19 13:00:00  Y    SYSAUX.257.1234567891
DATAFILE  MIRROR  COARSE   DEC 19 13:00:00  Y    UNDOTBS1.258.1234567892
DATAFILE  MIRROR  COARSE   DEC 19 13:00:00  N    USERS.259.1234567893
"""

# Vérifier l'espace utilisé dans les disk groups
ASMCMD> lsdg
"""
State    Type    Rebal  Sector  Logical_Sector  Block       AU  Total_MB  Free_MB  Req_mir_free_MB  Usable_file_MB  Offline_disks  Voting_files  Name
MOUNTED  NORMAL  N         512             512   4096  1048576     81920    80200            20480           29860              0             N  DATA/
MOUNTED  NORMAL  N         512             512   4096  1048576     40960    40700            10240           15230              0             N  FRA/
"""

# Explication :
"""
DATA :
- Total_MB : 81920 MB (4 disques × 20 GB chacun)
- Free_MB : 80200 MB (la base utilise ~1.7 GB)
- Usable_file_MB : 29860 MB disponibles pour de nouveaux fichiers
  (prend en compte le mirroring et l'espace réservé)

FRA :
- Total_MB : 40960 MB (2 disques × 20 GB chacun)
- Free_MB : 40700 MB (presque vide, sauvegardes pas encore faites)
- Usable_file_MB : 15230 MB disponibles
"""

ASMCMD> exit


[OK] PARTIE 8 : OPÉRATIONS COURANTES SUR ASM

# === AJOUT D'UN DATAFILE SUR ASM ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│                  GESTION DES FICHIERS DATABASE SUR ASM                 │
└────────────────────────────────────────────────────────────────────────┘

Toutes les opérations de gestion de fichiers se font via SQL,
ASM gère automatiquement le stockage physique
"""

# ÉTAPE 28 : AJOUTER UN DATAFILE À UN TABLESPACE

sudo su - oracle
sqlplus / as sysdba

# Ajouter un datafile au tablespace USERS
SQL> ALTER TABLESPACE users 
     ADD DATAFILE '+DATA' SIZE 100M AUTOEXTEND ON NEXT 10M MAXSIZE 1G;

# Explication :
"""
ALTER TABLESPACE users
-> Modifier le tablespace USERS

ADD DATAFILE '+DATA'
-> Créer un nouveau datafile sur le disk group DATA
-> PAS besoin de spécifier le nom complet !
-> ASM génère automatiquement : +DATA/ORCL/DATAFILE/users.264.1234567900

SIZE 100M
-> Taille initiale : 100 MB

AUTOEXTEND ON
-> Le fichier peut grandir automatiquement si besoin

NEXT 10M
-> Grandit par incréments de 10 MB

MAXSIZE 1G
-> Taille maximum : 1 GB
"""

# Sortie :
"""
Tablespace altered.
"""

# Vérifier
SQL> SELECT file_name, bytes/1024/1024 AS size_mb, autoextensible, maxbytes/1024/1024 AS max_mb
     FROM dba_data_files
     WHERE tablespace_name = 'USERS';

# Sortie :
"""
FILE_NAME                                          SIZE_MB AUTOEXTENSIBLE   MAX_MB
-------------------------------------------------- ------- -------------- --------
+DATA/ORCL/DATAFILE/users.259.1234567893                 5 YES            UNLIMITED
+DATA/ORCL/DATAFILE/users.264.1234567900               100 YES                1024
"""


# === CRÉATION D'UN NOUVEAU TABLESPACE SUR ASM ===

# Créer un tablespace pour une application
SQL> CREATE TABLESPACE app_data
     DATAFILE '+DATA' SIZE 500M AUTOEXTEND ON NEXT 50M MAXSIZE 5G
     EXTENT MANAGEMENT LOCAL AUTOALLOCATE
     SEGMENT SPACE MANAGEMENT AUTO;

# Explication :
"""
CREATE TABLESPACE app_data
-> Créer un nouveau tablespace nommé APP_DATA

DATAFILE '+DATA' SIZE 500M
-> Créer le datafile sur +DATA, taille initiale 500 MB

EXTENT MANAGEMENT LOCAL AUTOALLOCATE
-> Gestion des extents localement (dans le datafile)
-> AUTOALLOCATE : Oracle choisit la taille des extents automatiquement

SEGMENT SPACE MANAGEMENT AUTO
-> Gestion automatique de l'espace dans les segments (ASSM)
-> Recommandé pour les performances
"""

# Vérifier
SQL> SELECT tablespace_name, file_name, bytes/1024/1024 AS size_mb
     FROM dba_data_files
     WHERE tablespace_name = 'APP_DATA';


# === DÉPLACEMENT D'UN DATAFILE VERS ASM ===

"""
Scénario : Tu as une base existante sur filesystem classique,
tu veux migrer les datafiles vers ASM
"""

# MÉTHODE 1 : Avec la base ouverte (ALTER DATABASE MOVE DATAFILE)
# Disponible depuis Oracle 12c

SQL> ALTER DATABASE MOVE DATAFILE '/u01/oradata/ORCL/users01.dbf' 
     TO '+DATA';

# Oracle va :
# 1. Copier le fichier vers +DATA
# 2. Mettre à jour le fichier de contrôle
# 3. Supprimer l'ancien fichier
# Tout cela SANS arrêter la base ! [OK]


# MÉTHODE 2 : Avec RMAN (Plus flexible)

# Arrêter la base
SQL> SHUTDOWN IMMEDIATE;
SQL> EXIT

# Lancer RMAN
rman target /

# Démarrer la base en mode MOUNT (pas OPEN)
RMAN> STARTUP MOUNT;

# Copier et basculer tous les datafiles vers ASM
RMAN> BACKUP AS COPY DATABASE FORMAT '+DATA';
RMAN> SWITCH DATABASE TO COPY;

# Ouvrir la base
RMAN> ALTER DATABASE OPEN;

# Vérifier
RMAN> REPORT SCHEMA;

# Sortie :
"""
List of Permanent Datafiles
===========================
File Size(MB) Tablespace           Name
---- -------- -------------------- -------------------------------------
1    800      SYSTEM               +DATA/ORCL/DATAFILE/system.256.1234567890
2    600      SYSAUX               +DATA/ORCL/DATAFILE/sysaux.257.1234567891
3    100      UNDOTBS1             +DATA/ORCL/DATAFILE/undotbs1.258.1234567892
4    5        USERS                +DATA/ORCL/DATAFILE/users.259.1234567893
"""

RMAN> EXIT


# === REDIMENSIONNEMENT D'UN DATAFILE ===

sudo su - oracle
sqlplus / as sysdba

# Agrandir un datafile
SQL> ALTER DATABASE DATAFILE '+DATA/ORCL/DATAFILE/users.259.1234567893' 
     RESIZE 200M;

# Activer/désactiver l'autoextend
SQL> ALTER DATABASE DATAFILE '+DATA/ORCL/DATAFILE/users.259.1234567893'
     AUTOEXTEND ON NEXT 10M MAXSIZE 2G;


# === SUPPRESSION D'UN DATAFILE ===

# Supprimer un datafile d'un tablespace (le tablespace doit avoir d'autres datafiles)
SQL> ALTER TABLESPACE users 
     DROP DATAFILE '+DATA/ORCL/DATAFILE/users.264.1234567900';

# ASM supprime automatiquement le fichier du disk group


# === GESTION DES REDO LOGS SUR ASM ===

"""
Les redo logs sont CRITIQUES pour la base de données
Recommandations :
[OK] Utiliser MULTIPLEXING (plusieurs copies)
[OK] Les placer sur des disk groups séparés si possible
[OK] Utiliser la redondance HIGH pour les redo logs
"""

# Ajouter un nouveau groupe de redo log
SQL> ALTER DATABASE ADD LOGFILE GROUP 4 ('+DATA', '+FRA') SIZE 200M;

# Explication :
"""
GROUP 4
-> Numéro du groupe (doit être unique)

('+DATA', '+FRA')
-> MULTIPLEXING : créer une copie sur +DATA ET une copie sur +FRA
-> Si un disk group meurt, l'autre copie est toujours disponible ! [OK]

SIZE 200M
-> Taille de chaque membre : 200 MB
"""

# Vérifier
SQL> SELECT group#, member FROM v$logfile ORDER BY group#;

# Sortie :
"""
    GROUP# MEMBER
---------- --------------------------------------------------
         1 +DATA/ORCL/ONLINELOG/group_1.261.1234567896
         2 +DATA/ORCL/ONLINELOG/group_2.262.1234567897
         3 +DATA/ORCL/ONLINELOG/group_3.263.1234567898
         4 +DATA/ORCL/ONLINELOG/group_4.265.1234567901
         4 +FRA/ORCL/ONLINELOG/group_4.257.1234567902
"""

# Supprimer un groupe de redo log (doit être INACTIVE, pas CURRENT)
SQL> ALTER DATABASE DROP LOGFILE GROUP 1;

# Ajouter un membre à un groupe existant
SQL> ALTER DATABASE ADD LOGFILE MEMBER '+FRA' TO GROUP 2;


# === GESTION DES FICHIERS DE CONTRÔLE ===

# Vérifier les fichiers de contrôle actuels
SQL> SELECT name FROM v$controlfile;

# Ajouter un fichier de contrôle supplémentaire

# 1. Arrêter la base
SQL> SHUTDOWN IMMEDIATE;

# 2. Éditer le SPFILE pour ajouter le nouveau controlfile
# Démarrer en mode NOMOUNT
SQL> STARTUP NOMOUNT;

# 3. Créer un PFILE temporaire depuis le SPFILE
SQL> CREATE PFILE='/tmp/init_temp.ora' FROM SPFILE;

# 4. Éditer /tmp/init_temp.ora et modifier la ligne control_files :
# control_files='+DATA/ORCL/CONTROLFILE/current.260.1234567894','+FRA/ORCL/CONTROLFILE/current.256.1234567895','+DATA/ORCL/CONTROLFILE/current2.266.1234567903'

# 5. Recréer le SPFILE
SQL> CREATE SPFILE FROM PFILE='/tmp/init_temp.ora';

# 6. Redémarrer en mode MOUNT
SQL> SHUTDOWN IMMEDIATE;
SQL> STARTUP MOUNT;

# 7. Copier un controlfile existant vers le nouveau emplacement
SQL> ALTER DATABASE BACKUP CONTROLFILE TO '+DATA/ORCL/CONTROLFILE/current2.266.1234567903' REUSE;

# 8. Ouvrir la base
SQL> ALTER DATABASE OPEN;

# Vérifier
SQL> SELECT name FROM v$controlfile;


[OK] PARTIE 9 : MAINTENANCE ET MONITORING ASM

# === SURVEILLANCE DE L'ESPACE DISQUE ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│                    MONITORING DE L'ESPACE ASM                          │
└────────────────────────────────────────────────────────────────────────┘

Il est CRUCIAL de surveiller l'espace disponible dans les disk groups
pour éviter les problèmes de manque d'espace
"""

# ÉTAPE 29 : SURVEILLER L'ESPACE DES DISK GROUPS

sudo su - grid
sqlplus / as sysasm

# Vue d'ensemble des disk groups
SQL> SELECT name, 
            state, 
            type, 
            total_mb, 
            free_mb, 
            required_mirror_free_mb,
            usable_file_mb,
            ROUND((1 - (free_mb / total_mb)) * 100, 2) AS pct_used
     FROM v$asm_diskgroup;

# Sortie :
"""
NAME  STATE   TYPE    TOTAL_MB  FREE_MB  REQ_MIR_FREE_MB  USABLE_FILE_MB  PCT_USED
----- ------- ------- --------- -------- ---------------- --------------- --------
DATA  MOUNTED NORMAL  81920     80200    20480            29860           2.10
FRA   MOUNTED NORMAL  40960     40700    10240            15230           0.63
"""

# Explication détaillée :
"""
TOTAL_MB : Espace total brut (somme de tous les disques)

FREE_MB : Espace libre actuel

REQUIRED_MIRROR_FREE_MB : Espace réservé pour reconstruction
-> En cas de panne d'un disque, ASM a besoin d'espace pour reconstruire
-> Avec NORMAL redundancy : ~25% du total
-> Avec HIGH redundancy : ~33% du total

USABLE_FILE_MB : Espace réellement utilisable pour de nouveaux fichiers
-> Formule (NORMAL) : (FREE_MB - REQUIRED_MIRROR_FREE_MB) / 2
-> Le /2 car chaque fichier est dupliqué (mirroring)

PCT_USED : Pourcentage d'utilisation
"""

# Détail par disque
SQL> SELECT dg.name AS diskgroup,
            d.name AS disk_name,
            d.path,
            d.total_mb,
            d.free_mb,
            ROUND((1 - (d.free_mb / d.total_mb)) * 100, 2) AS pct_used,
            d.state
     FROM v$asm_disk d
     JOIN v$asm_diskgroup dg ON d.group_number = dg.group_number
     ORDER BY dg.name, d.name;

# Sortie :
"""
DISKGROUP DISK_NAME  PATH                     TOTAL_MB  FREE_MB  PCT_USED STATE
--------- ---------- ------------------------ --------- -------- -------- ------
DATA      DATA_0000  /dev/oracleasm/disk1     20480     20050    2.10     NORMAL
DATA      DATA_0001  /dev/oracleasm/disk2     20480     20050    2.10     NORMAL
DATA      DATA_0002  /dev/oracleasm/disk3     20480     20050    2.10     NORMAL
DATA      DATA_0003  /dev/oracleasm/disk4     20480     20050    2.10     NORMAL
FRA       FRA_0000   /dev/oracleasm/disk5     20480     20350    0.63     NORMAL
FRA       FRA_0001   /dev/oracleasm/disk6     20480     20350    0.63     NORMAL
"""

# [ATTENTION] ALERTE SI :
# - PCT_USED > 80% : Ajouter des disques bientôt
# - PCT_USED > 90% : URGENT, ajouter des disques immédiatement
# - STATE != NORMAL : Problème matériel


# === SURVEILLANCE DES OPÉRATIONS ASM ===

# Voir les opérations en cours (rééquilibrage, resize, etc.)
SQL> SELECT group_number,
            operation,
            state,
            power,
            actual,
            sofar,
            est_work,
            est_rate,
            est_minutes
     FROM v$asm_operation;

# Sortie (pendant un rééquilibrage) :
"""
GRP_NUM OPERATION  STATE   POWER  ACTUAL  SOFAR  EST_WORK  EST_RATE  EST_MINUTES
------- ---------- ------- ------ ------- ------ --------- --------- -----------
1       REBAL      RUN     1      1       2500   5000      200       12
"""

# Si vide : aucune opération en cours [OK]


# === ALERTES ET LOGS ASM ===

# Consulter le fichier d'alerte ASM
SQL> SELECT name, value FROM v$diag_info WHERE name = 'Diag Alert';

# Sortie :
"""
NAME        VALUE
----------- --------------------------------------------------------
Diag Alert  /u01/app/grid/diag/asm/+asm/+ASM/trace/alert_+ASM.log
"""

# Examiner les alertes récentes (en tant que grid)
sudo su - grid
tail -100 /u01/app/grid/diag/asm/+asm/+ASM/trace/alert_+ASM.log

# Chercher des erreurs
grep -i "error\|warning\|failure" /u01/app/grid/diag/asm/+asm/+ASM/trace/alert_+ASM.log | tail -50


# === VÉRIFICATION DE LA SANTÉ DES DISQUES ===

sudo su - grid
sqlplus / as sysasm

# État général des disques
SQL> SELECT path, header_status, mode_status, state, total_mb, free_mb
     FROM v$asm_disk
     WHERE header_status != 'MEMBER' OR mode_status != 'ONLINE' OR state != 'NORMAL';

# Si cette requête retourne des lignes : PROBLÈME !
# Sortie normale (vide) : aucun problème


# Historique des pannes de disques
SQL> SELECT group_number,
            disk_number,
            event_time,
            error_count,
            bytes_read,
            bytes_written,
            io_count
     FROM v$asm_disk_iostat
     WHERE error_count > 0
     ORDER BY event_time DESC;


# === SCRIPTS DE MONITORING AUTOMATIQUE ===

# ÉTAPE 30 : CRÉER UN SCRIPT DE MONITORING

sudo su - grid

cat > ~/monitor_asm.sh <<'EOF'
#!/bin/bash
# Script de monitoring ASM
# Usage : ./monitor_asm.sh

export ORACLE_HOME=/u01/app/19.3.0/grid
export ORACLE_SID=+ASM
export PATH=$ORACLE_HOME/bin:$PATH

echo "═══════════════════════════════════════════════════════════════"
echo "   ASM HEALTH CHECK - $(date)"
echo "═══════════════════════════════════════════════════════════════"
echo

# 1. Vérifier que l'instance ASM est démarrée
echo "1. Instance ASM Status:"
echo "━━━━━━━━━━━━━━━━━━━━━━"
ps -ef | grep asm_pmon | grep -v grep > /dev/null
if [ $? -eq 0 ]; then
    echo "[OK] ASM instance is RUNNING"
else
    echo "[X] ASM instance is NOT RUNNING"
    exit 1
fi
echo

# 2. État des disk groups
echo "2. Disk Groups Space Usage:"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━"
sqlplus -s / as sysasm <<SQL
SET PAGESIZE 50 LINESIZE 150
COLUMN name FORMAT A10
COLUMN state FORMAT A10
COLUMN type FORMAT A10
COLUMN total_mb FORMAT 999,999
COLUMN free_mb FORMAT 999,999
COLUMN usable_mb FORMAT 999,999
COLUMN pct_used FORMAT 999.99

SELECT name,
       state,
       type,
       total_mb,
       free_mb,
       usable_file_mb AS usable_mb,
       ROUND((1 - (free_mb / total_mb)) * 100, 2) AS pct_used
FROM v\$asm_diskgroup;
SQL
echo

# 3. État des disques
echo "3. Disk Status:"
echo "━━━━━━━━━━━━━━━━━━"
sqlplus -s / as sysasm <<SQL
SET PAGESIZE 50 LINESIZE 150
COLUMN name FORMAT A15
COLUMN path FORMAT A30
COLUMN state FORMAT A10
COLUMN total_mb FORMAT 999,999
COLUMN free_mb FORMAT 999,999

SELECT name, path, state, total_mb, free_mb
FROM v\$asm_disk
ORDER BY name;
SQL
echo

# 4. Opérations en cours
echo "4. ASM Operations in Progress:"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
OPS=$(sqlplus -s / as sysasm <<SQL
SET HEADING OFF FEEDBACK OFF
SELECT COUNT(*) FROM v\$asm_operation;
SQL
)

if [ "$OPS" -eq 0 ]; then
    echo "[OK] No operations in progress"
else
    echo "[ATTENTION]  $OPS operation(s) in progress:"
    sqlplus -s / as sysasm <<SQL
    SET PAGESIZE 50 LINESIZE 150
    COLUMN operation FORMAT A15
    COLUMN state FORMAT A10
    SELECT group_number, operation, state, power, sofar, est_work, est_minutes
    FROM v\$asm_operation;
SQL
fi
echo

# 5. Alertes critiques
echo "5. Critical Alerts (last 24h):"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
ALERT_LOG=$(sqlplus -s / as sysasm <<SQL
SET HEADING OFF FEEDBACK OFF
SELECT value FROM v\$diag_info WHERE name = 'Diag Alert';
SQL
)

CRITICAL=$(grep -i "error\|failure\|corrupt" "$ALERT_LOG" | tail -10 | wc -l)

if [ "$CRITICAL" -eq 0 ]; then
    echo "[OK] No critical alerts in last 24 hours"
else
    echo "[ATTENTION]  $CRITICAL critical alert(s) found:"
    grep -i "error\|failure\|corrupt" "$ALERT_LOG" | tail -10
fi
echo

echo "═══════════════════════════════════════════════════════════════"
echo "   Monitoring complete"
echo "═══════════════════════════════════════════════════════════════"
EOF

chmod +x ~/monitor_asm.sh

# Tester le script
~/monitor_asm.sh


# Programmer l'exécution automatique (crontab)
# Exécuter toutes les heures et envoyer un email si problème
crontab -e

# Ajouter la ligne :
# 0 * * * * /home/grid/monitor_asm.sh > /tmp/asm_check.log 2>&1


[OK] PARTIE 10 : BACKUP ET RECOVERY AVEC ASM

# === SAUVEGARDE AVEC RMAN SUR ASM ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│                   BACKUP ET RECOVERY AVEC RMAN + ASM                   │
└────────────────────────────────────────────────────────────────────────┘

RMAN (Recovery Manager) est l'outil standard Oracle pour les sauvegardes
Il s'intègre parfaitement avec ASM
"""

# ÉTAPE 31 : CONFIGURER RMAN POUR UTILISER ASM

sudo su - oracle

# Lancer RMAN
rman target /

# Configurer le Fast Recovery Area (FRA) sur ASM
RMAN> CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT '+FRA';

# Sortie :
"""
new RMAN configuration parameters:
CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT   '+FRA';
new RMAN configuration parameters are successfully stored
"""

# Configurer la rétention des sauvegardes (7 jours)
RMAN> CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;

# Configurer l'auto-backup du fichier de contrôle
RMAN> CONFIGURE CONTROLFILE AUTOBACKUP ON;
RMAN> CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '+FRA/%F';

# Afficher la configuration
RMAN> SHOW ALL;

# Sortie :
"""
RMAN configuration parameters for database with db_unique_name ORCL are:
CONFIGURE RETENTION POLICY TO RECOVERY WINDOW OF 7 DAYS;
CONFIGURE BACKUP OPTIMIZATION OFF;
CONFIGURE DEFAULT DEVICE TYPE TO DISK;
CONFIGURE CONTROLFILE AUTOBACKUP ON;
CONFIGURE CONTROLFILE AUTOBACKUP FORMAT FOR DEVICE TYPE DISK TO '+FRA/%F';
CONFIGURE DEVICE TYPE DISK PARALLELISM 1 BACKUP TYPE TO BACKUPSET;
CONFIGURE DATAFILE BACKUP COPIES FOR DEVICE TYPE DISK TO 1;
CONFIGURE ARCHIVELOG BACKUP COPIES FOR DEVICE TYPE DISK TO 1;
CONFIGURE CHANNEL DEVICE TYPE DISK FORMAT   '+FRA';
CONFIGURE MAXSETSIZE TO UNLIMITED;
CONFIGURE ENCRYPTION FOR DATABASE OFF;
CONFIGURE ENCRYPTION ALGORITHM 'AES128';
CONFIGURE COMPRESSION ALGORITHM 'BASIC' AS OF RELEASE 'DEFAULT' OPTIMIZE FOR LOAD TRUE;
CONFIGURE ARCHIVELOG DELETION POLICY TO NONE;
CONFIGURE SNAPSHOT CONTROLFILE NAME TO '/u01/app/oracle/product/19.3.0/dbhome_1/dbs/snapcf_ORCL.f';
"""


# === SAUVEGARDE COMPLÈTE (FULL BACKUP) ===

# Sauvegarde complète de la base + archived redo logs
RMAN> BACKUP DATABASE PLUS ARCHIVELOG;

# RMAN va :
# 1. Sauvegarder tous les archived redo logs
# 2. Sauvegarder tous les datafiles
# 3. Sauvegarder les fichiers de contrôle
# 4. Sauvegarder le SPFILE
# 5. Sauvegarder à nouveau les archived redo logs créés pendant la sauvegarde

# Sortie typique :
"""
Starting backup at 19-DEC-24
current log archived
using channel ORA_DISK_1
channel ORA_DISK_1: starting archived log backup set
channel ORA_DISK_1: specifying archived log(s) in backup set
input archived log thread=1 sequence=1 RECID=1 STAMP=1234567890
channel ORA_DISK_1: starting piece 1 at 19-DEC-24
channel ORA_DISK_1: finished piece 1 at 19-DEC-24
piece handle=+FRA/ORCL/BACKUPSET/2024_12_19/annnnn_TAG20241219T120000_0.256.1234567891 tag=TAG20241219T120000 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:00:05

Starting backup at 19-DEC-24
using channel ORA_DISK_1
channel ORA_DISK_1: starting full datafile backup set
channel ORA_DISK_1: specifying datafile(s) in backup set
input datafile file number=00001 name=+DATA/ORCL/DATAFILE/system.256.1234567890
input datafile file number=00002 name=+DATA/ORCL/DATAFILE/sysaux.257.1234567891
input datafile file number=00003 name=+DATA/ORCL/DATAFILE/undotbs1.258.1234567892
input datafile file number=00004 name=+DATA/ORCL/DATAFILE/users.259.1234567893
channel ORA_DISK_1: starting piece 1 at 19-DEC-24
channel ORA_DISK_1: finished piece 1 at 19-DEC-24
piece handle=+FRA/ORCL/BACKUPSET/2024_12_19/nnnnn_TAG20241219T120010_0.257.1234567892 tag=TAG20241219T120010 comment=NONE
channel ORA_DISK_1: backup set complete, elapsed time: 00:02:15
Finished backup at 19-DEC-24

Starting Control File and SPFILE Autobackup at 19-DEC-24
piece handle=+FRA/ORCL/AUTOBACKUP/2024_12_19/s_1234567893.258.1234567894 comment=NONE
Finished Control File and SPFILE Autobackup at 19-DEC-24
"""


# === SAUVEGARDE INCRÉMENTALE (INCREMENTAL BACKUP) ===

# Sauvegarde incrémentale niveau 0 (= full backup)
RMAN> BACKUP INCREMENTAL LEVEL 0 DATABASE PLUS ARCHIVELOG;

# Sauvegarde incrémentale niveau 1 (seulement les blocs modifiés depuis level 0)
RMAN> BACKUP INCREMENTAL LEVEL 1 DATABASE PLUS ARCHIVELOG;

# Avantage des sauvegardes incrémentales :
# - Plus rapides
# - Prennent moins d'espace
# - Permettent une restauration complète en combinant level 0 + level 1


# === VÉRIFICATION DES SAUVEGARDES ===

# Lister toutes les sauvegardes
RMAN> LIST BACKUP SUMMARY;

# Sortie :
"""
List of Backups
===============
Key     TY LV S Device Type Completion Time #Pieces #Copies Compressed Tag
------- -- -- - ----------- --------------- ------- ------- ---------- ---
1       B  F  A DISK        19-DEC-24       1       1       NO         TAG20241219T120000
2       B  F  A DISK        19-DEC-24       1       1       NO         TAG20241219T120010
3       B  F  A DISK        19-DEC-24       1       1       NO         TAG20241219T120225
"""

# Vérifier l'intégrité des sauvegardes
RMAN> VALIDATE BACKUPSET ALL;

# Sortie :
"""
using channel ORA_DISK_1
channel ORA_DISK_1: starting validation of datafile backup set
channel ORA_DISK_1: reading from backup piece +FRA/ORCL/BACKUPSET/2024_12_19/nnnnn_TAG20241219T120010_0.257.1234567892
channel ORA_DISK_1: piece handle=+FRA/ORCL/BACKUPSET/2024_12_19/nnnnn_TAG20241219T120010_0.257.1234567892 tag=TAG20241219T120010
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: validation complete, elapsed time: 00:01:05
Finished validate at 19-DEC-24
"""


# === RESTAURATION DEPUIS ASM ===

"""
Scénarios de restauration :
1. Perte d'un datafile
2. Perte de tous les datafiles
3. Perte de la base complète
"""

# SCÉNARIO 1 : RESTAURATION D'UN SEUL DATAFILE

# Simuler la perte d'un datafile (NE PAS FAIRE EN PRODUCTION !)
sudo su - grid
asmcmd
ASMCMD> rm +DATA/ORCL/DATAFILE/users.259.1234567893
ASMCMD> exit

# La base va détecter l'erreur au prochain accès au fichier
sudo su - oracle
sqlplus / as sysdba

SQL> SELECT * FROM dba_users;
# Erreur : ORA-01116: error in opening database file 4

# Restaurer le datafile avec RMAN
rman target /

# Mettre le datafile offline
RMAN> SQL 'ALTER DATABASE DATAFILE 4 OFFLINE';

# Restaurer et récupérer
RMAN> RESTORE DATAFILE 4;
RMAN> RECOVER DATAFILE 4;

# Remettre le datafile online
RMAN> SQL 'ALTER DATABASE DATAFILE 4 ONLINE';

# Sortie :
"""
Starting restore at 19-DEC-24
using channel ORA_DISK_1

channel ORA_DISK_1: starting datafile backup set restore
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_DISK_1: restoring datafile 00004 to +DATA/ORCL/DATAFILE/users.259.1234567893
channel ORA_DISK_1: reading from backup piece +FRA/ORCL/BACKUPSET/2024_12_19/nnnnn_TAG20241219T120010_0.257.1234567892
channel ORA_DISK_1: piece handle=+FRA/ORCL/BACKUPSET/2024_12_19/nnnnn_TAG20241219T120010_0.257.1234567892 tag=TAG20241219T120010
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: restore complete, elapsed time: 00:00:15
Finished restore at 19-DEC-24

Starting recover at 19-DEC-24
using channel ORA_DISK_1

starting media recovery
media recovery complete, elapsed time: 00:00:03

Finished recover at 19-DEC-24
"""


# SCÉNARIO 2 : RESTAURATION COMPLÈTE DE LA BASE

# Arrêter la base
sqlplus / as sysdba
SQL> SHUTDOWN ABORT;
SQL> STARTUP MOUNT;
SQL> EXIT

# Restaurer et récupérer toute la base
rman target /

RMAN> RESTORE DATABASE;
RMAN> RECOVER DATABASE;
RMAN> ALTER DATABASE OPEN;

# Cette procédure restaure TOUS les datafiles depuis la dernière sauvegarde
# puis applique tous les archived redo logs pour récupérer jusqu'au dernier commit


# === NETTOYAGE DES ANCIENNES SAUVEGARDES ===

# Supprimer les sauvegardes obsolètes (selon la politique de rétention)
RMAN> DELETE OBSOLETE;

# Sortie :
"""
RMAN retention policy will be applied to the command
RMAN retention policy is set to recovery window of 7 days
using channel ORA_DISK_1
Deleting the following obsolete backups and copies:
Type                 Key    Completion Time    Filename/Handle
-------------------- ------ ------------------ --------------------
Backup Set           5      15-DEC-24          +FRA/ORCL/BACKUPSET/2024_12_15/...
Backup Set           6      15-DEC-24          +FRA/ORCL/BACKUPSET/2024_12_15/...

Do you really want to delete the above objects (enter YES or NO)? YES
deleted backup piece
backup piece handle=+FRA/ORCL/BACKUPSET/2024_12_15/... RECID=5 STAMP=1234567000
Deleted 2 objects
"""

# Supprimer les archived redo logs déjà sauvegardés
RMAN> DELETE ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-2';

# Cette commande supprime les archived logs de plus de 2 jours


[OK] PARTIE 11 : PERFORMANCE TUNING ASM

# === OPTIMISATION DES PERFORMANCES ASM ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│                  TUNING ET OPTIMISATION DES PERFORMANCES               │
└────────────────────────────────────────────────────────────────────────┘
"""

# ÉTAPE 32 : PARAMÈTRES DE PERFORMANCE ASM

sudo su - grid
sqlplus / as sysasm

# 1. Ajuster la vitesse de rééquilibrage
SQL> ALTER SYSTEM SET asm_power_limit = 8;

# Explication :
"""
asm_power_limit : 1-11
- 1 = très lent, priorité aux I/O utilisateurs
- 4 = équilibré (par défaut)
- 11 = très rapide, priorité au rééquilibrage

Utiliser 1-4 en production (heures de pointe)
Utiliser 8-11 en maintenance (heures creuses)
"""

# 2. Configurer les préférences de disk
# Marquer certains disques comme préférés pour certains types de fichiers

SQL> ALTER DISKGROUP data SET ATTRIBUTE 
     'preferred_read.orcl' = 'data.disk1';

# Ceci indique à l'instance ORCL de préférer lire depuis data.disk1
# Utile dans un environnement RAC


# 3. Optimiser le nombre de processus de rééquilibrage
SQL> SHOW PARAMETER asm_power_limit;

# Sortie :
"""
NAME              TYPE    VALUE
----------------- ------- -----
asm_power_limit   integer 8
"""


# === MONITORING DES PERFORMANCES I/O ===

# Vue des statistiques I/O par disque
SQL> SELECT d.name AS disk_name,
            d.path,
            ds.reads,
            ds.writes,
            ds.read_time,
            ds.write_time,
            ROUND(ds.read_time / NULLIF(ds.reads, 0), 2) AS avg_read_ms,
            ROUND(ds.write_time / NULLIF(ds.writes, 0), 2) AS avg_write_ms
     FROM v$asm_disk d
     JOIN v$asm_disk_stat ds ON d.group_number = ds.group_number 
                              AND d.disk_number = ds.disk_number
     WHERE d.state = 'NORMAL'
     ORDER BY d.name;

# Sortie :
"""
DISK_NAME  PATH                    READS    WRITES  READ_TIME WRITE_TIME AVG_READ_MS AVG_WRITE_MS
---------- ----------------------- -------- ------- --------- ---------- ----------- ------------
DATA_0000  /dev/oracleasm/disk1    123456   45678   12345     4567       0.10        0.10
DATA_0001  /dev/oracleasm/disk2    123450   45680   12340     4565       0.10        0.10
DATA_0002  /dev/oracleasm/disk3    123500   45700   12400     4580       0.10        0.10
DATA_0003  /dev/oracleasm/disk4    123480   45690   12360     4570       0.10        0.10
"""

# [ATTENTION] SI avg_read_ms ou avg_write_ms > 10 ms : Problème de performance disque !


# === STATISTIQUES PAR FICHIER ===

# Voir les fichiers les plus actifs (depuis l'instance Database)
sudo su - oracle
sqlplus / as sysdba

SQL> SELECT file#,
            name,
            phyrds AS physical_reads,
            phywrts AS physical_writes,
            readtim AS read_time_cs,
            writetim AS write_time_cs,
            ROUND(readtim / NULLIF(phyrds, 0) / 100, 4) AS avg_read_sec,
            ROUND(writetim / NULLIF(phywrts, 0) / 100, 4) AS avg_write_sec
     FROM v$datafile df
     JOIN v$filestat fs ON df.file# = fs.file#
     ORDER BY physical_reads DESC;

# Sortie :
"""
FILE# NAME                                      PHYRDS  PHYWRTS READ_TIME WRITE_TIME AVG_READ AVG_WRITE
----- ----------------------------------------- ------- -------- --------- ---------- -------- ---------
    1 +DATA/ORCL/DATAFILE/system.256...        234567   12345    23456      1234      0.0010   0.0010
    2 +DATA/ORCL/DATAFILE/sysaux.257...        123456   23456    12345      2345      0.0010   0.0010
    3 +DATA/ORCL/DATAFILE/undotbs1.258...       45678   56789     4567      5678      0.0010   0.0010
    4 +DATA/ORCL/DATAFILE/users.259...          12345    5678     1234       567      0.0010   0.0010
"""


# === OPTIMISATION DU STRIPING ===

# Vérifier le type de striping utilisé
sudo su - grid
sqlplus / as sysasm

SQL> SELECT dg.name AS diskgroup,
            f.name AS file_name,
            f.type AS file_type,
            a.name AS alias_name,
            a.system_created,
            t.stripe AS stripe_type
     FROM v$asm_file f
     JOIN v$asm_diskgroup dg ON f.group_number = dg.group_number
     LEFT JOIN v$asm_alias a ON f.file_number = a.file_number 
                               AND f.group_number = a.group_number
     JOIN v$asm_template t ON f.type = t.name 
                             AND f.group_number = t.group_number
     WHERE f.type IN ('DATAFILE', 'ONLINELOG', 'ARCHIVELOG')
     ORDER BY dg.name, f.type;

# Sortie :
"""
DISKGROUP FILE_NAME              FILE_TYPE  ALIAS_NAME              SYS_CREATED STRIPE_TYPE
--------- ---------------------- ---------- ----------------------- ----------- -----------
DATA      SYSTEM.256.1234567890  DATAFILE   DATAFILE/system.256...  Y           COARSE
DATA      USERS.259.1234567893   DATAFILE   DATAFILE/users.259...   Y           COARSE
DATA      group_1.261.1234567896 ONLINELOG  ONLINELOG/group_1...    Y           FINE
FRA       arc_123.256.1234567900 ARCHIVELOG (none)                  Y           COARSE
"""

# Explication :
"""
FINE (128 KB) : Pour fichiers avec I/O aléatoires (datafiles, redo logs)
COARSE (1 MB) : Pour fichiers avec I/O séquentiels (archives, backups)
"""

# Modifier le template (affectera les NOUVEAUX fichiers uniquement)
SQL> ALTER DISKGROUP data ALTER TEMPLATE datafile 
     ATTRIBUTES (STRIPE FINE);


[OK] PARTIE 12 : TROUBLESHOOTING ET RÉSOLUTION DE PROBLÈMES

# === PROBLÈMES COURANTS ET SOLUTIONS ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│                   RÉSOLUTION DES PROBLÈMES ASM                         │
└────────────────────────────────────────────────────────────────────────┘
"""

# PROBLÈME 1 : ASM NE DÉMARRE PAS

"""
Symptôme : ORA-15032: not all alterations performed
ou ORA-15001: diskgroup "DATA" does not exist or is not mounted
"""

# Diagnostic :
sudo su - grid
sqlplus / as sysasm

SQL> SELECT name, state FROM v$asm_diskgroup;

# Si state = 'DISMOUNTED' :
SQL> ALTER DISKGROUP data MOUNT;

# Si erreur ORA-15032 : problème de découverte des disques
SQL> SHOW PARAMETER asm_diskstring;

# Vérifier que le pattern couvre tes disques
SQL> ALTER SYSTEM SET asm_diskstring = '/dev/oracleasm/*';

# Redémarrer ASM
SQL> SHUTDOWN IMMEDIATE;
SQL> STARTUP;


# PROBLÈME 2 : DISQUE EN ÉTAT ANORMAL

"""
Symptôme : Un disque apparaît avec state != 'NORMAL'
"""

# Vérifier l'état des disques
SQL> SELECT name, path, header_status, mode_status, state 
     FROM v$asm_disk
     WHERE state != 'NORMAL';

# Sortie problématique :
"""
NAME       PATH                     HEADER_STATUS MODE_STATUS STATE
---------- ------------------------ ------------- ----------- --------
DATA_0002  /dev/oracleasm/disk3     MEMBER        OFFLINE     DROPPING
"""

# États possibles :
"""
NORMAL    : OK [OK]
DROPPING  : En cours de suppression (opération en cours)
OFFLINE   : Hors ligne (panne ou retiré volontairement)
HUNG      : Bloqué (très mauvais signe)
"""

# Si OFFLINE :
# 1. Vérifier la santé physique du disque
sudo smartctl -a /dev/sdc

# 2. Si le disque est OK, le remettre online
SQL> ALTER DISKGROUP data ONLINE DISK data_0002;

# 3. Si le disque est HS (hardware failure), le remplacer :
SQL> ALTER DISKGROUP data DROP DISK data_0002;

# Attendre que le drop soit terminé
SQL> SELECT * FROM v$asm_operation;

# Ajouter un nouveau disque
SQL> ALTER DISKGROUP data ADD DISK '/dev/oracleasm/disk7';


# PROBLÈME 3 : MANQUE D'ESPACE DANS UN DISK GROUP

"""
Symptôme : ORA-15041: diskgroup "DATA" space exhausted
"""

# Vérifier l'espace
SQL> SELECT name, 
            total_mb, 
            free_mb, 
            usable_file_mb,
            ROUND((1 - (free_mb / total_mb)) * 100, 2) AS pct_used
     FROM v$asm_diskgroup
     WHERE name = 'DATA';

# Solutions :
# 1. Ajouter des disques
SQL> ALTER DISKGROUP data ADD DISK '/dev/oracleasm/disk7', '/dev/oracleasm/disk8';

# 2. Supprimer les anciennes sauvegardes
sudo su - oracle
rman target /
RMAN> DELETE OBSOLETE;
RMAN> DELETE ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-7';

# 3. Réduire la taille des datafiles si possible
sqlplus / as sysdba
SQL> ALTER DATABASE DATAFILE '+DATA/ORCL/DATAFILE/users.259.1234567893' RESIZE 50M;


# PROBLÈME 4 : RÉÉQUILIBRAGE BLOQUÉ

"""
Symptôme : Le rééquilibrage ne progresse pas
"""

# Vérifier l'état du rééquilibrage
SQL> SELECT * FROM v$asm_operation;

# Si pas de progression pendant longtemps :
# 1. Augmenter la puissance
SQL> ALTER DISKGROUP data REBALANCE POWER 10;

# 2. Si toujours bloqué, annuler et relancer
SQL> ALTER DISKGROUP data REBALANCE POWER 0;  -- Annuler
# Attendre quelques secondes
SQL> ALTER DISKGROUP data REBALANCE POWER 5;  -- Relancer


# PROBLÈME 5 : IMPOSSIBLE DE MONTER UN DISK GROUP

"""
Symptôme : ORA-15032: not all alterations performed
         ORA-15017: diskgroup "DATA" cannot be mounted
"""

# Vérifier les fichiers d'alerte
sudo su - grid
tail -100 /u01/app/grid/diag/asm/+asm/+ASM/trace/alert_+ASM.log

# Chercher des messages comme :
# "disk header validation failed"
# "insufficient diskgroup redundancy"

# Solution 1 : Forcer le montage (si redondance suffisante)
sqlplus / as sysasm
SQL> ALTER DISKGROUP data MOUNT FORCE;

# Solution 2 : Si disques corrompus
# Utiliser RMAN pour restaurer depuis une sauvegarde


# PROBLÈME 6 : PERFORMANCE DÉGRADÉE

"""
Symptôme : Requêtes très lentes, latence I/O élevée
"""

# Vérifier les statistiques I/O
SQL> SELECT d.name,
            ds.reads,
            ds.writes,
            ROUND(ds.read_time / NULLIF(ds.reads, 0), 2) AS avg_read_ms
     FROM v$asm_disk d
     JOIN v$asm_disk_stat ds ON d.group_number = ds.group_number 
                              AND d.disk_number = ds.disk_number
     WHERE d.state = 'NORMAL'
     ORDER BY avg_read_ms DESC;

# Si avg_read_ms > 10-20 ms :
# 1. Vérifier la santé des disques (smartctl)
# 2. Vérifier la charge système (iostat, sar)
# 3. Considérer le passage à des disques SSD
# 4. Vérifier que le contrôleur disque a un cache activé


# === COMMANDES DE DIAGNOSTIC UTILES ===

# Générer un rapport complet sur ASM
sudo su - grid
asmcmd lsdg --statistics

# Dump des métadonnées ASM (pour support Oracle)
sqlplus / as sysasm
SQL> ALTER DISKGROUP data DUMP METADATA TO '/tmp/data_metadata.dump';

# Activer le tracing ASM (debug avancé)
SQL> ALTER SESSION SET EVENTS 'trace[asm] disk=high';

# Examiner les traces
ls -lrt /u01/app/grid/diag/asm/+asm/+ASM/trace/*.trc | tail -5


[OK] PARTIE 13 : MIGRATION VERS ASM

# === MIGRER UNE BASE EXISTANTE VERS ASM ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│         MIGRATION D'UNE BASE DE DONNÉES VERS ASM                       │
└────────────────────────────────────────────────────────────────────────┘

Scénario : Tu as une base existante sur filesystem (/u01/oradata)
            et tu veux la migrer vers ASM
"""

# ÉTAPE 33 : PRÉPARATION DE LA MIGRATION

sudo su - oracle

# 1. Faire une sauvegarde complète AVANT la migration
rman target /
RMAN> BACKUP DATABASE PLUS ARCHIVELOG;
RMAN> BACKUP CURRENT CONTROLFILE FOR STANDBY;
RMAN> EXIT

# 2. Vérifier l'espace nécessaire dans ASM
sqlplus / as sysdba
SQL> SELECT SUM(bytes)/1024/1024/1024 AS total_gb FROM dba_data_files;
SQL> SELECT SUM(bytes)/1024/1024/1024 AS total_gb FROM v$log;

# Sortie :
"""
TOTAL_GB
----------
      2.5
"""

# 3. Vérifier l'espace disponible dans ASM
sudo su - grid
sqlplus / as sysasm
SQL> SELECT name, usable_file_mb/1024 AS usable_gb 
     FROM v$asm_diskgroup 
     WHERE name = 'DATA';


# === MÉTHODE 1 : MIGRATION AVEC RMAN (RECOMMANDÉE) ===

"""
Avantages :
[OK] Automatique
[OK] Rapide
[OK] Pas de downtime (ou très court)
"""

sudo su - oracle
sqlplus / as sysdba

# 1. Arrêter proprement la base
SQL> SHUTDOWN IMMEDIATE;

# 2. Démarrer en mode MOUNT
SQL> STARTUP MOUNT;
SQL> EXIT

# 3. Utiliser RMAN pour copier vers ASM
rman target /

# Copier TOUS les fichiers vers ASM
RMAN> BACKUP AS COPY DATABASE FORMAT '+DATA';

# Basculer la base pour utiliser les nouvelles copies
RMAN> SWITCH DATABASE TO COPY;

# Copier les fichiers de contrôle vers ASM
RMAN> RESTORE CONTROLFILE FROM '/u01/oradata/ORCL/control01.ctl';
RMAN> REPLICATE CONTROLFILE FROM '+DATA/ORCL/CONTROLFILE/current.260.1234567890';

# Copier les redo logs vers ASM (must recreate)
RMAN> ALTER DATABASE OPEN RESETLOGS;

# Recréer les redo logs sur ASM
SQL> ALTER DATABASE ADD LOGFILE GROUP 4 ('+DATA') SIZE 200M;
SQL> ALTER DATABASE ADD LOGFILE GROUP 5 ('+DATA') SIZE 200M;
SQL> ALTER DATABASE ADD LOGFILE GROUP 6 ('+DATA') SIZE 200M;

# Attendre que les nouveaux logs soient utilisés
SQL> ALTER SYSTEM SWITCH LOGFILE;
SQL> ALTER SYSTEM CHECKPOINT;

# Supprimer les anciens logs
SQL> ALTER DATABASE DROP LOGFILE GROUP 1;
SQL> ALTER DATABASE DROP LOGFILE GROUP 2;
SQL> ALTER DATABASE DROP LOGFILE GROUP 3;

# 4. Mettre à jour les paramètres
SQL> ALTER SYSTEM SET db_recovery_file_dest = '+FRA' SCOPE=BOTH;
SQL> ALTER SYSTEM SET db_recovery_file_dest_size = 10G SCOPE=BOTH;

# 5. Vérifier que tout est sur ASM
SQL> SELECT name FROM v$datafile;
SQL> SELECT member FROM v$logfile;
SQL> SELECT name FROM v$controlfile;

# Tous les chemins doivent commencer par +DATA ou +FRA


# === MÉTHODE 2 : MIGRATION AVEC DBMS_FILE_TRANSFER ===

"""
Pour migrer fichier par fichier (plus de contrôle)
"""

# 1. Copier un datafile
sqlplus / as sysdba

SQL> ALTER TABLESPACE users OFFLINE;

SQL> BEGIN
  DBMS_FILE_TRANSFER.COPY_FILE(
    source_directory_object => 'ORADATA_DIR',
    source_file_name => 'users01.dbf',
    destination_directory_object => 'ASM_DATA',
    destination_file_name => '+DATA/ORCL/DATAFILE/users01.dbf'
  );
END;
/

# 2. Renommer le datafile dans le fichier de contrôle
SQL> ALTER DATABASE RENAME FILE 
     '/u01/oradata/ORCL/users01.dbf' 
     TO '+DATA/ORCL/DATAFILE/users01.dbf';

SQL> ALTER TABLESPACE users ONLINE;

# Répéter pour tous les datafiles


# === APRÈS LA MIGRATION : NETTOYAGE ===

# 1. Vérifier que tout fonctionne
sqlplus / as sysdba
SQL> SELECT COUNT(*) FROM dba_objects WHERE status = 'INVALID';
# Doit retourner 0 ou un petit nombre

# 2. Supprimer les anciens fichiers
sudo su - oracle
cd /u01/oradata/ORCL
ls -lh

# ATTENTION : Vérifier que la base fonctionne bien sur ASM avant de supprimer !
rm -i *.dbf *.log *.ctl

# 3. Mettre à jour le fichier oratab
sudo vi /etc/oratab
# Changer :
# ORCL:/u01/app/oracle/product/19.3.0/dbhome_1:N
# En :
# ORCL:/u01/app/oracle/product/19.3.0/dbhome_1:N

# 4. Faire une nouvelle sauvegarde complète
rman target /
RMAN> BACKUP DATABASE PLUS ARCHIVELOG DELETE INPUT;


[OK] PARTIE 14 : SCRIPTS D'AUTOMATISATION

# === SCRIPT DE DÉMARRAGE/ARRÊT AUTOMATIQUE ===

"""
┌────────────────────────────────────────────────────────────────────────┐
│              AUTOMATISATION DU DÉMARRAGE/ARRÊT D'ASM                   │
└────────────────────────────────────────────────────────────────────────┘
"""

# ÉTAPE 34 : CRÉER UN SCRIPT SYSTEMD POUR ASM

sudo cat > /etc/systemd/system/oracle-asm.service <<'EOF'
[Unit]
Description=Oracle ASM Instance
After=network.target

[Service]
Type=forking
User=grid
Group=oinstall
Environment=ORACLE_HOME=/u01/app/19.3.0/grid
Environment=ORACLE_SID=+ASM
ExecStart=/u01/app/19.3.0/grid/bin/crsctl start has
ExecStop=/u01/app/19.3.0/grid/bin/crsctl stop has
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

# Activer le service
sudo systemctl daemon-reload
sudo systemctl enable oracle-asm.service

# Tester
sudo systemctl start oracle-asm
sudo systemctl status oracle-asm


# === SCRIPT DE BACKUP AUTOMATIQUE ===

sudo su - oracle

cat > ~/backup_database.sh <<'EOF'
#!/bin/bash
# Script de backup automatique RMAN
# Usage : ./backup_database.sh [full|incremental]

export ORACLE_HOME=/u01/app/oracle/product/19.3.0/dbhome_1
export ORACLE_SID=ORCL
export PATH=$ORACLE_HOME/bin:$PATH

BACKUP_TYPE=${1:-incremental}
LOG_DIR=/u01/app/oracle/admin/ORCL/backup_logs
LOG_FILE=$LOG_DIR/backup_$(date +%Y%m%d_%H%M%S).log

mkdir -p $LOG_DIR

echo "═══════════════════════════════════════════════════════════════" | tee -a $LOG_FILE
echo "   Oracle Database Backup - $(date)" | tee -a $LOG_FILE
echo "   Type: $BACKUP_TYPE" | tee -a $LOG_FILE
echo "═══════════════════════════════════════════════════════════════" | tee -a $LOG_FILE
echo | tee -a $LOG_FILE

if [ "$BACKUP_TYPE" = "full" ]; then
    rman target / <<RMAN | tee -a $LOG_FILE
    BACKUP INCREMENTAL LEVEL 0 DATABASE PLUS ARCHIVELOG DELETE INPUT;
    BACKUP CURRENT CONTROLFILE;
    DELETE NOPROMPT OBSOLETE;
RMAN
else
    rman target / <<RMAN | tee -a $LOG_FILE
    BACKUP INCREMENTAL LEVEL 1 DATABASE PLUS ARCHIVELOG DELETE INPUT;
    DELETE NOPROMPT ARCHIVELOG ALL COMPLETED BEFORE 'SYSDATE-7';
RMAN
fi

if [ $? -eq 0 ]; then
    echo "[OK] Backup completed successfully" | tee -a $LOG_FILE
else
    echo "[X] Backup FAILED!" | tee -a $LOG_FILE
    # Envoyer une alerte par email
    echo "Backup failed on $(hostname) at $(date)" | mail -s "ALERT: Oracle Backup Failed" admin@example.com
fi

echo "═══════════════════════════════════════════════════════════════" | tee -a $LOG_FILE
EOF

chmod +x ~/backup_database.sh

# Programmer dans crontab
crontab -e

# Ajouter :
# Backup incrémental tous les jours à 2h du matin
0 2 * * * /home/oracle/backup_database.sh incremental >> /tmp/backup_cron.log 2>&1

# Backup complet tous les dimanches à 3h du matin
0 3 * * 0 /home/oracle/backup_database.sh full >> /tmp/backup_cron.log 2>&1


# === SCRIPT D'ALERTE ESPACE ASM ===

sudo su - grid

cat > ~/alert_asm_space.sh <<'EOF'
#!/bin/bash
# Script d'alerte espace disque ASM
# Usage : ./alert_asm_space.sh [threshold_percentage]

export ORACLE_HOME=/u01/app/19.3.0/grid
export ORACLE_SID=+ASM
export PATH=$ORACLE_HOME/bin:$PATH

THRESHOLD=${1:-80}
EMAIL="admin@example.com"

sqlplus -s / as sysasm <<SQL | grep -v "^$" > /tmp/asm_space_check.tmp
SET HEADING OFF FEEDBACK OFF PAGESIZE 0
SELECT name || '|' || ROUND((1 - (free_mb / total_mb)) * 100, 2)
FROM v\$asm_diskgroup;
SQL

while IFS='|' read -r dg_name pct_used; do
    if (( $(echo "$pct_used > $THRESHOLD" | bc -l) )); then
        echo "[ATTENTION]  ALERT: Disk Group $dg_name is ${pct_used}% full (threshold: ${THRESHOLD}%)"
        echo "Disk Group $dg_name on $(hostname) is ${pct_used}% full" | \
            mail -s "ALERT: ASM Disk Group Space Warning" $EMAIL
    fi
done < /tmp/asm_space_check.tmp

rm -f /tmp/asm_space_check.tmp
EOF

chmod +x ~/alert_asm_space.sh

# Programmer dans crontab
crontab -e

# Vérifier l'espace toutes les heures
0 * * * * /home/grid/alert_asm_space.sh 80 >> /tmp/asm_space_alert.log 2>&1


[OK] CONCLUSION ET BONNES PRATIQUES

"""
┌────────────────────────────────────────────────────────────────────────┐
│                   RÉCAPITULATIF ET BONNES PRATIQUES                    │
└────────────────────────────────────────────────────────────────────────┘

CONFIGURATION RECOMMANDÉE POUR PRODUCTION :
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

1. SÉPARATION DES DISK GROUPS :
   [OK] +DATA : Datafiles (NORMAL redundancy)
   [OK] +FRA : Sauvegardes, archives (NORMAL redundancy)  
   [OK] +REDO : Redo logs (HIGH redundancy)

2. HARDWARE :
   [OK] Utiliser des disques SSD pour +DATA et +REDO
   [OK] Utiliser des disques SAS/SATA pour +FRA (moins critique)
   [OK] Minimum 4 disques par disk group (pour performance)
   [OK] Utiliser des contrôleurs disques avec cache BBU (Battery Backup Unit)

3. CONFIGURATION :
   [OK] Toujours utiliser UDEV pour noms persistants
   [OK] Définir des failure groups (séparation physique)
   [OK] Activer l'auto-backup du controlfile
   [OK] Configurer FRA sur un disk group séparé
   [OK] Utiliser asm_power_limit = 4 en production, 8-11 en maintenance

4. MONITORING :
   [OK] Surveiller l'espace disque (alerte à 80%)
   [OK] Surveiller les statistiques I/O (latence < 10 ms)
   [OK] Consulter régulièrement le fichier alert_+ASM.log
   [OK] Vérifier l'état des disques avec smartctl
   [OK] Programmer des checks automatiques (cron)

5. BACKUP :
   [OK] Backup incrémental quotidien
   [OK] Backup complet hebdomadaire
   [OK] Tester régulièrement la restauration
   [OK] Conserver 7-30 jours de sauvegardes
   [OK] Automatiser avec des scripts

6. SÉCURITÉ :
   [OK] Utiliser des mots de passe forts (SYSASM, SYS)
   [OK] Séparer les utilisateurs grid et oracle
   [OK] Restreindre les permissions (660 sur les disques)
   [OK] Auditer les opérations ASM

7. DOCUMENTATION :
   [OK] Documenter l'architecture (diagram)
   [OK] Noter les numéros de série des disques
   [OK] Conserver les logs d'installation
   [OK] Maintenir un runbook pour les incidents

COMMANDES À CONNAÎTRE PAR CŒUR :
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

# Vérifier l'état d'ASM
crsctl stat res -t

# Se connecter à ASM
sqlplus / as sysasm

# Lister les disk groups
SELECT name, state, total_mb, free_mb FROM v$asm_diskgroup;

# Vérifier les disques
SELECT path, name, state FROM v$asm_disk;

# Lancer ASMCMD
asmcmd

# Vérifier l'espace
asmcmd lsdg

# Ajouter un disque
ALTER DISKGROUP data ADD DISK '/dev/oracleasm/disk7';

# Sauvegarder la base
rman target /
BACKUP DATABASE PLUS ARCHIVELOG;

RESSOURCES SUPPLÉMENTAIRES :
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[DOCS] Documentation Oracle :
- Oracle ASM Administrator's Guide
  https://docs.oracle.com/en/database/oracle/oracle-database/19/ostmg/

- Oracle Grid Infrastructure Installation Guide
  https://docs.oracle.com/en/database/oracle/oracle-database/19/cwlin/

[TELEVISION] Tutoriels recommandés :
- Oracle Learning Library (OLL)
- Oracle LiveSQL (exercices pratiques)

[OUTILS] Outils utiles :
- ASMCA : ASM Configuration Assistant (GUI)
- ASMCMD : Ligne de commande ASM
- Enterprise Manager : Monitoring graphique

[SPEECH_BALLOON] Communautés :
- Oracle Forums : forums.oracle.com
- Stack Overflow : tag [oracle-asm]
- Reddit : r/oracle

FIN DU GUIDE ASM POUR GRANDS DÉBUTANTS ! [BRAVO]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Tu as maintenant toutes les connaissances pour :
[OK] Comprendre l'architecture ASM
[OK] Installer Grid Infrastructure
[OK] Configurer des disk groups
[OK] Créer une base de données sur ASM
[OK] Gérer les opérations courantes
[OK] Résoudre les problèmes
[OK] Optimiser les performances
[OK] Automatiser les tâches

BRAVO ! [RAPIDE] Tu es maintenant un expert ASM ! [FORCE]
"""

# FIN DU FICHIER ASM.txt