概要
データベースシステムにおける「データベースを開く」および「データベースを閉じる」という操作は、単にアプリケーションがデータベースに接続し、その後切断するというレベルの話に留まりません。プロフェッショナルなデータベース管理者(DBA)にとって、これらの操作はRDBMS(リレーショナルデータベース管理システム)インスタンスのライフサイクル管理、データ整合性の確保、システムリソースの効率的な利用、そして何よりもシステムの可用性と安定性を維持するための極めて重要なプロセスを意味します。
「データベースを開く」とは、RDBMSインスタンスが起動し、必要なメモリ構造を確保し、データファイル、制御ファイル、REDOログファイルといった物理ファイルを読み込み、トランザクション処理を受け入れられる状態にする一連のプロセスを指します。一方、「データベースを閉じる」とは、その逆で、稼働中のデータベースインスタンスを安全かつ整合性のある形で停止させ、すべてのリソースを解放するプロセスです。これらの操作は、システムのメンテナンス、バックアップ、リカバリ、アップグレード、あるいは緊急時の対応において、DBAが日常的に直面するタスクであり、その挙動と影響を深く理解しておくことが不可欠です。本記事では、これらの操作の技術的な詳細、実際のコマンド例、そして実務における重要な考慮事項について解説します。
詳細解説
RDBMSインスタンスの起動プロセス(データベースを開く)
データベースインスタンスの起動は、いくつかの段階を経て行われます。各RDBMSには独自のプロセスがありますが、ここでは一般的な概念とOracle Databaseの例を交えて説明します。
1. **NOMOUNTフェーズ(Oracleの場合)**:
* この段階では、RDBMSはまだデータベースファイルに関する情報を何も知りません。
* 主に、インスタンスの起動に必要なメモリ領域(OracleではSGA: System Global Area、PGA: Program Global Areaなど)をOSから確保し、バックグラウンドプロセス群(PMON, SMON, DBWn, LGWR, CKPTなど)を起動します。
* この時、初期化パラメータファイル(SPFILEまたはPFILE)を読み込み、インスタンスの基本的な設定をロードします。
* この状態では、データベース自体はまだ開かれておらず、データファイルへのアクセスはできません。
2. **MOUNTフェーズ(Oracleの場合)**:
* NOMOUNT状態から、データベースは制御ファイル(control file)を読み込みます。制御ファイルには、データベース名、データファイルの場所と名前、REDOログファイルの場所と名前、現在のログシーケンス番号、チェックポイント情報など、データベースの物理構造に関する重要なメタデータが格納されています。
* 制御ファイルを読み込むことで、インスタンスはデータベースの物理的なレイアウトを認識しますが、まだデータファイル自体はオープンされていません。
* この状態では、データファイルやREDOログファイルへの変更はできませんが、リカバリやバックアップなどの特定の管理操作は可能です。
3. **OPENフェーズ(Oracleの場合)**:
* MOUNT状態から、RDBMSはデータファイルとREDOログファイルをオープンし、トランザクション処理を受け入れられる状態になります。
* この段階で、必要に応じてクラッシュリカバリが自動的に実行されます。これは、停止前のコミットされていないトランザクションをロールバックし、コミットされたがディスクに書き込まれていなかった変更を適用するプロセスです。これにより、データベースの整合性が保証されます。
* リカバリが完了すると、データベースは完全にオープンされ、ユーザーセッションからの接続とSQL文の実行を受け入れる準備が整います。
* PostgreSQLやMySQLなどのRDBMSでは、これらのフェーズがより統合されており、通常は単一の起動コマンドでインスタンスの起動とデータベースのオープンが同時に行われますが、内部的には同様のステップを踏んでいます。例えば、PostgreSQLでは共有メモリの確保、バックグラウンドプロセスの起動、WAL(Write-Ahead Log)のリカバリなどが起動時に実行されます。
RDBMSインスタンスの停止プロセス(データベースを閉じる)
データベースの停止は、データ整合性を保ちつつ安全にリソースを解放するために、複数のモードが提供されます。適切な停止モードの選択は、システムの可用性とデータ損失のリスクに直結します。
1. **NORMAL停止**:
* 最も安全で穏やかな停止モードです。
* 新規の接続を拒否し、既存のすべてのユーザーセッションが切断されるまで、または進行中のトランザクションが完了するまで待機します。
* すべてのデータ変更がディスクに書き込まれ、整合性が完全に保証されます。
* ダウンタイムが予測しにくいという欠点があります。
2. **IMMEDIATE停止**:
* 新規の接続を拒否し、既存のユーザーセッションは強制的に切断されます。
* 進行中のトランザクションはすべてロールバックされます。
* すべてのデータ変更がディスクに書き込まれ、整合性は保証されます。
* NORMAL停止よりも迅速に停止できますが、ユーザーには予期せぬ切断が発生します。多くのメンテナンス作業で推奨される停止モードです。
3. **TRANSACTIONAL停止(Oracleの場合)**:
* 新規の接続は拒否されますが、既存のトランザクションが完了するまで待機します。
* トランザクションが完了したセッションは切断されます。
* トランザクションが長時間かかる場合、停止に時間がかかる可能性があります。IMMEDIATE停止とNORMAL停止の中間のような挙動です。
4. **ABORT停止**:
* 最も高速ですが、最も危険な停止モードです。
* すべてのユーザーセッションを即座に強制終了し、進行中のトランザクションもロールバックされずに終了します。
* メモリ上の変更がディスクに書き込まれるのを待たずにインスタンスを停止するため、データベースは整合性のない状態になる可能性があります。
* 次にデータベースを起動する際に、自動的にクラッシュリカバリが実行され、整合性が回復されます。
* 緊急時や、他の停止モードで停止できない場合にのみ使用すべきです。
アプリケーションからのデータベース接続と切断
アプリケーションがデータベースを利用する際には、通常、特定のRDBMSに接続し、処理が完了したら切断します。
* **接続**:
* JDBC (Java Database Connectivity) や ODBC (Open Database Connectivity) などのAPIを通じて、アプリケーションはデータベースサーバーにネットワーク接続を確立します。
* 接続時には、ユーザー名、パスワード、接続先のホスト名/IPアドレス、ポート番号、サービス名/データベース名などの情報が使用されます。
* 認証と認可が成功すると、データベースセッションが確立され、SQL文の実行が可能になります。
* 効率化のため、接続プール(Connection Pool)が一般的に利用されます。これは、アプリケーション起動時に一定数のデータベース接続を事前に確立しておき、必要に応じてプールから接続を借り、使用後にプールに返却することで、接続確立・切断のオーバーヘッドを削減する仕組みです。
* **切断**:
* アプリケーションがデータベース処理を完了した後、確立された接続は明示的にクローズされるべきです。
* 接続をクローズすることで、データベースサーバー側のリソース(メモリ、プロセス、ロックなど)が解放されます。
* 接続プールの場合は、接続をプールに返却します。
* 明示的な切断を怠ると、リソースリークが発生し、データベースサーバーのリソースが枯渇して、最終的にシステム全体のパフォーマンス低下や停止につながる可能性があります。
ファイルシステムレベルでのデータベースのオープン/クローズ
これは、RDBMSインスタンスの起動/停止とは少し異なる概念ですが、DBAがデータファイルの可用性を制御する際に使用します。
* **データファイルのオンライン/オフライン**:
* 特定のデータファイルや表領域を一時的にオフラインにすることで、そのファイルへのアクセスを停止させることができます。これは、破損したファイルを修復したり、バックアップからリストアしたりする際に利用されます。
* オフラインにしたファイルは、修復後に再びオンラインに戻すことで、データベース全体を停止せずに部分的なメンテナンスを行うことが可能です。
サンプルコード
ここでは、主要なRDBMSにおけるインスタンスの起動/停止コマンドと、Java JDBCによるアプリケーションからの接続/切断の例を示します。
RDBMSインスタンスの起動/停止
1. **Oracle Database (SQL*Plus)**
* 起動:
— SQL*PlusにSYSDBAとして接続
sqlplus / as sysdba
— インスタンスをNOMOUNTで起動
STARTUP NOMOUNT;
— 制御ファイルをマウント
ALTER DATABASE MOUNT;
— データベースをオープン
ALTER DATABASE OPEN;
— 全てを一度に実行
STARTUP;
* 停止:
— NORMAL停止
SHUTDOWN NORMAL;
— IMMEDIATE停止
SHUTDOWN IMMEDIATE;
— TRANSACTIONAL停止
SHUTDOWN TRANSACTIONAL;
— ABORT停止 (緊急時のみ)
SHUTDOWN ABORT;
2. **PostgreSQL (pg_ctl)**
* 起動:
pg_ctl -D /path/to/your/data/directory start
* 停止:
# スマート停止 (NORMAL相当)
pg_ctl -D /path/to/your/data/directory stop -m smart
# 高速停止 (IMMEDIATE相当)
pg_ctl -D /path/to/your/data/directory stop -m fast
# 強制停止 (ABORT相当)
pg_ctl -D /path/to/your/data/directory stop -m immediate
3. **MySQL (mysqladminまたはsystemctl)**
* 起動 (systemdを使用する場合):
sudo systemctl start mysql
* 停止 (systemdを使用する場合):
sudo systemctl stop mysql
* 停止 (mysqladminを使用する場合):
mysqladmin -u root -p shutdown
アプリケーションからのデータベース接続と切断 (Java JDBC)
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;
public class DbConnectionExample {
private static final String DB_URL = "jdbc:postgresql://localhost:5432/mydatabase";
private static final String USER = "myuser";
private static final String PASS = "mypassword";
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
// 1. データベースドライバーのロード (JDBC 4.0以降は不要な場合が多い)
// Class.forName("org.postgresql.Driver");
System.out.println("データベースに接続中...");
// 2. データベースへの接続確立
connection = DriverManager.getConnection(DB_URL, USER, PASS);
System.out.println("データベースに接続しました。");
// 3. SQLステートメントの作成
statement = connection.createStatement();
// 4. SQLの実行 (例: データ問い合わせ)
String sql = "SELECT id, name FROM users";
resultSet = statement.executeQuery(sql);
// 5. 結果セットの処理
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
System.out.println("ID: " + id + ", Name: " + name);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 6. リソースの解放 (

コメント