MySQLとは何か — クライアント/サーバー型データベースと接続のコスト
この章の目次開く
MySQLは、世界でもっとも広く使われているリレーショナルデータベース管理システム(RDBMS)のひとつです。 WordPress、多くのWebサービス、社内の業務システムなど、動いている場所は数え切れません。
この本では、SELECT や JOIN といったSQLの文法そのものは扱いません。
そこは SQLとデータベースの基礎 で学んだ内容がそのまま通用します。
この本が扱うのは、MySQLならではの部分です。接続の仕組み、文字コード、InnoDB、そしてアプリケーションからの使い方。
学習者SQLが書けるようになったら、MySQLのことも分かったことになりませんか?
なりません。SQLが書けることと、MySQLを運用できることは別の技能です。
たとえば「アプリが突然 Too many connections で落ちる」「絵文字を保存したらエラーになる」「本番だけクエリが遅い」——これらはSQLの文法を完璧に覚えても解決しません。
この章では、その土台になるMySQLの構造を押さえます。
MySQLはサーバーである
MySQLを理解する上で最初に押さえるべきことは、これです。
MySQLは「ファイル」ではなく「常時起動しているサーバープログラム」であり、アプリケーションはネットワーク越しにそこへ接続して使います。同じデータベースでも、SQLite は考え方がまったく違います。SQLiteはファイルを直接開くだけで、サーバープロセスが存在しません。
| SQLite | MySQL | |
|---|---|---|
| 実体 | 1つのファイル | 常駐するサーバープロセス |
| 使い方 | ファイルを開く | サーバーに接続する |
| 別マシンから使う | 基本的に不可 | 可能(ネットワーク越し) |
| 同時書き込み | 1つに制限される | 複数同時に可能 |
| 起動 | 不要 | 必要(mysqld) |
この違いが、以降のすべての話につながります。接続という概念があるのはMySQL側だけです。

「接続する」とき何が起きているか
アプリケーションのコードでは、接続はたった1行に見えます。
const conn = await mysql.createConnection({ host, user, password, database });しかしこの1行の裏側では、いくつもの手順が順番に実行されています。
- TCP接続を開く — ネットワークの3ウェイハンドシェイク
- サーバーが初期パケットを返す — バージョンや認証方式の提示
- クライアントが認証情報を送る — ユーザー名とパスワード
- サーバーが認証して確立 — ここでようやくクエリが投げられる状態になる
つまり、クエリを1本投げる前に、往復が何度も発生しているということです。 ローカルなら数ミリ秒ですが、別マシンやクラウドのマネージドDBが相手なら、この確立だけで数十ミリ秒かかることもあります。
先生ここが後で効いてくるよ。リクエストのたびに接続を作り直すと、この手順を毎回やり直すことになる。
接続1本につきスレッド1本
MySQLのもうひとつ重要な性質が、接続の扱い方です。 実際に動いているMySQL 8.4で設定を確認すると、次のようになっています。
mysql -e "SHOW VARIABLES LIKE 'thread_handling'"+-----------------+---------------------------+
| Variable_name | Value |
+-----------------+---------------------------+
| thread_handling | one-thread-per-connection |
+-----------------+---------------------------+
名前がそのまま答えになっています。one-thread-per-connection — 接続1本ごとに、サーバー側でスレッドが1本割り当てられるという意味です。
だからこそ、MySQLには接続数の上限があります。
mysql -e "SHOW VARIABLES LIKE 'max_connections'"+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| max_connections | 151 |
+-----------------+-------+
デフォルトは 151。この数を超えて接続しようとすると、クライアント側は次のエラーを受け取ります。
ER_CON_COUNT_ERROR: Too many connections
有限の資源としての接続
ここまでを整理すると、MySQLの接続には2つの性質があります。
| 性質 | 何が起きるか |
|---|---|
| 確立にコストがかかる | 毎回作り直すとレイテンシが積み上がる |
| 本数に上限がある | 作りすぎると Too many connections で落ちる |
この2つは、方向が逆の制約です。「毎回作り直すと遅い」からといって開きっぱなしにすれば上限に当たり、「上限が怖い」からといって毎回閉じれば確立コストを払い続ける。
学習者じゃあ、どうすればいいんですか?どっちを選んでも困りそうですけど…
この板挟みを解くための仕組みが、コネクションプールです。 あらかじめ数本の接続を作って使い回し、使い終わったら閉じずに返却する。この本のNode.jsからMySQLに接続するで詳しく扱います。

バージョンの読み方
MySQLのバージョンには、知っておくと混乱しない事情があります。
| バージョン | 位置づけ |
|---|---|
| 5.7 | 長く使われた旧世代。公式サポートは終了済み |
| 8.0 | 現在も広く動いている世代 |
| 8.4 | LTS(長期サポート)版 |
自分が使っているバージョンは、次で確認できます。
mysql -e "SELECT VERSION()"+-----------+
| VERSION() |
+-----------+
| 8.4.0 |
+-----------+
よくあるハマりどころ
「DBが落ちた」と「接続できない」を混同する
Too many connections が出たとき、MySQLサーバー自体は元気に動いています。落ちているのは接続の受け入れだけです。
サーバーを再起動すると確かに直りますが、それは接続が全部切れてカウンタがリセットされただけで、原因は何も解決していません。しばらくすると再発します。
接続数をアプリ側だけで考える
max_connections はサーバー全体の上限です。アプリケーションが複数インスタンス動いていれば、その全部が同じ151を分け合います。
さらに、管理ツール、バッチ処理、監視エージェント、開発者の手元の mysql コマンドも接続を1本ずつ消費します。
ちゃんと使うためのポイント
- MySQLはファイルではなくサーバー。アプリはネットワーク越しに接続して使う
- 接続の確立にはTCP接続と認証の往復があり、コストがかかる
- 接続1本ごとにサーバー側でスレッドが1本使われる(
one-thread-per-connection) - 同時接続数には上限があり、デフォルトは151(
max_connections) - 「毎回作ると遅い」「作りすぎると落ちる」の板挟みを解くのがコネクションプール
接続を確認するでは、実際に mysql コマンドで接続し、いま何本の接続が開いているのかを自分の目で確認します。