1. 程式人生 > >PostgreSQL 11 新特性之跨分割槽移動資料

PostgreSQL 11 新特性之跨分割槽移動資料

文章目錄

在 PostgreSQL 10 中,如果 UPDATE 語句修改了分割槽欄位的值,導致資料需要移動到其他分割槽時,語句將會失敗。

-- PostgreSQL 10
CREATE TABLE rtable(c1 INT, c2 VARCHAR(10)) PARTITION BY RANGE(c1);
CREATE TABLE rtable100 PARTITION OF rtable FOR VALUES FROM (1) TO (100);
CREATE TABLE rtable200 PARTITION OF rtable FOR VALUES FROM (101
) TO (200); INSERT INTO rtable(c1, c2) VALUES (50, 'val50'); SELECT * FROM rtable100; c1 | c2 ----+------- 50 | val50 (1 row)

以下語句更新分割槽欄位 c1,導致記錄(c1 = 50)需要移動到分割槽 rtable200;不過語句執行失敗。

-- PostgreSQL 10
UPDATE rtable
postgres-# SET c1 = c1 + 100
postgres-# WHERE c1 = 50;
ERROR:  new row for relation "rtable100"
violates partition constraint DETAIL: Failing row contains (150, val50).

PostgreSQL 11 能夠正確處理更新分割槽欄位的操作:

-- PostgreSQL 11
CREATE TABLE rtable(c1 INT, c2 VARCHAR(10)) PARTITION BY RANGE(c1);
CREATE TABLE rtable100 PARTITION OF rtable FOR VALUES FROM (1) TO (100);
CREATE TABLE rtable200 PARTITION OF rtable FOR
VALUES FROM (101) TO (200); INSERT INTO rtable(c1, c2) VALUES (50, 'val50'); SELECT * FROM rtable100; c1 | c2 ----+------- 50 | val50 (1 row) UPDATE rtable SET c1 = c1 + 100 WHERE c1 = 50; SELECT * FROM rtable200; c1 | c2 -----+------- 150 | val50 (1 row)

根據提交記錄,這種 UPDATE 語句實際上分為兩步執行:從舊的分割槽中 DELETE 相應記錄,在新的分割槽中INSERT 相應記錄。對於併發場景,這種方式可能會產生意料之外的行為。官方已經記錄該問題,並且等待提交補丁。

另外,跨分割槽移動資料的 UPDATE 語句將會導致觸發器的執行順序更加複雜,相關資訊可以參考“PostgreSQL 11 新特性之分割槽錶行級觸發器”。

官方文件:Table Partitioning

人生本來短暫,你又何必匆匆!點個贊再走吧!