Synthèse

Après un échec ou une interruption de la suppression d'une base de données via odacli, le référentiel interne du DCS Agent conserve les entrées de métadonnées correspondantes. La base n'existe plus physiquement (ASM, ACFS) mais le DCS Agent la considère toujours présente. Toute tentative de recréer une base avec le même nom échoue avec une erreur "already exists".

Ce problème concerne toutes les versions ODA :

Version ODA Référentiel DCS
≤ 19.9 Apache Derby (base Java embarquée)
≥ 19.10 MySQL

MOS Doc ID : 2723755.1


1. Symptômes

Erreur lors d'un odacli create-database avec un nom déjà utilisé :

DCS-10044: Object <DBNAME> already exists with same value

ou :

DCS-10001: Internal error encountered:
           Fail to run command
           Failed to create FileGroup DAT<DBNAME> on DiskGroup DATA

Le job odacli delete-database précédent peut apparaître en statut Failed ou Success partiel dans odacli list-jobs, alors que la base n'existe plus physiquement sur le système (aucun processus pmon, aucun fichier ASM).


2. Cause racine

Le workflow de suppression d'une base ODA est multi-étapes :

  1. Arrêt des instances Oracle
  2. Suppression des fichiers de données (ASM ou ACFS)
  3. Suppression du DB Home si plus utilisé
  4. Nettoyage des entrées dans le référentiel DCS

En cas d'échec ou d'interruption aux étapes 1, 2 ou 3, l'étape 4 n'est jamais exécutée. Les entrées orphelines restent dans la base Derby (ou MySQL) du DCS Agent, qui considère donc la base comme encore existante.

Localisation du référentiel selon la version :

Version ≤ 19.9  →  Apache Derby
                   Répertoire : /opt/oracle/dcs/repo/db-derby-10.14.2.0-bin/
                   Base       : node_0

Version ≥ 19.10 →  MySQL
                   Socket : /opt/oracle/dcs/mysql/log/mysqldb.sock

3. Workaround — Version ≤ 19.9 (Derby)

Procédure validée en production sur un ODA X8-2S en version 19.8.

Important : arrêter le controller et l'agent avant toute intervention. Ne jamais modifier la base Derby avec les services actifs.

Étape 1 — Identifier la base orpheline

Vérifier que la base n'existe plus physiquement :

# Aucun processus pmon ne doit être retourné
ps -ef | grep pmon | grep <DBNAME>

# Aucun fichier ASM ne doit exister
asmcmd ls DATA/<DBNAME>

Étape 2 — Arrêter le controller et l'agent DCS

systemctl stop initdcscontroller.service
systemctl stop initdcsagent.service

Étape 3 — Sauvegarder le référentiel Derby

cd /opt/oracle/dcs
tar cfz /root/Derby_$(date +%Y%m%d_%Hh%M).tgz repo/

Étape 4 — Configurer l'environnement Java et Derby

export JAVA_HOME=/opt/oracle/dcs/java/1.8.0_251
export DERBY_HOME=/opt/oracle/dcs/repo/db-derby-10.14.2.0-bin
export CLASSPATH=${DERBY_HOME}/lib/derby.jar:\
${DERBY_HOME}/lib/derbynet.jar:\
${DERBY_HOME}/lib/derbyclient.jar:\
${DERBY_HOME}/lib/derbytools.jar:\
${DERBY_HOME}/lib/derbyoptionaltools.jar

Étape 5 — Lancer le client Derby et nettoyer les entrées orphelines

cd /opt/oracle/dcs/repo
$JAVA_HOME/bin/java -cp $CLASSPATH org.apache.derby.tools.ij

Une fois dans le client ij :

-- Se connecter à la base DCS
connect 'jdbc:derby:node_0';

-- Optionnel : lister toutes les tables
show tables;

-- 1. Récupérer l'ID de la base orpheline
select ID, NAME from DB where NAME='<DBNAME>';

-- 2. Supprimer les réseaux attachés (utiliser l'ID récupéré ci-dessus)
select * from ATTACHED_NETWORKS where db_id='<DB_ID>';
delete from ATTACHED_NETWORKS where db_id='<DB_ID>';

-- 3. Récupérer l'ID du stockage
select ID, NAME from DBSTORAGEDETAILS where NAME='<DBNAME>';

-- 4. Supprimer les volumes de stockage (utiliser l'ID récupéré ci-dessus)
delete from DBSTORAGEDETAILS_VOLS where DBSTORAGEDETAILS_ID='<STORAGE_ID>';

-- 5. Supprimer les autres entrées liées à la base
delete from DBSTORAGEDETAILS where NAME='<DBNAME>';
delete from DB where NAME='<DBNAME>';
delete from DBSTORAGELOCATIONS where NAME='<DBNAME>';

quit;

Récapitulatif des tables à nettoyer :

Table Clé de suppression
ATTACHED_NETWORKS db_id
DBSTORAGEDETAILS_VOLS DBSTORAGEDETAILS_ID
DBSTORAGEDETAILS NAME
DB NAME
DBSTORAGELOCATIONS NAME

Étape 6 — Redémarrer le controller et l'agent DCS

systemctl start initdcscontroller.service
systemctl start initdcsagent.service

Étape 7 — Valider la correction

# La base ne doit plus apparaître dans la liste
odacli list-databases

# Recréer la base si nécessaire
odacli create-database -n <DBNAME> [options]

4. Workaround — Version ≥ 19.10 (MySQL)

⚠️ Même principe : arrêter les services avant toute intervention.

Arrêter le controller et l'agent DCS

systemctl stop initdcscontroller.service
systemctl stop initdcsagent.service

Sauvegarder le référentiel MySQL

/opt/oracle/dcs/mysql/bin/mysqldump -u root \
  --socket=/opt/oracle/dcs/mysql/log/mysqldb.sock \
  dcsagentdb > /tmp/dcsagentdb_backup_$(date +%Y%m%d).sql

Nettoyer les entrées orphelines

/opt/oracle/dcs/mysql/bin/mysql -u root \
  --socket=/opt/oracle/dcs/mysql/log/mysqldb.sock
use dcsagentdb;

-- Identifier la base orpheline
select id, name, status from db where name='<DBNAME>';

-- Supprimer les dépendances
delete from ATTACHED_NETWORKS where db_id='<id>';
delete from DBSTORAGEDETAILS_VOLS where DBSTORAGEDETAILS_ID='<STORAGE_ID>';
delete from DBSTORAGEDETAILS where name='<DBNAME>';
delete from db where name='<DBNAME>';
delete from DBSTORAGELOCATIONS where name='<DBNAME>';
commit;
exit;

Redémarrer et valider

systemctl start initdcscontroller.service
systemctl start initdcsagent.service
odacli list-databases

5. Précautions et points d'attention

  1. Toujours sauvegarder le référentiel avant toute intervention (étape 3 ci-dessus).

  2. Ne jamais supprimer une entrée dont le statut est Configured ou Running sans avoir vérifié physiquement que la base n'existe plus.

  3. En cas de doute, ouvrir un ticket Oracle Support en référençant le MOS Doc ID 2723755.1 plutôt qu'intervenir manuellement.

  4. Argument pour patcher vers ≥ 19.10 : la manipulation est plus simple et moins risquée sous MySQL que sous Derby.


6. Lien avec la migration Derby → MySQL

À partir de la version 19.10, MySQL remplace Apache Derby comme métastore du DCS Agent. Sur les ODA encore en version 19.8, la commande odacli update-dcscomponents lors du premier palier de patching (19.8 → 19.11) migre automatiquement le référentiel Derby vers MySQL.

Recommandation : avant d'appliquer ce patch, vérifier l'absence d'entrées orphelines dans Derby et les nettoyer le cas échéant. Une entrée corrompue pourrait provoquer un échec de la migration.

# Lister toutes les bases du référentiel Derby avant migration
export JAVA_HOME=/opt/oracle/dcs/java/1.8.0_251
export DERBY_HOME=/opt/oracle/dcs/repo/db-derby-10.14.2.0-bin
export CLASSPATH=${DERBY_HOME}/lib/derby.jar:\
${DERBY_HOME}/lib/derbynet.jar:\
${DERBY_HOME}/lib/derbyclient.jar:\
${DERBY_HOME}/lib/derbytools.jar:\
${DERBY_HOME}/lib/derbyoptionaltools.jar

cd /opt/oracle/dcs/repo
$JAVA_HOME/bin/java -cp $CLASSPATH org.apache.derby.tools.ij

connect 'jdbc:derby:node_0';
select name, status from DB;
quit;

# Comparer avec la réalité
odacli list-databases
ps -ef | grep pmon

Sources et références

  1. MOS Doc ID 2723755.1 — ODA Create/Delete/Create Database Fails DCS-10001 (compte My Oracle Support requis)
  2. Oracle Database Appliance 19.10 — Known Issues (migration Derby/MySQL)
  3. Oracle Database Appliance 19.12 — Patching (comportement update-dcscomponents)
Yacine Oumghar · DBA Oracle depuis 1998 Retour au blog