如何在同时运行时阻止两个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进程插入完全相同的数据库记录?的主要内容,如果未能解决你的问题,请参考以下文章
Node & Master——roscorerosrunrosnode
在运行不受信任的用户代码时阻止 Node.js 中的系统调用