首页 > 解决方案 > 在 postgres 中删除和插入的竞争条件

问题描述

我正在开发一个节点项目,我在其中导入了 pg 库以进行数据库操作。我有一个 Kafka 队列,我从中获取事件并将它们存储在数据库中。我正在从 kafka 获取订单,每次更新订单时都会生成一个新事件,我需要删除旧的订单详细信息并用新的替换它们。

下面是代码

async function saveOrders(orders: Array<TransactionOnOrders>) {
  const client = await pool.connect()
 
  try {
    await client.query('BEGIN')
    if (orders.length) {
      const deleted = await deleteOrders(client, orders[0].orderId)
      logger.debug(`deleted rowCount ${deleted.rowCount} ${orders[0].orderId}`)
    }
    const queries = orders.map(ord => saveTransactionOnOrders(client, ord))
    await Promise.all(queries)
    await client.query('COMMIT')
  } catch (e) {
    await client.query('ROLLBACK')
    throw e
  } finally {
    client.release()
  }
}

订单更新非常频繁,我们收到大量事件,创建竞争条件导致记录不被删除并插入额外记录。例如:假设我们收到 order123 的事件并且事务正在进行中,直到它完成 order123 的另一个事件的时间,因此删除查询返回 0 行受影响,插入查询插入另一行导致 2 行应该只有一个记录存在。

我试图更改效果不佳并导致错误的隔离级别

await client.query('BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ')
await client.query('BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE')

我在这里做错了什么还是有更好的方法来处理上述情况?

标签: node.jsdatabasepostgresqlrace-condition

解决方案


如果您更新行而不是删除它们并重新创建它们,这可能会更容易。在这种情况下,您可以依靠行锁来防止并发更新。


推荐阅读