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

Commit29b5905

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 parent255ed90 commit29b5905

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
@@ -36,9 +36,11 @@
3636
#include"utils/syscache.h"
3737

3838
staticvoidCheckAndCreateToastTable(OidrelOid,Datumreloptions,
39-
LOCKMODElockmode,boolcheck);
39+
LOCKMODElockmode,boolcheck,
40+
OidOIDOldToast);
4041
staticboolcreate_toast_table(Relationrel,OidtoastOid,OidtoastIndexOid,
41-
Datumreloptions,LOCKMODElockmode,boolcheck);
42+
Datumreloptions,LOCKMODElockmode,boolcheck,
43+
OidOIDOldToast);
4244
staticboolneeds_toast_table(Relationrel);
4345

4446

@@ -57,30 +59,34 @@ static bool needs_toast_table(Relation rel);
5759
void
5860
AlterTableCreateToastTable(OidrelOid,Datumreloptions,LOCKMODElockmode)
5961
{
60-
CheckAndCreateToastTable(relOid,reloptions,lockmode, true);
62+
CheckAndCreateToastTable(relOid,reloptions,lockmode, true,InvalidOid);
6163
}
6264

6365
void
64-
NewHeapCreateToastTable(OidrelOid,Datumreloptions,LOCKMODElockmode)
66+
NewHeapCreateToastTable(OidrelOid,Datumreloptions,LOCKMODElockmode,
67+
OidOIDOldToast)
6568
{
66-
CheckAndCreateToastTable(relOid,reloptions,lockmode, false);
69+
CheckAndCreateToastTable(relOid,reloptions,lockmode, false,OIDOldToast);
6770
}
6871

6972
void
7073
NewRelationCreateToastTable(OidrelOid,Datumreloptions)
7174
{
72-
CheckAndCreateToastTable(relOid,reloptions,AccessExclusiveLock, false);
75+
CheckAndCreateToastTable(relOid,reloptions,AccessExclusiveLock, false,
76+
InvalidOid);
7377
}
7478

7579
staticvoid
76-
CheckAndCreateToastTable(OidrelOid,Datumreloptions,LOCKMODElockmode,boolcheck)
80+
CheckAndCreateToastTable(OidrelOid,Datumreloptions,LOCKMODElockmode,
81+
boolcheck,OidOIDOldToast)
7782
{
7883
Relationrel;
7984

8085
rel=table_open(relOid,lockmode);
8186

8287
/* create_toast_table does all the work */
83-
(void)create_toast_table(rel,InvalidOid,InvalidOid,reloptions,lockmode,check);
88+
(void)create_toast_table(rel,InvalidOid,InvalidOid,reloptions,lockmode,
89+
check,OIDOldToast);
8490

8591
table_close(rel,NoLock);
8692
}
@@ -104,7 +110,7 @@ BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid)
104110

105111
/* create_toast_table does all the work */
106112
if (!create_toast_table(rel,toastOid,toastIndexOid, (Datum)0,
107-
AccessExclusiveLock, false))
113+
AccessExclusiveLock, false,InvalidOid))
108114
elog(ERROR,"\"%s\" does not require a toast table",
109115
relName);
110116

@@ -121,7 +127,8 @@ BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid)
121127
*/
122128
staticbool
123129
create_toast_table(Relationrel,OidtoastOid,OidtoastIndexOid,
124-
Datumreloptions,LOCKMODElockmode,boolcheck)
130+
Datumreloptions,LOCKMODElockmode,boolcheck,
131+
OidOIDOldToast)
125132
{
126133
OidrelOid=RelationGetRelid(rel);
127134
HeapTuplereltup;
@@ -258,7 +265,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
258265
false,
259266
true,
260267
true,
261-
InvalidOid,
268+
OIDOldToast,
262269
NULL);
263270
Assert(toast_relid!=InvalidOid);
264271

‎src/backend/commands/cluster.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, Oid NewAccessMethod,
735735
if (isNull)
736736
reloptions= (Datum)0;
737737

738-
NewHeapCreateToastTable(OIDNewHeap,reloptions,lockmode);
738+
NewHeapCreateToastTable(OIDNewHeap,reloptions,lockmode,toastid);
739739

740740
ReleaseSysCache(tuple);
741741
}
@@ -1526,6 +1526,14 @@ finish_heap_swap(Oid OIDOldHeap, Oid OIDNewHeap,
15261526

15271527
RenameRelationInternal(toastidx,
15281528
NewToastName, true, true);
1529+
1530+
/*
1531+
* Reset the relrewrite for the toast. The command-counter
1532+
* increment is required here as we are about to update
1533+
* the tuple that is updated as part of RenameRelationInternal.
1534+
*/
1535+
CommandCounterIncrement();
1536+
ResetRelRewrite(newrel->rd_rel->reltoastrelid);
15291537
}
15301538
relation_close(newrel,NoLock);
15311539
}

‎src/backend/commands/tablecmds.c

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

3852+
/*
3853+
*ResetRelRewrite - reset relrewrite
3854+
*/
3855+
void
3856+
ResetRelRewrite(Oid myrelid)
3857+
{
3858+
Relationrelrelation;/* for RELATION relation */
3859+
HeapTuplereltup;
3860+
Form_pg_class relform;
3861+
3862+
/*
3863+
* Find relation's pg_class tuple.
3864+
*/
3865+
relrelation = table_open(RelationRelationId, RowExclusiveLock);
3866+
3867+
reltup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(myrelid));
3868+
if (!HeapTupleIsValid(reltup))/* shouldn't happen */
3869+
elog(ERROR, "cache lookup failed for relation %u", myrelid);
3870+
relform = (Form_pg_class) GETSTRUCT(reltup);
3871+
3872+
/*
3873+
* Update pg_class tuple.
3874+
*/
3875+
relform->relrewrite = InvalidOid;
3876+
3877+
CatalogTupleUpdate(relrelation, &reltup->t_self, reltup);
3878+
3879+
heap_freetuple(reltup);
3880+
table_close(relrelation, RowExclusiveLock);
3881+
}
3882+
38523883
/*
38533884
* Disallow ALTER TABLE (and similar commands) when the current backend has
38543885
* 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
@@ -21,7 +21,7 @@
2121
*/
2222
externvoidNewRelationCreateToastTable(OidrelOid,Datumreloptions);
2323
externvoidNewHeapCreateToastTable(OidrelOid,Datumreloptions,
24-
LOCKMODElockmode);
24+
LOCKMODElockmode,OidOIDOldToast);
2525
externvoidAlterTableCreateToastTable(OidrelOid,Datumreloptions,
2626
LOCKMODElockmode);
2727
externvoidBootstrapToastTable(char*relName,

‎src/include/commands/tablecmds.h

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

81+
externvoidResetRelRewrite(Oidmyrelid);
82+
8183
externvoidfind_composite_type_dependencies(OidtypeOid,
8284
RelationorigRelation,
8385
constchar*origTypeName);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp