mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-15 10:11:29 +08:00
In the function `ts_hypercube_from_constraints` a hypercube is build from constraints which reference dimension slices in `dimension_slice`. As part of a run of `drop_chunks` or when a chunk is explicitly dropped as part of other operations, dimension slices can be removed from this table causing the dimension slices to be removed, which makes the hypercube reference non-existent dimension slices which subsequently causes a crash. This commit fixes this by adding a tuple lock on the dimension slices that are used to build the hypercube. If two `drop_chunks` are running concurrently, there can be a race if dimension slices are removed as a result removing a chunk. We treat this case in the same way as if the dimension slice was updated: report an error that another session locked the tuple. Fixes #1986
129 lines
5.9 KiB
Plaintext
129 lines
5.9 KiB
Plaintext
-- This file and its contents are licensed under the Apache License 2.0.
|
|
-- Please see the included NOTICE for copyright information and
|
|
-- LICENSE-APACHE for a copy of the license.
|
|
-- Hypertables can break as a result of race conditions, but we should
|
|
-- still not crash when trying to truncate or delete the broken table.
|
|
\c :TEST_DBNAME :ROLE_SUPERUSER
|
|
CREATE VIEW missing_slices AS
|
|
SELECT DISTINCT
|
|
dimension_slice_id,
|
|
constraint_name,
|
|
attname AS column_name,
|
|
pg_get_expr(conbin, conrelid) AS constraint_expr
|
|
FROM
|
|
_timescaledb_catalog.chunk_constraint cc
|
|
JOIN _timescaledb_catalog.chunk ch ON cc.chunk_id = ch.id
|
|
JOIN pg_constraint ON conname = constraint_name
|
|
JOIN pg_namespace ns ON connamespace = ns.oid
|
|
AND ns.nspname = ch.schema_name
|
|
JOIN pg_attribute ON attnum = conkey[1]
|
|
AND attrelid = conrelid
|
|
WHERE
|
|
dimension_slice_id NOT IN (SELECT id FROM _timescaledb_catalog.dimension_slice);
|
|
-- To drop rows from dimension_slice table, we need to remove some
|
|
-- constraints.
|
|
ALTER TABLE _timescaledb_catalog.chunk_constraint
|
|
DROP CONSTRAINT chunk_constraint_dimension_slice_id_fkey;
|
|
CREATE TABLE chunk_test_int(time integer, temp float8, tag integer, color integer);
|
|
SELECT create_hypertable('chunk_test_int', 'time', 'tag', 2, chunk_time_interval => 3);
|
|
NOTICE: adding not-null constraint to column "time"
|
|
create_hypertable
|
|
-----------------------------
|
|
(1,public,chunk_test_int,t)
|
|
(1 row)
|
|
|
|
INSERT INTO chunk_test_int VALUES
|
|
(4, 24.3, 1, 1),
|
|
(4, 24.3, 2, 1),
|
|
(10, 24.3, 2, 1);
|
|
SELECT * FROM _timescaledb_catalog.dimension_slice ORDER BY id;
|
|
id | dimension_id | range_start | range_end
|
|
----+--------------+----------------------+---------------------
|
|
1 | 1 | 3 | 6
|
|
2 | 2 | -9223372036854775808 | 1073741823
|
|
3 | 2 | 1073741823 | 9223372036854775807
|
|
4 | 1 | 9 | 12
|
|
(4 rows)
|
|
|
|
SELECT DISTINCT
|
|
chunk_id,
|
|
dimension_slice_id,
|
|
constraint_name,
|
|
pg_get_expr(conbin, conrelid) AS constraint_expr
|
|
FROM _timescaledb_catalog.chunk_constraint,
|
|
LATERAL (
|
|
SELECT *
|
|
FROM pg_constraint JOIN pg_namespace ns ON connamespace = ns.oid
|
|
WHERE conname = constraint_name
|
|
) AS con
|
|
ORDER BY chunk_id, dimension_slice_id;
|
|
chunk_id | dimension_slice_id | constraint_name | constraint_expr
|
|
----------+--------------------+-----------------+---------------------------------------------------------------
|
|
1 | 1 | constraint_1 | (("time" >= 3) AND ("time" < 6))
|
|
1 | 2 | constraint_2 | (_timescaledb_internal.get_partition_hash(tag) < 1073741823)
|
|
2 | 1 | constraint_1 | (("time" >= 3) AND ("time" < 6))
|
|
2 | 3 | constraint_3 | (_timescaledb_internal.get_partition_hash(tag) >= 1073741823)
|
|
3 | 3 | constraint_3 | (_timescaledb_internal.get_partition_hash(tag) >= 1073741823)
|
|
3 | 4 | constraint_4 | (("time" >= 9) AND ("time" < 12))
|
|
(6 rows)
|
|
|
|
DELETE FROM _timescaledb_catalog.dimension_slice WHERE id = 1;
|
|
SELECT * FROM missing_slices;
|
|
dimension_slice_id | constraint_name | column_name | constraint_expr
|
|
--------------------+-----------------+-------------+----------------------------------
|
|
1 | constraint_1 | time | (("time" >= 3) AND ("time" < 6))
|
|
(1 row)
|
|
|
|
-- Setting level to ERROR since warnings are printed in different
|
|
-- order on PG11 and PG12.
|
|
SET client_min_messages TO error;
|
|
TRUNCATE TABLE chunk_test_int;
|
|
DROP TABLE chunk_test_int;
|
|
RESET client_min_messages;
|
|
CREATE TABLE chunk_test_int(time integer, temp float8, tag integer, color integer);
|
|
SELECT create_hypertable('chunk_test_int', 'time', 'tag', 2, chunk_time_interval => 3);
|
|
NOTICE: adding not-null constraint to column "time"
|
|
create_hypertable
|
|
-----------------------------
|
|
(2,public,chunk_test_int,t)
|
|
(1 row)
|
|
|
|
INSERT INTO chunk_test_int VALUES
|
|
(4, 24.3, 1, 1),
|
|
(4, 24.3, 2, 1),
|
|
(10, 24.3, 2, 1);
|
|
SELECT DISTINCT
|
|
chunk_id,
|
|
dimension_slice_id,
|
|
constraint_name,
|
|
pg_get_expr(conbin, conrelid) AS constraint_expr
|
|
FROM _timescaledb_catalog.chunk_constraint,
|
|
LATERAL (
|
|
SELECT *
|
|
FROM pg_constraint JOIN pg_namespace ns ON connamespace = ns.oid
|
|
WHERE conname = constraint_name
|
|
) AS con
|
|
ORDER BY chunk_id, dimension_slice_id;
|
|
chunk_id | dimension_slice_id | constraint_name | constraint_expr
|
|
----------+--------------------+-----------------+---------------------------------------------------------------
|
|
4 | 5 | constraint_5 | (("time" >= 3) AND ("time" < 6))
|
|
4 | 6 | constraint_6 | (_timescaledb_internal.get_partition_hash(tag) < 1073741823)
|
|
5 | 5 | constraint_5 | (("time" >= 3) AND ("time" < 6))
|
|
5 | 7 | constraint_7 | (_timescaledb_internal.get_partition_hash(tag) >= 1073741823)
|
|
6 | 7 | constraint_7 | (_timescaledb_internal.get_partition_hash(tag) >= 1073741823)
|
|
6 | 8 | constraint_8 | (("time" >= 9) AND ("time" < 12))
|
|
(6 rows)
|
|
|
|
DELETE FROM _timescaledb_catalog.dimension_slice WHERE id = 5;
|
|
SELECT * FROM missing_slices;
|
|
dimension_slice_id | constraint_name | column_name | constraint_expr
|
|
--------------------+-----------------+-------------+----------------------------------
|
|
5 | constraint_5 | time | (("time" >= 3) AND ("time" < 6))
|
|
(1 row)
|
|
|
|
-- Setting level to ERROR since warnings are printed in different
|
|
-- order on PG11 and PG12.
|
|
SET client_min_messages TO error;
|
|
DROP TABLE chunk_test_int;
|
|
RESET client_min_messages;
|