Я работаю с Spring boot с сервером mysql. У меня есть запланированный метод, который удаляет записи (тысячи), а затем вставляет (тысячи) записей. Обе операции массового удаления + вставки выполняются внутри транзакции.
Вот код:
@Service
public class BulkInsert
{
public static final String DELETE_ALL_ROWS_QUERY = "DELETE FROM GnsEntity where is_synced = true and was_removed = false";
@Inject
private EntityManager entityManager;
@Transactional
public void save(List<GnsEntity> gnsEntityList)
{
Session session = entityManager.unwrap(Session.class);
Query entity = session.createQuery(DELETE_ALL_ROWS_QUERY);
entity.executeUpdate();
for (int i = 0; i < gnsEntityList.size(); ++i)
{
try
{
session.save(gnsEntityList.get(i));
}
catch(NonUniqueObjectException nonUniEx)
{
}
}
}
}
Запланированный аннотированный код метода:
@Log4j
@Component
public class PeriodicDataSynchornizer
{
@Inject
private LdapService m_ldapService;
@Inject
private BulkInsert m_bulkInsert;
@Inject
private RestTemplate restTemplate;
@Scheduled(fixedDelayString = "#{ 60000*${swiss.GNSSynchronizer.rateMin}}")
public void run()
{
log.info("starting syncing process");
List<GnsEntity> allowedPaths = null;
try
{
allowedPaths = m_ldapService.dumpAllowedPaths();
allowedPaths.addAll(m_ldapService.dumpAllGnsPathHistory());
}
catch (NamingException e)
{
log.info("caught NamingException from LdapService",e);
return;
}
log.info("got " + allowedPaths.size() + "elements from GNS database");
m_bulkInsert.save(allowedPaths);
log.info("finished syncing");
}
}
Этот метод Schedule выполняется каждые 2-3 минуты и единственный, который обращается к БД.
Я пытаюсь понять, что я получаю следующее исключение много раз:
{"@timestamp ":" 2019-10-18T19: 28: 39.851Z "," logLevel ":" WARN "," message ":" Ошибка SQL: 1213, SQLState: 40001 "," service ":" GNSSynchronizer "," instanceId":" 1" , "приложение": "MyApp", "пространство": "MySpace", "класс": "org.hibernate.engine.jdbc.spi.SqlExceptionHelper", "нить": "бассейн-3-жильный-1 "," X-B3-TraceId ":" 5daa1244ee26ba17344882356d926d42 "," X-B3-Spa nId ":" 344882356d926d42 "} {" @timestamp ":" 2019-10-18T19: 28: 39.851Z "," logLevel":" ОШИБКА "," message ":" Обнаружена тупиковая ситуация при попытке получить блокировку; попробуйте перезапустить транзакцию "," service ":" GNSSynchronizer "," instanceId ":" 1 "," application ":" myapp "," space":" mysapce " "класс":" org.hibernate.engine.jdbc.spi.SqlExceptionHelper "," thread ":" pool-3-thread-1 "," X-B3-TraceId ":" 5daa1244 ee26ba17344882356d926d42 "," X-B3-SpanId ":" 344882356d926d42 "}
Почему это происходит? Как я могу отладить это?
В будущем также будет другая служба, которая будет читать все записи - как мне убедиться, что она не будет ждать окончания удаления + вставки? это mvv - поведение mysql по умолчанию?
Кроме того, я пытаюсь сделать эту операцию sql для массового запуска.
У меня есть это свойство spring: spring.jpa.properties. hibernate.jdbc.batch_size = 20
, а в URL-адресе соединения есть "rewriteBatchedStatemen = true", но вы все равно вставляете в журнал все вставки одну за другой:
/* insert com.a.b.microservices.gnssynchronizer.GnsEntity
*/ insert
into
gns_entity
(changer, comments, description, dir_type, history_rec, is_synced, owner, status, submitter, was_removed, path, update_time)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
Hibernate:
/* insert com.a.b.microservices.gnssynchronizer.GnsEntity
*/ insert
into
gns_entity
(changer, comments, description, dir_type, history_rec, is_synced, owner, status, submitter, was_removed, path, update_time)
values
(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
вместо всех вместе водно большое sql заявление.
Спасибо за вашу помощь!