Результаты разные с MySQL 5.7.18 по сравнению с 5.7.16

Мы находимся в процессе обновления нашей версии MySQL с 5.7.16 до 5.7.18. У нас есть существующий процесс, который, похоже, не совместим с более новой версией MySQL.

Это процесс подкачки, который обновляет до 100 000 строк, выполняя по 500 одновременно. Он отлично работал в течение многих лет на 5.7.16 и всех предыдущих версиях MySQL. Поскольку мы обновили, процесс выполнит 500 строк только несколько раз, а затем перейдет к последующим шагам. Например, он обновит 500 строк 3 раза, а затем в четвертый раз обновит только 1 строку. Иногда он обновляет 500 строк 5 раз, а затем в шестой раз обновляет только 1 строку. Кажется подозрительным, что процесс повторяется несколько раз, а затем всегда только 1 строка в последний раз.

Что-то не так с нашей старой реализацией, которая не совместима с более новой версией MySQL в отношении LIMIT или ORDER BY? Это единственные две вещи, которые, по нашему мнению, могут стать причиной неудачи. Нам было легко заметить ошибку в этой области, но нам нужно знать, почему одна реализация работает, а не другая, чтобы мы могли найти любые другие области в нашей кодовой базе, где ошибка менее очевидна.

Старая реализация, которая не работает с 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 ответов

Другие вопросы по тегам