许多人遇到的错误与以下消息相关:
[Warning] Aborted connection 38 to db: 'database_name' user:
'root' host: 'localhost' (Got an error reading communication packets)
Run Code Online (Sandbox Code Playgroud)
这是在 MySQL 日志中找到的。就我而言,数据库是通过 java 客户端使用驱动程序和众所周知的 C3P0 池在本地访问的。com.mysql.jdbc.Driver我的 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
Run Code Online (Sandbox Code Playgroud)
和
[mysqldump]
quick
quote-names
max_allowed_packet = 64M
Run Code Online (Sandbox Code Playgroud)
我的数据库中的表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
Run Code Online (Sandbox Code Playgroud)
当我INSERT使用 mysql 客户端(即mysql -u root -p)在该表中获取值时,我在日志中没有收到任何警告。然而,当尝试相同的 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);
Run Code Online (Sandbox Code Playgroud)
首先准备声明:
PreparedStatement ps = connection.prepareStatement(getSql());
Run Code Online (Sandbox Code Playgroud)
然后参数化:
ps.setString(1, user.getUid());
ps.setString(2, user.getName());
ps.setString(3, user.getMail());
ps.setString(4, user.getHashedPass());
Run Code Online (Sandbox Code Playgroud)
然后执行:
int update = ps.executeUpdate();
Run Code Online (Sandbox Code Playgroud)
然后关闭准备好的语句:
ps.close();
Run Code Online (Sandbox Code Playgroud)
并且 SQL 连接已关闭:
if (connection != null) {
try {
if (!connection.isClosed()) {
connection.close();
}
} catch (SQLException ex) {
throw new DbException(ex);
}
}
Run Code Online (Sandbox Code Playgroud)
整个程序(在我看来)似乎是合法的。根据http://dev.mysql.com/doc/refman/5.0/en/communication-errors.html上的 MySQL 手册,此警告可能意味着:
客户端程序退出前没有调用mysql_close()。
或者那个:
客户端程序在数据传输过程中突然结束。
出于我的应用程序的目的,我使用 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 |
+-------------------------+-------------------+
Run Code Online (Sandbox Code Playgroud)
和
Java version: 1.6.0_22, (build 1.6.0_22-b04)
Run Code Online (Sandbox Code Playgroud)
试图更深入地探究此警告的原因......
\n\n首先,我注意到我在日志文件中收到的警告消息数量等于或非常接近指定的最小池大小datasource.setMinPoolSize(int);而为了测试而每次将初始池大小设置为等于最小大小。
此外,通过使用调试器并逐步执行语句,我有时间观察到单元测试一完成就记录了警告。这些事实使我得出这样的结论:C3P0 汇集的连接实际上在被丢弃之前并未关闭。需要的是,一旦不再使用调用该方法就关闭数据源com.\xe2\x80\x8bmchange.\xe2\x80\x8bv2.\xe2\x80\x8bc3p0.\xe2\x80\x8bimpl.\xe2\x80\x8bAbstractPoolBackedDataSource#close()。当然,只有在单元测试结束时才这样做才有意义,所以就我而言,修改如下:
@AfterClass\npublic static void tearDownClass() throws Exception {\n // Close the pool \n DataSourceFactory.getInstance().close();\n}\nRun Code Online (Sandbox Code Playgroud)\n\n在我的应用程序中,我添加了一个关闭挂钩,以便数据源在执行停止之前关闭。在此之前,池连接保持完整,驱动程序必须关闭它们,从而导致 MySQL 日志中出现警告。这解决了所有 INSERT 操作的问题,但不幸的是,没有解决 SELECT 操作的问题。请注意,我关闭了所有结果集、语句、准备好的语句和连接,并使用FindBugs检查了我的源代码(静态分析工具)解决方法让我再次怀疑 C3P0 有问题,但我不能确定。因此,以下内容使警告消失......
\n\n@AfterClass\npublic static void tearDownClass() throws Exception {\n Thread.sleep(100000); // wait for 100 secs\n DataSourceFactory.getInstance().close();\n}\nRun Code Online (Sandbox Code Playgroud)\n\n请注意,在 100 秒的时间结束(并且数据源工厂关闭)之前,日志中不会出现任何警告!所以就是datasource.close()导致他们...
| 归档时间: |
|
| 查看次数: |
4389 次 |
| 最近记录: |