PostgreSQLとMySQLの違いを自前運用の視点で比較する|アーキテクチャとレプリケーション方式・向き不向きの見極め

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtipsデーターベース管理 > PostgreSQLとMySQLの違いを自前運用の視点で比較する|アーキテクチャとレプリケーション方式・向き不向きの見極め
「MySQLとPostgreSQL、うちのシステムにはどっちを入れればいいんですか?」
Linux管理者ならば一度は聞かれたことがあるはずだ。どちらも長年の実績を持つオープンソースRDBMSだが、アーキテクチャもレプリケーションの仕組みも根本から異なる。

「とりあえずMySQL」で問題ないケースは確かにある。だが、複雑な集計クエリや地理情報、JSONB型が要件に入った瞬間に、後から移行する羽目になる。この記事では、Linuxサーバーへのセルフホスト運用に絞り、選定判断に直結するアーキテクチャの差・レプリケーション方式の違い・向き不向きを実務目線で比較する。

この記事のポイント

・PostgreSQLはMVCC+プロセスモデル、MySQLはスレッドモデルで別物
・レプリケーションはWALストリーミング(PG)とbinlog/GTID(MySQL)で仕組みが異なる
・複雑な集計・JSONB・地理情報ならPostgreSQL、高速CRUD・大量接続はMySQL
・VACUUM管理と移行コストがセルフホスト選定で見落とされやすい注意点


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

なぜアーキテクチャの違いが自前運用の判断を左右するのか

表面上はどちらも「SQLを話すRDBMS」として同じに見える。しかし内部構造が違うと、自前運用での挙動—トランザクション競合時の振る舞い、レプリカの遅延、チューニングパラメータの意味—が変わる。選定ミスに気づくのは、大抵は本番に入れた後だ。

最初にアーキテクチャの核心を押さえておく。後のレプリケーション設計やトラブル対処の判断が、ここを理解しているかどうかで大きく変わる。

ストレージエンジンとMVCCの仕組みの違い

1. PostgreSQLのプロセスモデルとMVCC

PostgreSQLはクライアント接続ごとに独立したバックエンドプロセスをfork()で生成する。プロセスモデルのため、コネクション数が増えるとOSレベルのプロセス管理コストが増える。100接続を超える環境では、pg_bouncerなどのコネクションプーラーが実務では必須に近い。

トランザクション制御にはMVCC(Multi-Version Concurrency Control:マルチバージョン同時実行制御)を採用している。行を更新・削除しても旧バージョンをヒープ上に物理的に残し、後でVACUUMで回収する設計だ。このため「読み取りが書き込みをブロックしない」という特性が強く、SELECT多めのワークロードに向く。ただし更新・削除が頻繁なテーブルはVACUUMが追いつかないとテーブルが肥大化する点に注意が必要だ。

データ型の豊富さもPostgreSQLの特徴だ。配列型・JSONB型・範囲型・地理情報型(PostGISで拡張)など、標準のRDBMSとは異色の幅広さを持つ。

2. MySQLのスレッドモデルとInnoDB

MySQLはクライアント接続をスレッドで処理する。プロセスよりコンテキストスイッチが軽いため、同時接続数が増えてもPostgreSQLほどメモリを消費しない。PHP + MySQLという組み合わせがWebアプリで長年デファクトになってきた背景はここにある。

ストレージエンジンはInnoDB(デフォルト)を使う。行レベルロックと独自MVCCを持つが、PostgreSQLとは内部実装が異なる。MySQLのMVCCはUndoログを使って旧バージョンを参照する設計で、PostgreSQLのようなVACUUM処理が不要な代わりに、Undoログの肥大化(ibdata1の膨張)には注意が必要だ。

3. サービス起動とポートの確認

どちらを選んでも、自前運用の第一歩はサービスの起動確認だ。MySQLはデフォルトでTCP 3306番、PostgreSQLは5432番でリッスンする。

# MySQL が起動してリッスンしているかを確認 [root@db-server ~]# ss -tlnp | grep 3306 LISTEN 0 151 0.0.0.0:3306 0.0.0.0:* users:(("mysqld",pid=2345,fd=21)) # PostgreSQL の場合 [root@db-server ~]# ss -tlnp | grep 5432 LISTEN 0 244 127.0.0.1:5432 0.0.0.0:* users:(("postgres",pid=1891,fd=5))

MySQLはデフォルトで0.0.0.0(全インターフェース)、PostgreSQLはlocalhost(127.0.0.1)でリッスンする点が異なる。リモート接続を許可するにはPostgreSQLはpostgresql.confの`listen_addresses`を変更し、さらにpg_hba.confで接続元を明示的に許可する必要がある。ポートが開いているかの確認方法はLinux ポート確認の全コマンドも参照してほしい。

レプリケーション方式を比較する

自前運用で可用性を高めるには、レプリケーションの設定が避けられない。両者の仕組みと設定の手間を具体的に比較する。

1. PostgreSQLのWALストリーミングレプリケーション

PostgreSQLのレプリケーションはWAL(Write-Ahead Log:先行書き込みログ)ファイルをスタンバイへ転送する方式だ。プライマリのpostgresql.confとpg_hba.conf、スタンバイ側のpostgresql.conf(PostgreSQL 12以降はstandby.signalファイルを配置)を設定する。

プライマリ側の最低限の設定例(/etc/postgresql/16/main/postgresql.conf):

wal_level = replica max_wal_senders = 5 wal_keep_size = 256MB

スタンバイ側はpg_basebackupでベースバックアップを取得してから起動する。レプリケーション状態の確認はプライマリ上で以下のSQLを実行する:

[root@db-primary ~]# psql -U postgres -c \ "SELECT pid, usename, client_addr, state, sent_lsn, replay_lsn FROM pg_stat_replication;" pid | usename | client_addr | state | sent_lsn | replay_lsn ------+----------+---------------+-----------+-----------+------------ 3421 | repl_usr | 192.168.1.101 | streaming | 0/4A0B210 | 0/4A0B210 (1 row)

`state = streaming`、`sent_lsn`と`replay_lsn`が一致していれば遅延なしで動いている。フェイルオーバーの自動化にはPatroniやRepmgrが必要で、標準機能だけでは手動昇格になる点を覚えておく。

2. MySQLのGTIDレプリケーション

MySQLのレプリケーションはバイナリログ(binlog)を転送する方式で、GTID(Global Transaction ID:グローバルトランザクションID)を使った自動位置管理が現在の主流だ。

ソース側の/etc/my.cnfへの追記例:

[mysqld] server-id = 1 log_bin = mysql-bin gtid_mode = ON enforce_gtid_consistency = ON

レプリカ側でのレプリケーション開始コマンド:

mysql> CHANGE REPLICATION SOURCE TO -> SOURCE_HOST='192.168.1.100', -> SOURCE_USER='repl_usr', -> SOURCE_PASSWORD='xxxxxxxx', -> SOURCE_AUTO_POSITION=1; mysql> START REPLICA;

状態確認:

mysql> SHOW REPLICA STATUS\G *************************** 1. row *************************** Replica_IO_Running: Yes Replica_SQL_Running: Yes Source_Host: 192.168.1.100 Seconds_Behind_Source: 0

3. 設定の難易度を実感として比較する

PostgreSQLのレプリケーションは設定項目が少なくシンプルだが、pg_basebackupでベースバックアップを取ってからスタンバイを起動する手順が初見では分かりにくい。フェイルオーバーを自動化したい場合は別途ツールの習得が必要だ。

MySQLのGTIDレプリケーションは設定項目が多いものの、公式ドキュメントとコミュニティの情報が豊富でトラブル時に情報を探しやすい。MySQL RouterやOrchestatorなどのHA構成ツールとの組み合わせ事例も多く、エコシステムが充実している。

向き不向きのケース別判断

PostgreSQLが向いているケース

・複雑なJOINや窓関数(ウィンドウ関数)を多用する分析系クエリ
・JSONB型で半構造化データをRDB内で柔軟に扱いたい
・PostGISで緯度経度・ポリゴンなどの地理情報を処理したい
・外部キー制約やCHECK制約・部分インデックス・関数インデックスを厳密に使いたい
・ストアドプロシージャをPL/pgSQL以外(Python・Perl・C)で書きたい

MySQLが向いているケース

・PHP・Laravel・WordPressなど既存スタックでの実績がある
・同時接続数が数百を超えるWebアプリでコネクションプールを極力減らしたい
・読み取りスケールのためにレプリカを複数台並べるシンプルな構成
・チーム内のMySQL経験者が多く、移行コストを最小化したい
・シンプルなCRUDが主体でORMを薄く保ちたい場合

どちらを選んでも、Linuxサーバー上でのレプリケーション設定・バックアップ運用・チューニングを体系的に習得することが長期的な安定運用の鍵になる。実機を触りながら習得したい方はLinux実践ハンズオンセミナーも選択肢に入れてほしい。

インストールと初期設定の違い

1. Rocky Linux / RHEL系での導入

MySQLは公式コミュニティリポジトリをDNFで追加してインストールする。初回起動時に一時パスワードが自動生成され、mysql_secure_installationで変更する流れだ。

# MySQL Community リポジトリ追加(Rocky Linux 9 / RHEL 9) [root@db-server ~]# dnf install https://dev.mysql.com/get/mysql84-community-release-el9-1.noarch.rpm [root@db-server ~]# dnf install mysql-community-server [root@db-server ~]# systemctl enable --now mysqld [root@db-server ~]# grep 'temporary password' /var/log/mysqld.log 2026-09-09T09:12:03.421044Z 6 [Note] [MY-010454] [Server] A temporary password is generated \ for root@localhost: bXrDk7pf;mCL [root@db-server ~]# mysql_secure_installation

PostgreSQLはPGDGリポジトリを使う。バージョン管理が明確で、複数バージョンを同一サーバーに共存させやすい点が特徴だ。

# PGDGリポジトリ追加(Rocky Linux 9 / RHEL 9) [root@db-server ~]# dnf install https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm [root@db-server ~]# dnf -qy module disable postgresql [root@db-server ~]# dnf install postgresql16-server [root@db-server ~]# /usr/pgsql-16/bin/postgresql-16-setup initdb [root@db-server ~]# systemctl enable --now postgresql-16

PostgreSQLはデフォルトでローカル接続のみ許可され、OSの`postgres`ユーザーでpsqlにログインするところから始まる。`/var/lib/pgsql/16/data/pg_hba.conf`の認証設定が初見では戸惑う箇所だ。スクラム認証(scram-sha-256)がデフォルトになっているため、接続できない場合はまずpg_hba.confを確認する。

2. Ubuntu / Debian系での導入

Ubuntuの場合、MySQLは`apt install mysql-server`一発で入り、初期設定もシンプルだ。PostgreSQLも`apt install postgresql-16`でインストールできるが、やはり`/etc/postgresql/16/main/pg_hba.conf`の設定が必要になる。Ubuntu環境ではpostgresパッケージが複数バージョンを管理する`pg_lsclusters`コマンドを使ってクラスター状態を確認できる。

[root@db-server ~]# pg_lsclusters Ver Cluster Port Status Owner Data directory Log file 16 main 5432 online postgres /var/lib/postgresql/16/main /var/log/postgresql/...

バックアップと復旧の手順の違い

論理バックアップは専用ツールを使う。MySQLはmysqldumpが定番で、行単位のSQL形式で出力する。PostgreSQLはpg_dump(1データベース)またはpg_dumpall(全データベース)を使う。
操作 MySQL PostgreSQL
論理バックアップ(全DB) mysqldump --all-databases -u root -p pg_dumpall -U postgres
論理バックアップ(1DB) mysqldump -u root -p dbname pg_dump -U postgres dbname
リストア mysql -u root -p dbname < dump.sql psql -U postgres dbname < dump.sql
物理バックアップ mysqlbackup / Percona XtraBackup pg_basebackup -D /backup -Fp -Xs -P
物理バックアップはPostgreSQLのpg_basebackupがシンプルで使いやすく、WALとセットでポイントインタイムリカバリ(PITR)にも活用できる。Percona XtraBackupは高機能だが設定が複雑で、ホットバックアップには習熟が必要だ。

運用中に差が出るトラブルのパターン

「MySQLで動いているからそのまま移行しよう」のワナ

MySQLからPostgreSQLへの移行は、SQL方言の差が想定以上に大きい。AUTO_INCREMENT(MySQL)とSERIAL/IDENTITY(PostgreSQL)の違い、GROUP BYの厳密さの差、文字列の大文字小文字比較の挙動など、数百本のSQLを書き直すコストが発生することがある。既存MySQLシステムの移行を検討するなら、事前にpgloaderなどで差分を洗い出すことを強く勧める。

VACUUMを放置すると起きること

PostgreSQLでUPDATE/DELETEが多いテーブルのVACUUMを放置すると、テーブルが肥大化してディスクを圧迫する。さらに32億トランザクションを超えると「XID周回(Transaction ID Wraparound)」と呼ばれる深刻な問題が起きる。autovacuumが正常に動いているかは定期的に確認する習慣をつけておく。

# autovacuum の直近の動作ログを確認 [root@db-server ~]# grep "automatic vacuum" /var/log/postgresql/postgresql-2026-09-09_000000.log | tail -5 2026-09-09 08:15:02 JST [3821]: LOG: automatic vacuum of table "mydb.public.orders": index scans: 0 pages: 0 removed, 1024 remain, 8 outside target tuples: 5142 removed, 98756 remain, 0 are dead but not yet removable avg read rate: 2.1 MB/s, avg write rate: 0.4 MB/s

MySQLのmax_connectionsとコネクション枯渇

MySQLのデフォルトmax_connectionsは151(環境によって異なる)と低い。Webアプリのデプロイ時にコネクションプールの設定を見直さないまま本番に入れると、高負荷時に`Too many connections`エラーで詰まる。現在の接続数と上限はSHOW STATUSで確認できる。

mysql> SHOW STATUS LIKE 'Threads_connected'; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | Threads_connected | 148 | +-------------------+-------+ mysql> SHOW VARIABLES LIKE 'max_connections'; +-----------------+-------+ | Variable_name | Value | +-----------------+-------+ | max_connections | 151 | +-----------------+-------+

max_connectionsに迫っていたら、/etc/my.cnfで値を引き上げるとともにアプリ側のコネクションプール設定を見直す。

本記事のまとめ

比較軸 PostgreSQL MySQL
プロセスモデル コネクションごとにプロセスをfork(重い) スレッドモデル(コネクション増加に強い)
MVCC実装 旧バージョン行をヒープに保持・VACUUMで回収 Undoログで旧バージョンを参照
レプリケーション WALストリーミング(設定が少なくシンプル) binlog/GTID転送(情報豊富・ツール充実)
データ型 配列・JSONB・範囲型・地理情報など豊富 標準的なSQL型が中心
バックアップ pg_dump / pg_basebackup(PITR対応) mysqldump / Percona XtraBackup
向いているワークロード 複雑な集計・JSONB・地理情報・厳密な制約 高速CRUD・大量接続・既存PHPスタック
移行コスト SQL方言の差が大きく既存資産の移行は重い WordPress等との組み合わせ事例が豊富
注意点 VACUUMとXID周回・pg_hba.confの設定 max_connections・Undoログ肥大化
「まずMySQL」という判断は間違いではない。既存チームの習熟度やエコシステムを活かせる場面は多い。一方、複雑な集計・地理情報・JSONB活用が要件に入るなら、最初からPostgreSQLを選ぶほうが後の設計変更コストを減らせる。どちらを選んでも、自前運用ではレプリケーション設定とバックアップ手順を立てられるかどうかが本質的な判断基準になる。

DBエンジンを選んだ後に差がつくのは、Linuxサーバー運用の「型」を知っているかどうか

PostgreSQLでもMySQLでも、DBエンジンの選定はスタートラインです。本番環境を安定して運用し続けるには、サービス設定・レプリケーション・バックアップの手順を体系的に身につけることが不可欠です。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。