Обсуждение: Questions of 'for update'

Поиск
Список
Период
Сортировка

Questions of 'for update'

От
Zhenghua Lyu
Дата:
Hi,

    I am reading the code that generating plan for `rowmarks` of Postgres 9.4 (https://github.com/postgres/postgres/blob/REL9_4_STABLE/src/backend/optimizer/plan/planner.c#L2070

  After emitting the `LockRows` plannode, the results cannot be considered in order, and there are comments there:
/*
 * The result can no longer be assumed sorted, since locking might
 * cause the sort key columns to be replaced with new values.
 */

I do not understand the reason and after some guess, I come up with a case:

```
create table t(c int);
insert into t values (1), (2), (3), (4);

-- Transaction 1
begin;
update t set c = 999 where c = 1; -- change the smallest value to a very big one
-- transaction 1 not commit yet

-- Transaction 2, another session
begin;
select * from t order by c limit 1 for update; -- Want to find the smallest value, and then update it
-- this transaction will be blocked by transaction 1

-- then, transaction 1 commit and transaction 2 will return the tuple with value 999
```

I think the reason is that EvalPlanQual does not check the order.

I try this case under mysql, it will output 2 (which is the correct value for the meaning of smallest).

So, in summary, my questions are:

1. why after emitting `lockrows` plannode,  the result can no longer be assumed sorted?
2. Is the case above a bug or a feature?

Thanks!

Best Regards,
Zhenghua Lyu

Re: Questions of 'for update'

От
Kuntal Ghosh
Дата:
Hello,

On Mon, Jun 10, 2019 at 11:31 AM Zhenghua Lyu <zlv@pivotal.io> wrote:

1. why after emitting `lockrows` plannode,  the result can no longer be assumed sorted?
The plan corresponding to your select query is as following:
          QUERY PLAN            
-------------------------------
Limit
  ->  LockRows
        ->  Sort
              Sort Key: c
              ->  Seq Scan on t

In LockRows node, the executer tries to lock each tuple which are provided by the Sort node. In the meantime, it's possible that some transaction updates a tuple (which is to be locked by the current transaction) and gets committed. These changes will be visible to the current transaction if it has a transaction isolation level lesser than REPEATABLE_READ. So, the current transaction needs to check whether the updated tuple still satisfies the qual check (in your query, there is no quals, so it always satisfies). If it satisfies, it returns the updated tuple.
Since, the sort has been performed by an earlier node, the output will no longer be sorted.
 
 
2. Is the case above a bug or a feature?

IMHO, it looks like an expected behaviour of a correct transaction management implementation. The argument can be that the snapshot is consistent throughout all the nodes. Whatever tuple you've fetched from the bottom level is locked correctly.

--
Thanks & Regards,
Kuntal Ghosh
EnterpriseDB: http://www.enterprisedb.com

Re: Questions of 'for update'

От
Etsuro Fujita
Дата:
Hi,

On Mon, Jun 10, 2019 at 3:50 PM Kuntal Ghosh <kuntalghosh.2007@gmail.com> wrote:
> On Mon, Jun 10, 2019 at 11:31 AM Zhenghua Lyu <zlv@pivotal.io> wrote:
>> 2. Is the case above a bug or a feature?
>>
> IMHO, it looks like an expected behaviour of a correct transaction management implementation.

This is documented behavior; see the Caution for The Locking Clause on
the SELECT reference page:
https://www.postgresql.org/docs/11/sql-select.html

Best regards,
Etsuro Fujita



Re: Questions of 'for update'

От
Kuntal Ghosh
Дата:
On Mon, Jun 10, 2019 at 12:42 PM Etsuro Fujita <etsuro.fujita@gmail.com> wrote:
Hi,

On Mon, Jun 10, 2019 at 3:50 PM Kuntal Ghosh <kuntalghosh.2007@gmail.com> wrote:
> On Mon, Jun 10, 2019 at 11:31 AM Zhenghua Lyu <zlv@pivotal.io> wrote:
>> 2. Is the case above a bug or a feature?
>>
> IMHO, it looks like an expected behaviour of a correct transaction management implementation.

This is documented behavior; see the Caution for The Locking Clause on
the SELECT reference page:
https://www.postgresql.org/docs/11/sql-select.html


Great. It also suggests a workaround. 


--
Thanks & Regards,
Kuntal Ghosh
EnterpriseDB: http://www.enterprisedb.com

Re: Questions of 'for update'

От
Zhenghua Lyu
Дата:
Thanks so much.

I understand now.

Best Regards,
Zhenghua Lyu


On Mon, Jun 10, 2019 at 3:22 PM Kuntal Ghosh <kuntalghosh.2007@gmail.com> wrote:
On Mon, Jun 10, 2019 at 12:42 PM Etsuro Fujita <etsuro.fujita@gmail.com> wrote:
Hi,

On Mon, Jun 10, 2019 at 3:50 PM Kuntal Ghosh <kuntalghosh.2007@gmail.com> wrote:
> On Mon, Jun 10, 2019 at 11:31 AM Zhenghua Lyu <zlv@pivotal.io> wrote:
>> 2. Is the case above a bug or a feature?
>>
> IMHO, it looks like an expected behaviour of a correct transaction management implementation.

This is documented behavior; see the Caution for The Locking Clause on
the SELECT reference page:
https://www.postgresql.org/docs/11/sql-select.html


Great. It also suggests a workaround. 


--
Thanks & Regards,
Kuntal Ghosh
EnterpriseDB: http://www.enterprisedb.com