MySQL 错误剖析
每个 MySQL 错误都由标识错误的以下部分组成:
ERROR NUMBER
是标识每个错误的唯一编号。SQLSTATE
是标识 SQL 错误情况的代码。ERROR MESSAGE
以人类可读的格式描述错误。
下面是一个 MySQL 错误示例:
1 | ERROR 1146 (42S02): Table 'test.no_such_table' doesn't exist |
在上面的示例中:
- 1146 是错误号
- 42S02 是 SQLSTATE
- 表 ‘test.no_such_table’ 不存在是错误消息
You have an error in your SQL syntax
1 | ERROR 1064 (42000): You have an error in your SQL syntax |
这意味着 MySQL 由于语法问题而无法理解您的查询。通常,问题的原因是忘记将某些文本或值括在反引号或引号中。例如,而不是在 MySQL 查询中使用数据库名称,因为它应该是 。my-databasemy-database
错误消息甚至会更进一步,并指出语法开始无效的位置,您可以将其用作寻找问题的起点。
💡 仔细检查您的查询,确保所有 SQL 语句的格式正确并遵循 MySQL 的语法规则。
连接问题
用户 ‘root‘@’localhost’ 的访问被拒绝(使用密码:YES)
1 | ERROR 1045: Access denied for user 'root'@'localhost' |
任何使用 MySQL 的人都可能至少遇到过一次。
此错误可能有多种原因,例如用户名和/或密码错误,或缺少对数据库的权限。
此错误表示 MySQL 服务器在尝试使用提供的密码从 ‘localhost’ 服务器进行连接时拒绝了对 ‘root’ 用户的访问。
💡要解决此问题,请仔细检查密码并确保用户具有必要的权限。
您可以重置密码或授予解决此问题所需的权限。
Lost connection to MySQL server during query
1 | ERROR 2013: Lost connection to MySQL server during query |
在连接被断开之后,客户端再次发送请求,导致的。需要重新来连接一下。
Too many connections
1 | ERROR 1040: Too many connections |
当 MySQL 服务器达到其允许的最大连接数限制时,会出现此错误。
💡 如果实际连接线程数过大,可以考虑增加服务器节点来分流;如果实际线程数并不算过大,那么可以配置 max_connections
来增加允许的最大连接数。需要注意的是,连接数不宜过大,一般来说,单库每秒有 2000 个并发连接时,就可以考虑扩容了,健康的状态应该维持在每秒 1000 个并发连接左右。
(1)查看最大连接数
1 | mysql> show variables like '%max_connections%'; |
(2)查看服务器响应的最大连接数
1 | mysql> show global status like 'Max_used_connections'; |
(3)临时设置最大连接数
1 | set GLOBAL max_connections=256; |
注意:当服务器重启时,最大连接数会被重置。
(4)永久设置最大连接数
修改 /etc/my.cnf
配置文件,在 [mysqld]
添加以下配置:
1 | max_connections=256 |
重启 mysql 以生效
(5)修改 Linux 最大文件数限制
设置了最大连接数,如果还是没有生效,考虑检查一下 Linux 最大文件数
Mysql 最大连接数会受到最大文件数限制,vim /etc/security/limits.conf
,添加 mysql 用户配置
1 | mysql hard nofile 65535 |
(6)检查 LimitNOFILE
如果是使用 rpm 方式安装 mysql,检查 mysqld.service 文件中的 LimitNOFILE
是否配置的太小。
MySQL server has gone away
1 | ERROR 2006 (HY000): MySQL server has gone away |
此错误表示 MySQL 服务器意外终止了连接。
这可能是由于各种原因造成的,包括长时间运行的查询或服务器超时。
💡 要防止这种情况,您可以在 MySQL 配置中调整 wait_timeout 和 interactive_timeout 设置。
MySQL client ran out of memory
1 | ERROR 2008: MySQL client ran out of memory |
当 MySQL 客户端消耗的内存超过可用内存时,会发生此错误。
💡 要解决此问题,您可能需要优化查询、限制结果集或为 MySQL 客户端分配更多内存。
查询问题
索引失效问题
eg:假设age是整数类型,但是却使用字符串类型
1 | SELECT * FROM user WHERE age = '20'; |
MySQL 需要在查询时转换 ‘20’ 为整数类型,可能会导致索引无法使用。 某个电商平台就有这么一个类似的bug,导致下单超时崩盘30分钟。
MySql 5.7 解决GROUP BY出现的问题
报错如下:
1 | 1055 - Expression #1 of SElECT list is not in GRoUp BY clause and contains nonaggregated column 'projhigh.project node.i whicn is not functionally dependent on columns in GROup BY clause; this is incompatible with sql mode=only_full_group_by |
引起的原因是:这个错误一般发生在mysql 5.7以及 5.7以上的版本中,其原因是mysql的默认配置中,sql_mode=”ONLY_FULL_GROUP_BY” 这个配置严格执行了 ‘SQL92标准’,所以很高网站维护人员在升级mysql版本时,都会修改 sql_mode 的配置,使其能兼容。
解决方法1,重启mysql后会失效:
1 | -- 查看ONLY_FULL_GROUP_BY 校验规则是否开启 |
解决方法2:
修改配置文件 my.ini
1 | 在 [mysqld] 下面添加代码: |
重启mysql服务。
注意:
1、不同的系统,mysql 的配置文件名以及路径不同
2、Mac或Linux文件 /etc/my.cnf
3、windows 在数据库安装目录下的 my.ini
空间问题
The table is full
1 | ERROR 1114 (HY000): The table is full |
如果发生 table-full 错误,则可能是磁盘已满或表已达到其最大大小。
MySQL 数据库的有效最大表大小通常由操作系统对文件大小的限制决定,而不是由 MySQL 内部限制决定。
💡 要解决此问题,您可以:
- 增加 MEMORY 表允许的最大大小
1 | [mysqld] |
- 切换到 InnoDB 存储引擎
- 检查磁盘空间并增加可用空间:
Packet too large
1 | ERROR: Packet too large |
当 MySQL 客户端或 mysqld 服务器获取的数据包大于max_allowed_packet字节,它会发出 Packet too large 错误并关闭连接。
1 GB 数据包大小是可以传输到 MySQL 服务器或客户端或从 MySQL 服务器或客户端传输的最大数据包大小。如果 MySQL 服务器或客户端收到大于 max_allowed_packet 字节的数据包,则发出 ER_NET_PACKET_TOO_LARGE 错误并关闭连接。
💡 您可以通过调整 MySQL 配置文件中的 max_allowed_packet 设置来解决此问题。
Can’t create/write to file
1 | ERROR: Can’t create/write to file |
当 MySQL 无法创建或写入文件时,通常会发生此错误,通常是由于权限不足或磁盘空间不足。
💡 确保 MySQL 用户具有必要的文件权限,并检查可用磁盘空间以解决此问题。
Packet for query is too large错误
1 | 在mysql安装目录中找到my.ini配置文件 |
数值可以 MB为单位,16M
数据库事务问题
Lock wait timeout exceeded; try restarting transaction
这是 MySQL 数据库中的一个常见错误,通常发生在使用 InnoDB 存储引擎的事务中。它的含义是:某个事务在尝试获取锁资源时,等待时间超过了数据库配置的阈值(innodb_lock_wait_timeout,默认 50 秒),因此被强制终止
时区问题
时区(time_zone)偏差
现象
数据库中存储的 Timestamp 字段值比真实值少了 13 个小时。
原因
- 当 JDBC 与 MySQL 开始建立连接时,会获取服务器参数。
- 当 MySQL 的
time_zone
值为SYSTEM
时,会取system_time_zone
值作为协调时区,若得到的是CST
那么 Java 会误以为这是CST -0500
,因此会给出错误的时区信息(国内一般是CST +0800
,即东八区)。
查看时区方法:
通过 show variables like '%time_zone%';
命令查看 Mysql 时区配置:
1 | mysql> show variables like '%time_zone%'; |
解决方案
方案一
1 | mysql> set global time_zone = '+08:00'; |
方案二
修改 my.cnf
文件,在 [mysqld]
节下增加 default-time-zone='+08:00'
,然后重启。
参考
https://simplebackups.com/blog/extensive-mysql-common-errors-list/#the-anatomy-of-mysql-errors