从数据修改中锁定 table 行

Lock table row from data modifying

CREATE TABLE t1 (
  id serial int,
  col text
);

insert into t1(col) values('old_value');

现在,我需要锁定此 table 数据修改,而下面的 plsql 块是 运行ning

DO $$
  declare 
     res1 TEXT;
     res2 TEXT;
  BEGIN 
        --PERFORM pg_advisory_lock( )  
        select col from t1 where id = 1 into  res1;
        FOR i in 1..2000000000 LOOP
           -- this is just for waiting several second
        END LOOP;
        select col from t1 where id = 1 into  res2;
        RAISE NOTICE '% - %', res1, res2;
        --PERFORM pg_advisory_unlock( )  
  END;
  $$ LANGUAGE PLPGSQL

所以当这个块是 运行ning 时,我 运行 其他查询:

update t1 SET col = 'new_value' where id = 1;

当 运行ning plsql 块未完成时,此查询会立即运行并更新行。

相反,我需要更新不工作并等待,而 plsql 块 运行ning。

我想 pg_advisory_lock()pg_advisory_unlock() 会有所帮助,但是如何使用它,我不明白,这些功能的关键参数是什么,我不明白。

也不确定这些功能是否有效。

如有任何帮助,我们将不胜感激。

你想要select col from t1 where id = 1 FOR UPDATE into res1;获得锁,所以整个块应该如下所示:

做 $$ 宣布 res1 文本; res2 文本; 开始 --PERFORM pg_advisory_lock( )<br> select col from t1 where id = 1 into FOR UPDATE res1; FOR i 在 1..2000000000 循环中 -- 这只是等待几秒钟 结束循环; select col from t1 where id = 1 into res2; 发出通知 '% - %', res1, res2; --PERFORM pg_advisory_unlock( )<br> 结尾; $$ 语言 PLPGSQL

http://www.postgresql.org/docs/9.4/static/explicit-locking.html

您可以在 SELECT 子句中显式锁定事务中的行:

DO $$
  DECLARE
     res1 TEXT;
     res2 TEXT;
  BEGIN 
    SELECT col INTO res1 FROM t1 WHERE id = 1 FOR SHARE;
    pg_sleep(5); -- Sleep 5 seconds
    SELECT col INTO res2 FROM t1 WHERE id = 1;
    RAISE NOTICE '% - %', res1, res2;
  END
$$ LANGUAGE plpgsql;

使用 FOR SHARE 子句而不是 FOR UPDATE 以允许其他会话读取数据,但不能更新。