Результаты разные с 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;
}