- データベース
DBMSとは|RDBMSとの違い・役割をSQLiteとPostgreSQLで実演
結論
DBMS(データベース管理システム)とは、データの保存・検索に加えて、同時更新の順番待ち・失敗した処理の取り消し・障害からの回復・権限の管理を受け持つソフトウェアです。RDBMS は、データを表(行と列)で扱う DBMS の一種です。
この記事でわかること
- DBMSの6つの役割と、RDBMS・NoSQL・NewSQLの違い
- SQLiteとPostgreSQLで起こしたロック・ROLLBACK・回復・権限エラーの原文
- CSVファイルで同じことをしたときとの違い(実測)と、製品の選び方
アプリはデータを直接ファイルに書かず、DBMS に「この条件で探して」「この行を変えて」と SQL で頼みます。DBMS は、頼まれた仕事を安全な順番で実行し、結果だけを返します。
flowchart TD
A[アプリ・利用者] -->|SQLで依頼| D
subgraph D[DBMS]
P[SQLの解析と実行計画]
L[同時実行制御<br>ロック]
T[トランザクション<br>COMMIT・ROLLBACK]
R[障害回復<br>WAL・ジャーナル]
G[権限・認証]
end
D -->|読み書き| F[(データファイル<br>インデックス)]
よく調べられることの答えを先にまとめます。
| 知りたいこと | 答え | 詳しい節 |
|---|---|---|
| DBMSとは | データベースを作り、読み書きを安全に管理するソフトウェア | DBMSとは(意味) |
| データベースとDBMSの違い | データベースは「データの集まり」、DBMSは「それを管理する仕組み」 | DBMSとは(意味) |
| RDBMSとは・DBMSとの違い | RDBMSは表でデータを扱うDBMS。DBMSはNoSQLなども含む総称 | DBMSの種類とRDBMSとの違い |
| DBMSの機能・役割 | 定義・操作・同時実行制御・トランザクション・障害回復・権限 | DBMSの6つの役割 |
| 2人が同時に更新したら | 後から来た側が待たされ、更新は失われない | 同時実行制御(ロック) |
| 途中で失敗したら | ROLLBACKで全部が元に戻る | トランザクションとROLLBACK |
| Excel・CSVとの違い | 同時更新で数が狂う・書きかけを読む問題をDBMSが防ぐ | CSVファイルとの違い |
| DBMSの例・製品 | Oracle・MySQL・PostgreSQL・SQL Server・SQLite など | 主要なDBMS製品の比較 |
確認環境:Ubuntu 24.04.5 LTS(2 CPU・メモリ 8GB)の上で、PostgreSQL 16.15(Ubuntu のパッケージ)を作業用のフォルダーに initdb し、127.0.0.1 の空きポートで起動しました。psql 16.15 で2つの接続を同時に開き、行ロックの待ち・lock_timeout・デッドロック・ROLLBACK・権限(GRANT と scram-sha-256 のパスワード認証)を確かめ、pg_ctl stop -m immediate(公式ドキュメントで「次の起動でクラッシュリカバリーになる」と説明されている止め方)で障害を起こして、WAL からの回復をサーバーログと pg_waldump で見ました。SQLite は Python 3.13.18 の sqlite3 モジュール(SQLite 3.53.1)とコマンドラインの sqlite3 3.45.1 で、ロック・ROLLBACK・プロセスを強制終了したあとの回復(WAL モードとロールバックジャーナルの両方)・読み取り専用の扱いを確かめました。インデックスの効果は30万行、CSV との比較は同じデータで、どれも同じマシンで測っています。Oracle Database・SQL Server・MySQL は手元で動かしておらず、ライセンスと版は各社の公式サイトで確かめました。図は mermaid で描画を確かめています(確認日 2026年10月29日)。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「DBMSとは|RDBMSとの違い・役割をSQLiteとPostgreSQLで実演」
DBMSとは(意味・データベースとの違い)
この節では、DBMS という言葉の意味と、「データベース」との違いが分かります。
DBMS は Database Management System の略で、日本語では「データベース管理システム」です。データベース(整理して保存されたデータの集まり)を作り、データの追加・検索・更新・削除を受け付け、その間にデータが壊れたり食い違ったりしないように管理するソフトウェアを指します。MySQL・PostgreSQL・Oracle Database・SQL Server・SQLite は、どれも DBMS の製品です。
日常の会話では「データベース」と「DBMS」を同じ意味で使うことが多いですが、分けると次のようになります。
| データベース | DBMS | |
|---|---|---|
| 何か | データの集まり(顧客の一覧・注文の記録) | データベースを管理するソフトウェア |
| たとえると | 図書館の本 | 本の貸し出し・返却・場所の管理をする司書と仕組み |
| 手元で見える形 | データファイル(SQLite なら1つのファイル) | 動いているプログラム(PostgreSQL ならサーバーのプロセス) |
| 例 | 「会員データベース」「商品データベース」 | PostgreSQL・MySQL・SQLite |
データベースそのもの(表・行・列・主キー、Excel との違い、SQL の基本)は、関連記事「データベースとは|種類・Excelとの違い・SQLの基本を実例で解説」で扱っています。この記事は、その中身を管理する側の DBMS に絞り、DBMS が裏で何をしているのかを実際に動かして見せます。
DBMS が無いとどうなるか
DBMS が広まる前は、アプリがそれぞれ自分の形式でファイルを読み書きしていました。そのやり方には、次の問題がありました。
- 同時に書くと壊れる:2つのプログラムが同じファイルを同時に書き換えると、片方の変更が消える。
- 途中で止まると半端な状態が残る:振込の「引く」だけが終わって「足す」の前に止まると、お金が消える。
- 探すのが遅い:毎回ファイルを先頭から最後まで読む。
- 見せる範囲を分けにくい:ファイルを読める人は全部読めてしまう。
- 形式がアプリごとに違う:別のアプリから使い回せない。
DBMS は、こうした問題を「アプリの外の1か所」でまとめて引き受けます。この記事の後半では、CSV ファイルで実際に1つ目と2つ目の問題を起こし、DBMS では起きないことを同じデータで確かめます。
DBMSの6つの役割(機能の一覧)
この節では、DBMS が受け持つ主な機能と、この記事で実際に確かめた範囲が分かります。
DBMS の機能は、資料によって「5つ」「4つ」などと数え方が違いますが、中身はおおむね次の6つにまとまります。情報処理技術者試験でも、データ定義・データ操作・同時実行制御(排他制御)・トランザクション管理・障害回復・機密保護がよく問われます。
1データ定義
表・列の型・制約(主キー、NOT NULL、CHECK)を決める。CREATE TABLE など(DDL)。
2データ操作と検索
追加・検索・更新・削除。SELECT・INSERT など(DML)。インデックスと実行計画で速く探す。
3同時実行制御
複数の利用者が同時に同じデータを変えても食い違わないよう、ロックで順番を決める。
4トランザクション管理
「全部やる」か「全部やらない」かのどちらかにする。COMMIT・ROLLBACK(TCL)。
5障害回復
電源断・強制終了のあと、確定した変更は残し、確定していない変更は消す。WAL・ジャーナル・バックアップ。
6機密保護(権限)
誰が・どの表に・何をしてよいかを決める。GRANT・REVOKE(DCL)と認証。
| 役割 | この記事で起こしたこと | 確かめたDBMS |
|---|---|---|
| 同時実行制御 | 2つの接続で同じ行を更新し、後の側が待つ・タイムアウト・デッドロック | PostgreSQL・SQLite |
| トランザクション | 振込の途中で制約違反を起こし、ROLLBACKで元に戻る | PostgreSQL・SQLite |
| 障害回復 | 確定済み1,000行と未確定500行がある状態で強制停止し、再起動 | PostgreSQL・SQLite |
| 検索(インデックス) | 30万行からメールアドレスで1件探す。インデックスの有無で比較 | PostgreSQL・SQLite |
| 権限 | 読むだけの利用者で更新・削除・表の作成を試す | PostgreSQL・SQLite |
| CSVとの違い | 2つのプロセスで在庫を500回ずつ減らす | CSV・SQLite |
同時実行制御:2つの接続で同時に更新したときのロック
この節では、2人が同じデータを同時に変えようとしたとき、DBMS がロックでどう順番を決めるのかが、実際の出力で分かります。
口座の表を作り、佐藤さんの残高 1,000円 から、接続Aが100円、接続Bが200円を同時に引きます。Aは更新したあと確定(COMMIT)せずに6秒待ち、その間にBが同じ行を更新します。
-- 準備
CREATE TABLE accounts (
id int PRIMARY KEY,
name text NOT NULL,
balance int NOT NULL CHECK (balance >= 0)
);
INSERT INTO accounts VALUES (1,'佐藤',1000),(2,'鈴木',500);
-- 接続A
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
SELECT pg_sleep(6); -- 確定する前に6秒かかる処理のつもり
COMMIT;
-- 接続B(Aの1秒後)
UPDATE accounts SET balance = balance - 200 WHERE id = 1;
Bが待っている間に、3つ目の接続から PostgreSQL の中を見ました。
pid | app | state | wait_event_type | wait_event | query
------+------+--------+-----------------+---------------+----------------------------------------------------
2839 | psql | active | Timeout | PgSleep | SELECT pg_sleep(6);
2938 | psql | active | Lock | transactionid | UPDATE accounts SET balance = balance - 200 WHERE
pid | blocked_by
------+------------
2938 | {2839}
pid | locktype | mode | granted
------+---------------+------------------+---------
2839 | transactionid | ExclusiveLock | t
2938 | tuple | ExclusiveLock | t
2938 | transactionid | ExclusiveLock | t
2938 | transactionid | ShareLock | f
Bの UPDATE は wait_event_type = Lock で止まり、pg_blocking_pids は「2839(接続A)に止められている」と示しました。最後の行の granted = f は「Aのトランザクションが終わるのを待つロックを、まだもらえていない」という意味です。Aが確定すると、Bは動き出しました。
UPDATE 1
B wait: 5.037561236
id | name | balance
----+------+---------
1 | 佐藤 | 700
2 | 鈴木 | 500
Bは約5.04秒待ち、残高は 1,000 − 100 − 200 = 700円 になりました。Bは、Aが確定したあとの値(900円)から200円を引いています。どちらかの更新が消える「ロストアップデート」は起きていません。
違う行なら待たない・読むだけなら待たない
Aが佐藤さんの行(id=1)をロックしている間に、Bが鈴木さんの行(id=2)を更新すると Time: 2.361 ms ですぐ終わりました。PostgreSQL のロックは行単位だからです。また、Aが残高を9999に書き換えて確定していない間に SELECT すると、0.839 ms で 確定済みの700 が返りました。PostgreSQL は MVCC(多版型同時実行制御。更新前の版を残しておく仕組み)で、読む側を待たせません。
待ちすぎを防ぐ lock_timeout と、デッドロック
待ち時間に上限を付けると、ロックが取れないときにエラーで戻ります。
SET lock_timeout = '2s';
UPDATE accounts SET balance = 0 WHERE id = 1;
ERROR: canceling statement due to lock timeout
CONTEXT: while updating tuple (0,6) in relation "accounts"
2つの接続が「id=1→id=2」と「id=2→id=1」の逆の順番で行を更新すると、お互いが相手を待つデッドロックになります。PostgreSQL は数秒で検知し、片方を取り消しました。
ERROR: deadlock detected
DETAIL: Process 6416 waits for ShareLock on transaction 767; blocked by process 6430.
Process 6430 waits for ShareLock on transaction 766; blocked by process 6416.
HINT: See server log for query details.
CONTEXT: while updating tuple (0,10) in relation "accounts"
ロックの調べ方(止めている接続の特定から解除まで)は関連記事「PostgreSQLロック確認SQL|ブロッキング特定から解除までコピペ集」で扱っています。
SQLite は「データベース全体」で1人ずつ書く
同じことを SQLite(WAL モード)で、待ち時間の上限を2秒にして試しました。Aは id=1 を更新して確定せず、Bは別の行の id=2 を更新します。
B reads while A writes: (1000,)
B write: OperationalError: database is locked (waited 2.01s)
B write after A commit: ok
[(1, '佐藤', 900), (2, '鈴木', 300)]
読む側は確定済みの1000をすぐ受け取れましたが、書く側は別の行でも2.01秒待ったあと database is locked になりました。SQLite の公式ドキュメントは「読み手は同時にいくつでもよいが、書き手は同時に1つだけ」と説明しています。Aが確定したあとは、Bの更新も通りました。
PostgreSQL(サーバー型)
ロックは行単位。別の行は待たずに更新できた(2.4ms)
同じ行は、先の確定まで待ってから正しい値で更新(5.04秒待ち)
読む側は待たない(MVCC)
SQLite(組み込み型)
書き込みはデータベース全体で1つずつ。別の行でも待った
待ち時間の上限(timeout)を超えると database is locked
WAL モードなら読む側は待たない
トランザクションとROLLBACK:途中で失敗したら全部戻る
この節では、トランザクション(まとめて1つの仕事として扱う単位)と ROLLBACK が、どう「半端な状態」を防ぐのかが分かります。
佐藤さんから鈴木さんへ 3,000円 を振り込みます。鈴木さんに足す更新は通りますが、佐藤さんの残高は1,000円なので、引く更新は「残高は0以上」の制約に違反します。
BEGIN
UPDATE 1
ERROR: new row for relation "accounts" violates check constraint "accounts_balance_check"
DETAIL: Failing row contains (1, 佐藤, -2000).
ERROR: current transaction is aborted, commands ignored until end of transaction block
ROLLBACK
id | name | balance
----+------+---------
1 | 佐藤 | 1000
2 | 鈴木 | 500
鈴木さんへの「足す」は一度成功していますが、ROLLBACK で取り消され、2人とも元の残高に戻りました。エラーのあとの current transaction is aborted は、「このトランザクションは失敗済みなので、ROLLBACK するまで次の命令は受け付けない」という PostgreSQL の決まりです。
SQLite でも同じ振込を試すと、トランザクションの中では鈴木さんが一時的に3,300円になって見えますが、ROLLBACK のあとは元に戻りました。
error: IntegrityError CHECK constraint failed: balance>=0
inside txn: [(1, '佐藤', 900), (2, '鈴木', 3300)]
after ROLLBACK: [(1, '佐藤', 900), (2, '鈴木', 300)]
ACID特性:トランザクションが守る4つの性質
| 性質 | 意味 | この記事で見た場面 |
|---|---|---|
| Atomicity(原子性) | 全部やるか、全部やらないか | 振込の片方だけが残らなかった |
| Consistency(一貫性) | 決まり(制約)に合わない状態にならない | 残高がマイナスになる更新を拒否した |
| Isolation(独立性) | 同時に動く処理どうしが、互いの途中を見ない | 確定前の9999は他の接続から見えなかった |
| Durability(永続性) | 確定した変更は、障害のあとも残る | 強制停止のあとも確定済み1,000行が残った(次の節) |
「独立性」をどこまで厳しくするか(分離レベル)は、関連記事「トランザクション分離レベルの違いをわかりやすく解説」で扱っています。
障害回復:強制停止のあとWALで元に戻る様子
この節では、処理の途中でサーバーが止まったとき、DBMS が何を残し何を捨てるのかが、PostgreSQL と SQLite の実物で分かります。
PostgreSQL:確定済みは残り、確定前は消える
注文の表に1,000行を入れて確定し、続けて別のトランザクションで500行を入れている途中(まだ COMMIT していない)で、pg_ctl stop -m immediate でサーバーを止めました。公式ドキュメントはこの止め方を「すべてのサーバープロセスをきれいな終了をせずに直ちに中断する。次の起動でクラッシュリカバリーになる」と説明しています。つまり、停電やプロセスの異常終了に近い止まり方です。
再起動したときのサーバーログです(各行の先頭の日時は省きました)。
LOG: database system was interrupted; last known up at ...
LOG: database system was not properly shut down; automatic recovery in progress
LOG: redo starts at 0/19257A0
LOG: invalid magic number 0000 in WAL segment 000000010000000000000001, LSN 0/195E000, offset 9822208
LOG: redo done at 0/195DFC0 system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s
LOG: checkpoint starting: end-of-recovery immediate wait
LOG: checkpoint complete: wrote 22 buffers (0.3%); ...
LOG: database system is ready to accept connections
種類 | count
----------+-------
確定済み | 1000
「きちんと終了していないので自動で回復する」と記録したあと、WAL(Write-Ahead Log。データファイルより先に書く変更の記録)を読み直し(redo)、確定済みの1,000行だけが残りました。途中だった500行は1行も残っていません。invalid magic number 0000 は WAL の記録がそこで終わっていることを示すもので、ここでは異常ではありません。
WAL の中身を pg_waldump で出し、トランザクションごとに記録の種類を数えると(uniq -c の結果を見出しを付けて並べ直しました)、理由が分かります。
件数 トランザクション 記録の種類
1 745 COMMIT
1999 745 INSERT(表と主キーの索引)
942 746 INSERT(表と主キーの索引)
確定した745番には COMMIT の記録があり、途中だった746番には INSERT の記録が942件あるのに COMMIT がありません。PostgreSQL は COMMIT の記録が無いトランザクションを「無かったこと」として扱います。DBMS が「確定した」と応答するのは、COMMIT の記録を WAL に書き終えてからです。
SQLite:プロセスを強制終了しても戻る
SQLite はサーバーを持たず、アプリのプロセスの中で動きます。そこで、アプリ自身が1,000行を確定し、500行を入れている途中で自分に SIGKILL を送って強制終了させました。
pid 4952 killing self with SIGKILL during open transaction
Killed
-rw-r--r-- 1 root root 4096 crash.db
-rw-r--r-- 1 root root 32768 crash.db-shm
-rw-r--r-- 1 root root 41232 crash.db-wal
(次に開いたとき)
('ok',) [('確定済み', 1000)]
-rw-r--r-- 1 root root 32768 crash.db
WAL モードでは、変更はまず -wal ファイルに追記されます。次に開いたときは、確定済みの1,000行だけが見え、PRAGMA integrity_check は ok でした。閉じたときに WAL の中身がデータベース本体に移り、-wal と -shm は消えました。
WAL を使わない既定の「ロールバックジャーナル」の形でも試しました。こちらは、書き換える前のページを -journal に控えてから本体を直接書き換えます。
-rw-r--r-- 1 root root 1466368 j.db
-rw-r--r-- 1 root root 13840 j.db-journal
(次に開いたとき)
('ok',) [('確定済み', 1000)]
-rw-r--r-- 1 root root 32768 j.db
強制終了の時点で本体は 1.4MB まで書き換わっていましたが、次に開いたときに SQLite がジャーナルから元のページを書き戻し、32KB・確定済み1,000行の状態に戻りました。このとき -journal ファイルを消したり、本体だけを別の場所にコピーしたりすると、書き戻しができなくなります。SQLite の公式ドキュメント(Atomic Commit In SQLite)も、ジャーナル(ホットジャーナル)を消すと壊れる原因になると説明しています。
データベースのファイルの扱い
回復に使う記録は、本体と組でそろって初めて意味を持つ
インデックス:あり・なしで検索の速さを比べる
この節では、DBMS がインデックス(索引)と実行計画で検索を速くする様子と、その代わりに増える負担が分かります。
30万人分の顧客の表から、メールアドレスで1人を探しました。PostgreSQL の EXPLAIN ANALYZE の出力です。
-- インデックスなし
Gather (cost=1000.00..5696.98 rows=1 width=33) (actual time=14.795..35.596 rows=1 loops=1)
Workers Planned: 1
Workers Launched: 1
-> Parallel Seq Scan on customers (cost=0.00..4696.88 rows=1 width=33) (actual time=20.764..29.520 rows=0 loops=2)
Filter: (email = 'user123456@example.com'::text)
Rows Removed by Filter: 150000
Execution Time: 35.613 ms
-- CREATE INDEX customers_email_idx ON customers(email); (Time: 389.393 ms)
Index Scan using customers_email_idx on customers (cost=0.42..8.44 rows=1 width=33) (actual time=0.004..0.005 rows=1 loops=1)
Index Cond: (email = 'user123456@example.com'::text)
Execution Time: 0.010 ms
インデックスが無いときは、2つのプロセスで15万行ずつ全部を読み(Seq Scan)、1件のために29万9,999行を捨てていました。インデックスを作ると、DBMS が自分で実行計画を Index Scan に切り替えました。SQL は1文字も変えていません。どう探すかを決めるのは DBMS の仕事です。
SQLite も EXPLAIN QUERY PLAN で同じ変化が見えます。
plan: [(2, 0, 216, 'SCAN customers')]
plan: [(3, 0, 62, 'SEARCH customers USING INDEX idx_email (email=?)')]
インデックスの代わりに増えるもの
インデックスは「探す」を速くする一方で、「書く」たびに索引も直す手間が増えます。PostgreSQL で20万行を一度に入れた時間を比べました(2回測定)。
| 表 | 20万行の INSERT(1回目) | 2回目 | 大きさ |
|---|---|---|---|
| インデックスなし | 346ms | 404ms | ― |
| インデックス2本(id・email) | 1,247ms | 1,386ms | ― |
| 30万行の customers(参考) | ― | ― | 表 19MB・索引 12MB |
書き込みは約3.5倍の時間になり、索引だけで表の6割ほどの容量を使いました。検索の条件によく使う列にだけ作るのが基本です。インデックスを作っても使われない書き方(列に関数をかける・前方一致でない LIKE など)は、関連記事「SQLのインデックスが効かない10のパターンと確認方法」で扱っています。
権限:許可されていない操作をDBMSが断る
この節では、DBMS の機密保護(認証と権限)が、どんなエラーで操作を断るのかが分かります。
PostgreSQL で、口座の表を「読むだけ」の利用者 reader を作りました。
CREATE ROLE reader LOGIN PASSWORD '********';
GRANT CONNECT ON DATABASE t125db TO reader;
GRANT USAGE ON SCHEMA public TO reader;
GRANT SELECT ON accounts TO reader;
\dp accounts
Schema | Name | Type | Access privileges
--------+----------+-------+---------------------------
public | accounts | table | postgres=arwdDxt/postgres+
| | | reader=r/postgres
reader=r の r は read(SELECT)だけを持つという意味です。reader で操作すると、次のようになりました。
SELECT * FROM accounts ORDER BY id; → 2行が返る
UPDATE accounts SET balance = 0 WHERE id = 1;
ERROR: permission denied for table accounts
DELETE FROM accounts;
ERROR: permission denied for table accounts
CREATE TABLE memo(id int);
ERROR: permission denied for schema public
LINE 1: CREATE TABLE memo(id int);
^
読むことはできても、更新・削除・表の作成は DBMS が断りました。PostgreSQL 15 以降は、一般の利用者が public スキーマに表を作れない設定が既定です。
「誰か」を確かめる認証も DBMS の仕事です。reader の接続をパスワード認証(scram-sha-256)にして、違うパスワードで接続しました。
psql: error: connection to server at "127.0.0.1", port 54125 failed: FATAL: password authentication failed for user "reader"
権限の設計の型(読み取り専用・アプリ用・管理者用のロールの分け方)は、関連記事「PostgreSQLのロールと権限|GRANT設計テンプレートとエラー対処」で扱っています。
SQLite には利用者と GRANT が無い
$ sqlite3 bank.db "GRANT SELECT ON accounts TO reader;"
Error: in prepare, near "GRANT": syntax error
$ sqlite3 "file:bank.db?mode=ro" "UPDATE accounts SET balance=0;"
Error: stepping, attempt to write a readonly database (8)
SQLite には利用者という考え方が無く、GRANT は文法エラーになります。読み書きを分けたいときは、OS のファイルの権限か、読み取り専用で開く(mode=ro)方法を使います。ファイルの所有者以外(nobody)で開くと、SELECT は通り、UPDATE は attempt to write a readonly database で断られました。複数の利用者ごとに細かく権限を分けたいなら、サーバー型の DBMS を選ぶ理由になります。
CSVファイルで管理する場合との違い(同じデータで実測)
この節では、DBMS を使わずに CSV ファイルでデータを管理すると、何が起きるのかが実測で分かります。
在庫1,000本のボールペンを、2つのプロセスが同時に500回ずつ1本減らします。正しければ最後は0本です。CSV では「ファイルを読む→1引く→ファイルを書き直す」、SQLite では UPDATE stock SET qty = qty - 1 を使いました。
| 回 | CSV の最後の在庫 | CSV で書きかけを読んだ回数 | SQLite の最後の在庫 |
|---|---|---|---|
| 1回目 | 216本 | 839回 | 0本 |
| 2回目 | 248本 | 209回 | 0本 |
| 3回目 | 104本 | 920回 | 0本 |
CSV では1,000回減らしたはずが、毎回100〜250本ほどの「減らした記録」が消えました。2つのプロセスが同じ値を読んで、それぞれ1引いて書き戻すと、2回の減算が1回分になります。さらに、相手が書き直している最中のファイル(空や途中まで)を読む場面が数百回ありました。最初の版のスクリプトはこれを想定しておらず、IndexError('list index out of range') で片方のプロセスが止まりました。SQLite は3回とも0本で、かかった時間も CSV と同じ 0.04〜0.06秒でした。
1同時更新で数が狂う
CSV は「読んでから書く」の間に割り込まれる。DBMS はロックで1つずつ処理した。
2書きかけが見える
CSV は書き直しの途中を他の人が読める。DBMS は確定した版だけを見せた。
3探すのが遅い
30万行から1件:CSV を先頭から読むと 62.0ms、SQLite+インデックスは 0.012ms。
大きさは、30万行の CSV が 11.2MB、同じデータの SQLite がインデックス込みで 20.6MB でした。DBMS は索引や管理用の情報を持つぶん容量は増えます。1人で読み書きし、他のツールに渡すことが目的なら、CSV のほうが向いている場面もあります。
DBMSの種類とRDBMSとの違い(RDBMS・NoSQL・NewSQL)
この節では、RDBMS とは何か、DBMS との関係、NoSQL・NewSQL など他の種類との違いが分かります。
RDBMS(Relational Database Management System、リレーショナルデータベース管理システム)は、データを「表(行と列)」で持ち、表どうしを共通の値で結び付けて扱う DBMS です。操作には SQL を使います。DBMS は総称で、RDBMS はその一種という関係です。この記事で動かした PostgreSQL と SQLite は、どちらも RDBMS です。
一部の解説では「DBMS はファイルでデータを持ち、1人で使う。RDBMS は表で持ち、複数人で使う」のように対比されます。これは、表の形を持たない以前の DBMS と RDBMS を比べた説明です。今「DBMS」と言うときは、RDBMS も NoSQL も含む総称として使われるのが普通です。
| 種類 | データの持ち方 | 主な製品・例 | 向く用途 |
|---|---|---|---|
| RDBMS(リレーショナル) | 表(行と列)と、表どうしの関係 | PostgreSQL・MySQL・Oracle Database・SQL Server・SQLite | 業務システム・会員・注文・会計 |
| NoSQL:キーバリュー | キーと値の組 | Redis・Amazon DynamoDB | キャッシュ・セッション |
| NoSQL:ドキュメント | JSON のような文書 | MongoDB・Couchbase | 項目が変わりやすいデータ |
| NoSQL:列指向(ワイドカラム) | 行ごとに列の組が違ってよい表 | Apache Cassandra | 大量の書き込み・時系列 |
| NoSQL:グラフ | 点(ノード)と線(関係) | Neo4j | つながりをたどる検索 |
| NewSQL(分散SQL) | 表と SQL のまま、複数のサーバーに分けて持つ | Google Cloud Spanner・CockroachDB・TiDB | RDBMS の形で大きく広げたい |
| 階層型・ネットワーク型 | 木構造・網の目の構造 | IBM IMS(階層型)・IDMS(ネットワーク型) | RDBMS 以前から続く基幹系 |
NoSQL は「Not only SQL」の略とされ、表の形にこだわらずに、速さや広げやすさを優先した DBMS の総称です。多くの NoSQL 製品にも、同時実行制御・障害回復・認証といった DBMS の役割があります。どこまで厳密にトランザクションを守るかは製品ごとに違うため、公式ドキュメントで確かめて選びます。
DBMS と RDBMS の関係
「果物」と「りんご」の関係と同じ
主要なDBMS製品の比較(Oracle・MySQL・PostgreSQL・SQL Server・SQLite)
この節では、よく名前を聞く5つの DBMS 製品の違いが、ライセンス・形・版の表で分かります。
| 製品 | ライセンス・費用 | 形 | 2026年10月29日時点の版 |
|---|---|---|---|
| Oracle Database | 商用。無料版あり(CPU 2スレッド・メモリ 2GB・データ 12GBまで) | サーバー型 | 公式サイトでは「Oracle AI Database 26ai」 |
| MySQL | GPLv2 と商用のデュアルライセンス | サーバー型 | LTS(8.4 系など)と Innovation の2系統 |
| PostgreSQL | PostgreSQL License(BSD・MIT に近い緩いライセンス)。無料 | サーバー型 | 18.6(14〜18 がサポート中) |
| SQL Server | 商用。Express は無料(データベース 50GB まで等の上限あり) | サーバー型 | SQL Server 2025(17.x) |
| SQLite | パブリックドメイン。無料 | 組み込み型(アプリの中で動く) | 3.54.1(2026年10月16日) |
- Oracle Database:大企業の基幹システムで長く使われてきた商用の RDBMS。無料版「Oracle AI Database 26ai Free」は、公式サイトによると CPU 2スレッド・データベースのメモリ 2GB・利用者データ 12GB までです。
- MySQL:Web サービスで広く使われる RDBMS。公式サイトによると、サーバーとクライアントライブラリは GPL バージョン2 で、組み込んで配布する場合などのために商用ライセンスもあります。リリースは、長く同じ動きを保つ LTS と、新機能が入る Innovation の2系統です(MySQL 8.4 リファレンスマニュアル)。
- PostgreSQL:機能が多く、無料で使える RDBMS。公式のバージョン表では、2026年10月29日時点で 18.6・17.11・16.15・15.19・14.24 がサポート中で、14 は 2026年11月12日に最後のリリースの予定です。この記事は 16.15 で確かめました。
- SQL Server:Microsoft の RDBMS。Microsoft Learn によると、SQL Server 2025 の Express エディションは「入門用の無料のデータベース」で、データベースの最大サイズ 50GB、バッファープールのメモリ 1,410MB、計算能力は「1ソケットか4コアの少ない方」までです。Developer エディションは開発・テスト用で、本番には使えません。
- SQLite:サーバーを持たず、アプリに組み込んで1つのファイルで動く RDBMS。スマートフォンのアプリやブラウザの内部でも使われています。公式サイトは「SQLite はクライアント・サーバー型のデータベースと競合しない。競合するのは fopen()(ファイルを開く関数)だ」と説明しています。使い方は関連記事「SQLiteの使い方|コマンド早見表とPython連携を実行例で解説」で扱っています。
料金・上限・版は変わることがあります。採用する前に、各社の公式ページで最新の情報を確かめます。
DBMSの仕組み:構成要素・SQLの種類・3層スキーマ
この節では、DBMS がどんな部品と言葉でできているのかと、試験でよく問われる用語が分かります。
DBMS を使うときに出てくる要素
| 要素 | 中身 | この記事での例 |
|---|---|---|
| ソフトウェア | DBMS 本体(サーバーのプロセス、またはライブラリ) | postgres のプロセス、Python の sqlite3 |
| データ | 利用者のデータと、表の定義などのメタデータ | accounts の行、\dp で見た権限 |
| 記録 | WAL・ジャーナル・サーバーログ | pg_wal、crash.db-wal、j.db-journal |
| 問い合わせ言語 | SQL(NoSQL では各製品の API や言語) | SELECT・UPDATE・GRANT |
| 利用者 | アプリ、開発者、DBA(データベース管理者) | postgres(管理者)と reader |
| ハードウェア | ディスク・メモリ・CPU | 2 CPU・メモリ 8GB の Linux |
SQLの4つの分類
| 分類 | 役割 | 主な命令 |
|---|---|---|
| DDL(データ定義言語) | 表や索引の形を決める | CREATE・ALTER・DROP |
| DML(データ操作言語) | データを読み書きする | SELECT・INSERT・UPDATE・DELETE |
| DCL(データ制御言語) | 権限を与える・取り上げる | GRANT・REVOKE |
| TCL(トランザクション制御言語) | トランザクションを確定・取り消し | BEGIN・COMMIT・ROLLBACK |
3層スキーマ(外部・概念・内部)
DBMS は、データの「見せ方」と「しまい方」を分けて考えます。これを3層スキーマと呼びます。
- 外部スキーマ:利用者やアプリから見える形。ビュー(VIEW)など。
- 概念スキーマ:表・列・関係など、データ全体の論理的な形。CREATE TABLE で決める部分。
- 内部スキーマ:ディスク上のしまい方。ファイル・ページ・インデックス。
インデックスを作っても SQL を変えずに速くなったのは、内部スキーマを変えても、その上の層に影響しないように分けてあるからです(物理的データ独立性)。
DBMSでよくあるエラー・つまずき(原文つき)
この節では、この記事の実験で実際に出たエラーの原文と、意味と直し方が分かります。
| エラー原文 | DBMS | 意味 | 直し方 |
|---|---|---|---|
database is locked |
SQLite | 他の接続が書き込み中で、待ち時間の上限を超えた | トランザクションを短くする。timeout を延ばす。WAL モードにする |
canceling statement due to lock timeout |
PostgreSQL | lock_timeout の間にロックが取れなかった | 止めている接続を pg_blocking_pids で探す。確定し忘れを直す |
deadlock detected |
PostgreSQL | 2つの処理がお互いを待った。片方が取り消された | 更新する行の順番をそろえる。取り消された側をやり直す |
current transaction is aborted, commands ignored until end of transaction block |
PostgreSQL | トランザクションの中で一度エラーが出た | ROLLBACK してからやり直す |
violates check constraint |
PostgreSQL | CHECK 制約に合わない値を入れようとした | 入れる値か、処理の順番を見直す |
permission denied for table accounts |
PostgreSQL | その表に対する権限が無い | 必要な権限だけを GRANT する。接続している利用者を確かめる |
permission denied for schema public |
PostgreSQL | public スキーマに表を作る権限が無い(15 以降の既定) | アプリ用のスキーマを作り、CREATE 権限を与える |
password authentication failed for user "reader" |
PostgreSQL | パスワードが違う、または利用者名が違う | 接続先・利用者名・パスワードを確かめる。pg_hba.conf の方式も見る |
attempt to write a readonly database |
SQLite | 読み取り専用で開いた、またはファイルに書き込み権限が無い | 開き方(mode=ro)とファイル・フォルダーの権限を見る |
near "GRANT": syntax error |
SQLite | SQLite には GRANT が無い | OS のファイル権限で分ける。必要ならサーバー型を選ぶ |
database "nosuchdb" does not exist |
PostgreSQL | 接続先のデータベース名が無い | \l で一覧を見る。createdb で作る |
ロック待ちで画面が止まったように見えたときは、次の順で調べると原因に早くたどり着けます。
待っている処理を見つける
PostgreSQL なら pg_stat_activity で wait_event_type が Lock の行を探す。この記事では UPDATE が transactionid を待っていた。
止めている側を特定する
pg_blocking_pids(pid) で、どの接続が止めているかが分かる。state が idle in transaction なら、確定し忘れの可能性が高い。
止めている側のトランザクションを終わらせる
まずはその処理を COMMIT か ROLLBACK で終わらせる。終わらせられないときに限り、管理者が pg_cancel_backend・pg_terminate_backend を使う。
再発を防ぐ
トランザクションの中で外部 API の呼び出しや人の入力待ちをしない。lock_timeout や statement_timeout で待ちの上限を決める。
どのDBMSを選ぶか(判断表)
この節では、用途から DBMS の種類と製品を選ぶ目安が分かります。
| こんなとき | 選ぶもの | 理由(この記事で見たこと) |
|---|---|---|
| スマホ・デスクトップのアプリの中にデータを持つ | SQLite | サーバー不要で1ファイル。強制終了しても確定分は戻った |
| 学習・試作・小さな社内ツール(書く人が少ない) | SQLite か PostgreSQL | SQLite は同時に書けるのが1つだけ。書く人が増えるなら PostgreSQL |
| Web サービス・業務システム(同時に多くの人が書く) | PostgreSQL・MySQL | 行単位のロックで、別の行の更新は待たなかった |
| 利用者ごとに見せる範囲を分けたい | サーバー型の RDBMS | GRANT で表ごとに権限を分けられた。SQLite には GRANT が無い |
| Microsoft 製品・Windows Server と組み合わせる | SQL Server | Express は無料(50GB 等の上限)。上位版へ移れる |
| 既に Oracle Database で動いている基幹システム | Oracle Database | 移行には SQL の書き換えや検証の手間がかかる |
| キャッシュ・大量のログ・つながりの検索 | NoSQL(Redis・Cassandra・Neo4j など) | 表の形より速さや形の自由さを優先する |
| Excel・CSV で回していて、複数人が更新し始めた | RDBMS へ移す | CSV は同時更新で100〜250本分の記録が消えた |
迷ったときは、次の4つを確かめると絞り込めます。
手元で DBMS の働きを確かめたいときは、この記事と同じ順で試すと、6つの役割を1時間ほどで一通り見られます。
- 1SQLite で表を作り、ROLLBACK を試すPython に付いている sqlite3 だけでできる
- 22つの接続で同時に書いて database is locked を見るtimeout の値を変えて待ち方を確かめる
- 3PostgreSQL を手元で起動し、行ロックと MVCC を見るpg_stat_activity と pg_blocking_pids
- 4EXPLAIN でインデックスの有無を比べるSQL を変えずに計画が変わることを見る
- 5読むだけの利用者を作り、権限エラーを見るGRANT SELECT だけを与える
よくある質問
Q. DBMSとは何ですか? A. データベース管理システム(Database Management System)の略で、データベースを作り、データの追加・検索・更新・削除を受け付け、同時実行制御・トランザクション・障害回復・権限によってデータを安全に保つソフトウェアです。
Q. データベースとDBMSの違いは何ですか? A. データベースは「整理して保存されたデータの集まり」、DBMS は「それを管理するソフトウェア」です。会話では同じ意味で使われることも多く、文脈で判断します。
Q. RDBMSとは何ですか?DBMSとの違いは? A. RDBMS は、データを表(行と列)で持ち、SQL で操作する DBMS です。DBMS は総称で、RDBMS はその一種です。PostgreSQL・MySQL・Oracle Database・SQL Server・SQLite は RDBMS です。
Q. DBMSの主な機能はいくつありますか? A. 資料によって数え方が違いますが、データ定義・データ操作・同時実行制御・トランザクション管理・障害回復・機密保護(権限)の6つにまとめると全体を押さえられます。
Q. Excel はDBMSですか? A. Excel は表計算ソフトで、DBMS ではありません。複数人が同時に同じデータを更新したときの順番待ちや、途中で失敗したときの取り消しを、DBMS のように保証する仕組みは持っていません。この記事の CSV の実験では、同時更新で100〜250本分の記録が消えました。
Q. SQLite は本番で使えますか? A. 用途によります。アプリや機器の中にデータを持つ使い方には広く使われています。一方、SQLite の公式ドキュメントは、多くのコンピューターからネットワーク越しに同時に直接書き込む使い方は避けるよう勧めています。書き込みは同時に1つだけです。
Q. NoSQL はDBMSではないのですか? A. NoSQL も DBMS の一種です。表の形(リレーショナルモデル)を使わない DBMS をまとめて NoSQL と呼びます。トランザクションをどこまで守るかは製品ごとに違います。
Q. DBMSが止まったら、データは消えますか? A. 確定(COMMIT)したデータは、WAL やジャーナルによって再起動のときに戻ります。この記事では、PostgreSQL も SQLite も、強制停止のあと確定済みの1,000行が残り、確定していない500行は消えました。ディスクそのものが壊れた場合に備えて、別にバックアップが要ります。
Q. 無料で使えるDBMSはどれですか? A. PostgreSQL・MySQL(GPL 版)・SQLite は無料で使えます。SQL Server には Express、Oracle Database には容量などに上限のある無料版があります(2026年10月29日時点の各社公式サイト)。
Q. DBMSを学ぶには何から始めればよいですか? A. SQLite で表を作り SQL の基本を覚え、次に PostgreSQL か MySQL を手元で動かして、トランザクション・ロック・インデックス・権限を試す順が分かりやすいです。この記事の「どのDBMSを選ぶか」の節の5段階が、その順番です。
まとめ
この節では、記事の要点を5つにまとめます。
- DBMS はデータベースを管理するソフトウェアで、定義・操作・同時実行制御・トランザクション・障害回復・権限の6つを受け持つ。
- RDBMS は表で扱う DBMS。DBMS は総称で、NoSQL・NewSQL も含む。
- 同時に更新してもロックで順番が決まり、PostgreSQL では5.04秒待ったあと正しい700円になった。SQLite は書き込みが同時に1つだけ。
- ROLLBACK と WAL で「半端な状態」が残らない。強制停止のあとも確定済み1,000行だけが残った。
- CSV では同時更新で記録が消え、インデックスのある DBMS は30万行から1件を0.01ms台で探せた。
参考・出典
確認日はいずれも 2026年10月29日です。
- PostgreSQL「Versioning Policy」:https://www.postgresql.org/support/versioning/
- PostgreSQL「License」:https://www.postgresql.org/about/licence/
- PostgreSQL 16 Documentation「pg_ctl」:https://www.postgresql.org/docs/16/app-pg-ctl.html
- PostgreSQL 16 Documentation「Write-Ahead Logging (WAL)」:https://www.postgresql.org/docs/16/wal-intro.html
- PostgreSQL 16 Documentation「Explicit Locking」:https://www.postgresql.org/docs/16/explicit-locking.html
- PostgreSQL 16 Documentation「Privileges」:https://www.postgresql.org/docs/16/ddl-priv.html
- SQLite「SQLite Home Page」(最新版とライセンス):https://www.sqlite.org/index.html
- SQLite「Appropriate Uses For SQLite」:https://www.sqlite.org/whentouse.html
- SQLite「Write-Ahead Logging」:https://www.sqlite.org/wal.html
- SQLite「Atomic Commit In SQLite」:https://www.sqlite.org/atomiccommit.html
- MySQL 8.4 Reference Manual「MySQL Releases: Innovation and LTS」:https://dev.mysql.com/doc/refman/8.4/en/mysql-releases.html
- MySQL「Licensing Information」:https://www.mysql.com/about/legal/licensing/oem/
- Microsoft Learn「Editions and supported features of SQL Server 2025」:https://learn.microsoft.com/en-us/sql/sql-server/editions-and-components-of-sql-server-2025
- Oracle「Oracle AI Database Free」:https://www.oracle.com/database/free/
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「DBMSとは|RDBMSとの違い・役割をSQLiteとPostgreSQLで実演」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。