【完全版】MySQL「ERROR 1045 (28000): Access denied」の原因と対処法
- 作成日 2026.06.17
- その他
MySQL/MariaDBに接続しようとして、以下のエラーで弾かれることはないですか?
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
ERROR 1045 (28000): Access denied for user 'app_user'@'192.168.1.100' (using password: YES)
ERROR 1045 (28000): Access denied for user ''@'localhost' (using password: NO)
SQLSTATE[HY000] [1045] Access denied for user 'user'@'host'
「ユーザー名かパスワードが違います」を意味する MySQL のエラーですが、実際の原因は10種類以上あり、パスワードを正しく入力していてもこのエラーが出るケースが頻発します。
- パスワードは合っているはずなのに接続できない
- 別のマシンからは接続できないが、サーバー上では成功する
- MySQL 8 にアップグレードしたら既存アプリが繋がらなくなった
- Docker MySQL コンテナに root で入れない
- 新規ユーザーを作ったのに接続失敗する
- AWS RDS で接続失敗する
- 「(using password: NO)」と表示される
本記事では、MySQL ERROR 1045 のすべての原因と対処法を、現場で即使えるトラブルシューティング手順として整理します。MySQL認証の仕組みから、'user'@'host'の意味、認証プラグイン(caching_sha2_password / mysql_native_password)の違い、root パスワードリセット手順、Docker・AWS RDS対応、PHP/Python/Javaからの接続まで完全網羅。この1本でMySQL認証エラーの悩みが全て解決します。
- 1. 結論:今すぐ試すべき3ステップ
- 2. まず押さえる:MySQL認証の仕組み
- 3. エラーの原因カテゴリ
- 4. 【原因①】パスワードの入力ミス・特殊文字
- 5. 【原因②】ホスト指定の不一致(最頻出・要注意)
- 6. 【原因③】認証プラグインの不一致(MySQL 8.0以降の重要原因)
- 7. 【原因④】rootパスワードを忘れた場合
- 8. 【原因⑤】ユーザーが存在しない・権限不足
- 9. 【原因⑥】bind-address による接続制限
- 10. Docker環境でのERROR 1045
- 11. クラウドDB(AWS RDS、Aurora、Cloud SQL等)
- 12. プログラム言語別 ERROR 1045 対処
- 13. 関連エラーと違い
- 14. セキュリティ・運用ベストプラクティス
- 15. トラブルシューティング・チェックリスト
- 16. よくある質問(FAQ)
- 16.1. Q1. ローカルでは繋がるのにアプリから接続できません
- 16.2. Q2. (using password: NO) と表示されます
- 16.3. Q3. MySQL 8 にアップグレード後、PHPアプリが繋がらなくなりました
- 16.4. Q4. root のパスワードを変更したらどこからも繋がらなくなりました
- 16.5. Q5. ユーザーが存在するのに接続できません
- 16.6. Q6. SSL関連でエラーが出ます
- 16.7. Q7. Docker でMySQLに繋がりません
- 16.8. Q8. AWS RDS に接続できなくなりました
- 16.9. Q9. mysql_native_password が使えないバージョンがあるの?
- 16.10. Q10. /tmp/mysql.sock で繋がりません
- 16.11. Q11. アプリのパスワード変更後、しばらくして接続できなくなります
- 16.12. Q12. パスワードを忘れたが MySQL の停止ができません
- 17. 参考リンク・関連資料
- 18. まとめ
結論:今すぐ試すべき3ステップ
時間がない方向けに、まず試すべき手順を示します。
ステップ1:エラーメッセージから情報を読み取る
ERROR 1045 (28000): Access denied for user 'app_user'@'192.168.1.100' (using password: YES)
↑ ↑ ↑
ユーザー名 接続元IP パスワード入力有無
この情報を元に切り分けます。
ステップ2:MySQL サーバー上でユーザー存在確認
-- root で MySQL に接続して
mysql -u root -p
-- ユーザーとホスト指定の組み合わせを確認
SELECT user, host FROM mysql.user;
ステップ3:該当ユーザーのパスワードを再設定
-- ユーザーが存在する場合
ALTER USER 'app_user'@'192.168.1.100' IDENTIFIED BY 'new_password';
-- ユーザーが存在しない場合(新規作成)
CREATE USER 'app_user'@'192.168.1.100' IDENTIFIED BY 'new_password';
GRANT ALL PRIVILEGES ON dbname.* TO 'app_user'@'192.168.1.100';
FLUSH PRIVILEGES;
それでも解決しない場合は、以下の詳細な原因分析へ進んでください。
まず押さえる:MySQL認証の仕組み
MySQLの認証エラーを理解するには、'user'@'host'というユーザー識別の仕組みを知る必要があります。
MySQLのユーザーは「ユーザー名+接続元ホスト」のペア
OracleやPostgreSQLと違い、MySQLは「ユーザー名」だけでなく**「どこから接続するか」もセット**でユーザーを管理します。
-- これらは「別々のユーザー」として扱われる
'app_user'@'localhost' -- ローカルからのみ接続可能
'app_user'@'192.168.1.100' -- 特定IPからのみ
'app_user'@'192.168.1.%' -- 192.168.1.x全般から
'app_user'@'%' -- どこからでも
つまり、app_user というユーザー名が同じでも、接続元ホストが違えば別のユーザーとして扱われます。これがMySQL認証で多くの混乱を生む元となります。
エラーメッセージの読み解き方
Access denied for user 'app_user'@'192.168.1.100' (using password: YES)
| 要素 | 意味 |
|---|---|
'app_user' | 接続を試みたユーザー名 |
'192.168.1.100' | サーバーから見た接続元のIP/ホスト名 |
using password: YES | パスワードを送信した |
using password: NO | パスワードを送信していない |
特に重要: @ の後ろは、自分のマシン名ではなくMySQLサーバーから見た自分のアドレスです。NAT越しなら全く違うIPになります。
エラーの原因カテゴリ
| カテゴリ | 例 | 頻度 |
|---|---|---|
| パスワード関連 | 入力ミス、リセット忘れ、特殊文字エスケープ | 最多 |
| ホスト指定問題 | localhost vs %、IP違い、ホスト名解決失敗 | 多 |
| ユーザー未作成 | 該当ユーザーが存在しない | 多 |
| 権限不足 | ユーザーは存在するが該当DBに権限なし | 中 |
| 認証プラグイン | caching_sha2_password と mysql_native_password の競合 | 中(MySQL 8.0以降特に) |
| root特殊事情 | rootパスワード忘れ、auth_socket認証 | 中 |
| 設定問題 | skip-name-resolve、bind-address制限 | 中 |
| Docker/クラウド固有 | コンテナ内外、AWS RDS設定 | 中 |
これらを順番に切り分けます。
【原因①】パスワードの入力ミス・特殊文字
最も多いケースです。基本ですが意外な落とし穴も。
よくあるタイプミス
- スペース混入(前後・中間)
- Caps Lock有効
- 全角文字混入
- 似た文字の混同(
O/0、l/1、I/l) - メモ帳からコピー時の改行コード・ゼロ幅スペース混入
コマンドラインでの特殊文字エスケープ
パスワードに$、!、"、'等の記号が含まれる場合、シェルが解釈してしまう可能性:
# ❌ 失敗例($がシェルで解釈される)
mysql -u app -p$ecret!Pass
# ✅ シングルクォートで囲む
mysql -u app -p'$ecret!Pass'
# ✅ 対話的にプロンプトで入力(最も安全)
mysql -u app -p
# Enter password: ← 表示されない入力
Windows コマンドプロンプト
mysql -u app -p"$ecret!Pass"
-p の前後にスペースを入れない
# ❌ NG(パスワードがDB名と解釈される)
mysql -u app -p secretpass
# ✅ OK(スペースなし)
mysql -u app -psecretpass
# ✅ OK(プロンプトで入力)
mysql -u app -p
【原因②】ホスト指定の不一致(最頻出・要注意)
MySQL認証の特殊性で最も混乱を生む原因です。
現象
'app_user'@'localhost' で接続OKなのに、'app_user'@'127.0.0.1' で接続NG、というケース。これは:
'app_user'@'localhost'ユーザーが作成されている'app_user'@'127.0.0.1'または'app_user'@'%'は作成されていない
ためです。
localhost と 127.0.0.1 は別物
MySQLでは:
localhost: UNIXソケット接続(TCPを介さない)127.0.0.1: TCP/IP経由のループバック接続
接続プロトコルが違うため、別のユーザーエントリが必要です。
接続時にどちらが使われるか確認
# UNIX socket強制
mysql --protocol=socket -u app -p
# TCP/IP強制
mysql --protocol=tcp -h 127.0.0.1 -u app -p
自分が「どこから接続している」と見えるか確認
サーバー上で接続中のセッション一覧を見ると分かります:
SELECT host FROM information_schema.processlist WHERE user = CURRENT_USER();
-- または
SELECT CURRENT_USER();
-- 結果例: 'app_user'@'192.168.1.100'
ユーザー一覧でホスト指定を確認
SELECT user, host FROM mysql.user WHERE user = 'app_user';
出力例:
+----------+-------------+
| user | host |
+----------+-------------+
| app_user | localhost |
| app_user | % |
+----------+-------------+
localhost と % は別エントリで、それぞれパスワードや権限が独立しています。
対処:必要なホスト指定でユーザーを作成
-- 192.168.1.100からのみ接続を許可
CREATE USER 'app_user'@'192.168.1.100' IDENTIFIED BY 'password';
GRANT ALL ON appdb.* TO 'app_user'@'192.168.1.100';
-- 192.168.1.x全般から
CREATE USER 'app_user'@'192.168.1.%' IDENTIFIED BY 'password';
-- どこからでも(開発環境のみ推奨)
CREATE USER 'app_user'@'%' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
⚠️ '%'は世界中からの接続を意味するセキュリティリスクがあります。本番では具体的IP範囲に限定推奨。
skip-name-resolve の影響
my.cnfに以下が設定されているとホスト名→IP変換が行われません:
[mysqld]
skip-name-resolve
この場合、'user'@'webserver'のようなホスト名指定ユーザーは認証失敗します。IPアドレスで指定しましょう。
-- ホスト名指定(skip-name-resolve環境では動かない)
'app_user'@'webserver.example.com'
-- IPで指定(推奨)
'app_user'@'192.168.1.100'
設定確認:
SHOW VARIABLES LIKE 'skip_name_resolve';
【原因③】認証プラグインの不一致(MySQL 8.0以降の重要原因)
MySQL 8.0からデフォルト認証プラグインがcaching_sha2_passwordに変更され、古いクライアント・ドライバとの互換性問題が頻発します。
認証プラグインの確認
SELECT user, host, plugin FROM mysql.user;
主な値:
| プラグイン | 説明 |
|---|---|
caching_sha2_password | MySQL 8.0デフォルト。高セキュリティだが古いクライアント非対応 |
mysql_native_password | 5.7以前のデフォルト。広く互換性あり |
auth_socket | UNIXソケット経由でOSユーザーと連携(Linux root等) |
sha256_password | 古い強化認証(非推奨) |
MySQL 8.0でのよくある現象
- Java JDBC(古いConnector/J)で接続失敗
- PHP(mysqlnd未対応版)で接続失敗
- Workbench接続で
Authentication plugin caching_sha2_password cannot be loaded
対処1:ユーザーの認証プラグインを変更
特定ユーザーだけを互換性プラグインに:
ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
対処2:MySQLサーバーのデフォルト変更
/etc/mysql/my.cnf または mysqld.cnf に追加:
[mysqld]
default-authentication-plugin=mysql_native_password
設定後にMySQLサーバー再起動。新規作成されるユーザーはこのプラグインで作られます。
⚠️ MySQL 8.4以降ではmysql_native_passwordがデフォルトで無効化されています。明示的に有効化が必要:
[mysqld]
mysql_native_password=ON
対処3:クライアントを更新
根本的にはクライアント側のドライバを新しくするのがベスト:
- JDBC:
mysql-connector-j8.0.x以降 - PHP: mysqlnd(PHP 5.4+で標準)を使用
- Python:
mysql-connector-python8.0.x以降、またはPyMySQL
auth_socket の場合(特殊)
UbuntuのMySQL初期インストール時、rootはauth_socketプラグインで設定されます。これは「OS上で root ユーザーが実行した場合のみ」認証が通る仕組みで、パスワード認証ではありません。
# OS上のrootから(成功)
sudo mysql
# 一般ユーザーから(失敗)
mysql -u root -p # → ERROR 1045
対処:
# sudo付きで接続
sudo mysql
# プラグイン変更
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'newpassword';
FLUSH PRIVILEGES;
EXIT
これで通常のパスワード認証も使えるようになります。
【原因④】rootパスワードを忘れた場合
最後の手段としての、rootパスワードリセット手順です。
Linux(systemd環境)
手順1:MySQLを安全モードで起動
# MySQLを停止
sudo systemctl stop mysql
# 認証なしで起動
sudo mysqld_safe --skip-grant-tables --skip-networking &
# またはsystemd経由
sudo systemctl set-environment MYSQLD_OPTS="--skip-grant-tables --skip-networking"
sudo systemctl start mysql
手順2:パスワード変更
# パスワードなしで接続
mysql -u root
-- 認証情報をリロード(grant tablesをロード)
FLUSH PRIVILEGES;
-- パスワード変更
ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password';
EXIT;
手順3:通常モードで再起動
sudo systemctl unset-environment MYSQLD_OPTS
sudo systemctl restart mysql
これでmysql -u root -pで新パスワード接続できます。
Windows
REM MySQL停止
net stop MySQL80
REM init.txtを作成
echo ALTER USER 'root'@'localhost' IDENTIFIED BY 'new_password'; > C:\temp\init.txt
REM 初期化ファイル指定で起動
mysqld --init-file=C:\temp\init.txt --console
REM 別ウィンドウから接続確認
mysql -u root -p
REM 通常モードに戻す(Ctrl+C で初期化モード停止後)
net start MySQL80
Docker環境
Docker環境では別アプローチ:
# 1. 環境変数で初期化されたコンテナを削除
docker stop mysql-container
docker rm mysql-container
# 2. 新しい環境変数で再作成
docker run -d --name mysql-container \
-e MYSQL_ROOT_PASSWORD=new_password \
-p 3306:3306 \
-v mysql_data:/var/lib/mysql \
mysql:8.0
⚠️ 既存ボリュームの場合はパスワード初期化されません。ボリューム削除 or --skip-grant-tables 経由のリセットが必要です。
【原因⑤】ユーザーが存在しない・権限不足
シンプルですが多いケース。
ユーザーの存在確認
SELECT user, host FROM mysql.user WHERE user = 'app_user';
何も返ってこなければユーザー未作成です。
権限の確認
SHOW GRANTS FOR 'app_user'@'localhost';
出力例:
GRANT USAGE ON *.* TO `app_user`@`localhost`
USAGEだけだとログインはできるがDB操作不可。USAGEは単純な接続権限です。
権限付与
-- 特定DBへの全権限
GRANT ALL PRIVILEGES ON appdb.* TO 'app_user'@'localhost';
-- 読み取り専用
GRANT SELECT ON appdb.* TO 'app_user'@'localhost';
-- 複数操作
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'app_user'@'localhost';
-- 全DBへのスーパーユーザー権限(要注意)
GRANT ALL PRIVILEGES ON *.* TO 'app_user'@'localhost' WITH GRANT OPTION;
-- 反映
FLUSH PRIVILEGES;
「Access denied for user (using password: NO)」の場合
パスワードを送信していない状態です。原因:
- パスワードオプション
-pを付け忘れた - スクリプトでパスワード変数が空になっていた
# ❌
mysql -u app
# ✅
mysql -u app -p
匿名ユーザーの罠
MySQLには歴史的経緯で''@'localhost'(空ユーザー名)が存在することがあります。これがあると、ユーザー名指定なしでも接続できてしまい、セキュリティリスクになります。
SELECT user, host FROM mysql.user WHERE user = '';
該当があれば削除:
DROP USER ''@'localhost';
DROP USER ''@'%';
FLUSH PRIVILEGES;
【原因⑥】bind-address による接続制限
サーバー側でリスナーのバインドアドレスを制限している場合、リモート接続が拒否されます。
現状確認
SHOW VARIABLES LIKE 'bind_address';
| 値 | 動作 |
|---|---|
127.0.0.1 | localhostのみ受け付け(デフォルト:MySQL 8.0以降は変更されたバージョンあり) |
0.0.0.0 | すべてのインターフェース |
:: | IPv6含む全インターフェース |
| 特定IP | そのIPのみ |
127.0.0.1 の場合、リモートからは ORA-1045 ではなく接続拒否
リモートから接続を試みると、エラー1045ではなく 2003 (HY000): Can't connect to MySQL server が出ることが多いですが、ファイアウォール構成によっては1045として返ることもあります。
対処:bind-address 変更
/etc/mysql/mysql.conf.d/mysqld.cnf:
[mysqld]
bind-address = 0.0.0.0
MySQL再起動:
sudo systemctl restart mysql
⚠️ 外部公開する場合は、ファイアウォールとMySQLユーザーのホスト指定の両方で適切な制限を必ず設定してください。
Docker環境でのERROR 1045
Docker MySQL は特殊事情があります。
よくあるシナリオ
# コンテナ起動
docker run -d --name mysql -e MYSQL_ROOT_PASSWORD=mypass -p 3306:3306 mysql:8.0
# ホストから接続
mysql -h 127.0.0.1 -u root -p
# ERROR 1045 (28000): Access denied for user 'root'@'172.17.0.1'
原因: Docker MySQLのrootはデフォルトで'root'@'localhost'のみ作成されており、ホストからの接続(コンテナから見ると別IP)は拒否されます。
対処1:環境変数でリモート root を有効化
docker run -d --name mysql \
-e MYSQL_ROOT_PASSWORD=mypass \
-e MYSQL_ROOT_HOST=% \
-p 3306:3306 \
mysql:8.0
MYSQL_ROOT_HOST=%で全ホストからroot接続可能になります。
対処2:別ユーザーを作成
docker run -d --name mysql \
-e MYSQL_ROOT_PASSWORD=mypass \
-e MYSQL_USER=appuser \
-e MYSQL_PASSWORD=apppass \
-e MYSQL_DATABASE=appdb \
-p 3306:3306 \
mysql:8.0
MYSQL_USERで作成されるユーザーは'appuser'@'%'としてアクセス可能です。
対処3:コンテナ内部に入って手動で設定
docker exec -it mysql mysql -u root -p
# コンテナ内で
mysql> CREATE USER 'app'@'%' IDENTIFIED BY 'apppass';
mysql> GRANT ALL ON *.* TO 'app'@'%';
mysql> FLUSH PRIVILEGES;
docker-compose 例
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_ROOT_HOST: '%' # ← リモートrootアクセス
MYSQL_DATABASE: appdb
MYSQL_USER: appuser
MYSQL_PASSWORD: apppass
ports:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql
volumes:
mysql_data:
クラウドDB(AWS RDS、Aurora、Cloud SQL等)
クラウドマネージドDBでも頻発するエラーです。
AWS RDS for MySQL / Aurora
よくある原因
- マスターユーザーのパスワード忘れ → RDSコンソールで変更
- セキュリティグループでクライアントIPからの接続が許可されていない
- VPC外からの接続でパブリックアクセスが無効化されている
対処:マスターパスワード変更
- AWS Console → RDS → 該当インスタンスを選択
- 「変更」→ 「新しいマスターパスワード」入力
- 反映に1〜2分かかる
接続元 IP 確認
curl ifconfig.me # 自分のグローバルIP
セキュリティグループのインバウンドルールに自分のIP + 3306ポートが許可されている確認。
Google Cloud SQL
# Cloud SQL Authプロキシ経由が推奨
./cloud_sql_proxy -instances=PROJECT:REGION:INSTANCE=tcp:3306
mysql -u root -p -h 127.0.0.1
直接接続の場合は、Cloud SQL の「Authorized networks」設定でクライアントIPを追加。
Azure Database for MySQL
Azure Portal → MySQL サーバー → 「接続のセキュリティ」 → ファイアウォール規則でクライアントIPを許可。
ユーザー名フォーマットの違い
クラウドサービスによって特殊なユーザー名形式が必要なことがあります:
- Azure Database for MySQL:
username@servername - AWS RDS Proxy経由: IAMトークン認証の場合は特殊
各サービスの公式ドキュメントを確認してください。
プログラム言語別 ERROR 1045 対処
PHP(PDO・mysqli)
<?php
try {
$pdo = new PDO(
'mysql:host=localhost;dbname=appdb;charset=utf8mb4',
'app_user',
'password'
);
} catch (PDOException $e) {
if ($e->getCode() == 1045) {
echo "認証エラー: ユーザー名・パスワード・ホスト指定を確認\n";
}
throw $e;
}
PHP(caching_sha2_passwordエラー)
PHP Fatal error: Uncaught PDOException: SQLSTATE[HY000] [2054]
The server requested authentication method unknown to the client
このエラーは ERROR 1045 とセットで出ます。対処:
ALTER USER 'app_user'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
または PHP のmysqlndモジュールを新しくする。
Python(PyMySQL / mysql-connector-python)
import pymysql
try:
conn = pymysql.connect(
host='localhost',
user='app_user',
password='password',
database='appdb'
)
except pymysql.err.OperationalError as e:
if e.args[0] == 1045:
print("ERROR 1045: 認証失敗")
print("- パスワード確認")
print("- 'user'@'host' の組み合わせ確認")
print(f"- 接続元IP: {e}")
Java(JDBC)
String url = "jdbc:mysql://localhost:3306/appdb?useSSL=false";
try {
Connection conn = DriverManager.getConnection(url, "app_user", "password");
} catch (SQLException e) {
if (e.getErrorCode() == 1045) {
System.err.println("ERROR 1045: 認証失敗");
System.err.println("確認事項:");
System.err.println("- パスワード");
System.err.println("- ユーザーのホスト指定");
System.err.println("- mysql_native_password vs caching_sha2_password");
}
}
JDBC ドライバの選択:
- MySQL 5.7まで:
mysql-connector-java5.1.x または 8.x - MySQL 8.0以降:
mysql-connector-j8.0.x(旧名 mysql-connector-java は廃止)
Node.js(mysql2)
const mysql = require('mysql2/promise');
try {
const conn = await mysql.createConnection({
host: 'localhost',
user: 'app_user',
password: 'password',
database: 'appdb'
});
} catch (err) {
if (err.errno === 1045) {
console.error('ERROR 1045 - 認証失敗');
console.error('原因候補:', err.message);
}
}
mysql2はcaching_sha2_passwordに対応していますが、古いmysqlパッケージは未対応。マイグレーションが必要です。
.NET(MySql.Data)
using MySql.Data.MySqlClient;
string connStr = "server=localhost;user=app;password=secret;database=appdb;";
try {
using var conn = new MySqlConnection(connStr);
conn.Open();
} catch (MySqlException ex) when (ex.Number == 1045) {
Console.WriteLine("認証エラー: ユーザー/パスワード/ホスト確認");
}
関連エラーと違い
ERROR 1044 (42000): Access denied for user to database
接続認証は成功したが、特定データベースへの権限がない場合。
GRANT ALL ON dbname.* TO 'user'@'host';
FLUSH PRIVILEGES;
ERROR 1142: command denied to user
特定操作の権限がない。例: SELECT権限はあるがDELETE権限がない。
GRANT DELETE ON dbname.tablename TO 'user'@'host';
ERROR 2003: Can’t connect to MySQL server
そもそもサーバーに到達できない。1045とは別物(ネットワーク、bind-address、ポート問題)。
ERROR 2059: Authentication plugin ‘caching_sha2_password’ cannot be loaded
クライアント側がcaching_sha2_passwordプラグインを認識できない。対処:
- クライアントドライバ更新
- またはサーバー側で
mysql_native_passwordに変更
ERROR 1396: Operation CREATE USER failed
既に同じユーザーが存在する。
-- 存在確認
SELECT user, host FROM mysql.user WHERE user = 'app';
-- 削除してから再作成
DROP USER 'app'@'%';
CREATE USER 'app'@'%' IDENTIFIED BY 'pass';
セキュリティ・運用ベストプラクティス
ERROR 1045 を回避しつつ、安全な運用を実現するための指針です。
1. root はリモートから繋がない
-- root のホストは localhost のみに限定
SELECT user, host FROM mysql.user WHERE user = 'root';
-- リモート可能な root エントリは削除
DROP USER 'root'@'%';
2. アプリケーションごとに専用ユーザー
-- 各アプリ用ユーザーを最小権限で作成
CREATE USER 'webapp'@'10.0.1.%' IDENTIFIED BY 'WebAppP@ss2026';
GRANT SELECT, INSERT, UPDATE, DELETE ON webdb.* TO 'webapp'@'10.0.1.%';
CREATE USER 'batch'@'10.0.2.%' IDENTIFIED BY 'BatchP@ss2026';
GRANT SELECT ON webdb.* TO 'batch'@'10.0.2.%';
3. パスワードの定期更新
-- パスワード有効期限を90日に
ALTER USER 'webapp'@'10.0.1.%' PASSWORD EXPIRE INTERVAL 90 DAY;
4. 接続元IPの範囲を厳格化
-- ❌ 開発のみ
'app'@'%'
-- ✅ 本番(社内ネットワークから限定)
'app'@'10.0.0.0/255.0.0.0'
ただしMySQLのhostはCIDR非対応で、10.%等のワイルドカードで指定します。
5. 匿名ユーザー・テストDBの削除
DELETE FROM mysql.user WHERE user = '';
DROP DATABASE IF EXISTS test;
FLUSH PRIVILEGES;
mysql_secure_installationコマンドで自動的に行えます。
6. パスワードポリシーの強化
SET GLOBAL validate_password.policy = STRONG;
SET GLOBAL validate_password.length = 12;
7. 失敗ログイン試行の監視
general_logを一時的に有効化して、認証失敗を観測:
SET GLOBAL general_log = 'ON';
SET GLOBAL log_output = 'TABLE';
-- 失敗ログの確認
SELECT * FROM mysql.general_log WHERE argument LIKE '%Access denied%';
トラブルシューティング・チェックリスト
ERROR 1045 が出た時に上から順にチェック:
- エラーメッセージから
'user'@'host'を確認 (using password: YES/NO)を確認- MySQL サーバー上で
SELECT user, host FROM mysql.user実行 - 該当ユーザーが存在するか、ホスト指定が一致するか確認
- パスワード再設定で接続テスト
- MySQL 8.0以降なら認証プラグインを確認
skip-name-resolve、bind-address設定確認- Docker環境なら
MYSQL_ROOT_HOSTを確認 - クラウドDBならセキュリティグループ・ファイアウォール確認
- クライアントドライバが新しい認証方式に対応しているか確認
よくある質問(FAQ)
Q1. ローカルでは繋がるのにアプリから接続できません
ユーザーのホスト指定が問題の可能性が高いです。アプリサーバーから見たMySQLサーバー上での「アプリのIPアドレス」を確認:
-- 接続失敗時のエラーメッセージから 'user'@'host' を確認
-- そのホストでユーザーが登録されているか確認
SELECT user, host FROM mysql.user WHERE user = 'app';
Q2. (using password: NO) と表示されます
パスワードが空文字、または送信されていません:
# パスワード忘れ
mysql -u app # ❌
# パスワード指定
mysql -u app -p # ✅
Q3. MySQL 8 にアップグレード後、PHPアプリが繋がらなくなりました
caching_sha2_passwordへのプラグイン変更が原因の可能性大。mysql_native_passwordに変更:
ALTER USER 'app'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
長期的にはPHPのmysqlndモジュール更新を推奨。
Q4. root のパスワードを変更したらどこからも繋がらなくなりました
ALTER USER でホスト指定をミスした可能性:
-- 全rootエントリ確認
SELECT user, host, plugin FROM mysql.user WHERE user = 'root';
'root'@'localhost'以外のエントリにパスワード設定したかも。本記事のrootパスワードリセット手順で復旧。
Q5. ユーザーが存在するのに接続できません
主な原因:
- ホスト指定(
'user'@'localhost'vs'user'@'%')が違う - パスワードが間違っている
- 認証プラグインがクライアント未対応
SELECT user, host, plugin FROM mysql.user WHERE user = 'app';
の結果で確認してください。
Q6. SSL関連でエラーが出ます
MySQL 8.0以降、デフォルトでSSL要求があります:
# SSLを無効化(開発のみ)
mysql -u app -p --ssl-mode=DISABLED
# クライアント側で対応
JDBCの場合:
jdbc:mysql://host:3306/db?useSSL=false&allowPublicKeyRetrieval=true
Q7. Docker でMySQLに繋がりません
最頻出原因は 'root'@'localhost' のみ作成され、ホスト側から繋ぐ際の 'root'@'172.17.0.1'等の組み合わせがないこと。本記事のDocker環境セクションを参照。
Q8. AWS RDS に接続できなくなりました
確認順:
- RDSインスタンスは起動しているか(Available状態)
- セキュリティグループに自分のIPが許可されているか
- パブリックアクセスが「あり」になっているか(VPC外接続の場合)
- マスターパスワードを正しく覚えているか
- エンドポイント(URL)が正しいか
Q9. mysql_native_password が使えないバージョンがあるの?
MySQL 8.4以降はmysql_native_passwordがデフォルトで無効化されています:
# my.cnf に追加で復活
[mysqld]
mysql_native_password=ON
ただし将来的には完全削除される予定なので、クライアント更新が本筋です。
Q10. /tmp/mysql.sock で繋がりません
ソケットファイルパスが違う可能性:
SHOW VARIABLES LIKE 'socket';
クライアント側でも合わせる:
mysql -u root -p --socket=/var/run/mysqld/mysqld.sock
my.cnfに永続化:
[client]
socket=/var/run/mysqld/mysqld.sock
Q11. アプリのパスワード変更後、しばらくして接続できなくなります
接続プールに古い認証情報が残っている可能性。アプリ再起動で解決します。
Q12. パスワードを忘れたが MySQL の停止ができません
本番稼働中で停止できない場合の選択肢:
- 別ユーザーで SUPER 権限を持つアカウントを使う
- レプリカDBで作業し、後でフェイルオーバー
- どうしても無理ならメンテナンス時間を確保して手順実行
クラウドマネージドDB(RDS等)ならコンソールから即時変更可能です。
参考リンク・関連資料
MySQL公式ドキュメント
- MySQL 8.0 Reference – Access Denied Errors – 公式トラブルシューティング
- MySQL 8.0 Reference – Authentication Plugins – 認証プラグイン
- MySQL 8.0 Reference – CREATE USER – ユーザー作成
- MySQL 8.0 Reference – GRANT – 権限付与
- MySQL 8.0 Reference – Resetting the Root Password – rootパスワードリセット
MariaDB
- MariaDB – GRANT – MariaDBでの権限管理
- MariaDB – User Account Management – ユーザー管理
クライアントドライバ
- MySQL Connector/J Documentation – Java JDBC
- MySQL Connector/Python – Python公式
- PyMySQL – Python代替実装
- mysql2 (Node.js) – Node.js
- MySQL Connector/NET – .NET
Docker / クラウド
- Docker Hub – MySQL – 公式Dockerイメージ
- AWS RDS MySQL – AWS RDS公式
- Google Cloud SQL for MySQL – GCP公式
- Azure Database for MySQL – Azure公式
関連エラー記事(本サイト)
- 「Address already in use」エラーの対処法 – ポート競合
- SSH「Host key verification failed」エラーの対処 – SSH認証エラー
- Docker「no space left on device」エラーの対処 – Docker容量問題
- ORA-01017: invalid username/password エラー対処 – Oracle認証エラー(類似)
まとめ
MySQL ERROR 1045 は、シンプルなメッセージとは裏腹に10以上の原因があります。要点を再整理します。
- MySQL認証の鍵: 「ユーザー名+ホスト指定」のペアで管理(他DBと違う)
- エラーメッセージから情報を読む:
'user'@'host' (using password: YES/NO)から原因を絞り込む - 最頻出はホスト指定不一致:
'user'@'localhost'と'user'@'%'は別ユーザー - MySQL 8.0以降:
caching_sha2_passwordと古いクライアントの互換性問題が頻発 - rootパスワード忘れ:
--skip-grant-tablesモードでリセット可能 - Docker:
MYSQL_ROOT_HOST=%または別ユーザー作成 - クラウド: セキュリティグループ・ファイアウォール・マスターユーザー設定
- セキュリティ: 最小権限の原則、ホスト範囲限定、パスワードポリシー強化
これらの知識は、Webアプリ開発・データベース管理・本番運用・トラブル対応など、MySQL を扱うあらゆる場面で必須です。本記事をブックマークしておけば、ERROR 1045 に遭遇した時の対応が大幅に効率化されます。
本記事は2026年6月時点の情報をもとに、MySQL 5.7 / 8.0 / 8.4 および MariaDB 10.x / 11.x での動作確認・公式ドキュメントに基づき作成しています。バージョンによってデフォルト動作が異なる場合があるため、最新の情報はMySQL公式ドキュメントもあわせてご確認ください。
-
前の記事
ORA-00060: deadlock detected エラーの原因と対処法|Oracleデッドロックの仕組み 2026.06.16
-
次の記事
「Address already in use」エラーの原因と対処法|ポート競合の解決方法を環境別に徹底解説 2026.06.17
コメントを書く