Installer une base Oracle 19.25 sur un ODA GI 19.14 (version DB non supportée par le GI installé)

⚠️ Avertissements avant de reproduire sur un ODA réel

Contexte / objectif

Forcer odacli create-dbhome puis odacli create-database à accepter une version de base de données (ex: 19.25) plus récente que le Grid Infrastructure installé (ex: 19.14) — cas normalement bloqué par ODA, qui impose GI ≥ DB.

Prérequis

Étape 0 — Vérifier la version de l'agent DCS et adapter si besoin

odacli describe-component 2>&1 | grep -i "DCS-AGENT\|version"

Si la version diffère de 19.14.0.0.0, décompiler le jar correspondant pour confirmer que la logique de validation est similaire avant de continuer :

mkdir -p /tmp/jarcheck && cd /tmp/jarcheck
unzip -o -q /opt/oracle/dcs/bin/dcs-agent-<version>.jar -d dcsagent
javap -p -c com.oracle.dcs.agent.service.db.DbHomeServiceValidator | grep -B30 "not supported for GRID"
javap -p -c com.oracle.dcs.agent.utils.rhp.RhpUtils | grep -B10 "Can't get RHP"

Confirmer que la logique correspond à la description ci-dessous (comparaison de "base version" GI vs DB, lecture de GiUtils.getGiCurrentVersion() depuis une table MySQL, puis lookup imagenames.xml/img_metadata).

Étape 1 — Déposer le clone dans le repository ACFS

Copier db<version>.tar.gz (et son .info) dans le répertoire ACFS réel des clones — pas un éventuel répertoire .local orphelin, vérifier avec crsctl stat res -t | grep -A2 acfsclone pour confirmer le point de montage actif :

cp db19.XXXXXX.tar.gz db19.XXXXXX.tar.gz.info /opt/oracle/oak/pkgrepos/orapkgs/clones/

Étape 2 — clonemetadata.xml

Fichier : /opt/oracle/oak/pkgrepos/orapkgs/clones/clonemetadata.xml (backup avant modif : cp -p clonemetadata.xml clonemetadata.xml.bak-pre-<version>).

Ajouter une ligne <supported .../> dans la section <dbhomes> (ne pas utiliser <defaulthome>, qui doit rester unique et pointer sur la version GI native) :

<supported version="<version_complete>" clone="db<version>.tar.gz"
           min_gi_version="19.0" max_gi_version="19.99" size="1.5"
           agent_version="<version_agent_dcs_reelle>"
           ignore_patches="<repris tel quel du clonemetadata.xml fourni dans le zip officiel>"/>

Point clé : agent_version doit être la version de l'agent DCS réellement installée sur l'ODA, pas celle indiquée dans le zip source du patch (qui suppose un agent mis à jour en même temps que le GI — ce qu'on ne fait pas ici). Le fichier officiel Oracle contient déjà des exemples de ce pairing cross-version (ex: DB 21.5 associée à un agent 19.14.0.0.0) — s'en inspirer directement si le zip du patch cible contient un clonemetadata.xml complet.

Étape 3 — Table MySQL gihome

/opt/oracle/dcs/mysql/bin/mysql --socket=/opt/oracle/dcs/mysql/log/mysqldb.sock -u root dcsagentdb -e "select id,giversion,homelocation from gihome;"

Noter l'id et la giversion d'origine (pour rollback), puis :

UPDATE gihome SET giversion='<version_complete>' WHERE id=<id_noté>;

Rollback : UPDATE gihome SET giversion='<valeur_origine>' WHERE id=<id>;

Étape 4 — imagenames.xml

Fichier : /opt/oracle/rhp/imagenames.xml (backup avant modif).

Choisir un nom d'image suivant la convention observée dans le fichier (IMGDB<major><minor>00, ex IMGDB192500 pour 19.25), puis ajouter dans <dbhomes> :

<supported version="<major.minor>"                name="IMGDB<code>"/>
<supported version="<major.minor>.0.0"            name="IMGDB<code>"/>
<supported version="<version_complete>"           name="IMGDB<code>"/>

Vérifier au préalable si RHP est configuré sur cet ODA (rhpctl query image) — si oui, une étape d'enregistrement rhpctl add image pourrait être requise en complément (non testé sur notre simulation, RHP absent).

Étape 5 — img_metadata

Fichier JSON : /opt/oracle/rhp/img_metadata (backup avant modif). Éditer via un script Python (json.load/json.dump), jamais sed, pour garantir un JSON valide :

import json, collections
with open('/opt/oracle/rhp/img_metadata') as f:
    data = json.load(f, object_pairs_hook=collections.OrderedDict)
data['<code_sans_prefixe>'] = [
    {
        'image_type': 'db',
        'version': '19.0.0.0.0',
        'ru_version': '<major.minor>.0.0.0',
        'groups': '',
        'aru_id': '226',
        'patches': '',
        'nonrolling_patches': '',
        'lspatches_bugs': '',
        'image_name': 'IMGDB<code>',
        'image': '/opt/oracle/oak/pkgrepos/orapkgs/clones/db<version>.tar.gz'
    }
]
with open('/opt/oracle/rhp/img_metadata', 'w') as f:
    json.dump(data, f, indent=4)

Pas besoin d'entrée gi jumelle dans le même groupe (confirmé par des groupes DB-only existants dans le fichier, ex 11204/11.2.0.4).

Vérifier la validité JSON avant de continuer :

python2 -c "import json; json.load(open('/opt/oracle/rhp/img_metadata')); print('JSON valide')"

(ou python3 selon ce qui est disponible sur l'ODA cible)

Étape 6 — Créer le dbhome

odacli create-dbhome -v <version_complete>

Surveiller via odacli describe-job -i <id>. Si Extract DB clone échoue ou que la VM/le nœud plante pendant cette étape (opération lourde en I/O, plusieurs Go à extraire) : voir section "Robustesse I/O" plus bas.

Étape 7 — Créer la base

odacli create-database --dbname <NOM> --dbshape <shape> --dbstorage ASM --dbhomeid <id_dbhome>

Important : cette commande (comme create-appliance) demande un mot de passe SYS/SYSTEM/PDB Admin de façon interactive via System.console() — elle échoue silencieusement en SSH non-interactif (Enter ... password: null). Doit être lancée depuis une vraie console (console IPMI/ILOM sur ODA réel, ou console série).

Vérification finale

odacli list-databases
su - oracle -c "export ORACLE_HOME=<home_location>; export ORACLE_SID=<NOM>; \$ORACLE_HOME/bin/sqlplus -s / as sysdba <<< 'select name,open_mode,database_role from v\$database;'"

Nettoyage en cas d'échec partiel

Si create-dbhome échoue en cours de route (ex: extraction interrompue), la suppression standard peut elle-même échouer :

odacli delete-dbhome -i <id>
→ PRGH-1010 / deinstall: No such file or directory

(le script deinstall n'existe pas si l'extraction n'a jamais fini). Nettoyage manuel dans ce cas :

rm -rf <home_location_incomplet>
mysql --socket=/opt/oracle/dcs/mysql/log/mysqldb.sock -u root dcsagentdb \
  -e "DELETE FROM DatabaseHome WHERE id='<id>';"

Robustesse I/O (retour d'expérience simulation)

Les étapes d'extraction (update-repository, Extract DB clone) sont lourdes en I/O et CPU. Sur notre simulation, plusieurs kernel panics se sont produits pendant ces opérations, avec des causes variées (pression mémoire ARC ZFS côté hôte, contention disque avec d'autres opérations concurrentes). Sur un vrai ODA (matériel dédié, pas de virtualisation partagée), ce risque est probablement bien moindre, mais reste une bonne pratique de :

Résumé des fichiers modifiés (pense-bête)

Fichier/Table Modification Backup recommandé
clones/db<version>.tar.gz Ajouté — (fichier source)
clones/clonemetadata.xml 1 ligne <supported> ajoutée .bak-pre-<version>
MySQL dcsagentdb.gihome.giversion Valeur modifiée Noter la valeur d'origine
/opt/oracle/rhp/imagenames.xml 3 lignes ajoutées .bak-pre-<version>
/opt/oracle/rhp/img_metadata 1 clé JSON ajoutée .bak-pre-<version>

Validation finale

Cette procédure a été testée avec succès de 3 façons indépendantes sur la simulation, confirmant qu'un dbhome créé via ce hack se comporte ensuite comme un dbhome légitime :

Base Chemin de création Stockage Résultat
DB25 Création directe sur le home 19.25 hacké ASM ✅ READ WRITE/PRIMARY
DBTEST Upgrade cross-major depuis 12.2.0.1.220118 ASM ✅ READ WRITE/PRIMARY
DBACFS12 Upgrade cross-major depuis 12.2.0.1.220118 ACFS ✅ READ WRITE/PRIMARY

Aucune instabilité observée après création, sur plusieurs jours de tests cumulés.

Point technique confirmé : le chemin cross-major (ex: 12.2.0.1→19.25) fonctionne nativement, sans ce hack, dès lors que le dbhome 19.25 existe déjà sur le GI 19.14 (Oracle rapporte des versions génériques réellement différentes entre lignes majeures). Seul un upgrade same-major 19.x→19.x (ex: 19.14→19.25) reste bloqué par un bug distinct (DCS-10045, troncature de version à 4 segments comparée à v$instance.version, qui rapporte génériquement "19.0.0.0.0" pour toute la ligne 19.x).

Yacine Oumghar · DBA Oracle depuis 1998 Retour au blog