Contents
チェックリスト概要と本記事の目的
Flask と MySQL の接続エラーは、設定ミス・環境不整合・ドライバ選択という 3 つの観点で整理できます。本稿では、2026 年現在主流となっている Python 3.12 と MySQL 8.0 系列に焦点を当て、実務ですぐに適用できるチェックリストを提示します。
まずはエラーメッセージの意味を把握し、次に開発環境と DB 設定を統一する手順を確認してください。最後に、推奨ドライバと最小権限ユーザーの作り方、そして障害時のハンドリング例を示します。
結論 – 本チェックリストを 1 回実行すれば、Flask‑MySQL の接続失敗はほぼ防げます。
代表的な接続エラーメッセージと原因例
ここでは実務で頻出する 4 種類のエラーを取り上げ、それぞれに対応すべき確認項目をまとめました。エラーメッセージは問題箇所への手がかりになるので、まずは正確に読み取ることが重要です。
Access denied エラー
Access denied for user 'user'@'host' (using password: YES) は認証情報が合致しないときに返ります。
- 主な原因
- ユーザー名・パスワードのタイプミス
- MySQL 側で該当ユーザーが存在しない、またはホスト制限がかかっている
-
.envに記載した情報と実際の DB がずれている -
チェック項目
| 項目 | 確認方法 |
|---|---|
MYSQL_USER / MYSQL_PASSWORD の正確性 |
.env と SELECT User, Host FROM mysql.user; を比較 |
| 接続元 IP が許可されているか | SELECT Host FROM mysql.user WHERE User='app_user'; |
| パスワードポリシーで変更が必要か | SHOW VARIABLES LIKE 'validate_password%'; |
Can't connect to MySQL server エラー
Can't connect to MySQL server on '127.0.0.1' (111) は TCP 接続が確立できないときに出ます。
- 主な原因
- サーバーが停止している、またはポート番号が違う
- ファイアウォール / Docker ネットワークでブロックされている
-
bind-addressが外部からの接続を拒否している -
チェック項目
| 項目 | 確認方法 |
|---|---|
| MySQL サービスの稼働状態 | systemctl status mysql / docker ps |
設定ファイル (my.cnf) の port と bind-address |
grep -E 'port|bind-address' /etc/mysql/my.cnf |
| ネットワーク到達性 | nc -zv 127.0.0.1 3306 または docker exec … curl |
MySQL server has gone away エラー
MySQL server has gone away は、サーバー側で接続が切断された後にクエリを送ろうとしたときに発生します。
- 主な原因
wait_timeout/interactive_timeoutが短く設定されているmax_allowed_packetを超えるサイズのデータを送信しようとしている-
コネクションプールが長時間アイドル状態になる
-
チェック項目
| 項目 | 推奨設定例 |
|---|---|
wait_timeout |
最低でも 18000 秒(5 h) |
max_allowed_packet |
アプリで扱う最大 BLOB の 2 倍以上、例: 64M |
| SQLAlchemy のプールリサイクル | pool_recycle=1800(30 分ごとに再接続) |
SSL/TLS エラー
SSL connection error: TLS handshake failed は暗号化ハンドシェイクが失敗したことを示します。
- 正しい前提
- MySQL 8.0 系列はデフォルトで TLS 接続は 任意(
require_secure_transport=OFF)。TLS1.3 が必須になる設定はrequire_secure_transport=ONと明示的に変更した場合のみです。 -
MySQL は TLS1.2 を最低サポートし、8.0.16 以降で TLS1.3 が利用可能になりますが、クライアント側のドライバが対応している必要があります。
-
主な原因
- 使用している Python ドライバが TLS1.3 に未対応(古いバージョン)
- 証明書パスや CA ファイルが誤っている、または権限不足
-
サーバー側の
ssl_cipherがクライアントと合致しない -
チェック項目
| 項目 | 推奨バージョン |
|---|---|
pymysql(TLS) |
≥ 1.0.0(TLS1.2 対応) |
mysql‑connector‑python(TLS) |
≥ 8.0.30(TLS1.3 完全対応) |
mysqlclient(C ライブラリ) |
libmysqlclient 8.0.26 以降で TLS1.3 利用可 |
ローカル開発環境の正しい構築手順
エラーの多くは「ローカルと本番で設定が食い違う」ことから生じます。以下では、Python 仮想環境作成から OS 別 MySQL クライアントインストールまでを体系的に示します。
virtualenv と python‑dotenv のセットアップ
まずはプロジェクトごとに独立した仮想環境を用意し、.env ファイルの自動ロードを有効化します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 1. プロジェクトディレクトリへ移動 cd my_flask_app # 2. Python 3.12 で仮想環境作成 python3.12 -m venv .venv # 3. 仮想環境を有効化(Unix 系) source .venv/bin/activate # 4. パッケージ最新版にアップデートし、必要ライブラリをインストール pip install --upgrade pip pip install Flask SQLAlchemy python-dotenv \ pymysql mysql-connector-python mysqlclient |
ポイント –
.venvは必ず.gitignoreに追加し、作業前にsource .venv/bin/activateを忘れないようにしましょう。
OS 別 MySQL クライアントライブラリのインストール
Python の C 拡張ドライバ(mysqlclient)はシステムの開発ヘッダーが必要です。代表的なディストリビューション向けコマンドを表にまとめました。
| OS | インストール例 |
|---|---|
| Ubuntu 22.04 / Debian 12 | sudo apt-get update && sudo apt-get install libmysqlclient-dev |
| macOS (Homebrew) | brew install mysql-client ※ PATH に /opt/homebrew/opt/mysql-client/bin を追加 |
| Windows (WSL2 推奨) | 上記 Ubuntu コマンドをそのまま使用 |
インストール後、pip install mysqlclient がエラーなく完了すれば準備完了です。
.env に必要な変数を記述
環境依存情報はコードに埋め込まず .env にまとめます。以下は最小構成例です(SSL が不要な場合は MYSQL_SSL_* 系は省略可)。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# Flask 基本設定 FLASK_APP=app.py FLASK_ENV=development # MySQL 接続情報 MYSQL_HOST=127.0.0.1 MYSQL_PORT=3306 MYSQL_DB=mydb MYSQL_USER=app_user MYSQL_PASSWORD=StrongP@ssw0rd! # SSL(必要なときだけ) MYSQL_SSL_CA=/path/to/ca.pem MYSQL_SSL_CERT=/path/to/client-cert.pem MYSQL_SSL_KEY=/path/to/client-key.pem |
python-dotenv の load_dotenv() をアプリ起動直後に呼び出すだけで、上記変数は自動的に環境変数として利用できます。
Flask の設定と推奨ドライバ比較/DB ユーザー作成ベストプラクティス
ドライバ別機能比較
| 項目 | pymysql | mysql‑connector‑python | mysqlclient |
|---|---|---|---|
| 実装言語 | Pure Python | C + Python (Oracle 公式) | C 拡張 (libmysqlclient) |
| TLS1.2 サポート | ✔︎(1.0.0 以降) | ✔︎ | ✔︎ |
| TLS1.3 サポート | ✖︎(未実装) | ✔︎(8.0.30 以降) | ✔︎(libmysqlclient が 8.0.26+ の場合) |
| パフォーマンス | 中程度 | 高速 | 最高速(ビルド環境依存) |
| 推奨利用シーン | Docker イメージを小さくしたいとき、C 環境が不要なとき | TLS1.3 必須・高可用性が求められる本番環境 | 開発マシンでビルドツールが揃っている Linux/macOS |
結論 – TLS1.3 が必須の場合は
mysql-connector-python、軽量さを優先するならpymysqlを選択してください。mysqlclientはパフォーマンス重視か既存 C 環境が整っている場合に限ります。
Flask アプリの DB 設定例(SQLAlchemy URL)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# app.py import os from flask import Flask from flask_sqlalchemy import SQLAlchemy from dotenv import load_dotenv load_dotenv() # .env のロード app = Flask(__name__) # 環境変数でドライバ切替可能にする driver = os.getenv('MYSQL_DRIVER', 'pymysql') # pymysql / mysqlconnector / mysqldb db_url = ( f"mysql+{driver}://" f"{os.getenv('MYSQL_USER')}:{os.getenv('MYSQL_PASSWORD')}@" f"{os.getenv('MYSQL_HOST')}:{os.getenv('MYSQL_PORT')}/" f"{os.getenv('MYSQL_DB')}" ) app.config['SQLALCHEMY_DATABASE_URI'] = db_url app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # 接続プールの基本設定(環境変数で上書き可) app.config['SQLALCHEMY_POOL_SIZE'] = int(os.getenv('POOL_SIZE', 10)) app.config['SQLALCHEMY_MAX_OVERFLOW']= int(os.getenv('MAX_OVERFLOW', 5)) app.config['SQLALCHEMY_POOL_TIMEOUT'] = int(os.getenv('POOL_TIMEOUT', 30)) app.config['SQLALCHEMY_POOL_RECYCLE'] = int(os.getenv('POOL_RECYCLE', 1800)) db = SQLAlchemy(app) |
ポイント –
MYSQL_DRIVERを変更するだけでコードを書き換える必要がなく、ステージング・本番環境の差異を.envだけで吸収できます。
最小権限ユーザー作成手順
セキュリティ上、アプリは 最小権限 の専用ユーザーで接続させることが必須です。以下は一般的な CRUD アプリ向けの例です(IP は実際にデプロイするホストに合わせて変更してください)。
|
1 2 3 4 5 6 7 8 9 |
-- 1. ユーザー作成(パスワードは十分に強固に) CREATE USER 'app_user'@'127.0.0.1' IDENTIFIED BY 'StrongP@ssw0rd!'; -- 2. 必要最小限の権限付与 GRANT SELECT, INSERT, UPDATE, DELETE ON mydb.* TO 'app_user'@'127.0.0.1'; -- 3. ストアドプロシージャやビューが必要な場合は個別に許可 -- GRANT EXECUTE ON PROCEDURE mydb.my_proc TO 'app_user'@'127.0.0.1'; |
注意点 –
%'(全ホスト)での許可は避け、接続元 IP を限定してください。また、MySQL のパスワードポリシーを強化する場合はvalidate_password_policy=MEDIUM以上に設定すると安全です。
エラーハンドリング実装・接続プール設定・デバッグ支援ツール
Flask での例外ハンドリング(SQLAlchemyError)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
from flask import jsonify from sqlalchemy.exc import SQLAlchemyError @app.errorhandler(SQLAlchemyError) def handle_db_error(exc): app.logger.error(f"DB error: {exc}") # 必ずロールバックしてプール破損を防止 db.session.rollback() return jsonify({ "error": "database_failure", "message": "データベースへのアクセス中にエラーが発生しました。" }), 500 |
ポイント – ハンドラで
session.rollback()を必ず呼び出すことで、プール内の破損コネクションを回収できます。
ロギング設定(コンソール+ローテーションファイル)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import logging from logging.handlers import RotatingFileHandler # コンソール(開発時) console = logging.StreamHandler() console.setLevel(logging.DEBUG) # ファイル(本番向け、10 MB/5世代でローテーション) file_handler = RotatingFileHandler( 'logs/flask_app.log', maxBytes=10*1024*1024, backupCount=5 ) file_handler.setLevel(logging.INFO) formatter = logging.Formatter('[%(asctime)s] %(levelname)s in %(module)s: %(message)s') console.setFormatter(formatter) file_handler.setFormatter(formatter) app.logger.addHandler(console) app.logger.addHandler(file_handler) app.logger.setLevel(logging.DEBUG) # 全体の最小レベル |
ポイント –
engine.echo = Trueを有効にすると SQL の実行ログが出力され、クエリ単位でデバッグしやすくなります。
接続プールと『MySQL server has gone away』対策
SQLAlchemy のプール設定はサーバ側のタイムアウトと合わせる必要があります。以下は推奨構成です。
|
1 2 3 4 |
# app.config に追記(前述の Flask 設定ブロックに組み込む) app.config['SQLALCHEMY_POOL_RECYCLE'] = int(os.getenv('POOL_RECYCLE', 1800)) # 30 分で再接続 app.config['SQLALCHEMY_POOL_PRE_PING'] = True # 接続取得時に ping を実施し、切断を自動検知 |
- 理由 –
wait_timeoutが短いクラウド環境や Docker では、プールされた接続がサーバ側で切れるケースが多いため、pool_recycleとpre_pingの併用が安全です。 - 実践 – エラーが頻発したら
SHOW VARIABLES LIKE 'wait_timeout';を確認し、必要に応じて MySQL 側でも延長してください。
MySQL 側のログ取得方法
| ログ種別 | 有効化手順 | 主な活用シーン |
|---|---|---|
| General Log | SET GLOBAL general_log = 'ON'; SET GLOBAL log_output='TABLE'; |
接続開始・終了タイミングを全て記録したいとき |
| Slow Query Log | SET GLOBAL slow_query_log=ON; SET GLOBAL long_query_time=1; |
パフォーマンスボトルネックの特定 |
| InnoDB Status | SHOW ENGINE INNODB STATUS\G |
ロックやバッファプールの状態確認 |
注意 – 本番環境で General Log を長時間オンにすると I/O 負荷が増大します。デバッグ後は必ず
SET GLOBAL general_log = 'OFF';に戻しましょう。
実務で陥りやすい落とし穴まとめ(チェックリスト)
| # | 落とし穴 | 確認手順 |
|---|---|---|
| 1 | 仮想環境を有効化せずに pip install → パッケージバージョン不整合 |
which python が .venv/bin/python か確認 |
| 2 | OS に libmysqlclient が無く mysqlclient のインストールが失敗 |
前述の OS 別パッケージを先に導入 |
| 3 | .env をリポジトリにコミット → 本番で環境変数が上書きされる |
.gitignore に .env を追加、CI/CD ではシークレット管理ツール使用 |
| 4 | TLS 設定を忘れ、古いドライバで接続 → ハンドシェイクエラー | pip list でドライババージョン確認、必要ならアップグレード |
| 5 | MySQL 側の require_secure_transport を有効化したまま開発環境だけ TLS 設定を省略 |
SHOW VARIABLES LIKE 'require_secure_transport'; を必ずチェック |
まとめ
- エラーはメッセージが指し示す原因に分解できる – 認証・ネットワーク・タイムアウト・SSL の4カテゴリ。
- 環境構築は virtualenv + python‑dotenv、OS 別の MySQL クライアントインストールで完了。
- ドライバ選択は TLS1.3 対応とパフォーマンスを基準に –本番では
mysql-connector-python、軽量開発や Docker ではpymysqlが安全です。 - 最小権限ユーザーでセキュリティを確保し、IP 制限・強固なパスワードポリシーを適用してください。
- 例外ハンドリングとロギングで障害検知を自動化し、
pool_recycleとpre_pingで接続切断を防止します。 - MySQL 側のログ(General/Slow/InnoDB)も併用すれば根本原因の特定が容易に。
上記チェックリストを順に実行すれば、Flask‑MySQL の接続エラーは設定・コード修正だけで確実に解決できます。ぜひ本稿の手順をプロジェクトに組み込み、安定した開発環境と本番運用を実現してください。