1.

SQL ダンプ (.sql) とは|mysqldump / pg_dump によるバックアップとリストア

編集
この記事の要点
  • .sql は SQL(Structured Query Language)の文を平文で並べたテキストファイル。RDBMS のスキーマ定義・データ投入・バックアップに使われる
  • 代表的な生成元は mysqldump(MySQL / MariaDB)、pg_dump(PostgreSQL)、sqlite3 .dump。CREATE TABLE と INSERT が連続する典型構造
  • テキストなので diffgrep が効き、Git で差分管理できる。リストアは mysql < dump.sql のようにリダイレクトで取り込む
  • 巨大ダンプは --single-transaction(InnoDB)や -Fc(PostgreSQL カスタム形式)で整合性とサイズを両立させる
  • 文字コードに注意:SET NAMES utf8mb4\encoding UTF8 を冒頭に入れる。BOM 付き UTF-8 はパーサが嫌うので避ける
  • バージョン違いの DB 間移行で SQL モード や予約語衝突に当たることが多い。テスト環境で必ず再投入を試す
  • 世代管理は日次フル + バイナリログ(MySQL)/ WAL(PostgreSQL)で PITR を組むのが王道

概要

SQL ダンプ.sql)は、リレーショナルデータベースのスキーマとデータを SQL 文の羅列 として書き出した平文テキストファイルです。CREATE TABLECREATE INDEXINSERT INTO などが順番に並んでおり、そのまま別の DB に流し込めば再構築できる という直感的な形式が特徴です。バックアップ・別環境への複製・バージョン管理・データ提供(OSS のサンプル DB など)と幅広く使われます。

代表的な生成元は MySQL / MariaDB の mysqldump、PostgreSQL の pg_dump(プレーン SQL モード)、SQLite の .dump コマンドです。テキストなので head で中身を覗いたり grep で特定テーブル定義を取り出したりが可能で、Git で差分管理 もできます(ただし数百 MB を超えると現実的でなくなるため、その場合はバイナリ形式やオブジェクトストレージ管理に切り替えます)。

リストアは極めて単純で、MySQL なら mysql -u user -p dbname < dump.sql、PostgreSQL なら psql -d dbname -f dump.sql、SQLite なら sqlite3 new.db < dump.sql のように 標準入力やファイル指定で流し込む だけです。スキーマだけ・データだけ・特定テーブルだけといった分割ダンプもオプションで指定できます。

内部構造とよくある中身

典型的な mysqldump 出力の冒頭は次のような構造です(説明用に簡略化)。

-- MySQL dump 10.13  Distrib 8.0.36
-- Host: localhost    Database: shop
-- ------------------------------------------------------
SET NAMES utf8mb4;
SET @amp;@OLD_FOREIGN_KEY_CHECKS=@amp;@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `email` VARCHAR(255) NOT NULL,
  `created_at` DATETIME NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `users_email_unique` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

LOCK TABLES `users` WRITE;
INSERT INTO `users` VALUES
  (1,'alice@example.com','2026-01-01 00:00:00'),
  (2,'bob@example.com','2026-01-02 00:00:00');
UNLOCK TABLES;

SET FOREIGN_KEY_CHECKS=@amp;@OLD_FOREIGN_KEY_CHECKS;

ポイントは (1) 環境変数のバックアップと復元FOREIGN_KEY_CHECKS 等を一時的に切る)、(2) DROP TABLE IF EXISTS + CREATE TABLE で冪等性を担保(3) INSERT を 1 文に複数値でまとめる(拡張 INSERT、サイズと速度を両立)の 3 点です。pg_dump も概ね同じ構造で、COPY ... FROM stdin; ブロックでバルクロードする点だけ異なります。

条件付きエクスポートでは WHERE id < 10WHERE created_at >= '2026-01-01' のような句がコマンドラインで指定でき、差分ダンプを作れます。ただし参照整合性は呼び出し側の責任になるため、外部キーで繋がる範囲を意識する必要があります。

主な用途

  • 日次バックアップ: cron で mysqldump | gzip > dump-$(date +%F).sql.gz を回す王道パターン。テキスト + gzip でサイズを抑える
  • 本番→検証環境の複製: 個人情報をマスキングしつつスキーマとサンプルデータを移す。--where で 1% サンプリングする運用も多い
  • マイグレーション初期データ: アプリのリポジトリに seeds.sql として同梱し、開発者が make seed で投入できるようにする
  • OSS のサンプル DB: world.sql / sakila.sql(MySQL)、dvdrental.sql(PostgreSQL)などはチュートリアル素材として定番
  • DR(災害復旧)の最終リカバリ: バイナリログ / WAL と組み合わせて PITR を構成し、フル + 増分の二段構えにする

関連形式との比較

形式可読性サイズリストア速度用途
.sql(プレーン)◎(grep 可)遅い長期保存・移行・Git 管理
カスタム形式 -Fc(pg_dump)×(バイナリ)小(圧縮)速い(並列)運用バックアップ
ディレクトリ形式 -Fd△(per table)非常に速い(並列)大規模 DB の高速バックアップ
CSV / TSV速い(COPY/LOAD)外部システム連携・分析
物理バックアップ(Percona XtraBackup 等)×最速大規模本番の停止時間最小化

「テキスト性」「サイズ」「リストア速度」はトレードオフです。日々のオペレーションは カスタム形式、長期アーカイブと監査用は プレーン SQL、と使い分ける現場が多いです。

コマンド・ツール

# MySQL: 整合性を保ったままダンプ(InnoDB)
mysqldump --single-transaction --quick --routines --triggers \
  -u root -p shop > shop-$(date +%F).sql

# 圧縮して保存
mysqldump --single-transaction shop | gzip -9 > shop.sql.gz

# 特定テーブルだけ
mysqldump shop users orders > partial.sql

# PostgreSQL: プレーン SQL(移行・長期保存向け)
pg_dump -U postgres -d shop -F p -f shop.sql

# PostgreSQL: カスタム形式(運用バックアップ向け、並列リストア可)
pg_dump -U postgres -d shop -F c -f shop.dump
pg_restore -U postgres -d shop_new -j 4 shop.dump

# SQLite: テキストダンプとリストア
sqlite3 source.db ".dump" > source.sql
sqlite3 target.db < source.sql

GUI なら MySQL Workbench / pgAdmin / DBeaver / TablePlus が エクスポート / インポートウィザード を持っています。CI でリストアテストを回す場合は Docker の公式イメージ(mysql:8 / postgres:16)に流し込むのが定番です。

注意点

  • 文字コード事故: SET NAMES utf8mb4 を冒頭に入れ忘れると、リストア先で latin1 解釈されて文字化け(いわゆる「mojibake」)が起きる。--default-character-set=utf8mb4 も明示する
  • ロック時間: mysqldump はデフォルトで全テーブルにロックをかける。本番では --single-transaction を必ず付け、可能ならレプリカから取得する
  • 巨大 INSERT: 1 文に何万行も詰め込んだ拡張 INSERT は max_allowed_packet を超える。サーバ側で max_allowed_packet=256M 程度に上げる
  • バージョン非互換: MySQL 5.7 → 8.0 で予約語が追加された(RANKWINDOW 等)。古いダンプを新版で読むときは sed で書き換えるか、--column-statistics=0 を試す
  • 機密情報: 個人情報を含むダンプを Git に push する事故が後を絶たない。.gitignore*.sql を入れる、または専用ストレージに分ける
  • 外部キー順序: 手書きで INSERT を作る場合、参照される親テーブルから順に投入する。FOREIGN_KEY_CHECKS=0 で抑止しつつ最後に再有効化するのが定番

関連リンク

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. SQL ダンプ(.sql)
  2. SQLite(.sqlite / .sqlite3 / .db)
  3. Parquet(.parquet)
  4. Avro(.avro)
  5. ORC(.orc)
  6. NDJSON / JSONL(.ndjson / .jsonl)
  7. BSON(.bson)
  8. Protocol Buffers(.proto)
  9. Feather / Arrow IPC(.feather / .ipc / .arrow)
  10. DB ダンプ(.dump / .bak)

最近更新/作成されたページ