我有下表:
CREATE TABLE myid
(
nid bigserial NOT NULL,
myid character varying NOT NULL,
CONSTRAINT myid_pkey PRIMARY KEY (myid )
)
现在,我想使用以下函数向此表添加记录:
CREATE FUNCTION getmyid(_myid character varying)
RETURNS bigint AS
$BODY$ --version 1.1 2015-03-04 08:16
DECLARE
p_nid bigint;
BEGIN
SELECT nid INTO p_nid FROM myid WHERE myid=_myid FOR UPDATE;
IF NOT FOUND THEN
INSERT INTO myid(myid) VALUES(_myid) RETURNING nid INTO p_nid;
END IF;
RETURN p_nid;
END;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
一般情况下它工作正常,但在高负荷下,此功能有时会失败并且#34;重复键值违反了唯一约束" myid_pkey&#34 ;; 从另一个表上的insert上的触发器调用此函数,并在事务中调用插入。隔离级别设置为Debian Wheezy上的READ COMMITED,postgres 9.1。 我做错了什么?
答案 0 :(得分:1)
我看到它是如何发生的。
myid
同时调用该函数。 SELECT nid INTO ..
查询,并看到 - 现在表中没有这样的myid
。 IF NOT FOUND THEN
INSERT INTO myid(myid)
并提交没有错误的事务INSERT INTO myid(myid)
并失败,因为表中已存在相同的myid
值(PRIMARY KEY约束)。 为什么线程2在自己的事务中看到其他事务提交数据? 由于'不可重复读'现象,这可以通过READ COMMITTED隔离(http://www.postgresql.org/docs/9.2/static/transaction-iso.html)来实现。