sql - 如何为 PostgreSQL 编写我自己的全局锁定/解锁函数

标签 sql postgresql concurrency locking blocking

我有 postgresql(在 perlu 中)函数 getTravelTime(integer, timestamp),它会尝试为指定的 ID 和时间戳选择数据。如果没有数据或者数据是旧的,它会从外部服务器下载它们(下载时间~300ms)。

多个进程使用这个数据库和这个函数。当两个进程找不到数据并下载它们并尝试插入 travel_time 表时会出现错误(id 和时间戳对必须是唯一的)。我想到了锁。锁定整个表将阻止所有进程并只允许一个继续进行。我只需要锁定 id 和时间戳。 pg_advisory_lock 似乎只锁定在“当前 session ”中。但是我的进程使用它们自己的 session 。

我尝试编写自己的锁定/解锁函数。我做对了吗?我使用主动等待,我怎么能省略这个呢?也许有一种方法可以使用 pg_advisory_lock() 作为全局锁?

我的代码:

CREATE TABLE travel_time_locks (
    id_key integer NOT NULL,
    time_key timestamp without time zone NOT NULL,
    UNIQUE (id_key, time_key) 
);

------------
-- Function: mylock(integer, timestamp)
DROP FUNCTION IF EXISTS mylock(integer, timestamp) CASCADE;
-- Usage: SELECT mylock(1, '2010-03-28T19:45');
-- function tries to do a global lock similar to pg_advisory_lock(key, key)
CREATE OR REPLACE FUNCTION mylock(id_input integer, time_input timestamp)
  RETURNS void AS
$BODY$
DECLARE
    rows int;
BEGIN
    LOOP

        BEGIN
            -- active waiting here !!!! :(
            INSERT INTO travel_time_locks (id_key, time_key) VALUES (id_input, time_input);
        EXCEPTION WHEN unique_violation THEN
            CONTINUE;
        END;
        EXIT;
    END LOOP;
END;
$BODY$ LANGUAGE 'plpgsql' VOLATILE
    COST 1;

------------
-- Function: myunlock(integer, timestamp)
DROP FUNCTION IF EXISTS myunlock(integer, timestamp) CASCADE;
-- Usage: SELECT myunlock(1, '2010-03-28T19:45');
-- function tries to do a global unlock similar to pg_advisory_unlock(key, key)
CREATE OR REPLACE FUNCTION myunlock(id_input integer, time_input timestamp)
  RETURNS integer AS
$BODY$
DECLARE
BEGIN
    DELETE FROM ONLY travel_time_locks WHERE id_key=id_input AND time_key=time_input;
    RETURN 1;
END;
$BODY$ LANGUAGE 'plpgsql' VOLATILE
    COST 1;

最佳答案

使用 pg_advisory_lock()。这正是您所需要的。

关于sql - 如何为 PostgreSQL 编写我自己的全局锁定/解锁函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2633006/

相关文章:

mysql - 如何从架构中的每一列获取示例值

java - 使用 Java 从 postgreSQL 检索 inet 数据类型?

android - 何时用刷新 token 交换访问 token

database - 创建 postgres 数据库的 docker 镜像?

java - 使用 SwingWorker 更新 GUI

concurrency - 单个进程可以在多个内核中运行吗?

mysql - 根据两列选择行并根据第三列排序

MySQL 将数据分离到两个新列

sql - 在存储过程中使用 CASE 语句

postgresql - 如何在 POSTGIS 中找到最近的点?