如何防止两个节点进程在 运行 同时插入完全相同的数据库记录?

How do I prevent two Node processes from inserting the exact same database record when running simultaneously?

我有一个 Lambda,一次可以将数千个事件发送给它。并发保留为默认值,这意味着 AWS 将启动多个实例来处理传入事件。 Lambda 获取数据并将一些数据插入数据库(如果该数据尚不存在)。 Lambda 是用 Node.js 编写的,并使用 Knex 连接到 Postgres 数据库。

Lambda 本质上包含以下逻辑:

Does a record with ID X exist?     
a. Yes: do nothing
b. No: create a new record with ID X.

问题在于,当 50 个 Lambda 同时启动时,它们将进入竞争状态,其中 3 或 4 个将同时(或在几微秒内)检查现有记录彼此) 而找不到它,因此插入多个重复记录。

我知道解决这个问题的一种方法是在 table 上创建一个唯一约束,以防止 ID 为 X 的多个记录。然后我的逻辑将如下所示:

Does a record with ID X exist? 
a. Yes: do nothing 
b. No: create a new record with ID X.
   b.1. Did that succeed?
      a. Yes: continue on.
      b. No, it threw a unique constraint error: go back to line 1.

这似乎有点做作,但应该可行。还有更好的选择吗?

编辑:

这是实际代码:

let location = await Location.query().where({ external_id }).first();
if(!location){
    location = await Location.query().insert({
        name,
        external_id
    });
}

这样的代码:

Does a record with ID X exist?      
a. Yes: do nothing 
b. No: create a new record with ID X.

不以某种方式锁定数据库是一种竞争条件。在查询记录 X 和创建它之间,其他一些请求也可以创建它。永远不要这样做。这很活泼。

您必须查看您的数据库提供的特定工具,但执行上述序列的常见方法是设置数据库,使其不允许 ID X 重复,然后您只需尝试创建ID为x的记录。然后,它将自动创建或 return 一个错误,并且不会有竞争条件的机会。您只需查找错误并处理它