1

Specifically, this section of the postgres doc doc says I should be able to avoid a scan of the default partition:

Before running the ATTACH PARTITION command, it is recommended to create a CHECK constraint on the table to be attached that matches the expected partition constraint, as illustrated above. That way, the system will be able to skip the scan which is otherwise needed to validate the implicit partition constraint. Without the CHECK constraint, the table will be scanned to validate the partition constraint while holding an ACCESS EXCLUSIVE lock on that partition. It is recommended to drop the now-redundant CHECK constraint after the ATTACH PARTITION is complete. If the table being attached is itself a partitioned table, then each of its sub-partitions will be recursively locked and scanned until either a suitable CHECK constraint is encountered or the leaf partitions are reached.

Similarly, if the partitioned table has a DEFAULT partition, it is recommended to create a CHECK constraint which excludes the to-be-attached partition's constraint. If this is not done then the DEFAULT partition will be scanned to verify that it contains no records which should be located in the partition being attached. This operation will be performed whilst holding an ACCESS EXCLUSIVE lock on the DEFAULT partition. If the DEFAULT partition is itself a partitioned table, then each of its partitions will be recursively checked in the same way as the table being attached, as mentioned above.

But, the below doesn't work for me: task_time is not null and of type timestamp (6) with timezone.

-- create new empty partition table
CREATE TABLE tasks_partitions.tasks_20230111
(LIKE tasks INCLUDING DEFAULTS INCLUDING CONSTRAINTS);

-- add CHECK constraint on new partition 
ALTER TABLE tasks_partitions.tasks_20230111 ADD CONSTRAINT tmp_20230111
CHECK (task_time >= '2023-01-11 00:00:00+00' AND task_time <= '2023-01-11 23:59:59.999999+00');

-- add CHECK constraint on default partition that excludes new partition constraint
ALTER TABLE tasks_partitions.tasks_20230111 ADD CONSTRAINT tmp20230111_default
CHECK (task_time < '2023-01-11 00:00:00+00' and task time > '2023-01-11 23:59:59.999999+00') NOT VALID;

-- attach partition
ALTER TABLE tasks ATTACH PARTITION tasks_partitions_tasks_20230111
FOR VALUES FROM ('2023-01-11 00:00:00+00') TO ('2023-01-11 23:59:59.999999+00')

Attaching the partition still holds the AccessExclusiveLock.

Laurenz Albe
  • 209,280
  • 17
  • 206
  • 263
user797963
  • 2,907
  • 9
  • 47
  • 88
  • Please do [not crosspost](http://meta.stackexchange.com/q/64068/157328). Also asked here: https://dba.stackexchange.com/questions/321918/how-to-prevent-accessexclusive-lock-on-default-partition-when-attaching-new-part –  Jan 10 '23 at 06:21
  • Deleted the other question. – user797963 Jan 12 '23 at 17:38

1 Answers1

2

This operation will always take an ACCESS EXCLUSIVE lock. The documentation only tells you how you can reduce the time the lock is held.

Laurenz Albe
  • 209,280
  • 17
  • 206
  • 263
  • And what if there is no default partition? In a test instance, I've tried detaching the default partition and am still stuck with a long scan and lock on the new partition to add. Is my check constraint correct? – user797963 Jan 11 '23 at 22:39
  • That's a different question. If the column is nulllable, the constraint must also have an `IS NOT NULL` check. – Laurenz Albe Jan 12 '23 at 06:50
  • The column is not null. I can open a new question. – user797963 Jan 12 '23 at 15:00
  • For anyone look at this in the future, this is what I did: 1. Detach default partition. 2. Rename default partition. 3. Create new empty partition for today's date range. 4. Attach new empty partition for today's date range. 5. Select data for today's date out of old default partition and into new partition for today's date range. I did this in a single transaction to hold a lock and prevent inserts or queries against today's date range without all data being available. I then went back and created partitions for old data and back filled it from the old default table. – user797963 Jan 12 '23 at 16:37
  • A default partition makes adding new partitions complicated. Consider doing without a default partition. – Laurenz Albe Jan 12 '23 at 16:42
  • Definitely a good call, thanks. I've detached the default partition on the tables that I've already cleaned up, and resolved the issue with partition creation. I now create partitions two weeks out every day, with alerts if partition creation should fail. Here's the other question I created for the constraint on new partitions failing to prevent the scan and `ACCESS EXCLUSIVE` lock: https://stackoverflow.com/questions/75100066/postgresql-check-constraint-not-preventing-access-exclusive-lock-and-table-sca – user797963 Jan 12 '23 at 17:25