【问题标题】:Are the rows locked in order in a SELECT ... ORDER BY ... FOR UPDATE statement?SELECT ... ORDER BY ... FOR UPDATE 语句中的行是否按顺序锁定?
【发布时间】:2019-01-29 00:43:58
【问题描述】:

这个问题可以看作是我对Can two concurrent but identical DELETE statements cause a deadlock?的评论的后续。

我想知道以下语句中的行是否以升序锁定my_status

SELECT 1 FROM my_table ORDER BY my_status FOR UPDATE;

https://www.postgresql.org/docs/9.5/static/sql-select.html 上有一条有趣的评论说:

SELECT 命令可以在READ COMMITTED 事务隔离级别运行并使用ORDER BY 和锁定子句以乱序返回行。这是因为首先应用了ORDER BY。该命令对结果进行排序,但随后可能会阻止尝试获取一个或多个行的锁定。一旦SELECT 解除阻塞,一些排序列值可能已被修改,导致这些行看起来是乱序的(尽管它们在原始列值方面是按顺序排列的)。这可以通过将FOR UPDATE/SHARE 子句放在子查询中来解决,例如

SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss ORDER BY column1;

我不确定这是否能回答我的问题。这就是说首先应用ORDER BY,并且您需要将FOR UPDATE 放在子查询中以解决副作用,即如果订单列的值已更改,实际输出顺序可能会有所不同与此同时。换句话说,将FOR UPDATE 放在子查询中可确保在排序之前发生锁定。

但这并不能真正告诉我们这些行是否真的按照ORDER BY 子句确定的顺序锁定?

【问题讨论】:

    标签: sql postgresql postgresql-9.5 database-deadlocks


    【解决方案1】:

    按照ORDER BY 子句的顺序锁定行就像扫描表时一样

    执行查询并对行进行排序,然后 PostgreSQL 按顺序锁定行。本质上,ORDER BY 发生在 FOR UPDATE 之前。

    现在可能会发生锁定行阻塞,因为并发事务持有锁。如果发生这种情况,并且我们处于 READ COMMITTED 隔离级别,那么 PostgreSQL 等待直到它能够获得锁,然后然后获取它锁定的行的当前版本 .

    如果并发事务修改了定义排序的列,最终结果将不会按照ORDER BY定义的顺序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-05
      • 2012-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-26
      • 1970-01-01
      相关资源
      最近更新 更多