From 04ee0d429817403612d8984da42a3dfea971fda0 Mon Sep 17 00:00:00 2001 From: Manuel Kniep Date: Thu, 16 Mar 2023 18:14:27 +0100 Subject: [PATCH 1/2] add option to retry on lock_not_available We typically move table with a lock_timeout to avoid to long exclusive locks. This adds additional parameters retries and sleep_sec to define the number of unsuccessful retries and the nap time between them. --- mvtbl--0.0.2--0.0.3.sql | 20 +++++++++++++++++ mvtbl--0.0.3--0.0.2.sql | 4 ++++ mvtbl--0.0.3.sql | 43 ++++++++++++++++++++++++++++++++++++ mvtbl.control | 2 +- sql/mvtbl.sql | 24 +++++++++++++++++--- test/expected/mvtbl_test.out | 14 ++++++++++++ test/sql/mvtbl_test.sql | 6 +++++ 7 files changed, 109 insertions(+), 4 deletions(-) create mode 100644 mvtbl--0.0.2--0.0.3.sql create mode 100644 mvtbl--0.0.3--0.0.2.sql create mode 100644 mvtbl--0.0.3.sql diff --git a/mvtbl--0.0.2--0.0.3.sql b/mvtbl--0.0.2--0.0.3.sql new file mode 100644 index 0000000..bfe4ea5 --- /dev/null +++ b/mvtbl--0.0.2--0.0.3.sql @@ -0,0 +1,20 @@ +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION mvtbl UPDATE TO '0.0.3'" to load this file. \quit + +CREATE FUNCTION mvtbl(tbl text, tblspace text, retries int, sleep_sec int DEFAULT 10) +RETURNS bigint AS +$$ + DECLARE + res bigint; + BEGIN + FOR i in 1..retries LOOP + BEGIN + res = mvtbl(tbl, tblspace); + EXIT; + EXCEPTION WHEN lock_not_available THEN + pg_sleep(sleep_sec); + END; + END LOOP; + RETURN res; + END; +$$ LANGUAGE plpgsql STRICT; diff --git a/mvtbl--0.0.3--0.0.2.sql b/mvtbl--0.0.3--0.0.2.sql new file mode 100644 index 0000000..2ff406b --- /dev/null +++ b/mvtbl--0.0.3--0.0.2.sql @@ -0,0 +1,4 @@ +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "ALTER EXTENSION mvtbl UPDATE TO '0.0.2'" to load this file. \quit + +DROP FUNCTION mvtbl(tbl text, tblspace text, retries int, sleep_sec int) \ No newline at end of file diff --git a/mvtbl--0.0.3.sql b/mvtbl--0.0.3.sql new file mode 100644 index 0000000..cdbd5b5 --- /dev/null +++ b/mvtbl--0.0.3.sql @@ -0,0 +1,43 @@ +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION mvtbl" to load this file. \quit + +CREATE FUNCTION mvtbl(tbl text, tblspace text) +RETURNS bigint AS +$$ + DECLARE + r RECORD; + tbl_oid oid := tbl::regclass::oid; + res bigint = 0; + BEGIN + EXECUTE format($sql$ ALTER TABLE %s SET TABLESPACE %s $sql$, tbl, tblspace); + SELECT pg_catalog.pg_total_relation_size(tbl) INTO res; + + FOR r IN SELECT + c2.oid::regclass as iname + FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i + WHERE c.oid = tbl_oid AND c.oid = i.indrelid AND i.indexrelid = c2.oid + ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname LOOP + + EXECUTE format($sql$ ALTER INDEX %s SET TABLESPACE %s $sql$, r.iname, tblspace); + END LOOP; + RETURN res; + END; +$$ LANGUAGE plpgsql STRICT; + +CREATE FUNCTION mvtbl(tbl text, tblspace text, retries int, sleep_sec int DEFAULT 10) +RETURNS bigint AS +$$ + DECLARE + res bigint; + BEGIN + FOR i in 1..retries LOOP + BEGIN + res = mvtbl(tbl, tblspace); + EXIT; + EXCEPTION WHEN lock_not_available THEN + pg_sleep(sleep_sec); + END; + END LOOP; + RETURN res; + END; +$$ LANGUAGE plpgsql STRICT; diff --git a/mvtbl.control b/mvtbl.control index 97feab8..d242fac 100644 --- a/mvtbl.control +++ b/mvtbl.control @@ -1,5 +1,5 @@ # mvtbl extension comment = 'Helper to move tables around tablespaces' -default_version = '0.0.2' +default_version = '0.0.3' relocatable = true requires = '' diff --git a/sql/mvtbl.sql b/sql/mvtbl.sql index 978a45b..3693f91 100644 --- a/sql/mvtbl.sql +++ b/sql/mvtbl.sql @@ -1,15 +1,15 @@ -CREATE FUNCTION mvtbl(tbl text, tblspace text) +CREATE FUNCTION mvtbl(tbl text, tblspace text) RETURNS bigint AS $$ DECLARE - r RECORD; + r RECORD; tbl_oid oid := tbl::regclass::oid; res bigint = 0; BEGIN EXECUTE format($sql$ ALTER TABLE %s SET TABLESPACE %s $sql$, tbl, tblspace); SELECT pg_catalog.pg_total_relation_size(tbl) INTO res; - FOR r IN SELECT + FOR r IN SELECT c2.oid::regclass as iname FROM pg_catalog.pg_class c, pg_catalog.pg_class c2, pg_catalog.pg_index i WHERE c.oid = tbl_oid AND c.oid = i.indrelid AND i.indexrelid = c2.oid @@ -20,3 +20,21 @@ $$ RETURN res; END; $$ LANGUAGE plpgsql STRICT; + +CREATE FUNCTION mvtbl(tbl text, tblspace text, retries int, sleep_sec int DEFAULT 10) +RETURNS bigint AS +$$ + DECLARE + res bigint; + BEGIN + FOR i in 1..retries LOOP + BEGIN + res = mvtbl(tbl, tblspace); + EXIT; + EXCEPTION WHEN lock_not_available THEN + pg_sleep(sleep_sec); + END; + END LOOP; + RETURN res; + END; +$$ LANGUAGE plpgsql STRICT; diff --git a/test/expected/mvtbl_test.out b/test/expected/mvtbl_test.out index 9985bb9..5427e3f 100644 --- a/test/expected/mvtbl_test.out +++ b/test/expected/mvtbl_test.out @@ -15,4 +15,18 @@ SELECT pg_size_pretty(mvtbl('test','pg_default')); 123 MB (1 row) +SELECT pg_size_pretty(mvtbl('test','mvtbl_test_tblspace', 3, 3)); + pg_size_pretty +---------------- + 123 MB +(1 row) + +SELECT pg_size_pretty(mvtbl('test','pg_default', 3)); + pg_size_pretty +---------------- + 123 MB +(1 row) + +ALTER EXTENSION mvtbl UPDATE TO '0.0.2'; +ALTER EXTENSION mvtbl UPDATE TO '0.0.3'; DROP TABLESPACE mvtbl_test_tblspace; diff --git a/test/sql/mvtbl_test.sql b/test/sql/mvtbl_test.sql index 7a213f9..8a045cf 100644 --- a/test/sql/mvtbl_test.sql +++ b/test/sql/mvtbl_test.sql @@ -8,4 +8,10 @@ CREATE INDEX ON test(c); SELECT pg_size_pretty(mvtbl('test','mvtbl_test_tblspace')); SELECT pg_size_pretty(mvtbl('test','pg_default')); +SELECT pg_size_pretty(mvtbl('test','mvtbl_test_tblspace', 3, 3)); +SELECT pg_size_pretty(mvtbl('test','pg_default', 3)); + +ALTER EXTENSION mvtbl UPDATE TO '0.0.2'; +ALTER EXTENSION mvtbl UPDATE TO '0.0.3'; + DROP TABLESPACE mvtbl_test_tblspace; \ No newline at end of file From 3c301a45ec8220a61c9713f6c20a1f5ac99ed930 Mon Sep 17 00:00:00 2001 From: Manuel Kniep Date: Fri, 17 Mar 2023 08:16:58 +0100 Subject: [PATCH 2/2] re-raise error after retries attemps --- Makefile | 4 ++-- mvtbl--0.0.2--0.0.3.sql | 5 ++++- mvtbl--0.0.3.sql | 5 ++++- sql/mvtbl.sql | 3 +++ 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index f31675f..14e312c 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ TESTS = $(wildcard test/sql/*.sql) REGRESS = $(patsubst test/sql/%.sql,%,$(TESTS)) REGRESS_OPTS = --inputdir=test \ --load-extension=$(EXTENSION) \ - --temp-instance=$$PWD/tmp + --temp-instance=$$PWD/tmp REGRESS_PREP = mktblspace SQLSRC = $(wildcard sql/*.sql) include $(PGXS) @@ -21,4 +21,4 @@ $(EXTENSION)--$(EXTVERSION).sql: $(SQLSRC) @cat $^ >> $@ mktblspace: - mkdir -p /tmp/tsttblsp + mkdir -p /tmp/tsttblsp diff --git a/mvtbl--0.0.2--0.0.3.sql b/mvtbl--0.0.2--0.0.3.sql index bfe4ea5..339fcda 100644 --- a/mvtbl--0.0.2--0.0.3.sql +++ b/mvtbl--0.0.2--0.0.3.sql @@ -12,7 +12,10 @@ $$ res = mvtbl(tbl, tblspace); EXIT; EXCEPTION WHEN lock_not_available THEN - pg_sleep(sleep_sec); + IF i = retries THEN + RAISE; + END IF; + PERFORM pg_sleep(sleep_sec); END; END LOOP; RETURN res; diff --git a/mvtbl--0.0.3.sql b/mvtbl--0.0.3.sql index cdbd5b5..67d9aed 100644 --- a/mvtbl--0.0.3.sql +++ b/mvtbl--0.0.3.sql @@ -35,7 +35,10 @@ $$ res = mvtbl(tbl, tblspace); EXIT; EXCEPTION WHEN lock_not_available THEN - pg_sleep(sleep_sec); + IF i = retries THEN + RAISE; + END IF; + PERFORM pg_sleep(sleep_sec); END; END LOOP; RETURN res; diff --git a/sql/mvtbl.sql b/sql/mvtbl.sql index 3693f91..2a26d00 100644 --- a/sql/mvtbl.sql +++ b/sql/mvtbl.sql @@ -32,6 +32,9 @@ $$ res = mvtbl(tbl, tblspace); EXIT; EXCEPTION WHEN lock_not_available THEN + IF i = retries THEN + RAISE; + END IF; pg_sleep(sleep_sec); END; END LOOP;