背景
需要使用JDBC处理来自mysql DB的近6000万条记录。这里的交互只是基于主键id的来自DB的“selection”。提取的字段是id,name和description。其他一些异步线程将处理获取的数据,不涉及数据库交互。
现在这个程序将一系列id作为参数,例如: 1到100,101到200等,该程序的多个实例将在不同的机器上运行。因此,每个程序实例将处理不同范围的ID。
这是创建回填数据的一次性工作,但只会选择生产数据库。
观察
mysql> SHOW STATUS WHERE `variable_name` = 'Threads_connected';
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| Threads_connected | 12 |
+-------------------+-------+
当我使用25到95的范围时,它只有20个记录,但观察到的连接数为12,并且在整个处理过程中它们保持不变。
代码
public void processRange(String fromid, String toid) {
if (!fromid.isEmpty() && !toid.isEmpty()) {
try {
Class.forName("com.mysql.jdbc.Driver");
this.connection = DriverManager.getConnection(this.url, this.user, this.password);
this.statement = connection.prepareStatement("SELECT id, name, contents FROM sometable WHERE id >= " + fromid + " and id <= " + toid);
this.results = statement.executeQuery();
while(results.next()) {
if(name != null && !name.isEmpty() && contents != null && !contents.isEmpty()) {
//PROCESS using async futures
}
}
} catch (SQLException sqle) {
sqle.printStackTrace();
} catch (Exception exp) {
exp.printStackTrace();
} finally {
try {
if(results != null) {
this.results.close();
}
if(statement != null) {
this.statement.close();
}
if(connection != null) {
this.connection.close();
}
} catch (SQLException sqle) {
sqle.printStackTrace();
}
}
}
}
问题
这是非常简单的JDBC代码。现在,如果我按照后台中的说明运行此进程的多个实例,如何确保数据库不会因“Too many connections”错误而停止运行。有没有办法只获取数据,关闭连接并处理异步“离线”,以便尽快释放连接。
另一方面,我认为循环遍历范围然后为每个id获取数据是解决此问题最糟糕的事情,而不是批量提取。如果有人另有想法,请发表评论。
更新
目前的速度需要数月才能完成任务......!任何其他并行方法可以使整个任务更快?
我也尝试使用MAP REDUCE来实现相同的目标,但我不确定这是否是一个有效的用例。
以上观察基于本地机器。当我在相对强大的盒子上测试它时,与最大数量相比,连接非常少。我在同一台机器上运行此过程的5个实例,查看由resultset处理的10000个ID(总共50K)。我仍然有17个连接,最多允许500个。但这需要花费很多时间才能完成,CPU使用率达到99%。因此需要进行一些调整以使其运行更快或分发到其他机器。
答案 0 :(得分:0)
案例1:大多数代码都在MySQL中,而不是在Java中:
为此流程创建特殊的“用户”登录信息。设置max_user_connections = 12
。尝试连接时“捕获”相关错误。睡一会然后重试。
请注意,根据您使用的MySQL版本,代码的功能,拥有的CPU核心数等,拥有太多线程实际上会损害性能。一些较旧的基准测试显示4-8作为实际限制。一些较新的(版本5.7)显示64.(但这是针对某个工作量,而不是你的。)
在您完成所有这些工作之后,您可能会发现拥有多个异步流程几乎没有您希望的那么多。
案例2:大部分处理都在MySQL之外:
拥有max_connections = 1000
并在许多服务器上产生大量线程应该没问题。这是因为每个MySQL线程大部分时间都处于“睡眠”状态。
答案 1 :(得分:0)
问题不在于DB。瓶颈是FTP。这些图像是根据从DB获取的信息创建的,它应该被FTP到另一台主机。因此,将每个图像放到FTP服务器上,将多个图像压缩在一起然后上传。