Ok

En poursuivant votre navigation sur ce site, vous acceptez l'utilisation de cookies. Ces derniers assurent le bon fonctionnement de nos services. En savoir plus.

[ORACLE] Restore

Script de restore d'une instance Oracle

 

#!/bin/bash
# script : restoreInst.sh
# Objet  : Restauration DR d’une CDB + PDB avec limite de recover
#          sur la dernière séquence d’archivelog réellement disponible.
# Auteur : Josselin
# Mise à jour : 2026-03-04 (version corrigée sans RENAME de redo logs)

set -euo pipefail

# ---------- Usage ----------
usage() {
    echo ""
    echo "Usage : $0 <CDBCIBLE> <CDBSOURCE> <RestoreDirectory> <RESTOREPDB> <NEWPDB> [THREAD]"
    echo ""
    echo "Exemple :"
    echo "  $0 SOURCECDB TGTCDB /appli/oracle/backup/INSTANCE/20260104 PDB1PROD PDB1TEST 1"
    echo ""
    echo "Paramètres :"
    echo "  CDBCIBLE         Nom de la base cible "
    echo "  CDBSOURCE        Nom de la base source "
    echo "  RestoreDirectory Répertoire contenant les backups RMAN (.bkp)"
    echo "  RESTOREPDB       Nom de la PDB à restaurer "
    echo "  NEWPDB           Nouveau nom de la PDB "
    echo "  THREAD           (optionnel, défaut=1) Thread d’archivelogs à récupérer"
    echo ""
    exit 1
}

# ---------- Vérification des arguments ----------
if [[ $# -lt 5 || $# -gt 6 ]]; then
    echo "[ERROR] Nombre de paramètres incorrect."
    usage
fi

# ---------- Paramètres ----------
CDBCIBLE="$1"
CDBSOURCE="$2"
RestoreDirectory="$3"
RESTOREPDB="$4"
NEWPDB="$5"
THREAD="${6:-1}"   # défaut THREAD=1

LOG_DIR="/appli/home/oracle/dbascripts/logs"
mkdir -p "${LOG_DIR}"
TS="$(date +%Y%m%d_%H%M%S)"
LOG_FILE="${LOG_DIR}/dr_restore_${CDBCIBLE}_${RESTOREPDB}_${TS}.log"

# ---------- Trap & logging ----------
cleanup() { [[ -n "${TMP_LS:-}" && -f "$TMP_LS" ]] && rm -f "$TMP_LS" || true; }
trap cleanup EXIT

exec > >(tee -a "${LOG_FILE}") 2>&1

echo "============================================================"
echo "[INFO] DR Restore ${CDBCIBLE} / PDB ${RESTOREPDB} -> ${NEWPDB}"
echo "[INFO] Host    : $(hostname -f)"
echo "[INFO] Started : $(date)"
echo "============================================================"

# ---------- Environnement Oracle (DB cible) ----------
export ORACLE_SID="${CDBCIBLE}"
export ORAENV_ASK=NO
if command -v oraenv >/dev/null 2>&1; then
  . oraenv >/dev/null 2>&1
elif [[ -x /usr/local/bin/oraenv ]]; then
  . /usr/local/bin/oraenv >/dev/null 2>&1
else
  echo "[ERROR] oraenv introuvable dans le PATH."
  exit 10
fi

echo "[INFO] ORACLE_SID=${ORACLE_SID}, ORACLE_HOME=${ORACLE_HOME}"
echo "[INFO] CDBSOURCE=${CDBSOURCE}, RestoreDirectory=${RestoreDirectory}, THREAD=${THREAD}"
echo "[INFO] PDB à restaurer : ${RESTOREPDB}  →  Nouveau nom : ${NEWPDB}"

# ---------- Création PFILE minimal (OMF activé) ----------
echo "[INFO] Création du pfile pour ${CDBCIBLE}"
mkdir -p "/appli/oracle/admin/${CDBCIBLE}/pfile/"

cat > "/appli/oracle/admin/${CDBCIBLE}/pfile/init${CDBCIBLE}.ora" <<EOF
audit_file_dest='/appli/oracle/diag/audit'
db_name='${CDBSOURCE}'
db_unique_name='${CDBCIBLE}'
memory_target=8G
control_files='+DATA_DG/${CDBCIBLE}/controlfile/control01.ctl'
compatible='19.0.0'
enable_pluggable_database=TRUE
_disk_sector_size_override=TRUE
db_files=400
db_recovery_file_dest='+FRA_DG'
db_recovery_file_dest_size=1500G
log_file_name_convert='DATA_DG','+REDO_DG'
db_create_online_log_dest_1='+REDO_DG'
EOF

# ---------- Startup NOMOUNT ----------
echo "[INFO] Startup NOMOUNT"
sqlplus -s / as sysdba <<EOF
set echo off feedback on
shutdown abort;
startup nomount pfile='/appli/oracle/admin/${CDBCIBLE}/pfile/init${CDBCIBLE}.ora';
exit
EOF

# ---------- Restauration du controlfile ----------
CTL_FILE=$(ls "${RestoreDirectory}/${CDBSOURCE}_ctl_"*.bkp 2>/dev/null | head -1 || true)
echo "[INFO] Restauration du controlfile"
if [[ -n "${CTL_FILE}" ]]; then
  echo "[INFO] Controlfile trouvé : ${CTL_FILE}"
  rman target / <<RMAN
restore controlfile from '${CTL_FILE}';
alter database mount;
RMAN
else
  echo "[INFO] Aucun controlfile explicite trouvé. Tentative via AUTOBACKUP."
  rman target / <<'RMAN'
restore controlfile from autobackup;
alter database mount;
RMAN
fi

# ---------- Catalog des backups ----------
echo "[INFO] Catalog des backup pieces dans ${RestoreDirectory}"
rman target / <<RMAN
run {
  allocate channel c1 type disk;
  catalog start with '${RestoreDirectory}/' noprompt;
  release channel c1;
}
RMAN

# ---------- Extraction de la dernière séquence disponible ----------
TMP_LS=$(mktemp)
echo "[INFO] Extraction de la dernière séquence via LIST BACKUP OF ARCHIVELOG ALL (THREAD=${THREAD})"
rman target / <<'RMAN' > "${TMP_LS}"
list backup of archivelog all;
RMAN

# On cible les lignes du tableau : "Thrd  Seq  ...", on filtre le thread et on prend la plus grande séquence
LAST_SEQ=$(awk -v T="${THREAD}" '
  /^[[:space:]]*[0-9]+[[:space:]]+[0-9]+[[:space:]]+[0-9]+/ {
     # colonnes: Thrd Seq LowSCN...
     if ($1 == T) print $2
  }
' "${TMP_LS}" | sort -n | tail -1)

if [[ -z "${LAST_SEQ}" ]]; then
  echo "[ERROR] Impossible de déterminer la dernière séquence d’archivelog depuis les backups."
  echo "        Vérifie que les backup pieces d’archivelogs sont bien catalogués dans ${RestoreDirectory}."
  exit 2
fi

TARGET_SEQ=$((LAST_SEQ - 1))
echo "[INFO] LAST_SEQ=${LAST_SEQ} => TARGET_SEQ (LAST_SEQ-1)=${TARGET_SEQ}"

# ---------- Préparation répertoire ASM pour REDO (oraenv -> +ASM) ----------
echo "[INFO] Préparation ASM : +REDO_DG/${CDBCIBLE}/ONLINELOG"
SAVE_ORACLE_SID="${ORACLE_SID}"
export ORACLE_SID="+ASM"
. oraenv >/dev/null 2>&1 || . /usr/local/bin/oraenv >/dev/null 2>&1

# Vérification accès ASM
if ! asmcmd ls / >/dev/null 2>&1; then
  echo "[ERROR] ASM non accessible (ORACLE_SID=+ASM ? permissions ?)."
  exit 11
fi

# Création des répertoires si absents
asmcmd ls +REDO_DG/${CDBCIBLE} >/dev/null 2>&1 || asmcmd mkdir +REDO_DG/${CDBCIBLE}
asmcmd ls +REDO_DG/${CDBCIBLE}/ONLINELOG >/dev/null 2>&1 || asmcmd mkdir +REDO_DG/${CDBCIBLE}/ONLINELOG
echo "[INFO] Répertoire prêt : +REDO_DG/${CDBCIBLE}/ONLINELOG"

# Retour environnement DB cible
export ORACLE_SID="${SAVE_ORACLE_SID}"
. oraenv >/dev/null 2>&1 || . /usr/local/bin/oraenv >/dev/null 2>&1

# ---------- RESTORE / RECOVER avec SET UNTIL (AVANT RESTORE) ----------
echo "[INFO] Lancement RESTORE/RECOVER avec SET UNTIL SEQUENCE ${TARGET_SEQ} THREAD ${THREAD}"
rman target / <<EOF
run {
    allocate channel primary1 type disk;
    allocate channel primary2 type disk;
    allocate channel primary3 type disk;
    allocate channel primary4 type disk;

    crosscheck backup;

    # Point de récupération limité
    SET UNTIL SEQUENCE ${TARGET_SEQ} THREAD ${THREAD};

    # OMF + redirection PDB à +DATA_DG (si besoin spécifique pour la PDB)
    SET NEWNAME FOR PLUGGABLE DATABASE ${RESTOREPDB} TO '+DATA_DG/${CDBCIBLE}/%U';

    # Restaure ROOT + SEED + PDB ciblée
    restore database root;
    restore database "PDB$SEED";
    restore database ${RESTOREPDB};

    # Place les datafiles restaurés en OMF
    switch datafile all;

    # Recover jusqu’à la séquence cible
    recover database;

    release channel primary1;
    release channel primary2;
    release channel primary3;
    release channel primary4;
}
EOF

# ---------- OPEN RESETLOGS + création des redo logs + renommage PDB ----------
echo "[INFO] OPEN RESETLOGS et post-actions"
sqlplus -s / as sysdba <<EOF
set echo on timing on
alter database open resetlogs;

-- Crée des online redo logs NEUFS dans le répertoire ASM cible
-- Ajuste SIZE / GROUPS selon tes standards
ALTER DATABASE ADD LOGFILE GROUP 1 ('+REDO_DG','REDO_DG') SIZE 2048M;
ALTER DATABASE ADD LOGFILE GROUP 2 ('+REDO_DG','REDO_DG') SIZE 2048M;
ALTER DATABASE ADD LOGFILE GROUP 3 ('+REDO_DG','REDO_DG') SIZE 2048M;

-- 2-3 switches pour initialiser les nouveaux fichiers
alter system switch logfile;
alter system switch logfile;
alter system checkpoint;

-- Ouvre/renomme la PDB
alter pluggable database ${RESTOREPDB} open restricted;
alter session set container=${RESTOREPDB};
alter pluggable database rename global_name to ${NEWPDB};
alter pluggable database close immediate;
alter pluggable database open;

-- Crée un SPFILE à partir du PFILE utilisé au démarrage
create spfile from pfile='/appli/oracle/admin/${CDBCIBLE}/pfile/init${CDBCIBLE}.ora';

-- Redémarrage avec SPFILE pour pérenniser les paramètres
shutdown immediate;
startup;

-- (Optionnel) Post-refresh applicatif
-- alter session set container=${NEWPDB};
-- EXEC sys_pck_db_post_refresh.start_refresh;
-- COMMIT;
exit
EOF

echo "============================================================"
echo "[SUCCESS] Restauration ${CDBCIBLE}/${RESTOREPDB} -> ${NEWPDB} terminée"
echo "[INFO] Point de recover : UNTIL SEQUENCE ${TARGET_SEQ} THREAD ${THREAD}"
echo "[INFO] Log : ${LOG_FILE}"
echo "============================================================"

Les commentaires sont fermés.