sql - SELECT ... FOR UPDATE SKIP LOCKED in REPEATABLE READ 事务

标签 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

不幸的是,当我运行它时,我有时会得到:

[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

这意味着事务回滚,因为其他事务同时修改了记录。 (我想?)

这个我不是很明白。不同的事务如何修改通过 for update skip locked 选择并删除的记录?

最佳答案

This quote from the manual 准确地讨论您的案例:

UPDATE, DELETE, SELECT FOR UPDATE, and SELECT FOR SHARE commands behave the same as SELECT in terms of searching for target rows: they will only find target rows that were committed as of the transaction start time. However, such a target row might have already been updated (or deleted or locked) by another concurrent transaction by the time it is found. In this case, the repeatable read transaction will wait for the first updating transaction to commit or roll back (if it is still in progress). If the first updater rolls back, then its effects are negated and the repeatable read transaction can proceed with updating the originally found row. But if the first updater commits (and actually updated or deleted the row, not just locked it) then the repeatable read transaction will be rolled back with the message

ERROR:  could not serialize access due to concurrent update

意思是,您的事务无法锁定开始的行 - 由于首先到达那里的并发写访问。 SKIP LOCKED 无法将您从这里完全拯救出来,因为可能不再有可跳过的锁,并且如果该行已被更改(并且已提交更改 - 因此锁定),我们仍然会遇到序列化失败发布)自交易开始。

相同的语句在默认的 READ COMMITTED 事务隔离下应该工作得很好。相关:

关于sql - SELECT ... FOR UPDATE SKIP LOCKED in REPEATABLE READ 事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53288584/

相关文章:

Spring 事务管理器 : Rollback doesnt work

sql - SQL vs NoSQL构建示例

sql - 在 SQL 中使用两个 DISTINCT 语句

mysql - 遍历mysql表以填充Node中的数组

java - 使用 ibatis 检索新插入行的 ID 时的并发问题

spring - 提交事务后Spring是否关闭连接?

mysql - 将 ipv4 和 ipv6 地址转换为整数

sql - PostgreSQL - 有条件地从 WHERE 子句中排除语句

postgresql - 创建从我计算机上的 CSV 文件复制到位于 Postgres 中另一台计算机上的数据库的查询

php - MySQLI:事务,允许PHP处理还是在MySQL中处理?