Skip to content

Commit 8deb6b3

Browse files
committed
Reinstate HEAP_XMAX_LOCK_ONLY|HEAP_KEYS_UPDATED as allowed
Commit 866e24d added an assert that HEAP_XMAX_LOCK_ONLY and HEAP_KEYS_UPDATED cannot appear together, on the faulty assumption that the latter necessarily referred to an update and not a tuple lock; but that's wrong, because SELECT FOR UPDATE can use precisely that combination, as evidenced by the amcheck test case added here. Remove the Assert(), and also patch amcheck's verify_heapam.c to not complain if the combination is found. Also, out of overabundance of caution, update (across all branches) README.tuplock to be more explicit about this. Author: Julien Rouhaud <rjuju123@gmail.com> Reviewed-by: Mahendra Singh Thalor <mahi6run@gmail.com> Reviewed-by: Dilip Kumar <dilipbalaut@gmail.com> Discussion: https://postgr.es/m/20210124061758.GA11756@nol
1 parent 3db05e7 commit 8deb6b3

File tree

4 files changed

+20
-16
lines changed

4 files changed

+20
-16
lines changed

contrib/amcheck/t/001_verify_heapam.pl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use PostgresNode;
55
use TestLib;
66

7-
use Test::More tests => 79;
7+
use Test::More tests => 80;
88

99
my ($node, $result);
1010

@@ -47,6 +47,9 @@
4747
#
4848
fresh_test_table('test');
4949
$node->safe_psql('postgres', q(VACUUM (FREEZE, DISABLE_PAGE_SKIPPING) test));
50+
detects_no_corruption(
51+
"verify_heapam('test')",
52+
"all-frozen not corrupted table");
5053
corrupt_first_page('test');
5154
detects_heap_corruption("verify_heapam('test')",
5255
"all-frozen corrupted table");
@@ -92,6 +95,15 @@ sub fresh_test_table
9295
ALTER TABLE $relname ALTER b SET STORAGE external;
9396
INSERT INTO $relname (a, b)
9497
(SELECT gs, repeat('b',gs*10) FROM generate_series(1,1000) gs);
98+
BEGIN;
99+
SAVEPOINT s1;
100+
SELECT 1 FROM $relname WHERE a = 42 FOR UPDATE;
101+
UPDATE $relname SET b = b WHERE a = 42;
102+
RELEASE s1;
103+
SAVEPOINT s1;
104+
SELECT 1 FROM $relname WHERE a = 42 FOR UPDATE;
105+
UPDATE $relname SET b = b WHERE a = 42;
106+
COMMIT;
95107
));
96108
}
97109

contrib/amcheck/verify_heapam.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -608,13 +608,6 @@ check_tuple_header_and_visibilty(HeapTupleHeader tuphdr, HeapCheckContext *ctx)
608608
ctx->tuphdr->t_hoff, ctx->lp_len));
609609
header_garbled = true;
610610
}
611-
if ((ctx->tuphdr->t_infomask & HEAP_XMAX_LOCK_ONLY) &&
612-
(ctx->tuphdr->t_infomask2 & HEAP_KEYS_UPDATED))
613-
{
614-
report_corruption(ctx,
615-
pstrdup("tuple is marked as only locked, but also claims key columns were updated"));
616-
header_garbled = true;
617-
}
618611

619612
if ((ctx->tuphdr->t_infomask & HEAP_XMAX_COMMITTED) &&
620613
(ctx->tuphdr->t_infomask & HEAP_XMAX_IS_MULTI))

src/backend/access/heap/README.tuplock

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,10 @@ The following infomask bits are applicable:
146146
FOR UPDATE; this is implemented by the HEAP_KEYS_UPDATED bit.
147147

148148
- HEAP_KEYS_UPDATED
149-
This bit lives in t_infomask2. If set, indicates that the XMAX updated
150-
this tuple and changed the key values, or it deleted the tuple.
151-
It's set regardless of whether the XMAX is a TransactionId or a MultiXactId.
149+
This bit lives in t_infomask2. If set, indicates that the operation(s) done
150+
by the XMAX compromise the tuple key, such as a SELECT FOR UPDATE, an UPDATE
151+
that modifies the columns of the key, or a DELETE. It's set regardless of
152+
whether the XMAX is a TransactionId or a MultiXactId.
152153

153154
We currently never set the HEAP_XMAX_COMMITTED when the HEAP_XMAX_IS_MULTI bit
154155
is set.

src/backend/access/heap/hio.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,10 @@ RelationPutHeapTuple(Relation relation,
4949

5050
/*
5151
* Do not allow tuples with invalid combinations of hint bits to be placed
52-
* on a page. These combinations are detected as corruption by the
53-
* contrib/amcheck logic, so if you disable one or both of these
54-
* assertions, make corresponding changes there.
52+
* on a page. This combination is detected as corruption by the
53+
* contrib/amcheck logic, so if you disable this assertion, make
54+
* corresponding changes there.
5555
*/
56-
Assert(!((tuple->t_data->t_infomask & HEAP_XMAX_LOCK_ONLY) &&
57-
(tuple->t_data->t_infomask2 & HEAP_KEYS_UPDATED)));
5856
Assert(!((tuple->t_data->t_infomask & HEAP_XMAX_COMMITTED) &&
5957
(tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI)));
6058

0 commit comments

Comments
 (0)