当前位置: 首页 > 知识库问答 >
问题:

PESSIMESTIC LOCK不适用于访问MySQL的Spring Data

劳昊明
2023-03-14

我正在使用Spring Boot构建一个调度作业数据处理应用程序。主要的逻辑是在一个预定的作业中,该作业接收一批记录并处理它们。我应该运行应用程序的2个实例,不应该选择相同的记录两次。我试图利用无等待悲观锁来解决任何记录选择冲突。事情不像预期的那样运转。两个实例都选择了相同的记录,尽管我期望只有一个实例锁定并处理一些记录,而另一个实例跳过第一个实例锁定的记录。Spring Boot版本:2.2.4 .发布

数据库:MySQl

首先,我尝试使用@Lock和@QueryHint注释:

@Lock(value = LockModeType.PESSIMISTIC_WRITE) // adds 'FOR UPDATE' statement
@QueryHints(value={@QueryHint(name = "javax.persistence.lock.timeout", value = LockOptions.SKIP_LOCKED+"")})
Page<Transaction> findByStatus(String status, Pageable pageable);

即使有WAIT_FOREVER,行为也没有改变,好像@QueryHints被完全忽略了一样。我尝试的另一个选项是使用NativeQuery:

@Query(value ="select * from transaction t where t.status = ?1 limit ?2 for update SKIP LOCKED",
            countQuery="select count(*) from transaction t where t.status = ?1",
            nativeQuery = true)
List<Transaction> findByStatusNQ(String status, Integer pageSize);

同样的行为。没有锁定,两个应用程序实例都在选择相同的数据集这是定义的实体:

@Entity
public class Transaction {
    @Id
    private Long id;

    private String description;

    private String status;

    private String managedBy;

    @Temporal(TemporalType.TIMESTAMP)
    private Date manageDate;
...
}

调用方服务组件带有@Transactional注释,以强制为每个执行创建新事务:

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public List<Transaction> updateTrxStatus(String oldStatus,String newStatus){

        List<Transaction> trxs = this.executeUsingNQ(oldStatus);

        if(trxs.size()>0) {
            logger.info( "Start updating Data");
            trxs.forEach(transaction -> {
                transaction.setStatus(newStatus);
                transaction.setManagedBy(instanceName);
                transaction.setManageDate(new Date(System.currentTimeMillis()));
            });
        }else{
            logger.info(" Nothing to process");
        }
        return trxs;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public List<Transaction> executeUsingNQ(String oldStatus){
        List<Transaction> trxs = trxRepo.findByStatusNQ(oldStatus,2);
        return trxs;
    }
    @Transactional(propagation = Propagation.REQUIRED)
    public List<Transaction> executeWithPage(String oldStatus){
        Pageable firstPageWithTwoElements = PageRequest.of(0, 2);
        Page<Transaction> trxs = trxRepo.findByStatus(oldStatus, firstPageWithTwoElements);
        return trxs.getContent();
    }

希望有人可以帮助确定是否存在一些编码问题或缺少配置!!!!

共有1个答案

夹谷星剑
2023-03-14

据运行,该问题是由于在MySql中使用了不正确的方言引起的。该版本的Dialect“MySQLDialect”在创建表时假定“MyISAMStorageEngine”为默认存储引擎。该引擎不支持任何类型的事务。唯一支持事务的存储引擎是“InnoDB”,当使用其他方言(如“MySQL55Dialect”、“MySQL57Dialect“或“MySQL8Dialect)时,它被选为默认选项

 类似资料:
  • 我在Windows 2012R2上运行MySQL 5.6.26,mysql.ini一切都配置为使用UTF-8 Unicode(utf8)。 我用这张桌子: 当我执行以下SQL命令时: 数据库会将以下数据返回给我: 118 Veneanar Forscherliga 3 5 0 56 但它不应该返回任何内容,因为“Venean–r”没有条目。 这个问题发生在PHPMyAdmin中的PHP脚本(使用P

  • 我是Spring的新手,我很困惑@CreatedDate注释在实体中是如何工作的。 我做了一次谷歌搜索,有很多解决方案,但除了一个,没有一个适合我。我很困惑为什么? 这是我先试的 它不起作用。我为列中的值获取了NULL。 然后我做了这个。 这实际上将时间戳存储在db中。我的问题是,我遵循的大多数教程都建议我不需要来获取当前时间戳。看起来我确实需要它。我缺少什么吗?

  • 我做了一个表单来更新历史数据和一个子表单,用来检查结果!除了一个小问题外,一切都很好。

  • 问题内容: 我正在使用一个平台(performforms),该平台要求我对大多数查询使用存储过程,并且从未使用过存储过程,所以无法弄清楚自己在做什么错。以下语句执行无错误: 但是当我尝试使用以下命令调用它时: 我收到以下错误: 我正在phpmyadmin 3.2.4,PHP版本5.2.12和mysql服务器版本5.0.89-community中执行这些语句。 当我编写一个存储过程返回一个参数,然后

  • 我正在为一个中国客户创建一个Android应用程序,他们需要地图集成,所以谷歌地图不是一个选项,因为所有谷歌服务在中国都被屏蔽了。我正在尝试使用百度地图,它被称为百度LBS(基于位置的服务)云。 获得一个没有覆盖的基本地图相对容易。过程在这里描述(中文,但如果你不懂语言,代码不言自明)。下载最新的百度AndroidSDK(在撰写本文时为v3.2.0)并将其作为库集成到我的Eclipse项目中没问题