timescaledb/test/sql/tablespace.sql
Erik Nordström e3fabf993a Fix chunk-related deadlocks.
This patch fixes two deadlock cases.

The first case occurred as a result of taking partition and chunk
locks in inconsistent orders. When creating the first chunk C1
in a table, concurrent INSERT workers would race to create
that chunk. The result would be that the transactions queue up on
the partition lock P, effectively serializing these transactions.
This would lead to these concurrent transactions to insert
at very different offsets in time, one at a time. At some point
in the future, some n'th transaction Tn queued up on P would get
that lock as the preceeding inserters T1-(n-1) finish their inserts
and move on to their next batches. When Tn finally holds P, one of
the preceeding workers starts a new transaction that finds that it
needs to close C1, grabbing a lock on C1 and then on P. However,
it will block on P since Tn already holds P. Tn will also believe
it needs to close C1, thus trying to grab a lock on C1, but will
block, causing a deadlock.

The second case can occur on multi-partition hypertables. With
multiple partitions there are more than one open-ended chunk
at a time (one for each partition). This leads to a deadlock case
when two processes try to close (and thus lock) the chunks in
different order. For instance process P1 closes chunk C1 and then
C2, while process P2 locks in order C2 and C1.

The fix for the first case is to remove the partition lock
altogether. As it turns out, this lock is not needed.
Instead, transactions can race to create new chunks, thus causing
conflicts. A conflict in creating a new chunk can safely be
ignored and it also avoids taking unecessary locks. Removing the
partition lock also avoids the transaction serialization that
happens around this lock, which is especially bad for long-running
transactions (e.g., big INSERT batches).

The fix for the second multi-partition deadlock case is to always
close chunks in chunk ID order. This requires closing chunks at
the end of a transaction, once a transaction knows all the chunks
it needs to close. This also has the added benefit of reducing the
time a transaction holds exclusive locks on chunks, potentially
improving insert performance.
2017-02-23 15:41:57 +01:00

33 lines
922 B
SQL

\set ON_ERROR_STOP 1
\set SHOW_CONTEXT never
\ir include/create_single_db.sql
\set ECHO ALL
\c single
\set ON_ERROR_STOP 0
SET client_min_messages = ERROR;
drop tablespace if exists tspace1;
SET client_min_messages = NOTICE;
\set VERBOSITY verbose
--test hypertable with tables space
create tablespace tspace1 location :TEST_TABLESPACE_PATH;
create table test_tspace(time timestamp, temp float, device_id text) tablespace tspace1;
select create_hypertable('test_tspace', 'time', 'device_id');
select * from _iobeamdb_catalog.partition p INNER JOIN _iobeamdb_catalog.partition_replica pr ON (pr.partition_id = p.id);
insert into test_tspace values ('2017-01-20T09:00:01', 24.3, 'dev1');
insert into test_tspace values ('2017-01-20T09:00:02', 22.3, 'dev7');
\dt test_tspace
--verify that the table chunk has the correct tablespace
\d+ _iobeamdb_internal.*
--cleanup
drop table test_tspace;
drop tablespace tspace1;