假设我有一个名为
我们有一个函数可以获取消息并从关系中删除它,像这样:
假设使用隔离级别
据我了解,在第二个
这是真的吗?或者我还应该执行
message
的关系,用于保存使用以下命令创建的消息:CREATE TABLE message
(
id serial primary key,
foo1 integer,
foo2 integer,
foo3 text
)
我们有一个函数可以获取消息并从关系中删除它,像这样:
CREATE FUNCTION get_and_delete_message(p_foo1 integer)
RETURNS TABLE(r_id integer, r_foo1 integer, r_foo2 integer, r_foo3 text) AS $$
DECLARE
message_id integer;
BEGIN
SELECT id INTO message_id FROM message WHERE foo1 = p_foo1 LIMIT 1;
RETURN QUERY SELECT * FROM message WHERE foo1 = p_foo1 LIMIT 1;
DELETE FROM message where id = message_id;
END;
$$ LANGUAGE plpgsql;
假设使用隔离级别
READ_COMMITTED
,可能会发生两个并发事务从两个用户返回相同的消息,尽管显然只有一个删除/获取它。这不是我的应用程序所期望的行为,我希望一条消息只能被一个用户读取。
如果使用 REPEATABLE_READ
,则不会发生这种情况。
但在阅读了有关 FOR UPDATE
的内容后,我认为仍然可以使用 READ_COMMITTED
级别,并将 get_and_delete_message
函数更改如下:
...
BEGIN
SELECT id INTO message_id FROM message WHERE foo1 = p_foo1 LIMIT 1;
RETURN QUERY SELECT * FROM message WHERE foo1 = p_foo1 LIMIT 1 FOR UPDATE;
DELETE FROM message where id = message_id;
END;
...
据我了解,在第二个
SELECT
语句中使用FOR UPDATE
实际上会锁定返回的行,直到事务结束,因此如果我们有两个并发事务,只有一个事务会返回并删除消息。这是真的吗?或者我还应该执行
SELECT id INTO message_id FROM message WHERE foo1 = p_foo1 LIMIT 1 FOR UPDATE
吗?我找不到关于将SELECT INTO
与FOR UPDATE
结合使用的任何信息。对此有什么想法吗?
READ_COMMITTED
隔离级别能保证没有两个并发事务返回相同的消息吗?还有一点:实际上,我试图让问题的例子简单化,所以我使用了SELECT ... ORDER BY
,但似乎不能用DELETE
做同样的事情。最后,你的答案并没有真正回答我的问题:S,尽管我非常感谢你花时间回答。 - insumity