Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit794025e

Browse files
author
Amit Kapila
committed
Fix toast rewrites in logical decoding.
Commit325f2ec introduced pg_class.relwrite to skip operations ontables created as part of a heap rewrite during DDL. It links suchtransient heaps to the original relation OID via this new field inpg_class but forgot to do anything about toast tables. So, logicaldecoding was not able to skip operations on internally created toasttables. This leads to an error when we tried to decode the WAL for thenext operation for which it appeared that there is a toast data whereactually it didn't have any toast data.To fix this, we set pg_class.relwrite for internally created toast tablesas well which allowed skipping operations on them during logical decoding.Author: Bertrand DrouvotReviewed-by: David Zhang, Amit KapilaBackpatch-through: 11, where it was introducedDiscussion:https://postgr.es/m/b5146fb1-ad9e-7d6e-f980-98ed68744a7c@amazon.com
1 parent7d9026c commit794025e

File tree

7 files changed

+99
-13
lines changed

7 files changed

+99
-13
lines changed

‎contrib/test_decoding/expected/toast.out

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,28 @@ WHERE data NOT LIKE '%INSERT: %';
360360
COMMIT
361361
(4 rows)
362362

363+
/*
364+
* Test decoding relation rewrite with toast. The insert into tbl2 within the
365+
* same transaction is there to check that there is no remaining toast_hash not
366+
* being reset.
367+
*/
368+
CREATE TABLE tbl1 (a INT, b TEXT);
369+
CREATE TABLE tbl2 (a INT);
370+
ALTER TABLE tbl1 ALTER COLUMN b SET STORAGE EXTERNAL;
371+
BEGIN;
372+
INSERT INTO tbl1 VALUES(1, repeat('a', 4000)) ;
373+
ALTER TABLE tbl1 ADD COLUMN id serial primary key;
374+
INSERT INTO tbl2 VALUES(1);
375+
commit;
376+
SELECT substr(data, 1, 200) FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1');
377+
substr
378+
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
379+
BEGIN
380+
table public.tbl1: INSERT: a[integer]:1 b[text]:'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
381+
table public.tbl2: INSERT: a[integer]:1
382+
COMMIT
383+
(4 rows)
384+
363385
SELECT pg_drop_replication_slot('regression_slot');
364386
pg_drop_replication_slot
365387
--------------------------

‎contrib/test_decoding/sql/toast.sql

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,4 +308,20 @@ DROP TABLE toasted_several;
308308

309309
SELECT regexp_replace(data,'^(.{100}).*(.{100})$','\1..\2')FROM pg_logical_slot_get_changes('regression_slot',NULL,NULL,'include-xids','0','skip-empty-xacts','1')
310310
WHERE data NOTLIKE'%INSERT: %';
311+
312+
/*
313+
* Test decoding relation rewrite with toast. The insert into tbl2 within the
314+
* same transaction is there to check that there is no remaining toast_hash not
315+
* being reset.
316+
*/
317+
CREATETABLEtbl1 (aINT, bTEXT);
318+
CREATETABLEtbl2 (aINT);
319+
ALTERTABLE tbl1 ALTER COLUMN bSET STORAGE EXTERNAL;
320+
BEGIN;
321+
INSERT INTO tbl1VALUES(1, repeat('a',4000)) ;
322+
ALTERTABLE tbl1 ADD COLUMN idserialprimary key;
323+
INSERT INTO tbl2VALUES(1);
324+
commit;
325+
SELECT substr(data,1,200)FROM pg_logical_slot_get_changes('regression_slot',NULL,NULL,'include-xids','0','skip-empty-xacts','1');
326+
311327
SELECT pg_drop_replication_slot('regression_slot');

‎src/backend/catalog/toasting.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,11 @@
3838
Oidbinary_upgrade_next_toast_pg_type_oid=InvalidOid;
3939

4040
staticvoidCheckAndCreateToastTable(OidrelOid,Datumreloptions,
41-
LOCKMODElockmode,boolcheck);
41+
LOCKMODElockmode,boolcheck,
42+
OidOIDOldToast);
4243
staticboolcreate_toast_table(Relationrel,OidtoastOid,OidtoastIndexOid,
43-
Datumreloptions,LOCKMODElockmode,boolcheck);
44+
Datumreloptions,LOCKMODElockmode,boolcheck,
45+
OidOIDOldToast);
4446
staticboolneeds_toast_table(Relationrel);
4547

4648

@@ -59,30 +61,34 @@ static bool needs_toast_table(Relation rel);
5961
void
6062
AlterTableCreateToastTable(OidrelOid,Datumreloptions,LOCKMODElockmode)
6163
{
62-
CheckAndCreateToastTable(relOid,reloptions,lockmode, true);
64+
CheckAndCreateToastTable(relOid,reloptions,lockmode, true,InvalidOid);
6365
}
6466

6567
void
66-
NewHeapCreateToastTable(OidrelOid,Datumreloptions,LOCKMODElockmode)
68+
NewHeapCreateToastTable(OidrelOid,Datumreloptions,LOCKMODElockmode,
69+
OidOIDOldToast)
6770
{
68-
CheckAndCreateToastTable(relOid,reloptions,lockmode, false);
71+
CheckAndCreateToastTable(relOid,reloptions,lockmode, false,OIDOldToast);
6972
}
7073

7174
void
7275
NewRelationCreateToastTable(OidrelOid,Datumreloptions)
7376
{
74-
CheckAndCreateToastTable(relOid,reloptions,AccessExclusiveLock, false);
77+
CheckAndCreateToastTable(relOid,reloptions,AccessExclusiveLock, false,
78+
InvalidOid);
7579
}
7680

7781
staticvoid
78-
CheckAndCreateToastTable(OidrelOid,Datumreloptions,LOCKMODElockmode,boolcheck)
82+
CheckAndCreateToastTable(OidrelOid,Datumreloptions,LOCKMODElockmode,
83+
boolcheck,OidOIDOldToast)
7984
{
8085
Relationrel;
8186

8287
rel=table_open(relOid,lockmode);
8388

8489
/* create_toast_table does all the work */
85-
(void)create_toast_table(rel,InvalidOid,InvalidOid,reloptions,lockmode,check);
90+
(void)create_toast_table(rel,InvalidOid,InvalidOid,reloptions,lockmode,
91+
check,OIDOldToast);
8692

8793
table_close(rel,NoLock);
8894
}
@@ -108,7 +114,7 @@ BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid)
108114

109115
/* create_toast_table does all the work */
110116
if (!create_toast_table(rel,toastOid,toastIndexOid, (Datum)0,
111-
AccessExclusiveLock, false))
117+
AccessExclusiveLock, false,InvalidOid))
112118
elog(ERROR,"\"%s\" does not require a toast table",
113119
relName);
114120

@@ -125,7 +131,8 @@ BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid)
125131
*/
126132
staticbool
127133
create_toast_table(Relationrel,OidtoastOid,OidtoastIndexOid,
128-
Datumreloptions,LOCKMODElockmode,boolcheck)
134+
Datumreloptions,LOCKMODElockmode,boolcheck,
135+
OidOIDOldToast)
129136
{
130137
OidrelOid=RelationGetRelid(rel);
131138
HeapTuplereltup;
@@ -270,7 +277,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
270277
false,
271278
true,
272279
true,
273-
InvalidOid,
280+
OIDOldToast,
274281
NULL);
275282
Assert(toast_relid!=InvalidOid);
276283

‎src/backend/commands/cluster.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, char relpersistence,
709709
if (isNull)
710710
reloptions= (Datum)0;
711711

712-
NewHeapCreateToastTable(OIDNewHeap,reloptions,lockmode);
712+
NewHeapCreateToastTable(OIDNewHeap,reloptions,lockmode,toastid);
713713

714714
ReleaseSysCache(tuple);
715715
}
@@ -1487,6 +1487,14 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
14871487

14881488
RenameRelationInternal(toastidx,
14891489
NewToastName, true, true);
1490+
1491+
/*
1492+
* Reset the relrewrite for the toast. The command-counter
1493+
* increment is required here as we are about to update
1494+
* the tuple that is updated as part of RenameRelationInternal.
1495+
*/
1496+
CommandCounterIncrement();
1497+
ResetRelRewrite(newrel->rd_rel->reltoastrelid);
14901498
}
14911499
relation_close(newrel,NoLock);
14921500
}

‎src/backend/commands/tablecmds.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3562,6 +3562,37 @@ RenameRelationInternal(Oid myrelid, const char *newrelname, bool is_internal, bo
35623562
relation_close(targetrelation, NoLock);
35633563
}
35643564

3565+
/*
3566+
*ResetRelRewrite - reset relrewrite
3567+
*/
3568+
void
3569+
ResetRelRewrite(Oid myrelid)
3570+
{
3571+
Relationrelrelation;/* for RELATION relation */
3572+
HeapTuplereltup;
3573+
Form_pg_class relform;
3574+
3575+
/*
3576+
* Find relation's pg_class tuple.
3577+
*/
3578+
relrelation = table_open(RelationRelationId, RowExclusiveLock);
3579+
3580+
reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
3581+
if (!HeapTupleIsValid(reltup))/* shouldn't happen */
3582+
elog(ERROR, "cache lookup failed for relation %u", myrelid);
3583+
relform = (Form_pg_class) GETSTRUCT(reltup);
3584+
3585+
/*
3586+
* Update pg_class tuple.
3587+
*/
3588+
relform->relrewrite = InvalidOid;
3589+
3590+
CatalogTupleUpdate(relrelation, &reltup->t_self, reltup);
3591+
3592+
heap_freetuple(reltup);
3593+
table_close(relrelation, RowExclusiveLock);
3594+
}
3595+
35653596
/*
35663597
* Disallow ALTER TABLE (and similar commands) when the current backend has
35673598
* any open reference to the target table besides the one just acquired by

‎src/include/catalog/toasting.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
*/
2525
externvoidNewRelationCreateToastTable(OidrelOid,Datumreloptions);
2626
externvoidNewHeapCreateToastTable(OidrelOid,Datumreloptions,
27-
LOCKMODElockmode);
27+
LOCKMODElockmode,OidOIDOldToast);
2828
externvoidAlterTableCreateToastTable(OidrelOid,Datumreloptions,
2929
LOCKMODElockmode);
3030
externvoidBootstrapToastTable(char*relName,

‎src/include/commands/tablecmds.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ extern void RenameRelationInternal(Oid myrelid,
7171
constchar*newrelname,boolis_internal,
7272
boolis_index);
7373

74+
externvoidResetRelRewrite(Oidmyrelid);
75+
7476
externvoidfind_composite_type_dependencies(OidtypeOid,
7577
RelationorigRelation,
7678
constchar*origTypeName);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp