解决读后写竞争条件
Resolve write after read race condition
这是我需要帮助的竞争条件场景:
我们正在尝试在数据库中创建项目 A 和项目 B,并且我们希望保留项目 B 是项目 A 的“childOf”。我们假设请求创建项目 B 以及“childOf”关系数据在请求创建项目 A 之前到达。
以下是假设单个作业一次处理一个请求的步骤
- 创建项目 B 的请求首先到达,其中包含表明项目 B 是项目 A 的子项的“childOf”关系数据
- 首先,我们检查项目 A 是否存在
- 如果项目 A 存在,则创建项目 B,并在项目 B 和项目 A 之间创建“childOf”关系记录
- 如果项目 A 不存在,该过程会在数据库中创建一个挂起记录,说明项目 A 尚未创建
- 当创建项目 A 的请求到达时,将创建项目 A,并检查数据库中是否有与作为父项的项目 A 关联的任何“待定”记录,如果有待定记录,则添加“childOf”关系在项目 B 和项目 A 之间,现在项目 A 已在数据库中创建。
如果同时有多个作业运行,则可能会出现竞争条件:
Process A
Process B
req to create item B
check db for item A and item A is not found
req to create item A arrives and item A is created
since item A doesn't exist when it was checked last time, create a pending record in db with the relationship details
the pending record stays in the DB forever since item A is already created by process A while the pending record hasn't been inserted in the DB yet
如何解决此竞争条件?对不起,如果这太抽象了。如果我应该进一步详细说明,请告诉我。
我会创建一个“待定”对象,而不是作为一个单独的、不同的对象,而是在“真实”对象所在的地方,只是用一个标志来指示它的状态。
CREATE TABLE object (
name varchar(100)
CONSTRAINT object_pkey PRIMATY KEY,
pending boolean DEFAULT FALSE NOT NULL
);
现在我将像这样添加一个常规对象:
INSERT INTO object (name)
VALUES ('A')
ON CONFLICT ON CONSTRAINT object_pkey
DO UPDATE SET pending = FALSE;
挂起的对象是这样插入的:
INSERT INTO onject (name, pending)
VALUES ('A', TRUE)
ON CONFLICT ON CONSTRAINT object_pkey
DO NOTHING;
那么你在添加对象之前不需要检查是否存在,竞争条件就没有了。 INSERT ... ON CONFLICT
被设计成原子性的并且没有竞争条件。
这是我需要帮助的竞争条件场景:
我们正在尝试在数据库中创建项目 A 和项目 B,并且我们希望保留项目 B 是项目 A 的“childOf”。我们假设请求创建项目 B 以及“childOf”关系数据在请求创建项目 A 之前到达。
以下是假设单个作业一次处理一个请求的步骤
- 创建项目 B 的请求首先到达,其中包含表明项目 B 是项目 A 的子项的“childOf”关系数据
- 首先,我们检查项目 A 是否存在
- 如果项目 A 存在,则创建项目 B,并在项目 B 和项目 A 之间创建“childOf”关系记录
- 如果项目 A 不存在,该过程会在数据库中创建一个挂起记录,说明项目 A 尚未创建
- 当创建项目 A 的请求到达时,将创建项目 A,并检查数据库中是否有与作为父项的项目 A 关联的任何“待定”记录,如果有待定记录,则添加“childOf”关系在项目 B 和项目 A 之间,现在项目 A 已在数据库中创建。
如果同时有多个作业运行,则可能会出现竞争条件:
Process A | Process B |
---|---|
req to create item B | |
check db for item A and item A is not found | |
req to create item A arrives and item A is created | |
since item A doesn't exist when it was checked last time, create a pending record in db with the relationship details | |
the pending record stays in the DB forever since item A is already created by process A while the pending record hasn't been inserted in the DB yet |
如何解决此竞争条件?对不起,如果这太抽象了。如果我应该进一步详细说明,请告诉我。
我会创建一个“待定”对象,而不是作为一个单独的、不同的对象,而是在“真实”对象所在的地方,只是用一个标志来指示它的状态。
CREATE TABLE object (
name varchar(100)
CONSTRAINT object_pkey PRIMATY KEY,
pending boolean DEFAULT FALSE NOT NULL
);
现在我将像这样添加一个常规对象:
INSERT INTO object (name)
VALUES ('A')
ON CONFLICT ON CONSTRAINT object_pkey
DO UPDATE SET pending = FALSE;
挂起的对象是这样插入的:
INSERT INTO onject (name, pending)
VALUES ('A', TRUE)
ON CONFLICT ON CONSTRAINT object_pkey
DO NOTHING;
那么你在添加对象之前不需要检查是否存在,竞争条件就没有了。 INSERT ... ON CONFLICT
被设计成原子性的并且没有竞争条件。