如何在Oracle/PostgreSQL中保护正在运行的列(MAX-result锁定之类的东西)

Tou*_*uko 2 oracle postgresql concurrency transactions

我需要有关Oracle/PostgreSQL的以下情况的建议:

我有一个带有"运行计数器"的数据库表,并希望在以下两种并发事务的情况下保护它:

T1                      T2
SELECT MAX(C) FROM TABLE WHERE CODE='xx'
-- C for new : result + 1
                        SELECT MAX(C) FROM TABLE WHERE CODE='xx';
                        -- C for new : result + 1
                        INSERT INTO TABLE... 
INSERT INTO TABLE... 
Run Code Online (Sandbox Code Playgroud)

因此,在这两种情况下,INSERT的列值都是从一个添加的旧结果计算出来的.

由此,db处理的一些运行计数器就可以了.但这不起作用,因为

  • 计数器值或现有行有时会更改
  • 有时我希望有多个计数器"值组"(与提到的CODE一样):对于CODE的不同值,计数器将是独立的.

对于其他一些数据库,这可以通过SERIALIZABLE隔离状态来处理,但至少对于Oracle和Postgre,可以防止幻像读取,但结果表最终会有两个具有相同计数器值的不同行.这似乎与谓词锁定有关,锁定"查询覆盖的所有可能行" - 其他一些db:s最终会锁定整个表或其他东西.

SELECT ... FOR UPDATE -statements似乎用于其他目的,甚至似乎不适用于MAX()函数.

在列上设置UNIQUE约束可能是解决方案但是有其他方法可以防止这种情况吗?

br Touko

编辑:一个选项可能是手动锁定,即使它对我来说不是很好..

Vin*_*vic 6

无论甲骨文PostgreSQL的支持什么叫做序列和完美契合您的问题.您可以拥有常规的int列,但每个组定义一个序列,并执行单个查询

--PostgreSQL
insert into table (id, ... ) values (nextval(sequence_name_for_group_xx), ... )

--Oracle
insert into table (id, ... ) values (sequence_name_for_group_xx.nextval, ... )
Run Code Online (Sandbox Code Playgroud)

序列的增量是原子的,所以你的问题就不存在了.这只是创建所需序列的问题,每组一个.