mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-17 02:53:51 +08:00
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.
33 lines
922 B
SQL
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;
|