postgresql Postgres隔离水平

oug3syen  于 2023-02-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(117)

我想请你帮忙解决我的问题。我有一个程序,它可以并行触发异步计算,并在循环中等待,直到它们完成。
我使用Postgres作为数据库,在其中创建了表computation_status,当计算被触发时,该表包含以下数据:
| 计算|完成的|
| - ------|- ------|
| 计算_A|零|
| 计算_B|零|
| 计算_C|零|
然后,我在循环中等待,直到所有计算完成。此循环接受每个已完成计算的通知,并触发SQL事务更新其状态,检查是否有任何其他计算正在运行。例如:
T1:

BEGIN_TRANSACTION
    update computation_status set finished = NOW() where and computation = 'COMPUTATION_A'
    select exists (select 1 from computation_status where finished is null)
COMMIT

T2:

BEGIN_TRANSACTION
    update computation_status set finished = NOW() where and computation = 'COMPUTATION_B'
    select exists (select 1 from computation_status where finished is null)
COMMIT

T3:

BEGIN_TRANSACTION
    update computation_status set finished = NOW() where and computation = 'COMPUTATION_C'
    select exists (select 1 from computation_status where finished is null)
COMMIT

当最后一次计算完成时,程序退出等待循环。
我应该使用什么级别的隔离来避免这些问题?我知道我至少应该使用READ_COMMITED隔离级别来防止不可重复的读取,但这足够了吗?或者,是否也有可能发生幻像读取,我应该使用REPETABLE_READ?(我不确定UPDATE是否也算作READ)。
我想避免这样的问题,例如计算A和B将在最后一个同时完成,然后T1将设置A=finished并读取B未完成,T2将设置B=finished并读取A未被钓鱼,这将导致我的应用程序出现问题,因为它将以无限循环结束。

11dmarpk

11dmarpk1#

为了避免出现争用情况,必须有效地序列化事务。
唯一能可靠工作的隔离级别是SERIALIZABLE。但是,这会导致性能损失,并且您必须准备好在引发序列化错误时重复事务。如果并发运行多个这样的事务,则会引发序列化错误。
另一种选择是使用锁,但这不是很有吸引力:使用行锁会导致死锁,而使用表锁会阻塞autovacuum,这最终会使系统崩溃。

相关问题