在 Postgres 支持的 .NET 应用程序中实现乐观并发时,我陷入了僵局。
以下存储函数返回 FOUND,如果传递的 ID 与 WHERE 子句不匹配,则调用端点将返回 404:
CREATE OR REPLACE FUNCTION institution_delete_by_id(IN in_id UUID) RETURNS BOOLEAN
LANGUAGE plpgsql
AS
$$
BEGIN
DELETE
FROM institution
WHERE id = in_id;
RETURN FOUND;
END
$$;
引入乐观并发,我会做类似以下的事情(我想当我读完之后我会使用 xmin ):
CREATE OR REPLACE FUNCTION institution_delete_by_id(IN in_id UUID, IN in_version BIGINT) RETURNS BOOLEAN
LANGUAGE plpgsql
AS
$$
BEGIN
DELETE
FROM institution
WHERE id = in_id AND version = in_version; -- Here's the addition
RETURN FOUND;
END
$$;
但是,这样做时,应用程序无法推断 FOUND 是否因 ID 不匹配而为假,或者 FOUND 是否因表的并发更新而为假。因此,端点无法判断是否应该返回 404 还是 409(冲突)。
那么,如何理想地使用 FOUND 并实现乐观并发,同时允许应用程序区分差异?
我猜,当
version
!= 时,人们可以提出一个特殊的例外
in_version.
但是如何呢?
这将使应用程序根据特定的异常类型控制其流程。我不喜欢那样,但是这里可以吗?
解决这个问题没有一个标准吗?我使用 Npgsql 作为数据库接口。
我尝试寻找类似的例子,但没有找到任何适用的。
您想要返回三种状态之一:
我建议你使用整数或枚举来编码这三种状态。
关于功能实现:
DECLARE
current_version bigint;
row_id tid;
BEGIN
-- find and lock the row if it exists
SELECT version, ctid
INTO current_version, row_id
FROM institution
WHERE id = in_id
FOR UPDATE;
IF NOT FOUND THEN
RETURN 0;
END IF;
-- give up if the row was modified
IF current_version <> in_version THEN
RETURN 1;
END IF;
DELETE FROM institution
WHERE ctid = row_id;
RETURN 2;
END;