[英]Postgresql - CHECK constraint not preventing ACCESS EXCLUSIVE lock and table scan when attaching new partition
I'm running postgresql 13.我正在运行 postgresql 13。
The below section of the postgres doc doc says I should be able to avoid a scan and ACCESS EXCLUSIVE lock to validate the partition constraint. postgres doc文档的以下部分说我应该能够避免扫描和 ACCESS EXCLUSIVE 锁来验证分区约束。
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.
在运行 ATTACH PARTITION 命令之前,建议在要附加的表上创建一个 CHECK 约束,该约束与预期的分区约束相匹配,如上所示。 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.
如果没有 CHECK 约束,将扫描表以验证分区约束,同时对该分区持有 ACCESS EXCLUSIVE 锁。
But, when I create a new partition with a check constraint, insert data into it, and then attach it, an ACCESS EXCLUSIVE lock is held while the table is scanned.但是,当我创建一个带有检查约束的新分区,将数据插入其中,然后附加它时,在扫描表时会持有一个 ACCESS EXCLUSIVE 锁。
The partitioned table:分区表:
CREATE TABLE IF NOT EXISTS tasks
(
task_time timestamp(6) with time zone not null,
task_sp_time timestamp(6) with time zone,
task_org_id text not null,
build_id text,
unit_id text,
unit_req numeric(12,2),
... 30 columns truncated ...,
constraint tasks_pkey1
primary key (task_org_id, task_time)
)
partition by RANGE(task_time);
task_time
is not null
and of type timestamp (6) with timezone
. task_time
not null
并且类型为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');
-- select around 100 million rows into the new partition from an old default partition that has been detached.
INSERT INTO tasks_partitions.tasks_20230111
SELECT * FROM tasks_partitions.tasks_default_old where (task_time >= '2023-01-11 00:00:00+00' AND task_time <= '2023-01-11 23:59:59.999999+00');
-- 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 ACCESS EXLUSIVE
lock and the entire table is scanned.附加分区仍然持有
ACCESS EXLUSIVE
锁,并且扫描整个表。
The tasks
table did have a default partition at one point, but I detached it and renamed it in order to resolve another issue. tasks
表曾经有一个默认分区,但我将其分离并重命名以解决另一个问题。 I currently do not have a default partition attached to tasks
.我目前没有附加到
tasks
的默认分区。
When I attach the partition from the example above, I see an ACCESS EXCLUSIVE
lock on the new partition and a seemingly random relation, 468140
.当我附加上例中的分区时,我看到新分区上有一个
ACCESS EXCLUSIVE
锁和一个看似随机的关系468140
。 I cannot insert any records into the tasks
table while the partition is being attached and the locks are in place.在附加分区并且锁定到位时,我无法将任何记录插入到
tasks
表中。
If it helps, the query I run to see locks is:如果有帮助,我运行以查看锁的查询是:
SELECT a.datname,
l.relation::regclass,
l.transactionid,
l.mode,
l.GRANTED,
l.usename,
a.query,
a.query_start,
age(now(), a.query_start) AS "age",
a.pid
FROM pg_stat_activity a
JOIN pg_locks l ON l.pid = a.pid
ORDER BY a.query_start;
The check constraint you are creating does not match the partition boundaries.您正在创建的检查约束与分区边界不匹配。 You missed this statement from the documentation :
您错过了文档中的此声明:
When creating a range partition, the lower bound specified with
FROM
is an inclusive bound, whereas the upper bound specified withTO
is an exclusive bound.创建范围分区时,
FROM
指定的下限是包含边界,而TO
指定的上限是排他边界。
So you should define the constraint as所以你应该将约束定义为
ALTER TABLE tasks_partitions.tasks_20230111 ADD
CHECK (task_time >= '2023-01-11 00:00:00+00' AND
task_time < '2023-01-12 00:00:00+00');
and attach the partition with并附加分区
ALTER TABLE tasks ATTACH PARTITION tasks_partitions_tasks_20230111
FOR VALUES FROM ('2023-01-11 00:00:00+00')
TO ('2023-01-12 00:00:00+00');
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.