gpdb: Wrong lock mode used for UPDATE / DELETE of the AO/AOCS partitioned table
Bug Report
With GDD enabled, when update / delete on AO/AOCS partitioned table (without unique index), i found that RowExclusiveLock was used instead of ExclusiveLock.
After #13897 , RelationIsAppendOptimized is changed to false when relation is a partitioned table, which changed lock level to RowExclusiveLock when update / delete AO/AOCS table. Is this expected behavior or a bug?
Greenplum version or build
master branch
Step to reproduce the behavior
create table partlockt (i int, t text) using ao_row
partition by range(i)
(start(1) end(10) every(1));
begin;
delete from partlockt where i = 4;
select * from pg_locks where relation = 'partlockt_1_prt_4'::regclass;
select * from pg_locks where relation = 'partlockt'::regclass;
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 16 (16 by maintainers)
Hi @linxuh and @charliettxx , thanks for reporting the issue and proposing the fix.
Firstly, the reason why
RelationIsAppendOptimizedwas changed to exclude partition table in https://github.com/greenplum-db/gpdb/pull/13897 is to keep existing behavior unchanged:pg_class.relamis always 0). SoRelationIsAppendOptimizedwould always return false for partitioned tables.RelationIsAppendOptimizedstill always returns false for partitioned tables.However, what I didn’t realize at that time is that the “existing behavior” was not the right behavior. In GP6, partitioned tables could return true for
RelationIsAppendOptimizedbecause GP6 uses a GP-specific data fieldpg_class.relstorageto indicate the table storage format, and partitioned tables could have validpg_class.relstorage. I guess during the PG12 merge when we replacedrelstoragewithrelam, we changed the behavior inadvertently.That’s why in GP6, exclusive lock would be acquired in the concerning scenario (due to the reason @kainwen mentioned), but not in GP7. So yes, we should fix this issue.
Now about the fix: I agree we should remove the
relkindcheck inRelationIsAppendOptimized. The macro should be as generic as just checking the relstorage/relam, same asRelationIsAoRowsandRelationIsAoCols. However, there could be some other issues after that. For example, inRelationBuildDescwe build the pg_appendonly information for a non-partitioned AO table (partitioned table doesn’t have pg_appendonly entry in GP7): https://github.com/greenplum-db/gpdb/blob/main/src/backend/utils/cache/relcache.c#L1297-L1298. So after the change ofRelationIsAppendOptimized, we need to change the condition inRelationBuildDescto exclude partitioned table. Basically, we need to move therelkind != RELKIND_PARTITIONED_TABLEcheck fromRelationIsAppendOptimizedto where it is needed. @charliettxx we can discuss more when you start working on the fix.Greenplum is MPP database, holding RowExclusive Lock for Update|Delete statement will lead concurrently update|delete happen on segment which means it is possible for transactions wait for others on segments. This can lead to global deadlock.
Since Greenplum 6, we introduce global deadlock detector, when it is turned on, for heap table’s update | delete, we can hold the same lock level as Postgres.
However, even with global deadlock detector enabled, for AO|AOCS table, due to its implementation of visibility map design, it does not support concurrenly update|delete on segments. That is why Greenplum always hold Exclusive Lock for AO|AOCS tables. This is documented behavior: https://docs.vmware.com/en/VMware-Greenplum/6/greenplum-database/admin_guide-dml.html .
I close this issue, feel free to reopen if needed.