When using a cursor and trying to update a value using the cursor when data is compressed, a crash occurs.
There seems to be multiple underlying issues for why this doesn't work.
Compression uses a VirtualTupleTableSlot that has no TID. When the code asks to update the tuple at the cursor location an invalid TID is used.
DML decompression transparently moves data from the compresse rel to the non-compressed rel, so the tuple that the TID pointed to (if there would be a valid TID) will be deleted.
TimescaleDB version affected
2.15
PostgreSQL version used
16
What operating system did you use?
Ubuntu 24.04
What installation method did you use?
Source
What platform did you run on?
On prem/Self-hosted
Relevant log output and stack trace
Program terminated with signal SIGABRT, Aborted.
#0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>)
at ./nptl/pthread_kill.c:44
warning: 44 ./nptl/pthread_kill.c: No such file or directory
(gdb) bt
#0 __pthread_kill_implementation (no_tid=0, signo=6, threadid=<optimized out>)
at ./nptl/pthread_kill.c:44
#1 __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2 __GI___pthread_kill (threadid=<optimized out>, signo=signo@entry=6)
at ./nptl/pthread_kill.c:89
#3 0x0000750d1f1c626e in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#4 0x0000750d1f1a98ff in __GI_abort () at ./stdlib/abort.c:79
#5 0x00005cc253744b37 in ExceptionalCondition (
conditionName=0x5cc2537d3898 "ItemPointerIsValid(pointer)",
fileName=0x5cc2537d38b4 "../../../../src/include/storage/itemptr.h", lineNumber=105)
at assert.c:66
#6 0x00005cc252fa9b35 in ItemPointerGetBlockNumber (pointer=0x5cc2559c7bf4)
at ../../../../src/include/storage/itemptr.h:105
#7 0x00005cc252fb0924 in heap_lock_tuple (relation=0x750d14a9dff0, tuple=0x5cc2559c7bf0,
cid=0, mode=LockTupleExclusive, wait_policy=LockWaitBlock, follow_updates=true,
buffer=0x7fffda162940, tmfd=0x7fffda162a6c) at heapam.c:4174
#8 0x00005cc252fbc48b in heapam_tuple_lock (relation=0x750d14a9dff0, tid=0x7fffda162a80,
snapshot=0x5cc255915618, slot=0x5cc2559c7ba0, cid=0, mode=LockTupleExclusive,
wait_policy=LockWaitBlock, flags=3 '\003', tmfd=0x7fffda162a6c) at heapam_handler.c:377
#9 0x00005cc2532a3de3 in table_tuple_lock (rel=0x750d14a9dff0, tid=0x7fffda162a80,
snapshot=0x5cc255915618, slot=0x5cc2559c7ba0, cid=0, mode=LockTupleExclusive,
wait_policy=LockWaitBlock, flags=3 '\003', tmfd=0x7fffda162a6c)
at ../../../src/include/access/tableam.h:1580
#10 0x00005cc2532a37d9 in ExecLockRows (pstate=0x5cc2558ebc08) at nodeLockRows.c:185
How can we reproduce the bug?
create table hyper (time timestamptz, device_id int, location_id int, temp float);
select create_hypertable('hyper', 'time', create_default_indexes => false);
alter table hyper set (
timescaledb.compress,
timescaledb.compress_orderby = 'time',
timescaledb.compress_segmentby = 'device_id'
);
insert into hyper values
('2022-06-01 05:00', 1, 6, 6.0),
('2022-06-01 06:00', 1, 7, 7.0),
('2022-06-01 07:00', 1, 8, 8.0),
('2022-06-01 08:00', 2, 8, 8.0),
('2022-06-01 09:00', 2, 8, 8.0),
('2022-06-01 10:00', 3, 1, 8.0),
('2022-06-01 11:00', 3, 3, 9.0),
('2022-06-01 12:00', 3, 4, 11.0);
SELECT format('%I.%I', chunk_schema, chunk_name)::regclass AS chunk
FROM timescaledb_information.chunks
WHERE format('%I.%I', hypertable_schema, hypertable_name)::regclass = 'hyper'::regclass
LIMIT 1 \gset
SELECT relname, reltuples, relpages
FROM pg_class
WHERE oid = :'chunk'::regclass;
select compress_chunk(ch) from show_chunks('hyper') ch;
-- VIA chunk
\x on
-- pick a row that is stored in the compressed relation
--select ctid, * from :chunk order by time offset 5 limit 1;
select time as created_at, location_id, device_id
from :chunk order by time offset 5 limit 1 \gset
\x off
begin;
declare curs1 cursor for select temp from :chunk where time = :'created_at' for update;
fetch forward 1 from curs1;
explain (verbose)
update :chunk set temp = 200.0 where current of curs1;
update :chunk set temp = 200.0 where current of curs1;
commit;
select temp from :chunk where time = :'created_at';
-- VIA hypertable
\x on
-- pick a row that is stored in the compressed relation
--select ctid, * from hyper order by time offset 5 limit 1;
select time as created_at, location_id, device_id
from hyper order by time offset 5 limit 1 \gset
\x off
begin;
declare curs1 cursor for select temp from hyper where time = :'created_at' for update;
fetch forward 1 from curs1;
update hyper set temp = 200.0 where current of curs1;
commit;
select temp from hyper where time = :'created_at';
What type of bug is this?
Crash
What subsystems and features are affected?
Compression
What happened?
When using a cursor and trying to update a value using the cursor when data is compressed, a crash occurs.
There seems to be multiple underlying issues for why this doesn't work.
TimescaleDB version affected
2.15
PostgreSQL version used
16
What operating system did you use?
Ubuntu 24.04
What installation method did you use?
Source
What platform did you run on?
On prem/Self-hosted
Relevant log output and stack trace
How can we reproduce the bug?