サーバー運用

PythonでのMySQL接続エラーの原因と対策

2026-04-29 読了7分 3PV
PythonでのMySQL接続エラーの原因と対策

こんにちは、AIシステムズです。
この記事は、代表コバが現場で対応してきたPython開発・運用の知見をもとに、AIを活用して構成・執筆し、弊社にて最終チェックを行ったものです。

PythonからMySQLに接続しようとして「Can't connect to MySQL server」「Access denied for user」「2003 - HY000」などのエラーが返ってくる——業務効率化スクリプトやデータ処理を組む現場で必ず一度は遭遇するトラブルです。接続エラーは「ネットワーク到達性」「認証情報」「ドライバ・文字コード」の3層に分けて切り分けると短時間で解消できます。

  • PythonからのMySQL接続エラーの分類
  • ホスト・ポート到達性の確認
  • ユーザー権限とホスト指定の落とし穴
  • ドライバ(PyMySQL・mysqlclient・mysql-connector)の選定
  • 文字コードとタイムアウトの設定

目次

  1. 接続エラーの分類
  2. ネットワーク到達性の確認
  3. 認証情報とMySQLユーザーのホスト指定
  4. Pythonドライバの選定と使い分け
  5. 文字コードと接続タイムアウト
  6. こういう用途に向いている/向いていない
  7. 再発防止チェックリスト

接続エラーの分類

弊社が中小企業のデータ連携・業務効率化スクリプトで対応してきた中で、エラーは次の3層に分けられます。

  • ネットワーク層Can't connect to MySQL server on 'host' (timed out)Connection refused
  • 認証層Access denied for user 'xxx'@'yyy'
  • ドライバ・データ層UnicodeDecodeErrorLost connection during query

エラーメッセージのキーワードで層を見分け、その層から切り分けます。

ネットワーク到達性の確認

1. ポートが空いているか

nc -zv mysql.example.com 3306
# 接続成功なら succeeded! と表示

タイムアウトする場合は、MySQLサーバーがLISTENしていないか、ファイアウォール/セキュリティグループで遮断されています。VPCやセキュリティグループで「DBサーバーへのインバウンドは特定IPのみ」になっているケースが多いので、接続元IPを許可します。

2. bind-addressの確認

MySQL側の /etc/my.cnf または /etc/mysql/mysql.conf.d/mysqld.cnfbind-address = 127.0.0.1 になっていると、ローカルからしか接続できません。外部から接続させるには 0.0.0.0 に変更してMySQLを再起動します。

3. SSH越し接続の選択肢

直接3306を開けたくない場合は、SSHトンネル経由で接続します。

ssh -L 3307:localhost:3306 user@db-server

Python側からは localhost:3307 へ接続します。

認証情報とMySQLユーザーのホスト指定

MySQLのユーザーは「ユーザー名 + 接続元ホスト」の組み合わせで識別されます。'webuser'@'localhost''webuser'@'%' はまったく別のユーザー扱いです。

SELECT user, host FROM mysql.user WHERE user = 'webuser';

接続元から見たMySQL側のhostがワイルドカード(%)か特定IPで許可されている必要があります。許可されていなければ作成します。

CREATE USER 'webuser'@'192.168.1.%' IDENTIFIED BY 'password';
GRANT SELECT, INSERT, UPDATE ON appdb.* TO 'webuser'@'192.168.1.%';
FLUSH PRIVILEGES;

Pythonドライバの選定と使い分け

  • PyMySQL:純Pythonで実装、インストールが簡単。中小規模スクリプトの第一選択
  • mysqlclient:C実装で高速。本番Webアプリで採用するならこちら。OS側にlibmysqlclientが必要
  • mysql-connector-python:Oracle公式。デフォルトの認証プラグイン互換性が高い

PyMySQLでの接続例:

import pymysql

conn = pymysql.connect(
    host='mysql.example.com',
    port=3306,
    user='webuser',
    password='password',
    database='appdb',
    charset='utf8mb4',
    connect_timeout=10,
    cursorclass=pymysql.cursors.DictCursor,
)

文字コードと接続タイムアウト

日本語データを扱う場合、charset='utf8mb4' を必ず指定します。utf8(=utf8mb3)は絵文字を含む文字を保存できず、UnicodeDecodeErrorの原因になります。
長時間スクリプトでは、MySQL側のタイムアウト(wait_timeout)でコネクションが切られて「Lost connection」になります。対策は次のいずれかです。

  • 処理ごとに接続を開閉する
  • 定期的に conn.ping(reconnect=True) を呼ぶ
  • SQLAlchemyなどのコネクションプールを使う

こういう用途に向いている/向いていない

このPython+MySQL構成は、中小企業の業務データの抽出・加工・連携、定期バッチ、Webアプリのバックエンドなど幅広く適しています。データ量がテラバイト規模に達するケースや、リアルタイム性が極めて重要なケースでは、別のデータベース(PostgreSQL、ClickHouseなど)の検討も必要です。

再発防止チェックリスト

  • 接続先ホスト・ポートに到達できるかncで確認しているか
  • MySQLユーザーのhost指定が接続元と一致しているか
  • charsetをutf8mb4に指定しているか
  • 長時間処理ではconnection.pingまたはプール再接続を実装しているか
  • パスワードを環境変数で渡し、ソースコードに直書きしていないか

まとめ

PythonからのMySQL接続エラーは、ネットワーク到達性 → 認証情報 → ドライバ・文字コードの順に切り分ければ短時間で原因を特定できます。nc でポート確認、mysql.user でユーザーのhost確認、utf8mb4 指定の3点をルーチン化するのが定石です。

本記事は、代表コバが中小企業のPython・データ連携の現場で対応してきた知見をもとに、AIを活用して構成・執筆し、弊社にて最終確認を行っています。業務スクリプトの設計、データ連携基盤の構築、既存スクリプトの保守・改善について、具体的な状況をふまえた相談を承っています。費用感だけ知りたい方も、お気軽にご相談ください。

AI Systemsへの無料相談はこちら

「何から始めればいいか分からない」段階からでも、お気軽にご相談ください。
まずは、お話を聞かせていただくだけでも大丈夫です。

無料で相談する
コバ

コバ

AI活用 / Web制作 / 業務自動化支援

中小企業さま向けに「お手頃に・早く・成果が出る」開発支援を行っています。AI・Web・自動化の3分野を、まとめてサポートしています。

この記事をシェアする

一覧へ戻る