使用MySQL避免死锁ON DUPLICATE KEY UPDATE Spring JDBC

时间:2018-02-16 19:38:11

标签: mysql spring-boot jdbc spring-data-jpa

通过Spring Boot / JPA和MySQL进行“upsert”时,我遇到了避免死锁的麻烦。我异步调用服务层中的方法,因此单个请求可以同时多次调用upsert,同时也可以有多个请求。性能也是一个考虑因素。我需要做些什么来避免死锁?

这是我的Spring JPA方法:

@Modifying
@Transactional
@Query(value = "INSERT INTO message_resource (organizationId, messageId, bucket, friendlyName, fullPathName, uuid, md5, contentType, reference, size, created, updated)\n" +
        "VALUES (:organizationId, :messageId, :bucket, :friendlyName, :fullPathName, :uuid, :md5, :contentType, :reference, :size, :created, :updated)\n" +
        "ON DUPLICATE KEY UPDATE id=LAST_INSERT_ID(id), friendlyName=:friendlyName, uuid=:uuid, md5=:md5, contentType=:contentType, reference=:reference, size=:size, created=:created, updated=:updated", nativeQuery = true)
int upsert(
        @Param("organizationId") long organizationId,
        @Param("messageId") long messageId,
        @Param("bucket") String bucket,
        @Param("friendlyName") String friendlyName,
        @Param("fullPathName") String fullPathName,
        @Param("uuid") String uuid,
        @Param("md5") String md5,
        @Param("contentType") String contentType,
        @Param("reference") String reference,
        @Param("size") long size,
        @Param("created") long created,
        @Param("updated") long updated);

这是我的服务层呼叫:

@Async
public void upsert() throws IOException {

    ...

    EntityManager entityManager = entityManagerFactory.createEntityManager();
    entityManager.getTransaction().begin();

    messageResourceRepository.upsert(
            mediaObject.getOrganizationId(),
            mediaObject.getMessageId(),
            messageResourceEntity.getBucket(),
            messageResourceEntity.getFriendlyName(),
            messageResourceEntity.getFullPathName(),
            messageResourceEntity.getUuid(),
            messageResourceEntity.getMd5(),
            messageResourceEntity.getContentType(),
            messageResourceEntity.getReference(),
            messageResourceEntity.getSize(),
            messageResourceEntity.getCreated(),
            messageResourceEntity.getUpdated()
    );

    entityManager.getTransaction().commit();
    entityManager.close();
    ...
}

1 个答案:

答案 0 :(得分:0)

这是mysql 5.7的错误,应改用普通插入。

请参阅此处:https://sadlil.com/blog/mysql-deadlock/