Question: How do you connect Python to an Oracle Database to run administrative health checks, and what basic steps must your code follow?
Answer:
To interact with Oracle Database via Python, you use the oracledb driver. The communication follows a strict object-oriented lifecycle: - Establish a Connection: Initialize a session using credentials and a Data Source Name (DSN).
- Create a Cursor: Open a cursor object to serve as the execution context for SQL statements.
- Execute SQL Command: Run administrative queries (e.g., fetching system metrics from
V$ views). - Fetch and Process Data: Extract row data using methods like
fetchall() or an iterator loop. - Resource Cleanup: Close the cursor and database connection to prevent lingering process locks.
Required Python Basic SyntaxThis script connects as a DBA to extract the active database version and current status. It implements best-practice Python structures, including Exception Handling (try-except) and Context Managers (with) to safely manage database states. pythonimport oracledb
# Define connection credentials and targets
DB_USER = "sys"
DB_PASSWORD = "YourSecureDBAPassword"
# Syntax format for DSN: "hostname:port/service_name"
DB_DSN = "localhost:1521/orclpdb"
try:
# 1. Open connection safely using a context manager
# Note: Connecting as SYSDBA requires specifying the 'mode'
with oracledb.connect(
user=DB_USER,
password=DB_PASSWORD,
dsn=DB_DSN,
mode=oracledb.SYSDBA
) as connection:
print("✅ Successfully connected to the Oracle Database Instance.")
# 2. Allocate an isolated database cursor
with connection.cursor() as cursor:
# 3. Define an administrative DBA task query
# Checking database version information
query = "SELECT banner FROM v$version"
# 4. Execute statement inside the engine
cursor.execute(query)
# 5. Fetch structural dataset records
records = cursor.fetchall()
print("\n--- System Version Information ---")
for row in records:
# 'row' is returned as a data tuple
print(row[0])
except oracledb.DatabaseError as error:
# Trap and output database failure conditions safely
print(f"❌ Oracle Database failure occurred: {error}")
except Exception as general_error:
# Trap system or network layer errors
print(f"❌ Application environment error: {general_error}")
# Context managers automatically invoke '.close()' on connection and cursor items
print("\n🔒 Resources closed out successfully.")
⚙️ Core Technical Concepts for DBAsWhen explaining this code during an interview, be sure to highlight these structural components:oracledb.connect(): Instantiates your session. For primary container instance work, explicit assignment parameters (host, port, service_name) can be declared individually as alternative input parameters. mode=oracledb.SYSDBA: Vital for DBA operations. It escalates privileges so you can query performance and structural dictionary boundaries (like V$VERSION, V$INSTANCE, or DBA_DATA_FILES). - The
with Statement: A standard Python context manager. It guarantees that even if a query crashes or encounters a semantic error halfway through, it gracefully handles connection teardown hooks automatically.
Question:How do you check for tablespace usage space alerts in an Oracle Database, and which data dictionary views would you use to prevent a production application outage?
Answer:To monitor tablespace capacity, a DBA should query the DBA_TABLESPACE_USAGE_METRICS view. This view calculates space utilization dynamically by taking into account data files that have AUTOEXTEND enabled. - Critical Metrics: You must calculate the
USED_PERCENT. Production alerts should trigger a warning at 85% and a critical alarm at 95% capacity. - Alternative Views: If specific block breakdowns or physical file limits are needed, you can join
DBA_DATA_FILES, DBA_FREE_SPACE, and DBA_TABLESPACES. - Actionable Fixes: If a tablespace hits 99% utilization, immediate remediation includes adding a new datafile, resizing an existing datafile with
ALTER DATABASE DATAFILE... RESIZE, or verifying that AUTOEXTEND hasn't hit its OS file system limit.
Part 2: Python Script for Oracle DBA TaskThis script automates the task described above. It connects to the database using the modern Thin Mode of the python-oracledb Driver and lists tablespaces exceeding a configurable threshold. pythonimport os
import oracledb
def get_db_connection():
"""
Establishes a connection to the Oracle Database using environment variables.
Utilizes the modern thin driver mode (no Instant Client required).
"""
# Fetch database credentials from environment variables for security
db_user = os.environ.get("DB_USER", "system")
db_password = os.environ.get("DB_PASSWORD")
db_dsn = os.environ.get("DB_DSN", "localhost:1521/ORCLPDB")
if not db_password:
raise ValueError("Database password must be set via DB_PASSWORD environment variable.")
# Establish standalone thin connection
connection = oracledb.connect(
user=db_user,
password=db_password,
dsn=db_dsn
)
return connection
def check_tablespace_usage(threshold_percent=85.0):
"""
Queries the database for tablespaces exceeding the specified usage threshold percentage.
"""
query = """
SELECT tablespace_name,
ROUND(used_space * 8192 / 1024 / 1024, 2) as used_mb,
ROUND(tablespace_size * 8192 / 1024 / 1024, 2) as max_mb,
ROUND(used_percent, 2) as used_pct
FROM dba_tablespace_usage_metrics
WHERE used_percent >= :threshold
ORDER BY used_percent DESC
"""
connection = None
alerts = []
try:
connection = get_db_connection()
with connection.cursor() as cursor:
# Bind parameters to guard against SQL injection
cursor.execute(query, threshold=threshold_percent)
# Fetch all matching problem tablespaces
for row in cursor.fetchall():
alerts.append({
"tablespace_name": row[0],
"used_mb": row[1],
"max_mb": row[2],
"used_percent": row[3]
})
except oracledb.DatabaseError as e:
print(f"Oracle Database Error occurred: {e}")
raise
finally:
if connection:
connection.close()
return alerts
if __name__ == "__main__":
# Example local script execution configuration
os.environ["DB_PASSWORD"] = "YourSecurePasswordHere"
print("Scanning Oracle Database for high-utilization tablespaces...")
problem_spaces = check_tablespace_usage(threshold_percent=80.0)
if problem_spaces:
print("\n⚠️ WARNING: The following tablespaces require immediate attention:")
for space in problem_spaces:
print(f"- {space['tablespace_name']}: {space['used_percent']}% used "
f"({space['used_mb']}MB / {space['max_mb']}MB)")
else:
print("\n✅ All database tablespaces are operating within healthy capacity boundaries.")
Part 3: Python Unit Test CaseTo safely validate our script logic without executing a real database infrastructure call, we use unittest.mock to simulate database interactions.pythonimport unittest
from unittest.mock import patch, MagicMock
import oracledb
# Assuming the script above is saved as 'dba_monitor.py'
import dba_monitor
class TestOracleDBAMonitor(unittest.TestCase):
@patch('dba_monitor.os.environ.get')
@patch('dba_monitor.oracledb.connect')
def test_get_db_connection_success(self, mock_connect, mock_env_get):
"""Test successful initialization of the Oracle connection."""
mock_env_get.side_effect = lambda key, default=None: {
"DB_USER": "test_user",
"DB_PASSWORD": "test_password",
"DB_DSN": "test_host:1521/test_service"
}.get(key, default)
dba_monitor.get_db_connection()
mock_connect.assert_called_once_with(
user="test_user",
password="test_password",
dsn="test_host:1521/test_service"
)
@patch('dba_monitor.get_db_connection')
def test_check_tablespace_usage_alerts(self, mock_get_conn):
"""Test alert array generation when database returns high-usage rows."""
# Setup mock connection and cursor
mock_conn = MagicMock()
mock_cursor = MagicMock()
mock_get_conn.return_value = mock_conn
mock_conn.cursor.return_value.__enter__.return_value = mock_cursor
# Simulate row results: (tablespace_name, used_mb, max_mb, used_percent)
mock_cursor.fetchall.return_value = [
("SYSTEM", 950.00, 1000.00, 95.00),
("SYSAUX", 880.00, 1000.00, 88.00)
]
# Run function tracking alerts above 85%
results = dba_monitor.check_tablespace_usage(threshold_percent=85.0)
# Assertions
self.assertEqual(len(results), 2)
self.assertEqual(results[0]["tablespace_name"], "SYSTEM")
self.assertEqual(results[0]["used_percent"], 95.00)
self.assertEqual(results[1]["tablespace_name"], "SYSAUX")
mock_cursor.execute.assert_called_once()
@patch('dba_monitor.get_db_connection')
def test_database_exception_handling(self, mock_get_conn):
"""Verify that Oracle Database driver errors are bubbled up gracefully."""
mock_conn = MagicMock()
mock_get_conn.return_value = mock_conn
# Force a database exception on execution
mock_conn.cursor.return_value.__enter__.return_value.execute.side_effect = oracledb.DatabaseError("ORA-00942: table or view does not exist")
with self.assertRaises(oracledb.DatabaseError):
dba_monitor.check_tablespace_usage()
if __name__ == '__main__':
unittest.main()
Question: How do you connect Python to an Oracle Database to run administrative health checks, and what basic steps must your code follow?
Answer:
To interact with Oracle Database via Python, you use the oracledb driver. The communication follows a strict object-oriented lifecycle: - Establish a Connection: Initialize a session using credentials and a Data Source Name (DSN).
- Create a Cursor: Open a cursor object to serve as the execution context for SQL statements.
- Execute SQL Command: Run administrative queries (e.g., fetching system metrics from
V$ views). - Fetch and Process Data: Extract row data using methods like
fetchall() or an iterator loop. - Resource Cleanup: Close the cursor and database connection to prevent lingering process locks.
Required Python Basic SyntaxThis script connects as a DBA to extract the active database version and current status. It implements best-practice Python structures, including Exception Handling (try-except) and Context Managers (with) to safely manage database states. pythonimport oracledb
# Define connection credentials and targets
DB_USER = "sys"
DB_PASSWORD = "YourSecureDBAPassword"
# Syntax format for DSN: "hostname:port/service_name"
DB_DSN = "localhost:1521/orclpdb"
try:
# 1. Open connection safely using a context manager
# Note: Connecting as SYSDBA requires specifying the 'mode'
with oracledb.connect(
user=DB_USER,
password=DB_PASSWORD,
dsn=DB_DSN,
mode=oracledb.SYSDBA
) as connection:
print("✅ Successfully connected to the Oracle Database Instance.")
# 2. Allocate an isolated database cursor
with connection.cursor() as cursor:
# 3. Define an administrative DBA task query
# Checking database version information
query = "SELECT banner FROM v$version"
# 4. Execute statement inside the engine
cursor.execute(query)
# 5. Fetch structural dataset records
records = cursor.fetchall()
print("\n--- System Version Information ---")
for row in records:
# 'row' is returned as a data tuple
print(row[0])
except oracledb.DatabaseError as error:
# Trap and output database failure conditions safely
print(f"❌ Oracle Database failure occurred: {error}")
except Exception as general_error:
# Trap system or network layer errors
print(f"❌ Application environment error: {general_error}")
# Context managers automatically invoke '.close()' on connection and cursor items
print("\n🔒 Resources closed out successfully.")
⚙️ Core Technical Concepts for DBAsWhen explaining this code during an interview, be sure to highlight these structural components:oracledb.connect(): Instantiates your session. For primary container instance work, explicit assignment parameters (host, port, service_name) can be declared individually as alternative input parameters. mode=oracledb.SYSDBA: Vital for DBA operations. It escalates privileges so you can query performance and structural dictionary boundaries (like V$VERSION, V$INSTANCE, or DBA_DATA_FILES). - The
with Statement: A standard Python context manager. It guarantees that even if a query crashes or encounters a semantic error halfway through, it gracefully handles connection teardown hooks automatically.
Question: How do you connect Python to an Oracle Database to run administrative health checks, and what basic steps must your code follow?
To interact with Oracle Database via Python, you use the oracledb driver. The communication follows a strict object-oriented lifecycle:
- Establish a Connection: Initialize a session using credentials and a Data Source Name (DSN).
- Create a Cursor: Open a cursor object to serve as the execution context for SQL statements.
- Execute SQL Command: Run administrative queries (e.g., fetching system metrics from
V$views). - Fetch and Process Data: Extract row data using methods like
fetchall()or an iterator loop. - Resource Cleanup: Close the cursor and database connection to prevent lingering process locks.
try-except) and Context Managers (with) to safely manage database states. import oracledb
# Define connection credentials and targets
DB_USER = "sys"
DB_PASSWORD = "YourSecureDBAPassword"
# Syntax format for DSN: "hostname:port/service_name"
DB_DSN = "localhost:1521/orclpdb"
try:
# 1. Open connection safely using a context manager
# Note: Connecting as SYSDBA requires specifying the 'mode'
with oracledb.connect(
user=DB_USER,
password=DB_PASSWORD,
dsn=DB_DSN,
mode=oracledb.SYSDBA
) as connection:
print("✅ Successfully connected to the Oracle Database Instance.")
# 2. Allocate an isolated database cursor
with connection.cursor() as cursor:
# 3. Define an administrative DBA task query
# Checking database version information
query = "SELECT banner FROM v$version"
# 4. Execute statement inside the engine
cursor.execute(query)
# 5. Fetch structural dataset records
records = cursor.fetchall()
print("\n--- System Version Information ---")
for row in records:
# 'row' is returned as a data tuple
print(row[0])
except oracledb.DatabaseError as error:
# Trap and output database failure conditions safely
print(f"❌ Oracle Database failure occurred: {error}")
except Exception as general_error:
# Trap system or network layer errors
print(f"❌ Application environment error: {general_error}")
# Context managers automatically invoke '.close()' on connection and cursor items
print("\n🔒 Resources closed out successfully.")
oracledb.connect(): Instantiates your session. For primary container instance work, explicit assignment parameters (host,port,service_name) can be declared individually as alternative input parameters.mode=oracledb.SYSDBA: Vital for DBA operations. It escalates privileges so you can query performance and structural dictionary boundaries (likeV$VERSION,V$INSTANCE, orDBA_DATA_FILES).- The
withStatement: A standard Python context manager. It guarantees that even if a query crashes or encounters a semantic error halfway through, it gracefully handles connection teardown hooks automatically.
Question:How do you check for tablespace usage space alerts in an Oracle Database, and which data dictionary views would you use to prevent a production application outage?
DBA_TABLESPACE_USAGE_METRICS view. This view calculates space utilization dynamically by taking into account data files that have AUTOEXTEND enabled. - Critical Metrics: You must calculate the
USED_PERCENT. Production alerts should trigger a warning at 85% and a critical alarm at 95% capacity. - Alternative Views: If specific block breakdowns or physical file limits are needed, you can join
DBA_DATA_FILES,DBA_FREE_SPACE, andDBA_TABLESPACES. - Actionable Fixes: If a tablespace hits 99% utilization, immediate remediation includes adding a new datafile, resizing an existing datafile with
ALTER DATABASE DATAFILE... RESIZE, or verifying thatAUTOEXTENDhasn't hit its OS file system limit.
import os
import oracledb
def get_db_connection():
"""
Establishes a connection to the Oracle Database using environment variables.
Utilizes the modern thin driver mode (no Instant Client required).
"""
# Fetch database credentials from environment variables for security
db_user = os.environ.get("DB_USER", "system")
db_password = os.environ.get("DB_PASSWORD")
db_dsn = os.environ.get("DB_DSN", "localhost:1521/ORCLPDB")
if not db_password:
raise ValueError("Database password must be set via DB_PASSWORD environment variable.")
# Establish standalone thin connection
connection = oracledb.connect(
user=db_user,
password=db_password,
dsn=db_dsn
)
return connection
def check_tablespace_usage(threshold_percent=85.0):
"""
Queries the database for tablespaces exceeding the specified usage threshold percentage.
"""
query = """
SELECT tablespace_name,
ROUND(used_space * 8192 / 1024 / 1024, 2) as used_mb,
ROUND(tablespace_size * 8192 / 1024 / 1024, 2) as max_mb,
ROUND(used_percent, 2) as used_pct
FROM dba_tablespace_usage_metrics
WHERE used_percent >= :threshold
ORDER BY used_percent DESC
"""
connection = None
alerts = []
try:
connection = get_db_connection()
with connection.cursor() as cursor:
# Bind parameters to guard against SQL injection
cursor.execute(query, threshold=threshold_percent)
# Fetch all matching problem tablespaces
for row in cursor.fetchall():
alerts.append({
"tablespace_name": row[0],
"used_mb": row[1],
"max_mb": row[2],
"used_percent": row[3]
})
except oracledb.DatabaseError as e:
print(f"Oracle Database Error occurred: {e}")
raise
finally:
if connection:
connection.close()
return alerts
if __name__ == "__main__":
# Example local script execution configuration
os.environ["DB_PASSWORD"] = "YourSecurePasswordHere"
print("Scanning Oracle Database for high-utilization tablespaces...")
problem_spaces = check_tablespace_usage(threshold_percent=80.0)
if problem_spaces:
print("\n⚠️ WARNING: The following tablespaces require immediate attention:")
for space in problem_spaces:
print(f"- {space['tablespace_name']}: {space['used_percent']}% used "
f"({space['used_mb']}MB / {space['max_mb']}MB)")
else:
print("\n✅ All database tablespaces are operating within healthy capacity boundaries.")
unittest.mock to simulate database interactions.import unittest
from unittest.mock import patch, MagicMock
import oracledb
# Assuming the script above is saved as 'dba_monitor.py'
import dba_monitor
class TestOracleDBAMonitor(unittest.TestCase):
@patch('dba_monitor.os.environ.get')
@patch('dba_monitor.oracledb.connect')
def test_get_db_connection_success(self, mock_connect, mock_env_get):
"""Test successful initialization of the Oracle connection."""
mock_env_get.side_effect = lambda key, default=None: {
"DB_USER": "test_user",
"DB_PASSWORD": "test_password",
"DB_DSN": "test_host:1521/test_service"
}.get(key, default)
dba_monitor.get_db_connection()
mock_connect.assert_called_once_with(
user="test_user",
password="test_password",
dsn="test_host:1521/test_service"
)
@patch('dba_monitor.get_db_connection')
def test_check_tablespace_usage_alerts(self, mock_get_conn):
"""Test alert array generation when database returns high-usage rows."""
# Setup mock connection and cursor
mock_conn = MagicMock()
mock_cursor = MagicMock()
mock_get_conn.return_value = mock_conn
mock_conn.cursor.return_value.__enter__.return_value = mock_cursor
# Simulate row results: (tablespace_name, used_mb, max_mb, used_percent)
mock_cursor.fetchall.return_value = [
("SYSTEM", 950.00, 1000.00, 95.00),
("SYSAUX", 880.00, 1000.00, 88.00)
]
# Run function tracking alerts above 85%
results = dba_monitor.check_tablespace_usage(threshold_percent=85.0)
# Assertions
self.assertEqual(len(results), 2)
self.assertEqual(results[0]["tablespace_name"], "SYSTEM")
self.assertEqual(results[0]["used_percent"], 95.00)
self.assertEqual(results[1]["tablespace_name"], "SYSAUX")
mock_cursor.execute.assert_called_once()
@patch('dba_monitor.get_db_connection')
def test_database_exception_handling(self, mock_get_conn):
"""Verify that Oracle Database driver errors are bubbled up gracefully."""
mock_conn = MagicMock()
mock_get_conn.return_value = mock_conn
# Force a database exception on execution
mock_conn.cursor.return_value.__enter__.return_value.execute.side_effect = oracledb.DatabaseError("ORA-00942: table or view does not exist")
with self.assertRaises(oracledb.DatabaseError):
dba_monitor.check_tablespace_usage()
if __name__ == '__main__':
unittest.main()Question: How do you connect Python to an Oracle Database, what library do you use, and how would you implement a lightweight, production-grade monitoring script that handles exceptions safely?
Answer:- Library Selection: Use the modern
oracledb driver. It runs in an architecture called Thin mode by default, meaning it does not require heavy Oracle Instant Client installations. [ - Connection Strategy: Use context managers (
with blocks) for both the connection and the execution cursor. This guarantees that database connections and resources are safely closed even if runtime exceptions or system failures occur. [ - Monitoring Strategy: Query diagnostic virtual views like
V$SESSION, V$INSTANCE, or V$SYSSTAT. For a basic health check, a query like SELECT status FROM v$instance; verifies whether the instance is up and accepting traffic. - Error Handling: Catch
oracledb.Error to intercept database-specific network drops, invalid credentials, or timeout constraints while isolating systemic script issues.
Part 2: Production Monitoring ScriptSave this script as db_monitor.py. It establishes a connection, executes a heartbeat check, and safely closes out resources. pythonimport os
import oracledb
def check_oracle_health(username, password, dsn):
"""
Connects to the Oracle Database and validates its runtime status.
Returns a dictionary indicating health metrics.
"""
health_status = {
"status": "DOWN",
"database_status": "UNKNOWN",
"error_message": None
}
try:
# Thin mode initialization (No thick client libraries required)
# For legacy thick clients, you would call oracledb.init_oracle_client() here
with oracledb.connect(user=username, password=password, dsn=dsn) as connection:
with connection.cursor() as cursor:
# Primary heartbeat query to check instance status
cursor.execute("SELECT status FROM v$instance")
row = cursor.fetchone()
if row:
health_status["status"] = "UP"
health_status["database_status"] = row[0] # E.g., 'OPEN'
except oracledb.Error as db_error:
# Catch specific Oracle engine errors (e.g., ORA-12154, ORA-01017)
health_status["status"] = "DOWN"
health_status["error_message"] = str(db_error)
except Exception as general_error:
# Catch unexpected infrastructure issues
health_status["status"] = "DOWN"
health_status["error_message"] = f"Unexpected system error: {general_error}"
return health_status
if __name__ == "__main__":
# Real-world usage simulation using environment variables or fallbacks
DB_USER = os.getenv("DB_USER", "system")
DB_PASSWORD = os.getenv("DB_PASSWORD", "YourSecurePassword")
DB_DSN = os.getenv("DB_DSN", "localhost:1521/FREEPDB1") # Easy Connect string
print("Initiating database health validation diagnostics...")
report = check_oracle_health(DB_USER, DB_PASSWORD, DB_DSN)
print(f"Diagnostic Results: {report}")
Part 3: Automated Unit Test CaseSave this file as test_db_monitor.py. This script uses Python's built-in unittest.mock package to validate your monitoring code without establishing real network sockets or depending on a live Oracle database instance. pythonimport unittest
from unittest.mock import patch, MagicMock
import oracledb
from db_monitor import check_oracle_health
class TestOracleMonitoringScript(unittest.TestCase):
@patch("oracledb.connect")
def test_health_check_success(self, mock_connect):
"""Test the monitoring script when the database is fully functional."""
# Arrange: Setup mock hierarchy for connection and cursor context managers
mock_conn = MagicMock()
mock_cursor = MagicMock()
# Configure cursor to return standard 'OPEN' state row
mock_cursor.fetchone.return_value = ["OPEN"]
# Chain context managers: connect().__enter__() returns connection object
mock_connect.return_value.__enter__.return_value = mock_conn
# connection.cursor().__enter__() returns cursor object
mock_conn.cursor.return_value.__enter__.return_value = mock_cursor
# Act: Run function
result = check_oracle_health("test_user", "password", "localhost:1521/ORCL")
# Assert: Validate success flags
self.assertEqual(result["status"], "UP")
self.assertEqual(result["database_status"], "OPEN")
self.assertIsNone(result["error_message"])
mock_cursor.execute.assert_called_once_with("SELECT status FROM v$instance")
@patch("oracledb.connect")
def test_health_check_database_down(self, mock_connect):
"""Test script resilience when Oracle rejects connections (e.g., wrong password)."""
# Arrange: Raise an official oracledb driver exception on connect
error_message = "ORA-01017: invalid username/password; logon denied"
mock_connect.side_effect = oracledb.Error(error_message)
# Act: Run function
result = check_oracle_health("wrong_user", "bad_pass", "localhost:1521/ORCL")
# Assert: Validate failure reporting
self.assertEqual(result["status"], "DOWN")
self.assertEqual(result["database_status"], "UNKNOWN")
self.assertIn("ORA-01017", result["error_message"])
if __name__ == "__main__":
unittest.main()
Execution Instructions- Install dependencies: Run
pip install oracledb. - Execute production script: Run
python db_monitor.py. - Execute testing suite: Run
python test_db_monitor.py to see passing assertions.
Question: How do you connect Python to an Oracle Database, what library do you use, and how would you implement a lightweight, production-grade monitoring script that handles exceptions safely?
- Library Selection: Use the modern
oracledbdriver. It runs in an architecture called Thin mode by default, meaning it does not require heavy Oracle Instant Client installations. [ - Connection Strategy: Use context managers (
withblocks) for both the connection and the execution cursor. This guarantees that database connections and resources are safely closed even if runtime exceptions or system failures occur. [ - Monitoring Strategy: Query diagnostic virtual views like
V$SESSION,V$INSTANCE, orV$SYSSTAT. For a basic health check, a query likeSELECT status FROM v$instance;verifies whether the instance is up and accepting traffic. - Error Handling: Catch
oracledb.Errorto intercept database-specific network drops, invalid credentials, or timeout constraints while isolating systemic script issues.
db_monitor.py. It establishes a connection, executes a heartbeat check, and safely closes out resources. import os
import oracledb
def check_oracle_health(username, password, dsn):
"""
Connects to the Oracle Database and validates its runtime status.
Returns a dictionary indicating health metrics.
"""
health_status = {
"status": "DOWN",
"database_status": "UNKNOWN",
"error_message": None
}
try:
# Thin mode initialization (No thick client libraries required)
# For legacy thick clients, you would call oracledb.init_oracle_client() here
with oracledb.connect(user=username, password=password, dsn=dsn) as connection:
with connection.cursor() as cursor:
# Primary heartbeat query to check instance status
cursor.execute("SELECT status FROM v$instance")
row = cursor.fetchone()
if row:
health_status["status"] = "UP"
health_status["database_status"] = row[0] # E.g., 'OPEN'
except oracledb.Error as db_error:
# Catch specific Oracle engine errors (e.g., ORA-12154, ORA-01017)
health_status["status"] = "DOWN"
health_status["error_message"] = str(db_error)
except Exception as general_error:
# Catch unexpected infrastructure issues
health_status["status"] = "DOWN"
health_status["error_message"] = f"Unexpected system error: {general_error}"
return health_status
if __name__ == "__main__":
# Real-world usage simulation using environment variables or fallbacks
DB_USER = os.getenv("DB_USER", "system")
DB_PASSWORD = os.getenv("DB_PASSWORD", "YourSecurePassword")
DB_DSN = os.getenv("DB_DSN", "localhost:1521/FREEPDB1") # Easy Connect string
print("Initiating database health validation diagnostics...")
report = check_oracle_health(DB_USER, DB_PASSWORD, DB_DSN)
print(f"Diagnostic Results: {report}")
test_db_monitor.py. This script uses Python's built-in unittest.mock package to validate your monitoring code without establishing real network sockets or depending on a live Oracle database instance. import unittest
from unittest.mock import patch, MagicMock
import oracledb
from db_monitor import check_oracle_health
class TestOracleMonitoringScript(unittest.TestCase):
@patch("oracledb.connect")
def test_health_check_success(self, mock_connect):
"""Test the monitoring script when the database is fully functional."""
# Arrange: Setup mock hierarchy for connection and cursor context managers
mock_conn = MagicMock()
mock_cursor = MagicMock()
# Configure cursor to return standard 'OPEN' state row
mock_cursor.fetchone.return_value = ["OPEN"]
# Chain context managers: connect().__enter__() returns connection object
mock_connect.return_value.__enter__.return_value = mock_conn
# connection.cursor().__enter__() returns cursor object
mock_conn.cursor.return_value.__enter__.return_value = mock_cursor
# Act: Run function
result = check_oracle_health("test_user", "password", "localhost:1521/ORCL")
# Assert: Validate success flags
self.assertEqual(result["status"], "UP")
self.assertEqual(result["database_status"], "OPEN")
self.assertIsNone(result["error_message"])
mock_cursor.execute.assert_called_once_with("SELECT status FROM v$instance")
@patch("oracledb.connect")
def test_health_check_database_down(self, mock_connect):
"""Test script resilience when Oracle rejects connections (e.g., wrong password)."""
# Arrange: Raise an official oracledb driver exception on connect
error_message = "ORA-01017: invalid username/password; logon denied"
mock_connect.side_effect = oracledb.Error(error_message)
# Act: Run function
result = check_oracle_health("wrong_user", "bad_pass", "localhost:1521/ORCL")
# Assert: Validate failure reporting
self.assertEqual(result["status"], "DOWN")
self.assertEqual(result["database_status"], "UNKNOWN")
self.assertIn("ORA-01017", result["error_message"])
if __name__ == "__main__":
unittest.main()
- Install dependencies: Run
pip install oracledb. - Execute production script: Run
python db_monitor.py. - Execute testing suite: Run
python test_db_monitor.pyto see passing assertions.
Question :How to connect with oracle database and write python script for monitoring with example and test case
To connect a Python script to an Oracle Database, you must use the official, open-source python-oracledb driver, which has completely replaced the legacy cx_Oracle library. The modern driver operates in a lightweight "Thin mode" by default, meaning you do not need to install Oracle Instant Client libraries to establish a database connection.
pip: pip install oracledb
monitor.py)oracledb parameters to securely fetch metrics. import os
import sys
import oracledb
def get_db_connection():
"""Establishes standalone connection using environment variables."""
# Fetch connection credentials securely from the system environment
db_user = os.environ.get("DB_USER", "system")
db_password = os.environ.get("DB_PASSWORD", "YourSecurePassword")
db_dsn = os.environ.get("DB_DSN", "localhost:1521/ORCLPDB")
try:
# Connects in Thin mode directly to Oracle Database
connection = oracledb.connect(user=db_user, password=db_password, dsn=db_dsn)
return connection
except oracledb.DatabaseError as e:
print(f"CRITICAL: Failed to connect to database. Error: {e}")
sys.exit(1)
def monitor_heartbeat(cursor):
"""Verifies that the database is active and accepting basic queries."""
try:
cursor.execute("SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') FROM DUAL")
db_time = cursor.fetchone()[0]
print(f"[OK] Heartbeat Status: Database is up. Current Server Time: {db_time}")
return True
except oracledb.DatabaseError as e:
print(f"[CRITICAL] Heartbeat Status: Failed query execution. Error: {e}")
return False
def monitor_tablespaces(cursor, threshold_pct=85):
"""Checks tablespace allocation and flags paths exceeding the safety threshold."""
query = """
SELECT
df.tablespace_name,
ROUND(((df.total_space - NVL(fs.free_space, 0)) / df.total_space) * 100, 2) AS used_percent
FROM
(SELECT tablespace_name, SUM(bytes) AS total_space FROM dba_data_files GROUP BY tablespace_name) df
LEFT JOIN
(SELECT tablespace_name, SUM(bytes) AS free_space FROM dba_free_space GROUP BY tablespace_name) fs
ON df.tablespace_name = fs.tablespace_name
"""
try:
cursor.execute(query)
issues_found = False
print("\n--- Tablespace Storage Status ---")
for row in cursor.fetchall():
ts_name, used_pct = row[0], row[1]
if used_pct >= threshold_pct:
print(f"[ALERT] Tablespace '{ts_name}' is critically high: {used_pct}% used! (Threshold: {threshold_pct}%)")
issues_found = True
else:
print(f"[OK] Tablespace '{ts_name}': {used_pct}% used.")
return not issues_found
except oracledb.DatabaseError as e:
print(f"[ERROR] Failed to query tablespace data. Error: {e}")
return False
if __name__ == "__main__":
# Ensure automated cleanup using context managers
with get_db_connection() as conn:
with conn.cursor() as cur:
heartbeat_ok = monitor_heartbeat(cur)
storage_ok = monitor_tablespaces(cur, threshold_pct=80)
if not (heartbeat_ok and storage_ok):
print("\nResult: Monitoring script finished with alert conditions.")
sys.exit(1)
else:
print("\nResult: All core health checks passed successfully.")
sys.exit(0)
test_monitor.py)unittest.mock framework to simulate API cursors and query results. import unittest
from unittest.mock import MagicMock, patch
import oracledb
from monitor import monitor_heartbeat, monitor_tablespaces
class TestOracleMonitoring(unittest.TestCase):
def setUp(self):
"""Build mock database objects before each test execution step."""
self.mock_cursor = MagicMock()
def test_monitor_heartbeat_success(self):
"""Ensure correct parsing and True return on a working connection."""
self.mock_cursor.fetchone.return_value = ["2026-06-19 14:20:00"]
result = monitor_heartbeat(self.mock_cursor)
self.assertTrue(result)
self.mock_cursor.execute.assert_called_once_with(
"SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') FROM DUAL"
)
def test_monitor_heartbeat_failure(self):
"""Ensure exceptions are properly intercepted and return False."""
self.mock_cursor.execute.side_effect = oracledb.DatabaseError("ORA-00942: table or view does not exist")
result = monitor_heartbeat(self.mock_cursor)
self.assertFalse(result)
def test_monitor_tablespaces_under_threshold(self):
"""Confirm valid paths pass successfully under structural safety parameters."""
# Simulating data: USERS tablespace at 45% capacity, SYSTEM at 70% capacity
self.mock_cursor.fetchall.return_value = [("USERS", 45.00), ("SYSTEM", 70.00)]
result = monitor_tablespaces(self.mock_cursor, threshold_pct=80)
self.assertTrue(result)
def test_monitor_tablespaces_over_threshold_alert(self):
"""Verify that breaching the safety ceiling yields an appropriate warning flag."""
# Simulating data: DATA_TS tablespace at 88% capacity (Breaches 80% ceiling)
self.mock_cursor.fetchall.return_value = [("USERS", 40.00), ("DATA_TS", 88.00)]
result = monitor_tablespaces(self.mock_cursor, threshold_pct=80)
self.assertFalse(result, "Expected False because a tablespace exceeded the limit.")
if __name__ == "__main__":
unittest.main()
python -m unittest test_monitor.py
No comments:
Post a Comment