MySQL 出现 java.sql.SQLException 之 Got error 28 from storage engine 问题分析以及解决方法
来源:互联网 发布:格伦罗宾逊数据 编辑:程序博客网 时间:2024/05/21 09:07
1 发现问题
一直好好的 MySQL 数据库,今天突然报错了,是用户在查询数据时发现的(web 应用)。赶紧看看应用日志:
Caused by: java.sql.SQLException: Got error 28 from storage engine at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078) at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4237) at com.mysql.jdbc.MysqlIO.nextRowFast(MysqlIO.java:2190) at com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:2046) at com.mysql.jdbc.MysqlIO.readSingleRowSet(MysqlIO.java:3543) at com.mysql.jdbc.MysqlIO.getResultSet(MysqlIO.java:491) at com.mysql.jdbc.MysqlIO.readResultsForQueryOrUpdate(MysqlIO.java:3245) at com.mysql.jdbc.MysqlIO.readAllResults(MysqlIO.java:2413) at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2836) at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2825) at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2156) at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:2323) at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeQuery(FilterChainImpl.java:2712) at com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_executeQuery(FilterEventAdapter.java:465) at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeQuery(FilterChainImpl.java:2709) at com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_executeQuery(FilterEventAdapter.java:465) at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_executeQuery(FilterChainImpl.java:2709) at com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.executeQuery(PreparedStatementProxyImpl.java:132) at com.alibaba.druid.pool.DruidPooledPreparedStatement.executeQuery(DruidPooledPreparedStatement.java:227) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:56) ... 139 more
2 原因分析
2.1 分析源代码
根据出错日志的堆栈信息,可以看出是 MySQL 在验证操作系统返回的响应包时报的错(MysqlIO.checkErrorPacket) ,打开源代码跟踪看看:
private void checkErrorPacket(Buffer resultPacket) throws SQLException { int statusCode = resultPacket.readByte(); // Error handling if (statusCode == (byte) 0xff) { String serverErrorMessage; int errno = 2000; if (this.protocolVersion > 9) { errno = resultPacket.readInt(); String xOpen = null; serverErrorMessage = resultPacket.readString(this.connection.getErrorMessageEncoding(), getExceptionInterceptor()); if (serverErrorMessage.charAt(0) == '#') { // we have an SQLState if (serverErrorMessage.length() > 6) { xOpen = serverErrorMessage.substring(1, 6); serverErrorMessage = serverErrorMessage.substring(6); if (xOpen.equals("HY000")) { xOpen = SQLError.mysqlToSqlState(errno, this.connection.getUseSqlStateCodes()); } } else { xOpen = SQLError.mysqlToSqlState(errno, this.connection.getUseSqlStateCodes()); } } else { xOpen = SQLError.mysqlToSqlState(errno, this.connection.getUseSqlStateCodes()); } clearInputStream(); StringBuilder errorBuf = new StringBuilder(); String xOpenErrorMessage = SQLError.get(xOpen); if (!this.connection.getUseOnlyServerErrorMessages()) { if (xOpenErrorMessage != null) { errorBuf.append(xOpenErrorMessage); errorBuf.append(Messages.getString("MysqlIO.68")); } } errorBuf.append(serverErrorMessage); if (!this.connection.getUseOnlyServerErrorMessages()) { if (xOpenErrorMessage != null) { errorBuf.append("\""); } } appendDeadlockStatusInformation(xOpen, errorBuf); if (xOpen != null && xOpen.startsWith("22")) { throw new MysqlDataTruncation(errorBuf.toString(), 0, true, false, 0, 0, errno); } throw SQLError.createSQLException(errorBuf.toString(), xOpen, errno, false, getExceptionInterceptor(), this.connection); } serverErrorMessage = resultPacket.readString(this.connection.getErrorMessageEncoding(), getExceptionInterceptor()); clearInputStream(); if (serverErrorMessage.indexOf(Messages.getString("MysqlIO.70")) != -1) { throw SQLError.createSQLException(SQLError.get(SQLError.SQL_STATE_COLUMN_NOT_FOUND) + ", " + serverErrorMessage, SQLError.SQL_STATE_COLUMN_NOT_FOUND, -1, false, getExceptionInterceptor(), this.connection); } StringBuilder errorBuf = new StringBuilder(Messages.getString("MysqlIO.72")); errorBuf.append(serverErrorMessage); errorBuf.append("\""); throw SQLError.createSQLException(SQLError.get(SQLError.SQL_STATE_GENERAL_ERROR) + ", " + errorBuf.toString(), SQLError.SQL_STATE_GENERAL_ERROR, -1, false, getExceptionInterceptor(), this.connection); }}
这些代码都是为了对操作系统返回的错误代码信息,进行转义,转换为 MySQL 自己的错误信息。所以 SQLError 一定就是 MySQL 的错误信息字典咯!打开一看,果然是这样:
mysqlToSqlState = new Hashtable<Integer, String>();mysqlToSqlState.put(MysqlErrorNumbers.ER_SELECT_REDUCED, SQL_STATE_WARNING);mysqlToSqlState.put(MysqlErrorNumbers.ER_WARN_TOO_FEW_RECORDS, SQL_STATE_WARNING);...mysqlToSqlState.put(MysqlErrorNumbers.ER_LOCK_DEADLOCK, SQL_STATE_ROLLBACK_SERIALIZATION_FAILURE);
MysqlErrorNumbers 是 MySQL 定义的错误代码常量类,里面可以找到 Got error 28 from storage engine 定义的出处:
public final static int ER_GET_ERRNO = 1030; //SQLSTATE: HY000 Message: Got error %d from storage engine...
有的人会发现这个 ER_GET_ERRNO 根本就没有被其他代码调用过!个人猜测是因为 MySQL 的 jar 源代码与实际的 jar 版本不一致造成的。
2.2 神秘的 “28”
那么 “28” 究竟又是什么意思呢?
在 MySQL 官网有这样的一个问题解答,翻译如下:无法创建或者写数据到文件怎么办?
如果在执行 SQL 查询时,会得到下列错误,那就意味着 MySQL 无法在临时目录上创建临时文件(数据的结果集需要用到临时文件)。
Can't create/write to file '\\sqla3fe_0.ism'.
windows 经常会出现这样的提示,Unix 的提示与 windows 类似。
修复方法是使用 mysqld 方法,重新指定一个有权限文件夹,像这样:
[mysqld]tmpdir=C:/temp
C:/temp
必须存在并且有足够的磁盘空间供 MySQL 使用。
没有权限也会引发这个问题,所以必须确保 MySQL 有权限写 tmpdir 文件夹。
也可以使用 perror 命令来确定错误代码的含义。还有一个原因是磁盘空间满了:
shell> perror 28OS error code 28: No space left on device
看到了没有,这就是 28 的真正含义!
查了一下 linux 的错误码中 28 的含义,也是 No space left on device!
现在清楚了吧 O(∩_∩)O~
3 解决问题
linux 中先查询磁盘空间使用量:
myServer# df -h
肯定有一个文件系统是 100%,可能像这样:
Filesystem Size Used Avail Capacity Mounted on/dev/vdisk 13G 13G 46M 100% /devfs 1.0k 1.0k 0B 100% /dev
剩下的事情就简单咯,删除无用文件;把大文件移动到其他文件系统;甚至在 MySQL 中重新指定临时文件目录的路径…这些方法目的都是为了把磁盘空间给腾出来 O(∩_∩)O~
- MySQL 出现 java.sql.SQLException 之 Got error 28 from storage engine 问题分析以及解决方法
- java.sql.SQLException: Got error 28 from storage engine 解决方案
- mysql出现1030 Got error 28 from storage engine解决方法
- Mysql 出现Got error 28 from storage engine 解决方法
- mysql出现1030 Got error 28 from storage engine解决方法
- MySQL出现1030-Got error 28 from storage engine错误
- Got error 28 from storage engine 解决方法
- Got error 28 from storage engine 解决方法
- Got error 28 from storage engine 解决方法
- Got error 28 from storage engine 解决方法
- Mysql:Got error 28 from storage engine
- mysql Got error 28 from storage engine
- got error 28 from storage engine mysql
- Mysql报Got error 28 from storage engine错误问题
- 数据库问题之Got error 28 from storage engine。
- MYSQL-ERROR(1030 - Got error 28 from storage engine)
- Got error 28 from storage engine 解决方法 [打印]
- mysql:Mysql Got error 28 from storage engine
- 简单的上拉加载下拉刷新实现
- 使用PDH性能计数器(Windows)获取CPU使用率、可用物理内存、上传/下载速率、磁盘读写速率
- 解决ubuntu usb开机无法使用,只有重启才可恢复问题
- Android开发入门之采用Service实现电话应用
- google gcm接入
- MySQL 出现 java.sql.SQLException 之 Got error 28 from storage engine 问题分析以及解决方法
- 字符串匹配算法——Sunday算法和KMP算法(java版本)
- jmeter脚本录制
- aliyun_oss文件夹内的文件上传
- 大前端公共知识杂谈
- CGroup 介绍、应用实例及原理描述
- 1594
- 前端web app之rem的介绍
- 旋转数组的最小数字