MySQL 5.7.18与5.7.16

时间:2017-09-20 16:09:47

标签: java mysql spring hibernate sql-limit

我们正在将我们的MySQL版本从5.7.16升级到5.7.18。我们的现有流程似乎与较新版本的MySQL不兼容。

这是一个分页过程,通过一次500个来更新多达100,000行。它在5.7.16以及之前版本的MySQL上运行良好多年。由于我们升级了该过程,因此只会执行500行几次,然后继续执行后续步骤。例如,它将更新500行3次,然后在第四次更新仅1行。有时它会更新500行5次,然后第六次它将再次更新1行。似乎可疑的是,进程迭代了几次,然后在最后一次总是只有1行。

我们的旧实现是否与LIMIT或ORDER BY的新版MySQL不兼容?这是我们认为可能导致失败的两件事。我们很容易注意到这个领域的失败,但是我们需要知道为什么一个实现工作而不是另一个实现,以便我们可以在代码库中找到故障不太明显的任何其他区域。

不适用于MySQL 5.7.18的旧实现:

public void changeItemsType(TypeEnum inProgress, TypeEnum complete) {
    int howMany = 500;
    int selectSize = howMany;
    Long lastId = 0L;
    while (selectSize == howMany) {
        Query q = null;
        q = buildChangeQuery(inProgress, howMany, lastId);
        List<BigInteger> rows = GenericsUtil.cast(q.getResultList());
        selectSize = rows.size();
        if (rows != null && !rows.isEmpty()) {
            lastId = buildIdUpdateList(complete, lastId, rows, inProgress);
        }
    }
}

private Query buildChangeQuery(TypeEnum inProgress, int howMany, Long lastId) {
    StringBuffer sb = new StringBuffer();
    sb.append("select id from Item \n");
    sb.append("where processType = :inprogress \n");
    sb.append("and id > :lastId \n");
    sb.append("order by id \n");
    Query q = this.em.createNativeQuery(sb.toString());
    q.setParameter("inprogress", inProgress.name());
    q.setParameter("lastId", lastId);
    q.setMaxResults(howMany);
    return q;
}

private Long buildIdUpdateList(TypeEnum complete, Long lastId, List<BigInteger> rows, TypeEnum inProgress) {
    List<Long> ids = new ArrayList<Long>();
    Long itemId = 0L;
    for (BigInteger row : rows) {
        itemId = row.longValue();
        ids.add(itemId);
    }
    lastId = itemId;
    updateItems(complete, ids, inProgress);
    return lastId;
}

private void updateItems(TypeEnum complete, List<Long> ids, TypeEnum inProgress) {
    Collections.sort(ids);
    StringBuffer sb = new StringBuffer();
    sb.append("update Item \n");
    sb.append("set type = :complete, \n");
    sb.append("updateDate = :now, \n");
    sb.append("version = version + 1, \n");
    sb.append("updateAction = :inProgress \n");
    sb.append("where id in (:ids) \n");
    Query q = this.em.createNativeQuery(sb.toString());
    q.setParameter("complete", complete.name());
    q.setParameter("ids", ids);
    q.setParameter("now", new Date());
    q.setParameter("inProgress", inProgress.name().replaceAll("IN_PROGRESS_", ""));
    q.executeUpdate();
}

同一进程的新实现,它与MySQL 5.7.18一起使用:

public void changeItemsType(TypeEnum inProgress, TypeEnum complete, int howMany) {
    int updateCount = -1;
    while (updateCount != 0) {
        updateCount = 0;
        updateCount = updateItems(inProgress, complete, howMany);
    }
}

private int updateItems(TypeEnum inProgress, TypeEnum complete, int howMany) {
    StringBuffer sb = new StringBuffer();
    sb.append("update Item \n");
    sb.append("set processType = :complete, \n");
    sb.append("updateDate = :now, \n");
    sb.append("version = version + 1, \n");
    sb.append("updateAction = :inProgress \n");
    sb.append("where type = :inProgressTemp \n");

    Query q = this.em.createNativeQuery(sb.toString());
    q.setParameter("inProgressTemp", inProgress.name());
    q.setParameter("complete", complete.name());
    q.setParameter("now", new Date());
    q.setParameter("inProgress", inProgress.name().replaceAll("IN_PROGRESS_", ""));
    q.setMaxResults(howMany);

    int updateSize = 0;
    updateSize = q.executeUpdate();
    return updateSize;
}

0 个答案:

没有答案