Hi, (Tomas, CCing you because you IIRC mentioned encountered an issue like this)
I just spent quite a while debugging an issue where running logical decoding yielded a: ERROR: could not map filenode "base/$X/$Y" to relation OID error. After discarding like 30 different theories, I have found the cause: During rewrites (i.e. VACUUM FULL / CLUSTER) of a mapped relation with a toast table with actual live toasted tuples (pg_proc in my case and henceforth) heap inserts with the toast data happen into the new toast relation, triggered by: static void raw_heap_insert(RewriteState state, HeapTuple tup) ... /* * If the new tuple is too big for storage or contains already toasted * out-of-line attributes from some other relation, invoke the toaster. * * Note: below this point, heaptup is the data we actually intend to store * into the relation; tup is the caller's original untoasted data. */ if (state->rs_new_rel->rd_rel->relkind == RELKIND_TOASTVALUE) { /* toast table entries should never be recursively toasted */ Assert(!HeapTupleHasExternal(tup)); heaptup = tup; } else if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD) heaptup = toast_insert_or_update(state->rs_new_rel, tup, NULL, HEAP_INSERT_SKIP_FSM | (state->rs_use_wal ? 0 : HEAP_INSERT_SKIP_WAL)); else heaptup = tup; At that point the new toast relation does *NOT* appear to be a system catalog, it's just appears as an "independent" table. Therefore we do not trigger, in heap_insert(): /* * RelationIsLogicallyLogged * True if we need to log enough information to extract the data from the * WAL stream. * * We don't log information for unlogged tables (since they don't WAL log * anyway) and for system tables (their content is hard to make sense of, and * it would complicate decoding slightly for little gain). Note that we *do* * log information for user defined catalog tables since they presumably are * interesting to the user... */ #define RelationIsLogicallyLogged(relation) \ (XLogLogicalInfoActive() && \ RelationNeedsWAL(relation) && \ !IsCatalogRelation(relation)) /* * For logical decoding, we need the tuple even if we're doing a full * page write, so make sure it's included even if we take a full-page * image. (XXX We could alternatively store a pointer into the FPW). */ if (RelationIsLogicallyLogged(relation)) { xlrec.flags |= XLH_INSERT_CONTAINS_NEW_TUPLE; bufflags |= REGBUF_KEEP_DATA; } i.e. the inserted toast tuple will be marked as XLH_INSERT_CONTAINS_NEW_TUPLE - which it shouldn't, because it's a system table. Which we currently do not allow do be logically decoded. That normally ends up being harmless, because ReorderBufferCommit() has the following check: if (!RelationIsLogicallyLogged(relation)) goto change_done; but to reach that check, we first have to map the relfilenode from the WAL to the corresponding OID: reloid = RelidByRelfilenode(change->data.tp.relnode.spcNode, change->data.tp.relnode.relNode); That works correctly if there's only one rewrite - the relmapper contains the data for the new toast table. But if there's been *two* consecutive rewrites, the relmapper *does not* contain the intermediary relfilenode of pg_proc. There's no such problem for non-mapped tables, because historic snapshots allow us to access the relevant data, but the relmapper isn't mvcc. Therefore the catalog-rewrite escape hatch of: /* * Catalog tuple without data, emitted while catalog was * in the process of being rewritten. */ if (reloid == InvalidOid && change->data.tp.newtuple == NULL && change->data.tp.oldtuple == NULL) goto change_done; does not trigger and we run into: else if (reloid == InvalidOid) elog(ERROR, "could not map filenode \"%s\" to relation OID", relpathperm(change->data.tp.relnode, MAIN_FORKNUM)); commenting out this error / converting it into a warning makes this case harmless, but could obviously be problematic in other scenarios. I suspect the proper fix would be to have a new HEAP_INSERT_NO_LOGICAL option, and specify that in raw_heap_insert() iff RelationIsLogicallyLogged(state->rs_old_rel) or something like that. Attached is a *prototype* patch of that approach. Without the code level changes the addition to test_decoding's rewrite.sql trigger the bug, after it they're fixed. The only reason the scenario I was debugging hit this was that there was a cluster wide VACUUM FULL a couple times a day, and replication was several hours behind due to slow network / receiving side. Now I'm having a beer outside. Greetings, Andres Freund
diff --git a/contrib/test_decoding/expected/rewrite.out b/contrib/test_decoding/expected/rewrite.out index 4dcd4895438..12eaab99b83 100644 --- a/contrib/test_decoding/expected/rewrite.out +++ b/contrib/test_decoding/expected/rewrite.out @@ -34,6 +34,407 @@ VACUUM FULL pg_opclass; VACUUM FULL pg_type; VACUUM FULL pg_index; VACUUM FULL pg_database; +-- ensure there's a catalog table that is toasted. +CREATE FUNCTION speaketh() RETURNS TEXT IMMUTABLE LANGUAGE SQL AS $f$ +SELECT text $t$ +ACT I +SCENE I. Elsinore. A platform before the castle. + + FRANCISCO at his post. Enter to him BERNARDO + +BERNARDO + + Who's there? + +FRANCISCO + + Nay, answer me: stand, and unfold yourself. + +BERNARDO + + Long live the king! + +FRANCISCO + + Bernardo? + +BERNARDO + + He. + +FRANCISCO + + You come most carefully upon your hour. + +BERNARDO + + 'Tis now struck twelve; get thee to bed, Francisco. + +FRANCISCO + + For this relief much thanks: 'tis bitter cold, + And I am sick at heart. + +BERNARDO + + Have you had quiet guard? + +FRANCISCO + + Not a mouse stirring. + +BERNARDO + + Well, good night. + If you do meet Horatio and Marcellus, + The rivals of my watch, bid them make haste. + +FRANCISCO + + I think I hear them. Stand, ho! Who's there? + + Enter HORATIO and MARCELLUS + +HORATIO + + Friends to this ground. + +MARCELLUS + + And liegemen to the Dane. + +FRANCISCO + + Give you good night. + +MARCELLUS + + O, farewell, honest soldier: + Who hath relieved you? + +FRANCISCO + + Bernardo has my place. + Give you good night. + + Exit + +MARCELLUS + + Holla! Bernardo! + +BERNARDO + + Say, + What, is Horatio there? + +HORATIO + + A piece of him. + +BERNARDO + + Welcome, Horatio: welcome, good Marcellus. + +MARCELLUS + + What, has this thing appear'd again to-night? + +BERNARDO + + I have seen nothing. + +MARCELLUS + + Horatio says 'tis but our fantasy, + And will not let belief take hold of him + Touching this dreaded sight, twice seen of us: + Therefore I have entreated him along + With us to watch the minutes of this night; + That if again this apparition come, + He may approve our eyes and speak to it. + +HORATIO + + Tush, tush, 'twill not appear. + +BERNARDO + + Sit down awhile; + And let us once again assail your ears, + That are so fortified against our story + What we have two nights seen. + +HORATIO + + Well, sit we down, + And let us hear Bernardo speak of this. + +BERNARDO + + Last night of all, + When yond same star that's westward from the pole + Had made his course to illume that part of heaven + Where now it burns, Marcellus and myself, + The bell then beating one,-- + + Enter Ghost + +MARCELLUS + + Peace, break thee off; look, where it comes again! + +BERNARDO + + In the same figure, like the king that's dead. + +MARCELLUS + + Thou art a scholar; speak to it, Horatio. + +BERNARDO + + Looks it not like the king? mark it, Horatio. + +HORATIO + + Most like: it harrows me with fear and wonder. + +BERNARDO + + It would be spoke to. + +MARCELLUS + + Question it, Horatio. + +HORATIO + + What art thou that usurp'st this time of night, + Together with that fair and warlike form + In which the majesty of buried Denmark + Did sometimes march? by heaven I charge thee, speak! + +MARCELLUS + + It is offended. + +BERNARDO + + See, it stalks away! + +HORATIO + + Stay! speak, speak! I charge thee, speak! + + Exit Ghost + +MARCELLUS + + 'Tis gone, and will not answer. + +BERNARDO + + How now, Horatio! you tremble and look pale: + Is not this something more than fantasy? + What think you on't? + +HORATIO + + Before my God, I might not this believe + Without the sensible and true avouch + Of mine own eyes. + +MARCELLUS + + Is it not like the king? + +HORATIO + + As thou art to thyself: + Such was the very armour he had on + When he the ambitious Norway combated; + So frown'd he once, when, in an angry parle, + He smote the sledded Polacks on the ice. + 'Tis strange. + +MARCELLUS + + Thus twice before, and jump at this dead hour, + With martial stalk hath he gone by our watch. + +HORATIO + + In what particular thought to work I know not; + But in the gross and scope of my opinion, + This bodes some strange eruption to our state. + +MARCELLUS + + Good now, sit down, and tell me, he that knows, + Why this same strict and most observant watch + So nightly toils the subject of the land, + And why such daily cast of brazen cannon, + And foreign mart for implements of war; + Why such impress of shipwrights, whose sore task + Does not divide the Sunday from the week; + What might be toward, that this sweaty haste + Doth make the night joint-labourer with the day: + Who is't that can inform me? + +HORATIO + + That can I; + At least, the whisper goes so. Our last king, + Whose image even but now appear'd to us, + Was, as you know, by Fortinbras of Norway, + Thereto prick'd on by a most emulate pride, + Dared to the combat; in which our valiant Hamlet-- + For so this side of our known world esteem'd him-- + Did slay this Fortinbras; who by a seal'd compact, + Well ratified by law and heraldry, + Did forfeit, with his life, all those his lands + Which he stood seized of, to the conqueror: + Against the which, a moiety competent + Was gaged by our king; which had return'd + To the inheritance of Fortinbras, + Had he been vanquisher; as, by the same covenant, + And carriage of the article design'd, + His fell to Hamlet. Now, sir, young Fortinbras, + Of unimproved mettle hot and full, + Hath in the skirts of Norway here and there + Shark'd up a list of lawless resolutes, + For food and diet, to some enterprise + That hath a stomach in't; which is no other-- + As it doth well appear unto our state-- + But to recover of us, by strong hand + And terms compulsatory, those foresaid lands + So by his father lost: and this, I take it, + Is the main motive of our preparations, + The source of this our watch and the chief head + Of this post-haste and romage in the land. + +BERNARDO + + I think it be no other but e'en so: + Well may it sort that this portentous figure + Comes armed through our watch; so like the king + That was and is the question of these wars. + +HORATIO + + A mote it is to trouble the mind's eye. + In the most high and palmy state of Rome, + A little ere the mightiest Julius fell, + The graves stood tenantless and the sheeted dead + Did squeak and gibber in the Roman streets: + As stars with trains of fire and dews of blood, + Disasters in the sun; and the moist star + Upon whose influence Neptune's empire stands + Was sick almost to doomsday with eclipse: + And even the like precurse of fierce events, + As harbingers preceding still the fates + And prologue to the omen coming on, + Have heaven and earth together demonstrated + Unto our climatures and countrymen.-- + But soft, behold! lo, where it comes again! + + Re-enter Ghost + I'll cross it, though it blast me. Stay, illusion! + If thou hast any sound, or use of voice, + Speak to me: + If there be any good thing to be done, + That may to thee do ease and grace to me, + Speak to me: + + Cock crows + If thou art privy to thy country's fate, + Which, happily, foreknowing may avoid, O, speak! + Or if thou hast uphoarded in thy life + Extorted treasure in the womb of earth, + For which, they say, you spirits oft walk in death, + Speak of it: stay, and speak! Stop it, Marcellus. + +MARCELLUS + + Shall I strike at it with my partisan? + +HORATIO + + Do, if it will not stand. + +BERNARDO + + 'Tis here! + +HORATIO + + 'Tis here! + +MARCELLUS + + 'Tis gone! + + Exit Ghost + We do it wrong, being so majestical, + To offer it the show of violence; + For it is, as the air, invulnerable, + And our vain blows malicious mockery. + +BERNARDO + + It was about to speak, when the cock crew. + +HORATIO + + And then it started like a guilty thing + Upon a fearful summons. I have heard, + The cock, that is the trumpet to the morn, + Doth with his lofty and shrill-sounding throat + Awake the god of day; and, at his warning, + Whether in sea or fire, in earth or air, + The extravagant and erring spirit hies + To his confine: and of the truth herein + This present object made probation. + +MARCELLUS + + It faded on the crowing of the cock. + Some say that ever 'gainst that season comes + Wherein our Saviour's birth is celebrated, + The bird of dawning singeth all night long: + And then, they say, no spirit dares stir abroad; + The nights are wholesome; then no planets strike, + No fairy takes, nor witch hath power to charm, + So hallow'd and so gracious is the time. + +HORATIO + + So have I heard and do in part believe it. + But, look, the morn, in russet mantle clad, + Walks o'er the dew of yon high eastward hill: + Break we our watch up; and by my advice, + Let us impart what we have seen to-night + Unto young Hamlet; for, upon my life, + This spirit, dumb to us, will speak to him. + Do you consent we shall acquaint him with it, + As needful in our loves, fitting our duty? + +MARCELLUS + + Let's do't, I pray; and I this morning know + Where we shall find him most conveniently. + + Exeunt +$t$ +$f$; +SELECT pg_relation_size((SELECT reltoastrelid FROM pg_class WHERE oid = 'pg_proc'::regclass)) > 0; + ?column? +---------- + t +(1 row) + +VACUUM FULL pg_proc; -- repeated rewrites that fail BEGIN; CLUSTER pg_class USING pg_class_oid_index; @@ -76,6 +477,13 @@ SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'inc COMMIT (15 rows) +VACUUM FULL pg_proc; +VACUUM FULL pg_proc; +SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); + data +------ +(0 rows) + SELECT pg_drop_replication_slot('regression_slot'); pg_drop_replication_slot -------------------------- @@ -83,3 +491,4 @@ SELECT pg_drop_replication_slot('regression_slot'); (1 row) DROP TABLE IF EXISTS replication_example; +DROP FUNCTION speaketh(); diff --git a/contrib/test_decoding/sql/rewrite.sql b/contrib/test_decoding/sql/rewrite.sql index 8a7329423de..b3ea848cad0 100644 --- a/contrib/test_decoding/sql/rewrite.sql +++ b/contrib/test_decoding/sql/rewrite.sql @@ -28,6 +28,404 @@ VACUUM FULL pg_type; VACUUM FULL pg_index; VACUUM FULL pg_database; +-- ensure there's a catalog table that is toasted. +CREATE FUNCTION speaketh() RETURNS TEXT IMMUTABLE LANGUAGE SQL AS $f$ +SELECT text $t$ +ACT I +SCENE I. Elsinore. A platform before the castle. + + FRANCISCO at his post. Enter to him BERNARDO + +BERNARDO + + Who's there? + +FRANCISCO + + Nay, answer me: stand, and unfold yourself. + +BERNARDO + + Long live the king! + +FRANCISCO + + Bernardo? + +BERNARDO + + He. + +FRANCISCO + + You come most carefully upon your hour. + +BERNARDO + + 'Tis now struck twelve; get thee to bed, Francisco. + +FRANCISCO + + For this relief much thanks: 'tis bitter cold, + And I am sick at heart. + +BERNARDO + + Have you had quiet guard? + +FRANCISCO + + Not a mouse stirring. + +BERNARDO + + Well, good night. + If you do meet Horatio and Marcellus, + The rivals of my watch, bid them make haste. + +FRANCISCO + + I think I hear them. Stand, ho! Who's there? + + Enter HORATIO and MARCELLUS + +HORATIO + + Friends to this ground. + +MARCELLUS + + And liegemen to the Dane. + +FRANCISCO + + Give you good night. + +MARCELLUS + + O, farewell, honest soldier: + Who hath relieved you? + +FRANCISCO + + Bernardo has my place. + Give you good night. + + Exit + +MARCELLUS + + Holla! Bernardo! + +BERNARDO + + Say, + What, is Horatio there? + +HORATIO + + A piece of him. + +BERNARDO + + Welcome, Horatio: welcome, good Marcellus. + +MARCELLUS + + What, has this thing appear'd again to-night? + +BERNARDO + + I have seen nothing. + +MARCELLUS + + Horatio says 'tis but our fantasy, + And will not let belief take hold of him + Touching this dreaded sight, twice seen of us: + Therefore I have entreated him along + With us to watch the minutes of this night; + That if again this apparition come, + He may approve our eyes and speak to it. + +HORATIO + + Tush, tush, 'twill not appear. + +BERNARDO + + Sit down awhile; + And let us once again assail your ears, + That are so fortified against our story + What we have two nights seen. + +HORATIO + + Well, sit we down, + And let us hear Bernardo speak of this. + +BERNARDO + + Last night of all, + When yond same star that's westward from the pole + Had made his course to illume that part of heaven + Where now it burns, Marcellus and myself, + The bell then beating one,-- + + Enter Ghost + +MARCELLUS + + Peace, break thee off; look, where it comes again! + +BERNARDO + + In the same figure, like the king that's dead. + +MARCELLUS + + Thou art a scholar; speak to it, Horatio. + +BERNARDO + + Looks it not like the king? mark it, Horatio. + +HORATIO + + Most like: it harrows me with fear and wonder. + +BERNARDO + + It would be spoke to. + +MARCELLUS + + Question it, Horatio. + +HORATIO + + What art thou that usurp'st this time of night, + Together with that fair and warlike form + In which the majesty of buried Denmark + Did sometimes march? by heaven I charge thee, speak! + +MARCELLUS + + It is offended. + +BERNARDO + + See, it stalks away! + +HORATIO + + Stay! speak, speak! I charge thee, speak! + + Exit Ghost + +MARCELLUS + + 'Tis gone, and will not answer. + +BERNARDO + + How now, Horatio! you tremble and look pale: + Is not this something more than fantasy? + What think you on't? + +HORATIO + + Before my God, I might not this believe + Without the sensible and true avouch + Of mine own eyes. + +MARCELLUS + + Is it not like the king? + +HORATIO + + As thou art to thyself: + Such was the very armour he had on + When he the ambitious Norway combated; + So frown'd he once, when, in an angry parle, + He smote the sledded Polacks on the ice. + 'Tis strange. + +MARCELLUS + + Thus twice before, and jump at this dead hour, + With martial stalk hath he gone by our watch. + +HORATIO + + In what particular thought to work I know not; + But in the gross and scope of my opinion, + This bodes some strange eruption to our state. + +MARCELLUS + + Good now, sit down, and tell me, he that knows, + Why this same strict and most observant watch + So nightly toils the subject of the land, + And why such daily cast of brazen cannon, + And foreign mart for implements of war; + Why such impress of shipwrights, whose sore task + Does not divide the Sunday from the week; + What might be toward, that this sweaty haste + Doth make the night joint-labourer with the day: + Who is't that can inform me? + +HORATIO + + That can I; + At least, the whisper goes so. Our last king, + Whose image even but now appear'd to us, + Was, as you know, by Fortinbras of Norway, + Thereto prick'd on by a most emulate pride, + Dared to the combat; in which our valiant Hamlet-- + For so this side of our known world esteem'd him-- + Did slay this Fortinbras; who by a seal'd compact, + Well ratified by law and heraldry, + Did forfeit, with his life, all those his lands + Which he stood seized of, to the conqueror: + Against the which, a moiety competent + Was gaged by our king; which had return'd + To the inheritance of Fortinbras, + Had he been vanquisher; as, by the same covenant, + And carriage of the article design'd, + His fell to Hamlet. Now, sir, young Fortinbras, + Of unimproved mettle hot and full, + Hath in the skirts of Norway here and there + Shark'd up a list of lawless resolutes, + For food and diet, to some enterprise + That hath a stomach in't; which is no other-- + As it doth well appear unto our state-- + But to recover of us, by strong hand + And terms compulsatory, those foresaid lands + So by his father lost: and this, I take it, + Is the main motive of our preparations, + The source of this our watch and the chief head + Of this post-haste and romage in the land. + +BERNARDO + + I think it be no other but e'en so: + Well may it sort that this portentous figure + Comes armed through our watch; so like the king + That was and is the question of these wars. + +HORATIO + + A mote it is to trouble the mind's eye. + In the most high and palmy state of Rome, + A little ere the mightiest Julius fell, + The graves stood tenantless and the sheeted dead + Did squeak and gibber in the Roman streets: + As stars with trains of fire and dews of blood, + Disasters in the sun; and the moist star + Upon whose influence Neptune's empire stands + Was sick almost to doomsday with eclipse: + And even the like precurse of fierce events, + As harbingers preceding still the fates + And prologue to the omen coming on, + Have heaven and earth together demonstrated + Unto our climatures and countrymen.-- + But soft, behold! lo, where it comes again! + + Re-enter Ghost + I'll cross it, though it blast me. Stay, illusion! + If thou hast any sound, or use of voice, + Speak to me: + If there be any good thing to be done, + That may to thee do ease and grace to me, + Speak to me: + + Cock crows + If thou art privy to thy country's fate, + Which, happily, foreknowing may avoid, O, speak! + Or if thou hast uphoarded in thy life + Extorted treasure in the womb of earth, + For which, they say, you spirits oft walk in death, + Speak of it: stay, and speak! Stop it, Marcellus. + +MARCELLUS + + Shall I strike at it with my partisan? + +HORATIO + + Do, if it will not stand. + +BERNARDO + + 'Tis here! + +HORATIO + + 'Tis here! + +MARCELLUS + + 'Tis gone! + + Exit Ghost + We do it wrong, being so majestical, + To offer it the show of violence; + For it is, as the air, invulnerable, + And our vain blows malicious mockery. + +BERNARDO + + It was about to speak, when the cock crew. + +HORATIO + + And then it started like a guilty thing + Upon a fearful summons. I have heard, + The cock, that is the trumpet to the morn, + Doth with his lofty and shrill-sounding throat + Awake the god of day; and, at his warning, + Whether in sea or fire, in earth or air, + The extravagant and erring spirit hies + To his confine: and of the truth herein + This present object made probation. + +MARCELLUS + + It faded on the crowing of the cock. + Some say that ever 'gainst that season comes + Wherein our Saviour's birth is celebrated, + The bird of dawning singeth all night long: + And then, they say, no spirit dares stir abroad; + The nights are wholesome; then no planets strike, + No fairy takes, nor witch hath power to charm, + So hallow'd and so gracious is the time. + +HORATIO + + So have I heard and do in part believe it. + But, look, the morn, in russet mantle clad, + Walks o'er the dew of yon high eastward hill: + Break we our watch up; and by my advice, + Let us impart what we have seen to-night + Unto young Hamlet; for, upon my life, + This spirit, dumb to us, will speak to him. + Do you consent we shall acquaint him with it, + As needful in our loves, fitting our duty? + +MARCELLUS + + Let's do't, I pray; and I this morning know + Where we shall find him most conveniently. + + Exeunt +$t$ +$f$; +SELECT pg_relation_size((SELECT reltoastrelid FROM pg_class WHERE oid = 'pg_proc'::regclass)) > 0; + +VACUUM FULL pg_proc; + -- repeated rewrites that fail BEGIN; CLUSTER pg_class USING pg_class_oid_index; @@ -57,6 +455,11 @@ COMMIT; CHECKPOINT; SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); -SELECT pg_drop_replication_slot('regression_slot'); +VACUUM FULL pg_proc; +VACUUM FULL pg_proc; +SELECT data FROM pg_logical_slot_get_changes('regression_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); + +SELECT pg_drop_replication_slot('regression_slot'); DROP TABLE IF EXISTS replication_example; +DROP FUNCTION speaketh(); diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 56f1d82f962..f971705507e 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -2551,7 +2551,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid, * page write, so make sure it's included even if we take a full-page * image. (XXX We could alternatively store a pointer into the FPW). */ - if (RelationIsLogicallyLogged(relation)) + if (RelationIsLogicallyLogged(relation) && !(options & HEAP_INSERT_NO_LOGICAL)) { xlrec.flags |= XLH_INSERT_CONTAINS_NEW_TUPLE; bufflags |= REGBUF_KEEP_DATA; diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c index 85f92973c95..6bae129f6a6 100644 --- a/src/backend/access/heap/rewriteheap.c +++ b/src/backend/access/heap/rewriteheap.c @@ -652,10 +652,18 @@ raw_heap_insert(RewriteState state, HeapTuple tup) heaptup = tup; } else if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD) + { + int options = HEAP_INSERT_SKIP_FSM; + + if (!state->rs_use_wal) + options |= HEAP_INSERT_SKIP_WAL; + + if (!RelationIsLogicallyLogged(state->rs_old_rel)) + options |= HEAP_INSERT_NO_LOGICAL; + heaptup = toast_insert_or_update(state->rs_new_rel, tup, NULL, - HEAP_INSERT_SKIP_FSM | - (state->rs_use_wal ? - 0 : HEAP_INSERT_SKIP_WAL)); + options); + } else heaptup = tup; diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index ca5cad7497f..40e153f71ad 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -29,6 +29,7 @@ #define HEAP_INSERT_SKIP_FSM 0x0002 #define HEAP_INSERT_FROZEN 0x0004 #define HEAP_INSERT_SPECULATIVE 0x0008 +#define HEAP_INSERT_NO_LOGICAL 0x0010 typedef struct BulkInsertStateData *BulkInsertState;