【发布时间】:2018-04-09 05:22:46
【问题描述】:
我阅读了很多文章并找到了一些批处理的方法
其中之一是使用 flush 和 clear ,以下是代码
long t1 = System.currentTimeMillis();
Session session = getSession();
Transaction transaction = session.beginTransaction();
try {
Query query = session.createQuery("FROM PersonEntity WHERE id > " + lastMaxId + " ORDER BY id");
query.setMaxResults(1000);
rows = query.list();
int count = 0;
if (rows == null || rows.size() == 0) {
return;
}
LOGGER.info("fetched {} rows from db", rows.size());
for (Object row : rows) {
PersonEntity personEntity = (PersonEntity) row;
personEntity.setName(randomAlphaNumeric(30));
lastMaxId = personEntity.getId();
session.saveOrUpdate(personEntity);
if (++count % 50 == 0) {
session.flush();
session.clear();
LOGGER.info("Flushed and Cleared");
}
}
} finally {
if (session != null && session.isOpen()) {
LOGGER.info("Closing Session and commiting transaction");
transaction.commit();
session.close();
}
}
long t2 = System.currentTimeMillis();
LOGGER.info("time taken {}s", (t2 - t1) / 1000);
在上面的代码中,我们批量处理 1000 条记录并在同一个事务中更新它们。
只需要批量更新就可以了。
但我有以下问题:
- 可能会有其他线程 (T2) 为某些运行时更新操作访问同一行集的情况,但在这种情况下,直到 1000 批不会被提交,T2 remians 卡住了
那么,我们应该如何处理这种情况呢?
我可能的想法/解决方案:
- 我认为我们可以在不同的会话中进行更新,例如 50 个小批量
- 对更新使用不同的无状态连接并逐个提交事务,但在一批 1000 完成时关闭会话。
请帮助我获得更好的解决方案。
【问题讨论】:
-
您能否说明您需要对这些实体进行什么样的更新,以及为什么您不想或不能对其使用 SQL 或 HQL?例如docs.jboss.org/hibernate/orm/3.3/reference/en/html/…
-
如果您有两个事务处理相同的数据,您预计会发生什么?
-
假设我们有票务系统,并且有一个 TimerTsk 定期读取和批量更新。现在假设一些工单也更新了,现在第二个操作会卡住一段时间,如果及时任务,这一行将出现在当前批次中。
-
是的,数据库就是这样工作的。
-
是的,这就是我要问的原因,有没有更好的方法可以最大限度地减少这种滞后
标签: java postgresql hibernate jdbc batch-processing