Purge automatique des archivelogs en PL/SQL
Purge automatique des archivelogs en PL/SQL
Aujourd'hui, je vous propose de voir comment répondre à la problématique suivante :
Comment supprimer à intervalles réguliers les archivelogs d'une base de données sur un système sur lequel le planificateur Unix (cron) n'est pas activé pour le compte oracle ?
De plus, on ne connait pas le mot de passe de ce dernier (accès en "sudo su" uniquement).
Pour cela, une première possibilité que l'on trouve rapidement après une petite recherche sur internet et dans la doc Oracle est d'utiliser le scheduler pour planifier un job de type "external script" qui appellerait donc un script shell .
La définition du job serait comme celle-ci :
dbms_scheduler.create_job(job_name => 'purge_al',
job_type => 'EXTERNAL_SCRIPT',
job_action => 'purge_archivelog.sh',
credential_name => 'oracle_cred',
enabled => true,
auto_drop => false);
Ce script purge_archivelog.sh exécuterait lui-même un script RMAN contenant simplement le bloc suivant par exemple, pour :
run {
delete archivelog all completed before 'sysdate-3/24';
}
Ce job devant être exécuté avec le compte système oracle, il faut cependant définir un "credential" associé au compte Oracle et pour cela il faudrait connaitre son mot de passe ce qui n'est pas notre cas (sic).
begin
dbms_credential.create_credential(
credential_name => 'oracle_cred',
username => 'oracle',
password => 'oracle password');
end;
/
Il reste donc une alternative dans ce cas et c'est l'objet de cet article : exécuter la suppression des archivelogs via une procédure PL/SQL.
En effet, celle-ci peut être exécutée sans avoir à créer de credentials ni connaitre de mot de passe, du moment que l'on a accès à l'utilisateur SYS (en ayant accès accès au compte Oracle sur le serveur de la base de données).
Au lieu de créer un job du scheduler Oracle de type "External script", on le crée donc de type "PL/SQL BLOCK".
Pour la suppression des archivelogs, le code fait appel à la procédure deleteArchivedLog du package dbms_backup_restore.
Il suffit de sélectionner les archivelogs à supprimer, en particulier en fonction d'un critère de date via le champ first_time et de les passer à la procédure.
La procédure dont voici le code complet ci-dessous est définie pour s'exécuter toutes les 4 heures à heure fixe (0,4,8,12,16,20) et supprime les archivelogs dont la date de 1ère séquence a plus de 3 heures. La procédure est à cataloguer avec le user SYS.
BEGIN
DBMS_SCHEDULER.create_job (
job_name => 'delete_archivelog_job',
job_type => 'PLSQL_BLOCK',
start_date => SYSTIMESTAMP,
repeat_interval => 'freq=hourly; byhour=0,4,8,12,16,20; byminute=0; bysecond=0;',
enabled => TRUE,
job_action => 'DECLARE f_count integer;
BEGIN
f_count:=0;
for c1 in (
select RECID,STAMP,NAME,THREAD#,SEQUENCE#,RESETLOGS_CHANGE#,FIRST_CHANGE#,BLOCK_SIZE
from v$archived_log
where STANDBY_DEST=''NO'' and deleted=''NO'' and FIRST_TIME < sysdate-3/24
)
loop
begin
dbms_backup_restore.deleteArchivedLog(c1.RECID,c1.STAMP,c1.NAME,c1.THREAD#,c1.SEQUENCE#,c1.RESETLOGS_CHANGE#,c1.FIRST_CHANGE#,c1.BLOCK_SIZE);
f_count:=f_count+1;
exception
when others then
null;
end;
end loop;
if f_count=0 then
dbms_output.put_line(''No archive log files deleted.'');
else
dbms_output.put_line(f_count || '' archive log files deleted.'');
end if;
END; '
);
END;
/
C'est tout, ça fonctionne directement !
Et pour terminer, voici quelques procédures pour piloter ce job :
Pour exécuter la procédure manuellement :
set serveroutput on
execute dbms_scheduler.run_job('DELETE_ARCHIVELOG_JOB');
Pour suspendre ou réactiver la planification de la procédure :
exec dbms_scheduler.disable('DELETE_ARCHIVELOG_JOB');
exec dbms_scheduler.enable('DELETE_ARCHIVELOG_JOB'
Pour le suivi d'exécution :
select log_date, job_name, status, run_duration,error#,output
from dba_scheduler_job_run_details where job_name='DELETE_ARCHIVELOG_JOB' ;