Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit cc1965a

Browse files
committed
Add support for REFRESH MATERIALIZED VIEW CONCURRENTLY.
This allows reads to continue without any blocking while a REFRESH runs. The new data appears atomically as part of transaction commit. Review questioned the Assert that a matview was not a system relation. This will be addressed separately. Reviewed by Hitoshi Harada, Robert Haas, Andres Freund. Merged after review with security patch f3ab5d4.
1 parent 7f7485a commit cc1965a

File tree

16 files changed

+646
-59
lines changed

16 files changed

+646
-59
lines changed

doc/src/sgml/mvcc.sgml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -928,8 +928,7 @@ ERROR: could not serialize access due to read/write dependencies among transact
928928
</para>
929929

930930
<para>
931-
This lock mode is not automatically acquired on tables by any
932-
<productname>PostgreSQL</productname> command.
931+
Acquired by <command>REFRESH MATERIALIZED VIEW CONCURRENTLY</command>.
933932
</para>
934933
</listitem>
935934
</varlistentry>

doc/src/sgml/ref/refresh_materialized_view.sgml

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ PostgreSQL documentation
2121

2222
<refsynopsisdiv>
2323
<synopsis>
24-
REFRESH MATERIALIZED VIEW <replaceable class="PARAMETER">name</replaceable>
24+
REFRESH MATERIALIZED VIEW [ CONCURRENTLY ] <replaceable class="PARAMETER">name</replaceable>
2525
[ WITH [ NO ] DATA ]
2626
</synopsis>
2727
</refsynopsisdiv>
@@ -38,12 +38,44 @@ REFRESH MATERIALIZED VIEW <replaceable class="PARAMETER">name</replaceable>
3838
data is generated and the materialized view is left in an unscannable
3939
state.
4040
</para>
41+
<para>
42+
<literal>CONCURRENTLY</literal> and <literal>WITH NO DATA</literal> may not
43+
be specified together.
44+
</para>
4145
</refsect1>
4246

4347
<refsect1>
4448
<title>Parameters</title>
4549

4650
<variablelist>
51+
<varlistentry>
52+
<term><literal>CONCURRENTLY</literal></term>
53+
<listitem>
54+
<para>
55+
Refresh the materialized view without locking out concurrent selects on
56+
the materialized view. Without this option a refresh which affects a
57+
lot of rows will tend to use fewer resources and complete more quickly,
58+
but could block other connections which are trying to read from the
59+
materialized view. This option may be faster in cases where a small
60+
number of rows are affected.
61+
</para>
62+
<para>
63+
This option is only allowed if there is at least one
64+
<literal>UNIQUE</literal> index on the materialized view which uses only
65+
column names and includes all rows; that is, it must not index on any
66+
expressions nor include a <literal>WHERE</literal> clause.
67+
</para>
68+
<para>
69+
This option may not be used when the materialized view is not already
70+
populated.
71+
</para>
72+
<para>
73+
Even with this option only one <literal>REFRESH</literal> at a time may
74+
run against any one materialized view.
75+
</para>
76+
</listitem>
77+
</varlistentry>
78+
4779
<varlistentry>
4880
<term><replaceable class="PARAMETER">name</replaceable></term>
4981
<listitem>

src/backend/commands/cluster.c

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,8 @@ rebuild_relation(Relation OldHeap, Oid indexOid,
589589
heap_close(OldHeap, NoLock);
590590

591591
/* Create the transient table that will receive the re-ordered data */
592-
OIDNewHeap = make_new_heap(tableOid, tableSpace);
592+
OIDNewHeap = make_new_heap(tableOid, tableSpace, false,
593+
AccessExclusiveLock);
593594

594595
/* Copy the heap data into the new table in the desired order */
595596
copy_heap_data(OIDNewHeap, tableOid, indexOid,
@@ -616,7 +617,8 @@ rebuild_relation(Relation OldHeap, Oid indexOid,
616617
* data, then call finish_heap_swap to complete the operation.
617618
*/
618619
Oid
619-
make_new_heap(Oid OIDOldHeap, Oid NewTableSpace)
620+
make_new_heap(Oid OIDOldHeap, Oid NewTableSpace, bool forcetemp,
621+
LOCKMODE lockmode)
620622
{
621623
TupleDesc OldHeapDesc;
622624
char NewHeapName[NAMEDATALEN];
@@ -626,8 +628,10 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace)
626628
HeapTuple tuple;
627629
Datum reloptions;
628630
bool isNull;
631+
Oid namespaceid;
632+
char relpersistence;
629633

630-
OldHeap = heap_open(OIDOldHeap, AccessExclusiveLock);
634+
OldHeap = heap_open(OIDOldHeap, lockmode);
631635
OldHeapDesc = RelationGetDescr(OldHeap);
632636

633637
/*
@@ -648,6 +652,17 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace)
648652
if (isNull)
649653
reloptions = (Datum) 0;
650654

655+
if (forcetemp)
656+
{
657+
namespaceid = LookupCreationNamespace("pg_temp");
658+
relpersistence = RELPERSISTENCE_TEMP;
659+
}
660+
else
661+
{
662+
namespaceid = RelationGetNamespace(OldHeap);
663+
relpersistence = OldHeap->rd_rel->relpersistence;
664+
}
665+
651666
/*
652667
* Create the new heap, using a temporary name in the same namespace as
653668
* the existing table. NOTE: there is some risk of collision with user
@@ -663,16 +678,16 @@ make_new_heap(Oid OIDOldHeap, Oid NewTableSpace)
663678
snprintf(NewHeapName, sizeof(NewHeapName), "pg_temp_%u", OIDOldHeap);
664679

665680
OIDNewHeap = heap_create_with_catalog(NewHeapName,
666-
RelationGetNamespace(OldHeap),
681+
namespaceid,
667682
NewTableSpace,
668683
InvalidOid,
669684
InvalidOid,
670685
InvalidOid,
671686
OldHeap->rd_rel->relowner,
672687
OldHeapDesc,
673688
NIL,
674-
OldHeap->rd_rel->relkind,
675-
OldHeap->rd_rel->relpersistence,
689+
RELKIND_RELATION,
690+
relpersistence,
676691
false,
677692
RelationIsMapped(OldHeap),
678693
true,

0 commit comments

Comments
 (0)