许多人遇到的错误与消息有关:
[Warning] Aborted connection 38 to db: 'database_name' user:
'root' host: 'localhost' (Got an error reading communication packets)
在 MySQL 日志中找到。在我的例子中,数据库是通过使用驱动程序 com.mysql.jdbc.Driver
和众所周知的 C3P0 池的 java 客户端本地访问的。我的 MySQL 服务器配置为接受相当多的连接,并且 max_allowed_packet 值设置为 64M。这是我的 my.cnf 文件(MySQL 配置)的摘录:
[mysqld]
max_allowed_packet = 64M
thread_concurrency = 8
thread_cache_size = 8
thread_stack = 192K
query_cache_size = 0
query_cache_type = 0
max_connections = 1024
back_log = 50
innodb_thread_concurrency = 6
innodb_lock_wait_timeout = 120
log_warnings
和
[mysqldump]
quick
quote-names
max_allowed_packet = 64M
我的数据库中的表 User
具有以下简单结构:
CREATE TABLE `User` (
`uid` varchar(255) COLLATE utf8_bin NOT NULL,
`name` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`mail` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`password` varchar(255) COLLATE utf8_bin DEFAULT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`maxParallelTasks` tinyint(4) NOT NULL DEFAULT '10',
`maxModels` int(11) NOT NULL DEFAULT '2000',
`maxBibTeX` int(11) NOT NULL DEFAULT '2000',
PRIMARY KEY (`uid`) USING BTREE,
UNIQUE KEY `mail` (`mail`) USING BTREE,
KEY `uid` (`uid`) USING BTREE,
KEY `index_user_name` (`name`) USING BTREE,
KEY `index_user_mail` (`mail`) USING BTREE,
KEY `index_user_maxModels` (`maxModels`) USING BTREE,
KEY `index_user_maxBibTeX` (`maxBibTeX`) USING BTREE,
KEY `index_user_maxParallelTasks` (`maxParallelTasks`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
当我使用 mysql 客户端(即 mysql -u root -p
)在该表中INSERT
一个值时,我在日志中没有收到任何警告。然而,当尝试相同的 Java 端时,上述警告多次出现在日志中!因此,在 Java 端,我的连接是从配置如下的 C3P0 连接池中提取的:
datasource = new ComboPooledDataSource();
datasource.setJdbcUrl(connectURI);
datasource.setMaxPoolSize(1000);
datasource.setMinPoolSize(20);
datasource.setInitialPoolSize(50);
datasource.setNumHelperThreads(6);
datasource.setTestConnectionOnCheckin(true);
datasource.setTestConnectionOnCheckout(true);
首先准备语句:
PreparedStatement ps = connection.prepareStatement(getSql());
然后参数化:
ps.setString(1, user.getUid());
ps.setString(2, user.getName());
ps.setString(3, user.getMail());
ps.setString(4, user.getHashedPass());
然后执行:
int update = ps.executeUpdate();
然后关闭准备好的语句:
ps.close();
SQL 连接关闭:
if (connection != null) {
try {
if (!connection.isClosed()) {
connection.close();
}
} catch (SQLException ex) {
throw new DbException(ex);
}
}
整个过程(对我来说)似乎是合法的。根据 http://dev.mysql.com/doc/refman/5.0/en/communication-errors.html 处的 MySQL 手册,此警告可能意味着:
The client program did not call mysql_close() before exiting.
或者那个:
The client program ended abruptly in the middle of a data transfer.
出于我的应用程序的目的,我使用 C3P0 使用 200 多个并行线程在该数据库中写入和读取,并且在检查数据是否实际传输到数据库中并正常从数据库中检索时没有内存泄漏.有没有人有类似的经历?
最后,我包括了我的 MySQL 版本以及可能对故障排除有用的其他信息:
mysql> show variables like "%version%";
+-------------------------+-------------------+
| Variable_name | Value |
+-------------------------+-------------------+
| protocol_version | 10 |
| version | 5.1.37-1ubuntu5.5 |
| version_comment | (Ubuntu) |
| version_compile_machine | x86_64 |
| version_compile_os | debian-linux-gnu |
+-------------------------+-------------------+
和
Java version: 1.6.0_22, (build 1.6.0_22-b04)
最佳答案
好吧,很高兴看到一个问题包含了恰到好处的信息,这些信息会暗示系统可能会遇到问题的地方。这是我要检查的内容:
- 尝试在关闭
Connection
对象之前关闭PreparedStatement
对象,并验证这是否解决了问题。这听起来可能没有必要,但在某些 JDBC 驱动程序的情况下是必需的,尤其是 Oracle(也可能是 MySQL)。基本原理是Connection
对象并没有真正关闭,特别是如果ResultSet
和Statement
对象等派生对象没有先关闭(按照提到的顺序)。部分原因在于 JDBC 驱动程序的编写方式。 - 验证所涉及的机器是否真的可以处理您希望它们处理的负载。如果底层网络基础设施根本无法处理指定数量的连接,那么连接很可能会被丢弃。如果第一个建议没有帮助,您可能想要查看 wireshark 转储并从中得出推论。
- 使用
debugUnreturnedConnectionStackTraces
标志检测任何连接池泄漏。这也要求 unreturnedConnectionTimeout 为正数。该标志确保为应用程序不将连接返回到池的情况提供堆栈跟踪。堆栈跟踪将指示代码中最初保留连接的位置。
关于java - C3P0 + MySQL : Got an error reading communication packets,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4993760/