mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +03:00
Prevent loss of init fork when truncating an unlogged table.
Fixes bug #6635, reported by Akira Kurosawa.
This commit is contained in:
@ -1290,24 +1290,10 @@ heap_create_with_catalog(const char *relname,
|
|||||||
if (oncommit != ONCOMMIT_NOOP)
|
if (oncommit != ONCOMMIT_NOOP)
|
||||||
register_on_commit_action(relid, oncommit);
|
register_on_commit_action(relid, oncommit);
|
||||||
|
|
||||||
/*
|
|
||||||
* If this is an unlogged relation, it needs an init fork so that it can
|
|
||||||
* be correctly reinitialized on restart. Since we're going to do an
|
|
||||||
* immediate sync, we only need to xlog this if archiving or streaming is
|
|
||||||
* enabled. And the immediate sync is required, because otherwise there's
|
|
||||||
* no guarantee that this will hit the disk before the next checkpoint
|
|
||||||
* moves the redo pointer.
|
|
||||||
*/
|
|
||||||
if (relpersistence == RELPERSISTENCE_UNLOGGED)
|
if (relpersistence == RELPERSISTENCE_UNLOGGED)
|
||||||
{
|
{
|
||||||
Assert(relkind == RELKIND_RELATION || relkind == RELKIND_TOASTVALUE);
|
Assert(relkind == RELKIND_RELATION || relkind == RELKIND_TOASTVALUE);
|
||||||
|
heap_create_init_fork(new_rel_desc);
|
||||||
RelationOpenSmgr(new_rel_desc);
|
|
||||||
smgrcreate(new_rel_desc->rd_smgr, INIT_FORKNUM, false);
|
|
||||||
if (XLogIsNeeded())
|
|
||||||
log_smgrcreate(&new_rel_desc->rd_smgr->smgr_rnode.node,
|
|
||||||
INIT_FORKNUM);
|
|
||||||
smgrimmedsync(new_rel_desc->rd_smgr, INIT_FORKNUM);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1320,6 +1306,22 @@ heap_create_with_catalog(const char *relname,
|
|||||||
return relid;
|
return relid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set up an init fork for an unlogged table so that it can be correctly
|
||||||
|
* reinitialized on restart. Since we're going to do an immediate sync, we
|
||||||
|
* only need to xlog this if archiving or streaming is enabled. And the
|
||||||
|
* immediate sync is required, because otherwise there's no guarantee that
|
||||||
|
* this will hit the disk before the next checkpoint moves the redo pointer.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
heap_create_init_fork(Relation rel)
|
||||||
|
{
|
||||||
|
RelationOpenSmgr(rel);
|
||||||
|
smgrcreate(rel->rd_smgr, INIT_FORKNUM, false);
|
||||||
|
if (XLogIsNeeded())
|
||||||
|
log_smgrcreate(&rel->rd_smgr->smgr_rnode.node, INIT_FORKNUM);
|
||||||
|
smgrimmedsync(rel->rd_smgr, INIT_FORKNUM);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RelationRemoveInheritance
|
* RelationRemoveInheritance
|
||||||
|
@ -1059,6 +1059,8 @@ ExecuteTruncate(TruncateStmt *stmt)
|
|||||||
* deletion at commit.
|
* deletion at commit.
|
||||||
*/
|
*/
|
||||||
RelationSetNewRelfilenode(rel, RecentXmin);
|
RelationSetNewRelfilenode(rel, RecentXmin);
|
||||||
|
if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
|
||||||
|
heap_create_init_fork(rel);
|
||||||
|
|
||||||
heap_relid = RelationGetRelid(rel);
|
heap_relid = RelationGetRelid(rel);
|
||||||
toast_relid = rel->rd_rel->reltoastrelid;
|
toast_relid = rel->rd_rel->reltoastrelid;
|
||||||
@ -1070,6 +1072,8 @@ ExecuteTruncate(TruncateStmt *stmt)
|
|||||||
{
|
{
|
||||||
rel = relation_open(toast_relid, AccessExclusiveLock);
|
rel = relation_open(toast_relid, AccessExclusiveLock);
|
||||||
RelationSetNewRelfilenode(rel, RecentXmin);
|
RelationSetNewRelfilenode(rel, RecentXmin);
|
||||||
|
if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
|
||||||
|
heap_create_init_fork(rel);
|
||||||
heap_close(rel, NoLock);
|
heap_close(rel, NoLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +65,8 @@ extern Oid heap_create_with_catalog(const char *relname,
|
|||||||
bool use_user_acl,
|
bool use_user_acl,
|
||||||
bool allow_system_table_mods);
|
bool allow_system_table_mods);
|
||||||
|
|
||||||
|
extern void heap_create_init_fork(Relation rel);
|
||||||
|
|
||||||
extern void heap_drop_with_catalog(Oid relid);
|
extern void heap_drop_with_catalog(Oid relid);
|
||||||
|
|
||||||
extern void heap_truncate(List *relids);
|
extern void heap_truncate(List *relids);
|
||||||
|
Reference in New Issue
Block a user