我试图在一个函数中创建一个事务块,我的目标是使这个函数一次只能使用一次。如果有人使用了这个函数并且另一个人想要使用它,则必须等待第一个人完成后才能使用。
CREATE OR REPLACE FUNCTION my_job(time_to_wait integer) RETURNS INTEGER AS $$
DECLARE
max INT;
BEGIN
BEGIN;
SELECT MAX(max_value) INTO max FROM sch_lock.table_concurente;
INSERT INTO sch_lock.table_concurente(max_value, date_insertion) VALUES(max + 1, now());
-- Sleep a wail
PERFORM pg_sleep(time_to_wait);
RETURN max;
COMMIT;
END;
$$
LANGUAGE plpgsql;
但似乎不起作用,我有一个语法错误 BEGIN;
如果没有BEGIN;
和COMMIT
,我会得到正确的结果,我使用这个查询来检查:
-- First user should to wait 10 second
SELECT my_job(10) as max_value;
-- First user should to wait 3 second
SELECT my_job(3) as max_value;
所以结果是:
+-----+----------------------------+------------+
| id | date | max_value |
+-----+----------------------------+------------+
| 1 | 2017-02-13 13:03:58.12+00 | 1 |
+-----|----------------------------+------------+
| 2 | 2017-02-13 13:10:00.291+00 | 2 |
+-----+----------------------------+------------+
| 3 | 2017-02-13 13:10:00.291+00 | 2 |
+-----+----------------------------+------------+
但结果应该是:
+-----+----------------------------+------------+
| id | date | max_value |
+-----+----------------------------+------------+
| 1 | 2017-02-13 13:03:58.12+00 | 1 |
+-----|----------------------------+------------+
| 2 | 2017-02-13 13:10:00.291+00 | 2 |
+-----+----------------------------+------------+
| 3 | 2017-02-13 13:10:00.291+00 | 3 |
+-----+----------------------------+------------+
因此,第三个
id = 3
应该具有 max_value = 3
而不是 2
,这是因为第一个用户选择了 max = 1
并等待了 10 秒
,第二个用户选择了 max = 1
并等待了 3 秒
才进行插入,但正确的解决方案是:在第一个完成之前,我不能使用此函数,因此我想要创建一些安全和受保护的东西。我的问题是:
- 如何在函数内部创建事务块?
- 您有任何建议,可以以安全的方式实现吗?
READ UNCOMMITTED
作为暂时的解决方法,但在这样做之前,你需要真正了解其中的影响。 - Chris Travers