This change allows to create new dimensions even with
existing chunks.
It does not modify any existing data or do migration,
instead it creates full-range (-inf/inf) dimension slice for
existing chunks in order to be compatible with newly created
dimension.
All new chunks created after this will follow logic of the new
dimension and its partitioning.
Fix: #2818
Chunk scan performance during querying is improved by avoiding
repeated open and close of relations and indexes when joining chunk
information from different metadata tables.
When executing a query on a hypertable, it is expanded to include all
its children chunks. However, during the expansion, the chunks that
don't match the query constraints should also be excluded. The
following changes are made to make the scanning and exclusion more
efficient:
* Ensure metadata relations and indexes are only opened once even
though metadata for multiple chunks are scanned. This avoids doing
repeated open and close of tables and indexes for each chunk
scanned.
* Avoid interleaving scans of different relations, ensuring better
data locality, and having, e.g., indexes warm in cache.
* Avoid unnecessary scans that repeat work already done.
* Ensure chunks are locked in a consistent order (based on Oid).
To enable the above changes, some refactoring was necessary. The chunk
scans that happen during constraint exclusion are moved into separate
source files (`chunk_scan.c`) for better structure and readability.
Some test outputs are affected due to the new ordering of chunks in
append relations.
Rework debug waitpoint functionality to produce an error in
case if the waitpoint is enabled.
This update introduce a controlled way to simulate errors
scenarios during testing.
Add a workflow to check that CMake files are correctly formatted as
well as a custom target to format CMake files in the repository. This
commit also runs the formatting on all CMake files in the repository.
The flake in `multi_transaction_indexing` is because of a race between
`CREATE INDEX` and `DROP INDEX` and this commit add a debug waitpoint
so that we can reliably reproduce the race condition in the isolation
test.
This change makes two changes to address issues with processes doing
concurrent inserts and `drop_chunks` calls:
- When a new chunk is created, any dimension slices that existed prior
to creating the new chunk are locked to prevent them from being
dropped before the chunk-creating process commits.
- When a chunk is being dropped, concurrent inserts into the chunk
that is being dropped will try to lock the dimension slices of the
chunk. In case the locking fails (due to the slices being
concurrently deleted), the insert process will treat the chunk as
not existing and will instead recreate it. Previously, the chunk
slices (and thus chunk) would be found, but the insert would fail
when committing since the chunk was concurrently deleted.
A prior commit (PR #2150) partially solved a related problem, but
didn't lock all the slices of a chunk. That commit also threw an error
when a lock on a slice could not be taken due to the slice being
deleted by another transaction. This is now changed to treat that case
as a missing slice instead, causing it to be recreated.
Fixes#1986
The test `deadlock_dropchunks_select` get a timeout on MacOS, but not
on other platforms, so this commit extend the lock timeout to make the
test pass.
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
If a new chunk is created as part of an insert and drop_chunks runs
concurrently with the insert, there is a risk of a race. This is a test
for this.
Add locks for dimension slice tuples
If a dimension slice tuple is found while adding new chunk constraints
as part of a chunk creation it is not locked prior to adding the chunk
constraint. Hence a concurrently executing `drop_chunks` can find a
dimension slice unused (because there is no chunk constraint that
references it) and subsequently remove it. The insert will the continue
to add the chunk constraint with a reference to a now non-existent
dimension slice.
This commit fixes this by locking the dimension slice tuple with a
share lock when creating chunks and locking the dimension slice with an
exclusive lock prior to scanning for existing chunk constraints.
The commit also contains a script that repair the `dimension_slice`
table if it is broken by extracting information about dimension slices
that are mentioned in `chunk_constraint` table but not present in
`dimension_slice` table and re-create the rows from the constraints on
the chunks.
In slower environments the isolation tests are extremely flaky
because lock_timeout is only 50ms this patch changes lock_timeout
to 500ms for the isolation tests leading to much more reliable tests
in those environments.
The `drop_chunks` function is refactored to make table name mandatory
for the function. As a result, the function was also refactored to
accept the `regclass` type instead of table name plus schema name and
the parameters were reordered to match the order for `show_chunks`.
The commit also refactor the code to pass the hypertable structure
between internal functions rather than the hypertable relid and moving
error checks to the PostgreSQL function. This allow the internal
functions to avoid some lookups and use the information in the
structure directly and also give errors earlier instead of first
dropping chunks and then error and roll back the transaction.
This just addresses some minor test changes for PostgresQL version
12. Specifically it changes the tests to set client_min_message to
error, as fatal is no longer a valid setting here. This also hides
a new NOTICE message in bgw_job_delete, which was including a PID
and was thus nondeterministic.
Docker images are build with latest versions of PostgreSQL, thus
updating regression tests to run on the latest PG versions. Fixing
authentication for PG docker images, since it is required after a
recent change in docker-library/postgres@42ce743.
Running isolation tests on new versions of PG produces additional
output:
- Notifications are not missed to print postgres/postgres@ebd4992
- Notifications are prefixed with session name
postgres/postgres@a28e10e
- Timeout cancellation is printed in isolation tests
postgres/postgres@b578404
The expected outputs are modified to succeed on latest PG versions,
while the affected isolation tests are disabled for earlier versions
of PG.
Adds test infrastructure for deleting bgw jobs. We do this
using isolation tests. We add infrastructure for running bgws
in isolation tests. We also add infrastructure to control which
user runs the bgw scheduler and jobs during the tests. We
test the bgw delete as non-superuser.
Previously, drop_chunks returned an empty table, giving the user
no indication of what (if anything) had happened.
Now, drop_chunks returns a list of the chunks identifiers in the
same style as show_chunks, with the chunk's schema and table name.
Notably, when show_chunks is called directly before drop_chunks, the
output should be the same.
Currently CREATE INDEX creates the indices for all chunks in a single
transaction, which holds a lock on the root hypertable and all chunks. This
means that during CREATE INDEX no new inserts can occur, even if we're not
currently building an index on the table being inserted to.
This commit adds the option to create indices using a separate
transaction for each chunk. This option, used like
CREATE INDEX ON <table> WITH (timescaledb.transaction_per_chunk);
should cause less contention than a regular CREATE INDEX, in exchange
for the possibility that the index will be created on only some, or none,
of the chunks, if the command fails partway through. The command holds a lock on
the root index used as a template throughout the command, and each of the only
additionally locks the chunk being indexed. This means that that chunks which
are not currently being indexed can be inserted to, and new chunks can be
created while the CREATE INDEX command is in progress.
To enable detection of failed transaction_per_chunk CREATE INDEXs, the
hypertable's index is marked as invalid while the CREATE INDEX is in progress,
if the command fails partway through, the index will remain invalid. If such an
invalid index is discovered, it can be dropped an recreated to ensure that all
chunks have a copy of the index, in the future, we may add a command to create
indexes on only those chunks which are missing them. Note that even though the
hypertable's index is marked as invalid, new chunks will have a copy of the
index build as normal.
As part of the refactoring to make this command work, normal index creation was
slightly modified. Instead of getting the column names an index uses
one-at-a-time we get them all at once at the beginning of index creation, this
allows to close the hypertable's root table once we've determined all of while
we create the index info for each chunk. Secondly, it changes our function to
lookup a tablespace, ts_hypertable_get_tablespace_at_offset_from, to only take a
hypertable id, instead of the hypertable's entire cache entry; this function
only ever used the id, so this allows us to release the hypertable cache earlier
Acquire foreign key related table locks prior to dropping chunks. This
helps avoid deadlocks in scenarios where select and drop chunks are
trying to acquire locks on the same set of tables.
Changes to isolation test suite to prevent diffs related to displaying
hypertable id differences across test suite runs.
Fixes#865
Change create_hypertable to return a record consisting of
(hypertable_id, schema_name, table_name). This improves user feedback
about success of the operation but also gives the function an API
returning useful information for non-human consumption.
Postgres has a tool pg_isolation_regress which allows testing the behavior of
concurrent commands. Despite not being installed by default, the tool is still
build with the rest of postgres, and can run outside of the postgres src
directory. This commit adds hooks within the timescale build system to call
pg_isolation_regress from the postgres source tree, and run timescale tests
using it.
This commit also adds some basic tests for the behavior of concurrent INSERTS
that create chunks.