00

Required Oracle Grants

Grant these privileges to the TuneVault service account before running health checks. The account needs SELECT_CATALOG_ROLE plus two explicit grants that catalog role does not cover.

🔒 Minimum required grants

Copy and run these statements as SYS or SYSTEM. Replace tunevault_user with your service account name.

-- Core catalog access (covers DBA_* views, V$* views)
GRANT SELECT_CATALOG_ROLE TO tunevault_user;
GRANT CREATE SESSION TO tunevault_user;

-- Alert log access (not covered by SELECT_CATALOG_ROLE)
GRANT SELECT ON V_$DIAG_ALERT_EXT TO tunevault_user;

                
No write access needed. TuneVault never executes INSERT, UPDATE, DELETE, or DDL statements. All queries are SELECT-only against system catalog views (DBA_*, V$*, GV$*). The service account requires no object privileges beyond what's listed above.
AWR / ADDM checks (the optional on-demand panel) require Oracle Enterprise Edition with the Diagnostics Pack license (control_management_pack_access = DIAGNOSTIC+TUNING). TuneVault checks for this license before running AWR queries and skips them gracefully on Standard Edition or unlicensed systems.
01

SQL Queries Executed Against Your Database

All queries shown below are executed during a health check run. They are read-only SELECTs. Queries are run in parallel where possible to minimise elapsed time. Click any row to expand the literal SQL.

Instance & Version
Instance information
Identifies Oracle version, host, uptime, CPU count, SGA/PGA targets, and block size
V$DATABASE V$INSTANCE V$PARAMETER
SELECT
  d.NAME, i.INSTANCE_NAME, i.HOST_NAME, i.VERSION,
  d.PLATFORM_NAME,
  TO_CHAR(i.STARTUP_TIME, 'YYYY-MM-DD HH24:MI:SS'),
  ROUND(SYSDATE - i.STARTUP_TIME),
  (SELECT VALUE FROM v$parameter WHERE name = 'cpu_count'),
  ROUND((SELECT TO_NUMBER(VALUE)/1024/1024/1024 FROM v$parameter WHERE name = 'sga_target'), 1),
  ROUND((SELECT TO_NUMBER(VALUE)/1024/1024/1024 FROM v$parameter WHERE name = 'pga_aggregate_target'), 1),
  (SELECT TO_NUMBER(VALUE) FROM v$parameter WHERE name = 'db_block_size')
FROM v$database d, v$instance i
Database version banner
Retrieves the version banner to detect Enterprise vs Standard Edition (gates AWR/ADDM queries)
V$VERSION
SELECT BANNER FROM V$VERSION WHERE ROWNUM = 1
Storage
Tablespace usage
Reports used/total GB and % utilisation for every tablespace; flags >80% as warning, >90% as critical
DBA_TABLESPACE_USAGE_METRICS DBA_TABLESPACES DBA_DATA_FILES
SELECT
  ts.TABLESPACE_NAME,
  ROUND(um.USED_SPACE * ts.BLOCK_SIZE / 1024/1024/1024, 1) AS used_gb,
  ROUND(um.TABLESPACE_SIZE * ts.BLOCK_SIZE / 1024/1024/1024, 1) AS total_gb,
  ROUND(um.USED_PERCENT, 1) AS pct_used,
  CASE WHEN df.autoext > 0 THEN 1 ELSE 0 END AS autoextend
FROM DBA_TABLESPACE_USAGE_METRICS um
JOIN DBA_TABLESPACES ts ON ts.TABLESPACE_NAME = um.TABLESPACE_NAME
LEFT JOIN (
  SELECT TABLESPACE_NAME,
    SUM(CASE WHEN AUTOEXTENSIBLE = 'YES' THEN 1 ELSE 0 END) AS autoext
  FROM DBA_DATA_FILES GROUP BY TABLESPACE_NAME
) df ON df.TABLESPACE_NAME = um.TABLESPACE_NAME
ORDER BY um.USED_PERCENT DESC
Undo tablespace health
Checks undo retention, block counts, and concurrency; historical peak usage via AWR when licensed
V$UNDOSTAT DBA_DATA_FILES DBA_TABLESPACES DBA_HIST_UNDOSTAT
SELECT UNDOBLKS, TXNCOUNT, MAXQUERYLEN, MAXCONCURRENCY,
       TUNED_UNDORETENTION, EXPIREDBLKS, UNEXPIREDBLKS, ACTIVEBLKS
FROM V$UNDOSTAT WHERE ROWNUM = 1 ORDER BY END_TIME DESC

-- Undo tablespace size
SELECT d.TABLESPACE_NAME, SUM(d.BYTES)/1073741824,
       SUM(d.BYTES - NVL(f.FREE_BYTES,0))/1073741824,
       ROUND(SUM(d.BYTES - NVL(f.FREE_BYTES,0))/SUM(d.BYTES)*100,1), t.RETENTION
FROM DBA_DATA_FILES d JOIN DBA_TABLESPACES t ON t.TABLESPACE_NAME=d.TABLESPACE_NAME
LEFT JOIN (SELECT FILE_ID, SUM(BYTES) AS FREE_BYTES FROM DBA_FREE_SPACE GROUP BY FILE_ID) f
  ON f.FILE_ID=d.FILE_ID
WHERE t.CONTENTS='UNDO' GROUP BY d.TABLESPACE_NAME, t.RETENTION
Temp tablespace usage
Reports temp space used/free; lists top sessions by temp usage to identify runaway sorts or hash joins
DBA_TEMP_FREE_SPACE V$TEMPSEG_USAGE
SELECT TABLESPACE_NAME, ROUND(TABLESPACE_SIZE/1073741824,2),
       ROUND(FREE_SPACE/1073741824,2),
       ROUND((TABLESPACE_SIZE-FREE_SPACE)/NULLIF(TABLESPACE_SIZE,0)*100,1)
FROM DBA_TEMP_FREE_SPACE

-- Top temp-consuming sessions
SELECT s.SID, s.SERIAL#, s.USERNAME,
       ROUND(s.BLOCKS*8192/1048576,1), s.TABLESPACE
FROM V$TEMPSEG_USAGE s ORDER BY s.BLOCKS DESC FETCH FIRST 10 ROWS ONLY
Top segments by size
Identifies the 10 largest tables/indexes by GB to spot unexpected growth
DBA_SEGMENTS
SELECT OWNER, SEGMENT_NAME, SEGMENT_TYPE,
       ROUND(SUM(BYTES)/1073741824, 2) AS size_gb
FROM DBA_SEGMENTS
WHERE OWNER NOT IN ('SYS','SYSTEM','DBSNMP','SYSMAN','OUTLN','MDSYS',
  'ORDSYS','XDB','CTXSYS','WMSYS','EXFSYS')
GROUP BY OWNER, SEGMENT_NAME, SEGMENT_TYPE
ORDER BY size_gb DESC FETCH FIRST 10 ROWS ONLY
Datafile status
Counts offline or problem datafiles that could cause partial data unavailability
DBA_DATA_FILES
SELECT COUNT(*) AS problem_count,
       COUNT(CASE WHEN STATUS = 'OFFLINE' THEN 1 END) AS offline_count
FROM DBA_DATA_FILES
WHERE STATUS NOT IN ('AVAILABLE','ONLINE')
Recycle bin size
Measures wasted space from dropped-but-not-purged objects
DBA_RECYCLEBIN
SELECT COUNT(*) AS object_count,
       ROUND(SUM(SPACE)*8192/1073741824, 2) AS size_gb
FROM DBA_RECYCLEBIN
Memory (SGA / PGA)
SGA components & hit ratios
Buffer cache hit ratio, library cache hit ratio, dictionary cache hit ratio, shared pool free %, and parse rates
V$SGA V$SYSSTAT V$LIBRARYCACHE V$ROWCACHE V$SGASTAT
SELECT ROUND(SUM(VALUE)/1024/1024/1024, 1) FROM V$SGA

-- Buffer cache hit ratio
SELECT ROUND((1 - (phys.VALUE / (db_gets.VALUE + con_gets.VALUE))) * 100, 1)
FROM (SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'physical reads') phys,
     (SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'db block gets') db_gets,
     (SELECT VALUE FROM V$SYSSTAT WHERE NAME = 'consistent gets') con_gets

-- Library cache hit ratio
SELECT ROUND(SUM(PINS - RELOADS) / NULLIF(SUM(PINS), 0) * 100, 1) FROM V$LIBRARYCACHE

-- Dictionary cache hit ratio
SELECT ROUND(SUM(GETS - GETMISSES) / NULLIF(SUM(GETS), 0) * 100, 1) FROM V$ROWCACHE

-- Shared pool free %
SELECT ROUND(free_bytes.val / total_bytes.val * 100, 1)
FROM (SELECT SUM(BYTES) AS val FROM V$SGASTAT WHERE POOL='shared pool' AND NAME='free memory') free_bytes,
     (SELECT SUM(BYTES) AS val FROM V$SGASTAT WHERE POOL='shared pool') total_bytes
PGA statistics
PGA target vs allocated, over-allocation count, cache hit %, and work area execution modes (optimal/onepass/multipass)
V$PGASTAT V$PARAMETER V$SQL_WORKAREA_HISTOGRAM
SELECT
  ROUND((SELECT TO_NUMBER(VALUE)/1024/1024/1024 FROM v$parameter WHERE name='pga_aggregate_target'),1),
  ROUND((SELECT VALUE/1024/1024/1024 FROM V$PGASTAT WHERE NAME='total PGA allocated'),1),
  ROUND((SELECT VALUE/1024/1024/1024 FROM V$PGASTAT WHERE NAME='maximum PGA allocated'),1),
  (SELECT VALUE FROM V$PGASTAT WHERE NAME='over allocation count'),
  ROUND((SELECT VALUE FROM V$PGASTAT WHERE NAME='cache hit percentage'),1)
FROM DUAL

-- Work area execution modes
SELECT ROUND(optimal.cnt/NULLIF(total.cnt,0)*100,1),
       ROUND(onepass.cnt/NULLIF(total.cnt,0)*100,1),
       ROUND(multipass.cnt/NULLIF(total.cnt,0)*100,1)
FROM (SELECT SUM(OPTIMAL_EXECUTIONS+ONEPASS_EXECUTIONS+MULTIPASSES_EXECUTIONS) AS cnt
      FROM V$SQL_WORKAREA_HISTOGRAM WHERE LOW_OPTIMAL_SIZE>0) total,
     (SELECT SUM(OPTIMAL_EXECUTIONS) AS cnt FROM V$SQL_WORKAREA_HISTOGRAM WHERE LOW_OPTIMAL_SIZE>0) optimal,
     (SELECT SUM(ONEPASS_EXECUTIONS) AS cnt FROM V$SQL_WORKAREA_HISTOGRAM WHERE LOW_OPTIMAL_SIZE>0) onepass,
     (SELECT SUM(MULTIPASSES_EXECUTIONS) AS cnt FROM V$SQL_WORKAREA_HISTOGRAM WHERE LOW_OPTIMAL_SIZE>0) multipass
OS memory & CPU stats (via Oracle)
Physical memory, free memory, CPU count, CPU utilisation %, and I/O wait % — read from Oracle's OS stats view, no shell access required
V$OSSTAT
SELECT STAT_NAME, VALUE FROM V$OSSTAT
WHERE STAT_NAME IN (
  'NUM_CPUS','IDLE_TIME','BUSY_TIME','USER_TIME',
  'SYS_TIME','IOWAIT_TIME',
  'PHYSICAL_MEMORY_BYTES','FREE_MEMORY_BYTES'
)
SGA resize history (AWR)
Shows recent SGA component resizes and peak PGA allocation over the last 30 days (requires AWR license)
V$SGA_RESIZE_OPS DBA_HIST_PGASTAT DBA_HIST_SGA DBA_HIST_SNAPSHOT
-- SGA component resizes
SELECT TO_CHAR(START_TIME,'YYYY-MM-DD HH24:MI'), COMPONENT,
       OPER_TYPE, ROUND(INITIAL_SIZE/1073741824,2),
       ROUND(FINAL_SIZE/1073741824,2), STATUS
FROM V$SGA_RESIZE_OPS ORDER BY START_TIME DESC FETCH FIRST 20 ROWS ONLY

-- AWR: peak PGA (licensed only)
SELECT ROUND(MAX(VALUE)/1073741824,2),
       TO_CHAR(MAX(s.END_INTERVAL_TIME) KEEP
               (DENSE_RANK LAST ORDER BY p.VALUE),'YYYY-MM-DD HH24:MI')
FROM DBA_HIST_PGASTAT p
JOIN DBA_HIST_SNAPSHOT s ON s.SNAP_ID=p.SNAP_ID
WHERE p.NAME='maximum PGA allocated' AND s.END_INTERVAL_TIME>SYSDATE-30
Performance
Top 10 SQL by elapsed time
Identifies the most resource-intensive SQL statements; excludes system schemas and internal metadata queries
V$SQL
SELECT SQL_ID, SUBSTR(SQL_TEXT, 1, 500), EXECUTIONS,
  ROUND(ELAPSED_TIME/1000000, 1), ROUND(CPU_TIME/1000000, 1),
  BUFFER_GETS, DISK_READS, ROWS_PROCESSED,
  CASE WHEN EXECUTIONS > 0 THEN ROUND(ELAPSED_TIME/EXECUTIONS/1000, 2) ELSE 0 END,
  CASE WHEN EXECUTIONS > 0 THEN ROUND(BUFFER_GETS/EXECUTIONS) ELSE 0 END,
  PLAN_HASH_VALUE
FROM V$SQL
WHERE EXECUTIONS > 0 AND ELAPSED_TIME > 0
  AND PARSING_SCHEMA_NAME NOT IN ('SYS','SYSTEM','DBSNMP','SYSMAN','OUTLN',
    'MDSYS','ORDSYS','EXFSYS','WMSYS','APPQOSSYS','DBSFWUSER')
  AND SQL_TEXT NOT LIKE '%v$%' AND SQL_TEXT NOT LIKE '%V$%'
  AND COMMAND_TYPE IN (2, 3, 6, 7, 189)
ORDER BY ELAPSED_TIME DESC FETCH FIRST 10 ROWS ONLY
Top 15 wait events
Identifies the leading wait events (excluding idle) that are consuming database time
V$SYSTEM_EVENT
SELECT EVENT, WAIT_CLASS, TOTAL_WAITS,
  ROUND(TIME_WAITED/100, 1) AS time_waited_s,
  CASE WHEN TOTAL_WAITS > 0
    THEN ROUND((TIME_WAITED/100/TOTAL_WAITS)*1000, 2) ELSE 0 END AS avg_wait_ms
FROM V$SYSTEM_EVENT
WHERE WAIT_CLASS NOT IN ('Idle') AND TOTAL_WAITS > 0
ORDER BY TIME_WAITED DESC FETCH FIRST 15 ROWS ONLY
Index health (top 20 fragmented)
Detects indexes with high B-tree depth (>3) or low direct access % — candidates for rebuild
DBA_INDEXES DBA_IND_STATISTICS V$PARAMETER
SELECT i.OWNER, i.INDEX_NAME, i.TABLE_NAME,
  ROUND(s.LEAF_BLOCKS *
    (SELECT TO_NUMBER(VALUE) FROM v$parameter WHERE name='db_block_size')
    / 1024/1024) AS size_mb,
  i.BLEVEL, s.LEAF_BLOCKS, i.CLUSTERING_FACTOR,
  NVL(s.PCT_DIRECT_ACCESS,100), i.STATUS,
  CASE
    WHEN i.STATUS != 'VALID' THEN 'unusable'
    WHEN i.BLEVEL > 4 THEN 'critical'
    WHEN NVL(s.PCT_DIRECT_ACCESS,100) < 50 THEN 'critical'
    WHEN i.BLEVEL > 3 THEN 'fragmented'
    WHEN NVL(s.PCT_DIRECT_ACCESS,100) < 70 THEN 'fragmented'
    ELSE 'ok'
  END AS health_status
FROM DBA_INDEXES i
LEFT JOIN DBA_IND_STATISTICS s
  ON s.OWNER=i.OWNER AND s.INDEX_NAME=i.INDEX_NAME AND s.PARTITION_NAME IS NULL
WHERE i.OWNER NOT IN ('SYS','SYSTEM','DBSNMP','SYSMAN','OUTLN','MDSYS','ORDSYS',
  'EXFSYS','WMSYS','XDB','CTXSYS','APPQOSSYS','DBSFWUSER',
  'APEX_040000','APEX_040200','APEX_050000','FLOWS_FILES')
  AND i.INDEX_TYPE = 'NORMAL' AND NVL(s.LEAF_BLOCKS, 0) > 100
ORDER BY CASE WHEN i.STATUS != 'VALID' THEN 1 WHEN i.BLEVEL > 4 THEN 2
              WHEN i.BLEVEL > 3 THEN 3 ELSE 4 END,
         s.LEAF_BLOCKS DESC NULLS LAST
FETCH FIRST 20 ROWS ONLY
Resource limits
Current and maximum utilisation of sessions, processes, transactions, and lock resources vs. configured limits
V$RESOURCE_LIMIT DBA_HIST_RESOURCE_LIMIT
SELECT RESOURCE_NAME, CURRENT_UTILIZATION, MAX_UTILIZATION,
       INITIAL_ALLOCATION, LIMIT_VALUE
FROM V$RESOURCE_LIMIT
WHERE RESOURCE_NAME IN (
  'sessions','processes','enqueue_locks','enqueue_resources',
  'dml_locks','temporary_table_locks','transactions','max_rollback_segments'
)
ORDER BY CASE RESOURCE_NAME
  WHEN 'sessions' THEN 1 WHEN 'processes' THEN 2
  WHEN 'transactions' THEN 3 WHEN 'enqueue_locks' THEN 4 ELSE 9 END
Session counts & blocked sessions
Total / active / user session counts; identifies blocked sessions and long-running SQL (>5 minutes)
V$SESSION
-- Session counts
SELECT COUNT(*), COUNT(CASE WHEN STATUS='ACTIVE' AND TYPE='USER' THEN 1 END),
       COUNT(CASE WHEN TYPE='USER' THEN 1 END)
FROM V$SESSION

-- Blocked sessions
SELECT COUNT(*) FROM V$SESSION
WHERE BLOCKING_SESSION IS NOT NULL AND STATUS = 'ACTIVE'

-- Long-running SQL
SELECT COUNT(*), ROUND(MAX((SYSDATE - SQL_EXEC_START)*1440), 1)
FROM V$SESSION
WHERE STATUS='ACTIVE' AND TYPE='USER'
  AND SQL_EXEC_START IS NOT NULL
  AND (SYSDATE - SQL_EXEC_START)*1440 > 5
Disk sort & full table scan ratios
Ratio of disk-based sorts to in-memory sorts; ratio of full table scans to index lookups — high values indicate PGA undersizing or missing indexes
V$SYSSTAT
SELECT d.VALUE AS disk_sorts, m.VALUE AS mem_sorts
FROM (SELECT VALUE FROM V$SYSSTAT WHERE NAME='sorts (disk)') d,
     (SELECT VALUE FROM V$SYSSTAT WHERE NAME='sorts (memory)') m

SELECT s.VALUE AS long_scans, i.VALUE AS index_lookups
FROM (SELECT VALUE FROM V$SYSSTAT WHERE NAME='table scans (long tables)') s,
     (SELECT VALUE FROM V$SYSSTAT WHERE NAME='table fetch by rowid') i
Invalid objects & stale statistics
Counts invalid packages, procedures, views, and triggers; counts tables with stale or missing optimizer statistics
DBA_OBJECTS DBA_TAB_STATISTICS
SELECT COUNT(*),
  COUNT(CASE WHEN OBJECT_TYPE IN ('PACKAGE BODY','PACKAGE') THEN 1 END),
  COUNT(CASE WHEN OBJECT_TYPE='PROCEDURE' THEN 1 END),
  COUNT(CASE WHEN OBJECT_TYPE='VIEW' THEN 1 END),
  COUNT(CASE WHEN OBJECT_TYPE='TRIGGER' THEN 1 END)
FROM DBA_OBJECTS
WHERE STATUS='INVALID'
  AND OWNER NOT IN ('SYS','SYSTEM','DBSNMP','SYSMAN','OUTLN',
    'MDSYS','ORDSYS','XDB','CTXSYS','WMSYS','EXFSYS','APPQOSSYS',
    'DBSFWUSER','OJVMSYS','DVSYS','LBACSYS')

SELECT COUNT(*), COUNT(CASE WHEN LAST_ANALYZED IS NULL THEN 1 END)
FROM DBA_TAB_STATISTICS
WHERE STALE_STATS='YES'
  AND OWNER NOT IN ('SYS','SYSTEM','DBSNMP','SYSMAN','OUTLN',
    'MDSYS','ORDSYS','XDB','CTXSYS','WMSYS','EXFSYS')
SCN headroom
Calculates days until SCN exhaustion — low values require emergency patching
V$DATABASE
SELECT CURRENT_SCN,
  ROUND(
    (TO_NUMBER(SYSDATE - TO_DATE('01-01-1988','DD-MM-YYYY'))
     * 24 * 3600 * 16384 * 1024 - CURRENT_SCN)
    / (24*3600*16384), 0
  ) AS days_remaining
FROM V$DATABASE
Alert log errors (last 24h)
Reads the last 24 hours of ORA- errors, checkpoints, corruption warnings, and TNS errors from the in-memory alert log view
V$DIAG_ALERT_EXT
SELECT TO_CHAR(ORIGINATING_TIMESTAMP,'YYYY-MM-DD HH24:MI:SS'),
       MESSAGE_TEXT
FROM V$DIAG_ALERT_EXT
WHERE ORIGINATING_TIMESTAMP > SYSDATE-1
  AND (MESSAGE_TEXT LIKE 'ORA-%'
       OR MESSAGE_TEXT LIKE '%checkpoint%'
       OR MESSAGE_TEXT LIKE '%corruption%'
       OR MESSAGE_TEXT LIKE '%recovery%'
       OR MESSAGE_TEXT LIKE '%error%'
       OR MESSAGE_TEXT LIKE '%warning%'
       OR MESSAGE_TEXT LIKE '%TNS-%'
       OR MESSAGE_TEXT LIKE '%instance%'
       OR MESSAGE_TEXT LIKE 'Thread%')
ORDER BY ORIGINATING_TIMESTAMP DESC FETCH FIRST 200 ROWS ONLY

-- Note: requires explicit GRANT SELECT ON V_$DIAG_ALERT_EXT TO tunevault_user
-- This grant is NOT included in SELECT_CATALOG_ROLE
Backup & Recovery
RMAN backup freshness
Last full/incremental/archivelog backup time and size; flags >48h since last full as critical
V$RMAN_BACKUP_JOB_DETAILS
-- Last backup by type
SELECT INPUT_TYPE, STATUS,
  TO_CHAR(START_TIME,'YYYY-MM-DD HH24:MI:SS'),
  TO_CHAR(END_TIME,'YYYY-MM-DD HH24:MI:SS'),
  ROUND((SYSDATE - END_TIME)*24, 1) AS hours_ago,
  ROUND(OUTPUT_BYTES/1073741824, 2) AS size_gb,
  ELAPSED_SECONDS
FROM (
  SELECT INPUT_TYPE, STATUS, START_TIME, END_TIME,
         OUTPUT_BYTES, ELAPSED_SECONDS,
         ROW_NUMBER() OVER (PARTITION BY INPUT_TYPE ORDER BY END_TIME DESC) AS RN
  FROM V$RMAN_BACKUP_JOB_DETAILS WHERE STATUS='COMPLETED'
) WHERE RN=1
ORDER BY CASE INPUT_TYPE
  WHEN 'DB FULL' THEN 1 WHEN 'DB INCR' THEN 2
  WHEN 'ARCHIVELOG' THEN 3 ELSE 4 END

-- Recent 10 jobs
SELECT INPUT_TYPE, STATUS,
  TO_CHAR(START_TIME,'YYYY-MM-DD HH24:MI:SS'),
  TO_CHAR(END_TIME,'YYYY-MM-DD HH24:MI:SS'),
  ROUND((SYSDATE-END_TIME)*24,1), ROUND(OUTPUT_BYTES/1073741824,2), ELAPSED_SECONDS
FROM V$RMAN_BACKUP_JOB_DETAILS
ORDER BY START_TIME DESC FETCH FIRST 10 ROWS ONLY
Fast Recovery Area (FRA) usage
FRA size, used space, reclaimable space, and breakdown by file type; estimates hours until FRA fills
V$RECOVERY_FILE_DEST V$FLASH_RECOVERY_AREA_USAGE V$ARCHIVED_LOG
SELECT NAME,
  ROUND(SPACE_LIMIT/1073741824,2), ROUND(SPACE_USED/1073741824,2),
  ROUND(SPACE_RECLAIMABLE/1073741824,2), NUMBER_OF_FILES
FROM V$RECOVERY_FILE_DEST

SELECT FILE_TYPE, ROUND(PERCENT_SPACE_USED,1),
       ROUND(PERCENT_SPACE_RECLAIMABLE,1), NUMBER_OF_FILES
FROM V$FLASH_RECOVERY_AREA_USAGE ORDER BY PERCENT_SPACE_USED DESC

-- Archivelog generation rate (last 24h) for "hours until full" forecast
SELECT ROUND(SUM(BLOCKS * BLOCK_SIZE)/1073741824, 2)
FROM V$ARCHIVED_LOG
WHERE COMPLETION_TIME > SYSDATE-1 AND STANDBY_DEST='NO'
Archivelog mode & log switch rate
Confirms database is in ARCHIVELOG mode; measures log switch frequency (alert if >20/hour, indicating redo log sizing issue)
V$DATABASE V$INSTANCE V$ARCHIVED_LOG V$LOG V$LOG_HISTORY
SELECT LOG_MODE, ROUND((SYSDATE - STARTUP_TIME)*24)
FROM V$DATABASE, V$INSTANCE

-- Hourly archivelog volume (last 24h)
SELECT TO_CHAR(COMPLETION_TIME,'YYYY-MM-DD HH24'), COUNT(*),
       ROUND(SUM(BLOCKS*BLOCK_SIZE)/1048576, 1)
FROM V$ARCHIVED_LOG
WHERE COMPLETION_TIME > SYSDATE-1 AND STANDBY_DEST='NO'
GROUP BY TO_CHAR(COMPLETION_TIME,'YYYY-MM-DD HH24') ORDER BY 1 DESC

-- Log switch frequency
SELECT ROUND(COUNT(*)/24.0, 1), COUNT(*)
FROM V$LOG_HISTORY WHERE FIRST_TIME > SYSDATE-1
Backup corruption check
Counts corruption markers in RMAN backup sets and image copies
V$RMAN_STATUS V$BACKUP_CORRUPTION V$COPY_CORRUPTION
-- Recent RMAN operations
SELECT OPERATION, STATUS,
  TO_CHAR(START_TIME,'YYYY-MM-DD HH24:MI:SS'),
  TO_CHAR(END_TIME,'YYYY-MM-DD HH24:MI:SS'),
  MBYTES_PROCESSED, OUTPUT
FROM V$RMAN_STATUS
WHERE OPERATION IN ('BACKUP','RESTORE','RECOVER','DELETE','VALIDATE')
  AND START_TIME > SYSDATE-7
ORDER BY START_TIME DESC FETCH FIRST 20 ROWS ONLY

-- Backup set corruption
SELECT COUNT(*), SUM(BLOCKS) FROM V$BACKUP_CORRUPTION

-- Copy corruption
SELECT COUNT(*), SUM(BLOCKS) FROM V$COPY_CORRUPTION
Security
Default-password accounts
Counts OPEN accounts still using well-known default passwords (Oracle's own advisory view)
DBA_USERS_WITH_DEFPWD
SELECT COUNT(*) FROM DBA_USERS_WITH_DEFPWD
WHERE ACCOUNT_STATUS = 'OPEN'
Dangerous PUBLIC grants
Flags if PUBLIC has been granted dangerous privileges such as CREATE ANY PROCEDURE or ALTER SYSTEM
DBA_SYS_PRIVS
SELECT COUNT(*) FROM DBA_SYS_PRIVS
WHERE GRANTEE = 'PUBLIC'
  AND PRIVILEGE IN (
    'CREATE PROCEDURE','CREATE ANY PROCEDURE',
    'CREATE ANY TRIGGER','ALTER SYSTEM','ALTER DATABASE',
    'DROP ANY TABLE','EXECUTE ANY PROCEDURE'
  )
Password policy & audit settings
Checks whether a password complexity function is configured and whether auditing is enabled
DBA_PROFILES V$PARAMETER
SELECT LIMIT FROM DBA_PROFILES
WHERE PROFILE='DEFAULT' AND RESOURCE_NAME='PASSWORD_VERIFY_FUNCTION'

SELECT VALUE FROM V$PARAMETER WHERE NAME='audit_trail'
DBA-privileged user count
Counts non-system accounts with DBA privilege — should be minimal in hardened environments
DBA_SYS_PRIVS
SELECT COUNT(DISTINCT GRANTEE) FROM DBA_SYS_PRIVS
WHERE PRIVILEGE='DBA'
  AND GRANTEE NOT IN ('SYS','SYSTEM','DBA','SYSMAN')
Schema-only (no-auth) open accounts
Lists schema-owner accounts with no authentication that are OPEN — should be locked in production
DBA_USERS
SELECT COUNT(*) FROM DBA_USERS
WHERE ACCOUNT_STATUS='OPEN'
  AND AUTHENTICATION_TYPE='NONE'
  AND USERNAME NOT IN ('SYS','SYSTEM')
ADDM (on-demand panel — Enterprise Edition + Diagnostics Pack only)
License gate. TuneVault checks V$VERSION for 'ENTERPRISE' and DBA_FEATURE_USAGE_STATISTICS for Diagnostics Pack before running any AWR/ADDM queries. These queries are skipped silently on Standard Edition or non-licensed systems.
ADDM findings (AWR-backed)
Reads Automatic Database Diagnostic Monitor findings for the specified lookback window
DBA_HIST_SNAPSHOT DBA_HIST_ADDM_TASKS DBA_HIST_ADDM_FINDINGS DBA_HIST_ADDM_INSTANCES DBA_ADVISOR_FINDINGS
-- Find snapshot range for lookback period
SELECT MIN(SNAP_ID), MAX(SNAP_ID), MIN(BEGIN_INTERVAL_TIME), MAX(END_INTERVAL_TIME)
FROM DBA_HIST_SNAPSHOT
WHERE END_INTERVAL_TIME > SYSDATE - :lookback_hours/24

-- ADDM task for snapshot range
SELECT TASK_ID, TASK_NAME FROM DBA_HIST_ADDM_TASKS
WHERE BEGIN_SNAP_ID = :begin_snap AND END_SNAP_ID = :end_snap
  AND STATUS = 'COMPLETED' FETCH FIRST 1 ROWS ONLY

-- ADDM findings
SELECT f.FINDING_ID, f.TYPE, f.MESSAGE, f.BENEFIT,
       d.ATTR1 AS recommendation, d.TYPE AS rec_type
FROM DBA_ADVISOR_FINDINGS f
LEFT JOIN DBA_ADVISOR_RECOMMENDATIONS d ON d.TASK_ID=f.TASK_ID AND d.FINDING_ID=f.FINDING_ID
WHERE f.TASK_ID = :task_id
ORDER BY f.BENEFIT DESC NULLS LAST FETCH FIRST 20 ROWS ONLY
02

OS Commands Executed on Your Server

The proxy reads OS and memory metrics exclusively through Oracle's V$OSSTAT view. No shell commands are executed for any health check.

No shell access needed. CPU utilisation, memory, and I/O wait are read from V$OSSTAT via the Oracle connection — no df, ps, or cat commands are executed. All 100+ health checks are pure Oracle SQL.
Proxy isolation. The proxy binds to 127.0.0.1:3100 only (configurable via BIND_HOST env var). It never opens inbound ports on external interfaces. Access from TuneVault's servers goes through your existing outbound HTTPS proxy — the proxy agent itself makes no inbound connections.
03

Network Egress from the Proxy

The proxy makes exactly two outbound HTTPS connections. No inbound ports are opened. No data is sent to third parties.

Destination
tunevault.app (Render, US region)
Port / Protocol
443 / HTTPS (TLS 1.2+)
Purpose
Delivers health check results to your TuneVault account. JSON payload only — Oracle metric data collected during the health check run.
Authentication
64-hex API key in X-API-Key header, generated locally on your server during proxy installation
Data sent
Oracle metrics (tablespace usage, wait events, SQL statistics, etc.). No Oracle credentials, no database schema objects, no user data rows.
Destination
tunevault.app/api/proxy/version (same host)
Purpose
Auto-update check. Proxy polls this endpoint every 6 hours to see if a newer version is available. Update is applied by downloading the new binary, validating its SHA-256 checksum, and replacing itself in-place via os.execv (Node) or os.execv (Python). No restart of the parent process manager (PM2/systemd) is required.
Data sent
Current proxy version string only. No credentials, no metrics.
No Cloudflare Tunnel, no inbound connections. TuneVault uses a standard outbound HTTPS proxy pattern — you configure your existing reverse proxy (nginx, Apache, HAProxy) to forward requests on a hostname to http://localhost:3100. The proxy agent itself never opens any inbound port outside of localhost. TuneVault's servers make outbound HTTPS calls to your proxy URL — your firewall only needs to allow inbound HTTPS on port 443 from TuneVault's IP ranges (same as any HTTPS client).