存储过程避免并发语句的死锁

时间:2015-10-01 19:52:10

标签: postgresql

我有以下存储过程

CREATE OR REPLACE FUNCTION testFunction(iRowID1 integer, iRowID2 integer) RETURNS void AS $$
BEGIN   
    UPDATE Table1 SET Value1=Value1+1 WHERE rowID=iRowID1;
    UPDATE Table1 SET Value1=Value1-1 WHERE rowID=iRowID2;    
END;
$$ LANGUAGE plpgsql;

如果我同时运行以下两个命令

SELECT testFunction(1,2);

SELECT testFunction(2,1);

我发现其中一个命令出现死锁检测错误。有没有办法避免这种僵局?

1 个答案:

答案 0 :(得分:2)

我现在无法对此进行测试,因为目前我无法访问PostgreSQL数据库,但从理论上说它应该可以正常工作,因为如果以相同的顺序锁定事物并且永远不会升级,则始终可以避免死锁锁定级别(例如,将读锁定升级为写锁定。)

按特定顺序执行更新:

CREATE OR REPLACE FUNCTION testFunction(iRowID1 integer, iRowID2 integer) RETURNS void AS $$
BEGIN
    IF iRowID1 < iRowID2 THEN
        UPDATE Table1 SET Value1=Value1+1 WHERE rowID=iRowID1;
        UPDATE Table1 SET Value1=Value1-1 WHERE rowID=iRowID2;
    ELSE
        UPDATE Table1 SET Value1=Value1-1 WHERE rowID=iRowID2;
        UPDATE Table1 SET Value1=Value1+1 WHERE rowID=iRowID1;
    END IF
END;
$$ LANGUAGE plpgsql;

这将始终以数字升序更新行,因此在您的示例中,第1行将始终在第2行之前更新,第二次调用无法在第一次调用完成之前开始更新。