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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在同时运行时阻止两个Node进程插入完全相同的数据库记录?相关的知识,希望对你有一定的参考价值。

我有一个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个Lambdas同时旋转时,它们将进入竞争状态,例如,其中3个或4个将同时检查现有记录(或彼此的微秒内),而不是找到它,因此插入多个重复的记录。

我知道解决这个问题的一种方法是在表上创建一个唯一约束来防止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创建记录。然后,它将原子地创建或返回错误,并且没有竞争条件的机会。您只需查找错误并处理它

以上是关于如何在同时运行时阻止两个Node进程插入完全相同的数据库记录?的主要内容,如果未能解决你的问题,请参考以下文章

MSSQL - 有关插入查询如何运行的问题

Node & Master——roscorerosrunrosnode

在运行不受信任的用户代码时阻止 Node.js 中的系统调用

我在数据库中建了两个字段完全相同的表

docker-compose RabbitMQ与Nodejs接收端同时运行时的错误

如何在 UITableView 中插入和删除行时模拟折纸