- MySQL
MySQLエラーコード一覧と対処法|ERROR 1045・2002の原因別解決
MySQLのエラーコードとは、ERROR 1045 (28000): Access denied ... のように「番号・SQLSTATE・メッセージ」の3点で原因を示す識別子です。 1000〜1999 と 3000番台以降がサーバー側のエラー、2000番台がクライアント(接続ライブラリ)側のエラーです。番号から原因の分類がわかるので、まず番号を見て、どの層の問題かを決めると解決が早くなります。
この記事では、よく出るエラー約50件を 接続・認証/権限/構文/制約/データ/ロック/容量・設定 に分けた一覧表にし、そのうち40件以上を MySQL 8.0.46 で実際に再現したエラー全文 つきで掲載します。特に検索の多い ERROR 1045・2002・2003 は、ソケットパス・ホスト・ポート・認証プラグイン・bind-address の順に切り分けるフローで整理しました。
MySQLエラーコード早見表(よく出る順)
| コード | SQLSTATE | メッセージ(要約) | 主な原因 | 最初にやること |
|---|---|---|---|---|
| 1045 | 28000 | Access denied for user (using password: YES/NO) | パスワード違い、ホスト照合違い | SELECT user,host FROM mysql.user |
| 2002 | HY000 | Can't connect to local MySQL server through socket | サーバー停止、ソケットパス違い | -h127.0.0.1 で TCP 接続を試す |
| 2003 | HY000 | Can't connect to MySQL server on 'host:port' | ポート違い、bind-address、FW | ss -lntp | grep mysqld |
| 1064 | 42000 | You have an error in your SQL syntax ... near '...' | 構文ミス、予約語 | near の直前を見る |
| 1062 | 23000 | Duplicate entry 'x' for key 'k' | 主キー・UNIQUE重複 | 既存行を確認、UPSERT |
| 1452 | 23000 | Cannot add or update a child row | 親行がない外部キー | 親を先に INSERT |
| 1406 | 22001 | Data too long for column | 文字数超過 | 列を広げる・入力を検証 |
| 1366 | HY000 | Incorrect integer/string value | 型違い、4バイト文字 | 型と文字コードを確認 |
| 1213 | 40001 | Deadlock found when trying to get lock | ロック順序の交差 | トランザクションを再実行 |
| 1205 | HY000 | Lock wait timeout exceeded | 長いトランザクション | ロック保持者を特定 |
| 1290 | HY000 | running with the --xxx option | read_only・secure_file_priv | オプション名を読む |
| 1142 | 42000 | XXX command denied ... for table | テーブル単位の権限不足 | GRANT を追加 |
| 1040 | 08004 | Too many connections | 接続数上限 | max_connections・接続プール |
番号の範囲で層がわかります。 1000〜1999・3000〜は「サーバーまで届いたうえでの拒否」、2000番台は「サーバーまで届いていない」ことを示します。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「MySQLエラーコード一覧と対処法|ERROR 1045・2002の原因別解決」
検証環境とバージョン
| 項目 | 内容 |
|---|---|
| MySQL | 8.0.46(Ubuntu パッケージ、ポート 7246、ソケット指定で起動) |
| sql_mode | 8.0 既定(STRICT_TRANS_TABLES・ONLY_FULL_GROUP_BY など) |
MySQL 8.0 は2026年4月にサポートが終了しています。 この記事のエラー番号と対処は、MySQL 8.4 LTS・9.7 LTS でも同じ手順で使えます。8.4 以降は mysql_native_password が既定で無効(9.x では削除)のため、古いクライアントでは認証プラグイン関連のエラー(2059 など)が出やすくなる点だけ違いがあります。本文の「実行結果」は、すべて手元の 8.0.46 で再現したものです。
エラーの読み方と perror での確認
| 部分 | 意味 | 使いどころ |
|---|---|---|
| 番号(1062) | MySQL 固有のエラー番号 | 検索・一覧表で原因を引く |
| SQLSTATE(23000) | 標準SQLの分類。先頭2文字がクラス | アプリ側で分類して処理を分ける |
| メッセージ | 値やキー名が入った説明 | どの行・列が原因かを特定 |
SQLSTATE の先頭2文字は、アプリで処理を分けるときに使えます。
| クラス | 意味 | 例 |
|---|---|---|
| 08 | 接続の例外 | 1040(08004)、1153(08S01) |
| 22 | データの例外 | 1406(22001)、1264(22003)、1292(22007) |
| 23 | 整合性制約違反 | 1062、1452、1451、1048(すべて 23000) |
| 28 | 認証エラー | 1045(28000) |
| 40 | トランザクションのロールバック | 1213(40001) |
| 42 | 構文・権限 | 1064、1146(42S02)、1054(42S22)、1142 |
perror コマンドでサーバー側のエラー番号の定義を確認できます。
perror 1045 1213
MySQL error code MY-001045 (ER_ACCESS_DENIED_ERROR): Access denied for user '%-.48s'@'%-.64s' (using password: %s)
MySQL error code MY-001213 (ER_LOCK_DEADLOCK): Deadlock found when trying to get lock; try restarting transaction
なお perror 2002 は Illegal error code: 2002 になりました。2000番台はクライアントライブラリのエラーなので、perror の対象外です。公式リファレンスの「Client Error Message Reference」で確認します。
分類別エラーコード一覧(約50件)
「再現」列が ○ のものは、この記事の環境で実際に発生させたエラーです。
接続・認証
| コード | SQLSTATE | メッセージ | 主な原因 | 対処 | 再現 |
|---|---|---|---|---|---|
| 1045 | 28000 | Access denied for user 'u'@'h' (using password: YES) | パスワード違い、ホスト照合違い | 下の切り分けフロー | ○ |
| 1045 | 28000 | ... (using password: NO) | パスワードを送っていない | -p を付ける、設定ファイル確認 |
○ |
| 2002 | HY000 | Can't connect to local MySQL server through socket '...' (2) | 停止中、ソケットパス違い | 起動確認、-S か -h127.0.0.1 |
○ |
| 2003 | HY000 | Can't connect to MySQL server on 'h:p' (111) | ポートで待ち受けていない | ポート・bind-address 確認 | ○ |
| 2005 | HY000 | Unknown MySQL server host 'x' | ホスト名を解決できない | ホスト名・DNS・hosts を確認 | ○ |
| 1130 | HY000 | Host 'h' is not allowed to connect | 接続元に合うアカウントがない | 接続元ホストでユーザー作成 | perror で確認 |
| 1049 | 42000 | Unknown database 'x' | DB名違い | SHOW DATABASES |
○ |
| 1040 | 08004 | Too many connections | max_connections 超過 |
接続プール、解放漏れ確認 | ○ |
| 2061 | HY000 | caching_sha2_password ... requires secure connection | 非TLSで初回認証 | TLS接続、--get-server-public-key |
別記事で再現 |
| 2059 | HY000 | Authentication plugin '...' cannot be loaded | クライアントが認証方式に未対応 | ドライバ更新 | 公式で確認 |
| 1820 | HY000 | You must reset your password | パスワード期限切れ | ALTER USER USER() IDENTIFIED BY |
別記事で再現 |
| 3118 | HY000 | Account is locked | ACCOUNT LOCK 中 |
ACCOUNT UNLOCK |
別記事で再現 |
| 3955 | HY000 | Account is blocked ... consecutive failed logins | 連続失敗ロック | ACCOUNT UNLOCK |
別記事で再現 |
| 4031 | HY000 | disconnected by the server because of inactivity | wait_timeout 超過 |
再接続、プールの検証設定 | ○ |
| 2013 | HY000 | Lost connection to MySQL server during query | 実行中の切断、タイムアウト | ネットワーク・net_read_timeout |
公式で確認 |
| 2006 | HY000 | MySQL server has gone away | 切断後の再利用、巨大パケット | 再接続、max_allowed_packet |
公式で確認 |
権限
| コード | SQLSTATE | メッセージ | 主な原因 | 対処 | 再現 |
|---|---|---|---|---|---|
| 1044 | 42000 | Access denied for user ... to database 'x' | DB単位の権限なし | GRANT ... ON db.* |
○ |
| 1142 | 42000 | CREATE command denied ... for table 'x' | テーブル操作の権限なし | 必要な操作だけ GRANT | ○ |
| 1143 | 42000 | command denied ... for column | カラム権限なし | 列を明示、権限追加 | 別記事で再現 |
| 1227 | 42000 | you need (at least one of) the SUPER or SYSTEM_VARIABLES_ADMIN privilege(s) | 管理権限なし | 動的権限を付与 | ○ |
| 1290 | HY000 | running with the --read-only option | 読み取り専用サーバー | 書き込み先(プライマリ)を確認 | ○ |
| 1290 | HY000 | running with the --secure-file-priv option | 許可外のパスへ出力 | @@secure_file_priv のパスを使う |
○ |
ユーザー作成と権限付与の手順は、別記事「MySQLユーザー作成と権限付与」で詳しく扱っています。
構文・名前
| コード | SQLSTATE | メッセージ | 主な原因 | 対処 | 再現 |
|---|---|---|---|---|---|
| 1064 | 42000 | You have an error in your SQL syntax ... near '...' | 綴り、予約語、カンマ | near の直前を見る |
○ |
| 1046 | 3D000 | No database selected | DB未選択 | USE db か db.table |
○ |
| 1146 | 42S02 | Table 'db.t' doesn't exist | テーブル名違い | SHOW TABLES |
○ |
| 1054 | 42S22 | Unknown column 'x' in 'field list' | 列名違い | DESC t |
○ |
| 1052 | 23000 | Column 'id' in field list is ambiguous | JOIN で同名列 | テーブル.列 で修飾 |
○ |
| 1050 | 42S01 | Table 'x' already exists | 二重作成 | IF NOT EXISTS |
○ |
| 1051 | 42S02 | Unknown table 'db.x' | ないテーブルを DROP | IF EXISTS |
○ |
| 1060 | 42S21 | Duplicate column name 'x' | 同名列の追加 | 列名変更 | ○ |
| 1091 | 42000 | Can't DROP 'x'; check that column/key exists | ない索引・列の削除 | SHOW INDEX |
○ |
| 1136 | 21S01 | Column count doesn't match value count | 列数と値の数が違う | 列リストを明示 | ○ |
| 1055 | 42000 | ... incompatible with sql_mode=only_full_group_by | GROUP BY にない列 | 集約関数か GROUP BY に追加 | ○ |
| 1242 | 21000 | Subquery returns more than 1 row | = に複数行 |
IN か LIMIT 1 |
○ |
| 1093 | HY000 | You can't specify target table 'x' for update in FROM clause | 更新対象を副問い合わせで参照 | JOIN に書き換え | ○ |
| 1305 | 42000 | FUNCTION db.x does not exist | 関数名違い・未作成 | 名前・DB を確認 | ○ |
| 3141 | 22032 | Invalid JSON text in argument 1 | 不正な JSON | JSON_VALID() で事前確認 |
○ |
制約・データ
| コード | SQLSTATE | メッセージ | 主な原因 | 対処 | 再現 |
|---|---|---|---|---|---|
| 1062 | 23000 | Duplicate entry 'x' for key 't.k' | 主キー・UNIQUE 重複 | UPSERT、事前チェック | ○ |
| 1452 | 23000 | Cannot add or update a child row | 親行がない | 親を先に登録 | ○ |
| 1451 | 23000 | Cannot delete or update a parent row | 子行が参照中 | 子を先に削除、ON DELETE |
○ |
| 1048 | 23000 | Column 'x' cannot be null | NOT NULL 列に NULL | 値を入れる、DEFAULT | ○ |
| 3819 | HY000 | Check constraint 'x' is violated | CHECK 制約違反 | 値の範囲を確認 | ○ |
| 1406 | 22001 | Data too long for column 'x' | 文字数超過 | 列を広げる、入力検証 | ○ |
| 1366 | HY000 | Incorrect integer value: 'abc' | 型が違う値 | アプリ側で型変換 | ○ |
| 1366 | HY000 | Incorrect string value: '\xF0\x9F...' | utf8mb3 列に4バイト文字 | 列を utf8mb4 に | ○ |
| 1264 | 22003 | Out of range value for column 'x' | 型の範囲外 | 型を広げる | ○ |
| 1292 | 22007 | Incorrect date value: '2026-02-30' | 存在しない日付 | 日付を検証 | ○ |
| 1690 | 22003 | BIGINT UNSIGNED value is out of range | UNSIGNED の引き算で負数 | CAST(... AS SIGNED) |
○ |
| 3780 | HY000 | Referencing column and referenced column ... are incompatible | 外部キーの型不一致 | 型・符号・照合順序をそろえる | ○ |
| 1824 | HY000 | Failed to open the referenced table 'x' | 参照先がない | 親テーブルを先に作る | ○ |
ロック・トランザクション
| コード | SQLSTATE | メッセージ | 主な原因 | 対処 | 再現 |
|---|---|---|---|---|---|
| 1213 | 40001 | Deadlock found when trying to get lock | ロック順序の交差 | 再実行、更新順をそろえる | ○ |
| 1205 | HY000 | Lock wait timeout exceeded | 他トランザクションが保持 | 保持者を特定、短く分割 | ○ |
| 1175 | HY000 | You are using safe update mode | キーなし UPDATE/DELETE | WHERE にキー列 | ○ |
容量・設定
| コード | SQLSTATE | メッセージ | 主な原因 | 対処 | 再現 |
|---|---|---|---|---|---|
| 1153 | 08S01 | Got a packet bigger than 'max_allowed_packet' bytes | 巨大な SQL・BLOB | max_allowed_packet を上げる |
○ |
| 1118 | 42000 | Row size too large ... 65535 | VARCHAR 合計が大きすぎ | TEXT へ変更 | ○ |
| 1071 | 42000 | Specified key was too long; max key length is 3072 bytes | 索引が長すぎ | プレフィックス長を短く | ○ |
| 1114 | HY000 | The table 'x' is full | ディスク・一時領域不足 | 容量確認 | 公式で確認 |
ERROR 1045・2002・2003 の切り分けフロー
flowchart TD
A[接続エラー] --> B{エラー番号}
B -->|2002| C[ソケット接続で失敗]
B -->|2003| D[TCPで失敗]
B -->|2005| E[ホスト名を解決できない]
B -->|1045| F[サーバーには届いた・認証で拒否]
C --> C1{サーバーは起動している?}
C1 -->|いいえ| C2[起動してエラーログを見る]
C1 -->|はい| C3[@@socket と -S のパスを合わせる / -h127.0.0.1 で TCP に]
D --> D1{ポートで待ち受けている?}
D1 -->|いいえ| D2[port / bind-address / skip-networking を確認]
D1 -->|はい| D3[ファイアウォール・Docker のポート公開を確認]
F --> F1{using password: NO?}
F1 -->|はい| F2[-p を付ける / 設定ファイルを確認]
F1 -->|いいえ| F3[同名ユーザーの host 違い・パスワード・認証プラグインを確認]
ERROR 2002:ソケットパスの違い
# 存在しないソケットを指定
mysql -uroot -S /tmp/nosuch.sock -e "SELECT 1"
# -h localhost は TCP ではなく既定のソケットを使う
mysql -uroot -h localhost -P 7246 -e "SELECT 1"
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/nosuch.sock' (2)
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock' (2)
-h localhost はポートを指定してもソケット接続になります。 2つ目はサーバーが別のソケット(/tmp/t124my/mysql.sock)で動いているのに、クライアントが既定の /var/run/mysqld/mysqld.sock を探したため失敗しました。括弧内の (2) は OS のエラー番号で「ファイルがない」という意味です。
| 対処 | コマンド |
|---|---|
| サーバー側のソケットパスを確認 | SELECT @@socket;(接続できる別経路で) |
| ソケットを明示する | mysql -S /tmp/t124my/mysql.sock |
| TCP で接続する | mysql -h 127.0.0.1 -P 3306 |
| 設定ファイルでそろえる | [client] と [mysqld] の socket= を同じにする |
ERROR 2003:ポートと bind-address
mysql -uroot -h 127.0.0.1 -P 7249 -e "SELECT 1"
ERROR 2003 (HY000): Can't connect to MySQL server on '127.0.0.1:7249' (111)
(111) は「接続拒否(そのポートで誰も待ち受けていない)」です。タイムアウトする場合は (110) になり、ファイアウォールなどで通信が届いていない可能性が高くなります。
SELECT @@port, @@bind_address, @@skip_networking;
今回の環境では @@bind_address は 127.0.0.1 でした。この設定では同じマシンからしか TCP 接続できません。 別のマシンやコンテナの外から接続するには、bind-address = 0.0.0.0(または特定のIP)に変えて再起動し、接続元に合わせたユーザー('app'@'10.0.1.%' など)を用意します。
ERROR 1045:認証で拒否された
ERROR 1045 (28000): Access denied for user 'app'@'localhost' (using password: YES)
ERROR 1045 (28000): Access denied for user 'app'@'localhost' (using password: NO)
1045 はサーバーまで届いている証拠です。 ネットワークではなくアカウント側を確認します。
| チェック | SQL・ポイント |
|---|---|
| どのアカウントに照合されたか | エラー文の 'app'@'localhost' を読む |
| 同名ユーザーが複数ホストにないか | SELECT user, host, plugin FROM mysql.user WHERE user='app'; |
| パスワードを送ったか | using password: NO なら -p や設定ファイルの password= を確認 |
| 認証プラグイン・ロック | plugin・account_locked・password_expired 列 |
今回の環境では、ユーザーを 'remote'@'10.9.9.%' だけで作って 127.0.0.1 から接続すると、1130 ではなく 1045('remote'@'localhost')になりました。接続元のホスト名が解決できる環境では、「接続元に合うアカウントがない」場合も 1045 として表示されることがあります。
root のパスワードがわからなくなったときの再設定手順(--skip-grant-tables や --init-file)は、公式ドキュメント「How to Reset the Root Password」に沿って行ってください。
よく出るエラーの再現と直し方
ここからは、次のテーブルを使って再現しています。
CREATE DATABASE errdb;
USE errdb;
CREATE TABLE members (
id INT PRIMARY KEY,
email VARCHAR(20) NOT NULL UNIQUE,
name VARCHAR(10),
age TINYINT UNSIGNED,
joined DATE,
CHECK (age < 150)
);
CREATE TABLE orders (
id INT PRIMARY KEY AUTO_INCREMENT,
member_id INT NOT NULL,
qty INT,
FOREIGN KEY (member_id) REFERENCES members(id)
);
CREATE TABLE stock (id INT PRIMARY KEY, qty INT);
INSERT INTO members VALUES (1,'a@example.com','Aoki',30,'2026-01-01'),
(2,'b@example.com','Baba',40,'2026-02-01');
INSERT INTO orders (member_id, qty) VALUES (1, 2);
INSERT INTO stock VALUES (1,10),(2,20);
1062:重複キー
INSERT INTO members VALUES (3,'a@example.com','Chiba',20,'2026-03-01');
ERROR 1062 (23000): Duplicate entry 'a@example.com' for key 'members.email'
8.0 からはキー名が テーブル名.キー名 で表示されるので、どの UNIQUE に当たったかがすぐわかります。 「あれば更新、なければ追加」にしたいときは UPSERT を使います(詳細は別記事「SQL UPSERTの書き方」)。
INSERT INTO members VALUES (3,'a@example.com','Chiba',20,'2026-03-01') AS new
ON DUPLICATE KEY UPDATE name = new.name;
1452・1451:外部キー
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`errdb`.`orders`, CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`member_id`) REFERENCES `members` (`id`))
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails (`errdb`.`orders`, CONSTRAINT `orders_ibfk_1` FOREIGN KEY (`member_id`) REFERENCES `members` (`id`))
| エラー | 起きた操作 | 直し方 |
|---|---|---|
| 1452 | orders に存在しない member_id=99 を INSERT |
親(members)を先に登録する |
| 1451 | 注文が残っている members.id=1 を DELETE |
子を先に削除、または ON DELETE CASCADE を設計で検討 |
データ移行で SET FOREIGN_KEY_CHECKS=0; を使った場合は、移行後に =1 へ戻し、LEFT JOIN ... WHERE 親.id IS NULL で孤立行がないかを確認します。
1406・1366・1264・1292:値が列に合わない
ERROR 1406 (22001): Data too long for column 'name' at row 1
ERROR 1366 (HY000): Incorrect integer value: 'abc' for column 'age' at row 1
ERROR 1264 (22003): Out of range value for column 'age' at row 1
ERROR 1292 (22007): Incorrect date value: '2026-02-30' for column 'joined' at row 1
8.0 の既定 sql_mode には STRICT_TRANS_TABLES が含まれるため、合わない値は切り捨てずにエラーになります。 1264 は TINYINT UNSIGNED(0〜255)に 300 や -1 を入れたときに出ました。sql_mode を緩めると値が丸められて保存されるので、列の型か入力検証で直すのが確実です。
1366:4バイト文字(絵文字)
CREATE TABLE notes3 (body VARCHAR(20) CHARACTER SET utf8mb3);
INSERT INTO notes3 VALUES ('OK😀');
ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x98\x80' for column 'body' at row 1
\xF0 で始まる値は4バイト文字です。 utf8mb3(旧 utf8)は3バイトまでしか保存できないため、列を utf8mb4 に変更します。次の ALTER の後は同じ INSERT が成功し、HEX(body) は 4F4BF09F9880 になりました。
ALTER TABLE notes3 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
なお検証中、mysql -e をロケール未設定のシェルから実行したところ character_set_client が latin1 になり、エラーにならずに崩れた値が保存されました。クライアント側は --default-character-set=utf8mb4 を指定すると確実です。 文字化けの見分け方は別記事「文字化けの原因と直し方」を参照してください。
1064:構文エラー
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELEC * FROM members' at line 1
near '...' に表示された文字列の「直前」が原因の場所です。 よくある原因は次のとおりです。
| 原因 | 例 | 直し方 |
|---|---|---|
| 綴り | SELEC |
SELECT |
| 予約語を名前に使う | CREATE TABLE order (...) |
`order` とバッククォートで囲む |
| 末尾のカンマ | SELECT id, name, FROM t |
最後のカンマを消す |
| 8.0 で廃止された書き方 | GRANT ... IDENTIFIED BY |
CREATE USER と分ける |
1146・1054・1052:名前の間違い
ERROR 1146 (42S02): Table 'errdb.member' doesn't exist
ERROR 1054 (42S22): Unknown column 'nam' in 'field list'
ERROR 1052 (23000): Column 'id' in field list is ambiguous
Linux では既定でテーブル名の大文字・小文字が区別されます(lower_case_table_names=0)。1052 は JOIN で両方のテーブルに id があるときに出るので、members.id のように修飾します。
1055:ONLY_FULL_GROUP_BY
ERROR 1055 (42000): Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'errdb.orders.qty' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by
-- 直す前
SELECT member_id, qty FROM orders GROUP BY member_id;
-- 直した後(集約するか、GROUP BY に含める)
SELECT member_id, SUM(qty) AS total_qty FROM orders GROUP BY member_id;
どの行の qty を返すかが決まらないため、エラーになります。 どれでもよい場合は ANY_VALUE(qty) も使えます。
1093:更新対象を副問い合わせで参照
ERROR 1093 (HY000): You can't specify target table 'members' for update in FROM clause
-- 直す前
UPDATE members SET age = age + 1
WHERE id IN (SELECT id FROM members WHERE age > 35);
-- 直した後(JOIN に書き換え):検証環境で2行更新
UPDATE members m
JOIN (SELECT id FROM members WHERE age > 35) t ON m.id = t.id
SET m.age = m.age + 1;
1213・1205:デッドロックとロック待ちタイムアウト
2つのセッションで stock の id=1 と id=2 を逆の順番で更新すると、片方が 1213 になりました。
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
片方のセッションがロックを持ったまま、もう片方が innodb_lock_wait_timeout=3 で待つと 1205 になりました(既定値は 50 秒)。
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
| 項目 | 1213 デッドロック | 1205 ロック待ちタイムアウト |
|---|---|---|
| 起きること | InnoDB が片方を自動でロールバック | 待った側の文だけがエラー |
| トランザクション | 全体がロールバック済み | 既定では文だけ失敗、トランザクションは継続 |
| 対処 | トランザクション全体を再実行 | ロック保持者を特定し、トランザクションを短く |
| 調べ方 | SHOW ENGINE INNODB STATUS |
sys.innodb_lock_waits |
1205 の後はトランザクションが続いているので、ROLLBACK するか再実行するかをアプリ側で明示します。 再現手順とログの読み方は別記事「デッドロックの原因と対策」で詳しく扱っています。
1290:read_only と secure_file_priv
ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
1290 はメッセージ内のオプション名で原因が決まります。 read_only はレプリカや切り替え中のサーバーに書き込んだときに出るので、接続先を確認します。secure_file_priv は SELECT ... INTO OUTFILE や LOAD DATA INFILE で許可外のパスを使ったときに出ます。今回の環境の値は /var/lib/mysql-files/ でした。CSV の取り込み全般は別記事「MySQL CSVインポート」を参照してください。
1040・4031・1153:接続数・タイムアウト・パケット
ERROR 1040 (08004): Too many connections
ERROR 4031 (HY000): The client was disconnected by the server because of inactivity. See wait_timeout and interactive_timeout for configuring this behavior.
ERROR 1153 (08S01): Got a packet bigger than 'max_allowed_packet' bytes
| エラー | 再現した条件 | 対処 |
|---|---|---|
| 1040 | max_connections=2 で一般ユーザーが3本目を接続 |
接続プールの上限、解放漏れ、max_connections |
| 4031 | wait_timeout=2 のセッションで4秒放置後に実行 |
プールの接続検証、wait_timeout の調整 |
| 1153 | max_allowed_packet=1MB で約2MBの SQL を送信 |
サーバーとクライアント両方の値を上げる |
1040 の状態でも root では接続できました。CONNECTION_ADMIN(または SUPER)を持つユーザー用に1本分の予備枠があるため、管理者がログインして原因を調べられます。4031 は 8.0.24 以降のメッセージで、それ以前のクライアントでは 2013 や 2006 として表示されることがあります。
Docker・WSL・macOS(Homebrew)別の確認コマンド
このセクションのコマンドは、各環境の公式ドキュメントに沿って記載したもので、この記事の検証環境では実行していません。
| 環境 | 起動確認 | 接続のポイント | エラーログ |
|---|---|---|---|
| Linux(deb/apt) | systemctl status mysql |
既定ソケット /var/run/mysqld/mysqld.sock |
/var/log/mysql/error.log |
| Linux(rpm/dnf) | systemctl status mysqld |
既定ソケット /var/lib/mysql/mysql.sock |
/var/log/mysqld.log |
| Docker(公式イメージ) | docker ps、docker logs <コンテナ名> |
ホストからは -h 127.0.0.1 -P <公開ポート> |
標準出力(docker logs) |
| WSL2 | sudo service mysql status |
Windows 側からは 127.0.0.1 で接続 |
Linux(deb)と同じ |
| macOS(Homebrew) | brew services list |
既定ソケット /tmp/mysql.sock |
$(brew --prefix)/var/mysql/<ホスト名>.err |
Docker でよくある組み合わせ
# コンテナ内で接続(ソケット)
docker exec -it db mysql -uroot -p
# ホストから接続:localhost ではなく 127.0.0.1 を指定(2002 回避)
mysql -h 127.0.0.1 -P 3306 -uroot -p
# ポート公開を確認(2003 の切り分け)
docker port db
ホストから -h localhost で接続するとソケットを探して 2002 になります。 Docker では -h 127.0.0.1 と -p 3306:3306 のポート公開をセットで確認します。コンテナ間の接続では、ホスト名にサービス名(例:db)を使います。
エラーログの場所と見方
まずは SQL でログの場所を確認します。
SELECT @@log_error, @@log_error_verbosity, @@log_timestamps;
検証環境では /tmp/t124my/err.log、2、UTC でした。log_timestamps が UTC の場合、日本時間より9時間前の時刻で記録されます。
2026-10-01T15:55:26.780393Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.46-0ubuntu0.24.04.4' socket: '/tmp/t124my/mysql.sock' port: 7246 (Ubuntu).
2026-10-01T16:01:29.283836Z 132 [Note] [MY-010926] [Server] Access denied for user 'app'@'localhost' (using password: YES)
各行は「時刻(Z は UTC)・スレッドID・重要度(System/Warning/Note)・ログ用コード(MY-xxxxxx)・サブシステム・本文」の順です。
ログイン失敗(Access denied)は log_error_verbosity=3 のときだけ Note として記録されます。 既定の 2 では記録されないので、1045 の原因調査中だけ一時的に 3 に上げると便利です。
SET GLOBAL log_error_verbosity = 3; -- 調査後は 2 に戻す
8.0.22 以降は、エラーログを SQL で読むこともできます。
SELECT LOGGED, PRIO, ERROR_CODE, LEFT(DATA, 80) AS DATA
FROM performance_schema.error_log
ORDER BY LOGGED DESC LIMIT 3;
実行すると、上のログファイルと同じ内容が LOGGED(セッションのタイムゾーンで表示)・PRIO・ERROR_CODE・DATA の列で返りました。
どのエラーが何回起きたかは、performance_schema の集計表で確認できます。 アプリが出しているエラーの傾向をつかむのに役立ちます。
SELECT ERROR_NUMBER, ERROR_NAME, SQL_STATE, SUM_ERROR_RAISED
FROM performance_schema.events_errors_summary_global_by_error
WHERE SUM_ERROR_RAISED > 0
ORDER BY SUM_ERROR_RAISED DESC LIMIT 5;
検証環境では、上位に ER_ACCESS_DENIED_ERROR(1045、9回)や ER_TABLEACCESS_DENIED_ERROR(1142、5回)など、この記事で再現したエラーが並びました。
よくある質問
Q. ERROR 2002 と 2003 はどう違いますか?
A. 2002 はソケット(同じマシン内のファイル)での接続失敗、2003 は TCP(ホスト名・IPとポート)での接続失敗です。-h localhost はソケット、-h 127.0.0.1 は TCP になるので、片方で失敗したらもう片方を試すと原因を絞り込めます。
Q. ERROR 1045 でパスワードは合っているはずなのに入れません。
A. 同じユーザー名で localhost と % の両方のアカウントがあり、想定と違う方に照合されている可能性があります。エラー文の 'ユーザー'@'ホスト' と SELECT user, host FROM mysql.user を見比べてください。
Q. 1213 と 1205 はどちらもリトライすればよいですか? A. 1213 はトランザクション全体がロールバック済みなので、最初から再実行します。1205 は既定ではその文だけが失敗しているため、ROLLBACK してから再実行するか、待ちの原因を取り除いてから続行します。
Q. MySQL 8.4 や 9.7 でもエラー番号は同じですか? A. この記事で扱った番号とメッセージは、8.4・9.7 でも同じ意味で使われています。新しい版ではメッセージの文言が少し変わることがあるので、正確な文言は各版の「Server Error Message Reference」で確認してください。
まとめ
- 番号で層を判断:1000〜1999・3000〜はサーバー、2000番台はクライアント(届いていない)
- 2002 はソケット、2003 は TCP。
-h localhostと-h 127.0.0.1を切り替えて切り分ける - 1045 は届いたうえでの拒否。
'ユーザー'@'ホスト'の照合とパスワードを確認 - 制約系(1062・1452・1451・1048)は SQLSTATE 23000 でまとめて扱える
- 1213 は全体を再実行、1205 は ROLLBACK を明示
- エラーログは
@@log_error、SQL ならperformance_schema.error_log - 8.4・9.7でも同じ手順で使える。サーバーのエラーは
perrorで定義を確認
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「MySQLエラーコード一覧と対処法|ERROR 1045・2002の原因別解決」
株式会社RJCでは、MySQLのエラーの読み解き方を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。