【问题标题】:Atomic Batch Insert / Update in JooqJooq 中的原子批量插入/更新
【发布时间】:2021-01-20 18:40:53
【问题描述】:

我有一个监控服务并保存其当前状态的程序。我的程序会定期检查每个服务并将有关它们的信息存储在 postgres 中。大多数情况下,这涉及更新数据库中的现有行。但有时,也需要添加新服务。

我将它们存储在一个看起来像这样的架构中:

CREATE TABLE services IF NOT EXISTS (
  id          SERIAL    NOT NULL,
  name        TEXT      NOT NULL,
  status      TEXT    ,
  PRIMARY KEY (id, name)
)

其中 ID 指定一台机器,名称指定该机器上的一项服务。 POJO 非常简单:

public class Service {
  int id;
  String name;
  String status;
}

例如,我的表格可能只有一行:(22, "api", "active")。在预定的时间间隔内,我的程序确定现在有 2 个服务在一台机器上运行,并且当前服务的状态发生了变化:

  • (22, "api", "error")
  • (22, "消息", "活动")

我的方法是这样的:

  Set<ServicesRecord> records = listServices
    .stream()
    .map(service -> {
      ServicesRecord record = new ServicesRecord();
      record.setId(service.id);
      record.setName(service.name);
      record.setStatus(service.status);
      return record;
    })
    .collect(Collectors.toSet());
    DSLContext dsl = DSL.using(this.configuration);
    dsl.batchStore(records).execute();
}

但是,当我尝试运行它时,这给了我一个错误:

Caused by: org.jooq.exception.DataAccessException: SQL [insert into "foobar"."services" ("id", "name", "status", values (?, ?, ?)]; Batch entry 0 insert into "foobar"."services" ("id", "name", "status") values (1, 'testName', 'baz') was aborted: ERROR: duplicate key value violates unique constraint "services_pkey"

我可以看到 batchStore 失败,因为它使用了 UpdatableRecord 的 store 方法,而该方法又失败了,因为我正在创建一条新记录,而不是从 jooq 获取一条。

我正在考虑这样的替代方法:

  1. 从数据库中获取所有记录。
  2. 对于与records 匹配的每条记录,我将changed 设置为true。
  3. 然后我运行batchStore

或者,我可以这样做吗?

  1. 从数据库中获取所有记录。
  2. 制作要插入的记录列表并使用batchInsert
  3. 制作要更新的记录列表,修改其记录,使用batchStore

但是这两个都冒着不是原子的风险。如果在执行第 2 步时数据库发生更改,我对 batchStore 的使用仍然会失败。我想要的是一种在单个操作中进行这种批量存储的方法,而不是先执行获取然后执行。有没有办法做到这一点?

【问题讨论】:

    标签: postgresql jooq


    【解决方案1】:

    您正在寻找的是 batchMerge(),它将随 jOOQ 3.14 一起提供:https://github.com/jOOQ/jOOQ/issues/10046

    或者,您可以使用data import API。然后,您可以将onDuplicateKeyUpdate() 子句与适当的batch sizes 结合起来。

    或者,您可以写明确的INSERT .. ON CONFLICT statements 和batch them explicitly。

    【讨论】:

      猜你喜欢
      • 2018-08-13
      • 2021-03-27
      • 2020-05-22
      • 2017-12-29
      • 1970-01-01
      • 2021-05-23
      • 1970-01-01
      • 1970-01-01
      • 2012-02-16
      相关资源
      最近更新 更多