我开始在PostgreSQL玩,发现sequence
从来没有回退,甚至失败INSERT
。
我读过,这是预期,以防止并发事务的重复序列,我发现奇怪的是我的数据库的经验是只有GTM此时事务重启是常见的,这正是使用。PostgreSQL的交易重新启动
所以我想测试在PGSQL重新启动,并在数据库中装载这样的:
CREATE SEQUENCE account_id_seq;
CREATE TABLE account
(
id integer NOT NULL DEFAULT nextval('account_id_seq'),
title character varying(40) NOT NULL,
balance integer NOT NULL DEFAULT 0,
CONSTRAINT account_pkey PRIMARY KEY (id)
);
INSERT INTO account (title) VALUES ('Test Account');
CREATE OR REPLACE FUNCTION mytest() RETURNS integer AS $$
DECLARE
cc integer;
BEGIN
cc := balance from account where id=1;
RAISE NOTICE 'Balance: %', cc;
perform pg_sleep(3);
update account set balance = cc+10 where id=1 RETURNING balance INTO cc;
return cc;
END
$$
LANGUAGE plpgsql;
因此,功能mytest()
将检索的平衡,等待3秒(让我启动其他程序),然后更新余额基于已保存的变量。
我现在从外壳推出2次调用该函数直接:
void$ psql -c "select * from account where id=1"
id | title | balance
----+--------------+---------
1 | Test Account | 0
(1 row)
void$ psql -c "select mytest()" & PIDA=$! && psql -c "select mytest()" && wait $PIDA
[1] 3312
NOTICE: Balance: 0
NOTICE: Balance: 0
mytest
--------
10
(1 row)
mytest
--------
10
(1 row)
[1]+ Done psql -c "select mytest()"
void$ psql -c "select * from account where id=1"
id | title | balance
----+--------------+---------
1 | Test Account | 10
(1 row)
我希望平衡是20,不是10,作为最后的交易将被提交应重新启动作为的balance from account where id=1
“视图”在加工过程中改变...
我读过有关transaction isolation in official documentation和它的声音对我说默认read committed
应该强制执行这种行为恰恰..
我也测试了改变隔离级别serializable
,然后最后TRAN saction承诺不抛出一个异常,但我想知道,如果没有任何“交易重启”功能(如我所描述的),或者如果我失去了一些东西......
锁是不完全一样的,因为我想/描述的行为,但它是一个替代方案,我也不知道如何使用和适用于我的情况,因此被接受为答案,谢谢!我知道我可以把它简化成一个单一的更新,但目的是为了方便地正是测试,看它是否会“重新启动”。 – 2015-03-31 14:19:02
对于“重启”,我的意思是第二个事务不会等待第一个完成(就像第一行的LOCK),但它会执行,并且只在COMMIT部分检查“原始数据库视图”是否更改以及结果将是意外的,因此从START TRANSACTION点重新开始。 – 2015-03-31 14:21:53
将事务隔离级别设置为“可序列化”是否会执行此操作,但不会重新启动会引发异常。我想我可以有一个outter函数处理这个异常,它会重新执行内部函数,直到它没有抛出它,但是暂时LOCKs工作,甚至听起来像是一个更适合我的场景的解决方案。 – 2015-03-31 14:23:46