日期:2014-05-19  浏览次数:20863 次

执行大量SQL语句导致程序崩溃
系统有一个自动计时触发的程序,此程序需要执行上万条修改语句的SQL,执行时间有一二十分钟。执行过程中总是导致系统崩溃。请问这是为什么?一般来说我直接执行几万条SQL语句最多也就10来秒就完了。有什么解决方案?

以下是UPDATE语句,用了hibernate的。条件B,C为主键。

UPDATE TEST t SET t.A=? WHERE t.id.B=? AND t.id.C=?

以下是核心的执行代码,全部添加进一个LIST然后调用此方法执行:

Transaction tx = session.beginTransaction();
try {
for (int i = 0; i < hqlList.size(); i++) {
Query query = session.createQuery(hqlList.get(i));

if (i < parList.size()) {
List pars = (List) parList.get(i);
for (int j = 0; j < pars.size(); j++) {
query.setParameter(j, pars.get(j));
}
}
query.executeUpdate();

if (i % 20 == 0) { 

session.flush();
session.clear();
}
}
tx.commit();

------解决方案--------------------
首先不知道LZ的定时是怎么处理?是多线程还是单线程?
如果是单线程的话,如果处理太慢,上一次定时没做完,下一次定时肯定被堵塞着(此时的下一次处理的数据信息是如何保存的?),这样的每次累计的定时堵塞就会越来越多
如果是多线程的话,list之间的同步保证了没有,数据库的死锁保证了没有,因为多线程的话,可能是多个事务并行,那么更新的数据如果有影响,比如线程1要更新数据1,但是线程2已经更新了,但是还没commit,那么线程1就会等待,同样的,线程2也有可能发生等待,于是就有可能发生死锁


------解决方案--------------------
那就用jdbc的批处理器,这个对批量更新,批量新增效率比直接用hibernate这样更新效率高!
Connection conn = getSession().connection();
PreparedStatement pst = null;
try {
conn.setAutoCommit(false);
String sql = "UPDATE TEST t SET t.A=? WHERE t.id.B=? AND t.id.C=?";
pst = conn.prepareStatement(sql);
for(int i = 0; i < hqlList.size(); i++){
//根据数据类型设置参数如
//每个?都要设置参数,参数从1开始
pst.setInt(第几个参数,参数的值);
pst.addBatch();
}
pst.executeBatch();
conn.commit();
catch(Exception e){
}