PostgreSQL中有40001错误

时间:2017-07-05 07:00:55

标签: sql postgresql

我有简单的表"计数器":

"CounterId" SERIAL (PK)

"CounterName" VARCHAR(50) NOT NULL (UNIQUE INDEX)

"Value" BIGINT NOT NULL

当两个可序列化的事务(实际上有很多这样的事务在同一时间内)执行查询时:

SELECT NULL 
FROM "Counters" 
WHERE "CounterName" = @Value FOR UPDATE

SELECT "CounterId", "CounterName", "Value" 
FROM "Counters" 
WHERE "CounterName" = @Value
LIMIT 2 

(此查询由Entity Framework在相同的连接和事务中执行)

UPDATE "Counters" SET "Value" = @Value WHERE "CounterId" = @CounterId

其中一个交易回滚,错误40001

  由于事务之间的读/写依赖性,

无法序列化访问

我正在重试错误事务(5次),但仍然会发生此错误。

这可能是由第一次和第三次查询中的不同谓词引起的?

1 个答案:

答案 0 :(得分:4)

如果上面描述的两个事务同时运行,则会发生以下情况:

  1. 事务1使用SELECT ... FOR UPDATE锁定一行。

  2. 事务2尝试锁定同一行并被阻止。

  3. 事务1修改值并提交。

  4. 事务2未被阻塞,在锁定行之前,必须重新检查它要锁定的行版本是否仍然是最新版本。由于事务1的修改,不再是这种情况,并且抛出了序列化错误。

  5. 如果隔离级别为REPEATABLE READ或更高级别的多个事务正在尝试修改相同的行,则无法避免该问题。准备好经常重试!

    事务似乎实际上锁定了比修改更多的行。这加剧了这个问题。只锁定那些需要更改的行!