sql - 如何以最佳方式锁定postgres中的数据
问题描述
我有这两个函数充当互斥锁和解锁:
CREATE OR REPLACE FUNCTION get_config (guildid_in int8, key_in varchar) RETURNS jsonb AS $$
DECLARE d JSONB;
BEGIN
WHILE (SELECT locked FROM guild_options WHERE guildid = guildid_in AND key = key_in) LOOP END LOOP;
UPDATE guild_options SET locked = true WHERE guildid = guildid_in AND key = key_in;
SELECT data INTO d FROM guild_options WHERE guildid = guildid_in AND key = key_in ;
REtURN d;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION set_config (guildid_in int8, key_in varchar, data_in jsonb) RETURNS void AS $$
BEGIN
UPDATE guild_options SET locked = false, data = data_in WHERE guildid = guildid_in AND key = key_in;
END;
$$ LANGUAGE plpgsql;
我有这两个功能的原因是因为我不希望不同客户端之间的数据竞争覆盖数据等等,这允许我锁定一段数据,修改它然后解锁以供其他客户端读取/更新。我没有使用 postgres 锁(表锁、行锁、咨询锁),因为我需要锁定多个事务的能力,并且因为我在程序中使用数据库池,所以我不能使用咨询锁,因为有多个会话一次连接到数据库,我无法控制哪一个锁定/解锁
有没有更好的方法来做到这一点(比如更好的投票)?
解决方案
您“需要锁定多个事务的能力”。这正是 Postgres 锁的作用。可以在事务或会话级别获取建议锁。您可能还希望将其视为Serializable Isolation Level。
顺便说一句:您的功能没有达到您的预期。在get_config
您将锁定的列更新为 True,但在您提交之前没有其他会话看到此内容。现在,如果此过程是更大且仅部分完成的事务的一部分,则此处的提交将提交到目前为止完成的所有事务,如果稍后整个事务失败,则您已提交事务的一部分。即使您在更新后提交,仍然有可能在更新和提交之间出现另一个事务(苗条但不是 0)。同样适用该set_config
功能。
推荐阅读
- python - 使函数不等待其中的其他函数
- blazor - 如何在 Blazor 中获取单击事件的目标元素
- ios - 再次打开我的应用程序后,如何保存对象数组并使用相同的值重复使用。#迅速
- c# - 如何在 Entity Framework Core 3 中没有密钥的情况下播种数据?
- python - Python:如何根据用户输入打印对象属性
- sql - 如何替换Oracle中的字符串?
- java - 导入时无法解析符号 TreeMap
- java - 反转数组的方法导致 StackOverflowError
- stripe-payments - Stripe:在期末取消订阅之前发送电子邮件/通知
- database - Oracle 10g 数据库恢复