Oracle Database Security Hardening & Performance Tuning

 

1. Introduction

Modern enterprise databases must balance two critical priorities: strong security and optimal performance. Database administrators are responsible not only for protecting data but also for ensuring efficient query execution, workload stability, and proactive monitoring.

This document provides a practical, hands-on guide to Oracle Database Security Hardening and Performance Tuning within a multi-tenant (CDB/PDB) architecture. It covers key administrative domains including user and role management, database security controls, DBSAT assessment, SQL tuning, AWR analysis, and ADDM recommendations.


The goal of this guide is to present a real-world, production-oriented approach that reflects actual Oracle DBA responsibilities. It demonstrates how to secure database environments, assess risks, monitor workload behavior, and optimize SQL performance using native Oracle tools.

Based on practical implementation scenarios, this documentation serves as a structured reference for Oracle DBAs and learners who want a clear understanding of both database hardening and performance optimization in modern enterprise environments.



2. Objective

The primary objective of this document is to:

  • Implement database security hardening best practices
  • Perform privilege and role management
  • Assess database security posture using DBSAT
  • Identify and resolve SQL performance issues
  • Analyze database workload using AWR and ADDM
  • Improve overall database performance and stability
  • Provide a structured, real-world DBA reference guide

3. Scope

This document covers:

  • User and role management best practices
  • Privilege control and least privilege model
  • Database security hardening techniques
  • Oracle Database Security Assessment Tool (DBSAT) usage
  • SQL performance tuning techniques
  • AWR report analysis
  • ADDM diagnostics and recommendations
  • End-to-end DBA operational workflow

4. Environment Details

Component

Details

Database Architecture

Multi-tenant (CDB/PDB)

CDB Name

PROD

PDBs

PRODPDB,  TESTPDB

Storage

ASM Disk Groups

Deployment

Clustered Database Environment

OS User

oracle

Monitoring Tools

AWR, ADDM, ASH

Security Tool

DBSAT

 

5. Prerequisites

Before implementation, ensure the following:

  • Oracle Database installed and configured
  • Multi-tenant architecture enabled (CDB/PDB)
  • SYSDBA privileges available
  • AWR snapshots enabled
  • Diagnostic Pack licensed (for AWR/ADDM usage)
  • DBSAT utility downloaded and configured
  • OS-level access for running DBSAT collector
  • Basic understanding of Oracle performance views

6. Use Cases

This implementation is useful in the following scenarios:

  • Database security audits
  • Pre-production hardening
  • Compliance readiness (ISO, SOC, etc.)
  • Performance troubleshooting
  • Production health checks
  • Migration readiness validation
  • DBA knowledge building and documentation

7. Methodology

The implementation follows a structured and layered approach:

1.    Secure user and role configuration

2.    Apply database security hardening measures

3.    Run DBSAT to assess security posture

4.    Identify risky privileges and sensitive data exposure

5.    Generate and analyze AWR reports

6.    Identify top SQL performance bottlenecks

7.    Use ADDM findings for root cause analysis

8.    Apply SQL tuning and configuration improvements

9.    Validate performance improvements


8. Implementation Steps

This section describes the practical implementation workflow for Oracle Database Security Hardening and Performance Tuning in a multi-tenant environment.

 

Environment Validation and Database Readiness Check



All critical components were validated successfully:

Clusterware healthy
RAC nodes operational
ASM disk groups mounted
Database instances running on both nodes
Multi-tenant architecture validated
PDBs open and operational

The environment is confirmed as:

Production-ready and stable for security hardening and performance tuning implementation.

 

8.1: User and Role Management

1. Overview

The first phase of database security hardening focuses on implementing strong identity and access management using the least privilege principle. Proper user and role management ensures that only authorized users can access database resources with minimal required privileges.

In multi-tenant architectures, access control must be carefully designed at both the Container Database (CDB) and Pluggable Database (PDB) levels to prevent privilege escalation and reduce attack surfaces.

 

2. Objective

The objective of this phase is to:

  • Implement secure password policies
  • Enforce role-based access control (RBAC)
  • Create application users with minimal privileges
  • Separate system users and application users
  • Enforce security controls at the PDB level

This ensures controlled and auditable database access.

 

3. Why This Is Important

Improper user management is one of the most common security risks in Oracle environments. Overprivileged users can lead to:

  • Unauthorized data access
  • Privilege escalation
  • Compliance violations
  • Increased attack surface

Implementing RBAC and password policies ensures a secure and compliant environment.

 

4. Implementation Steps

Step 1: Switch to Target PDB

User and role creation was performed at the pluggable database level to isolate application access.

This ensures that the security configuration is applied locally within the PDB.

 

Step 2: Create Secure Password Profile

A strong password profile was created to enforce authentication policies.

Security Controls Implemented:

  • Account lock after 5 failed logins
  • Mandatory password rotation (90 days)
  • Password reuse restrictions
  • Complexity validation using Oracle verify function

This enforces enterprise-grade password security.

 

Step 3: Create Application User

A dedicated application user was created with controlled resource usage.

This ensures:

  • Resource isolation
  • Password policy enforcement
  • Controlled tablespace usage

 

Step 4: Grant Minimum Required Privileges

The user was granted only the required login privilege.

This follows the least privilege model.

 

Step 5: Implement Role-Based Access Control (RBAC)

A read-only role was created to avoid direct privilege assignment.

Benefits of RBAC:

  • Centralized privilege management
  • Easier audits
  • Simplified privilege revocation
  • Improved scalability

 

5. Validation

The user and role creation were verified successfully at the PDB level.

Key validations performed:

  • Profile assigned correctly
  • Role inheritance confirmed
  • Session creation privileges validated

This confirms successful RBAC implementation.

 

6. Best Practices Followed

  • Created users at PDB level (not CDB root)
  • Implemented strong password policies
  • Used role-based privilege assignment
  • Avoided direct system privileges
  • Followed least privilege model

These practices align with enterprise Oracle security standards.

 

7. Key Outcome

After this implementation:

Secure authentication enforced
Controlled application access
Role-based privilege model implemented
Reduced privilege exposure

This establishes a strong identity and access management foundation for further hardening.

 

8.2: Security Hardening

1. Overview

Account hardening is a critical step in Oracle database security that focuses on minimizing the attack surface by disabling unused, default, and sample accounts. Many Oracle installations include pre-created schemas and legacy accounts that may pose security risks if left enabled.

This implementation ensures that only necessary and actively used accounts remain accessible across both Container Database (CDB) and Pluggable Databases (PDBs).

 

2. Objective

The objective of account hardening is to:

  • Identify Oracle-maintained and custom accounts
  • Lock unused default accounts
  • Disable legacy schemas
  • Harden both CDB and PDB layers
  • Prevent unauthorized lateral access

This significantly reduces database exposure.

 

3. Why Account Lockdown Is Important

Unused accounts are a common entry point for attackers due to:

  • Default credentials
  • Weak password policies
  • Legacy dependencies
  • Misconfigurations

Locking unused accounts ensures:

  • Reduced attack surface
  • Better compliance readiness
  • Improved audit posture
  • Stronger access governance

 

4. Implementation Steps

Step 1: Identify Oracle-Maintained Accounts

Switched to root container to identify Oracle-managed users.

 

 

This distinguishes system-managed accounts from user-created accounts.

Step 2: Identify Non-Oracle Accounts

Custom users were identified for review.



This helped identify:

  • Application schemas
  • Test users
  • Sample schemas (HR, SCOTT)

 

 

Step 3: Lock Unused System Accounts

Non-required system accounts were locked at the CDB level.

This prevents unauthorized use of legacy accounts.

 

Step 4: Lock Sample Schemas in PDB

Switched to the target PDB and locked sample users.



This eliminates risks from:

  • Demo schemas
  • Default passwords
  • Legacy objects

 

Step 5: Cross-Container Validation

Performed container-wide validation to ensure consistent lockdown.

 

This confirmed account lockdown across:

  • CDB$ROOT
  • PRODS
  • TESTPDB

 

5. Best Practices Followed

  • Locked unused default accounts
  • Disabled sample schemas
  • Hardened both CDB and PDB levels
  • Verified lockdown across containers
  • Avoided locking critical Oracle-managed accounts blindly

 

6. Key Outcome

After implementing account hardening:

Reduced attack surface
Disabled legacy and unused accounts
Eliminated risks from sample schemas
Enforced container-wide lockdown

This establishes a secure baseline before enabling auditing and compliance controls.

 

8.3: Database Auditing

1. Overview

Database auditing provides visibility into user activities and privileged operations. It enables tracking of security-sensitive actions such as configuration changes, user management, and data access, which is essential for compliance and forensic analysis.

In this implementation, traditional Oracle auditing was configured to monitor critical database activities.

Unified Auditing is centralized, efficient, and easier to manage, while Traditional Auditing is older, fragmented, and less performant.

 

2. Objective

The objective of auditing implementation is to:

  • Validate current auditing mode
  • Enable auditing for privileged operations
  • Track user and schema changes
  • Monitor sensitive data access
  • Establish audit visibility for compliance

This improves traceability and accountability.

 

3. Auditing Strategy

The auditing approach focused on:

  • Privileged operations monitoring
  • User lifecycle auditing
  • Data access auditing
  • Minimal performance overhead

This ensures balanced security and performance.

 

4. Implementation Steps

Step 1: Verify Auditing Mode

Validated whether Unified Auditing is enabled.



Result:
Unified Auditing was disabled.

Step 2: Check Traditional Auditing Configuration

Verified database auditing parameter.



Result:

  • audit_trail = DB
  • Traditional auditing enabled

This confirms audit records are stored in database tables.

 

Step 3: Enable Statement Auditing

Enabled auditing for critical administrative actions.

These actions help detect:

  • Unauthorized configuration changes
  • Suspicious user creation
  • Privilege misuse

 

Step 4: Enable Data Access Auditing

Enabled auditing for table access.


 


This ensures visibility into sensitive data access patterns.

 

Step 5: Validate Audit Configuration

Audit settings were verified using data dictionary views.

Validation confirmed:

  • Auditing enabled for both success and failure
  • Coverage for high-risk operations

5. Best Practices Followed

  • Verified auditing mode before configuration
  • Enabled targeted auditing (not blanket auditing)
  • Balanced visibility and performance
  • Audited high-risk operations first
  • Validated audit policies post-implementation

 

6. Key Outcome

After implementing auditing:

Visibility into privileged operations
Traceability for user management actions
Monitoring of sensitive data access
Improved compliance readiness
Stronger forensic capabilities

This completes the foundational database security layer.

 

8.4: Run DBSAT Assessment

Oracle's Database Security Assessment Tool (DBSAT) is a utility designed to help database administrators evaluate the security posture of Oracle databases. It performs a comprehensive security scan and generates reports highlighting configuration issues, account weaknesses, and auditing gaps.

1 Overview

DBSAT provides:

  • Analysis of database configuration against security best practices.
  • Identification of weak passwords, user privileges, and roles.
  • Review of auditing and system privileges.
  • Exportable reports in HTML, TXT, JSON, and XLSX formats.

DBSAT supports both on-premises and cloud databases (like Oracle 19c in a multi-tenant environment).

 

2 Installation & Setup

1.    Prepare Environment

Ensure Java 1.8 is installed and set:

 

2.    Unpack DBSAT

 

3 Running DBSAT Collection

  • Execute the collector to scan the database:

Notes:

  • The collector connects as SYSDBA to retrieve configuration, user, privilege, and audit information.
  • Some OS-level checks may be skipped depending on environment permissions.
  • Output is generated in a compressed .zip file (dbsat_out.zip) and can be encrypted with a password.

 

4 Generating DBSAT Reports

  • After collection, generate the security report:

  • Reports are created in multiple formats:

Ø dbsat_out_report.html — Viewable in any browser.

Ø dbsat_out_report.txt — Plain text summary.

Ø dbsat_out_report.xlsx — Excel for analysis.

Ø dbsat_out_report.json — Machine-readable format.

The report can be transferred to a Windows workstation using WinSCP, FileZilla, or similar tools to review the HTML or TXT output.

 

 

5 Benefits of DBSAT

  • Provides comprehensive security assessment without manual querying.
  • Identifies misconfigurations and excessive privileges.
  • Helps ensure compliance with company and regulatory security policies.
  • Generates readable and actionable reports for auditors or management.

 

6 Best Practices

  • Run DBSAT regularly as part of database security audits.
  • Use the generated HTML/Excel reports to track remediation progress.
  • Avoid running on production during peak hours to reduce load.
  • Encrypt output files to protect sensitive information.

 

 

Security Remediation

Based on DBSAT findings, remediation is performed.

Common Remediation Tasks

  • Revoke excessive privileges
  • Mask sensitive data exposure
  • Implement auditing controls
  • Remove insecure configurations
  • Enforce password complexity

 

Example

REVOKE ANY TABLE FROM app_user;
ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME 90;

 

Validation

  • Re-run DBSAT
  • Compare risk reduction

8.5: AWR Report Generation

AWR (Automatic Workload Repository) captures and stores performance statistics for Oracle databases. AWR reports help DBAs identify performance issues, workload patterns, and resource bottlenecks.

 

1 Overview

AWR (Automatic Workload Repository) is an Oracle database performance monitoring and tuning tool that collects, processes, and maintains performance statistics. It provides detailed insights into database workloads, helping DBAs identify bottlenecks and optimize system performance.

 

2 Objectives

  • Track database performance trends over time.
  • Identify high-load SQL statements and resource bottlenecks.
  • Support proactive performance tuning and capacity planning.
  • Provide historical performance data for troubleshooting.

 

3 Why Use AWR

  • Helps in diagnosing performance issues quickly.
  • Enables data-driven decisions for tuning SQL, memory, and I/O.
  • Facilitates trend analysis and historical comparisons.
  • Required for Enterprise Manager performance dashboards.

 

4 How It Works

1.    AWR captures snapshots of database performance statistics periodically (default every 60 minutes).

2.    Snapshots are stored in the SYSAUX tablespace within the DBA_HIST views.

3.    Reports are generated by selecting begin and end snapshot IDs for a given time period.

4.    Output formats: HTML, text, active-html.

 

5 Use Case

  • Multi-node RAC database experiencing intermittent performance degradation.
  • DBA wants a 7-day performance summary and to identify which SQL statements or resources are consuming the most time.

 

8.5.6 Implementation Steps

 

  • Report is generated in HTML format.
  • Transfer to local machine via WinSCP for review in a browser.

 

7 Best Practices

  • Run AWR reports periodically (weekly or monthly) for trend analysis.
  • For RAC, include all instances for complete performance visibility.
  • Archive AWR reports for historical reference.
  • Focus on top SQL, wait events, and load statistics.

 

8 Key Outcomes

  • Identifies high-load SQL and performance bottlenecks.
  • Provides resource utilization insights for tuning.
  • Helps in forecasting system scaling requirements.
  • Serves as a reference for ADDM analysis.

 

8.6: ADDM Analysis

1 Overview

ADDM (Automatic Database Diagnostic Monitor) analyzes AWR snapshots to provide actionable recommendations for improving Oracle database performance. ADDM highlights root causes of performance issues, eliminating manual analysis complexity.

 

2 Objectives

  • Automatically diagnose database performance issues.
  • Recommend tuning actions for SQL, memory, and I/O.
  • Quantify impact of performance problems.
  • Prioritize issues based on resource consumption.

 

3 Why Use ADDM

  • Reduces time and effort spent on manual performance analysis.
  • Provides instance-level and RAC-wide insights.
  • Helps proactively optimize system before end-user impact.
  • Supports capacity planning with workload impact projections.

 

4 How It Works

1.    ADDM reads AWR snapshots and calculates metrics such as:

o   Wait times

o   SQL execution times

o   I/O and memory statistics

2.    It generates recommendations such as:

o   SQL tuning

o   Index suggestions

o   Memory allocation adjustments

o   Load balancing across RAC nodes

3.    Reports are generated as text or HTML files.

5 Use Case

  • RAC database showing high CPU usage on prod1 node.
  • DBA runs ADDM for snapshots 100 → 103 to understand performance degradation and identify actionable recommendations.

 

6 Implementation Steps

  • Output: addm_rac_rpt.txt
  • Transfer to local machine for detailed review.

 

7 Best Practices

  • Always run AWR before ADDM to have snapshot data.
  • Use ADDM reports to implement recommendations incrementally.
  • Archive reports for audit and trend analysis.
  • Prioritize high-impact recommendations first (CPU, I/O, top SQL).

 

8 Key Outcomes

  • Provides root-cause analysis for performance issues.
  • Offers practical tuning recommendations.
  • Highlights system bottlenecks for proactive action.
  • Improves RAC instance balance and resource utilization.

 

 

 

AWR Remediation

Overview: Analyze database performance using AWR reports to identify bottlenecks.
Objective: Improve SQL, memory, and I/O efficiency.
Common Tasks:

  • Tune high-load SQL
  • Adjust SGA/PGA memory
  • Optimize I/O and storage
  • Balance RAC instance load

Example:

EXEC DBMS_STATS.GATHER_SCHEMA_STATS('HR');
CREATE INDEX idx_emp_dept ON emp(department_id);
ALTER SYSTEM SET sga_target=4G SCOPE=BOTH;

Validation:

  • Re-run AWR reports
  • Check CPU, I/O, and SQL improvements

 

ADDM Remediation

Overview: Use ADDM to get actionable performance recommendations.
Objective: Apply targeted fixes to reduce wait events and improve throughput.
Common Tasks:

  • Fix top wait events
  • Tune SQL statements
  • Adjust memory parameters
  • Implement ADDM suggested changes

Example:

-- Apply ADDM recommendations
EXEC DBMS_ADVISOR.IMPLEMENT_RECOMMENDATIONS('ADDMSQL_RECOMMEND');

Validation:

  • Re-run ADDM analysis
  • Compare improvements in response time and resource usage

8.7: SQL Tuning

Overview:
SQL Tuning improves query performance by reducing execution time, optimizing resource usage, and ensuring consistent execution plans.

 

Objective:

  • Reduce CPU, I/O, and memory usage
  • Minimize hard parses
  • Ensure consistent and efficient execution plans

 

Why SQL Tuning:
Even the same SQL can generate different PLAN_HASH_VALUEs due to changes in:

  • Table/index statistics
  • Execution plan changes (optimizer decisions)
  • Bind variable usage vs literals

 

Use Case:

  • High OLTP transaction systems
  • Reporting queries with large datasets
  • Queries showing variable execution times

 

Implementation Steps:

All SQL statements have to go through the following stages of execution:

1.Parse

  a.syntactic

  b.semantic check

2.Bind

3.Execute

4.Fetch

1) PARSE: Every SQL statement has to be parsed which includes checking the syntax, validating, ensuring that all references to objects are correct and ensuring that relevant privileges to those object exist.

 

Parsing -

1.syntactic

2.semantic check

 

u1-sql> select empname, job, sal, manager from emp where deptno=20;

 

syntactic check - standard for writing query

semantic check - object, users and their permission exist in DD

(The semantics check to confirm that the correct object name is used and also whether the user has the proper privileges to execute the query)

 

Hard Parse and Soft Parse –

If there is a fresh(new) query and its hash code does not exist in shared pool then that query has to pass through from the additional steps known as hard parsing otherwise if hash code exists then query does not passes through additional steps. It just passes directly to execution engine. This is known as soft parsing.

 

2) BIND: After parsing, the oracle server knows the meaning of the oracle statement but still may not have enough info(values for variables) to execute the statement. The process of obtaining these value is called as bind values.

 

SQL> select emp, ename, sal from emp where empno=7099;     

SQL> select emp, ename, sal from Emp where empno=7900;

SQL> select emp, ename, Sal from emp where deptno=8712;

 

SQL> variable deptno number

SQL> exec :deptno := 10          (exec : deptno := text1.value)

SQL> select emp, ename, sal from emp where deptno = :deptno;

 

 

3) EXECUTE: After binding, the Oracle server executes the statement.

 

4) FETCH: In the fetch stage, rows are selected and ordered and each successive row retrieves another row of the result until the last row has been fetched. This stage is only for certain DQL statements like SELECT.

 

Whenever a SQL statement is executed, Oracle Engine performs below actions on it:

 

1. Validate the Syntax

2. Validate the objects being referenced in the statement

3. Privileges assigned to user executing the Job

4. Verifying if statement is already available in the shared pool. Oracle engine will calculate the hash value    for the SQL statement and look in

 

  select empno, ename from emp where deptno=10;

 

5. If statement is not already present then allocate shared memory and create a cursor in shared pool

6. Generate the Execution Plan

SQL_ID - A unique 13-character alphanumeric string that identifies a normalized SQL statement.

 

HASH_VALUE - What it is: A numeric hash of the SQL text, generated using Oracle's internal algorithm.

 

PLAN_HASH_VALUE - A numeric hash representing the execution plan structure.

Purpose: Identifies whether a SQL is using the same or different execution plan over time.

                                                                                                                   

Usage: Helps in performance tuning, especially when the same SQL has multiple execution plans         (adaptive, stats change, bind variables, etc.)

 

 

select empno, ename, job, sal from emp; 

 

select empno, ename, job, sal from Emp;

 

select empno, Ename, job, sal from emp;

 

select empno, ename, job, sal from emP;

 

select empno, ename, job, sal from emp where empno=7839;

 

select sql_id, address, hash_value, plan_hash_value from v$sqlarea where sql_text=<string to identify my query>

 

select sql_id, SQL_TEXT, address, hash_value, plan_hash_value from v$sqlarea where sql_text like '%select empno%';

 

set lines 200

set pages 20

col SQL_TEXT for a60

select sql_id, SQL_TEXT, plan_hash_value from v$sqlarea where sql_text like '%select empno%';

 

SQL> alter system flush shared_pool;

 

System altered.

 

sql> select empno, ename, job, sal from emp;

 

SQL> select sql_id, address, hash_value, plan_hash_value from v$sqlarea where sql_text='select empno, ename, job, sal from emp';

 

SQL_ID        ADDRESS          HASH_VALUE PLAN_HASH_VALUE

------------- ---------------- ---------- ---------------

1jvn42p3gccuc 0000000076986C10 1190540108      3956160932

 

 

SQL> Select empno, ename, job, sal from EMP;

 

SQL> select sql_id, address, hash_value, plan_hash_value from v$sqlarea where sql_text='Select empno, ename, job, sal from EMP';

 

SQL_ID        ADDRESS          HASH_VALUE PLAN_HASH_VALUE

------------- ---------------- ---------- ---------------

a6fs5r3mzr422 000000007EE6E9E0 3892023362      3956160932

Note:

The SQL ID is a hash of the text of the SQL statement.

Similarly, the hash_value is a numeric hash of the statement itself. You expect these to be the same every time you run a statement.

 

The plan_hash_value is a hash of the execution plan. This will change if you get a different plan.

 

Bind variable

Bind variables are «substitution» variables that are used in place of literals (such as 674, 234, 332) and that have the effect of sending exactly the same SQL to Oracle every time the query is executed.

select empno, ename, job, sal from emp where empno=7839;   hash value

select empno, ename, job, sal from emp where empno=7840;   hash value

 

In SQL*Plus you can use bind variables as follows:

 

SQL> variable deptno number

SQL> exec :deptno := 10

SQL> select * from emp where deptno = :deptno;

 

Note: At run time it will assign value to variable.

 

Each time the query is submitted, Oracle first checks in the shared pool to see whether this statement has been submitted before. If it has, the execution plan that this statement previously used is retrieved, and the SQL is executed. If the statement cannot be found in the shared pool, Oracle has to go through the process of parsing the statement, working out the various execution paths and coming up with an optimal access plan before it can be executed. This process is known as a «hard parse» and for OLTP applications can actually take longer to carry out that the DML instruction itself.

 

The order of Query Execution is following

1)From Clause

2)Where Clause

3)Group By Clause

4)Having Clause

5)Select

6)Order By Clause

 

how the same SQL can result in different PLAN_HASH_VALUEs due to plan changes in Oracle.

 

Creates the table

Inserts data

Runs SQL

create index on that table

Run SQL after index creation

Captures and compares execution plans

 

LAB PLAN_HASH_VALUEs

 

STEP 1: Drop table if exists

 

DROP TABLE plan_demo PURGE;

 

BEGIN

  EXECUTE IMMEDIATE 'DROP TABLE plan_demo PURGE';

EXCEPTION

  WHEN OTHERS THEN

    NULL;

END;

/

 

STEP 2: Create table

CREATE TABLE plan_demo (

  id      NUMBER,

  name    VARCHAR2(50),

  salary  NUMBER

);

 

 

STEP 3: Insert sample data

BEGIN

  FOR i IN 1 .. 100000 LOOP

    INSERT INTO plan_demo VALUES (

      i,

      'Employee ' || i,

      MOD(i, 5000) + 30000

    );

  END LOOP;

  COMMIT;

END;

/

 

explain plan for SELECT * FROM plan_demo WHERE salary = 30001;

select * from table(DBMS_XPLAN.DISPLAY);

 

STEP 4: Gather stats

EXEC DBMS_STATS.GATHER_TABLE_STATS('U1', 'PLAN_DEMO');

 

STEP 5: Run SQL before index (Expect FULL TABLE SCAN)

SELECT * FROM plan_demo WHERE salary = 30001;

 

STEP 6: Find SQL_ID and PLAN_HASH_VALUE

SELECT sql_id, plan_hash_value, sql_text

FROM v$sql

WHERE sql_text LIKE 'SELECT * FROM plan_demo WHERE salary = 30001%';

 

STEP 7: Show Execution Plan

 

explain plan for SELECT * FROM plan_demo WHERE salary = 30001;

select * from table(DBMS_XPLAN.DISPLAY);

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));

 

STEP 8: Create index

CREATE INDEX idx_plan_salary ON plan_demo(salary);

EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'PLAN_DEMO');

STEP 9: Re-run the same SQL

SELECT * FROM plan_demo WHERE salary = 30001;

 

STEP 10: Check SQL_ID and PLAN_HASH_VALUE again

SELECT sql_id, plan_hash_value, sql_text

FROM v$sql

WHERE sql_text LIKE 'SELECT * FROM plan_demo WHERE salary = 30001%';

 

STEP 11: Show New Execution Plan

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));

 

STEP 12: Clean up (Optional)

DROP TABLE plan_demo PURGE;

 

Best Practices:

  • Use bind variables to reuse SQL in shared pool (reduces hard parses)
  • Keep statistics up-to-date for optimizer efficiency
  • Avoid unnecessary full table scans; create proper indexes
  • Monitor SQL_ID and PLAN_HASH_VALUE for plan stability

 

Key Outcomes:

  • Faster query execution
  • Reduced CPU and I/O load
  • Consistent execution plans across runs
  • Better use of shared pool and caching

8.8 Session Locking and Blocking Analysis

Overview

In multi-user Oracle databases, concurrent sessions can block each other when accessing the same resources. Understanding session locks and blocking is critical for performance tuning and troubleshooting concurrency issues.

 

Objective

Identify blocking sessions, resolve locks, and ensure smooth transaction processing.

 

Why

  • Prevent long waits or application timeouts caused by uncommitted transactions.
  • Detect and resolve deadlocks or resource contention.
  • Maintain database concurrency and transactional consistency.

 

How

  • Query v$lock to find blocking and waiting sessions.
  • Query v$session to identify session details (SID, SERIAL#, USERNAME).
  • Kill or terminate blocking sessions if necessary.

 

Use Case

1.    User U1 updates emp table and holds a lock.

2.    User U2 tries to update the same row → session blocks.

3.    SYS checks v$lock and v$session to find blocking session.

4.    SYS kills U1’s session → lock released, U2 continues.

 

Implementation Steps


 


U1:

 

U2:

U2 hangs

Show blocking sessions


Identify session details




Kill blocking session



Confirm locks are released

 

Best Practices

  • Avoid long-running transactions on frequently updated tables.
  • Regularly monitor v$session and v$lock for blocking issues.
  • Use row-level locking instead of table-level where possible.
  • Communicate with users before killing sessions in production.

 

Key Outcomes

  • Quickly identify blocking sessions and resolve locks.
  • Reduce application wait times and prevent deadlocks.
  • Improve concurrency and transaction throughput.

 

Validation and Review

The final step validates both security and performance improvements.

Security Validation

  • Re-run DBSAT
  • Validate privilege models
  • Review audit settings

Performance Validation

  • Compare before/after AWR reports
  • Validate ADDM improvements
  • Monitor wait event reductions
  • Confirm improved SQL execution plans

Operational Checks

  • Validate across all PDBs
  • Monitor application behavior
  • Document baselines

 

Final Outcome

After implementation:

  • Hardened security posture
  • Reduced privilege risks
  • Optimized SQL execution
  • Improved concurrency handling
  • Proactive performance monitoring
  • Production-ready DBA baseline

9. Daily Health Checks (BONUS)

Overview

Daily health checks ensure the Oracle database environment is stable, performant, and free from potential issues. This includes monitoring instance status, tablespace usage, sessions, redo logs, and system resources.

 

Objective

  • Detect and resolve early warnings of database issues.
  • Track resource utilization and growth trends.
  • Validate backup, log, and Data Guard statuses.
  • Ensure all database users and objects are healthy.

 

Why

  • Prevent downtime and performance degradation.
  • Maintain SLA compliance and database reliability.
  • Provide actionable insights for proactive maintenance.

 

How

  • Run a pre-built health_check.sql script daily.
  • Capture instance info, tablespaces, schema sizes, sessions, and system metrics.
  • Review outputs and take corrective action as needed.

 

Use Case

  • Check tablespace usage → prevent out-of-space errors.
  • Monitor active/inactive sessions → identify blocking or long-running queries.
  • Validate FRA, ASM, filesystem, memory, and CPU utilization → ensure adequate resources.
  • Review redo log generation → confirm proper logging for recovery.
  • Verify Data Guard status → ensure primary-standby sync.
  • Review backup and invalid object/indexes → ensure recoverability.

 

I have created a health_check.sql script for automation
This allows a single-click full health check of the database

THIS IS THE SCRIPT :

select current_timestamp from dual;

 

alter session set nls_date_format='mm/dd/yy hh24:mi:ss'

/

 

prompt

prompt DB Information

Prompt

 

set line 200 pages 200

col host_name for a30

col Instance_name for a30

select distinct instance_name,Host_name,open_mode,database_role,log_mode,startup_time,created,edition from gv$instance,gv$database;

 

prompt

prompt "Chek Tablespace Utilization"

Prompt

 

select * from dba_tablespace_usage_metrics order by 4;

 

prompt

prompt Database Size

prompt

select sum(bytes/1024/1024/1024) "USED SPACE GB", (sum(maxbytes/1024/1024/1024)-sum(bytes/1024/1024/1024)) "FREE SPACE GB" ,(sum(bytes/1024/1024/1024)+(sum(maxbytes/1024/1024/1024)-sum(bytes/1024/1024/1024))) "TOTAL SPACE GB"

from dba_data_files;

prompt

prompt

prompt Schemas Size

prompt

col owner for a30

select owner,sum(bytes/1024/1024/1024) GB from dba_segments

where owner not in ('SYS','SYSTEM','DBSNMP','CTXSYS','OJVMSYS','DVSYS','AUDSYS','GSMADMIN_INTERNAL','ORDDATA','MDSYS','LBACSYS','OUTLN','PROFILE_MANAGER','XDB','WMSYS','ORDSYS')  group by owner order by GB desc

/

 

prompt

prompt USER DETAILS

prompt

col USERNAME FOR a15

select username,Account_status,expiry_date from dba_users where common='NO' and Oracle_maintained='N';

 

prompt

prompt Unusable Indexes

prompt

SELECT 'ALTER INDEX '||INDEX_NAME||' REBUILD;' FROM DBA_INDEXES WHERE STATUS = 'UNUSABLE';

 

prompt

prompt Invalid Objects

prompt

 

COLUMN owner FORMAT A20

COLUMN object_type FORMAT A20

COLUMN object_name FORMAT A35

 

SELECT owner, object_type, object_name

FROM dba_objects

WHERE status = 'INVALID'

ORDER BY owner, object_type;

 

select owner,object_type,count(status) from dba_objects where status='INVALID' group by owner,object_type;

 

prompt

prompt Invalid Indexes

prompt

select a.owner, a.table_name,a.index_name,a.index_type,a.status,a.blevel,a.clustering_factor,a.distinct_keys,a.partitioned,a.last_analyzed

from dba_indexes a where status not in ('VALID') and owner not in ('SYS','SYSTEM','AUDSYS');

 

prompt

prompt Current Active SESSIONS

prompt

 

col service_name for a30

col username for a30

col machine for a30

select service_name,machine,username,status,count(service_name) as Total from gv$session where status='ACTIVE' group by service_name,machine,username,status

/

 

prompt

prompt Current INACTIVE SESSIONS

prompt

 

col service_name for a30

col username for a30

col machine for a30

select service_name,machine,username,status,count(service_name) as Total from gv$session where status='INACTIVE' group by service_name,machine,username,status

/

 

Prompt

Prompt FRA Utilization

Prompt

 

col name for a30

select name,round(space_limit/1048576) SPACE_LIMIT_MB, round(SPACE_USED/1048576) SPACE_USED_MB, round(((SPACE_USED/1048576) * 100) / (space_limit/1048576), 2) PRC_USED from v$recovery_file_dest;

 

prompt

 

set line 200

select file_type,percent_space_used USED, percent_space_reclaimable RECLAIMABLE, number_of_files as "NUMBER" from v$flash_recovery_area_usage;

 

prompt

prompt ASM Disk Utilization

prompt

SELECT name, total_mb / 1024 AS ALLOCATED_GB, free_mb / 1024 AS EMPTY_GB, ((total_mb - free_mb) / total_mb) * 100 AS PERCENT_USED, state FROM v$asm_diskgroup;

 

SELECT

    name,

    ROUND(total_mb / 1024 / 1024, 2) AS ALLOCATED_TB,

    ROUND(free_mb / 1024 / 1024, 2) AS EMPTY_TB,

    ROUND(((total_mb - free_mb) / total_mb) * 100, 2) AS PERCENT_USED,

    state

FROM

    v$asm_diskgroup;

 

prompt

prompt Show sessions that are blocking each other

prompt

select    'SID ' || l1.sid ||' is blocking  ' || l2.sid blocking from       gv$lock l1, gv$lock l2

where    l1.block =1 and l2.request > 0

and        l1.id1=l2.id1

and        l1.id2=l2.id2

/

 

SELECT inst_id,DECODE(request,0,'Holder: ','Waiter: ')||sid sess,

id1, id2, lmode, request, type

FROM GV$LOCK

WHERE (id1, id2, type) IN

(SELECT id1, id2, type FROM gV$LOCK WHERE request>0)

ORDER BY id1, request

/



col username     format a40

col sess_id          format a10

col object            format a25

col mode_held   format a10

select    oracle_username || ' (' || s.osuser || ')' username

,              s.sid || ',' || s.serial# sess_id

,              owner || '.' ||    object_name object

,              object_type

,              decode(               l.block

               ,              0, 'Not Blocking'

               ,              1, 'Blocking'

               ,              2, 'Global') status

,              decode(v.locked_mode

               ,              0, 'None'

               ,              1, 'Null'

               ,              2, 'Row-S (SS)'

               ,              3, 'Row-X (SX)'

               ,              4, 'Share'

               ,              5, 'S/Row-X (SSX)'

               ,              6, 'Exclusive', TO_CHAR(lmode)) mode_held

from      gv$locked_object v

,              dba_objects d

,              gv$lock l

,              gv$session s

where   v.object_id = d.object_id

and        v.object_id = l.id1

and        v.session_id = s.sid

order by oracle_username

,              session_id

/

prompt

prompt Backup Status

prompt

 

set pages 2000 lines 200

COL STATUS FORMAT a9

COL hrs FORMAT 999.99

set pages 2000 lines 200

COL STATUS FORMAT a9

COL hrs FORMAT 999.99

SELECT

    INPUT_TYPE,

    STATUS,

    TO_CHAR(START_TIME, 'mm/dd/yy hh24:mi') AS start_time,

    TO_CHAR(END_TIME, 'mm/dd/yy hh24:mi') AS end_time,

    ELAPSED_SECONDS/3600 AS hrs,

    INPUT_BYTES/1024/1024/1024 AS SUM_BYTES_BACKED_IN_GB,

    OUTPUT_BYTES/1024/1024/1024 AS SUM_BACKUP_PIECES_IN_GB,

    OUTPUT_DEVICE_TYPE  

FROM

    V$RMAN_BACKUP_JOB_DETAILS

WHERE

    START_TIME > SYSDATE - INTERVAL '2' DAY

ORDER BY

    SESSION_KEY;

 

prompt

prompt Redolog Generation

prompt

set line 200 pages 200

select trunc(completion_time) logdate, count(*) logswitch, round((sum(blocks*block_size) / 1024 / 1024)) "REDO PER DAY(MB)"

from v$archived_log

group by trunc(completion_time)

order by 1;

 

prompt

prompt Dataguard Status

prompt

SELECT ARCH.THREAD# "Thread", ARCH.SEQUENCE# "Last Sequence Received", APPL.SEQUENCE# "Last Sequence Applied", (ARCH.SEQUENCE# - APPL.SEQUENCE#) "Difference"

FROM

(SELECT THREAD# ,SEQUENCE# FROM V$ARCHIVED_LOG WHERE (THREAD#,FIRST_TIME ) IN (SELECT THREAD#,MAX(FIRST_TIME) FROM V$ARCHIVED_LOG GROUP BY THREAD#)) ARCH,

 (SELECT THREAD# ,SEQUENCE# FROM V$LOG_HISTORY WHERE (THREAD#,FIRST_TIME ) IN (SELECT THREAD#,MAX(FIRST_TIME) FROM V$LOG_HISTORY GROUP BY THREAD#)) APPL

WHERE ARCH.THREAD# = APPL.THREAD# ORDER BY 1;

 

select thread#,max(sequence#) from v$log where status='CURRENT' group by thread# order by 1;

 

prompt

prompt DB USERS VALIDATION

prompt

set line 200 pages 200

col username for a25

col ACCOUNT_STATUS for a25

col CREATED for a20

col EXPIRY_DATE for a20

col LAST_LOGIN for a40

 SELECT

    username,

    account_status,

    created,

    expiry_date,

    last_login

FROM

    dba_users

WHERE

    username IN ('SYS','SYSTEM','C##VAPTUSER','CMSUSER','C##VAPTUSER','PDBUSER','C##DBLCMUSER','DBSNMP');

 

prompt

prompt DB USERS VALIDATION

prompt

set line 200 pages 200

select severity, username, expiry_date from (

select 'Warning' as SEVERITY, username, to_char(expiry_date,'DD-MON-YYYY') as EXPIRY_DATE

from dba_users

where account_status='OPEN' and (expiry_date > sysdate+15) and (expiry_date <= sysdate+14)

union

select 'Critical' as SEVERITY, username, to_char(expiry_date,'DD-MON-YYYY') as EXPIRY_DATE

from dba_users

where (account_status = 'OPEN' and (expiry_date<= sysdate+10)) or account_status='EXPIRED(GRACE)'

) order by 3;




Prompt

prompt Filesystem Utilization

Prompt

!df -h

prompt

prompt

prompt Memory Utilization

prompt

!free -h

prompt

prompt

prompt CPU Utilization

prompt

!sar 1 10

Prompt

 

Implementation Steps

Connect to target database


Run health check script
@/home/oracle/scripts/health_check.sql

Sample checks included in script:
1. Instance and database role info
2. Tablespace utilization
3. Database, schema, and object size
4. Unusable/invalid indexes or objects
5. Active and inactive sessions
6. FRA and ASM disk usage
7. Blocking sessions
8. Backup and redo log status
9. Data Guard lag and status
10. Database users validation
11. Filesystem, memory, and CPU utilization






 

 

 

Best Practices

  • Run the script at a consistent time daily.
  • Send automated reports to DBAs for review.
  • Monitor trends over time to detect anomalies early.
  • Validate critical alerts (tablespace full, blocking sessions, invalid objects) immediately.

 

Key Outcomes

  • Early detection of potential issues and performance bottlenecks.
  • Comprehensive overview of the database and server health.
  • Proactive maintenance, avoiding critical outages or performance degradation.

 


10. Risks and Mitigation

Implementing database security hardening and performance tuning introduces certain operational and architectural risks. Proper planning and mitigation strategies are essential to ensure stability, compliance, and performance consistency.

 

1. Privilege Misconfiguration Risk

Risk:
Incorrect privilege revocation may break application functionality or administrative operations.

Mitigation:

  • Follow least privilege principle gradually
  • Perform privilege review in staging environment
  • Maintain rollback scripts for revoked privileges
  • Use privilege analysis tools before enforcement

 

2. Performance Impact from Security Controls

Risk:
Security measures such as auditing, encryption, or monitoring may introduce performance overhead.

Mitigation:

  • Enable auditing selectively
  • Monitor performance after security changes
  • Use AWR baselines before and after implementation
  • Apply controls incrementally

 

3. Misinterpretation of DBSAT Findings

Risk:
DBSAT reports may highlight risks that require contextual analysis, leading to over-hardening or unnecessary changes.

Mitigation:

  • Review findings based on business context
  • Prioritize high and critical risks first
  • Validate recommendations before implementation
  • Align remediation with security policies

 

4. SQL Tuning Regression Risk

Risk:
Improper SQL tuning or indexing may negatively impact execution plans or other workloads.

Mitigation:

  • Capture execution plan baselines
  • Use SQL Plan Management (SPM) where applicable
  • Test tuning changes in non-production environments
  • Monitor performance after deployment

 

5. AWR/ADDM Licensing and Usage Risk

Risk:
Improper usage of AWR and ADDM without proper licensing may lead to compliance issues.

Mitigation:

  • Ensure Diagnostic Pack licensing compliance
  • Validate feature usage with licensing guidelines
  • Use Statspack as an alternative if required

 

6. Over-Hardening Risk

Risk:
Excessive security hardening may reduce operational flexibility or slow down troubleshooting.

Mitigation:

  • Maintain a balance between security and usability
  • Document security exceptions where required
  • Implement role-based administrative access
  • Follow phased hardening approach

 

7. Inconsistent Multi-tenant Configuration

Risk:
Security and performance configurations may differ across CDB and PDBs, leading to inconsistent behavior.

Mitigation:

  • Standardize configurations across containers
  • Validate settings at both CDB and PDB levels
  • Use common users and roles where applicable
  • Perform container-wide validation checks

 

8. Change Management Risk

Risk:
Untracked changes during hardening and tuning may lead to operational instability.

Mitigation:

  • Follow change management procedures
  • Maintain implementation documentation
  • Enable configuration auditing
  • Use version-controlled scripts

11. Conclusion

This implementation successfully demonstrated a comprehensive approach to Oracle Database Security Hardening and Performance Tuning through practical, real-world scenarios. The guide combined critical administrative domains including user and role management, security controls, DBSAT assessment, AWR and ADDM diagnostics, and SQL performance optimization into a unified operational workflow.

Through this hands-on implementation, essential security practices such as least privilege enforcement, privilege review, and database hardening were applied to strengthen the overall security posture. The use of DBSAT provided deeper visibility into potential risks, sensitive data exposure, and privilege-related vulnerabilities, enabling informed remediation strategies aligned with enterprise security standards.

On the performance side, AWR and ADDM were leveraged to analyze workload behavior, identify bottlenecks, and understand system performance patterns. SQL tuning techniques were then applied to optimize inefficient queries, improve execution plans, and enhance overall database responsiveness and stability.

This practical implementation highlights the importance of balancing security and performance in modern database environments. It reinforces the value of proactive monitoring, periodic security assessments, and continuous tuning as part of a mature Oracle DBA strategy.

Overall, this guide serves as a solid reference for Oracle DBAs seeking to implement structured security hardening and performance tuning practices. It provides a strong foundation for maintaining secure, stable, and high-performing Oracle database environments aligned with enterprise best practices and real-world operational requirements.


12. Limitations

This implementation is performed in a controlled lab environment designed to demonstrate practical Oracle database security and performance tuning concepts. While it effectively covers core administrative practices, it has certain limitations:

  • The implementation does not include enterprise security frameworks such as SIEM integration or centralized identity management
  • Real-time production workloads and large-scale concurrency patterns are not fully simulated
  • Advanced integrations like Data Guard security hardening, Zero Trust architecture, and cross-region deployments are not covered
  • Some performance diagnostics rely on licensed features such as AWR and ADDM
  • External security validation methods such as penetration testing or compliance audits are not included
  • Application-level performance tuning and code optimization are outside the scope of this document

These limitations are acceptable for learning and foundational implementation purposes but should be expanded upon when applying these practices in enterprise production environments.