-- ==========================================================
-- OEM Report: Databases Not Protected by Backup (Family-Level)
-- Includes which member has the last successful backup
-- ==========================================================
WITH db_targets AS (
SELECT t.target_guid, t.target_name, t.host_name
FROM sysman.mgmt$target t
WHERE t.target_type IN ('oracle_database','rac_database')
),
db_properties AS (
SELECT
p.target_guid,
MAX(CASE WHEN p.property_name = 'DBName' THEN p.property_value END) AS db_name,
-- canonical base name: remove trailing letters (A-Z, a-z)
MAX(CASE WHEN p.property_name = 'DBName' THEN REGEXP_REPLACE(p.property_value,'[A-Za-z]+$','') END) AS base_name,
MAX(CASE WHEN p.property_name IN ('DatabaseRole','DBRole','DataGuardStatus') THEN p.property_value END) AS dg_role
FROM sysman.mgmt$target_properties p
GROUP BY p.target_guid
),
rman_configured AS (
SELECT DISTINCT r.target_guid
FROM sysman.mgmt$ha_rman_config r
),
recent_backup AS (
SELECT
b.target_guid,
MAX(CASE WHEN UPPER(NVL(b.status,'UNKNOWN')) = 'SUCCESS' THEN b.end_time END) AS last_success_time
FROM sysman.mgmt$ha_backup b
GROUP BY b.target_guid
),
merged AS (
SELECT
t.target_guid,
t.target_name,
t.host_name,
dp.db_name,
dp.base_name,
NVL(dp.dg_role,'NONE') AS dg_role,
CASE WHEN rc.target_guid IS NOT NULL THEN 1 ELSE 0 END AS config_flag,
rb.last_success_time
FROM db_targets t
JOIN db_properties dp ON t.target_guid = dp.target_guid
LEFT JOIN rman_configured rc ON t.target_guid = rc.target_guid
LEFT JOIN recent_backup rb ON t.target_guid = rb.target_guid
),
-- Aggregate at family level
family_agg AS (
SELECT
base_name,
LISTAGG(db_name || '(' || dg_role || ')', ', ') WITHIN GROUP (ORDER BY db_name) AS members,
MAX(config_flag) AS any_configured,
MAX(last_success_time) AS last_backup_time,
MAX(CASE WHEN last_success_time >= SYSDATE - 3 THEN 1 ELSE 0 END) AS recent_backup_done
FROM merged
GROUP BY base_name
),
-- Identify member(s) that ran the last successful backup
last_backup_member AS (
SELECT
f.base_name,
LISTAGG(m.db_name || '(' || m.dg_role || ')', ', ') WITHIN GROUP (ORDER BY m.db_name) AS backup_members
FROM family_agg f
JOIN merged m ON f.base_name = m.base_name
WHERE m.last_success_time = f.last_backup_time
GROUP BY f.base_name
)
SELECT
f.base_name,
f.members AS all_members,
TO_CHAR(f.last_backup_time,'YYYY-MM-DD HH24:MI:SS') AS last_backup_time,
lb.backup_members AS member_with_last_backup,
CASE
WHEN f.any_configured = 0 AND f.recent_backup_done = 0 THEN '❌ NO BACKUP CONFIGURED OR RUN'
WHEN f.any_configured = 1 AND f.recent_backup_done = 0 THEN '⚠️ CONFIGURED BUT NO RECENT SUCCESSFUL BACKUP'
WHEN f.any_configured = 0 AND f.recent_backup_done = 1 THEN '⚠️ BACKUP RUN BUT NO CONFIGURATION FOUND'
ELSE '✅ BACKUP OK (Primary or Standby Covered)'
END AS backup_protection_status,
ROUND(CASE WHEN f.last_backup_time IS NOT NULL THEN SYSDATE - f.last_backup_time ELSE NULL END, 2) AS days_since_last_success
FROM family_agg f
LEFT JOIN last_backup_member lb ON f.base_name = lb.base_name
WHERE f.recent_backup_done = 0 -- Only show families without a recent backup
ORDER BY backup_protection_status, f.base_name;





0 comments:
Post a Comment