Ynv*_*Ynv 5 sql postgresql transactions isolation-level locks
我的 PostgreSQL 10.5 数据库中有以下语句,我在repeatable read事务中执行:
delete from task
where task.task_id = (
select task.task_id
from task
order by task.created_at asc
limit 1
for update skip locked
)
returning
task.task_id,
task.created_at
Run Code Online (Sandbox Code Playgroud)
不幸的是,当我运行它时,我有时会得到:
[67] ERROR: could not serialize access due to concurrent update
[67] STATEMENT: delete from task
where task.task_id = (
select task.task_id
from task
order by task.created_at asc
limit $1
for update skip locked
)
returning
task.task_id,
task.created_at
Run Code Online (Sandbox Code Playgroud)
这意味着事务回滚,因为在此期间其他事务修改了记录。(我认为?)
我不太明白这一点。不同的事务如何修改使用 选择for update skip locked并删除的记录?
Erw*_*ter 10
手册中的这句话正好讨论了您的情况:
UPDATE、DELETE、SELECT FOR UPDATE和SELECT FOR SHARE命令的行为与SELECT搜索目标行的行为相同:它们只会查找在事务开始时间提交的目标行。但是,这样的目标行在找到时可能已经被另一个并发事务更新(或删除或锁定)。在这种情况下,可重复读事务将等待第一个更新事务提交或回滚(如果它仍在进行中)。如果第一个更新器回滚,那么它的影响就被否定了,可重复读取事务可以继续更新最初找到的行。但是如果第一个更新程序提交(并且实际上更新或删除了该行,而不仅仅是锁定它)那么可重复读取事务将与消息一起回滚Run Code Online (Sandbox Code Playgroud)ERROR: could not serialize access due to concurrent update
意思是,您的事务无法锁定行开始 - 由于首先到达那里的并发写访问。SKIP LOCKED无法完全避免这种情况,因为可能不再有锁可以跳过,如果行已经更改(并且更改已提交 - 因此锁已释放)自事务开始以来,我们仍然会遇到序列化失败。
相同的语句在默认READ COMMITTED事务隔离下应该可以正常工作。有关的:
| 归档时间: |
|
| 查看次数: |
4974 次 |
| 最近记录: |