在一个connection内,短时间访问数据库几万次会导致connection自动关闭么?

观鱼塘主 2013-11-27 12:04:27
最近写了个小程序,从日志文件当中抓取IP
-------------------------------------此为背景--------------------------------------------
问题描述:日志文件很多(每天的日志文件保存在一个日期命名的文件夹里,每个日志文件为10M,超过自动写入一个新的日志文件),算下来,每个日志文件有6W条数据。
每读出一条记录,就判断记录中的IP在数据库是否存在,如果不存在则写入数据库,否则取下一条记录。
我试过每次查询都新建一个connection,但循环到1000条的时候就报内存溢出的错了,数据库缓存爆掉了(貌似),所以我改用一个connection来完成所有的查询操作。
结果现在一个日志文件都还没有分析完就报
com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: No operations allowed after connection closed.这个错误,网上找了很多都没找到一个可行的方案。
求大神赐教!
PS:我没有使用任何框架,就是最原始的java project,只添加了一个jar包:mysql-connector-java.jar。
下面是我的部分代码:
public void saveLogFiles() throws IOException, SQLException, ClassNotFoundException {

Long count = 0L; // 重复记录条数
BufferedReader br = null;
String syslogPath = "D:\\syslog";
File syslog = new File(syslogPath);
Connection con = backUpDao.getConnection();
List<LogInfo> logInfos = new ArrayList<LogInfo>();

for (String dayFileName : syslog.list()) {

String daFilePath = syslogPath + "\\" + dayFileName;
File dayFile = new File(daFilePath);
if (dayFile.isFile()) {

// 如果在syslog文件夹下的当前文件不是日志文件夹,则判断下一个文件
continue;
}
for (String logFileName : dayFile.list()) {

String logFilePath = syslogPath + "\\" + dayFileName + "\\" + logFileName;
System.out.println("正在分析日志文件:" + logFilePath);
File logFile = new File(logFilePath);
try {

br = new BufferedReader(new FileReader(logFile));
String line = "";
while ((line = br.readLine()) != null) {

int indexOfLen = line.indexOf("len");
int indexOfFrom = line.indexOf("from");

if (indexOfLen == -1 || indexOfFrom == -1) {

// 如果找不到对应字符,则跳过该行
continue;
}

String srcIpAndPort = getSrcIpFromLog(line);
String srcIp = srcIpAndPort.split(":")[0];

String destIpAndPort = getDesIpFromLog(line);
String destIp = destIpAndPort.split(":")[0];

String date = getDateFromLog(line, indexOfLen, indexOfFrom);

Calendar cal = Calendar.getInstance();

long startDate = sdf.parse(date).getTime();

cal.setTimeInMillis(startDate);
cal.set(Calendar.DATE, cal.get(Calendar.DATE) +1);

long endDate = cal.getTimeInMillis();

String mac = getMacFromLog(line);

// 该条记录已存在相同IP,不在写入数据库
if (backUpDao.getByIp(con, srcIp, destIp, startDate, endDate, LogInfo.Area.XIAOSHAN.toString())) {

System.out.println("repeat log count: " + ++count + "; the content is " + line);
continue;
}

// 封装LogInfo
LogInfo logInfo = new LogInfo();

logInfo.setMac(mac);
logInfo.setSrcIp(srcIpAndPort);
logInfo.setDesIp(destIpAndPort);
logInfo.setDate(date);
logInfo.setContent(line);
logInfo.setArea(LogInfo.Area.XIAOSHAN);

logInfos.add(logInfo);
}
} catch (FileNotFoundException e) {

e.printStackTrace();
} catch (IOException e) {

e.printStackTrace();
} catch (ParseException e) {

e.printStackTrace();
} finally {

br.close();
backUpDao.closeConnection(null, null, con);
}
}
}
System.out.println("分析完成...\n开始写入数据库...");
backUpDao.saveLogoInfo(logInfos);
}


dao层代码如下:
public boolean getByIp(Connection con, String srcIp, String destIp, long startTimestamp, long endTimestamp, String area) throws SQLException {

PreparedStatement ps = null;
ResultSet rs = null;
try {

if (con == null) {

con = getConnection();
}


// 查询该条记录中的源IP和目标IP在数据库中当天记录里面是否存在
String sql = "select * from log l where l.src_ip_and_port like ? and l.dest_ip_and_port like ? and unix_timestamp(l.date) >= ? and unix_timestamp(l.date) < ? and l.area = ?";

ps = con.prepareStatement(sql);
ps.setString(1, srcIp + "%");
ps.setString(2, destIp + "%");
// mysqk的unix_timestamp函数以秒为准,所以下面要除以1000
ps.setLong(3, startTimestamp / 1000);
ps.setLong(4, endTimestamp / 1000);
ps.setString(5, area);

rs = ps.executeQuery();
while (rs.next()) {

return true;
}
} catch (Exception e) {

e.printStackTrace();
} finally {

closeConnection(rs, ps, null);
}
return false;
}

一开始数据库是没有数据的,也就是说:一开始虽然每次都去查询,但是查询的都是空的数据库
...全文
582 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
观鱼塘主 2013-11-28
  • 打赏
  • 举报
回复
引用 13 楼 yousteely 的回复:
For Windows-based platforms, see Microsoft Knowledge Base Article 196271 (Q196271). at com.mysql.jdbc.Connection.createNewIO(Connection.java:2847) at com.mysql.jdbc.Connection.<init>(Connection.java:1555) at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:285) at java.sql.DriverManager.getConnection(DriverManager.java:582) at java.sql.DriverManager.getConnection(DriverManager.java:185) at com.hjc.backup.dao.BackUpDao.getConnection(BackUpDao.java:30) at com.hjc.backup.dao.BackUpDao.getByIp(BackUpDao.java:109) at com.hjc.backup.service.LogService.saveLogFiles(LogService.java:91) at com.hjc.backup.service.LogService.main(LogService.java:280) 丢,还真在getByIp里面调用了getConnection() 看来我的猜测是对的阿,问题是为什么传进来的conn为==null呢?
我在service里面开了一个connection,然后一直用的这个connection来查询的,getByIp方法里面的con是从service里面传递过来的连接,如果传递过来的con是空,才会去开一个新链接。但是不知道为啥,理论上不可能存在连接断开的问题啊!可是还是报连接断开的错误。。
steely_chen 2013-11-27
  • 打赏
  • 举报
回复
说说执行到哪里的时候抛出了 com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: No operations allowed after connection closed
genganpeng 2013-11-27
  • 打赏
  • 举报
回复
引用 2 楼 jchuang2011 的回复:
[quote=引用 1 楼 rumlee 的回复:] 你是不是开启了事务了。 对于这种问题,我建议的做法是用连接池。 每条数据该请求连接的时候请求连接,该释放连接的时候释放连接,就这么简单。你每次打开数据库连接,那程序性能很差,速度很慢。而如果全部共用一个连接的话,容易出一些莫名故障,如果有并发的话,问题会很多。所以最好的解决方案还是用连接池。
连接池经常听到,但是从来没用过,目前这个项目没有搭建任何框架,纯servlet做的。能做连接池么[/quote] 可以的,jdbc就有连接池的配置,比如c3p0连接池,看你的代码应该dao层代码不用改的,改改getConnection()就可以了
观鱼塘主 2013-11-27
  • 打赏
  • 举报
回复
引用 1 楼 rumlee 的回复:
你是不是开启了事务了。 对于这种问题,我建议的做法是用连接池。 每条数据该请求连接的时候请求连接,该释放连接的时候释放连接,就这么简单。你每次打开数据库连接,那程序性能很差,速度很慢。而如果全部共用一个连接的话,容易出一些莫名故障,如果有并发的话,问题会很多。所以最好的解决方案还是用连接池。
连接池经常听到,但是从来没用过,目前这个项目没有搭建任何框架,纯servlet做的。能做连接池么
rumlee 2013-11-27
  • 打赏
  • 举报
回复
你是不是开启了事务了。 对于这种问题,我建议的做法是用连接池。 每条数据该请求连接的时候请求连接,该释放连接的时候释放连接,就这么简单。你每次打开数据库连接,那程序性能很差,速度很慢。而如果全部共用一个连接的话,容易出一些莫名故障,如果有并发的话,问题会很多。所以最好的解决方案还是用连接池。
steely_chen 2013-11-27
  • 打赏
  • 举报
回复
For Windows-based platforms, see Microsoft Knowledge Base Article 196271 (Q196271). at com.mysql.jdbc.Connection.createNewIO(Connection.java:2847) at com.mysql.jdbc.Connection.<init>(Connection.java:1555) at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:285) at java.sql.DriverManager.getConnection(DriverManager.java:582) at java.sql.DriverManager.getConnection(DriverManager.java:185) at com.hjc.backup.dao.BackUpDao.getConnection(BackUpDao.java:30) at com.hjc.backup.dao.BackUpDao.getByIp(BackUpDao.java:109) at com.hjc.backup.service.LogService.saveLogFiles(LogService.java:91) at com.hjc.backup.service.LogService.main(LogService.java:280) 丢,还真在getByIp里面调用了getConnection() 看来我的猜测是对的阿,问题是为什么传进来的conn为==null呢?
steely_chen 2013-11-27
  • 打赏
  • 举报
回复
引用 11 楼 yousteely 的回复:
[quote=引用 5 楼 jchuang2011 的回复:] [quote=引用 4 楼 yousteely 的回复:] 说说执行到哪里的时候抛出了 com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: No operations allowed after connection closed
 // 该条记录已存在相同IP,不在写入数据库
                        if (backUpDao.getByIp(con, srcIp, destIp, startDate, endDate, LogInfo.Area.XIAOSHAN.toString())) {
                             
                            System.out.println("repeat log count: " + ++count + "; the content is " + line);
                            continue;
                        }
这里,我先把所有数据都分析完了再插入数据库。[/quote] getConnection() 检查一下是不是每次getConnection 都新开了一个连接 closeConnection(rs, ps, null); 这个方法好像并没有关闭Connection 连接 如果直是这样,有可能你打开的连接数超过了数据库的最大连接。 解决方法有: 1. getConnection 的时候重复利用已经打开的连接 (比较靠谱) 2. closeConnection 的时候关闭连接 (有点靠谱) 3. 把数据库连接数设置大一点 (不是太靠谱,因为你的程序设计的不好,再大的连接数都会爆的一刻)[/quote] 以上观点当说没过,没仔细看你的程序,应该不存在过多连接的问题
steely_chen 2013-11-27
  • 打赏
  • 举报
回复
引用 5 楼 jchuang2011 的回复:
[quote=引用 4 楼 yousteely 的回复:] 说说执行到哪里的时候抛出了 com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: No operations allowed after connection closed
 // 该条记录已存在相同IP,不在写入数据库
                        if (backUpDao.getByIp(con, srcIp, destIp, startDate, endDate, LogInfo.Area.XIAOSHAN.toString())) {
                             
                            System.out.println("repeat log count: " + ++count + "; the content is " + line);
                            continue;
                        }
这里,我先把所有数据都分析完了再插入数据库。[/quote] getConnection() 检查一下是不是每次getConnection 都新开了一个连接 closeConnection(rs, ps, null); 这个方法好像并没有关闭Connection 连接 如果直是这样,有可能你打开的连接数超过了数据库的最大连接。 解决方法有: 1. getConnection 的时候重复利用已经打开的连接 (比较靠谱) 2. closeConnection 的时候关闭连接 (有点靠谱) 3. 把数据库连接数设置大一点 (不是太靠谱,因为你的程序设计的不好,再大的连接数都会爆的一刻)
观鱼塘主 2013-11-27
  • 打赏
  • 举报
回复
是我搞错了,最近试了集中方法,报错一堆,然后记不清楚了、、、
观鱼塘主 2013-11-27
  • 打赏
  • 举报
回复
开始备份日志文件...
正在分析日志文件:D:\syslog\20131123\0015.log
com.mysql.jdbc.CommunicationsException: The driver was unable to create a connection due to an inability to establish the client portion of a socket.

This is usually caused by a limit on the number of sockets imposed by the operating system. This limit is usually configurable. 

For Unix-based platforms, see the manual page for the 'ulimit' command. Kernel or system reconfiguration may also be required.

For Windows-based platforms, see Microsoft Knowledge Base Article 196271 (Q196271).
	at com.mysql.jdbc.Connection.createNewIO(Connection.java:2847)
	at com.mysql.jdbc.Connection.<init>(Connection.java:1555)
	at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:285)
	at java.sql.DriverManager.getConnection(DriverManager.java:582)
	at java.sql.DriverManager.getConnection(DriverManager.java:185)
	at com.hjc.backup.dao.BackUpDao.getConnection(BackUpDao.java:30)
	at com.hjc.backup.dao.BackUpDao.getByIp(BackUpDao.java:109)
	at com.hjc.backup.service.LogService.saveLogFiles(LogService.java:91)
	at com.hjc.backup.service.LogService.main(LogService.java:280)
引用 8 楼 defonds 的回复:
[quote=引用 7 楼 jchuang2011 的回复:] [quote=引用 6 楼 defonds 的回复:] 你怎么知道数据库缓存爆掉了?内存溢出是 java client 还是 db? 另外,建议你发一下临界溢出时的 java client 和 db server 各自的 cpu、内存负载情况。
频繁创建connection,到1000个就报Java heap space错误,目前还没在tomcat上面跑,就在控制台跑跑的。[/quote]Java heap space 是 java 报的,还是 db 报的? 你不会 java 和 db 跑在一台了?[/quote]
Defonds 2013-11-27
  • 打赏
  • 举报
回复
引用 7 楼 jchuang2011 的回复:
[quote=引用 6 楼 defonds 的回复:] 你怎么知道数据库缓存爆掉了?内存溢出是 java client 还是 db? 另外,建议你发一下临界溢出时的 java client 和 db server 各自的 cpu、内存负载情况。
频繁创建connection,到1000个就报Java heap space错误,目前还没在tomcat上面跑,就在控制台跑跑的。[/quote]Java heap space 是 java 报的,还是 db 报的? 你不会 java 和 db 跑在一台了?
观鱼塘主 2013-11-27
  • 打赏
  • 举报
回复
引用 6 楼 defonds 的回复:
你怎么知道数据库缓存爆掉了?内存溢出是 java client 还是 db? 另外,建议你发一下临界溢出时的 java client 和 db server 各自的 cpu、内存负载情况。
频繁创建connection,到1000个就报Java heap space错误,目前还没在tomcat上面跑,就在控制台跑跑的。
Defonds 2013-11-27
  • 打赏
  • 举报
回复
你怎么知道数据库缓存爆掉了?内存溢出是 java client 还是 db? 另外,建议你发一下临界溢出时的 java client 和 db server 各自的 cpu、内存负载情况。
观鱼塘主 2013-11-27
  • 打赏
  • 举报
回复
引用 4 楼 yousteely 的回复:
说说执行到哪里的时候抛出了 com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: No operations allowed after connection closed
 // 该条记录已存在相同IP,不在写入数据库
                        if (backUpDao.getByIp(con, srcIp, destIp, startDate, endDate, LogInfo.Area.XIAOSHAN.toString())) {
                             
                            System.out.println("repeat log count: " + ++count + "; the content is " + line);
                            continue;
                        }
这里,我先把所有数据都分析完了再插入数据库。

81,094

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧