1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

REINDEX CONCURRENTLY

This adds the CONCURRENTLY option to the REINDEX command.  A REINDEX
CONCURRENTLY on a specific index creates a new index (like CREATE
INDEX CONCURRENTLY), then renames the old index away and the new index
in place and adjusts the dependencies, and then drops the old
index (like DROP INDEX CONCURRENTLY).  The REINDEX command also has
the capability to run its other variants (TABLE, DATABASE) with the
CONCURRENTLY option (but not SYSTEM).

The reindexdb command gets the --concurrently option.

Author: Michael Paquier, Andreas Karlsson, Peter Eisentraut
Reviewed-by: Andres Freund, Fujii Masao, Jim Nasby, Sergei Kornilov
Discussion: https://www.postgresql.org/message-id/flat/60052986-956b-4478-45ed-8bd119e9b9cf%402ndquadrant.com#74948a1044c56c5e817a5050f554ddee
This commit is contained in:
Peter Eisentraut
2019-03-29 08:25:20 +01:00
parent d25f519107
commit 5dc92b844e
26 changed files with 2049 additions and 184 deletions

View File

@ -0,0 +1,78 @@
Parsed test spec with 3 sessions
starting permutation: reindex sel1 upd2 ins2 del2 end1 end2
step reindex: REINDEX TABLE CONCURRENTLY reind_con_tab;
step sel1: SELECT data FROM reind_con_tab WHERE id = 3;
data
aaaa
step upd2: UPDATE reind_con_tab SET data = 'bbbb' WHERE id = 3;
step ins2: INSERT INTO reind_con_tab(data) VALUES ('cccc');
step del2: DELETE FROM reind_con_tab WHERE data = 'cccc';
step end1: COMMIT;
step end2: COMMIT;
starting permutation: sel1 reindex upd2 ins2 del2 end1 end2
step sel1: SELECT data FROM reind_con_tab WHERE id = 3;
data
aaaa
step reindex: REINDEX TABLE CONCURRENTLY reind_con_tab; <waiting ...>
step upd2: UPDATE reind_con_tab SET data = 'bbbb' WHERE id = 3;
step ins2: INSERT INTO reind_con_tab(data) VALUES ('cccc');
step del2: DELETE FROM reind_con_tab WHERE data = 'cccc';
step end1: COMMIT;
step end2: COMMIT;
step reindex: <... completed>
starting permutation: sel1 upd2 reindex ins2 del2 end1 end2
step sel1: SELECT data FROM reind_con_tab WHERE id = 3;
data
aaaa
step upd2: UPDATE reind_con_tab SET data = 'bbbb' WHERE id = 3;
step reindex: REINDEX TABLE CONCURRENTLY reind_con_tab; <waiting ...>
step ins2: INSERT INTO reind_con_tab(data) VALUES ('cccc');
step del2: DELETE FROM reind_con_tab WHERE data = 'cccc';
step end1: COMMIT;
step end2: COMMIT;
step reindex: <... completed>
starting permutation: sel1 upd2 ins2 reindex del2 end1 end2
step sel1: SELECT data FROM reind_con_tab WHERE id = 3;
data
aaaa
step upd2: UPDATE reind_con_tab SET data = 'bbbb' WHERE id = 3;
step ins2: INSERT INTO reind_con_tab(data) VALUES ('cccc');
step reindex: REINDEX TABLE CONCURRENTLY reind_con_tab; <waiting ...>
step del2: DELETE FROM reind_con_tab WHERE data = 'cccc';
step end1: COMMIT;
step end2: COMMIT;
step reindex: <... completed>
starting permutation: sel1 upd2 ins2 del2 reindex end1 end2
step sel1: SELECT data FROM reind_con_tab WHERE id = 3;
data
aaaa
step upd2: UPDATE reind_con_tab SET data = 'bbbb' WHERE id = 3;
step ins2: INSERT INTO reind_con_tab(data) VALUES ('cccc');
step del2: DELETE FROM reind_con_tab WHERE data = 'cccc';
step reindex: REINDEX TABLE CONCURRENTLY reind_con_tab; <waiting ...>
step end1: COMMIT;
step end2: COMMIT;
step reindex: <... completed>
starting permutation: sel1 upd2 ins2 del2 end1 reindex end2
step sel1: SELECT data FROM reind_con_tab WHERE id = 3;
data
aaaa
step upd2: UPDATE reind_con_tab SET data = 'bbbb' WHERE id = 3;
step ins2: INSERT INTO reind_con_tab(data) VALUES ('cccc');
step del2: DELETE FROM reind_con_tab WHERE data = 'cccc';
step end1: COMMIT;
step reindex: REINDEX TABLE CONCURRENTLY reind_con_tab; <waiting ...>
step end2: COMMIT;
step reindex: <... completed>

View File

@ -42,6 +42,7 @@ test: multixact-no-forget
test: lock-committed-update
test: lock-committed-keyupdate
test: update-locked-tuple
test: reindex-concurrently
test: propagate-lock-delete
test: tuplelock-conflict
test: tuplelock-update

View File

@ -0,0 +1,40 @@
# REINDEX CONCURRENTLY
#
# Ensure that concurrent operations work correctly when a REINDEX is performed
# concurrently.
setup
{
CREATE TABLE reind_con_tab(id serial primary key, data text);
INSERT INTO reind_con_tab(data) VALUES ('aa');
INSERT INTO reind_con_tab(data) VALUES ('aaa');
INSERT INTO reind_con_tab(data) VALUES ('aaaa');
INSERT INTO reind_con_tab(data) VALUES ('aaaaa');
}
teardown
{
DROP TABLE reind_con_tab;
}
session "s1"
setup { BEGIN; }
step "sel1" { SELECT data FROM reind_con_tab WHERE id = 3; }
step "end1" { COMMIT; }
session "s2"
setup { BEGIN; }
step "upd2" { UPDATE reind_con_tab SET data = 'bbbb' WHERE id = 3; }
step "ins2" { INSERT INTO reind_con_tab(data) VALUES ('cccc'); }
step "del2" { DELETE FROM reind_con_tab WHERE data = 'cccc'; }
step "end2" { COMMIT; }
session "s3"
step "reindex" { REINDEX TABLE CONCURRENTLY reind_con_tab; }
permutation "reindex" "sel1" "upd2" "ins2" "del2" "end1" "end2"
permutation "sel1" "reindex" "upd2" "ins2" "del2" "end1" "end2"
permutation "sel1" "upd2" "reindex" "ins2" "del2" "end1" "end2"
permutation "sel1" "upd2" "ins2" "reindex" "del2" "end1" "end2"
permutation "sel1" "upd2" "ins2" "del2" "reindex" "end1" "end2"
permutation "sel1" "upd2" "ins2" "del2" "end1" "reindex" "end2"

View File

@ -3250,6 +3250,101 @@ INFO: index "reindex_verbose_pkey" was reindexed
\set VERBOSITY default
DROP TABLE reindex_verbose;
--
-- REINDEX CONCURRENTLY
--
CREATE TABLE concur_reindex_tab (c1 int);
-- REINDEX
REINDEX TABLE concur_reindex_tab; -- notice
NOTICE: table "concur_reindex_tab" has no indexes
REINDEX TABLE CONCURRENTLY concur_reindex_tab; -- notice
NOTICE: table "concur_reindex_tab" has no indexes
ALTER TABLE concur_reindex_tab ADD COLUMN c2 text; -- add toast index
-- Normal index with integer column
CREATE UNIQUE INDEX concur_reindex_ind1 ON concur_reindex_tab(c1);
-- Normal index with text column
CREATE INDEX concur_reindex_ind2 ON concur_reindex_tab(c2);
-- UNIQUE index with expression
CREATE UNIQUE INDEX concur_reindex_ind3 ON concur_reindex_tab(abs(c1));
-- Duplicate column names
CREATE INDEX concur_reindex_ind4 ON concur_reindex_tab(c1, c1, c2);
-- Create table for check on foreign key dependence switch with indexes swapped
ALTER TABLE concur_reindex_tab ADD PRIMARY KEY USING INDEX concur_reindex_ind1;
CREATE TABLE concur_reindex_tab2 (c1 int REFERENCES concur_reindex_tab);
INSERT INTO concur_reindex_tab VALUES (1, 'a');
INSERT INTO concur_reindex_tab VALUES (2, 'a');
-- Reindex concurrently of exclusion constraint currently not supported
CREATE TABLE concur_reindex_tab3 (c1 int, c2 int4range, EXCLUDE USING gist (c2 WITH &&));
INSERT INTO concur_reindex_tab3 VALUES (3, '[1,2]');
REINDEX INDEX CONCURRENTLY concur_reindex_tab3_c2_excl; -- error
ERROR: concurrent index creation for exclusion constraints is not supported
REINDEX TABLE CONCURRENTLY concur_reindex_tab3; -- succeeds with warning
WARNING: cannot reindex concurrently exclusion constraint index "public.concur_reindex_tab3_c2_excl", skipping
INSERT INTO concur_reindex_tab3 VALUES (4, '[2,4]');
ERROR: conflicting key value violates exclusion constraint "concur_reindex_tab3_c2_excl"
DETAIL: Key (c2)=([2,5)) conflicts with existing key (c2)=([1,3)).
-- Check materialized views
CREATE MATERIALIZED VIEW concur_reindex_matview AS SELECT * FROM concur_reindex_tab;
REINDEX INDEX CONCURRENTLY concur_reindex_ind1;
REINDEX TABLE CONCURRENTLY concur_reindex_tab;
REINDEX TABLE CONCURRENTLY concur_reindex_matview;
-- Check that comments are preserved
CREATE TABLE testcomment (i int);
CREATE INDEX testcomment_idx1 ON testcomment (i);
COMMENT ON INDEX testcomment_idx1 IS 'test comment';
SELECT obj_description('testcomment_idx1'::regclass, 'pg_class');
obj_description
-----------------
test comment
(1 row)
REINDEX TABLE testcomment;
SELECT obj_description('testcomment_idx1'::regclass, 'pg_class');
obj_description
-----------------
test comment
(1 row)
REINDEX TABLE CONCURRENTLY testcomment ;
SELECT obj_description('testcomment_idx1'::regclass, 'pg_class');
obj_description
-----------------
test comment
(1 row)
DROP TABLE testcomment;
-- Check errors
-- Cannot run inside a transaction block
BEGIN;
REINDEX TABLE CONCURRENTLY concur_reindex_tab;
ERROR: REINDEX CONCURRENTLY cannot run inside a transaction block
COMMIT;
REINDEX TABLE CONCURRENTLY pg_database; -- no shared relation
ERROR: concurrent index creation on system catalog tables is not supported
REINDEX TABLE CONCURRENTLY pg_class; -- no catalog relations
ERROR: concurrent index creation on system catalog tables is not supported
REINDEX SYSTEM CONCURRENTLY postgres; -- not allowed for SYSTEM
ERROR: concurrent reindex of system catalogs is not supported
-- Warns about catalog relations
REINDEX SCHEMA CONCURRENTLY pg_catalog;
WARNING: concurrent reindex is not supported for catalog relations, skipping all
-- Check the relation status, there should not be invalid indexes
\d concur_reindex_tab
Table "public.concur_reindex_tab"
Column | Type | Collation | Nullable | Default
--------+---------+-----------+----------+---------
c1 | integer | | not null |
c2 | text | | |
Indexes:
"concur_reindex_ind1" PRIMARY KEY, btree (c1)
"concur_reindex_ind3" UNIQUE, btree (abs(c1))
"concur_reindex_ind2" btree (c2)
"concur_reindex_ind4" btree (c1, c1, c2)
Referenced by:
TABLE "concur_reindex_tab2" CONSTRAINT "concur_reindex_tab2_c1_fkey" FOREIGN KEY (c1) REFERENCES concur_reindex_tab(c1)
DROP MATERIALIZED VIEW concur_reindex_matview;
DROP TABLE concur_reindex_tab, concur_reindex_tab2, concur_reindex_tab3;
--
-- REINDEX SCHEMA
--
REINDEX SCHEMA schema_to_reindex; -- failure, schema does not exist
@ -3308,6 +3403,8 @@ BEGIN;
REINDEX SCHEMA schema_to_reindex; -- failure, cannot run in a transaction
ERROR: REINDEX SCHEMA cannot run inside a transaction block
END;
-- concurrently
REINDEX SCHEMA CONCURRENTLY schema_to_reindex;
-- Failure for unauthorized user
CREATE ROLE regress_reindexuser NOLOGIN;
SET SESSION ROLE regress_reindexuser;

View File

@ -1172,6 +1172,65 @@ REINDEX (VERBOSE) TABLE reindex_verbose;
\set VERBOSITY default
DROP TABLE reindex_verbose;
--
-- REINDEX CONCURRENTLY
--
CREATE TABLE concur_reindex_tab (c1 int);
-- REINDEX
REINDEX TABLE concur_reindex_tab; -- notice
REINDEX TABLE CONCURRENTLY concur_reindex_tab; -- notice
ALTER TABLE concur_reindex_tab ADD COLUMN c2 text; -- add toast index
-- Normal index with integer column
CREATE UNIQUE INDEX concur_reindex_ind1 ON concur_reindex_tab(c1);
-- Normal index with text column
CREATE INDEX concur_reindex_ind2 ON concur_reindex_tab(c2);
-- UNIQUE index with expression
CREATE UNIQUE INDEX concur_reindex_ind3 ON concur_reindex_tab(abs(c1));
-- Duplicate column names
CREATE INDEX concur_reindex_ind4 ON concur_reindex_tab(c1, c1, c2);
-- Create table for check on foreign key dependence switch with indexes swapped
ALTER TABLE concur_reindex_tab ADD PRIMARY KEY USING INDEX concur_reindex_ind1;
CREATE TABLE concur_reindex_tab2 (c1 int REFERENCES concur_reindex_tab);
INSERT INTO concur_reindex_tab VALUES (1, 'a');
INSERT INTO concur_reindex_tab VALUES (2, 'a');
-- Reindex concurrently of exclusion constraint currently not supported
CREATE TABLE concur_reindex_tab3 (c1 int, c2 int4range, EXCLUDE USING gist (c2 WITH &&));
INSERT INTO concur_reindex_tab3 VALUES (3, '[1,2]');
REINDEX INDEX CONCURRENTLY concur_reindex_tab3_c2_excl; -- error
REINDEX TABLE CONCURRENTLY concur_reindex_tab3; -- succeeds with warning
INSERT INTO concur_reindex_tab3 VALUES (4, '[2,4]');
-- Check materialized views
CREATE MATERIALIZED VIEW concur_reindex_matview AS SELECT * FROM concur_reindex_tab;
REINDEX INDEX CONCURRENTLY concur_reindex_ind1;
REINDEX TABLE CONCURRENTLY concur_reindex_tab;
REINDEX TABLE CONCURRENTLY concur_reindex_matview;
-- Check that comments are preserved
CREATE TABLE testcomment (i int);
CREATE INDEX testcomment_idx1 ON testcomment (i);
COMMENT ON INDEX testcomment_idx1 IS 'test comment';
SELECT obj_description('testcomment_idx1'::regclass, 'pg_class');
REINDEX TABLE testcomment;
SELECT obj_description('testcomment_idx1'::regclass, 'pg_class');
REINDEX TABLE CONCURRENTLY testcomment ;
SELECT obj_description('testcomment_idx1'::regclass, 'pg_class');
DROP TABLE testcomment;
-- Check errors
-- Cannot run inside a transaction block
BEGIN;
REINDEX TABLE CONCURRENTLY concur_reindex_tab;
COMMIT;
REINDEX TABLE CONCURRENTLY pg_database; -- no shared relation
REINDEX TABLE CONCURRENTLY pg_class; -- no catalog relations
REINDEX SYSTEM CONCURRENTLY postgres; -- not allowed for SYSTEM
-- Warns about catalog relations
REINDEX SCHEMA CONCURRENTLY pg_catalog;
-- Check the relation status, there should not be invalid indexes
\d concur_reindex_tab
DROP MATERIALIZED VIEW concur_reindex_matview;
DROP TABLE concur_reindex_tab, concur_reindex_tab2, concur_reindex_tab3;
--
-- REINDEX SCHEMA
--
@ -1214,6 +1273,9 @@ BEGIN;
REINDEX SCHEMA schema_to_reindex; -- failure, cannot run in a transaction
END;
-- concurrently
REINDEX SCHEMA CONCURRENTLY schema_to_reindex;
-- Failure for unauthorized user
CREATE ROLE regress_reindexuser NOLOGIN;
SET SESSION ROLE regress_reindexuser;