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

Commite4b0a02

Browse files
committed
Skip WAL for new relfilenodes, under wal_level=minimal.
Until now, only selected bulk operations (e.g. COPY) did this. If agiven relfilenode received both a WAL-skipping COPY and a WAL-loggedoperation (e.g. INSERT), recovery could lose tuples from the COPY. Seesrc/backend/access/transam/README section "Skipping WAL for NewRelFileNode" for the new coding rules. Maintainers of table accessmethods should examine that section.To maintain data durability, just before commit, we choose between anfsync of the relfilenode and copying its contents to WAL. A new GUC,wal_skip_threshold, guides that choice. If this change slows a workloadthat creates small, permanent relfilenodes under wal_level=minimal, tryadjusting wal_skip_threshold. Users setting a timeout on COMMIT mayneed to adjust that timeout, and log_min_duration_statement analysiswill reflect time consumption moving to COMMIT from commands like COPY.Internally, this requires a reliable determination of whetherRollbackAndReleaseCurrentSubTransaction() would unlink a relation'scurrent relfilenode. Introduce rd_firstRelfilenodeSubid. Amend thespecification of rd_createSubid such that the field is zero when a newrel has an old rd_node. Make relcache.c retain entries for certaindropped relations until end of transaction.Back-patch to 9.5 (all supported versions). This introduces a new WALrecord type, XLOG_GIST_ASSIGN_LSN, without bumping XLOG_PAGE_MAGIC. Asalways, update standby systems before master systems. This changessizeof(RelationData) and sizeof(IndexStmt), breaking binarycompatibility for affected extensions. (The most recent commit toaffect the same class of extensions was089e4d4.)Kyotaro Horiguchi, reviewed (in earlier, similar versions) by RobertHaas. Heikki Linnakangas and Michael Paquier implemented earlierdesigns that materially clarified the problem. Reviewed, in earlierdesigns, by Andrew Dunstan, Andres Freund, Alvaro Herrera, Tom Lane,Fujii Masao, and Simon Riggs. Reported by Martijn van Oosterhout.Discussion:https://postgr.es/m/20150702220524.GA9392@svana.org
1 parenta5abec5 commite4b0a02

File tree

51 files changed

+1447
-332
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1447
-332
lines changed

‎contrib/pg_visibility/expected/pg_visibility.out

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,40 @@
11
CREATE EXTENSION pg_visibility;
22
--
3+
-- recently-dropped table
4+
--
5+
\set VERBOSITY sqlstate
6+
BEGIN;
7+
CREATE TABLE droppedtest (c int);
8+
SELECT 'droppedtest'::regclass::oid AS oid \gset
9+
SAVEPOINT q; DROP TABLE droppedtest; RELEASE q;
10+
SAVEPOINT q; SELECT * FROM pg_visibility_map(:oid); ROLLBACK TO q;
11+
ERROR: XX000
12+
-- ERROR: could not open relation with OID 16xxx
13+
SAVEPOINT q; SELECT 1; ROLLBACK TO q;
14+
?column?
15+
----------
16+
1
17+
(1 row)
18+
19+
SAVEPOINT q; SELECT 1; ROLLBACK TO q;
20+
?column?
21+
----------
22+
1
23+
(1 row)
24+
25+
SELECT pg_relation_size(:oid), pg_relation_filepath(:oid),
26+
has_table_privilege(:oid, 'SELECT');
27+
pg_relation_size | pg_relation_filepath | has_table_privilege
28+
------------------+----------------------+---------------------
29+
| |
30+
(1 row)
31+
32+
SELECT * FROM pg_visibility_map(:oid);
33+
ERROR: XX000
34+
-- ERROR: could not open relation with OID 16xxx
35+
ROLLBACK;
36+
\set VERBOSITY default
37+
--
338
-- check that using the module's functions with unsupported relations will fail
439
--
540
-- partitioned tables (the parent ones) don't have visibility maps

‎contrib/pg_visibility/sql/pg_visibility.sql

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,24 @@
11
CREATE EXTENSION pg_visibility;
22

3+
--
4+
-- recently-dropped table
5+
--
6+
\set VERBOSITY sqlstate
7+
BEGIN;
8+
CREATETABLEdroppedtest (cint);
9+
SELECT'droppedtest'::regclass::oidASoid \gset
10+
SAVEPOINT q;DROPTABLEdroppedtest; RELEASE q;
11+
SAVEPOINT q;SELECT*FROM pg_visibility_map(:oid);ROLLBACK TO q;
12+
-- ERROR: could not open relation with OID 16xxx
13+
SAVEPOINT q;SELECT1;ROLLBACK TO q;
14+
SAVEPOINT q;SELECT1;ROLLBACK TO q;
15+
SELECT pg_relation_size(:oid), pg_relation_filepath(:oid),
16+
has_table_privilege(:oid,'SELECT');
17+
SELECT*FROM pg_visibility_map(:oid);
18+
-- ERROR: could not open relation with OID 16xxx
19+
ROLLBACK;
20+
\set VERBOSITY default
21+
322
--
423
-- check that using the module's functions with unsupported relations will fail
524
--

‎doc/src/sgml/config.sgml

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2462,16 +2462,19 @@ include_dir 'conf.d'
24622462
levels. This parameter can only be set at server start.
24632463
</para>
24642464
<para>
2465-
In <literal>minimal</literal> level, WAL-logging of some bulk
2466-
operations can be safely skipped, which can make those
2467-
operations much faster (see <xref linkend="populate-pitr"/>).
2468-
Operations in which this optimization can be applied include:
2465+
In <literal>minimal</literal> level, no information is logged for
2466+
permanent relations for the remainder of a transaction that creates or
2467+
rewrites them. This can make operations much faster (see
2468+
<xref linkend="populate-pitr"/>). Operations that initiate this
2469+
optimization include:
24692470
<simplelist>
2470-
<member><command>CREATE TABLE AS</command></member>
2471-
<member><command>CREATE INDEX</command></member>
2471+
<member><command>ALTER ... SET TABLESPACE</command></member>
24722472
<member><command>CLUSTER</command></member>
2473-
<member><command>COPY</command> into tables that were created or truncated in the same
2474-
transaction</member>
2473+
<member><command>CREATE TABLE</command></member>
2474+
<member><command>REFRESH MATERIALIZED VIEW</command>
2475+
(without <option>CONCURRENTLY</option>)</member>
2476+
<member><command>REINDEX</command></member>
2477+
<member><command>TRUNCATE</command></member>
24752478
</simplelist>
24762479
But minimal WAL does not contain enough information to reconstruct the
24772480
data from a base backup and the WAL logs, so <literal>replica</literal> or
@@ -2868,6 +2871,26 @@ include_dir 'conf.d'
28682871
</listitem>
28692872
</varlistentry>
28702873

2874+
<varlistentry id="guc-wal-skip-threshold" xreflabel="wal_skip_threshold">
2875+
<term><varname>wal_skip_threshold</varname> (<type>integer</type>)
2876+
<indexterm>
2877+
<primary><varname>wal_skip_threshold</varname> configuration parameter</primary>
2878+
</indexterm>
2879+
</term>
2880+
<listitem>
2881+
<para>
2882+
When <varname>wal_level</varname> is <literal>minimal</literal> and a
2883+
transaction commits after creating or rewriting a permanent relation,
2884+
this setting determines how to persist the new data. If the data is
2885+
smaller than this setting, write it to the WAL log; otherwise, use an
2886+
fsync of affected files. Depending on the properties of your storage,
2887+
raising or lowering this value might help if such commits are slowing
2888+
concurrent transactions. The default is two megabytes
2889+
(<literal>2MB</literal>).
2890+
</para>
2891+
</listitem>
2892+
</varlistentry>
2893+
28712894
<varlistentry id="guc-commit-delay" xreflabel="commit_delay">
28722895
<term><varname>commit_delay</varname> (<type>integer</type>)
28732896
<indexterm>

‎doc/src/sgml/perform.sgml

Lines changed: 9 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1606,8 +1606,8 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse;
16061606
needs to be written, because in case of an error, the files
16071607
containing the newly loaded data will be removed anyway.
16081608
However, this consideration only applies when
1609-
<xref linkend="guc-wal-level"/> is <literal>minimal</literal> for
1610-
non-partitioned tablesas all commands must write WAL otherwise.
1609+
<xref linkend="guc-wal-level"/> is <literal>minimal</literal>
1610+
as all commands must write WAL otherwise.
16111611
</para>
16121612

16131613
</sect2>
@@ -1707,42 +1707,13 @@ SELECT * FROM x, y, a, b, c WHERE something AND somethingelse;
17071707
</para>
17081708

17091709
<para>
1710-
Aside from avoiding the time for the archiver or WAL sender to
1711-
process the WAL data,
1712-
doing this will actually make certain commands faster, because they
1713-
are designed not to write WAL at all if <varname>wal_level</varname>
1714-
is <literal>minimal</literal>. (They can guarantee crash safety more cheaply
1715-
by doing an <function>fsync</function> at the end than by writing WAL.)
1716-
This applies to the following commands:
1717-
<itemizedlist>
1718-
<listitem>
1719-
<para>
1720-
<command>CREATE TABLE AS SELECT</command>
1721-
</para>
1722-
</listitem>
1723-
<listitem>
1724-
<para>
1725-
<command>CREATE INDEX</command> (and variants such as
1726-
<command>ALTER TABLE ADD PRIMARY KEY</command>)
1727-
</para>
1728-
</listitem>
1729-
<listitem>
1730-
<para>
1731-
<command>ALTER TABLE SET TABLESPACE</command>
1732-
</para>
1733-
</listitem>
1734-
<listitem>
1735-
<para>
1736-
<command>CLUSTER</command>
1737-
</para>
1738-
</listitem>
1739-
<listitem>
1740-
<para>
1741-
<command>COPY FROM</command>, when the target table has been
1742-
created or truncated earlier in the same transaction
1743-
</para>
1744-
</listitem>
1745-
</itemizedlist>
1710+
Aside from avoiding the time for the archiver or WAL sender to process the
1711+
WAL data, doing this will actually make certain commands faster, because
1712+
they do not to write WAL at all if <varname>wal_level</varname>
1713+
is <literal>minimal</literal> and the current subtransaction (or top-level
1714+
transaction) created or truncated the table or index they change. (They
1715+
can guarantee crash safety more cheaply by doing
1716+
an <function>fsync</function> at the end than by writing WAL.)
17461717
</para>
17471718
</sect2>
17481719

‎src/backend/access/gist/gistutil.c

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,23 +1019,44 @@ gistproperty(Oid index_oid, int attno,
10191019
}
10201020

10211021
/*
1022-
*Temporary and unlogged GiSTindexes are not WAL-logged, but we need LSNs
1023-
*to detect concurrent pagesplits anyway. This function provides a fake
1024-
*sequence of LSNs for thatpurpose.
1022+
*Someindexes are not WAL-logged, but we need LSNs to detect concurrent page
1023+
* splits anyway. This function provides a fake sequence of LSNs for that
1024+
* purpose.
10251025
*/
10261026
XLogRecPtr
10271027
gistGetFakeLSN(Relationrel)
10281028
{
1029-
staticXLogRecPtrcounter=FirstNormalUnloggedLSN;
1030-
10311029
if (rel->rd_rel->relpersistence==RELPERSISTENCE_TEMP)
10321030
{
10331031
/*
10341032
* Temporary relations are only accessible in our session, so a simple
10351033
* backend-local counter will do.
10361034
*/
1035+
staticXLogRecPtrcounter=FirstNormalUnloggedLSN;
1036+
10371037
returncounter++;
10381038
}
1039+
elseif (rel->rd_rel->relpersistence==RELPERSISTENCE_PERMANENT)
1040+
{
1041+
/*
1042+
* WAL-logging on this relation will start after commit, so its LSNs
1043+
* must be distinct numbers smaller than the LSN at the next commit.
1044+
* Emit a dummy WAL record if insert-LSN hasn't advanced after the
1045+
* last call.
1046+
*/
1047+
staticXLogRecPtrlastlsn=InvalidXLogRecPtr;
1048+
XLogRecPtrcurrlsn=GetXLogInsertRecPtr();
1049+
1050+
/* Shouldn't be called for WAL-logging relations */
1051+
Assert(!RelationNeedsWAL(rel));
1052+
1053+
/* No need for an actual record if we already have a distinct LSN */
1054+
if (!XLogRecPtrIsInvalid(lastlsn)&&lastlsn==currlsn)
1055+
currlsn=gistXLogAssignLSN();
1056+
1057+
lastlsn=currlsn;
1058+
returncurrlsn;
1059+
}
10391060
else
10401061
{
10411062
/*

‎src/backend/access/gist/gistxlog.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,9 @@ gist_redo(XLogReaderState *record)
449449
caseXLOG_GIST_PAGE_DELETE:
450450
gistRedoPageDelete(record);
451451
break;
452+
caseXLOG_GIST_ASSIGN_LSN:
453+
/* nop. See gistGetFakeLSN(). */
454+
break;
452455
default:
453456
elog(PANIC,"gist_redo: unknown op code %u",info);
454457
}
@@ -592,6 +595,24 @@ gistXLogPageDelete(Buffer buffer, FullTransactionId xid,
592595
returnrecptr;
593596
}
594597

598+
/*
599+
* Write an empty XLOG record to assign a distinct LSN.
600+
*/
601+
XLogRecPtr
602+
gistXLogAssignLSN(void)
603+
{
604+
intdummy=0;
605+
606+
/*
607+
* Records other than SWITCH_WAL must have content. We use an integer 0 to
608+
* follow the restriction.
609+
*/
610+
XLogBeginInsert();
611+
XLogSetRecordFlags(XLOG_MARK_UNIMPORTANT);
612+
XLogRegisterData((char*)&dummy,sizeof(dummy));
613+
returnXLogInsert(RM_GIST_ID,XLOG_GIST_ASSIGN_LSN);
614+
}
615+
595616
/*
596617
* Write XLOG record about reuse of a deleted page.
597618
*/

‎src/backend/access/heap/heapam.c

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
*heap_multi_insert - insert multiple tuples into a relation
2222
*heap_delete- delete a tuple from a relation
2323
*heap_update- replace a tuple in a relation with another tuple
24-
*heap_sync- sync heap, for when no WAL has been written
2524
*
2625
* NOTES
2726
* This file contains the heap_ routines which implement
@@ -1936,7 +1935,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
19361935
MarkBufferDirty(buffer);
19371936

19381937
/* XLOG stuff */
1939-
if (!(options&HEAP_INSERT_SKIP_WAL)&&RelationNeedsWAL(relation))
1938+
if (RelationNeedsWAL(relation))
19401939
{
19411940
xl_heap_insertxlrec;
19421941
xl_heap_headerxlhdr;
@@ -2119,7 +2118,7 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
21192118
/* currently not needed (thus unsupported) for heap_multi_insert() */
21202119
AssertArg(!(options&HEAP_INSERT_NO_LOGICAL));
21212120

2122-
needwal=!(options&HEAP_INSERT_SKIP_WAL)&&RelationNeedsWAL(relation);
2121+
needwal=RelationNeedsWAL(relation);
21232122
saveFreeSpace=RelationGetTargetPageFreeSpace(relation,
21242123
HEAP_DEFAULT_FILLFACTOR);
21252124

@@ -8921,18 +8920,13 @@ heap2_redo(XLogReaderState *record)
89218920
}
89228921

89238922
/*
8924-
*heap_sync- sync a heap, for use when no WAL has been written
8925-
*
8926-
* This forces the heap contents (including TOAST heap if any) down to disk.
8927-
* If we skipped using WAL, and WAL is otherwise needed, we must force the
8928-
* relation down to disk before it's safe to commit the transaction. This
8929-
* requires writing out any dirty buffers and then doing a forced fsync.
8923+
*heap_sync- for binary compatibility
89308924
*
8931-
*Indexes are not touched.(Currently, index operations associated with
8932-
*the commands that use this are WAL-logged and so do not need fsync.
8933-
*That behavior might change someday, but in any case it's likely that
8934-
*any fsync decisions required would be per-index and hence not appropriate
8935-
*to be done here.)
8925+
*A newer PostgreSQL version removes this function.It exists here just in
8926+
*case an extension calls it. See "Skipping WAL for New RelFileNode" in
8927+
*src/backend/access/transam/README for the system that superseded it,
8928+
*allowing removal of most calls. Cases like RelationCopyStorage() should
8929+
*call smgrimmedsync() directly.
89368930
*/
89378931
void
89388932
heap_sync(Relationrel)

‎src/backend/access/heap/heapam_handler.c

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -559,17 +559,6 @@ heapam_tuple_lock(Relation relation, ItemPointer tid, Snapshot snapshot,
559559
returnresult;
560560
}
561561

562-
staticvoid
563-
heapam_finish_bulk_insert(Relationrelation,intoptions)
564-
{
565-
/*
566-
* If we skipped writing WAL, then we need to sync the heap (but not
567-
* indexes since those use WAL anyway / don't go through tableam)
568-
*/
569-
if (options&HEAP_INSERT_SKIP_WAL)
570-
heap_sync(relation);
571-
}
572-
573562

574563
/* ------------------------------------------------------------------------
575564
* DDL related callbacks for heap AM.
@@ -702,7 +691,6 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
702691
IndexScanDescindexScan;
703692
TableScanDesctableScan;
704693
HeapScanDescheapScan;
705-
booluse_wal;
706694
boolis_system_catalog;
707695
Tuplesortstate*tuplesort;
708696
TupleDescoldTupDesc=RelationGetDescr(OldHeap);
@@ -717,12 +705,9 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
717705
is_system_catalog=IsSystemRelation(OldHeap);
718706

719707
/*
720-
*We need to log the copied data in WAL iff WAL archiving/streaming is
721-
*enabled AND it's a WAL-logged rel.
708+
*Valid smgr_targblock implies something already wrote to the relation.
709+
*This may be harmless, but this function hasn't planned for it.
722710
*/
723-
use_wal=XLogIsNeeded()&&RelationNeedsWAL(NewHeap);
724-
725-
/* use_wal off requires smgr_targblock be initially invalid */
726711
Assert(RelationGetTargetBlock(NewHeap)==InvalidBlockNumber);
727712

728713
/* Preallocate values/isnull arrays */
@@ -732,7 +717,7 @@ heapam_relation_copy_for_cluster(Relation OldHeap, Relation NewHeap,
732717

733718
/* Initialize the rewrite operation */
734719
rwstate=begin_heap_rewrite(OldHeap,NewHeap,OldestXmin,*xid_cutoff,
735-
*multi_cutoff,use_wal);
720+
*multi_cutoff);
736721

737722

738723
/* Set up sorting if wanted */
@@ -2626,7 +2611,6 @@ static const TableAmRoutine heapam_methods = {
26262611
.tuple_delete=heapam_tuple_delete,
26272612
.tuple_update=heapam_tuple_update,
26282613
.tuple_lock=heapam_tuple_lock,
2629-
.finish_bulk_insert=heapam_finish_bulk_insert,
26302614

26312615
.tuple_fetch_row_version=heapam_fetch_row_version,
26322616
.tuple_get_latest_tid=heap_get_latest_tid,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp