はじめに
とある案件で「Oracle勉強した方がいいな…」と感じたのでOracle Databaseの構造についてざっくりまとめてみました。誰かの参考になれば幸いです。
Oracle Databaseの構造について
Oracle Databaseの構造はざっくり以下のようになっています。
上図の①から⑤まで順に解説していきます。
①サーバ・プロセス群(フォアグラウンド・プロセス群)
サーバ・プロセスとはOracleクライアントとやり取りを行う部分です。
具体的にはOracleクライアントからSQL文を受け付け、その中身が解析されます。
ちなみに図中のPGA(Program Gloabal Area)とは各サーバ・プロセス、またはバックグラウンド・プロセス毎に使用されるメモリ領域で、他のプロセスと共有されません。
➁共有メモリ(SGA: System Global Area)
データや実行計画を各ユーザ間で共有することで、ディスクI/Oを減らしてデータの検索や更新等の効率を上げるメモリ領域です。PGAは各サーバ・プロセスが個別に持つ情報をキャッシュしていましたが、SGAでは全てのプロセスが共有すべき情報をキャッシュしています。具体的には以下の仕組みが内蔵されています。
- データベース・バッファ・キャッシュ:ストレージ上のディスクから取得されたデータ・ブロックをキャッシュする場所です。
- 共有プール:SQL文の処理方法(実行計画)をキャッシュする場所です。
- REDOログ・バッファ:REDO情報をストレージ上のディスクのREDOログファイルに書き込むまでキャッシュしておく場所です。
➂バックグラウンド・プロセス群
ストレージへの変更を反映させる部分です。本記事では一部抜粋して紹介します。
- CKPT(チェックポイント・プロセス):チェックポイントの際、制御ファイルやデータファイルのヘッダに管理情報を書き込むプロセス。
- LGWR(ログ・ライター・プロセス):COMMIT時などで、REDOログ・バッファ上のREDOログをストレージ上のディスクにあるREDOログファイルに書き出すプロセス。
- ARCH(アーカイバ・プロセス):REDOログファイルをアーカイブするプロセス。
- DBWR(データベース・ライター・プロセス):ストレージ上のディスクに負荷をかけないよう、データベース・バッファ・キャッシュで更新されたデータを定期的にデータファイルに書き込む。
データやログを書き込んだり、監視をしたり、インスタンスの障害時にインスタンスのリカバリを行ったり色々な処理が行われます。説明は省略しますが、SMON、PMONといったプロセスが出てくるのもこの部分です。
➃Oracleインスタンス(サーバ)
上記➁共有メモリと➂バックグラウンド・プロセス群をまとめてOracleインスタンスといいます。データを取り出して必要な処理を実行する部分です。
➄Oracleデータベース(ストレージ)
データを格納する部分です。様々なファイルが格納されていますが、本記事では一部を紹介します。
- データファイル:その名の通りデータを格納しています
- 制御ファイル:データファイルやREDOログファイルの位置などデータベースの構造に関わる情報を格納しています。また、メモリ上の変更をいつどこまでファイルに反映したかのチェックポイント情報も格納しています。
- REDOログファイル:データベースへの変更情報を格納しており、障害からの復旧時に必要です。数とサイズに限りがあるため、REDOログを長期間保存する場合はアーカイブREDOログファイルに情報が移されます。
- 初期化パラメータファイル:Oracleインスタンスの構成(メモリ、プロセスなど)や制御ファイルの位置等が記載されています。
- アーカイブREDOログファイル:REDOログを長期保存する際に使用します。
Oracle Databaseの処理の流れ
構造の説明を終えたので、三つ処理の流れを図示して解説します。
※説明の都合上、上記構成図を簡略化したものを用いて解説します。
■SELECT処理
Oracleクライアントからデータの更新(UPDATE)を要求したときの動きを見てみましょう。
SQL文(SELECTの要求)をサーバプロセスが受け付けた後(➀)、共有プールでSQL文の実行計画を立てます。(➁)
共有メモリのデータベース・バッファ・キャッシュ内にSELECT対象のデータがあるか確認します。(➂)
データベース・バッファ・キャッシュ内で対象データがヒットしなかった場合、ストレージ上のディスクにあるデータファイルにアクセスしてデータベース・バッファ・キャッシュに対象データを格納し(➃)、SELECT分の結果をクライアントに返します(➄)。
アクセスされる可能性のあるファイルがデータファイルのみであるところがポイントです。
■UPDATE処理
Oracleクライアントからデータの更新(UPDATE)を要求したときの動きを見てみましょう。
SQL文(UPDATEの要求)をサーバプロセスが受け付けた後(➀)、共有プールでSQL文の実行計画を立てます。(➁)
共有メモリのデータベース・バッファ・キャッシュ内にUPDATE対象のデータがあるか確認します。(➂)
データベース・バッファ・キャッシュ内で対象データがヒットしなかった場合、ストレージ上のディスクにあるデータファイルにアクセスしてバッファ・キャッシュに格納します。(➃)
対象データを更新する旨をREDOログ・バッファに記録した後(➄)、データベース・バッファ・キャッシュ上のデータを更新します。更新情報だけでなくトランザクションが失敗したときに備えて、更新前の情報(UNDO情報)も格納されます。(➅)最後にOracleクライアントに返信します。(➆)
UPDATEの処理自体はこの時点で行われず、Oracleクライアントに「処理は受け付けたぞ」と返答する部分がポイントです。このあと説明するCOMMIT時に実際にデータファイルにデータ更新が反映されます。
■COMMIT処理
Oracleクライアントからトランザクション処理の確定(COMMIT)をしたときの動きを見てみましょう。上のUPDATE処理の続きとしてご覧ください。COMMITでは様々なプロセスやファイルが絡んでくるので、図を2つに分けて解説を行います。
データベース・バッファ・キャッシュとREDOログ・バッファキャッシュにはUPDATE時に格納された更新履歴がある状態です。SQL文(COMMIT)をサーバプロセスが受け付けた後(➀)、REDOログ・バッファ上の更新履歴をOracleデータベースのREDOログファイルへ書き込みます。(➁)
REDOログファイルへの書き込み中にファイルが一杯になってしまったら、別のREDOログファイルへと書き込み先を変更します。これをログスイッチといいます。(➂)REDOログファイルの数には限りがあるため、REDOログを長時間貯めておくことができません。そこで、REDOログを長期保存するために、ARCHを用いてREDOログファイルを、アーカイブREDOログファイルへと格納します。(➃)また、ログスイッチのタイミングでCKPTにより、データファイルと制御ファイルに更新がかけられます。ちなみにチェックポイントはログスイッチ以外にもデータファイルのオンラインバックアップ実行中や、インスタンスのシャットダウン時等で発生します。(➄)まだデータファイルに更新は反映されていませんが、以上でクライアントに完了通知が送られます。(➅)データファイルへの書き込みは非同期で後ほどDBWRで実施します。(➆)DBWRの発生タイミングは他にもありますが、本記事では省略します。
最後に
今回はOracle Databaseの構造と処理の流れについてざっくりと解説を行いました。最初は「OracleはDBMSの一種ですよね?」くらいの知識しかありませんでしたが、いい感じに知識整理できたと思います。ここまでお読みいただきありがとうございました!
参考資料
- Oracle19C公式ドキュメント「Oracleデータベース・インスタンス」
- Oracle19C公式ドキュメント「メモリー・アーキテクチャ」
- 日本Oracleセミナー資料『今さら聞けない!? Oracle入門 概要編(Oracle公式)』
- 日本Oracleセミナー資料『今さら聞けない!? Oracle入門 アーキテクチャ編(Oracle公式)』
- アシスト社セミナー資料『夜な夜な! なにわオラクル塾 Presented By アシスト #43』
- Oracle JapanのYoutube動画『1) データベースのバックアップについて』
- Oracle JapanのYoutube動画『2) Oracle Database のアーキテクチャ概要』
- 書籍『絵で見てわかるOracleの仕組み【新装版】』
- 書籍『オラクルマスター教科書 Bronze DBA Oracle Database Fundamentals』
- 記事『SQLの実行と排他制御からDBの内部動作を知る(前編)』
- 記事『Oracleデータベースアーキテクチャを復習する』