業務システム開発・保守の実務メモを発信中

Oracleの表領域使用率をPythonで毎朝メール通知する

Oracleの表領域は、足りなくなってから気づくと対応が重くなります。アプリケーションの登録処理が止まる、夜間バッチが途中で落ちる、急いでデータファイル追加を依頼する。こうなると、朝の確認が一気に障害対応になります。

毎朝SQLを手で実行する運用でも確認はできます。ただ、休み明けやリリース直後、月末月初のように見るものが多い日は抜けやすいです。表領域の使用率だけなら、Pythonで取得してメールするくらいの小さな仕組みにしておくと、保守作業が少し楽になります。

ここでは、Oracleの表領域使用率をSQLで取得し、PythonでOKWARNINGCRITICALに分けてメール送信するサンプルを作ります。WindowsタスクスケジューラとLinuxのcron/systemd timerで毎朝実行するところまで扱います。

サンプル一式は、GitHubの oracle-tablespace-mail に置いています。

目次

使用するバージョンと前提を決める

今回のサンプルは、Python 3.10以上とpython-oracledbを前提にしています。requirements.txtでは次のように指定しています。

Markdown
oracledb>=2.5,<4

python-oracledbは、現在のドキュメントではPython 3.10から3.15を対象にしています。Oracle Database側は19以降で、Thin modeではOracle Database 12.1以降に接続できます。

この記事の検証想定は次です。

項目想定補足
Python3.10以上運用サーバーに入っているPythonが古い場合は先に確認します。
Oracle接続ライブラリpython-oracledb基本はThin modeで接続します。
Oracle Database19c以上を主な想定12.1以降でもThin mode接続対象ですが、古い環境は検証してから使います。
実行環境Windows または LinuxWindowsはタスクスケジューラ、Linuxはcronまたはsystemd timerで実行します。
メール送信SMTP社内SMTPやメールリレーを使う前提です。

Python 3.10以上を前提にする

運用サーバーに入っているPythonが3.9以下なら、先にPythonの入れ替え可否を確認します。既存ジョブが同じPythonを使っているサーバーでは、OS標準のPythonを無理に置き換えず、別パスにPythonを入れるか、仮想環境の作り方を分けます。

OS標準のPythonを安易に差し替えると、別の管理コマンドや既存バッチに影響することがあります。 保守サーバーでは、スクリプト単位の仮想環境で閉じる方が扱いやすいです。

Thin modeでつなぐかThick modeが必要か

python-oracledbは、基本的な接続ならOracle Clientを入れずに使えるThin modeで動きます。保守用の小さな監視スクリプトなら、まずThin modeで試すのが始めやすいです。

ただし、古いOracle、特殊な認証、既存のOracle Client設定に依存した接続では、Thick modeが必要になることがあります。接続方式で詰まると表領域監視以前の話になるので、最初に--dry-runでDB接続だけ確認します。

表領域不足を毎朝メールで見つける構成

作る処理は小さく分けます。

Markdown
1. Oracleへ接続する
2. 表領域使用率SQLを実行する
3. 使用率を80%と90%で判定する
4. 件名と本文を作る
5. SMTPでメールを送る
6. WindowsまたはLinuxで毎朝実行する

監視製品の代わりを全部作るわけではありません。ここで作るのは、毎朝の保守確認を忘れにくくするための通知です。表領域の追加、ASMやディスクの空き確認、容量計画まで自動化するものではありません。

メールで十分な範囲を決める

この仕組みが向いているのは、小規模な業務システムや、監視基盤に載せる前の暫定確認です。毎朝の保守メールで、使用率が上がっている表領域を拾えればよい、という範囲に絞ります。

逆に、複数DBをまとめて監視したい、通知先を当番表と連動したい、障害チケットを自動起票したい場合は、このサンプルだけでは足りません。その場合は監視製品やクラウド監視へ寄せた方が後で楽です。

通知後の作業を決めておく

メールが届いたあとに誰が見るかを決めていないと、通知だけ増えます。件名にWARNINGCRITICALを入れるのは、朝のメール一覧で優先度を見分けるためです。

通知メールは、対応を自動化するものではなく、確認の入口です。メールを受けた人が、対象表領域、増加傾向、AUTOEXTEND、ディスク空きを見るところまでを運用として決めます。

表領域が危険値になったときに、スクリプトが勝手にデータファイルを追加する作りにはしません。通知を受けたあと、対象表領域、AUTOEXTEND、物理ディスク、増加傾向を人が確認してから作業します。

Oracleの表領域使用率をSQLで取得する

表領域の使用率はDBA_TABLESPACE_USAGE_METRICSから取得します。サンプルではDBA_TABLESPACESと結合し、表領域名、種別、状態、使用率、使用MB、最大MBを出しています。

SQL
SELECT
    m.tablespace_name,
    t.contents,
    t.status,
    ROUND(m.used_percent, 2) AS used_percent,
    ROUND(m.used_space * t.block_size / 1024 / 1024, 1) AS used_mb,
    ROUND(m.tablespace_size * t.block_size / 1024 / 1024, 1) AS max_mb
FROM
    dba_tablespace_usage_metrics m
    JOIN dba_tablespaces t
      ON t.tablespace_name = m.tablespace_name
ORDER BY
    m.used_percent DESC,
    m.tablespace_name

used_spacetablespace_sizeはブロック数なので、DBA_TABLESPACESblock_sizeを使ってMBに直しています。メールでは細かいバイト数より、表領域名と使用率、使用MB、最大MBが読めれば十分な場面が多いです。

権限が足りない場合に確認すること

DBA_ビューを参照するため、実行ユーザーに権限が必要です。権限がないユーザーで動かすと、SQL実行時にビューが見えない、または権限エラーになります。

本番では、アプリケーションの接続ユーザーをそのまま使うより、監視用ユーザーを分けた方が扱いやすいです。最低限の参照権限で実行し、更新権限を持たせない構成にします。

AUTOEXTENDの見方を間違えない

DBA_TABLESPACE_USAGE_METRICSの使用率は、表領域がどこまで拡張できるかの影響を受けます。AUTOEXTENDの上限が大きい環境では、現在のデータファイルサイズだけを見た使用率と印象が変わることがあります。

この記事のSQLは、毎朝の入口として使います。WARNINGになったら、表領域の使用率だけで判断せず、データファイルの拡張上限、ASMやディスクの空き、直近の増加量を追加で確認します。

tomo

本番DBに接続するスクリプトなので、最初から強い権限のユーザーで動かすのは避けます。表領域を見るだけなら、更新権限はいりません。

Pythonで使用率を判定してメール本文を作る

GitHubのサンプルでは、monitor_tablespaces.pyに処理をまとめています。設定は.envから読みます。

Markdown
ORACLE_USER=system
ORACLE_PASSWORD=change_me
ORACLE_DSN=localhost:1521/XEPDB1

SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=alert@example.com
SMTP_PASSWORD=change_me
SMTP_USE_TLS=true
MAIL_FROM=alert@example.com
MAIL_TO=dba@example.com,system-owner@example.com

WARNING_PERCENT=80
CRITICAL_PERCENT=90
MAIL_ALWAYS=true
LOG_FILE=logs/tablespace-monitor.log

パスワードやSMTP情報をPythonファイルに直書きしないためです。.envはGitに入れず、共有するのは.env.exampleだけにします。

Oracleへ接続する処理

接続部分はこの形です。

Python
with oracledb.connect(
    user=os.environ["ORACLE_USER"],
    password=os.environ["ORACLE_PASSWORD"],
    dsn=os.environ["ORACLE_DSN"],
) as connection:
    with connection.cursor() as cursor:
        cursor.execute(sql)
        return [
            TablespaceUsage(
                name=str(row[0]),
                contents=str(row[1]),
                status=str(row[2]),
                used_percent=float(row[3]),
                used_mb=float(row[4]),
                max_mb=float(row[5]),
            )
            for row in cursor
        ]

ORACLE_DSNは環境に合わせます。例えば、サービス名で接続するなら次のような形です。

Markdown
ORACLE_DSN=db-host.example.local:1521/ORCLPDB1

80%と90%で状態を分ける

サンプルでは、80%以上をWARNING、90%以上をCRITICALにしています。

Python
def row_status(row: TablespaceUsage, warning_percent: float, critical_percent: float) -> str:
    if row.used_percent >= critical_percent:
        return "CRITICAL"
    if row.used_percent >= warning_percent:
        return "WARNING"
    return "OK"

80%と90%は固定値ではありません。月末に一気に増えるDBなら早めに警告した方がいいですし、AUTOEXTENDの上限が十分にある環境なら、使用率だけで焦ると空振りが増えます。しきい値は、容量の増え方と対応に必要なリードタイムで決めます。

送信前にdry-runで動作確認する

メール送信や本番DB接続をいきなり動かすと、失敗したときの切り分けが面倒です。サンプルには2つの確認方法を入れています。

Oracleなしでメール本文を確認する

--sample --dry-runを使うと、サンプルデータで件名と本文だけを表示します。

PowerShell
python monitor_tablespaces.py --sample --dry-run

出力例です。

Markdown
[CRITICAL] Oracle tablespace usage report 2026-08-01

Oracle tablespace usage report
Checked at: 2026-08-01 08:36:24
Warning: 80.0% / Critical: 90.0%

status     tablespace             contents    used%      used_mb      max_mb
---------  ---------------------  ----------  ------  -----------  ----------
OK         USERS                  PERMANENT     64.2       6420.0     10000.0
WARNING    APP_DATA               PERMANENT     84.7      16940.0     20000.0
OK         APP_INDEX              PERMANENT     72.1       7210.0     10000.0
CRITICAL   TEMP                   TEMPORARY     91.3       9130.0     10000.0
OK         UNDOTBS1               UNDO          43.5       4350.0     10000.0

この段階ではOracleにもSMTPにも接続しません。件名にCRITICALが入るか、表領域名や使用率が読めるかを見ます。

DB接続だけ確認する

Oracleに接続できる環境では、--dry-runでSQL実行と本文作成まで確認します。

PowerShell
python monitor_tablespaces.py --dry-run

ここで失敗する場合は、だいたい次のどれかです。

Markdown
ORACLE_DSNが違う
DBサーバーへ通信できない
ユーザー名またはパスワードが違う
DBA_TABLESPACE_USAGE_METRICSを参照できない
python-oracledbがインストールされていない

メール送信は最後に確認します。DB接続とSMTP送信を同時に初回確認すると、どちらで落ちたのか追いにくくなります。

Windowsで毎朝実行する

Windowsサーバーなら、タスクスケジューラに登録します。ポイントは、プログラム、引数、開始フォルダを分けることです。

項目設定例
プログラムC:\path\to\nexive-lab\python\oracle-tablespace-mail\.venv\Scripts\python.exe
引数C:\path\to\nexive-lab\python\oracle-tablespace-mail\monitor_tablespaces.py
開始C:\path\to\nexive-lab\python\oracle-tablespace-mail
トリガー毎日 8:00
実行ユーザーDB接続とログ出力に必要な権限を持つ保守用ユーザー

開始を空にすると、.envsql/tablespace_usage.sqlの読み込みで迷うことがあります。サンプルはスクリプトの場所を基準にファイルを読むようにしていますが、タスクスケジューラでは開始フォルダも明示しておく方が確認しやすいです。

実行ユーザーで手動実行する

タスク登録後は、タスクスケジューラの実行ユーザーでコマンドを手動実行します。普段ログインしているユーザーでは動くのに、タスクでは失敗することがあります。

確認するコマンドは次です。

PowerShell
C:\path\to\nexive-lab\python\oracle-tablespace-mail\.venv\Scripts\python.exe C:\path\to\nexive-lab\python\oracle-tablespace-mail\monitor_tablespaces.py --sample --dry-run

ログ出力先を先に作る

サンプルはLOG_FILE=logs/tablespace-monitor.logにログを出します。フォルダはスクリプト側で作りますが、保守サーバーではログ保存先の権限と容量を先に確認します。

タスクが成功扱いなのにメールが来ない場合は、ログファイルを最初に見ます。 SMTPで失敗したのか、DB接続で失敗したのか、Python自体が起動していないのかを分けるためです。

tomo

タスクスケジューラで動かないときは、まず同じ実行ユーザーで手動実行します。設定画面を眺めるより、コマンドを1本ずつ潰す方が早いです。

Linuxで毎朝実行する

Linuxではcronかsystemd timerを使います。既存サーバーでcron運用があるならcronで十分です。systemdでサービス管理を寄せているサーバーなら、timerにしておくと実行履歴をjournalctlで追いやすくなります。

cronで実行する例

毎朝8時に実行する例です。相対パスに頼らず、作業ディレクトリへ移動してから仮想環境のPythonを呼びます。

Bash
0 8 * * * cd /opt/nexive-lab/python/oracle-tablespace-mail && /opt/nexive-lab/python/oracle-tablespace-mail/.venv/bin/python monitor_tablespaces.py

cronでは、ログインシェルで使っている環境変数やPATHがそのまま入るとは限りません。仮想環境のpythonを絶対パスで指定し、.envはスクリプトと同じディレクトリに置きます。

systemd timerで実行する例

systemdで管理する場合は、serviceとtimerを分けます。

/etc/systemd/system/oracle-tablespace-mail.service:

INI
[Unit]
Description=Oracle tablespace mail monitor

[Service]
Type=oneshot
WorkingDirectory=/opt/nexive-lab/python/oracle-tablespace-mail
ExecStart=/opt/nexive-lab/python/oracle-tablespace-mail/.venv/bin/python monitor_tablespaces.py

/etc/systemd/system/oracle-tablespace-mail.timer:

INI
[Unit]
Description=Run Oracle tablespace mail monitor every morning

[Timer]
OnCalendar=*-*-* 08:00:00
Persistent=true

[Install]
WantedBy=timers.target

有効化します。

Bash
sudo systemctl daemon-reload
sudo systemctl enable --now oracle-tablespace-mail.timer
systemctl list-timers oracle-tablespace-mail.timer

実行結果を見るときは次のように確認します。

Bash
systemctl status oracle-tablespace-mail.service
journalctl -u oracle-tablespace-mail.service

Persistent=trueを入れておくと、実行予定時刻にサーバーが止まっていた場合の扱いをsystemd側で追いやすくなります。ただし、起動直後にメールが飛ぶのが困る運用なら、ここはサーバーの運用ルールに合わせて調整します。

運用前に確認する注意事項

スクリプトが動くことと、保守運用に入れてよいことは別です。少なくとも次を確認してから毎朝実行に入れます。

確認項目見ること理由
DBユーザー参照に必要な権限だけを持っているか保守スクリプトに不要な更新権限を持たせないため
接続先本番、検証、待機系を取り違えていないか別DBの正常メールを見て安心しないため
しきい値80%/90%で足りるか増加ペースが速いDBでは警告が遅い場合があるため
AUTOEXTEND拡張上限と物理ディスクの空きを見るか使用率だけでは余裕を読み違えることがあるため
TEMP表領域通常表領域と同じ扱いでよいか一時的なSQL負荷で上がることがあるため
メール経路送信失敗時のログと連絡先を決めているか通知の失敗に気づけないと監視にならないため
秘密情報.envの権限とバックアップ対象を確認したかDBパスワードとSMTPパスワードを漏らさないため

特に接続先の取り違えは怖いです。検証DBを見てOKメールが来ているのに、本番DBの表領域が増え続けていたら意味がありません。メール本文にDB名やホスト名を出す運用にしてもよいです。

本番運用に入れる前に、意図的にWARNING_PERCENTを低くして警告メールが届くことを確認します。 正常時だけ確認して終わると、危険時のメール本文や通知経路が未検証のまま残ります。

TEMP表領域は別枠で見る

TEMP表領域は、重い検索や一時的なソートで使用率が上がることがあります。常に同じ見方で即対応すると、通知が多すぎて誰も見なくなります。

TEMPのCRITICALが続くなら、どのSQLが使っているか、時間帯が偏っているか、バッチ処理と重なっていないかを見ます。通常表領域とTEMP表領域は、メール内では並べて出しても、対応判断は分けた方が無難です。

通知失敗も監視対象にする

メール通知スクリプトは、SMTP接続に失敗するとメールを送れません。つまり、失敗をメールだけで知る作りには限界があります。

Windowsならタスクスケジューラの履歴とログファイル、Linuxならjournalctlやログファイルで失敗を追えるようにします。毎朝メールが来る設定にしておくと、通知が来ないこと自体に気づきやすくなります。

tomo

最初の運用では、警告時だけ送るより毎朝送る設定の方が確認しやすいです。何日か回して、本文としきい値が落ち着いてから通知条件を絞ると失敗に気づきやすくなります。

毎朝の確認に入れる前の最終チェック

Oracleの表領域確認は、SQLを1回書ければ終わりではありません。毎朝見るなら、取得、判定、通知、ログ、定期実行までをまとめて確認できる形にします。

今回のサンプルでは、DBA_TABLESPACE_USAGE_METRICSから使用率を取得し、PythonでOKWARNINGCRITICALに分け、SMTPでメール送信します。--sample --dry-runを使えば、Oracleに接続する前にメール本文の形も確認できます。

Windowsならタスクスケジューラ、Linuxならcronまたはsystemd timerで毎朝実行できます。最初に見るべきなのは、スクリプトの便利さよりも、接続先、権限、しきい値、通知失敗時の扱いです。保守用の自動化は、動くことより、失敗したときに追えることを先に決めると運用に乗せやすくなります。

まずdry-runを残す

初回は--sample --dry-runの出力と、実DBへ接続した--dry-runの出力を作業メモに残します。メール本文の見え方、表領域名、しきい値、ログ出力先を確認した証跡になります。

次に定期実行を1回だけ確認する

タスクスケジューラ、cron、systemd timerのどれを使う場合でも、登録したあとに手動実行します。登録画面や設定ファイルだけを見て終わらせず、実行ユーザー、作業フォルダ、ログ出力、メール送信まで見ます。

最後に運用メモへ落とす

運用メモには、実行時刻、接続先DB、通知先、しきい値、ログファイル、失敗時の確認場所を書きます。スクリプトだけが残っている状態だと、半年後に誰も触れなくなります。

よかったらシェアしてね!
  • URLをコピーしました!
目次