让'说我在PostgreSQL中有以下存储过程。 (请注意,这不是真正的代码。我知道这可以用另一种更好的方式完成,这只是一个例子来说明我的问题)
CREATE FUNCTION testFunction( ) RETURNS integer AS $$
DECLARE iNewID integer;
BEGIN
SELECT CurrentID INTO iNewID FROM TestTable; // statement 1
iNewID := iNewID + 1;
UPDATE TestTable SET CurrentID=iNewID; // statement 2
RETURN iNewID;
END; $$
LANGUAGE PLPGSQL;
让我们说两个不同的用户几乎同时运行它。他们可以获得相同的ID吗?
换句话说,我会试着解释一下。在代码中我评论了两个语句。如果两个用户同时运行它。命令的语句顺序是什么。我可以肯定会是这样的:
或者它可能是这样的(导致相同的ID):
我希望你理解我的问题。我真的试图在网上寻找答案,但没有运气。这可能是因为我没有这个名字?这叫什么?
非常感谢您的帮助。
答案 0 :(得分:3)
假设有两个不同的用户几乎同时运行它。他们可以获得相同的ID吗?
是的,当然。这就像你在事务之外将它作为两个单独的语句运行一样,在你的应用程序中进行添加。
使用SEQUENCE
确保唯一ID。 SERIAL
伪类型使这更容易。请注意,ID不能保证无间隙;拥有以下ID是正常的:1,3,4,5,6,9,10,11,14 ......如果事务回滚,服务器重新启动等等。
如果这对您来说是个问题,那么您需要改为:
SELECT CurrentID INTO iNewID FROM TestTable FOR UPDATE;
... blah blah ...
...将锁定该行,以便其他事务在当前提交或回滚之前无法更新它。实际上可以使用PostgreSQL特有的功能简化为:
UPDATE TestTable
SET CurrentID = iNewID
RETURNING CurrentID;
然后可以将其包装在SQL函数中,或者使用RETURN QUERY
在PL / PgSQL中运行。