【问题标题】:why select for update works properly only with versioned entity?为什么选择更新仅适用于版本化实体?
【发布时间】:2019-07-03 05:47:13
【问题描述】:

我将 HSQLDB 2.4.1 与 Spring data-jpa 一起使用。 如果字段“@Version”不存在,我看到另一个线程能够更新同一行。 Spring '@Scheduled' 运行的 2 个线程正在更新具有特殊状态的记录,这意味着它尚未被处理。

Repository 中的读取方法:

@Lock(LockModeType.PESSIMISTIC_READ)
@Query("select t from Task t where t.state = 0")
Page<Task> findUnprocessed(Pageable p);

“process1”和“process2”执行几乎相同的简单更新,但“process1”在保存之前暂停时间更长。

@Scheduled(fixedDelay = 10)
@Transactional(Transactional.TxType.REQUIRED)
public void process1() throws Exception {
    try {
        Task task = getTasks();
        System.out.println("process1: " + task + " by " + Thread.currentThread().getName());
        task.data= task.data + " by 1";
        task.state = 1;
        Thread.sleep(random.nextInt(4_000));
        repo.save(task);
        System.out.println("process1 updated: " + task.id);
        System.out.println("process1 read same = " + repo.findById(task.id));
    } catch (EmptyResultDataAccessException e) {
        //do nothing
    }
}

处理日志:

process1: Task(id=1) by thr-1
process2: Task(id=1) by thr-2
process2 updated: 1
process2 read same = Task(id=1, data= by 2) <<!!!
process2: Task(id=2, data=) by thr-2
process2 updated: 2
process2 read same = Task(id=2, data= by 2)
process1 updated: 1
process1 read same = Task(id=1, data= by 1) <<!!!

因此,任务#1 在进程 2 已更新后由“进程 1”更新。为什么如果使用了“更新锁定”? '@Version' 字段一切正常(然后 process2 出现异常)。

【问题讨论】:

    标签: sql database spring transactions hsqldb


    【解决方案1】:

    需要设置HSQLDB数据库的并发控制模型。如果您想要悲观锁定,请使用SET DATABASE TRANSACTION CONTROL LOCKS。这会同时启用读锁和写锁。

    详见指南http://hsqldb.org/doc/2.0/guide/sessions-chapt.html#snc_tx_tx_cc

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多