Additional Chapter for Tutorial
Our documentation explains many details about commands, tools,
parameters in detail and with high accuracy. Nevertheless my impression
is that we neglect the 'big picture': why certain processes exist and
what their relation to each other is, summary of strategies,
visualization of key situations, ... . People with mature knowledge
don't miss this information because they know all about it. But for
beginners such explanations would be a great help. In the time before
GSoD 2019 we had similar discussions.
I plan to extend over time the part 'Tutorial' by an additional chapter
with an overview about key design decisions and basic features. The
typical audience should consist of persons with limited pre-knowledge in
database systems and some interest in PostgreSQL. In the attachment you
find a patch for the first sub-chapter. Subsequent sub-chapters should
be: MVCC, transactions, VACUUM, backup, replication, ... - mostly with
the focus on the PostgreSQL implementation and not on generic topics
like b-trees.
There is a predecessor of this patch:
/messages/by-id/974e09b8-edf5-f38f-2fb5-a5875782ffc9@purtz.de
. In the meanwhile its glossary-part is separated and commited. The new
patch contains two elements: textual descriptions and 4 figures. My
opinion concerning figures is set out in detail in the previous patch.
Kind regards, Jürgen Purtz
Attachments:
0001-architecture.patchtext/x-patch; charset=UTF-8; name=0001-architecture.patchDownload
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
index ae5f3fac75..965eb751c0 100644
--- a/doc/src/sgml/advanced.sgml
+++ b/doc/src/sgml/advanced.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/advanced.sgml -->
<chapter id="tutorial-advanced">
- <title>Advanced Features</title>
+ <title>Advanced SQL Features</title>
<sect1 id="tutorial-advanced-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
new file mode 100644
index 0000000000..bbed0c3466
--- /dev/null
+++ b/doc/src/sgml/architecture.sgml
@@ -0,0 +1,449 @@
+<!-- doc/src/sgml/architecture.sgml -->
+
+ <chapter id="tutorial-architecture">
+ <title>The Architecture</title>
+
+ <para>
+ Every DBMS implements basic strategies to achieve a fast and
+ robust system. This chapter provides an overview of what
+ techniques <productname>PostgreSQL</productname> uses to
+ reach this aim.
+ </para>
+
+ <sect1 id="tutorial-ram-proc-file">
+ <title>Collabortion of Processes, RAM, and Files</title>
+ <para>
+ As is a matter of course, in a client/server architecture
+ clients do not have direct access to the database. Instead,
+ they merely send requests to the server side and receives
+ resulting information from there. In the case of
+ <productname>PostgreSQL</productname>, at the server
+ side there is one process per client, the so-called
+ <glossterm linkend="glossary-backend">Backend process</glossterm>.
+ He acts in close cooperation with the
+ <glossterm linkend="glossary-instance">Instance</glossterm> which
+ is a group of tightly coupled other server side processes plus a
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>
+ area.
+ </para>
+
+ <para>
+ At start time, an instance is initiated by the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm> process.
+ He loads the configuration files, allocates the
+ <firstterm>Shared Memory</firstterm>
+ and starts the comprehensive network of processes:
+ <glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
+ <glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
+ <glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
+ <glossterm linkend="glossary-wal-archiver">WAL Archiver</glossterm>,
+ <glossterm linkend="glossary-autovacuum">Autovacuum processes</glossterm>,
+ <glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
+ <glossterm linkend="glossary-logger">Logger</glossterm>, and more.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes
+ main aspects of their collaboration.
+ </para>
+
+ <figure id="tutorial-ram-proc-file-figure">
+ <title>Architecture</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ Whenever a client application tries to connect to a
+ <glossterm linkend="glossary-database">database</glossterm>, this request is handled
+ in a first step by the <firstterm>Postmaster
+ process</firstterm>. He checks the authorization, starts a
+ new <firstterm>Backend process</firstterm>,
+ and instructs the client application to connect to him. All further
+ client requests go to this process and are handled
+ by him.
+ </para>
+
+ <para>
+ Client requests (SELECT, UPDATE, ...) usually leads to the
+ necessity to read or write some data. In an first attempt
+ the client's <firstterm>Backend process</firstterm> tries
+ to get the information out of <firstterm>Shared
+ Memory</firstterm>. This <firstterm>Shared
+ Memory</firstterm> is a mirror of parts of the
+ <glossterm linkend="glossary-heap">heap</glossterm> and
+ <glossterm linkend="glossary-index">index</glossterm> files. Because files are
+ much huger than memory, it's likely that
+ the desired information is not (completely) available
+ in the RAM. In this case the <firstterm>Backend process
+ </firstterm> must transfer additional file pages to
+ <firstterm>Shared Memory</firstterm>. Files are physically
+ organized in pages. Every transfer between files and
+ RAM is performed in units of complete pages while retaining
+ their size and layout.
+ </para>
+
+ <para>
+ Reading file pages is notedly slower than reading
+ RAM. This is the main motivation for the existence of
+ <firstterm>Shared Memory</firstterm>. As soon as one
+ of the <firstterm>Backend processes</firstterm> has done
+ the job those pages are available for all other
+ <firstterm>Backend processes</firstterm> for direct
+ access in RAM.
+ </para>
+
+ <para>
+ <firstterm>Shared Memory</firstterm> is limited in size.
+ Sooner or later it is necessary to overwrite old RAM
+ pages. As long as the content of such pages hasn't
+ changed this is not a problem. But in
+ <firstterm>Shared Memory</firstterm> also write
+ actions take place
+ - performed by any of the <firstterm>Backend
+ processes</firstterm> (or an
+ <glossterm linkend="glossary-autovacuum">autovacuum process</glossterm>,
+ or other processes). Such modified pages are called
+ <firstterm>dirty pages</firstterm>.
+ Before <firstterm>dirty pages</firstterm> can be overwritten,
+ they must be transfered back to disk. This is a two-step process.
+ </para>
+
+ <para>
+ First, whenever the content of a page changes, a
+ <glossterm linkend="glossary-wal-record">WAL record</glossterm> is created out
+ of the delta-information (difference between old and
+ new content) and stored in another area of the
+ <firstterm>Shared Memory</firstterm>. These
+ <firstterm>WAL records</firstterm> are read by the
+ <firstterm>WAL Writer</firstterm> process,
+ who runs in parallel to the <firstterm>Backend
+ processes</firstterm> and all other processes of
+ the <firstterm>Instance</firstterm>. He writes
+ the continuously arising <firstterm>WAL records</firstterm> to
+ the end of the current
+ <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
+ Because of the sequential nature of this writing, it is much
+ faster than the more or less random access
+ to data files with <firstterm>heap</firstterm>
+ and <firstterm>index</firstterm> information.
+ As mentioned, this WAL-writing happens
+ in an independent process. Nevertheless all
+ <firstterm>WAL records</firstterm> created out of one
+ <firstterm>dirty page</firstterm> must be transfered
+ to disk before the <firstterm>dirty page</firstterm>
+ itself can be transfered to disk (???).
+ </para>
+
+ <para>
+ Second, the transfer of <firstterm>dirty pages</firstterm>
+ from <firstterm>Shared Memory</firstterm> to files must
+ take place. This is the primarily duty of the
+ <firstterm>Background Writer</firstterm> process. Because
+ huge I/O activities can block other processes significantly,
+ he starts periodically and acts only for a short period.
+ Doing so, his expensive I/O activities are spread over
+ time avoiding huge I/O peaks. Also the <firstterm>
+ Checkpointer</firstterm> process transfers
+ <firstterm>dirty pages</firstterm> to files, see next
+ paragraph.
+ </para>
+
+ <para>
+ The <firstterm>Checkpointer</firstterm> has a special
+ duty. As its name suggests, he has to create
+ <firstterm>Checkpoints</firstterm>. Such a
+ <glossterm linkend="glossary-checkpoint">Checkpoint</glossterm> is a point in time
+ when all older <firstterm>dirty pages</firstterm>,
+ all older <firstterm>WAL records</firstterm>, and
+ lastly a special <firstterm>Checkpoint record
+ </firstterm> have been written and flushed to disk.
+ In consequence, after a <firstterm>Checkpoint</firstterm>
+ data files and <firstterm>WAL files</firstterm> are in sync.
+ In case of a recovery (after a crash of the instance)
+ it is known that the information of all
+ <firstterm>WAL records</firstterm> preceding
+ the last <firstterm>Checkpoint record</firstterm>
+ is already integrated into the data files. This
+ speeds up a possibly occurring recovery.
+ </para>
+
+ <para>
+ In correlation with data changes,
+ <firstterm>WAL records</firstterm> arise and are writen
+ to <firstterm>WAL files</firstterm>.
+ Those <firstterm>WAL files</firstterm> - in combination with
+ a previously taken <firstterm>Base Backup</firstterm> -
+ are necessary to restore a database after a crash of the
+ disk, where data files have been stored. Therefore it is
+ recommended to transfer a copy of the <firstterm>
+ WAL files</firstterm>
+ to a second, independent place. The purpose of the
+ <firstterm>WAL Archiver</firstterm> process is to perform
+ this copy action.
+ </para>
+
+ <para>
+ The <glossterm linkend="glossary-stats-collector">Stats Collector</glossterm>
+ collects counter about accesses to <firstterm>SQL
+ objects</firstterm> like tables, rows, indexes, pages,
+ and others. He stores the obtained information in system
+ tables.
+ </para>
+
+ <para>
+ The <glossterm linkend="glossary-logger">Logger</glossterm> writes
+ text lines about serious and non-serious events which can happen
+ during database access, e.g.: wrong password, no permission,
+ long-running queries, ... .
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-cluster-db-schema">
+ <title>Cluster, Database, Schema</title>
+
+ <para>
+ On a <glossterm linkend="glossary-server">Server</glossterm>
+ exists one or more <glossterm linkend="glossary-cluster">Cluster</glossterm>,
+ each of them contains three or more
+ <glossterm linkend="glossary-database">databases</glossterm>, each
+ database contains many <glossterm linkend="glossary-schema">schema</glossterm>,
+ a schema contains <glossterm linkend="glossary-table">tables</glossterm>,
+ <glossterm linkend="glossary-view">views</glossterm>, and a lot of other objects.
+ Each <firstterm>table</firstterm> or <firstterm>view</firstterm>
+ belongs to a certain <firstterm>schema</firstterm>, they cannot
+ belong to another <firstterm>schema</firstterm>. The same is
+ true for the schema/database and database/cluster relation.
+ <xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
+ this hierarchy.
+ </para>
+
+ <figure id="tutorial-cluster-db-schema-figure">
+ <title>Cluster, Database, Schema</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ A <firstterm>Cluster</firstterm> is the outer frame for a
+ collection of databases. Clusters are created by the command
+ <xref linkend="app-initdb"/>.
+ </para>
+
+ <para>
+ <literal>template0</literal> is the very first
+ <firstterm>database</firstterm> of any
+ <firstterm>cluster</firstterm>. C-routines create
+ <literal>template0</literal> during the initialization phase of
+ the <firstterm>cluster</firstterm>.
+ In a second step <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal> and finally
+ <literal>postgres</literal> as a copy of
+ <literal>template1</literal>. All other
+ <glossterm linkend="app-createdb">new databases</glossterm>
+ of this <firstterm>cluster</firstterm>,
+ such as <literal>my_db</literal>, are also copied from
+ <literal>template1</literal>. Due to the special
+ role of <literal>template0</literal> as the origin
+ of all other <firstterm>databases</firstterm>, no client
+ can connect to it.
+ </para>
+
+ <para>
+ Every database contains <glossterm linkend="glossary-schema">
+ schemas</glossterm>, and
+ <firstterm>schemas</firstterm> contain the other
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>.
+ <firstterm>Schemas</firstterm> are namespaces for
+ their <firstterm>SQL objects</firstterm> and ensure - with one
+ exception - that within their scope names are used only once across all
+ types of <firstterm>SQL objects</firstterm>. E.g.: it is not possible
+ to have a table <literal>employee</literal> and a view
+ <literal>employee</literal> within the same
+ <firstterm>schema</firstterm>. But it is possible to have
+ two tables <literal>employee</literal> in different
+ <firstterm>schemas</firstterm>. In this case the two tables
+ are different objects and absolutely independent from each
+ other. The only exception to this cross-type uniqueness is that
+ <glossterm linkend="glossary-unique-constraint">unique constraints
+ </glossterm> and the according <firstterm>unique index</firstterm>
+ use the same name.
+ </para>
+
+ <para>
+ Some <firstterm>schemas</firstterm> are predefined.
+ <literal>public</literal> acts as the default
+ <firstterm>schema</firstterm> and contains all such
+ <firstterm>SQL objects</firstterm>, which are created
+ within <literal>public</literal> or without using any schema
+ name. <literal>public</literal> shall not contain user defined
+ <firstterm>SQL objects</firstterm>. Instead, it is recommended to
+ create a separate <firstterm>schema</firstterm> which
+ holds individual objects like application-specific tables or
+ views. <literal>pg_catalog</literal> is a schema for all tables
+ and views of the <glossterm linkend="glossary-system-catalog">
+ System Catalog</glossterm>.
+ <literal>information_schema</literal> is a schema for several
+ tables and views of the <firstterm>System Catalog</firstterm>
+ in a way which conforms to the SQL standard.
+ </para>
+
+ <para>
+ There are a lot of different <firstterm>SQL object</firstterm>
+ types: <firstterm>database, schema, table, view, materialized
+ view, index, constraint, sequence, function, procedure,
+ trigger, role, data type, operator, tablespace, extension,
+ foreign data wrapper</firstterm>, and more. A few of them, the
+ <glossterm linkend="glossary-global-sql-object">Global SQL Objects</glossterm>,
+ are outside of the strict hierarchy:
+ All database names, all tablespace names, and all role names
+ are automatically known and available throughout the
+ complete <firstterm>cluster</firstterm>, independent from
+ the database or schema in which they where originally
+ defined. <xref linkend="tutorial-internal-objects-hierarchy-figure"/>
+ shows the relation between the object types.
+ </para>
+
+ <figure id="tutorial-internal-objects-hierarchy-figure">
+ <title>Hierarchy of Internal Objects</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="720px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect1>
+
+ <sect1 id="tutorial-directories">
+ <title>Directory Structure</title>
+
+ <para>
+ <productname>PostgreSQL</productname> organizes long lasting
+ data as well as volatile state information about transactions
+ or replication actions in the file system. Every
+ <firstterm>Cluster</firstterm> has its own root directory
+ anywhere in the file system. In many cases, the environment
+ variable <literal>PGDATA</literal> points to this directory.
+ The example of the following survey, which is shown in
+ <xref linkend="tutorial-directories-figure"/>, uses
+ <literal>data</literal> as the name of this root directory.
+ </para>
+
+ <figure id="tutorial-directories-figure">
+ <title>Directory Structure</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ <literal>data</literal> contains many subdirectories and
+ some files, all of which are necessary to store long lasting
+ as well as temporary data. The following paragraphs
+ describe the files and subdirectories in
+ <literal>data</literal>.
+ </para>
+
+ <para>
+ <literal>base</literal> is a subdirectory in which one
+ subdirectory per <firstterm>database</firstterm> exists.
+ The names of those sudirectories consists of numbers.
+ These are the internal
+ <firstterm>Object Identifiers (OID)</firstterm>, which are
+ numbers to identify the database definition in the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ </para>
+
+ <para>
+ Within the <firstterm>database</firstterm>-specific
+ subdirectories there are many files. Primarily they contain
+ the <firstterm>heap</firstterm> and <firstterm>
+ index</firstterm>. But there are also optimization information
+ like <link linkend="storage-fsm">Free Space Maps</link> or
+ <link linkend="storage-vm">Visibility Maps</link>.
+ </para>
+
+ <para>
+ Another important subdirectory is <literal>global</literal>.
+ In analogy to the <firstterm>database</firstterm>-specific
+ subdirectories, there are files containing information about
+ <glossterm linkend="glossary-global-sql-object">Global SQL objects</glossterm>.
+ One type
+ of such <firstterm>Global Objects</firstterm> are
+ <firstterm>tablespaces</firstterm>. In
+ <literal>global</literal> there are information about
+ the <firstterm>tablespaces</firstterm>, not the
+ <firstterm>tablespaces</firstterm> itself.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_wal</literal> contains the
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
+ They arise and grow parallel to data changes in the
+ <firstterm>cluster</firstterm> and remain alive as long as
+ they are required for recovery, archiving, or replication.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_xact</literal> contains
+ information about the status of each transaction
+ (IN_PROGRESS, COMMITTED, ABORTED, or SUB_COMMITTED).
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal> there are symbolic links
+ that point to directories containing such<firstterm>
+ SQL objects</firstterm> that are created within
+ <firstterm>tablespaces</firstterm>.
+ </para>
+
+ <para>
+ In the directory <literal>data</literal>
+ there are also some files.
+ In many cases, the configuration
+ files of this <firstterm>cluster</firstterm>
+ are stored here. As long as the <firstterm>
+ cluster</firstterm> is up and running, the file
+ <literal>postmaster.pid</literal> exists here
+ and contains the ID of the
+ <firstterm>Postmaster</firstterm> process.
+ </para>
+
+ </sect1>
+
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 68179f71cd..ca29c8bc4e 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -8,9 +8,10 @@
<!ENTITY problems SYSTEM "problems.sgml">
<!-- tutorial -->
-<!ENTITY advanced SYSTEM "advanced.sgml">
-<!ENTITY query SYSTEM "query.sgml">
-<!ENTITY start SYSTEM "start.sgml">
+<!ENTITY start SYSTEM "start.sgml">
+<!ENTITY architecture SYSTEM "architecture.sgml">
+<!ENTITY query SYSTEM "query.sgml">
+<!ENTITY advanced SYSTEM "advanced.sgml">
<!-- user's guide -->
<!ENTITY array SYSTEM "array.sgml">
diff --git a/doc/src/sgml/glossary.sgml b/doc/src/sgml/glossary.sgml
index 8c6cb6e942..25762b7c3a 100644
--- a/doc/src/sgml/glossary.sgml
+++ b/doc/src/sgml/glossary.sgml
@@ -208,15 +208,6 @@
</glossdef>
</glossentry>
- <glossentry id="glossary-checkpointer">
- <glossterm>Checkpointer (process)</glossterm>
- <glossdef>
- <para>
- A specialized process responsible for executing checkpoints.
- </para>
- </glossdef>
- </glossentry>
-
<glossentry id="glossary-checkpoint">
<glossterm>Checkpoint</glossterm>
<glossdef>
@@ -244,6 +235,15 @@
</glossdef>
</glossentry>
+ <glossentry id="glossary-checkpointer">
+ <glossterm>Checkpointer (process)</glossterm>
+ <glossdef>
+ <para>
+ A specialized process responsible for executing checkpoints.
+ </para>
+ </glossdef>
+ </glossentry>
+
<glossentry>
<glossterm>Class (archaic)</glossterm>
<glosssee otherterm="glossary-relation" />
@@ -761,25 +761,6 @@
</glossdef>
</glossentry>
- <glossentry id="glossary-logger">
- <glossterm>Logger (process)</glossterm>
- <glossdef>
- <para>
- If activated, the
- <glossterm linkend="glossary-logger">Logger</glossterm> process
- writes information about database events into the current
- <glossterm linkend="glossary-log-file">log file</glossterm>.
- When reaching certain time- or
- volume-dependent criteria, a new log file is created.
- Also called <firstterm>syslogger</firstterm>.
- </para>
- <para>
- For more information, see
- <xref linkend="runtime-config-logging"/>.
- </para>
- </glossdef>
- </glossentry>
-
<glossentry id="glossary-log-record">
<glossterm>Log Record</glossterm>
<glossdef>
@@ -803,6 +784,25 @@
</glossdef>
</glossentry>
+ <glossentry id="glossary-logger">
+ <glossterm>Logger (process)</glossterm>
+ <glossdef>
+ <para>
+ If activated, the
+ <glossterm linkend="glossary-logger">Logger</glossterm> process
+ writes information about database events into the current
+ <glossterm linkend="glossary-log-file">log file</glossterm>.
+ When reaching certain time- or
+ volume-dependent criteria, a new log file is created.
+ Also called <firstterm>syslogger</firstterm>.
+ </para>
+ <para>
+ For more information, see
+ <xref linkend="runtime-config-logging"/>.
+ </para>
+ </glossdef>
+ </glossentry>
+
<glossentry>
<glossterm>Master (server)</glossterm>
<glosssee otherterm="glossary-primary-server" />
@@ -1651,6 +1651,11 @@
</glossdef>
</glossentry>
+ <glossentry>
+ <glossterm>WAL</glossterm>
+ <glosssee otherterm="glossary-wal" />
+ </glossentry>
+
<glossentry id="glossary-wal-archiver">
<glossterm>WAL Archiver (process)</glossterm>
<glossdef>
@@ -1696,11 +1701,6 @@
</glossdef>
</glossentry>
- <glossentry>
- <glossterm>WAL</glossterm>
- <glosssee otherterm="glossary-wal" />
- </glossentry>
-
<glossentry id="glossary-wal-record">
<glossterm>WAL Record</glossterm>
<glossdef>
@@ -1728,8 +1728,8 @@
<glossdef>
<para>
A process that writes <glossterm linkend="glossary-wal-record">WAL records</glossterm>
- from <glossterm id="linkend-shared-memory">shared memory</glossterm> to
- <glossterm id="linkend-wal-file">WAL files</glossterm>.
+ from <glossterm linkend="glossary-shared-memory">shared memory</glossterm> to
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
</para>
<para>
For more information, see
diff --git a/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
new file mode 100644
index 0000000000..6acb2b69fe
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
@@ -0,0 +1,160 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="685" viewBox="0 0 900 685">
+ <title>
+ Server (Hardware, Container, or VM)
+ </title>
+ <style>
+ .text_normal,.text_small{font-style:normal;font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_small{font-size:12px}.text_normal{font-size:16px}
+ </style>
+ <defs>
+ <symbol id="rectangles_special_0">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="rectangles_special_1">
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="125">
+ 'my_schema' (optional)
+ </text>
+ <text class="text_small" x="20" y="145">
+ tables, views, ...
+ </text>
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="190">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M450 10v230H0V0h440v10h10L440 0"/>
+ </symbol>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="270" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Server (Hardware, Container, or VM)
+ </text>
+ <path stroke="blue" stroke-width="2" fill="none" d="M20 110h790v555H20z"/>
+ <text class="text_normal" x="180" y="25" transform="translate(20 110)">
+ cluster 'data' (default, managed by one instance)
+ </text>
+ <path d="M50 110V80h790v555h-30" stroke="blue" stroke-width="2" fill="none"/>
+ <text class="text_normal" x="190" y="-10" transform="translate(45 110)">
+ cluster 'cluster_2' (optional, managed by a different instance)
+ </text>
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangles_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template0'
+ </text>
+ </g>
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangles_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template1'
+ </text>
+ </g>
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangles_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangles_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'my_db' (optional)
+ </text>
+ </g>
+ <g transform="translate(320 330)">
+ <rect width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4"/>
+ <text class="text_normal" x="15" y="27">
+ Global SQL objects
+ </text>
+ <path d="M0 5l-65-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M80 0v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M180 40h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M0 40l-45 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ </g>
+ <g transform="translate(335 405)">
+ <use xlink:href="#note"/>
+ <text class="text_small" x="10" y="20">
+ 1)
+ </text>
+ <text class="text_small" x="30" y="20">
+ By default, you work in the cluster 'data', database 'postgres',
+ </text>
+ <text class="text_small" x="30" y="35">
+ schema 'public'.
+ </text>
+ <text class="text_small" x="10" y="55">
+ 2)
+ </text>
+ <text class="text_small" x="30" y="55">
+ More system schemas: pg_catalog, information_schema,
+ </text>
+ <text class="text_small" x="30" y="70">
+ pg_temp, pg_toast.
+ </text>
+ <text class="text_small" x="10" y="90">
+ 3)
+ </text>
+ <text class="text_small" x="30" y="90">
+ Global SQL objects: Some SQL objects are automatically active
+ </text>
+ <text class="text_small" x="30" y="105">
+ and known database- or even cluster-wide.
+ </text>
+ <text class="text_small" x="10" y="125">
+ 4)
+ </text>
+ <text class="text_small" x="30" y="125">
+ The command 'initdb' creates a new cluster with the three
+ </text>
+ <text class="text_small" x="30" y="140">
+ databases 'template0', 'template1', and 'postgres'. The command
+ </text>
+ <text class="text_small" x="30" y="155">
+ 'createdb' creates a new database.
+ </text>
+ <text class="text_small" x="10" y="175">
+ 5)
+ </text>
+ <text class="text_small" x="30" y="175">
+ If multiple clusters are active on one server at the same time,
+ </text>
+ <text class="text_small" x="30" y="190">
+ each one is managed by an individual instance. Each such instance
+ </text>
+ <text class="text_small" x="30" y="205">
+ uses a different port.
+ </text>
+ <text class="text_small" x="10" y="225">
+ 6)
+ </text>
+ <text class="text_small" x="30" y="225">
+ No client application is allowed to connect to 'template0'.
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink.svg b/doc/src/sgml/images/cluster-db-schema-ink.svg
new file mode 100644
index 0000000000..a70fbe2102
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink.svg
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="685px"
+ viewBox="0 0 900 685"
+ id="svg147"
+ sodipodi:docname="cluster-db-schema-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Server (Hardware, Container, or VM)</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.34452555"
+ inkscape:cx="450"
+ inkscape:cy="342.5"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Server (Hardware, Container, or VM)</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs49">
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangles_special_0">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect6" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="195"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect8" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text10">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text12">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="195"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect14" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text16">(more system schemas)</text>
+ </symbol>
+ <!-- same as before, but one more schema -->
+ <symbol
+ id="rectangles_special_1">
+ <!-- the database -->
+ <rect
+ width="245"
+ height="225"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect19" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect21" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text23">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text25">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect27" />
+ <text
+ class="text_normal"
+ x="20"
+ y="125"
+ id="text29">'my_schema' (optional)</text>
+ <text
+ class="text_small"
+ x="20"
+ y="145"
+ id="text31">tables, views, ...</text>
+ <rect
+ x="15"
+ y="170"
+ width="205"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect33" />
+ <text
+ class="text_small"
+ x="20"
+ y="190"
+ id="text35">(more system schemas)</text>
+ </symbol>
+ <symbol
+ id="note"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title38">UML Note</title>
+ <path
+ d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10"
+ id="path40" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path43" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path46" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect51" />
+ <text
+ class="text_big"
+ x="270"
+ y="40"
+ id="text53">Server (Hardware, Container, or VM)</text>
+ <!-- two clusters -->
+ <g
+ transform="translate(20 110)"
+ id="g59">
+ <rect
+ x="0"
+ y="0"
+ width="790"
+ height="555"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="rect55" />
+ <text
+ class="text_normal"
+ x="180"
+ y="25"
+ id="text57">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g
+ transform="translate(45 110)"
+ id="g65">
+ <path
+ d="M 5,0 v -30 h 790 v 555 h -30"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="path61" />
+ <text
+ class="text_normal"
+ x="190"
+ y="-10"
+ id="text63">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+ <!-- database template 0 -->
+ <g
+ transform="translate(40 155)"
+ id="g71">
+ <use
+ xlink:href="#rectangles_special_0"
+ id="use67" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text69">database 'template0'</text>
+ </g>
+ <!-- database template 1 -->
+ <g
+ transform="translate(290 155)"
+ id="g77">
+ <use
+ xlink:href="#rectangles_special_0"
+ id="use73" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text75">database 'template1'</text>
+ </g>
+ <!-- database postgres -->
+ <g
+ transform="translate(540 155)"
+ id="g83">
+ <use
+ xlink:href="#rectangles_special_1"
+ id="use79" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text81">database 'postgres'</text>
+ </g>
+ <!-- database my_db -->
+ <g
+ transform="translate(40 350)"
+ id="g89">
+ <use
+ xlink:href="#rectangles_special_1"
+ id="use85" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text87">database 'my_db' (optional)</text>
+ </g>
+ <!-- global objects -->
+ <g
+ transform="translate(320 330)"
+ id="g103">
+ <rect
+ x="0"
+ y="0"
+ width="180"
+ height="45"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="10 4 4 4"
+ id="rect91" />
+ <text
+ class="text_normal"
+ x="15"
+ y="27"
+ id="text93">Global SQL objects</text>
+ <path
+ d="M 0,5 l-65,-35"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path95" />
+ <path
+ d="M 80,0 v-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path97" />
+ <path
+ d="M 180,40 h50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path99" />
+ <path
+ d="M 0,40 l-45,20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path101" />
+ </g>
+ <!-- Some comments -->
+ <g
+ transform="translate(335 405)"
+ id="g145">
+ <use
+ xlink:href="#note"
+ x="0"
+ y="0"
+ id="use105" />
+ <text
+ class="text_small"
+ x="10"
+ y="20"
+ id="text107">1)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="20"
+ id="text109">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text
+ class="text_small"
+ x="30"
+ y="35"
+ id="text111">schema 'public'.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="55"
+ id="text113">2)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="55"
+ id="text115">More system schemas: pg_catalog, information_schema,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="70"
+ id="text117">pg_temp, pg_toast.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="90"
+ id="text119">3)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="90"
+ id="text121">Global SQL objects: Some SQL objects are automatically active</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text123">and known database- or even cluster-wide.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="125"
+ id="text125">4)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="125"
+ id="text127">The command 'initdb' creates a new cluster with the three</text>
+ <text
+ class="text_small"
+ x="30"
+ y="140"
+ id="text129">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text
+ class="text_small"
+ x="30"
+ y="155"
+ id="text131">'createdb' creates a new database.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="175"
+ id="text133">5)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="175"
+ id="text135">If multiple clusters are active on one server at the same time,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="190"
+ id="text137">each one is managed by an individual instance. Each such instance</text>
+ <text
+ class="text_small"
+ x="30"
+ y="205"
+ id="text139">uses a different port.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="225"
+ id="text141">6)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="225"
+ id="text143">No client application is allowed to connect to 'template0'.</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
new file mode 100644
index 0000000000..a4919165e2
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="685px"
+ viewBox="0 0 900 685" >
+
+ <title>Server (Hardware, Container, or VM)</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangles_special_0">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">(more system schemas)</text>
+ </symbol>
+
+ <!-- same as before, but one more schema -->
+ <symbol id="rectangles_special_1">
+ <!-- the database -->
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="125">'my_schema' (optional)</text>
+ <text class="text_small" x="20" y="145">tables, views, ...</text>
+
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="190">(more system schemas)</text>
+ </symbol>
+
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="270" y="40">Server (Hardware, Container, or VM)</text>
+
+ <!-- two clusters -->
+ <g transform="translate(20 110)">
+ <rect x="0" y="0" width="790" height="555" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="180" y="25">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g transform="translate(45 110)">
+ <path d="M 5,0 v -30 h 790 v 555 h -30" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="190" y="-10">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+
+
+ <!-- database template 0 -->
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangles_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template0'</text>
+ </g>
+
+ <!-- database template 1 -->
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangles_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template1'</text>
+ </g>
+
+ <!-- database postgres -->
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangles_special_1" />
+ <text class="text_normal" x="10" y="25">database 'postgres'</text>
+ </g>
+
+ <!-- database my_db -->
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangles_special_1" />
+ <text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
+ </g>
+
+ <!-- global objects -->
+ <g transform="translate(320 330)">
+ <rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
+ <text class="text_normal" x="15" y="27">Global SQL objects</text>
+ <path d="M 0,5 l-65,-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ </g>
+
+ <!-- Some comments -->
+ <g transform="translate(335 405)">
+ <use xlink:href="#note" x="0" y="0" />
+
+ <text class="text_small" x="10" y="20">1)</text>
+ <text class="text_small" x="30" y="20">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text class="text_small" x="30" y="35">schema 'public'.</text>
+
+ <text class="text_small" x="10" y="55">2)</text>
+ <text class="text_small" x="30" y="55">More system schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="70">pg_temp, pg_toast.</text>
+
+ <text class="text_small" x="10" y="90">3)</text>
+ <text class="text_small" x="30" y="90">Global SQL objects: Some SQL objects are automatically active</text>
+ <text class="text_small" x="30" y="105">and known database- or even cluster-wide.</text>
+
+ <text class="text_small" x="10" y="125">4)</text>
+ <text class="text_small" x="30" y="125">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="140">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="155">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="175">5)</text>
+ <text class="text_small" x="30" y="175">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="190">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="205">uses a different port.</text>
+
+ <text class="text_small" x="10" y="225">6)</text>
+ <text class="text_small" x="30" y="225">No client application is allowed to connect to 'template0'.</text>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/directories-ink-svgo.svg b/doc/src/sgml/images/directories-ink-svgo.svg
new file mode 100644
index 0000000000..95fa76b9c6
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink-svgo.svg
@@ -0,0 +1,164 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="640" viewBox="0 0 900 640">
+ <title>
+ Directory structure of a cluster
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <symbol id="directory" stroke="blue" stroke-width=".3" fill="aqua">
+ <title>
+ Directory
+ </title>
+ <path d="M0 10h110v20H0z"/>
+ <path d="M0 10V8l3-3h35l3 3v2"/>
+ </symbol>
+ <symbol id="file" stroke="black" fill="none">
+ <title>
+ File
+ </title>
+ <path stroke="blue" d="M0 0h40v50H0z"/>
+ <path d="M5 10h20" stroke-dasharray="4 2"/>
+ <path d="M5 17h15" stroke-dasharray="6 2"/>
+ <path d="M5 24h25" stroke-dasharray="4 2"/>
+ <path d="M5 31h20" stroke-dasharray="5 2"/>
+ </symbol>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="50" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Directory Structure
+ </text>
+ <g transform="translate(20 100)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /pg/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ An arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 130)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ data/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of cluster 'data' (see: PGDATA)
+ </text>
+ </g>
+ <g transform="translate(120 160)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ base/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing per-database subdirectories
+ </text>
+ </g>
+ <g transform="translate(170 190)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 1/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of first database 'template0'
+ </text>
+ </g>
+ <g transform="translate(170 220)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12992/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of second database 'template1'
+ </text>
+ </g>
+ <g transform="translate(170 250)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12999/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of third database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(170 280)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ nnnnn/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Optional: more subdirectories for databases, e.g. 'my_db'
+ </text>
+ </g>
+ <g transform="translate(120 310)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ global/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory with information about Global SQL Objects
+ </text>
+ </g>
+ <g transform="translate(120 340)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_wal/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 370)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_xact/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for transaction commit status ('pg_clog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 400)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_tblspc/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing symbolic links to tablespaces
+ </text>
+ </g>
+ <g transform="translate(120 430)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_... /
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Some more subdirectories
+ </text>
+ </g>
+ <g transform="translate(120 465)">
+ <use xlink:href="#file"/>
+ <use xlink:href="#file" x="50"/>
+ <text x="200" y="26" class="text_normal">
+ 'postmaster.pid' and other files with cluster-wide relevance
+ </text>
+ </g>
+ <g transform="translate(20 540)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /xyz/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ Same or another arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 570)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ cluster_2/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of another cluster 'cluster_2'
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-ink.svg b/doc/src/sgml/images/directories-ink.svg
new file mode 100644
index 0000000000..4661ef13fb
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink.svg
@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="640px"
+ viewBox="0 0 900 640"
+ id="svg303"
+ sodipodi:docname="directories-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata307">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Directory structure of a cluster</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview305"
+ showgrid="false"
+ inkscape:zoom="0.36875"
+ inkscape:cx="450"
+ inkscape:cy="320"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg303" />
+ <title
+ id="title153">Directory structure of a cluster</title>
+ <style
+ type="text/css"
+ id="style155">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs177">
+ <!-- Directory -->
+ <symbol
+ id="directory"
+ stroke="blue"
+ stroke-width="0.3px"
+ fill="aqua">
+ <title
+ id="title157">Directory</title>
+ <rect
+ x="0"
+ y="10"
+ width="110"
+ height="20"
+ id="rect159" />
+ <path
+ d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2"
+ id="path161" />
+ </symbol>
+ <!-- File -->
+ <symbol
+ id="file"
+ stroke="black"
+ fill="none">
+ <title
+ id="title164">File</title>
+ <rect
+ x="0"
+ y="0"
+ width="40"
+ height="50"
+ stroke="blue"
+ id="rect166" />
+ <path
+ d="M 5,10 h 20"
+ stroke-dasharray="4 2"
+ id="path168" />
+ <path
+ d="M 5,17 h 15"
+ stroke-dasharray="6 2"
+ id="path170" />
+ <path
+ d="M 5,24 h 25"
+ stroke-dasharray="4 2"
+ id="path172" />
+ <path
+ d="M 5,31 h 20"
+ stroke-dasharray="5 2"
+ id="path174" />
+ </symbol>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect179" />
+ <!-- caption -->
+ <text
+ x="200"
+ y="50"
+ class="text_big"
+ id="text181">Directory Structure</text>
+ <!-- the directories -->
+ <g
+ transform="translate(20, 100)"
+ id="g189">
+ <use
+ xlink:href="#directory"
+ id="use183" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text185">... /pg/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text187">An arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 130)"
+ id="g197">
+ <use
+ xlink:href="#directory"
+ id="use191" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text193">data/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text195">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+ <g
+ transform="translate(120, 160)"
+ id="g205">
+ <use
+ xlink:href="#directory"
+ id="use199" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text201">base/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text203">Subdirectory containing per-database subdirectories</text>
+ </g>
+ <!-- -->
+ <g
+ transform="translate(170, 190)"
+ id="g213">
+ <use
+ xlink:href="#directory"
+ id="use207" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text209">1/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text211">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g
+ transform="translate(170, 220)"
+ id="g221">
+ <use
+ xlink:href="#directory"
+ id="use215" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text217">12992/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text219">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g
+ transform="translate(170, 250)"
+ id="g229">
+ <use
+ xlink:href="#directory"
+ id="use223" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text225">12999/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text227">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g
+ transform="translate(170, 280)"
+ id="g237">
+ <use
+ xlink:href="#directory"
+ id="use231" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text233">nnnnn/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text235">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+ <g
+ transform="translate(120, 310)"
+ id="g245">
+ <use
+ xlink:href="#directory"
+ id="use239" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text241">global/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text243">Subdirectory with information about Global SQL Objects</text>
+ </g>
+ <g
+ transform="translate(120, 340)"
+ id="g253">
+ <use
+ xlink:href="#directory"
+ id="use247" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text249">pg_wal/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text251">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 370)"
+ id="g261">
+ <use
+ xlink:href="#directory"
+ id="use255" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text257">pg_xact/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text259">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 400)"
+ id="g269">
+ <use
+ xlink:href="#directory"
+ id="use263" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text265">pg_tblspc/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text267">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+ <g
+ transform="translate(120, 430)"
+ id="g277">
+ <use
+ xlink:href="#directory"
+ id="use271" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text273">pg_... /</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text275">Some more subdirectories</text>
+ </g>
+ <g
+ transform="translate(120, 465)"
+ id="g285">
+ <use
+ xlink:href="#file"
+ x="0"
+ y="0"
+ id="use279" />
+ <use
+ xlink:href="#file"
+ x="50"
+ y="0"
+ id="use281" />
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text283">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+ <!-- next cluster -->
+ <g
+ transform="translate(20, 540)"
+ id="g293">
+ <use
+ xlink:href="#directory"
+ id="use287" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text289">... /xyz/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text291">Same or another arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 570)"
+ id="g301">
+ <use
+ xlink:href="#directory"
+ id="use295" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text297">cluster_2/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text299">Root of another cluster 'cluster_2'</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
new file mode 100644
index 0000000000..8869eb9390
--- /dev/null
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="640px"
+ viewBox="0 0 900 640">
+
+ <title>Directory structure of a cluster</title>
+
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Directory -->
+ <symbol id="directory" stroke="blue" stroke-width="0.3px" fill="aqua">
+ <title>Directory</title>
+ <rect x="0" y="10" width="110" height="20" />
+ <path d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2" />
+ </symbol>
+
+ <!-- File -->
+ <symbol id="file" stroke="black" fill="none" >
+ <title>File</title>
+ <rect x="0" y="0" width="40" height="50" stroke="blue" />
+ <path d="M 5,10 h 20" stroke-dasharray="4 2" />
+ <path d="M 5,17 h 15" stroke-dasharray="6 2" />
+ <path d="M 5,24 h 25" stroke-dasharray="4 2" />
+ <path d="M 5,31 h 20" stroke-dasharray="5 2" />
+ </symbol>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption -->
+ <text x="200" y="50" class="text_big">Directory Structure</text>
+
+ <!-- the directories -->
+ <g transform="translate(20, 100)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /pg/</text>
+ <text x="300" y="26" class="text_normal">An arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 130)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">data/</text>
+ <text x="250" y="26" class="text_normal">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+
+ <g transform="translate(120, 160)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">base/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing per-database subdirectories</text>
+ </g>
+
+ <!-- -->
+ <g transform="translate(170, 190)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">1/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g transform="translate(170, 220)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12992/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g transform="translate(170, 250)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12999/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g transform="translate(170, 280)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">nnnnn/</text>
+ <text x="150" y="26" class="text_normal">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+
+ <g transform="translate(120, 310)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">global/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory with information about Global SQL Objects</text>
+ </g>
+
+ <g transform="translate(120, 340)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 370)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 400)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+
+ <g transform="translate(120, 430)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_... /</text>
+ <text x="200" y="26" class="text_normal">Some more subdirectories</text>
+ </g>
+
+ <g transform="translate(120, 465)">
+ <use xlink:href="#file" x="0" y="0" />
+ <use xlink:href="#file" x="50" y="0" />
+ <text x="200" y="26" class="text_normal">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+
+ <!-- next cluster -->
+ <g transform="translate(20, 540)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /xyz/</text>
+ <text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 570)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster 'cluster_2'</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
new file mode 100644
index 0000000000..4156bbc834
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
@@ -0,0 +1,83 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="720" height="430" viewBox="0 0 720 430">
+ <title>
+ Hierarchy of Internal Objects
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Hierarchy of Internal Objects
+ </text>
+ <g fill="none">
+ <g transform="translate(350 240)">
+ <ellipse rx="320" ry="170" stroke="blue"/>
+ <text class="text_normal" x="-140" y="-130">
+ Cluster
+ </text>
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-60" y="5">
+ Database Names
+ </text>
+ </g>
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-40" y="5">
+ Tablespace
+ </text>
+ </g>
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-70" y="5">
+ Replication Origins
+ </text>
+ </g>
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue"/>
+ <text class="text_normal" x="-60" y="-3">
+ Subscription for
+ </text>
+ <text class="text_normal" x="-68" y="10">
+ Logical Replication
+ </text>
+ </g>
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-15" y="5">
+ Role
+ </text>
+ </g>
+ </g>
+ <g transform="translate(270 250)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2"/>
+ <text class="text_normal" x="-60" y="-80">
+ Database
+ </text>
+ <g transform="translate(-150 -30)">
+ <ellipse rx="50" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Extension
+ </text>
+ </g>
+ <g transform="translate(-155 35)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Collation
+ </text>
+ </g>
+ <g transform="translate(30 20)">
+ <ellipse rx="140" ry="70" stroke="blue"/>
+ <text class="text_normal" x="-80" y="-35">
+ Schema
+ </text>
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue"/>
+ <text class="text_normal" x="-50" y="5">
+ Table, View, ...
+ </text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
new file mode 100644
index 0000000000..cf03d6a701
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="720px"
+ height="430px"
+ viewBox="0 0 720 430"
+ id="svg389"
+ sodipodi:docname="internal-objects-hierarchy-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata395">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Hierarchy of Internal Objects</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs393" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="906"
+ inkscape:window-height="678"
+ id="namedview391"
+ showgrid="false"
+ inkscape:zoom="0.51944444"
+ inkscape:cx="360"
+ inkscape:cy="215"
+ inkscape:window-x="502"
+ inkscape:window-y="91"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg389" />
+ <title
+ id="title309">Hierarchy of Internal Objects</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style311">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect313" />
+ <text
+ class="text_big"
+ x="200"
+ y="40"
+ id="text315">Hierarchy of Internal Objects</text>
+ <!-- set centre of figure and default values -->
+ <g
+ transform="translate(350 240)"
+ fill="none"
+ id="g387">
+ <g
+ id="g353">
+ <ellipse
+ rx="320"
+ ry="170"
+ stroke="blue"
+ id="ellipse317" />
+ <text
+ class="text_normal"
+ x="-140"
+ y="-130"
+ id="text319">Cluster</text>
+ <g
+ transform="translate(40 -125)"
+ id="g325">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse321" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="5"
+ id="text323">Database Names</text>
+ </g>
+ <g
+ transform="translate(180 -70)"
+ id="g331">
+ <ellipse
+ rx="60"
+ ry="20"
+ stroke="blue"
+ id="ellipse327" />
+ <text
+ class="text_normal"
+ x="-40"
+ y="5"
+ id="text329">Tablespace</text>
+ </g>
+ <g
+ transform="translate(230 -5)"
+ id="g337">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse333" />
+ <text
+ class="text_normal"
+ x="-70"
+ y="5"
+ id="text335">Replication Origins</text>
+ </g>
+ <g
+ transform="translate(200 70)"
+ id="g345">
+ <ellipse
+ rx="78"
+ ry="27"
+ stroke="blue"
+ id="ellipse339" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-3"
+ id="text341">Subscription for</text>
+ <text
+ class="text_normal"
+ x="-68"
+ y="10"
+ id="text343">Logical Replication</text>
+ </g>
+ <g
+ transform="translate(100 120)"
+ id="g351">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse347" />
+ <text
+ class="text_normal"
+ x="-15"
+ y="5"
+ id="text349">Role</text>
+ </g>
+ </g>
+ <g
+ transform="translate(-80 10)"
+ id="g385">
+ <ellipse
+ rx="220"
+ ry="110"
+ stroke="blue"
+ stroke-width="2px"
+ id="ellipse355" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-80"
+ id="text357">Database</text>
+ <g
+ transform="translate(-120 -50)"
+ id="g383">
+ <g
+ transform="translate(-30 20)"
+ id="g363">
+ <ellipse
+ rx="50"
+ ry="20"
+ stroke="blue"
+ id="ellipse359" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text361">Extension</text>
+ </g>
+ <g
+ transform="translate(-35 85)"
+ id="g369">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse365" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text367">Collation</text>
+ </g>
+ <g
+ transform="translate(150 70)"
+ id="g381">
+ <ellipse
+ rx="140"
+ ry="70"
+ stroke="blue"
+ id="ellipse371" />
+ <text
+ class="text_normal"
+ x="-80"
+ y="-35"
+ id="text373">Schema</text>
+ <g
+ transform="translate(20 10)"
+ id="g379">
+ <ellipse
+ rx="90"
+ ry="30"
+ stroke="blue"
+ id="ellipse375" />
+ <text
+ class="text_normal"
+ x="-50"
+ y="5"
+ id="text377">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
new file mode 100644
index 0000000000..45387bbd9b
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="720px" height="430px"
+ viewBox="0 0 720 430" >
+
+ <title>Hierarchy of Internal Objects</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="200" y="40">Hierarchy of Internal Objects</text>
+
+
+ <!-- set centre of figure and default values -->
+ <g transform="translate(350 240)" fill="none">
+
+ <g>
+ <ellipse rx="320" ry="170" stroke="blue" />
+ <text class="text_normal" x="-140" y="-130">Cluster</text>
+
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-60" y="5">Database Names</text>
+ </g>
+
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue" />
+ <text class="text_normal" x="-40" y="5">Tablespace</text>
+ </g>
+
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-70" y="5">Replication Origins</text>
+ </g>
+
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue" />
+ <text class="text_normal" x="-60" y="-3">Subscription for</text>
+ <text class="text_normal" x="-68" y="10">Logical Replication</text>
+ </g>
+
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-15" y="5">Role</text>
+ </g>
+
+ </g>
+
+ <g transform="translate(-80 10)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2px" />
+ <text class="text_normal" x="-60" y="-80">Database</text>
+
+ <g transform="translate(-120 -50)">
+ <g transform="translate(-30 20)">
+ <ellipse rx="50" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Extension</text>
+ </g>
+
+ <g transform="translate(-35 85)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Collation</text>
+ </g>
+
+ <g transform="translate(150 70)">
+ <ellipse rx="140" ry="70" stroke="blue" />
+ <text class="text_normal" x="-80" y="-35">Schema</text>
+
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue" />
+ <text class="text_normal" x="-50" y="5">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink-svgo.svg b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
new file mode 100644
index 0000000000..bf638f6c63
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
@@ -0,0 +1,285 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 900 600">
+ <title>
+ PG Overall Server Architecture
+ </title>
+ <style>
+ .text_big{font-style:normal}.text_big,.text_comment,.text_normal,.text_small{font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_normal,.text_small{font-style:normal}.text_small{font-size:12px}.text_normal{font-size:16px}.text_big{font-size:24px}.text_comment{font-style:italic;font-size:16px}
+ </style>
+ <defs>
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (200 x 20 px)
+ </title>
+ <path d="M200 10v10H0V0h190v10h10L190 0"/>
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (250 x 20 px)
+ </title>
+ <path d="M250 10v10H0V0h240v10h10L240 0"/>
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (100 x 35 px)
+ </title>
+ <path d="M100 10v25H0V0h90v10h10L90 0"/>
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (170 x 50 px)
+ </title>
+ <path d="M170 10v40H0V0h160v10h10L160 0"/>
+ </symbol>
+ <symbol id="state_300x120">
+ <title>
+ UML State, big
+ </title>
+ <rect width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>
+ UML State, big
+ </title>
+ <rect width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="disc" stroke="blue" fill="none">
+ <title>
+ Disc
+ </title>
+ <ellipse cx="51" cy="13" rx="50" ry="12"/>
+ <path d="M1 13v60"/>
+ <path d="M101 13v60"/>
+ <path d="M1 73a50 12 0 00100 0"/>
+ </symbol>
+ <symbol id="laptop" stroke="black" fill="none">
+ <title>
+ Laptop
+ </title>
+ <path d="M20 40V0h54v40l15 15H5l15-15h54"/>
+ <path d="M23 3h48v34H23z"/>
+ <path d="M30 10h20"/>
+ <path d="M30 15h25"/>
+ <path d="M30 20h10"/>
+ <path d="M30 30h20"/>
+ <path d="M25 50h45l2 2H22z"/>
+ </symbol>
+ <marker id="arrowhead_start" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto">
+ <path d="M6 0L0 3l6 3" stroke="black" fill="none"/>
+ </marker>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="15" y="40" class="text_big">
+ Client
+ </text>
+ <text x="140" y="40" class="text_big">
+ Server
+ </text>
+ <use xlink:href="#laptop" x="5" y="210"/>
+ <g transform="translate(130 70)">
+ <use xlink:href="#state_350x120"/>
+ <text x="5" y="20" class="text_normal">
+ maintenance_work_mem (per connection)
+ </text>
+ <text x="5" y="45" class="text_normal">
+ work_mem (per query operation)
+ </text>
+ <text x="5" y="70" class="text_normal">
+ autovacuum_work_mem (per worker process)
+ </text>
+ <text x="5" y="95" class="text_normal">
+ temp_buffer (per connection)
+ </text>
+ <text x="5" y="110" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_200x20" x="140" y="-15"/>
+ <text x="150" class="text_comment">
+ Individual Memory
+ </text>
+ </g>
+ <g transform="translate(520 70)">
+ <use xlink:href="#state_300x120"/>
+ <text x="10" y="30" class="text_normal">
+ shared_buffers (heap and index)
+ </text>
+ <text x="10" y="70" class="text_normal">
+ wal_buffers (WAL records)
+ </text>
+ <text x="10" y="100" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_250x20" x="40" y="-15"/>
+ <text x="50" class="text_comment">
+ Shared Memory (per Cluster)
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M190 215h200v30H190z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(190 215)">
+ Postmaster process
+ </text>
+ <path d="M90 230h85" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 230)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 1
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M150 315h370v30H150z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(150 315)">
+ Backend processes (one per connection)
+ </text>
+ <path d="M155 315v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M160 310v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M90 240l63 63" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 290)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 3
+ </text>
+ </g>
+ <path d="M360 250v50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(190 255)">
+ <use xlink:href="#note_250x20"/>
+ <text x="10" y="15" class="text_comment">
+ Creates backend processes
+ </text>
+ </g>
+ <g transform="translate(360 281)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 2
+ </text>
+ </g>
+ <path d="M460 300V200" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M498 300V95h30" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M508 300V135h20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M550 220h120v30H550z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(550 220)">
+ WAL Writer
+ </text>
+ <path d="M590 150v65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M590 255v230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 340h140v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 340)">
+ Checkpointer
+ </text>
+ <path d="M740 110v220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 355H475v130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M700 330V150" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50"/>
+ <text x="60" y="-35" class="text_comment">
+ Checkpoint
+ </text>
+ <text x="60" y="-20" class="text_comment">
+ Record
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M610 380h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 380)">
+ Background Writer
+ </text>
+ <path d="M770 110v260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 395H485v90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 420h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 420)">
+ WAL Archiver
+ </text>
+ <path d="M620 485l30-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M740 455v30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M135 380h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 380)">
+ AutoVacuum
+ </text>
+ <path d="M140 380v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path d="M145 375v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path stroke="blue" fill="none" d="M135 430h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 430)">
+ Log Writer
+ </text>
+ <path stroke="blue" fill="none" d="M290 370h140v30H290z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(290 370)">
+ Stats Collector
+ </text>
+ <g transform="translate(145 490)">
+ <use xlink:href="#disc"/>
+ <text x="35" y="45" class="text_normal">
+ Log
+ </text>
+ <text x="20" y="60" class="text_small">
+ text lines,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <path d="M195 465v20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(410 490)">
+ <use xlink:href="#disc"/>
+ <text x="10" y="40" class="text_normal">
+ Heap and
+ </text>
+ <text x="25" y="55" class="text_normal">
+ Index
+ </text>
+ <text x="15" y="70" class="text_small">
+ binary blocks,
+ </text>
+ <text x="30" y="80" class="text_small">
+ random
+ </text>
+ </g>
+ <path d="M450 485V350" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(295 420)">
+ <use xlink:href="#note_170x50"/>
+ <text x="5" y="15" class="text_comment">
+ Read heap and index
+ </text>
+ <text x="5" y="30" class="text_comment">
+ pages and transfer
+ </text>
+ <text x="5" y="45" class="text_comment">
+ them to shared_buffers
+ </text>
+ </g>
+ <g transform="translate(550 490)">
+ <use xlink:href="#disc"/>
+ <text x="30" y="45" class="text_normal">
+ WAL
+ </text>
+ <text x="10" y="60" class="text_small">
+ binary records,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <g transform="translate(690 490)">
+ <use xlink:href="#disc"/>
+ <text x="16" y="45" class="text_normal">
+ Archived
+ </text>
+ <text x="36" y="60" class="text_normal">
+ WAL
+ </text>
+ </g>
+ <path d="M110 20v550" stroke="black" fill="none"/>
+ <g transform="rotate(90 -33.5 156.5)">
+ <use xlink:href="#note_200x20"/>
+ <text class="text_comment" x="10" y="15">
+ Via TCP/IP or socket
+ </text>
+ </g>
+ <text class="text_big" x="95" transform="rotate(90 425 425)">
+ RAM
+ </text>
+ <text class="text_big" x="250" transform="rotate(90 425 425)">
+ PROCESSES
+ </text>
+ <text class="text_big" x="500" transform="rotate(90 425 425)">
+ FILES
+ </text>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink.svg b/doc/src/sgml/images/ram-proc-file-ink.svg
new file mode 100644
index 0000000000..6c960702a0
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink.svg
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="600px"
+ viewBox="0 0 900 600"
+ id="svg701"
+ sodipodi:docname="ram-proc-file-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata705">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>PG Overall Server Architecture</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="846"
+ inkscape:window-height="675"
+ id="namedview703"
+ showgrid="false"
+ inkscape:zoom="0.39333333"
+ inkscape:cx="450"
+ inkscape:cy="300"
+ inkscape:window-x="503"
+ inkscape:window-y="91"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg701" />
+ <title
+ id="title397">PG Overall Server Architecture</title>
+ <style
+ type="text/css"
+ id="style399">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs465">
+ <!-- Some notes in different sizes -->
+ <symbol
+ id="note_200x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title401">UML Note (200 x 20 px)</title>
+ <path
+ d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10"
+ id="path403" />
+ </symbol>
+ <symbol
+ id="note_250x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title406">UML Note (250 x 20 px)</title>
+ <path
+ d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10"
+ id="path408" />
+ </symbol>
+ <symbol
+ id="note_100x35"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title411">UML Note (100 x 35 px)</title>
+ <path
+ d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10"
+ id="path413" />
+ </symbol>
+ <symbol
+ id="note_170x50"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title416">UML Note (170 x 50 px)</title>
+ <path
+ d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10"
+ id="path418" />
+ </symbol>
+ <!-- UML states (used for buffers) -->
+ <symbol
+ id="state_300x120">
+ <title
+ id="title421">UML State, big</title>
+ <rect
+ x="0"
+ y="0"
+ width="300"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect423" />
+ </symbol>
+ <symbol
+ id="state_350x120">
+ <title
+ id="title426">UML State, big</title>
+ <rect
+ x="0"
+ y="0"
+ width="350"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect428" />
+ </symbol>
+ <!-- Discs -->
+ <symbol
+ id="disc"
+ stroke="blue"
+ fill="none">
+ <title
+ id="title431">Disc</title>
+ <ellipse
+ cx="51"
+ cy="13"
+ rx="50"
+ ry="12"
+ id="ellipse433" />
+ <!-- top -->
+ <path
+ d="M 1,13 v 60"
+ id="path435" />
+ <!-- left -->
+ <path
+ d="M 101,13 v 60"
+ id="path437" />
+ <!-- right -->
+ <path
+ d="M 1,73 A 50, 12, 0, 0, 0, 101,73"
+ id="path439" />
+ <!-- bottom -->
+ </symbol>
+ <!-- Laptop -->
+ <symbol
+ id="laptop"
+ stroke="black"
+ fill="none">
+ <title
+ id="title442">Laptop</title>
+ <path
+ d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54"
+ id="path444" />
+ <rect
+ x="23"
+ y="3"
+ width="48"
+ height="34"
+ id="rect446" />
+ <!-- symbolize some lines -->
+ <path
+ d="M 30,10 h 20"
+ id="path448" />
+ <path
+ d="M 30,15 h 25"
+ id="path450" />
+ <path
+ d="M 30,20 h 10"
+ id="path452" />
+ <path
+ d="M 30,30 h 20"
+ id="path454" />
+ <!-- symbolize keyboard -->
+ <path
+ d="M 25,50 h 45 l 2,2 h -50 z "
+ id="path456" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path459" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path462" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect467" />
+ <!-- caption, client side -->
+ <text
+ x="15"
+ y="40"
+ class="text_big"
+ id="text469">Client</text>
+ <text
+ x="140"
+ y="40"
+ class="text_big"
+ id="text471">Server</text>
+ <use
+ xlink:href="#laptop"
+ x="5"
+ y="210"
+ id="use473" />
+ <!-- individual memory -->
+ <g
+ transform="translate(130, 70)"
+ id="g491">
+ <use
+ xlink:href="#state_350x120"
+ x="0"
+ y="0"
+ id="use475" />
+ <text
+ x="5"
+ y="20"
+ class="text_normal"
+ id="text477">maintenance_work_mem (per connection)</text>
+ <text
+ x="5"
+ y="45"
+ class="text_normal"
+ id="text479">work_mem (per query operation)</text>
+ <text
+ x="5"
+ y="70"
+ class="text_normal"
+ id="text481">autovacuum_work_mem (per worker process)</text>
+ <text
+ x="5"
+ y="95"
+ class="text_normal"
+ id="text483">temp_buffer (per connection)</text>
+ <text
+ x="5"
+ y="110"
+ class="text_normal"
+ id="text485">...</text>
+ <use
+ xlink:href="#note_200x20"
+ x="140"
+ y="-15"
+ id="use487" />
+ <text
+ x="150"
+ y="0"
+ class="text_comment"
+ id="text489">Individual Memory</text>
+ </g>
+ <!-- shared memory -->
+ <g
+ transform="translate(520, 70)"
+ id="g505">
+ <use
+ xlink:href="#state_300x120"
+ x="0"
+ y="0"
+ id="use493" />
+ <text
+ x="10"
+ y="30"
+ class="text_normal"
+ id="text495">shared_buffers (heap and index)</text>
+ <text
+ x="10"
+ y="70"
+ class="text_normal"
+ id="text497">wal_buffers (WAL records)</text>
+ <text
+ x="10"
+ y="100"
+ class="text_normal"
+ id="text499">...</text>
+ <use
+ xlink:href="#note_250x20"
+ x="40"
+ y="-15"
+ id="use501" />
+ <text
+ x="50"
+ y="0"
+ class="text_comment"
+ id="text503">Shared Memory (per Cluster)</text>
+ </g>
+ <!-- postmaster -->
+ <g
+ transform="translate(190, 215)"
+ id="g511">
+ <rect
+ width="200"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect507" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text509">Postmaster process</text>
+ </g>
+ <path
+ d="M 90,230 h 85"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path513" />
+ <g
+ transform="translate(140, 230)"
+ id="g519">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle515" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text517">1</text>
+ </g>
+ <!-- backend processes -->
+ <g
+ transform="translate(150, 315)"
+ id="g529">
+ <rect
+ width="370"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect521" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text523">Backend processes (one per connection)</text>
+ <path
+ d="M 5,0 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path525" />
+ <path
+ d="M 10,-5 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path527" />
+ </g>
+ <path
+ d="M 90,240 153,303"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path531" />
+ <g
+ transform="translate(140, 290)"
+ id="g537">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle533" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text535">3</text>
+ </g>
+ <!-- connection between postmaster and backend processes -->
+ <path
+ d="M 360,250 v 50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path539" />
+ <g
+ transform="translate(190, 255)"
+ id="g545">
+ <use
+ xlink:href="#note_250x20"
+ id="use541" />
+ <text
+ x="10"
+ y="15"
+ class="text_comment"
+ id="text543">Creates backend processes</text>
+ </g>
+ <g
+ transform="translate(360, 281)"
+ id="g551">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle547" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text549">2</text>
+ </g>
+ <!-- backend process' access to individual memory -->
+ <path
+ d="M 460,300 v -100"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path553" />
+ <!-- its access to shared buffers and WAL buffers -->
+ <path
+ d="M 498,300 v -205 h 30"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path555" />
+ <path
+ d="M 508,300 v -165 h 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path557" />
+ <!-- WAL writer -->
+ <g
+ transform="translate(550, 220)"
+ id="g563">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect559" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text561">WAL Writer</text>
+ </g>
+ <path
+ d="M 590,150 v 65"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path565" />
+ <path
+ d="M 590,255 v 230"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path567" />
+ <!-- Checkpoiner -->
+ <g
+ transform="translate(610, 340)"
+ id="g573">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect569" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text571">Checkpointer</text>
+ </g>
+ <path
+ d="M 740,110 v 220"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path575" />
+ <path
+ d="M 605,355 h -130 v 130"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path577" />
+ <path
+ d="M 700,330 v -180"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path579" />
+ <g
+ transform="translate(570, 330)"
+ id="g587">
+ <use
+ xlink:href="#note_100x35"
+ x="50"
+ y="-50"
+ id="use581" />
+ <text
+ x="60"
+ y="-35"
+ class="text_comment"
+ id="text583">Checkpoint</text>
+ <text
+ x="60"
+ y="-20"
+ class="text_comment"
+ id="text585">Record</text>
+ </g>
+ <!-- BG writer -->
+ <g
+ transform="translate(610, 380)"
+ id="g593">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect589" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text591">Background Writer</text>
+ </g>
+ <path
+ d="M 770,110 v 260"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path595" />
+ <path
+ d="M 605,395 h -120 v 90"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path597" />
+ <!-- Archiver -->
+ <g
+ transform="translate(610, 420)"
+ id="g603">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect599" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text601">WAL Archiver</text>
+ </g>
+ <path
+ d="M 620,485 l 30,-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path605" />
+ <path
+ d="M 740,455 v 30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path607" />
+ <!-- Vacuum -->
+ <g
+ transform="translate(135, 380)"
+ id="g617">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect609" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text611">AutoVacuum</text>
+ <path
+ d="M 5,0 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path613" />
+ <path
+ d="M 10,-5 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path615" />
+ </g>
+ <!-- Log Writer -->
+ <g
+ transform="translate(135, 430)"
+ id="g623">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect619" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text621">Log Writer</text>
+ </g>
+ <!-- Stats Collector (135, 460) -->
+ <g
+ transform="translate(290, 370)"
+ id="g629">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect625" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text627">Stats Collector</text>
+ </g>
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g
+ transform="translate(145, 490)"
+ id="g639">
+ <use
+ xlink:href="#disc"
+ id="use631" />
+ <text
+ x="35"
+ y="45"
+ class="text_normal"
+ id="text633">Log</text>
+ <text
+ x="20"
+ y="60"
+ class="text_small"
+ id="text635">text lines,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text637">sequential</text>
+ </g>
+ <path
+ d="M 195,465 v 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path641" />
+ <g
+ transform="translate(410, 490)"
+ id="g653">
+ <use
+ xlink:href="#disc"
+ id="use643" />
+ <text
+ x="10"
+ y="40"
+ class="text_normal"
+ id="text645">Heap and</text>
+ <text
+ x="25"
+ y="55"
+ class="text_normal"
+ id="text647">Index</text>
+ <text
+ x="15"
+ y="70"
+ class="text_small"
+ id="text649">binary blocks,</text>
+ <text
+ x="30"
+ y="80"
+ class="text_small"
+ id="text651">random</text>
+ </g>
+ <path
+ d="M 450,485 v -135"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path655" />
+ <g
+ transform="translate(295, 420)"
+ id="g665">
+ <use
+ xlink:href="#note_170x50"
+ id="use657" />
+ <text
+ x="5"
+ y="15"
+ class="text_comment"
+ id="text659">Read heap and index</text>
+ <text
+ x="5"
+ y="30"
+ class="text_comment"
+ id="text661">pages and transfer</text>
+ <text
+ x="5"
+ y="45"
+ class="text_comment"
+ id="text663">them to shared_buffers</text>
+ </g>
+ <g
+ transform="translate(550, 490)"
+ id="g675">
+ <use
+ xlink:href="#disc"
+ id="use667" />
+ <text
+ x="30"
+ y="45"
+ class="text_normal"
+ id="text669">WAL</text>
+ <text
+ x="10"
+ y="60"
+ class="text_small"
+ id="text671">binary records,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text673">sequential</text>
+ </g>
+ <g
+ transform="translate(690, 490)"
+ id="g683">
+ <use
+ xlink:href="#disc"
+ id="use677" />
+ <text
+ x="16"
+ y="45"
+ class="text_normal"
+ id="text679">Archived</text>
+ <text
+ x="36"
+ y="60"
+ class="text_normal"
+ id="text681">WAL</text>
+ </g>
+ <!-- boarder between client and server side -->
+ <path
+ d="M 110,20 v 550"
+ stroke="black"
+ fill="none"
+ id="path685" />
+ <g
+ transform="translate(123, 190) rotate(90)"
+ id="g691">
+ <use
+ xlink:href="#note_200x20"
+ id="use687" />
+ <text
+ class="text_comment"
+ x="10"
+ y="15"
+ id="text689">Via TCP/IP or socket</text>
+ </g>
+ <!-- right side -->
+ <g
+ transform="translate(850, 0) rotate(90)"
+ id="g699">
+ <text
+ class="text_big"
+ x="95"
+ id="text693">RAM</text>
+ <text
+ class="text_big"
+ x="250"
+ id="text695">PROCESSES</text>
+ <text
+ class="text_big"
+ x="500"
+ id="text697">FILES</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-raw.svg b/doc/src/sgml/images/ram-proc-file-raw.svg
new file mode 100644
index 0000000000..26eacde411
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-raw.svg
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="600px"
+ viewBox="0 0 900 600">
+
+ <title>PG Overall Server Architecture</title>
+
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Some notes in different sizes -->
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>UML Note (200 x 20 px)</title>
+ <path d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>UML Note (250 x 20 px)</title>
+ <path d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>UML Note (100 x 35 px)</title>
+ <path d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>UML Note (170 x 50 px)</title>
+ <path d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- UML states (used for buffers) -->
+ <symbol id="state_300x120">
+ <title>UML State, big</title>
+ <rect x="0" y="0" width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>UML State, big</title>
+ <rect x="0" y="0" width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- Discs -->
+ <symbol id="disc" stroke="blue" fill="none" >
+ <title>Disc</title>
+ <ellipse cx="51" cy="13" rx="50" ry="12" /> <!-- top -->
+ <path d="M 1,13 v 60" /> <!-- left -->
+ <path d="M 101,13 v 60" /> <!-- right -->
+ <path d="M 1,73 A 50, 12, 0, 0, 0, 101,73" /> <!-- bottom -->
+ </symbol>
+
+ <!-- Laptop -->
+ <symbol id="laptop" stroke="black" fill="none" >
+ <title>Laptop</title>
+ <path d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54" />
+ <rect x="23" y="3" width="48" height="34" />
+ <!-- symbolize some lines -->
+ <path d="M 30,10 h 20" />
+ <path d="M 30,15 h 25" />
+ <path d="M 30,20 h 10" />
+ <path d="M 30,30 h 20" />
+ <!-- symbolize keyboard -->
+ <path d="M 25,50 h 45 l 2,2 h -50 z " />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption, client side -->
+ <text x="15" y="40" class="text_big">Client</text>
+ <text x="140" y="40" class="text_big">Server</text>
+ <use xlink:href="#laptop" x="5" y="210" />
+
+
+ <!-- individual memory -->
+ <g transform="translate(130, 70)">
+ <use xlink:href="#state_350x120" x="0" y="0" />
+ <text x="5" y="20" class="text_normal">maintenance_work_mem (per connection)</text>
+ <text x="5" y="45" class="text_normal">work_mem (per query operation)</text>
+ <text x="5" y="70" class="text_normal">autovacuum_work_mem (per worker process)</text>
+ <text x="5" y="95" class="text_normal">temp_buffer (per connection)</text>
+ <text x="5" y="110" class="text_normal">...</text>
+ <use xlink:href="#note_200x20" x="140" y="-15" />
+ <text x="150" y="0" class="text_comment">Individual Memory</text>
+ </g>
+
+ <!-- shared memory -->
+ <g transform="translate(520, 70)">
+ <use xlink:href="#state_300x120" x="0" y="0" />
+ <text x="10" y="30" class="text_normal">shared_buffers (heap and index)</text>
+ <text x="10" y="70" class="text_normal">wal_buffers (WAL records)</text>
+ <text x="10" y="100" class="text_normal">...</text>
+ <use xlink:href="#note_250x20" x="40" y="-15" />
+ <text x="50" y="0" class="text_comment">Shared Memory (per Cluster)</text>
+ </g>
+
+ <!-- postmaster -->
+ <g transform="translate(190, 215)">
+ <rect width="200" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Postmaster process</text>
+ </g>
+ <path d="M 90,230 h 85" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 230)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">1</text>
+ </g>
+
+ <!-- backend processes -->
+ <g transform="translate(150, 315)">
+ <rect width="370" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Backend processes (one per connection)</text>
+ <path d="M 5,0 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <path d="M 90,240 153,303" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 290)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">3</text>
+ </g>
+
+ <!-- connection between postmaster and backend processes -->
+ <path d="M 360,250 v 50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(190, 255)">
+ <use xlink:href="#note_250x20" />
+ <text x="10" y="15" class="text_comment">Creates backend processes</text>
+ </g>
+ <g transform="translate(360, 281)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">2</text>
+ </g>
+
+ <!-- backend process' access to individual memory -->
+ <path d="M 460,300 v -100" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <!-- its access to shared buffers and WAL buffers -->
+ <path d="M 498,300 v -205 h 30" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M 508,300 v -165 h 20" stroke="black" fill="none"
+ marker-end="url(#arrowhead_end)"/>
+
+ <!-- WAL writer -->
+ <g transform="translate(550, 220)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Writer</text>
+ </g>
+ <path d="M 590,150 v 65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 590,255 v 230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Checkpoiner -->
+ <g transform="translate(610, 340)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Checkpointer</text>
+ </g>
+ <path d="M 740,110 v 220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,355 h -130 v 130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 700,330 v -180" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570, 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50" />
+ <text x="60" y="-35" class="text_comment">Checkpoint</text>
+ <text x="60" y="-20" class="text_comment">Record</text>
+ </g>
+
+ <!-- BG writer -->
+ <g transform="translate(610, 380)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Background Writer</text>
+ </g>
+ <path d="M 770,110 v 260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,395 h -120 v 90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Archiver -->
+ <g transform="translate(610, 420)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Archiver</text>
+ </g>
+ <path d="M 620,485 l 30,-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 740,455 v 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Vacuum -->
+ <g transform="translate(135, 380)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">AutoVacuum</text>
+ <path d="M 5,0 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <!-- Log Writer -->
+ <g transform="translate(135, 430)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Log Writer</text>
+ </g>
+
+ <!-- Stats Collector (135, 460) -->
+ <g transform="translate(290, 370)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Stats Collector</text>
+ </g>
+
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g transform="translate(145, 490)">
+ <use xlink:href="#disc" />
+ <text x="35" y="45" class="text_normal">Log</text>
+ <text x="20" y="60" class="text_small">text lines,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+ <path d="M 195,465 v 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(410, 490)">
+ <use xlink:href="#disc" />
+ <text x="10" y="40" class="text_normal">Heap and</text>
+ <text x="25" y="55" class="text_normal">Index</text>
+ <text x="15" y="70" class="text_small">binary blocks,</text>
+ <text x="30" y="80" class="text_small">random</text>
+ </g>
+ <path d="M 450,485 v -135" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(295, 420)">
+ <use xlink:href="#note_170x50" />
+ <text x="5" y="15" class="text_comment">Read heap and index</text>
+ <text x="5" y="30" class="text_comment">pages and transfer</text>
+ <text x="5" y="45" class="text_comment">them to shared_buffers</text>
+ </g>
+
+ <g transform="translate(550, 490)">
+ <use xlink:href="#disc" />
+ <text x="30" y="45" class="text_normal">WAL</text>
+ <text x="10" y="60" class="text_small">binary records,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+
+ <g transform="translate(690, 490)">
+ <use xlink:href="#disc" />
+ <text x="16" y="45" class="text_normal">Archived</text>
+ <text x="36" y="60" class="text_normal">WAL</text>
+ </g>
+
+ <!-- boarder between client and server side -->
+ <path d="M 110,20 v 550" stroke="black" fill="none" />
+ <g transform="translate(123, 190) rotate(90)">
+ <use xlink:href="#note_200x20" />
+ <text class="text_comment" x="10" y ="15">Via TCP/IP or socket</text>
+ </g>
+
+ <!-- right side -->
+ <g transform="translate(850, 0) rotate(90)">
+ <text class="text_big" x="95">RAM</text>
+ <text class="text_big" x="250">PROCESSES</text>
+ <text class="text_big" x="500">FILES</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index c41ce9499b..6254bf9376 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -60,6 +60,7 @@ break is not needed in a wider output rendering.
</partintro>
&start;
+ &architecture;
&query;
&advanced;
I plan to extend over time the part 'Tutorial' by an additional chapter
with an overview about key design decisions and basic features. The
typical audience should consist of persons with limited pre-knowledge in
database systems and some interest in PostgreSQL. In the attachment you
find a patch for the first sub-chapter. Subsequent sub-chapters should
be: MVCC, transactions, VACUUM, backup, replication, ... - mostly with
the focus on the PostgreSQL implementation and not on generic topics
like b-trees.
+1
On 2020-04-17 19:56, Jürgen Purtz wrote:
Our documentation explains many details about commands, tools,
parameters in detail and with high accuracy. Nevertheless my
impression is that we neglect the 'big picture': why certain processes
[0001-architecture.patch]
Very good stuff, and useful. I think.
I mean that but nevertheless here is a lot of comment :)
(I didn't fully compile as docs, just read the 'text' from the patch
file)
Collabortion
Collaboration
drop 'resulting'
He acts in close cooperation with the
It acts in close cooperation with the
He loads the configuration files, allocates the
It loads the configuration files, allocates the
process</firstterm>. He checks the authorization, starts a
process</firstterm>. it checks the authorization, starts a
and instructs the client application to connect to him. All further
and instructs the client application to connect to it. All further
by him.
by it.
In an first attempt
In a first attempt
much huger than memory, it's likely that
much larger than memory, it's likely that
RAM is performed in units of complete pages while retaining
RAM is performed in units of complete pages, retaining
Sooner or later it is necessary to overwrite old RAM
Sooner or later it becomes necessary to overwrite old RAM
transfered
transferred
(multiple times)
who runs
which runs
He writes
it writes
This is the primarily duty of the
This is primarily the duty of the
or possibly:
This is the primary duty of the
he starts periodically
it starts periodically
speeds up a possibly occurring recovery.
can speed up recovery.
writen
written
collects counter about accesses
collects counters about accesses
and others. He stores the obtained information in system
and more. It stores the obtained information in system
sudirectories consists
subdirectories consist <-- plural, no -s
there are information
there is information
and contains the ID of the
and contains the ID (pid) of the
( IMHO, it is conventional (and therefore easier to read) to have 'e.g.'
followed by a comma, and not by a semi-colon, although obviously that's
not really wrong either. )
Thanks,
Erik Rijkers
On 17.04.20 20:40, Erik Rijkers wrote:
Very good stuff, and useful. I think.
I mean that but nevertheless here is a lot of comment :)
(I didn't fully compile as docs, just read the 'text' from the patch
file)
Thanks. Added nearly all of the suggestions.
--
Jürgen Purtz
Attachments:
0002-architecture.patchtext/x-patch; charset=UTF-8; name=0002-architecture.patchDownload
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
index ae5f3fac75..965eb751c0 100644
--- a/doc/src/sgml/advanced.sgml
+++ b/doc/src/sgml/advanced.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/advanced.sgml -->
<chapter id="tutorial-advanced">
- <title>Advanced Features</title>
+ <title>Advanced SQL Features</title>
<sect1 id="tutorial-advanced-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
new file mode 100644
index 0000000000..81dedc90b4
--- /dev/null
+++ b/doc/src/sgml/architecture.sgml
@@ -0,0 +1,449 @@
+<!-- doc/src/sgml/architecture.sgml -->
+
+ <chapter id="tutorial-architecture">
+ <title>The Architecture</title>
+
+ <para>
+ Every DBMS implements basic strategies to achieve a fast and
+ robust system. This chapter provides an overview of what
+ techniques <productname>PostgreSQL</productname> uses to
+ reach this aim.
+ </para>
+
+ <sect1 id="tutorial-ram-proc-file">
+ <title>Collaboration of Processes, RAM, and Files</title>
+ <para>
+ As is a matter of course, in a client/server architecture
+ clients do not have direct access to the database. Instead,
+ they merely send requests to the server side and receives
+ according information from there. In the case of
+ <productname>PostgreSQL</productname>, at the server
+ side there is one process per client, the so-called
+ <glossterm linkend="glossary-backend">Backend process</glossterm>.
+ It acts in close cooperation with the
+ <glossterm linkend="glossary-instance">Instance</glossterm> which
+ is a group of tightly coupled other server side processes plus a
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>
+ area.
+ </para>
+
+ <para>
+ At start time, an instance is initiated by the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm> process.
+ It loads the configuration files, allocates the
+ <firstterm>Shared Memory</firstterm>
+ and starts the comprehensive network of processes:
+ <glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
+ <glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
+ <glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
+ <glossterm linkend="glossary-wal-archiver">WAL Archiver</glossterm>,
+ <glossterm linkend="glossary-autovacuum">Autovacuum processes</glossterm>,
+ <glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
+ <glossterm linkend="glossary-logger">Logger</glossterm>, and more.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes
+ main aspects of their collaboration.
+ </para>
+
+ <figure id="tutorial-ram-proc-file-figure">
+ <title>Architecture</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ Whenever a client application tries to connect to a
+ <glossterm linkend="glossary-database">database</glossterm>, this request is handled
+ in a first step by the <firstterm>Postmaster
+ process</firstterm>. It checks the authorization, starts a
+ new <firstterm>Backend process</firstterm>,
+ and instructs the client application to connect to it. All further
+ client requests go to this process and are handled
+ by it.
+ </para>
+
+ <para>
+ Client requests (SELECT, UPDATE, ...) usually leads to the
+ necessity to read or write some data. In a first attempt
+ the client's <firstterm>Backend process</firstterm> tries
+ to get the information out of <firstterm>Shared
+ Memory</firstterm>. This <firstterm>Shared
+ Memory</firstterm> is a mirror of parts of the
+ <glossterm linkend="glossary-heap">heap</glossterm> and
+ <glossterm linkend="glossary-index">index</glossterm> files. Because files are
+ much larger than memory, it's likely that
+ the desired information is not (completely) available
+ in the RAM. In this case the <firstterm>Backend process
+ </firstterm> must transfer additional file pages to
+ <firstterm>Shared Memory</firstterm>. Files are physically
+ organized in pages. Every transfer between files and
+ RAM is performed in units of complete pages, retaining
+ their size and layout.
+ </para>
+
+ <para>
+ Reading file pages is notedly slower than reading
+ RAM. This is the main motivation for the existence of
+ <firstterm>Shared Memory</firstterm>. As soon as one
+ of the <firstterm>Backend processes</firstterm> has done
+ the job those pages are available for all other
+ <firstterm>Backend processes</firstterm> for direct
+ access in RAM.
+ </para>
+
+ <para>
+ <firstterm>Shared Memory</firstterm> is limited in size.
+ Sooner or later it becomes necessary to overwrite old RAM
+ pages. As long as the content of such pages hasn't
+ changed this is not a problem. But in
+ <firstterm>Shared Memory</firstterm> also write
+ actions take place
+ - performed by any of the <firstterm>Backend
+ processes</firstterm> (or an
+ <glossterm linkend="glossary-autovacuum">autovacuum process</glossterm>,
+ or other processes). Such modified pages are called
+ <firstterm>dirty pages</firstterm>.
+ Before <firstterm>dirty pages</firstterm> can be overwritten,
+ they must be transferred back to disk. This is a two-step process.
+ </para>
+
+ <para>
+ First, whenever the content of a page changes, a
+ <glossterm linkend="glossary-wal-record">WAL record</glossterm> is created out
+ of the delta-information (difference between old and
+ new content) and stored in another area of the
+ <firstterm>Shared Memory</firstterm>. These
+ <firstterm>WAL records</firstterm> are read by the
+ <firstterm>WAL Writer</firstterm> process,
+ which runs in parallel to the <firstterm>Backend
+ processes</firstterm> and all other processes of
+ the <firstterm>Instance</firstterm>. It writes
+ the continuously arising <firstterm>WAL records</firstterm> to
+ the end of the current
+ <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
+ Because of the sequential nature of this writing, it is much
+ faster than the more or less random access
+ to data files with <firstterm>heap</firstterm>
+ and <firstterm>index</firstterm> information.
+ As mentioned, this WAL-writing happens
+ in an independent process. Nevertheless all
+ <firstterm>WAL records</firstterm> created out of one
+ <firstterm>dirty page</firstterm> must be transferred
+ to disk before the <firstterm>dirty page</firstterm>
+ itself can be transferred to disk (???).
+ </para>
+
+ <para>
+ Second, the transfer of <firstterm>dirty pages</firstterm>
+ from <firstterm>Shared Memory</firstterm> to files must
+ take place. This is the primary duty of the
+ <firstterm>Background Writer</firstterm> process. Because
+ huge I/O activities can block other processes significantly,
+ it starts periodically and acts only for a short period.
+ Doing so, his expensive I/O activities are spread over
+ time avoiding huge I/O peaks. Also the <firstterm>
+ Checkpointer</firstterm> process transfers
+ <firstterm>dirty pages</firstterm> to files, see next
+ paragraph.
+ </para>
+
+ <para>
+ The <firstterm>Checkpointer</firstterm> has a special
+ duty. As its name suggests, he has to create
+ <firstterm>Checkpoints</firstterm>. Such a
+ <glossterm linkend="glossary-checkpoint">Checkpoint</glossterm> is a point in time
+ when all older <firstterm>dirty pages</firstterm>,
+ all older <firstterm>WAL records</firstterm>, and
+ lastly a special <firstterm>Checkpoint record
+ </firstterm> have been written and flushed to disk.
+ In consequence, after a <firstterm>Checkpoint</firstterm>
+ data files and <firstterm>WAL files</firstterm> are in sync.
+ In case of a recovery (after a crash of the instance)
+ it is known that the information of all
+ <firstterm>WAL records</firstterm> preceding
+ the last <firstterm>Checkpoint record</firstterm>
+ is already integrated into the data files. This
+ speeds up a possibly occurring recovery.
+ </para>
+
+ <para>
+ In correlation with data changes,
+ <firstterm>WAL records</firstterm> arise and are written
+ to <firstterm>WAL files</firstterm>.
+ Those <firstterm>WAL files</firstterm> - in combination with
+ a previously taken <firstterm>Base Backup</firstterm> -
+ are necessary to restore a database after a crash of the
+ disk, where data files have been stored. Therefore it is
+ recommended to transfer a copy of the <firstterm>
+ WAL files</firstterm>
+ to a second, independent place. The purpose of the
+ <firstterm>WAL Archiver</firstterm> process is to perform
+ this copy action.
+ </para>
+
+ <para>
+ The <glossterm linkend="glossary-stats-collector">Stats Collector</glossterm>
+ collects counters about accesses to <firstterm>SQL
+ objects</firstterm> like tables, rows, indexes, pages,
+ and more. It stores the obtained information in system
+ tables.
+ </para>
+
+ <para>
+ The <glossterm linkend="glossary-logger">Logger</glossterm> writes
+ text lines about serious and non-serious events which can happen
+ during database access, e.g.: wrong password, no permission,
+ long-running queries, ... .
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-cluster-db-schema">
+ <title>Cluster, Database, Schema</title>
+
+ <para>
+ On a <glossterm linkend="glossary-server">Server</glossterm>
+ exists one or more <glossterm linkend="glossary-cluster">Cluster</glossterm>,
+ each of them contains three or more
+ <glossterm linkend="glossary-database">databases</glossterm>, each
+ database contains many <glossterm linkend="glossary-schema">schema</glossterm>,
+ a schema contains <glossterm linkend="glossary-table">tables</glossterm>,
+ <glossterm linkend="glossary-view">views</glossterm>, and a lot of other objects.
+ Each <firstterm>table</firstterm> or <firstterm>view</firstterm>
+ belongs to a certain <firstterm>schema</firstterm>, they cannot
+ belong to another <firstterm>schema</firstterm>. The same is
+ true for the schema/database and database/cluster relation.
+ <xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
+ this hierarchy.
+ </para>
+
+ <figure id="tutorial-cluster-db-schema-figure">
+ <title>Cluster, Database, Schema</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ A <firstterm>Cluster</firstterm> is the outer frame for a
+ collection of databases. Clusters are created by the command
+ <xref linkend="app-initdb"/>.
+ </para>
+
+ <para>
+ <literal>template0</literal> is the very first
+ <firstterm>database</firstterm> of any
+ <firstterm>cluster</firstterm>. C-routines create
+ <literal>template0</literal> during the initialization phase of
+ the <firstterm>cluster</firstterm>.
+ In a second step <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal> and finally
+ <literal>postgres</literal> as a copy of
+ <literal>template1</literal>. All other
+ <glossterm linkend="app-createdb">new databases</glossterm>
+ of this <firstterm>cluster</firstterm>,
+ such as <literal>my_db</literal>, are also copied from
+ <literal>template1</literal>. Due to the special
+ role of <literal>template0</literal> as the origin
+ of all other <firstterm>databases</firstterm>, no client
+ can connect to it.
+ </para>
+
+ <para>
+ Every database contains <glossterm linkend="glossary-schema">
+ schemas</glossterm>, and
+ <firstterm>schemas</firstterm> contain the other
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>.
+ <firstterm>Schemas</firstterm> are namespaces for
+ their <firstterm>SQL objects</firstterm> and ensure - with one
+ exception - that within their scope names are used only once across all
+ types of <firstterm>SQL objects</firstterm>. E.g., it is not possible
+ to have a table <literal>employee</literal> and a view
+ <literal>employee</literal> within the same
+ <firstterm>schema</firstterm>. But it is possible to have
+ two tables <literal>employee</literal> in different
+ <firstterm>schemas</firstterm>. In this case the two tables
+ are different objects and absolutely independent from each
+ other. The only exception to this cross-type uniqueness is that
+ <glossterm linkend="glossary-unique-constraint">unique constraints
+ </glossterm> and the according <firstterm>unique index</firstterm>
+ use the same name.
+ </para>
+
+ <para>
+ Some <firstterm>schemas</firstterm> are predefined.
+ <literal>public</literal> acts as the default
+ <firstterm>schema</firstterm> and contains all such
+ <firstterm>SQL objects</firstterm>, which are created
+ within <literal>public</literal> or without using any schema
+ name. <literal>public</literal> shall not contain user defined
+ <firstterm>SQL objects</firstterm>. Instead, it is recommended to
+ create a separate <firstterm>schema</firstterm> which
+ holds individual objects like application-specific tables or
+ views. <literal>pg_catalog</literal> is a schema for all tables
+ and views of the <glossterm linkend="glossary-system-catalog">
+ System Catalog</glossterm>.
+ <literal>information_schema</literal> is a schema for several
+ tables and views of the <firstterm>System Catalog</firstterm>
+ in a way which conforms to the SQL standard.
+ </para>
+
+ <para>
+ There are a lot of different <firstterm>SQL object</firstterm>
+ types: <firstterm>database, schema, table, view, materialized
+ view, index, constraint, sequence, function, procedure,
+ trigger, role, data type, operator, tablespace, extension,
+ foreign data wrapper</firstterm>, and more. A few of them, the
+ <glossterm linkend="glossary-global-sql-object">Global SQL Objects</glossterm>,
+ are outside of the strict hierarchy:
+ All database names, all tablespace names, and all role names
+ are automatically known and available throughout the
+ complete <firstterm>cluster</firstterm>, independent from
+ the database or schema in which they where originally
+ defined. <xref linkend="tutorial-internal-objects-hierarchy-figure"/>
+ shows the relation between the object types.
+ </para>
+
+ <figure id="tutorial-internal-objects-hierarchy-figure">
+ <title>Hierarchy of Internal Objects</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="720px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect1>
+
+ <sect1 id="tutorial-directories">
+ <title>Directory Structure</title>
+
+ <para>
+ <productname>PostgreSQL</productname> organizes long lasting
+ data as well as volatile state information about transactions
+ or replication actions in the file system. Every
+ <firstterm>Cluster</firstterm> has its own root directory
+ anywhere in the file system. In many cases, the environment
+ variable <literal>PGDATA</literal> points to this directory.
+ The example of the following survey, which is shown in
+ <xref linkend="tutorial-directories-figure"/>, uses
+ <literal>data</literal> as the name of this root directory.
+ </para>
+
+ <figure id="tutorial-directories-figure">
+ <title>Directory Structure</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ <literal>data</literal> contains many subdirectories and
+ some files, all of which are necessary to store long lasting
+ as well as temporary data. The following paragraphs
+ describe the files and subdirectories in
+ <literal>data</literal>.
+ </para>
+
+ <para>
+ <literal>base</literal> is a subdirectory in which one
+ subdirectory per <firstterm>database</firstterm> exists.
+ The names of those subdirectories consist of numbers.
+ These are the internal
+ <firstterm>Object Identifiers (OID)</firstterm>, which are
+ numbers to identify the database definition in the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ </para>
+
+ <para>
+ Within the <firstterm>database</firstterm>-specific
+ subdirectories there are many files. Primarily they contain
+ the <firstterm>heap</firstterm> and <firstterm>
+ index</firstterm>. But there are also optimization information
+ like <link linkend="storage-fsm">Free Space Maps</link> or
+ <link linkend="storage-vm">Visibility Maps</link>.
+ </para>
+
+ <para>
+ Another important subdirectory is <literal>global</literal>.
+ In analogy to the <firstterm>database</firstterm>-specific
+ subdirectories, there are files containing information about
+ <glossterm linkend="glossary-global-sql-object">Global SQL objects</glossterm>.
+ One type
+ of such <firstterm>Global Objects</firstterm> are
+ <firstterm>tablespaces</firstterm>. In
+ <literal>global</literal> there is information about
+ the <firstterm>tablespaces</firstterm>, not the
+ <firstterm>tablespaces</firstterm> itself.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_wal</literal> contains the
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
+ They arise and grow parallel to data changes in the
+ <firstterm>cluster</firstterm> and remain alive as long as
+ they are required for recovery, archiving, or replication.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_xact</literal> contains
+ information about the status of each transaction
+ (IN_PROGRESS, COMMITTED, ABORTED, or SUB_COMMITTED).
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal> there are symbolic links
+ that point to directories containing such<firstterm>
+ SQL objects</firstterm> that are created within
+ <firstterm>tablespaces</firstterm>.
+ </para>
+
+ <para>
+ In the directory <literal>data</literal>
+ there are also some files.
+ In many cases, the configuration
+ files of this <firstterm>cluster</firstterm>
+ are stored here. As long as the <firstterm>
+ cluster</firstterm> is up and running, the file
+ <literal>postmaster.pid</literal> exists here
+ and contains the ID (pid) of the
+ <firstterm>Postmaster</firstterm> process.
+ </para>
+
+ </sect1>
+
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 68179f71cd..ca29c8bc4e 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -8,9 +8,10 @@
<!ENTITY problems SYSTEM "problems.sgml">
<!-- tutorial -->
-<!ENTITY advanced SYSTEM "advanced.sgml">
-<!ENTITY query SYSTEM "query.sgml">
-<!ENTITY start SYSTEM "start.sgml">
+<!ENTITY start SYSTEM "start.sgml">
+<!ENTITY architecture SYSTEM "architecture.sgml">
+<!ENTITY query SYSTEM "query.sgml">
+<!ENTITY advanced SYSTEM "advanced.sgml">
<!-- user's guide -->
<!ENTITY array SYSTEM "array.sgml">
diff --git a/doc/src/sgml/glossary.sgml b/doc/src/sgml/glossary.sgml
index 8c6cb6e942..25762b7c3a 100644
--- a/doc/src/sgml/glossary.sgml
+++ b/doc/src/sgml/glossary.sgml
@@ -208,15 +208,6 @@
</glossdef>
</glossentry>
- <glossentry id="glossary-checkpointer">
- <glossterm>Checkpointer (process)</glossterm>
- <glossdef>
- <para>
- A specialized process responsible for executing checkpoints.
- </para>
- </glossdef>
- </glossentry>
-
<glossentry id="glossary-checkpoint">
<glossterm>Checkpoint</glossterm>
<glossdef>
@@ -244,6 +235,15 @@
</glossdef>
</glossentry>
+ <glossentry id="glossary-checkpointer">
+ <glossterm>Checkpointer (process)</glossterm>
+ <glossdef>
+ <para>
+ A specialized process responsible for executing checkpoints.
+ </para>
+ </glossdef>
+ </glossentry>
+
<glossentry>
<glossterm>Class (archaic)</glossterm>
<glosssee otherterm="glossary-relation" />
@@ -761,25 +761,6 @@
</glossdef>
</glossentry>
- <glossentry id="glossary-logger">
- <glossterm>Logger (process)</glossterm>
- <glossdef>
- <para>
- If activated, the
- <glossterm linkend="glossary-logger">Logger</glossterm> process
- writes information about database events into the current
- <glossterm linkend="glossary-log-file">log file</glossterm>.
- When reaching certain time- or
- volume-dependent criteria, a new log file is created.
- Also called <firstterm>syslogger</firstterm>.
- </para>
- <para>
- For more information, see
- <xref linkend="runtime-config-logging"/>.
- </para>
- </glossdef>
- </glossentry>
-
<glossentry id="glossary-log-record">
<glossterm>Log Record</glossterm>
<glossdef>
@@ -803,6 +784,25 @@
</glossdef>
</glossentry>
+ <glossentry id="glossary-logger">
+ <glossterm>Logger (process)</glossterm>
+ <glossdef>
+ <para>
+ If activated, the
+ <glossterm linkend="glossary-logger">Logger</glossterm> process
+ writes information about database events into the current
+ <glossterm linkend="glossary-log-file">log file</glossterm>.
+ When reaching certain time- or
+ volume-dependent criteria, a new log file is created.
+ Also called <firstterm>syslogger</firstterm>.
+ </para>
+ <para>
+ For more information, see
+ <xref linkend="runtime-config-logging"/>.
+ </para>
+ </glossdef>
+ </glossentry>
+
<glossentry>
<glossterm>Master (server)</glossterm>
<glosssee otherterm="glossary-primary-server" />
@@ -1651,6 +1651,11 @@
</glossdef>
</glossentry>
+ <glossentry>
+ <glossterm>WAL</glossterm>
+ <glosssee otherterm="glossary-wal" />
+ </glossentry>
+
<glossentry id="glossary-wal-archiver">
<glossterm>WAL Archiver (process)</glossterm>
<glossdef>
@@ -1696,11 +1701,6 @@
</glossdef>
</glossentry>
- <glossentry>
- <glossterm>WAL</glossterm>
- <glosssee otherterm="glossary-wal" />
- </glossentry>
-
<glossentry id="glossary-wal-record">
<glossterm>WAL Record</glossterm>
<glossdef>
@@ -1728,8 +1728,8 @@
<glossdef>
<para>
A process that writes <glossterm linkend="glossary-wal-record">WAL records</glossterm>
- from <glossterm id="linkend-shared-memory">shared memory</glossterm> to
- <glossterm id="linkend-wal-file">WAL files</glossterm>.
+ from <glossterm linkend="glossary-shared-memory">shared memory</glossterm> to
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
</para>
<para>
For more information, see
diff --git a/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
new file mode 100644
index 0000000000..6acb2b69fe
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
@@ -0,0 +1,160 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="685" viewBox="0 0 900 685">
+ <title>
+ Server (Hardware, Container, or VM)
+ </title>
+ <style>
+ .text_normal,.text_small{font-style:normal;font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_small{font-size:12px}.text_normal{font-size:16px}
+ </style>
+ <defs>
+ <symbol id="rectangles_special_0">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="rectangles_special_1">
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="125">
+ 'my_schema' (optional)
+ </text>
+ <text class="text_small" x="20" y="145">
+ tables, views, ...
+ </text>
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="190">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M450 10v230H0V0h440v10h10L440 0"/>
+ </symbol>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="270" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Server (Hardware, Container, or VM)
+ </text>
+ <path stroke="blue" stroke-width="2" fill="none" d="M20 110h790v555H20z"/>
+ <text class="text_normal" x="180" y="25" transform="translate(20 110)">
+ cluster 'data' (default, managed by one instance)
+ </text>
+ <path d="M50 110V80h790v555h-30" stroke="blue" stroke-width="2" fill="none"/>
+ <text class="text_normal" x="190" y="-10" transform="translate(45 110)">
+ cluster 'cluster_2' (optional, managed by a different instance)
+ </text>
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangles_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template0'
+ </text>
+ </g>
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangles_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template1'
+ </text>
+ </g>
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangles_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangles_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'my_db' (optional)
+ </text>
+ </g>
+ <g transform="translate(320 330)">
+ <rect width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4"/>
+ <text class="text_normal" x="15" y="27">
+ Global SQL objects
+ </text>
+ <path d="M0 5l-65-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M80 0v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M180 40h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M0 40l-45 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ </g>
+ <g transform="translate(335 405)">
+ <use xlink:href="#note"/>
+ <text class="text_small" x="10" y="20">
+ 1)
+ </text>
+ <text class="text_small" x="30" y="20">
+ By default, you work in the cluster 'data', database 'postgres',
+ </text>
+ <text class="text_small" x="30" y="35">
+ schema 'public'.
+ </text>
+ <text class="text_small" x="10" y="55">
+ 2)
+ </text>
+ <text class="text_small" x="30" y="55">
+ More system schemas: pg_catalog, information_schema,
+ </text>
+ <text class="text_small" x="30" y="70">
+ pg_temp, pg_toast.
+ </text>
+ <text class="text_small" x="10" y="90">
+ 3)
+ </text>
+ <text class="text_small" x="30" y="90">
+ Global SQL objects: Some SQL objects are automatically active
+ </text>
+ <text class="text_small" x="30" y="105">
+ and known database- or even cluster-wide.
+ </text>
+ <text class="text_small" x="10" y="125">
+ 4)
+ </text>
+ <text class="text_small" x="30" y="125">
+ The command 'initdb' creates a new cluster with the three
+ </text>
+ <text class="text_small" x="30" y="140">
+ databases 'template0', 'template1', and 'postgres'. The command
+ </text>
+ <text class="text_small" x="30" y="155">
+ 'createdb' creates a new database.
+ </text>
+ <text class="text_small" x="10" y="175">
+ 5)
+ </text>
+ <text class="text_small" x="30" y="175">
+ If multiple clusters are active on one server at the same time,
+ </text>
+ <text class="text_small" x="30" y="190">
+ each one is managed by an individual instance. Each such instance
+ </text>
+ <text class="text_small" x="30" y="205">
+ uses a different port.
+ </text>
+ <text class="text_small" x="10" y="225">
+ 6)
+ </text>
+ <text class="text_small" x="30" y="225">
+ No client application is allowed to connect to 'template0'.
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink.svg b/doc/src/sgml/images/cluster-db-schema-ink.svg
new file mode 100644
index 0000000000..a70fbe2102
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink.svg
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="685px"
+ viewBox="0 0 900 685"
+ id="svg147"
+ sodipodi:docname="cluster-db-schema-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Server (Hardware, Container, or VM)</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.34452555"
+ inkscape:cx="450"
+ inkscape:cy="342.5"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Server (Hardware, Container, or VM)</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs49">
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangles_special_0">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect6" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="195"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect8" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text10">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text12">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="195"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect14" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text16">(more system schemas)</text>
+ </symbol>
+ <!-- same as before, but one more schema -->
+ <symbol
+ id="rectangles_special_1">
+ <!-- the database -->
+ <rect
+ width="245"
+ height="225"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect19" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect21" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text23">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text25">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect27" />
+ <text
+ class="text_normal"
+ x="20"
+ y="125"
+ id="text29">'my_schema' (optional)</text>
+ <text
+ class="text_small"
+ x="20"
+ y="145"
+ id="text31">tables, views, ...</text>
+ <rect
+ x="15"
+ y="170"
+ width="205"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect33" />
+ <text
+ class="text_small"
+ x="20"
+ y="190"
+ id="text35">(more system schemas)</text>
+ </symbol>
+ <symbol
+ id="note"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title38">UML Note</title>
+ <path
+ d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10"
+ id="path40" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path43" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path46" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect51" />
+ <text
+ class="text_big"
+ x="270"
+ y="40"
+ id="text53">Server (Hardware, Container, or VM)</text>
+ <!-- two clusters -->
+ <g
+ transform="translate(20 110)"
+ id="g59">
+ <rect
+ x="0"
+ y="0"
+ width="790"
+ height="555"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="rect55" />
+ <text
+ class="text_normal"
+ x="180"
+ y="25"
+ id="text57">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g
+ transform="translate(45 110)"
+ id="g65">
+ <path
+ d="M 5,0 v -30 h 790 v 555 h -30"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="path61" />
+ <text
+ class="text_normal"
+ x="190"
+ y="-10"
+ id="text63">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+ <!-- database template 0 -->
+ <g
+ transform="translate(40 155)"
+ id="g71">
+ <use
+ xlink:href="#rectangles_special_0"
+ id="use67" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text69">database 'template0'</text>
+ </g>
+ <!-- database template 1 -->
+ <g
+ transform="translate(290 155)"
+ id="g77">
+ <use
+ xlink:href="#rectangles_special_0"
+ id="use73" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text75">database 'template1'</text>
+ </g>
+ <!-- database postgres -->
+ <g
+ transform="translate(540 155)"
+ id="g83">
+ <use
+ xlink:href="#rectangles_special_1"
+ id="use79" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text81">database 'postgres'</text>
+ </g>
+ <!-- database my_db -->
+ <g
+ transform="translate(40 350)"
+ id="g89">
+ <use
+ xlink:href="#rectangles_special_1"
+ id="use85" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text87">database 'my_db' (optional)</text>
+ </g>
+ <!-- global objects -->
+ <g
+ transform="translate(320 330)"
+ id="g103">
+ <rect
+ x="0"
+ y="0"
+ width="180"
+ height="45"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="10 4 4 4"
+ id="rect91" />
+ <text
+ class="text_normal"
+ x="15"
+ y="27"
+ id="text93">Global SQL objects</text>
+ <path
+ d="M 0,5 l-65,-35"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path95" />
+ <path
+ d="M 80,0 v-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path97" />
+ <path
+ d="M 180,40 h50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path99" />
+ <path
+ d="M 0,40 l-45,20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path101" />
+ </g>
+ <!-- Some comments -->
+ <g
+ transform="translate(335 405)"
+ id="g145">
+ <use
+ xlink:href="#note"
+ x="0"
+ y="0"
+ id="use105" />
+ <text
+ class="text_small"
+ x="10"
+ y="20"
+ id="text107">1)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="20"
+ id="text109">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text
+ class="text_small"
+ x="30"
+ y="35"
+ id="text111">schema 'public'.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="55"
+ id="text113">2)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="55"
+ id="text115">More system schemas: pg_catalog, information_schema,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="70"
+ id="text117">pg_temp, pg_toast.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="90"
+ id="text119">3)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="90"
+ id="text121">Global SQL objects: Some SQL objects are automatically active</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text123">and known database- or even cluster-wide.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="125"
+ id="text125">4)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="125"
+ id="text127">The command 'initdb' creates a new cluster with the three</text>
+ <text
+ class="text_small"
+ x="30"
+ y="140"
+ id="text129">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text
+ class="text_small"
+ x="30"
+ y="155"
+ id="text131">'createdb' creates a new database.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="175"
+ id="text133">5)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="175"
+ id="text135">If multiple clusters are active on one server at the same time,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="190"
+ id="text137">each one is managed by an individual instance. Each such instance</text>
+ <text
+ class="text_small"
+ x="30"
+ y="205"
+ id="text139">uses a different port.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="225"
+ id="text141">6)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="225"
+ id="text143">No client application is allowed to connect to 'template0'.</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
new file mode 100644
index 0000000000..a4919165e2
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="685px"
+ viewBox="0 0 900 685" >
+
+ <title>Server (Hardware, Container, or VM)</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangles_special_0">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">(more system schemas)</text>
+ </symbol>
+
+ <!-- same as before, but one more schema -->
+ <symbol id="rectangles_special_1">
+ <!-- the database -->
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="125">'my_schema' (optional)</text>
+ <text class="text_small" x="20" y="145">tables, views, ...</text>
+
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="190">(more system schemas)</text>
+ </symbol>
+
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="270" y="40">Server (Hardware, Container, or VM)</text>
+
+ <!-- two clusters -->
+ <g transform="translate(20 110)">
+ <rect x="0" y="0" width="790" height="555" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="180" y="25">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g transform="translate(45 110)">
+ <path d="M 5,0 v -30 h 790 v 555 h -30" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="190" y="-10">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+
+
+ <!-- database template 0 -->
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangles_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template0'</text>
+ </g>
+
+ <!-- database template 1 -->
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangles_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template1'</text>
+ </g>
+
+ <!-- database postgres -->
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangles_special_1" />
+ <text class="text_normal" x="10" y="25">database 'postgres'</text>
+ </g>
+
+ <!-- database my_db -->
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangles_special_1" />
+ <text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
+ </g>
+
+ <!-- global objects -->
+ <g transform="translate(320 330)">
+ <rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
+ <text class="text_normal" x="15" y="27">Global SQL objects</text>
+ <path d="M 0,5 l-65,-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ </g>
+
+ <!-- Some comments -->
+ <g transform="translate(335 405)">
+ <use xlink:href="#note" x="0" y="0" />
+
+ <text class="text_small" x="10" y="20">1)</text>
+ <text class="text_small" x="30" y="20">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text class="text_small" x="30" y="35">schema 'public'.</text>
+
+ <text class="text_small" x="10" y="55">2)</text>
+ <text class="text_small" x="30" y="55">More system schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="70">pg_temp, pg_toast.</text>
+
+ <text class="text_small" x="10" y="90">3)</text>
+ <text class="text_small" x="30" y="90">Global SQL objects: Some SQL objects are automatically active</text>
+ <text class="text_small" x="30" y="105">and known database- or even cluster-wide.</text>
+
+ <text class="text_small" x="10" y="125">4)</text>
+ <text class="text_small" x="30" y="125">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="140">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="155">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="175">5)</text>
+ <text class="text_small" x="30" y="175">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="190">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="205">uses a different port.</text>
+
+ <text class="text_small" x="10" y="225">6)</text>
+ <text class="text_small" x="30" y="225">No client application is allowed to connect to 'template0'.</text>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/directories-ink-svgo.svg b/doc/src/sgml/images/directories-ink-svgo.svg
new file mode 100644
index 0000000000..95fa76b9c6
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink-svgo.svg
@@ -0,0 +1,164 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="640" viewBox="0 0 900 640">
+ <title>
+ Directory structure of a cluster
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <symbol id="directory" stroke="blue" stroke-width=".3" fill="aqua">
+ <title>
+ Directory
+ </title>
+ <path d="M0 10h110v20H0z"/>
+ <path d="M0 10V8l3-3h35l3 3v2"/>
+ </symbol>
+ <symbol id="file" stroke="black" fill="none">
+ <title>
+ File
+ </title>
+ <path stroke="blue" d="M0 0h40v50H0z"/>
+ <path d="M5 10h20" stroke-dasharray="4 2"/>
+ <path d="M5 17h15" stroke-dasharray="6 2"/>
+ <path d="M5 24h25" stroke-dasharray="4 2"/>
+ <path d="M5 31h20" stroke-dasharray="5 2"/>
+ </symbol>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="50" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Directory Structure
+ </text>
+ <g transform="translate(20 100)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /pg/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ An arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 130)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ data/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of cluster 'data' (see: PGDATA)
+ </text>
+ </g>
+ <g transform="translate(120 160)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ base/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing per-database subdirectories
+ </text>
+ </g>
+ <g transform="translate(170 190)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 1/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of first database 'template0'
+ </text>
+ </g>
+ <g transform="translate(170 220)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12992/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of second database 'template1'
+ </text>
+ </g>
+ <g transform="translate(170 250)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12999/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of third database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(170 280)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ nnnnn/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Optional: more subdirectories for databases, e.g. 'my_db'
+ </text>
+ </g>
+ <g transform="translate(120 310)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ global/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory with information about Global SQL Objects
+ </text>
+ </g>
+ <g transform="translate(120 340)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_wal/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 370)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_xact/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for transaction commit status ('pg_clog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 400)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_tblspc/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing symbolic links to tablespaces
+ </text>
+ </g>
+ <g transform="translate(120 430)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_... /
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Some more subdirectories
+ </text>
+ </g>
+ <g transform="translate(120 465)">
+ <use xlink:href="#file"/>
+ <use xlink:href="#file" x="50"/>
+ <text x="200" y="26" class="text_normal">
+ 'postmaster.pid' and other files with cluster-wide relevance
+ </text>
+ </g>
+ <g transform="translate(20 540)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /xyz/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ Same or another arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 570)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ cluster_2/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of another cluster 'cluster_2'
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-ink.svg b/doc/src/sgml/images/directories-ink.svg
new file mode 100644
index 0000000000..4661ef13fb
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink.svg
@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="640px"
+ viewBox="0 0 900 640"
+ id="svg303"
+ sodipodi:docname="directories-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata307">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Directory structure of a cluster</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview305"
+ showgrid="false"
+ inkscape:zoom="0.36875"
+ inkscape:cx="450"
+ inkscape:cy="320"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg303" />
+ <title
+ id="title153">Directory structure of a cluster</title>
+ <style
+ type="text/css"
+ id="style155">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs177">
+ <!-- Directory -->
+ <symbol
+ id="directory"
+ stroke="blue"
+ stroke-width="0.3px"
+ fill="aqua">
+ <title
+ id="title157">Directory</title>
+ <rect
+ x="0"
+ y="10"
+ width="110"
+ height="20"
+ id="rect159" />
+ <path
+ d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2"
+ id="path161" />
+ </symbol>
+ <!-- File -->
+ <symbol
+ id="file"
+ stroke="black"
+ fill="none">
+ <title
+ id="title164">File</title>
+ <rect
+ x="0"
+ y="0"
+ width="40"
+ height="50"
+ stroke="blue"
+ id="rect166" />
+ <path
+ d="M 5,10 h 20"
+ stroke-dasharray="4 2"
+ id="path168" />
+ <path
+ d="M 5,17 h 15"
+ stroke-dasharray="6 2"
+ id="path170" />
+ <path
+ d="M 5,24 h 25"
+ stroke-dasharray="4 2"
+ id="path172" />
+ <path
+ d="M 5,31 h 20"
+ stroke-dasharray="5 2"
+ id="path174" />
+ </symbol>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect179" />
+ <!-- caption -->
+ <text
+ x="200"
+ y="50"
+ class="text_big"
+ id="text181">Directory Structure</text>
+ <!-- the directories -->
+ <g
+ transform="translate(20, 100)"
+ id="g189">
+ <use
+ xlink:href="#directory"
+ id="use183" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text185">... /pg/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text187">An arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 130)"
+ id="g197">
+ <use
+ xlink:href="#directory"
+ id="use191" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text193">data/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text195">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+ <g
+ transform="translate(120, 160)"
+ id="g205">
+ <use
+ xlink:href="#directory"
+ id="use199" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text201">base/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text203">Subdirectory containing per-database subdirectories</text>
+ </g>
+ <!-- -->
+ <g
+ transform="translate(170, 190)"
+ id="g213">
+ <use
+ xlink:href="#directory"
+ id="use207" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text209">1/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text211">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g
+ transform="translate(170, 220)"
+ id="g221">
+ <use
+ xlink:href="#directory"
+ id="use215" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text217">12992/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text219">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g
+ transform="translate(170, 250)"
+ id="g229">
+ <use
+ xlink:href="#directory"
+ id="use223" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text225">12999/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text227">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g
+ transform="translate(170, 280)"
+ id="g237">
+ <use
+ xlink:href="#directory"
+ id="use231" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text233">nnnnn/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text235">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+ <g
+ transform="translate(120, 310)"
+ id="g245">
+ <use
+ xlink:href="#directory"
+ id="use239" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text241">global/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text243">Subdirectory with information about Global SQL Objects</text>
+ </g>
+ <g
+ transform="translate(120, 340)"
+ id="g253">
+ <use
+ xlink:href="#directory"
+ id="use247" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text249">pg_wal/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text251">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 370)"
+ id="g261">
+ <use
+ xlink:href="#directory"
+ id="use255" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text257">pg_xact/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text259">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 400)"
+ id="g269">
+ <use
+ xlink:href="#directory"
+ id="use263" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text265">pg_tblspc/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text267">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+ <g
+ transform="translate(120, 430)"
+ id="g277">
+ <use
+ xlink:href="#directory"
+ id="use271" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text273">pg_... /</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text275">Some more subdirectories</text>
+ </g>
+ <g
+ transform="translate(120, 465)"
+ id="g285">
+ <use
+ xlink:href="#file"
+ x="0"
+ y="0"
+ id="use279" />
+ <use
+ xlink:href="#file"
+ x="50"
+ y="0"
+ id="use281" />
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text283">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+ <!-- next cluster -->
+ <g
+ transform="translate(20, 540)"
+ id="g293">
+ <use
+ xlink:href="#directory"
+ id="use287" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text289">... /xyz/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text291">Same or another arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 570)"
+ id="g301">
+ <use
+ xlink:href="#directory"
+ id="use295" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text297">cluster_2/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text299">Root of another cluster 'cluster_2'</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
new file mode 100644
index 0000000000..8869eb9390
--- /dev/null
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="640px"
+ viewBox="0 0 900 640">
+
+ <title>Directory structure of a cluster</title>
+
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Directory -->
+ <symbol id="directory" stroke="blue" stroke-width="0.3px" fill="aqua">
+ <title>Directory</title>
+ <rect x="0" y="10" width="110" height="20" />
+ <path d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2" />
+ </symbol>
+
+ <!-- File -->
+ <symbol id="file" stroke="black" fill="none" >
+ <title>File</title>
+ <rect x="0" y="0" width="40" height="50" stroke="blue" />
+ <path d="M 5,10 h 20" stroke-dasharray="4 2" />
+ <path d="M 5,17 h 15" stroke-dasharray="6 2" />
+ <path d="M 5,24 h 25" stroke-dasharray="4 2" />
+ <path d="M 5,31 h 20" stroke-dasharray="5 2" />
+ </symbol>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption -->
+ <text x="200" y="50" class="text_big">Directory Structure</text>
+
+ <!-- the directories -->
+ <g transform="translate(20, 100)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /pg/</text>
+ <text x="300" y="26" class="text_normal">An arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 130)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">data/</text>
+ <text x="250" y="26" class="text_normal">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+
+ <g transform="translate(120, 160)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">base/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing per-database subdirectories</text>
+ </g>
+
+ <!-- -->
+ <g transform="translate(170, 190)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">1/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g transform="translate(170, 220)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12992/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g transform="translate(170, 250)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12999/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g transform="translate(170, 280)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">nnnnn/</text>
+ <text x="150" y="26" class="text_normal">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+
+ <g transform="translate(120, 310)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">global/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory with information about Global SQL Objects</text>
+ </g>
+
+ <g transform="translate(120, 340)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 370)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 400)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+
+ <g transform="translate(120, 430)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_... /</text>
+ <text x="200" y="26" class="text_normal">Some more subdirectories</text>
+ </g>
+
+ <g transform="translate(120, 465)">
+ <use xlink:href="#file" x="0" y="0" />
+ <use xlink:href="#file" x="50" y="0" />
+ <text x="200" y="26" class="text_normal">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+
+ <!-- next cluster -->
+ <g transform="translate(20, 540)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /xyz/</text>
+ <text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 570)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster 'cluster_2'</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
new file mode 100644
index 0000000000..4156bbc834
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
@@ -0,0 +1,83 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="720" height="430" viewBox="0 0 720 430">
+ <title>
+ Hierarchy of Internal Objects
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Hierarchy of Internal Objects
+ </text>
+ <g fill="none">
+ <g transform="translate(350 240)">
+ <ellipse rx="320" ry="170" stroke="blue"/>
+ <text class="text_normal" x="-140" y="-130">
+ Cluster
+ </text>
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-60" y="5">
+ Database Names
+ </text>
+ </g>
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-40" y="5">
+ Tablespace
+ </text>
+ </g>
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-70" y="5">
+ Replication Origins
+ </text>
+ </g>
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue"/>
+ <text class="text_normal" x="-60" y="-3">
+ Subscription for
+ </text>
+ <text class="text_normal" x="-68" y="10">
+ Logical Replication
+ </text>
+ </g>
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-15" y="5">
+ Role
+ </text>
+ </g>
+ </g>
+ <g transform="translate(270 250)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2"/>
+ <text class="text_normal" x="-60" y="-80">
+ Database
+ </text>
+ <g transform="translate(-150 -30)">
+ <ellipse rx="50" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Extension
+ </text>
+ </g>
+ <g transform="translate(-155 35)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Collation
+ </text>
+ </g>
+ <g transform="translate(30 20)">
+ <ellipse rx="140" ry="70" stroke="blue"/>
+ <text class="text_normal" x="-80" y="-35">
+ Schema
+ </text>
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue"/>
+ <text class="text_normal" x="-50" y="5">
+ Table, View, ...
+ </text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
new file mode 100644
index 0000000000..cf03d6a701
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="720px"
+ height="430px"
+ viewBox="0 0 720 430"
+ id="svg389"
+ sodipodi:docname="internal-objects-hierarchy-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata395">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Hierarchy of Internal Objects</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs393" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="906"
+ inkscape:window-height="678"
+ id="namedview391"
+ showgrid="false"
+ inkscape:zoom="0.51944444"
+ inkscape:cx="360"
+ inkscape:cy="215"
+ inkscape:window-x="502"
+ inkscape:window-y="91"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg389" />
+ <title
+ id="title309">Hierarchy of Internal Objects</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style311">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect313" />
+ <text
+ class="text_big"
+ x="200"
+ y="40"
+ id="text315">Hierarchy of Internal Objects</text>
+ <!-- set centre of figure and default values -->
+ <g
+ transform="translate(350 240)"
+ fill="none"
+ id="g387">
+ <g
+ id="g353">
+ <ellipse
+ rx="320"
+ ry="170"
+ stroke="blue"
+ id="ellipse317" />
+ <text
+ class="text_normal"
+ x="-140"
+ y="-130"
+ id="text319">Cluster</text>
+ <g
+ transform="translate(40 -125)"
+ id="g325">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse321" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="5"
+ id="text323">Database Names</text>
+ </g>
+ <g
+ transform="translate(180 -70)"
+ id="g331">
+ <ellipse
+ rx="60"
+ ry="20"
+ stroke="blue"
+ id="ellipse327" />
+ <text
+ class="text_normal"
+ x="-40"
+ y="5"
+ id="text329">Tablespace</text>
+ </g>
+ <g
+ transform="translate(230 -5)"
+ id="g337">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse333" />
+ <text
+ class="text_normal"
+ x="-70"
+ y="5"
+ id="text335">Replication Origins</text>
+ </g>
+ <g
+ transform="translate(200 70)"
+ id="g345">
+ <ellipse
+ rx="78"
+ ry="27"
+ stroke="blue"
+ id="ellipse339" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-3"
+ id="text341">Subscription for</text>
+ <text
+ class="text_normal"
+ x="-68"
+ y="10"
+ id="text343">Logical Replication</text>
+ </g>
+ <g
+ transform="translate(100 120)"
+ id="g351">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse347" />
+ <text
+ class="text_normal"
+ x="-15"
+ y="5"
+ id="text349">Role</text>
+ </g>
+ </g>
+ <g
+ transform="translate(-80 10)"
+ id="g385">
+ <ellipse
+ rx="220"
+ ry="110"
+ stroke="blue"
+ stroke-width="2px"
+ id="ellipse355" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-80"
+ id="text357">Database</text>
+ <g
+ transform="translate(-120 -50)"
+ id="g383">
+ <g
+ transform="translate(-30 20)"
+ id="g363">
+ <ellipse
+ rx="50"
+ ry="20"
+ stroke="blue"
+ id="ellipse359" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text361">Extension</text>
+ </g>
+ <g
+ transform="translate(-35 85)"
+ id="g369">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse365" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text367">Collation</text>
+ </g>
+ <g
+ transform="translate(150 70)"
+ id="g381">
+ <ellipse
+ rx="140"
+ ry="70"
+ stroke="blue"
+ id="ellipse371" />
+ <text
+ class="text_normal"
+ x="-80"
+ y="-35"
+ id="text373">Schema</text>
+ <g
+ transform="translate(20 10)"
+ id="g379">
+ <ellipse
+ rx="90"
+ ry="30"
+ stroke="blue"
+ id="ellipse375" />
+ <text
+ class="text_normal"
+ x="-50"
+ y="5"
+ id="text377">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
new file mode 100644
index 0000000000..45387bbd9b
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="720px" height="430px"
+ viewBox="0 0 720 430" >
+
+ <title>Hierarchy of Internal Objects</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="200" y="40">Hierarchy of Internal Objects</text>
+
+
+ <!-- set centre of figure and default values -->
+ <g transform="translate(350 240)" fill="none">
+
+ <g>
+ <ellipse rx="320" ry="170" stroke="blue" />
+ <text class="text_normal" x="-140" y="-130">Cluster</text>
+
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-60" y="5">Database Names</text>
+ </g>
+
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue" />
+ <text class="text_normal" x="-40" y="5">Tablespace</text>
+ </g>
+
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-70" y="5">Replication Origins</text>
+ </g>
+
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue" />
+ <text class="text_normal" x="-60" y="-3">Subscription for</text>
+ <text class="text_normal" x="-68" y="10">Logical Replication</text>
+ </g>
+
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-15" y="5">Role</text>
+ </g>
+
+ </g>
+
+ <g transform="translate(-80 10)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2px" />
+ <text class="text_normal" x="-60" y="-80">Database</text>
+
+ <g transform="translate(-120 -50)">
+ <g transform="translate(-30 20)">
+ <ellipse rx="50" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Extension</text>
+ </g>
+
+ <g transform="translate(-35 85)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Collation</text>
+ </g>
+
+ <g transform="translate(150 70)">
+ <ellipse rx="140" ry="70" stroke="blue" />
+ <text class="text_normal" x="-80" y="-35">Schema</text>
+
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue" />
+ <text class="text_normal" x="-50" y="5">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink-svgo.svg b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
new file mode 100644
index 0000000000..bf638f6c63
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
@@ -0,0 +1,285 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 900 600">
+ <title>
+ PG Overall Server Architecture
+ </title>
+ <style>
+ .text_big{font-style:normal}.text_big,.text_comment,.text_normal,.text_small{font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_normal,.text_small{font-style:normal}.text_small{font-size:12px}.text_normal{font-size:16px}.text_big{font-size:24px}.text_comment{font-style:italic;font-size:16px}
+ </style>
+ <defs>
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (200 x 20 px)
+ </title>
+ <path d="M200 10v10H0V0h190v10h10L190 0"/>
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (250 x 20 px)
+ </title>
+ <path d="M250 10v10H0V0h240v10h10L240 0"/>
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (100 x 35 px)
+ </title>
+ <path d="M100 10v25H0V0h90v10h10L90 0"/>
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (170 x 50 px)
+ </title>
+ <path d="M170 10v40H0V0h160v10h10L160 0"/>
+ </symbol>
+ <symbol id="state_300x120">
+ <title>
+ UML State, big
+ </title>
+ <rect width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>
+ UML State, big
+ </title>
+ <rect width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="disc" stroke="blue" fill="none">
+ <title>
+ Disc
+ </title>
+ <ellipse cx="51" cy="13" rx="50" ry="12"/>
+ <path d="M1 13v60"/>
+ <path d="M101 13v60"/>
+ <path d="M1 73a50 12 0 00100 0"/>
+ </symbol>
+ <symbol id="laptop" stroke="black" fill="none">
+ <title>
+ Laptop
+ </title>
+ <path d="M20 40V0h54v40l15 15H5l15-15h54"/>
+ <path d="M23 3h48v34H23z"/>
+ <path d="M30 10h20"/>
+ <path d="M30 15h25"/>
+ <path d="M30 20h10"/>
+ <path d="M30 30h20"/>
+ <path d="M25 50h45l2 2H22z"/>
+ </symbol>
+ <marker id="arrowhead_start" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto">
+ <path d="M6 0L0 3l6 3" stroke="black" fill="none"/>
+ </marker>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="15" y="40" class="text_big">
+ Client
+ </text>
+ <text x="140" y="40" class="text_big">
+ Server
+ </text>
+ <use xlink:href="#laptop" x="5" y="210"/>
+ <g transform="translate(130 70)">
+ <use xlink:href="#state_350x120"/>
+ <text x="5" y="20" class="text_normal">
+ maintenance_work_mem (per connection)
+ </text>
+ <text x="5" y="45" class="text_normal">
+ work_mem (per query operation)
+ </text>
+ <text x="5" y="70" class="text_normal">
+ autovacuum_work_mem (per worker process)
+ </text>
+ <text x="5" y="95" class="text_normal">
+ temp_buffer (per connection)
+ </text>
+ <text x="5" y="110" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_200x20" x="140" y="-15"/>
+ <text x="150" class="text_comment">
+ Individual Memory
+ </text>
+ </g>
+ <g transform="translate(520 70)">
+ <use xlink:href="#state_300x120"/>
+ <text x="10" y="30" class="text_normal">
+ shared_buffers (heap and index)
+ </text>
+ <text x="10" y="70" class="text_normal">
+ wal_buffers (WAL records)
+ </text>
+ <text x="10" y="100" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_250x20" x="40" y="-15"/>
+ <text x="50" class="text_comment">
+ Shared Memory (per Cluster)
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M190 215h200v30H190z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(190 215)">
+ Postmaster process
+ </text>
+ <path d="M90 230h85" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 230)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 1
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M150 315h370v30H150z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(150 315)">
+ Backend processes (one per connection)
+ </text>
+ <path d="M155 315v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M160 310v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M90 240l63 63" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 290)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 3
+ </text>
+ </g>
+ <path d="M360 250v50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(190 255)">
+ <use xlink:href="#note_250x20"/>
+ <text x="10" y="15" class="text_comment">
+ Creates backend processes
+ </text>
+ </g>
+ <g transform="translate(360 281)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 2
+ </text>
+ </g>
+ <path d="M460 300V200" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M498 300V95h30" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M508 300V135h20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M550 220h120v30H550z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(550 220)">
+ WAL Writer
+ </text>
+ <path d="M590 150v65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M590 255v230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 340h140v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 340)">
+ Checkpointer
+ </text>
+ <path d="M740 110v220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 355H475v130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M700 330V150" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50"/>
+ <text x="60" y="-35" class="text_comment">
+ Checkpoint
+ </text>
+ <text x="60" y="-20" class="text_comment">
+ Record
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M610 380h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 380)">
+ Background Writer
+ </text>
+ <path d="M770 110v260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 395H485v90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 420h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 420)">
+ WAL Archiver
+ </text>
+ <path d="M620 485l30-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M740 455v30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M135 380h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 380)">
+ AutoVacuum
+ </text>
+ <path d="M140 380v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path d="M145 375v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path stroke="blue" fill="none" d="M135 430h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 430)">
+ Log Writer
+ </text>
+ <path stroke="blue" fill="none" d="M290 370h140v30H290z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(290 370)">
+ Stats Collector
+ </text>
+ <g transform="translate(145 490)">
+ <use xlink:href="#disc"/>
+ <text x="35" y="45" class="text_normal">
+ Log
+ </text>
+ <text x="20" y="60" class="text_small">
+ text lines,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <path d="M195 465v20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(410 490)">
+ <use xlink:href="#disc"/>
+ <text x="10" y="40" class="text_normal">
+ Heap and
+ </text>
+ <text x="25" y="55" class="text_normal">
+ Index
+ </text>
+ <text x="15" y="70" class="text_small">
+ binary blocks,
+ </text>
+ <text x="30" y="80" class="text_small">
+ random
+ </text>
+ </g>
+ <path d="M450 485V350" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(295 420)">
+ <use xlink:href="#note_170x50"/>
+ <text x="5" y="15" class="text_comment">
+ Read heap and index
+ </text>
+ <text x="5" y="30" class="text_comment">
+ pages and transfer
+ </text>
+ <text x="5" y="45" class="text_comment">
+ them to shared_buffers
+ </text>
+ </g>
+ <g transform="translate(550 490)">
+ <use xlink:href="#disc"/>
+ <text x="30" y="45" class="text_normal">
+ WAL
+ </text>
+ <text x="10" y="60" class="text_small">
+ binary records,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <g transform="translate(690 490)">
+ <use xlink:href="#disc"/>
+ <text x="16" y="45" class="text_normal">
+ Archived
+ </text>
+ <text x="36" y="60" class="text_normal">
+ WAL
+ </text>
+ </g>
+ <path d="M110 20v550" stroke="black" fill="none"/>
+ <g transform="rotate(90 -33.5 156.5)">
+ <use xlink:href="#note_200x20"/>
+ <text class="text_comment" x="10" y="15">
+ Via TCP/IP or socket
+ </text>
+ </g>
+ <text class="text_big" x="95" transform="rotate(90 425 425)">
+ RAM
+ </text>
+ <text class="text_big" x="250" transform="rotate(90 425 425)">
+ PROCESSES
+ </text>
+ <text class="text_big" x="500" transform="rotate(90 425 425)">
+ FILES
+ </text>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink.svg b/doc/src/sgml/images/ram-proc-file-ink.svg
new file mode 100644
index 0000000000..6c960702a0
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink.svg
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="600px"
+ viewBox="0 0 900 600"
+ id="svg701"
+ sodipodi:docname="ram-proc-file-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata705">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>PG Overall Server Architecture</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="846"
+ inkscape:window-height="675"
+ id="namedview703"
+ showgrid="false"
+ inkscape:zoom="0.39333333"
+ inkscape:cx="450"
+ inkscape:cy="300"
+ inkscape:window-x="503"
+ inkscape:window-y="91"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg701" />
+ <title
+ id="title397">PG Overall Server Architecture</title>
+ <style
+ type="text/css"
+ id="style399">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs465">
+ <!-- Some notes in different sizes -->
+ <symbol
+ id="note_200x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title401">UML Note (200 x 20 px)</title>
+ <path
+ d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10"
+ id="path403" />
+ </symbol>
+ <symbol
+ id="note_250x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title406">UML Note (250 x 20 px)</title>
+ <path
+ d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10"
+ id="path408" />
+ </symbol>
+ <symbol
+ id="note_100x35"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title411">UML Note (100 x 35 px)</title>
+ <path
+ d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10"
+ id="path413" />
+ </symbol>
+ <symbol
+ id="note_170x50"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title416">UML Note (170 x 50 px)</title>
+ <path
+ d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10"
+ id="path418" />
+ </symbol>
+ <!-- UML states (used for buffers) -->
+ <symbol
+ id="state_300x120">
+ <title
+ id="title421">UML State, big</title>
+ <rect
+ x="0"
+ y="0"
+ width="300"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect423" />
+ </symbol>
+ <symbol
+ id="state_350x120">
+ <title
+ id="title426">UML State, big</title>
+ <rect
+ x="0"
+ y="0"
+ width="350"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect428" />
+ </symbol>
+ <!-- Discs -->
+ <symbol
+ id="disc"
+ stroke="blue"
+ fill="none">
+ <title
+ id="title431">Disc</title>
+ <ellipse
+ cx="51"
+ cy="13"
+ rx="50"
+ ry="12"
+ id="ellipse433" />
+ <!-- top -->
+ <path
+ d="M 1,13 v 60"
+ id="path435" />
+ <!-- left -->
+ <path
+ d="M 101,13 v 60"
+ id="path437" />
+ <!-- right -->
+ <path
+ d="M 1,73 A 50, 12, 0, 0, 0, 101,73"
+ id="path439" />
+ <!-- bottom -->
+ </symbol>
+ <!-- Laptop -->
+ <symbol
+ id="laptop"
+ stroke="black"
+ fill="none">
+ <title
+ id="title442">Laptop</title>
+ <path
+ d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54"
+ id="path444" />
+ <rect
+ x="23"
+ y="3"
+ width="48"
+ height="34"
+ id="rect446" />
+ <!-- symbolize some lines -->
+ <path
+ d="M 30,10 h 20"
+ id="path448" />
+ <path
+ d="M 30,15 h 25"
+ id="path450" />
+ <path
+ d="M 30,20 h 10"
+ id="path452" />
+ <path
+ d="M 30,30 h 20"
+ id="path454" />
+ <!-- symbolize keyboard -->
+ <path
+ d="M 25,50 h 45 l 2,2 h -50 z "
+ id="path456" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path459" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path462" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect467" />
+ <!-- caption, client side -->
+ <text
+ x="15"
+ y="40"
+ class="text_big"
+ id="text469">Client</text>
+ <text
+ x="140"
+ y="40"
+ class="text_big"
+ id="text471">Server</text>
+ <use
+ xlink:href="#laptop"
+ x="5"
+ y="210"
+ id="use473" />
+ <!-- individual memory -->
+ <g
+ transform="translate(130, 70)"
+ id="g491">
+ <use
+ xlink:href="#state_350x120"
+ x="0"
+ y="0"
+ id="use475" />
+ <text
+ x="5"
+ y="20"
+ class="text_normal"
+ id="text477">maintenance_work_mem (per connection)</text>
+ <text
+ x="5"
+ y="45"
+ class="text_normal"
+ id="text479">work_mem (per query operation)</text>
+ <text
+ x="5"
+ y="70"
+ class="text_normal"
+ id="text481">autovacuum_work_mem (per worker process)</text>
+ <text
+ x="5"
+ y="95"
+ class="text_normal"
+ id="text483">temp_buffer (per connection)</text>
+ <text
+ x="5"
+ y="110"
+ class="text_normal"
+ id="text485">...</text>
+ <use
+ xlink:href="#note_200x20"
+ x="140"
+ y="-15"
+ id="use487" />
+ <text
+ x="150"
+ y="0"
+ class="text_comment"
+ id="text489">Individual Memory</text>
+ </g>
+ <!-- shared memory -->
+ <g
+ transform="translate(520, 70)"
+ id="g505">
+ <use
+ xlink:href="#state_300x120"
+ x="0"
+ y="0"
+ id="use493" />
+ <text
+ x="10"
+ y="30"
+ class="text_normal"
+ id="text495">shared_buffers (heap and index)</text>
+ <text
+ x="10"
+ y="70"
+ class="text_normal"
+ id="text497">wal_buffers (WAL records)</text>
+ <text
+ x="10"
+ y="100"
+ class="text_normal"
+ id="text499">...</text>
+ <use
+ xlink:href="#note_250x20"
+ x="40"
+ y="-15"
+ id="use501" />
+ <text
+ x="50"
+ y="0"
+ class="text_comment"
+ id="text503">Shared Memory (per Cluster)</text>
+ </g>
+ <!-- postmaster -->
+ <g
+ transform="translate(190, 215)"
+ id="g511">
+ <rect
+ width="200"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect507" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text509">Postmaster process</text>
+ </g>
+ <path
+ d="M 90,230 h 85"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path513" />
+ <g
+ transform="translate(140, 230)"
+ id="g519">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle515" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text517">1</text>
+ </g>
+ <!-- backend processes -->
+ <g
+ transform="translate(150, 315)"
+ id="g529">
+ <rect
+ width="370"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect521" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text523">Backend processes (one per connection)</text>
+ <path
+ d="M 5,0 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path525" />
+ <path
+ d="M 10,-5 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path527" />
+ </g>
+ <path
+ d="M 90,240 153,303"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path531" />
+ <g
+ transform="translate(140, 290)"
+ id="g537">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle533" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text535">3</text>
+ </g>
+ <!-- connection between postmaster and backend processes -->
+ <path
+ d="M 360,250 v 50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path539" />
+ <g
+ transform="translate(190, 255)"
+ id="g545">
+ <use
+ xlink:href="#note_250x20"
+ id="use541" />
+ <text
+ x="10"
+ y="15"
+ class="text_comment"
+ id="text543">Creates backend processes</text>
+ </g>
+ <g
+ transform="translate(360, 281)"
+ id="g551">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle547" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text549">2</text>
+ </g>
+ <!-- backend process' access to individual memory -->
+ <path
+ d="M 460,300 v -100"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path553" />
+ <!-- its access to shared buffers and WAL buffers -->
+ <path
+ d="M 498,300 v -205 h 30"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path555" />
+ <path
+ d="M 508,300 v -165 h 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path557" />
+ <!-- WAL writer -->
+ <g
+ transform="translate(550, 220)"
+ id="g563">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect559" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text561">WAL Writer</text>
+ </g>
+ <path
+ d="M 590,150 v 65"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path565" />
+ <path
+ d="M 590,255 v 230"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path567" />
+ <!-- Checkpoiner -->
+ <g
+ transform="translate(610, 340)"
+ id="g573">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect569" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text571">Checkpointer</text>
+ </g>
+ <path
+ d="M 740,110 v 220"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path575" />
+ <path
+ d="M 605,355 h -130 v 130"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path577" />
+ <path
+ d="M 700,330 v -180"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path579" />
+ <g
+ transform="translate(570, 330)"
+ id="g587">
+ <use
+ xlink:href="#note_100x35"
+ x="50"
+ y="-50"
+ id="use581" />
+ <text
+ x="60"
+ y="-35"
+ class="text_comment"
+ id="text583">Checkpoint</text>
+ <text
+ x="60"
+ y="-20"
+ class="text_comment"
+ id="text585">Record</text>
+ </g>
+ <!-- BG writer -->
+ <g
+ transform="translate(610, 380)"
+ id="g593">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect589" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text591">Background Writer</text>
+ </g>
+ <path
+ d="M 770,110 v 260"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path595" />
+ <path
+ d="M 605,395 h -120 v 90"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path597" />
+ <!-- Archiver -->
+ <g
+ transform="translate(610, 420)"
+ id="g603">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect599" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text601">WAL Archiver</text>
+ </g>
+ <path
+ d="M 620,485 l 30,-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path605" />
+ <path
+ d="M 740,455 v 30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path607" />
+ <!-- Vacuum -->
+ <g
+ transform="translate(135, 380)"
+ id="g617">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect609" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text611">AutoVacuum</text>
+ <path
+ d="M 5,0 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path613" />
+ <path
+ d="M 10,-5 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path615" />
+ </g>
+ <!-- Log Writer -->
+ <g
+ transform="translate(135, 430)"
+ id="g623">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect619" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text621">Log Writer</text>
+ </g>
+ <!-- Stats Collector (135, 460) -->
+ <g
+ transform="translate(290, 370)"
+ id="g629">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect625" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text627">Stats Collector</text>
+ </g>
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g
+ transform="translate(145, 490)"
+ id="g639">
+ <use
+ xlink:href="#disc"
+ id="use631" />
+ <text
+ x="35"
+ y="45"
+ class="text_normal"
+ id="text633">Log</text>
+ <text
+ x="20"
+ y="60"
+ class="text_small"
+ id="text635">text lines,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text637">sequential</text>
+ </g>
+ <path
+ d="M 195,465 v 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path641" />
+ <g
+ transform="translate(410, 490)"
+ id="g653">
+ <use
+ xlink:href="#disc"
+ id="use643" />
+ <text
+ x="10"
+ y="40"
+ class="text_normal"
+ id="text645">Heap and</text>
+ <text
+ x="25"
+ y="55"
+ class="text_normal"
+ id="text647">Index</text>
+ <text
+ x="15"
+ y="70"
+ class="text_small"
+ id="text649">binary blocks,</text>
+ <text
+ x="30"
+ y="80"
+ class="text_small"
+ id="text651">random</text>
+ </g>
+ <path
+ d="M 450,485 v -135"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path655" />
+ <g
+ transform="translate(295, 420)"
+ id="g665">
+ <use
+ xlink:href="#note_170x50"
+ id="use657" />
+ <text
+ x="5"
+ y="15"
+ class="text_comment"
+ id="text659">Read heap and index</text>
+ <text
+ x="5"
+ y="30"
+ class="text_comment"
+ id="text661">pages and transfer</text>
+ <text
+ x="5"
+ y="45"
+ class="text_comment"
+ id="text663">them to shared_buffers</text>
+ </g>
+ <g
+ transform="translate(550, 490)"
+ id="g675">
+ <use
+ xlink:href="#disc"
+ id="use667" />
+ <text
+ x="30"
+ y="45"
+ class="text_normal"
+ id="text669">WAL</text>
+ <text
+ x="10"
+ y="60"
+ class="text_small"
+ id="text671">binary records,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text673">sequential</text>
+ </g>
+ <g
+ transform="translate(690, 490)"
+ id="g683">
+ <use
+ xlink:href="#disc"
+ id="use677" />
+ <text
+ x="16"
+ y="45"
+ class="text_normal"
+ id="text679">Archived</text>
+ <text
+ x="36"
+ y="60"
+ class="text_normal"
+ id="text681">WAL</text>
+ </g>
+ <!-- boarder between client and server side -->
+ <path
+ d="M 110,20 v 550"
+ stroke="black"
+ fill="none"
+ id="path685" />
+ <g
+ transform="translate(123, 190) rotate(90)"
+ id="g691">
+ <use
+ xlink:href="#note_200x20"
+ id="use687" />
+ <text
+ class="text_comment"
+ x="10"
+ y="15"
+ id="text689">Via TCP/IP or socket</text>
+ </g>
+ <!-- right side -->
+ <g
+ transform="translate(850, 0) rotate(90)"
+ id="g699">
+ <text
+ class="text_big"
+ x="95"
+ id="text693">RAM</text>
+ <text
+ class="text_big"
+ x="250"
+ id="text695">PROCESSES</text>
+ <text
+ class="text_big"
+ x="500"
+ id="text697">FILES</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-raw.svg b/doc/src/sgml/images/ram-proc-file-raw.svg
new file mode 100644
index 0000000000..26eacde411
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-raw.svg
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="600px"
+ viewBox="0 0 900 600">
+
+ <title>PG Overall Server Architecture</title>
+
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Some notes in different sizes -->
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>UML Note (200 x 20 px)</title>
+ <path d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>UML Note (250 x 20 px)</title>
+ <path d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>UML Note (100 x 35 px)</title>
+ <path d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>UML Note (170 x 50 px)</title>
+ <path d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- UML states (used for buffers) -->
+ <symbol id="state_300x120">
+ <title>UML State, big</title>
+ <rect x="0" y="0" width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>UML State, big</title>
+ <rect x="0" y="0" width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- Discs -->
+ <symbol id="disc" stroke="blue" fill="none" >
+ <title>Disc</title>
+ <ellipse cx="51" cy="13" rx="50" ry="12" /> <!-- top -->
+ <path d="M 1,13 v 60" /> <!-- left -->
+ <path d="M 101,13 v 60" /> <!-- right -->
+ <path d="M 1,73 A 50, 12, 0, 0, 0, 101,73" /> <!-- bottom -->
+ </symbol>
+
+ <!-- Laptop -->
+ <symbol id="laptop" stroke="black" fill="none" >
+ <title>Laptop</title>
+ <path d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54" />
+ <rect x="23" y="3" width="48" height="34" />
+ <!-- symbolize some lines -->
+ <path d="M 30,10 h 20" />
+ <path d="M 30,15 h 25" />
+ <path d="M 30,20 h 10" />
+ <path d="M 30,30 h 20" />
+ <!-- symbolize keyboard -->
+ <path d="M 25,50 h 45 l 2,2 h -50 z " />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption, client side -->
+ <text x="15" y="40" class="text_big">Client</text>
+ <text x="140" y="40" class="text_big">Server</text>
+ <use xlink:href="#laptop" x="5" y="210" />
+
+
+ <!-- individual memory -->
+ <g transform="translate(130, 70)">
+ <use xlink:href="#state_350x120" x="0" y="0" />
+ <text x="5" y="20" class="text_normal">maintenance_work_mem (per connection)</text>
+ <text x="5" y="45" class="text_normal">work_mem (per query operation)</text>
+ <text x="5" y="70" class="text_normal">autovacuum_work_mem (per worker process)</text>
+ <text x="5" y="95" class="text_normal">temp_buffer (per connection)</text>
+ <text x="5" y="110" class="text_normal">...</text>
+ <use xlink:href="#note_200x20" x="140" y="-15" />
+ <text x="150" y="0" class="text_comment">Individual Memory</text>
+ </g>
+
+ <!-- shared memory -->
+ <g transform="translate(520, 70)">
+ <use xlink:href="#state_300x120" x="0" y="0" />
+ <text x="10" y="30" class="text_normal">shared_buffers (heap and index)</text>
+ <text x="10" y="70" class="text_normal">wal_buffers (WAL records)</text>
+ <text x="10" y="100" class="text_normal">...</text>
+ <use xlink:href="#note_250x20" x="40" y="-15" />
+ <text x="50" y="0" class="text_comment">Shared Memory (per Cluster)</text>
+ </g>
+
+ <!-- postmaster -->
+ <g transform="translate(190, 215)">
+ <rect width="200" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Postmaster process</text>
+ </g>
+ <path d="M 90,230 h 85" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 230)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">1</text>
+ </g>
+
+ <!-- backend processes -->
+ <g transform="translate(150, 315)">
+ <rect width="370" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Backend processes (one per connection)</text>
+ <path d="M 5,0 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <path d="M 90,240 153,303" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 290)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">3</text>
+ </g>
+
+ <!-- connection between postmaster and backend processes -->
+ <path d="M 360,250 v 50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(190, 255)">
+ <use xlink:href="#note_250x20" />
+ <text x="10" y="15" class="text_comment">Creates backend processes</text>
+ </g>
+ <g transform="translate(360, 281)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">2</text>
+ </g>
+
+ <!-- backend process' access to individual memory -->
+ <path d="M 460,300 v -100" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <!-- its access to shared buffers and WAL buffers -->
+ <path d="M 498,300 v -205 h 30" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M 508,300 v -165 h 20" stroke="black" fill="none"
+ marker-end="url(#arrowhead_end)"/>
+
+ <!-- WAL writer -->
+ <g transform="translate(550, 220)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Writer</text>
+ </g>
+ <path d="M 590,150 v 65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 590,255 v 230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Checkpoiner -->
+ <g transform="translate(610, 340)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Checkpointer</text>
+ </g>
+ <path d="M 740,110 v 220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,355 h -130 v 130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 700,330 v -180" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570, 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50" />
+ <text x="60" y="-35" class="text_comment">Checkpoint</text>
+ <text x="60" y="-20" class="text_comment">Record</text>
+ </g>
+
+ <!-- BG writer -->
+ <g transform="translate(610, 380)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Background Writer</text>
+ </g>
+ <path d="M 770,110 v 260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,395 h -120 v 90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Archiver -->
+ <g transform="translate(610, 420)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Archiver</text>
+ </g>
+ <path d="M 620,485 l 30,-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 740,455 v 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Vacuum -->
+ <g transform="translate(135, 380)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">AutoVacuum</text>
+ <path d="M 5,0 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <!-- Log Writer -->
+ <g transform="translate(135, 430)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Log Writer</text>
+ </g>
+
+ <!-- Stats Collector (135, 460) -->
+ <g transform="translate(290, 370)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Stats Collector</text>
+ </g>
+
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g transform="translate(145, 490)">
+ <use xlink:href="#disc" />
+ <text x="35" y="45" class="text_normal">Log</text>
+ <text x="20" y="60" class="text_small">text lines,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+ <path d="M 195,465 v 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(410, 490)">
+ <use xlink:href="#disc" />
+ <text x="10" y="40" class="text_normal">Heap and</text>
+ <text x="25" y="55" class="text_normal">Index</text>
+ <text x="15" y="70" class="text_small">binary blocks,</text>
+ <text x="30" y="80" class="text_small">random</text>
+ </g>
+ <path d="M 450,485 v -135" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(295, 420)">
+ <use xlink:href="#note_170x50" />
+ <text x="5" y="15" class="text_comment">Read heap and index</text>
+ <text x="5" y="30" class="text_comment">pages and transfer</text>
+ <text x="5" y="45" class="text_comment">them to shared_buffers</text>
+ </g>
+
+ <g transform="translate(550, 490)">
+ <use xlink:href="#disc" />
+ <text x="30" y="45" class="text_normal">WAL</text>
+ <text x="10" y="60" class="text_small">binary records,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+
+ <g transform="translate(690, 490)">
+ <use xlink:href="#disc" />
+ <text x="16" y="45" class="text_normal">Archived</text>
+ <text x="36" y="60" class="text_normal">WAL</text>
+ </g>
+
+ <!-- boarder between client and server side -->
+ <path d="M 110,20 v 550" stroke="black" fill="none" />
+ <g transform="translate(123, 190) rotate(90)">
+ <use xlink:href="#note_200x20" />
+ <text class="text_comment" x="10" y ="15">Via TCP/IP or socket</text>
+ </g>
+
+ <!-- right side -->
+ <g transform="translate(850, 0) rotate(90)">
+ <text class="text_big" x="95">RAM</text>
+ <text class="text_big" x="250">PROCESSES</text>
+ <text class="text_big" x="500">FILES</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index c41ce9499b..6254bf9376 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -60,6 +60,7 @@ break is not needed in a wider output rendering.
</partintro>
&start;
+ &architecture;
&query;
&advanced;
On 20.04.20 10:30, Jürgen Purtz wrote:
On 17.04.20 20:40, Erik Rijkers wrote:
Very good stuff, and useful. I think.
I mean that but nevertheless here is a lot of comment :)
(I didn't fully compile as docs, just read the 'text' from the patch
file)Thanks. Added nearly all of the suggestions.
What is new? Added two sub-chapters 'mvcc' and 'vacuum' plus graphics.
Made some modifications in previous sub-chapters and in existing titles.
Added some glossary entries.
--
Jürgen Purtz
Attachments:
0003-architecture.patchtext/x-patch; charset=UTF-8; name=0003-architecture.patchDownload
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
index f6c4627c3e..be04972bd7 100644
--- a/doc/src/sgml/advanced.sgml
+++ b/doc/src/sgml/advanced.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/advanced.sgml -->
<chapter id="tutorial-advanced">
- <title>Advanced Features</title>
+ <title>Advanced SQL Features</title>
<sect1 id="tutorial-advanced-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
new file mode 100644
index 0000000000..014a1172b6
--- /dev/null
+++ b/doc/src/sgml/architecture.sgml
@@ -0,0 +1,1159 @@
+<!-- doc/src/sgml/architecture.sgml -->
+
+ <chapter id="tutorial-architecture">
+ <title>Architecture of <productname>PostgreSQL</productname></title>
+
+ <para>
+ Every DBMS implements basic strategies to achieve a fast and
+ robust system. This chapter provides an overview of what
+ techniques <productname>PostgreSQL</productname> uses to
+ reach this aim.
+ </para>
+
+ <sect1 id="tutorial-ram-proc-file">
+ <title>Collaboration of Processes, RAM, and Files</title>
+ <para>
+ As is a matter of course, in a client/server architecture
+ clients do not have direct access to the database. Instead,
+ they merely send requests to the server side and receives
+ according information from there. In the case of
+ <productname>PostgreSQL</productname>, at the server
+ side there is one process per client, the so-called
+ <glossterm linkend="glossary-backend">Backend process</glossterm>.
+ It acts in close cooperation with the
+ <glossterm linkend="glossary-instance">Instance</glossterm> which
+ is a group of tightly coupled other server side processes plus a
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>
+ area.
+ </para>
+
+ <para>
+ At start time, an instance is initiated by the
+ <glossterm linkend="glossary-postgres">Postgres</glossterm>
+ (or: Postmaster) process.
+ It loads the configuration files, allocates the
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>
+ and starts the comprehensive network of processes:
+ <glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
+ <glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
+ <glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
+ <glossterm linkend="glossary-wal-archiver">WAL Archiver</glossterm>,
+ <glossterm linkend="glossary-autovacuum">Autovacuum processes</glossterm>,
+ <glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
+ <glossterm linkend="glossary-logger">Logger</glossterm>, and more.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes
+ main aspects of their collaboration.
+ </para>
+
+ <figure id="tutorial-ram-proc-file-figure">
+ <title>Architecture</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ Whenever a client application tries to connect to a
+ <glossterm linkend="glossary-database">database</glossterm>,
+ this request is handled in a first step by the <firstterm>
+ Postgres process</firstterm>. It checks the authorization,
+ starts a new <firstterm>Backend process</firstterm>,
+ and instructs the client application to connect to it. All
+ further client requests go to this process and are handled
+ by it.
+ </para>
+
+ <para>
+ Client requests (SELECT, UPDATE, ...) usually leads to the
+ necessity to read or write some data. In a first attempt
+ the client's <firstterm>Backend process</firstterm> tries
+ to get the information out of <firstterm>Shared
+ Memory</firstterm>. This <firstterm>Shared
+ Memory</firstterm> is a mirror of parts of the
+ <glossterm linkend="glossary-heap">heap</glossterm> and
+ <glossterm linkend="glossary-index">index</glossterm> files.
+ Because files are much larger than memory, it's likely that
+ the desired information is not (completely) available
+ in the RAM. In this case the <firstterm>Backend process
+ </firstterm> must transfer additional file pages to
+ <firstterm>Shared Memory</firstterm>. Files are physically
+ organized in pages. Every transfer between files and
+ RAM is performed in units of complete pages, retaining
+ their size and layout.
+ </para>
+
+ <para>
+ Reading file pages is notedly slower than reading
+ RAM. This is the main motivation for the existence of
+ <firstterm>Shared Memory</firstterm>. As soon as one
+ of the <firstterm>Backend processes</firstterm> has done
+ the job those pages are available for all other
+ <firstterm>Backend processes</firstterm> for direct
+ access in RAM.
+ </para>
+
+ <para>
+ <firstterm>Shared Memory</firstterm> is limited in size.
+ Sooner or later it becomes necessary to overwrite old RAM
+ pages. As long as the content of such pages hasn't
+ changed this is not a problem. But in
+ <firstterm>Shared Memory</firstterm> also write
+ actions take place
+ - performed by any of the <firstterm>Backend
+ processes</firstterm> (or an
+ <glossterm linkend="glossary-autovacuum">autovacuum process</glossterm>,
+ or other processes). Such modified pages are called
+ <firstterm>dirty pages</firstterm>.
+ Before <firstterm>dirty pages</firstterm> can be overwritten,
+ they must be transferred back to disk. This is a two-step process.
+ </para>
+
+ <para>
+ First, whenever the content of a page changes, a
+ <glossterm linkend="glossary-wal-record">WAL record</glossterm>
+ is created out
+ of the delta-information (difference between old and
+ new content) and stored in another area of the
+ <firstterm>Shared Memory</firstterm>. These
+ <firstterm>WAL records</firstterm> are read by the
+ <firstterm>WAL Writer</firstterm> process,
+ which runs in parallel to the <firstterm>Backend
+ processes</firstterm> and all other processes of
+ the <firstterm>Instance</firstterm>. It writes
+ the continuously arising <firstterm>WAL records</firstterm> to
+ the end of the current
+ <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
+ Because of the sequential nature of this writing, it is much
+ faster than the more or less random access
+ to data files with <firstterm>heap</firstterm>
+ and <firstterm>index</firstterm> information.
+ As mentioned, this WAL-writing happens
+ in an independent process. Nevertheless all
+ <firstterm>WAL records</firstterm> created out of one
+ <firstterm>dirty page</firstterm> must be transferred
+ to disk before the <firstterm>dirty page</firstterm>
+ itself can be transferred to disk.
+ </para>
+
+ <para>
+ Second, the transfer of <firstterm>dirty buffers</firstterm>
+ from <firstterm>Shared Memory</firstterm> to files must
+ take place. This is the primary duty of the
+ <firstterm>Background Writer</firstterm> process. Because
+ huge I/O activities can block other processes significantly,
+ it starts periodically and acts only for a short period.
+ Doing so, his expensive I/O activities are spread over
+ time avoiding huge I/O peaks. Also the <firstterm>
+ Checkpointer</firstterm> process transfers
+ <firstterm>dirty buffers</firstterm> to files, see next
+ paragraph.
+ </para>
+
+ <para>
+ The <firstterm>Checkpointer</firstterm> has a special
+ duty. As its name suggests, he has to create
+ <firstterm>Checkpoints</firstterm>. Such a
+ <glossterm linkend="glossary-checkpoint">Checkpoint</glossterm>
+ is a point in time when all older <firstterm>dirty buffers</firstterm>,
+ all older <firstterm>WAL records</firstterm>, and
+ lastly a special <firstterm>Checkpoint record
+ </firstterm> have been written and flushed to disk.
+ In consequence, after a <firstterm>Checkpoint</firstterm>
+ data files and <firstterm>WAL files</firstterm> are in sync.
+ In case of a recovery (after a crash of the instance)
+ it is known that the information of all
+ <firstterm>WAL records</firstterm> preceding
+ the last <firstterm>Checkpoint record</firstterm>
+ is already integrated into the data files. This
+ speeds up a possibly occurring recovery.
+ </para>
+
+ <para>
+ In correlation with data changes,
+ <firstterm>WAL records</firstterm> arise and are written
+ to <firstterm>WAL files</firstterm>.
+ Those <firstterm>WAL files</firstterm> - in combination with
+ a previously taken <firstterm>Base Backup</firstterm> -
+ are necessary to restore a database after a crash of the
+ disk, where data files have been stored. Therefore it is
+ recommended to transfer a copy of the <firstterm>
+ WAL files</firstterm>
+ to a second, independent place. The purpose of the
+ <firstterm>WAL Archiver</firstterm> process is to perform
+ this copy action.
+ </para>
+
+ <para>
+ The <glossterm linkend="glossary-stats-collector">Stats Collector</glossterm>
+ collects counters about accesses to <firstterm>SQL
+ objects</firstterm> like tables, rows, indexes, pages,
+ and more. It stores the obtained information in system
+ tables.
+ </para>
+
+ <para>
+ The <glossterm linkend="glossary-logger">Logger</glossterm> writes
+ text lines about serious and non-serious events which can happen
+ during database access, e.g.: wrong password, no permission,
+ long-running queries, ... .
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-cluster-db-schema">
+ <title>The logical Perspective: Cluster, Database, Schema</title>
+
+ <para>
+ On a <glossterm linkend="glossary-server">Server</glossterm>
+ exists one or more <glossterm linkend="glossary-cluster">Cluster</glossterm>,
+ each of them contains three or more
+ <glossterm linkend="glossary-database">databases</glossterm>, each
+ database contains many <glossterm linkend="glossary-schema">schema</glossterm>,
+ a schema contains <glossterm linkend="glossary-table">tables</glossterm>,
+ <glossterm linkend="glossary-view">views</glossterm>, and a lot of other objects.
+ Each <firstterm>table</firstterm> or <firstterm>view</firstterm>
+ belongs to a certain <firstterm>schema</firstterm>, they cannot
+ belong to another <firstterm>schema</firstterm>. The same is
+ true for the schema/database and database/cluster relation.
+ <xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
+ this hierarchy.
+ </para>
+
+ <figure id="tutorial-cluster-db-schema-figure">
+ <title>Cluster, Database, Schema</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ A <firstterm>Cluster</firstterm> is the outer frame for a
+ collection of databases. Clusters are created by the command
+ <xref linkend="app-initdb"/>.
+ </para>
+
+ <para>
+ <literal>template0</literal> is the very first
+ <firstterm>database</firstterm> of any
+ <firstterm>cluster</firstterm>. C-routines create
+ <literal>template0</literal> during the initialization phase of
+ the <firstterm>cluster</firstterm>.
+ In a second step <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal> and finally
+ <literal>postgres</literal> as a copy of
+ <literal>template1</literal>. All other
+ <glossterm linkend="app-createdb">new databases</glossterm>
+ of this <firstterm>cluster</firstterm>,
+ such as <literal>my_db</literal>, are also copied from
+ <literal>template1</literal>. Due to the special
+ role of <literal>template0</literal> as the origin
+ of all other <firstterm>databases</firstterm>, no client
+ can connect to it.
+ </para>
+
+ <para>
+ Every database contains <glossterm linkend="glossary-schema">
+ schemas</glossterm>, and
+ <firstterm>schemas</firstterm> contain the other
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>.
+ <firstterm>Schemas</firstterm> are namespaces for
+ their <firstterm>SQL objects</firstterm> and ensure - with one
+ exception - that within their scope names are used only once across all
+ types of <firstterm>SQL objects</firstterm>. E.g., it is not possible
+ to have a table <literal>employee</literal> and a view
+ <literal>employee</literal> within the same
+ <firstterm>schema</firstterm>. But it is possible to have
+ two tables <literal>employee</literal> in different
+ <firstterm>schemas</firstterm>. In this case the two tables
+ are different objects and absolutely independent from each
+ other. The only exception to this cross-type uniqueness is that
+ <glossterm linkend="glossary-unique-constraint">unique constraints
+ </glossterm> and the according <firstterm>unique index</firstterm>
+ use the same name.
+ </para>
+
+ <para>
+ Some <firstterm>schemas</firstterm> are predefined.
+ <literal>public</literal> acts as the default
+ <firstterm>schema</firstterm> and contains all such
+ <firstterm>SQL objects</firstterm>, which are created
+ within <literal>public</literal> or without using any schema
+ name. <literal>public</literal> shall not contain user defined
+ <firstterm>SQL objects</firstterm>. Instead, it is recommended to
+ create a separate <firstterm>schema</firstterm> which
+ holds individual objects like application-specific tables or
+ views. <literal>pg_catalog</literal> is a schema for all tables
+ and views of the <glossterm linkend="glossary-system-catalog">
+ System Catalog</glossterm>.
+ <literal>information_schema</literal> is a schema for several
+ tables and views of the <firstterm>System Catalog</firstterm>
+ in a way which conforms to the SQL standard.
+ </para>
+
+ <para>
+ There are a lot of different <firstterm>SQL object</firstterm>
+ types: <firstterm>database, schema, table, view, materialized
+ view, index, constraint, sequence, function, procedure,
+ trigger, role, data type, operator, tablespace, extension,
+ foreign data wrapper</firstterm>, and more. A few of them, the
+ <glossterm linkend="glossary-global-sql-object">Global SQL Objects</glossterm>,
+ are outside of the strict hierarchy:
+ All database names, all tablespace names, and all role names
+ are automatically known and available throughout the
+ complete <firstterm>cluster</firstterm>, independent from
+ the database or schema in which they where originally
+ defined. <xref linkend="tutorial-internal-objects-hierarchy-figure"/>
+ shows the relation between the object types.
+ </para>
+
+ <figure id="tutorial-internal-objects-hierarchy-figure">
+ <title>Hierarchy of Internal Objects</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="720px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect1>
+
+ <sect1 id="tutorial-directories">
+ <title>The physical Perspective: Directories and Files</title>
+
+ <para>
+ <productname>PostgreSQL</productname> organizes long lasting
+ data as well as volatile state information about transactions
+ or replication actions in the file system. Every
+ <firstterm>Cluster</firstterm> has its own root directory
+ anywhere in the file system. In many cases, the environment
+ variable <literal>PGDATA</literal> points to this directory.
+ The example of the following survey, which is shown in
+ <xref linkend="tutorial-directories-figure"/>, uses
+ <literal>data</literal> as the name of this root directory.
+ </para>
+
+ <figure id="tutorial-directories-figure">
+ <title>Directory Structure</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ <literal>data</literal> contains many subdirectories and
+ some files, all of which are necessary to store long lasting
+ as well as temporary data. The following paragraphs
+ describe the files and subdirectories in
+ <literal>data</literal>.
+ </para>
+
+ <para>
+ <literal>base</literal> is a subdirectory in which one
+ subdirectory per <firstterm>database</firstterm> exists.
+ The names of those subdirectories consist of numbers.
+ These are the internal
+ <firstterm>Object Identifiers (OID)</firstterm>, which are
+ numbers to identify the database definition in the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ </para>
+
+ <para>
+ Within the <firstterm>database</firstterm>-specific
+ subdirectories there are many files: one or more for
+ every table and every index to store <firstterm>heap</firstterm>
+ and <firstterm>index</firstterm> data. Those files are
+ accompanied by files for the
+ <link linkend="storage-fsm">Free Space Maps</link>
+ (extension <literal>_fsm</literal>) and
+ <link linkend="storage-vm">Visibility Maps</link>
+ (extension <literal>_vm</literal>), which contain optimization information.
+ </para>
+
+ <para>
+ Another important subdirectory is <literal>global</literal>.
+ In analogy to the <firstterm>database</firstterm>-specific
+ subdirectories, there are files containing information about
+ <glossterm linkend="glossary-global-sql-object">Global SQL objects</glossterm>.
+ One type of such <firstterm>Global Objects</firstterm> are
+ <firstterm>tablespaces</firstterm>. In
+ <literal>global</literal> there is information about
+ the <firstterm>tablespaces</firstterm>, not the
+ <firstterm>tablespaces</firstterm> itself.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_wal</literal> contains the
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
+ They arise and grow parallel to data changes in the
+ <firstterm>cluster</firstterm> and remain alive as long as
+ they are required for recovery, archiving, or replication.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_xact</literal> contains
+ information about the status of each transaction
+ (IN_PROGRESS, COMMITTED, ABORTED, or SUB_COMMITTED).
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal> there are symbolic links
+ that point to directories containing such<firstterm>
+ SQL objects</firstterm> that are created within
+ <firstterm>tablespaces</firstterm>.
+ </para>
+
+ <para>
+ In the root directory <literal>data</literal>
+ there are also some files.
+ In many cases, the configuration
+ files of this <firstterm>cluster</firstterm>
+ are stored here. As long as the <firstterm>
+ cluster</firstterm> is up and running, the file
+ <literal>postmaster.pid</literal> exists here
+ and contains the ID (pid) of the
+ <firstterm>Postgres</firstterm> (respectively
+ <firstterm>Postmaster</firstterm>) process.
+ </para>
+
+ <para>
+ For more details about the physical implementation
+ of database objects, see <xref linkend="storage"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-mvcc">
+ <title>MVCC</title>
+
+ <para>
+ In most cases, <productname>PostgreSQL</productname> based applications
+ support many clients at the same time. Therefore, it is necessary to
+ protect simultaneously running requests from unwanted overwriting
+ of other's data as well as from reading inconsistent data. Imagine an
+ online shop offering the last copy of an article. Two clients show the
+ article at their user interface. After a while, but at the same time,
+ both users decide to put it to their shopping cart or even to buy it.
+ The dabase must take a sensible decision to prevent the application
+ from promising delivery of the single article to both clients.
+ </para>
+
+ <para>
+ A first approach may be the locking of critical rows. There are
+ two main categories of such techniques: <emphasis>Optimistic Concurrency
+ Control</emphasis> (OCC) and <emphasis>Two Phase Locking</emphasis> (2PL).
+ <productname>PostgreSQL</productname> implements the more sophisticated
+ technique <firstterm>Multiversion Concurrency Control</firstterm> (MVCC).
+ The crucial advantage of MVCC over other technologies gets evident
+ in multiuser OLTP environments with a huge number of concurrent write
+ actions. There, MVCC generally performs better than solutions using locks.
+ In a <productname>PostgreSQL</productname> database reading never blocks
+ writing and writing never blocks reading, even in the strictest level of
+ transaction isolation.
+ </para>
+
+ <para>
+ Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
+ a new version of the same row when any data-change takes place. In order
+ to distinct between these versions as well as to track the timeline
+ of the row, each of the versions contain, in additon to their user
+ defined columns, two special system columns, which are not visible
+ for the usual <command>SELECT * FROM ...</command> command.
+ The column <command>xmin</command> contains the transaction ID (xid)
+ of the transaction which creates this version of the row. Accordingly,
+ <command>xmax</command> contains the xid of the transaction which has
+ deleted this version respectively a zero, if the version is not
+ deleted. You can read both with the command
+ <command>SELECT xmin, xmax, * FROM ... </command>.
+ </para>
+
+ <para>
+ When we speak about transaction IDs, you need to know that xids are like
+ sequences. Every new transaction receives the next number as its ID.
+ Therefore, this flow of xids represents the flow of transaction
+ start events over time. But keep in mind that xids are independent from
+ any real time messurement - in milliseconds or whatever. If you dive
+ deeper into <productname>PostgreSQL</productname>, you will recognize
+ parameters with names such as 'xxx_age'. Despite of their names,
+ these '_age' parameters do not specify a period of time but represent
+ a certain number of transactions, e.g. 100 millions.
+ </para>
+
+ <para>
+ Please note that the description in this chapter simplifies the facts
+ by omitting details. When many transactions are running simultaneously,
+ things can get very complicated. Sometimes they get aborted via
+ ROLLBACK immediately or after a lot of other activities, sometimes
+ a single row is involved in more than one transaction, sometimes
+ a client crashes, sometimes the sequence of xids restarts
+ from zero, ... . Therefore, every version of a row contains more
+ system columns and flags, not only xmin and xmax.
+ </para>
+
+ <para>
+ So, what's going on in detail when write accesses take place?
+ <xref linkend="tutorial-mvcc-figure"/> shows details concerning
+ xmin, xmax, and the user data.
+ </para>
+
+ <figure id="tutorial-mvcc-figure">
+ <title>Multiversion Concurrency Control</title>
+ <mediaobject>
+ <imageobject role="html">
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ An <command>INSERT</command> command creates the first
+ version of a row. Beside its user data <literal>'x'</literal>,
+ this version contains the ID of the creating transaction <literal>123</literal>
+ in xmin and <literal>0</literal> in xmax. xmin indicates that the version
+ exists since transaction <literal>123</literal> and xmax indicates that
+ it is currently not deleted.
+ </para>
+
+ <para>
+ Somewhat later, transaction <literal>135</literal> executes an
+ <command>UPDATE</command> of this row, intending to change the user data
+ from <literal>'x'</literal> to <literal>'y'</literal>. According to
+ the MVCC principles, the data in the old version of the row does not
+ change! The value <literal>'x'</literal> keeps as it was before.
+ Only xmax changes to <literal>135</literal>. Now this version
+ is treated as valid exclusively for transactions with xids from
+ <literal>123</literal> to <literal>134</literal>. As a substitute
+ for the non-ocurring change of data in the old version, the
+ <command>UPDATE</command> creates a new version of the row with
+ its xid in xmin, 0 in xmax, and <literal>'y'</literal> in the
+ user data (plus all the other user data from the old version).
+ This version is now valid for all comming transactions.
+ </para>
+
+ <para>
+ All subsequent <command>UPDATE</command> commands behave in the
+ same way as the first one: they put their
+ xid to xmax of the current version, create the next version
+ with their xid in xmin, 0 in xmax, and the new user data.
+ </para>
+
+ <para>
+ Finally, a row may be deleted by a <command>DELETE</command>.
+ Even in this case all versions of the row keep as
+ before, nothing is thrown away! Only xmax of the last
+ version changes to the xid of the <command>DELETE</command>
+ transaction, which indicates that it is only valid for
+ transactions with xids older than its own (from
+ <literal>142</literal> to <literal>820</literal> in this
+ example).
+ </para>
+
+ <para>
+ In summary, the MVCC technology creates more and more versions
+ of the same row in a table's heap file and leaves them there,
+ even with a DELETE command. The youngest version is relevant
+ for all future transactions. But the system must also preserve
+ some of the older ones for a certain amount of time as there
+ is the possiblility that they are or could become relevant
+ for any of the pending transactions. Over time, also the
+ older ones get out of scope for ALL transactions and therefore
+ becomes unnecessary. Nevertheless, they exist physically on
+ the disk and occupy space.
+ </para>
+
+ <para>
+ Please keep in mind:
+ </para>
+ <itemizedlist spacing="compact" mark="opencircle">
+
+ <listitem>
+ <simpara>
+ xmin and xmax indicate the range from where to where
+ row versions are valid (visible) for transactions.
+ This range doesn't imply any direct temporal meaning,
+ the sequence of xids reflects only the sequence of
+ transaction begin events. As
+ xids grow, old row versions get out of scope over time.
+ If an old row version is no longer valid for ALL existing
+ transactions, it's called <firstterm>dead</firstterm>. The
+ space occupied by the sum of all dead row versions is
+ called <firstterm>bloat</firstterm>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Internally, an <command>UPDATE</command> command acts in the
+ same way as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Nothing gets wiped away - with the consequence that the database
+ occupies more and more disc space. It is obvious that
+ this behaviour has to be automatically corrected in some
+ way. The next chapter explains how AUTOVACUUM fulfills
+ this task.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ </sect1>
+
+ <sect1 id="tutorial-vacuum">
+ <title>Vacuum</title>
+
+ <para>
+ As we have seen in the previous chapter, the database tends to occupy
+ more and more disc space, the <firstterm>bloat</firstterm>.
+ This chapter explains how the SQL command
+ <firstterm>VACUUM</firstterm> and the automatically running
+ <firstterm>AUTOVACUUM</firstterm> processes clear the situation.
+ </para>
+
+ <para>
+ Client processes can issue the SQL command VACUUM at arbitrary
+ points in time. DBAs do this when they recognize special situations
+ or they start it in batch jobs which run on a regular basis.
+ AUTOVACUUM processes run as part of the
+ <link linkend="glossary-instance">Instance</link> at the server.
+ There is an constantly running AUTOVACUUM daemon. He permantly
+ controlls the state of all databases based on values which are
+ collected by the <link linkend="glossary-stats-collector">
+ Statistics Collector</link> and starts
+ AUTOVACUUM processes whenever he detects certain situations.
+ Thus, it's a dynamic behavior of <productname>PostgreSQL</productname>
+ with the intention to tidy up - not always, but whenever it
+ is appropriate.
+ </para>
+
+ <para>
+ VACUUM as well as AUTOVACUUM don't just eliminate bloat.
+ They perform additional tasks to minimizing future
+ I/O activities of themselves as well as of other processes.
+ This additional work can be done in a very efficient way,
+ since in most cases the expensive physical access to pages
+ has taken place anyway for the purpose of eliminating bloat.
+ The additional operations are:
+ </para>
+
+ <itemizedlist spacing="compact" mark="opencircle">
+
+ <listitem>
+ <simpara>
+ <firstterm>Freeze</firstterm>: Mark the jungest row version
+ as frozen. This means that the version
+ is always treated as valid (visible) independent from
+ the <firstterm>wraparound problematic</firstterm> (see below).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <firstterm>Visibility Map</firstterm> and
+ <firstterm>Free Space Map</firstterm>: Log information about
+ the state of the handled pages in two additional files, the
+ Visibility Map and the Free Space Map.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <emphasis>Statistics</emphasis>: Collect statistics about the
+ number of rows per table, the distribution of values, and so on,
+ as the basis for query planners decision making.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ The eagerness - you can call it 'agressivity' - of the
+ operations <emphasis>eliminating bloat</emphasis> and
+ <emphasis>freeze</emphasis> is controlled by configuration
+ parameters, runtime flags and in extreme situations by
+ themselves. Because vacuum operations typically are I/O
+ intensive, which can hinder other activities, AUTOVACUUM
+ avoids to perform many vacuum operations in a bulk. Instead,
+ it carries out many short actions with time gaps in between.
+ The SQL command VACUUM runs immediately without any
+ time gaps.
+ </para>
+
+ <sect2>
+ <title>Eliminate Bloat</title>
+
+ <para>
+ To determine which of the row versions are superfluous, the
+ elimination operation must evaluate xmax against several criterias
+ which all must apply:
+ </para>
+ <itemizedlist spacing="compact" mark="opencircle">
+
+ <listitem>
+ <simpara>
+ xmax must be different from zero because a value of zero
+ indicates that the row version is still valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ xmax must contain an xid which is older than the oldest xid of all
+ currently running transactions (min(pg_stat_activity.backend_xmin)).
+ This criterion guarantees that no existing or upcomming transaction
+ will have read or write access this row version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of xmax must be commited. If it was rollback-ed,
+ this row version is treated as valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there is the situation that the row version is part of
+ multiple transactions, special care and some more actions
+ must be taken, see: <xref linkend="vacuum-for-multixact-wraparound"/>.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ After the vacuum operation detects a superflous row version, it
+ marks its space as free for future use of writing
+ actions. Only in rare situations (or in the case of VACUUM FULL)
+ this space is released to the operating system. In most cases
+ it keeps occupied by PostgreSQL and will be used by future
+ INSERT or UPDATE commands concerning this or a completely
+ different row.
+ </para>
+
+ <para>
+ Which actions start the elimination of bloat?
+
+ <itemizedlist spacing="compact" mark="opencircle">
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM in its default format,
+ i.e. without any option. To boost performance, in this and the
+ next case VACUUM does not read and act on all pages of the heap.
+ The Visibility Map, which is very compact and therefore has a small
+ size, contains information about pages, where bloat-candidates might
+ be found. Only such pages are processed.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM with the option FREEZE.
+ (In this case it undertakes much more actions, see
+ <xref linkend="tutorial-freeze"/>).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM with the option FULL.
+ Also in this mode the bloat disappears, but the used strategy
+ is very different: In this case the complete table is copied
+ to a different file skipping all outdated row versions. This
+ leads to a significant reduction of used disc space because
+ the new file contains only the actual data and the old file
+ is deleted.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When an AUTOVACUUM process acts. For optimization
+ purposes he considers the Visiblility Map in the same way as
+ VACUUM. Additionally, he ignores tables with few modifications,
+ see <xref linkend="guc-autovacuum-vacuum-threshold"/>
+ which defaults to 50 rows and
+ <xref linkend="guc-autovacuum-vacuum-scale-factor"/>
+ which defaults to 20%.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </para>
+
+ <para>
+ This logic only applies to row versions of the heap. Index entries
+ don't use xmin/xmax. Nevertheless such index entries, which would
+ lead to outdated row versions, are released accordingly.
+ (??? more explanations ???)
+ </para>
+
+ <para>
+ The above descriptions omit the fact that xids on a real computer
+ have a limited size. They count up in the same way as sequences and after
+ a certain number of new transactions they are forced to restart
+ from the beginning, which is called <firstterm>wraparound</firstterm>.
+ Therefore the terms 'old transaction' / 'young transaction' does
+ not always correlate with low / hight values of xids. Near to the
+ wraparound point there are cases where xmin has a highter value
+ than xmax, although their meaning is said to be older than xmax.
+ </para>
+
+ <figure id="tutorial-wraparound-figure">
+ <title>Cyclic usage of XIDs</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect2>
+
+ <sect2 id="tutorial-freeze">
+ <title>Freeze Row Versions</title>
+
+ <para>
+ The use of a limited range of IDs for transactions leads
+ to the necessity to restart the sequence sooner or later.
+ This does not only have the rare consequence previously
+ described that sometimes xmin is huger than xmax. The far
+ more important problem is, that whenever the system has
+ to evaluate a WHERE condition, it must decide which row
+ versions are valid (visible) from the perspective of the
+ transaction of this query. If a wraparound couldn't happen,
+ this decision would be relative easy: the xid
+ must be between xmin and xmax, and the corresponding
+ transactions of xmin and xmax must be commited. However,
+ PostgeSQL has to consider the possiblity of wraparounds.
+ Therefore the decision becomes more complex. The general
+ idea of the solution is, to use the 'between xmin and xmax'
+ comparision only during the youngest period of the row
+ versions livetime and afterwards replace it with a
+ 'valid forever' flag in its header.
+ </para>
+
+ <itemizedlist spacing="compact" mark="opencircle">
+
+ <listitem>
+ <simpara>
+ In a first step, PostgreSQL divides the complete range of
+ possible xids into two halfs with the two splitt-points
+ 'txid_current' and 'txid_current + 2^31'. The half behind
+ 'txid_current' is considered to represent xids of the
+ 'past' and the half ahead of 'txid_current' those of the
+ 'future'. Those of the 'past' are valid (visible) and those
+ of the 'future' not.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Over time the two splitt-points move forward. When
+ 'txid_current + 2^31' would reach a row version with
+ xmin equal to that value, it would immediately jump
+ from 'past' to 'future' and would be no longer visible!
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ To avoid this unacceptable extinction of data the vacuum
+ operation <firstterm>freeze</firstterm> clears the situation
+ long before the splitt-point is reached. It sets a flag
+ in the header of the row version, which eliminates
+ completely the future use of xmin/xmax and indicates
+ that the version is valid not only in the 'past'-half
+ but also in the 'future'-half as well as in all comming
+ <glossterm linkend="glossary-epoch">epochs</glossterm>.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Which row versions can be frozen by the vacuum operation?
+ Again, serveral criterias must be checked and all must be met.
+
+ <itemizedlist spacing="compact" mark="opencircle">
+
+ <listitem>
+ <simpara>
+ xmax must be zero because only non-deleted rows can be
+ visible 'forever'.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ xmin must be older than all currently existing transactions.
+ This guarantees that no existing transaction can modify or
+ delete the version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of xmin must be commited.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ At what point in time the freeze operation will take place?
+
+ <itemizedlist spacing="compact" mark="opencircle">
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM with its
+ FREEZE option. In this case all such pages are
+ processed that are marked in the Visibility Map
+ to potentially have unfrozen rows.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM without any
+ option, but finds that there are xids older than
+ <xref linkend="guc-vacuum-freeze-table-age"/>
+ (default: 150 million) minus
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million).
+ As before, all such pages are processed that are
+ marked in the Visibility Map to potentially have unfrozen
+ rows.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When an AUTOVACUUM process runs. Such a process acts
+ in one of two modes:
+ </simpara>
+
+ <itemizedlist spacing="compact" mark="opencircle">
+ <listitem>
+ <simpara>
+ In the <emphasis>normal mode</emphasis> he skips
+ pages with row versions that are younger than
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million) and works only on pages where
+ all xids are older. The skipping of jung xids prevents
+ work on such pages, which are likely to be changed
+ by one of the future SQL commands.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The process switches
+ to an <emphasis>aggressive mode</emphasis>, if he recognize
+ that for the processed table their oldest xid exceeds
+ <xref linkend="guc-autovacuum-freeze-max-age"/>
+ (default: 200 million). The value of the oldest unfrozen
+ xid is stored per table in <emphasis>pg_class.relfrozenxid</emphasis>.
+ In this <emphasis>aggressive mode</emphasis> mode AUTOVACUUM
+ processes all such pages of the selected table that are marked
+ in the Visibility Map to potentially have bloat or unfrozen rows.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In the first two cases and with autovacuum in
+ <emphasis>aggressive mode</emphasis>, the system knowns
+ to which value the oldest unfrozen xid has moved forward and
+ logs the value in <emphasis>pg_class.relfrozenxid</emphasis>.
+ The distance between this value and the 'txid_current' split
+ point becomes smaller and the distance to 'txid_current + 2^31'
+ larger than before.
+ </para>
+
+ <figure id="tutorial-freeze-figure">
+ <title>Freeze</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect2>
+
+ <sect2>
+ <title>Protection against Wraparound Failure</title>
+
+ <para>
+ The AUTOVACUUM processes are initiated by the constantly
+ running <firstterm>autovacuum daemon</firstterm>. If the
+ daemon detects that for a table <firstterm>
+ autovacuum_freeze_max_age</firstterm> is exceeded, it starts
+ an AUTOVACUUM process in the <emphasis>aggressive mode</emphasis>
+ (see above) - even if AUTOVACUUM is disabled.
+ </para>
+ </sect2>
+
+ <sect2>
+ <title>Visibility Map and Free Space Map</title>
+
+ <para>
+ The <xref linkend="glossary-visibility-map"/> (VM)
+ contains two flags - stored as
+ two bits - for each page of the heap. If the first bit
+ is set, it indicates that the associated page does not
+ contain any bloat. If the second one is set, it indicates
+ that the page contains only frozen rows.
+ </para>
+
+ <para>
+ Please consider two details. First, usually a page
+ contains many rows, each of them in many versions.
+ However, the flags are associated with the page,
+ not with a row or a row version! The flags are set
+ only under the condition that they are valid for ALL
+ row versions of the page. Second, since there
+ are only two bits per page, the VM is considerably
+ smaller than the heap. Therefore it is buffered
+ in RAM in almost all cases.
+ </para>
+
+ <para>
+ The setting of the flags is silently done by VACUUM
+ and AUTOVACUUM during their bloat and freeze operations.
+ This is done to accelerate future vacuum actions,
+ regular accesses to heap pages, and some accesses to
+ the index. The flags are cleared with every data-modifying
+ operation on any row version of the page.
+ </para>
+
+ <para>
+ The <xref linkend="glossary-free-space-map"/> (FSM)
+ tracks the amount of free space per page. It is
+ organized as a highly condensed b-tree of (rounded) sizes.
+ As long as VACUUM or AUTOVACUUM change the free space
+ on any processed page, they log the new values in
+ the FSM in the same way as all other writing
+ processes.
+ </para>
+
+ </sect2>
+
+ <sect2>
+ <title>Statistics</title>
+
+ <para>
+ Statistic information helps the <link
+ linkend="planner-stats">Query Planner</link> to take optimal
+ decisions for the generation of execution plans. This
+ information can be gathered with the SQL commands ANALYZE
+ or VACUUM ANALYZE. But also autovacuum processes gather
+ such information. Depending on the percentage of changed rows
+ per table <xref linkend="guc-autovacuum-analyze-scale-factor"/>
+ the autovacuum daemon starts autovacuum processes to collect
+ statistics per table. This dynamic invocation of analyze
+ operations allows <productname>PostgreSQL</productname> to
+ adopt queries to changing circumstances.
+ </para>
+
+ <para>
+ For more details about vacuum operations, especially for its
+ numerous parameters, see <xref linkend="routine-vacuuming"/>.
+ </para>
+
+ </sect2>
+ </sect1>
+
+<!-- ToDo
+
+ <sect1 id="tutorial-transactions-mvcc">
+ <title>Transactions</title>
+
+ <para>
+...
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-backup">
+ <title>Backup</title>
+
+ <para>
+...
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-replication">
+ <title>Replication</title>
+
+ <para>
+...
+ </para>
+
+ </sect1>
+-->
+
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 68179f71cd..ca29c8bc4e 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -8,9 +8,10 @@
<!ENTITY problems SYSTEM "problems.sgml">
<!-- tutorial -->
-<!ENTITY advanced SYSTEM "advanced.sgml">
-<!ENTITY query SYSTEM "query.sgml">
-<!ENTITY start SYSTEM "start.sgml">
+<!ENTITY start SYSTEM "start.sgml">
+<!ENTITY architecture SYSTEM "architecture.sgml">
+<!ENTITY query SYSTEM "query.sgml">
+<!ENTITY advanced SYSTEM "advanced.sgml">
<!-- user's guide -->
<!ENTITY array SYSTEM "array.sgml">
diff --git a/doc/src/sgml/glossary.sgml b/doc/src/sgml/glossary.sgml
index 8c6cb6e942..ff2355a10c 100644
--- a/doc/src/sgml/glossary.sgml
+++ b/doc/src/sgml/glossary.sgml
@@ -141,7 +141,8 @@
<glossterm>Background Writer (process)</glossterm>
<glossdef>
<para>
- A process that continuously writes dirty pages from
+ A process that continuously writes
+ <glossterm linkend="glossary-dirty-buffer">dirty buffers</glossterm> from
<glossterm linkend="glossary-shared-memory">shared memory</glossterm> to
the file system. It wakes up periodically, but works only for a short
period in order to distribute its expensive <acronym>I/O</acronym>
@@ -155,6 +156,16 @@
</glossdef>
</glossentry>
+ <glossentry id="glossary-bloat">
+ <glossterm>Bloat</glossterm>
+ <glossdef>
+ <para>
+ Bloat is disk or RAM space, which does not contain relevant
+ data, e.g.: free space within blocks or outdated row versions.
+ </para>
+ </glossdef>
+ </glossentry>
+
<glossentry id="glossary-cast">
<glossterm>Cast</glossterm>
<glossdef>
@@ -208,15 +219,6 @@
</glossdef>
</glossentry>
- <glossentry id="glossary-checkpointer">
- <glossterm>Checkpointer (process)</glossterm>
- <glossdef>
- <para>
- A specialized process responsible for executing checkpoints.
- </para>
- </glossdef>
- </glossentry>
-
<glossentry id="glossary-checkpoint">
<glossterm>Checkpoint</glossterm>
<glossdef>
@@ -244,6 +246,15 @@
</glossdef>
</glossentry>
+ <glossentry id="glossary-checkpointer">
+ <glossterm>Checkpointer (process)</glossterm>
+ <glossdef>
+ <para>
+ A specialized process responsible for executing checkpoints.
+ </para>
+ </glossdef>
+ </glossentry>
+
<glossentry>
<glossterm>Class (archaic)</glossterm>
<glosssee otherterm="glossary-relation" />
@@ -446,6 +457,26 @@
</glossdef>
</glossentry>
+ <glossentry id="glossary-dirty-buffer">
+ <glossterm>Dirty Buffer</glossterm>
+ <glossdef>
+ <para>
+ File pages are mirrored in RAM (<glossterm
+ linkend="glossary-shared-memory">Shared Memory</glossterm>).
+ Data changes happens in a first step in RAM and are
+ transfered to disk at a later point in time. During the period
+ from the buffer change to its tranfer to disk, he is
+ called a dirty buffer. Sometimes people use the term
+ <glossterm linkend="glossary-dirty-page">dirty page</glossterm>.
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry id="glossary-dirty-page">
+ <glossterm>Dirty Page</glossterm>
+ <glosssee otherterm="glossary-dirty-buffer" />
+ </glossentry>
+
<glossentry id="glossary-durability">
<glossterm>Durability</glossterm>
<glossdef>
@@ -459,6 +490,23 @@
</glossdef>
</glossentry>
+ <glossentry id="glossary-epoch">
+ <glossterm>Epoch</glossterm>
+ <glossdef>
+ <para>
+ In a time-related context: The number of seconds since
+ 00:00:00 UTC on 1 January 1970, minus leap seconds.
+ </para>
+ <para>
+ In reference to transaction IDs: The number of available
+ <glossterm linkend="glossary-xid">xids</glossterm> is limited
+ because they use a 32-bit integer. Sooner or later the
+ sequence must restart from the beginning. Every such roundtrip
+ is called an epoch.
+ </para>
+ </glossdef>
+ </glossentry>
+
<glossentry id="glossary-extension">
<glossterm>Extension</glossterm>
<glossdef>
@@ -564,6 +612,38 @@
</glossdef>
</glossentry>
+ <glossentry id="glossary-fork">
+ <glossterm>Fork</glossterm>
+ <glossdef>
+ <para>
+ Each table and index has three so-called forks to
+ store data, Free Space Map, and Visibility Map in
+ separate files. The forks are called
+ <literal>'main'</literal>, <literal>'fsm'</literal>,
+ and <literal>'vm'</literal>. An unlogged table has
+ the additional fork <literal>'init'</literal> to
+ initialize the table in case of a crash.
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry id="glossary-free-space-map">
+ <glossterm>Free Space Map</glossterm>
+ <glossdef>
+ <para>
+ For each table and index exists an assigned file, the
+ Free Space Map. It tracks the amount of free space
+ per page. It is organized as a highly condensed b-tree
+ of (rounded) size.
+ </para>
+
+ <para>
+ For more information, see
+ <xref linkend="storage-fsm"/>.
+ </para>
+ </glossdef>
+ </glossentry>
+
<glossentry id="glossary-function">
<glossterm>Function</glossterm>
<glossdef>
@@ -761,25 +841,6 @@
</glossdef>
</glossentry>
- <glossentry id="glossary-logger">
- <glossterm>Logger (process)</glossterm>
- <glossdef>
- <para>
- If activated, the
- <glossterm linkend="glossary-logger">Logger</glossterm> process
- writes information about database events into the current
- <glossterm linkend="glossary-log-file">log file</glossterm>.
- When reaching certain time- or
- volume-dependent criteria, a new log file is created.
- Also called <firstterm>syslogger</firstterm>.
- </para>
- <para>
- For more information, see
- <xref linkend="runtime-config-logging"/>.
- </para>
- </glossdef>
- </glossentry>
-
<glossentry id="glossary-log-record">
<glossterm>Log Record</glossterm>
<glossdef>
@@ -803,6 +864,25 @@
</glossdef>
</glossentry>
+ <glossentry id="glossary-logger">
+ <glossterm>Logger (process)</glossterm>
+ <glossdef>
+ <para>
+ If activated, the
+ <glossterm linkend="glossary-logger">Logger</glossterm> process
+ writes information about database events into the current
+ <glossterm linkend="glossary-log-file">log file</glossterm>.
+ When reaching certain time- or
+ volume-dependent criteria, a new log file is created.
+ Also called <firstterm>syslogger</firstterm>.
+ </para>
+ <para>
+ For more information, see
+ <xref linkend="runtime-config-logging"/>.
+ </para>
+ </glossdef>
+ </glossentry>
+
<glossentry>
<glossterm>Master (server)</glossterm>
<glosssee otherterm="glossary-primary-server" />
@@ -929,8 +1009,8 @@
</glossdef>
</glossentry>
- <glossentry id="glossary-postmaster">
- <glossterm>Postmaster (process)</glossterm>
+ <glossentry id="glossary-postgres">
+ <glossterm>Postgres (process)</glossterm>
<glossdef>
<para>
The very first process of an <glossterm linkend="glossary-instance">instance</glossterm>.
@@ -945,6 +1025,16 @@
</glossdef>
</glossentry>
+ <glossentry id="glossary-postmaster">
+ <glossterm>Postmaster (process)</glossterm>
+ <glossdef>
+ <para>
+ An outdated term for the <glossterm
+ linkend="glossary-postgres"> Postgres</glossterm> process.
+ </para>
+ </glossdef>
+ </glossentry>
+
<glossentry id="glossary-primary-server">
<glossterm>Primary (server)</glossterm>
<glossdef>
@@ -1188,11 +1278,13 @@
<para>
A schema is a namespace for <glossterm linkend="glossary-sql-object">SQL objects</glossterm>,
which all reside in the same
- <glossterm linkend="glossary-database">database</glossterm>. Each
+ <glossterm linkend="glossary-database">database</glossterm>. Each
SQL object must reside in exactly one schema.
</para>
<para>
- The names of SQL objects of the same type in the same schema are enforced unique.
+ The names of SQL objects in the same schema are enforced unique.
+ This applies across all object types with a single exception:
+ Unique constraints and the according unique index use the same name.
There is no restriction on reusing a name in multiple schemas.
</para>
<para>
@@ -1651,6 +1743,24 @@
</glossdef>
</glossentry>
+ <glossentry id="glossary-visibility-map">
+ <glossterm>Visiblility Map</glossterm>
+ <glossdef>
+ <para>
+ For each table exists an assigned file, the Visibliltiy Map,
+ which contains two bit per file page. If the first bit
+ is set, it indicates that the associated page does not
+ contain any bloat. If the second one is set, it indicates
+ that the page contains only frozen rows.
+ </para>
+ </glossdef>
+ </glossentry>
+
+ <glossentry>
+ <glossterm>WAL</glossterm>
+ <glosssee otherterm="glossary-wal" />
+ </glossentry>
+
<glossentry id="glossary-wal-archiver">
<glossterm>WAL Archiver (process)</glossterm>
<glossdef>
@@ -1696,11 +1806,6 @@
</glossdef>
</glossentry>
- <glossentry>
- <glossterm>WAL</glossterm>
- <glosssee otherterm="glossary-wal" />
- </glossentry>
-
<glossentry id="glossary-wal-record">
<glossterm>WAL Record</glossterm>
<glossdef>
@@ -1728,8 +1833,8 @@
<glossdef>
<para>
A process that writes <glossterm linkend="glossary-wal-record">WAL records</glossterm>
- from <glossterm id="linkend-shared-memory">shared memory</glossterm> to
- <glossterm id="linkend-wal-file">WAL files</glossterm>.
+ from <glossterm linkend="glossary-shared-memory">shared memory</glossterm> to
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
</para>
<para>
For more information, see
@@ -1771,5 +1876,45 @@
</para>
</glossdef>
</glossentry>
+
+ <glossentry id="glossary-xid">
+ <glossterm>Transaction ID (xid)</glossterm>
+ <glossdef>
+ <para>
+ Like other objects, transactions need to have an unique
+ ID to identify them. The transaction manager creates
+ the sequence of xids. Because xids are stored in a 32-bit
+ integer, the available range is limited. Sooner or later
+ the sequence of xids must restart from the beginning.
+ </para>
+ <para>
+ There are three special xids:
+ </para>
+ <itemizedlist spacing="compact" mark="none">
+ <listitem>
+ <simpara>
+ <literal>0 (InvalidTransactionId)</literal>: is used for
+ xids of relations which are not a table.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <literal>1 (BootstrapTransactionId)</literal>: represents
+ transactions used during the first phase of cluster
+ initialization, see: <xref linkend="app-initdb"/>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ <literal>2 (FrozenTransactionId)</literal>: indicates a
+ frozen transaction. This value is no longer used. Instead,
+ the system uses a flag in the header of each row version
+ to mark them as frozen.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </glossdef>
+ </glossentry>
+
</glosslist>
</appendix>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
new file mode 100644
index 0000000000..7e13753d48
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
@@ -0,0 +1,160 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="685" viewBox="0 0 900 685">
+ <title>
+ Server (Hardware, Container, or VM)
+ </title>
+ <style>
+ .text_normal,.text_small{font-style:normal;font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_small{font-size:12px}.text_normal{font-size:16px}
+ </style>
+ <defs>
+ <symbol id="rectangle_special_0">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="rectangle_special_1">
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="125">
+ 'my_schema' (optional)
+ </text>
+ <text class="text_small" x="20" y="145">
+ tables, views, ...
+ </text>
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="190">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M450 10v230H0V0h440v10h10L440 0"/>
+ </symbol>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="270" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Server (Hardware, Container, or VM)
+ </text>
+ <path stroke="blue" stroke-width="2" fill="none" d="M20 110h790v555H20z"/>
+ <text class="text_normal" x="180" y="25" transform="translate(20 110)">
+ cluster 'data' (default, managed by one instance)
+ </text>
+ <path d="M50 110V80h790v555h-30" stroke="blue" stroke-width="2" fill="none"/>
+ <text class="text_normal" x="190" y="-10" transform="translate(45 110)">
+ cluster 'cluster_2' (optional, managed by a different instance)
+ </text>
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template0'
+ </text>
+ </g>
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template1'
+ </text>
+ </g>
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'my_db' (optional)
+ </text>
+ </g>
+ <g transform="translate(320 330)">
+ <rect width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4"/>
+ <text class="text_normal" x="15" y="27">
+ Global SQL objects
+ </text>
+ <path d="M0 5l-65-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M80 0v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M180 40h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M0 40l-45 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ </g>
+ <g transform="translate(335 405)">
+ <use xlink:href="#note"/>
+ <text class="text_small" x="10" y="20">
+ 1)
+ </text>
+ <text class="text_small" x="30" y="20">
+ By default, you work in the cluster 'data', database 'postgres',
+ </text>
+ <text class="text_small" x="30" y="35">
+ schema 'public'.
+ </text>
+ <text class="text_small" x="10" y="55">
+ 2)
+ </text>
+ <text class="text_small" x="30" y="55">
+ More system schemas: pg_catalog, information_schema,
+ </text>
+ <text class="text_small" x="30" y="70">
+ pg_temp, pg_toast.
+ </text>
+ <text class="text_small" x="10" y="90">
+ 3)
+ </text>
+ <text class="text_small" x="30" y="90">
+ Global SQL objects: Some SQL objects are automatically active
+ </text>
+ <text class="text_small" x="30" y="105">
+ and known database- or even cluster-wide.
+ </text>
+ <text class="text_small" x="10" y="125">
+ 4)
+ </text>
+ <text class="text_small" x="30" y="125">
+ The command 'initdb' creates a new cluster with the three
+ </text>
+ <text class="text_small" x="30" y="140">
+ databases 'template0', 'template1', and 'postgres'. The command
+ </text>
+ <text class="text_small" x="30" y="155">
+ 'createdb' creates a new database.
+ </text>
+ <text class="text_small" x="10" y="175">
+ 5)
+ </text>
+ <text class="text_small" x="30" y="175">
+ If multiple clusters are active on one server at the same time,
+ </text>
+ <text class="text_small" x="30" y="190">
+ each one is managed by an individual instance. Each such instance
+ </text>
+ <text class="text_small" x="30" y="205">
+ uses a different port.
+ </text>
+ <text class="text_small" x="10" y="225">
+ 6)
+ </text>
+ <text class="text_small" x="30" y="225">
+ No client application is allowed to connect to 'template0'.
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink.svg b/doc/src/sgml/images/cluster-db-schema-ink.svg
new file mode 100644
index 0000000000..58405ae685
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink.svg
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="685px"
+ viewBox="0 0 900 685"
+ id="svg147"
+ sodipodi:docname="cluster-db-schema-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Server (Hardware, Container, or VM)</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.34452555"
+ inkscape:cx="450"
+ inkscape:cy="342.5"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Server (Hardware, Container, or VM)</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs49">
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangle_special_0">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect6" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="195"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect8" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text10">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text12">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="195"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect14" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text16">(more system schemas)</text>
+ </symbol>
+ <!-- same as before, but one more schema -->
+ <symbol
+ id="rectangle_special_1">
+ <!-- the database -->
+ <rect
+ width="245"
+ height="225"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect19" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect21" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text23">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text25">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect27" />
+ <text
+ class="text_normal"
+ x="20"
+ y="125"
+ id="text29">'my_schema' (optional)</text>
+ <text
+ class="text_small"
+ x="20"
+ y="145"
+ id="text31">tables, views, ...</text>
+ <rect
+ x="15"
+ y="170"
+ width="205"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect33" />
+ <text
+ class="text_small"
+ x="20"
+ y="190"
+ id="text35">(more system schemas)</text>
+ </symbol>
+ <symbol
+ id="note"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title38">UML Note</title>
+ <path
+ d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10"
+ id="path40" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path43" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path46" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect51" />
+ <text
+ class="text_big"
+ x="270"
+ y="40"
+ id="text53">Server (Hardware, Container, or VM)</text>
+ <!-- two clusters -->
+ <g
+ transform="translate(20 110)"
+ id="g59">
+ <rect
+ x="0"
+ y="0"
+ width="790"
+ height="555"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="rect55" />
+ <text
+ class="text_normal"
+ x="180"
+ y="25"
+ id="text57">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g
+ transform="translate(45 110)"
+ id="g65">
+ <path
+ d="M 5,0 v -30 h 790 v 555 h -30"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="path61" />
+ <text
+ class="text_normal"
+ x="190"
+ y="-10"
+ id="text63">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+ <!-- database template 0 -->
+ <g
+ transform="translate(40 155)"
+ id="g71">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use67" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text69">database 'template0'</text>
+ </g>
+ <!-- database template 1 -->
+ <g
+ transform="translate(290 155)"
+ id="g77">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use73" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text75">database 'template1'</text>
+ </g>
+ <!-- database postgres -->
+ <g
+ transform="translate(540 155)"
+ id="g83">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use79" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text81">database 'postgres'</text>
+ </g>
+ <!-- database my_db -->
+ <g
+ transform="translate(40 350)"
+ id="g89">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use85" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text87">database 'my_db' (optional)</text>
+ </g>
+ <!-- global objects -->
+ <g
+ transform="translate(320 330)"
+ id="g103">
+ <rect
+ x="0"
+ y="0"
+ width="180"
+ height="45"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="10 4 4 4"
+ id="rect91" />
+ <text
+ class="text_normal"
+ x="15"
+ y="27"
+ id="text93">Global SQL objects</text>
+ <path
+ d="M 0,5 l-65,-35"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path95" />
+ <path
+ d="M 80,0 v-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path97" />
+ <path
+ d="M 180,40 h50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path99" />
+ <path
+ d="M 0,40 l-45,20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path101" />
+ </g>
+ <!-- Some comments -->
+ <g
+ transform="translate(335 405)"
+ id="g145">
+ <use
+ xlink:href="#note"
+ x="0"
+ y="0"
+ id="use105" />
+ <text
+ class="text_small"
+ x="10"
+ y="20"
+ id="text107">1)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="20"
+ id="text109">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text
+ class="text_small"
+ x="30"
+ y="35"
+ id="text111">schema 'public'.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="55"
+ id="text113">2)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="55"
+ id="text115">More system schemas: pg_catalog, information_schema,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="70"
+ id="text117">pg_temp, pg_toast.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="90"
+ id="text119">3)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="90"
+ id="text121">Global SQL objects: Some SQL objects are automatically active</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text123">and known database- or even cluster-wide.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="125"
+ id="text125">4)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="125"
+ id="text127">The command 'initdb' creates a new cluster with the three</text>
+ <text
+ class="text_small"
+ x="30"
+ y="140"
+ id="text129">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text
+ class="text_small"
+ x="30"
+ y="155"
+ id="text131">'createdb' creates a new database.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="175"
+ id="text133">5)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="175"
+ id="text135">If multiple clusters are active on one server at the same time,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="190"
+ id="text137">each one is managed by an individual instance. Each such instance</text>
+ <text
+ class="text_small"
+ x="30"
+ y="205"
+ id="text139">uses a different port.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="225"
+ id="text141">6)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="225"
+ id="text143">No client application is allowed to connect to 'template0'.</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
new file mode 100644
index 0000000000..af50c07330
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="685px"
+ viewBox="0 0 900 685" >
+
+ <title>Server (Hardware, Container, or VM)</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_0">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">(more system schemas)</text>
+ </symbol>
+
+ <!-- same as before, but one more schema -->
+ <symbol id="rectangle_special_1">
+ <!-- the database -->
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="125">'my_schema' (optional)</text>
+ <text class="text_small" x="20" y="145">tables, views, ...</text>
+
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="190">(more system schemas)</text>
+ </symbol>
+
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="270" y="40">Server (Hardware, Container, or VM)</text>
+
+ <!-- two clusters -->
+ <g transform="translate(20 110)">
+ <rect x="0" y="0" width="790" height="555" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="180" y="25">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g transform="translate(45 110)">
+ <path d="M 5,0 v -30 h 790 v 555 h -30" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="190" y="-10">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+
+
+ <!-- database template 0 -->
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template0'</text>
+ </g>
+
+ <!-- database template 1 -->
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template1'</text>
+ </g>
+
+ <!-- database postgres -->
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'postgres'</text>
+ </g>
+
+ <!-- database my_db -->
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
+ </g>
+
+ <!-- global objects -->
+ <g transform="translate(320 330)">
+ <rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
+ <text class="text_normal" x="15" y="27">Global SQL objects</text>
+ <path d="M 0,5 l-65,-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ </g>
+
+ <!-- Some comments -->
+ <g transform="translate(335 405)">
+ <use xlink:href="#note" x="0" y="0" />
+
+ <text class="text_small" x="10" y="20">1)</text>
+ <text class="text_small" x="30" y="20">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text class="text_small" x="30" y="35">schema 'public'.</text>
+
+ <text class="text_small" x="10" y="55">2)</text>
+ <text class="text_small" x="30" y="55">More system schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="70">pg_temp, pg_toast.</text>
+
+ <text class="text_small" x="10" y="90">3)</text>
+ <text class="text_small" x="30" y="90">Global SQL objects: Some SQL objects are automatically active</text>
+ <text class="text_small" x="30" y="105">and known database- or even cluster-wide.</text>
+
+ <text class="text_small" x="10" y="125">4)</text>
+ <text class="text_small" x="30" y="125">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="140">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="155">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="175">5)</text>
+ <text class="text_small" x="30" y="175">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="190">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="205">uses a different port.</text>
+
+ <text class="text_small" x="10" y="225">6)</text>
+ <text class="text_small" x="30" y="225">No client application is allowed to connect to 'template0'.</text>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/directories-ink-svgo.svg b/doc/src/sgml/images/directories-ink-svgo.svg
new file mode 100644
index 0000000000..95fa76b9c6
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink-svgo.svg
@@ -0,0 +1,164 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="640" viewBox="0 0 900 640">
+ <title>
+ Directory structure of a cluster
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <symbol id="directory" stroke="blue" stroke-width=".3" fill="aqua">
+ <title>
+ Directory
+ </title>
+ <path d="M0 10h110v20H0z"/>
+ <path d="M0 10V8l3-3h35l3 3v2"/>
+ </symbol>
+ <symbol id="file" stroke="black" fill="none">
+ <title>
+ File
+ </title>
+ <path stroke="blue" d="M0 0h40v50H0z"/>
+ <path d="M5 10h20" stroke-dasharray="4 2"/>
+ <path d="M5 17h15" stroke-dasharray="6 2"/>
+ <path d="M5 24h25" stroke-dasharray="4 2"/>
+ <path d="M5 31h20" stroke-dasharray="5 2"/>
+ </symbol>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="50" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Directory Structure
+ </text>
+ <g transform="translate(20 100)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /pg/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ An arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 130)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ data/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of cluster 'data' (see: PGDATA)
+ </text>
+ </g>
+ <g transform="translate(120 160)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ base/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing per-database subdirectories
+ </text>
+ </g>
+ <g transform="translate(170 190)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 1/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of first database 'template0'
+ </text>
+ </g>
+ <g transform="translate(170 220)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12992/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of second database 'template1'
+ </text>
+ </g>
+ <g transform="translate(170 250)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12999/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of third database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(170 280)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ nnnnn/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Optional: more subdirectories for databases, e.g. 'my_db'
+ </text>
+ </g>
+ <g transform="translate(120 310)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ global/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory with information about Global SQL Objects
+ </text>
+ </g>
+ <g transform="translate(120 340)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_wal/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 370)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_xact/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for transaction commit status ('pg_clog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 400)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_tblspc/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing symbolic links to tablespaces
+ </text>
+ </g>
+ <g transform="translate(120 430)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_... /
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Some more subdirectories
+ </text>
+ </g>
+ <g transform="translate(120 465)">
+ <use xlink:href="#file"/>
+ <use xlink:href="#file" x="50"/>
+ <text x="200" y="26" class="text_normal">
+ 'postmaster.pid' and other files with cluster-wide relevance
+ </text>
+ </g>
+ <g transform="translate(20 540)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /xyz/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ Same or another arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 570)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ cluster_2/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of another cluster 'cluster_2'
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-ink.svg b/doc/src/sgml/images/directories-ink.svg
new file mode 100644
index 0000000000..5cc9d48e20
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink.svg
@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="640px"
+ viewBox="0 0 900 640"
+ id="svg303"
+ sodipodi:docname="directories-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata307">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Directory structure of a cluster</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview305"
+ showgrid="false"
+ inkscape:zoom="0.36875"
+ inkscape:cx="450"
+ inkscape:cy="320"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg303" />
+ <title
+ id="title153">Directory structure of a cluster</title>
+ <style
+ type="text/css"
+ id="style155">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs177">
+ <!-- Directory -->
+ <symbol
+ id="directory"
+ stroke="blue"
+ stroke-width="0.3px"
+ fill="aqua">
+ <title
+ id="title157">Directory</title>
+ <rect
+ x="0"
+ y="10"
+ width="110"
+ height="20"
+ id="rect159" />
+ <path
+ d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2"
+ id="path161" />
+ </symbol>
+ <!-- File -->
+ <symbol
+ id="file"
+ stroke="black"
+ fill="none">
+ <title
+ id="title164">File</title>
+ <rect
+ x="0"
+ y="0"
+ width="40"
+ height="50"
+ stroke="blue"
+ id="rect166" />
+ <path
+ d="M 5,10 h 20"
+ stroke-dasharray="4 2"
+ id="path168" />
+ <path
+ d="M 5,17 h 15"
+ stroke-dasharray="6 2"
+ id="path170" />
+ <path
+ d="M 5,24 h 25"
+ stroke-dasharray="4 2"
+ id="path172" />
+ <path
+ d="M 5,31 h 20"
+ stroke-dasharray="5 2"
+ id="path174" />
+ </symbol>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect179" />
+ <!-- caption -->
+ <text
+ x="200"
+ y="50"
+ class="text_big"
+ id="text181">Directory Structure</text>
+ <!-- the directories -->
+ <g
+ transform="translate(20, 100)"
+ id="g189">
+ <use
+ xlink:href="#directory"
+ id="use183" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text185">... /pg/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text187">An arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 130)"
+ id="g197">
+ <use
+ xlink:href="#directory"
+ id="use191" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text193">data/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text195">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+ <g
+ transform="translate(120, 160)"
+ id="g205">
+ <use
+ xlink:href="#directory"
+ id="use199" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text201">base/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text203">Subdirectory containing per-database subdirectories</text>
+ </g>
+ <!-- -->
+ <g
+ transform="translate(170, 190)"
+ id="g213">
+ <use
+ xlink:href="#directory"
+ id="use207" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text209">1/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text211">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g
+ transform="translate(170, 220)"
+ id="g221">
+ <use
+ xlink:href="#directory"
+ id="use215" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text217">12992/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text219">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g
+ transform="translate(170, 250)"
+ id="g229">
+ <use
+ xlink:href="#directory"
+ id="use223" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text225">12999/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text227">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g
+ transform="translate(170, 280)"
+ id="g237">
+ <use
+ xlink:href="#directory"
+ id="use231" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text233">nnnnn/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text235">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+ <g
+ transform="translate(120, 310)"
+ id="g245">
+ <use
+ xlink:href="#directory"
+ id="use239" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text241">global/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text243">Subdirectory with information about Global SQL Objects</text>
+ </g>
+ <g
+ transform="translate(120, 340)"
+ id="g253">
+ <use
+ xlink:href="#directory"
+ id="use247" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text249">pg_wal/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text251">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 370)"
+ id="g261">
+ <use
+ xlink:href="#directory"
+ id="use255" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text257">pg_xact/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text259">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 400)"
+ id="g269">
+ <use
+ xlink:href="#directory"
+ id="use263" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text265">pg_tblspc/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text267">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+ <g
+ transform="translate(120, 430)"
+ id="g277">
+ <use
+ xlink:href="#directory"
+ id="use271" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text273">pg_... /</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text275">Some more subdirectories</text>
+ </g>
+ <g
+ transform="translate(120, 465)"
+ id="g285">
+ <use
+ xlink:href="#file"
+ x="0"
+ y="0"
+ id="use279" />
+ <use
+ xlink:href="#file"
+ x="50"
+ y="0"
+ id="use281" />
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text283">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+ <!-- next cluster -->
+ <g
+ transform="translate(20, 540)"
+ id="g293">
+ <use
+ xlink:href="#directory"
+ id="use287" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text289">... /xyz/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text291">Same or another arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 570)"
+ id="g301">
+ <use
+ xlink:href="#directory"
+ id="use295" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text297">cluster_2/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text299">Root of another cluster 'cluster_2'</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
new file mode 100644
index 0000000000..6d16a03169
--- /dev/null
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="640px"
+ viewBox="0 0 900 640">
+
+ <title>Directory structure of a cluster</title>
+
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Directory -->
+ <symbol id="directory" stroke="blue" stroke-width="0.3px" fill="aqua">
+ <title>Directory</title>
+ <rect x="0" y="10" width="110" height="20" />
+ <path d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2" />
+ </symbol>
+
+ <!-- File -->
+ <symbol id="file" stroke="black" fill="none" >
+ <title>File</title>
+ <rect x="0" y="0" width="40" height="50" stroke="blue" />
+ <path d="M 5,10 h 20" stroke-dasharray="4 2" />
+ <path d="M 5,17 h 15" stroke-dasharray="6 2" />
+ <path d="M 5,24 h 25" stroke-dasharray="4 2" />
+ <path d="M 5,31 h 20" stroke-dasharray="5 2" />
+ </symbol>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption -->
+ <text x="200" y="50" class="text_big">Directory Structure</text>
+
+ <!-- the directories -->
+ <g transform="translate(20, 100)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /pg/</text>
+ <text x="300" y="26" class="text_normal">An arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 130)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">data/</text>
+ <text x="250" y="26" class="text_normal">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+
+ <g transform="translate(120, 160)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">base/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing per-database subdirectories</text>
+ </g>
+
+ <!-- -->
+ <g transform="translate(170, 190)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">1/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g transform="translate(170, 220)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12992/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g transform="translate(170, 250)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12999/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g transform="translate(170, 280)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">nnnnn/</text>
+ <text x="150" y="26" class="text_normal">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+
+ <g transform="translate(120, 310)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">global/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory with information about Global SQL Objects</text>
+ </g>
+
+ <g transform="translate(120, 340)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 370)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 400)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+
+ <g transform="translate(120, 430)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_... /</text>
+ <text x="200" y="26" class="text_normal">Some more subdirectories</text>
+ </g>
+
+ <g transform="translate(120, 465)">
+ <use xlink:href="#file" x="0" y="0" />
+ <use xlink:href="#file" x="50" y="0" />
+ <text x="200" y="26" class="text_normal">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+
+ <!-- next cluster -->
+ <g transform="translate(20, 540)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /xyz/</text>
+ <text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 570)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster 'cluster_2'</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink-svgo.svg b/doc/src/sgml/images/freeze-ink-svgo.svg
new file mode 100644
index 0000000000..158a2e731c
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink-svgo.svg
@@ -0,0 +1,84 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="320" viewBox="0 0 850 320">
+ <title>
+ Freeze
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100)"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="70" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ <tspan font-style="italic" font-weight="700">Freeze</tspan> to keep alive
+ </text>
+ <g fill="none" transform="translate(170 190)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_120" startOffset="11.2%">(1)</textPath> <textPath xlink:href="#Path_120" startOffset="61.2%">(5)</textPath> <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%">|</textPath> <textPath xlink:href="#Path_120" startOffset="34%">(2)</textPath> <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(3)</textPath> <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%">|</textPath> <textPath xlink:href="#Path_120" startOffset="55%">(4)</textPath>
+ </text>
+ <path d="M-80-80L80 80" stroke="black"/>
+ <text class="text_normal" letter-spacing="12" transform="rotate(45 40.78 -38.1)">
+ PAST
+ </text>
+ <text class="text_normal" letter-spacing="12" transform="rotate(-135 27.43 23.79)">
+ FUTURE
+ </text>
+ <use xlink:href="#frozenPoint" transform="rotate(10)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(25)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(40)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(55)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(70)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(85)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(100)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(115)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(130)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(145)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(160)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(175)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(190)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(205)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(220)"/>
+ </g>
+ <g class="text_normal" transform="translate(380 30)">
+ <text>
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25">
+ 1: txid_current + 2 ^ 31 (splitt-point)
+ </text>
+ <text y="50">
+ 2: autovacuum_freeze_max_age (200 mio.)
+ </text>
+ <text y="75">
+ 3: vacuum_freeze_table_age (150 mio.)
+ </text>
+ <text y="100">
+ 4: vacuum_freeze_min_age (50 mio.)
+ </text>
+ <text y="125">
+ 5: txid_current (splitt-point, jungest xid)
+ </text>
+ <text y="155">
+ per table: pg_class.relfrozenxid <tspan font-weight="700">must</tspan> be between (1) and (5);
+ </text>
+ <text y="175" x="75">
+ normally it is between (3) and (4)
+ </text>
+ <use xlink:href="#unfrozenPoint" transform="translate(106 200)"/>
+ <text y="205" x="20">
+ Unfrozen xid
+ </text>
+ <use xlink:href="#frozenPoint" transform="translate(106 224)"/>
+ <text y="230" x="20">
+ Frozen xid
+ </text>
+ <text y="260">
+ (figure is out of scale)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink.svg b/doc/src/sgml/images/freeze-ink.svg
new file mode 100644
index 0000000000..9c16fc7b5b
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink.svg
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="320px"
+ viewBox="0 0 850 320"
+ id="svg454"
+ sodipodi:docname="freeze-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata458">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Freeze</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview456"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="160"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg454" />
+ <title
+ id="title309">Freeze</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style311">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs318">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle
+ id="frozenPoint"
+ r="3"
+ stroke="green"
+ fill="green"
+ transform="translate(-100, 0)" />
+ <circle
+ id="unfrozenPoint"
+ r="3"
+ stroke="green"
+ fill="none"
+ transform="translate(-100, 0)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect320" />
+ <text
+ class="text_big"
+ x="70"
+ y="40"
+ id="text324"><tspan
+ style="font-style:italic;font-weight:bold"
+ id="tspan322">
+ Freeze</tspan>
+ to keep alive</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 190)"
+ id="g418">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle326" />
+ <text
+ class="text_normal"
+ id="text350">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath328">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath330">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath332">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="11.2%"
+ id="textPath334">(1)</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="61.2%"
+ id="textPath336">(5)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="red"
+ stroke-width="3"
+ startOffset="34%"
+ id="textPath338">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="34%"
+ id="textPath340">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="black"
+ stroke-width="3"
+ startOffset="45%"
+ id="textPath342">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath344">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="green"
+ stroke-width="3"
+ startOffset="55%"
+ id="textPath346">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="55%"
+ id="textPath348">(4)</textPath>
+ </text>
+ <!-- split it into 'past' and 'future' -->
+ <path
+ d="M -80 -80 l 160 160"
+ stroke="black"
+ id="path352" />
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(-15, -40) rotate(45)"
+ id="text354">PAST</text>
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(30, 60) rotate(225)"
+ id="text356">FUTURE</text>
+ <g
+ transform="rotate(10)"
+ id="g360">
+ <use
+ xlink:href="#frozenPoint"
+ id="use358" />
+ </g>
+ <g
+ transform="rotate(25)"
+ id="g364">
+ <use
+ xlink:href="#frozenPoint"
+ id="use362" />
+ </g>
+ <g
+ transform="rotate(40)"
+ id="g368">
+ <use
+ xlink:href="#frozenPoint"
+ id="use366" />
+ </g>
+ <g
+ transform="rotate(55)"
+ id="g372">
+ <use
+ xlink:href="#frozenPoint"
+ id="use370" />
+ </g>
+ <g
+ transform="rotate(70)"
+ id="g376">
+ <use
+ xlink:href="#frozenPoint"
+ id="use374" />
+ </g>
+ <g
+ transform="rotate(85)"
+ id="g380">
+ <use
+ xlink:href="#frozenPoint"
+ id="use378" />
+ </g>
+ <g
+ transform="rotate(100)"
+ id="g384">
+ <use
+ xlink:href="#frozenPoint"
+ id="use382" />
+ </g>
+ <g
+ transform="rotate(115)"
+ id="g388">
+ <use
+ xlink:href="#frozenPoint"
+ id="use386" />
+ </g>
+ <g
+ transform="rotate(130)"
+ id="g392">
+ <use
+ xlink:href="#frozenPoint"
+ id="use390" />
+ </g>
+ <g
+ transform="rotate(145)"
+ id="g396">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use394" />
+ </g>
+ <g
+ transform="rotate(160)"
+ id="g400">
+ <use
+ xlink:href="#frozenPoint"
+ id="use398" />
+ </g>
+ <g
+ transform="rotate(175)"
+ id="g404">
+ <use
+ xlink:href="#frozenPoint"
+ id="use402" />
+ </g>
+ <g
+ transform="rotate(190)"
+ id="g408">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use406" />
+ </g>
+ <g
+ transform="rotate(205)"
+ id="g412">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use410" />
+ </g>
+ <g
+ transform="rotate(220)"
+ id="g416">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use414" />
+ </g>
+ </g>
+ <!-- legend -->
+ <g
+ class="text_normal"
+ transform="translate(380 30)"
+ id="g452">
+ <text
+ id="text424">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan420">^</tspan>
+<tspan
+ dy="5"
+ id="tspan422">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text426">1: txid_current + 2 ^ 31 (splitt-point)</text>
+ <text
+ y="50"
+ id="text428">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text
+ y="75"
+ id="text430">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text
+ y="100"
+ id="text432">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text
+ y="125"
+ id="text434">5: txid_current (splitt-point, jungest xid)</text>
+ <text
+ y="155"
+ id="text438">per table: pg_class.relfrozenxid
+ <tspan
+ style="font-weight:bold"
+ id="tspan436">must</tspan>
+ be between (1) and (5);</text>
+ <text
+ y="175"
+ x="75"
+ id="text440">normally it is between (3) and (4)</text>
+ <use
+ xlink:href="#unfrozenPoint"
+ transform="translate(106, 200)"
+ id="use442" />
+ <text
+ y="205"
+ x="20"
+ id="text444">Unfrozen xid</text>
+ <use
+ xlink:href="#frozenPoint"
+ transform="translate(106, 224)"
+ id="use446" />
+ <text
+ y="230"
+ x="20"
+ id="text448">Frozen xid</text>
+ <text
+ y="260"
+ id="text450">(figure is out of scale)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-raw.svg b/doc/src/sgml/images/freeze-raw.svg
new file mode 100644
index 0000000000..4816569fbb
--- /dev/null
+++ b/doc/src/sgml/images/freeze-raw.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="320px"
+ viewBox="0 0 850 320" >
+
+ <title>Freeze</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100, 0)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100, 0)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="70" y="40"><tspan style="font-style:italic;font-weight:bold">
+ Freeze</tspan> to keep alive</text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 190)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_120" startOffset="11.2%" >(1)</textPath>
+ <textPath xlink:href="#Path_120" startOffset="61.2%" >(5)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="34%" >(2)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(3)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="55%" >(4)</textPath>
+
+ </text>
+
+ <!-- split it into 'past' and 'future' -->
+ <path d="M -80 -80 l 160 160" stroke="black" />
+ <text class="text_normal" letter-spacing="12" transform="translate(-15, -40) rotate(45)">PAST</text>
+ <text class="text_normal" letter-spacing="12" transform="translate(30, 60) rotate(225)">FUTURE</text>
+
+ <g transform="rotate(10)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(25)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(40)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(55)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(70)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(85)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(100)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(115)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(130)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(145)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(160)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(175)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(190)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(205)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(220)"><use xlink:href="#unfrozenPoint"/></g>
+
+ </g>
+
+ <!-- legend -->
+ <g class="text_normal" transform="translate(380 30)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: txid_current + 2 ^ 31 (splitt-point)</text>
+ <text y="50">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text y="75">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text y="100">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text y="125">5: txid_current (splitt-point, jungest xid)</text>
+ <text y="155">per table: pg_class.relfrozenxid
+ <tspan style="font-weight:bold">must</tspan> be between (1) and (5);</text>
+ <text y="175" x="75">normally it is between (3) and (4)</text>
+
+ <use xlink:href="#unfrozenPoint" transform="translate(106, 200)"/>
+ <text y="205" x="20">Unfrozen xid</text>
+
+ <use xlink:href="#frozenPoint" transform="translate(106, 224)"/>
+ <text y="230" x="20">Frozen xid</text>
+
+ <text y="260">(figure is out of scale)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
new file mode 100644
index 0000000000..26bce6176d
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
@@ -0,0 +1,83 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="720" height="430" viewBox="0 0 720 430">
+ <title>
+ Hierarchy of Internal Objects
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Hierarchy of internal Objects
+ </text>
+ <g fill="none">
+ <g transform="translate(350 240)">
+ <ellipse rx="320" ry="170" stroke="blue"/>
+ <text class="text_normal" x="-140" y="-130">
+ Cluster
+ </text>
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-60" y="5">
+ Database Names
+ </text>
+ </g>
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-40" y="5">
+ Tablespace
+ </text>
+ </g>
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-70" y="5">
+ Replication Origins
+ </text>
+ </g>
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue"/>
+ <text class="text_normal" x="-60" y="-3">
+ Subscription for
+ </text>
+ <text class="text_normal" x="-68" y="10">
+ Logical Replication
+ </text>
+ </g>
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-15" y="5">
+ Role
+ </text>
+ </g>
+ </g>
+ <g transform="translate(270 250)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2"/>
+ <text class="text_normal" x="-60" y="-80">
+ Database
+ </text>
+ <g transform="translate(-150 -30)">
+ <ellipse rx="50" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Extension
+ </text>
+ </g>
+ <g transform="translate(-155 35)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Collation
+ </text>
+ </g>
+ <g transform="translate(30 20)">
+ <ellipse rx="140" ry="70" stroke="blue"/>
+ <text class="text_normal" x="-80" y="-35">
+ Schema
+ </text>
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue"/>
+ <text class="text_normal" x="-50" y="5">
+ Table, View, ...
+ </text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
new file mode 100644
index 0000000000..638ba83c4f
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="720px"
+ height="430px"
+ viewBox="0 0 720 430"
+ id="svg540"
+ sodipodi:docname="internal-objects-hierarchy-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata546">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Hierarchy of Internal Objects</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs544" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview542"
+ showgrid="false"
+ inkscape:zoom="0.51944444"
+ inkscape:cx="360"
+ inkscape:cy="215"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg540" />
+ <title
+ id="title460">Hierarchy of Internal Objects</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style462">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect464" />
+ <text
+ class="text_big"
+ x="200"
+ y="40"
+ id="text466">Hierarchy of internal Objects</text>
+ <!-- set centre of figure and default values -->
+ <g
+ transform="translate(350 240)"
+ fill="none"
+ id="g538">
+ <g
+ id="g504">
+ <ellipse
+ rx="320"
+ ry="170"
+ stroke="blue"
+ id="ellipse468" />
+ <text
+ class="text_normal"
+ x="-140"
+ y="-130"
+ id="text470">Cluster</text>
+ <g
+ transform="translate(40 -125)"
+ id="g476">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse472" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="5"
+ id="text474">Database Names</text>
+ </g>
+ <g
+ transform="translate(180 -70)"
+ id="g482">
+ <ellipse
+ rx="60"
+ ry="20"
+ stroke="blue"
+ id="ellipse478" />
+ <text
+ class="text_normal"
+ x="-40"
+ y="5"
+ id="text480">Tablespace</text>
+ </g>
+ <g
+ transform="translate(230 -5)"
+ id="g488">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse484" />
+ <text
+ class="text_normal"
+ x="-70"
+ y="5"
+ id="text486">Replication Origins</text>
+ </g>
+ <g
+ transform="translate(200 70)"
+ id="g496">
+ <ellipse
+ rx="78"
+ ry="27"
+ stroke="blue"
+ id="ellipse490" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-3"
+ id="text492">Subscription for</text>
+ <text
+ class="text_normal"
+ x="-68"
+ y="10"
+ id="text494">Logical Replication</text>
+ </g>
+ <g
+ transform="translate(100 120)"
+ id="g502">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse498" />
+ <text
+ class="text_normal"
+ x="-15"
+ y="5"
+ id="text500">Role</text>
+ </g>
+ </g>
+ <g
+ transform="translate(-80 10)"
+ id="g536">
+ <ellipse
+ rx="220"
+ ry="110"
+ stroke="blue"
+ stroke-width="2px"
+ id="ellipse506" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-80"
+ id="text508">Database</text>
+ <g
+ transform="translate(-120 -50)"
+ id="g534">
+ <g
+ transform="translate(-30 20)"
+ id="g514">
+ <ellipse
+ rx="50"
+ ry="20"
+ stroke="blue"
+ id="ellipse510" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text512">Extension</text>
+ </g>
+ <g
+ transform="translate(-35 85)"
+ id="g520">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse516" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text518">Collation</text>
+ </g>
+ <g
+ transform="translate(150 70)"
+ id="g532">
+ <ellipse
+ rx="140"
+ ry="70"
+ stroke="blue"
+ id="ellipse522" />
+ <text
+ class="text_normal"
+ x="-80"
+ y="-35"
+ id="text524">Schema</text>
+ <g
+ transform="translate(20 10)"
+ id="g530">
+ <ellipse
+ rx="90"
+ ry="30"
+ stroke="blue"
+ id="ellipse526" />
+ <text
+ class="text_normal"
+ x="-50"
+ y="5"
+ id="text528">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
new file mode 100644
index 0000000000..f0dc890f6b
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="720px" height="430px"
+ viewBox="0 0 720 430" >
+
+ <title>Hierarchy of Internal Objects</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="200" y="40">Hierarchy of internal Objects</text>
+
+
+ <!-- set centre of figure and default values -->
+ <g transform="translate(350 240)" fill="none">
+
+ <g>
+ <ellipse rx="320" ry="170" stroke="blue" />
+ <text class="text_normal" x="-140" y="-130">Cluster</text>
+
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-60" y="5">Database Names</text>
+ </g>
+
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue" />
+ <text class="text_normal" x="-40" y="5">Tablespace</text>
+ </g>
+
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-70" y="5">Replication Origins</text>
+ </g>
+
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue" />
+ <text class="text_normal" x="-60" y="-3">Subscription for</text>
+ <text class="text_normal" x="-68" y="10">Logical Replication</text>
+ </g>
+
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-15" y="5">Role</text>
+ </g>
+
+ </g>
+
+ <g transform="translate(-80 10)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2px" />
+ <text class="text_normal" x="-60" y="-80">Database</text>
+
+ <g transform="translate(-120 -50)">
+ <g transform="translate(-30 20)">
+ <ellipse rx="50" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Extension</text>
+ </g>
+
+ <g transform="translate(-35 85)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Collation</text>
+ </g>
+
+ <g transform="translate(150 70)">
+ <ellipse rx="140" ry="70" stroke="blue" />
+ <text class="text_normal" x="-80" y="-35">Schema</text>
+
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue" />
+ <text class="text_normal" x="-50" y="5">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink-svgo.svg b/doc/src/sgml/images/mvcc-ink-svgo.svg
new file mode 100644
index 0000000000..6a1aa9ffdf
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink-svgo.svg
@@ -0,0 +1,151 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="150" viewBox="0 0 850 150">
+ <title>
+ MVCC
+ </title>
+ <style>
+ .text_small{font-style:normal;font-weight:400;font-size:10px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <marker id="triangle_1" markerWidth="10" markerHeight="10" refX="5" refY="5" orient="auto" stroke="black" fill="none">
+ <path d="M0 0l10 5-10 5"/>
+ </marker>
+ <path id="arrow" d="M0 0q20-15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+ <g id="tuple" stroke="black">
+ <path d="M80 0H0v20h80M29 0v20M60 0v20"/>
+ <path d="M80 0h15M80 20h15" stroke-dasharray="2 1"/>
+ </g>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <g fill="none">
+ <g transform="translate(20 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">123</tspan> <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)" fill="#00f">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 83)" fill="#00f">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(185 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">135</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 53)" fill="#00f">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(350 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">142</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 23)" fill="#00f">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(515 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">821</tspan> <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 821
+ </text>
+ <text class="text_small" transform="translate(125 23)">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(740 110)">
+ <path d="M102-20H-18v90" stroke="black"/>
+ <text font-weight="400" font-size="16" font-family=""Open Sans",sans-serif" fill="#000">
+ Legend
+ </text>
+ <use xlink:href="#tuple" transform="translate(0 10)"/>
+ <text class="text_small" transform="translate(3 23)">
+ xmin
+ </text>
+ <text class="text_small" transform="translate(32 23)">
+ xmax
+ </text>
+ <text class="text_small" transform="translate(65 23)">
+ data
+ </text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink.svg b/doc/src/sgml/images/mvcc-ink.svg
new file mode 100644
index 0000000000..aeb499f674
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink.svg
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="150px"
+ viewBox="0 0 850 150"
+ id="svg693"
+ sodipodi:docname="mvcc-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata697">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>MVCC</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview695"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="75"
+ inkscape:window-x="81"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg693" />
+ <title
+ id="title548">MVCC</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style550">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs561">
+ <marker
+ id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto"
+ stroke="black"
+ fill="none">
+ <path
+ d="M 0,0 L 10,5 L 0,10"
+ id="path552" />
+ </marker>
+ <g
+ id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path
+ d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20"
+ stroke="black"
+ id="path555" />
+ <!-- prolong the rectangle -->
+ <path
+ d="M 80 0 h 15 M 80 20 h 15"
+ stroke="black"
+ stroke-dasharray="2 1"
+ id="path557" />
+ </g>
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path
+ id="arrow"
+ d="M 0 0 Q 20 -15 40 0"
+ stroke="black"
+ marker-end="url(#triangle_1)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect563" />
+ <!-- set default values -->
+ <g
+ fill="none"
+ id="g691">
+ <!-- start plus first INSERT -->
+ <g
+ transform="translate(20, 40)"
+ id="g581">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text569">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan565">123</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan567">: INSERT</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use571" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use573" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ style="fill:blue"
+ id="text575">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text577">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ style="fill:blue"
+ id="text579">'x'</text>
+ </g>
+ <!-- first UPDATE -->
+ <g
+ transform="translate(185, 40)"
+ id="g607">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text587">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan583">135</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan585">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use589" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use591" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ style="fill:blue"
+ id="text593">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text595">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ style="fill:blue"
+ id="text597">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use599" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text601">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text603">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text605">'x'</text>
+ </g>
+ <!-- next UPDATE -->
+ <g
+ transform="translate(350, 40)"
+ id="g641">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text613">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan609">142</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan611">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use615" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use617" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ style="fill:blue"
+ id="text619">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text621">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ style="fill:blue"
+ id="text623">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use625" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text627">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text629">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text631">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use633" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text635">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text637">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text639">'x'</text>
+ </g>
+ <!-- DELETE -->
+ <g
+ transform="translate(515, 40)"
+ id="g675">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text647">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan643">821</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan645">: DELTE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use649" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use651" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text653">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text655">821</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ id="text657">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use659" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text661">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ id="text663">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text665">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use667" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text669">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text671">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text673">'x'</text>
+ </g>
+ <!-- LEGEND -->
+ <g
+ transform="translate(740, 110)"
+ id="g689">
+ <path
+ d="M 102 -20 h -120 v 90"
+ stroke="black"
+ id="path677" />
+ <text
+ class="text_normal"
+ transform="translate(0, 0)"
+ id="text679">Legend</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(0, 10)"
+ id="use681" />
+ <text
+ class="text_small"
+ transform="translate(3, 23)"
+ id="text683">xmin</text>
+ <text
+ class="text_small"
+ transform="translate(32, 23)"
+ id="text685">xmax</text>
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text687">data</text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-raw.svg b/doc/src/sgml/images/mvcc-raw.svg
new file mode 100644
index 0000000000..c5005db37d
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-raw.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="150px"
+ viewBox="0 0 850 150" >
+
+ <title>MVCC</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <marker id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto" stroke="black" fill="none">
+ <path d="M 0,0 L 10,5 L 0,10" />
+ </marker>
+
+ <g id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20" stroke="black"/>
+ <!-- prolong the rectangle -->
+ <path d="M 80 0 h 15 M 80 20 h 15" stroke="black" stroke-dasharray="2 1"/>
+ </g>
+
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path id="arrow" d="M 0 0 Q 20 -15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- set default values -->
+ <g fill="none">
+
+ <!-- start plus first INSERT -->
+ <g transform="translate(20, 40)">
+
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">123</tspan>
+ <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)" style="fill:blue">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 83)" style="fill:blue">'x'</text>
+ </g>
+
+ <!-- first UPDATE -->
+ <g transform="translate(185, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">135</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 53)" style="fill:blue">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- next UPDATE -->
+ <g transform="translate(350, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">142</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 23)" style="fill:blue">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- DELETE -->
+ <g transform="translate(515, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">821</tspan>
+ <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">821</text>
+ <text class="text_small" transform="translate(125, 23)">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- LEGEND -->
+ <g transform="translate(740, 110)">
+ <path d="M 102 -20 h -120 v 90" stroke="black"/>
+ <text class="text_normal" transform="translate(0, 0)">Legend</text>
+ <use xlink:href="#tuple" transform="translate(0, 10)"/>
+ <text class="text_small" transform="translate(3, 23)">xmin</text>
+ <text class="text_small" transform="translate(32, 23)">xmax</text>
+ <text class="text_small" transform="translate(65, 23)">data</text>
+ </g>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink-svgo.svg b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
new file mode 100644
index 0000000000..15353bf307
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
@@ -0,0 +1,285 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 900 600">
+ <title>
+ PG Overall Server Architecture
+ </title>
+ <style>
+ .text_big{font-style:normal}.text_big,.text_comment,.text_normal,.text_small{font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_normal,.text_small{font-style:normal}.text_small{font-size:12px}.text_normal{font-size:16px}.text_big{font-size:24px}.text_comment{font-style:italic;font-size:16px}
+ </style>
+ <defs>
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (200 x 20 px)
+ </title>
+ <path d="M200 10v10H0V0h190v10h10L190 0"/>
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (250 x 20 px)
+ </title>
+ <path d="M250 10v10H0V0h240v10h10L240 0"/>
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (100 x 35 px)
+ </title>
+ <path d="M100 10v25H0V0h90v10h10L90 0"/>
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (170 x 50 px)
+ </title>
+ <path d="M170 10v40H0V0h160v10h10L160 0"/>
+ </symbol>
+ <symbol id="state_300x120">
+ <title>
+ UML State (300x120)
+ </title>
+ <rect width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>
+ UML State (350x120)
+ </title>
+ <rect width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="disc" stroke="blue" fill="none">
+ <title>
+ Disc
+ </title>
+ <ellipse cx="51" cy="13" rx="50" ry="12"/>
+ <path d="M1 13v60"/>
+ <path d="M101 13v60"/>
+ <path d="M1 73a50 12 0 00100 0"/>
+ </symbol>
+ <symbol id="laptop" stroke="black" fill="none">
+ <title>
+ Laptop
+ </title>
+ <path d="M20 40V0h54v40l15 15H5l15-15h54"/>
+ <path d="M23 3h48v34H23z"/>
+ <path d="M30 10h20"/>
+ <path d="M30 15h25"/>
+ <path d="M30 20h10"/>
+ <path d="M30 30h20"/>
+ <path d="M25 50h45l2 2H22z"/>
+ </symbol>
+ <marker id="arrowhead_start" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto">
+ <path d="M6 0L0 3l6 3" stroke="black" fill="none"/>
+ </marker>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="15" y="40" class="text_big">
+ Client
+ </text>
+ <text x="140" y="40" class="text_big">
+ Server
+ </text>
+ <use xlink:href="#laptop" x="5" y="210"/>
+ <g transform="translate(130 70)">
+ <use xlink:href="#state_350x120"/>
+ <text x="5" y="20" class="text_normal">
+ maintenance_work_mem (per connection)
+ </text>
+ <text x="5" y="45" class="text_normal">
+ work_mem (per query operation)
+ </text>
+ <text x="5" y="70" class="text_normal">
+ autovacuum_work_mem (per worker process)
+ </text>
+ <text x="5" y="95" class="text_normal">
+ temp_buffer (per connection)
+ </text>
+ <text x="5" y="110" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_200x20" x="140" y="-15"/>
+ <text x="150" class="text_comment">
+ Individual Memory
+ </text>
+ </g>
+ <g transform="translate(520 70)">
+ <use xlink:href="#state_300x120"/>
+ <text x="10" y="30" class="text_normal">
+ shared_buffers (heap and index)
+ </text>
+ <text x="10" y="70" class="text_normal">
+ wal_buffers (WAL records)
+ </text>
+ <text x="10" y="100" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_250x20" x="40" y="-15"/>
+ <text x="50" class="text_comment">
+ Shared Memory (per Cluster)
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M160 215h295v30H160z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(160 215)">
+ Postgres (outdated term: Postmaster)
+ </text>
+ <path d="M90 230h69" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 230)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 1
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M150 315h370v30H150z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(150 315)">
+ Backend processes (one per connection)
+ </text>
+ <path d="M155 315v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M160 310v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M90 240l63 63" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 290)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 3
+ </text>
+ </g>
+ <path d="M360 250v50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180 255)">
+ <use xlink:href="#note_250x20"/>
+ <text x="10" y="15" class="text_comment">
+ Creates backend processes
+ </text>
+ </g>
+ <g transform="translate(360 281)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 2
+ </text>
+ </g>
+ <path d="M460 300V200" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M498 300V95h30" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M508 300V135h20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M550 220h120v30H550z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(550 220)">
+ WAL Writer
+ </text>
+ <path d="M590 150v65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M590 255v230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 340h140v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 340)">
+ Checkpointer
+ </text>
+ <path d="M740 110v220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 355H475v130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M700 330V150" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50"/>
+ <text x="60" y="-35" class="text_comment">
+ Checkpoint
+ </text>
+ <text x="60" y="-20" class="text_comment">
+ Record
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M610 380h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 380)">
+ Background Writer
+ </text>
+ <path d="M770 110v260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 395H485v90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 420h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 420)">
+ WAL Archiver
+ </text>
+ <path d="M620 485l30-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M740 455v30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M135 380h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 380)">
+ AutoVacuum
+ </text>
+ <path d="M140 380v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path d="M145 375v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path stroke="blue" fill="none" d="M135 430h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 430)">
+ Log Writer
+ </text>
+ <path stroke="blue" fill="none" d="M290 370h140v30H290z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(290 370)">
+ Stats Collector
+ </text>
+ <g transform="translate(145 490)">
+ <use xlink:href="#disc"/>
+ <text x="35" y="45" class="text_normal">
+ Log
+ </text>
+ <text x="20" y="60" class="text_small">
+ text lines,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <path d="M195 465v20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(410 490)">
+ <use xlink:href="#disc"/>
+ <text x="10" y="40" class="text_normal">
+ Heap and
+ </text>
+ <text x="25" y="55" class="text_normal">
+ Index
+ </text>
+ <text x="15" y="70" class="text_small">
+ binary blocks,
+ </text>
+ <text x="30" y="80" class="text_small">
+ random
+ </text>
+ </g>
+ <path d="M450 485V350" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(295 420)">
+ <use xlink:href="#note_170x50"/>
+ <text x="5" y="15" class="text_comment">
+ Read heap and index
+ </text>
+ <text x="5" y="30" class="text_comment">
+ pages and transfer
+ </text>
+ <text x="5" y="45" class="text_comment">
+ them to shared_buffers
+ </text>
+ </g>
+ <g transform="translate(550 490)">
+ <use xlink:href="#disc"/>
+ <text x="30" y="45" class="text_normal">
+ WAL
+ </text>
+ <text x="10" y="60" class="text_small">
+ binary records,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <g transform="translate(690 490)">
+ <use xlink:href="#disc"/>
+ <text x="16" y="45" class="text_normal">
+ Archived
+ </text>
+ <text x="36" y="60" class="text_normal">
+ WAL
+ </text>
+ </g>
+ <path d="M110 20v550" stroke="black" fill="none"/>
+ <g transform="rotate(90 -33.5 156.5)">
+ <use xlink:href="#note_200x20"/>
+ <text class="text_comment" x="10" y="15">
+ Via TCP/IP or socket
+ </text>
+ </g>
+ <text class="text_big" x="95" transform="rotate(90 425 425)">
+ RAM
+ </text>
+ <text class="text_big" x="250" transform="rotate(90 425 425)">
+ PROCESSES
+ </text>
+ <text class="text_big" x="500" transform="rotate(90 425 425)">
+ FILES
+ </text>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink.svg b/doc/src/sgml/images/ram-proc-file-ink.svg
new file mode 100644
index 0000000000..6fe6ea7ef1
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink.svg
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="600px"
+ viewBox="0 0 900 600"
+ id="svg1003"
+ sodipodi:docname="ram-proc-file-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata1007">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>PG Overall Server Architecture</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="883"
+ inkscape:window-height="645"
+ id="namedview1005"
+ showgrid="false"
+ inkscape:zoom="0.39333333"
+ inkscape:cx="450"
+ inkscape:cy="300"
+ inkscape:window-x="468"
+ inkscape:window-y="125"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg1003" />
+ <title
+ id="title699">PG Overall Server Architecture</title>
+ <style
+ type="text/css"
+ id="style701">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs767">
+ <!-- Some notes in different sizes -->
+ <symbol
+ id="note_200x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title703">UML Note (200 x 20 px)</title>
+ <path
+ d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10"
+ id="path705" />
+ </symbol>
+ <symbol
+ id="note_250x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title708">UML Note (250 x 20 px)</title>
+ <path
+ d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10"
+ id="path710" />
+ </symbol>
+ <symbol
+ id="note_100x35"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title713">UML Note (100 x 35 px)</title>
+ <path
+ d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10"
+ id="path715" />
+ </symbol>
+ <symbol
+ id="note_170x50"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title718">UML Note (170 x 50 px)</title>
+ <path
+ d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10"
+ id="path720" />
+ </symbol>
+ <!-- UML states (used for buffers) -->
+ <symbol
+ id="state_300x120">
+ <title
+ id="title723">UML State (300x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="300"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect725" />
+ </symbol>
+ <symbol
+ id="state_350x120">
+ <title
+ id="title728">UML State (350x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="350"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect730" />
+ </symbol>
+ <!-- Discs -->
+ <symbol
+ id="disc"
+ stroke="blue"
+ fill="none">
+ <title
+ id="title733">Disc</title>
+ <ellipse
+ cx="51"
+ cy="13"
+ rx="50"
+ ry="12"
+ id="ellipse735" />
+ <!-- top -->
+ <path
+ d="M 1,13 v 60"
+ id="path737" />
+ <!-- left -->
+ <path
+ d="M 101,13 v 60"
+ id="path739" />
+ <!-- right -->
+ <path
+ d="M 1,73 A 50, 12, 0, 0, 0, 101,73"
+ id="path741" />
+ <!-- bottom -->
+ </symbol>
+ <!-- Laptop -->
+ <symbol
+ id="laptop"
+ stroke="black"
+ fill="none">
+ <title
+ id="title744">Laptop</title>
+ <path
+ d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54"
+ id="path746" />
+ <rect
+ x="23"
+ y="3"
+ width="48"
+ height="34"
+ id="rect748" />
+ <!-- symbolize some lines -->
+ <path
+ d="M 30,10 h 20"
+ id="path750" />
+ <path
+ d="M 30,15 h 25"
+ id="path752" />
+ <path
+ d="M 30,20 h 10"
+ id="path754" />
+ <path
+ d="M 30,30 h 20"
+ id="path756" />
+ <!-- symbolize keyboard -->
+ <path
+ d="M 25,50 h 45 l 2,2 h -50 z "
+ id="path758" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path761" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path764" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect769" />
+ <!-- caption, client side -->
+ <text
+ x="15"
+ y="40"
+ class="text_big"
+ id="text771">Client</text>
+ <text
+ x="140"
+ y="40"
+ class="text_big"
+ id="text773">Server</text>
+ <use
+ xlink:href="#laptop"
+ x="5"
+ y="210"
+ id="use775" />
+ <!-- individual memory -->
+ <g
+ transform="translate(130, 70)"
+ id="g793">
+ <use
+ xlink:href="#state_350x120"
+ x="0"
+ y="0"
+ id="use777" />
+ <text
+ x="5"
+ y="20"
+ class="text_normal"
+ id="text779">maintenance_work_mem (per connection)</text>
+ <text
+ x="5"
+ y="45"
+ class="text_normal"
+ id="text781">work_mem (per query operation)</text>
+ <text
+ x="5"
+ y="70"
+ class="text_normal"
+ id="text783">autovacuum_work_mem (per worker process)</text>
+ <text
+ x="5"
+ y="95"
+ class="text_normal"
+ id="text785">temp_buffer (per connection)</text>
+ <text
+ x="5"
+ y="110"
+ class="text_normal"
+ id="text787">...</text>
+ <use
+ xlink:href="#note_200x20"
+ x="140"
+ y="-15"
+ id="use789" />
+ <text
+ x="150"
+ y="0"
+ class="text_comment"
+ id="text791">Individual Memory</text>
+ </g>
+ <!-- shared memory -->
+ <g
+ transform="translate(520, 70)"
+ id="g807">
+ <use
+ xlink:href="#state_300x120"
+ x="0"
+ y="0"
+ id="use795" />
+ <text
+ x="10"
+ y="30"
+ class="text_normal"
+ id="text797">shared_buffers (heap and index)</text>
+ <text
+ x="10"
+ y="70"
+ class="text_normal"
+ id="text799">wal_buffers (WAL records)</text>
+ <text
+ x="10"
+ y="100"
+ class="text_normal"
+ id="text801">...</text>
+ <use
+ xlink:href="#note_250x20"
+ x="40"
+ y="-15"
+ id="use803" />
+ <text
+ x="50"
+ y="0"
+ class="text_comment"
+ id="text805">Shared Memory (per Cluster)</text>
+ </g>
+ <!-- postmaster -->
+ <g
+ transform="translate(160, 215)"
+ id="g813">
+ <rect
+ width="295"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect809" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text811">Postgres (outdated term: Postmaster)</text>
+ </g>
+ <path
+ d="M 90,230 h 69"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path815" />
+ <g
+ transform="translate(140, 230)"
+ id="g821">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle817" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text819">1</text>
+ </g>
+ <!-- backend processes -->
+ <g
+ transform="translate(150, 315)"
+ id="g831">
+ <rect
+ width="370"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect823" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text825">Backend processes (one per connection)</text>
+ <path
+ d="M 5,0 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path827" />
+ <path
+ d="M 10,-5 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path829" />
+ </g>
+ <path
+ d="M 90,240 153,303"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path833" />
+ <g
+ transform="translate(140, 290)"
+ id="g839">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle835" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text837">3</text>
+ </g>
+ <!-- connection between postmaster and backend processes -->
+ <path
+ d="M 360,250 v 50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path841" />
+ <g
+ transform="translate(180, 255)"
+ id="g847">
+ <use
+ xlink:href="#note_250x20"
+ id="use843" />
+ <text
+ x="10"
+ y="15"
+ class="text_comment"
+ id="text845">Creates backend processes</text>
+ </g>
+ <g
+ transform="translate(360, 281)"
+ id="g853">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle849" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text851">2</text>
+ </g>
+ <!-- backend process' access to individual memory -->
+ <path
+ d="M 460,300 v -100"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path855" />
+ <!-- its access to shared buffers and WAL buffers -->
+ <path
+ d="M 498,300 v -205 h 30"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path857" />
+ <path
+ d="M 508,300 v -165 h 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path859" />
+ <!-- WAL writer -->
+ <g
+ transform="translate(550, 220)"
+ id="g865">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect861" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text863">WAL Writer</text>
+ </g>
+ <path
+ d="M 590,150 v 65"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path867" />
+ <path
+ d="M 590,255 v 230"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path869" />
+ <!-- Checkpoiner -->
+ <g
+ transform="translate(610, 340)"
+ id="g875">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect871" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text873">Checkpointer</text>
+ </g>
+ <path
+ d="M 740,110 v 220"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path877" />
+ <path
+ d="M 605,355 h -130 v 130"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path879" />
+ <path
+ d="M 700,330 v -180"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path881" />
+ <g
+ transform="translate(570, 330)"
+ id="g889">
+ <use
+ xlink:href="#note_100x35"
+ x="50"
+ y="-50"
+ id="use883" />
+ <text
+ x="60"
+ y="-35"
+ class="text_comment"
+ id="text885">Checkpoint</text>
+ <text
+ x="60"
+ y="-20"
+ class="text_comment"
+ id="text887">Record</text>
+ </g>
+ <!-- BG writer -->
+ <g
+ transform="translate(610, 380)"
+ id="g895">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect891" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text893">Background Writer</text>
+ </g>
+ <path
+ d="M 770,110 v 260"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path897" />
+ <path
+ d="M 605,395 h -120 v 90"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path899" />
+ <!-- Archiver -->
+ <g
+ transform="translate(610, 420)"
+ id="g905">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect901" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text903">WAL Archiver</text>
+ </g>
+ <path
+ d="M 620,485 l 30,-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path907" />
+ <path
+ d="M 740,455 v 30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path909" />
+ <!-- Vacuum -->
+ <g
+ transform="translate(135, 380)"
+ id="g919">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect911" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text913">AutoVacuum</text>
+ <path
+ d="M 5,0 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path915" />
+ <path
+ d="M 10,-5 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path917" />
+ </g>
+ <!-- Log Writer -->
+ <g
+ transform="translate(135, 430)"
+ id="g925">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect921" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text923">Log Writer</text>
+ </g>
+ <!-- Stats Collector -->
+ <g
+ transform="translate(290, 370)"
+ id="g931">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect927" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text929">Stats Collector</text>
+ </g>
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g
+ transform="translate(145, 490)"
+ id="g941">
+ <use
+ xlink:href="#disc"
+ id="use933" />
+ <text
+ x="35"
+ y="45"
+ class="text_normal"
+ id="text935">Log</text>
+ <text
+ x="20"
+ y="60"
+ class="text_small"
+ id="text937">text lines,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text939">sequential</text>
+ </g>
+ <path
+ d="M 195,465 v 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path943" />
+ <g
+ transform="translate(410, 490)"
+ id="g955">
+ <use
+ xlink:href="#disc"
+ id="use945" />
+ <text
+ x="10"
+ y="40"
+ class="text_normal"
+ id="text947">Heap and</text>
+ <text
+ x="25"
+ y="55"
+ class="text_normal"
+ id="text949">Index</text>
+ <text
+ x="15"
+ y="70"
+ class="text_small"
+ id="text951">binary blocks,</text>
+ <text
+ x="30"
+ y="80"
+ class="text_small"
+ id="text953">random</text>
+ </g>
+ <path
+ d="M 450,485 v -135"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path957" />
+ <g
+ transform="translate(295, 420)"
+ id="g967">
+ <use
+ xlink:href="#note_170x50"
+ id="use959" />
+ <text
+ x="5"
+ y="15"
+ class="text_comment"
+ id="text961">Read heap and index</text>
+ <text
+ x="5"
+ y="30"
+ class="text_comment"
+ id="text963">pages and transfer</text>
+ <text
+ x="5"
+ y="45"
+ class="text_comment"
+ id="text965">them to shared_buffers</text>
+ </g>
+ <g
+ transform="translate(550, 490)"
+ id="g977">
+ <use
+ xlink:href="#disc"
+ id="use969" />
+ <text
+ x="30"
+ y="45"
+ class="text_normal"
+ id="text971">WAL</text>
+ <text
+ x="10"
+ y="60"
+ class="text_small"
+ id="text973">binary records,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text975">sequential</text>
+ </g>
+ <g
+ transform="translate(690, 490)"
+ id="g985">
+ <use
+ xlink:href="#disc"
+ id="use979" />
+ <text
+ x="16"
+ y="45"
+ class="text_normal"
+ id="text981">Archived</text>
+ <text
+ x="36"
+ y="60"
+ class="text_normal"
+ id="text983">WAL</text>
+ </g>
+ <!-- boarder between client and server side -->
+ <path
+ d="M 110,20 v 550"
+ stroke="black"
+ fill="none"
+ id="path987" />
+ <g
+ transform="translate(123, 190) rotate(90)"
+ id="g993">
+ <use
+ xlink:href="#note_200x20"
+ id="use989" />
+ <text
+ class="text_comment"
+ x="10"
+ y="15"
+ id="text991">Via TCP/IP or socket</text>
+ </g>
+ <!-- right side -->
+ <g
+ transform="translate(850, 0) rotate(90)"
+ id="g1001">
+ <text
+ class="text_big"
+ x="95"
+ id="text995">RAM</text>
+ <text
+ class="text_big"
+ x="250"
+ id="text997">PROCESSES</text>
+ <text
+ class="text_big"
+ x="500"
+ id="text999">FILES</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-raw.svg b/doc/src/sgml/images/ram-proc-file-raw.svg
new file mode 100644
index 0000000000..814ff6dff1
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-raw.svg
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="600px"
+ viewBox="0 0 900 600">
+
+ <title>PG Overall Server Architecture</title>
+
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Some notes in different sizes -->
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>UML Note (200 x 20 px)</title>
+ <path d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>UML Note (250 x 20 px)</title>
+ <path d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>UML Note (100 x 35 px)</title>
+ <path d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>UML Note (170 x 50 px)</title>
+ <path d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- UML states (used for buffers) -->
+ <symbol id="state_300x120">
+ <title>UML State (300x120)</title>
+ <rect x="0" y="0" width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>UML State (350x120)</title>
+ <rect x="0" y="0" width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- Discs -->
+ <symbol id="disc" stroke="blue" fill="none" >
+ <title>Disc</title>
+ <ellipse cx="51" cy="13" rx="50" ry="12" /> <!-- top -->
+ <path d="M 1,13 v 60" /> <!-- left -->
+ <path d="M 101,13 v 60" /> <!-- right -->
+ <path d="M 1,73 A 50, 12, 0, 0, 0, 101,73" /> <!-- bottom -->
+ </symbol>
+
+ <!-- Laptop -->
+ <symbol id="laptop" stroke="black" fill="none" >
+ <title>Laptop</title>
+ <path d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54" />
+ <rect x="23" y="3" width="48" height="34" />
+ <!-- symbolize some lines -->
+ <path d="M 30,10 h 20" />
+ <path d="M 30,15 h 25" />
+ <path d="M 30,20 h 10" />
+ <path d="M 30,30 h 20" />
+ <!-- symbolize keyboard -->
+ <path d="M 25,50 h 45 l 2,2 h -50 z " />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption, client side -->
+ <text x="15" y="40" class="text_big">Client</text>
+ <text x="140" y="40" class="text_big">Server</text>
+ <use xlink:href="#laptop" x="5" y="210" />
+
+
+ <!-- individual memory -->
+ <g transform="translate(130, 70)">
+ <use xlink:href="#state_350x120" x="0" y="0" />
+ <text x="5" y="20" class="text_normal">maintenance_work_mem (per connection)</text>
+ <text x="5" y="45" class="text_normal">work_mem (per query operation)</text>
+ <text x="5" y="70" class="text_normal">autovacuum_work_mem (per worker process)</text>
+ <text x="5" y="95" class="text_normal">temp_buffer (per connection)</text>
+ <text x="5" y="110" class="text_normal">...</text>
+ <use xlink:href="#note_200x20" x="140" y="-15" />
+ <text x="150" y="0" class="text_comment">Individual Memory</text>
+ </g>
+
+ <!-- shared memory -->
+ <g transform="translate(520, 70)">
+ <use xlink:href="#state_300x120" x="0" y="0" />
+ <text x="10" y="30" class="text_normal">shared_buffers (heap and index)</text>
+ <text x="10" y="70" class="text_normal">wal_buffers (WAL records)</text>
+ <text x="10" y="100" class="text_normal">...</text>
+ <use xlink:href="#note_250x20" x="40" y="-15" />
+ <text x="50" y="0" class="text_comment">Shared Memory (per Cluster)</text>
+ </g>
+
+ <!-- postmaster -->
+ <g transform="translate(160, 215)">
+ <rect width="295" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Postgres (outdated term: Postmaster)</text>
+ </g>
+ <path d="M 90,230 h 69" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 230)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">1</text>
+ </g>
+
+ <!-- backend processes -->
+ <g transform="translate(150, 315)">
+ <rect width="370" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Backend processes (one per connection)</text>
+ <path d="M 5,0 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <path d="M 90,240 153,303" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 290)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">3</text>
+ </g>
+
+ <!-- connection between postmaster and backend processes -->
+ <path d="M 360,250 v 50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180, 255)">
+ <use xlink:href="#note_250x20" />
+ <text x="10" y="15" class="text_comment">Creates backend processes</text>
+ </g>
+ <g transform="translate(360, 281)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">2</text>
+ </g>
+
+ <!-- backend process' access to individual memory -->
+ <path d="M 460,300 v -100" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <!-- its access to shared buffers and WAL buffers -->
+ <path d="M 498,300 v -205 h 30" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M 508,300 v -165 h 20" stroke="black" fill="none"
+ marker-end="url(#arrowhead_end)"/>
+
+ <!-- WAL writer -->
+ <g transform="translate(550, 220)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Writer</text>
+ </g>
+ <path d="M 590,150 v 65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 590,255 v 230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Checkpoiner -->
+ <g transform="translate(610, 340)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Checkpointer</text>
+ </g>
+ <path d="M 740,110 v 220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,355 h -130 v 130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 700,330 v -180" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570, 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50" />
+ <text x="60" y="-35" class="text_comment">Checkpoint</text>
+ <text x="60" y="-20" class="text_comment">Record</text>
+ </g>
+
+ <!-- BG writer -->
+ <g transform="translate(610, 380)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Background Writer</text>
+ </g>
+ <path d="M 770,110 v 260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,395 h -120 v 90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Archiver -->
+ <g transform="translate(610, 420)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Archiver</text>
+ </g>
+ <path d="M 620,485 l 30,-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 740,455 v 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Vacuum -->
+ <g transform="translate(135, 380)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">AutoVacuum</text>
+ <path d="M 5,0 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <!-- Log Writer -->
+ <g transform="translate(135, 430)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Log Writer</text>
+ </g>
+
+ <!-- Stats Collector -->
+ <g transform="translate(290, 370)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Stats Collector</text>
+ </g>
+
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g transform="translate(145, 490)">
+ <use xlink:href="#disc" />
+ <text x="35" y="45" class="text_normal">Log</text>
+ <text x="20" y="60" class="text_small">text lines,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+ <path d="M 195,465 v 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(410, 490)">
+ <use xlink:href="#disc" />
+ <text x="10" y="40" class="text_normal">Heap and</text>
+ <text x="25" y="55" class="text_normal">Index</text>
+ <text x="15" y="70" class="text_small">binary blocks,</text>
+ <text x="30" y="80" class="text_small">random</text>
+ </g>
+ <path d="M 450,485 v -135" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(295, 420)">
+ <use xlink:href="#note_170x50" />
+ <text x="5" y="15" class="text_comment">Read heap and index</text>
+ <text x="5" y="30" class="text_comment">pages and transfer</text>
+ <text x="5" y="45" class="text_comment">them to shared_buffers</text>
+ </g>
+
+ <g transform="translate(550, 490)">
+ <use xlink:href="#disc" />
+ <text x="30" y="45" class="text_normal">WAL</text>
+ <text x="10" y="60" class="text_small">binary records,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+
+ <g transform="translate(690, 490)">
+ <use xlink:href="#disc" />
+ <text x="16" y="45" class="text_normal">Archived</text>
+ <text x="36" y="60" class="text_normal">WAL</text>
+ </g>
+
+ <!-- boarder between client and server side -->
+ <path d="M 110,20 v 550" stroke="black" fill="none" />
+ <g transform="translate(123, 190) rotate(90)">
+ <use xlink:href="#note_200x20" />
+ <text class="text_comment" x="10" y ="15">Via TCP/IP or socket</text>
+ </g>
+
+ <!-- right side -->
+ <g transform="translate(850, 0) rotate(90)">
+ <text class="text_big" x="95">RAM</text>
+ <text class="text_big" x="250">PROCESSES</text>
+ <text class="text_big" x="500">FILES</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink-svgo.svg b/doc/src/sgml/images/wraparound-ink-svgo.svg
new file mode 100644
index 0000000000..9882d2be23
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink-svgo.svg
@@ -0,0 +1,40 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="280" viewBox="0 0 850 280">
+ <title>
+ Cyclic usage of XIDs
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="370" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ Cyclic usage of XIDs modulo 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan>
+ </text>
+ <g fill="none" transform="translate(170 150)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_095" startOffset="30.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="30%">(1)</textPath> <textPath xlink:href="#Path_095" startOffset="45.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(2)</textPath> <textPath xlink:href="#Path_095" startOffset="50.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="50%">(3)</textPath> <textPath xlink:href="#Path_095" startOffset="62.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="62%">(4)</textPath>
+ </text>
+ </g>
+ <g class="text_normal">
+ <text transform="translate(400 130)">
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25" transform="translate(400 130)">
+ 1: oldest <tspan font-weight="700">active</tspan> xid (pg_stat_activity.backend_xmin)
+ </text>
+ <text y="50" transform="translate(400 130)">
+ 2: xmin of one row version
+ </text>
+ <text y="75" transform="translate(400 130)">
+ 3: xmax of the same row version
+ </text>
+ <text y="100" transform="translate(400 130)">
+ 4: jungest xid (txid_current)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink.svg b/doc/src/sgml/images/wraparound-ink.svg
new file mode 100644
index 0000000000..ca5e45ac2b
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="280px"
+ viewBox="0 0 850 280"
+ id="svg1072"
+ sodipodi:docname="wraparound-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata1076">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Cyclic usage of XIDs</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="860"
+ inkscape:window-height="644"
+ id="namedview1074"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="140"
+ inkscape:window-x="346"
+ inkscape:window-y="93"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg1072" />
+ <title
+ id="title1009">Cyclic usage of XIDs</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style1011">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs1016">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect1018" />
+ <text
+ class="text_big"
+ x="370"
+ y="40"
+ id="text1024">Cyclic usage of XIDs modulo 2
+ <tspan
+ dy="-5"
+ id="tspan1020">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1022">32</tspan>
+</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 150)"
+ id="g1052">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle1026" />
+ <text
+ class="text_normal"
+ id="text1050">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath1028">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath1030">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath1032">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="30.5%"
+ id="textPath1034">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="30%"
+ id="textPath1036">(1)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="45.5%"
+ id="textPath1038">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath1040">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="50.5%"
+ id="textPath1042">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="50%"
+ id="textPath1044">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="62.5%"
+ id="textPath1046">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="62%"
+ id="textPath1048">(4)</textPath>
+ </text>
+ </g>
+ <g
+ class="text_normal"
+ transform="translate(400 130)"
+ id="g1070">
+ <text
+ id="text1058">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan1054">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1056">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text1062">1: oldest <tspan
+ style="font-weight:bold"
+ id="tspan1060">active</tspan>
+ xid (pg_stat_activity.backend_xmin)</text>
+ <text
+ y="50"
+ id="text1064">2: xmin of one row version</text>
+ <text
+ y="75"
+ id="text1066">3: xmax of the same row version</text>
+ <text
+ y="100"
+ id="text1068">4: jungest xid (txid_current)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-raw.svg b/doc/src/sgml/images/wraparound-raw.svg
new file mode 100644
index 0000000000..9406f52970
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-raw.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="280px"
+ viewBox="0 0 850 280" >
+
+ <title>Cyclic usage of XIDs</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="370" y="40">Cyclic usage of XIDs modulo 2
+ <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan></text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 150)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_095" startOffset="30.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="30%" >(1)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="45.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(2)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="50.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="50%" >(3)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="62.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="62%" >(4)</textPath>
+ </text>
+ </g>
+
+ <g class="text_normal" transform="translate(400 130)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: oldest <tspan style="font-weight:bold">active</tspan> xid (pg_stat_activity.backend_xmin)</text>
+ <text y="50">2: xmin of one row version</text>
+ <text y="75">3: xmax of the same row version</text>
+ <text y="100">4: jungest xid (txid_current)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index c41ce9499b..6254bf9376 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -60,6 +60,7 @@ break is not needed in a wider output rendering.
</partintro>
&start;
+ &architecture;
&query;
&advanced;
diff --git a/doc/src/sgml/query.sgml b/doc/src/sgml/query.sgml
index c0889743c4..870349780f 100644
--- a/doc/src/sgml/query.sgml
+++ b/doc/src/sgml/query.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/query.sgml -->
<chapter id="tutorial-sql">
- <title>The <acronym>SQL</acronym> Language</title>
+ <title>Basics of the <acronym>SQL</acronym> Language</title>
<sect1 id="tutorial-sql-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml
index 5b73557835..b9184feb39 100644
--- a/doc/src/sgml/start.sgml
+++ b/doc/src/sgml/start.sgml
@@ -53,7 +53,7 @@
<sect1 id="tutorial-arch">
- <title>Architectural Fundamentals</title>
+ <title>Client/Server Model</title>
<para>
Before we proceed, you should understand the basic
@@ -65,37 +65,59 @@
<para>
In database jargon, <productname>PostgreSQL</productname> uses a
- client/server model. A <productname>PostgreSQL</productname>
+ client/server model. A <productname>PostgreSQL</productname>
session consists of the following cooperating processes
(programs):
+ </para>
- <itemizedlist>
- <listitem>
- <para>
- A server process, which manages the database files, accepts
- connections to the database from client applications, and
- performs database actions on behalf of the clients. The
- database server program is called
- <filename>postgres</filename>.
- <indexterm><primary>postgres</primary></indexterm>
- </para>
- </listitem>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A process at the server site with the name
+ <glossterm linkend="glossary-postmaster">
+ postgres (outdated term: Postmaster)</glossterm>
+ <indexterm><primary>postgres</primary></indexterm>.
+ It accepts connection requests from client applications, starts
+ (<quote>forks</quote>) a new <glossterm linkend="glossary-backend">
+ Backend process</glossterm> for each of them, and passes
+ the connection to it. From that point on, the client and the new
+ <firstterm>Backend process</firstterm>
+ communicate directly without intervention by the original
+ <firstterm>postgres</firstterm> process. Thus, the
+ <firstterm>postgres</firstterm> process is always running, waiting
+ for new client connections, whereas clients and associated
+ <firstterm>Backend processes</firstterm> come and go.
+ (All of this is of course invisible to the user. We only mention it
+ here for completeness.)
+ </para>
+ </listitem>
- <listitem>
- <para>
- The user's client (frontend) application that wants to perform
- database operations. Client applications can be very diverse
- in nature: a client could be a text-oriented tool, a graphical
- application, a web server that accesses the database to
- display web pages, or a specialized database maintenance tool.
- Some client applications are supplied with the
- <productname>PostgreSQL</productname> distribution; most are
- developed by users.
- </para>
- </listitem>
+ <listitem>
+ <para>
+ A group of processes at the server site, the <glossterm
+ linkend="glossary-instance">instance</glossterm>, to which also the
+ <firstterm>postgres</firstterm> process belongs. Their duties are
+ handling of central, common database activities like file access,
+ vacuum, <glossterm linkend="glossary-checkpoint">checkpoints</glossterm>,
+ replication, and more. The mentioned <firstterm>Backend processes</firstterm>
+ delegate those actions to the <firstterm>instance</firstterm>.
+ </para>
+ </listitem>
- </itemizedlist>
- </para>
+ <listitem>
+ <para>
+ The user's client (frontend) application that wants to perform
+ database operations. Client applications can be very diverse
+ in nature: a client could be a text-oriented tool, a graphical
+ application, a web server that accesses the database to
+ display web pages, or a specialized database maintenance tool.
+ Some client applications are supplied with the
+ <productname>PostgreSQL</productname> distribution; most are
+ developed by users.
+ </para>
+ </listitem>
+
+ </itemizedlist>
<para>
As is typical of client/server applications, the client and the
@@ -106,18 +128,6 @@
file name) on the database server machine.
</para>
- <para>
- The <productname>PostgreSQL</productname> server can handle
- multiple concurrent connections from clients. To achieve this it
- starts (<quote>forks</quote>) a new process for each connection.
- From that point on, the client and the new server process
- communicate without intervention by the original
- <filename>postgres</filename> process. Thus, the
- master server process is always running, waiting for
- client connections, whereas client and associated server processes
- come and go. (All of this is of course invisible to the user. We
- only mention it here for completeness.)
- </para>
</sect1>
On 2020-04-29 16:13, Jürgen Purtz wrote:
On 20.04.20 10:30, Jürgen Purtz wrote:
On 17.04.20 20:40, Erik Rijkers wrote:
Very good stuff, and useful. I think.
I mean that but nevertheless here is a lot of comment :)
(I didn't fully compile as docs, just read the 'text' from the patch
file)Thanks. Added nearly all of the suggestions.
What is new? Added two sub-chapters 'mvcc' and 'vacuum' plus graphics.
Made some modifications in previous sub-chapters and in existing
titles. Added some glossary entries.
[0003-architecture.patch]
Hi Jürgen,
Here are again some suggested changes, up to line 600 (of the patch -
that is around start of the new NVCC paragraph)
I may have repeated some thing you have already rejected (it was too
much work to go back and check). I am not a native speaker of english.
One general remark: in my humble opinion, you write too many capitalized
words. It's not really a problem but overall it's becomes bit too much.
But I have not marked these. perhaps some future iteration.
I'll probably read through the latter part of the patch later (probably
tomorrow).
Thanks,
Erik Rijkers
they merely send requests to the server side and receives
they merely send requests to the server side and receive
is a group of tightly coupled other server side processes plus a
is a group of tightly coupled other server-side processes plus a
Client requests (SELECT, UPDATE, ...) usually leads to the
Client requests (SELECT, UPDATE, ...) usually lead to the
Because files are much larger than memory, it's likely that
Because files are often larger than memory, it's likely that
RAM is performed in units of complete pages, retaining their size and
layout.
RAM is performed in units of complete pages.
Reading file pages is notedly slower than reading
Reading file pages is slower than reading
of the <firstterm>Backend processes</firstterm> has done the job those
pages are available for all other
of the <firstterm>Backend processes</firstterm> has read pages into
memory those pages are available for all other
they must be transferred back to disk. This is a two-step process.
they must be written back to disk. This is a two-step process.
Because of the sequential nature of this writing, it is much
Because of this writing is sequential, it is much
in an independent process. Nevertheless all
in an independent process. Nevertheless, all
huge I/O activities can block other processes significantly,
I/O activities can block other processes,
it starts periodically and acts only for a short period.
it starts periodically and is active only for a short period.
duty. As its name suggests, he has to create
duty. As its name suggests, it has to create
In consequence, after a <firstterm>Checkpoint</firstterm>
After a <firstterm>Checkpoint</firstterm>,
In correlation with data changes,
As a result of data changes,
text lines about serious and non-serious events which can happen
text lines about serious and less serious events which can happen
database contains many <glossterm
linkend="glossary-schema">schema</glossterm>,
database contains many <glossterm
linkend="glossary-schema">schemas</glossterm>,
belongs to a certain <firstterm>schema</firstterm>, they cannot
belongs to a single <firstterm>schema</firstterm>, they cannot
A <firstterm>Cluster</firstterm> is the outer frame for a
A <firstterm>Cluster</firstterm> is the outer container for a
<literal>postgres</literal> as a copy of
<literal>postgres</literal> is generated as a copy of
role of <literal>template0</literal> as the origin
role of <literal>template0</literal> as the pristine origin
are different objects and absolutely independent from each
are different objects and independent from each
complete <firstterm>cluster</firstterm>, independent from
<firstterm>cluster</firstterm>, independent from
anywhere in the file system. In many cases, the environment
somewhere in the file system. In many cases, the environment
some files, all of which are necessary to store long lasting
some files, all of which are necessary to store long-lasting
<firstterm>tablespaces</firstterm> itself.
<firstterm>tablespaces</firstterm> themselves.
<firstterm>Postgres</firstterm> (respectively
<firstterm>Postmaster</firstterm>) process.
<firstterm>Postgres</firstterm> process (also known as
<firstterm>Postmaster</firstterm>).
<title>MVCC</title>
<title>MVCC - Multiversion Concurrency Control</title>
The dabase must take a sensible decision to prevent the application
The database must take a sensible decision to prevent the application
# this sentence I just don't understand - can you please elucidate?
The database must take a sensible decision to prevent the application
from promising delivery of the single article to both clients.
On 2020-04-29 16:13, Jürgen Purtz wrote:
On 20.04.20 10:30, Jürgen Purtz wrote:
On 17.04.20 20:40, Erik Rijkers wrote:
Very good stuff, and useful. I think.
I mean that but nevertheless here is a lot of comment :)
(I didn't fully compile as docs, just read the 'text' from the patch
file)Thanks. Added nearly all of the suggestions.
What is new? Added two sub-chapters 'mvcc' and 'vacuum' plus graphics.
Made some modifications in previous sub-chapters and in existing titles.
Added some glossary entries.
I don't see this really as belonging into the tutorial. The tutorial
should be hands-on, how do you get started, how do you get some results.
Your material is more of an overview of the whole system. What's a new
user supposed to do with that?
--
Peter Eisentraut http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
On 29.04.20 21:12, Peter Eisentraut wrote:
I don't see this really as belonging into the tutorial. The tutorial
should be hands-on, how do you get started, how do you get some results.
Yes, the tutorial should be a short overview and give instructions how
to start. IMO the first 4 sub-chapters fulfill this expectation. Indeed,
the fifth (VACUUM) is extensive and offers many details.
During the inspection of the existing documentation I recognized that
there are many details about VACUUM, AUTOVACUUM, all of their parameters
as well as their behavior. But the information is spread across many
pages: Automatic Vacuuming, Client Connection Defaults, Routine
Vacuuming, Resource Consumption, VACUUM. Even for a person with some
pre-knowledge it is hard to get an overview how this fits together and
why things are solved in exactly this way. In the end we have very good
descriptions of all details but I miss the 'big picture'. Therefore I
summarized central aspects and tried to give an answer to the question
'why is it done in this way?'. I do not dispute that the current version
of the page is not adequate for beginners. But at some place we should
have such a summary about vacuuming and freezing.
How to proceed?
- Remove the page and add a short paragraph to the MVCC page instead.
- Cut down the page to a tiny portion.
- Divide it into two parts: a) a short introduction and b) the rest
after a statement like 'The following offers more details and parameters
that are more interesting for an experienced user than for a beginner.
You can easily skip it.'
Your material is more of an overview of the whole system. What's a
new user supposed to do with that?
When I dive into a new subject, I'm more interested in its architecture
than in its details. We shall offer an overview about the major PG
components and strategies to beginners.
--
Jürgen Purtz
On 30.04.20 14:31, Jürgen Purtz wrote:
On 29.04.20 21:12, Peter Eisentraut wrote:
I don't see this really as belonging into the tutorial. The tutorial
should be hands-on, how do you get started, how do you get some results.Yes, the tutorial should be a short overview and give instructions how
to start. IMO the first 4 sub-chapters fulfill this expectation.
Indeed, the fifth (VACUUM) is extensive and offers many details.During the inspection of the existing documentation I recognized that
there are many details about VACUUM, AUTOVACUUM, all of their
parameters as well as their behavior. But the information is spread
across many pages: Automatic Vacuuming, Client Connection Defaults,
Routine Vacuuming, Resource Consumption, VACUUM. Even for a person
with some pre-knowledge it is hard to get an overview how this fits
together and why things are solved in exactly this way. In the end we
have very good descriptions of all details but I miss the 'big
picture'. Therefore I summarized central aspects and tried to give an
answer to the question 'why is it done in this way?'. I do not dispute
that the current version of the page is not adequate for beginners.
But at some place we should have such a summary about vacuuming and
freezing.How to proceed?
- Remove the page and add a short paragraph to the MVCC page instead.
- Cut down the page to a tiny portion.
- Divide it into two parts: a) a short introduction and b) the rest
after a statement like 'The following offers more details and
parameters that are more interesting for an experienced user than for
a beginner. You can easily skip it.'Your material is more of an overview of the whole system. What's a
new user supposed to do with that?When I dive into a new subject, I'm more interested in its
architecture than in its details. We shall offer an overview about the
major PG components and strategies to beginners.
In comparison with to previous patch this one contains:
- Position and title changed to reflect its intention and importance.
- A <note> delimits VACUUM basics from details. This is done because I
cannot find another suitable place for such a summarizing description.
- Three additional sub-chapters.
--
Jürgen Purtz
Attachments:
0004-architecture.patchtext/x-patch; charset=UTF-8; name=0004-architecture.patchDownload
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
index f6c4627c3e..be04972bd7 100644
--- a/doc/src/sgml/advanced.sgml
+++ b/doc/src/sgml/advanced.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/advanced.sgml -->
<chapter id="tutorial-advanced">
- <title>Advanced Features</title>
+ <title>Advanced SQL Features</title>
<sect1 id="tutorial-advanced-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
new file mode 100644
index 0000000000..1a2117f42a
--- /dev/null
+++ b/doc/src/sgml/architecture.sgml
@@ -0,0 +1,1549 @@
+<!-- doc/src/sgml/architecture.sgml -->
+
+ <chapter id="tutorial-architecture">
+ <title>Architectural and implementational Cornerstones</title>
+
+ <para>
+ Every DBMS implements basic strategies to achieve a fast and
+ robust system. This chapter provides an overview of what
+ techniques <productname>PostgreSQL</productname> uses to
+ reach this aim.
+ </para>
+
+ <sect1 id="tutorial-ram-proc-file">
+ <title>Collaboration of Processes, RAM, and Files</title>
+ <para>
+ As is a matter of course, in a client/server architecture
+ clients do not have direct access to the database. Instead,
+ they merely send requests to the server-side and receive
+ according information from there. In the case of
+ <productname>PostgreSQL</productname>, at the server-side
+ there is one process per client, the so-called
+ <glossterm linkend="glossary-backend">Backend process</glossterm>.
+ It acts in close cooperation with the
+ <glossterm linkend="glossary-instance">Instance</glossterm> which
+ is a group of tightly coupled other server-side processes plus a
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>
+ area.
+ </para>
+
+ <para>
+ At start time, an instance is initiated by the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>
+ process.
+ It loads the configuration files, allocates the
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>,
+ and starts the comprehensive network of processes:
+ <glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
+ <glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
+ <glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
+ <glossterm linkend="glossary-wal-archiver">WAL Archiver</glossterm>,
+ <glossterm linkend="glossary-autovacuum">Autovacuum processes</glossterm>,
+ <glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
+ <glossterm linkend="glossary-logger">Logger</glossterm>, and more.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes
+ the main aspects of their collaboration.
+ </para>
+
+ <figure id="tutorial-ram-proc-file-figure">
+ <title>Architecture</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ Whenever a client application tries to connect to a
+ <glossterm linkend="glossary-database">database</glossterm>,
+ this request is handled in a first step by the <firstterm>
+ Postgres process</firstterm>. It checks the authorization,
+ starts a new <firstterm>Backend process</firstterm>,
+ and instructs the client application to connect to it. All
+ further client requests go to this process and are handled
+ by it.
+ </para>
+
+ <para>
+ Client requests (SELECT, UPDATE, ...) usually lead to the
+ necessity to read or write some data. In a first attempt
+ the client's <firstterm>Backend process</firstterm> tries
+ to get the information out of <firstterm>Shared
+ Memory</firstterm>. This <firstterm>Shared
+ Memory</firstterm> is a mirror of parts of the
+ <glossterm linkend="glossary-heap">heap</glossterm> and
+ <glossterm linkend="glossary-index">index</glossterm> files.
+ Because files are often larger than memory, it's likely that
+ the desired information is not (completely) available
+ in the RAM. In this case the <firstterm>Backend process</firstterm>
+ must transfer additional file pages to
+ <firstterm>Shared Memory</firstterm>. Files are physically
+ organized in pages. Every transfer between files and
+ RAM is performed in units of complete pages. Such transfers
+ don't change the size or layout of pages.
+ </para>
+
+ <para>
+ Reading file pages is notedly slower than reading
+ RAM. This is the primary motivation for the existence of
+ <firstterm>Shared Memory</firstterm>. As soon as one
+ of the <firstterm>Backend processes</firstterm> has
+ read pages into memory, those pages are available for all
+ other <firstterm>Backend processes</firstterm> for direct
+ access in RAM.
+ </para>
+
+ <para>
+ <firstterm>Shared Memory</firstterm> is limited in size.
+ Sooner or later, it becomes necessary to overwrite old RAM
+ pages. As long as the content of such pages hasn't
+ changed, this is not a problem. But in
+ <firstterm>Shared Memory</firstterm> also write
+ actions take place
+ — performed by any of the <firstterm>Backend
+ processes</firstterm> (or an
+ <glossterm linkend="glossary-autovacuum">autovacuum process</glossterm>,
+ or other processes). Such modified pages are called
+ <firstterm>dirty pages</firstterm>.
+ Before <firstterm>dirty pages</firstterm> can be overwritten,
+ they must be written back to disk. This is a two-step process.
+ </para>
+
+ <para>
+ First, whenever the content of a page changes, a
+ <glossterm linkend="glossary-wal-record">WAL record</glossterm>
+ is created out
+ of the delta-information (difference between old and
+ new content) and stored in another area of the
+ <firstterm>Shared Memory</firstterm>. These
+ <firstterm>WAL records</firstterm> are read by the
+ <firstterm>WAL Writer</firstterm> process,
+ which runs in parallel to the <firstterm>Backend
+ processes</firstterm> and all other processes of
+ the <firstterm>Instance</firstterm>. It writes
+ the continuously arising <firstterm>WAL records</firstterm> to
+ the end of the current
+ <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
+ Because this writing is sequential, it is much
+ faster than the more or less random access
+ to data files with <firstterm>heap</firstterm>
+ and <firstterm>index</firstterm> information.
+ As mentioned, this WAL-writing happens
+ in an independent process. Nevertheless, all
+ <firstterm>WAL records</firstterm> created out of one
+ <firstterm>dirty page</firstterm> must be transferred
+ to disk before the <firstterm>dirty page</firstterm>
+ itself can be transferred to disk.
+ </para>
+
+ <para>
+ Second, the transfer of <firstterm>dirty buffers</firstterm>
+ from <firstterm>Shared Memory</firstterm> to files must
+ take place. This is the primary duty of the
+ <firstterm>Background Writer</firstterm> process. Because
+ I/O activities can block other processes significantly,
+ it starts periodically and acts only for a short period.
+ Doing so, his expensive I/O activities are spread over
+ time, avoiding huge I/O peaks. Also, the <firstterm>
+ Checkpointer</firstterm> process transfers
+ <firstterm>dirty buffers</firstterm> to files —
+ see next paragraph.
+ </para>
+
+ <para>
+ The <firstterm>Checkpointer</firstterm> has a special
+ duty. As its name suggests, it has to create
+ <firstterm>Checkpoints</firstterm>. Such a
+ <glossterm linkend="glossary-checkpoint">Checkpoint</glossterm>
+ is a point in time when all older <firstterm>dirty buffers</firstterm>,
+ all older <firstterm>WAL records</firstterm>, and
+ finally a special <firstterm>Checkpoint record</firstterm>
+ have been written and flushed to disk.
+ After a <firstterm>Checkpoint</firstterm>,
+ data files and <firstterm>WAL files</firstterm> are in sync.
+ In case of a recovery (after a crash of the instance)
+ it is known that the information of all
+ <firstterm>WAL records</firstterm> preceding
+ the last <firstterm>Checkpoint record</firstterm>
+ is already integrated into the data files. This
+ speeds up a possibly occurring recovery.
+ </para>
+
+ <para>
+ As a result of data changes,
+ <firstterm>WAL records</firstterm> arise and get written
+ to <firstterm>WAL files</firstterm>.
+ Those <firstterm>WAL files</firstterm> — in combination with
+ a previously taken <firstterm>Base Backup</firstterm> —
+ are necessary to restore a database after a crash of the
+ disk, where data files have been stored. Therefore it is
+ recommended to transfer a copy of the <firstterm>
+ WAL files</firstterm>
+ to a second, independent place. The purpose of the
+ <firstterm>WAL Archiver</firstterm> process is to perform
+ this copy action.
+ </para>
+
+ <para>
+ The <glossterm linkend="glossary-stats-collector">Stats Collector</glossterm>
+ collects counters about accesses to <firstterm>SQL
+ objects</firstterm> like tables, rows, indexes, pages,
+ and more. It stores the obtained information in system
+ tables.
+ </para>
+
+ <para>
+ The <glossterm linkend="glossary-logger">Logger</glossterm> writes
+ text lines about serious and less serious events which can happen
+ during database access, e.g., wrong password, no permission,
+ long-running queries, ... .
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-cluster-db-schema">
+ <title>The logical Perspective: Cluster, Database, Schema</title>
+
+ <para>
+<!-- TODO: Link to cluster -->
+ On a <glossterm linkend="glossary-server">Server</glossterm>
+ exists one or more <glossterm linkend="glossary-instance">Cluster</glossterm>,
+ each of them contains three or more
+ <glossterm linkend="glossary-database">databases</glossterm>, each
+ database contains many <glossterm linkend="glossary-schema">schemas</glossterm>,
+ a schema contains <glossterm linkend="glossary-table">tables</glossterm>,
+ <glossterm linkend="glossary-view">views</glossterm>, and a lot of other objects.
+ Each <firstterm>table</firstterm> or <firstterm>view</firstterm>
+ belongs to a single <firstterm>schema</firstterm>; they cannot
+ belong to another <firstterm>schema</firstterm>. The same is
+ true for the schema/database and database/cluster relation.
+ <xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
+ this hierarchy.
+ </para>
+
+ <figure id="tutorial-cluster-db-schema-figure">
+ <title>Cluster, Database, Schema</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ A <firstterm>Cluster</firstterm> is the outer container for a
+ collection of databases. Clusters are created by the command
+ <xref linkend="app-initdb"/>.
+ </para>
+
+ <para>
+ <literal>template0</literal> is the very first
+ <firstterm>database</firstterm> of any
+ <firstterm>cluster</firstterm>. C-routines create
+ <literal>template0</literal> during the initialization phase of
+ the <firstterm>cluster</firstterm>.
+ In a second step, <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal>, and finally
+ <literal>postgres</literal> is generated as a copy of
+ <literal>template1</literal>. All other
+ <glossterm linkend="app-createdb">new databases</glossterm>
+ of this <firstterm>cluster</firstterm>,
+ such as <literal>my_db</literal>, are also copied from
+ <literal>template1</literal>. Due to the unique
+ role of <literal>template0</literal> as the pristine origin
+ of all other <firstterm>databases</firstterm>, no client
+ can connect to it.
+ </para>
+
+ <para>
+ Every database contains <glossterm linkend="glossary-schema">
+ schemas</glossterm>, and
+ <firstterm>schemas</firstterm> contain the other
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>.
+ <firstterm>Schemas</firstterm> are namespaces for
+ their <firstterm>SQL objects</firstterm> and ensure — with one
+ exception — that within their scope names are used only once across all
+ types of <firstterm>SQL objects</firstterm>. E.g., it is not possible
+ to have a table <literal>employee</literal> and a view
+ <literal>employee</literal> within the same
+ <firstterm>schema</firstterm>. But it is possible to have
+ two tables <literal>employee</literal> in different
+ <firstterm>schemas</firstterm>. In this case, the two tables
+ are separate objects and independent of each
+ other. The only exception to this cross-type uniqueness is that
+ <glossterm linkend="glossary-unique-constraint">unique constraints
+ </glossterm> and the according <firstterm>unique index</firstterm>
+ use the same name.
+ </para>
+
+ <para>
+ Some <firstterm>schemas</firstterm> are predefined.
+ <literal>public</literal> acts as the default
+ <firstterm>schema</firstterm> and contains all such
+ <firstterm>SQL objects</firstterm>, which are created
+ within <literal>public</literal> or without using any schema
+ name. <literal>public</literal> shall not contain user-defined
+ <firstterm>SQL objects</firstterm>. Instead, it is recommended to
+ create a separate <firstterm>schema</firstterm> that
+ holds individual objects like application-specific tables or
+ views. <literal>pg_catalog</literal> is a schema for all tables
+ and views of the <glossterm linkend="glossary-system-catalog">
+ System Catalog</glossterm>.
+ <literal>information_schema</literal> is a schema for several
+ tables and views of the <firstterm>System Catalog</firstterm>
+ in a way that conforms to the SQL standard.
+ </para>
+
+ <para>
+ There are a lot of different <firstterm>SQL object</firstterm>
+ types: <firstterm>database, schema, table, view, materialized
+ view, index, constraint, sequence, function, procedure,
+ trigger, role, data type, operator, tablespace, extension,
+ foreign data wrapper</firstterm>, and more. A few of them, the
+ <firstterm>Global SQL Objects</firstterm>,
+ are outside of the strict hierarchy:
+ All database names, all tablespace names, and all role names
+ are automatically known and available throughout the
+ <firstterm>cluster</firstterm>, independent from
+ the database or schema in which they where defined originally.
+ <xref linkend="tutorial-internal-objects-hierarchy-figure"/>
+ shows the relation between the object types.
+ </para>
+
+ <figure id="tutorial-internal-objects-hierarchy-figure">
+ <title>Hierarchy of Internal Objects</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="720px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect1>
+
+ <sect1 id="tutorial-directories">
+ <title>The physical Perspective: Directories and Files</title>
+
+ <para>
+ <productname>PostgreSQL</productname> organizes long-lasting
+ data as well as volatile state information about transactions
+ or replication actions in the file system. Every
+ <firstterm>Cluster</firstterm> has its root directory
+ somewhere in the file system. In many cases, the environment
+ variable <literal>PGDATA</literal> points to this directory.
+ The example of the survey shown in
+ <xref linkend="tutorial-directories-figure"/> uses
+ <literal>data</literal> as the name of this root directory.
+ </para>
+
+ <figure id="tutorial-directories-figure">
+ <title>Directory Structure</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ <literal>data</literal> contains many subdirectories and
+ some files, all of which are necessary to store long-lasting
+ as well as temporary data. The following paragraphs
+ describe the files and subdirectories in
+ <literal>data</literal>.
+ </para>
+
+ <para>
+ <literal>base</literal> is a subdirectory in which one
+ subdirectory per <firstterm>database</firstterm> exists.
+ The names of those subdirectories consist of numbers.
+ These are the internal
+ <firstterm>Object Identifiers (OID)</firstterm>, which are
+ numbers to identify the database definition in the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ </para>
+
+ <para>
+ Within the <firstterm>database</firstterm>-specific
+ subdirectories, there are many files: one or more for
+ every table and every index to store <firstterm>heap</firstterm>
+ and <firstterm>index</firstterm> data. Those files are
+ accompanied by files for the
+ <link linkend="storage-fsm">Free Space Maps</link>
+ (extension <literal>_fsm</literal>) and
+ <link linkend="storage-vm">Visibility Maps</link>
+ (extension <literal>_vm</literal>), which contain optimization information.
+ </para>
+
+ <para>
+ Another prominent subdirectory is <literal>global</literal>.
+ In analogy to the <firstterm>database</firstterm>-specific
+ subdirectories, there are files containing information about
+ <glossterm linkend="glossary-sql-object">Global SQL objects</glossterm>.
+ One type of such <firstterm>Global Objects</firstterm> are
+ <firstterm>tablespaces</firstterm>. In
+ <literal>global</literal> there is information about
+ the <firstterm>tablespaces</firstterm>, not the
+ <firstterm>tablespaces</firstterm> themselves.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_wal</literal> contains the
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
+ They arise and grow parallel to data changes in the
+ <firstterm>cluster</firstterm> and remain alive as long as
+ they are required for recovery, archiving, or replication.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_xact</literal> contains
+ information about the status of each transaction
+ (IN_PROGRESS, COMMITTED, ABORTED, or SUB_COMMITTED).
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal>, there are symbolic links
+ that point to directories containing such<firstterm>
+ SQL objects</firstterm> that are created within
+ <firstterm>tablespaces</firstterm>.
+ </para>
+
+ <para>
+ In the root directory <literal>data</literal>
+ there are also some files. In many cases, the configuration
+ files of this <firstterm>cluster</firstterm> are stored
+ here. As long as the <firstterm>instance</firstterm>
+ is up and running, the file
+ <literal>postmaster.pid</literal> exists here
+ and contains the ID (pid) of the
+ <firstterm>Postmaster</firstterm> process which
+ has started the instance.
+ </para>
+
+ <para>
+ For more details about the physical implementation
+ of database objects, see <xref linkend="storage"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-mvcc">
+ <title>MVCC — Multiversion Concurrency Control</title>
+
+ <para>
+ In most cases, <productname>PostgreSQL</productname> based applications
+ support many clients at the same time. Therefore, it is necessary to
+ protect concurrently running requests from unwanted overwriting
+ of other's data as well as from reading inconsistent data. Imagine an
+ online shop offering the last copy of an article. Two clients show the
+ article at their user interface. After a while, but at the same time,
+ both users decide to put it to their shopping cart or even to buy it.
+ Both have seen the article, but only one can be allowed to get it.
+ The database must bring the two requests in a row, permit the access
+ to one of them, block the other, and inform this one about the
+ situation that the data was changed by a different process.
+ </para>
+
+ <para>
+ A first approach to implement protections against concurrent
+ accesses to the same data may be the locking of critical
+ rows. There are two main categories of such techniques:
+ <emphasis>Optimistic Concurrency Control</emphasis> (OCC)
+ and <emphasis>Two Phase Locking</emphasis> (2PL).
+ <productname>PostgreSQL</productname> implements the more
+ sophisticated technique <firstterm>Multiversion Concurrency
+ Control</firstterm> (MVCC). The crucial advantage of MVCC
+ over other technologies gets evident in multiuser OLTP
+ environments with a massive number of concurrent write
+ actions. There, MVCC generally performs better than solutions
+ using locks. In a <productname>PostgreSQL</productname>
+ database reading never blocks writing and writing never
+ blocks reading, even in the strictest level of transaction
+ isolation.
+ </para>
+
+ <para>
+ Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
+ a new version of the same row when any data-change takes place. To
+ distinguish between these versions as well as to track the timeline
+ of the row, each of the versions contains, in addition to their user-defined
+ columns, two special system columns, which are not visible
+ for the usual <command>SELECT * FROM ...</command> command.
+ The column <literal>xmin</literal> contains the transaction ID (xid)
+ of the transaction, which creates this version of the row. Accordingly,
+ <literal>xmax</literal> contains the xid of the transaction, which has
+ deleted this version, respectively a zero, if the version is not
+ deleted. You can read both with the command
+ <command>SELECT xmin, xmax, * FROM ... </command>.
+ </para>
+
+ <para>
+ When we speak about transaction IDs, you need to know that xids are like
+ sequences. Every new transaction receives the next number as its ID.
+ Therefore, this flow of xids represents the flow of transaction
+ start events over time. But keep in mind that xids are independent of
+ any time measurement — in milliseconds or whatever. If you dive
+ deeper into <productname>PostgreSQL</productname>, you will recognize
+ parameters with names such as 'xxx_age'. Despite their names,
+ these '_age' parameters do not specify a period of time but represent
+ a certain number of transactions, e.g., 100 million.
+ </para>
+
+ <para>
+ Please note that the description in this chapter simplifies the situation
+ by omitting details. When many transactions are running simultaneously,
+ things can get very complicated. Sometimes they get aborted via
+ ROLLBACK immediately or after a lot of other activities, sometimes
+ a single row is involved in more than one transaction, sometimes
+ a client crashes, sometimes the sequence of xids restarts
+ from zero, ... . Therefore, every version of a row contains more
+ system columns and flags, not only <literal>xmin</literal>
+ and <literal>xmax</literal>.
+ </para>
+
+ <para>
+ So, what's going on in detail when write accesses take place?
+ <xref linkend="tutorial-mvcc-figure"/> shows details concerning
+ <literal>xmin</literal>, <literal>xmax</literal>, and user data.
+ </para>
+
+ <figure id="tutorial-mvcc-figure">
+ <title>Multiversion Concurrency Control</title>
+ <mediaobject>
+ <imageobject role="html">
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ An <command>INSERT</command> command creates the first
+ version of a row. Besides its user data <literal>'x'</literal>,
+ this version contains the ID of the creating transaction
+ <literal>123</literal> in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ <literal>xmin</literal> indicates that the version
+ exists since transaction <literal>123</literal> and
+ <literal>xmax</literal> that it is currently not deleted.
+ </para>
+
+ <para>
+ Somewhat later, transaction <literal>135</literal>
+ executes an <command>UPDATE</command> of this row by
+ changing the user data from <literal>'x'</literal> to
+ <literal>'y'</literal>. According to the MVCC principles,
+ the data in the old version of the row does not change!
+ The value <literal>'x'</literal> keeps as it was before.
+ Only <literal>xmax</literal> changes to <literal>135</literal>.
+ Now, this version is treated as valid exclusively for
+ transactions with xids from <literal>123</literal> to
+ <literal>134</literal>. As a substitute for the non-occurring
+ data change in the old version, the <command>UPDATE</command>
+ creates a new version of the row with its xid in
+ <literal>xmin</literal>, <literal>0</literal> in
+ <literal>xmax</literal>, and <literal>'y'</literal> in the
+ user data (plus all the other user data from the old version).
+ This version is now valid for all coming transactions.
+ </para>
+
+ <para>
+ All subsequent <command>UPDATE</command> commands behave
+ in the same way as the first one: they put their xid to
+ <literal>xmax</literal> of the current version, create
+ the next version with their xid in <literal>xmin</literal>,
+ <literal>0</literal> in <literal>xmax</literal>, and the
+ new user data.
+ </para>
+
+ <para>
+ Finally, a row may be deleted by a <command>DELETE</command>
+ command. Even in this case, all versions of the row keep as
+ before. Nothing is thrown away so far! Only <literal>xmax</literal>
+ of the last version changes to the xid of the <command>DELETE</command>
+ transaction, which indicates that it is only valid for
+ transactions with xids older than its own (from
+ <literal>142</literal> to <literal>820</literal> in this
+ example).
+ </para>
+
+ <para>
+ In summary, the MVCC technology creates more and more versions
+ of the same row in the table's heap file and leaves them there,
+ even with a <command>DELETE</command> command. The youngest
+ version is relevant for all future transactions. But the
+ system must also preserve some of the older ones for a
+ certain amount of time because the possiblility exists that
+ they are or could become relevant for any of the pending
+ transactions. Over time, also the older ones get out of scope
+ for ALL transactions and therefore become unnecessary.
+ Nevertheless, they exist physically on the disk and occupy
+ space.
+ </para>
+
+ <para>
+ Please keep in mind:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> and <literal>xmax</literal> indicate the range from where to where
+ row versions are valid (visible) for transactions.
+ This range doesn't imply any direct temporal meaning;
+ the sequence of xids reflects only the sequence of
+ transaction begin events. As
+ xids grow, old row versions get out of scope over time.
+ If an old row version is no longer valid for ALL existing
+ transactions, it's called <firstterm>dead</firstterm>. The
+ space occupied by the sum of all dead row versions is
+ called <firstterm>bloat</firstterm>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Internally, an <command>UPDATE</command> command acts in the
+ same way as a <command>DELETE</command> command, followed by
+ an <command>INSERT</command> command.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Nothing gets wiped away — with the consequence that the database
+ occupies more and more disk space. It is obvious that
+ this behavior has to be automatically corrected in some
+ way. The next chapter explains how AUTOVACUUM fulfills
+ this task.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ </sect1>
+
+ <sect1 id="tutorial-vacuum">
+ <title>Vacuum</title>
+
+ <para>
+ As we have seen in the previous chapter, the database tends to occupy
+ more and more disk space, the <firstterm>bloat</firstterm>.
+ This chapter explains how the SQL command
+ <firstterm>VACUUM</firstterm> and the automatically running
+ <firstterm>AUTOVACUUM</firstterm> processes clear the situation
+ by eliminating <firstterm>bloat</firstterm>.
+ </para>
+
+ <note>
+ <para>
+ <firstterm>AUTOVACUUM</firstterm> runs automatically by
+ default. Its default parameters as well as such for
+ <firstterm>VACUUM</firstterm> fits well for most standard
+ situations. Therefore a novice database manager can
+ easily skip the rest of this chapter, which explains
+ a lot of details.
+ </para>
+ </note>
+
+ <para>
+ Client processes can issue the SQL command VACUUM at arbitrary
+ points in time. DBAs do this when they recognize special situations,
+ or they start it in batch jobs, which run periodically.
+ AUTOVACUUM processes run as part of the
+ <link linkend="glossary-instance">Instance</link> at the server.
+ There is a constantly running AUTOVACUUM daemon. He permanently
+ controls the state of all databases based on values that are
+ collected by the <link linkend="glossary-stats-collector">
+ Statistics Collector</link> and starts
+ AUTOVACUUM processes whenever he detects certain situations.
+ Thus, it's a dynamic behavior of <productname>PostgreSQL</productname>
+ with the intention to tidy up — not always, but whenever it
+ is appropriate.
+ </para>
+
+ <para>
+ VACUUM, as well as AUTOVACUUM, don't just eliminate bloat.
+ They perform additional tasks for minimizing future
+ I/O activities of themselves as well as of other processes.
+ This extra work can be done in a very efficient way
+ since in most cases the expensive physical access to pages
+ has taken place anyway to eliminate bloat.
+ The additional operations are:
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <firstterm>Freeze</firstterm>: Mark the youngest row version
+ as frozen. This means that the version
+ is always treated as valid (visible) independent from
+ the <firstterm>wraparound problematic</firstterm> (see below).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <firstterm>Visibility Map</firstterm> and
+ <firstterm>Free Space Map</firstterm>: Log information about
+ the state of the handled pages in two additional files, the
+ Visibility Map and the Free Space Map.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <emphasis>Statistics</emphasis>: Collect statistics about the
+ number of rows per table, the distribution of values, and so on,
+ as the basis for query planner's decision making.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ The eagerness — you can call it 'aggressivity' — of the
+ operations <emphasis>eliminating bloat</emphasis> and
+ <emphasis>freeze</emphasis> is controlled by configuration
+ parameters, runtime flags, and in extreme situations by
+ themselves. Because vacuum operations typically are I/O
+ intensive, which can hinder other activities, AUTOVACUUM
+ avoids performing many vacuum operations in bulk. Instead,
+ it carries out many small actions with time gaps in between.
+ The SQL command VACUUM runs immediately without any
+ time gaps.
+ </para>
+
+ <bridgehead renderas="sect2">Eliminate Bloat</bridgehead>
+
+ <para>
+ To determine which of the row versions are superfluous, the
+ elimination operation must evaluate xmax against several criteria
+ which all must apply:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ xmax must be different from zero because a value of zero
+ indicates that the row version is still valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ xmax must contain an xid which is older than the oldest xid of all
+ currently running transactions (min(pg_stat_activity.backend_xmin)).
+ This criterion guarantees that no existing or upcoming transaction
+ will have read or write access to this row version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of xmax must be committed. If it was rollback-ed,
+ this row version is treated as valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there is the situation that the row version is part of
+ multiple transactions, special care and some more actions
+ must be taken, see: <xref linkend="vacuum-for-multixact-wraparound"/>.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ After the vacuum operation detects a superfluous row version, it
+ marks its space as free for future use of writing
+ actions. Only in rare situations (or in the case of VACUUM FULL),
+ this space is released to the operating system. In most cases,
+ it keeps occupied by PostgreSQL and will be used by future
+ <command>INSERT</command> or <command>UPDATE</command>
+ commands concerning this row or a completely different one.
+ </para>
+
+ <para>
+ Which actions start the elimination of bloat?
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM in its default format,
+ i.e., without any option. To boost performance, in this and the
+ next case VACUUM does not read and act on all pages of the heap.
+ The Visibility Map, which is very compact and therefore has a small
+ size, contains information about pages, where bloat-candidates might
+ be found. Only such pages are processed.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM with the option
+ FREEZE. (In this case, it undertakes much more actions, see
+ <link linkend="tutorial-freeze">Freeze Row Versions</link>.)
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM with the option FULL.
+ Also, in this mode, the bloat disappears, but the used strategy
+ is very different: In this case, the complete table is copied
+ to a different file skipping all outdated row versions. This
+ leads to a significant reduction of used disk space because
+ the new file contains only the actual data. The old file
+ is deleted.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When an AUTOVACUUM process acts. For optimization
+ purposes, he considers the Visibility Map in the same way as
+ VACUUM. Additionally, he ignores tables with few modifications;
+ see <xref linkend="guc-autovacuum-vacuum-threshold"/>,
+ which defaults to 50 rows and
+ <xref linkend="guc-autovacuum-vacuum-scale-factor"/>,
+ which defaults to 20%.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </para>
+
+ <para>
+ This logic only applies to row versions of the heap. Index entries
+ don't use xmin/xmax. Nevertheless, such index entries, which would
+ lead to outdated row versions, are released accordingly.
+ (??? more explanations ???)
+ </para>
+
+ <para>
+ The above descriptions omit the fact that xids on a real computer
+ have a limited size. They count up in the same way as sequences, and after
+ a certain number of new transactions they are forced to restart
+ from the beginning, which is called <firstterm>wraparound</firstterm>.
+ Therefore the terms 'old transaction' / 'young transaction' does
+ not always correlate with low / hight values of xids. Near to the
+ wraparound point, there are cases where xmin has a higher value
+ than xmax, although their meaning is said to be older than xmax.
+ </para>
+
+ <figure id="tutorial-wraparound-figure">
+ <title>Cyclic usage of XIDs</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2" id="tutorial-freeze">Freeze Row Versions</bridgehead>
+
+ <para>
+ The use of a limited range of IDs for transactions leads
+ to the necessity to restart the sequence sooner or later.
+ This does not only have the rare consequence previously
+ described that sometimes xmin is huger than xmax. The far
+ more critical problem is that whenever the system has
+ to evaluate a WHERE condition, it must decide which row
+ versions are valid (visible) from the perspective of the
+ transaction of this query. If a wraparound couldn't happen,
+ this decision would be relatively easy: the xid
+ must be between xmin and xmax, and the corresponding
+ transactions of xmin and xmax must be committed. However,
+ PostgreSQL has to consider the possibility of wraparounds.
+ Therefore the decision becomes more complex. The general
+ idea of the solution is to use the 'between xmin and xmax'
+ comparison only during the youngest period of the row
+ versions lifetime and afterward replace it with a
+ 'valid forever' flag in its header.
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ In a first step, PostgreSQL divides the complete range of
+ possible xids into two halves with the two split-points
+ 'txid_current' and 'txid_current + 2^31'. The half behind
+ 'txid_current' is considered to represent xids of the
+ 'past' and the half ahead of 'txid_current' those of the
+ 'future'. Those of the 'past' are valid (visible) and those
+ of the 'future' not.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ With each newly created transaction the two split-points
+ move forward. When 'txid_current + 2^31' would reach a
+ row version with xmin equal to that value, it would
+ immediately jump from 'past' to 'future' and would be
+ no longer visible!
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ To avoid this unacceptable extinction of data, the vacuum
+ operation <firstterm>freeze</firstterm> clears the situation
+ long before the split-point is reached. It sets a flag
+ in the header of the row version, which completely eliminates
+ the future use of xmin/xmax and indicates
+ that the version is valid not only in the 'past'-half
+ but also in the 'future'-half as well as in all coming
+ <glossterm linkend="glossary-xid">epochs</glossterm>.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Which row versions can be frozen by the vacuum operation?
+ Again, several criteria must be checked, and all must be met.
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ xmax must be zero because only non-deleted rows can be
+ visible 'forever'.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ xmin must be older than all currently existing transactions.
+ This guarantees that no existing transaction can modify or
+ delete the version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of xmin must be committed.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ At what point in time the freeze operation will take place?
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM with its
+ FREEZE option. In this case, all such pages are
+ processed that are marked in the Visibility Map
+ to potentially have unfrozen rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM without any
+ option but finds that there are xids older than
+ <xref linkend="guc-vacuum-freeze-table-age"/>
+ (default: 150 million) minus
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million).
+ As before, all such pages are processed that are
+ marked in the Visibility Map to potentially have unfrozen
+ rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When an AUTOVACUUM process runs. Such a process acts
+ in one of two modes:
+ </simpara>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ In the <emphasis>normal mode</emphasis>, he skips
+ pages with row versions that are younger than
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million) and works only on pages where
+ all xids are older. The skipping of jung xids prevents
+ work on such pages, which are likely to be changed
+ by one of the future SQL commands.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ The process switches
+ to an <emphasis>aggressive mode</emphasis> if he recognizes
+ that for the processed table their oldest xid exceeds
+ <xref linkend="guc-autovacuum-freeze-max-age"/>
+ (default: 200 million). The value of the oldest unfrozen
+ xid is stored per table in <emphasis>pg_class.relfrozenxid</emphasis>.
+ In this <emphasis>aggressive mode</emphasis> AUTOVACUUM
+ processes all such pages of the selected table that are marked
+ in the Visibility Map to potentially have bloat or unfrozen rows.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In the first two cases and with autovacuum in
+ <emphasis>aggressive mode</emphasis>, the system knowns
+ to which value the oldest unfrozen xid has moved forward and
+ logs the value in <emphasis>pg_class.relfrozenxid</emphasis>.
+ The distance between this value and the 'txid_current' split
+ point becomes smaller, and the distance to 'txid_current + 2^31'
+ larger than before.
+ </para>
+
+ <figure id="tutorial-freeze-figure">
+ <title>Freeze</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2">Protection against Wraparound Failure</bridgehead>
+
+ <para>
+ The AUTOVACUUM processes are initiated by the constantly
+ running <firstterm>autovacuum daemon</firstterm>. If the
+ daemon detects that for a table <firstterm>
+ autovacuum_freeze_max_age</firstterm> is exceeded, it starts
+ an AUTOVACUUM process in the <emphasis>aggressive mode</emphasis>
+ (see above) — even if AUTOVACUUM is disabled.
+ </para>
+
+ <bridgehead renderas="sect2">Visibility Map and Free Space Map</bridgehead>
+
+ <para>
+ The <link linkend="glossary-vm">Visibility Map</link>
+ (VM) contains two flags — stored as
+ two bits — for each page of the heap. If the first bit
+ is set, it indicates that the associated page does not
+ contain any bloat. If the second one is set, it indicates
+ that the page contains only frozen rows.
+ </para>
+
+ <para>
+ Please consider two details. First, in most cases a page
+ contains many rows, some of them in many versions.
+ However, the flags are associated with the page,
+ not with a row or a row version! The flags are set
+ only under the condition that they are valid for ALL
+ row versions of the page. Second, since there
+ are only two bits per page, the VM is considerably
+ smaller than the heap. Therefore it is buffered
+ in RAM in almost all cases.
+ </para>
+
+ <para>
+ The setting of the flags is silently done by VACUUM
+ and AUTOVACUUM during their bloat and freeze operations.
+ This is done to accelerate future vacuum actions,
+ regular accesses to heap pages, and some accesses to
+ the index. Every data-modifying operation on any row
+ version of the page clears the flags.
+ </para>
+
+ <para>
+ The <link linkend="glossary-fsm">Free Space Map</link>
+ (FSM) tracks the amount of free space per page. It is
+ organized as a highly condensed b-tree of (rounded) sizes.
+ As long as VACUUM or AUTOVACUUM change the free space
+ on any processed page, they log the new values in
+ the FSM in the same way as all other writing
+ processes.
+ </para>
+
+ <bridgehead renderas="sect2">Statistics</bridgehead>
+
+ <para>
+ Statistic information helps the <link
+ linkend="planner-stats">Query Planner</link> to make optimal
+ decisions for the generation of execution plans. This
+ information can be gathered with the SQL commands ANALYZE
+ or VACUUM ANALYZE. But also autovacuum processes gather
+ such information. Depending on the percentage of changed rows
+ per table <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ the autovacuum daemon starts autovacuum processes to collect
+ statistics per table. This dynamic invocation of analyze
+ operations allows <productname>PostgreSQL</productname> to
+ adopt queries to changing circumstances.
+ </para>
+
+ <para>
+ For more details about vacuum operations, especially for its
+ numerous parameters, see <xref linkend="routine-vacuuming"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-transactions-mvcc">
+ <title>Transactions</title>
+ <para>
+ <link linkend="tutorial-transactions">Transactions</link>
+ are a fundamental concept of relational database systems.
+ Their essential point is that they bundle multiple
+ read- or write-operations into a single, all-or-nothing
+ operation. Furthermore, they separate and protect concurrent
+ actions of different connections from each other. Thereby
+ they implement the ACID paradigm.
+ </para>
+
+ <para>
+ In <productname>PostgreSQL</productname> there are two ways
+ to establish a transaction. The explicite way uses the keywords
+ <link linkend="sql-begin">BEGIN</link> and
+ <link linkend="sql-commit">COMMIT</link> (respectively
+ <link linkend="sql-rollback">ROLLBACK</link>) before
+ and after a sequence of SQL statements. The keywords mark
+ the transaction's start- and end-point. On the other hand, you
+ can omit the keywords. This is the implicit way, where
+ every single SQL command automatically establishes a new
+ transaction.
+
+ <programlisting>
+BEGIN; -- establish a new transaction
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+COMMIT; -- finish the transaction
+
+-- this UPDATE runs as the only command of a separate transaction ...
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+
+-- ... and this one runs in another transaction
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+ </programlisting>
+ </para>
+
+ <para>
+ As mentioned, the primary property of a transaction is its
+ atomicity: either all or none of its operations succeed,
+ regardless of the fact that it may consist of a lot of
+ different write-operations, and each such operation may
+ affect thousands or millions of rows. As soon as one of the
+ operations fails, all previous operations fail also, which
+ means that all modified rows retain their values as of the
+ beginning of the transaction.
+ </para>
+
+ <para>
+ The atomicity also affects the visibility of changes. All
+ connections running simultaneously to a data modifying
+ transaction will never see any change before the
+ transaction successfully executes a <command>COMMIT</command>
+ — even in the lowest
+ <link linkend="transaction-iso">isolation level</link>
+ of transactions. <productname>PostgreSQL</productname>
+ does never show uncommitted changes to other connections.
+ </para>
+
+ <para>
+ The situation regarding visibility is somewhat different
+ from the point of view of the modifying transaction.
+ <command>SELECT</command> commands issued inside the
+ transaction delivers all changes done so far by this
+ transaction.
+ </para>
+
+ <bridgehead renderas="sect2">How does it work?</bridgehead>
+
+ <para>
+ Every <command>INSERT</command>, <command>UPDATE</command>,
+ and <command>DELETE</command> command creates new row
+ versions — according to the MVCC rules. This
+ creates the risk that other transactions may see the
+ new row versions, and after a while and some more
+ activities of the modifying transaction they may see the
+ next row versions. Results would be a kind of 'moving
+ target' in absolute contrast to the all-or-nothing
+ principle.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> overcomes the
+ problem by showing only such row versions to other
+ transactions whose originating transaction is
+ successfully committed. It skips all row versions of
+ uncommitted transactions. And
+ <productname>PostgreSQL</productname> solves one more
+ problem. Even the single <command>COMMIT</command>
+ command needs a short time interval for its execution.
+ Therefor its critical 'dead-or-survival' phase
+ runs in a priviledged mode where it cannot be
+ interupted by other processes.
+ </para>
+
+ <bridgehead renderas="sect2">What are the benefits?</bridgehead>
+
+ <para>
+ Transactions relieve applications from many standard
+ actions that must be implemented for nearly every use case.
+ </para>
+
+ <para>
+ Business logic often contains strong, but for a computer,
+ relative abstract requirements. The above example shows
+ the transfers of some money from one account to another.
+ It is obvious
+ that the decrease of the one and the increase of the
+ other are impartible. Nevertheless, there is no particular
+ need for an application to do something to ensure the
+ <glossterm linkend="glossary-atomicity">atomicity</glossterm>
+ of its behavior. It's enough to surround them with
+ <command>BEGIN</command> and <command>COMMIT</command>.
+ </para>
+
+ <para>
+ Applications often demand the feature of 'undoing'
+ previously taken actions under some application-specific
+ conditions. In such cases, the application simply issues a
+ <command>ROLLBACK</command> command instead of a
+ <command>COMMIT</command>. The <command>ROLLBACK</command>
+ cancels the transaction, and all changes made so far retain
+ invisible forever; it's like they never happened. There
+ is no need for the application to log its activities and
+ undo every single step.
+ </para>
+
+ <para>
+ Transactions ensure that the
+ <glossterm linkend="glossary-consistency">consistency</glossterm>
+ of the complete database always keeps valid. Declarative
+ rules like
+ <link linkend="ddl-constraints-primary-keys">primary</link>- or
+ <link linkend="ddl-constraints-fk">foreign keys</link>,
+ <link linkend="ddl-constraints-check-constraints">checks</link>,
+ other constraints, or
+ <link linkend="trigger-definition">triggers</link>
+ are part of the all-or-nothing nature of transactions.
+ </para>
+
+ <para>
+ Also, all self-evident — but possibly not obvious
+ — low-level demands on the database system are
+ ensured; e.g., index entries for rows must become
+ visible at the same moment as the rows themselves.
+ </para>
+
+ <para>
+ There is an additional feature which defines transactions'
+ <link linkend="transaction-iso">isolation level</link>
+ to each other in a declarative way. It automatically
+ prevents applications from some strange situations.
+ </para>
+
+ <para>
+ Lastly, it is worth to notice that changes done by a
+ committed transaction will survive all future application,
+ instance, or hardware failures. The next chapter
+ explains this
+ <glossterm linkend="glossary-durability">durability</glossterm>.
+ </para>
+ </sect1>
+
+ <sect1 id="tutorial-reliability">
+ <title>Reliability</title>
+
+ <para>
+ Nothing is perfect and failures inevitably happen.
+ However, the most common types of failures are
+ well known and <productname>PostgreSQL</productname>
+ implements strategies to overcome them.
+ Such strategies use parts of the previously presented
+ techniques MVCC and transaction-rollback, plus additional
+ features.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the client side</bridgehead>
+ <para>
+ A <glossterm linkend="glossary-client">client</glossterm>
+ can fail in different ways. Its hardware can get damaged,
+ the power supply can fail, the network connection to the
+ server can break, or the client application may run into
+ a severe software error like a null pointer exception.
+ Because <productname>PostgreSQL</productname> uses a
+ client/server architecture, no direct problem for the
+ database will occur. In all of this cases, the
+ <glossterm linkend="glossary-backend">backend process</glossterm>,
+ which is the client's counterpart at the server-side,
+ may recognize that the network connection is no longer
+ working, or it may run into a timeout after a while. It
+ terminates, and there is no harm to the database. As
+ usual, uncommitted data changes initiated by this client
+ are not visible to any other client.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the server-side</bridgehead>
+
+ <bridgehead renderas="sect3">Instance failure</bridgehead>
+ <para>
+ The instance may suddenly fail because of <emphasis>power off</emphasis>
+ or other problems. This will affect all running processes, the RAM,
+ and possibly the consistency of disk files.
+ </para>
+ <para>
+ After a restart, <productname>PostgreSQL</productname>
+ automatically recognizes that the last shutdown of the
+ instance did not happen as expected: files might not be
+ closed properly and the <firstterm>postmaster.pid</firstterm>
+ file exists. <productname>PostgreSQL</productname>
+ tries to clean up the situation. This is possible because
+ all changes in the database are stored twice. First,
+ the WAL files contain them as a chronology of
+ <glossterm linkend="glossary-wal-record">WAL records</glossterm>,
+ which include the new data values and information about commit
+ actions. The WAL records are written first. Second,
+ the data itself shall exist in the heap and index files.
+ In opposite to the WAL records, this part may or may
+ not be transferred entirely from shared buffers to the files.
+ </para>
+ <para>
+ The automatic recovery searches within the WAL files for
+ the latest
+ <glossterm linkend="glossary-checkpoint">checkpoint</glossterm>.
+ This checkpoint signals that the database files are in
+ a consistent state, especially that all WAL records up to
+ this point were successfully stored in heap and index. Starting
+ here, the recovery process copies the following WAL records
+ to heap and index. As a result, the files contain all
+ changes and reach a consistent state. Changes of committed
+ transactions are visible; those of uncommited transactions
+ are also in the files, but - as usual - they are never seen
+ by any of the following transactions because uncommited
+ changes are never shown. Such recovery actions run
+ completely automatically, it is not necessary that you
+ configure or start anything by yourself.
+ </para>
+
+ <bridgehead renderas="sect3">Disk crash</bridgehead>
+ <para>
+ If a disk crashes, the course of actions described previously
+ cannot work. It is likely that the WAL files and/or the
+ data and index files are no longer available. You need
+ to take special actions to overcome such situations.
+ </para>
+ <para>
+ You obviously need a backup. How to take such a backup
+ and use it as a starting point for a recovery of the
+ cluster is explained in more detail in the next
+ <link linkend="tutorial-backup">chapter</link>.
+ </para>
+
+ <bridgehead renderas="sect3">Disk full</bridgehead>
+ <para>
+ It is conceivable that over time the disk gets full,
+ and there is no room for additional data. In this case,
+ <productname>PostgreSQL</productname> stops accepting
+ commands which change the data or even terminates
+ completely. No data loss or data corruption will
+ occur.
+ </para>
+ <para>
+ To come out of such a situation, you should remove
+ unused files from this disk. But you should never
+ delete files from the
+ <glossterm linkend="glossary-data-directory">data directory</glossterm>.
+ Nearly all of them are necessary for the consistency
+ of the database.
+ </para>
+
+ <bridgehead renderas="sect2">High availability</bridgehead>
+ <para>
+ Database servers can work together to allow a second
+ server to quickly take over the workload if the
+ primary server fails for whatever reason
+ (<link linkend="high-availability">high availability</link>),
+ or to allow several computers to serve the same data
+ for the purpose of load balancing.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-backup">
+ <title>Backup</title>
+
+ <para>
+ Taking backups is a basic task of database maintenance.
+ <productname>PostgreSQL</productname> supports
+ three different strategies; each has its own
+ strengths and weaknesses.
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ File system level backup
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Logical backup via pg_dump
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Continuous archiving based on pg_basebackup and WAL files
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <bridgehead renderas="sect2">File system level backup</bridgehead>
+ <para>
+ You can use any appropriate OS tool to create a
+ <link linkend="backup-file">copy</link>
+ of the cluster's directory structure and files. In
+ case of severe problems such a copy can serve as
+ the source of a recovery. But in order to get a
+ <emphasis>USABLE</emphasis> backup by this method,
+ the database server <emphasis>MUST</emphasis> be
+ shut down during the complete runtime of the copy
+ command!
+ </para>
+ <para>
+ The apparent disadvantage of this method is that there
+ is a downtime where no user interaction is possible.
+ </para>
+
+ <bridgehead renderas="sect2">Logical backup via pg_dump</bridgehead>
+ <para>
+ The tool <command>pg_dump</command> is able to take a
+ <link linkend="backup-dump">copy</link>
+ of the complete cluster or certain parts of it. It stores
+ the copy in the form of SQL <command>CREATE</command> and
+ <command>INSERT</command> commands. It runs in
+ parallel to other processes in its own transaction.
+ </para>
+ <para>
+ The output of <command>pg_dump</command> may be used as
+ input of <command>psql</command> to restore the data
+ (or to copy it to another database).
+ </para>
+ <para>
+ The main advantage over the other two methods is that it
+ can pick parts of the cluster, e.g. a single table or one
+ database. The other two methods work only at the level of
+ the complete cluster.
+ </para>
+
+ <bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
+ <para>
+ This <link linkend="continuous-archiving">method</link>
+ is the most sophisticated and complex one. It
+ consists of two phases.
+ </para>
+ <para>
+ First, you need to create a so called
+ <firstterm>basebackup</firstterm> with the tool
+ <command>pg_basebackup</command>. The result is a
+ directory structure plus files which contains a
+ consistent copy of the original cluster.
+ <command>pg_basebackup</command> runs in
+ parallel to other processes in its own transaction.
+ </para>
+ <para>
+ The second step is recommended but not necessary. All
+ changes to the data are stored in WAL files. If you
+ continuously save such WAL files, you have the history
+ of the cluster. This history can be applied to a
+ basebackup in order to recreate any state of the
+ cluster between the time of
+ <command>pg_basebackup</command>'s start time and
+ any later point in time. This technique
+ is called 'Point-in-Time Recovery (PITR)'.
+ </para>
+ <para>
+ If configured, the
+ <glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
+ will automatically copy every single WAL file to a save location.
+ <link linkend="backup-archiving-wal">It's configuration</link>
+ consists mainly of a string, which contains a copy command
+ in the operating system's syntax. In order to protect your
+ data against a disk crash, the destination location
+ of a <firstterm>basebackup</firstterm> as well as of the
+ <firstterm>archived WAL files</firstterm> should be on a
+ disk which is different from the data disk.
+ </para>
+ <para>
+ If it gets necessary to restore the cluster, you have to
+ copy the <firstterm>basebackup</firstterm> and the
+ <firstterm>archived WAL files</firstterm> to
+ their original directories. The configuration of this
+ <link linkend="backup-pitr-recovery">recovery procedure</link>
+ contains a string with the reverse copy command: from
+ archive location to database location.
+ </para>
+
+ </sect1>
+
+<!-- ToDo
+ <sect1 id="tutorial-replication">
+ <title>Replication</title>
+
+ <para>
+...
+ </para>
+
+ </sect1>
+-->
+
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 68179f71cd..4bc68f2da0 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -8,9 +8,10 @@
<!ENTITY problems SYSTEM "problems.sgml">
<!-- tutorial -->
-<!ENTITY advanced SYSTEM "advanced.sgml">
-<!ENTITY query SYSTEM "query.sgml">
-<!ENTITY start SYSTEM "start.sgml">
+<!ENTITY start SYSTEM "start.sgml">
+<!ENTITY query SYSTEM "query.sgml">
+<!ENTITY advanced SYSTEM "advanced.sgml">
+<!ENTITY architecture SYSTEM "architecture.sgml">
<!-- user's guide -->
<!ENTITY array SYSTEM "array.sgml">
diff --git a/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
new file mode 100644
index 0000000000..7e13753d48
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
@@ -0,0 +1,160 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="685" viewBox="0 0 900 685">
+ <title>
+ Server (Hardware, Container, or VM)
+ </title>
+ <style>
+ .text_normal,.text_small{font-style:normal;font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_small{font-size:12px}.text_normal{font-size:16px}
+ </style>
+ <defs>
+ <symbol id="rectangle_special_0">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="rectangle_special_1">
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="125">
+ 'my_schema' (optional)
+ </text>
+ <text class="text_small" x="20" y="145">
+ tables, views, ...
+ </text>
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="190">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M450 10v230H0V0h440v10h10L440 0"/>
+ </symbol>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="270" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Server (Hardware, Container, or VM)
+ </text>
+ <path stroke="blue" stroke-width="2" fill="none" d="M20 110h790v555H20z"/>
+ <text class="text_normal" x="180" y="25" transform="translate(20 110)">
+ cluster 'data' (default, managed by one instance)
+ </text>
+ <path d="M50 110V80h790v555h-30" stroke="blue" stroke-width="2" fill="none"/>
+ <text class="text_normal" x="190" y="-10" transform="translate(45 110)">
+ cluster 'cluster_2' (optional, managed by a different instance)
+ </text>
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template0'
+ </text>
+ </g>
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template1'
+ </text>
+ </g>
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'my_db' (optional)
+ </text>
+ </g>
+ <g transform="translate(320 330)">
+ <rect width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4"/>
+ <text class="text_normal" x="15" y="27">
+ Global SQL objects
+ </text>
+ <path d="M0 5l-65-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M80 0v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M180 40h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M0 40l-45 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ </g>
+ <g transform="translate(335 405)">
+ <use xlink:href="#note"/>
+ <text class="text_small" x="10" y="20">
+ 1)
+ </text>
+ <text class="text_small" x="30" y="20">
+ By default, you work in the cluster 'data', database 'postgres',
+ </text>
+ <text class="text_small" x="30" y="35">
+ schema 'public'.
+ </text>
+ <text class="text_small" x="10" y="55">
+ 2)
+ </text>
+ <text class="text_small" x="30" y="55">
+ More system schemas: pg_catalog, information_schema,
+ </text>
+ <text class="text_small" x="30" y="70">
+ pg_temp, pg_toast.
+ </text>
+ <text class="text_small" x="10" y="90">
+ 3)
+ </text>
+ <text class="text_small" x="30" y="90">
+ Global SQL objects: Some SQL objects are automatically active
+ </text>
+ <text class="text_small" x="30" y="105">
+ and known database- or even cluster-wide.
+ </text>
+ <text class="text_small" x="10" y="125">
+ 4)
+ </text>
+ <text class="text_small" x="30" y="125">
+ The command 'initdb' creates a new cluster with the three
+ </text>
+ <text class="text_small" x="30" y="140">
+ databases 'template0', 'template1', and 'postgres'. The command
+ </text>
+ <text class="text_small" x="30" y="155">
+ 'createdb' creates a new database.
+ </text>
+ <text class="text_small" x="10" y="175">
+ 5)
+ </text>
+ <text class="text_small" x="30" y="175">
+ If multiple clusters are active on one server at the same time,
+ </text>
+ <text class="text_small" x="30" y="190">
+ each one is managed by an individual instance. Each such instance
+ </text>
+ <text class="text_small" x="30" y="205">
+ uses a different port.
+ </text>
+ <text class="text_small" x="10" y="225">
+ 6)
+ </text>
+ <text class="text_small" x="30" y="225">
+ No client application is allowed to connect to 'template0'.
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink.svg b/doc/src/sgml/images/cluster-db-schema-ink.svg
new file mode 100644
index 0000000000..1fffb9737a
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink.svg
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="685px"
+ viewBox="0 0 900 685"
+ id="svg147"
+ sodipodi:docname="cluster-db-schema-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Server (Hardware, Container, or VM)</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1129"
+ inkscape:window-height="922"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.68905109"
+ inkscape:cx="737.16805"
+ inkscape:cy="342.1375"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Server (Hardware, Container, or VM)</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs49">
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangle_special_0">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect6" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="195"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect8" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text10">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text12">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="195"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect14" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text16">(more system schemas)</text>
+ </symbol>
+ <!-- same as before, but one more schema -->
+ <symbol
+ id="rectangle_special_1">
+ <!-- the database -->
+ <rect
+ width="245"
+ height="225"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect19" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect21" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text23">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text25">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect27" />
+ <text
+ class="text_normal"
+ x="20"
+ y="125"
+ id="text29">'my_schema' (optional)</text>
+ <text
+ class="text_small"
+ x="20"
+ y="145"
+ id="text31">tables, views, ...</text>
+ <rect
+ x="15"
+ y="170"
+ width="205"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect33" />
+ <text
+ class="text_small"
+ x="20"
+ y="190"
+ id="text35">(more system schemas)</text>
+ </symbol>
+ <symbol
+ id="note"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title38">UML Note</title>
+ <path
+ d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10"
+ id="path40" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path43" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path46" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect51" />
+ <text
+ class="text_big"
+ x="270"
+ y="40"
+ id="text53">Server (Hardware, Container, or VM)</text>
+ <!-- two clusters -->
+ <g
+ transform="translate(20 110)"
+ id="g59">
+ <rect
+ x="0"
+ y="0"
+ width="790"
+ height="555"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="rect55" />
+ <text
+ class="text_normal"
+ x="180"
+ y="25"
+ id="text57">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g
+ transform="translate(45 110)"
+ id="g65">
+ <path
+ d="M 5,0 v -30 h 790 v 555 h -30"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="path61" />
+ <text
+ class="text_normal"
+ x="190"
+ y="-10"
+ id="text63">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+ <!-- database template 0 -->
+ <g
+ transform="translate(40 155)"
+ id="g71">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use67" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text69">database 'template0'</text>
+ </g>
+ <!-- database template 1 -->
+ <g
+ transform="translate(290 155)"
+ id="g77">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use73" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text75">database 'template1'</text>
+ </g>
+ <!-- database postgres -->
+ <g
+ transform="translate(540 155)"
+ id="g83">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use79" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text81">database 'postgres'</text>
+ </g>
+ <!-- database my_db -->
+ <g
+ transform="translate(40 350)"
+ id="g89">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use85" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text87">database 'my_db' (optional)</text>
+ </g>
+ <!-- global objects -->
+ <g
+ transform="translate(320 330)"
+ id="g103">
+ <rect
+ x="0"
+ y="0"
+ width="180"
+ height="45"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="10 4 4 4"
+ id="rect91" />
+ <text
+ class="text_normal"
+ x="15"
+ y="27"
+ id="text93">Global SQL objects</text>
+ <path
+ d="M 0,5 l-65,-35"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path95" />
+ <path
+ d="M 80,0 v-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path97" />
+ <path
+ d="M 180,40 h50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path99" />
+ <path
+ d="M 0,40 l-45,20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path101" />
+ </g>
+ <!-- Some comments -->
+ <g
+ transform="translate(335 405)"
+ id="g145">
+ <use
+ xlink:href="#note"
+ x="0"
+ y="0"
+ id="use105" />
+ <text
+ class="text_small"
+ x="10"
+ y="20"
+ id="text107">1)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="20"
+ id="text109">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text
+ class="text_small"
+ x="30"
+ y="35"
+ id="text111">schema 'public'.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="55"
+ id="text113">2)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="55"
+ id="text115">More system schemas: pg_catalog, information_schema,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="70"
+ id="text117">pg_temp, pg_toast.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="90"
+ id="text119">3)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="90"
+ id="text121">Global SQL objects: Some SQL objects are automatically active</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text123">and known database- or even cluster-wide.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="125"
+ id="text125">4)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="125"
+ id="text127">The command 'initdb' creates a new cluster with the three</text>
+ <text
+ class="text_small"
+ x="30"
+ y="140"
+ id="text129">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text
+ class="text_small"
+ x="30"
+ y="155"
+ id="text131">'createdb' creates a new database.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="175"
+ id="text133">5)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="175"
+ id="text135">If multiple clusters are active on one server at the same time,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="190"
+ id="text137">each one is managed by an individual instance. Each such instance</text>
+ <text
+ class="text_small"
+ x="30"
+ y="205"
+ id="text139">uses a different port.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="225"
+ id="text141">6)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="225"
+ id="text143">No client application is allowed to connect to 'template0'.</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
new file mode 100644
index 0000000000..af50c07330
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="685px"
+ viewBox="0 0 900 685" >
+
+ <title>Server (Hardware, Container, or VM)</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_0">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">(more system schemas)</text>
+ </symbol>
+
+ <!-- same as before, but one more schema -->
+ <symbol id="rectangle_special_1">
+ <!-- the database -->
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="125">'my_schema' (optional)</text>
+ <text class="text_small" x="20" y="145">tables, views, ...</text>
+
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="190">(more system schemas)</text>
+ </symbol>
+
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="270" y="40">Server (Hardware, Container, or VM)</text>
+
+ <!-- two clusters -->
+ <g transform="translate(20 110)">
+ <rect x="0" y="0" width="790" height="555" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="180" y="25">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g transform="translate(45 110)">
+ <path d="M 5,0 v -30 h 790 v 555 h -30" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="190" y="-10">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+
+
+ <!-- database template 0 -->
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template0'</text>
+ </g>
+
+ <!-- database template 1 -->
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template1'</text>
+ </g>
+
+ <!-- database postgres -->
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'postgres'</text>
+ </g>
+
+ <!-- database my_db -->
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
+ </g>
+
+ <!-- global objects -->
+ <g transform="translate(320 330)">
+ <rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
+ <text class="text_normal" x="15" y="27">Global SQL objects</text>
+ <path d="M 0,5 l-65,-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ </g>
+
+ <!-- Some comments -->
+ <g transform="translate(335 405)">
+ <use xlink:href="#note" x="0" y="0" />
+
+ <text class="text_small" x="10" y="20">1)</text>
+ <text class="text_small" x="30" y="20">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text class="text_small" x="30" y="35">schema 'public'.</text>
+
+ <text class="text_small" x="10" y="55">2)</text>
+ <text class="text_small" x="30" y="55">More system schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="70">pg_temp, pg_toast.</text>
+
+ <text class="text_small" x="10" y="90">3)</text>
+ <text class="text_small" x="30" y="90">Global SQL objects: Some SQL objects are automatically active</text>
+ <text class="text_small" x="30" y="105">and known database- or even cluster-wide.</text>
+
+ <text class="text_small" x="10" y="125">4)</text>
+ <text class="text_small" x="30" y="125">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="140">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="155">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="175">5)</text>
+ <text class="text_small" x="30" y="175">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="190">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="205">uses a different port.</text>
+
+ <text class="text_small" x="10" y="225">6)</text>
+ <text class="text_small" x="30" y="225">No client application is allowed to connect to 'template0'.</text>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/directories-ink-svgo.svg b/doc/src/sgml/images/directories-ink-svgo.svg
new file mode 100644
index 0000000000..95fa76b9c6
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink-svgo.svg
@@ -0,0 +1,164 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="640" viewBox="0 0 900 640">
+ <title>
+ Directory structure of a cluster
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <symbol id="directory" stroke="blue" stroke-width=".3" fill="aqua">
+ <title>
+ Directory
+ </title>
+ <path d="M0 10h110v20H0z"/>
+ <path d="M0 10V8l3-3h35l3 3v2"/>
+ </symbol>
+ <symbol id="file" stroke="black" fill="none">
+ <title>
+ File
+ </title>
+ <path stroke="blue" d="M0 0h40v50H0z"/>
+ <path d="M5 10h20" stroke-dasharray="4 2"/>
+ <path d="M5 17h15" stroke-dasharray="6 2"/>
+ <path d="M5 24h25" stroke-dasharray="4 2"/>
+ <path d="M5 31h20" stroke-dasharray="5 2"/>
+ </symbol>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="50" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Directory Structure
+ </text>
+ <g transform="translate(20 100)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /pg/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ An arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 130)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ data/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of cluster 'data' (see: PGDATA)
+ </text>
+ </g>
+ <g transform="translate(120 160)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ base/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing per-database subdirectories
+ </text>
+ </g>
+ <g transform="translate(170 190)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 1/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of first database 'template0'
+ </text>
+ </g>
+ <g transform="translate(170 220)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12992/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of second database 'template1'
+ </text>
+ </g>
+ <g transform="translate(170 250)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12999/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of third database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(170 280)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ nnnnn/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Optional: more subdirectories for databases, e.g. 'my_db'
+ </text>
+ </g>
+ <g transform="translate(120 310)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ global/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory with information about Global SQL Objects
+ </text>
+ </g>
+ <g transform="translate(120 340)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_wal/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 370)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_xact/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for transaction commit status ('pg_clog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 400)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_tblspc/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing symbolic links to tablespaces
+ </text>
+ </g>
+ <g transform="translate(120 430)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_... /
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Some more subdirectories
+ </text>
+ </g>
+ <g transform="translate(120 465)">
+ <use xlink:href="#file"/>
+ <use xlink:href="#file" x="50"/>
+ <text x="200" y="26" class="text_normal">
+ 'postmaster.pid' and other files with cluster-wide relevance
+ </text>
+ </g>
+ <g transform="translate(20 540)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /xyz/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ Same or another arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 570)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ cluster_2/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of another cluster 'cluster_2'
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-ink.svg b/doc/src/sgml/images/directories-ink.svg
new file mode 100644
index 0000000000..8151cf583a
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink.svg
@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="640px"
+ viewBox="0 0 900 640"
+ id="svg303"
+ sodipodi:docname="directories-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata307">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Directory structure of a cluster</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1083"
+ inkscape:window-height="808"
+ id="namedview305"
+ showgrid="false"
+ inkscape:zoom="0.36875"
+ inkscape:cx="450"
+ inkscape:cy="320"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg303" />
+ <title
+ id="title153">Directory structure of a cluster</title>
+ <style
+ type="text/css"
+ id="style155">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs177">
+ <!-- Directory -->
+ <symbol
+ id="directory"
+ stroke="blue"
+ stroke-width="0.3px"
+ fill="aqua">
+ <title
+ id="title157">Directory</title>
+ <rect
+ x="0"
+ y="10"
+ width="110"
+ height="20"
+ id="rect159" />
+ <path
+ d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2"
+ id="path161" />
+ </symbol>
+ <!-- File -->
+ <symbol
+ id="file"
+ stroke="black"
+ fill="none">
+ <title
+ id="title164">File</title>
+ <rect
+ x="0"
+ y="0"
+ width="40"
+ height="50"
+ stroke="blue"
+ id="rect166" />
+ <path
+ d="M 5,10 h 20"
+ stroke-dasharray="4 2"
+ id="path168" />
+ <path
+ d="M 5,17 h 15"
+ stroke-dasharray="6 2"
+ id="path170" />
+ <path
+ d="M 5,24 h 25"
+ stroke-dasharray="4 2"
+ id="path172" />
+ <path
+ d="M 5,31 h 20"
+ stroke-dasharray="5 2"
+ id="path174" />
+ </symbol>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect179" />
+ <!-- caption -->
+ <text
+ x="200"
+ y="50"
+ class="text_big"
+ id="text181">Directory Structure</text>
+ <!-- the directories -->
+ <g
+ transform="translate(20, 100)"
+ id="g189">
+ <use
+ xlink:href="#directory"
+ id="use183" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text185">... /pg/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text187">An arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 130)"
+ id="g197">
+ <use
+ xlink:href="#directory"
+ id="use191" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text193">data/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text195">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+ <g
+ transform="translate(120, 160)"
+ id="g205">
+ <use
+ xlink:href="#directory"
+ id="use199" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text201">base/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text203">Subdirectory containing per-database subdirectories</text>
+ </g>
+ <!-- -->
+ <g
+ transform="translate(170, 190)"
+ id="g213">
+ <use
+ xlink:href="#directory"
+ id="use207" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text209">1/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text211">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g
+ transform="translate(170, 220)"
+ id="g221">
+ <use
+ xlink:href="#directory"
+ id="use215" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text217">12992/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text219">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g
+ transform="translate(170, 250)"
+ id="g229">
+ <use
+ xlink:href="#directory"
+ id="use223" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text225">12999/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text227">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g
+ transform="translate(170, 280)"
+ id="g237">
+ <use
+ xlink:href="#directory"
+ id="use231" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text233">nnnnn/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text235">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+ <g
+ transform="translate(120, 310)"
+ id="g245">
+ <use
+ xlink:href="#directory"
+ id="use239" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text241">global/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text243">Subdirectory with information about Global SQL Objects</text>
+ </g>
+ <g
+ transform="translate(120, 340)"
+ id="g253">
+ <use
+ xlink:href="#directory"
+ id="use247" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text249">pg_wal/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text251">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 370)"
+ id="g261">
+ <use
+ xlink:href="#directory"
+ id="use255" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text257">pg_xact/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text259">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 400)"
+ id="g269">
+ <use
+ xlink:href="#directory"
+ id="use263" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text265">pg_tblspc/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text267">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+ <g
+ transform="translate(120, 430)"
+ id="g277">
+ <use
+ xlink:href="#directory"
+ id="use271" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text273">pg_... /</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text275">Some more subdirectories</text>
+ </g>
+ <g
+ transform="translate(120, 465)"
+ id="g285">
+ <use
+ xlink:href="#file"
+ x="0"
+ y="0"
+ id="use279" />
+ <use
+ xlink:href="#file"
+ x="50"
+ y="0"
+ id="use281" />
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text283">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+ <!-- next cluster -->
+ <g
+ transform="translate(20, 540)"
+ id="g293">
+ <use
+ xlink:href="#directory"
+ id="use287" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text289">... /xyz/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text291">Same or another arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 570)"
+ id="g301">
+ <use
+ xlink:href="#directory"
+ id="use295" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text297">cluster_2/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text299">Root of another cluster 'cluster_2'</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
new file mode 100644
index 0000000000..6d16a03169
--- /dev/null
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="640px"
+ viewBox="0 0 900 640">
+
+ <title>Directory structure of a cluster</title>
+
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Directory -->
+ <symbol id="directory" stroke="blue" stroke-width="0.3px" fill="aqua">
+ <title>Directory</title>
+ <rect x="0" y="10" width="110" height="20" />
+ <path d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2" />
+ </symbol>
+
+ <!-- File -->
+ <symbol id="file" stroke="black" fill="none" >
+ <title>File</title>
+ <rect x="0" y="0" width="40" height="50" stroke="blue" />
+ <path d="M 5,10 h 20" stroke-dasharray="4 2" />
+ <path d="M 5,17 h 15" stroke-dasharray="6 2" />
+ <path d="M 5,24 h 25" stroke-dasharray="4 2" />
+ <path d="M 5,31 h 20" stroke-dasharray="5 2" />
+ </symbol>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption -->
+ <text x="200" y="50" class="text_big">Directory Structure</text>
+
+ <!-- the directories -->
+ <g transform="translate(20, 100)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /pg/</text>
+ <text x="300" y="26" class="text_normal">An arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 130)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">data/</text>
+ <text x="250" y="26" class="text_normal">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+
+ <g transform="translate(120, 160)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">base/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing per-database subdirectories</text>
+ </g>
+
+ <!-- -->
+ <g transform="translate(170, 190)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">1/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g transform="translate(170, 220)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12992/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g transform="translate(170, 250)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12999/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g transform="translate(170, 280)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">nnnnn/</text>
+ <text x="150" y="26" class="text_normal">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+
+ <g transform="translate(120, 310)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">global/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory with information about Global SQL Objects</text>
+ </g>
+
+ <g transform="translate(120, 340)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 370)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 400)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+
+ <g transform="translate(120, 430)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_... /</text>
+ <text x="200" y="26" class="text_normal">Some more subdirectories</text>
+ </g>
+
+ <g transform="translate(120, 465)">
+ <use xlink:href="#file" x="0" y="0" />
+ <use xlink:href="#file" x="50" y="0" />
+ <text x="200" y="26" class="text_normal">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+
+ <!-- next cluster -->
+ <g transform="translate(20, 540)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /xyz/</text>
+ <text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 570)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster 'cluster_2'</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink-svgo.svg b/doc/src/sgml/images/freeze-ink-svgo.svg
new file mode 100644
index 0000000000..6fedfb7633
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink-svgo.svg
@@ -0,0 +1,84 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="320" viewBox="0 0 850 320">
+ <title>
+ Freeze
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100)"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="70" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ <tspan font-style="italic" font-weight="700">Freeze</tspan> to keep visible
+ </text>
+ <g fill="none" transform="translate(170 190)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_120" startOffset="11.2%">(1)</textPath> <textPath xlink:href="#Path_120" startOffset="61.2%">(5)</textPath> <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%">|</textPath> <textPath xlink:href="#Path_120" startOffset="34%">(2)</textPath> <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(3)</textPath> <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%">|</textPath> <textPath xlink:href="#Path_120" startOffset="55%">(4)</textPath>
+ </text>
+ <path d="M-80-80L80 80" stroke="black"/>
+ <text class="text_normal" letter-spacing="12" transform="rotate(45 40.78 -38.1)">
+ PAST
+ </text>
+ <text class="text_normal" letter-spacing="12" transform="rotate(-135 27.43 23.79)">
+ FUTURE
+ </text>
+ <use xlink:href="#frozenPoint" transform="rotate(10)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(25)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(40)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(55)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(70)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(85)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(100)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(115)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(130)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(145)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(160)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(175)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(190)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(205)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(220)"/>
+ </g>
+ <g class="text_normal" transform="translate(380 30)">
+ <text>
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25">
+ 1: txid_current + 2 ^ 31 (split-point)
+ </text>
+ <text y="50">
+ 2: autovacuum_freeze_max_age (200 mio.)
+ </text>
+ <text y="75">
+ 3: vacuum_freeze_table_age (150 mio.)
+ </text>
+ <text y="100">
+ 4: vacuum_freeze_min_age (50 mio.)
+ </text>
+ <text y="125">
+ 5: txid_current (split-point, jungest xid)
+ </text>
+ <text y="155">
+ per table: pg_class.relfrozenxid <tspan font-weight="700">must</tspan> be between (1) and (5);
+ </text>
+ <text y="175" x="75">
+ normally it is between (3) and (4)
+ </text>
+ <use xlink:href="#unfrozenPoint" transform="translate(106 200)"/>
+ <text y="205" x="20">
+ Unfrozen xid
+ </text>
+ <use xlink:href="#frozenPoint" transform="translate(106 224)"/>
+ <text y="230" x="20">
+ Frozen xid
+ </text>
+ <text y="260">
+ (figure is out of scale)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink.svg b/doc/src/sgml/images/freeze-ink.svg
new file mode 100644
index 0000000000..009cfe4b41
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink.svg
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="320px"
+ viewBox="0 0 850 320"
+ id="svg454"
+ sodipodi:docname="freeze-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata458">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Freeze</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="979"
+ inkscape:window-height="857"
+ id="namedview456"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="160"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg454" />
+ <title
+ id="title309">Freeze</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style311">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs318">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle
+ id="frozenPoint"
+ r="3"
+ stroke="green"
+ fill="green"
+ transform="translate(-100, 0)" />
+ <circle
+ id="unfrozenPoint"
+ r="3"
+ stroke="green"
+ fill="none"
+ transform="translate(-100, 0)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect320" />
+ <text
+ class="text_big"
+ x="70"
+ y="40"
+ id="text324"><tspan
+ style="font-style:italic;font-weight:bold"
+ id="tspan322">
+ Freeze</tspan>
+ to keep visible</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 190)"
+ id="g418">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle326" />
+ <text
+ class="text_normal"
+ id="text350">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath328">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath330">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath332">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="11.2%"
+ id="textPath334">(1)</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="61.2%"
+ id="textPath336">(5)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="red"
+ stroke-width="3"
+ startOffset="34%"
+ id="textPath338">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="34%"
+ id="textPath340">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="black"
+ stroke-width="3"
+ startOffset="45%"
+ id="textPath342">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath344">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="green"
+ stroke-width="3"
+ startOffset="55%"
+ id="textPath346">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="55%"
+ id="textPath348">(4)</textPath>
+ </text>
+ <!-- split it into 'past' and 'future' -->
+ <path
+ d="M -80 -80 l 160 160"
+ stroke="black"
+ id="path352" />
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(-15, -40) rotate(45)"
+ id="text354">PAST</text>
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(30, 60) rotate(225)"
+ id="text356">FUTURE</text>
+ <g
+ transform="rotate(10)"
+ id="g360">
+ <use
+ xlink:href="#frozenPoint"
+ id="use358" />
+ </g>
+ <g
+ transform="rotate(25)"
+ id="g364">
+ <use
+ xlink:href="#frozenPoint"
+ id="use362" />
+ </g>
+ <g
+ transform="rotate(40)"
+ id="g368">
+ <use
+ xlink:href="#frozenPoint"
+ id="use366" />
+ </g>
+ <g
+ transform="rotate(55)"
+ id="g372">
+ <use
+ xlink:href="#frozenPoint"
+ id="use370" />
+ </g>
+ <g
+ transform="rotate(70)"
+ id="g376">
+ <use
+ xlink:href="#frozenPoint"
+ id="use374" />
+ </g>
+ <g
+ transform="rotate(85)"
+ id="g380">
+ <use
+ xlink:href="#frozenPoint"
+ id="use378" />
+ </g>
+ <g
+ transform="rotate(100)"
+ id="g384">
+ <use
+ xlink:href="#frozenPoint"
+ id="use382" />
+ </g>
+ <g
+ transform="rotate(115)"
+ id="g388">
+ <use
+ xlink:href="#frozenPoint"
+ id="use386" />
+ </g>
+ <g
+ transform="rotate(130)"
+ id="g392">
+ <use
+ xlink:href="#frozenPoint"
+ id="use390" />
+ </g>
+ <g
+ transform="rotate(145)"
+ id="g396">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use394" />
+ </g>
+ <g
+ transform="rotate(160)"
+ id="g400">
+ <use
+ xlink:href="#frozenPoint"
+ id="use398" />
+ </g>
+ <g
+ transform="rotate(175)"
+ id="g404">
+ <use
+ xlink:href="#frozenPoint"
+ id="use402" />
+ </g>
+ <g
+ transform="rotate(190)"
+ id="g408">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use406" />
+ </g>
+ <g
+ transform="rotate(205)"
+ id="g412">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use410" />
+ </g>
+ <g
+ transform="rotate(220)"
+ id="g416">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use414" />
+ </g>
+ </g>
+ <!-- legend -->
+ <g
+ class="text_normal"
+ transform="translate(380 30)"
+ id="g452">
+ <text
+ id="text424">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan420">^</tspan>
+<tspan
+ dy="5"
+ id="tspan422">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text426">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text
+ y="50"
+ id="text428">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text
+ y="75"
+ id="text430">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text
+ y="100"
+ id="text432">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text
+ y="125"
+ id="text434">5: txid_current (split-point, jungest xid)</text>
+ <text
+ y="155"
+ id="text438">per table: pg_class.relfrozenxid
+ <tspan
+ style="font-weight:bold"
+ id="tspan436">must</tspan>
+ be between (1) and (5);</text>
+ <text
+ y="175"
+ x="75"
+ id="text440">normally it is between (3) and (4)</text>
+ <use
+ xlink:href="#unfrozenPoint"
+ transform="translate(106, 200)"
+ id="use442" />
+ <text
+ y="205"
+ x="20"
+ id="text444">Unfrozen xid</text>
+ <use
+ xlink:href="#frozenPoint"
+ transform="translate(106, 224)"
+ id="use446" />
+ <text
+ y="230"
+ x="20"
+ id="text448">Frozen xid</text>
+ <text
+ y="260"
+ id="text450">(figure is out of scale)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-raw.svg b/doc/src/sgml/images/freeze-raw.svg
new file mode 100644
index 0000000000..2d1d256184
--- /dev/null
+++ b/doc/src/sgml/images/freeze-raw.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="320px"
+ viewBox="0 0 850 320" >
+
+ <title>Freeze</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100, 0)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100, 0)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="70" y="40"><tspan style="font-style:italic;font-weight:bold">
+ Freeze</tspan> to keep visible</text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 190)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_120" startOffset="11.2%" >(1)</textPath>
+ <textPath xlink:href="#Path_120" startOffset="61.2%" >(5)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="34%" >(2)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(3)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="55%" >(4)</textPath>
+
+ </text>
+
+ <!-- split it into 'past' and 'future' -->
+ <path d="M -80 -80 l 160 160" stroke="black" />
+ <text class="text_normal" letter-spacing="12" transform="translate(-15, -40) rotate(45)">PAST</text>
+ <text class="text_normal" letter-spacing="12" transform="translate(30, 60) rotate(225)">FUTURE</text>
+
+ <g transform="rotate(10)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(25)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(40)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(55)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(70)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(85)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(100)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(115)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(130)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(145)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(160)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(175)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(190)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(205)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(220)"><use xlink:href="#unfrozenPoint"/></g>
+
+ </g>
+
+ <!-- legend -->
+ <g class="text_normal" transform="translate(380 30)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text y="50">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text y="75">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text y="100">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text y="125">5: txid_current (split-point, jungest xid)</text>
+ <text y="155">per table: pg_class.relfrozenxid
+ <tspan style="font-weight:bold">must</tspan> be between (1) and (5);</text>
+ <text y="175" x="75">normally it is between (3) and (4)</text>
+
+ <use xlink:href="#unfrozenPoint" transform="translate(106, 200)"/>
+ <text y="205" x="20">Unfrozen xid</text>
+
+ <use xlink:href="#frozenPoint" transform="translate(106, 224)"/>
+ <text y="230" x="20">Frozen xid</text>
+
+ <text y="260">(figure is out of scale)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
new file mode 100644
index 0000000000..26bce6176d
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
@@ -0,0 +1,83 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="720" height="430" viewBox="0 0 720 430">
+ <title>
+ Hierarchy of Internal Objects
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Hierarchy of internal Objects
+ </text>
+ <g fill="none">
+ <g transform="translate(350 240)">
+ <ellipse rx="320" ry="170" stroke="blue"/>
+ <text class="text_normal" x="-140" y="-130">
+ Cluster
+ </text>
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-60" y="5">
+ Database Names
+ </text>
+ </g>
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-40" y="5">
+ Tablespace
+ </text>
+ </g>
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-70" y="5">
+ Replication Origins
+ </text>
+ </g>
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue"/>
+ <text class="text_normal" x="-60" y="-3">
+ Subscription for
+ </text>
+ <text class="text_normal" x="-68" y="10">
+ Logical Replication
+ </text>
+ </g>
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-15" y="5">
+ Role
+ </text>
+ </g>
+ </g>
+ <g transform="translate(270 250)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2"/>
+ <text class="text_normal" x="-60" y="-80">
+ Database
+ </text>
+ <g transform="translate(-150 -30)">
+ <ellipse rx="50" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Extension
+ </text>
+ </g>
+ <g transform="translate(-155 35)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Collation
+ </text>
+ </g>
+ <g transform="translate(30 20)">
+ <ellipse rx="140" ry="70" stroke="blue"/>
+ <text class="text_normal" x="-80" y="-35">
+ Schema
+ </text>
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue"/>
+ <text class="text_normal" x="-50" y="5">
+ Table, View, ...
+ </text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
new file mode 100644
index 0000000000..e5745818d9
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="720px"
+ height="430px"
+ viewBox="0 0 720 430"
+ id="svg540"
+ sodipodi:docname="internal-objects-hierarchy-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata546">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Hierarchy of Internal Objects</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs544" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1050"
+ inkscape:window-height="838"
+ id="namedview542"
+ showgrid="false"
+ inkscape:zoom="0.51944444"
+ inkscape:cx="360"
+ inkscape:cy="215"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg540" />
+ <title
+ id="title460">Hierarchy of Internal Objects</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style462">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect464" />
+ <text
+ class="text_big"
+ x="200"
+ y="40"
+ id="text466">Hierarchy of internal Objects</text>
+ <!-- set centre of figure and default values -->
+ <g
+ transform="translate(350 240)"
+ fill="none"
+ id="g538">
+ <g
+ id="g504">
+ <ellipse
+ rx="320"
+ ry="170"
+ stroke="blue"
+ id="ellipse468" />
+ <text
+ class="text_normal"
+ x="-140"
+ y="-130"
+ id="text470">Cluster</text>
+ <g
+ transform="translate(40 -125)"
+ id="g476">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse472" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="5"
+ id="text474">Database Names</text>
+ </g>
+ <g
+ transform="translate(180 -70)"
+ id="g482">
+ <ellipse
+ rx="60"
+ ry="20"
+ stroke="blue"
+ id="ellipse478" />
+ <text
+ class="text_normal"
+ x="-40"
+ y="5"
+ id="text480">Tablespace</text>
+ </g>
+ <g
+ transform="translate(230 -5)"
+ id="g488">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse484" />
+ <text
+ class="text_normal"
+ x="-70"
+ y="5"
+ id="text486">Replication Origins</text>
+ </g>
+ <g
+ transform="translate(200 70)"
+ id="g496">
+ <ellipse
+ rx="78"
+ ry="27"
+ stroke="blue"
+ id="ellipse490" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-3"
+ id="text492">Subscription for</text>
+ <text
+ class="text_normal"
+ x="-68"
+ y="10"
+ id="text494">Logical Replication</text>
+ </g>
+ <g
+ transform="translate(100 120)"
+ id="g502">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse498" />
+ <text
+ class="text_normal"
+ x="-15"
+ y="5"
+ id="text500">Role</text>
+ </g>
+ </g>
+ <g
+ transform="translate(-80 10)"
+ id="g536">
+ <ellipse
+ rx="220"
+ ry="110"
+ stroke="blue"
+ stroke-width="2px"
+ id="ellipse506" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-80"
+ id="text508">Database</text>
+ <g
+ transform="translate(-120 -50)"
+ id="g534">
+ <g
+ transform="translate(-30 20)"
+ id="g514">
+ <ellipse
+ rx="50"
+ ry="20"
+ stroke="blue"
+ id="ellipse510" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text512">Extension</text>
+ </g>
+ <g
+ transform="translate(-35 85)"
+ id="g520">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse516" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text518">Collation</text>
+ </g>
+ <g
+ transform="translate(150 70)"
+ id="g532">
+ <ellipse
+ rx="140"
+ ry="70"
+ stroke="blue"
+ id="ellipse522" />
+ <text
+ class="text_normal"
+ x="-80"
+ y="-35"
+ id="text524">Schema</text>
+ <g
+ transform="translate(20 10)"
+ id="g530">
+ <ellipse
+ rx="90"
+ ry="30"
+ stroke="blue"
+ id="ellipse526" />
+ <text
+ class="text_normal"
+ x="-50"
+ y="5"
+ id="text528">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
new file mode 100644
index 0000000000..f0dc890f6b
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="720px" height="430px"
+ viewBox="0 0 720 430" >
+
+ <title>Hierarchy of Internal Objects</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="200" y="40">Hierarchy of internal Objects</text>
+
+
+ <!-- set centre of figure and default values -->
+ <g transform="translate(350 240)" fill="none">
+
+ <g>
+ <ellipse rx="320" ry="170" stroke="blue" />
+ <text class="text_normal" x="-140" y="-130">Cluster</text>
+
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-60" y="5">Database Names</text>
+ </g>
+
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue" />
+ <text class="text_normal" x="-40" y="5">Tablespace</text>
+ </g>
+
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-70" y="5">Replication Origins</text>
+ </g>
+
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue" />
+ <text class="text_normal" x="-60" y="-3">Subscription for</text>
+ <text class="text_normal" x="-68" y="10">Logical Replication</text>
+ </g>
+
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-15" y="5">Role</text>
+ </g>
+
+ </g>
+
+ <g transform="translate(-80 10)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2px" />
+ <text class="text_normal" x="-60" y="-80">Database</text>
+
+ <g transform="translate(-120 -50)">
+ <g transform="translate(-30 20)">
+ <ellipse rx="50" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Extension</text>
+ </g>
+
+ <g transform="translate(-35 85)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Collation</text>
+ </g>
+
+ <g transform="translate(150 70)">
+ <ellipse rx="140" ry="70" stroke="blue" />
+ <text class="text_normal" x="-80" y="-35">Schema</text>
+
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue" />
+ <text class="text_normal" x="-50" y="5">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink-svgo.svg b/doc/src/sgml/images/mvcc-ink-svgo.svg
new file mode 100644
index 0000000000..8e67da93d1
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink-svgo.svg
@@ -0,0 +1,151 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="150" viewBox="0 0 850 150">
+ <title>
+ MVCC
+ </title>
+ <style>
+ .text_small{font-style:normal;font-weight:400;font-size:10px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <marker id="triangle_1" markerWidth="10" markerHeight="10" refX="5" refY="5" orient="auto" stroke="black" fill="none">
+ <path d="M0 0l10 5-10 5"/>
+ </marker>
+ <path id="arrow" d="M0 0q20-15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+ <g id="tuple" stroke="black">
+ <path d="M80 0H0v20h80M29 0v20M60 0v20"/>
+ <path d="M80 0h15M80 20h15" stroke-dasharray="2 1"/>
+ </g>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <g fill="none">
+ <g transform="translate(20 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">123</tspan> <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)" fill="#00f">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 83)" fill="#00f">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(185 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">135</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 53)" fill="#00f">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(350 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">142</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 23)" fill="#00f">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(515 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">821</tspan> <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 821
+ </text>
+ <text class="text_small" transform="translate(125 23)">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(740 110)">
+ <path d="M102-20H-18v60" stroke="black"/>
+ <text font-weight="400" font-size="16" font-family=""Open Sans",sans-serif" fill="#000">
+ Legend
+ </text>
+ <use xlink:href="#tuple" transform="translate(0 10)"/>
+ <text class="text_small" transform="translate(3 23)">
+ xmin
+ </text>
+ <text class="text_small" transform="translate(32 23)">
+ xmax
+ </text>
+ <text class="text_small" transform="translate(65 23)">
+ data
+ </text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink.svg b/doc/src/sgml/images/mvcc-ink.svg
new file mode 100644
index 0000000000..f4161b3e79
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink.svg
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="150px"
+ viewBox="0 0 850 150"
+ id="svg147"
+ sodipodi:docname="mvcc-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>MVCC</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1256"
+ inkscape:window-height="801"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="75"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">MVCC</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs15">
+ <marker
+ id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto"
+ stroke="black"
+ fill="none">
+ <path
+ d="M 0,0 L 10,5 L 0,10"
+ id="path6" />
+ </marker>
+ <g
+ id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path
+ d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20"
+ stroke="black"
+ id="path9" />
+ <!-- prolong the rectangle -->
+ <path
+ d="M 80 0 h 15 M 80 20 h 15"
+ stroke="black"
+ stroke-dasharray="2 1"
+ id="path11" />
+ </g>
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path
+ id="arrow"
+ d="M 0 0 Q 20 -15 40 0"
+ stroke="black"
+ marker-end="url(#triangle_1)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect17" />
+ <!-- set default values -->
+ <g
+ fill="none"
+ id="g145">
+ <!-- start plus first INSERT -->
+ <g
+ transform="translate(20, 40)"
+ id="g35">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text23">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan19">123</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan21">: INSERT</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use25" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use27" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ style="fill:blue"
+ id="text29">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text31">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ style="fill:blue"
+ id="text33">'x'</text>
+ </g>
+ <!-- first UPDATE -->
+ <g
+ transform="translate(185, 40)"
+ id="g61">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text41">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan37">135</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan39">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use43" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use45" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ style="fill:blue"
+ id="text47">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text49">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ style="fill:blue"
+ id="text51">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use53" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text55">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text57">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text59">'x'</text>
+ </g>
+ <!-- next UPDATE -->
+ <g
+ transform="translate(350, 40)"
+ id="g95">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text67">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan63">142</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan65">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use69" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use71" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ style="fill:blue"
+ id="text73">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text75">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ style="fill:blue"
+ id="text77">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use79" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text81">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text83">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text85">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use87" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text89">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text91">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text93">'x'</text>
+ </g>
+ <!-- DELETE -->
+ <g
+ transform="translate(515, 40)"
+ id="g129">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text101">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan97">821</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan99">: DELTE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use103" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use105" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text107">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text109">821</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ id="text111">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use113" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text115">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ id="text117">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text119">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use121" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text123">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text125">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text127">'x'</text>
+ </g>
+ <!-- LEGEND -->
+ <g
+ transform="translate(740, 110)"
+ id="g143">
+ <path
+ d="M 102 -20 h -120 v 60"
+ stroke="black"
+ id="path131" />
+ <text
+ class="text_normal"
+ transform="translate(0, 0)"
+ id="text133">Legend</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(0, 10)"
+ id="use135" />
+ <text
+ class="text_small"
+ transform="translate(3, 23)"
+ id="text137">xmin</text>
+ <text
+ class="text_small"
+ transform="translate(32, 23)"
+ id="text139">xmax</text>
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text141">data</text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-raw.svg b/doc/src/sgml/images/mvcc-raw.svg
new file mode 100644
index 0000000000..0481c4c938
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-raw.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="150px"
+ viewBox="0 0 850 150" >
+
+ <title>MVCC</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <marker id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto" stroke="black" fill="none">
+ <path d="M 0,0 L 10,5 L 0,10" />
+ </marker>
+
+ <g id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20" stroke="black"/>
+ <!-- prolong the rectangle -->
+ <path d="M 80 0 h 15 M 80 20 h 15" stroke="black" stroke-dasharray="2 1"/>
+ </g>
+
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path id="arrow" d="M 0 0 Q 20 -15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- set default values -->
+ <g fill="none">
+
+ <!-- start plus first INSERT -->
+ <g transform="translate(20, 40)">
+
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">123</tspan>
+ <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)" style="fill:blue">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 83)" style="fill:blue">'x'</text>
+ </g>
+
+ <!-- first UPDATE -->
+ <g transform="translate(185, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">135</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 53)" style="fill:blue">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- next UPDATE -->
+ <g transform="translate(350, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">142</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 23)" style="fill:blue">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- DELETE -->
+ <g transform="translate(515, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">821</tspan>
+ <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">821</text>
+ <text class="text_small" transform="translate(125, 23)">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- LEGEND -->
+ <g transform="translate(740, 110)">
+ <path d="M 102 -20 h -120 v 60" stroke="black"/>
+ <text class="text_normal" transform="translate(0, 0)">Legend</text>
+ <use xlink:href="#tuple" transform="translate(0, 10)"/>
+ <text class="text_small" transform="translate(3, 23)">xmin</text>
+ <text class="text_small" transform="translate(32, 23)">xmax</text>
+ <text class="text_small" transform="translate(65, 23)">data</text>
+ </g>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink-svgo.svg b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
new file mode 100644
index 0000000000..262275f05c
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
@@ -0,0 +1,285 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 900 600">
+ <title>
+ PG Overall Server Architecture
+ </title>
+ <style>
+ .text_big{font-style:normal}.text_big,.text_comment,.text_normal,.text_small{font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_normal,.text_small{font-style:normal}.text_small{font-size:12px}.text_normal{font-size:16px}.text_big{font-size:24px}.text_comment{font-style:italic;font-size:16px}
+ </style>
+ <defs>
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (200 x 20 px)
+ </title>
+ <path d="M200 10v10H0V0h190v10h10L190 0"/>
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (250 x 20 px)
+ </title>
+ <path d="M250 10v10H0V0h240v10h10L240 0"/>
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (100 x 35 px)
+ </title>
+ <path d="M100 10v25H0V0h90v10h10L90 0"/>
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (170 x 50 px)
+ </title>
+ <path d="M170 10v40H0V0h160v10h10L160 0"/>
+ </symbol>
+ <symbol id="state_300x120">
+ <title>
+ UML State (300x120)
+ </title>
+ <rect width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>
+ UML State (350x120)
+ </title>
+ <rect width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="disc" stroke="blue" fill="none">
+ <title>
+ Disc
+ </title>
+ <ellipse cx="51" cy="13" rx="50" ry="12"/>
+ <path d="M1 13v60"/>
+ <path d="M101 13v60"/>
+ <path d="M1 73a50 12 0 00100 0"/>
+ </symbol>
+ <symbol id="laptop" stroke="black" fill="none">
+ <title>
+ Laptop
+ </title>
+ <path d="M20 40V0h54v40l15 15H5l15-15h54"/>
+ <path d="M23 3h48v34H23z"/>
+ <path d="M30 10h20"/>
+ <path d="M30 15h25"/>
+ <path d="M30 20h10"/>
+ <path d="M30 30h20"/>
+ <path d="M25 50h45l2 2H22z"/>
+ </symbol>
+ <marker id="arrowhead_start" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto">
+ <path d="M6 0L0 3l6 3" stroke="black" fill="none"/>
+ </marker>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="15" y="40" class="text_big">
+ Client
+ </text>
+ <text x="140" y="40" class="text_big">
+ Server
+ </text>
+ <use xlink:href="#laptop" x="5" y="210"/>
+ <g transform="translate(130 70)">
+ <use xlink:href="#state_350x120"/>
+ <text x="5" y="20" class="text_normal">
+ maintenance_work_mem (per connection)
+ </text>
+ <text x="5" y="45" class="text_normal">
+ work_mem (per query operation)
+ </text>
+ <text x="5" y="70" class="text_normal">
+ autovacuum_work_mem (per worker process)
+ </text>
+ <text x="5" y="95" class="text_normal">
+ temp_buffer (per connection)
+ </text>
+ <text x="5" y="110" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_200x20" x="140" y="-15"/>
+ <text x="150" class="text_comment">
+ Individual Memory
+ </text>
+ </g>
+ <g transform="translate(520 70)">
+ <use xlink:href="#state_300x120"/>
+ <text x="10" y="30" class="text_normal">
+ shared_buffers (heap and index)
+ </text>
+ <text x="10" y="70" class="text_normal">
+ wal_buffers (WAL records)
+ </text>
+ <text x="10" y="100" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_250x20" x="40" y="-15"/>
+ <text x="50" class="text_comment">
+ Shared Memory (per Instance)
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M180 215h250v30H180z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(180 215)">
+ Postmaster
+ </text>
+ <path d="M90 230h75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 230)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 1
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M150 315h370v30H150z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(150 315)">
+ Backend processes (one per connection)
+ </text>
+ <path d="M155 315v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M160 310v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M90 240l63 63" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 290)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 3
+ </text>
+ </g>
+ <path d="M360 250v50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180 255)">
+ <use xlink:href="#note_250x20"/>
+ <text x="10" y="15" class="text_comment">
+ Creates backend processes
+ </text>
+ </g>
+ <g transform="translate(360 281)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 2
+ </text>
+ </g>
+ <path d="M460 300V200" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M498 300V95h30" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M508 300V135h20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M550 220h120v30H550z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(550 220)">
+ WAL Writer
+ </text>
+ <path d="M590 150v65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M590 255v230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 340h140v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 340)">
+ Checkpointer
+ </text>
+ <path d="M740 110v220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 355H475v130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M700 330V150" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50"/>
+ <text x="60" y="-35" class="text_comment">
+ Checkpoint
+ </text>
+ <text x="60" y="-20" class="text_comment">
+ Record
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M610 380h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 380)">
+ Background Writer
+ </text>
+ <path d="M770 110v260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 395H485v90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 420h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 420)">
+ WAL Archiver
+ </text>
+ <path d="M620 485l30-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M690 455l30 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M135 380h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 380)">
+ AutoVacuum
+ </text>
+ <path d="M140 380v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path d="M145 375v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path stroke="blue" fill="none" d="M135 430h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 430)">
+ Log Writer
+ </text>
+ <path stroke="blue" fill="none" d="M290 370h140v30H290z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(290 370)">
+ Stats Collector
+ </text>
+ <g transform="translate(145 490)">
+ <use xlink:href="#disc"/>
+ <text x="35" y="45" class="text_normal">
+ Log
+ </text>
+ <text x="20" y="60" class="text_small">
+ text lines,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <path d="M195 465v20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(410 490)">
+ <use xlink:href="#disc"/>
+ <text x="10" y="40" class="text_normal">
+ Heap and
+ </text>
+ <text x="25" y="55" class="text_normal">
+ Index
+ </text>
+ <text x="15" y="70" class="text_small">
+ binary blocks,
+ </text>
+ <text x="30" y="80" class="text_small">
+ random
+ </text>
+ </g>
+ <path d="M450 485V350" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(295 420)">
+ <use xlink:href="#note_170x50"/>
+ <text x="5" y="15" class="text_comment">
+ Read heap and index
+ </text>
+ <text x="5" y="30" class="text_comment">
+ pages and transfer
+ </text>
+ <text x="5" y="45" class="text_comment">
+ them to shared_buffers
+ </text>
+ </g>
+ <g transform="translate(550 490)">
+ <use xlink:href="#disc"/>
+ <text x="30" y="45" class="text_normal">
+ WAL
+ </text>
+ <text x="10" y="60" class="text_small">
+ binary records,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <g transform="translate(690 490)">
+ <use xlink:href="#disc"/>
+ <text x="16" y="45" class="text_normal">
+ Archived
+ </text>
+ <text x="36" y="60" class="text_normal">
+ WAL
+ </text>
+ </g>
+ <path d="M110 20v550" stroke="black" fill="none"/>
+ <g transform="rotate(90 -33.5 156.5)">
+ <use xlink:href="#note_200x20"/>
+ <text class="text_comment" x="10" y="15">
+ Via TCP/IP or socket
+ </text>
+ </g>
+ <text class="text_big" x="95" transform="rotate(90 425 425)">
+ RAM
+ </text>
+ <text class="text_big" x="250" transform="rotate(90 425 425)">
+ PROCESSES
+ </text>
+ <text class="text_big" x="500" transform="rotate(90 425 425)">
+ FILES
+ </text>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink.svg b/doc/src/sgml/images/ram-proc-file-ink.svg
new file mode 100644
index 0000000000..067920b99e
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink.svg
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="600px"
+ viewBox="0 0 900 600"
+ id="svg1003"
+ sodipodi:docname="ram-proc-file-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata1007">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>PG Overall Server Architecture</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1177"
+ inkscape:window-height="869"
+ id="namedview1005"
+ showgrid="false"
+ inkscape:zoom="0.39333333"
+ inkscape:cx="450"
+ inkscape:cy="300"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg1003" />
+ <title
+ id="title699">PG Overall Server Architecture</title>
+ <style
+ type="text/css"
+ id="style701">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs767">
+ <!-- Some notes in different sizes -->
+ <symbol
+ id="note_200x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title703">UML Note (200 x 20 px)</title>
+ <path
+ d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10"
+ id="path705" />
+ </symbol>
+ <symbol
+ id="note_250x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title708">UML Note (250 x 20 px)</title>
+ <path
+ d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10"
+ id="path710" />
+ </symbol>
+ <symbol
+ id="note_100x35"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title713">UML Note (100 x 35 px)</title>
+ <path
+ d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10"
+ id="path715" />
+ </symbol>
+ <symbol
+ id="note_170x50"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title718">UML Note (170 x 50 px)</title>
+ <path
+ d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10"
+ id="path720" />
+ </symbol>
+ <!-- UML states (used for buffers) -->
+ <symbol
+ id="state_300x120">
+ <title
+ id="title723">UML State (300x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="300"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect725" />
+ </symbol>
+ <symbol
+ id="state_350x120">
+ <title
+ id="title728">UML State (350x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="350"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect730" />
+ </symbol>
+ <!-- Discs -->
+ <symbol
+ id="disc"
+ stroke="blue"
+ fill="none">
+ <title
+ id="title733">Disc</title>
+ <ellipse
+ cx="51"
+ cy="13"
+ rx="50"
+ ry="12"
+ id="ellipse735" />
+ <!-- top -->
+ <path
+ d="M 1,13 v 60"
+ id="path737" />
+ <!-- left -->
+ <path
+ d="M 101,13 v 60"
+ id="path739" />
+ <!-- right -->
+ <path
+ d="M 1,73 A 50, 12, 0, 0, 0, 101,73"
+ id="path741" />
+ <!-- bottom -->
+ </symbol>
+ <!-- Laptop -->
+ <symbol
+ id="laptop"
+ stroke="black"
+ fill="none">
+ <title
+ id="title744">Laptop</title>
+ <path
+ d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54"
+ id="path746" />
+ <rect
+ x="23"
+ y="3"
+ width="48"
+ height="34"
+ id="rect748" />
+ <!-- symbolize some lines -->
+ <path
+ d="M 30,10 h 20"
+ id="path750" />
+ <path
+ d="M 30,15 h 25"
+ id="path752" />
+ <path
+ d="M 30,20 h 10"
+ id="path754" />
+ <path
+ d="M 30,30 h 20"
+ id="path756" />
+ <!-- symbolize keyboard -->
+ <path
+ d="M 25,50 h 45 l 2,2 h -50 z "
+ id="path758" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path761" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path764" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect769" />
+ <!-- caption, client side -->
+ <text
+ x="15"
+ y="40"
+ class="text_big"
+ id="text771">Client</text>
+ <text
+ x="140"
+ y="40"
+ class="text_big"
+ id="text773">Server</text>
+ <use
+ xlink:href="#laptop"
+ x="5"
+ y="210"
+ id="use775" />
+ <!-- individual memory -->
+ <g
+ transform="translate(130, 70)"
+ id="g793">
+ <use
+ xlink:href="#state_350x120"
+ x="0"
+ y="0"
+ id="use777" />
+ <text
+ x="5"
+ y="20"
+ class="text_normal"
+ id="text779">maintenance_work_mem (per connection)</text>
+ <text
+ x="5"
+ y="45"
+ class="text_normal"
+ id="text781">work_mem (per query operation)</text>
+ <text
+ x="5"
+ y="70"
+ class="text_normal"
+ id="text783">autovacuum_work_mem (per worker process)</text>
+ <text
+ x="5"
+ y="95"
+ class="text_normal"
+ id="text785">temp_buffer (per connection)</text>
+ <text
+ x="5"
+ y="110"
+ class="text_normal"
+ id="text787">...</text>
+ <use
+ xlink:href="#note_200x20"
+ x="140"
+ y="-15"
+ id="use789" />
+ <text
+ x="150"
+ y="0"
+ class="text_comment"
+ id="text791">Individual Memory</text>
+ </g>
+ <!-- shared memory -->
+ <g
+ transform="translate(520, 70)"
+ id="g807">
+ <use
+ xlink:href="#state_300x120"
+ x="0"
+ y="0"
+ id="use795" />
+ <text
+ x="10"
+ y="30"
+ class="text_normal"
+ id="text797">shared_buffers (heap and index)</text>
+ <text
+ x="10"
+ y="70"
+ class="text_normal"
+ id="text799">wal_buffers (WAL records)</text>
+ <text
+ x="10"
+ y="100"
+ class="text_normal"
+ id="text801">...</text>
+ <use
+ xlink:href="#note_250x20"
+ x="40"
+ y="-15"
+ id="use803" />
+ <text
+ x="50"
+ y="0"
+ class="text_comment"
+ id="text805">Shared Memory (per Instance)</text>
+ </g>
+ <!-- postmaster -->
+ <g
+ transform="translate(180, 215)"
+ id="g813">
+ <rect
+ width="250"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect809" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text811">Postmaster</text>
+ </g>
+ <path
+ d="M 90,230 h 75"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path815" />
+ <g
+ transform="translate(140, 230)"
+ id="g821">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle817" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text819">1</text>
+ </g>
+ <!-- backend processes -->
+ <g
+ transform="translate(150, 315)"
+ id="g831">
+ <rect
+ width="370"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect823" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text825">Backend processes (one per connection)</text>
+ <path
+ d="M 5,0 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path827" />
+ <path
+ d="M 10,-5 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path829" />
+ </g>
+ <path
+ d="M 90,240 153,303"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path833" />
+ <g
+ transform="translate(140, 290)"
+ id="g839">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle835" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text837">3</text>
+ </g>
+ <!-- connection between postmaster and backend processes -->
+ <path
+ d="M 360,250 v 50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path841" />
+ <g
+ transform="translate(180, 255)"
+ id="g847">
+ <use
+ xlink:href="#note_250x20"
+ id="use843" />
+ <text
+ x="10"
+ y="15"
+ class="text_comment"
+ id="text845">Creates backend processes</text>
+ </g>
+ <g
+ transform="translate(360, 281)"
+ id="g853">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle849" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text851">2</text>
+ </g>
+ <!-- backend process' access to individual memory -->
+ <path
+ d="M 460,300 v -100"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path855" />
+ <!-- its access to shared buffers and WAL buffers -->
+ <path
+ d="M 498,300 v -205 h 30"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path857" />
+ <path
+ d="M 508,300 v -165 h 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path859" />
+ <!-- WAL writer -->
+ <g
+ transform="translate(550, 220)"
+ id="g865">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect861" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text863">WAL Writer</text>
+ </g>
+ <path
+ d="M 590,150 v 65"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path867" />
+ <path
+ d="M 590,255 v 230"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path869" />
+ <!-- Checkpoiner -->
+ <g
+ transform="translate(610, 340)"
+ id="g875">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect871" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text873">Checkpointer</text>
+ </g>
+ <path
+ d="M 740,110 v 220"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path877" />
+ <path
+ d="M 605,355 h -130 v 130"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path879" />
+ <path
+ d="M 700,330 v -180"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path881" />
+ <g
+ transform="translate(570, 330)"
+ id="g889">
+ <use
+ xlink:href="#note_100x35"
+ x="50"
+ y="-50"
+ id="use883" />
+ <text
+ x="60"
+ y="-35"
+ class="text_comment"
+ id="text885">Checkpoint</text>
+ <text
+ x="60"
+ y="-20"
+ class="text_comment"
+ id="text887">Record</text>
+ </g>
+ <!-- BG writer -->
+ <g
+ transform="translate(610, 380)"
+ id="g895">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect891" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text893">Background Writer</text>
+ </g>
+ <path
+ d="M 770,110 v 260"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path897" />
+ <path
+ d="M 605,395 h -120 v 90"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path899" />
+ <!-- Archiver -->
+ <g
+ transform="translate(610, 420)"
+ id="g905">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect901" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text903">WAL Archiver</text>
+ </g>
+ <path
+ d="M 620,485 l 30,-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path907" />
+ <path
+ d="M 690,455 l 30, 30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path909" />
+ <!-- Vacuum -->
+ <g
+ transform="translate(135, 380)"
+ id="g919">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect911" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text913">AutoVacuum</text>
+ <path
+ d="M 5,0 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path915" />
+ <path
+ d="M 10,-5 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path917" />
+ </g>
+ <!-- Log Writer -->
+ <g
+ transform="translate(135, 430)"
+ id="g925">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect921" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text923">Log Writer</text>
+ </g>
+ <!-- Stats Collector -->
+ <g
+ transform="translate(290, 370)"
+ id="g931">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect927" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text929">Stats Collector</text>
+ </g>
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g
+ transform="translate(145, 490)"
+ id="g941">
+ <use
+ xlink:href="#disc"
+ id="use933" />
+ <text
+ x="35"
+ y="45"
+ class="text_normal"
+ id="text935">Log</text>
+ <text
+ x="20"
+ y="60"
+ class="text_small"
+ id="text937">text lines,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text939">sequential</text>
+ </g>
+ <path
+ d="M 195,465 v 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path943" />
+ <g
+ transform="translate(410, 490)"
+ id="g955">
+ <use
+ xlink:href="#disc"
+ id="use945" />
+ <text
+ x="10"
+ y="40"
+ class="text_normal"
+ id="text947">Heap and</text>
+ <text
+ x="25"
+ y="55"
+ class="text_normal"
+ id="text949">Index</text>
+ <text
+ x="15"
+ y="70"
+ class="text_small"
+ id="text951">binary blocks,</text>
+ <text
+ x="30"
+ y="80"
+ class="text_small"
+ id="text953">random</text>
+ </g>
+ <path
+ d="M 450,485 v -135"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path957" />
+ <g
+ transform="translate(295, 420)"
+ id="g967">
+ <use
+ xlink:href="#note_170x50"
+ id="use959" />
+ <text
+ x="5"
+ y="15"
+ class="text_comment"
+ id="text961">Read heap and index</text>
+ <text
+ x="5"
+ y="30"
+ class="text_comment"
+ id="text963">pages and transfer</text>
+ <text
+ x="5"
+ y="45"
+ class="text_comment"
+ id="text965">them to shared_buffers</text>
+ </g>
+ <g
+ transform="translate(550, 490)"
+ id="g977">
+ <use
+ xlink:href="#disc"
+ id="use969" />
+ <text
+ x="30"
+ y="45"
+ class="text_normal"
+ id="text971">WAL</text>
+ <text
+ x="10"
+ y="60"
+ class="text_small"
+ id="text973">binary records,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text975">sequential</text>
+ </g>
+ <g
+ transform="translate(690, 490)"
+ id="g985">
+ <use
+ xlink:href="#disc"
+ id="use979" />
+ <text
+ x="16"
+ y="45"
+ class="text_normal"
+ id="text981">Archived</text>
+ <text
+ x="36"
+ y="60"
+ class="text_normal"
+ id="text983">WAL</text>
+ </g>
+ <!-- boarder between client and server side -->
+ <path
+ d="M 110,20 v 550"
+ stroke="black"
+ fill="none"
+ id="path987" />
+ <g
+ transform="translate(123, 190) rotate(90)"
+ id="g993">
+ <use
+ xlink:href="#note_200x20"
+ id="use989" />
+ <text
+ class="text_comment"
+ x="10"
+ y="15"
+ id="text991">Via TCP/IP or socket</text>
+ </g>
+ <!-- right side -->
+ <g
+ transform="translate(850, 0) rotate(90)"
+ id="g1001">
+ <text
+ class="text_big"
+ x="95"
+ id="text995">RAM</text>
+ <text
+ class="text_big"
+ x="250"
+ id="text997">PROCESSES</text>
+ <text
+ class="text_big"
+ x="500"
+ id="text999">FILES</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-raw.svg b/doc/src/sgml/images/ram-proc-file-raw.svg
new file mode 100644
index 0000000000..8169295584
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-raw.svg
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="600px"
+ viewBox="0 0 900 600">
+
+ <title>PG Overall Server Architecture</title>
+
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Some notes in different sizes -->
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>UML Note (200 x 20 px)</title>
+ <path d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>UML Note (250 x 20 px)</title>
+ <path d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>UML Note (100 x 35 px)</title>
+ <path d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>UML Note (170 x 50 px)</title>
+ <path d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- UML states (used for buffers) -->
+ <symbol id="state_300x120">
+ <title>UML State (300x120)</title>
+ <rect x="0" y="0" width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>UML State (350x120)</title>
+ <rect x="0" y="0" width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- Discs -->
+ <symbol id="disc" stroke="blue" fill="none" >
+ <title>Disc</title>
+ <ellipse cx="51" cy="13" rx="50" ry="12" /> <!-- top -->
+ <path d="M 1,13 v 60" /> <!-- left -->
+ <path d="M 101,13 v 60" /> <!-- right -->
+ <path d="M 1,73 A 50, 12, 0, 0, 0, 101,73" /> <!-- bottom -->
+ </symbol>
+
+ <!-- Laptop -->
+ <symbol id="laptop" stroke="black" fill="none" >
+ <title>Laptop</title>
+ <path d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54" />
+ <rect x="23" y="3" width="48" height="34" />
+ <!-- symbolize some lines -->
+ <path d="M 30,10 h 20" />
+ <path d="M 30,15 h 25" />
+ <path d="M 30,20 h 10" />
+ <path d="M 30,30 h 20" />
+ <!-- symbolize keyboard -->
+ <path d="M 25,50 h 45 l 2,2 h -50 z " />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption, client side -->
+ <text x="15" y="40" class="text_big">Client</text>
+ <text x="140" y="40" class="text_big">Server</text>
+ <use xlink:href="#laptop" x="5" y="210" />
+
+
+ <!-- individual memory -->
+ <g transform="translate(130, 70)">
+ <use xlink:href="#state_350x120" x="0" y="0" />
+ <text x="5" y="20" class="text_normal">maintenance_work_mem (per connection)</text>
+ <text x="5" y="45" class="text_normal">work_mem (per query operation)</text>
+ <text x="5" y="70" class="text_normal">autovacuum_work_mem (per worker process)</text>
+ <text x="5" y="95" class="text_normal">temp_buffer (per connection)</text>
+ <text x="5" y="110" class="text_normal">...</text>
+ <use xlink:href="#note_200x20" x="140" y="-15" />
+ <text x="150" y="0" class="text_comment">Individual Memory</text>
+ </g>
+
+ <!-- shared memory -->
+ <g transform="translate(520, 70)">
+ <use xlink:href="#state_300x120" x="0" y="0" />
+ <text x="10" y="30" class="text_normal">shared_buffers (heap and index)</text>
+ <text x="10" y="70" class="text_normal">wal_buffers (WAL records)</text>
+ <text x="10" y="100" class="text_normal">...</text>
+ <use xlink:href="#note_250x20" x="40" y="-15" />
+ <text x="50" y="0" class="text_comment">Shared Memory (per Instance)</text>
+ </g>
+
+ <!-- postmaster -->
+ <g transform="translate(180, 215)">
+ <rect width="250" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Postmaster</text>
+ </g>
+ <path d="M 90,230 h 75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 230)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">1</text>
+ </g>
+
+ <!-- backend processes -->
+ <g transform="translate(150, 315)">
+ <rect width="370" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Backend processes (one per connection)</text>
+ <path d="M 5,0 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <path d="M 90,240 153,303" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 290)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">3</text>
+ </g>
+
+ <!-- connection between postmaster and backend processes -->
+ <path d="M 360,250 v 50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180, 255)">
+ <use xlink:href="#note_250x20" />
+ <text x="10" y="15" class="text_comment">Creates backend processes</text>
+ </g>
+ <g transform="translate(360, 281)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">2</text>
+ </g>
+
+ <!-- backend process' access to individual memory -->
+ <path d="M 460,300 v -100" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <!-- its access to shared buffers and WAL buffers -->
+ <path d="M 498,300 v -205 h 30" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M 508,300 v -165 h 20" stroke="black" fill="none"
+ marker-end="url(#arrowhead_end)"/>
+
+ <!-- WAL writer -->
+ <g transform="translate(550, 220)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Writer</text>
+ </g>
+ <path d="M 590,150 v 65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 590,255 v 230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Checkpoiner -->
+ <g transform="translate(610, 340)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Checkpointer</text>
+ </g>
+ <path d="M 740,110 v 220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,355 h -130 v 130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 700,330 v -180" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570, 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50" />
+ <text x="60" y="-35" class="text_comment">Checkpoint</text>
+ <text x="60" y="-20" class="text_comment">Record</text>
+ </g>
+
+ <!-- BG writer -->
+ <g transform="translate(610, 380)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Background Writer</text>
+ </g>
+ <path d="M 770,110 v 260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,395 h -120 v 90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Archiver -->
+ <g transform="translate(610, 420)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Archiver</text>
+ </g>
+ <path d="M 620,485 l 30,-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 690,455 l 30, 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Vacuum -->
+ <g transform="translate(135, 380)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">AutoVacuum</text>
+ <path d="M 5,0 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <!-- Log Writer -->
+ <g transform="translate(135, 430)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Log Writer</text>
+ </g>
+
+ <!-- Stats Collector -->
+ <g transform="translate(290, 370)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Stats Collector</text>
+ </g>
+
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g transform="translate(145, 490)">
+ <use xlink:href="#disc" />
+ <text x="35" y="45" class="text_normal">Log</text>
+ <text x="20" y="60" class="text_small">text lines,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+ <path d="M 195,465 v 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(410, 490)">
+ <use xlink:href="#disc" />
+ <text x="10" y="40" class="text_normal">Heap and</text>
+ <text x="25" y="55" class="text_normal">Index</text>
+ <text x="15" y="70" class="text_small">binary blocks,</text>
+ <text x="30" y="80" class="text_small">random</text>
+ </g>
+ <path d="M 450,485 v -135" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(295, 420)">
+ <use xlink:href="#note_170x50" />
+ <text x="5" y="15" class="text_comment">Read heap and index</text>
+ <text x="5" y="30" class="text_comment">pages and transfer</text>
+ <text x="5" y="45" class="text_comment">them to shared_buffers</text>
+ </g>
+
+ <g transform="translate(550, 490)">
+ <use xlink:href="#disc" />
+ <text x="30" y="45" class="text_normal">WAL</text>
+ <text x="10" y="60" class="text_small">binary records,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+
+ <g transform="translate(690, 490)">
+ <use xlink:href="#disc" />
+ <text x="16" y="45" class="text_normal">Archived</text>
+ <text x="36" y="60" class="text_normal">WAL</text>
+ </g>
+
+ <!-- boarder between client and server side -->
+ <path d="M 110,20 v 550" stroke="black" fill="none" />
+ <g transform="translate(123, 190) rotate(90)">
+ <use xlink:href="#note_200x20" />
+ <text class="text_comment" x="10" y ="15">Via TCP/IP or socket</text>
+ </g>
+
+ <!-- right side -->
+ <g transform="translate(850, 0) rotate(90)">
+ <text class="text_big" x="95">RAM</text>
+ <text class="text_big" x="250">PROCESSES</text>
+ <text class="text_big" x="500">FILES</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink-svgo.svg b/doc/src/sgml/images/wraparound-ink-svgo.svg
new file mode 100644
index 0000000000..9882d2be23
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink-svgo.svg
@@ -0,0 +1,40 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="280" viewBox="0 0 850 280">
+ <title>
+ Cyclic usage of XIDs
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="370" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ Cyclic usage of XIDs modulo 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan>
+ </text>
+ <g fill="none" transform="translate(170 150)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_095" startOffset="30.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="30%">(1)</textPath> <textPath xlink:href="#Path_095" startOffset="45.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(2)</textPath> <textPath xlink:href="#Path_095" startOffset="50.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="50%">(3)</textPath> <textPath xlink:href="#Path_095" startOffset="62.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="62%">(4)</textPath>
+ </text>
+ </g>
+ <g class="text_normal">
+ <text transform="translate(400 130)">
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25" transform="translate(400 130)">
+ 1: oldest <tspan font-weight="700">active</tspan> xid (pg_stat_activity.backend_xmin)
+ </text>
+ <text y="50" transform="translate(400 130)">
+ 2: xmin of one row version
+ </text>
+ <text y="75" transform="translate(400 130)">
+ 3: xmax of the same row version
+ </text>
+ <text y="100" transform="translate(400 130)">
+ 4: jungest xid (txid_current)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink.svg b/doc/src/sgml/images/wraparound-ink.svg
new file mode 100644
index 0000000000..a9c51f4e43
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="280px"
+ viewBox="0 0 850 280"
+ id="svg1072"
+ sodipodi:docname="wraparound-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata1076">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Cyclic usage of XIDs</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1193"
+ inkscape:window-height="788"
+ id="namedview1074"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="140"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg1072" />
+ <title
+ id="title1009">Cyclic usage of XIDs</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style1011">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs1016">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect1018" />
+ <text
+ class="text_big"
+ x="370"
+ y="40"
+ id="text1024">Cyclic usage of XIDs modulo 2
+ <tspan
+ dy="-5"
+ id="tspan1020">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1022">32</tspan>
+</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 150)"
+ id="g1052">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle1026" />
+ <text
+ class="text_normal"
+ id="text1050">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath1028">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath1030">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath1032">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="30.5%"
+ id="textPath1034">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="30%"
+ id="textPath1036">(1)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="45.5%"
+ id="textPath1038">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath1040">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="50.5%"
+ id="textPath1042">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="50%"
+ id="textPath1044">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="62.5%"
+ id="textPath1046">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="62%"
+ id="textPath1048">(4)</textPath>
+ </text>
+ </g>
+ <g
+ class="text_normal"
+ transform="translate(400 130)"
+ id="g1070">
+ <text
+ id="text1058">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan1054">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1056">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text1062">1: oldest <tspan
+ style="font-weight:bold"
+ id="tspan1060">active</tspan>
+ xid (pg_stat_activity.backend_xmin)</text>
+ <text
+ y="50"
+ id="text1064">2: xmin of one row version</text>
+ <text
+ y="75"
+ id="text1066">3: xmax of the same row version</text>
+ <text
+ y="100"
+ id="text1068">4: jungest xid (txid_current)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-raw.svg b/doc/src/sgml/images/wraparound-raw.svg
new file mode 100644
index 0000000000..9406f52970
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-raw.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="280px"
+ viewBox="0 0 850 280" >
+
+ <title>Cyclic usage of XIDs</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="370" y="40">Cyclic usage of XIDs modulo 2
+ <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan></text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 150)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_095" startOffset="30.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="30%" >(1)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="45.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(2)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="50.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="50%" >(3)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="62.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="62%" >(4)</textPath>
+ </text>
+ </g>
+
+ <g class="text_normal" transform="translate(400 130)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: oldest <tspan style="font-weight:bold">active</tspan> xid (pg_stat_activity.backend_xmin)</text>
+ <text y="50">2: xmin of one row version</text>
+ <text y="75">3: xmax of the same row version</text>
+ <text y="100">4: jungest xid (txid_current)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index c41ce9499b..7913f45897 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -62,6 +62,7 @@ break is not needed in a wider output rendering.
&start;
&query;
&advanced;
+ &architecture;
</part>
diff --git a/doc/src/sgml/query.sgml b/doc/src/sgml/query.sgml
index c0889743c4..b1906c6e36 100644
--- a/doc/src/sgml/query.sgml
+++ b/doc/src/sgml/query.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/query.sgml -->
<chapter id="tutorial-sql">
- <title>The <acronym>SQL</acronym> Language</title>
+ <title>Fundamentals of the <acronym>SQL</acronym> Language</title>
<sect1 id="tutorial-sql-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml
index 2a47f69079..9a703702f1 100644
--- a/doc/src/sgml/start.sgml
+++ b/doc/src/sgml/start.sgml
@@ -53,7 +53,7 @@
<sect1 id="tutorial-arch">
- <title>Architectural Fundamentals</title>
+ <title>Client/Server Model</title>
<para>
Before we proceed, you should understand the basic
@@ -68,34 +68,55 @@
client/server model. A <productname>PostgreSQL</productname>
session consists of the following cooperating processes
(programs):
+ </para>
- <itemizedlist>
- <listitem>
- <para>
- A server process, which manages the database files, accepts
- connections to the database from client applications, and
- performs database actions on behalf of the clients. The
- database server program is called
- <filename>postgres</filename>.
- <indexterm><primary>postgres</primary></indexterm>
- </para>
- </listitem>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A process at the server site with the name
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ <indexterm><primary>postgres</primary></indexterm>
+ It accepts connection requests from client applications, starts
+ (<quote>forks</quote>) a new <glossterm linkend="glossary-backend">
+ Backend process</glossterm> for each of them, and passes
+ the connection to it. From that point on, the client and the new
+ <firstterm>Backend process</firstterm>
+ communicate directly without intervention by the original
+ <firstterm>postgres</firstterm> process. Thus, the
+ <firstterm>postgres</firstterm> process is always running, waiting
+ for new client connections, whereas clients and associated
+ <firstterm>Backend processes</firstterm> come and go.
+ (All of this is of course invisible to the user. We only mention it
+ here for completeness.)
+ </para>
+ </listitem>
- <listitem>
- <para>
- The user's client (frontend) application that wants to perform
- database operations. Client applications can be very diverse
- in nature: a client could be a text-oriented tool, a graphical
- application, a web server that accesses the database to
- display web pages, or a specialized database maintenance tool.
- Some client applications are supplied with the
- <productname>PostgreSQL</productname> distribution; most are
- developed by users.
- </para>
- </listitem>
+ <listitem>
+ <para>
+ A group of processes at the server site, the <glossterm
+ linkend="glossary-instance">instance</glossterm>, to which also the
+ <firstterm>postgres</firstterm> process belongs. Their duties are
+ handling of central, common database activities like file access,
+ vacuum, <glossterm linkend="glossary-checkpoint">checkpoints</glossterm>,
+ replication, and more. The mentioned <firstterm>Backend processes</firstterm>
+ delegate those actions to the <firstterm>instance</firstterm>.
+ </para>
+ </listitem>
- </itemizedlist>
- </para>
+ <listitem>
+ <para>
+ The user's client (frontend) application that wants to perform
+ database operations. Client applications can be very diverse
+ in nature: a client could be a text-oriented tool, a graphical
+ application, a web server that accesses the database to
+ display web pages, or a specialized database maintenance tool.
+ Some client applications are supplied with the
+ <productname>PostgreSQL</productname> distribution; most are
+ developed by users.
+ </para>
+ </listitem>
+
+ </itemizedlist>
<para>
As is typical of client/server applications, the client and the
@@ -106,18 +127,6 @@
file name) on the database server machine.
</para>
- <para>
- The <productname>PostgreSQL</productname> server can handle
- multiple concurrent connections from clients. To achieve this it
- starts (<quote>forks</quote>) a new process for each connection.
- From that point on, the client and the new server process
- communicate without intervention by the original
- <filename>postgres</filename> process. Thus, the
- master server process is always running, waiting for
- client connections, whereas client and associated server processes
- come and go. (All of this is of course invisible to the user. We
- only mention it here for completeness.)
- </para>
</sect1>
On 2 Jun 2020, at 17:01, Jürgen Purtz <juergen@purtz.de> wrote:
In comparison with to previous patch this one contains:
- Position and title changed to reflect its intention and importance.
- A <note> delimits VACUUM basics from details. This is done because I cannot find another suitable place for such a summarizing description.
- Three additional sub-chapters.
This patch no longer applies, due to conflicts in start.sgml, can you please
submit a rebased version?
cheers ./daniel
On 12.07.20 22:45, Daniel Gustafsson wrote:
This patch no longer applies, due to conflicts in start.sgml, can you please
submit a rebased version?
ok. but I need some days. juergen
Which version is this application for?
I tried for v12 and v13 Beta, both failed.
Regards,
Naresh G
On Mon, Jul 13, 2020 at 11:45 AM Jürgen Purtz <juergen@purtz.de> wrote:
Show quoted text
On 12.07.20 22:45, Daniel Gustafsson wrote:
This patch no longer applies, due to conflicts in start.sgml, can you
please
submit a rebased version?
ok. but I need some days. juergen
On 13 Jul 2020, at 14:20, Naresh gandi <naresh5310@gmail.com> wrote:
(please avoid top-posting)
Which version is this application for?
I tried for v12 and v13 Beta, both failed.
Unless being a bugfix, all patches are only considered against the main
development branch in Git. As this is new material, it would be for v14.
cheers ./daniel
On 12.07.20 22:45, Daniel Gustafsson wrote:
This patch no longer applies, due to conflicts in start.sgml, can you please
submit a rebased version?cheers ./daniel
New version attached.
--
Jürgen Purtz
Attachments:
0005-architecture.patchtext/x-patch; charset=UTF-8; name=0005-architecture.patchDownload
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
index f6c4627c3e..be04972bd7 100644
--- a/doc/src/sgml/advanced.sgml
+++ b/doc/src/sgml/advanced.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/advanced.sgml -->
<chapter id="tutorial-advanced">
- <title>Advanced Features</title>
+ <title>Advanced SQL Features</title>
<sect1 id="tutorial-advanced-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
new file mode 100644
index 0000000000..1a2117f42a
--- /dev/null
+++ b/doc/src/sgml/architecture.sgml
@@ -0,0 +1,1549 @@
+<!-- doc/src/sgml/architecture.sgml -->
+
+ <chapter id="tutorial-architecture">
+ <title>Architectural and implementational Cornerstones</title>
+
+ <para>
+ Every DBMS implements basic strategies to achieve a fast and
+ robust system. This chapter provides an overview of what
+ techniques <productname>PostgreSQL</productname> uses to
+ reach this aim.
+ </para>
+
+ <sect1 id="tutorial-ram-proc-file">
+ <title>Collaboration of Processes, RAM, and Files</title>
+ <para>
+ As is a matter of course, in a client/server architecture
+ clients do not have direct access to the database. Instead,
+ they merely send requests to the server-side and receive
+ according information from there. In the case of
+ <productname>PostgreSQL</productname>, at the server-side
+ there is one process per client, the so-called
+ <glossterm linkend="glossary-backend">Backend process</glossterm>.
+ It acts in close cooperation with the
+ <glossterm linkend="glossary-instance">Instance</glossterm> which
+ is a group of tightly coupled other server-side processes plus a
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>
+ area.
+ </para>
+
+ <para>
+ At start time, an instance is initiated by the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>
+ process.
+ It loads the configuration files, allocates the
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>,
+ and starts the comprehensive network of processes:
+ <glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
+ <glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
+ <glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
+ <glossterm linkend="glossary-wal-archiver">WAL Archiver</glossterm>,
+ <glossterm linkend="glossary-autovacuum">Autovacuum processes</glossterm>,
+ <glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
+ <glossterm linkend="glossary-logger">Logger</glossterm>, and more.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes
+ the main aspects of their collaboration.
+ </para>
+
+ <figure id="tutorial-ram-proc-file-figure">
+ <title>Architecture</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ Whenever a client application tries to connect to a
+ <glossterm linkend="glossary-database">database</glossterm>,
+ this request is handled in a first step by the <firstterm>
+ Postgres process</firstterm>. It checks the authorization,
+ starts a new <firstterm>Backend process</firstterm>,
+ and instructs the client application to connect to it. All
+ further client requests go to this process and are handled
+ by it.
+ </para>
+
+ <para>
+ Client requests (SELECT, UPDATE, ...) usually lead to the
+ necessity to read or write some data. In a first attempt
+ the client's <firstterm>Backend process</firstterm> tries
+ to get the information out of <firstterm>Shared
+ Memory</firstterm>. This <firstterm>Shared
+ Memory</firstterm> is a mirror of parts of the
+ <glossterm linkend="glossary-heap">heap</glossterm> and
+ <glossterm linkend="glossary-index">index</glossterm> files.
+ Because files are often larger than memory, it's likely that
+ the desired information is not (completely) available
+ in the RAM. In this case the <firstterm>Backend process</firstterm>
+ must transfer additional file pages to
+ <firstterm>Shared Memory</firstterm>. Files are physically
+ organized in pages. Every transfer between files and
+ RAM is performed in units of complete pages. Such transfers
+ don't change the size or layout of pages.
+ </para>
+
+ <para>
+ Reading file pages is notedly slower than reading
+ RAM. This is the primary motivation for the existence of
+ <firstterm>Shared Memory</firstterm>. As soon as one
+ of the <firstterm>Backend processes</firstterm> has
+ read pages into memory, those pages are available for all
+ other <firstterm>Backend processes</firstterm> for direct
+ access in RAM.
+ </para>
+
+ <para>
+ <firstterm>Shared Memory</firstterm> is limited in size.
+ Sooner or later, it becomes necessary to overwrite old RAM
+ pages. As long as the content of such pages hasn't
+ changed, this is not a problem. But in
+ <firstterm>Shared Memory</firstterm> also write
+ actions take place
+ — performed by any of the <firstterm>Backend
+ processes</firstterm> (or an
+ <glossterm linkend="glossary-autovacuum">autovacuum process</glossterm>,
+ or other processes). Such modified pages are called
+ <firstterm>dirty pages</firstterm>.
+ Before <firstterm>dirty pages</firstterm> can be overwritten,
+ they must be written back to disk. This is a two-step process.
+ </para>
+
+ <para>
+ First, whenever the content of a page changes, a
+ <glossterm linkend="glossary-wal-record">WAL record</glossterm>
+ is created out
+ of the delta-information (difference between old and
+ new content) and stored in another area of the
+ <firstterm>Shared Memory</firstterm>. These
+ <firstterm>WAL records</firstterm> are read by the
+ <firstterm>WAL Writer</firstterm> process,
+ which runs in parallel to the <firstterm>Backend
+ processes</firstterm> and all other processes of
+ the <firstterm>Instance</firstterm>. It writes
+ the continuously arising <firstterm>WAL records</firstterm> to
+ the end of the current
+ <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
+ Because this writing is sequential, it is much
+ faster than the more or less random access
+ to data files with <firstterm>heap</firstterm>
+ and <firstterm>index</firstterm> information.
+ As mentioned, this WAL-writing happens
+ in an independent process. Nevertheless, all
+ <firstterm>WAL records</firstterm> created out of one
+ <firstterm>dirty page</firstterm> must be transferred
+ to disk before the <firstterm>dirty page</firstterm>
+ itself can be transferred to disk.
+ </para>
+
+ <para>
+ Second, the transfer of <firstterm>dirty buffers</firstterm>
+ from <firstterm>Shared Memory</firstterm> to files must
+ take place. This is the primary duty of the
+ <firstterm>Background Writer</firstterm> process. Because
+ I/O activities can block other processes significantly,
+ it starts periodically and acts only for a short period.
+ Doing so, his expensive I/O activities are spread over
+ time, avoiding huge I/O peaks. Also, the <firstterm>
+ Checkpointer</firstterm> process transfers
+ <firstterm>dirty buffers</firstterm> to files —
+ see next paragraph.
+ </para>
+
+ <para>
+ The <firstterm>Checkpointer</firstterm> has a special
+ duty. As its name suggests, it has to create
+ <firstterm>Checkpoints</firstterm>. Such a
+ <glossterm linkend="glossary-checkpoint">Checkpoint</glossterm>
+ is a point in time when all older <firstterm>dirty buffers</firstterm>,
+ all older <firstterm>WAL records</firstterm>, and
+ finally a special <firstterm>Checkpoint record</firstterm>
+ have been written and flushed to disk.
+ After a <firstterm>Checkpoint</firstterm>,
+ data files and <firstterm>WAL files</firstterm> are in sync.
+ In case of a recovery (after a crash of the instance)
+ it is known that the information of all
+ <firstterm>WAL records</firstterm> preceding
+ the last <firstterm>Checkpoint record</firstterm>
+ is already integrated into the data files. This
+ speeds up a possibly occurring recovery.
+ </para>
+
+ <para>
+ As a result of data changes,
+ <firstterm>WAL records</firstterm> arise and get written
+ to <firstterm>WAL files</firstterm>.
+ Those <firstterm>WAL files</firstterm> — in combination with
+ a previously taken <firstterm>Base Backup</firstterm> —
+ are necessary to restore a database after a crash of the
+ disk, where data files have been stored. Therefore it is
+ recommended to transfer a copy of the <firstterm>
+ WAL files</firstterm>
+ to a second, independent place. The purpose of the
+ <firstterm>WAL Archiver</firstterm> process is to perform
+ this copy action.
+ </para>
+
+ <para>
+ The <glossterm linkend="glossary-stats-collector">Stats Collector</glossterm>
+ collects counters about accesses to <firstterm>SQL
+ objects</firstterm> like tables, rows, indexes, pages,
+ and more. It stores the obtained information in system
+ tables.
+ </para>
+
+ <para>
+ The <glossterm linkend="glossary-logger">Logger</glossterm> writes
+ text lines about serious and less serious events which can happen
+ during database access, e.g., wrong password, no permission,
+ long-running queries, ... .
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-cluster-db-schema">
+ <title>The logical Perspective: Cluster, Database, Schema</title>
+
+ <para>
+<!-- TODO: Link to cluster -->
+ On a <glossterm linkend="glossary-server">Server</glossterm>
+ exists one or more <glossterm linkend="glossary-instance">Cluster</glossterm>,
+ each of them contains three or more
+ <glossterm linkend="glossary-database">databases</glossterm>, each
+ database contains many <glossterm linkend="glossary-schema">schemas</glossterm>,
+ a schema contains <glossterm linkend="glossary-table">tables</glossterm>,
+ <glossterm linkend="glossary-view">views</glossterm>, and a lot of other objects.
+ Each <firstterm>table</firstterm> or <firstterm>view</firstterm>
+ belongs to a single <firstterm>schema</firstterm>; they cannot
+ belong to another <firstterm>schema</firstterm>. The same is
+ true for the schema/database and database/cluster relation.
+ <xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
+ this hierarchy.
+ </para>
+
+ <figure id="tutorial-cluster-db-schema-figure">
+ <title>Cluster, Database, Schema</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ A <firstterm>Cluster</firstterm> is the outer container for a
+ collection of databases. Clusters are created by the command
+ <xref linkend="app-initdb"/>.
+ </para>
+
+ <para>
+ <literal>template0</literal> is the very first
+ <firstterm>database</firstterm> of any
+ <firstterm>cluster</firstterm>. C-routines create
+ <literal>template0</literal> during the initialization phase of
+ the <firstterm>cluster</firstterm>.
+ In a second step, <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal>, and finally
+ <literal>postgres</literal> is generated as a copy of
+ <literal>template1</literal>. All other
+ <glossterm linkend="app-createdb">new databases</glossterm>
+ of this <firstterm>cluster</firstterm>,
+ such as <literal>my_db</literal>, are also copied from
+ <literal>template1</literal>. Due to the unique
+ role of <literal>template0</literal> as the pristine origin
+ of all other <firstterm>databases</firstterm>, no client
+ can connect to it.
+ </para>
+
+ <para>
+ Every database contains <glossterm linkend="glossary-schema">
+ schemas</glossterm>, and
+ <firstterm>schemas</firstterm> contain the other
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>.
+ <firstterm>Schemas</firstterm> are namespaces for
+ their <firstterm>SQL objects</firstterm> and ensure — with one
+ exception — that within their scope names are used only once across all
+ types of <firstterm>SQL objects</firstterm>. E.g., it is not possible
+ to have a table <literal>employee</literal> and a view
+ <literal>employee</literal> within the same
+ <firstterm>schema</firstterm>. But it is possible to have
+ two tables <literal>employee</literal> in different
+ <firstterm>schemas</firstterm>. In this case, the two tables
+ are separate objects and independent of each
+ other. The only exception to this cross-type uniqueness is that
+ <glossterm linkend="glossary-unique-constraint">unique constraints
+ </glossterm> and the according <firstterm>unique index</firstterm>
+ use the same name.
+ </para>
+
+ <para>
+ Some <firstterm>schemas</firstterm> are predefined.
+ <literal>public</literal> acts as the default
+ <firstterm>schema</firstterm> and contains all such
+ <firstterm>SQL objects</firstterm>, which are created
+ within <literal>public</literal> or without using any schema
+ name. <literal>public</literal> shall not contain user-defined
+ <firstterm>SQL objects</firstterm>. Instead, it is recommended to
+ create a separate <firstterm>schema</firstterm> that
+ holds individual objects like application-specific tables or
+ views. <literal>pg_catalog</literal> is a schema for all tables
+ and views of the <glossterm linkend="glossary-system-catalog">
+ System Catalog</glossterm>.
+ <literal>information_schema</literal> is a schema for several
+ tables and views of the <firstterm>System Catalog</firstterm>
+ in a way that conforms to the SQL standard.
+ </para>
+
+ <para>
+ There are a lot of different <firstterm>SQL object</firstterm>
+ types: <firstterm>database, schema, table, view, materialized
+ view, index, constraint, sequence, function, procedure,
+ trigger, role, data type, operator, tablespace, extension,
+ foreign data wrapper</firstterm>, and more. A few of them, the
+ <firstterm>Global SQL Objects</firstterm>,
+ are outside of the strict hierarchy:
+ All database names, all tablespace names, and all role names
+ are automatically known and available throughout the
+ <firstterm>cluster</firstterm>, independent from
+ the database or schema in which they where defined originally.
+ <xref linkend="tutorial-internal-objects-hierarchy-figure"/>
+ shows the relation between the object types.
+ </para>
+
+ <figure id="tutorial-internal-objects-hierarchy-figure">
+ <title>Hierarchy of Internal Objects</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="720px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect1>
+
+ <sect1 id="tutorial-directories">
+ <title>The physical Perspective: Directories and Files</title>
+
+ <para>
+ <productname>PostgreSQL</productname> organizes long-lasting
+ data as well as volatile state information about transactions
+ or replication actions in the file system. Every
+ <firstterm>Cluster</firstterm> has its root directory
+ somewhere in the file system. In many cases, the environment
+ variable <literal>PGDATA</literal> points to this directory.
+ The example of the survey shown in
+ <xref linkend="tutorial-directories-figure"/> uses
+ <literal>data</literal> as the name of this root directory.
+ </para>
+
+ <figure id="tutorial-directories-figure">
+ <title>Directory Structure</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ <literal>data</literal> contains many subdirectories and
+ some files, all of which are necessary to store long-lasting
+ as well as temporary data. The following paragraphs
+ describe the files and subdirectories in
+ <literal>data</literal>.
+ </para>
+
+ <para>
+ <literal>base</literal> is a subdirectory in which one
+ subdirectory per <firstterm>database</firstterm> exists.
+ The names of those subdirectories consist of numbers.
+ These are the internal
+ <firstterm>Object Identifiers (OID)</firstterm>, which are
+ numbers to identify the database definition in the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ </para>
+
+ <para>
+ Within the <firstterm>database</firstterm>-specific
+ subdirectories, there are many files: one or more for
+ every table and every index to store <firstterm>heap</firstterm>
+ and <firstterm>index</firstterm> data. Those files are
+ accompanied by files for the
+ <link linkend="storage-fsm">Free Space Maps</link>
+ (extension <literal>_fsm</literal>) and
+ <link linkend="storage-vm">Visibility Maps</link>
+ (extension <literal>_vm</literal>), which contain optimization information.
+ </para>
+
+ <para>
+ Another prominent subdirectory is <literal>global</literal>.
+ In analogy to the <firstterm>database</firstterm>-specific
+ subdirectories, there are files containing information about
+ <glossterm linkend="glossary-sql-object">Global SQL objects</glossterm>.
+ One type of such <firstterm>Global Objects</firstterm> are
+ <firstterm>tablespaces</firstterm>. In
+ <literal>global</literal> there is information about
+ the <firstterm>tablespaces</firstterm>, not the
+ <firstterm>tablespaces</firstterm> themselves.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_wal</literal> contains the
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
+ They arise and grow parallel to data changes in the
+ <firstterm>cluster</firstterm> and remain alive as long as
+ they are required for recovery, archiving, or replication.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_xact</literal> contains
+ information about the status of each transaction
+ (IN_PROGRESS, COMMITTED, ABORTED, or SUB_COMMITTED).
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal>, there are symbolic links
+ that point to directories containing such<firstterm>
+ SQL objects</firstterm> that are created within
+ <firstterm>tablespaces</firstterm>.
+ </para>
+
+ <para>
+ In the root directory <literal>data</literal>
+ there are also some files. In many cases, the configuration
+ files of this <firstterm>cluster</firstterm> are stored
+ here. As long as the <firstterm>instance</firstterm>
+ is up and running, the file
+ <literal>postmaster.pid</literal> exists here
+ and contains the ID (pid) of the
+ <firstterm>Postmaster</firstterm> process which
+ has started the instance.
+ </para>
+
+ <para>
+ For more details about the physical implementation
+ of database objects, see <xref linkend="storage"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-mvcc">
+ <title>MVCC — Multiversion Concurrency Control</title>
+
+ <para>
+ In most cases, <productname>PostgreSQL</productname> based applications
+ support many clients at the same time. Therefore, it is necessary to
+ protect concurrently running requests from unwanted overwriting
+ of other's data as well as from reading inconsistent data. Imagine an
+ online shop offering the last copy of an article. Two clients show the
+ article at their user interface. After a while, but at the same time,
+ both users decide to put it to their shopping cart or even to buy it.
+ Both have seen the article, but only one can be allowed to get it.
+ The database must bring the two requests in a row, permit the access
+ to one of them, block the other, and inform this one about the
+ situation that the data was changed by a different process.
+ </para>
+
+ <para>
+ A first approach to implement protections against concurrent
+ accesses to the same data may be the locking of critical
+ rows. There are two main categories of such techniques:
+ <emphasis>Optimistic Concurrency Control</emphasis> (OCC)
+ and <emphasis>Two Phase Locking</emphasis> (2PL).
+ <productname>PostgreSQL</productname> implements the more
+ sophisticated technique <firstterm>Multiversion Concurrency
+ Control</firstterm> (MVCC). The crucial advantage of MVCC
+ over other technologies gets evident in multiuser OLTP
+ environments with a massive number of concurrent write
+ actions. There, MVCC generally performs better than solutions
+ using locks. In a <productname>PostgreSQL</productname>
+ database reading never blocks writing and writing never
+ blocks reading, even in the strictest level of transaction
+ isolation.
+ </para>
+
+ <para>
+ Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
+ a new version of the same row when any data-change takes place. To
+ distinguish between these versions as well as to track the timeline
+ of the row, each of the versions contains, in addition to their user-defined
+ columns, two special system columns, which are not visible
+ for the usual <command>SELECT * FROM ...</command> command.
+ The column <literal>xmin</literal> contains the transaction ID (xid)
+ of the transaction, which creates this version of the row. Accordingly,
+ <literal>xmax</literal> contains the xid of the transaction, which has
+ deleted this version, respectively a zero, if the version is not
+ deleted. You can read both with the command
+ <command>SELECT xmin, xmax, * FROM ... </command>.
+ </para>
+
+ <para>
+ When we speak about transaction IDs, you need to know that xids are like
+ sequences. Every new transaction receives the next number as its ID.
+ Therefore, this flow of xids represents the flow of transaction
+ start events over time. But keep in mind that xids are independent of
+ any time measurement — in milliseconds or whatever. If you dive
+ deeper into <productname>PostgreSQL</productname>, you will recognize
+ parameters with names such as 'xxx_age'. Despite their names,
+ these '_age' parameters do not specify a period of time but represent
+ a certain number of transactions, e.g., 100 million.
+ </para>
+
+ <para>
+ Please note that the description in this chapter simplifies the situation
+ by omitting details. When many transactions are running simultaneously,
+ things can get very complicated. Sometimes they get aborted via
+ ROLLBACK immediately or after a lot of other activities, sometimes
+ a single row is involved in more than one transaction, sometimes
+ a client crashes, sometimes the sequence of xids restarts
+ from zero, ... . Therefore, every version of a row contains more
+ system columns and flags, not only <literal>xmin</literal>
+ and <literal>xmax</literal>.
+ </para>
+
+ <para>
+ So, what's going on in detail when write accesses take place?
+ <xref linkend="tutorial-mvcc-figure"/> shows details concerning
+ <literal>xmin</literal>, <literal>xmax</literal>, and user data.
+ </para>
+
+ <figure id="tutorial-mvcc-figure">
+ <title>Multiversion Concurrency Control</title>
+ <mediaobject>
+ <imageobject role="html">
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ An <command>INSERT</command> command creates the first
+ version of a row. Besides its user data <literal>'x'</literal>,
+ this version contains the ID of the creating transaction
+ <literal>123</literal> in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ <literal>xmin</literal> indicates that the version
+ exists since transaction <literal>123</literal> and
+ <literal>xmax</literal> that it is currently not deleted.
+ </para>
+
+ <para>
+ Somewhat later, transaction <literal>135</literal>
+ executes an <command>UPDATE</command> of this row by
+ changing the user data from <literal>'x'</literal> to
+ <literal>'y'</literal>. According to the MVCC principles,
+ the data in the old version of the row does not change!
+ The value <literal>'x'</literal> keeps as it was before.
+ Only <literal>xmax</literal> changes to <literal>135</literal>.
+ Now, this version is treated as valid exclusively for
+ transactions with xids from <literal>123</literal> to
+ <literal>134</literal>. As a substitute for the non-occurring
+ data change in the old version, the <command>UPDATE</command>
+ creates a new version of the row with its xid in
+ <literal>xmin</literal>, <literal>0</literal> in
+ <literal>xmax</literal>, and <literal>'y'</literal> in the
+ user data (plus all the other user data from the old version).
+ This version is now valid for all coming transactions.
+ </para>
+
+ <para>
+ All subsequent <command>UPDATE</command> commands behave
+ in the same way as the first one: they put their xid to
+ <literal>xmax</literal> of the current version, create
+ the next version with their xid in <literal>xmin</literal>,
+ <literal>0</literal> in <literal>xmax</literal>, and the
+ new user data.
+ </para>
+
+ <para>
+ Finally, a row may be deleted by a <command>DELETE</command>
+ command. Even in this case, all versions of the row keep as
+ before. Nothing is thrown away so far! Only <literal>xmax</literal>
+ of the last version changes to the xid of the <command>DELETE</command>
+ transaction, which indicates that it is only valid for
+ transactions with xids older than its own (from
+ <literal>142</literal> to <literal>820</literal> in this
+ example).
+ </para>
+
+ <para>
+ In summary, the MVCC technology creates more and more versions
+ of the same row in the table's heap file and leaves them there,
+ even with a <command>DELETE</command> command. The youngest
+ version is relevant for all future transactions. But the
+ system must also preserve some of the older ones for a
+ certain amount of time because the possiblility exists that
+ they are or could become relevant for any of the pending
+ transactions. Over time, also the older ones get out of scope
+ for ALL transactions and therefore become unnecessary.
+ Nevertheless, they exist physically on the disk and occupy
+ space.
+ </para>
+
+ <para>
+ Please keep in mind:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> and <literal>xmax</literal> indicate the range from where to where
+ row versions are valid (visible) for transactions.
+ This range doesn't imply any direct temporal meaning;
+ the sequence of xids reflects only the sequence of
+ transaction begin events. As
+ xids grow, old row versions get out of scope over time.
+ If an old row version is no longer valid for ALL existing
+ transactions, it's called <firstterm>dead</firstterm>. The
+ space occupied by the sum of all dead row versions is
+ called <firstterm>bloat</firstterm>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Internally, an <command>UPDATE</command> command acts in the
+ same way as a <command>DELETE</command> command, followed by
+ an <command>INSERT</command> command.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Nothing gets wiped away — with the consequence that the database
+ occupies more and more disk space. It is obvious that
+ this behavior has to be automatically corrected in some
+ way. The next chapter explains how AUTOVACUUM fulfills
+ this task.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ </sect1>
+
+ <sect1 id="tutorial-vacuum">
+ <title>Vacuum</title>
+
+ <para>
+ As we have seen in the previous chapter, the database tends to occupy
+ more and more disk space, the <firstterm>bloat</firstterm>.
+ This chapter explains how the SQL command
+ <firstterm>VACUUM</firstterm> and the automatically running
+ <firstterm>AUTOVACUUM</firstterm> processes clear the situation
+ by eliminating <firstterm>bloat</firstterm>.
+ </para>
+
+ <note>
+ <para>
+ <firstterm>AUTOVACUUM</firstterm> runs automatically by
+ default. Its default parameters as well as such for
+ <firstterm>VACUUM</firstterm> fits well for most standard
+ situations. Therefore a novice database manager can
+ easily skip the rest of this chapter, which explains
+ a lot of details.
+ </para>
+ </note>
+
+ <para>
+ Client processes can issue the SQL command VACUUM at arbitrary
+ points in time. DBAs do this when they recognize special situations,
+ or they start it in batch jobs, which run periodically.
+ AUTOVACUUM processes run as part of the
+ <link linkend="glossary-instance">Instance</link> at the server.
+ There is a constantly running AUTOVACUUM daemon. He permanently
+ controls the state of all databases based on values that are
+ collected by the <link linkend="glossary-stats-collector">
+ Statistics Collector</link> and starts
+ AUTOVACUUM processes whenever he detects certain situations.
+ Thus, it's a dynamic behavior of <productname>PostgreSQL</productname>
+ with the intention to tidy up — not always, but whenever it
+ is appropriate.
+ </para>
+
+ <para>
+ VACUUM, as well as AUTOVACUUM, don't just eliminate bloat.
+ They perform additional tasks for minimizing future
+ I/O activities of themselves as well as of other processes.
+ This extra work can be done in a very efficient way
+ since in most cases the expensive physical access to pages
+ has taken place anyway to eliminate bloat.
+ The additional operations are:
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <firstterm>Freeze</firstterm>: Mark the youngest row version
+ as frozen. This means that the version
+ is always treated as valid (visible) independent from
+ the <firstterm>wraparound problematic</firstterm> (see below).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <firstterm>Visibility Map</firstterm> and
+ <firstterm>Free Space Map</firstterm>: Log information about
+ the state of the handled pages in two additional files, the
+ Visibility Map and the Free Space Map.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <emphasis>Statistics</emphasis>: Collect statistics about the
+ number of rows per table, the distribution of values, and so on,
+ as the basis for query planner's decision making.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ The eagerness — you can call it 'aggressivity' — of the
+ operations <emphasis>eliminating bloat</emphasis> and
+ <emphasis>freeze</emphasis> is controlled by configuration
+ parameters, runtime flags, and in extreme situations by
+ themselves. Because vacuum operations typically are I/O
+ intensive, which can hinder other activities, AUTOVACUUM
+ avoids performing many vacuum operations in bulk. Instead,
+ it carries out many small actions with time gaps in between.
+ The SQL command VACUUM runs immediately without any
+ time gaps.
+ </para>
+
+ <bridgehead renderas="sect2">Eliminate Bloat</bridgehead>
+
+ <para>
+ To determine which of the row versions are superfluous, the
+ elimination operation must evaluate xmax against several criteria
+ which all must apply:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ xmax must be different from zero because a value of zero
+ indicates that the row version is still valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ xmax must contain an xid which is older than the oldest xid of all
+ currently running transactions (min(pg_stat_activity.backend_xmin)).
+ This criterion guarantees that no existing or upcoming transaction
+ will have read or write access to this row version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of xmax must be committed. If it was rollback-ed,
+ this row version is treated as valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there is the situation that the row version is part of
+ multiple transactions, special care and some more actions
+ must be taken, see: <xref linkend="vacuum-for-multixact-wraparound"/>.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ After the vacuum operation detects a superfluous row version, it
+ marks its space as free for future use of writing
+ actions. Only in rare situations (or in the case of VACUUM FULL),
+ this space is released to the operating system. In most cases,
+ it keeps occupied by PostgreSQL and will be used by future
+ <command>INSERT</command> or <command>UPDATE</command>
+ commands concerning this row or a completely different one.
+ </para>
+
+ <para>
+ Which actions start the elimination of bloat?
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM in its default format,
+ i.e., without any option. To boost performance, in this and the
+ next case VACUUM does not read and act on all pages of the heap.
+ The Visibility Map, which is very compact and therefore has a small
+ size, contains information about pages, where bloat-candidates might
+ be found. Only such pages are processed.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM with the option
+ FREEZE. (In this case, it undertakes much more actions, see
+ <link linkend="tutorial-freeze">Freeze Row Versions</link>.)
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM with the option FULL.
+ Also, in this mode, the bloat disappears, but the used strategy
+ is very different: In this case, the complete table is copied
+ to a different file skipping all outdated row versions. This
+ leads to a significant reduction of used disk space because
+ the new file contains only the actual data. The old file
+ is deleted.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When an AUTOVACUUM process acts. For optimization
+ purposes, he considers the Visibility Map in the same way as
+ VACUUM. Additionally, he ignores tables with few modifications;
+ see <xref linkend="guc-autovacuum-vacuum-threshold"/>,
+ which defaults to 50 rows and
+ <xref linkend="guc-autovacuum-vacuum-scale-factor"/>,
+ which defaults to 20%.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </para>
+
+ <para>
+ This logic only applies to row versions of the heap. Index entries
+ don't use xmin/xmax. Nevertheless, such index entries, which would
+ lead to outdated row versions, are released accordingly.
+ (??? more explanations ???)
+ </para>
+
+ <para>
+ The above descriptions omit the fact that xids on a real computer
+ have a limited size. They count up in the same way as sequences, and after
+ a certain number of new transactions they are forced to restart
+ from the beginning, which is called <firstterm>wraparound</firstterm>.
+ Therefore the terms 'old transaction' / 'young transaction' does
+ not always correlate with low / hight values of xids. Near to the
+ wraparound point, there are cases where xmin has a higher value
+ than xmax, although their meaning is said to be older than xmax.
+ </para>
+
+ <figure id="tutorial-wraparound-figure">
+ <title>Cyclic usage of XIDs</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2" id="tutorial-freeze">Freeze Row Versions</bridgehead>
+
+ <para>
+ The use of a limited range of IDs for transactions leads
+ to the necessity to restart the sequence sooner or later.
+ This does not only have the rare consequence previously
+ described that sometimes xmin is huger than xmax. The far
+ more critical problem is that whenever the system has
+ to evaluate a WHERE condition, it must decide which row
+ versions are valid (visible) from the perspective of the
+ transaction of this query. If a wraparound couldn't happen,
+ this decision would be relatively easy: the xid
+ must be between xmin and xmax, and the corresponding
+ transactions of xmin and xmax must be committed. However,
+ PostgreSQL has to consider the possibility of wraparounds.
+ Therefore the decision becomes more complex. The general
+ idea of the solution is to use the 'between xmin and xmax'
+ comparison only during the youngest period of the row
+ versions lifetime and afterward replace it with a
+ 'valid forever' flag in its header.
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ In a first step, PostgreSQL divides the complete range of
+ possible xids into two halves with the two split-points
+ 'txid_current' and 'txid_current + 2^31'. The half behind
+ 'txid_current' is considered to represent xids of the
+ 'past' and the half ahead of 'txid_current' those of the
+ 'future'. Those of the 'past' are valid (visible) and those
+ of the 'future' not.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ With each newly created transaction the two split-points
+ move forward. When 'txid_current + 2^31' would reach a
+ row version with xmin equal to that value, it would
+ immediately jump from 'past' to 'future' and would be
+ no longer visible!
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ To avoid this unacceptable extinction of data, the vacuum
+ operation <firstterm>freeze</firstterm> clears the situation
+ long before the split-point is reached. It sets a flag
+ in the header of the row version, which completely eliminates
+ the future use of xmin/xmax and indicates
+ that the version is valid not only in the 'past'-half
+ but also in the 'future'-half as well as in all coming
+ <glossterm linkend="glossary-xid">epochs</glossterm>.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Which row versions can be frozen by the vacuum operation?
+ Again, several criteria must be checked, and all must be met.
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ xmax must be zero because only non-deleted rows can be
+ visible 'forever'.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ xmin must be older than all currently existing transactions.
+ This guarantees that no existing transaction can modify or
+ delete the version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of xmin must be committed.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ At what point in time the freeze operation will take place?
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM with its
+ FREEZE option. In this case, all such pages are
+ processed that are marked in the Visibility Map
+ to potentially have unfrozen rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command VACUUM without any
+ option but finds that there are xids older than
+ <xref linkend="guc-vacuum-freeze-table-age"/>
+ (default: 150 million) minus
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million).
+ As before, all such pages are processed that are
+ marked in the Visibility Map to potentially have unfrozen
+ rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When an AUTOVACUUM process runs. Such a process acts
+ in one of two modes:
+ </simpara>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ In the <emphasis>normal mode</emphasis>, he skips
+ pages with row versions that are younger than
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million) and works only on pages where
+ all xids are older. The skipping of jung xids prevents
+ work on such pages, which are likely to be changed
+ by one of the future SQL commands.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ The process switches
+ to an <emphasis>aggressive mode</emphasis> if he recognizes
+ that for the processed table their oldest xid exceeds
+ <xref linkend="guc-autovacuum-freeze-max-age"/>
+ (default: 200 million). The value of the oldest unfrozen
+ xid is stored per table in <emphasis>pg_class.relfrozenxid</emphasis>.
+ In this <emphasis>aggressive mode</emphasis> AUTOVACUUM
+ processes all such pages of the selected table that are marked
+ in the Visibility Map to potentially have bloat or unfrozen rows.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In the first two cases and with autovacuum in
+ <emphasis>aggressive mode</emphasis>, the system knowns
+ to which value the oldest unfrozen xid has moved forward and
+ logs the value in <emphasis>pg_class.relfrozenxid</emphasis>.
+ The distance between this value and the 'txid_current' split
+ point becomes smaller, and the distance to 'txid_current + 2^31'
+ larger than before.
+ </para>
+
+ <figure id="tutorial-freeze-figure">
+ <title>Freeze</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2">Protection against Wraparound Failure</bridgehead>
+
+ <para>
+ The AUTOVACUUM processes are initiated by the constantly
+ running <firstterm>autovacuum daemon</firstterm>. If the
+ daemon detects that for a table <firstterm>
+ autovacuum_freeze_max_age</firstterm> is exceeded, it starts
+ an AUTOVACUUM process in the <emphasis>aggressive mode</emphasis>
+ (see above) — even if AUTOVACUUM is disabled.
+ </para>
+
+ <bridgehead renderas="sect2">Visibility Map and Free Space Map</bridgehead>
+
+ <para>
+ The <link linkend="glossary-vm">Visibility Map</link>
+ (VM) contains two flags — stored as
+ two bits — for each page of the heap. If the first bit
+ is set, it indicates that the associated page does not
+ contain any bloat. If the second one is set, it indicates
+ that the page contains only frozen rows.
+ </para>
+
+ <para>
+ Please consider two details. First, in most cases a page
+ contains many rows, some of them in many versions.
+ However, the flags are associated with the page,
+ not with a row or a row version! The flags are set
+ only under the condition that they are valid for ALL
+ row versions of the page. Second, since there
+ are only two bits per page, the VM is considerably
+ smaller than the heap. Therefore it is buffered
+ in RAM in almost all cases.
+ </para>
+
+ <para>
+ The setting of the flags is silently done by VACUUM
+ and AUTOVACUUM during their bloat and freeze operations.
+ This is done to accelerate future vacuum actions,
+ regular accesses to heap pages, and some accesses to
+ the index. Every data-modifying operation on any row
+ version of the page clears the flags.
+ </para>
+
+ <para>
+ The <link linkend="glossary-fsm">Free Space Map</link>
+ (FSM) tracks the amount of free space per page. It is
+ organized as a highly condensed b-tree of (rounded) sizes.
+ As long as VACUUM or AUTOVACUUM change the free space
+ on any processed page, they log the new values in
+ the FSM in the same way as all other writing
+ processes.
+ </para>
+
+ <bridgehead renderas="sect2">Statistics</bridgehead>
+
+ <para>
+ Statistic information helps the <link
+ linkend="planner-stats">Query Planner</link> to make optimal
+ decisions for the generation of execution plans. This
+ information can be gathered with the SQL commands ANALYZE
+ or VACUUM ANALYZE. But also autovacuum processes gather
+ such information. Depending on the percentage of changed rows
+ per table <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ the autovacuum daemon starts autovacuum processes to collect
+ statistics per table. This dynamic invocation of analyze
+ operations allows <productname>PostgreSQL</productname> to
+ adopt queries to changing circumstances.
+ </para>
+
+ <para>
+ For more details about vacuum operations, especially for its
+ numerous parameters, see <xref linkend="routine-vacuuming"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-transactions-mvcc">
+ <title>Transactions</title>
+ <para>
+ <link linkend="tutorial-transactions">Transactions</link>
+ are a fundamental concept of relational database systems.
+ Their essential point is that they bundle multiple
+ read- or write-operations into a single, all-or-nothing
+ operation. Furthermore, they separate and protect concurrent
+ actions of different connections from each other. Thereby
+ they implement the ACID paradigm.
+ </para>
+
+ <para>
+ In <productname>PostgreSQL</productname> there are two ways
+ to establish a transaction. The explicite way uses the keywords
+ <link linkend="sql-begin">BEGIN</link> and
+ <link linkend="sql-commit">COMMIT</link> (respectively
+ <link linkend="sql-rollback">ROLLBACK</link>) before
+ and after a sequence of SQL statements. The keywords mark
+ the transaction's start- and end-point. On the other hand, you
+ can omit the keywords. This is the implicit way, where
+ every single SQL command automatically establishes a new
+ transaction.
+
+ <programlisting>
+BEGIN; -- establish a new transaction
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+COMMIT; -- finish the transaction
+
+-- this UPDATE runs as the only command of a separate transaction ...
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+
+-- ... and this one runs in another transaction
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+ </programlisting>
+ </para>
+
+ <para>
+ As mentioned, the primary property of a transaction is its
+ atomicity: either all or none of its operations succeed,
+ regardless of the fact that it may consist of a lot of
+ different write-operations, and each such operation may
+ affect thousands or millions of rows. As soon as one of the
+ operations fails, all previous operations fail also, which
+ means that all modified rows retain their values as of the
+ beginning of the transaction.
+ </para>
+
+ <para>
+ The atomicity also affects the visibility of changes. All
+ connections running simultaneously to a data modifying
+ transaction will never see any change before the
+ transaction successfully executes a <command>COMMIT</command>
+ — even in the lowest
+ <link linkend="transaction-iso">isolation level</link>
+ of transactions. <productname>PostgreSQL</productname>
+ does never show uncommitted changes to other connections.
+ </para>
+
+ <para>
+ The situation regarding visibility is somewhat different
+ from the point of view of the modifying transaction.
+ <command>SELECT</command> commands issued inside the
+ transaction delivers all changes done so far by this
+ transaction.
+ </para>
+
+ <bridgehead renderas="sect2">How does it work?</bridgehead>
+
+ <para>
+ Every <command>INSERT</command>, <command>UPDATE</command>,
+ and <command>DELETE</command> command creates new row
+ versions — according to the MVCC rules. This
+ creates the risk that other transactions may see the
+ new row versions, and after a while and some more
+ activities of the modifying transaction they may see the
+ next row versions. Results would be a kind of 'moving
+ target' in absolute contrast to the all-or-nothing
+ principle.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> overcomes the
+ problem by showing only such row versions to other
+ transactions whose originating transaction is
+ successfully committed. It skips all row versions of
+ uncommitted transactions. And
+ <productname>PostgreSQL</productname> solves one more
+ problem. Even the single <command>COMMIT</command>
+ command needs a short time interval for its execution.
+ Therefor its critical 'dead-or-survival' phase
+ runs in a priviledged mode where it cannot be
+ interupted by other processes.
+ </para>
+
+ <bridgehead renderas="sect2">What are the benefits?</bridgehead>
+
+ <para>
+ Transactions relieve applications from many standard
+ actions that must be implemented for nearly every use case.
+ </para>
+
+ <para>
+ Business logic often contains strong, but for a computer,
+ relative abstract requirements. The above example shows
+ the transfers of some money from one account to another.
+ It is obvious
+ that the decrease of the one and the increase of the
+ other are impartible. Nevertheless, there is no particular
+ need for an application to do something to ensure the
+ <glossterm linkend="glossary-atomicity">atomicity</glossterm>
+ of its behavior. It's enough to surround them with
+ <command>BEGIN</command> and <command>COMMIT</command>.
+ </para>
+
+ <para>
+ Applications often demand the feature of 'undoing'
+ previously taken actions under some application-specific
+ conditions. In such cases, the application simply issues a
+ <command>ROLLBACK</command> command instead of a
+ <command>COMMIT</command>. The <command>ROLLBACK</command>
+ cancels the transaction, and all changes made so far retain
+ invisible forever; it's like they never happened. There
+ is no need for the application to log its activities and
+ undo every single step.
+ </para>
+
+ <para>
+ Transactions ensure that the
+ <glossterm linkend="glossary-consistency">consistency</glossterm>
+ of the complete database always keeps valid. Declarative
+ rules like
+ <link linkend="ddl-constraints-primary-keys">primary</link>- or
+ <link linkend="ddl-constraints-fk">foreign keys</link>,
+ <link linkend="ddl-constraints-check-constraints">checks</link>,
+ other constraints, or
+ <link linkend="trigger-definition">triggers</link>
+ are part of the all-or-nothing nature of transactions.
+ </para>
+
+ <para>
+ Also, all self-evident — but possibly not obvious
+ — low-level demands on the database system are
+ ensured; e.g., index entries for rows must become
+ visible at the same moment as the rows themselves.
+ </para>
+
+ <para>
+ There is an additional feature which defines transactions'
+ <link linkend="transaction-iso">isolation level</link>
+ to each other in a declarative way. It automatically
+ prevents applications from some strange situations.
+ </para>
+
+ <para>
+ Lastly, it is worth to notice that changes done by a
+ committed transaction will survive all future application,
+ instance, or hardware failures. The next chapter
+ explains this
+ <glossterm linkend="glossary-durability">durability</glossterm>.
+ </para>
+ </sect1>
+
+ <sect1 id="tutorial-reliability">
+ <title>Reliability</title>
+
+ <para>
+ Nothing is perfect and failures inevitably happen.
+ However, the most common types of failures are
+ well known and <productname>PostgreSQL</productname>
+ implements strategies to overcome them.
+ Such strategies use parts of the previously presented
+ techniques MVCC and transaction-rollback, plus additional
+ features.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the client side</bridgehead>
+ <para>
+ A <glossterm linkend="glossary-client">client</glossterm>
+ can fail in different ways. Its hardware can get damaged,
+ the power supply can fail, the network connection to the
+ server can break, or the client application may run into
+ a severe software error like a null pointer exception.
+ Because <productname>PostgreSQL</productname> uses a
+ client/server architecture, no direct problem for the
+ database will occur. In all of this cases, the
+ <glossterm linkend="glossary-backend">backend process</glossterm>,
+ which is the client's counterpart at the server-side,
+ may recognize that the network connection is no longer
+ working, or it may run into a timeout after a while. It
+ terminates, and there is no harm to the database. As
+ usual, uncommitted data changes initiated by this client
+ are not visible to any other client.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the server-side</bridgehead>
+
+ <bridgehead renderas="sect3">Instance failure</bridgehead>
+ <para>
+ The instance may suddenly fail because of <emphasis>power off</emphasis>
+ or other problems. This will affect all running processes, the RAM,
+ and possibly the consistency of disk files.
+ </para>
+ <para>
+ After a restart, <productname>PostgreSQL</productname>
+ automatically recognizes that the last shutdown of the
+ instance did not happen as expected: files might not be
+ closed properly and the <firstterm>postmaster.pid</firstterm>
+ file exists. <productname>PostgreSQL</productname>
+ tries to clean up the situation. This is possible because
+ all changes in the database are stored twice. First,
+ the WAL files contain them as a chronology of
+ <glossterm linkend="glossary-wal-record">WAL records</glossterm>,
+ which include the new data values and information about commit
+ actions. The WAL records are written first. Second,
+ the data itself shall exist in the heap and index files.
+ In opposite to the WAL records, this part may or may
+ not be transferred entirely from shared buffers to the files.
+ </para>
+ <para>
+ The automatic recovery searches within the WAL files for
+ the latest
+ <glossterm linkend="glossary-checkpoint">checkpoint</glossterm>.
+ This checkpoint signals that the database files are in
+ a consistent state, especially that all WAL records up to
+ this point were successfully stored in heap and index. Starting
+ here, the recovery process copies the following WAL records
+ to heap and index. As a result, the files contain all
+ changes and reach a consistent state. Changes of committed
+ transactions are visible; those of uncommited transactions
+ are also in the files, but - as usual - they are never seen
+ by any of the following transactions because uncommited
+ changes are never shown. Such recovery actions run
+ completely automatically, it is not necessary that you
+ configure or start anything by yourself.
+ </para>
+
+ <bridgehead renderas="sect3">Disk crash</bridgehead>
+ <para>
+ If a disk crashes, the course of actions described previously
+ cannot work. It is likely that the WAL files and/or the
+ data and index files are no longer available. You need
+ to take special actions to overcome such situations.
+ </para>
+ <para>
+ You obviously need a backup. How to take such a backup
+ and use it as a starting point for a recovery of the
+ cluster is explained in more detail in the next
+ <link linkend="tutorial-backup">chapter</link>.
+ </para>
+
+ <bridgehead renderas="sect3">Disk full</bridgehead>
+ <para>
+ It is conceivable that over time the disk gets full,
+ and there is no room for additional data. In this case,
+ <productname>PostgreSQL</productname> stops accepting
+ commands which change the data or even terminates
+ completely. No data loss or data corruption will
+ occur.
+ </para>
+ <para>
+ To come out of such a situation, you should remove
+ unused files from this disk. But you should never
+ delete files from the
+ <glossterm linkend="glossary-data-directory">data directory</glossterm>.
+ Nearly all of them are necessary for the consistency
+ of the database.
+ </para>
+
+ <bridgehead renderas="sect2">High availability</bridgehead>
+ <para>
+ Database servers can work together to allow a second
+ server to quickly take over the workload if the
+ primary server fails for whatever reason
+ (<link linkend="high-availability">high availability</link>),
+ or to allow several computers to serve the same data
+ for the purpose of load balancing.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-backup">
+ <title>Backup</title>
+
+ <para>
+ Taking backups is a basic task of database maintenance.
+ <productname>PostgreSQL</productname> supports
+ three different strategies; each has its own
+ strengths and weaknesses.
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ File system level backup
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Logical backup via pg_dump
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Continuous archiving based on pg_basebackup and WAL files
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <bridgehead renderas="sect2">File system level backup</bridgehead>
+ <para>
+ You can use any appropriate OS tool to create a
+ <link linkend="backup-file">copy</link>
+ of the cluster's directory structure and files. In
+ case of severe problems such a copy can serve as
+ the source of a recovery. But in order to get a
+ <emphasis>USABLE</emphasis> backup by this method,
+ the database server <emphasis>MUST</emphasis> be
+ shut down during the complete runtime of the copy
+ command!
+ </para>
+ <para>
+ The apparent disadvantage of this method is that there
+ is a downtime where no user interaction is possible.
+ </para>
+
+ <bridgehead renderas="sect2">Logical backup via pg_dump</bridgehead>
+ <para>
+ The tool <command>pg_dump</command> is able to take a
+ <link linkend="backup-dump">copy</link>
+ of the complete cluster or certain parts of it. It stores
+ the copy in the form of SQL <command>CREATE</command> and
+ <command>INSERT</command> commands. It runs in
+ parallel to other processes in its own transaction.
+ </para>
+ <para>
+ The output of <command>pg_dump</command> may be used as
+ input of <command>psql</command> to restore the data
+ (or to copy it to another database).
+ </para>
+ <para>
+ The main advantage over the other two methods is that it
+ can pick parts of the cluster, e.g. a single table or one
+ database. The other two methods work only at the level of
+ the complete cluster.
+ </para>
+
+ <bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
+ <para>
+ This <link linkend="continuous-archiving">method</link>
+ is the most sophisticated and complex one. It
+ consists of two phases.
+ </para>
+ <para>
+ First, you need to create a so called
+ <firstterm>basebackup</firstterm> with the tool
+ <command>pg_basebackup</command>. The result is a
+ directory structure plus files which contains a
+ consistent copy of the original cluster.
+ <command>pg_basebackup</command> runs in
+ parallel to other processes in its own transaction.
+ </para>
+ <para>
+ The second step is recommended but not necessary. All
+ changes to the data are stored in WAL files. If you
+ continuously save such WAL files, you have the history
+ of the cluster. This history can be applied to a
+ basebackup in order to recreate any state of the
+ cluster between the time of
+ <command>pg_basebackup</command>'s start time and
+ any later point in time. This technique
+ is called 'Point-in-Time Recovery (PITR)'.
+ </para>
+ <para>
+ If configured, the
+ <glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
+ will automatically copy every single WAL file to a save location.
+ <link linkend="backup-archiving-wal">It's configuration</link>
+ consists mainly of a string, which contains a copy command
+ in the operating system's syntax. In order to protect your
+ data against a disk crash, the destination location
+ of a <firstterm>basebackup</firstterm> as well as of the
+ <firstterm>archived WAL files</firstterm> should be on a
+ disk which is different from the data disk.
+ </para>
+ <para>
+ If it gets necessary to restore the cluster, you have to
+ copy the <firstterm>basebackup</firstterm> and the
+ <firstterm>archived WAL files</firstterm> to
+ their original directories. The configuration of this
+ <link linkend="backup-pitr-recovery">recovery procedure</link>
+ contains a string with the reverse copy command: from
+ archive location to database location.
+ </para>
+
+ </sect1>
+
+<!-- ToDo
+ <sect1 id="tutorial-replication">
+ <title>Replication</title>
+
+ <para>
+...
+ </para>
+
+ </sect1>
+-->
+
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 64b5da0070..a9eac872f0 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -8,9 +8,10 @@
<!ENTITY problems SYSTEM "problems.sgml">
<!-- tutorial -->
-<!ENTITY advanced SYSTEM "advanced.sgml">
-<!ENTITY query SYSTEM "query.sgml">
-<!ENTITY start SYSTEM "start.sgml">
+<!ENTITY start SYSTEM "start.sgml">
+<!ENTITY query SYSTEM "query.sgml">
+<!ENTITY advanced SYSTEM "advanced.sgml">
+<!ENTITY architecture SYSTEM "architecture.sgml">
<!-- user's guide -->
<!ENTITY array SYSTEM "array.sgml">
diff --git a/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
new file mode 100644
index 0000000000..7e13753d48
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
@@ -0,0 +1,160 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="685" viewBox="0 0 900 685">
+ <title>
+ Server (Hardware, Container, or VM)
+ </title>
+ <style>
+ .text_normal,.text_small{font-style:normal;font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_small{font-size:12px}.text_normal{font-size:16px}
+ </style>
+ <defs>
+ <symbol id="rectangle_special_0">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="rectangle_special_1">
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="125">
+ 'my_schema' (optional)
+ </text>
+ <text class="text_small" x="20" y="145">
+ tables, views, ...
+ </text>
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="190">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M450 10v230H0V0h440v10h10L440 0"/>
+ </symbol>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="270" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Server (Hardware, Container, or VM)
+ </text>
+ <path stroke="blue" stroke-width="2" fill="none" d="M20 110h790v555H20z"/>
+ <text class="text_normal" x="180" y="25" transform="translate(20 110)">
+ cluster 'data' (default, managed by one instance)
+ </text>
+ <path d="M50 110V80h790v555h-30" stroke="blue" stroke-width="2" fill="none"/>
+ <text class="text_normal" x="190" y="-10" transform="translate(45 110)">
+ cluster 'cluster_2' (optional, managed by a different instance)
+ </text>
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template0'
+ </text>
+ </g>
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template1'
+ </text>
+ </g>
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'my_db' (optional)
+ </text>
+ </g>
+ <g transform="translate(320 330)">
+ <rect width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4"/>
+ <text class="text_normal" x="15" y="27">
+ Global SQL objects
+ </text>
+ <path d="M0 5l-65-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M80 0v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M180 40h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M0 40l-45 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ </g>
+ <g transform="translate(335 405)">
+ <use xlink:href="#note"/>
+ <text class="text_small" x="10" y="20">
+ 1)
+ </text>
+ <text class="text_small" x="30" y="20">
+ By default, you work in the cluster 'data', database 'postgres',
+ </text>
+ <text class="text_small" x="30" y="35">
+ schema 'public'.
+ </text>
+ <text class="text_small" x="10" y="55">
+ 2)
+ </text>
+ <text class="text_small" x="30" y="55">
+ More system schemas: pg_catalog, information_schema,
+ </text>
+ <text class="text_small" x="30" y="70">
+ pg_temp, pg_toast.
+ </text>
+ <text class="text_small" x="10" y="90">
+ 3)
+ </text>
+ <text class="text_small" x="30" y="90">
+ Global SQL objects: Some SQL objects are automatically active
+ </text>
+ <text class="text_small" x="30" y="105">
+ and known database- or even cluster-wide.
+ </text>
+ <text class="text_small" x="10" y="125">
+ 4)
+ </text>
+ <text class="text_small" x="30" y="125">
+ The command 'initdb' creates a new cluster with the three
+ </text>
+ <text class="text_small" x="30" y="140">
+ databases 'template0', 'template1', and 'postgres'. The command
+ </text>
+ <text class="text_small" x="30" y="155">
+ 'createdb' creates a new database.
+ </text>
+ <text class="text_small" x="10" y="175">
+ 5)
+ </text>
+ <text class="text_small" x="30" y="175">
+ If multiple clusters are active on one server at the same time,
+ </text>
+ <text class="text_small" x="30" y="190">
+ each one is managed by an individual instance. Each such instance
+ </text>
+ <text class="text_small" x="30" y="205">
+ uses a different port.
+ </text>
+ <text class="text_small" x="10" y="225">
+ 6)
+ </text>
+ <text class="text_small" x="30" y="225">
+ No client application is allowed to connect to 'template0'.
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink.svg b/doc/src/sgml/images/cluster-db-schema-ink.svg
new file mode 100644
index 0000000000..1fffb9737a
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink.svg
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="685px"
+ viewBox="0 0 900 685"
+ id="svg147"
+ sodipodi:docname="cluster-db-schema-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Server (Hardware, Container, or VM)</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1129"
+ inkscape:window-height="922"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.68905109"
+ inkscape:cx="737.16805"
+ inkscape:cy="342.1375"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Server (Hardware, Container, or VM)</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs49">
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangle_special_0">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect6" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="195"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect8" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text10">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text12">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="195"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect14" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text16">(more system schemas)</text>
+ </symbol>
+ <!-- same as before, but one more schema -->
+ <symbol
+ id="rectangle_special_1">
+ <!-- the database -->
+ <rect
+ width="245"
+ height="225"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect19" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect21" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text23">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text25">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect27" />
+ <text
+ class="text_normal"
+ x="20"
+ y="125"
+ id="text29">'my_schema' (optional)</text>
+ <text
+ class="text_small"
+ x="20"
+ y="145"
+ id="text31">tables, views, ...</text>
+ <rect
+ x="15"
+ y="170"
+ width="205"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect33" />
+ <text
+ class="text_small"
+ x="20"
+ y="190"
+ id="text35">(more system schemas)</text>
+ </symbol>
+ <symbol
+ id="note"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title38">UML Note</title>
+ <path
+ d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10"
+ id="path40" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path43" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path46" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect51" />
+ <text
+ class="text_big"
+ x="270"
+ y="40"
+ id="text53">Server (Hardware, Container, or VM)</text>
+ <!-- two clusters -->
+ <g
+ transform="translate(20 110)"
+ id="g59">
+ <rect
+ x="0"
+ y="0"
+ width="790"
+ height="555"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="rect55" />
+ <text
+ class="text_normal"
+ x="180"
+ y="25"
+ id="text57">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g
+ transform="translate(45 110)"
+ id="g65">
+ <path
+ d="M 5,0 v -30 h 790 v 555 h -30"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="path61" />
+ <text
+ class="text_normal"
+ x="190"
+ y="-10"
+ id="text63">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+ <!-- database template 0 -->
+ <g
+ transform="translate(40 155)"
+ id="g71">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use67" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text69">database 'template0'</text>
+ </g>
+ <!-- database template 1 -->
+ <g
+ transform="translate(290 155)"
+ id="g77">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use73" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text75">database 'template1'</text>
+ </g>
+ <!-- database postgres -->
+ <g
+ transform="translate(540 155)"
+ id="g83">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use79" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text81">database 'postgres'</text>
+ </g>
+ <!-- database my_db -->
+ <g
+ transform="translate(40 350)"
+ id="g89">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use85" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text87">database 'my_db' (optional)</text>
+ </g>
+ <!-- global objects -->
+ <g
+ transform="translate(320 330)"
+ id="g103">
+ <rect
+ x="0"
+ y="0"
+ width="180"
+ height="45"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="10 4 4 4"
+ id="rect91" />
+ <text
+ class="text_normal"
+ x="15"
+ y="27"
+ id="text93">Global SQL objects</text>
+ <path
+ d="M 0,5 l-65,-35"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path95" />
+ <path
+ d="M 80,0 v-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path97" />
+ <path
+ d="M 180,40 h50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path99" />
+ <path
+ d="M 0,40 l-45,20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path101" />
+ </g>
+ <!-- Some comments -->
+ <g
+ transform="translate(335 405)"
+ id="g145">
+ <use
+ xlink:href="#note"
+ x="0"
+ y="0"
+ id="use105" />
+ <text
+ class="text_small"
+ x="10"
+ y="20"
+ id="text107">1)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="20"
+ id="text109">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text
+ class="text_small"
+ x="30"
+ y="35"
+ id="text111">schema 'public'.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="55"
+ id="text113">2)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="55"
+ id="text115">More system schemas: pg_catalog, information_schema,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="70"
+ id="text117">pg_temp, pg_toast.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="90"
+ id="text119">3)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="90"
+ id="text121">Global SQL objects: Some SQL objects are automatically active</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text123">and known database- or even cluster-wide.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="125"
+ id="text125">4)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="125"
+ id="text127">The command 'initdb' creates a new cluster with the three</text>
+ <text
+ class="text_small"
+ x="30"
+ y="140"
+ id="text129">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text
+ class="text_small"
+ x="30"
+ y="155"
+ id="text131">'createdb' creates a new database.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="175"
+ id="text133">5)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="175"
+ id="text135">If multiple clusters are active on one server at the same time,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="190"
+ id="text137">each one is managed by an individual instance. Each such instance</text>
+ <text
+ class="text_small"
+ x="30"
+ y="205"
+ id="text139">uses a different port.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="225"
+ id="text141">6)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="225"
+ id="text143">No client application is allowed to connect to 'template0'.</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
new file mode 100644
index 0000000000..af50c07330
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="685px"
+ viewBox="0 0 900 685" >
+
+ <title>Server (Hardware, Container, or VM)</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_0">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">(more system schemas)</text>
+ </symbol>
+
+ <!-- same as before, but one more schema -->
+ <symbol id="rectangle_special_1">
+ <!-- the database -->
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="125">'my_schema' (optional)</text>
+ <text class="text_small" x="20" y="145">tables, views, ...</text>
+
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="190">(more system schemas)</text>
+ </symbol>
+
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="270" y="40">Server (Hardware, Container, or VM)</text>
+
+ <!-- two clusters -->
+ <g transform="translate(20 110)">
+ <rect x="0" y="0" width="790" height="555" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="180" y="25">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g transform="translate(45 110)">
+ <path d="M 5,0 v -30 h 790 v 555 h -30" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="190" y="-10">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+
+
+ <!-- database template 0 -->
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template0'</text>
+ </g>
+
+ <!-- database template 1 -->
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template1'</text>
+ </g>
+
+ <!-- database postgres -->
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'postgres'</text>
+ </g>
+
+ <!-- database my_db -->
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
+ </g>
+
+ <!-- global objects -->
+ <g transform="translate(320 330)">
+ <rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
+ <text class="text_normal" x="15" y="27">Global SQL objects</text>
+ <path d="M 0,5 l-65,-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ </g>
+
+ <!-- Some comments -->
+ <g transform="translate(335 405)">
+ <use xlink:href="#note" x="0" y="0" />
+
+ <text class="text_small" x="10" y="20">1)</text>
+ <text class="text_small" x="30" y="20">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text class="text_small" x="30" y="35">schema 'public'.</text>
+
+ <text class="text_small" x="10" y="55">2)</text>
+ <text class="text_small" x="30" y="55">More system schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="70">pg_temp, pg_toast.</text>
+
+ <text class="text_small" x="10" y="90">3)</text>
+ <text class="text_small" x="30" y="90">Global SQL objects: Some SQL objects are automatically active</text>
+ <text class="text_small" x="30" y="105">and known database- or even cluster-wide.</text>
+
+ <text class="text_small" x="10" y="125">4)</text>
+ <text class="text_small" x="30" y="125">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="140">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="155">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="175">5)</text>
+ <text class="text_small" x="30" y="175">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="190">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="205">uses a different port.</text>
+
+ <text class="text_small" x="10" y="225">6)</text>
+ <text class="text_small" x="30" y="225">No client application is allowed to connect to 'template0'.</text>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/directories-ink-svgo.svg b/doc/src/sgml/images/directories-ink-svgo.svg
new file mode 100644
index 0000000000..95fa76b9c6
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink-svgo.svg
@@ -0,0 +1,164 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="640" viewBox="0 0 900 640">
+ <title>
+ Directory structure of a cluster
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <symbol id="directory" stroke="blue" stroke-width=".3" fill="aqua">
+ <title>
+ Directory
+ </title>
+ <path d="M0 10h110v20H0z"/>
+ <path d="M0 10V8l3-3h35l3 3v2"/>
+ </symbol>
+ <symbol id="file" stroke="black" fill="none">
+ <title>
+ File
+ </title>
+ <path stroke="blue" d="M0 0h40v50H0z"/>
+ <path d="M5 10h20" stroke-dasharray="4 2"/>
+ <path d="M5 17h15" stroke-dasharray="6 2"/>
+ <path d="M5 24h25" stroke-dasharray="4 2"/>
+ <path d="M5 31h20" stroke-dasharray="5 2"/>
+ </symbol>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="50" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Directory Structure
+ </text>
+ <g transform="translate(20 100)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /pg/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ An arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 130)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ data/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of cluster 'data' (see: PGDATA)
+ </text>
+ </g>
+ <g transform="translate(120 160)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ base/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing per-database subdirectories
+ </text>
+ </g>
+ <g transform="translate(170 190)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 1/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of first database 'template0'
+ </text>
+ </g>
+ <g transform="translate(170 220)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12992/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of second database 'template1'
+ </text>
+ </g>
+ <g transform="translate(170 250)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12999/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of third database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(170 280)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ nnnnn/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Optional: more subdirectories for databases, e.g. 'my_db'
+ </text>
+ </g>
+ <g transform="translate(120 310)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ global/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory with information about Global SQL Objects
+ </text>
+ </g>
+ <g transform="translate(120 340)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_wal/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 370)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_xact/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for transaction commit status ('pg_clog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 400)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_tblspc/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing symbolic links to tablespaces
+ </text>
+ </g>
+ <g transform="translate(120 430)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_... /
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Some more subdirectories
+ </text>
+ </g>
+ <g transform="translate(120 465)">
+ <use xlink:href="#file"/>
+ <use xlink:href="#file" x="50"/>
+ <text x="200" y="26" class="text_normal">
+ 'postmaster.pid' and other files with cluster-wide relevance
+ </text>
+ </g>
+ <g transform="translate(20 540)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /xyz/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ Same or another arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 570)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ cluster_2/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of another cluster 'cluster_2'
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-ink.svg b/doc/src/sgml/images/directories-ink.svg
new file mode 100644
index 0000000000..8151cf583a
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink.svg
@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="640px"
+ viewBox="0 0 900 640"
+ id="svg303"
+ sodipodi:docname="directories-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata307">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Directory structure of a cluster</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1083"
+ inkscape:window-height="808"
+ id="namedview305"
+ showgrid="false"
+ inkscape:zoom="0.36875"
+ inkscape:cx="450"
+ inkscape:cy="320"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg303" />
+ <title
+ id="title153">Directory structure of a cluster</title>
+ <style
+ type="text/css"
+ id="style155">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs177">
+ <!-- Directory -->
+ <symbol
+ id="directory"
+ stroke="blue"
+ stroke-width="0.3px"
+ fill="aqua">
+ <title
+ id="title157">Directory</title>
+ <rect
+ x="0"
+ y="10"
+ width="110"
+ height="20"
+ id="rect159" />
+ <path
+ d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2"
+ id="path161" />
+ </symbol>
+ <!-- File -->
+ <symbol
+ id="file"
+ stroke="black"
+ fill="none">
+ <title
+ id="title164">File</title>
+ <rect
+ x="0"
+ y="0"
+ width="40"
+ height="50"
+ stroke="blue"
+ id="rect166" />
+ <path
+ d="M 5,10 h 20"
+ stroke-dasharray="4 2"
+ id="path168" />
+ <path
+ d="M 5,17 h 15"
+ stroke-dasharray="6 2"
+ id="path170" />
+ <path
+ d="M 5,24 h 25"
+ stroke-dasharray="4 2"
+ id="path172" />
+ <path
+ d="M 5,31 h 20"
+ stroke-dasharray="5 2"
+ id="path174" />
+ </symbol>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect179" />
+ <!-- caption -->
+ <text
+ x="200"
+ y="50"
+ class="text_big"
+ id="text181">Directory Structure</text>
+ <!-- the directories -->
+ <g
+ transform="translate(20, 100)"
+ id="g189">
+ <use
+ xlink:href="#directory"
+ id="use183" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text185">... /pg/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text187">An arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 130)"
+ id="g197">
+ <use
+ xlink:href="#directory"
+ id="use191" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text193">data/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text195">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+ <g
+ transform="translate(120, 160)"
+ id="g205">
+ <use
+ xlink:href="#directory"
+ id="use199" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text201">base/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text203">Subdirectory containing per-database subdirectories</text>
+ </g>
+ <!-- -->
+ <g
+ transform="translate(170, 190)"
+ id="g213">
+ <use
+ xlink:href="#directory"
+ id="use207" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text209">1/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text211">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g
+ transform="translate(170, 220)"
+ id="g221">
+ <use
+ xlink:href="#directory"
+ id="use215" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text217">12992/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text219">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g
+ transform="translate(170, 250)"
+ id="g229">
+ <use
+ xlink:href="#directory"
+ id="use223" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text225">12999/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text227">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g
+ transform="translate(170, 280)"
+ id="g237">
+ <use
+ xlink:href="#directory"
+ id="use231" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text233">nnnnn/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text235">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+ <g
+ transform="translate(120, 310)"
+ id="g245">
+ <use
+ xlink:href="#directory"
+ id="use239" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text241">global/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text243">Subdirectory with information about Global SQL Objects</text>
+ </g>
+ <g
+ transform="translate(120, 340)"
+ id="g253">
+ <use
+ xlink:href="#directory"
+ id="use247" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text249">pg_wal/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text251">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 370)"
+ id="g261">
+ <use
+ xlink:href="#directory"
+ id="use255" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text257">pg_xact/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text259">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 400)"
+ id="g269">
+ <use
+ xlink:href="#directory"
+ id="use263" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text265">pg_tblspc/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text267">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+ <g
+ transform="translate(120, 430)"
+ id="g277">
+ <use
+ xlink:href="#directory"
+ id="use271" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text273">pg_... /</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text275">Some more subdirectories</text>
+ </g>
+ <g
+ transform="translate(120, 465)"
+ id="g285">
+ <use
+ xlink:href="#file"
+ x="0"
+ y="0"
+ id="use279" />
+ <use
+ xlink:href="#file"
+ x="50"
+ y="0"
+ id="use281" />
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text283">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+ <!-- next cluster -->
+ <g
+ transform="translate(20, 540)"
+ id="g293">
+ <use
+ xlink:href="#directory"
+ id="use287" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text289">... /xyz/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text291">Same or another arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 570)"
+ id="g301">
+ <use
+ xlink:href="#directory"
+ id="use295" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text297">cluster_2/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text299">Root of another cluster 'cluster_2'</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
new file mode 100644
index 0000000000..6d16a03169
--- /dev/null
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="640px"
+ viewBox="0 0 900 640">
+
+ <title>Directory structure of a cluster</title>
+
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Directory -->
+ <symbol id="directory" stroke="blue" stroke-width="0.3px" fill="aqua">
+ <title>Directory</title>
+ <rect x="0" y="10" width="110" height="20" />
+ <path d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2" />
+ </symbol>
+
+ <!-- File -->
+ <symbol id="file" stroke="black" fill="none" >
+ <title>File</title>
+ <rect x="0" y="0" width="40" height="50" stroke="blue" />
+ <path d="M 5,10 h 20" stroke-dasharray="4 2" />
+ <path d="M 5,17 h 15" stroke-dasharray="6 2" />
+ <path d="M 5,24 h 25" stroke-dasharray="4 2" />
+ <path d="M 5,31 h 20" stroke-dasharray="5 2" />
+ </symbol>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption -->
+ <text x="200" y="50" class="text_big">Directory Structure</text>
+
+ <!-- the directories -->
+ <g transform="translate(20, 100)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /pg/</text>
+ <text x="300" y="26" class="text_normal">An arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 130)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">data/</text>
+ <text x="250" y="26" class="text_normal">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+
+ <g transform="translate(120, 160)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">base/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing per-database subdirectories</text>
+ </g>
+
+ <!-- -->
+ <g transform="translate(170, 190)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">1/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g transform="translate(170, 220)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12992/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g transform="translate(170, 250)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12999/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g transform="translate(170, 280)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">nnnnn/</text>
+ <text x="150" y="26" class="text_normal">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+
+ <g transform="translate(120, 310)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">global/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory with information about Global SQL Objects</text>
+ </g>
+
+ <g transform="translate(120, 340)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 370)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 400)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+
+ <g transform="translate(120, 430)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_... /</text>
+ <text x="200" y="26" class="text_normal">Some more subdirectories</text>
+ </g>
+
+ <g transform="translate(120, 465)">
+ <use xlink:href="#file" x="0" y="0" />
+ <use xlink:href="#file" x="50" y="0" />
+ <text x="200" y="26" class="text_normal">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+
+ <!-- next cluster -->
+ <g transform="translate(20, 540)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /xyz/</text>
+ <text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 570)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster 'cluster_2'</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink-svgo.svg b/doc/src/sgml/images/freeze-ink-svgo.svg
new file mode 100644
index 0000000000..6fedfb7633
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink-svgo.svg
@@ -0,0 +1,84 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="320" viewBox="0 0 850 320">
+ <title>
+ Freeze
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100)"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="70" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ <tspan font-style="italic" font-weight="700">Freeze</tspan> to keep visible
+ </text>
+ <g fill="none" transform="translate(170 190)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_120" startOffset="11.2%">(1)</textPath> <textPath xlink:href="#Path_120" startOffset="61.2%">(5)</textPath> <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%">|</textPath> <textPath xlink:href="#Path_120" startOffset="34%">(2)</textPath> <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(3)</textPath> <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%">|</textPath> <textPath xlink:href="#Path_120" startOffset="55%">(4)</textPath>
+ </text>
+ <path d="M-80-80L80 80" stroke="black"/>
+ <text class="text_normal" letter-spacing="12" transform="rotate(45 40.78 -38.1)">
+ PAST
+ </text>
+ <text class="text_normal" letter-spacing="12" transform="rotate(-135 27.43 23.79)">
+ FUTURE
+ </text>
+ <use xlink:href="#frozenPoint" transform="rotate(10)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(25)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(40)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(55)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(70)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(85)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(100)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(115)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(130)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(145)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(160)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(175)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(190)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(205)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(220)"/>
+ </g>
+ <g class="text_normal" transform="translate(380 30)">
+ <text>
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25">
+ 1: txid_current + 2 ^ 31 (split-point)
+ </text>
+ <text y="50">
+ 2: autovacuum_freeze_max_age (200 mio.)
+ </text>
+ <text y="75">
+ 3: vacuum_freeze_table_age (150 mio.)
+ </text>
+ <text y="100">
+ 4: vacuum_freeze_min_age (50 mio.)
+ </text>
+ <text y="125">
+ 5: txid_current (split-point, jungest xid)
+ </text>
+ <text y="155">
+ per table: pg_class.relfrozenxid <tspan font-weight="700">must</tspan> be between (1) and (5);
+ </text>
+ <text y="175" x="75">
+ normally it is between (3) and (4)
+ </text>
+ <use xlink:href="#unfrozenPoint" transform="translate(106 200)"/>
+ <text y="205" x="20">
+ Unfrozen xid
+ </text>
+ <use xlink:href="#frozenPoint" transform="translate(106 224)"/>
+ <text y="230" x="20">
+ Frozen xid
+ </text>
+ <text y="260">
+ (figure is out of scale)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink.svg b/doc/src/sgml/images/freeze-ink.svg
new file mode 100644
index 0000000000..009cfe4b41
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink.svg
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="320px"
+ viewBox="0 0 850 320"
+ id="svg454"
+ sodipodi:docname="freeze-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata458">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Freeze</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="979"
+ inkscape:window-height="857"
+ id="namedview456"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="160"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg454" />
+ <title
+ id="title309">Freeze</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style311">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs318">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle
+ id="frozenPoint"
+ r="3"
+ stroke="green"
+ fill="green"
+ transform="translate(-100, 0)" />
+ <circle
+ id="unfrozenPoint"
+ r="3"
+ stroke="green"
+ fill="none"
+ transform="translate(-100, 0)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect320" />
+ <text
+ class="text_big"
+ x="70"
+ y="40"
+ id="text324"><tspan
+ style="font-style:italic;font-weight:bold"
+ id="tspan322">
+ Freeze</tspan>
+ to keep visible</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 190)"
+ id="g418">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle326" />
+ <text
+ class="text_normal"
+ id="text350">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath328">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath330">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath332">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="11.2%"
+ id="textPath334">(1)</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="61.2%"
+ id="textPath336">(5)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="red"
+ stroke-width="3"
+ startOffset="34%"
+ id="textPath338">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="34%"
+ id="textPath340">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="black"
+ stroke-width="3"
+ startOffset="45%"
+ id="textPath342">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath344">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="green"
+ stroke-width="3"
+ startOffset="55%"
+ id="textPath346">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="55%"
+ id="textPath348">(4)</textPath>
+ </text>
+ <!-- split it into 'past' and 'future' -->
+ <path
+ d="M -80 -80 l 160 160"
+ stroke="black"
+ id="path352" />
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(-15, -40) rotate(45)"
+ id="text354">PAST</text>
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(30, 60) rotate(225)"
+ id="text356">FUTURE</text>
+ <g
+ transform="rotate(10)"
+ id="g360">
+ <use
+ xlink:href="#frozenPoint"
+ id="use358" />
+ </g>
+ <g
+ transform="rotate(25)"
+ id="g364">
+ <use
+ xlink:href="#frozenPoint"
+ id="use362" />
+ </g>
+ <g
+ transform="rotate(40)"
+ id="g368">
+ <use
+ xlink:href="#frozenPoint"
+ id="use366" />
+ </g>
+ <g
+ transform="rotate(55)"
+ id="g372">
+ <use
+ xlink:href="#frozenPoint"
+ id="use370" />
+ </g>
+ <g
+ transform="rotate(70)"
+ id="g376">
+ <use
+ xlink:href="#frozenPoint"
+ id="use374" />
+ </g>
+ <g
+ transform="rotate(85)"
+ id="g380">
+ <use
+ xlink:href="#frozenPoint"
+ id="use378" />
+ </g>
+ <g
+ transform="rotate(100)"
+ id="g384">
+ <use
+ xlink:href="#frozenPoint"
+ id="use382" />
+ </g>
+ <g
+ transform="rotate(115)"
+ id="g388">
+ <use
+ xlink:href="#frozenPoint"
+ id="use386" />
+ </g>
+ <g
+ transform="rotate(130)"
+ id="g392">
+ <use
+ xlink:href="#frozenPoint"
+ id="use390" />
+ </g>
+ <g
+ transform="rotate(145)"
+ id="g396">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use394" />
+ </g>
+ <g
+ transform="rotate(160)"
+ id="g400">
+ <use
+ xlink:href="#frozenPoint"
+ id="use398" />
+ </g>
+ <g
+ transform="rotate(175)"
+ id="g404">
+ <use
+ xlink:href="#frozenPoint"
+ id="use402" />
+ </g>
+ <g
+ transform="rotate(190)"
+ id="g408">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use406" />
+ </g>
+ <g
+ transform="rotate(205)"
+ id="g412">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use410" />
+ </g>
+ <g
+ transform="rotate(220)"
+ id="g416">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use414" />
+ </g>
+ </g>
+ <!-- legend -->
+ <g
+ class="text_normal"
+ transform="translate(380 30)"
+ id="g452">
+ <text
+ id="text424">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan420">^</tspan>
+<tspan
+ dy="5"
+ id="tspan422">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text426">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text
+ y="50"
+ id="text428">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text
+ y="75"
+ id="text430">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text
+ y="100"
+ id="text432">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text
+ y="125"
+ id="text434">5: txid_current (split-point, jungest xid)</text>
+ <text
+ y="155"
+ id="text438">per table: pg_class.relfrozenxid
+ <tspan
+ style="font-weight:bold"
+ id="tspan436">must</tspan>
+ be between (1) and (5);</text>
+ <text
+ y="175"
+ x="75"
+ id="text440">normally it is between (3) and (4)</text>
+ <use
+ xlink:href="#unfrozenPoint"
+ transform="translate(106, 200)"
+ id="use442" />
+ <text
+ y="205"
+ x="20"
+ id="text444">Unfrozen xid</text>
+ <use
+ xlink:href="#frozenPoint"
+ transform="translate(106, 224)"
+ id="use446" />
+ <text
+ y="230"
+ x="20"
+ id="text448">Frozen xid</text>
+ <text
+ y="260"
+ id="text450">(figure is out of scale)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-raw.svg b/doc/src/sgml/images/freeze-raw.svg
new file mode 100644
index 0000000000..2d1d256184
--- /dev/null
+++ b/doc/src/sgml/images/freeze-raw.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="320px"
+ viewBox="0 0 850 320" >
+
+ <title>Freeze</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100, 0)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100, 0)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="70" y="40"><tspan style="font-style:italic;font-weight:bold">
+ Freeze</tspan> to keep visible</text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 190)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_120" startOffset="11.2%" >(1)</textPath>
+ <textPath xlink:href="#Path_120" startOffset="61.2%" >(5)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="34%" >(2)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(3)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="55%" >(4)</textPath>
+
+ </text>
+
+ <!-- split it into 'past' and 'future' -->
+ <path d="M -80 -80 l 160 160" stroke="black" />
+ <text class="text_normal" letter-spacing="12" transform="translate(-15, -40) rotate(45)">PAST</text>
+ <text class="text_normal" letter-spacing="12" transform="translate(30, 60) rotate(225)">FUTURE</text>
+
+ <g transform="rotate(10)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(25)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(40)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(55)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(70)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(85)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(100)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(115)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(130)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(145)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(160)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(175)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(190)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(205)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(220)"><use xlink:href="#unfrozenPoint"/></g>
+
+ </g>
+
+ <!-- legend -->
+ <g class="text_normal" transform="translate(380 30)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text y="50">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text y="75">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text y="100">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text y="125">5: txid_current (split-point, jungest xid)</text>
+ <text y="155">per table: pg_class.relfrozenxid
+ <tspan style="font-weight:bold">must</tspan> be between (1) and (5);</text>
+ <text y="175" x="75">normally it is between (3) and (4)</text>
+
+ <use xlink:href="#unfrozenPoint" transform="translate(106, 200)"/>
+ <text y="205" x="20">Unfrozen xid</text>
+
+ <use xlink:href="#frozenPoint" transform="translate(106, 224)"/>
+ <text y="230" x="20">Frozen xid</text>
+
+ <text y="260">(figure is out of scale)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
new file mode 100644
index 0000000000..26bce6176d
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
@@ -0,0 +1,83 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="720" height="430" viewBox="0 0 720 430">
+ <title>
+ Hierarchy of Internal Objects
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Hierarchy of internal Objects
+ </text>
+ <g fill="none">
+ <g transform="translate(350 240)">
+ <ellipse rx="320" ry="170" stroke="blue"/>
+ <text class="text_normal" x="-140" y="-130">
+ Cluster
+ </text>
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-60" y="5">
+ Database Names
+ </text>
+ </g>
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-40" y="5">
+ Tablespace
+ </text>
+ </g>
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-70" y="5">
+ Replication Origins
+ </text>
+ </g>
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue"/>
+ <text class="text_normal" x="-60" y="-3">
+ Subscription for
+ </text>
+ <text class="text_normal" x="-68" y="10">
+ Logical Replication
+ </text>
+ </g>
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-15" y="5">
+ Role
+ </text>
+ </g>
+ </g>
+ <g transform="translate(270 250)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2"/>
+ <text class="text_normal" x="-60" y="-80">
+ Database
+ </text>
+ <g transform="translate(-150 -30)">
+ <ellipse rx="50" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Extension
+ </text>
+ </g>
+ <g transform="translate(-155 35)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Collation
+ </text>
+ </g>
+ <g transform="translate(30 20)">
+ <ellipse rx="140" ry="70" stroke="blue"/>
+ <text class="text_normal" x="-80" y="-35">
+ Schema
+ </text>
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue"/>
+ <text class="text_normal" x="-50" y="5">
+ Table, View, ...
+ </text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
new file mode 100644
index 0000000000..e5745818d9
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="720px"
+ height="430px"
+ viewBox="0 0 720 430"
+ id="svg540"
+ sodipodi:docname="internal-objects-hierarchy-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata546">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Hierarchy of Internal Objects</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs544" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1050"
+ inkscape:window-height="838"
+ id="namedview542"
+ showgrid="false"
+ inkscape:zoom="0.51944444"
+ inkscape:cx="360"
+ inkscape:cy="215"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg540" />
+ <title
+ id="title460">Hierarchy of Internal Objects</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style462">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect464" />
+ <text
+ class="text_big"
+ x="200"
+ y="40"
+ id="text466">Hierarchy of internal Objects</text>
+ <!-- set centre of figure and default values -->
+ <g
+ transform="translate(350 240)"
+ fill="none"
+ id="g538">
+ <g
+ id="g504">
+ <ellipse
+ rx="320"
+ ry="170"
+ stroke="blue"
+ id="ellipse468" />
+ <text
+ class="text_normal"
+ x="-140"
+ y="-130"
+ id="text470">Cluster</text>
+ <g
+ transform="translate(40 -125)"
+ id="g476">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse472" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="5"
+ id="text474">Database Names</text>
+ </g>
+ <g
+ transform="translate(180 -70)"
+ id="g482">
+ <ellipse
+ rx="60"
+ ry="20"
+ stroke="blue"
+ id="ellipse478" />
+ <text
+ class="text_normal"
+ x="-40"
+ y="5"
+ id="text480">Tablespace</text>
+ </g>
+ <g
+ transform="translate(230 -5)"
+ id="g488">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse484" />
+ <text
+ class="text_normal"
+ x="-70"
+ y="5"
+ id="text486">Replication Origins</text>
+ </g>
+ <g
+ transform="translate(200 70)"
+ id="g496">
+ <ellipse
+ rx="78"
+ ry="27"
+ stroke="blue"
+ id="ellipse490" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-3"
+ id="text492">Subscription for</text>
+ <text
+ class="text_normal"
+ x="-68"
+ y="10"
+ id="text494">Logical Replication</text>
+ </g>
+ <g
+ transform="translate(100 120)"
+ id="g502">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse498" />
+ <text
+ class="text_normal"
+ x="-15"
+ y="5"
+ id="text500">Role</text>
+ </g>
+ </g>
+ <g
+ transform="translate(-80 10)"
+ id="g536">
+ <ellipse
+ rx="220"
+ ry="110"
+ stroke="blue"
+ stroke-width="2px"
+ id="ellipse506" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-80"
+ id="text508">Database</text>
+ <g
+ transform="translate(-120 -50)"
+ id="g534">
+ <g
+ transform="translate(-30 20)"
+ id="g514">
+ <ellipse
+ rx="50"
+ ry="20"
+ stroke="blue"
+ id="ellipse510" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text512">Extension</text>
+ </g>
+ <g
+ transform="translate(-35 85)"
+ id="g520">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse516" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text518">Collation</text>
+ </g>
+ <g
+ transform="translate(150 70)"
+ id="g532">
+ <ellipse
+ rx="140"
+ ry="70"
+ stroke="blue"
+ id="ellipse522" />
+ <text
+ class="text_normal"
+ x="-80"
+ y="-35"
+ id="text524">Schema</text>
+ <g
+ transform="translate(20 10)"
+ id="g530">
+ <ellipse
+ rx="90"
+ ry="30"
+ stroke="blue"
+ id="ellipse526" />
+ <text
+ class="text_normal"
+ x="-50"
+ y="5"
+ id="text528">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
new file mode 100644
index 0000000000..f0dc890f6b
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="720px" height="430px"
+ viewBox="0 0 720 430" >
+
+ <title>Hierarchy of Internal Objects</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="200" y="40">Hierarchy of internal Objects</text>
+
+
+ <!-- set centre of figure and default values -->
+ <g transform="translate(350 240)" fill="none">
+
+ <g>
+ <ellipse rx="320" ry="170" stroke="blue" />
+ <text class="text_normal" x="-140" y="-130">Cluster</text>
+
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-60" y="5">Database Names</text>
+ </g>
+
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue" />
+ <text class="text_normal" x="-40" y="5">Tablespace</text>
+ </g>
+
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-70" y="5">Replication Origins</text>
+ </g>
+
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue" />
+ <text class="text_normal" x="-60" y="-3">Subscription for</text>
+ <text class="text_normal" x="-68" y="10">Logical Replication</text>
+ </g>
+
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-15" y="5">Role</text>
+ </g>
+
+ </g>
+
+ <g transform="translate(-80 10)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2px" />
+ <text class="text_normal" x="-60" y="-80">Database</text>
+
+ <g transform="translate(-120 -50)">
+ <g transform="translate(-30 20)">
+ <ellipse rx="50" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Extension</text>
+ </g>
+
+ <g transform="translate(-35 85)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Collation</text>
+ </g>
+
+ <g transform="translate(150 70)">
+ <ellipse rx="140" ry="70" stroke="blue" />
+ <text class="text_normal" x="-80" y="-35">Schema</text>
+
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue" />
+ <text class="text_normal" x="-50" y="5">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink-svgo.svg b/doc/src/sgml/images/mvcc-ink-svgo.svg
new file mode 100644
index 0000000000..8e67da93d1
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink-svgo.svg
@@ -0,0 +1,151 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="150" viewBox="0 0 850 150">
+ <title>
+ MVCC
+ </title>
+ <style>
+ .text_small{font-style:normal;font-weight:400;font-size:10px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <marker id="triangle_1" markerWidth="10" markerHeight="10" refX="5" refY="5" orient="auto" stroke="black" fill="none">
+ <path d="M0 0l10 5-10 5"/>
+ </marker>
+ <path id="arrow" d="M0 0q20-15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+ <g id="tuple" stroke="black">
+ <path d="M80 0H0v20h80M29 0v20M60 0v20"/>
+ <path d="M80 0h15M80 20h15" stroke-dasharray="2 1"/>
+ </g>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <g fill="none">
+ <g transform="translate(20 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">123</tspan> <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)" fill="#00f">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 83)" fill="#00f">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(185 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">135</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 53)" fill="#00f">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(350 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">142</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 23)" fill="#00f">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(515 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">821</tspan> <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 821
+ </text>
+ <text class="text_small" transform="translate(125 23)">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(740 110)">
+ <path d="M102-20H-18v60" stroke="black"/>
+ <text font-weight="400" font-size="16" font-family=""Open Sans",sans-serif" fill="#000">
+ Legend
+ </text>
+ <use xlink:href="#tuple" transform="translate(0 10)"/>
+ <text class="text_small" transform="translate(3 23)">
+ xmin
+ </text>
+ <text class="text_small" transform="translate(32 23)">
+ xmax
+ </text>
+ <text class="text_small" transform="translate(65 23)">
+ data
+ </text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink.svg b/doc/src/sgml/images/mvcc-ink.svg
new file mode 100644
index 0000000000..f4161b3e79
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink.svg
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="150px"
+ viewBox="0 0 850 150"
+ id="svg147"
+ sodipodi:docname="mvcc-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>MVCC</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1256"
+ inkscape:window-height="801"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="75"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">MVCC</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs15">
+ <marker
+ id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto"
+ stroke="black"
+ fill="none">
+ <path
+ d="M 0,0 L 10,5 L 0,10"
+ id="path6" />
+ </marker>
+ <g
+ id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path
+ d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20"
+ stroke="black"
+ id="path9" />
+ <!-- prolong the rectangle -->
+ <path
+ d="M 80 0 h 15 M 80 20 h 15"
+ stroke="black"
+ stroke-dasharray="2 1"
+ id="path11" />
+ </g>
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path
+ id="arrow"
+ d="M 0 0 Q 20 -15 40 0"
+ stroke="black"
+ marker-end="url(#triangle_1)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect17" />
+ <!-- set default values -->
+ <g
+ fill="none"
+ id="g145">
+ <!-- start plus first INSERT -->
+ <g
+ transform="translate(20, 40)"
+ id="g35">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text23">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan19">123</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan21">: INSERT</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use25" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use27" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ style="fill:blue"
+ id="text29">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text31">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ style="fill:blue"
+ id="text33">'x'</text>
+ </g>
+ <!-- first UPDATE -->
+ <g
+ transform="translate(185, 40)"
+ id="g61">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text41">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan37">135</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan39">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use43" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use45" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ style="fill:blue"
+ id="text47">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text49">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ style="fill:blue"
+ id="text51">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use53" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text55">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text57">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text59">'x'</text>
+ </g>
+ <!-- next UPDATE -->
+ <g
+ transform="translate(350, 40)"
+ id="g95">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text67">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan63">142</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan65">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use69" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use71" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ style="fill:blue"
+ id="text73">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text75">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ style="fill:blue"
+ id="text77">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use79" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text81">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text83">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text85">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use87" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text89">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text91">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text93">'x'</text>
+ </g>
+ <!-- DELETE -->
+ <g
+ transform="translate(515, 40)"
+ id="g129">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text101">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan97">821</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan99">: DELTE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use103" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use105" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text107">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text109">821</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ id="text111">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use113" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text115">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ id="text117">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text119">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use121" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text123">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text125">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text127">'x'</text>
+ </g>
+ <!-- LEGEND -->
+ <g
+ transform="translate(740, 110)"
+ id="g143">
+ <path
+ d="M 102 -20 h -120 v 60"
+ stroke="black"
+ id="path131" />
+ <text
+ class="text_normal"
+ transform="translate(0, 0)"
+ id="text133">Legend</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(0, 10)"
+ id="use135" />
+ <text
+ class="text_small"
+ transform="translate(3, 23)"
+ id="text137">xmin</text>
+ <text
+ class="text_small"
+ transform="translate(32, 23)"
+ id="text139">xmax</text>
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text141">data</text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-raw.svg b/doc/src/sgml/images/mvcc-raw.svg
new file mode 100644
index 0000000000..0481c4c938
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-raw.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="150px"
+ viewBox="0 0 850 150" >
+
+ <title>MVCC</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <marker id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto" stroke="black" fill="none">
+ <path d="M 0,0 L 10,5 L 0,10" />
+ </marker>
+
+ <g id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20" stroke="black"/>
+ <!-- prolong the rectangle -->
+ <path d="M 80 0 h 15 M 80 20 h 15" stroke="black" stroke-dasharray="2 1"/>
+ </g>
+
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path id="arrow" d="M 0 0 Q 20 -15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- set default values -->
+ <g fill="none">
+
+ <!-- start plus first INSERT -->
+ <g transform="translate(20, 40)">
+
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">123</tspan>
+ <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)" style="fill:blue">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 83)" style="fill:blue">'x'</text>
+ </g>
+
+ <!-- first UPDATE -->
+ <g transform="translate(185, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">135</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 53)" style="fill:blue">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- next UPDATE -->
+ <g transform="translate(350, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">142</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 23)" style="fill:blue">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- DELETE -->
+ <g transform="translate(515, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">821</tspan>
+ <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">821</text>
+ <text class="text_small" transform="translate(125, 23)">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- LEGEND -->
+ <g transform="translate(740, 110)">
+ <path d="M 102 -20 h -120 v 60" stroke="black"/>
+ <text class="text_normal" transform="translate(0, 0)">Legend</text>
+ <use xlink:href="#tuple" transform="translate(0, 10)"/>
+ <text class="text_small" transform="translate(3, 23)">xmin</text>
+ <text class="text_small" transform="translate(32, 23)">xmax</text>
+ <text class="text_small" transform="translate(65, 23)">data</text>
+ </g>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink-svgo.svg b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
new file mode 100644
index 0000000000..262275f05c
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
@@ -0,0 +1,285 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 900 600">
+ <title>
+ PG Overall Server Architecture
+ </title>
+ <style>
+ .text_big{font-style:normal}.text_big,.text_comment,.text_normal,.text_small{font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_normal,.text_small{font-style:normal}.text_small{font-size:12px}.text_normal{font-size:16px}.text_big{font-size:24px}.text_comment{font-style:italic;font-size:16px}
+ </style>
+ <defs>
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (200 x 20 px)
+ </title>
+ <path d="M200 10v10H0V0h190v10h10L190 0"/>
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (250 x 20 px)
+ </title>
+ <path d="M250 10v10H0V0h240v10h10L240 0"/>
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (100 x 35 px)
+ </title>
+ <path d="M100 10v25H0V0h90v10h10L90 0"/>
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (170 x 50 px)
+ </title>
+ <path d="M170 10v40H0V0h160v10h10L160 0"/>
+ </symbol>
+ <symbol id="state_300x120">
+ <title>
+ UML State (300x120)
+ </title>
+ <rect width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>
+ UML State (350x120)
+ </title>
+ <rect width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="disc" stroke="blue" fill="none">
+ <title>
+ Disc
+ </title>
+ <ellipse cx="51" cy="13" rx="50" ry="12"/>
+ <path d="M1 13v60"/>
+ <path d="M101 13v60"/>
+ <path d="M1 73a50 12 0 00100 0"/>
+ </symbol>
+ <symbol id="laptop" stroke="black" fill="none">
+ <title>
+ Laptop
+ </title>
+ <path d="M20 40V0h54v40l15 15H5l15-15h54"/>
+ <path d="M23 3h48v34H23z"/>
+ <path d="M30 10h20"/>
+ <path d="M30 15h25"/>
+ <path d="M30 20h10"/>
+ <path d="M30 30h20"/>
+ <path d="M25 50h45l2 2H22z"/>
+ </symbol>
+ <marker id="arrowhead_start" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto">
+ <path d="M6 0L0 3l6 3" stroke="black" fill="none"/>
+ </marker>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="15" y="40" class="text_big">
+ Client
+ </text>
+ <text x="140" y="40" class="text_big">
+ Server
+ </text>
+ <use xlink:href="#laptop" x="5" y="210"/>
+ <g transform="translate(130 70)">
+ <use xlink:href="#state_350x120"/>
+ <text x="5" y="20" class="text_normal">
+ maintenance_work_mem (per connection)
+ </text>
+ <text x="5" y="45" class="text_normal">
+ work_mem (per query operation)
+ </text>
+ <text x="5" y="70" class="text_normal">
+ autovacuum_work_mem (per worker process)
+ </text>
+ <text x="5" y="95" class="text_normal">
+ temp_buffer (per connection)
+ </text>
+ <text x="5" y="110" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_200x20" x="140" y="-15"/>
+ <text x="150" class="text_comment">
+ Individual Memory
+ </text>
+ </g>
+ <g transform="translate(520 70)">
+ <use xlink:href="#state_300x120"/>
+ <text x="10" y="30" class="text_normal">
+ shared_buffers (heap and index)
+ </text>
+ <text x="10" y="70" class="text_normal">
+ wal_buffers (WAL records)
+ </text>
+ <text x="10" y="100" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_250x20" x="40" y="-15"/>
+ <text x="50" class="text_comment">
+ Shared Memory (per Instance)
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M180 215h250v30H180z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(180 215)">
+ Postmaster
+ </text>
+ <path d="M90 230h75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 230)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 1
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M150 315h370v30H150z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(150 315)">
+ Backend processes (one per connection)
+ </text>
+ <path d="M155 315v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M160 310v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M90 240l63 63" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 290)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 3
+ </text>
+ </g>
+ <path d="M360 250v50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180 255)">
+ <use xlink:href="#note_250x20"/>
+ <text x="10" y="15" class="text_comment">
+ Creates backend processes
+ </text>
+ </g>
+ <g transform="translate(360 281)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 2
+ </text>
+ </g>
+ <path d="M460 300V200" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M498 300V95h30" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M508 300V135h20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M550 220h120v30H550z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(550 220)">
+ WAL Writer
+ </text>
+ <path d="M590 150v65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M590 255v230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 340h140v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 340)">
+ Checkpointer
+ </text>
+ <path d="M740 110v220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 355H475v130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M700 330V150" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50"/>
+ <text x="60" y="-35" class="text_comment">
+ Checkpoint
+ </text>
+ <text x="60" y="-20" class="text_comment">
+ Record
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M610 380h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 380)">
+ Background Writer
+ </text>
+ <path d="M770 110v260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 395H485v90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 420h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 420)">
+ WAL Archiver
+ </text>
+ <path d="M620 485l30-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M690 455l30 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M135 380h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 380)">
+ AutoVacuum
+ </text>
+ <path d="M140 380v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path d="M145 375v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path stroke="blue" fill="none" d="M135 430h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 430)">
+ Log Writer
+ </text>
+ <path stroke="blue" fill="none" d="M290 370h140v30H290z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(290 370)">
+ Stats Collector
+ </text>
+ <g transform="translate(145 490)">
+ <use xlink:href="#disc"/>
+ <text x="35" y="45" class="text_normal">
+ Log
+ </text>
+ <text x="20" y="60" class="text_small">
+ text lines,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <path d="M195 465v20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(410 490)">
+ <use xlink:href="#disc"/>
+ <text x="10" y="40" class="text_normal">
+ Heap and
+ </text>
+ <text x="25" y="55" class="text_normal">
+ Index
+ </text>
+ <text x="15" y="70" class="text_small">
+ binary blocks,
+ </text>
+ <text x="30" y="80" class="text_small">
+ random
+ </text>
+ </g>
+ <path d="M450 485V350" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(295 420)">
+ <use xlink:href="#note_170x50"/>
+ <text x="5" y="15" class="text_comment">
+ Read heap and index
+ </text>
+ <text x="5" y="30" class="text_comment">
+ pages and transfer
+ </text>
+ <text x="5" y="45" class="text_comment">
+ them to shared_buffers
+ </text>
+ </g>
+ <g transform="translate(550 490)">
+ <use xlink:href="#disc"/>
+ <text x="30" y="45" class="text_normal">
+ WAL
+ </text>
+ <text x="10" y="60" class="text_small">
+ binary records,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <g transform="translate(690 490)">
+ <use xlink:href="#disc"/>
+ <text x="16" y="45" class="text_normal">
+ Archived
+ </text>
+ <text x="36" y="60" class="text_normal">
+ WAL
+ </text>
+ </g>
+ <path d="M110 20v550" stroke="black" fill="none"/>
+ <g transform="rotate(90 -33.5 156.5)">
+ <use xlink:href="#note_200x20"/>
+ <text class="text_comment" x="10" y="15">
+ Via TCP/IP or socket
+ </text>
+ </g>
+ <text class="text_big" x="95" transform="rotate(90 425 425)">
+ RAM
+ </text>
+ <text class="text_big" x="250" transform="rotate(90 425 425)">
+ PROCESSES
+ </text>
+ <text class="text_big" x="500" transform="rotate(90 425 425)">
+ FILES
+ </text>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink.svg b/doc/src/sgml/images/ram-proc-file-ink.svg
new file mode 100644
index 0000000000..067920b99e
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink.svg
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="600px"
+ viewBox="0 0 900 600"
+ id="svg1003"
+ sodipodi:docname="ram-proc-file-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata1007">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>PG Overall Server Architecture</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1177"
+ inkscape:window-height="869"
+ id="namedview1005"
+ showgrid="false"
+ inkscape:zoom="0.39333333"
+ inkscape:cx="450"
+ inkscape:cy="300"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg1003" />
+ <title
+ id="title699">PG Overall Server Architecture</title>
+ <style
+ type="text/css"
+ id="style701">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs767">
+ <!-- Some notes in different sizes -->
+ <symbol
+ id="note_200x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title703">UML Note (200 x 20 px)</title>
+ <path
+ d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10"
+ id="path705" />
+ </symbol>
+ <symbol
+ id="note_250x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title708">UML Note (250 x 20 px)</title>
+ <path
+ d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10"
+ id="path710" />
+ </symbol>
+ <symbol
+ id="note_100x35"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title713">UML Note (100 x 35 px)</title>
+ <path
+ d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10"
+ id="path715" />
+ </symbol>
+ <symbol
+ id="note_170x50"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title718">UML Note (170 x 50 px)</title>
+ <path
+ d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10"
+ id="path720" />
+ </symbol>
+ <!-- UML states (used for buffers) -->
+ <symbol
+ id="state_300x120">
+ <title
+ id="title723">UML State (300x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="300"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect725" />
+ </symbol>
+ <symbol
+ id="state_350x120">
+ <title
+ id="title728">UML State (350x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="350"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect730" />
+ </symbol>
+ <!-- Discs -->
+ <symbol
+ id="disc"
+ stroke="blue"
+ fill="none">
+ <title
+ id="title733">Disc</title>
+ <ellipse
+ cx="51"
+ cy="13"
+ rx="50"
+ ry="12"
+ id="ellipse735" />
+ <!-- top -->
+ <path
+ d="M 1,13 v 60"
+ id="path737" />
+ <!-- left -->
+ <path
+ d="M 101,13 v 60"
+ id="path739" />
+ <!-- right -->
+ <path
+ d="M 1,73 A 50, 12, 0, 0, 0, 101,73"
+ id="path741" />
+ <!-- bottom -->
+ </symbol>
+ <!-- Laptop -->
+ <symbol
+ id="laptop"
+ stroke="black"
+ fill="none">
+ <title
+ id="title744">Laptop</title>
+ <path
+ d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54"
+ id="path746" />
+ <rect
+ x="23"
+ y="3"
+ width="48"
+ height="34"
+ id="rect748" />
+ <!-- symbolize some lines -->
+ <path
+ d="M 30,10 h 20"
+ id="path750" />
+ <path
+ d="M 30,15 h 25"
+ id="path752" />
+ <path
+ d="M 30,20 h 10"
+ id="path754" />
+ <path
+ d="M 30,30 h 20"
+ id="path756" />
+ <!-- symbolize keyboard -->
+ <path
+ d="M 25,50 h 45 l 2,2 h -50 z "
+ id="path758" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path761" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path764" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect769" />
+ <!-- caption, client side -->
+ <text
+ x="15"
+ y="40"
+ class="text_big"
+ id="text771">Client</text>
+ <text
+ x="140"
+ y="40"
+ class="text_big"
+ id="text773">Server</text>
+ <use
+ xlink:href="#laptop"
+ x="5"
+ y="210"
+ id="use775" />
+ <!-- individual memory -->
+ <g
+ transform="translate(130, 70)"
+ id="g793">
+ <use
+ xlink:href="#state_350x120"
+ x="0"
+ y="0"
+ id="use777" />
+ <text
+ x="5"
+ y="20"
+ class="text_normal"
+ id="text779">maintenance_work_mem (per connection)</text>
+ <text
+ x="5"
+ y="45"
+ class="text_normal"
+ id="text781">work_mem (per query operation)</text>
+ <text
+ x="5"
+ y="70"
+ class="text_normal"
+ id="text783">autovacuum_work_mem (per worker process)</text>
+ <text
+ x="5"
+ y="95"
+ class="text_normal"
+ id="text785">temp_buffer (per connection)</text>
+ <text
+ x="5"
+ y="110"
+ class="text_normal"
+ id="text787">...</text>
+ <use
+ xlink:href="#note_200x20"
+ x="140"
+ y="-15"
+ id="use789" />
+ <text
+ x="150"
+ y="0"
+ class="text_comment"
+ id="text791">Individual Memory</text>
+ </g>
+ <!-- shared memory -->
+ <g
+ transform="translate(520, 70)"
+ id="g807">
+ <use
+ xlink:href="#state_300x120"
+ x="0"
+ y="0"
+ id="use795" />
+ <text
+ x="10"
+ y="30"
+ class="text_normal"
+ id="text797">shared_buffers (heap and index)</text>
+ <text
+ x="10"
+ y="70"
+ class="text_normal"
+ id="text799">wal_buffers (WAL records)</text>
+ <text
+ x="10"
+ y="100"
+ class="text_normal"
+ id="text801">...</text>
+ <use
+ xlink:href="#note_250x20"
+ x="40"
+ y="-15"
+ id="use803" />
+ <text
+ x="50"
+ y="0"
+ class="text_comment"
+ id="text805">Shared Memory (per Instance)</text>
+ </g>
+ <!-- postmaster -->
+ <g
+ transform="translate(180, 215)"
+ id="g813">
+ <rect
+ width="250"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect809" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text811">Postmaster</text>
+ </g>
+ <path
+ d="M 90,230 h 75"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path815" />
+ <g
+ transform="translate(140, 230)"
+ id="g821">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle817" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text819">1</text>
+ </g>
+ <!-- backend processes -->
+ <g
+ transform="translate(150, 315)"
+ id="g831">
+ <rect
+ width="370"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect823" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text825">Backend processes (one per connection)</text>
+ <path
+ d="M 5,0 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path827" />
+ <path
+ d="M 10,-5 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path829" />
+ </g>
+ <path
+ d="M 90,240 153,303"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path833" />
+ <g
+ transform="translate(140, 290)"
+ id="g839">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle835" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text837">3</text>
+ </g>
+ <!-- connection between postmaster and backend processes -->
+ <path
+ d="M 360,250 v 50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path841" />
+ <g
+ transform="translate(180, 255)"
+ id="g847">
+ <use
+ xlink:href="#note_250x20"
+ id="use843" />
+ <text
+ x="10"
+ y="15"
+ class="text_comment"
+ id="text845">Creates backend processes</text>
+ </g>
+ <g
+ transform="translate(360, 281)"
+ id="g853">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle849" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text851">2</text>
+ </g>
+ <!-- backend process' access to individual memory -->
+ <path
+ d="M 460,300 v -100"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path855" />
+ <!-- its access to shared buffers and WAL buffers -->
+ <path
+ d="M 498,300 v -205 h 30"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path857" />
+ <path
+ d="M 508,300 v -165 h 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path859" />
+ <!-- WAL writer -->
+ <g
+ transform="translate(550, 220)"
+ id="g865">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect861" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text863">WAL Writer</text>
+ </g>
+ <path
+ d="M 590,150 v 65"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path867" />
+ <path
+ d="M 590,255 v 230"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path869" />
+ <!-- Checkpoiner -->
+ <g
+ transform="translate(610, 340)"
+ id="g875">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect871" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text873">Checkpointer</text>
+ </g>
+ <path
+ d="M 740,110 v 220"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path877" />
+ <path
+ d="M 605,355 h -130 v 130"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path879" />
+ <path
+ d="M 700,330 v -180"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path881" />
+ <g
+ transform="translate(570, 330)"
+ id="g889">
+ <use
+ xlink:href="#note_100x35"
+ x="50"
+ y="-50"
+ id="use883" />
+ <text
+ x="60"
+ y="-35"
+ class="text_comment"
+ id="text885">Checkpoint</text>
+ <text
+ x="60"
+ y="-20"
+ class="text_comment"
+ id="text887">Record</text>
+ </g>
+ <!-- BG writer -->
+ <g
+ transform="translate(610, 380)"
+ id="g895">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect891" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text893">Background Writer</text>
+ </g>
+ <path
+ d="M 770,110 v 260"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path897" />
+ <path
+ d="M 605,395 h -120 v 90"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path899" />
+ <!-- Archiver -->
+ <g
+ transform="translate(610, 420)"
+ id="g905">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect901" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text903">WAL Archiver</text>
+ </g>
+ <path
+ d="M 620,485 l 30,-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path907" />
+ <path
+ d="M 690,455 l 30, 30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path909" />
+ <!-- Vacuum -->
+ <g
+ transform="translate(135, 380)"
+ id="g919">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect911" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text913">AutoVacuum</text>
+ <path
+ d="M 5,0 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path915" />
+ <path
+ d="M 10,-5 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path917" />
+ </g>
+ <!-- Log Writer -->
+ <g
+ transform="translate(135, 430)"
+ id="g925">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect921" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text923">Log Writer</text>
+ </g>
+ <!-- Stats Collector -->
+ <g
+ transform="translate(290, 370)"
+ id="g931">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect927" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text929">Stats Collector</text>
+ </g>
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g
+ transform="translate(145, 490)"
+ id="g941">
+ <use
+ xlink:href="#disc"
+ id="use933" />
+ <text
+ x="35"
+ y="45"
+ class="text_normal"
+ id="text935">Log</text>
+ <text
+ x="20"
+ y="60"
+ class="text_small"
+ id="text937">text lines,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text939">sequential</text>
+ </g>
+ <path
+ d="M 195,465 v 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path943" />
+ <g
+ transform="translate(410, 490)"
+ id="g955">
+ <use
+ xlink:href="#disc"
+ id="use945" />
+ <text
+ x="10"
+ y="40"
+ class="text_normal"
+ id="text947">Heap and</text>
+ <text
+ x="25"
+ y="55"
+ class="text_normal"
+ id="text949">Index</text>
+ <text
+ x="15"
+ y="70"
+ class="text_small"
+ id="text951">binary blocks,</text>
+ <text
+ x="30"
+ y="80"
+ class="text_small"
+ id="text953">random</text>
+ </g>
+ <path
+ d="M 450,485 v -135"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path957" />
+ <g
+ transform="translate(295, 420)"
+ id="g967">
+ <use
+ xlink:href="#note_170x50"
+ id="use959" />
+ <text
+ x="5"
+ y="15"
+ class="text_comment"
+ id="text961">Read heap and index</text>
+ <text
+ x="5"
+ y="30"
+ class="text_comment"
+ id="text963">pages and transfer</text>
+ <text
+ x="5"
+ y="45"
+ class="text_comment"
+ id="text965">them to shared_buffers</text>
+ </g>
+ <g
+ transform="translate(550, 490)"
+ id="g977">
+ <use
+ xlink:href="#disc"
+ id="use969" />
+ <text
+ x="30"
+ y="45"
+ class="text_normal"
+ id="text971">WAL</text>
+ <text
+ x="10"
+ y="60"
+ class="text_small"
+ id="text973">binary records,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text975">sequential</text>
+ </g>
+ <g
+ transform="translate(690, 490)"
+ id="g985">
+ <use
+ xlink:href="#disc"
+ id="use979" />
+ <text
+ x="16"
+ y="45"
+ class="text_normal"
+ id="text981">Archived</text>
+ <text
+ x="36"
+ y="60"
+ class="text_normal"
+ id="text983">WAL</text>
+ </g>
+ <!-- boarder between client and server side -->
+ <path
+ d="M 110,20 v 550"
+ stroke="black"
+ fill="none"
+ id="path987" />
+ <g
+ transform="translate(123, 190) rotate(90)"
+ id="g993">
+ <use
+ xlink:href="#note_200x20"
+ id="use989" />
+ <text
+ class="text_comment"
+ x="10"
+ y="15"
+ id="text991">Via TCP/IP or socket</text>
+ </g>
+ <!-- right side -->
+ <g
+ transform="translate(850, 0) rotate(90)"
+ id="g1001">
+ <text
+ class="text_big"
+ x="95"
+ id="text995">RAM</text>
+ <text
+ class="text_big"
+ x="250"
+ id="text997">PROCESSES</text>
+ <text
+ class="text_big"
+ x="500"
+ id="text999">FILES</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-raw.svg b/doc/src/sgml/images/ram-proc-file-raw.svg
new file mode 100644
index 0000000000..8169295584
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-raw.svg
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="600px"
+ viewBox="0 0 900 600">
+
+ <title>PG Overall Server Architecture</title>
+
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Some notes in different sizes -->
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>UML Note (200 x 20 px)</title>
+ <path d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>UML Note (250 x 20 px)</title>
+ <path d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>UML Note (100 x 35 px)</title>
+ <path d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>UML Note (170 x 50 px)</title>
+ <path d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- UML states (used for buffers) -->
+ <symbol id="state_300x120">
+ <title>UML State (300x120)</title>
+ <rect x="0" y="0" width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>UML State (350x120)</title>
+ <rect x="0" y="0" width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- Discs -->
+ <symbol id="disc" stroke="blue" fill="none" >
+ <title>Disc</title>
+ <ellipse cx="51" cy="13" rx="50" ry="12" /> <!-- top -->
+ <path d="M 1,13 v 60" /> <!-- left -->
+ <path d="M 101,13 v 60" /> <!-- right -->
+ <path d="M 1,73 A 50, 12, 0, 0, 0, 101,73" /> <!-- bottom -->
+ </symbol>
+
+ <!-- Laptop -->
+ <symbol id="laptop" stroke="black" fill="none" >
+ <title>Laptop</title>
+ <path d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54" />
+ <rect x="23" y="3" width="48" height="34" />
+ <!-- symbolize some lines -->
+ <path d="M 30,10 h 20" />
+ <path d="M 30,15 h 25" />
+ <path d="M 30,20 h 10" />
+ <path d="M 30,30 h 20" />
+ <!-- symbolize keyboard -->
+ <path d="M 25,50 h 45 l 2,2 h -50 z " />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption, client side -->
+ <text x="15" y="40" class="text_big">Client</text>
+ <text x="140" y="40" class="text_big">Server</text>
+ <use xlink:href="#laptop" x="5" y="210" />
+
+
+ <!-- individual memory -->
+ <g transform="translate(130, 70)">
+ <use xlink:href="#state_350x120" x="0" y="0" />
+ <text x="5" y="20" class="text_normal">maintenance_work_mem (per connection)</text>
+ <text x="5" y="45" class="text_normal">work_mem (per query operation)</text>
+ <text x="5" y="70" class="text_normal">autovacuum_work_mem (per worker process)</text>
+ <text x="5" y="95" class="text_normal">temp_buffer (per connection)</text>
+ <text x="5" y="110" class="text_normal">...</text>
+ <use xlink:href="#note_200x20" x="140" y="-15" />
+ <text x="150" y="0" class="text_comment">Individual Memory</text>
+ </g>
+
+ <!-- shared memory -->
+ <g transform="translate(520, 70)">
+ <use xlink:href="#state_300x120" x="0" y="0" />
+ <text x="10" y="30" class="text_normal">shared_buffers (heap and index)</text>
+ <text x="10" y="70" class="text_normal">wal_buffers (WAL records)</text>
+ <text x="10" y="100" class="text_normal">...</text>
+ <use xlink:href="#note_250x20" x="40" y="-15" />
+ <text x="50" y="0" class="text_comment">Shared Memory (per Instance)</text>
+ </g>
+
+ <!-- postmaster -->
+ <g transform="translate(180, 215)">
+ <rect width="250" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Postmaster</text>
+ </g>
+ <path d="M 90,230 h 75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 230)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">1</text>
+ </g>
+
+ <!-- backend processes -->
+ <g transform="translate(150, 315)">
+ <rect width="370" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Backend processes (one per connection)</text>
+ <path d="M 5,0 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <path d="M 90,240 153,303" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 290)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">3</text>
+ </g>
+
+ <!-- connection between postmaster and backend processes -->
+ <path d="M 360,250 v 50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180, 255)">
+ <use xlink:href="#note_250x20" />
+ <text x="10" y="15" class="text_comment">Creates backend processes</text>
+ </g>
+ <g transform="translate(360, 281)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">2</text>
+ </g>
+
+ <!-- backend process' access to individual memory -->
+ <path d="M 460,300 v -100" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <!-- its access to shared buffers and WAL buffers -->
+ <path d="M 498,300 v -205 h 30" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M 508,300 v -165 h 20" stroke="black" fill="none"
+ marker-end="url(#arrowhead_end)"/>
+
+ <!-- WAL writer -->
+ <g transform="translate(550, 220)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Writer</text>
+ </g>
+ <path d="M 590,150 v 65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 590,255 v 230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Checkpoiner -->
+ <g transform="translate(610, 340)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Checkpointer</text>
+ </g>
+ <path d="M 740,110 v 220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,355 h -130 v 130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 700,330 v -180" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570, 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50" />
+ <text x="60" y="-35" class="text_comment">Checkpoint</text>
+ <text x="60" y="-20" class="text_comment">Record</text>
+ </g>
+
+ <!-- BG writer -->
+ <g transform="translate(610, 380)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Background Writer</text>
+ </g>
+ <path d="M 770,110 v 260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,395 h -120 v 90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Archiver -->
+ <g transform="translate(610, 420)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Archiver</text>
+ </g>
+ <path d="M 620,485 l 30,-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 690,455 l 30, 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Vacuum -->
+ <g transform="translate(135, 380)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">AutoVacuum</text>
+ <path d="M 5,0 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <!-- Log Writer -->
+ <g transform="translate(135, 430)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Log Writer</text>
+ </g>
+
+ <!-- Stats Collector -->
+ <g transform="translate(290, 370)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Stats Collector</text>
+ </g>
+
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g transform="translate(145, 490)">
+ <use xlink:href="#disc" />
+ <text x="35" y="45" class="text_normal">Log</text>
+ <text x="20" y="60" class="text_small">text lines,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+ <path d="M 195,465 v 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(410, 490)">
+ <use xlink:href="#disc" />
+ <text x="10" y="40" class="text_normal">Heap and</text>
+ <text x="25" y="55" class="text_normal">Index</text>
+ <text x="15" y="70" class="text_small">binary blocks,</text>
+ <text x="30" y="80" class="text_small">random</text>
+ </g>
+ <path d="M 450,485 v -135" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(295, 420)">
+ <use xlink:href="#note_170x50" />
+ <text x="5" y="15" class="text_comment">Read heap and index</text>
+ <text x="5" y="30" class="text_comment">pages and transfer</text>
+ <text x="5" y="45" class="text_comment">them to shared_buffers</text>
+ </g>
+
+ <g transform="translate(550, 490)">
+ <use xlink:href="#disc" />
+ <text x="30" y="45" class="text_normal">WAL</text>
+ <text x="10" y="60" class="text_small">binary records,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+
+ <g transform="translate(690, 490)">
+ <use xlink:href="#disc" />
+ <text x="16" y="45" class="text_normal">Archived</text>
+ <text x="36" y="60" class="text_normal">WAL</text>
+ </g>
+
+ <!-- boarder between client and server side -->
+ <path d="M 110,20 v 550" stroke="black" fill="none" />
+ <g transform="translate(123, 190) rotate(90)">
+ <use xlink:href="#note_200x20" />
+ <text class="text_comment" x="10" y ="15">Via TCP/IP or socket</text>
+ </g>
+
+ <!-- right side -->
+ <g transform="translate(850, 0) rotate(90)">
+ <text class="text_big" x="95">RAM</text>
+ <text class="text_big" x="250">PROCESSES</text>
+ <text class="text_big" x="500">FILES</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink-svgo.svg b/doc/src/sgml/images/wraparound-ink-svgo.svg
new file mode 100644
index 0000000000..9882d2be23
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink-svgo.svg
@@ -0,0 +1,40 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="280" viewBox="0 0 850 280">
+ <title>
+ Cyclic usage of XIDs
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="370" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ Cyclic usage of XIDs modulo 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan>
+ </text>
+ <g fill="none" transform="translate(170 150)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_095" startOffset="30.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="30%">(1)</textPath> <textPath xlink:href="#Path_095" startOffset="45.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(2)</textPath> <textPath xlink:href="#Path_095" startOffset="50.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="50%">(3)</textPath> <textPath xlink:href="#Path_095" startOffset="62.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="62%">(4)</textPath>
+ </text>
+ </g>
+ <g class="text_normal">
+ <text transform="translate(400 130)">
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25" transform="translate(400 130)">
+ 1: oldest <tspan font-weight="700">active</tspan> xid (pg_stat_activity.backend_xmin)
+ </text>
+ <text y="50" transform="translate(400 130)">
+ 2: xmin of one row version
+ </text>
+ <text y="75" transform="translate(400 130)">
+ 3: xmax of the same row version
+ </text>
+ <text y="100" transform="translate(400 130)">
+ 4: jungest xid (txid_current)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink.svg b/doc/src/sgml/images/wraparound-ink.svg
new file mode 100644
index 0000000000..a9c51f4e43
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="280px"
+ viewBox="0 0 850 280"
+ id="svg1072"
+ sodipodi:docname="wraparound-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata1076">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Cyclic usage of XIDs</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1193"
+ inkscape:window-height="788"
+ id="namedview1074"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="140"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg1072" />
+ <title
+ id="title1009">Cyclic usage of XIDs</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style1011">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs1016">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect1018" />
+ <text
+ class="text_big"
+ x="370"
+ y="40"
+ id="text1024">Cyclic usage of XIDs modulo 2
+ <tspan
+ dy="-5"
+ id="tspan1020">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1022">32</tspan>
+</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 150)"
+ id="g1052">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle1026" />
+ <text
+ class="text_normal"
+ id="text1050">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath1028">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath1030">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath1032">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="30.5%"
+ id="textPath1034">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="30%"
+ id="textPath1036">(1)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="45.5%"
+ id="textPath1038">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath1040">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="50.5%"
+ id="textPath1042">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="50%"
+ id="textPath1044">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="62.5%"
+ id="textPath1046">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="62%"
+ id="textPath1048">(4)</textPath>
+ </text>
+ </g>
+ <g
+ class="text_normal"
+ transform="translate(400 130)"
+ id="g1070">
+ <text
+ id="text1058">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan1054">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1056">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text1062">1: oldest <tspan
+ style="font-weight:bold"
+ id="tspan1060">active</tspan>
+ xid (pg_stat_activity.backend_xmin)</text>
+ <text
+ y="50"
+ id="text1064">2: xmin of one row version</text>
+ <text
+ y="75"
+ id="text1066">3: xmax of the same row version</text>
+ <text
+ y="100"
+ id="text1068">4: jungest xid (txid_current)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-raw.svg b/doc/src/sgml/images/wraparound-raw.svg
new file mode 100644
index 0000000000..9406f52970
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-raw.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="280px"
+ viewBox="0 0 850 280" >
+
+ <title>Cyclic usage of XIDs</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="370" y="40">Cyclic usage of XIDs modulo 2
+ <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan></text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 150)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_095" startOffset="30.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="30%" >(1)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="45.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(2)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="50.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="50%" >(3)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="62.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="62%" >(4)</textPath>
+ </text>
+ </g>
+
+ <g class="text_normal" transform="translate(400 130)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: oldest <tspan style="font-weight:bold">active</tspan> xid (pg_stat_activity.backend_xmin)</text>
+ <text y="50">2: xmin of one row version</text>
+ <text y="75">3: xmax of the same row version</text>
+ <text y="100">4: jungest xid (txid_current)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index c41ce9499b..7913f45897 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -62,6 +62,7 @@ break is not needed in a wider output rendering.
&start;
&query;
&advanced;
+ &architecture;
</part>
diff --git a/doc/src/sgml/query.sgml b/doc/src/sgml/query.sgml
index c0889743c4..b1906c6e36 100644
--- a/doc/src/sgml/query.sgml
+++ b/doc/src/sgml/query.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/query.sgml -->
<chapter id="tutorial-sql">
- <title>The <acronym>SQL</acronym> Language</title>
+ <title>Fundamentals of the <acronym>SQL</acronym> Language</title>
<sect1 id="tutorial-sql-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml
index 9bb5c1a6d5..8751410179 100644
--- a/doc/src/sgml/start.sgml
+++ b/doc/src/sgml/start.sgml
@@ -53,7 +53,7 @@
<sect1 id="tutorial-arch">
- <title>Architectural Fundamentals</title>
+ <title>Client/Server Model</title>
<para>
Before we proceed, you should understand the basic
@@ -68,34 +68,55 @@
client/server model. A <productname>PostgreSQL</productname>
session consists of the following cooperating processes
(programs):
+ </para>
- <itemizedlist>
- <listitem>
- <para>
- A server process, which manages the database files, accepts
- connections to the database from client applications, and
- performs database actions on behalf of the clients. The
- database server program is called
- <filename>postgres</filename>.
- <indexterm><primary>postgres</primary></indexterm>
- </para>
- </listitem>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A process at the server site with the name
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ <indexterm><primary>postgres</primary></indexterm>
+ It accepts connection requests from client applications, starts
+ (<quote>forks</quote>) a new <glossterm linkend="glossary-backend">
+ Backend process</glossterm> for each of them, and passes
+ the connection to it. From that point on, the client and the new
+ <firstterm>Backend process</firstterm>
+ communicate directly without intervention by the original
+ <firstterm>postgres</firstterm> process. Thus, the
+ <firstterm>postgres</firstterm> process is always running, waiting
+ for new client connections, whereas clients and associated
+ <firstterm>Backend processes</firstterm> come and go.
+ (All of this is of course invisible to the user. We only mention it
+ here for completeness.)
+ </para>
+ </listitem>
- <listitem>
- <para>
- The user's client (frontend) application that wants to perform
- database operations. Client applications can be very diverse
- in nature: a client could be a text-oriented tool, a graphical
- application, a web server that accesses the database to
- display web pages, or a specialized database maintenance tool.
- Some client applications are supplied with the
- <productname>PostgreSQL</productname> distribution; most are
- developed by users.
- </para>
- </listitem>
+ <listitem>
+ <para>
+ A group of processes at the server site, the <glossterm
+ linkend="glossary-instance">instance</glossterm>, to which also the
+ <firstterm>postgres</firstterm> process belongs. Their duties are
+ handling of central, common database activities like file access,
+ vacuum, <glossterm linkend="glossary-checkpoint">checkpoints</glossterm>,
+ replication, and more. The mentioned <firstterm>Backend processes</firstterm>
+ delegate those actions to the <firstterm>instance</firstterm>.
+ </para>
+ </listitem>
- </itemizedlist>
- </para>
+ <listitem>
+ <para>
+ The user's client (frontend) application that wants to perform
+ database operations. Client applications can be very diverse
+ in nature: a client could be a text-oriented tool, a graphical
+ application, a web server that accesses the database to
+ display web pages, or a specialized database maintenance tool.
+ Some client applications are supplied with the
+ <productname>PostgreSQL</productname> distribution; most are
+ developed by users.
+ </para>
+ </listitem>
+
+ </itemizedlist>
<para>
As is typical of client/server applications, the client and the
On 2020-07-17 11:32, Jürgen Purtz wrote:
On 12.07.20 22:45, Daniel Gustafsson wrote:
This patch no longer applies, due to conflicts in start.sgml, can you
please
submit a rebased version?cheers ./daniel
New version attached.
[0005-architecture.patch]
Hi,
I went through the architecture.sgml file once, and accumulated the
attached edits.
There are still far too many Unneeded Capitals On Words for my taste but
I have not changed many of those. We could use some more opinions on
that, I suppose. (if it becomes too silent maybe include the
pgsql-hackers again?)
Thanks,
Erik Rijkers
Show quoted text
--
Jürgen Purtz
Attachments:
architecture-20200718.sgmltext/x-diff; name=architecture-20200718.sgmlDownload
--- doc/src/sgml/architecture.sgml.orig 2020-07-17 16:24:04.345941142 +0200
+++ doc/src/sgml/architecture.sgml 2020-07-18 19:04:30.694039877 +0200
@@ -4,36 +4,36 @@
<title>Architectural and implementational Cornerstones</title>
<para>
- Every DBMS implements basic strategies to achieve a fast and
+ Every DBMS implements basic strategies for a fast and
robust system. This chapter provides an overview of what
techniques <productname>PostgreSQL</productname> uses to
- reach this aim.
+ achieve this.
</para>
<sect1 id="tutorial-ram-proc-file">
<title>Collaboration of Processes, RAM, and Files</title>
<para>
- As is a matter of course, in a client/server architecture
+ In a client/server architecture
clients do not have direct access to the database. Instead,
- they merely send requests to the server-side and receive
- according information from there. In the case of
+ they send requests to the server and receive
+ the requested information. In the case of
<productname>PostgreSQL</productname>, at the server-side
there is one process per client, the so-called
<glossterm linkend="glossary-backend">Backend process</glossterm>.
It acts in close cooperation with the
<glossterm linkend="glossary-instance">Instance</glossterm> which
- is a group of tightly coupled other server-side processes plus a
+ is a group of server-side processes plus a
<glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>
area.
</para>
<para>
- At start time, an instance is initiated by the
- <glossterm linkend="glossary-postmaster">Postmaster</glossterm>
+ At startup time, an instance is initiated by the
+ <glossterm linkend="glossary-postmaster">postmaster</glossterm>
process.
- It loads the configuration files, allocates the
+ The postmaster process loads the configuration files, allocates
<glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>,
- and starts the comprehensive network of processes:
+ and starts a network of processes:
<glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
<glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
<glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
@@ -65,8 +65,8 @@
Whenever a client application tries to connect to a
<glossterm linkend="glossary-database">database</glossterm>,
this request is handled in a first step by the <firstterm>
- Postgres process</firstterm>. It checks the authorization,
- starts a new <firstterm>Backend process</firstterm>,
+ postgres process</firstterm>. It checks authorization,
+ starts a new <firstterm>backend process</firstterm>,
and instructs the client application to connect to it. All
further client requests go to this process and are handled
by it.
@@ -83,20 +83,20 @@
<glossterm linkend="glossary-index">index</glossterm> files.
Because files are often larger than memory, it's likely that
the desired information is not (completely) available
- in the RAM. In this case the <firstterm>Backend process</firstterm>
+ in RAM. In this case the <firstterm>Backend process</firstterm>
must transfer additional file pages to
<firstterm>Shared Memory</firstterm>. Files are physically
organized in pages. Every transfer between files and
- RAM is performed in units of complete pages. Such transfers
- don't change the size or layout of pages.
+ RAM is performed in units of complete pages; such transfers
+ do not change the size or layout of pages.
</para>
<para>
- Reading file pages is notedly slower than reading
- RAM. This is the primary motivation for the existence of
+ Reading file pages is much slower than reading
+ RAM. This is the primary motivation for the usage of
<firstterm>Shared Memory</firstterm>. As soon as one
of the <firstterm>Backend processes</firstterm> has
- read pages into memory, those pages are available for all
+ read pages into memory, those pages become available for all
other <firstterm>Backend processes</firstterm> for direct
access in RAM.
</para>
@@ -121,13 +121,13 @@
First, whenever the content of a page changes, a
<glossterm linkend="glossary-wal-record">WAL record</glossterm>
is created out
- of the delta-information (difference between old and
- new content) and stored in another area of the
+ of the delta-information (difference between the old and
+ the new content) and stored in another area of
<firstterm>Shared Memory</firstterm>. These
<firstterm>WAL records</firstterm> are read by the
<firstterm>WAL Writer</firstterm> process,
which runs in parallel to the <firstterm>Backend
- processes</firstterm> and all other processes of
+ processes</firstterm> and other processes of
the <firstterm>Instance</firstterm>. It writes
the continuously arising <firstterm>WAL records</firstterm> to
the end of the current
@@ -137,7 +137,7 @@
to data files with <firstterm>heap</firstterm>
and <firstterm>index</firstterm> information.
As mentioned, this WAL-writing happens
- in an independent process. Nevertheless, all
+ in an independent process. All
<firstterm>WAL records</firstterm> created out of one
<firstterm>dirty page</firstterm> must be transferred
to disk before the <firstterm>dirty page</firstterm>
@@ -146,35 +146,34 @@
<para>
Second, the transfer of <firstterm>dirty buffers</firstterm>
- from <firstterm>Shared Memory</firstterm> to files must
- take place. This is the primary duty of the
+ from <firstterm>Shared Memory</firstterm> to file must
+ take place. This is the primary task of the
<firstterm>Background Writer</firstterm> process. Because
I/O activities can block other processes significantly,
it starts periodically and acts only for a short period.
- Doing so, his expensive I/O activities are spread over
- time, avoiding huge I/O peaks. Also, the <firstterm>
+ Doing so, its expensive I/O activities are spread over
+ time, avoiding debilitating I/O peaks. Also, the <firstterm>
Checkpointer</firstterm> process transfers
- <firstterm>dirty buffers</firstterm> to files —
+ <firstterm>dirty buffers</firstterm> to file —
see next paragraph.
</para>
<para>
- The <firstterm>Checkpointer</firstterm> has a special
- duty. As its name suggests, it has to create
- <firstterm>Checkpoints</firstterm>. Such a
+ The <firstterm>Checkpointer</firstterm> creates
+ <firstterm>Checkpoints</firstterm>. A
<glossterm linkend="glossary-checkpoint">Checkpoint</glossterm>
is a point in time when all older <firstterm>dirty buffers</firstterm>,
all older <firstterm>WAL records</firstterm>, and
finally a special <firstterm>Checkpoint record</firstterm>
have been written and flushed to disk.
- After a <firstterm>Checkpoint</firstterm>,
+ After a <firstterm>Checkpoint</firstterm>, we say
data files and <firstterm>WAL files</firstterm> are in sync.
In case of a recovery (after a crash of the instance)
- it is known that the information of all
+ it can be relied upon that the information of all
<firstterm>WAL records</firstterm> preceding
the last <firstterm>Checkpoint record</firstterm>
- is already integrated into the data files. This
- speeds up a possibly occurring recovery.
+ were already integrated into the data files. This
+ speeds up the recovery.
</para>
<para>
@@ -184,7 +183,7 @@
Those <firstterm>WAL files</firstterm> — in combination with
a previously taken <firstterm>Base Backup</firstterm> —
are necessary to restore a database after a crash of the
- disk, where data files have been stored. Therefore it is
+ disk on which data files have been stored. Therefore it is
recommended to transfer a copy of the <firstterm>
WAL files</firstterm>
to a second, independent place. The purpose of the
@@ -201,10 +200,10 @@
</para>
<para>
- The <glossterm linkend="glossary-logger">Logger</glossterm> writes
+ The <glossterm linkend="glossary-logger">Logger</glossterm> process writes
text lines about serious and less serious events which can happen
- during database access, e.g., wrong password, no permission,
- long-running queries, ... .
+ during database access, e.g. wrong password, no permission,
+ long-running queries, etc.
</para>
</sect1>
@@ -214,16 +213,17 @@
<para>
<!-- TODO: Link to cluster -->
- On a <glossterm linkend="glossary-server">Server</glossterm>
- exists one or more <glossterm linkend="glossary-instance">Cluster</glossterm>,
- each of them contains three or more
- <glossterm linkend="glossary-database">databases</glossterm>, each
- database contains many <glossterm linkend="glossary-schema">schemas</glossterm>,
- a schema contains <glossterm linkend="glossary-table">tables</glossterm>,
+ A <glossterm linkend="glossary-server">Server</glossterm>
+ contains one or more <glossterm linkend="glossary-instance">Clusters</glossterm>.
+ Each cluster contains three or more
+ <glossterm linkend="glossary-database">databases</glossterm>. Each
+ database can contain many <glossterm linkend="glossary-schema">schemas</glossterm>
+ (one schema, 'public', is provided by default).
+ A schema can contain <glossterm linkend="glossary-table">tables</glossterm>,
<glossterm linkend="glossary-view">views</glossterm>, and a lot of other objects.
Each <firstterm>table</firstterm> or <firstterm>view</firstterm>
- belongs to a single <firstterm>schema</firstterm>; they cannot
- belong to another <firstterm>schema</firstterm>. The same is
+ belongs to a single <firstterm>schema</firstterm> only; they cannot
+ belong to another <firstterm>schema</firstterm> as well. The same is
true for the schema/database and database/cluster relation.
<xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
this hierarchy.
@@ -254,30 +254,30 @@
<para>
<literal>template0</literal> is the very first
<firstterm>database</firstterm> of any
- <firstterm>cluster</firstterm>. C-routines create
- <literal>template0</literal> during the initialization phase of
- the <firstterm>cluster</firstterm>.
- In a second step, <literal>template1</literal> is generated
- as a copy of <literal>template0</literal>, and finally
+ <firstterm>cluster</firstterm>.
+ Database <literal>template0</literal> is created during the
+ initialization phase of the <firstterm>cluster</firstterm>.
+ In a second step, database <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal>, and finally database
<literal>postgres</literal> is generated as a copy of
- <literal>template1</literal>. All other
+ <literal>template1</literal>. Any
<glossterm linkend="app-createdb">new databases</glossterm>
- of this <firstterm>cluster</firstterm>,
- such as <literal>my_db</literal>, are also copied from
- <literal>template1</literal>. Due to the unique
- role of <literal>template0</literal> as the pristine origin
+ of the <firstterm>cluster</firstterm> that a user might need,
+ such as <literal>my_db</literal>, will be copied from the
+ <literal>template1</literal> database. Due to the unique
+ role of <literal>template0</literal> as the pristine original
of all other <firstterm>databases</firstterm>, no client
can connect to it.
</para>
<para>
- Every database contains <glossterm linkend="glossary-schema">
- schemas</glossterm>, and
+ Every database must contain <glossterm linkend="glossary-schema">
+ at least one schema</glossterm> because
<firstterm>schemas</firstterm> contain the other
<glossterm linkend="glossary-sql-object">SQL Objects</glossterm>.
<firstterm>Schemas</firstterm> are namespaces for
their <firstterm>SQL objects</firstterm> and ensure — with one
- exception — that within their scope names are used only once across all
+ exception — that within their scope, names are used only once across all
types of <firstterm>SQL objects</firstterm>. E.g., it is not possible
to have a table <literal>employee</literal> and a view
<literal>employee</literal> within the same
@@ -294,10 +294,10 @@
<para>
Some <firstterm>schemas</firstterm> are predefined.
<literal>public</literal> acts as the default
- <firstterm>schema</firstterm> and contains all such
- <firstterm>SQL objects</firstterm>, which are created
- within <literal>public</literal> or without using any schema
- name. <literal>public</literal> shall not contain user-defined
+ <firstterm>schema</firstterm> and contains all
+ <firstterm>SQL objects</firstterm> which are created
+ within <literal>public</literal> or without using an explicit schema
+ name. <literal>public</literal> should not contain user-defined
<firstterm>SQL objects</firstterm>. Instead, it is recommended to
create a separate <firstterm>schema</firstterm> that
holds individual objects like application-specific tables or
@@ -310,7 +310,7 @@
</para>
<para>
- There are a lot of different <firstterm>SQL object</firstterm>
+ There are many different <firstterm>SQL object</firstterm>
types: <firstterm>database, schema, table, view, materialized
view, index, constraint, sequence, function, procedure,
trigger, role, data type, operator, tablespace, extension,
@@ -353,7 +353,7 @@
<firstterm>Cluster</firstterm> has its root directory
somewhere in the file system. In many cases, the environment
variable <literal>PGDATA</literal> points to this directory.
- The example of the survey shown in
+ The example shown in
<xref linkend="tutorial-directories-figure"/> uses
<literal>data</literal> as the name of this root directory.
</para>
@@ -405,7 +405,7 @@
</para>
<para>
- Another prominent subdirectory is <literal>global</literal>.
+ Another subdirectory is <literal>global</literal>.
In analogy to the <firstterm>database</firstterm>-specific
subdirectories, there are files containing information about
<glossterm linkend="glossary-sql-object">Global SQL objects</glossterm>.
@@ -440,12 +440,12 @@
<para>
In the root directory <literal>data</literal>
there are also some files. In many cases, the configuration
- files of this <firstterm>cluster</firstterm> are stored
+ files of the <firstterm>cluster</firstterm> are stored
here. As long as the <firstterm>instance</firstterm>
is up and running, the file
<literal>postmaster.pid</literal> exists here
and contains the ID (pid) of the
- <firstterm>Postmaster</firstterm> process which
+ <firstterm>postmaster</firstterm> process which
has started the instance.
</para>
@@ -464,23 +464,23 @@
support many clients at the same time. Therefore, it is necessary to
protect concurrently running requests from unwanted overwriting
of other's data as well as from reading inconsistent data. Imagine an
- online shop offering the last copy of an article. Two clients show the
- article at their user interface. After a while, but at the same time,
+ online shop offering the last copy of an article. Two clients have the
+ article displayed at their user interface. After a while, but at the same time,
both users decide to put it to their shopping cart or even to buy it.
Both have seen the article, but only one can be allowed to get it.
The database must bring the two requests in a row, permit the access
- to one of them, block the other, and inform this one about the
- situation that the data was changed by a different process.
+ to one of them, block the other, and inform the blocked client
+ that the data was changed by a different process.
</para>
<para>
A first approach to implement protections against concurrent
accesses to the same data may be the locking of critical
- rows. There are two main categories of such techniques:
+ rows. Two such techniques are:
<emphasis>Optimistic Concurrency Control</emphasis> (OCC)
and <emphasis>Two Phase Locking</emphasis> (2PL).
- <productname>PostgreSQL</productname> implements the more
- sophisticated technique <firstterm>Multiversion Concurrency
+ <productname>PostgreSQL</productname> implements a third, more
+ sophisticated technique: <firstterm>Multiversion Concurrency
Control</firstterm> (MVCC). The crucial advantage of MVCC
over other technologies gets evident in multiuser OLTP
environments with a massive number of concurrent write
@@ -493,15 +493,15 @@
<para>
Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
- a new version of the same row when any data-change takes place. To
- distinguish between these versions as well as to track the timeline
+ a new version of the row when a data-change takes place. To
+ distinguish between these two versions and to track the timeline
of the row, each of the versions contains, in addition to their user-defined
columns, two special system columns, which are not visible
for the usual <command>SELECT * FROM ...</command> command.
The column <literal>xmin</literal> contains the transaction ID (xid)
- of the transaction, which creates this version of the row. Accordingly,
+ of the transaction, which created this version of the row. Accordingly,
<literal>xmax</literal> contains the xid of the transaction, which has
- deleted this version, respectively a zero, if the version is not
+ deleted this version, or zero, if the version is not
deleted. You can read both with the command
<command>SELECT xmin, xmax, * FROM ... </command>.
</para>
@@ -519,9 +519,9 @@
</para>
<para>
- Please note that the description in this chapter simplifies the situation
- by omitting details. When many transactions are running simultaneously,
- things can get very complicated. Sometimes they get aborted via
+ The description in this chapter simplifies by omitting detail.
+ When many transactions are running simultaneously,
+ things can get complicated. Sometimes transactions get aborted via
ROLLBACK immediately or after a lot of other activities, sometimes
a single row is involved in more than one transaction, sometimes
a client crashes, sometimes the sequence of xids restarts
@@ -567,7 +567,7 @@
changing the user data from <literal>'x'</literal> to
<literal>'y'</literal>. According to the MVCC principles,
the data in the old version of the row does not change!
- The value <literal>'x'</literal> keeps as it was before.
+ The value <literal>'x'</literal> remains as it was before.
Only <literal>xmax</literal> changes to <literal>135</literal>.
Now, this version is treated as valid exclusively for
transactions with xids from <literal>123</literal> to
@@ -591,7 +591,7 @@
<para>
Finally, a row may be deleted by a <command>DELETE</command>
- command. Even in this case, all versions of the row keep as
+ command. Even in this case, all versions of the row remain as
before. Nothing is thrown away so far! Only <literal>xmax</literal>
of the last version changes to the xid of the <command>DELETE</command>
transaction, which indicates that it is only valid for
@@ -603,14 +603,14 @@
<para>
In summary, the MVCC technology creates more and more versions
of the same row in the table's heap file and leaves them there,
- even with a <command>DELETE</command> command. The youngest
+ even after a <command>DELETE</command> command. Only the youngest
version is relevant for all future transactions. But the
system must also preserve some of the older ones for a
- certain amount of time because the possiblility exists that
- they are or could become relevant for any of the pending
+ certain amount of time because the possibility exists that
+ they are or could become relevant for any pending
transactions. Over time, also the older ones get out of scope
for ALL transactions and therefore become unnecessary.
- Nevertheless, they exist physically on the disk and occupy
+ Nevertheless, they do exist physically on the disk and occupy
space.
</para>
@@ -629,7 +629,7 @@
xids grow, old row versions get out of scope over time.
If an old row version is no longer valid for ALL existing
transactions, it's called <firstterm>dead</firstterm>. The
- space occupied by the sum of all dead row versions is
+ space occupied by all dead row versions is
called <firstterm>bloat</firstterm>.
</simpara>
</listitem>
@@ -637,7 +637,7 @@
<listitem>
<simpara>
Internally, an <command>UPDATE</command> command acts in the
- same way as a <command>DELETE</command> command, followed by
+ same way as a <command>DELETE</command> command followed by
an <command>INSERT</command> command.
</simpara>
</listitem>
@@ -646,7 +646,7 @@
<simpara>
Nothing gets wiped away — with the consequence that the database
occupies more and more disk space. It is obvious that
- this behavior has to be automatically corrected in some
+ this behavior has to be corrected in some
way. The next chapter explains how AUTOVACUUM fulfills
this task.
</simpara>
@@ -664,7 +664,7 @@
more and more disk space, the <firstterm>bloat</firstterm>.
This chapter explains how the SQL command
<firstterm>VACUUM</firstterm> and the automatically running
- <firstterm>AUTOVACUUM</firstterm> processes clear the situation
+ <firstterm>AUTOVACUUM</firstterm> processes clean up
by eliminating <firstterm>bloat</firstterm>.
</para>
@@ -672,9 +672,9 @@
<para>
<firstterm>AUTOVACUUM</firstterm> runs automatically by
default. Its default parameters as well as such for
- <firstterm>VACUUM</firstterm> fits well for most standard
+ <firstterm>VACUUM</firstterm> fit well for most standard
situations. Therefore a novice database manager can
- easily skip the rest of this chapter, which explains
+ easily skip the rest of this chapter which explains
a lot of details.
</para>
</note>
@@ -682,16 +682,16 @@
<para>
Client processes can issue the SQL command VACUUM at arbitrary
points in time. DBAs do this when they recognize special situations,
- or they start it in batch jobs, which run periodically.
+ or they start it in batch jobs which run periodically.
AUTOVACUUM processes run as part of the
<link linkend="glossary-instance">Instance</link> at the server.
- There is a constantly running AUTOVACUUM daemon. He permanently
+ There is a constantly running AUTOVACUUM daemon. It permanently
controls the state of all databases based on values that are
collected by the <link linkend="glossary-stats-collector">
Statistics Collector</link> and starts
- AUTOVACUUM processes whenever he detects certain situations.
+ AUTOVACUUM processes whenever it detects certain situations.
Thus, it's a dynamic behavior of <productname>PostgreSQL</productname>
- with the intention to tidy up — not always, but whenever it
+ with the intention to tidy up — whenever it
is appropriate.
</para>
@@ -712,7 +712,7 @@
<firstterm>Freeze</firstterm>: Mark the youngest row version
as frozen. This means that the version
is always treated as valid (visible) independent from
- the <firstterm>wraparound problematic</firstterm> (see below).
+ the <firstterm>wraparound problem</firstterm> (see below).
</simpara>
</listitem>
@@ -729,22 +729,22 @@
<simpara>
<emphasis>Statistics</emphasis>: Collect statistics about the
number of rows per table, the distribution of values, and so on,
- as the basis for query planner's decision making.
+ as the basis for decisions of the query planner.
</simpara>
</listitem>
</itemizedlist>
<para>
- The eagerness — you can call it 'aggressivity' — of the
+ The eagerness — you can call it 'aggression' — of the
operations <emphasis>eliminating bloat</emphasis> and
<emphasis>freeze</emphasis> is controlled by configuration
parameters, runtime flags, and in extreme situations by
- themselves. Because vacuum operations typically are I/O
+ the processes themselves. Because vacuum operations typically are I/O
intensive, which can hinder other activities, AUTOVACUUM
avoids performing many vacuum operations in bulk. Instead,
it carries out many small actions with time gaps in between.
- The SQL command VACUUM runs immediately without any
+ The SQL command VACUUM runs immediately and without any
time gaps.
</para>
@@ -794,8 +794,8 @@
After the vacuum operation detects a superfluous row version, it
marks its space as free for future use of writing
actions. Only in rare situations (or in the case of VACUUM FULL),
- this space is released to the operating system. In most cases,
- it keeps occupied by PostgreSQL and will be used by future
+ is this space released to the operating system. In most cases,
+ it remains occupied by PostgreSQL and will be used by future
<command>INSERT</command> or <command>UPDATE</command>
commands concerning this row or a completely different one.
</para>
@@ -827,7 +827,7 @@
<listitem>
<simpara>
When a client issues the SQL command VACUUM with the option FULL.
- Also, in this mode, the bloat disappears, but the used strategy
+ Also, in this mode, the bloat disappears, but the strategy used
is very different: In this case, the complete table is copied
to a different file skipping all outdated row versions. This
leads to a significant reduction of used disk space because
@@ -839,8 +839,8 @@
<listitem>
<simpara>
When an AUTOVACUUM process acts. For optimization
- purposes, he considers the Visibility Map in the same way as
- VACUUM. Additionally, he ignores tables with few modifications;
+ purposes, it considers the Visibility Map in the same way as
+ VACUUM. Additionally, it ignores tables with few modifications;
see <xref linkend="guc-autovacuum-vacuum-threshold"/>,
which defaults to 50 rows and
<xref linkend="guc-autovacuum-vacuum-scale-factor"/>,
@@ -864,7 +864,7 @@
a certain number of new transactions they are forced to restart
from the beginning, which is called <firstterm>wraparound</firstterm>.
Therefore the terms 'old transaction' / 'young transaction' does
- not always correlate with low / hight values of xids. Near to the
+ not always correlate with low / high values of xids. Near to the
wraparound point, there are cases where xmin has a higher value
than xmax, although their meaning is said to be older than xmax.
</para>
@@ -891,10 +891,10 @@
The use of a limited range of IDs for transactions leads
to the necessity to restart the sequence sooner or later.
This does not only have the rare consequence previously
- described that sometimes xmin is huger than xmax. The far
+ described that sometimes xmin is higher than xmax. The far
more critical problem is that whenever the system has
to evaluate a WHERE condition, it must decide which row
- versions are valid (visible) from the perspective of the
+ version is valid (visible) from the perspective of the
transaction of this query. If a wraparound couldn't happen,
this decision would be relatively easy: the xid
must be between xmin and xmax, and the corresponding
@@ -911,7 +911,7 @@
<listitem>
<simpara>
- In a first step, PostgreSQL divides the complete range of
+ As a first step, PostgreSQL divides the complete range of
possible xids into two halves with the two split-points
'txid_current' and 'txid_current + 2^31'. The half behind
'txid_current' is considered to represent xids of the
@@ -975,13 +975,13 @@
</para>
<para>
- At what point in time the freeze operation will take place?
+ At what point in time does the freeze operation take place?
<itemizedlist>
<listitem>
<simpara>
When a client issues the SQL command VACUUM with its
- FREEZE option. In this case, all such pages are
+ FREEZE option. In this case, all pages are
processed that are marked in the Visibility Map
to potentially have unfrozen rows.
</simpara>
@@ -989,12 +989,12 @@
<listitem>
<simpara>
When a client issues the SQL command VACUUM without any
- option but finds that there are xids older than
+ options but finds that there are xids older than
<xref linkend="guc-vacuum-freeze-table-age"/>
(default: 150 million) minus
<xref linkend="guc-vacuum-freeze-min-age"/>
(default: 50 million).
- As before, all such pages are processed that are
+ As before, all pages are processed that are
marked in the Visibility Map to potentially have unfrozen
rows.
</simpara>
@@ -1008,11 +1008,11 @@
<itemizedlist>
<listitem>
<simpara>
- In the <emphasis>normal mode</emphasis>, he skips
+ In the <emphasis>normal mode</emphasis>, it skips
pages with row versions that are younger than
<xref linkend="guc-vacuum-freeze-min-age"/>
(default: 50 million) and works only on pages where
- all xids are older. The skipping of jung xids prevents
+ all xids are older. The skipping of young xids prevents
work on such pages, which are likely to be changed
by one of the future SQL commands.
</simpara>
@@ -1020,7 +1020,7 @@
<listitem>
<simpara>
The process switches
- to an <emphasis>aggressive mode</emphasis> if he recognizes
+ to an <emphasis>aggressive mode</emphasis> if it recognizes
that for the processed table their oldest xid exceeds
<xref linkend="guc-autovacuum-freeze-max-age"/>
(default: 200 million). The value of the oldest unfrozen
@@ -1038,12 +1038,12 @@
<para>
In the first two cases and with autovacuum in
- <emphasis>aggressive mode</emphasis>, the system knowns
+ <emphasis>aggressive mode</emphasis>, the system knows
to which value the oldest unfrozen xid has moved forward and
logs the value in <emphasis>pg_class.relfrozenxid</emphasis>.
The distance between this value and the 'txid_current' split
point becomes smaller, and the distance to 'txid_current + 2^31'
- larger than before.
+ becomes larger than before.
</para>
<figure id="tutorial-freeze-figure">
@@ -1069,7 +1069,7 @@
running <firstterm>autovacuum daemon</firstterm>. If the
daemon detects that for a table <firstterm>
autovacuum_freeze_max_age</firstterm> is exceeded, it starts
- an AUTOVACUUM process in the <emphasis>aggressive mode</emphasis>
+ an AUTOVACUUM process in <emphasis>aggressive mode</emphasis>
(see above) — even if AUTOVACUUM is disabled.
</para>
@@ -1079,8 +1079,8 @@
The <link linkend="glossary-vm">Visibility Map</link>
(VM) contains two flags — stored as
two bits — for each page of the heap. If the first bit
- is set, it indicates that the associated page does not
- contain any bloat. If the second one is set, it indicates
+ is set, that indicates that the associated page does not
+ contain any bloat. If the second one is set, that indicates
that the page contains only frozen rows.
</para>
@@ -1099,7 +1099,7 @@
<para>
The setting of the flags is silently done by VACUUM
and AUTOVACUUM during their bloat and freeze operations.
- This is done to accelerate future vacuum actions,
+ This is done to speed up future vacuum actions,
regular accesses to heap pages, and some accesses to
the index. Every data-modifying operation on any row
version of the page clears the flags.
@@ -1122,7 +1122,7 @@
linkend="planner-stats">Query Planner</link> to make optimal
decisions for the generation of execution plans. This
information can be gathered with the SQL commands ANALYZE
- or VACUUM ANALYZE. But also autovacuum processes gather
+ or VACUUM ANALYZE. But autovacuum processes also gather
such information. Depending on the percentage of changed rows
per table <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
the autovacuum daemon starts autovacuum processes to collect
@@ -1144,7 +1144,7 @@
<link linkend="tutorial-transactions">Transactions</link>
are a fundamental concept of relational database systems.
Their essential point is that they bundle multiple
- read- or write-operations into a single, all-or-nothing
+ read- or write-operations into a single all-or-nothing
operation. Furthermore, they separate and protect concurrent
actions of different connections from each other. Thereby
they implement the ACID paradigm.
@@ -1152,7 +1152,7 @@
<para>
In <productname>PostgreSQL</productname> there are two ways
- to establish a transaction. The explicite way uses the keywords
+ to establish a transaction. The explicit way uses the keywords
<link linkend="sql-begin">BEGIN</link> and
<link linkend="sql-commit">COMMIT</link> (respectively
<link linkend="sql-rollback">ROLLBACK</link>) before
@@ -1188,9 +1188,9 @@
</para>
<para>
- The atomicity also affects the visibility of changes. All
+ The atomicity also affects the visibility of changes. No
connections running simultaneously to a data modifying
- transaction will never see any change before the
+ transaction will ever see any change before the
transaction successfully executes a <command>COMMIT</command>
— even in the lowest
<link linkend="transaction-iso">isolation level</link>
@@ -1221,7 +1221,7 @@
</para>
<para>
- <productname>PostgreSQL</productname> overcomes the
+ <productname>PostgreSQL</productname> overcomes this
problem by showing only such row versions to other
transactions whose originating transaction is
successfully committed. It skips all row versions of
@@ -1229,9 +1229,9 @@
<productname>PostgreSQL</productname> solves one more
problem. Even the single <command>COMMIT</command>
command needs a short time interval for its execution.
- Therefor its critical 'dead-or-survival' phase
+ Therefore its critical 'dead-or-survival' phase
runs in a priviledged mode where it cannot be
- interupted by other processes.
+ interrupted by other processes.
</para>
<bridgehead renderas="sect2">What are the benefits?</bridgehead>
@@ -1247,10 +1247,10 @@
the transfers of some money from one account to another.
It is obvious
that the decrease of the one and the increase of the
- other are impartible. Nevertheless, there is no particular
+ other must be indivisible. Nevertheless, there is no particular
need for an application to do something to ensure the
<glossterm linkend="glossary-atomicity">atomicity</glossterm>
- of its behavior. It's enough to surround them with
+ of this behavior. It's enough to surround them with
<command>BEGIN</command> and <command>COMMIT</command>.
</para>
@@ -1260,10 +1260,10 @@
conditions. In such cases, the application simply issues a
<command>ROLLBACK</command> command instead of a
<command>COMMIT</command>. The <command>ROLLBACK</command>
- cancels the transaction, and all changes made so far retain
+ cancels the transaction, and all changes made so far remain
invisible forever; it's like they never happened. There
is no need for the application to log its activities and
- undo every single step.
+ undo every step of the transaction separately.
</para>
<para>
@@ -1282,7 +1282,7 @@
<para>
Also, all self-evident — but possibly not obvious
— low-level demands on the database system are
- ensured; e.g., index entries for rows must become
+ ensured; e.g. index entries for rows must become
visible at the same moment as the rows themselves.
</para>
@@ -1307,7 +1307,7 @@
<para>
Nothing is perfect and failures inevitably happen.
- However, the most common types of failures are
+ However, the most common types of failure are
well known and <productname>PostgreSQL</productname>
implements strategies to overcome them.
Such strategies use parts of the previously presented
@@ -1356,7 +1356,7 @@
actions. The WAL records are written first. Second,
the data itself shall exist in the heap and index files.
In opposite to the WAL records, this part may or may
- not be transferred entirely from shared buffers to the files.
+ not have been transferred entirely from shared buffers (=RAM) to the files.
</para>
<para>
The automatic recovery searches within the WAL files for
@@ -1378,7 +1378,7 @@
<bridgehead renderas="sect3">Disk crash</bridgehead>
<para>
- If a disk crashes, the course of actions described previously
+ If a disk crashes, the course of action described previously
cannot work. It is likely that the WAL files and/or the
data and index files are no longer available. You need
to take special actions to overcome such situations.
@@ -1453,14 +1453,14 @@
<link linkend="backup-file">copy</link>
of the cluster's directory structure and files. In
case of severe problems such a copy can serve as
- the source of a recovery. But in order to get a
+ the source of recovery. But in order to get a
<emphasis>USABLE</emphasis> backup by this method,
the database server <emphasis>MUST</emphasis> be
shut down during the complete runtime of the copy
command!
</para>
<para>
- The apparent disadvantage of this method is that there
+ The obvious disadvantage of this method is that there
is a downtime where no user interaction is possible.
</para>
@@ -1515,7 +1515,7 @@
If configured, the
<glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
will automatically copy every single WAL file to a save location.
- <link linkend="backup-archiving-wal">It's configuration</link>
+ <link linkend="backup-archiving-wal">Its configuration</link>
consists mainly of a string, which contains a copy command
in the operating system's syntax. In order to protect your
data against a disk crash, the destination location
On 18.07.20 19:17, Erik Rijkers wrote:
Hi,
I went through the architecture.sgml file once, and accumulated the
attached edits.There are still far too many Unneeded Capitals On Words for my taste
but I have not changed many of those. We could use some more opinions
on that, I suppose. (if it becomes too silent maybe include the
pgsql-hackers again?)Thanks,
Erik Rijkers
The attached patch contains:
- integration of Erik's suggestions
- coordination of terms in text, graphic and glossary
- some changes in upper-case usage
- fewer usage of <firstterm> with two exceptions: The first chapter 4.1
emphasize all important terms to help beginners in their learning
process; chapter 4.5. emphasize the term 'autovacuum' to straighten the
fact that - despite its similarities - the tool autovacuum is something
else than the SQL command vacuum.
--
Jürgen Purtz
Attachments:
0007-architecture.patchtext/x-patch; charset=UTF-8; name=0007-architecture.patchDownload
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
index f6c4627c3e..be04972bd7 100644
--- a/doc/src/sgml/advanced.sgml
+++ b/doc/src/sgml/advanced.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/advanced.sgml -->
<chapter id="tutorial-advanced">
- <title>Advanced Features</title>
+ <title>Advanced SQL Features</title>
<sect1 id="tutorial-advanced-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
new file mode 100644
index 0000000000..2be9898d98
--- /dev/null
+++ b/doc/src/sgml/architecture.sgml
@@ -0,0 +1,1563 @@
+<!-- doc/src/sgml/architecture.sgml -->
+
+ <chapter id="tutorial-architecture">
+ <title>Architectural and implementational Cornerstones</title>
+
+ <para>
+ Every DBMS implements basic strategies for a fast and
+ robust system. This chapter provides an overview of what
+ techniques <productname>PostgreSQL</productname> uses to
+ achieve this.
+ </para>
+
+ <sect1 id="tutorial-ram-proc-file">
+ <title>Collaboration of Processes, RAM, and Files</title>
+ <para>
+ In a client/server architecture
+ clients do not have direct access to the database. Instead,
+ they send requests to the server and receive
+ the requested information. In the case of
+ <productname>PostgreSQL</productname>, at the server-side
+ there is one process per client, the so-called
+ <glossterm linkend="glossary-backend">Backend process</glossterm>.
+ It acts in close cooperation with the
+ <glossterm linkend="glossary-instance">instance</glossterm> which
+ is a group of tightly coupled server-side processes plus a
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>
+ area.
+ </para>
+
+ <para>
+ At startup time, an <firstterm>instance</firstterm> is initiated by the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ The <firstterm>Postmaster</firstterm> process loads the
+ configuration files, allocates
+ <firstterm>Shared Memory</firstterm>,
+ and starts a network of processes:
+ <glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
+ <glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
+ <glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
+ <glossterm linkend="glossary-wal-archiver">WAL Archiver</glossterm>,
+ <glossterm linkend="glossary-autovacuum">Autovacuum</glossterm>,
+ <glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
+ <glossterm linkend="glossary-logger">Logger</glossterm>, and more.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes
+ the main aspects of their collaboration.
+ </para>
+
+ <figure id="tutorial-ram-proc-file-figure">
+ <title>Architecture</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ Whenever a client application tries to connect to a
+ <glossterm linkend="glossary-database">database</glossterm>,
+ this request is handled in a first step by the
+ <firstterm>Postmaster</firstterm> process. It checks authorization,
+ starts a new <firstterm>Backend process</firstterm>,
+ and instructs the client application to connect to it. All
+ further client requests go to this process and are handled
+ by it.
+ </para>
+
+ <para>
+ Client requests like <command>SELECT</command> or
+ <command>UPDATE</command> usually lead to the
+ necessity to read or write some data. In a first attempt
+ the client's <firstterm>Backend process</firstterm> tries
+ to get the information out of <firstterm>Shared
+ Memory</firstterm>. This <firstterm>Shared
+ Memory</firstterm> is a mirror of parts of the
+ <glossterm linkend="glossary-heap">heap</glossterm> and
+ <glossterm linkend="glossary-index">index</glossterm> files.
+ Because files are often larger than memory, it's likely that
+ the desired information is not (completely) available
+ in RAM. In this case the <firstterm>Backend process</firstterm>
+ must transfer additional file pages to
+ <firstterm>Shared Memory</firstterm>. Files are physically
+ organized in pages. Every transfer between files and
+ RAM is performed in units of complete pages; such transfers
+ do not change the size or layout of pages.
+ </para>
+
+ <para>
+ Reading file pages is much slower than reading
+ RAM. This is the primary motivation for the usage of
+ <firstterm>Shared Memory</firstterm>. As soon as one
+ of the <firstterm>Backend processes</firstterm> has
+ read pages into memory, those pages become available for all
+ other <firstterm>Backend processes</firstterm> for direct
+ access in RAM.
+ </para>
+
+ <para>
+ <firstterm>Shared Memory</firstterm> is limited in size.
+ Sooner or later, it becomes necessary to overwrite old RAM
+ pages. As long as the content of such pages hasn't
+ changed, this is not a problem. But in
+ <firstterm>Shared Memory</firstterm> also write
+ actions take place
+ — performed by any of the <firstterm>Backend
+ processes</firstterm> (or an
+ <firstterm>autovacuum</firstterm> process,
+ or other processes). Such modified pages are called
+ <firstterm>dirty pages</firstterm>.
+ Before <firstterm>dirty pages</firstterm> can be overwritten,
+ they must be written back to disk. This is a two-step process.
+ </para>
+
+ <para>
+ First, whenever the content of a page changes, a
+ <glossterm linkend="glossary-wal-record">WAL record</glossterm>
+ is created out
+ of the delta-information (difference between the old and
+ the new content) and stored in another area of
+ <firstterm>Shared Memory</firstterm>. These
+ <firstterm>WAL records</firstterm> are read by the
+ <firstterm>WAL Writer</firstterm> process,
+ which runs in parallel to the <firstterm>Backend
+ processes</firstterm> and other processes of
+ the <firstterm>Instance</firstterm>. It writes
+ the continuously arising <firstterm>WAL records</firstterm> to
+ the end of the current
+ <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
+ Because this writing is sequential, it is much
+ faster than the more or less random access
+ to data files with <firstterm>heap</firstterm>
+ and <firstterm>index</firstterm> information.
+ As mentioned, this WAL-writing happens
+ in an independent process. All
+ <firstterm>WAL records</firstterm> created out of one
+ <firstterm>dirty page</firstterm> must be transferred
+ to disk before the <firstterm>dirty page</firstterm>
+ itself can be transferred to disk.
+ </para>
+
+ <para>
+ Second, the transfer of <firstterm>dirty buffers</firstterm>
+ from <firstterm>Shared Memory</firstterm> to file must
+ take place. This is the primary task of the
+ <firstterm>Background Writer</firstterm> process. Because
+ I/O activities can block other processes significantly,
+ it starts periodically and acts only for a short period.
+ Doing so, its expensive I/O activities are spread over
+ time, avoiding debilitating I/O peaks. Also, the <firstterm>
+ Checkpointer</firstterm> process transfers
+ <firstterm>dirty buffers</firstterm> to file —
+ see next paragraph.
+ </para>
+
+ <para>
+ The <firstterm>Checkpointer</firstterm> creates
+ <glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
+ A <firstterm>Checkpoint</firstterm>
+ is a point in time when all older <firstterm>dirty buffers</firstterm>,
+ all older <firstterm>WAL records</firstterm>, and
+ finally a special <firstterm>Checkpoint record</firstterm>
+ have been written and flushed to disk.
+ After a <firstterm>Checkpoint</firstterm>, we say
+ data files and <firstterm>WAL files</firstterm> are in sync.
+ In case of a recovery (after a crash of the instance)
+ it can be relied upon that the information of all
+ <firstterm>WAL records</firstterm> preceding
+ the last <firstterm>Checkpoint record</firstterm>
+ were already integrated into the data files. This
+ speeds up the recovery.
+ </para>
+
+ <para>
+ As a result of data changes,
+ <firstterm>WAL records</firstterm> arise and get written
+ to <firstterm>WAL files</firstterm>.
+ Those <firstterm>WAL files</firstterm> — in combination with
+ a previously taken <firstterm>Base Backup</firstterm> —
+ are necessary to restore a database after a crash of the
+ disk on which data files have been stored. Therefore it is
+ recommended to transfer a copy of the
+ <firstterm> WAL files</firstterm>
+ to a second, independent place. The purpose of the
+ <firstterm>WAL Archiver</firstterm> process is to perform
+ this copy action.
+ </para>
+
+ <para>
+ The <firstterm>Statistics Collector</firstterm> collects
+ counters about accesses to <firstterm>SQL objects</firstterm>
+ like tables, rows, indexes, pages, and more. It stores the
+ obtained information in system tables.
+ </para>
+
+ <para>
+ The <firstterm>Logger</firstterm> writes
+ text lines about serious and less serious events which can happen
+ during database access, e.g. wrong password, no permission,
+ long-running queries, etc.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-cluster-db-schema">
+ <title>The logical Perspective: Cluster, Database, Schema</title>
+
+ <para>
+ A <glossterm linkend="glossary-server">server</glossterm> contains one or more
+ <glossterm linkend="glossary-db-cluster">database clusters</glossterm>
+ (<glossterm linkend="glossary-db-cluster">clusters</glossterm>
+ for short). Each cluster contains three or more
+ <glossterm linkend="glossary-database">databases</glossterm>.
+ Each database can contain many
+ <glossterm linkend="glossary-schema">schemas</glossterm>.
+ A schema can contain
+ <glossterm linkend="glossary-table">tables</glossterm>,
+ <glossterm linkend="glossary-view">views</glossterm>, and a lot
+ of other objects. Each table or view belongs to a single schema
+ only; they cannot belong to another schema as well. The same is
+ true for the schema/database and database/cluster relation.
+ <xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
+ this hierarchy.
+ </para>
+
+ <figure id="tutorial-cluster-db-schema-figure">
+ <title>Cluster, Database, Schema</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ A cluster is the outer container for a
+ collection of databases. Clusters are created by the command
+ <xref linkend="app-initdb"/>.
+ </para>
+
+ <para>
+ <literal>template0</literal> is the very first
+ database of any cluster. Database <literal>template0</literal>
+ is created during the initialization phase of the cluster.
+ In a second step, database <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal>, and finally database
+ <literal>postgres</literal> is generated as a copy of
+ <literal>template1</literal>. Any
+ <glossterm linkend="app-createdb">new databases</glossterm>
+ of the cluster that a user might need,
+ such as <literal>my_db</literal>, will be copied from the
+ <literal>template1</literal> database. Due to the unique
+ role of <literal>template0</literal> as the pristine original
+ of all other databases, no client
+ can connect to it.
+ </para>
+
+ <para>
+ Every database must contain <glossterm linkend="glossary-schema">
+ at least one schema</glossterm> because
+ schemas contain the other
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>.
+ Schemas are namespaces for
+ their SQL objects and ensure — with one
+ exception — that within their scope, names are used only once across all
+ types of SQL objects. E.g., it is not possible
+ to have a table <literal>employee</literal> and a view
+ <literal>employee</literal> within the same
+ schema. But it is possible to have
+ two tables <literal>employee</literal> in different
+ schemas. In this case, the two tables
+ are separate objects and independent of each
+ other. The only exception to this cross-type uniqueness is that
+ <glossterm linkend="glossary-unique-constraint">unique constraints
+ </glossterm> and the according <firstterm>unique index</firstterm>
+ use the same name.
+ </para>
+
+ <para>
+ Some schemas are predefined. <literal>public</literal>
+ acts as the default schema and contains all
+ <firstterm>SQL objects</firstterm> which are created
+ within <literal>public</literal> or without using an explicit schema
+ name. <literal>public</literal> should not contain user-defined
+ SQL objects. Instead, it is recommended to
+ create a separate schema that
+ holds individual objects like application-specific tables or
+ views. <literal>pg_catalog</literal> is a schema for all tables
+ and views of the <glossterm linkend="glossary-system-catalog">
+ System Catalog</glossterm>.
+ <literal>information_schema</literal> is a schema for several
+ tables and views of the <firstterm>System Catalog</firstterm>
+ in a way that conforms to the SQL standard.
+ </para>
+
+ <para>
+ There are many different SQL object
+ types: <firstterm>database, schema, table, view, materialized
+ view, index, constraint, sequence, function, procedure,
+ trigger, role, data type, operator, tablespace, extension,
+ foreign data wrapper</firstterm>, and more. A few of them, the
+ <firstterm>Global SQL Objects</firstterm>,
+ are outside of the strict hierarchy:
+ All database names, all tablespace names, and all role names
+ are automatically known and available throughout the
+ cluster, independent from
+ the database or schema in which they where defined originally.
+ <xref linkend="tutorial-internal-objects-hierarchy-figure"/>
+ shows the relation between the object types.
+ </para>
+
+ <figure id="tutorial-internal-objects-hierarchy-figure">
+ <title>Hierarchy of Internal Objects</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="720px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect1>
+
+ <sect1 id="tutorial-directories">
+ <title>The physical Perspective: Directories and Files</title>
+
+ <para>
+ <productname>PostgreSQL</productname> organizes long-lasting
+ data as well as volatile state information about transactions
+ or replication actions in the file system. Every
+ <firstterm>Cluster</firstterm> has its root directory
+ somewhere in the file system. In many cases, the environment
+ variable <literal>PGDATA</literal> points to this directory.
+ The example shown in
+ <xref linkend="tutorial-directories-figure"/> uses
+ <literal>data</literal> as the name of this root directory.
+ </para>
+
+ <figure id="tutorial-directories-figure">
+ <title>Directory Structure</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ <literal>data</literal> contains many subdirectories and
+ some files, all of which are necessary to store long-lasting
+ as well as temporary data. The following paragraphs
+ describe the files and subdirectories in
+ <literal>data</literal>.
+ </para>
+
+ <para>
+ <literal>base</literal> is a subdirectory in which one
+ subdirectory per database exists. The names of those
+ subdirectories consist of numbers. These are the internal
+ Object Identifiers (OID), which are numbers to identify
+ the database definition in the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ </para>
+
+ <para>
+ Within the database-specific
+ subdirectories, there are many files: one or more for
+ every table and every index to store heap and index
+ data. Those files are accompanied by files for the
+ <link linkend="storage-fsm">Free Space Maps</link>
+ (extension <literal>_fsm</literal>) and
+ <link linkend="storage-vm">Visibility Maps</link>
+ (extension <literal>_vm</literal>), which contain optimization information.
+ </para>
+
+ <para>
+ Another subdirectory is <literal>global</literal>.
+ In analogy to the database-specific
+ subdirectories, there are files containing information about
+ <glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
+ One type of such Global SQL Objects are
+ <firstterm>tablespaces</firstterm>. In
+ <literal>global</literal> there is information about
+ the tablespaces, not the tablespaces themselves.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_wal</literal> contains the
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
+ They arise and grow parallel to data changes in the
+ cluster and remain alive as long as
+ they are required for recovery, archiving, or replication.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_xact</literal> contains
+ information about the status of each transaction:
+ in_progress, committed, aborted, or sub_committed.
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal>, there are symbolic links
+ that point to directories containing such<firstterm>
+ SQL objects</firstterm> that are created within
+ tablespaces.
+ </para>
+
+ <para>
+ In the root directory <literal>data</literal>
+ there are also some files. In many cases, the configuration
+ files of the cluster are stored here. As long as the
+ instance is up and running, the file
+ <literal>postmaster.pid</literal> exists here
+ and contains the process ID (pid) of the
+ Postmaster which has started the instance.
+ </para>
+
+ <para>
+ For more details about the physical implementation
+ of database objects, see <xref linkend="storage"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-mvcc">
+ <title>MVCC — Multiversion Concurrency Control</title>
+
+ <para>
+ In most cases, <productname>PostgreSQL</productname> based applications
+ support many clients at the same time. Therefore, it is necessary to
+ protect concurrently running requests from unwanted overwriting
+ of other's data as well as from reading inconsistent data. Imagine an
+ online shop offering the last copy of an article. Two clients have the
+ article displayed at their user interface. After a while, but at the same time,
+ both users decide to put it to their shopping cart or even to buy it.
+ Both have seen the article, but only one can be allowed to get it.
+ The database must bring the two requests in a row, permit the access
+ to one of them, block the other, and inform the blocked client
+ that the data was changed by a different process.
+ </para>
+
+ <para>
+ A first approach to implement protections against concurrent
+ accesses to the same data may be the locking of critical
+ rows. Two such techniques are:
+ <emphasis>Optimistic Concurrency Control</emphasis> (OCC)
+ and <emphasis>Two Phase Locking</emphasis> (2PL).
+ <productname>PostgreSQL</productname> implements a third, more
+ sophisticated technique: <firstterm>Multiversion Concurrency
+ Control</firstterm> (MVCC). The crucial advantage of MVCC
+ over other technologies gets evident in multiuser OLTP
+ environments with a massive number of concurrent write
+ actions. There, MVCC generally performs better than solutions
+ using locks. In a <productname>PostgreSQL</productname>
+ database reading never blocks writing and writing never
+ blocks reading, even in the strictest level of transaction
+ isolation.
+ </para>
+
+ <para>
+ Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
+ a new version of the row when a data-change takes place. To
+ distinguish between these two versions and to track the timeline
+ of the row, each of the versions contains, in addition to their user-defined
+ columns, two special system columns, which are not visible
+ for the usual <command>SELECT * FROM ...</command> command.
+ The column <literal>xmin</literal> contains the transaction ID (xid)
+ of the transaction, which created this version of the row. Accordingly,
+ <literal>xmax</literal> contains the xid of the transaction, which has
+ deleted this version, or zero, if the version is not
+ deleted. You can read both with the command
+ <command>SELECT xmin, xmax, * FROM ... </command>.
+ </para>
+
+ <para>
+ When we speak about transaction IDs, you need to know that xids are like
+ sequences. Every new transaction receives the next number as its ID.
+ Therefore, this flow of xids represents the flow of transaction
+ start events over time. But keep in mind that xids are independent of
+ any time measurement — in milliseconds or whatever. If you dive
+ deeper into <productname>PostgreSQL</productname>, you will recognize
+ parameters with names such as 'xxx_age'. Despite their names,
+ these '_age' parameters do not specify a period of time but represent
+ a certain number of transactions, e.g., 100 million.
+ </para>
+
+ <para>
+ The description in this chapter simplifies by omitting detail.
+ When many transactions are running simultaneously, things can
+ get complicated. Sometimes transactions get aborted via
+ <command>ROLLBACK</command> immediately or after a lot of other activities, sometimes
+ a single row is involved in more than one transaction, sometimes
+ a client crashes, sometimes the sequence of xids restarts
+ from zero, ... . Therefore, every version of a row contains more
+ system columns and flags, not only <literal>xmin</literal>
+ and <literal>xmax</literal>.
+ </para>
+
+ <para>
+ So, what's going on in detail when write accesses take place?
+ <xref linkend="tutorial-mvcc-figure"/> shows details concerning
+ <literal>xmin</literal>, <literal>xmax</literal>, and user data.
+ </para>
+
+ <figure id="tutorial-mvcc-figure">
+ <title>Multiversion Concurrency Control</title>
+ <mediaobject>
+ <imageobject role="html">
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ An <command>INSERT</command> command creates the first
+ version of a row. Besides its user data <literal>'x'</literal>,
+ this version contains the ID of the creating transaction
+ <literal>123</literal> in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ <literal>xmin</literal> indicates that the version
+ exists since transaction <literal>123</literal> and
+ <literal>xmax</literal> that it is currently not deleted.
+ </para>
+
+ <para>
+ Somewhat later, transaction <literal>135</literal>
+ executes an <command>UPDATE</command> of this row by
+ changing the user data from <literal>'x'</literal> to
+ <literal>'y'</literal>. According to the MVCC principles,
+ the data in the old version of the row does not change!
+ The value <literal>'x'</literal> remains as it was before.
+ Only <literal>xmax</literal> changes to <literal>135</literal>.
+ Now, this version is treated as valid exclusively for
+ transactions with xids from <literal>123</literal> to
+ <literal>134</literal>. As a substitute for the non-occurring
+ data change in the old version, the <command>UPDATE</command>
+ creates a new version of the row with its xid in
+ <literal>xmin</literal>, <literal>0</literal> in
+ <literal>xmax</literal>, and <literal>'y'</literal> in the
+ user data (plus all the other user data from the old version).
+ This version is now valid for all coming transactions.
+ </para>
+
+ <para>
+ All subsequent <command>UPDATE</command> commands behave
+ in the same way as the first one: they put their xid to
+ <literal>xmax</literal> of the current version, create
+ the next version with their xid in <literal>xmin</literal>,
+ <literal>0</literal> in <literal>xmax</literal>, and the
+ new user data.
+ </para>
+
+ <para>
+ Finally, a row may be deleted by a <command>DELETE</command>
+ command. Even in this case, all versions of the row remain as
+ before. Nothing is thrown away so far! Only <literal>xmax</literal>
+ of the last version changes to the xid of the <command>DELETE</command>
+ transaction, which indicates that it is only valid for
+ transactions with xids older than its own (from
+ <literal>142</literal> to <literal>820</literal> in this
+ example).
+ </para>
+
+ <para>
+ In summary, the MVCC technology creates more and more versions
+ of the same row in the table's heap file and leaves them there,
+ even after a <command>DELETE</command> command. Only the youngest
+ version is relevant for all future transactions. But the
+ system must also preserve some of the older ones for a
+ certain amount of time because the possibility exists that
+ they are or could become relevant for any pending
+ transactions. Over time, also the older ones get out of scope
+ for ALL transactions and therefore become unnecessary.
+ Nevertheless, they do exist physically on the disk and occupy
+ space.
+ </para>
+
+ <para>
+ Please keep in mind:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> and <literal>xmax</literal>
+ indicate the range from where to where
+ row versions are valid (visible) for transactions.
+ This range doesn't imply any direct temporal meaning;
+ the sequence of xids reflects only the sequence of
+ transaction begin events. As
+ xids grow, old row versions get out of scope over time.
+ If an old row version is no longer valid for ALL existing
+ transactions, it's called <firstterm>dead</firstterm>. The
+ space occupied by all dead row versions is called
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Internally, an <command>UPDATE</command> command acts in the
+ same way as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Nothing gets wiped away — with the consequence that the database
+ occupies more and more disk space. It is obvious that
+ this behavior has to be corrected in some
+ way. The next chapter explains how <firstterm>autovacuum</firstterm>
+ fulfills this task.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ </sect1>
+
+ <sect1 id="tutorial-vacuum">
+ <title>Vacuum</title>
+
+ <para>
+ As we have seen in the previous chapter, the database
+ tends to occupy more and more disk space, the
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ This chapter explains how the SQL command
+ <command>VACUUM</command> and the automatically running
+ <firstterm>autovacuum</firstterm> processes clean up
+ by eliminating bloat.
+ </para>
+
+ <note>
+ <para>
+ <firstterm>Autovacuum</firstterm> runs automatically by
+ default. Its default parameters as well as such for
+ <command>VACUUM</command> fit well for most standard
+ situations. Therefore a novice database manager can
+ easily skip the rest of this chapter which explains
+ a lot of details.
+ </para>
+ </note>
+
+ <para>
+ Client processes can issue the SQL command <command>VACUUM</command> at arbitrary
+ points in time. DBAs do this when they recognize special situations,
+ or they start it in batch jobs which run periodically.
+ <firstterm>Autovacuum</firstterm> processes run as part of the
+ <link linkend="glossary-instance">instance</link> at the server.
+ There is a constantly running <firstterm>autovacuum</firstterm> daemon.
+ It permanently controls the state of all databases based on values that
+ are collected by the
+ <link linkend="glossary-stats-collector">Statistics Collector</link>
+ and starts <firstterm>autovacuum</firstterm> processes whenever it detects
+ certain situations. Thus, it's a dynamic behavior of
+ <productname>PostgreSQL</productname> with the intention to tidy
+ up — whenever it is appropriate.
+ </para>
+
+ <para>
+ <command>VACUUM</command>, as well as
+ <firstterm>autovacuum</firstterm>, don't just eliminate bloat.
+ They perform additional tasks for minimizing future
+ I/O activities of themselves as well as of other processes.
+ This extra work can be done in a very efficient way
+ since in most cases the expensive physical access to pages
+ has taken place anyway to eliminate bloat.
+ The additional operations are:
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <firstterm>Freeze</firstterm>: Mark the youngest row version
+ as frozen. This means that the version
+ is always treated as valid (visible) independent from
+ the <firstterm>wraparound problem</firstterm> (see below).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <firstterm>Visibility Map</firstterm> and
+ <firstterm>Free Space Map</firstterm>: Log information about
+ the state of the handled pages in two additional files, the
+ Visibility Map and the Free Space Map.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <emphasis>Statistics</emphasis>: Collect statistics about the
+ number of rows per table, the distribution of values, and so on,
+ as the basis for decisions of the query planner.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ The eagerness — you can call it 'aggression' — of the
+ operations <emphasis>eliminating bloat</emphasis> and
+ <emphasis>freeze</emphasis> is controlled by configuration
+ parameters, runtime flags, and in extreme situations by
+ the processes themselves. Because vacuum operations typically are I/O
+ intensive, which can hinder other activities, <firstterm>autovacuum</firstterm>
+ avoids performing many vacuum operations in bulk. Instead,
+ it carries out many small actions with time gaps in between.
+ The SQL command <command>VACUUM</command> runs immediately
+ and without any time gaps.
+ </para>
+
+ <bridgehead renderas="sect2">Eliminate Bloat</bridgehead>
+
+ <para>
+ To determine which of the row versions are superfluous, the
+ elimination operation must evaluate <literal>xmax</literal>
+ against several criteria which all must apply:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be different from zero because a
+ value of zero indicates that the row version is still valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must contain an xid which is older
+ than the oldest xid of all
+ currently running transactions (min(pg_stat_activity.backend_xmin)).
+ This criterion guarantees that no existing or upcoming transaction
+ will have read or write access to this row version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of <literal>xmax</literal> must be committed. If it was rollback-ed,
+ this row version is treated as valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there is the situation that the row version is part of
+ multiple transactions, special care and some more actions
+ must be taken, see: <xref linkend="vacuum-for-multixact-wraparound"/>.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ After the vacuum operation detects a superfluous row version, it
+ marks its space as free for future use of writing
+ actions. Only in rare situations (or in the case of <command>VACUUM FULL</command>),
+ is this space released to the operating system. In most cases,
+ it remains occupied by <productname>PostgreSQL</productname>
+ and will be used by future <command>INSERT</command> or
+ <command>UPDATE</command> commands concerning this row or a
+ completely different one.
+ </para>
+
+ <para>
+ Which actions start the elimination of bloat?
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ in its default format, i.e., without any option. To boost performance,
+ in this and the next case <command>VACUUM</command> does not
+ read and act on all pages of the heap.
+ The Visibility Map, which is very compact and therefore has a small
+ size, contains information about pages, where bloat-candidates might
+ be found. Only such pages are processed.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FREEZE</command>. (In this case,
+ it undertakes much more actions, see
+ <link linkend="tutorial-freeze">Freeze Row Versions</link>.)
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FULL</command>.
+ Also, in this mode, the bloat disappears, but the strategy used
+ is very different: In this case, the complete table is copied
+ to a different file skipping all outdated row versions. This
+ leads to a significant reduction of used disk space because
+ the new file contains only the actual data. The old file
+ is deleted.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When an <firstterm>autovacuum</firstterm> process acts. For optimization
+ purposes, it considers the Visibility Map in the same way as
+ <command>VACUUM</command>. Additionally, it ignores tables with few modifications;
+ see <xref linkend="guc-autovacuum-vacuum-threshold"/>,
+ which defaults to 50 rows and
+ <xref linkend="guc-autovacuum-vacuum-scale-factor"/>,
+ which defaults to 20%.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </para>
+
+ <para>
+ This logic only applies to row versions of the heap. Index entries
+ don't use <literal>xmin/xmax</literal>. Nevertheless, such index
+ entries, which would lead to outdated row versions, are released
+ accordingly. (??? more explanations ???)
+ </para>
+
+ <para>
+ The above descriptions omit the fact that xids on a real computer
+ have a limited size. They count up in the same way as sequences, and after
+ a certain number of new transactions they are forced to restart
+ from the beginning, which is called <firstterm>wraparound</firstterm>.
+ Therefore the terms 'old transaction' / 'young transaction' does
+ not always correlate with low / high values of xids. Near to the
+ wraparound point, there are cases where <literal>xmin</literal> has
+ a higher value than <literal>xmax</literal>, although their meaning
+ is said to be older than <literal>xmax</literal>.
+ </para>
+
+ <figure id="tutorial-wraparound-figure">
+ <title>Cyclic usage of XIDs</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2" id="tutorial-freeze">Freeze Row Versions</bridgehead>
+
+ <para>
+ The use of a limited range of IDs for transactions leads
+ to the necessity to restart the sequence sooner or later.
+ This does not only have the rare consequence previously
+ described that sometimes <literal>xmin</literal> is
+ higher than <literal>xmax</literal>. The far
+ more critical problem is that whenever the system has
+ to evaluate a WHERE condition, it must decide which row
+ version is valid (visible) from the perspective of the
+ transaction of this query. If a wraparound couldn't happen,
+ this decision would be relatively easy: the xid
+ must be between <literal>xmin</literal> and <literal>xmax</literal>,
+ and the corresponding transactions of <literal>xmin</literal>
+ and <literal>xmax</literal> must be committed. However,
+ <productname>PostgreSQL</productname> has to consider the
+ possibility of wraparounds.
+ Therefore the decision becomes more complex. The general
+ idea of the solution is to use the 'between
+ <literal>xmin</literal> and <literal>xmax</literal>'
+ comparison only during the youngest period of the row
+ versions lifetime and afterward replace it with a
+ 'valid forever' flag in its header.
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ As a first step, <productname>PostgreSQL</productname>
+ divides the complete range of
+ possible xids into two halves with the two split-points
+ 'txid_current' and 'txid_current + 2^31'. The half behind
+ 'txid_current' is considered to represent xids of the
+ 'past' and the half ahead of 'txid_current' those of the
+ 'future'. Those of the 'past' are valid (visible) and those
+ of the 'future' not.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ With each newly created transaction the two split-points
+ move forward. When 'txid_current + 2^31' would reach a
+ row version with <literal>xmin</literal> equal to that value, it would
+ immediately jump from 'past' to 'future' and would be
+ no longer visible!
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ To avoid this unacceptable extinction of data, the vacuum
+ operation <firstterm>freeze</firstterm> clears the situation
+ long before the split-point is reached. It sets a flag
+ in the header of the row version, which completely eliminates
+ the future use of <literal>xmin/xmax</literal> and indicates
+ that the version is valid not only in the 'past'-half
+ but also in the 'future'-half as well as in all coming
+ <glossterm linkend="glossary-xid">epochs</glossterm>.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Which row versions can be frozen by the vacuum operation?
+ Again, several criteria must be checked, and all must be met.
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be zero because only
+ non-deleted rows can be visible 'forever'.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> must be older than all currently
+ existing transactions. This guarantees that no existing
+ transaction can modify or delete the version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of <literal>xmin</literal> must be committed.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ At what point in time does the freeze operation take place?
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with its <command>FREEZE</command> option. In this case, all
+ pages are processed that are marked in the Visibility Map
+ to potentially have unfrozen rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command> without
+ any options but finds that there are xids older than
+ <xref linkend="guc-vacuum-freeze-table-age"/>
+ (default: 150 million) minus
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million).
+ As before, all pages are processed that are
+ marked in the Visibility Map to potentially have unfrozen
+ rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When an <firstterm>autovacuum</firstterm> process runs. Such
+ a process acts in one of two modes:
+ </simpara>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ In the <emphasis>normal mode</emphasis>, it skips
+ pages with row versions that are younger than
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million) and works only on pages where
+ all xids are older. The skipping of young xids prevents
+ work on such pages, which are likely to be changed
+ by one of the future SQL commands.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ The process switches
+ to an <emphasis>aggressive mode</emphasis> if it recognizes
+ that for the processed table their oldest xid exceeds
+ <xref linkend="guc-autovacuum-freeze-max-age"/>
+ (default: 200 million). The value of the oldest unfrozen
+ xid is stored per table in <literal>pg_class.relfrozenxid</literal>.
+ In this <emphasis>aggressive mode</emphasis> <firstterm>autovacuum</firstterm>
+ processes all such pages of the selected table that are marked
+ in the Visibility Map to potentially have bloat or unfrozen rows.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In the first two cases and with <firstterm>autovacuum</firstterm> in
+ <emphasis>aggressive mode</emphasis>, the system knows
+ to which value the oldest unfrozen xid has moved forward and
+ logs the value in <literal>pg_class.relfrozenxid</literal>.
+ The distance between this value and the 'txid_current' split
+ point becomes smaller, and the distance to 'txid_current + 2^31'
+ becomes larger than before.
+ </para>
+
+ <figure id="tutorial-freeze-figure">
+ <title>Freeze</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2">Protection against Wraparound Failure</bridgehead>
+
+ <para>
+ The <firstterm>autovacuum</firstterm> processes are initiated by the
+ constantly running <firstterm>autovacuum</firstterm> daemon.
+ If the daemon detects that for a table
+ <firstterm>autovacuum_freeze_max_age</firstterm> is exceeded, it
+ starts an <firstterm>autovacuum</firstterm> process in
+ <emphasis>aggressive mode</emphasis>
+ (see above) — even if <firstterm>autovacuum</firstterm> is disabled.
+ </para>
+
+ <bridgehead renderas="sect2">Visibility Map and Free Space Map</bridgehead>
+
+ <para>
+ The <link linkend="glossary-vm">Visibility Map</link>
+ (VM) contains two flags — stored as
+ two bits — for each page of the heap. If the first bit
+ is set, that indicates that the associated page does not
+ contain any bloat. If the second one is set, that indicates
+ that the page contains only frozen rows.
+ </para>
+
+ <para>
+ Please consider two details. First, in most cases a page
+ contains many rows, some of them in many versions.
+ However, the flags are associated with the page,
+ not with a row or a row version. The flags are set
+ only under the condition that they are valid for ALL
+ row versions of the page. Second, since there
+ are only two bits per page, the VM is considerably
+ smaller than the heap. Therefore it is buffered
+ in RAM in almost all cases.
+ </para>
+
+ <para>
+ The setting of the flags is silently done by <command>VACUUM</command>
+ and <firstterm>autovacuum</firstterm> during their bloat and freeze operations.
+ This is done to speed up future vacuum actions,
+ regular accesses to heap pages, and some accesses to
+ the index. Every data-modifying operation on any row
+ version of the page clears the flags.
+ </para>
+
+ <para>
+ The <link linkend="glossary-fsm">Free Space Map</link>
+ (FSM) tracks the amount of free space per page. It is
+ organized as a highly condensed b-tree of (rounded) sizes.
+ As long as <command>VACUUM</command> or
+ <firstterm>autovacuum</firstterm> change the free space
+ on any processed page, they log the new values in
+ the FSM in the same way as all other writing
+ processes.
+ </para>
+
+ <bridgehead renderas="sect2">Statistics</bridgehead>
+
+ <para>
+ Statistic information helps the <link
+ linkend="planner-stats">Query Planner</link> to make optimal
+ decisions for the generation of execution plans. This
+ information can be gathered with the SQL commands
+ <command>ANALYZE</command> or <command>VACUUM ANALYZE</command>.
+ But <firstterm>autovacuum</firstterm> processes also gather
+ such information. Depending on the percentage of changed rows
+ per table <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ the <firstterm>autovacuum</firstterm> daemon starts
+ <firstterm>autovacuum</firstterm> processes to collect
+ statistics per table. This dynamic invocation of analyze
+ operations allows <productname>PostgreSQL</productname> to
+ adopt queries to changing circumstances.
+ </para>
+
+ <para>
+ For more details about vacuum operations, especially for its
+ numerous parameters, see <xref linkend="routine-vacuuming"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-transactions-mvcc">
+ <title>Transactions</title>
+ <para>
+ <link linkend="tutorial-transactions">Transactions</link>
+ are a fundamental concept of relational database systems.
+ Their essential point is that they bundle multiple
+ read- or write-operations into a single all-or-nothing
+ operation. Furthermore, they separate and protect concurrent
+ actions of different connections from each other. Thereby
+ they implement the ACID paradigm.
+ </para>
+
+ <para>
+ In <productname>PostgreSQL</productname> there are two ways
+ to establish a transaction. The explicit way uses the keywords
+ <link linkend="sql-begin">BEGIN</link> and
+ <link linkend="sql-commit">COMMIT</link> (respectively
+ <link linkend="sql-rollback">ROLLBACK</link>) before
+ and after a sequence of SQL statements. The keywords mark
+ the transaction's start- and end-point. On the other hand, you
+ can omit the keywords. This is the implicit way, where
+ every single SQL command automatically establishes a new
+ transaction.
+
+ <programlisting>
+BEGIN; -- establish a new transaction
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+COMMIT; -- finish the transaction
+
+-- this UPDATE runs as the only command of a separate transaction ...
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+
+-- ... and this one runs in another transaction
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+ </programlisting>
+ </para>
+
+ <para>
+ As mentioned, the primary property of a transaction is its
+ atomicity: either all or none of its operations succeed,
+ regardless of the fact that it may consist of a lot of
+ different write-operations, and each such operation may
+ affect thousands or millions of rows. As soon as one of the
+ operations fails, all previous operations fail also, which
+ means that all modified rows retain their values as of the
+ beginning of the transaction.
+ </para>
+
+ <para>
+ The atomicity also affects the visibility of changes. No
+ connections running simultaneously to a data modifying
+ transaction will ever see any change before the
+ transaction successfully executes a <command>COMMIT</command>
+ — even in the lowest
+ <link linkend="transaction-iso">isolation level</link>
+ of transactions. <productname>PostgreSQL</productname>
+ does never show uncommitted changes to other connections.
+ </para>
+
+ <para>
+ The situation regarding visibility is somewhat different
+ from the point of view of the modifying transaction.
+ <command>SELECT</command> commands issued inside a
+ transaction delivers all changes done so far by this
+ transaction.
+ </para>
+
+ <bridgehead renderas="sect2">How does it work?</bridgehead>
+
+ <para>
+ Every <command>INSERT</command>, <command>UPDATE</command>,
+ and <command>DELETE</command> command creates new row
+ versions — according to the MVCC rules. This
+ creates the risk that other transactions may see the
+ new row versions, and after a while and some more
+ activities of the modifying transaction they may see the
+ next row versions. Results would be a kind of 'moving
+ target' in absolute contrast to the all-or-nothing
+ principle.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> overcomes this
+ problem by showing only such row versions to other
+ transactions whose originating transaction is
+ successfully committed. It skips all row versions of
+ uncommitted transactions. And
+ <productname>PostgreSQL</productname> solves one more
+ problem. Even the single <command>COMMIT</command>
+ command needs a short time interval for its execution.
+ Therefore its critical 'dead-or-survival' phase
+ runs in a priviledged mode where it cannot be
+ interrupted by other processes.
+ </para>
+
+ <bridgehead renderas="sect2">What are the benefits?</bridgehead>
+
+ <para>
+ Transactions relieve applications from many standard
+ actions that must be implemented for nearly every use case.
+ </para>
+
+ <para>
+ Business logic often contains strong, but for a computer,
+ relative abstract requirements. The above example shows
+ the transfers of some money from one account to another.
+ It is obvious
+ that the decrease of the one and the increase of the
+ other must be indivisible. Nevertheless, there is no particular
+ need for an application to do something to ensure the
+ <glossterm linkend="glossary-atomicity">atomicity</glossterm>
+ of this behavior. It's enough to surround them with
+ <command>BEGIN</command> and <command>COMMIT</command>.
+ </para>
+
+ <para>
+ Applications often demand the feature of 'undoing'
+ previously taken actions under some application-specific
+ conditions. In such cases, the application simply issues a
+ <command>ROLLBACK</command> command instead of a
+ <command>COMMIT</command>. The <command>ROLLBACK</command>
+ cancels the transaction, and all changes made so far remain
+ invisible forever; it's like they never happened. There
+ is no need for the application to log its activities and
+ undo every step of the transaction separately.
+ </para>
+
+ <para>
+ Transactions ensure that the
+ <glossterm linkend="glossary-consistency">consistency</glossterm>
+ of the complete database always keeps valid. Declarative
+ rules like
+ <link linkend="ddl-constraints-primary-keys">primary</link>- or
+ <link linkend="ddl-constraints-fk">foreign keys</link>,
+ <link linkend="ddl-constraints-check-constraints">checks</link>,
+ other constraints, or
+ <link linkend="trigger-definition">triggers</link>
+ are part of the all-or-nothing nature of transactions.
+ </para>
+
+ <para>
+ Also, all self-evident — but possibly not obvious
+ — low-level demands on the database system are
+ ensured; e.g. index entries for rows must become
+ visible at the same moment as the rows themselves.
+ </para>
+
+ <para>
+ There is an additional feature which defines transactions'
+ <link linkend="transaction-iso">isolation level</link>
+ to each other in a declarative way. It automatically
+ prevents applications from some strange situations.
+ </para>
+
+ <para>
+ Lastly, it is worth to notice that changes done by a
+ committed transaction will survive all future application,
+ instance, or hardware failures. The next chapter
+ explains this
+ <glossterm linkend="glossary-durability">durability</glossterm>.
+ </para>
+ </sect1>
+
+ <sect1 id="tutorial-reliability">
+ <title>Reliability</title>
+
+ <para>
+ Nothing is perfect and failures inevitably happen.
+ However, the most common types of failure are
+ well known and <productname>PostgreSQL</productname>
+ implements strategies to overcome them.
+ Such strategies use parts of the previously presented
+ techniques MVCC and transaction-rollback, plus additional
+ features.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the client side</bridgehead>
+ <para>
+ A <glossterm linkend="glossary-client">client</glossterm>
+ can fail in different ways. Its hardware can get damaged,
+ the power supply can fail, the network connection to the
+ server can break, or the client application may run into
+ a severe software error like a null pointer exception.
+ Because <productname>PostgreSQL</productname> uses a
+ client/server architecture, no direct problem for the
+ database will occur. In all of this cases, the
+ <glossterm linkend="glossary-backend">Backend process</glossterm>,
+ which is the client's counterpart at the server-side,
+ may recognize that the network connection is no longer
+ working, or it may run into a timeout after a while. It
+ terminates, and there is no harm to the database. As
+ usual, uncommitted data changes initiated by this client
+ are not visible to any other client.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the server-side</bridgehead>
+
+ <bridgehead renderas="sect3">Instance failure</bridgehead>
+ <para>
+ The instance may suddenly fail because of <emphasis>power off</emphasis>
+ or other problems. This will affect all running processes, the RAM,
+ and possibly the consistency of disk files.
+ </para>
+ <para>
+ After a restart, <productname>PostgreSQL</productname>
+ automatically recognizes that the last shutdown of the
+ instance did not happen as expected: files might not be
+ closed properly and the <literal>postmaster.pid</literal>
+ file exists. <productname>PostgreSQL</productname>
+ tries to clean up the situation. This is possible because
+ all changes in the database are stored twice. First,
+ the WAL files contain them as a chronology of
+ <glossterm linkend="glossary-wal-record">WAL records</glossterm>,
+ which include the new data values and information about commit
+ actions. The WAL records are written first. Second,
+ the data itself shall exist in the heap and index files.
+ In opposite to the WAL records, this part may or may
+ not have been transferred entirely from Shared Memory
+ to the files.
+ </para>
+ <para>
+ The automatic recovery searches within the WAL files for
+ the latest
+ <glossterm linkend="glossary-checkpoint">checkpoint</glossterm>.
+ This checkpoint signals that the database files are in
+ a consistent state, especially that all WAL records up to
+ this point were successfully stored in heap and index. Starting
+ here, the recovery process copies the following WAL records
+ to heap and index. As a result, the files contain all
+ changes and reach a consistent state. Changes of committed
+ transactions are visible; those of uncommited transactions
+ are also in the files, but - as usual - they are never seen
+ by any of the following transactions because uncommited
+ changes are never shown. Such recovery actions run
+ completely automatically, it is not necessary that you
+ configure or start anything by yourself.
+ </para>
+
+ <bridgehead renderas="sect3">Disk crash</bridgehead>
+ <para>
+ If a disk crashes, the course of action described previously
+ cannot work. It is likely that the WAL files and/or the
+ data and index files are no longer available. You need
+ to take special actions to overcome such situations.
+ </para>
+ <para>
+ You obviously need a backup. How to take such a backup
+ and use it as a starting point for a recovery of the
+ cluster is explained in more detail in the next
+ <link linkend="tutorial-backup">chapter</link>.
+ </para>
+
+ <bridgehead renderas="sect3">Disk full</bridgehead>
+ <para>
+ It is conceivable that over time the disk gets full,
+ and there is no room for additional data. In this case,
+ <productname>PostgreSQL</productname> stops accepting
+ commands which change the data or even terminates
+ completely. No data loss or data corruption will
+ occur.
+ </para>
+ <para>
+ To come out of such a situation, you should remove
+ unused files from this disk. But you should never
+ delete files from the
+ <glossterm linkend="glossary-data-directory">data directory</glossterm>.
+ Nearly all of them are necessary for the consistency
+ of the database.
+ </para>
+
+ <bridgehead renderas="sect2">High availability</bridgehead>
+ <para>
+ Database servers can work together to allow a second
+ server to quickly take over the workload if the
+ primary server fails for whatever reason
+ (<link linkend="high-availability">high availability</link>),
+ or to allow several computers to serve the same data
+ for the purpose of load balancing.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-backup">
+ <title>Backup</title>
+
+ <para>
+ Taking backups is a basic task of database maintenance.
+ <productname>PostgreSQL</productname> supports
+ three different strategies; each has its own
+ strengths and weaknesses.
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ File system level backup
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Logical backup via <command>pg_dump</command>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Continuous archiving based on <command>pg_basebackup</command>
+ and WAL files
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <bridgehead renderas="sect2">File system level backup</bridgehead>
+ <para>
+ You can use any appropriate OS tool to create a
+ <link linkend="backup-file">copy</link>
+ of the cluster's directory structure and files. In
+ case of severe problems such a copy can serve as
+ the source of recovery. But in order to get a
+ <emphasis>USABLE</emphasis> backup by this method,
+ the database server <emphasis>MUST</emphasis> be
+ shut down during the complete runtime of the copy
+ command!
+ </para>
+ <para>
+ The obvious disadvantage of this method is that there
+ is a downtime where no user interaction is possible.
+ The other two strategies run during regular operating
+ times.
+ </para>
+
+ <bridgehead renderas="sect2">Logical backup via pg_dump</bridgehead>
+ <para>
+ The tool <command>pg_dump</command> is able to take a
+ <link linkend="backup-dump">copy</link>
+ of the complete cluster or certain parts of it. It stores
+ the copy in the form of SQL <command>CREATE</command> and
+ <command>INSERT</command> commands. It runs in
+ parallel to other processes in its own transaction.
+ </para>
+ <para>
+ The output of <command>pg_dump</command> may be used as
+ input of <command>psql</command> to restore the data
+ (or to copy it to another database).
+ </para>
+ <para>
+ The main advantage over the other two methods is that it
+ can pick parts of the cluster, e.g. a single table or one
+ database. The other two methods work only at the level of
+ the complete cluster.
+ </para>
+
+ <bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
+ <para>
+ <link linkend="continuous-archiving">This method</link>
+ is the most sophisticated and complex one. It
+ consists of two phases.
+ </para>
+ <para>
+ First, you need to create a so called
+ <firstterm>basebackup</firstterm> with the tool
+ <command>pg_basebackup</command>. The result is a
+ directory structure plus files which contains a
+ consistent copy of the original cluster.
+ <command>pg_basebackup</command> runs in
+ parallel to other processes in its own transaction.
+ </para>
+ <para>
+ The second step is recommended but not necessary. All
+ changes to the data are stored in WAL files. If you
+ continuously save such WAL files, you have the history
+ of the cluster. This history can be applied to a
+ basebackup in order to recreate
+ any state of the cluster between the time of
+ <command>pg_basebackup</command>'s start time and
+ any later point in time. This technique
+ is called 'Point-in-Time Recovery (PITR)'.
+ </para>
+ <para>
+ If configured, the
+ <glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
+ will automatically copy every single WAL file to a save location.
+ <link linkend="backup-archiving-wal">Its configuration</link>
+ consists mainly of a string, which contains a copy command
+ in the operating system's syntax. In order to protect your
+ data against a disk crash, the destination location
+ of a basebackup as well as of the
+ <firstterm>archived WAL files</firstterm> should be on a
+ disk which is different from the data disk.
+ </para>
+ <para>
+ If it gets necessary to restore the cluster, you have to
+ copy the basebackup and the
+ archived WAL files to
+ their original directories. The configuration of this
+ <link linkend="backup-pitr-recovery">recovery procedure</link>
+ contains a string with the reverse copy command: from
+ archive location to database location.
+ </para>
+
+ </sect1>
+
+<!-- ToDo: replication, index-types, extension mechanism, ...
+ <sect1 id="tutorial-replication">
+ <title>Replication</title>
+
+ <para>
+...
+ </para>
+
+ </sect1>
+-->
+
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 64b5da0070..a9eac872f0 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -8,9 +8,10 @@
<!ENTITY problems SYSTEM "problems.sgml">
<!-- tutorial -->
-<!ENTITY advanced SYSTEM "advanced.sgml">
-<!ENTITY query SYSTEM "query.sgml">
-<!ENTITY start SYSTEM "start.sgml">
+<!ENTITY start SYSTEM "start.sgml">
+<!ENTITY query SYSTEM "query.sgml">
+<!ENTITY advanced SYSTEM "advanced.sgml">
+<!ENTITY architecture SYSTEM "architecture.sgml">
<!-- user's guide -->
<!ENTITY array SYSTEM "array.sgml">
diff --git a/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
new file mode 100644
index 0000000000..7e13753d48
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
@@ -0,0 +1,160 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="685" viewBox="0 0 900 685">
+ <title>
+ Server (Hardware, Container, or VM)
+ </title>
+ <style>
+ .text_normal,.text_small{font-style:normal;font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_small{font-size:12px}.text_normal{font-size:16px}
+ </style>
+ <defs>
+ <symbol id="rectangle_special_0">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="rectangle_special_1">
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="125">
+ 'my_schema' (optional)
+ </text>
+ <text class="text_small" x="20" y="145">
+ tables, views, ...
+ </text>
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="190">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M450 10v230H0V0h440v10h10L440 0"/>
+ </symbol>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="270" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Server (Hardware, Container, or VM)
+ </text>
+ <path stroke="blue" stroke-width="2" fill="none" d="M20 110h790v555H20z"/>
+ <text class="text_normal" x="180" y="25" transform="translate(20 110)">
+ cluster 'data' (default, managed by one instance)
+ </text>
+ <path d="M50 110V80h790v555h-30" stroke="blue" stroke-width="2" fill="none"/>
+ <text class="text_normal" x="190" y="-10" transform="translate(45 110)">
+ cluster 'cluster_2' (optional, managed by a different instance)
+ </text>
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template0'
+ </text>
+ </g>
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template1'
+ </text>
+ </g>
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'my_db' (optional)
+ </text>
+ </g>
+ <g transform="translate(320 330)">
+ <rect width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4"/>
+ <text class="text_normal" x="15" y="27">
+ Global SQL objects
+ </text>
+ <path d="M0 5l-65-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M80 0v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M180 40h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M0 40l-45 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ </g>
+ <g transform="translate(335 405)">
+ <use xlink:href="#note"/>
+ <text class="text_small" x="10" y="20">
+ 1)
+ </text>
+ <text class="text_small" x="30" y="20">
+ By default, you work in the cluster 'data', database 'postgres',
+ </text>
+ <text class="text_small" x="30" y="35">
+ schema 'public'.
+ </text>
+ <text class="text_small" x="10" y="55">
+ 2)
+ </text>
+ <text class="text_small" x="30" y="55">
+ More system schemas: pg_catalog, information_schema,
+ </text>
+ <text class="text_small" x="30" y="70">
+ pg_temp, pg_toast.
+ </text>
+ <text class="text_small" x="10" y="90">
+ 3)
+ </text>
+ <text class="text_small" x="30" y="90">
+ Global SQL objects: Some SQL objects are automatically active
+ </text>
+ <text class="text_small" x="30" y="105">
+ and known database- or even cluster-wide.
+ </text>
+ <text class="text_small" x="10" y="125">
+ 4)
+ </text>
+ <text class="text_small" x="30" y="125">
+ The command 'initdb' creates a new cluster with the three
+ </text>
+ <text class="text_small" x="30" y="140">
+ databases 'template0', 'template1', and 'postgres'. The command
+ </text>
+ <text class="text_small" x="30" y="155">
+ 'createdb' creates a new database.
+ </text>
+ <text class="text_small" x="10" y="175">
+ 5)
+ </text>
+ <text class="text_small" x="30" y="175">
+ If multiple clusters are active on one server at the same time,
+ </text>
+ <text class="text_small" x="30" y="190">
+ each one is managed by an individual instance. Each such instance
+ </text>
+ <text class="text_small" x="30" y="205">
+ uses a different port.
+ </text>
+ <text class="text_small" x="10" y="225">
+ 6)
+ </text>
+ <text class="text_small" x="30" y="225">
+ No client application is allowed to connect to 'template0'.
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink.svg b/doc/src/sgml/images/cluster-db-schema-ink.svg
new file mode 100644
index 0000000000..1fffb9737a
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink.svg
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="685px"
+ viewBox="0 0 900 685"
+ id="svg147"
+ sodipodi:docname="cluster-db-schema-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Server (Hardware, Container, or VM)</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1129"
+ inkscape:window-height="922"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.68905109"
+ inkscape:cx="737.16805"
+ inkscape:cy="342.1375"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Server (Hardware, Container, or VM)</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs49">
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangle_special_0">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect6" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="195"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect8" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text10">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text12">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="195"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect14" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text16">(more system schemas)</text>
+ </symbol>
+ <!-- same as before, but one more schema -->
+ <symbol
+ id="rectangle_special_1">
+ <!-- the database -->
+ <rect
+ width="245"
+ height="225"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect19" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect21" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text23">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text25">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect27" />
+ <text
+ class="text_normal"
+ x="20"
+ y="125"
+ id="text29">'my_schema' (optional)</text>
+ <text
+ class="text_small"
+ x="20"
+ y="145"
+ id="text31">tables, views, ...</text>
+ <rect
+ x="15"
+ y="170"
+ width="205"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect33" />
+ <text
+ class="text_small"
+ x="20"
+ y="190"
+ id="text35">(more system schemas)</text>
+ </symbol>
+ <symbol
+ id="note"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title38">UML Note</title>
+ <path
+ d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10"
+ id="path40" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path43" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path46" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect51" />
+ <text
+ class="text_big"
+ x="270"
+ y="40"
+ id="text53">Server (Hardware, Container, or VM)</text>
+ <!-- two clusters -->
+ <g
+ transform="translate(20 110)"
+ id="g59">
+ <rect
+ x="0"
+ y="0"
+ width="790"
+ height="555"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="rect55" />
+ <text
+ class="text_normal"
+ x="180"
+ y="25"
+ id="text57">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g
+ transform="translate(45 110)"
+ id="g65">
+ <path
+ d="M 5,0 v -30 h 790 v 555 h -30"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="path61" />
+ <text
+ class="text_normal"
+ x="190"
+ y="-10"
+ id="text63">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+ <!-- database template 0 -->
+ <g
+ transform="translate(40 155)"
+ id="g71">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use67" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text69">database 'template0'</text>
+ </g>
+ <!-- database template 1 -->
+ <g
+ transform="translate(290 155)"
+ id="g77">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use73" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text75">database 'template1'</text>
+ </g>
+ <!-- database postgres -->
+ <g
+ transform="translate(540 155)"
+ id="g83">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use79" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text81">database 'postgres'</text>
+ </g>
+ <!-- database my_db -->
+ <g
+ transform="translate(40 350)"
+ id="g89">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use85" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text87">database 'my_db' (optional)</text>
+ </g>
+ <!-- global objects -->
+ <g
+ transform="translate(320 330)"
+ id="g103">
+ <rect
+ x="0"
+ y="0"
+ width="180"
+ height="45"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="10 4 4 4"
+ id="rect91" />
+ <text
+ class="text_normal"
+ x="15"
+ y="27"
+ id="text93">Global SQL objects</text>
+ <path
+ d="M 0,5 l-65,-35"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path95" />
+ <path
+ d="M 80,0 v-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path97" />
+ <path
+ d="M 180,40 h50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path99" />
+ <path
+ d="M 0,40 l-45,20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path101" />
+ </g>
+ <!-- Some comments -->
+ <g
+ transform="translate(335 405)"
+ id="g145">
+ <use
+ xlink:href="#note"
+ x="0"
+ y="0"
+ id="use105" />
+ <text
+ class="text_small"
+ x="10"
+ y="20"
+ id="text107">1)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="20"
+ id="text109">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text
+ class="text_small"
+ x="30"
+ y="35"
+ id="text111">schema 'public'.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="55"
+ id="text113">2)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="55"
+ id="text115">More system schemas: pg_catalog, information_schema,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="70"
+ id="text117">pg_temp, pg_toast.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="90"
+ id="text119">3)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="90"
+ id="text121">Global SQL objects: Some SQL objects are automatically active</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text123">and known database- or even cluster-wide.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="125"
+ id="text125">4)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="125"
+ id="text127">The command 'initdb' creates a new cluster with the three</text>
+ <text
+ class="text_small"
+ x="30"
+ y="140"
+ id="text129">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text
+ class="text_small"
+ x="30"
+ y="155"
+ id="text131">'createdb' creates a new database.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="175"
+ id="text133">5)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="175"
+ id="text135">If multiple clusters are active on one server at the same time,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="190"
+ id="text137">each one is managed by an individual instance. Each such instance</text>
+ <text
+ class="text_small"
+ x="30"
+ y="205"
+ id="text139">uses a different port.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="225"
+ id="text141">6)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="225"
+ id="text143">No client application is allowed to connect to 'template0'.</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
new file mode 100644
index 0000000000..af50c07330
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="685px"
+ viewBox="0 0 900 685" >
+
+ <title>Server (Hardware, Container, or VM)</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_0">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">(more system schemas)</text>
+ </symbol>
+
+ <!-- same as before, but one more schema -->
+ <symbol id="rectangle_special_1">
+ <!-- the database -->
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="125">'my_schema' (optional)</text>
+ <text class="text_small" x="20" y="145">tables, views, ...</text>
+
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="190">(more system schemas)</text>
+ </symbol>
+
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="270" y="40">Server (Hardware, Container, or VM)</text>
+
+ <!-- two clusters -->
+ <g transform="translate(20 110)">
+ <rect x="0" y="0" width="790" height="555" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="180" y="25">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g transform="translate(45 110)">
+ <path d="M 5,0 v -30 h 790 v 555 h -30" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="190" y="-10">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+
+
+ <!-- database template 0 -->
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template0'</text>
+ </g>
+
+ <!-- database template 1 -->
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template1'</text>
+ </g>
+
+ <!-- database postgres -->
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'postgres'</text>
+ </g>
+
+ <!-- database my_db -->
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
+ </g>
+
+ <!-- global objects -->
+ <g transform="translate(320 330)">
+ <rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
+ <text class="text_normal" x="15" y="27">Global SQL objects</text>
+ <path d="M 0,5 l-65,-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ </g>
+
+ <!-- Some comments -->
+ <g transform="translate(335 405)">
+ <use xlink:href="#note" x="0" y="0" />
+
+ <text class="text_small" x="10" y="20">1)</text>
+ <text class="text_small" x="30" y="20">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text class="text_small" x="30" y="35">schema 'public'.</text>
+
+ <text class="text_small" x="10" y="55">2)</text>
+ <text class="text_small" x="30" y="55">More system schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="70">pg_temp, pg_toast.</text>
+
+ <text class="text_small" x="10" y="90">3)</text>
+ <text class="text_small" x="30" y="90">Global SQL objects: Some SQL objects are automatically active</text>
+ <text class="text_small" x="30" y="105">and known database- or even cluster-wide.</text>
+
+ <text class="text_small" x="10" y="125">4)</text>
+ <text class="text_small" x="30" y="125">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="140">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="155">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="175">5)</text>
+ <text class="text_small" x="30" y="175">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="190">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="205">uses a different port.</text>
+
+ <text class="text_small" x="10" y="225">6)</text>
+ <text class="text_small" x="30" y="225">No client application is allowed to connect to 'template0'.</text>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/directories-ink-svgo.svg b/doc/src/sgml/images/directories-ink-svgo.svg
new file mode 100644
index 0000000000..95fa76b9c6
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink-svgo.svg
@@ -0,0 +1,164 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="640" viewBox="0 0 900 640">
+ <title>
+ Directory structure of a cluster
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <symbol id="directory" stroke="blue" stroke-width=".3" fill="aqua">
+ <title>
+ Directory
+ </title>
+ <path d="M0 10h110v20H0z"/>
+ <path d="M0 10V8l3-3h35l3 3v2"/>
+ </symbol>
+ <symbol id="file" stroke="black" fill="none">
+ <title>
+ File
+ </title>
+ <path stroke="blue" d="M0 0h40v50H0z"/>
+ <path d="M5 10h20" stroke-dasharray="4 2"/>
+ <path d="M5 17h15" stroke-dasharray="6 2"/>
+ <path d="M5 24h25" stroke-dasharray="4 2"/>
+ <path d="M5 31h20" stroke-dasharray="5 2"/>
+ </symbol>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="50" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Directory Structure
+ </text>
+ <g transform="translate(20 100)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /pg/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ An arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 130)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ data/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of cluster 'data' (see: PGDATA)
+ </text>
+ </g>
+ <g transform="translate(120 160)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ base/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing per-database subdirectories
+ </text>
+ </g>
+ <g transform="translate(170 190)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 1/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of first database 'template0'
+ </text>
+ </g>
+ <g transform="translate(170 220)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12992/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of second database 'template1'
+ </text>
+ </g>
+ <g transform="translate(170 250)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12999/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of third database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(170 280)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ nnnnn/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Optional: more subdirectories for databases, e.g. 'my_db'
+ </text>
+ </g>
+ <g transform="translate(120 310)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ global/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory with information about Global SQL Objects
+ </text>
+ </g>
+ <g transform="translate(120 340)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_wal/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 370)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_xact/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for transaction commit status ('pg_clog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 400)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_tblspc/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing symbolic links to tablespaces
+ </text>
+ </g>
+ <g transform="translate(120 430)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_... /
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Some more subdirectories
+ </text>
+ </g>
+ <g transform="translate(120 465)">
+ <use xlink:href="#file"/>
+ <use xlink:href="#file" x="50"/>
+ <text x="200" y="26" class="text_normal">
+ 'postmaster.pid' and other files with cluster-wide relevance
+ </text>
+ </g>
+ <g transform="translate(20 540)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /xyz/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ Same or another arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 570)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ cluster_2/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of another cluster 'cluster_2'
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-ink.svg b/doc/src/sgml/images/directories-ink.svg
new file mode 100644
index 0000000000..8151cf583a
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink.svg
@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="640px"
+ viewBox="0 0 900 640"
+ id="svg303"
+ sodipodi:docname="directories-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata307">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Directory structure of a cluster</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1083"
+ inkscape:window-height="808"
+ id="namedview305"
+ showgrid="false"
+ inkscape:zoom="0.36875"
+ inkscape:cx="450"
+ inkscape:cy="320"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg303" />
+ <title
+ id="title153">Directory structure of a cluster</title>
+ <style
+ type="text/css"
+ id="style155">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs177">
+ <!-- Directory -->
+ <symbol
+ id="directory"
+ stroke="blue"
+ stroke-width="0.3px"
+ fill="aqua">
+ <title
+ id="title157">Directory</title>
+ <rect
+ x="0"
+ y="10"
+ width="110"
+ height="20"
+ id="rect159" />
+ <path
+ d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2"
+ id="path161" />
+ </symbol>
+ <!-- File -->
+ <symbol
+ id="file"
+ stroke="black"
+ fill="none">
+ <title
+ id="title164">File</title>
+ <rect
+ x="0"
+ y="0"
+ width="40"
+ height="50"
+ stroke="blue"
+ id="rect166" />
+ <path
+ d="M 5,10 h 20"
+ stroke-dasharray="4 2"
+ id="path168" />
+ <path
+ d="M 5,17 h 15"
+ stroke-dasharray="6 2"
+ id="path170" />
+ <path
+ d="M 5,24 h 25"
+ stroke-dasharray="4 2"
+ id="path172" />
+ <path
+ d="M 5,31 h 20"
+ stroke-dasharray="5 2"
+ id="path174" />
+ </symbol>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect179" />
+ <!-- caption -->
+ <text
+ x="200"
+ y="50"
+ class="text_big"
+ id="text181">Directory Structure</text>
+ <!-- the directories -->
+ <g
+ transform="translate(20, 100)"
+ id="g189">
+ <use
+ xlink:href="#directory"
+ id="use183" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text185">... /pg/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text187">An arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 130)"
+ id="g197">
+ <use
+ xlink:href="#directory"
+ id="use191" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text193">data/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text195">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+ <g
+ transform="translate(120, 160)"
+ id="g205">
+ <use
+ xlink:href="#directory"
+ id="use199" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text201">base/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text203">Subdirectory containing per-database subdirectories</text>
+ </g>
+ <!-- -->
+ <g
+ transform="translate(170, 190)"
+ id="g213">
+ <use
+ xlink:href="#directory"
+ id="use207" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text209">1/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text211">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g
+ transform="translate(170, 220)"
+ id="g221">
+ <use
+ xlink:href="#directory"
+ id="use215" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text217">12992/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text219">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g
+ transform="translate(170, 250)"
+ id="g229">
+ <use
+ xlink:href="#directory"
+ id="use223" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text225">12999/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text227">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g
+ transform="translate(170, 280)"
+ id="g237">
+ <use
+ xlink:href="#directory"
+ id="use231" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text233">nnnnn/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text235">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+ <g
+ transform="translate(120, 310)"
+ id="g245">
+ <use
+ xlink:href="#directory"
+ id="use239" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text241">global/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text243">Subdirectory with information about Global SQL Objects</text>
+ </g>
+ <g
+ transform="translate(120, 340)"
+ id="g253">
+ <use
+ xlink:href="#directory"
+ id="use247" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text249">pg_wal/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text251">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 370)"
+ id="g261">
+ <use
+ xlink:href="#directory"
+ id="use255" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text257">pg_xact/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text259">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 400)"
+ id="g269">
+ <use
+ xlink:href="#directory"
+ id="use263" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text265">pg_tblspc/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text267">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+ <g
+ transform="translate(120, 430)"
+ id="g277">
+ <use
+ xlink:href="#directory"
+ id="use271" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text273">pg_... /</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text275">Some more subdirectories</text>
+ </g>
+ <g
+ transform="translate(120, 465)"
+ id="g285">
+ <use
+ xlink:href="#file"
+ x="0"
+ y="0"
+ id="use279" />
+ <use
+ xlink:href="#file"
+ x="50"
+ y="0"
+ id="use281" />
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text283">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+ <!-- next cluster -->
+ <g
+ transform="translate(20, 540)"
+ id="g293">
+ <use
+ xlink:href="#directory"
+ id="use287" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text289">... /xyz/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text291">Same or another arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 570)"
+ id="g301">
+ <use
+ xlink:href="#directory"
+ id="use295" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text297">cluster_2/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text299">Root of another cluster 'cluster_2'</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
new file mode 100644
index 0000000000..6d16a03169
--- /dev/null
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="640px"
+ viewBox="0 0 900 640">
+
+ <title>Directory structure of a cluster</title>
+
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Directory -->
+ <symbol id="directory" stroke="blue" stroke-width="0.3px" fill="aqua">
+ <title>Directory</title>
+ <rect x="0" y="10" width="110" height="20" />
+ <path d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2" />
+ </symbol>
+
+ <!-- File -->
+ <symbol id="file" stroke="black" fill="none" >
+ <title>File</title>
+ <rect x="0" y="0" width="40" height="50" stroke="blue" />
+ <path d="M 5,10 h 20" stroke-dasharray="4 2" />
+ <path d="M 5,17 h 15" stroke-dasharray="6 2" />
+ <path d="M 5,24 h 25" stroke-dasharray="4 2" />
+ <path d="M 5,31 h 20" stroke-dasharray="5 2" />
+ </symbol>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption -->
+ <text x="200" y="50" class="text_big">Directory Structure</text>
+
+ <!-- the directories -->
+ <g transform="translate(20, 100)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /pg/</text>
+ <text x="300" y="26" class="text_normal">An arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 130)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">data/</text>
+ <text x="250" y="26" class="text_normal">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+
+ <g transform="translate(120, 160)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">base/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing per-database subdirectories</text>
+ </g>
+
+ <!-- -->
+ <g transform="translate(170, 190)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">1/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g transform="translate(170, 220)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12992/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g transform="translate(170, 250)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12999/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g transform="translate(170, 280)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">nnnnn/</text>
+ <text x="150" y="26" class="text_normal">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+
+ <g transform="translate(120, 310)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">global/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory with information about Global SQL Objects</text>
+ </g>
+
+ <g transform="translate(120, 340)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 370)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 400)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+
+ <g transform="translate(120, 430)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_... /</text>
+ <text x="200" y="26" class="text_normal">Some more subdirectories</text>
+ </g>
+
+ <g transform="translate(120, 465)">
+ <use xlink:href="#file" x="0" y="0" />
+ <use xlink:href="#file" x="50" y="0" />
+ <text x="200" y="26" class="text_normal">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+
+ <!-- next cluster -->
+ <g transform="translate(20, 540)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /xyz/</text>
+ <text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 570)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster 'cluster_2'</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink-svgo.svg b/doc/src/sgml/images/freeze-ink-svgo.svg
new file mode 100644
index 0000000000..6fedfb7633
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink-svgo.svg
@@ -0,0 +1,84 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="320" viewBox="0 0 850 320">
+ <title>
+ Freeze
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100)"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="70" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ <tspan font-style="italic" font-weight="700">Freeze</tspan> to keep visible
+ </text>
+ <g fill="none" transform="translate(170 190)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_120" startOffset="11.2%">(1)</textPath> <textPath xlink:href="#Path_120" startOffset="61.2%">(5)</textPath> <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%">|</textPath> <textPath xlink:href="#Path_120" startOffset="34%">(2)</textPath> <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(3)</textPath> <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%">|</textPath> <textPath xlink:href="#Path_120" startOffset="55%">(4)</textPath>
+ </text>
+ <path d="M-80-80L80 80" stroke="black"/>
+ <text class="text_normal" letter-spacing="12" transform="rotate(45 40.78 -38.1)">
+ PAST
+ </text>
+ <text class="text_normal" letter-spacing="12" transform="rotate(-135 27.43 23.79)">
+ FUTURE
+ </text>
+ <use xlink:href="#frozenPoint" transform="rotate(10)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(25)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(40)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(55)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(70)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(85)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(100)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(115)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(130)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(145)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(160)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(175)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(190)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(205)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(220)"/>
+ </g>
+ <g class="text_normal" transform="translate(380 30)">
+ <text>
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25">
+ 1: txid_current + 2 ^ 31 (split-point)
+ </text>
+ <text y="50">
+ 2: autovacuum_freeze_max_age (200 mio.)
+ </text>
+ <text y="75">
+ 3: vacuum_freeze_table_age (150 mio.)
+ </text>
+ <text y="100">
+ 4: vacuum_freeze_min_age (50 mio.)
+ </text>
+ <text y="125">
+ 5: txid_current (split-point, jungest xid)
+ </text>
+ <text y="155">
+ per table: pg_class.relfrozenxid <tspan font-weight="700">must</tspan> be between (1) and (5);
+ </text>
+ <text y="175" x="75">
+ normally it is between (3) and (4)
+ </text>
+ <use xlink:href="#unfrozenPoint" transform="translate(106 200)"/>
+ <text y="205" x="20">
+ Unfrozen xid
+ </text>
+ <use xlink:href="#frozenPoint" transform="translate(106 224)"/>
+ <text y="230" x="20">
+ Frozen xid
+ </text>
+ <text y="260">
+ (figure is out of scale)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink.svg b/doc/src/sgml/images/freeze-ink.svg
new file mode 100644
index 0000000000..009cfe4b41
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink.svg
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="320px"
+ viewBox="0 0 850 320"
+ id="svg454"
+ sodipodi:docname="freeze-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata458">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Freeze</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="979"
+ inkscape:window-height="857"
+ id="namedview456"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="160"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg454" />
+ <title
+ id="title309">Freeze</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style311">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs318">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle
+ id="frozenPoint"
+ r="3"
+ stroke="green"
+ fill="green"
+ transform="translate(-100, 0)" />
+ <circle
+ id="unfrozenPoint"
+ r="3"
+ stroke="green"
+ fill="none"
+ transform="translate(-100, 0)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect320" />
+ <text
+ class="text_big"
+ x="70"
+ y="40"
+ id="text324"><tspan
+ style="font-style:italic;font-weight:bold"
+ id="tspan322">
+ Freeze</tspan>
+ to keep visible</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 190)"
+ id="g418">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle326" />
+ <text
+ class="text_normal"
+ id="text350">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath328">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath330">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath332">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="11.2%"
+ id="textPath334">(1)</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="61.2%"
+ id="textPath336">(5)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="red"
+ stroke-width="3"
+ startOffset="34%"
+ id="textPath338">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="34%"
+ id="textPath340">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="black"
+ stroke-width="3"
+ startOffset="45%"
+ id="textPath342">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath344">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="green"
+ stroke-width="3"
+ startOffset="55%"
+ id="textPath346">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="55%"
+ id="textPath348">(4)</textPath>
+ </text>
+ <!-- split it into 'past' and 'future' -->
+ <path
+ d="M -80 -80 l 160 160"
+ stroke="black"
+ id="path352" />
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(-15, -40) rotate(45)"
+ id="text354">PAST</text>
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(30, 60) rotate(225)"
+ id="text356">FUTURE</text>
+ <g
+ transform="rotate(10)"
+ id="g360">
+ <use
+ xlink:href="#frozenPoint"
+ id="use358" />
+ </g>
+ <g
+ transform="rotate(25)"
+ id="g364">
+ <use
+ xlink:href="#frozenPoint"
+ id="use362" />
+ </g>
+ <g
+ transform="rotate(40)"
+ id="g368">
+ <use
+ xlink:href="#frozenPoint"
+ id="use366" />
+ </g>
+ <g
+ transform="rotate(55)"
+ id="g372">
+ <use
+ xlink:href="#frozenPoint"
+ id="use370" />
+ </g>
+ <g
+ transform="rotate(70)"
+ id="g376">
+ <use
+ xlink:href="#frozenPoint"
+ id="use374" />
+ </g>
+ <g
+ transform="rotate(85)"
+ id="g380">
+ <use
+ xlink:href="#frozenPoint"
+ id="use378" />
+ </g>
+ <g
+ transform="rotate(100)"
+ id="g384">
+ <use
+ xlink:href="#frozenPoint"
+ id="use382" />
+ </g>
+ <g
+ transform="rotate(115)"
+ id="g388">
+ <use
+ xlink:href="#frozenPoint"
+ id="use386" />
+ </g>
+ <g
+ transform="rotate(130)"
+ id="g392">
+ <use
+ xlink:href="#frozenPoint"
+ id="use390" />
+ </g>
+ <g
+ transform="rotate(145)"
+ id="g396">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use394" />
+ </g>
+ <g
+ transform="rotate(160)"
+ id="g400">
+ <use
+ xlink:href="#frozenPoint"
+ id="use398" />
+ </g>
+ <g
+ transform="rotate(175)"
+ id="g404">
+ <use
+ xlink:href="#frozenPoint"
+ id="use402" />
+ </g>
+ <g
+ transform="rotate(190)"
+ id="g408">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use406" />
+ </g>
+ <g
+ transform="rotate(205)"
+ id="g412">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use410" />
+ </g>
+ <g
+ transform="rotate(220)"
+ id="g416">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use414" />
+ </g>
+ </g>
+ <!-- legend -->
+ <g
+ class="text_normal"
+ transform="translate(380 30)"
+ id="g452">
+ <text
+ id="text424">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan420">^</tspan>
+<tspan
+ dy="5"
+ id="tspan422">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text426">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text
+ y="50"
+ id="text428">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text
+ y="75"
+ id="text430">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text
+ y="100"
+ id="text432">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text
+ y="125"
+ id="text434">5: txid_current (split-point, jungest xid)</text>
+ <text
+ y="155"
+ id="text438">per table: pg_class.relfrozenxid
+ <tspan
+ style="font-weight:bold"
+ id="tspan436">must</tspan>
+ be between (1) and (5);</text>
+ <text
+ y="175"
+ x="75"
+ id="text440">normally it is between (3) and (4)</text>
+ <use
+ xlink:href="#unfrozenPoint"
+ transform="translate(106, 200)"
+ id="use442" />
+ <text
+ y="205"
+ x="20"
+ id="text444">Unfrozen xid</text>
+ <use
+ xlink:href="#frozenPoint"
+ transform="translate(106, 224)"
+ id="use446" />
+ <text
+ y="230"
+ x="20"
+ id="text448">Frozen xid</text>
+ <text
+ y="260"
+ id="text450">(figure is out of scale)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-raw.svg b/doc/src/sgml/images/freeze-raw.svg
new file mode 100644
index 0000000000..2d1d256184
--- /dev/null
+++ b/doc/src/sgml/images/freeze-raw.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="320px"
+ viewBox="0 0 850 320" >
+
+ <title>Freeze</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100, 0)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100, 0)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="70" y="40"><tspan style="font-style:italic;font-weight:bold">
+ Freeze</tspan> to keep visible</text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 190)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_120" startOffset="11.2%" >(1)</textPath>
+ <textPath xlink:href="#Path_120" startOffset="61.2%" >(5)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="34%" >(2)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(3)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="55%" >(4)</textPath>
+
+ </text>
+
+ <!-- split it into 'past' and 'future' -->
+ <path d="M -80 -80 l 160 160" stroke="black" />
+ <text class="text_normal" letter-spacing="12" transform="translate(-15, -40) rotate(45)">PAST</text>
+ <text class="text_normal" letter-spacing="12" transform="translate(30, 60) rotate(225)">FUTURE</text>
+
+ <g transform="rotate(10)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(25)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(40)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(55)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(70)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(85)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(100)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(115)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(130)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(145)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(160)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(175)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(190)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(205)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(220)"><use xlink:href="#unfrozenPoint"/></g>
+
+ </g>
+
+ <!-- legend -->
+ <g class="text_normal" transform="translate(380 30)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text y="50">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text y="75">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text y="100">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text y="125">5: txid_current (split-point, jungest xid)</text>
+ <text y="155">per table: pg_class.relfrozenxid
+ <tspan style="font-weight:bold">must</tspan> be between (1) and (5);</text>
+ <text y="175" x="75">normally it is between (3) and (4)</text>
+
+ <use xlink:href="#unfrozenPoint" transform="translate(106, 200)"/>
+ <text y="205" x="20">Unfrozen xid</text>
+
+ <use xlink:href="#frozenPoint" transform="translate(106, 224)"/>
+ <text y="230" x="20">Frozen xid</text>
+
+ <text y="260">(figure is out of scale)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
new file mode 100644
index 0000000000..26bce6176d
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
@@ -0,0 +1,83 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="720" height="430" viewBox="0 0 720 430">
+ <title>
+ Hierarchy of Internal Objects
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Hierarchy of internal Objects
+ </text>
+ <g fill="none">
+ <g transform="translate(350 240)">
+ <ellipse rx="320" ry="170" stroke="blue"/>
+ <text class="text_normal" x="-140" y="-130">
+ Cluster
+ </text>
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-60" y="5">
+ Database Names
+ </text>
+ </g>
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-40" y="5">
+ Tablespace
+ </text>
+ </g>
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-70" y="5">
+ Replication Origins
+ </text>
+ </g>
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue"/>
+ <text class="text_normal" x="-60" y="-3">
+ Subscription for
+ </text>
+ <text class="text_normal" x="-68" y="10">
+ Logical Replication
+ </text>
+ </g>
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-15" y="5">
+ Role
+ </text>
+ </g>
+ </g>
+ <g transform="translate(270 250)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2"/>
+ <text class="text_normal" x="-60" y="-80">
+ Database
+ </text>
+ <g transform="translate(-150 -30)">
+ <ellipse rx="50" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Extension
+ </text>
+ </g>
+ <g transform="translate(-155 35)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Collation
+ </text>
+ </g>
+ <g transform="translate(30 20)">
+ <ellipse rx="140" ry="70" stroke="blue"/>
+ <text class="text_normal" x="-80" y="-35">
+ Schema
+ </text>
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue"/>
+ <text class="text_normal" x="-50" y="5">
+ Table, View, ...
+ </text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
new file mode 100644
index 0000000000..e5745818d9
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="720px"
+ height="430px"
+ viewBox="0 0 720 430"
+ id="svg540"
+ sodipodi:docname="internal-objects-hierarchy-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata546">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Hierarchy of Internal Objects</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs544" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1050"
+ inkscape:window-height="838"
+ id="namedview542"
+ showgrid="false"
+ inkscape:zoom="0.51944444"
+ inkscape:cx="360"
+ inkscape:cy="215"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg540" />
+ <title
+ id="title460">Hierarchy of Internal Objects</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style462">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect464" />
+ <text
+ class="text_big"
+ x="200"
+ y="40"
+ id="text466">Hierarchy of internal Objects</text>
+ <!-- set centre of figure and default values -->
+ <g
+ transform="translate(350 240)"
+ fill="none"
+ id="g538">
+ <g
+ id="g504">
+ <ellipse
+ rx="320"
+ ry="170"
+ stroke="blue"
+ id="ellipse468" />
+ <text
+ class="text_normal"
+ x="-140"
+ y="-130"
+ id="text470">Cluster</text>
+ <g
+ transform="translate(40 -125)"
+ id="g476">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse472" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="5"
+ id="text474">Database Names</text>
+ </g>
+ <g
+ transform="translate(180 -70)"
+ id="g482">
+ <ellipse
+ rx="60"
+ ry="20"
+ stroke="blue"
+ id="ellipse478" />
+ <text
+ class="text_normal"
+ x="-40"
+ y="5"
+ id="text480">Tablespace</text>
+ </g>
+ <g
+ transform="translate(230 -5)"
+ id="g488">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse484" />
+ <text
+ class="text_normal"
+ x="-70"
+ y="5"
+ id="text486">Replication Origins</text>
+ </g>
+ <g
+ transform="translate(200 70)"
+ id="g496">
+ <ellipse
+ rx="78"
+ ry="27"
+ stroke="blue"
+ id="ellipse490" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-3"
+ id="text492">Subscription for</text>
+ <text
+ class="text_normal"
+ x="-68"
+ y="10"
+ id="text494">Logical Replication</text>
+ </g>
+ <g
+ transform="translate(100 120)"
+ id="g502">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse498" />
+ <text
+ class="text_normal"
+ x="-15"
+ y="5"
+ id="text500">Role</text>
+ </g>
+ </g>
+ <g
+ transform="translate(-80 10)"
+ id="g536">
+ <ellipse
+ rx="220"
+ ry="110"
+ stroke="blue"
+ stroke-width="2px"
+ id="ellipse506" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-80"
+ id="text508">Database</text>
+ <g
+ transform="translate(-120 -50)"
+ id="g534">
+ <g
+ transform="translate(-30 20)"
+ id="g514">
+ <ellipse
+ rx="50"
+ ry="20"
+ stroke="blue"
+ id="ellipse510" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text512">Extension</text>
+ </g>
+ <g
+ transform="translate(-35 85)"
+ id="g520">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse516" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text518">Collation</text>
+ </g>
+ <g
+ transform="translate(150 70)"
+ id="g532">
+ <ellipse
+ rx="140"
+ ry="70"
+ stroke="blue"
+ id="ellipse522" />
+ <text
+ class="text_normal"
+ x="-80"
+ y="-35"
+ id="text524">Schema</text>
+ <g
+ transform="translate(20 10)"
+ id="g530">
+ <ellipse
+ rx="90"
+ ry="30"
+ stroke="blue"
+ id="ellipse526" />
+ <text
+ class="text_normal"
+ x="-50"
+ y="5"
+ id="text528">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
new file mode 100644
index 0000000000..f0dc890f6b
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="720px" height="430px"
+ viewBox="0 0 720 430" >
+
+ <title>Hierarchy of Internal Objects</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="200" y="40">Hierarchy of internal Objects</text>
+
+
+ <!-- set centre of figure and default values -->
+ <g transform="translate(350 240)" fill="none">
+
+ <g>
+ <ellipse rx="320" ry="170" stroke="blue" />
+ <text class="text_normal" x="-140" y="-130">Cluster</text>
+
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-60" y="5">Database Names</text>
+ </g>
+
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue" />
+ <text class="text_normal" x="-40" y="5">Tablespace</text>
+ </g>
+
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-70" y="5">Replication Origins</text>
+ </g>
+
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue" />
+ <text class="text_normal" x="-60" y="-3">Subscription for</text>
+ <text class="text_normal" x="-68" y="10">Logical Replication</text>
+ </g>
+
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-15" y="5">Role</text>
+ </g>
+
+ </g>
+
+ <g transform="translate(-80 10)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2px" />
+ <text class="text_normal" x="-60" y="-80">Database</text>
+
+ <g transform="translate(-120 -50)">
+ <g transform="translate(-30 20)">
+ <ellipse rx="50" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Extension</text>
+ </g>
+
+ <g transform="translate(-35 85)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Collation</text>
+ </g>
+
+ <g transform="translate(150 70)">
+ <ellipse rx="140" ry="70" stroke="blue" />
+ <text class="text_normal" x="-80" y="-35">Schema</text>
+
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue" />
+ <text class="text_normal" x="-50" y="5">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink-svgo.svg b/doc/src/sgml/images/mvcc-ink-svgo.svg
new file mode 100644
index 0000000000..8e67da93d1
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink-svgo.svg
@@ -0,0 +1,151 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="150" viewBox="0 0 850 150">
+ <title>
+ MVCC
+ </title>
+ <style>
+ .text_small{font-style:normal;font-weight:400;font-size:10px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <marker id="triangle_1" markerWidth="10" markerHeight="10" refX="5" refY="5" orient="auto" stroke="black" fill="none">
+ <path d="M0 0l10 5-10 5"/>
+ </marker>
+ <path id="arrow" d="M0 0q20-15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+ <g id="tuple" stroke="black">
+ <path d="M80 0H0v20h80M29 0v20M60 0v20"/>
+ <path d="M80 0h15M80 20h15" stroke-dasharray="2 1"/>
+ </g>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <g fill="none">
+ <g transform="translate(20 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">123</tspan> <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)" fill="#00f">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 83)" fill="#00f">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(185 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">135</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 53)" fill="#00f">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(350 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">142</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 23)" fill="#00f">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(515 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">821</tspan> <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 821
+ </text>
+ <text class="text_small" transform="translate(125 23)">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(740 110)">
+ <path d="M102-20H-18v60" stroke="black"/>
+ <text font-weight="400" font-size="16" font-family=""Open Sans",sans-serif" fill="#000">
+ Legend
+ </text>
+ <use xlink:href="#tuple" transform="translate(0 10)"/>
+ <text class="text_small" transform="translate(3 23)">
+ xmin
+ </text>
+ <text class="text_small" transform="translate(32 23)">
+ xmax
+ </text>
+ <text class="text_small" transform="translate(65 23)">
+ data
+ </text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink.svg b/doc/src/sgml/images/mvcc-ink.svg
new file mode 100644
index 0000000000..f4161b3e79
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink.svg
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="150px"
+ viewBox="0 0 850 150"
+ id="svg147"
+ sodipodi:docname="mvcc-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>MVCC</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1256"
+ inkscape:window-height="801"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="75"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">MVCC</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs15">
+ <marker
+ id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto"
+ stroke="black"
+ fill="none">
+ <path
+ d="M 0,0 L 10,5 L 0,10"
+ id="path6" />
+ </marker>
+ <g
+ id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path
+ d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20"
+ stroke="black"
+ id="path9" />
+ <!-- prolong the rectangle -->
+ <path
+ d="M 80 0 h 15 M 80 20 h 15"
+ stroke="black"
+ stroke-dasharray="2 1"
+ id="path11" />
+ </g>
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path
+ id="arrow"
+ d="M 0 0 Q 20 -15 40 0"
+ stroke="black"
+ marker-end="url(#triangle_1)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect17" />
+ <!-- set default values -->
+ <g
+ fill="none"
+ id="g145">
+ <!-- start plus first INSERT -->
+ <g
+ transform="translate(20, 40)"
+ id="g35">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text23">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan19">123</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan21">: INSERT</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use25" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use27" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ style="fill:blue"
+ id="text29">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text31">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ style="fill:blue"
+ id="text33">'x'</text>
+ </g>
+ <!-- first UPDATE -->
+ <g
+ transform="translate(185, 40)"
+ id="g61">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text41">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan37">135</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan39">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use43" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use45" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ style="fill:blue"
+ id="text47">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text49">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ style="fill:blue"
+ id="text51">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use53" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text55">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text57">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text59">'x'</text>
+ </g>
+ <!-- next UPDATE -->
+ <g
+ transform="translate(350, 40)"
+ id="g95">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text67">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan63">142</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan65">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use69" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use71" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ style="fill:blue"
+ id="text73">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text75">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ style="fill:blue"
+ id="text77">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use79" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text81">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text83">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text85">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use87" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text89">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text91">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text93">'x'</text>
+ </g>
+ <!-- DELETE -->
+ <g
+ transform="translate(515, 40)"
+ id="g129">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text101">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan97">821</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan99">: DELTE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use103" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use105" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text107">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text109">821</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ id="text111">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use113" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text115">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ id="text117">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text119">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use121" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text123">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text125">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text127">'x'</text>
+ </g>
+ <!-- LEGEND -->
+ <g
+ transform="translate(740, 110)"
+ id="g143">
+ <path
+ d="M 102 -20 h -120 v 60"
+ stroke="black"
+ id="path131" />
+ <text
+ class="text_normal"
+ transform="translate(0, 0)"
+ id="text133">Legend</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(0, 10)"
+ id="use135" />
+ <text
+ class="text_small"
+ transform="translate(3, 23)"
+ id="text137">xmin</text>
+ <text
+ class="text_small"
+ transform="translate(32, 23)"
+ id="text139">xmax</text>
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text141">data</text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-raw.svg b/doc/src/sgml/images/mvcc-raw.svg
new file mode 100644
index 0000000000..0481c4c938
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-raw.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="150px"
+ viewBox="0 0 850 150" >
+
+ <title>MVCC</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <marker id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto" stroke="black" fill="none">
+ <path d="M 0,0 L 10,5 L 0,10" />
+ </marker>
+
+ <g id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20" stroke="black"/>
+ <!-- prolong the rectangle -->
+ <path d="M 80 0 h 15 M 80 20 h 15" stroke="black" stroke-dasharray="2 1"/>
+ </g>
+
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path id="arrow" d="M 0 0 Q 20 -15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- set default values -->
+ <g fill="none">
+
+ <!-- start plus first INSERT -->
+ <g transform="translate(20, 40)">
+
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">123</tspan>
+ <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)" style="fill:blue">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 83)" style="fill:blue">'x'</text>
+ </g>
+
+ <!-- first UPDATE -->
+ <g transform="translate(185, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">135</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 53)" style="fill:blue">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- next UPDATE -->
+ <g transform="translate(350, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">142</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 23)" style="fill:blue">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- DELETE -->
+ <g transform="translate(515, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">821</tspan>
+ <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">821</text>
+ <text class="text_small" transform="translate(125, 23)">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- LEGEND -->
+ <g transform="translate(740, 110)">
+ <path d="M 102 -20 h -120 v 60" stroke="black"/>
+ <text class="text_normal" transform="translate(0, 0)">Legend</text>
+ <use xlink:href="#tuple" transform="translate(0, 10)"/>
+ <text class="text_small" transform="translate(3, 23)">xmin</text>
+ <text class="text_small" transform="translate(32, 23)">xmax</text>
+ <text class="text_small" transform="translate(65, 23)">data</text>
+ </g>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink-svgo.svg b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
new file mode 100644
index 0000000000..723d67bd8d
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
@@ -0,0 +1,285 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 900 600">
+ <title>
+ PG Overall Server Architecture
+ </title>
+ <style>
+ .text_big{font-style:normal}.text_big,.text_comment,.text_normal,.text_small{font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_normal,.text_small{font-style:normal}.text_small{font-size:12px}.text_normal{font-size:16px}.text_big{font-size:24px}.text_comment{font-style:italic;font-size:16px}
+ </style>
+ <defs>
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (200 x 20 px)
+ </title>
+ <path d="M200 10v10H0V0h190v10h10L190 0"/>
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (250 x 20 px)
+ </title>
+ <path d="M250 10v10H0V0h240v10h10L240 0"/>
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (100 x 35 px)
+ </title>
+ <path d="M100 10v25H0V0h90v10h10L90 0"/>
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (170 x 50 px)
+ </title>
+ <path d="M170 10v40H0V0h160v10h10L160 0"/>
+ </symbol>
+ <symbol id="state_300x120">
+ <title>
+ UML State (300x120)
+ </title>
+ <rect width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>
+ UML State (350x120)
+ </title>
+ <rect width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="disc" stroke="blue" fill="none">
+ <title>
+ Disc
+ </title>
+ <ellipse cx="51" cy="13" rx="50" ry="12"/>
+ <path d="M1 13v60"/>
+ <path d="M101 13v60"/>
+ <path d="M1 73a50 12 0 00100 0"/>
+ </symbol>
+ <symbol id="laptop" stroke="black" fill="none">
+ <title>
+ Laptop
+ </title>
+ <path d="M20 40V0h54v40l15 15H5l15-15h54"/>
+ <path d="M23 3h48v34H23z"/>
+ <path d="M30 10h20"/>
+ <path d="M30 15h25"/>
+ <path d="M30 20h10"/>
+ <path d="M30 30h20"/>
+ <path d="M25 50h45l2 2H22z"/>
+ </symbol>
+ <marker id="arrowhead_start" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto">
+ <path d="M6 0L0 3l6 3" stroke="black" fill="none"/>
+ </marker>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="15" y="40" class="text_big">
+ Client
+ </text>
+ <text x="140" y="40" class="text_big">
+ Server
+ </text>
+ <use xlink:href="#laptop" x="5" y="210"/>
+ <g transform="translate(130 70)">
+ <use xlink:href="#state_350x120"/>
+ <text x="5" y="20" class="text_normal">
+ maintenance_work_mem (per connection)
+ </text>
+ <text x="5" y="45" class="text_normal">
+ work_mem (per query operation)
+ </text>
+ <text x="5" y="70" class="text_normal">
+ autovacuum_work_mem (per worker process)
+ </text>
+ <text x="5" y="95" class="text_normal">
+ temp_buffer (per connection)
+ </text>
+ <text x="5" y="110" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_200x20" x="140" y="-15"/>
+ <text x="150" class="text_comment">
+ Individual Memory
+ </text>
+ </g>
+ <g transform="translate(520 70)">
+ <use xlink:href="#state_300x120"/>
+ <text x="10" y="30" class="text_normal">
+ shared_buffers (heap and index)
+ </text>
+ <text x="10" y="70" class="text_normal">
+ wal_buffers (WAL records)
+ </text>
+ <text x="10" y="100" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_250x20" x="40" y="-15"/>
+ <text x="50" class="text_comment">
+ Shared Memory (per Instance)
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M180 215h250v30H180z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(180 215)">
+ Postmaster
+ </text>
+ <path d="M90 230h75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 230)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 1
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M150 315h370v30H150z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(150 315)">
+ Backend processes (one per connection)
+ </text>
+ <path d="M155 315v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M160 310v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M90 240l63 63" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 290)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 3
+ </text>
+ </g>
+ <path d="M360 250v50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180 255)">
+ <use xlink:href="#note_250x20"/>
+ <text x="10" y="15" class="text_comment">
+ Creates backend processes
+ </text>
+ </g>
+ <g transform="translate(360 281)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 2
+ </text>
+ </g>
+ <path d="M460 300V200" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M498 300V95h30" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M508 300V135h20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M550 220h120v30H550z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(550 220)">
+ WAL Writer
+ </text>
+ <path d="M590 150v65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M590 255v230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 340h140v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 340)">
+ Checkpointer
+ </text>
+ <path d="M740 110v220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 355H475v130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M700 330V150" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50"/>
+ <text x="60" y="-35" class="text_comment">
+ Checkpoint
+ </text>
+ <text x="60" y="-20" class="text_comment">
+ Record
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M610 380h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 380)">
+ Background Writer
+ </text>
+ <path d="M770 110v260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 395H485v90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 420h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 420)">
+ WAL Archiver
+ </text>
+ <path d="M620 485l30-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M690 455l30 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M135 380h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 380)">
+ Autovacuum
+ </text>
+ <path d="M140 380v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path d="M145 375v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path stroke="blue" fill="none" d="M135 430h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 430)">
+ Logger
+ </text>
+ <path stroke="blue" fill="none" d="M290 370h140v30H290z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(290 370)">
+ Stats Collector
+ </text>
+ <g transform="translate(145 490)">
+ <use xlink:href="#disc"/>
+ <text x="35" y="45" class="text_normal">
+ Log
+ </text>
+ <text x="20" y="60" class="text_small">
+ text lines,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <path d="M195 465v20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(410 490)">
+ <use xlink:href="#disc"/>
+ <text x="10" y="40" class="text_normal">
+ Heap and
+ </text>
+ <text x="25" y="55" class="text_normal">
+ Index
+ </text>
+ <text x="15" y="70" class="text_small">
+ binary blocks,
+ </text>
+ <text x="30" y="80" class="text_small">
+ random
+ </text>
+ </g>
+ <path d="M450 485V350" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(295 420)">
+ <use xlink:href="#note_170x50"/>
+ <text x="5" y="15" class="text_comment">
+ Read heap and index
+ </text>
+ <text x="5" y="30" class="text_comment">
+ pages and transfer
+ </text>
+ <text x="5" y="45" class="text_comment">
+ them to shared_buffers
+ </text>
+ </g>
+ <g transform="translate(550 490)">
+ <use xlink:href="#disc"/>
+ <text x="30" y="45" class="text_normal">
+ WAL
+ </text>
+ <text x="10" y="60" class="text_small">
+ binary records,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <g transform="translate(690 490)">
+ <use xlink:href="#disc"/>
+ <text x="16" y="45" class="text_normal">
+ Archived
+ </text>
+ <text x="36" y="60" class="text_normal">
+ WAL
+ </text>
+ </g>
+ <path d="M110 20v550" stroke="black" fill="none"/>
+ <g transform="rotate(90 -33.5 156.5)">
+ <use xlink:href="#note_200x20"/>
+ <text class="text_comment" x="10" y="15">
+ Via TCP/IP or socket
+ </text>
+ </g>
+ <text class="text_big" x="95" transform="rotate(90 425 425)">
+ RAM
+ </text>
+ <text class="text_big" x="250" transform="rotate(90 425 425)">
+ PROCESSES
+ </text>
+ <text class="text_big" x="500" transform="rotate(90 425 425)">
+ FILES
+ </text>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink.svg b/doc/src/sgml/images/ram-proc-file-ink.svg
new file mode 100644
index 0000000000..4490bf51e1
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink.svg
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="600px"
+ viewBox="0 0 900 600"
+ id="svg306"
+ sodipodi:docname="ram-proc-file-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata310">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>PG Overall Server Architecture</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1048"
+ inkscape:window-height="771"
+ id="namedview308"
+ showgrid="false"
+ inkscape:zoom="0.39333333"
+ inkscape:cx="450"
+ inkscape:cy="300"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg306" />
+ <title
+ id="title2">PG Overall Server Architecture</title>
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs70">
+ <!-- Some notes in different sizes -->
+ <symbol
+ id="note_200x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title6">UML Note (200 x 20 px)</title>
+ <path
+ d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10"
+ id="path8" />
+ </symbol>
+ <symbol
+ id="note_250x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title11">UML Note (250 x 20 px)</title>
+ <path
+ d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10"
+ id="path13" />
+ </symbol>
+ <symbol
+ id="note_100x35"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title16">UML Note (100 x 35 px)</title>
+ <path
+ d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10"
+ id="path18" />
+ </symbol>
+ <symbol
+ id="note_170x50"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title21">UML Note (170 x 50 px)</title>
+ <path
+ d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10"
+ id="path23" />
+ </symbol>
+ <!-- UML states (used for buffers) -->
+ <symbol
+ id="state_300x120">
+ <title
+ id="title26">UML State (300x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="300"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect28" />
+ </symbol>
+ <symbol
+ id="state_350x120">
+ <title
+ id="title31">UML State (350x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="350"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect33" />
+ </symbol>
+ <!-- Discs -->
+ <symbol
+ id="disc"
+ stroke="blue"
+ fill="none">
+ <title
+ id="title36">Disc</title>
+ <ellipse
+ cx="51"
+ cy="13"
+ rx="50"
+ ry="12"
+ id="ellipse38" />
+ <!-- top -->
+ <path
+ d="M 1,13 v 60"
+ id="path40" />
+ <!-- left -->
+ <path
+ d="M 101,13 v 60"
+ id="path42" />
+ <!-- right -->
+ <path
+ d="M 1,73 A 50, 12, 0, 0, 0, 101,73"
+ id="path44" />
+ <!-- bottom -->
+ </symbol>
+ <!-- Laptop -->
+ <symbol
+ id="laptop"
+ stroke="black"
+ fill="none">
+ <title
+ id="title47">Laptop</title>
+ <path
+ d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54"
+ id="path49" />
+ <rect
+ x="23"
+ y="3"
+ width="48"
+ height="34"
+ id="rect51" />
+ <!-- symbolize some lines -->
+ <path
+ d="M 30,10 h 20"
+ id="path53" />
+ <path
+ d="M 30,15 h 25"
+ id="path55" />
+ <path
+ d="M 30,20 h 10"
+ id="path57" />
+ <path
+ d="M 30,30 h 20"
+ id="path59" />
+ <!-- symbolize keyboard -->
+ <path
+ d="M 25,50 h 45 l 2,2 h -50 z "
+ id="path61" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path64" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path67" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect72" />
+ <!-- caption, client side -->
+ <text
+ x="15"
+ y="40"
+ class="text_big"
+ id="text74">Client</text>
+ <text
+ x="140"
+ y="40"
+ class="text_big"
+ id="text76">Server</text>
+ <use
+ xlink:href="#laptop"
+ x="5"
+ y="210"
+ id="use78" />
+ <!-- individual memory -->
+ <g
+ transform="translate(130, 70)"
+ id="g96">
+ <use
+ xlink:href="#state_350x120"
+ x="0"
+ y="0"
+ id="use80" />
+ <text
+ x="5"
+ y="20"
+ class="text_normal"
+ id="text82">maintenance_work_mem (per connection)</text>
+ <text
+ x="5"
+ y="45"
+ class="text_normal"
+ id="text84">work_mem (per query operation)</text>
+ <text
+ x="5"
+ y="70"
+ class="text_normal"
+ id="text86">autovacuum_work_mem (per worker process)</text>
+ <text
+ x="5"
+ y="95"
+ class="text_normal"
+ id="text88">temp_buffer (per connection)</text>
+ <text
+ x="5"
+ y="110"
+ class="text_normal"
+ id="text90">...</text>
+ <use
+ xlink:href="#note_200x20"
+ x="140"
+ y="-15"
+ id="use92" />
+ <text
+ x="150"
+ y="0"
+ class="text_comment"
+ id="text94">Individual Memory</text>
+ </g>
+ <!-- shared memory -->
+ <g
+ transform="translate(520, 70)"
+ id="g110">
+ <use
+ xlink:href="#state_300x120"
+ x="0"
+ y="0"
+ id="use98" />
+ <text
+ x="10"
+ y="30"
+ class="text_normal"
+ id="text100">shared_buffers (heap and index)</text>
+ <text
+ x="10"
+ y="70"
+ class="text_normal"
+ id="text102">wal_buffers (WAL records)</text>
+ <text
+ x="10"
+ y="100"
+ class="text_normal"
+ id="text104">...</text>
+ <use
+ xlink:href="#note_250x20"
+ x="40"
+ y="-15"
+ id="use106" />
+ <text
+ x="50"
+ y="0"
+ class="text_comment"
+ id="text108">Shared Memory (per Instance)</text>
+ </g>
+ <!-- postmaster -->
+ <g
+ transform="translate(180, 215)"
+ id="g116">
+ <rect
+ width="250"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect112" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text114">Postmaster</text>
+ </g>
+ <path
+ d="M 90,230 h 75"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path118" />
+ <g
+ transform="translate(140, 230)"
+ id="g124">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle120" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text122">1</text>
+ </g>
+ <!-- backend processes -->
+ <g
+ transform="translate(150, 315)"
+ id="g134">
+ <rect
+ width="370"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect126" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text128">Backend processes (one per connection)</text>
+ <path
+ d="M 5,0 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path130" />
+ <path
+ d="M 10,-5 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path132" />
+ </g>
+ <path
+ d="M 90,240 153,303"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path136" />
+ <g
+ transform="translate(140, 290)"
+ id="g142">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle138" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text140">3</text>
+ </g>
+ <!-- connection between postmaster and backend processes -->
+ <path
+ d="M 360,250 v 50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path144" />
+ <g
+ transform="translate(180, 255)"
+ id="g150">
+ <use
+ xlink:href="#note_250x20"
+ id="use146" />
+ <text
+ x="10"
+ y="15"
+ class="text_comment"
+ id="text148">Creates backend processes</text>
+ </g>
+ <g
+ transform="translate(360, 281)"
+ id="g156">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle152" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text154">2</text>
+ </g>
+ <!-- backend process' access to individual memory -->
+ <path
+ d="M 460,300 v -100"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path158" />
+ <!-- its access to shared buffers and WAL buffers -->
+ <path
+ d="M 498,300 v -205 h 30"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path160" />
+ <path
+ d="M 508,300 v -165 h 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path162" />
+ <!-- WAL writer -->
+ <g
+ transform="translate(550, 220)"
+ id="g168">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect164" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text166">WAL Writer</text>
+ </g>
+ <path
+ d="M 590,150 v 65"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path170" />
+ <path
+ d="M 590,255 v 230"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path172" />
+ <!-- Checkpoiner -->
+ <g
+ transform="translate(610, 340)"
+ id="g178">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect174" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text176">Checkpointer</text>
+ </g>
+ <path
+ d="M 740,110 v 220"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path180" />
+ <path
+ d="M 605,355 h -130 v 130"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path182" />
+ <path
+ d="M 700,330 v -180"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path184" />
+ <g
+ transform="translate(570, 330)"
+ id="g192">
+ <use
+ xlink:href="#note_100x35"
+ x="50"
+ y="-50"
+ id="use186" />
+ <text
+ x="60"
+ y="-35"
+ class="text_comment"
+ id="text188">Checkpoint</text>
+ <text
+ x="60"
+ y="-20"
+ class="text_comment"
+ id="text190">Record</text>
+ </g>
+ <!-- BG writer -->
+ <g
+ transform="translate(610, 380)"
+ id="g198">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect194" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text196">Background Writer</text>
+ </g>
+ <path
+ d="M 770,110 v 260"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path200" />
+ <path
+ d="M 605,395 h -120 v 90"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path202" />
+ <!-- Archiver -->
+ <g
+ transform="translate(610, 420)"
+ id="g208">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect204" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text206">WAL Archiver</text>
+ </g>
+ <path
+ d="M 620,485 l 30,-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path210" />
+ <path
+ d="M 690,455 l 30, 30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path212" />
+ <!-- Vacuum -->
+ <g
+ transform="translate(135, 380)"
+ id="g222">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect214" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text216">Autovacuum</text>
+ <path
+ d="M 5,0 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path218" />
+ <path
+ d="M 10,-5 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path220" />
+ </g>
+ <!-- Log Writer -->
+ <g
+ transform="translate(135, 430)"
+ id="g228">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect224" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text226">Logger</text>
+ </g>
+ <!-- Stats Collector -->
+ <g
+ transform="translate(290, 370)"
+ id="g234">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect230" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text232">Stats Collector</text>
+ </g>
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g
+ transform="translate(145, 490)"
+ id="g244">
+ <use
+ xlink:href="#disc"
+ id="use236" />
+ <text
+ x="35"
+ y="45"
+ class="text_normal"
+ id="text238">Log</text>
+ <text
+ x="20"
+ y="60"
+ class="text_small"
+ id="text240">text lines,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text242">sequential</text>
+ </g>
+ <path
+ d="M 195,465 v 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path246" />
+ <g
+ transform="translate(410, 490)"
+ id="g258">
+ <use
+ xlink:href="#disc"
+ id="use248" />
+ <text
+ x="10"
+ y="40"
+ class="text_normal"
+ id="text250">Heap and</text>
+ <text
+ x="25"
+ y="55"
+ class="text_normal"
+ id="text252">Index</text>
+ <text
+ x="15"
+ y="70"
+ class="text_small"
+ id="text254">binary blocks,</text>
+ <text
+ x="30"
+ y="80"
+ class="text_small"
+ id="text256">random</text>
+ </g>
+ <path
+ d="M 450,485 v -135"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path260" />
+ <g
+ transform="translate(295, 420)"
+ id="g270">
+ <use
+ xlink:href="#note_170x50"
+ id="use262" />
+ <text
+ x="5"
+ y="15"
+ class="text_comment"
+ id="text264">Read heap and index</text>
+ <text
+ x="5"
+ y="30"
+ class="text_comment"
+ id="text266">pages and transfer</text>
+ <text
+ x="5"
+ y="45"
+ class="text_comment"
+ id="text268">them to shared_buffers</text>
+ </g>
+ <g
+ transform="translate(550, 490)"
+ id="g280">
+ <use
+ xlink:href="#disc"
+ id="use272" />
+ <text
+ x="30"
+ y="45"
+ class="text_normal"
+ id="text274">WAL</text>
+ <text
+ x="10"
+ y="60"
+ class="text_small"
+ id="text276">binary records,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text278">sequential</text>
+ </g>
+ <g
+ transform="translate(690, 490)"
+ id="g288">
+ <use
+ xlink:href="#disc"
+ id="use282" />
+ <text
+ x="16"
+ y="45"
+ class="text_normal"
+ id="text284">Archived</text>
+ <text
+ x="36"
+ y="60"
+ class="text_normal"
+ id="text286">WAL</text>
+ </g>
+ <!-- boarder between client and server side -->
+ <path
+ d="M 110,20 v 550"
+ stroke="black"
+ fill="none"
+ id="path290" />
+ <g
+ transform="translate(123, 190) rotate(90)"
+ id="g296">
+ <use
+ xlink:href="#note_200x20"
+ id="use292" />
+ <text
+ class="text_comment"
+ x="10"
+ y="15"
+ id="text294">Via TCP/IP or socket</text>
+ </g>
+ <!-- right side -->
+ <g
+ transform="translate(850, 0) rotate(90)"
+ id="g304">
+ <text
+ class="text_big"
+ x="95"
+ id="text298">RAM</text>
+ <text
+ class="text_big"
+ x="250"
+ id="text300">PROCESSES</text>
+ <text
+ class="text_big"
+ x="500"
+ id="text302">FILES</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-raw.svg b/doc/src/sgml/images/ram-proc-file-raw.svg
new file mode 100644
index 0000000000..aec5811c54
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-raw.svg
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="600px"
+ viewBox="0 0 900 600">
+
+ <title>PG Overall Server Architecture</title>
+
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Some notes in different sizes -->
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>UML Note (200 x 20 px)</title>
+ <path d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>UML Note (250 x 20 px)</title>
+ <path d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>UML Note (100 x 35 px)</title>
+ <path d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>UML Note (170 x 50 px)</title>
+ <path d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- UML states (used for buffers) -->
+ <symbol id="state_300x120">
+ <title>UML State (300x120)</title>
+ <rect x="0" y="0" width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>UML State (350x120)</title>
+ <rect x="0" y="0" width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- Discs -->
+ <symbol id="disc" stroke="blue" fill="none" >
+ <title>Disc</title>
+ <ellipse cx="51" cy="13" rx="50" ry="12" /> <!-- top -->
+ <path d="M 1,13 v 60" /> <!-- left -->
+ <path d="M 101,13 v 60" /> <!-- right -->
+ <path d="M 1,73 A 50, 12, 0, 0, 0, 101,73" /> <!-- bottom -->
+ </symbol>
+
+ <!-- Laptop -->
+ <symbol id="laptop" stroke="black" fill="none" >
+ <title>Laptop</title>
+ <path d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54" />
+ <rect x="23" y="3" width="48" height="34" />
+ <!-- symbolize some lines -->
+ <path d="M 30,10 h 20" />
+ <path d="M 30,15 h 25" />
+ <path d="M 30,20 h 10" />
+ <path d="M 30,30 h 20" />
+ <!-- symbolize keyboard -->
+ <path d="M 25,50 h 45 l 2,2 h -50 z " />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption, client side -->
+ <text x="15" y="40" class="text_big">Client</text>
+ <text x="140" y="40" class="text_big">Server</text>
+ <use xlink:href="#laptop" x="5" y="210" />
+
+
+ <!-- individual memory -->
+ <g transform="translate(130, 70)">
+ <use xlink:href="#state_350x120" x="0" y="0" />
+ <text x="5" y="20" class="text_normal">maintenance_work_mem (per connection)</text>
+ <text x="5" y="45" class="text_normal">work_mem (per query operation)</text>
+ <text x="5" y="70" class="text_normal">autovacuum_work_mem (per worker process)</text>
+ <text x="5" y="95" class="text_normal">temp_buffer (per connection)</text>
+ <text x="5" y="110" class="text_normal">...</text>
+ <use xlink:href="#note_200x20" x="140" y="-15" />
+ <text x="150" y="0" class="text_comment">Individual Memory</text>
+ </g>
+
+ <!-- shared memory -->
+ <g transform="translate(520, 70)">
+ <use xlink:href="#state_300x120" x="0" y="0" />
+ <text x="10" y="30" class="text_normal">shared_buffers (heap and index)</text>
+ <text x="10" y="70" class="text_normal">wal_buffers (WAL records)</text>
+ <text x="10" y="100" class="text_normal">...</text>
+ <use xlink:href="#note_250x20" x="40" y="-15" />
+ <text x="50" y="0" class="text_comment">Shared Memory (per Instance)</text>
+ </g>
+
+ <!-- postmaster -->
+ <g transform="translate(180, 215)">
+ <rect width="250" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Postmaster</text>
+ </g>
+ <path d="M 90,230 h 75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 230)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">1</text>
+ </g>
+
+ <!-- backend processes -->
+ <g transform="translate(150, 315)">
+ <rect width="370" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Backend processes (one per connection)</text>
+ <path d="M 5,0 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <path d="M 90,240 153,303" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 290)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">3</text>
+ </g>
+
+ <!-- connection between postmaster and backend processes -->
+ <path d="M 360,250 v 50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180, 255)">
+ <use xlink:href="#note_250x20" />
+ <text x="10" y="15" class="text_comment">Creates backend processes</text>
+ </g>
+ <g transform="translate(360, 281)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">2</text>
+ </g>
+
+ <!-- backend process' access to individual memory -->
+ <path d="M 460,300 v -100" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <!-- its access to shared buffers and WAL buffers -->
+ <path d="M 498,300 v -205 h 30" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M 508,300 v -165 h 20" stroke="black" fill="none"
+ marker-end="url(#arrowhead_end)"/>
+
+ <!-- WAL writer -->
+ <g transform="translate(550, 220)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Writer</text>
+ </g>
+ <path d="M 590,150 v 65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 590,255 v 230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Checkpoiner -->
+ <g transform="translate(610, 340)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Checkpointer</text>
+ </g>
+ <path d="M 740,110 v 220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,355 h -130 v 130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 700,330 v -180" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570, 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50" />
+ <text x="60" y="-35" class="text_comment">Checkpoint</text>
+ <text x="60" y="-20" class="text_comment">Record</text>
+ </g>
+
+ <!-- BG writer -->
+ <g transform="translate(610, 380)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Background Writer</text>
+ </g>
+ <path d="M 770,110 v 260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,395 h -120 v 90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Archiver -->
+ <g transform="translate(610, 420)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Archiver</text>
+ </g>
+ <path d="M 620,485 l 30,-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 690,455 l 30, 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Vacuum -->
+ <g transform="translate(135, 380)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Autovacuum</text>
+ <path d="M 5,0 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <!-- Log Writer -->
+ <g transform="translate(135, 430)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Logger</text>
+ </g>
+
+ <!-- Stats Collector -->
+ <g transform="translate(290, 370)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Stats Collector</text>
+ </g>
+
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g transform="translate(145, 490)">
+ <use xlink:href="#disc" />
+ <text x="35" y="45" class="text_normal">Log</text>
+ <text x="20" y="60" class="text_small">text lines,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+ <path d="M 195,465 v 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(410, 490)">
+ <use xlink:href="#disc" />
+ <text x="10" y="40" class="text_normal">Heap and</text>
+ <text x="25" y="55" class="text_normal">Index</text>
+ <text x="15" y="70" class="text_small">binary blocks,</text>
+ <text x="30" y="80" class="text_small">random</text>
+ </g>
+ <path d="M 450,485 v -135" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(295, 420)">
+ <use xlink:href="#note_170x50" />
+ <text x="5" y="15" class="text_comment">Read heap and index</text>
+ <text x="5" y="30" class="text_comment">pages and transfer</text>
+ <text x="5" y="45" class="text_comment">them to shared_buffers</text>
+ </g>
+
+ <g transform="translate(550, 490)">
+ <use xlink:href="#disc" />
+ <text x="30" y="45" class="text_normal">WAL</text>
+ <text x="10" y="60" class="text_small">binary records,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+
+ <g transform="translate(690, 490)">
+ <use xlink:href="#disc" />
+ <text x="16" y="45" class="text_normal">Archived</text>
+ <text x="36" y="60" class="text_normal">WAL</text>
+ </g>
+
+ <!-- boarder between client and server side -->
+ <path d="M 110,20 v 550" stroke="black" fill="none" />
+ <g transform="translate(123, 190) rotate(90)">
+ <use xlink:href="#note_200x20" />
+ <text class="text_comment" x="10" y ="15">Via TCP/IP or socket</text>
+ </g>
+
+ <!-- right side -->
+ <g transform="translate(850, 0) rotate(90)">
+ <text class="text_big" x="95">RAM</text>
+ <text class="text_big" x="250">PROCESSES</text>
+ <text class="text_big" x="500">FILES</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink-svgo.svg b/doc/src/sgml/images/wraparound-ink-svgo.svg
new file mode 100644
index 0000000000..9882d2be23
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink-svgo.svg
@@ -0,0 +1,40 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="280" viewBox="0 0 850 280">
+ <title>
+ Cyclic usage of XIDs
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="370" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ Cyclic usage of XIDs modulo 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan>
+ </text>
+ <g fill="none" transform="translate(170 150)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_095" startOffset="30.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="30%">(1)</textPath> <textPath xlink:href="#Path_095" startOffset="45.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(2)</textPath> <textPath xlink:href="#Path_095" startOffset="50.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="50%">(3)</textPath> <textPath xlink:href="#Path_095" startOffset="62.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="62%">(4)</textPath>
+ </text>
+ </g>
+ <g class="text_normal">
+ <text transform="translate(400 130)">
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25" transform="translate(400 130)">
+ 1: oldest <tspan font-weight="700">active</tspan> xid (pg_stat_activity.backend_xmin)
+ </text>
+ <text y="50" transform="translate(400 130)">
+ 2: xmin of one row version
+ </text>
+ <text y="75" transform="translate(400 130)">
+ 3: xmax of the same row version
+ </text>
+ <text y="100" transform="translate(400 130)">
+ 4: jungest xid (txid_current)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink.svg b/doc/src/sgml/images/wraparound-ink.svg
new file mode 100644
index 0000000000..a9c51f4e43
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="280px"
+ viewBox="0 0 850 280"
+ id="svg1072"
+ sodipodi:docname="wraparound-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata1076">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Cyclic usage of XIDs</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1193"
+ inkscape:window-height="788"
+ id="namedview1074"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="140"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg1072" />
+ <title
+ id="title1009">Cyclic usage of XIDs</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style1011">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs1016">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect1018" />
+ <text
+ class="text_big"
+ x="370"
+ y="40"
+ id="text1024">Cyclic usage of XIDs modulo 2
+ <tspan
+ dy="-5"
+ id="tspan1020">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1022">32</tspan>
+</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 150)"
+ id="g1052">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle1026" />
+ <text
+ class="text_normal"
+ id="text1050">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath1028">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath1030">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath1032">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="30.5%"
+ id="textPath1034">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="30%"
+ id="textPath1036">(1)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="45.5%"
+ id="textPath1038">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath1040">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="50.5%"
+ id="textPath1042">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="50%"
+ id="textPath1044">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="62.5%"
+ id="textPath1046">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="62%"
+ id="textPath1048">(4)</textPath>
+ </text>
+ </g>
+ <g
+ class="text_normal"
+ transform="translate(400 130)"
+ id="g1070">
+ <text
+ id="text1058">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan1054">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1056">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text1062">1: oldest <tspan
+ style="font-weight:bold"
+ id="tspan1060">active</tspan>
+ xid (pg_stat_activity.backend_xmin)</text>
+ <text
+ y="50"
+ id="text1064">2: xmin of one row version</text>
+ <text
+ y="75"
+ id="text1066">3: xmax of the same row version</text>
+ <text
+ y="100"
+ id="text1068">4: jungest xid (txid_current)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-raw.svg b/doc/src/sgml/images/wraparound-raw.svg
new file mode 100644
index 0000000000..9406f52970
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-raw.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="280px"
+ viewBox="0 0 850 280" >
+
+ <title>Cyclic usage of XIDs</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="370" y="40">Cyclic usage of XIDs modulo 2
+ <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan></text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 150)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_095" startOffset="30.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="30%" >(1)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="45.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(2)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="50.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="50%" >(3)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="62.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="62%" >(4)</textPath>
+ </text>
+ </g>
+
+ <g class="text_normal" transform="translate(400 130)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: oldest <tspan style="font-weight:bold">active</tspan> xid (pg_stat_activity.backend_xmin)</text>
+ <text y="50">2: xmin of one row version</text>
+ <text y="75">3: xmax of the same row version</text>
+ <text y="100">4: jungest xid (txid_current)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index c41ce9499b..7913f45897 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -62,6 +62,7 @@ break is not needed in a wider output rendering.
&start;
&query;
&advanced;
+ &architecture;
</part>
diff --git a/doc/src/sgml/query.sgml b/doc/src/sgml/query.sgml
index c0889743c4..b1906c6e36 100644
--- a/doc/src/sgml/query.sgml
+++ b/doc/src/sgml/query.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/query.sgml -->
<chapter id="tutorial-sql">
- <title>The <acronym>SQL</acronym> Language</title>
+ <title>Fundamentals of the <acronym>SQL</acronym> Language</title>
<sect1 id="tutorial-sql-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml
index 9bb5c1a6d5..8751410179 100644
--- a/doc/src/sgml/start.sgml
+++ b/doc/src/sgml/start.sgml
@@ -53,7 +53,7 @@
<sect1 id="tutorial-arch">
- <title>Architectural Fundamentals</title>
+ <title>Client/Server Model</title>
<para>
Before we proceed, you should understand the basic
@@ -68,34 +68,55 @@
client/server model. A <productname>PostgreSQL</productname>
session consists of the following cooperating processes
(programs):
+ </para>
- <itemizedlist>
- <listitem>
- <para>
- A server process, which manages the database files, accepts
- connections to the database from client applications, and
- performs database actions on behalf of the clients. The
- database server program is called
- <filename>postgres</filename>.
- <indexterm><primary>postgres</primary></indexterm>
- </para>
- </listitem>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A process at the server site with the name
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ <indexterm><primary>postgres</primary></indexterm>
+ It accepts connection requests from client applications, starts
+ (<quote>forks</quote>) a new <glossterm linkend="glossary-backend">
+ Backend process</glossterm> for each of them, and passes
+ the connection to it. From that point on, the client and the new
+ <firstterm>Backend process</firstterm>
+ communicate directly without intervention by the original
+ <firstterm>postgres</firstterm> process. Thus, the
+ <firstterm>postgres</firstterm> process is always running, waiting
+ for new client connections, whereas clients and associated
+ <firstterm>Backend processes</firstterm> come and go.
+ (All of this is of course invisible to the user. We only mention it
+ here for completeness.)
+ </para>
+ </listitem>
- <listitem>
- <para>
- The user's client (frontend) application that wants to perform
- database operations. Client applications can be very diverse
- in nature: a client could be a text-oriented tool, a graphical
- application, a web server that accesses the database to
- display web pages, or a specialized database maintenance tool.
- Some client applications are supplied with the
- <productname>PostgreSQL</productname> distribution; most are
- developed by users.
- </para>
- </listitem>
+ <listitem>
+ <para>
+ A group of processes at the server site, the <glossterm
+ linkend="glossary-instance">instance</glossterm>, to which also the
+ <firstterm>postgres</firstterm> process belongs. Their duties are
+ handling of central, common database activities like file access,
+ vacuum, <glossterm linkend="glossary-checkpoint">checkpoints</glossterm>,
+ replication, and more. The mentioned <firstterm>Backend processes</firstterm>
+ delegate those actions to the <firstterm>instance</firstterm>.
+ </para>
+ </listitem>
- </itemizedlist>
- </para>
+ <listitem>
+ <para>
+ The user's client (frontend) application that wants to perform
+ database operations. Client applications can be very diverse
+ in nature: a client could be a text-oriented tool, a graphical
+ application, a web server that accesses the database to
+ display web pages, or a specialized database maintenance tool.
+ Some client applications are supplied with the
+ <productname>PostgreSQL</productname> distribution; most are
+ developed by users.
+ </para>
+ </listitem>
+
+ </itemizedlist>
<para>
As is typical of client/server applications, the client and the
Hi all,
I want to import XML file into PG database table.
I've find functions to get the XML content of a cell after imported an XML file with the pg_get_file function.
But, I want to explode the XML content to colums. How can I do this ?
PG 10 under Ubuntu 18
_________________________________
Cordialement, Pascal CROZET
DBA - Qualis Consulting
• 300 Route Nationale 6 – 69760 LIMONEST
_________________________________
Again, I don't see how this belongs into the tutorial. It is mostly
advanced low-level information that is irrelevant for someone starting
up, it is not hands-on, so quite unlike the rest of the tutorial, and
for the most part the information just duplicates what is already
explained elsewhere.
--
Peter Eisentraut http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
On 01.09.20 23:30, Peter Eisentraut wrote:
It is mostly advanced low-level information that is irrelevant for
someone starting up,
That applies only to the VACUUM chapter. VACUUM and AUTOVACUUM are
controlled by a lot of parameters. Therefor the current documentation
concerning the two mechanism spreads the description across different
pages (20.4, 25.1, VACUUM command). Because of the structure of our
documentation that's ok. But we should have a summary page somewhere -
not necessarily in the tutorial.
the most part the information just duplicates what is already
explained elsewhere.
That is the nature of a tutorial respectively a summary.
--
J. Purtz
On 2020-09-02 09:04, Jürgen Purtz wrote:
On 01.09.20 23:30, Peter Eisentraut wrote:
It is mostly advanced low-level information that is irrelevant for
someone starting up,That applies only to the VACUUM chapter. VACUUM and AUTOVACUUM are
controlled by a lot of parameters. Therefor the current documentation
concerning the two mechanism spreads the description across different
pages (20.4, 25.1, VACUUM command). Because of the structure of our
documentation that's ok. But we should have a summary page somewhere -
not necessarily in the tutorial.
There is probably room for improvement, but the section numbers you
mention are not about VACUUM, AFAICT, so I can't really comment on what
you have in mind.
--
Peter Eisentraut http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
On 10.09.20 18:26, Peter Eisentraut wrote:
On 2020-09-02 09:04, Jürgen Purtz wrote:
On 01.09.20 23:30, Peter Eisentraut wrote:
It is mostly advanced low-level information that is irrelevant for
someone starting up,That applies only to the VACUUM chapter. VACUUM and AUTOVACUUM are
controlled by a lot of parameters. Therefor the current documentation
concerning the two mechanism spreads the description across different
pages (20.4, 25.1, VACUUM command). Because of the structure of our
documentation that's ok. But we should have a summary page somewhere -
not necessarily in the tutorial.There is probably room for improvement, but the section numbers you
mention are not about VACUUM, AFAICT, so I can't really comment on
what you have in mind.
Because of the additional chapter for the 'tutorial' on my local
computer, the numbers increased for me. The regular chapter numbers are
19.4 and 24.1. Sorry for the confusion. In detail:
19.4: parameters to configure the server, especially five parameters
'vacuum_cost_xxx'.
19.10: parameters to configure autovacuum.
19.11: parameters to configure client connections, especially five
parameters 'vacuum_xxx' concerning their freeze-behavior.
24.1: explains the general necessity of (auto)vacuum and their strategies.
The page about the SQL command VACUUM explains the different options
(FULL, FREEZE, ..) and their meaning.
--
Jürgen Purtz
On Wed, Sep 2, 2020 at 12:04 AM Jürgen Purtz <juergen@purtz.de> wrote:
On 01.09.20 23:30, Peter Eisentraut wrote:
It is mostly advanced low-level information that is irrelevant for
someone starting up,That applies only to the VACUUM chapter. VACUUM and AUTOVACUUM are
controlled by a lot of parameters. Therefor the current documentation
concerning the two mechanism spreads the description across different
pages (20.4, 25.1, VACUUM command). Because of the structure of our
documentation that's ok. But we should have a summary page somewhere -
not necessarily in the tutorial.the most part the information just duplicates what is already
explained elsewhere.That is the nature of a tutorial respectively a summary.
I've begun looking at this and have included quite a few html comments
within the patch. However, the two main items that I have found so far are:
One, I agree with Peter that this seems misplaced in Tutorial. I would
create a new Internals Chapter and place this material there, or maybe
consider a sub-chapter under "Overview of PostgreSQL Internals". If this
is deemed to be of a more primary importance than the content in the
Internals section I would recommend placing it in Reference. I feel it
does fit there and given the general importance of that section readers
will be inclined to click into it and skim over its content.
Two, I find the amount of detail being provided here to be on the too-much
side. A bit more judicious use of links into the appropriate detail
chapters seems warranted.
I took a pretty heavy hand to the original section though aside from the
scope comment it can probably be considered a bit weighted toward style
preferences. Though I did note/rewrite a couple of things that seemed
factually incorrect - and seemingly not done intentionally in the interest
of simplification. Specifically the client connection process and, I
think, the relationship between the checkpointer and background writer.
I do like the idea and the general flow of the material so far - though I
haven't really looked at the overall structure yet, just started reading
and editing from the top of the new file.
I've attached the original 0007 patch and my diff against it applied to
HEAD.
Took a quick peek at the image (at the end) and while I will need a second
pass over this section regardless I figured I'd provide this subset of
feedback now in order to move things along a bit.
David J.
Attachments:
0007-architecture.patchapplication/octet-stream; name=0007-architecture.patchDownload
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
index f6c4627c3e..be04972bd7 100644
--- a/doc/src/sgml/advanced.sgml
+++ b/doc/src/sgml/advanced.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/advanced.sgml -->
<chapter id="tutorial-advanced">
- <title>Advanced Features</title>
+ <title>Advanced SQL Features</title>
<sect1 id="tutorial-advanced-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
new file mode 100644
index 0000000000..2be9898d98
--- /dev/null
+++ b/doc/src/sgml/architecture.sgml
@@ -0,0 +1,1563 @@
+<!-- doc/src/sgml/architecture.sgml -->
+
+ <chapter id="tutorial-architecture">
+ <title>Architectural and implementational Cornerstones</title>
+
+ <para>
+ Every DBMS implements basic strategies for a fast and
+ robust system. This chapter provides an overview of what
+ techniques <productname>PostgreSQL</productname> uses to
+ achieve this.
+ </para>
+
+ <sect1 id="tutorial-ram-proc-file">
+ <title>Collaboration of Processes, RAM, and Files</title>
+ <para>
+ In a client/server architecture
+ clients do not have direct access to the database. Instead,
+ they send requests to the server and receive
+ the requested information. In the case of
+ <productname>PostgreSQL</productname>, at the server-side
+ there is one process per client, the so-called
+ <glossterm linkend="glossary-backend">Backend process</glossterm>.
+ It acts in close cooperation with the
+ <glossterm linkend="glossary-instance">instance</glossterm> which
+ is a group of tightly coupled server-side processes plus a
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>
+ area.
+ </para>
+
+ <para>
+ At startup time, an <firstterm>instance</firstterm> is initiated by the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ The <firstterm>Postmaster</firstterm> process loads the
+ configuration files, allocates
+ <firstterm>Shared Memory</firstterm>,
+ and starts a network of processes:
+ <glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
+ <glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
+ <glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
+ <glossterm linkend="glossary-wal-archiver">WAL Archiver</glossterm>,
+ <glossterm linkend="glossary-autovacuum">Autovacuum</glossterm>,
+ <glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
+ <glossterm linkend="glossary-logger">Logger</glossterm>, and more.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes
+ the main aspects of their collaboration.
+ </para>
+
+ <figure id="tutorial-ram-proc-file-figure">
+ <title>Architecture</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ Whenever a client application tries to connect to a
+ <glossterm linkend="glossary-database">database</glossterm>,
+ this request is handled in a first step by the
+ <firstterm>Postmaster</firstterm> process. It checks authorization,
+ starts a new <firstterm>Backend process</firstterm>,
+ and instructs the client application to connect to it. All
+ further client requests go to this process and are handled
+ by it.
+ </para>
+
+ <para>
+ Client requests like <command>SELECT</command> or
+ <command>UPDATE</command> usually lead to the
+ necessity to read or write some data. In a first attempt
+ the client's <firstterm>Backend process</firstterm> tries
+ to get the information out of <firstterm>Shared
+ Memory</firstterm>. This <firstterm>Shared
+ Memory</firstterm> is a mirror of parts of the
+ <glossterm linkend="glossary-heap">heap</glossterm> and
+ <glossterm linkend="glossary-index">index</glossterm> files.
+ Because files are often larger than memory, it's likely that
+ the desired information is not (completely) available
+ in RAM. In this case the <firstterm>Backend process</firstterm>
+ must transfer additional file pages to
+ <firstterm>Shared Memory</firstterm>. Files are physically
+ organized in pages. Every transfer between files and
+ RAM is performed in units of complete pages; such transfers
+ do not change the size or layout of pages.
+ </para>
+
+ <para>
+ Reading file pages is much slower than reading
+ RAM. This is the primary motivation for the usage of
+ <firstterm>Shared Memory</firstterm>. As soon as one
+ of the <firstterm>Backend processes</firstterm> has
+ read pages into memory, those pages become available for all
+ other <firstterm>Backend processes</firstterm> for direct
+ access in RAM.
+ </para>
+
+ <para>
+ <firstterm>Shared Memory</firstterm> is limited in size.
+ Sooner or later, it becomes necessary to overwrite old RAM
+ pages. As long as the content of such pages hasn't
+ changed, this is not a problem. But in
+ <firstterm>Shared Memory</firstterm> also write
+ actions take place
+ — performed by any of the <firstterm>Backend
+ processes</firstterm> (or an
+ <firstterm>autovacuum</firstterm> process,
+ or other processes). Such modified pages are called
+ <firstterm>dirty pages</firstterm>.
+ Before <firstterm>dirty pages</firstterm> can be overwritten,
+ they must be written back to disk. This is a two-step process.
+ </para>
+
+ <para>
+ First, whenever the content of a page changes, a
+ <glossterm linkend="glossary-wal-record">WAL record</glossterm>
+ is created out
+ of the delta-information (difference between the old and
+ the new content) and stored in another area of
+ <firstterm>Shared Memory</firstterm>. These
+ <firstterm>WAL records</firstterm> are read by the
+ <firstterm>WAL Writer</firstterm> process,
+ which runs in parallel to the <firstterm>Backend
+ processes</firstterm> and other processes of
+ the <firstterm>Instance</firstterm>. It writes
+ the continuously arising <firstterm>WAL records</firstterm> to
+ the end of the current
+ <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
+ Because this writing is sequential, it is much
+ faster than the more or less random access
+ to data files with <firstterm>heap</firstterm>
+ and <firstterm>index</firstterm> information.
+ As mentioned, this WAL-writing happens
+ in an independent process. All
+ <firstterm>WAL records</firstterm> created out of one
+ <firstterm>dirty page</firstterm> must be transferred
+ to disk before the <firstterm>dirty page</firstterm>
+ itself can be transferred to disk.
+ </para>
+
+ <para>
+ Second, the transfer of <firstterm>dirty buffers</firstterm>
+ from <firstterm>Shared Memory</firstterm> to file must
+ take place. This is the primary task of the
+ <firstterm>Background Writer</firstterm> process. Because
+ I/O activities can block other processes significantly,
+ it starts periodically and acts only for a short period.
+ Doing so, its expensive I/O activities are spread over
+ time, avoiding debilitating I/O peaks. Also, the <firstterm>
+ Checkpointer</firstterm> process transfers
+ <firstterm>dirty buffers</firstterm> to file —
+ see next paragraph.
+ </para>
+
+ <para>
+ The <firstterm>Checkpointer</firstterm> creates
+ <glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
+ A <firstterm>Checkpoint</firstterm>
+ is a point in time when all older <firstterm>dirty buffers</firstterm>,
+ all older <firstterm>WAL records</firstterm>, and
+ finally a special <firstterm>Checkpoint record</firstterm>
+ have been written and flushed to disk.
+ After a <firstterm>Checkpoint</firstterm>, we say
+ data files and <firstterm>WAL files</firstterm> are in sync.
+ In case of a recovery (after a crash of the instance)
+ it can be relied upon that the information of all
+ <firstterm>WAL records</firstterm> preceding
+ the last <firstterm>Checkpoint record</firstterm>
+ were already integrated into the data files. This
+ speeds up the recovery.
+ </para>
+
+ <para>
+ As a result of data changes,
+ <firstterm>WAL records</firstterm> arise and get written
+ to <firstterm>WAL files</firstterm>.
+ Those <firstterm>WAL files</firstterm> — in combination with
+ a previously taken <firstterm>Base Backup</firstterm> —
+ are necessary to restore a database after a crash of the
+ disk on which data files have been stored. Therefore it is
+ recommended to transfer a copy of the
+ <firstterm> WAL files</firstterm>
+ to a second, independent place. The purpose of the
+ <firstterm>WAL Archiver</firstterm> process is to perform
+ this copy action.
+ </para>
+
+ <para>
+ The <firstterm>Statistics Collector</firstterm> collects
+ counters about accesses to <firstterm>SQL objects</firstterm>
+ like tables, rows, indexes, pages, and more. It stores the
+ obtained information in system tables.
+ </para>
+
+ <para>
+ The <firstterm>Logger</firstterm> writes
+ text lines about serious and less serious events which can happen
+ during database access, e.g. wrong password, no permission,
+ long-running queries, etc.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-cluster-db-schema">
+ <title>The logical Perspective: Cluster, Database, Schema</title>
+
+ <para>
+ A <glossterm linkend="glossary-server">server</glossterm> contains one or more
+ <glossterm linkend="glossary-db-cluster">database clusters</glossterm>
+ (<glossterm linkend="glossary-db-cluster">clusters</glossterm>
+ for short). Each cluster contains three or more
+ <glossterm linkend="glossary-database">databases</glossterm>.
+ Each database can contain many
+ <glossterm linkend="glossary-schema">schemas</glossterm>.
+ A schema can contain
+ <glossterm linkend="glossary-table">tables</glossterm>,
+ <glossterm linkend="glossary-view">views</glossterm>, and a lot
+ of other objects. Each table or view belongs to a single schema
+ only; they cannot belong to another schema as well. The same is
+ true for the schema/database and database/cluster relation.
+ <xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
+ this hierarchy.
+ </para>
+
+ <figure id="tutorial-cluster-db-schema-figure">
+ <title>Cluster, Database, Schema</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ A cluster is the outer container for a
+ collection of databases. Clusters are created by the command
+ <xref linkend="app-initdb"/>.
+ </para>
+
+ <para>
+ <literal>template0</literal> is the very first
+ database of any cluster. Database <literal>template0</literal>
+ is created during the initialization phase of the cluster.
+ In a second step, database <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal>, and finally database
+ <literal>postgres</literal> is generated as a copy of
+ <literal>template1</literal>. Any
+ <glossterm linkend="app-createdb">new databases</glossterm>
+ of the cluster that a user might need,
+ such as <literal>my_db</literal>, will be copied from the
+ <literal>template1</literal> database. Due to the unique
+ role of <literal>template0</literal> as the pristine original
+ of all other databases, no client
+ can connect to it.
+ </para>
+
+ <para>
+ Every database must contain <glossterm linkend="glossary-schema">
+ at least one schema</glossterm> because
+ schemas contain the other
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>.
+ Schemas are namespaces for
+ their SQL objects and ensure — with one
+ exception — that within their scope, names are used only once across all
+ types of SQL objects. E.g., it is not possible
+ to have a table <literal>employee</literal> and a view
+ <literal>employee</literal> within the same
+ schema. But it is possible to have
+ two tables <literal>employee</literal> in different
+ schemas. In this case, the two tables
+ are separate objects and independent of each
+ other. The only exception to this cross-type uniqueness is that
+ <glossterm linkend="glossary-unique-constraint">unique constraints
+ </glossterm> and the according <firstterm>unique index</firstterm>
+ use the same name.
+ </para>
+
+ <para>
+ Some schemas are predefined. <literal>public</literal>
+ acts as the default schema and contains all
+ <firstterm>SQL objects</firstterm> which are created
+ within <literal>public</literal> or without using an explicit schema
+ name. <literal>public</literal> should not contain user-defined
+ SQL objects. Instead, it is recommended to
+ create a separate schema that
+ holds individual objects like application-specific tables or
+ views. <literal>pg_catalog</literal> is a schema for all tables
+ and views of the <glossterm linkend="glossary-system-catalog">
+ System Catalog</glossterm>.
+ <literal>information_schema</literal> is a schema for several
+ tables and views of the <firstterm>System Catalog</firstterm>
+ in a way that conforms to the SQL standard.
+ </para>
+
+ <para>
+ There are many different SQL object
+ types: <firstterm>database, schema, table, view, materialized
+ view, index, constraint, sequence, function, procedure,
+ trigger, role, data type, operator, tablespace, extension,
+ foreign data wrapper</firstterm>, and more. A few of them, the
+ <firstterm>Global SQL Objects</firstterm>,
+ are outside of the strict hierarchy:
+ All database names, all tablespace names, and all role names
+ are automatically known and available throughout the
+ cluster, independent from
+ the database or schema in which they where defined originally.
+ <xref linkend="tutorial-internal-objects-hierarchy-figure"/>
+ shows the relation between the object types.
+ </para>
+
+ <figure id="tutorial-internal-objects-hierarchy-figure">
+ <title>Hierarchy of Internal Objects</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="720px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect1>
+
+ <sect1 id="tutorial-directories">
+ <title>The physical Perspective: Directories and Files</title>
+
+ <para>
+ <productname>PostgreSQL</productname> organizes long-lasting
+ data as well as volatile state information about transactions
+ or replication actions in the file system. Every
+ <firstterm>Cluster</firstterm> has its root directory
+ somewhere in the file system. In many cases, the environment
+ variable <literal>PGDATA</literal> points to this directory.
+ The example shown in
+ <xref linkend="tutorial-directories-figure"/> uses
+ <literal>data</literal> as the name of this root directory.
+ </para>
+
+ <figure id="tutorial-directories-figure">
+ <title>Directory Structure</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ <literal>data</literal> contains many subdirectories and
+ some files, all of which are necessary to store long-lasting
+ as well as temporary data. The following paragraphs
+ describe the files and subdirectories in
+ <literal>data</literal>.
+ </para>
+
+ <para>
+ <literal>base</literal> is a subdirectory in which one
+ subdirectory per database exists. The names of those
+ subdirectories consist of numbers. These are the internal
+ Object Identifiers (OID), which are numbers to identify
+ the database definition in the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ </para>
+
+ <para>
+ Within the database-specific
+ subdirectories, there are many files: one or more for
+ every table and every index to store heap and index
+ data. Those files are accompanied by files for the
+ <link linkend="storage-fsm">Free Space Maps</link>
+ (extension <literal>_fsm</literal>) and
+ <link linkend="storage-vm">Visibility Maps</link>
+ (extension <literal>_vm</literal>), which contain optimization information.
+ </para>
+
+ <para>
+ Another subdirectory is <literal>global</literal>.
+ In analogy to the database-specific
+ subdirectories, there are files containing information about
+ <glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
+ One type of such Global SQL Objects are
+ <firstterm>tablespaces</firstterm>. In
+ <literal>global</literal> there is information about
+ the tablespaces, not the tablespaces themselves.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_wal</literal> contains the
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
+ They arise and grow parallel to data changes in the
+ cluster and remain alive as long as
+ they are required for recovery, archiving, or replication.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_xact</literal> contains
+ information about the status of each transaction:
+ in_progress, committed, aborted, or sub_committed.
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal>, there are symbolic links
+ that point to directories containing such<firstterm>
+ SQL objects</firstterm> that are created within
+ tablespaces.
+ </para>
+
+ <para>
+ In the root directory <literal>data</literal>
+ there are also some files. In many cases, the configuration
+ files of the cluster are stored here. As long as the
+ instance is up and running, the file
+ <literal>postmaster.pid</literal> exists here
+ and contains the process ID (pid) of the
+ Postmaster which has started the instance.
+ </para>
+
+ <para>
+ For more details about the physical implementation
+ of database objects, see <xref linkend="storage"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-mvcc">
+ <title>MVCC — Multiversion Concurrency Control</title>
+
+ <para>
+ In most cases, <productname>PostgreSQL</productname> based applications
+ support many clients at the same time. Therefore, it is necessary to
+ protect concurrently running requests from unwanted overwriting
+ of other's data as well as from reading inconsistent data. Imagine an
+ online shop offering the last copy of an article. Two clients have the
+ article displayed at their user interface. After a while, but at the same time,
+ both users decide to put it to their shopping cart or even to buy it.
+ Both have seen the article, but only one can be allowed to get it.
+ The database must bring the two requests in a row, permit the access
+ to one of them, block the other, and inform the blocked client
+ that the data was changed by a different process.
+ </para>
+
+ <para>
+ A first approach to implement protections against concurrent
+ accesses to the same data may be the locking of critical
+ rows. Two such techniques are:
+ <emphasis>Optimistic Concurrency Control</emphasis> (OCC)
+ and <emphasis>Two Phase Locking</emphasis> (2PL).
+ <productname>PostgreSQL</productname> implements a third, more
+ sophisticated technique: <firstterm>Multiversion Concurrency
+ Control</firstterm> (MVCC). The crucial advantage of MVCC
+ over other technologies gets evident in multiuser OLTP
+ environments with a massive number of concurrent write
+ actions. There, MVCC generally performs better than solutions
+ using locks. In a <productname>PostgreSQL</productname>
+ database reading never blocks writing and writing never
+ blocks reading, even in the strictest level of transaction
+ isolation.
+ </para>
+
+ <para>
+ Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
+ a new version of the row when a data-change takes place. To
+ distinguish between these two versions and to track the timeline
+ of the row, each of the versions contains, in addition to their user-defined
+ columns, two special system columns, which are not visible
+ for the usual <command>SELECT * FROM ...</command> command.
+ The column <literal>xmin</literal> contains the transaction ID (xid)
+ of the transaction, which created this version of the row. Accordingly,
+ <literal>xmax</literal> contains the xid of the transaction, which has
+ deleted this version, or zero, if the version is not
+ deleted. You can read both with the command
+ <command>SELECT xmin, xmax, * FROM ... </command>.
+ </para>
+
+ <para>
+ When we speak about transaction IDs, you need to know that xids are like
+ sequences. Every new transaction receives the next number as its ID.
+ Therefore, this flow of xids represents the flow of transaction
+ start events over time. But keep in mind that xids are independent of
+ any time measurement — in milliseconds or whatever. If you dive
+ deeper into <productname>PostgreSQL</productname>, you will recognize
+ parameters with names such as 'xxx_age'. Despite their names,
+ these '_age' parameters do not specify a period of time but represent
+ a certain number of transactions, e.g., 100 million.
+ </para>
+
+ <para>
+ The description in this chapter simplifies by omitting detail.
+ When many transactions are running simultaneously, things can
+ get complicated. Sometimes transactions get aborted via
+ <command>ROLLBACK</command> immediately or after a lot of other activities, sometimes
+ a single row is involved in more than one transaction, sometimes
+ a client crashes, sometimes the sequence of xids restarts
+ from zero, ... . Therefore, every version of a row contains more
+ system columns and flags, not only <literal>xmin</literal>
+ and <literal>xmax</literal>.
+ </para>
+
+ <para>
+ So, what's going on in detail when write accesses take place?
+ <xref linkend="tutorial-mvcc-figure"/> shows details concerning
+ <literal>xmin</literal>, <literal>xmax</literal>, and user data.
+ </para>
+
+ <figure id="tutorial-mvcc-figure">
+ <title>Multiversion Concurrency Control</title>
+ <mediaobject>
+ <imageobject role="html">
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ An <command>INSERT</command> command creates the first
+ version of a row. Besides its user data <literal>'x'</literal>,
+ this version contains the ID of the creating transaction
+ <literal>123</literal> in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ <literal>xmin</literal> indicates that the version
+ exists since transaction <literal>123</literal> and
+ <literal>xmax</literal> that it is currently not deleted.
+ </para>
+
+ <para>
+ Somewhat later, transaction <literal>135</literal>
+ executes an <command>UPDATE</command> of this row by
+ changing the user data from <literal>'x'</literal> to
+ <literal>'y'</literal>. According to the MVCC principles,
+ the data in the old version of the row does not change!
+ The value <literal>'x'</literal> remains as it was before.
+ Only <literal>xmax</literal> changes to <literal>135</literal>.
+ Now, this version is treated as valid exclusively for
+ transactions with xids from <literal>123</literal> to
+ <literal>134</literal>. As a substitute for the non-occurring
+ data change in the old version, the <command>UPDATE</command>
+ creates a new version of the row with its xid in
+ <literal>xmin</literal>, <literal>0</literal> in
+ <literal>xmax</literal>, and <literal>'y'</literal> in the
+ user data (plus all the other user data from the old version).
+ This version is now valid for all coming transactions.
+ </para>
+
+ <para>
+ All subsequent <command>UPDATE</command> commands behave
+ in the same way as the first one: they put their xid to
+ <literal>xmax</literal> of the current version, create
+ the next version with their xid in <literal>xmin</literal>,
+ <literal>0</literal> in <literal>xmax</literal>, and the
+ new user data.
+ </para>
+
+ <para>
+ Finally, a row may be deleted by a <command>DELETE</command>
+ command. Even in this case, all versions of the row remain as
+ before. Nothing is thrown away so far! Only <literal>xmax</literal>
+ of the last version changes to the xid of the <command>DELETE</command>
+ transaction, which indicates that it is only valid for
+ transactions with xids older than its own (from
+ <literal>142</literal> to <literal>820</literal> in this
+ example).
+ </para>
+
+ <para>
+ In summary, the MVCC technology creates more and more versions
+ of the same row in the table's heap file and leaves them there,
+ even after a <command>DELETE</command> command. Only the youngest
+ version is relevant for all future transactions. But the
+ system must also preserve some of the older ones for a
+ certain amount of time because the possibility exists that
+ they are or could become relevant for any pending
+ transactions. Over time, also the older ones get out of scope
+ for ALL transactions and therefore become unnecessary.
+ Nevertheless, they do exist physically on the disk and occupy
+ space.
+ </para>
+
+ <para>
+ Please keep in mind:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> and <literal>xmax</literal>
+ indicate the range from where to where
+ row versions are valid (visible) for transactions.
+ This range doesn't imply any direct temporal meaning;
+ the sequence of xids reflects only the sequence of
+ transaction begin events. As
+ xids grow, old row versions get out of scope over time.
+ If an old row version is no longer valid for ALL existing
+ transactions, it's called <firstterm>dead</firstterm>. The
+ space occupied by all dead row versions is called
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Internally, an <command>UPDATE</command> command acts in the
+ same way as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Nothing gets wiped away — with the consequence that the database
+ occupies more and more disk space. It is obvious that
+ this behavior has to be corrected in some
+ way. The next chapter explains how <firstterm>autovacuum</firstterm>
+ fulfills this task.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ </sect1>
+
+ <sect1 id="tutorial-vacuum">
+ <title>Vacuum</title>
+
+ <para>
+ As we have seen in the previous chapter, the database
+ tends to occupy more and more disk space, the
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ This chapter explains how the SQL command
+ <command>VACUUM</command> and the automatically running
+ <firstterm>autovacuum</firstterm> processes clean up
+ by eliminating bloat.
+ </para>
+
+ <note>
+ <para>
+ <firstterm>Autovacuum</firstterm> runs automatically by
+ default. Its default parameters as well as such for
+ <command>VACUUM</command> fit well for most standard
+ situations. Therefore a novice database manager can
+ easily skip the rest of this chapter which explains
+ a lot of details.
+ </para>
+ </note>
+
+ <para>
+ Client processes can issue the SQL command <command>VACUUM</command> at arbitrary
+ points in time. DBAs do this when they recognize special situations,
+ or they start it in batch jobs which run periodically.
+ <firstterm>Autovacuum</firstterm> processes run as part of the
+ <link linkend="glossary-instance">instance</link> at the server.
+ There is a constantly running <firstterm>autovacuum</firstterm> daemon.
+ It permanently controls the state of all databases based on values that
+ are collected by the
+ <link linkend="glossary-stats-collector">Statistics Collector</link>
+ and starts <firstterm>autovacuum</firstterm> processes whenever it detects
+ certain situations. Thus, it's a dynamic behavior of
+ <productname>PostgreSQL</productname> with the intention to tidy
+ up — whenever it is appropriate.
+ </para>
+
+ <para>
+ <command>VACUUM</command>, as well as
+ <firstterm>autovacuum</firstterm>, don't just eliminate bloat.
+ They perform additional tasks for minimizing future
+ I/O activities of themselves as well as of other processes.
+ This extra work can be done in a very efficient way
+ since in most cases the expensive physical access to pages
+ has taken place anyway to eliminate bloat.
+ The additional operations are:
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <firstterm>Freeze</firstterm>: Mark the youngest row version
+ as frozen. This means that the version
+ is always treated as valid (visible) independent from
+ the <firstterm>wraparound problem</firstterm> (see below).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <firstterm>Visibility Map</firstterm> and
+ <firstterm>Free Space Map</firstterm>: Log information about
+ the state of the handled pages in two additional files, the
+ Visibility Map and the Free Space Map.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <emphasis>Statistics</emphasis>: Collect statistics about the
+ number of rows per table, the distribution of values, and so on,
+ as the basis for decisions of the query planner.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ The eagerness — you can call it 'aggression' — of the
+ operations <emphasis>eliminating bloat</emphasis> and
+ <emphasis>freeze</emphasis> is controlled by configuration
+ parameters, runtime flags, and in extreme situations by
+ the processes themselves. Because vacuum operations typically are I/O
+ intensive, which can hinder other activities, <firstterm>autovacuum</firstterm>
+ avoids performing many vacuum operations in bulk. Instead,
+ it carries out many small actions with time gaps in between.
+ The SQL command <command>VACUUM</command> runs immediately
+ and without any time gaps.
+ </para>
+
+ <bridgehead renderas="sect2">Eliminate Bloat</bridgehead>
+
+ <para>
+ To determine which of the row versions are superfluous, the
+ elimination operation must evaluate <literal>xmax</literal>
+ against several criteria which all must apply:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be different from zero because a
+ value of zero indicates that the row version is still valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must contain an xid which is older
+ than the oldest xid of all
+ currently running transactions (min(pg_stat_activity.backend_xmin)).
+ This criterion guarantees that no existing or upcoming transaction
+ will have read or write access to this row version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of <literal>xmax</literal> must be committed. If it was rollback-ed,
+ this row version is treated as valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there is the situation that the row version is part of
+ multiple transactions, special care and some more actions
+ must be taken, see: <xref linkend="vacuum-for-multixact-wraparound"/>.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ After the vacuum operation detects a superfluous row version, it
+ marks its space as free for future use of writing
+ actions. Only in rare situations (or in the case of <command>VACUUM FULL</command>),
+ is this space released to the operating system. In most cases,
+ it remains occupied by <productname>PostgreSQL</productname>
+ and will be used by future <command>INSERT</command> or
+ <command>UPDATE</command> commands concerning this row or a
+ completely different one.
+ </para>
+
+ <para>
+ Which actions start the elimination of bloat?
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ in its default format, i.e., without any option. To boost performance,
+ in this and the next case <command>VACUUM</command> does not
+ read and act on all pages of the heap.
+ The Visibility Map, which is very compact and therefore has a small
+ size, contains information about pages, where bloat-candidates might
+ be found. Only such pages are processed.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FREEZE</command>. (In this case,
+ it undertakes much more actions, see
+ <link linkend="tutorial-freeze">Freeze Row Versions</link>.)
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FULL</command>.
+ Also, in this mode, the bloat disappears, but the strategy used
+ is very different: In this case, the complete table is copied
+ to a different file skipping all outdated row versions. This
+ leads to a significant reduction of used disk space because
+ the new file contains only the actual data. The old file
+ is deleted.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When an <firstterm>autovacuum</firstterm> process acts. For optimization
+ purposes, it considers the Visibility Map in the same way as
+ <command>VACUUM</command>. Additionally, it ignores tables with few modifications;
+ see <xref linkend="guc-autovacuum-vacuum-threshold"/>,
+ which defaults to 50 rows and
+ <xref linkend="guc-autovacuum-vacuum-scale-factor"/>,
+ which defaults to 20%.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </para>
+
+ <para>
+ This logic only applies to row versions of the heap. Index entries
+ don't use <literal>xmin/xmax</literal>. Nevertheless, such index
+ entries, which would lead to outdated row versions, are released
+ accordingly. (??? more explanations ???)
+ </para>
+
+ <para>
+ The above descriptions omit the fact that xids on a real computer
+ have a limited size. They count up in the same way as sequences, and after
+ a certain number of new transactions they are forced to restart
+ from the beginning, which is called <firstterm>wraparound</firstterm>.
+ Therefore the terms 'old transaction' / 'young transaction' does
+ not always correlate with low / high values of xids. Near to the
+ wraparound point, there are cases where <literal>xmin</literal> has
+ a higher value than <literal>xmax</literal>, although their meaning
+ is said to be older than <literal>xmax</literal>.
+ </para>
+
+ <figure id="tutorial-wraparound-figure">
+ <title>Cyclic usage of XIDs</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2" id="tutorial-freeze">Freeze Row Versions</bridgehead>
+
+ <para>
+ The use of a limited range of IDs for transactions leads
+ to the necessity to restart the sequence sooner or later.
+ This does not only have the rare consequence previously
+ described that sometimes <literal>xmin</literal> is
+ higher than <literal>xmax</literal>. The far
+ more critical problem is that whenever the system has
+ to evaluate a WHERE condition, it must decide which row
+ version is valid (visible) from the perspective of the
+ transaction of this query. If a wraparound couldn't happen,
+ this decision would be relatively easy: the xid
+ must be between <literal>xmin</literal> and <literal>xmax</literal>,
+ and the corresponding transactions of <literal>xmin</literal>
+ and <literal>xmax</literal> must be committed. However,
+ <productname>PostgreSQL</productname> has to consider the
+ possibility of wraparounds.
+ Therefore the decision becomes more complex. The general
+ idea of the solution is to use the 'between
+ <literal>xmin</literal> and <literal>xmax</literal>'
+ comparison only during the youngest period of the row
+ versions lifetime and afterward replace it with a
+ 'valid forever' flag in its header.
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ As a first step, <productname>PostgreSQL</productname>
+ divides the complete range of
+ possible xids into two halves with the two split-points
+ 'txid_current' and 'txid_current + 2^31'. The half behind
+ 'txid_current' is considered to represent xids of the
+ 'past' and the half ahead of 'txid_current' those of the
+ 'future'. Those of the 'past' are valid (visible) and those
+ of the 'future' not.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ With each newly created transaction the two split-points
+ move forward. When 'txid_current + 2^31' would reach a
+ row version with <literal>xmin</literal> equal to that value, it would
+ immediately jump from 'past' to 'future' and would be
+ no longer visible!
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ To avoid this unacceptable extinction of data, the vacuum
+ operation <firstterm>freeze</firstterm> clears the situation
+ long before the split-point is reached. It sets a flag
+ in the header of the row version, which completely eliminates
+ the future use of <literal>xmin/xmax</literal> and indicates
+ that the version is valid not only in the 'past'-half
+ but also in the 'future'-half as well as in all coming
+ <glossterm linkend="glossary-xid">epochs</glossterm>.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Which row versions can be frozen by the vacuum operation?
+ Again, several criteria must be checked, and all must be met.
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be zero because only
+ non-deleted rows can be visible 'forever'.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> must be older than all currently
+ existing transactions. This guarantees that no existing
+ transaction can modify or delete the version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of <literal>xmin</literal> must be committed.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ At what point in time does the freeze operation take place?
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with its <command>FREEZE</command> option. In this case, all
+ pages are processed that are marked in the Visibility Map
+ to potentially have unfrozen rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command> without
+ any options but finds that there are xids older than
+ <xref linkend="guc-vacuum-freeze-table-age"/>
+ (default: 150 million) minus
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million).
+ As before, all pages are processed that are
+ marked in the Visibility Map to potentially have unfrozen
+ rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When an <firstterm>autovacuum</firstterm> process runs. Such
+ a process acts in one of two modes:
+ </simpara>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ In the <emphasis>normal mode</emphasis>, it skips
+ pages with row versions that are younger than
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million) and works only on pages where
+ all xids are older. The skipping of young xids prevents
+ work on such pages, which are likely to be changed
+ by one of the future SQL commands.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ The process switches
+ to an <emphasis>aggressive mode</emphasis> if it recognizes
+ that for the processed table their oldest xid exceeds
+ <xref linkend="guc-autovacuum-freeze-max-age"/>
+ (default: 200 million). The value of the oldest unfrozen
+ xid is stored per table in <literal>pg_class.relfrozenxid</literal>.
+ In this <emphasis>aggressive mode</emphasis> <firstterm>autovacuum</firstterm>
+ processes all such pages of the selected table that are marked
+ in the Visibility Map to potentially have bloat or unfrozen rows.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In the first two cases and with <firstterm>autovacuum</firstterm> in
+ <emphasis>aggressive mode</emphasis>, the system knows
+ to which value the oldest unfrozen xid has moved forward and
+ logs the value in <literal>pg_class.relfrozenxid</literal>.
+ The distance between this value and the 'txid_current' split
+ point becomes smaller, and the distance to 'txid_current + 2^31'
+ becomes larger than before.
+ </para>
+
+ <figure id="tutorial-freeze-figure">
+ <title>Freeze</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2">Protection against Wraparound Failure</bridgehead>
+
+ <para>
+ The <firstterm>autovacuum</firstterm> processes are initiated by the
+ constantly running <firstterm>autovacuum</firstterm> daemon.
+ If the daemon detects that for a table
+ <firstterm>autovacuum_freeze_max_age</firstterm> is exceeded, it
+ starts an <firstterm>autovacuum</firstterm> process in
+ <emphasis>aggressive mode</emphasis>
+ (see above) — even if <firstterm>autovacuum</firstterm> is disabled.
+ </para>
+
+ <bridgehead renderas="sect2">Visibility Map and Free Space Map</bridgehead>
+
+ <para>
+ The <link linkend="glossary-vm">Visibility Map</link>
+ (VM) contains two flags — stored as
+ two bits — for each page of the heap. If the first bit
+ is set, that indicates that the associated page does not
+ contain any bloat. If the second one is set, that indicates
+ that the page contains only frozen rows.
+ </para>
+
+ <para>
+ Please consider two details. First, in most cases a page
+ contains many rows, some of them in many versions.
+ However, the flags are associated with the page,
+ not with a row or a row version. The flags are set
+ only under the condition that they are valid for ALL
+ row versions of the page. Second, since there
+ are only two bits per page, the VM is considerably
+ smaller than the heap. Therefore it is buffered
+ in RAM in almost all cases.
+ </para>
+
+ <para>
+ The setting of the flags is silently done by <command>VACUUM</command>
+ and <firstterm>autovacuum</firstterm> during their bloat and freeze operations.
+ This is done to speed up future vacuum actions,
+ regular accesses to heap pages, and some accesses to
+ the index. Every data-modifying operation on any row
+ version of the page clears the flags.
+ </para>
+
+ <para>
+ The <link linkend="glossary-fsm">Free Space Map</link>
+ (FSM) tracks the amount of free space per page. It is
+ organized as a highly condensed b-tree of (rounded) sizes.
+ As long as <command>VACUUM</command> or
+ <firstterm>autovacuum</firstterm> change the free space
+ on any processed page, they log the new values in
+ the FSM in the same way as all other writing
+ processes.
+ </para>
+
+ <bridgehead renderas="sect2">Statistics</bridgehead>
+
+ <para>
+ Statistic information helps the <link
+ linkend="planner-stats">Query Planner</link> to make optimal
+ decisions for the generation of execution plans. This
+ information can be gathered with the SQL commands
+ <command>ANALYZE</command> or <command>VACUUM ANALYZE</command>.
+ But <firstterm>autovacuum</firstterm> processes also gather
+ such information. Depending on the percentage of changed rows
+ per table <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ the <firstterm>autovacuum</firstterm> daemon starts
+ <firstterm>autovacuum</firstterm> processes to collect
+ statistics per table. This dynamic invocation of analyze
+ operations allows <productname>PostgreSQL</productname> to
+ adopt queries to changing circumstances.
+ </para>
+
+ <para>
+ For more details about vacuum operations, especially for its
+ numerous parameters, see <xref linkend="routine-vacuuming"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-transactions-mvcc">
+ <title>Transactions</title>
+ <para>
+ <link linkend="tutorial-transactions">Transactions</link>
+ are a fundamental concept of relational database systems.
+ Their essential point is that they bundle multiple
+ read- or write-operations into a single all-or-nothing
+ operation. Furthermore, they separate and protect concurrent
+ actions of different connections from each other. Thereby
+ they implement the ACID paradigm.
+ </para>
+
+ <para>
+ In <productname>PostgreSQL</productname> there are two ways
+ to establish a transaction. The explicit way uses the keywords
+ <link linkend="sql-begin">BEGIN</link> and
+ <link linkend="sql-commit">COMMIT</link> (respectively
+ <link linkend="sql-rollback">ROLLBACK</link>) before
+ and after a sequence of SQL statements. The keywords mark
+ the transaction's start- and end-point. On the other hand, you
+ can omit the keywords. This is the implicit way, where
+ every single SQL command automatically establishes a new
+ transaction.
+
+ <programlisting>
+BEGIN; -- establish a new transaction
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+COMMIT; -- finish the transaction
+
+-- this UPDATE runs as the only command of a separate transaction ...
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+
+-- ... and this one runs in another transaction
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+ </programlisting>
+ </para>
+
+ <para>
+ As mentioned, the primary property of a transaction is its
+ atomicity: either all or none of its operations succeed,
+ regardless of the fact that it may consist of a lot of
+ different write-operations, and each such operation may
+ affect thousands or millions of rows. As soon as one of the
+ operations fails, all previous operations fail also, which
+ means that all modified rows retain their values as of the
+ beginning of the transaction.
+ </para>
+
+ <para>
+ The atomicity also affects the visibility of changes. No
+ connections running simultaneously to a data modifying
+ transaction will ever see any change before the
+ transaction successfully executes a <command>COMMIT</command>
+ — even in the lowest
+ <link linkend="transaction-iso">isolation level</link>
+ of transactions. <productname>PostgreSQL</productname>
+ does never show uncommitted changes to other connections.
+ </para>
+
+ <para>
+ The situation regarding visibility is somewhat different
+ from the point of view of the modifying transaction.
+ <command>SELECT</command> commands issued inside a
+ transaction delivers all changes done so far by this
+ transaction.
+ </para>
+
+ <bridgehead renderas="sect2">How does it work?</bridgehead>
+
+ <para>
+ Every <command>INSERT</command>, <command>UPDATE</command>,
+ and <command>DELETE</command> command creates new row
+ versions — according to the MVCC rules. This
+ creates the risk that other transactions may see the
+ new row versions, and after a while and some more
+ activities of the modifying transaction they may see the
+ next row versions. Results would be a kind of 'moving
+ target' in absolute contrast to the all-or-nothing
+ principle.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> overcomes this
+ problem by showing only such row versions to other
+ transactions whose originating transaction is
+ successfully committed. It skips all row versions of
+ uncommitted transactions. And
+ <productname>PostgreSQL</productname> solves one more
+ problem. Even the single <command>COMMIT</command>
+ command needs a short time interval for its execution.
+ Therefore its critical 'dead-or-survival' phase
+ runs in a priviledged mode where it cannot be
+ interrupted by other processes.
+ </para>
+
+ <bridgehead renderas="sect2">What are the benefits?</bridgehead>
+
+ <para>
+ Transactions relieve applications from many standard
+ actions that must be implemented for nearly every use case.
+ </para>
+
+ <para>
+ Business logic often contains strong, but for a computer,
+ relative abstract requirements. The above example shows
+ the transfers of some money from one account to another.
+ It is obvious
+ that the decrease of the one and the increase of the
+ other must be indivisible. Nevertheless, there is no particular
+ need for an application to do something to ensure the
+ <glossterm linkend="glossary-atomicity">atomicity</glossterm>
+ of this behavior. It's enough to surround them with
+ <command>BEGIN</command> and <command>COMMIT</command>.
+ </para>
+
+ <para>
+ Applications often demand the feature of 'undoing'
+ previously taken actions under some application-specific
+ conditions. In such cases, the application simply issues a
+ <command>ROLLBACK</command> command instead of a
+ <command>COMMIT</command>. The <command>ROLLBACK</command>
+ cancels the transaction, and all changes made so far remain
+ invisible forever; it's like they never happened. There
+ is no need for the application to log its activities and
+ undo every step of the transaction separately.
+ </para>
+
+ <para>
+ Transactions ensure that the
+ <glossterm linkend="glossary-consistency">consistency</glossterm>
+ of the complete database always keeps valid. Declarative
+ rules like
+ <link linkend="ddl-constraints-primary-keys">primary</link>- or
+ <link linkend="ddl-constraints-fk">foreign keys</link>,
+ <link linkend="ddl-constraints-check-constraints">checks</link>,
+ other constraints, or
+ <link linkend="trigger-definition">triggers</link>
+ are part of the all-or-nothing nature of transactions.
+ </para>
+
+ <para>
+ Also, all self-evident — but possibly not obvious
+ — low-level demands on the database system are
+ ensured; e.g. index entries for rows must become
+ visible at the same moment as the rows themselves.
+ </para>
+
+ <para>
+ There is an additional feature which defines transactions'
+ <link linkend="transaction-iso">isolation level</link>
+ to each other in a declarative way. It automatically
+ prevents applications from some strange situations.
+ </para>
+
+ <para>
+ Lastly, it is worth to notice that changes done by a
+ committed transaction will survive all future application,
+ instance, or hardware failures. The next chapter
+ explains this
+ <glossterm linkend="glossary-durability">durability</glossterm>.
+ </para>
+ </sect1>
+
+ <sect1 id="tutorial-reliability">
+ <title>Reliability</title>
+
+ <para>
+ Nothing is perfect and failures inevitably happen.
+ However, the most common types of failure are
+ well known and <productname>PostgreSQL</productname>
+ implements strategies to overcome them.
+ Such strategies use parts of the previously presented
+ techniques MVCC and transaction-rollback, plus additional
+ features.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the client side</bridgehead>
+ <para>
+ A <glossterm linkend="glossary-client">client</glossterm>
+ can fail in different ways. Its hardware can get damaged,
+ the power supply can fail, the network connection to the
+ server can break, or the client application may run into
+ a severe software error like a null pointer exception.
+ Because <productname>PostgreSQL</productname> uses a
+ client/server architecture, no direct problem for the
+ database will occur. In all of this cases, the
+ <glossterm linkend="glossary-backend">Backend process</glossterm>,
+ which is the client's counterpart at the server-side,
+ may recognize that the network connection is no longer
+ working, or it may run into a timeout after a while. It
+ terminates, and there is no harm to the database. As
+ usual, uncommitted data changes initiated by this client
+ are not visible to any other client.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the server-side</bridgehead>
+
+ <bridgehead renderas="sect3">Instance failure</bridgehead>
+ <para>
+ The instance may suddenly fail because of <emphasis>power off</emphasis>
+ or other problems. This will affect all running processes, the RAM,
+ and possibly the consistency of disk files.
+ </para>
+ <para>
+ After a restart, <productname>PostgreSQL</productname>
+ automatically recognizes that the last shutdown of the
+ instance did not happen as expected: files might not be
+ closed properly and the <literal>postmaster.pid</literal>
+ file exists. <productname>PostgreSQL</productname>
+ tries to clean up the situation. This is possible because
+ all changes in the database are stored twice. First,
+ the WAL files contain them as a chronology of
+ <glossterm linkend="glossary-wal-record">WAL records</glossterm>,
+ which include the new data values and information about commit
+ actions. The WAL records are written first. Second,
+ the data itself shall exist in the heap and index files.
+ In opposite to the WAL records, this part may or may
+ not have been transferred entirely from Shared Memory
+ to the files.
+ </para>
+ <para>
+ The automatic recovery searches within the WAL files for
+ the latest
+ <glossterm linkend="glossary-checkpoint">checkpoint</glossterm>.
+ This checkpoint signals that the database files are in
+ a consistent state, especially that all WAL records up to
+ this point were successfully stored in heap and index. Starting
+ here, the recovery process copies the following WAL records
+ to heap and index. As a result, the files contain all
+ changes and reach a consistent state. Changes of committed
+ transactions are visible; those of uncommited transactions
+ are also in the files, but - as usual - they are never seen
+ by any of the following transactions because uncommited
+ changes are never shown. Such recovery actions run
+ completely automatically, it is not necessary that you
+ configure or start anything by yourself.
+ </para>
+
+ <bridgehead renderas="sect3">Disk crash</bridgehead>
+ <para>
+ If a disk crashes, the course of action described previously
+ cannot work. It is likely that the WAL files and/or the
+ data and index files are no longer available. You need
+ to take special actions to overcome such situations.
+ </para>
+ <para>
+ You obviously need a backup. How to take such a backup
+ and use it as a starting point for a recovery of the
+ cluster is explained in more detail in the next
+ <link linkend="tutorial-backup">chapter</link>.
+ </para>
+
+ <bridgehead renderas="sect3">Disk full</bridgehead>
+ <para>
+ It is conceivable that over time the disk gets full,
+ and there is no room for additional data. In this case,
+ <productname>PostgreSQL</productname> stops accepting
+ commands which change the data or even terminates
+ completely. No data loss or data corruption will
+ occur.
+ </para>
+ <para>
+ To come out of such a situation, you should remove
+ unused files from this disk. But you should never
+ delete files from the
+ <glossterm linkend="glossary-data-directory">data directory</glossterm>.
+ Nearly all of them are necessary for the consistency
+ of the database.
+ </para>
+
+ <bridgehead renderas="sect2">High availability</bridgehead>
+ <para>
+ Database servers can work together to allow a second
+ server to quickly take over the workload if the
+ primary server fails for whatever reason
+ (<link linkend="high-availability">high availability</link>),
+ or to allow several computers to serve the same data
+ for the purpose of load balancing.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-backup">
+ <title>Backup</title>
+
+ <para>
+ Taking backups is a basic task of database maintenance.
+ <productname>PostgreSQL</productname> supports
+ three different strategies; each has its own
+ strengths and weaknesses.
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ File system level backup
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Logical backup via <command>pg_dump</command>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Continuous archiving based on <command>pg_basebackup</command>
+ and WAL files
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <bridgehead renderas="sect2">File system level backup</bridgehead>
+ <para>
+ You can use any appropriate OS tool to create a
+ <link linkend="backup-file">copy</link>
+ of the cluster's directory structure and files. In
+ case of severe problems such a copy can serve as
+ the source of recovery. But in order to get a
+ <emphasis>USABLE</emphasis> backup by this method,
+ the database server <emphasis>MUST</emphasis> be
+ shut down during the complete runtime of the copy
+ command!
+ </para>
+ <para>
+ The obvious disadvantage of this method is that there
+ is a downtime where no user interaction is possible.
+ The other two strategies run during regular operating
+ times.
+ </para>
+
+ <bridgehead renderas="sect2">Logical backup via pg_dump</bridgehead>
+ <para>
+ The tool <command>pg_dump</command> is able to take a
+ <link linkend="backup-dump">copy</link>
+ of the complete cluster or certain parts of it. It stores
+ the copy in the form of SQL <command>CREATE</command> and
+ <command>INSERT</command> commands. It runs in
+ parallel to other processes in its own transaction.
+ </para>
+ <para>
+ The output of <command>pg_dump</command> may be used as
+ input of <command>psql</command> to restore the data
+ (or to copy it to another database).
+ </para>
+ <para>
+ The main advantage over the other two methods is that it
+ can pick parts of the cluster, e.g. a single table or one
+ database. The other two methods work only at the level of
+ the complete cluster.
+ </para>
+
+ <bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
+ <para>
+ <link linkend="continuous-archiving">This method</link>
+ is the most sophisticated and complex one. It
+ consists of two phases.
+ </para>
+ <para>
+ First, you need to create a so called
+ <firstterm>basebackup</firstterm> with the tool
+ <command>pg_basebackup</command>. The result is a
+ directory structure plus files which contains a
+ consistent copy of the original cluster.
+ <command>pg_basebackup</command> runs in
+ parallel to other processes in its own transaction.
+ </para>
+ <para>
+ The second step is recommended but not necessary. All
+ changes to the data are stored in WAL files. If you
+ continuously save such WAL files, you have the history
+ of the cluster. This history can be applied to a
+ basebackup in order to recreate
+ any state of the cluster between the time of
+ <command>pg_basebackup</command>'s start time and
+ any later point in time. This technique
+ is called 'Point-in-Time Recovery (PITR)'.
+ </para>
+ <para>
+ If configured, the
+ <glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
+ will automatically copy every single WAL file to a save location.
+ <link linkend="backup-archiving-wal">Its configuration</link>
+ consists mainly of a string, which contains a copy command
+ in the operating system's syntax. In order to protect your
+ data against a disk crash, the destination location
+ of a basebackup as well as of the
+ <firstterm>archived WAL files</firstterm> should be on a
+ disk which is different from the data disk.
+ </para>
+ <para>
+ If it gets necessary to restore the cluster, you have to
+ copy the basebackup and the
+ archived WAL files to
+ their original directories. The configuration of this
+ <link linkend="backup-pitr-recovery">recovery procedure</link>
+ contains a string with the reverse copy command: from
+ archive location to database location.
+ </para>
+
+ </sect1>
+
+<!-- ToDo: replication, index-types, extension mechanism, ...
+ <sect1 id="tutorial-replication">
+ <title>Replication</title>
+
+ <para>
+...
+ </para>
+
+ </sect1>
+-->
+
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 64b5da0070..a9eac872f0 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -8,9 +8,10 @@
<!ENTITY problems SYSTEM "problems.sgml">
<!-- tutorial -->
-<!ENTITY advanced SYSTEM "advanced.sgml">
-<!ENTITY query SYSTEM "query.sgml">
-<!ENTITY start SYSTEM "start.sgml">
+<!ENTITY start SYSTEM "start.sgml">
+<!ENTITY query SYSTEM "query.sgml">
+<!ENTITY advanced SYSTEM "advanced.sgml">
+<!ENTITY architecture SYSTEM "architecture.sgml">
<!-- user's guide -->
<!ENTITY array SYSTEM "array.sgml">
diff --git a/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
new file mode 100644
index 0000000000..7e13753d48
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
@@ -0,0 +1,160 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="685" viewBox="0 0 900 685">
+ <title>
+ Server (Hardware, Container, or VM)
+ </title>
+ <style>
+ .text_normal,.text_small{font-style:normal;font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_small{font-size:12px}.text_normal{font-size:16px}
+ </style>
+ <defs>
+ <symbol id="rectangle_special_0">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="rectangle_special_1">
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="125">
+ 'my_schema' (optional)
+ </text>
+ <text class="text_small" x="20" y="145">
+ tables, views, ...
+ </text>
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="190">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M450 10v230H0V0h440v10h10L440 0"/>
+ </symbol>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="270" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Server (Hardware, Container, or VM)
+ </text>
+ <path stroke="blue" stroke-width="2" fill="none" d="M20 110h790v555H20z"/>
+ <text class="text_normal" x="180" y="25" transform="translate(20 110)">
+ cluster 'data' (default, managed by one instance)
+ </text>
+ <path d="M50 110V80h790v555h-30" stroke="blue" stroke-width="2" fill="none"/>
+ <text class="text_normal" x="190" y="-10" transform="translate(45 110)">
+ cluster 'cluster_2' (optional, managed by a different instance)
+ </text>
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template0'
+ </text>
+ </g>
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template1'
+ </text>
+ </g>
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'my_db' (optional)
+ </text>
+ </g>
+ <g transform="translate(320 330)">
+ <rect width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4"/>
+ <text class="text_normal" x="15" y="27">
+ Global SQL objects
+ </text>
+ <path d="M0 5l-65-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M80 0v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M180 40h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M0 40l-45 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ </g>
+ <g transform="translate(335 405)">
+ <use xlink:href="#note"/>
+ <text class="text_small" x="10" y="20">
+ 1)
+ </text>
+ <text class="text_small" x="30" y="20">
+ By default, you work in the cluster 'data', database 'postgres',
+ </text>
+ <text class="text_small" x="30" y="35">
+ schema 'public'.
+ </text>
+ <text class="text_small" x="10" y="55">
+ 2)
+ </text>
+ <text class="text_small" x="30" y="55">
+ More system schemas: pg_catalog, information_schema,
+ </text>
+ <text class="text_small" x="30" y="70">
+ pg_temp, pg_toast.
+ </text>
+ <text class="text_small" x="10" y="90">
+ 3)
+ </text>
+ <text class="text_small" x="30" y="90">
+ Global SQL objects: Some SQL objects are automatically active
+ </text>
+ <text class="text_small" x="30" y="105">
+ and known database- or even cluster-wide.
+ </text>
+ <text class="text_small" x="10" y="125">
+ 4)
+ </text>
+ <text class="text_small" x="30" y="125">
+ The command 'initdb' creates a new cluster with the three
+ </text>
+ <text class="text_small" x="30" y="140">
+ databases 'template0', 'template1', and 'postgres'. The command
+ </text>
+ <text class="text_small" x="30" y="155">
+ 'createdb' creates a new database.
+ </text>
+ <text class="text_small" x="10" y="175">
+ 5)
+ </text>
+ <text class="text_small" x="30" y="175">
+ If multiple clusters are active on one server at the same time,
+ </text>
+ <text class="text_small" x="30" y="190">
+ each one is managed by an individual instance. Each such instance
+ </text>
+ <text class="text_small" x="30" y="205">
+ uses a different port.
+ </text>
+ <text class="text_small" x="10" y="225">
+ 6)
+ </text>
+ <text class="text_small" x="30" y="225">
+ No client application is allowed to connect to 'template0'.
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink.svg b/doc/src/sgml/images/cluster-db-schema-ink.svg
new file mode 100644
index 0000000000..1fffb9737a
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink.svg
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="685px"
+ viewBox="0 0 900 685"
+ id="svg147"
+ sodipodi:docname="cluster-db-schema-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Server (Hardware, Container, or VM)</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1129"
+ inkscape:window-height="922"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.68905109"
+ inkscape:cx="737.16805"
+ inkscape:cy="342.1375"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Server (Hardware, Container, or VM)</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs49">
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangle_special_0">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect6" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="195"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect8" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text10">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text12">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="195"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect14" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text16">(more system schemas)</text>
+ </symbol>
+ <!-- same as before, but one more schema -->
+ <symbol
+ id="rectangle_special_1">
+ <!-- the database -->
+ <rect
+ width="245"
+ height="225"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect19" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect21" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text23">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text25">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect27" />
+ <text
+ class="text_normal"
+ x="20"
+ y="125"
+ id="text29">'my_schema' (optional)</text>
+ <text
+ class="text_small"
+ x="20"
+ y="145"
+ id="text31">tables, views, ...</text>
+ <rect
+ x="15"
+ y="170"
+ width="205"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect33" />
+ <text
+ class="text_small"
+ x="20"
+ y="190"
+ id="text35">(more system schemas)</text>
+ </symbol>
+ <symbol
+ id="note"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title38">UML Note</title>
+ <path
+ d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10"
+ id="path40" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path43" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path46" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect51" />
+ <text
+ class="text_big"
+ x="270"
+ y="40"
+ id="text53">Server (Hardware, Container, or VM)</text>
+ <!-- two clusters -->
+ <g
+ transform="translate(20 110)"
+ id="g59">
+ <rect
+ x="0"
+ y="0"
+ width="790"
+ height="555"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="rect55" />
+ <text
+ class="text_normal"
+ x="180"
+ y="25"
+ id="text57">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g
+ transform="translate(45 110)"
+ id="g65">
+ <path
+ d="M 5,0 v -30 h 790 v 555 h -30"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="path61" />
+ <text
+ class="text_normal"
+ x="190"
+ y="-10"
+ id="text63">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+ <!-- database template 0 -->
+ <g
+ transform="translate(40 155)"
+ id="g71">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use67" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text69">database 'template0'</text>
+ </g>
+ <!-- database template 1 -->
+ <g
+ transform="translate(290 155)"
+ id="g77">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use73" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text75">database 'template1'</text>
+ </g>
+ <!-- database postgres -->
+ <g
+ transform="translate(540 155)"
+ id="g83">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use79" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text81">database 'postgres'</text>
+ </g>
+ <!-- database my_db -->
+ <g
+ transform="translate(40 350)"
+ id="g89">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use85" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text87">database 'my_db' (optional)</text>
+ </g>
+ <!-- global objects -->
+ <g
+ transform="translate(320 330)"
+ id="g103">
+ <rect
+ x="0"
+ y="0"
+ width="180"
+ height="45"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="10 4 4 4"
+ id="rect91" />
+ <text
+ class="text_normal"
+ x="15"
+ y="27"
+ id="text93">Global SQL objects</text>
+ <path
+ d="M 0,5 l-65,-35"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path95" />
+ <path
+ d="M 80,0 v-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path97" />
+ <path
+ d="M 180,40 h50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path99" />
+ <path
+ d="M 0,40 l-45,20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path101" />
+ </g>
+ <!-- Some comments -->
+ <g
+ transform="translate(335 405)"
+ id="g145">
+ <use
+ xlink:href="#note"
+ x="0"
+ y="0"
+ id="use105" />
+ <text
+ class="text_small"
+ x="10"
+ y="20"
+ id="text107">1)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="20"
+ id="text109">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text
+ class="text_small"
+ x="30"
+ y="35"
+ id="text111">schema 'public'.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="55"
+ id="text113">2)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="55"
+ id="text115">More system schemas: pg_catalog, information_schema,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="70"
+ id="text117">pg_temp, pg_toast.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="90"
+ id="text119">3)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="90"
+ id="text121">Global SQL objects: Some SQL objects are automatically active</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text123">and known database- or even cluster-wide.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="125"
+ id="text125">4)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="125"
+ id="text127">The command 'initdb' creates a new cluster with the three</text>
+ <text
+ class="text_small"
+ x="30"
+ y="140"
+ id="text129">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text
+ class="text_small"
+ x="30"
+ y="155"
+ id="text131">'createdb' creates a new database.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="175"
+ id="text133">5)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="175"
+ id="text135">If multiple clusters are active on one server at the same time,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="190"
+ id="text137">each one is managed by an individual instance. Each such instance</text>
+ <text
+ class="text_small"
+ x="30"
+ y="205"
+ id="text139">uses a different port.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="225"
+ id="text141">6)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="225"
+ id="text143">No client application is allowed to connect to 'template0'.</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
new file mode 100644
index 0000000000..af50c07330
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="685px"
+ viewBox="0 0 900 685" >
+
+ <title>Server (Hardware, Container, or VM)</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_0">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">(more system schemas)</text>
+ </symbol>
+
+ <!-- same as before, but one more schema -->
+ <symbol id="rectangle_special_1">
+ <!-- the database -->
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="125">'my_schema' (optional)</text>
+ <text class="text_small" x="20" y="145">tables, views, ...</text>
+
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="190">(more system schemas)</text>
+ </symbol>
+
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="270" y="40">Server (Hardware, Container, or VM)</text>
+
+ <!-- two clusters -->
+ <g transform="translate(20 110)">
+ <rect x="0" y="0" width="790" height="555" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="180" y="25">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g transform="translate(45 110)">
+ <path d="M 5,0 v -30 h 790 v 555 h -30" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="190" y="-10">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+
+
+ <!-- database template 0 -->
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template0'</text>
+ </g>
+
+ <!-- database template 1 -->
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template1'</text>
+ </g>
+
+ <!-- database postgres -->
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'postgres'</text>
+ </g>
+
+ <!-- database my_db -->
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
+ </g>
+
+ <!-- global objects -->
+ <g transform="translate(320 330)">
+ <rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
+ <text class="text_normal" x="15" y="27">Global SQL objects</text>
+ <path d="M 0,5 l-65,-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ </g>
+
+ <!-- Some comments -->
+ <g transform="translate(335 405)">
+ <use xlink:href="#note" x="0" y="0" />
+
+ <text class="text_small" x="10" y="20">1)</text>
+ <text class="text_small" x="30" y="20">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text class="text_small" x="30" y="35">schema 'public'.</text>
+
+ <text class="text_small" x="10" y="55">2)</text>
+ <text class="text_small" x="30" y="55">More system schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="70">pg_temp, pg_toast.</text>
+
+ <text class="text_small" x="10" y="90">3)</text>
+ <text class="text_small" x="30" y="90">Global SQL objects: Some SQL objects are automatically active</text>
+ <text class="text_small" x="30" y="105">and known database- or even cluster-wide.</text>
+
+ <text class="text_small" x="10" y="125">4)</text>
+ <text class="text_small" x="30" y="125">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="140">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="155">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="175">5)</text>
+ <text class="text_small" x="30" y="175">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="190">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="205">uses a different port.</text>
+
+ <text class="text_small" x="10" y="225">6)</text>
+ <text class="text_small" x="30" y="225">No client application is allowed to connect to 'template0'.</text>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/directories-ink-svgo.svg b/doc/src/sgml/images/directories-ink-svgo.svg
new file mode 100644
index 0000000000..95fa76b9c6
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink-svgo.svg
@@ -0,0 +1,164 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="640" viewBox="0 0 900 640">
+ <title>
+ Directory structure of a cluster
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <symbol id="directory" stroke="blue" stroke-width=".3" fill="aqua">
+ <title>
+ Directory
+ </title>
+ <path d="M0 10h110v20H0z"/>
+ <path d="M0 10V8l3-3h35l3 3v2"/>
+ </symbol>
+ <symbol id="file" stroke="black" fill="none">
+ <title>
+ File
+ </title>
+ <path stroke="blue" d="M0 0h40v50H0z"/>
+ <path d="M5 10h20" stroke-dasharray="4 2"/>
+ <path d="M5 17h15" stroke-dasharray="6 2"/>
+ <path d="M5 24h25" stroke-dasharray="4 2"/>
+ <path d="M5 31h20" stroke-dasharray="5 2"/>
+ </symbol>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="50" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Directory Structure
+ </text>
+ <g transform="translate(20 100)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /pg/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ An arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 130)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ data/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of cluster 'data' (see: PGDATA)
+ </text>
+ </g>
+ <g transform="translate(120 160)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ base/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing per-database subdirectories
+ </text>
+ </g>
+ <g transform="translate(170 190)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 1/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of first database 'template0'
+ </text>
+ </g>
+ <g transform="translate(170 220)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12992/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of second database 'template1'
+ </text>
+ </g>
+ <g transform="translate(170 250)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12999/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of third database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(170 280)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ nnnnn/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Optional: more subdirectories for databases, e.g. 'my_db'
+ </text>
+ </g>
+ <g transform="translate(120 310)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ global/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory with information about Global SQL Objects
+ </text>
+ </g>
+ <g transform="translate(120 340)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_wal/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 370)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_xact/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for transaction commit status ('pg_clog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 400)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_tblspc/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing symbolic links to tablespaces
+ </text>
+ </g>
+ <g transform="translate(120 430)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_... /
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Some more subdirectories
+ </text>
+ </g>
+ <g transform="translate(120 465)">
+ <use xlink:href="#file"/>
+ <use xlink:href="#file" x="50"/>
+ <text x="200" y="26" class="text_normal">
+ 'postmaster.pid' and other files with cluster-wide relevance
+ </text>
+ </g>
+ <g transform="translate(20 540)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /xyz/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ Same or another arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 570)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ cluster_2/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of another cluster 'cluster_2'
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-ink.svg b/doc/src/sgml/images/directories-ink.svg
new file mode 100644
index 0000000000..8151cf583a
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink.svg
@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="640px"
+ viewBox="0 0 900 640"
+ id="svg303"
+ sodipodi:docname="directories-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata307">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Directory structure of a cluster</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1083"
+ inkscape:window-height="808"
+ id="namedview305"
+ showgrid="false"
+ inkscape:zoom="0.36875"
+ inkscape:cx="450"
+ inkscape:cy="320"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg303" />
+ <title
+ id="title153">Directory structure of a cluster</title>
+ <style
+ type="text/css"
+ id="style155">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs177">
+ <!-- Directory -->
+ <symbol
+ id="directory"
+ stroke="blue"
+ stroke-width="0.3px"
+ fill="aqua">
+ <title
+ id="title157">Directory</title>
+ <rect
+ x="0"
+ y="10"
+ width="110"
+ height="20"
+ id="rect159" />
+ <path
+ d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2"
+ id="path161" />
+ </symbol>
+ <!-- File -->
+ <symbol
+ id="file"
+ stroke="black"
+ fill="none">
+ <title
+ id="title164">File</title>
+ <rect
+ x="0"
+ y="0"
+ width="40"
+ height="50"
+ stroke="blue"
+ id="rect166" />
+ <path
+ d="M 5,10 h 20"
+ stroke-dasharray="4 2"
+ id="path168" />
+ <path
+ d="M 5,17 h 15"
+ stroke-dasharray="6 2"
+ id="path170" />
+ <path
+ d="M 5,24 h 25"
+ stroke-dasharray="4 2"
+ id="path172" />
+ <path
+ d="M 5,31 h 20"
+ stroke-dasharray="5 2"
+ id="path174" />
+ </symbol>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect179" />
+ <!-- caption -->
+ <text
+ x="200"
+ y="50"
+ class="text_big"
+ id="text181">Directory Structure</text>
+ <!-- the directories -->
+ <g
+ transform="translate(20, 100)"
+ id="g189">
+ <use
+ xlink:href="#directory"
+ id="use183" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text185">... /pg/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text187">An arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 130)"
+ id="g197">
+ <use
+ xlink:href="#directory"
+ id="use191" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text193">data/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text195">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+ <g
+ transform="translate(120, 160)"
+ id="g205">
+ <use
+ xlink:href="#directory"
+ id="use199" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text201">base/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text203">Subdirectory containing per-database subdirectories</text>
+ </g>
+ <!-- -->
+ <g
+ transform="translate(170, 190)"
+ id="g213">
+ <use
+ xlink:href="#directory"
+ id="use207" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text209">1/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text211">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g
+ transform="translate(170, 220)"
+ id="g221">
+ <use
+ xlink:href="#directory"
+ id="use215" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text217">12992/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text219">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g
+ transform="translate(170, 250)"
+ id="g229">
+ <use
+ xlink:href="#directory"
+ id="use223" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text225">12999/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text227">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g
+ transform="translate(170, 280)"
+ id="g237">
+ <use
+ xlink:href="#directory"
+ id="use231" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text233">nnnnn/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text235">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+ <g
+ transform="translate(120, 310)"
+ id="g245">
+ <use
+ xlink:href="#directory"
+ id="use239" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text241">global/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text243">Subdirectory with information about Global SQL Objects</text>
+ </g>
+ <g
+ transform="translate(120, 340)"
+ id="g253">
+ <use
+ xlink:href="#directory"
+ id="use247" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text249">pg_wal/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text251">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 370)"
+ id="g261">
+ <use
+ xlink:href="#directory"
+ id="use255" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text257">pg_xact/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text259">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 400)"
+ id="g269">
+ <use
+ xlink:href="#directory"
+ id="use263" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text265">pg_tblspc/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text267">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+ <g
+ transform="translate(120, 430)"
+ id="g277">
+ <use
+ xlink:href="#directory"
+ id="use271" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text273">pg_... /</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text275">Some more subdirectories</text>
+ </g>
+ <g
+ transform="translate(120, 465)"
+ id="g285">
+ <use
+ xlink:href="#file"
+ x="0"
+ y="0"
+ id="use279" />
+ <use
+ xlink:href="#file"
+ x="50"
+ y="0"
+ id="use281" />
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text283">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+ <!-- next cluster -->
+ <g
+ transform="translate(20, 540)"
+ id="g293">
+ <use
+ xlink:href="#directory"
+ id="use287" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text289">... /xyz/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text291">Same or another arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 570)"
+ id="g301">
+ <use
+ xlink:href="#directory"
+ id="use295" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text297">cluster_2/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text299">Root of another cluster 'cluster_2'</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
new file mode 100644
index 0000000000..6d16a03169
--- /dev/null
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="640px"
+ viewBox="0 0 900 640">
+
+ <title>Directory structure of a cluster</title>
+
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Directory -->
+ <symbol id="directory" stroke="blue" stroke-width="0.3px" fill="aqua">
+ <title>Directory</title>
+ <rect x="0" y="10" width="110" height="20" />
+ <path d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2" />
+ </symbol>
+
+ <!-- File -->
+ <symbol id="file" stroke="black" fill="none" >
+ <title>File</title>
+ <rect x="0" y="0" width="40" height="50" stroke="blue" />
+ <path d="M 5,10 h 20" stroke-dasharray="4 2" />
+ <path d="M 5,17 h 15" stroke-dasharray="6 2" />
+ <path d="M 5,24 h 25" stroke-dasharray="4 2" />
+ <path d="M 5,31 h 20" stroke-dasharray="5 2" />
+ </symbol>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption -->
+ <text x="200" y="50" class="text_big">Directory Structure</text>
+
+ <!-- the directories -->
+ <g transform="translate(20, 100)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /pg/</text>
+ <text x="300" y="26" class="text_normal">An arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 130)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">data/</text>
+ <text x="250" y="26" class="text_normal">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+
+ <g transform="translate(120, 160)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">base/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing per-database subdirectories</text>
+ </g>
+
+ <!-- -->
+ <g transform="translate(170, 190)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">1/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g transform="translate(170, 220)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12992/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g transform="translate(170, 250)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12999/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g transform="translate(170, 280)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">nnnnn/</text>
+ <text x="150" y="26" class="text_normal">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+
+ <g transform="translate(120, 310)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">global/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory with information about Global SQL Objects</text>
+ </g>
+
+ <g transform="translate(120, 340)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 370)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 400)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+
+ <g transform="translate(120, 430)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_... /</text>
+ <text x="200" y="26" class="text_normal">Some more subdirectories</text>
+ </g>
+
+ <g transform="translate(120, 465)">
+ <use xlink:href="#file" x="0" y="0" />
+ <use xlink:href="#file" x="50" y="0" />
+ <text x="200" y="26" class="text_normal">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+
+ <!-- next cluster -->
+ <g transform="translate(20, 540)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /xyz/</text>
+ <text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 570)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster 'cluster_2'</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink-svgo.svg b/doc/src/sgml/images/freeze-ink-svgo.svg
new file mode 100644
index 0000000000..6fedfb7633
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink-svgo.svg
@@ -0,0 +1,84 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="320" viewBox="0 0 850 320">
+ <title>
+ Freeze
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100)"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="70" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ <tspan font-style="italic" font-weight="700">Freeze</tspan> to keep visible
+ </text>
+ <g fill="none" transform="translate(170 190)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_120" startOffset="11.2%">(1)</textPath> <textPath xlink:href="#Path_120" startOffset="61.2%">(5)</textPath> <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%">|</textPath> <textPath xlink:href="#Path_120" startOffset="34%">(2)</textPath> <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(3)</textPath> <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%">|</textPath> <textPath xlink:href="#Path_120" startOffset="55%">(4)</textPath>
+ </text>
+ <path d="M-80-80L80 80" stroke="black"/>
+ <text class="text_normal" letter-spacing="12" transform="rotate(45 40.78 -38.1)">
+ PAST
+ </text>
+ <text class="text_normal" letter-spacing="12" transform="rotate(-135 27.43 23.79)">
+ FUTURE
+ </text>
+ <use xlink:href="#frozenPoint" transform="rotate(10)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(25)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(40)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(55)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(70)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(85)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(100)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(115)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(130)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(145)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(160)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(175)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(190)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(205)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(220)"/>
+ </g>
+ <g class="text_normal" transform="translate(380 30)">
+ <text>
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25">
+ 1: txid_current + 2 ^ 31 (split-point)
+ </text>
+ <text y="50">
+ 2: autovacuum_freeze_max_age (200 mio.)
+ </text>
+ <text y="75">
+ 3: vacuum_freeze_table_age (150 mio.)
+ </text>
+ <text y="100">
+ 4: vacuum_freeze_min_age (50 mio.)
+ </text>
+ <text y="125">
+ 5: txid_current (split-point, jungest xid)
+ </text>
+ <text y="155">
+ per table: pg_class.relfrozenxid <tspan font-weight="700">must</tspan> be between (1) and (5);
+ </text>
+ <text y="175" x="75">
+ normally it is between (3) and (4)
+ </text>
+ <use xlink:href="#unfrozenPoint" transform="translate(106 200)"/>
+ <text y="205" x="20">
+ Unfrozen xid
+ </text>
+ <use xlink:href="#frozenPoint" transform="translate(106 224)"/>
+ <text y="230" x="20">
+ Frozen xid
+ </text>
+ <text y="260">
+ (figure is out of scale)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink.svg b/doc/src/sgml/images/freeze-ink.svg
new file mode 100644
index 0000000000..009cfe4b41
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink.svg
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="320px"
+ viewBox="0 0 850 320"
+ id="svg454"
+ sodipodi:docname="freeze-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata458">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Freeze</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="979"
+ inkscape:window-height="857"
+ id="namedview456"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="160"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg454" />
+ <title
+ id="title309">Freeze</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style311">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs318">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle
+ id="frozenPoint"
+ r="3"
+ stroke="green"
+ fill="green"
+ transform="translate(-100, 0)" />
+ <circle
+ id="unfrozenPoint"
+ r="3"
+ stroke="green"
+ fill="none"
+ transform="translate(-100, 0)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect320" />
+ <text
+ class="text_big"
+ x="70"
+ y="40"
+ id="text324"><tspan
+ style="font-style:italic;font-weight:bold"
+ id="tspan322">
+ Freeze</tspan>
+ to keep visible</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 190)"
+ id="g418">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle326" />
+ <text
+ class="text_normal"
+ id="text350">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath328">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath330">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath332">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="11.2%"
+ id="textPath334">(1)</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="61.2%"
+ id="textPath336">(5)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="red"
+ stroke-width="3"
+ startOffset="34%"
+ id="textPath338">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="34%"
+ id="textPath340">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="black"
+ stroke-width="3"
+ startOffset="45%"
+ id="textPath342">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath344">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="green"
+ stroke-width="3"
+ startOffset="55%"
+ id="textPath346">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="55%"
+ id="textPath348">(4)</textPath>
+ </text>
+ <!-- split it into 'past' and 'future' -->
+ <path
+ d="M -80 -80 l 160 160"
+ stroke="black"
+ id="path352" />
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(-15, -40) rotate(45)"
+ id="text354">PAST</text>
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(30, 60) rotate(225)"
+ id="text356">FUTURE</text>
+ <g
+ transform="rotate(10)"
+ id="g360">
+ <use
+ xlink:href="#frozenPoint"
+ id="use358" />
+ </g>
+ <g
+ transform="rotate(25)"
+ id="g364">
+ <use
+ xlink:href="#frozenPoint"
+ id="use362" />
+ </g>
+ <g
+ transform="rotate(40)"
+ id="g368">
+ <use
+ xlink:href="#frozenPoint"
+ id="use366" />
+ </g>
+ <g
+ transform="rotate(55)"
+ id="g372">
+ <use
+ xlink:href="#frozenPoint"
+ id="use370" />
+ </g>
+ <g
+ transform="rotate(70)"
+ id="g376">
+ <use
+ xlink:href="#frozenPoint"
+ id="use374" />
+ </g>
+ <g
+ transform="rotate(85)"
+ id="g380">
+ <use
+ xlink:href="#frozenPoint"
+ id="use378" />
+ </g>
+ <g
+ transform="rotate(100)"
+ id="g384">
+ <use
+ xlink:href="#frozenPoint"
+ id="use382" />
+ </g>
+ <g
+ transform="rotate(115)"
+ id="g388">
+ <use
+ xlink:href="#frozenPoint"
+ id="use386" />
+ </g>
+ <g
+ transform="rotate(130)"
+ id="g392">
+ <use
+ xlink:href="#frozenPoint"
+ id="use390" />
+ </g>
+ <g
+ transform="rotate(145)"
+ id="g396">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use394" />
+ </g>
+ <g
+ transform="rotate(160)"
+ id="g400">
+ <use
+ xlink:href="#frozenPoint"
+ id="use398" />
+ </g>
+ <g
+ transform="rotate(175)"
+ id="g404">
+ <use
+ xlink:href="#frozenPoint"
+ id="use402" />
+ </g>
+ <g
+ transform="rotate(190)"
+ id="g408">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use406" />
+ </g>
+ <g
+ transform="rotate(205)"
+ id="g412">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use410" />
+ </g>
+ <g
+ transform="rotate(220)"
+ id="g416">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use414" />
+ </g>
+ </g>
+ <!-- legend -->
+ <g
+ class="text_normal"
+ transform="translate(380 30)"
+ id="g452">
+ <text
+ id="text424">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan420">^</tspan>
+<tspan
+ dy="5"
+ id="tspan422">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text426">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text
+ y="50"
+ id="text428">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text
+ y="75"
+ id="text430">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text
+ y="100"
+ id="text432">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text
+ y="125"
+ id="text434">5: txid_current (split-point, jungest xid)</text>
+ <text
+ y="155"
+ id="text438">per table: pg_class.relfrozenxid
+ <tspan
+ style="font-weight:bold"
+ id="tspan436">must</tspan>
+ be between (1) and (5);</text>
+ <text
+ y="175"
+ x="75"
+ id="text440">normally it is between (3) and (4)</text>
+ <use
+ xlink:href="#unfrozenPoint"
+ transform="translate(106, 200)"
+ id="use442" />
+ <text
+ y="205"
+ x="20"
+ id="text444">Unfrozen xid</text>
+ <use
+ xlink:href="#frozenPoint"
+ transform="translate(106, 224)"
+ id="use446" />
+ <text
+ y="230"
+ x="20"
+ id="text448">Frozen xid</text>
+ <text
+ y="260"
+ id="text450">(figure is out of scale)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-raw.svg b/doc/src/sgml/images/freeze-raw.svg
new file mode 100644
index 0000000000..2d1d256184
--- /dev/null
+++ b/doc/src/sgml/images/freeze-raw.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="320px"
+ viewBox="0 0 850 320" >
+
+ <title>Freeze</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100, 0)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100, 0)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="70" y="40"><tspan style="font-style:italic;font-weight:bold">
+ Freeze</tspan> to keep visible</text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 190)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_120" startOffset="11.2%" >(1)</textPath>
+ <textPath xlink:href="#Path_120" startOffset="61.2%" >(5)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="34%" >(2)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(3)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="55%" >(4)</textPath>
+
+ </text>
+
+ <!-- split it into 'past' and 'future' -->
+ <path d="M -80 -80 l 160 160" stroke="black" />
+ <text class="text_normal" letter-spacing="12" transform="translate(-15, -40) rotate(45)">PAST</text>
+ <text class="text_normal" letter-spacing="12" transform="translate(30, 60) rotate(225)">FUTURE</text>
+
+ <g transform="rotate(10)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(25)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(40)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(55)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(70)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(85)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(100)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(115)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(130)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(145)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(160)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(175)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(190)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(205)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(220)"><use xlink:href="#unfrozenPoint"/></g>
+
+ </g>
+
+ <!-- legend -->
+ <g class="text_normal" transform="translate(380 30)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text y="50">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text y="75">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text y="100">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text y="125">5: txid_current (split-point, jungest xid)</text>
+ <text y="155">per table: pg_class.relfrozenxid
+ <tspan style="font-weight:bold">must</tspan> be between (1) and (5);</text>
+ <text y="175" x="75">normally it is between (3) and (4)</text>
+
+ <use xlink:href="#unfrozenPoint" transform="translate(106, 200)"/>
+ <text y="205" x="20">Unfrozen xid</text>
+
+ <use xlink:href="#frozenPoint" transform="translate(106, 224)"/>
+ <text y="230" x="20">Frozen xid</text>
+
+ <text y="260">(figure is out of scale)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
new file mode 100644
index 0000000000..26bce6176d
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
@@ -0,0 +1,83 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="720" height="430" viewBox="0 0 720 430">
+ <title>
+ Hierarchy of Internal Objects
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Hierarchy of internal Objects
+ </text>
+ <g fill="none">
+ <g transform="translate(350 240)">
+ <ellipse rx="320" ry="170" stroke="blue"/>
+ <text class="text_normal" x="-140" y="-130">
+ Cluster
+ </text>
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-60" y="5">
+ Database Names
+ </text>
+ </g>
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-40" y="5">
+ Tablespace
+ </text>
+ </g>
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-70" y="5">
+ Replication Origins
+ </text>
+ </g>
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue"/>
+ <text class="text_normal" x="-60" y="-3">
+ Subscription for
+ </text>
+ <text class="text_normal" x="-68" y="10">
+ Logical Replication
+ </text>
+ </g>
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-15" y="5">
+ Role
+ </text>
+ </g>
+ </g>
+ <g transform="translate(270 250)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2"/>
+ <text class="text_normal" x="-60" y="-80">
+ Database
+ </text>
+ <g transform="translate(-150 -30)">
+ <ellipse rx="50" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Extension
+ </text>
+ </g>
+ <g transform="translate(-155 35)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Collation
+ </text>
+ </g>
+ <g transform="translate(30 20)">
+ <ellipse rx="140" ry="70" stroke="blue"/>
+ <text class="text_normal" x="-80" y="-35">
+ Schema
+ </text>
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue"/>
+ <text class="text_normal" x="-50" y="5">
+ Table, View, ...
+ </text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
new file mode 100644
index 0000000000..e5745818d9
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="720px"
+ height="430px"
+ viewBox="0 0 720 430"
+ id="svg540"
+ sodipodi:docname="internal-objects-hierarchy-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata546">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Hierarchy of Internal Objects</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs544" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1050"
+ inkscape:window-height="838"
+ id="namedview542"
+ showgrid="false"
+ inkscape:zoom="0.51944444"
+ inkscape:cx="360"
+ inkscape:cy="215"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg540" />
+ <title
+ id="title460">Hierarchy of Internal Objects</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style462">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect464" />
+ <text
+ class="text_big"
+ x="200"
+ y="40"
+ id="text466">Hierarchy of internal Objects</text>
+ <!-- set centre of figure and default values -->
+ <g
+ transform="translate(350 240)"
+ fill="none"
+ id="g538">
+ <g
+ id="g504">
+ <ellipse
+ rx="320"
+ ry="170"
+ stroke="blue"
+ id="ellipse468" />
+ <text
+ class="text_normal"
+ x="-140"
+ y="-130"
+ id="text470">Cluster</text>
+ <g
+ transform="translate(40 -125)"
+ id="g476">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse472" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="5"
+ id="text474">Database Names</text>
+ </g>
+ <g
+ transform="translate(180 -70)"
+ id="g482">
+ <ellipse
+ rx="60"
+ ry="20"
+ stroke="blue"
+ id="ellipse478" />
+ <text
+ class="text_normal"
+ x="-40"
+ y="5"
+ id="text480">Tablespace</text>
+ </g>
+ <g
+ transform="translate(230 -5)"
+ id="g488">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse484" />
+ <text
+ class="text_normal"
+ x="-70"
+ y="5"
+ id="text486">Replication Origins</text>
+ </g>
+ <g
+ transform="translate(200 70)"
+ id="g496">
+ <ellipse
+ rx="78"
+ ry="27"
+ stroke="blue"
+ id="ellipse490" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-3"
+ id="text492">Subscription for</text>
+ <text
+ class="text_normal"
+ x="-68"
+ y="10"
+ id="text494">Logical Replication</text>
+ </g>
+ <g
+ transform="translate(100 120)"
+ id="g502">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse498" />
+ <text
+ class="text_normal"
+ x="-15"
+ y="5"
+ id="text500">Role</text>
+ </g>
+ </g>
+ <g
+ transform="translate(-80 10)"
+ id="g536">
+ <ellipse
+ rx="220"
+ ry="110"
+ stroke="blue"
+ stroke-width="2px"
+ id="ellipse506" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-80"
+ id="text508">Database</text>
+ <g
+ transform="translate(-120 -50)"
+ id="g534">
+ <g
+ transform="translate(-30 20)"
+ id="g514">
+ <ellipse
+ rx="50"
+ ry="20"
+ stroke="blue"
+ id="ellipse510" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text512">Extension</text>
+ </g>
+ <g
+ transform="translate(-35 85)"
+ id="g520">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse516" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text518">Collation</text>
+ </g>
+ <g
+ transform="translate(150 70)"
+ id="g532">
+ <ellipse
+ rx="140"
+ ry="70"
+ stroke="blue"
+ id="ellipse522" />
+ <text
+ class="text_normal"
+ x="-80"
+ y="-35"
+ id="text524">Schema</text>
+ <g
+ transform="translate(20 10)"
+ id="g530">
+ <ellipse
+ rx="90"
+ ry="30"
+ stroke="blue"
+ id="ellipse526" />
+ <text
+ class="text_normal"
+ x="-50"
+ y="5"
+ id="text528">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
new file mode 100644
index 0000000000..f0dc890f6b
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="720px" height="430px"
+ viewBox="0 0 720 430" >
+
+ <title>Hierarchy of Internal Objects</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="200" y="40">Hierarchy of internal Objects</text>
+
+
+ <!-- set centre of figure and default values -->
+ <g transform="translate(350 240)" fill="none">
+
+ <g>
+ <ellipse rx="320" ry="170" stroke="blue" />
+ <text class="text_normal" x="-140" y="-130">Cluster</text>
+
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-60" y="5">Database Names</text>
+ </g>
+
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue" />
+ <text class="text_normal" x="-40" y="5">Tablespace</text>
+ </g>
+
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-70" y="5">Replication Origins</text>
+ </g>
+
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue" />
+ <text class="text_normal" x="-60" y="-3">Subscription for</text>
+ <text class="text_normal" x="-68" y="10">Logical Replication</text>
+ </g>
+
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-15" y="5">Role</text>
+ </g>
+
+ </g>
+
+ <g transform="translate(-80 10)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2px" />
+ <text class="text_normal" x="-60" y="-80">Database</text>
+
+ <g transform="translate(-120 -50)">
+ <g transform="translate(-30 20)">
+ <ellipse rx="50" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Extension</text>
+ </g>
+
+ <g transform="translate(-35 85)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Collation</text>
+ </g>
+
+ <g transform="translate(150 70)">
+ <ellipse rx="140" ry="70" stroke="blue" />
+ <text class="text_normal" x="-80" y="-35">Schema</text>
+
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue" />
+ <text class="text_normal" x="-50" y="5">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink-svgo.svg b/doc/src/sgml/images/mvcc-ink-svgo.svg
new file mode 100644
index 0000000000..8e67da93d1
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink-svgo.svg
@@ -0,0 +1,151 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="150" viewBox="0 0 850 150">
+ <title>
+ MVCC
+ </title>
+ <style>
+ .text_small{font-style:normal;font-weight:400;font-size:10px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <marker id="triangle_1" markerWidth="10" markerHeight="10" refX="5" refY="5" orient="auto" stroke="black" fill="none">
+ <path d="M0 0l10 5-10 5"/>
+ </marker>
+ <path id="arrow" d="M0 0q20-15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+ <g id="tuple" stroke="black">
+ <path d="M80 0H0v20h80M29 0v20M60 0v20"/>
+ <path d="M80 0h15M80 20h15" stroke-dasharray="2 1"/>
+ </g>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <g fill="none">
+ <g transform="translate(20 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">123</tspan> <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)" fill="#00f">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 83)" fill="#00f">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(185 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">135</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 53)" fill="#00f">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(350 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">142</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 23)" fill="#00f">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(515 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">821</tspan> <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 821
+ </text>
+ <text class="text_small" transform="translate(125 23)">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(740 110)">
+ <path d="M102-20H-18v60" stroke="black"/>
+ <text font-weight="400" font-size="16" font-family=""Open Sans",sans-serif" fill="#000">
+ Legend
+ </text>
+ <use xlink:href="#tuple" transform="translate(0 10)"/>
+ <text class="text_small" transform="translate(3 23)">
+ xmin
+ </text>
+ <text class="text_small" transform="translate(32 23)">
+ xmax
+ </text>
+ <text class="text_small" transform="translate(65 23)">
+ data
+ </text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink.svg b/doc/src/sgml/images/mvcc-ink.svg
new file mode 100644
index 0000000000..f4161b3e79
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink.svg
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="150px"
+ viewBox="0 0 850 150"
+ id="svg147"
+ sodipodi:docname="mvcc-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>MVCC</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1256"
+ inkscape:window-height="801"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="75"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">MVCC</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs15">
+ <marker
+ id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto"
+ stroke="black"
+ fill="none">
+ <path
+ d="M 0,0 L 10,5 L 0,10"
+ id="path6" />
+ </marker>
+ <g
+ id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path
+ d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20"
+ stroke="black"
+ id="path9" />
+ <!-- prolong the rectangle -->
+ <path
+ d="M 80 0 h 15 M 80 20 h 15"
+ stroke="black"
+ stroke-dasharray="2 1"
+ id="path11" />
+ </g>
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path
+ id="arrow"
+ d="M 0 0 Q 20 -15 40 0"
+ stroke="black"
+ marker-end="url(#triangle_1)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect17" />
+ <!-- set default values -->
+ <g
+ fill="none"
+ id="g145">
+ <!-- start plus first INSERT -->
+ <g
+ transform="translate(20, 40)"
+ id="g35">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text23">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan19">123</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan21">: INSERT</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use25" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use27" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ style="fill:blue"
+ id="text29">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text31">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ style="fill:blue"
+ id="text33">'x'</text>
+ </g>
+ <!-- first UPDATE -->
+ <g
+ transform="translate(185, 40)"
+ id="g61">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text41">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan37">135</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan39">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use43" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use45" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ style="fill:blue"
+ id="text47">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text49">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ style="fill:blue"
+ id="text51">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use53" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text55">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text57">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text59">'x'</text>
+ </g>
+ <!-- next UPDATE -->
+ <g
+ transform="translate(350, 40)"
+ id="g95">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text67">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan63">142</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan65">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use69" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use71" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ style="fill:blue"
+ id="text73">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text75">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ style="fill:blue"
+ id="text77">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use79" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text81">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text83">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text85">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use87" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text89">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text91">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text93">'x'</text>
+ </g>
+ <!-- DELETE -->
+ <g
+ transform="translate(515, 40)"
+ id="g129">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text101">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan97">821</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan99">: DELTE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use103" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use105" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text107">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text109">821</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ id="text111">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use113" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text115">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ id="text117">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text119">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use121" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text123">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text125">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text127">'x'</text>
+ </g>
+ <!-- LEGEND -->
+ <g
+ transform="translate(740, 110)"
+ id="g143">
+ <path
+ d="M 102 -20 h -120 v 60"
+ stroke="black"
+ id="path131" />
+ <text
+ class="text_normal"
+ transform="translate(0, 0)"
+ id="text133">Legend</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(0, 10)"
+ id="use135" />
+ <text
+ class="text_small"
+ transform="translate(3, 23)"
+ id="text137">xmin</text>
+ <text
+ class="text_small"
+ transform="translate(32, 23)"
+ id="text139">xmax</text>
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text141">data</text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-raw.svg b/doc/src/sgml/images/mvcc-raw.svg
new file mode 100644
index 0000000000..0481c4c938
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-raw.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="150px"
+ viewBox="0 0 850 150" >
+
+ <title>MVCC</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <marker id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto" stroke="black" fill="none">
+ <path d="M 0,0 L 10,5 L 0,10" />
+ </marker>
+
+ <g id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20" stroke="black"/>
+ <!-- prolong the rectangle -->
+ <path d="M 80 0 h 15 M 80 20 h 15" stroke="black" stroke-dasharray="2 1"/>
+ </g>
+
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path id="arrow" d="M 0 0 Q 20 -15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- set default values -->
+ <g fill="none">
+
+ <!-- start plus first INSERT -->
+ <g transform="translate(20, 40)">
+
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">123</tspan>
+ <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)" style="fill:blue">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 83)" style="fill:blue">'x'</text>
+ </g>
+
+ <!-- first UPDATE -->
+ <g transform="translate(185, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">135</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 53)" style="fill:blue">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- next UPDATE -->
+ <g transform="translate(350, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">142</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 23)" style="fill:blue">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- DELETE -->
+ <g transform="translate(515, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">821</tspan>
+ <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">821</text>
+ <text class="text_small" transform="translate(125, 23)">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- LEGEND -->
+ <g transform="translate(740, 110)">
+ <path d="M 102 -20 h -120 v 60" stroke="black"/>
+ <text class="text_normal" transform="translate(0, 0)">Legend</text>
+ <use xlink:href="#tuple" transform="translate(0, 10)"/>
+ <text class="text_small" transform="translate(3, 23)">xmin</text>
+ <text class="text_small" transform="translate(32, 23)">xmax</text>
+ <text class="text_small" transform="translate(65, 23)">data</text>
+ </g>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink-svgo.svg b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
new file mode 100644
index 0000000000..723d67bd8d
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
@@ -0,0 +1,285 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 900 600">
+ <title>
+ PG Overall Server Architecture
+ </title>
+ <style>
+ .text_big{font-style:normal}.text_big,.text_comment,.text_normal,.text_small{font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_normal,.text_small{font-style:normal}.text_small{font-size:12px}.text_normal{font-size:16px}.text_big{font-size:24px}.text_comment{font-style:italic;font-size:16px}
+ </style>
+ <defs>
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (200 x 20 px)
+ </title>
+ <path d="M200 10v10H0V0h190v10h10L190 0"/>
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (250 x 20 px)
+ </title>
+ <path d="M250 10v10H0V0h240v10h10L240 0"/>
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (100 x 35 px)
+ </title>
+ <path d="M100 10v25H0V0h90v10h10L90 0"/>
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (170 x 50 px)
+ </title>
+ <path d="M170 10v40H0V0h160v10h10L160 0"/>
+ </symbol>
+ <symbol id="state_300x120">
+ <title>
+ UML State (300x120)
+ </title>
+ <rect width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>
+ UML State (350x120)
+ </title>
+ <rect width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="disc" stroke="blue" fill="none">
+ <title>
+ Disc
+ </title>
+ <ellipse cx="51" cy="13" rx="50" ry="12"/>
+ <path d="M1 13v60"/>
+ <path d="M101 13v60"/>
+ <path d="M1 73a50 12 0 00100 0"/>
+ </symbol>
+ <symbol id="laptop" stroke="black" fill="none">
+ <title>
+ Laptop
+ </title>
+ <path d="M20 40V0h54v40l15 15H5l15-15h54"/>
+ <path d="M23 3h48v34H23z"/>
+ <path d="M30 10h20"/>
+ <path d="M30 15h25"/>
+ <path d="M30 20h10"/>
+ <path d="M30 30h20"/>
+ <path d="M25 50h45l2 2H22z"/>
+ </symbol>
+ <marker id="arrowhead_start" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto">
+ <path d="M6 0L0 3l6 3" stroke="black" fill="none"/>
+ </marker>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="15" y="40" class="text_big">
+ Client
+ </text>
+ <text x="140" y="40" class="text_big">
+ Server
+ </text>
+ <use xlink:href="#laptop" x="5" y="210"/>
+ <g transform="translate(130 70)">
+ <use xlink:href="#state_350x120"/>
+ <text x="5" y="20" class="text_normal">
+ maintenance_work_mem (per connection)
+ </text>
+ <text x="5" y="45" class="text_normal">
+ work_mem (per query operation)
+ </text>
+ <text x="5" y="70" class="text_normal">
+ autovacuum_work_mem (per worker process)
+ </text>
+ <text x="5" y="95" class="text_normal">
+ temp_buffer (per connection)
+ </text>
+ <text x="5" y="110" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_200x20" x="140" y="-15"/>
+ <text x="150" class="text_comment">
+ Individual Memory
+ </text>
+ </g>
+ <g transform="translate(520 70)">
+ <use xlink:href="#state_300x120"/>
+ <text x="10" y="30" class="text_normal">
+ shared_buffers (heap and index)
+ </text>
+ <text x="10" y="70" class="text_normal">
+ wal_buffers (WAL records)
+ </text>
+ <text x="10" y="100" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_250x20" x="40" y="-15"/>
+ <text x="50" class="text_comment">
+ Shared Memory (per Instance)
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M180 215h250v30H180z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(180 215)">
+ Postmaster
+ </text>
+ <path d="M90 230h75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 230)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 1
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M150 315h370v30H150z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(150 315)">
+ Backend processes (one per connection)
+ </text>
+ <path d="M155 315v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M160 310v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M90 240l63 63" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 290)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 3
+ </text>
+ </g>
+ <path d="M360 250v50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180 255)">
+ <use xlink:href="#note_250x20"/>
+ <text x="10" y="15" class="text_comment">
+ Creates backend processes
+ </text>
+ </g>
+ <g transform="translate(360 281)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 2
+ </text>
+ </g>
+ <path d="M460 300V200" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M498 300V95h30" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M508 300V135h20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M550 220h120v30H550z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(550 220)">
+ WAL Writer
+ </text>
+ <path d="M590 150v65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M590 255v230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 340h140v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 340)">
+ Checkpointer
+ </text>
+ <path d="M740 110v220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 355H475v130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M700 330V150" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50"/>
+ <text x="60" y="-35" class="text_comment">
+ Checkpoint
+ </text>
+ <text x="60" y="-20" class="text_comment">
+ Record
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M610 380h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 380)">
+ Background Writer
+ </text>
+ <path d="M770 110v260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 395H485v90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 420h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 420)">
+ WAL Archiver
+ </text>
+ <path d="M620 485l30-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M690 455l30 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M135 380h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 380)">
+ Autovacuum
+ </text>
+ <path d="M140 380v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path d="M145 375v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path stroke="blue" fill="none" d="M135 430h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 430)">
+ Logger
+ </text>
+ <path stroke="blue" fill="none" d="M290 370h140v30H290z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(290 370)">
+ Stats Collector
+ </text>
+ <g transform="translate(145 490)">
+ <use xlink:href="#disc"/>
+ <text x="35" y="45" class="text_normal">
+ Log
+ </text>
+ <text x="20" y="60" class="text_small">
+ text lines,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <path d="M195 465v20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(410 490)">
+ <use xlink:href="#disc"/>
+ <text x="10" y="40" class="text_normal">
+ Heap and
+ </text>
+ <text x="25" y="55" class="text_normal">
+ Index
+ </text>
+ <text x="15" y="70" class="text_small">
+ binary blocks,
+ </text>
+ <text x="30" y="80" class="text_small">
+ random
+ </text>
+ </g>
+ <path d="M450 485V350" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(295 420)">
+ <use xlink:href="#note_170x50"/>
+ <text x="5" y="15" class="text_comment">
+ Read heap and index
+ </text>
+ <text x="5" y="30" class="text_comment">
+ pages and transfer
+ </text>
+ <text x="5" y="45" class="text_comment">
+ them to shared_buffers
+ </text>
+ </g>
+ <g transform="translate(550 490)">
+ <use xlink:href="#disc"/>
+ <text x="30" y="45" class="text_normal">
+ WAL
+ </text>
+ <text x="10" y="60" class="text_small">
+ binary records,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <g transform="translate(690 490)">
+ <use xlink:href="#disc"/>
+ <text x="16" y="45" class="text_normal">
+ Archived
+ </text>
+ <text x="36" y="60" class="text_normal">
+ WAL
+ </text>
+ </g>
+ <path d="M110 20v550" stroke="black" fill="none"/>
+ <g transform="rotate(90 -33.5 156.5)">
+ <use xlink:href="#note_200x20"/>
+ <text class="text_comment" x="10" y="15">
+ Via TCP/IP or socket
+ </text>
+ </g>
+ <text class="text_big" x="95" transform="rotate(90 425 425)">
+ RAM
+ </text>
+ <text class="text_big" x="250" transform="rotate(90 425 425)">
+ PROCESSES
+ </text>
+ <text class="text_big" x="500" transform="rotate(90 425 425)">
+ FILES
+ </text>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink.svg b/doc/src/sgml/images/ram-proc-file-ink.svg
new file mode 100644
index 0000000000..4490bf51e1
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink.svg
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="600px"
+ viewBox="0 0 900 600"
+ id="svg306"
+ sodipodi:docname="ram-proc-file-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata310">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>PG Overall Server Architecture</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1048"
+ inkscape:window-height="771"
+ id="namedview308"
+ showgrid="false"
+ inkscape:zoom="0.39333333"
+ inkscape:cx="450"
+ inkscape:cy="300"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg306" />
+ <title
+ id="title2">PG Overall Server Architecture</title>
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs70">
+ <!-- Some notes in different sizes -->
+ <symbol
+ id="note_200x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title6">UML Note (200 x 20 px)</title>
+ <path
+ d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10"
+ id="path8" />
+ </symbol>
+ <symbol
+ id="note_250x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title11">UML Note (250 x 20 px)</title>
+ <path
+ d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10"
+ id="path13" />
+ </symbol>
+ <symbol
+ id="note_100x35"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title16">UML Note (100 x 35 px)</title>
+ <path
+ d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10"
+ id="path18" />
+ </symbol>
+ <symbol
+ id="note_170x50"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title21">UML Note (170 x 50 px)</title>
+ <path
+ d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10"
+ id="path23" />
+ </symbol>
+ <!-- UML states (used for buffers) -->
+ <symbol
+ id="state_300x120">
+ <title
+ id="title26">UML State (300x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="300"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect28" />
+ </symbol>
+ <symbol
+ id="state_350x120">
+ <title
+ id="title31">UML State (350x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="350"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect33" />
+ </symbol>
+ <!-- Discs -->
+ <symbol
+ id="disc"
+ stroke="blue"
+ fill="none">
+ <title
+ id="title36">Disc</title>
+ <ellipse
+ cx="51"
+ cy="13"
+ rx="50"
+ ry="12"
+ id="ellipse38" />
+ <!-- top -->
+ <path
+ d="M 1,13 v 60"
+ id="path40" />
+ <!-- left -->
+ <path
+ d="M 101,13 v 60"
+ id="path42" />
+ <!-- right -->
+ <path
+ d="M 1,73 A 50, 12, 0, 0, 0, 101,73"
+ id="path44" />
+ <!-- bottom -->
+ </symbol>
+ <!-- Laptop -->
+ <symbol
+ id="laptop"
+ stroke="black"
+ fill="none">
+ <title
+ id="title47">Laptop</title>
+ <path
+ d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54"
+ id="path49" />
+ <rect
+ x="23"
+ y="3"
+ width="48"
+ height="34"
+ id="rect51" />
+ <!-- symbolize some lines -->
+ <path
+ d="M 30,10 h 20"
+ id="path53" />
+ <path
+ d="M 30,15 h 25"
+ id="path55" />
+ <path
+ d="M 30,20 h 10"
+ id="path57" />
+ <path
+ d="M 30,30 h 20"
+ id="path59" />
+ <!-- symbolize keyboard -->
+ <path
+ d="M 25,50 h 45 l 2,2 h -50 z "
+ id="path61" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path64" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path67" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect72" />
+ <!-- caption, client side -->
+ <text
+ x="15"
+ y="40"
+ class="text_big"
+ id="text74">Client</text>
+ <text
+ x="140"
+ y="40"
+ class="text_big"
+ id="text76">Server</text>
+ <use
+ xlink:href="#laptop"
+ x="5"
+ y="210"
+ id="use78" />
+ <!-- individual memory -->
+ <g
+ transform="translate(130, 70)"
+ id="g96">
+ <use
+ xlink:href="#state_350x120"
+ x="0"
+ y="0"
+ id="use80" />
+ <text
+ x="5"
+ y="20"
+ class="text_normal"
+ id="text82">maintenance_work_mem (per connection)</text>
+ <text
+ x="5"
+ y="45"
+ class="text_normal"
+ id="text84">work_mem (per query operation)</text>
+ <text
+ x="5"
+ y="70"
+ class="text_normal"
+ id="text86">autovacuum_work_mem (per worker process)</text>
+ <text
+ x="5"
+ y="95"
+ class="text_normal"
+ id="text88">temp_buffer (per connection)</text>
+ <text
+ x="5"
+ y="110"
+ class="text_normal"
+ id="text90">...</text>
+ <use
+ xlink:href="#note_200x20"
+ x="140"
+ y="-15"
+ id="use92" />
+ <text
+ x="150"
+ y="0"
+ class="text_comment"
+ id="text94">Individual Memory</text>
+ </g>
+ <!-- shared memory -->
+ <g
+ transform="translate(520, 70)"
+ id="g110">
+ <use
+ xlink:href="#state_300x120"
+ x="0"
+ y="0"
+ id="use98" />
+ <text
+ x="10"
+ y="30"
+ class="text_normal"
+ id="text100">shared_buffers (heap and index)</text>
+ <text
+ x="10"
+ y="70"
+ class="text_normal"
+ id="text102">wal_buffers (WAL records)</text>
+ <text
+ x="10"
+ y="100"
+ class="text_normal"
+ id="text104">...</text>
+ <use
+ xlink:href="#note_250x20"
+ x="40"
+ y="-15"
+ id="use106" />
+ <text
+ x="50"
+ y="0"
+ class="text_comment"
+ id="text108">Shared Memory (per Instance)</text>
+ </g>
+ <!-- postmaster -->
+ <g
+ transform="translate(180, 215)"
+ id="g116">
+ <rect
+ width="250"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect112" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text114">Postmaster</text>
+ </g>
+ <path
+ d="M 90,230 h 75"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path118" />
+ <g
+ transform="translate(140, 230)"
+ id="g124">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle120" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text122">1</text>
+ </g>
+ <!-- backend processes -->
+ <g
+ transform="translate(150, 315)"
+ id="g134">
+ <rect
+ width="370"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect126" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text128">Backend processes (one per connection)</text>
+ <path
+ d="M 5,0 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path130" />
+ <path
+ d="M 10,-5 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path132" />
+ </g>
+ <path
+ d="M 90,240 153,303"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path136" />
+ <g
+ transform="translate(140, 290)"
+ id="g142">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle138" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text140">3</text>
+ </g>
+ <!-- connection between postmaster and backend processes -->
+ <path
+ d="M 360,250 v 50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path144" />
+ <g
+ transform="translate(180, 255)"
+ id="g150">
+ <use
+ xlink:href="#note_250x20"
+ id="use146" />
+ <text
+ x="10"
+ y="15"
+ class="text_comment"
+ id="text148">Creates backend processes</text>
+ </g>
+ <g
+ transform="translate(360, 281)"
+ id="g156">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle152" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text154">2</text>
+ </g>
+ <!-- backend process' access to individual memory -->
+ <path
+ d="M 460,300 v -100"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path158" />
+ <!-- its access to shared buffers and WAL buffers -->
+ <path
+ d="M 498,300 v -205 h 30"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path160" />
+ <path
+ d="M 508,300 v -165 h 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path162" />
+ <!-- WAL writer -->
+ <g
+ transform="translate(550, 220)"
+ id="g168">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect164" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text166">WAL Writer</text>
+ </g>
+ <path
+ d="M 590,150 v 65"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path170" />
+ <path
+ d="M 590,255 v 230"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path172" />
+ <!-- Checkpoiner -->
+ <g
+ transform="translate(610, 340)"
+ id="g178">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect174" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text176">Checkpointer</text>
+ </g>
+ <path
+ d="M 740,110 v 220"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path180" />
+ <path
+ d="M 605,355 h -130 v 130"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path182" />
+ <path
+ d="M 700,330 v -180"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path184" />
+ <g
+ transform="translate(570, 330)"
+ id="g192">
+ <use
+ xlink:href="#note_100x35"
+ x="50"
+ y="-50"
+ id="use186" />
+ <text
+ x="60"
+ y="-35"
+ class="text_comment"
+ id="text188">Checkpoint</text>
+ <text
+ x="60"
+ y="-20"
+ class="text_comment"
+ id="text190">Record</text>
+ </g>
+ <!-- BG writer -->
+ <g
+ transform="translate(610, 380)"
+ id="g198">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect194" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text196">Background Writer</text>
+ </g>
+ <path
+ d="M 770,110 v 260"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path200" />
+ <path
+ d="M 605,395 h -120 v 90"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path202" />
+ <!-- Archiver -->
+ <g
+ transform="translate(610, 420)"
+ id="g208">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect204" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text206">WAL Archiver</text>
+ </g>
+ <path
+ d="M 620,485 l 30,-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path210" />
+ <path
+ d="M 690,455 l 30, 30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path212" />
+ <!-- Vacuum -->
+ <g
+ transform="translate(135, 380)"
+ id="g222">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect214" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text216">Autovacuum</text>
+ <path
+ d="M 5,0 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path218" />
+ <path
+ d="M 10,-5 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path220" />
+ </g>
+ <!-- Log Writer -->
+ <g
+ transform="translate(135, 430)"
+ id="g228">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect224" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text226">Logger</text>
+ </g>
+ <!-- Stats Collector -->
+ <g
+ transform="translate(290, 370)"
+ id="g234">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect230" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text232">Stats Collector</text>
+ </g>
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g
+ transform="translate(145, 490)"
+ id="g244">
+ <use
+ xlink:href="#disc"
+ id="use236" />
+ <text
+ x="35"
+ y="45"
+ class="text_normal"
+ id="text238">Log</text>
+ <text
+ x="20"
+ y="60"
+ class="text_small"
+ id="text240">text lines,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text242">sequential</text>
+ </g>
+ <path
+ d="M 195,465 v 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path246" />
+ <g
+ transform="translate(410, 490)"
+ id="g258">
+ <use
+ xlink:href="#disc"
+ id="use248" />
+ <text
+ x="10"
+ y="40"
+ class="text_normal"
+ id="text250">Heap and</text>
+ <text
+ x="25"
+ y="55"
+ class="text_normal"
+ id="text252">Index</text>
+ <text
+ x="15"
+ y="70"
+ class="text_small"
+ id="text254">binary blocks,</text>
+ <text
+ x="30"
+ y="80"
+ class="text_small"
+ id="text256">random</text>
+ </g>
+ <path
+ d="M 450,485 v -135"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path260" />
+ <g
+ transform="translate(295, 420)"
+ id="g270">
+ <use
+ xlink:href="#note_170x50"
+ id="use262" />
+ <text
+ x="5"
+ y="15"
+ class="text_comment"
+ id="text264">Read heap and index</text>
+ <text
+ x="5"
+ y="30"
+ class="text_comment"
+ id="text266">pages and transfer</text>
+ <text
+ x="5"
+ y="45"
+ class="text_comment"
+ id="text268">them to shared_buffers</text>
+ </g>
+ <g
+ transform="translate(550, 490)"
+ id="g280">
+ <use
+ xlink:href="#disc"
+ id="use272" />
+ <text
+ x="30"
+ y="45"
+ class="text_normal"
+ id="text274">WAL</text>
+ <text
+ x="10"
+ y="60"
+ class="text_small"
+ id="text276">binary records,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text278">sequential</text>
+ </g>
+ <g
+ transform="translate(690, 490)"
+ id="g288">
+ <use
+ xlink:href="#disc"
+ id="use282" />
+ <text
+ x="16"
+ y="45"
+ class="text_normal"
+ id="text284">Archived</text>
+ <text
+ x="36"
+ y="60"
+ class="text_normal"
+ id="text286">WAL</text>
+ </g>
+ <!-- boarder between client and server side -->
+ <path
+ d="M 110,20 v 550"
+ stroke="black"
+ fill="none"
+ id="path290" />
+ <g
+ transform="translate(123, 190) rotate(90)"
+ id="g296">
+ <use
+ xlink:href="#note_200x20"
+ id="use292" />
+ <text
+ class="text_comment"
+ x="10"
+ y="15"
+ id="text294">Via TCP/IP or socket</text>
+ </g>
+ <!-- right side -->
+ <g
+ transform="translate(850, 0) rotate(90)"
+ id="g304">
+ <text
+ class="text_big"
+ x="95"
+ id="text298">RAM</text>
+ <text
+ class="text_big"
+ x="250"
+ id="text300">PROCESSES</text>
+ <text
+ class="text_big"
+ x="500"
+ id="text302">FILES</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-raw.svg b/doc/src/sgml/images/ram-proc-file-raw.svg
new file mode 100644
index 0000000000..aec5811c54
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-raw.svg
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="600px"
+ viewBox="0 0 900 600">
+
+ <title>PG Overall Server Architecture</title>
+
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Some notes in different sizes -->
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>UML Note (200 x 20 px)</title>
+ <path d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>UML Note (250 x 20 px)</title>
+ <path d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>UML Note (100 x 35 px)</title>
+ <path d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>UML Note (170 x 50 px)</title>
+ <path d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- UML states (used for buffers) -->
+ <symbol id="state_300x120">
+ <title>UML State (300x120)</title>
+ <rect x="0" y="0" width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>UML State (350x120)</title>
+ <rect x="0" y="0" width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- Discs -->
+ <symbol id="disc" stroke="blue" fill="none" >
+ <title>Disc</title>
+ <ellipse cx="51" cy="13" rx="50" ry="12" /> <!-- top -->
+ <path d="M 1,13 v 60" /> <!-- left -->
+ <path d="M 101,13 v 60" /> <!-- right -->
+ <path d="M 1,73 A 50, 12, 0, 0, 0, 101,73" /> <!-- bottom -->
+ </symbol>
+
+ <!-- Laptop -->
+ <symbol id="laptop" stroke="black" fill="none" >
+ <title>Laptop</title>
+ <path d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54" />
+ <rect x="23" y="3" width="48" height="34" />
+ <!-- symbolize some lines -->
+ <path d="M 30,10 h 20" />
+ <path d="M 30,15 h 25" />
+ <path d="M 30,20 h 10" />
+ <path d="M 30,30 h 20" />
+ <!-- symbolize keyboard -->
+ <path d="M 25,50 h 45 l 2,2 h -50 z " />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption, client side -->
+ <text x="15" y="40" class="text_big">Client</text>
+ <text x="140" y="40" class="text_big">Server</text>
+ <use xlink:href="#laptop" x="5" y="210" />
+
+
+ <!-- individual memory -->
+ <g transform="translate(130, 70)">
+ <use xlink:href="#state_350x120" x="0" y="0" />
+ <text x="5" y="20" class="text_normal">maintenance_work_mem (per connection)</text>
+ <text x="5" y="45" class="text_normal">work_mem (per query operation)</text>
+ <text x="5" y="70" class="text_normal">autovacuum_work_mem (per worker process)</text>
+ <text x="5" y="95" class="text_normal">temp_buffer (per connection)</text>
+ <text x="5" y="110" class="text_normal">...</text>
+ <use xlink:href="#note_200x20" x="140" y="-15" />
+ <text x="150" y="0" class="text_comment">Individual Memory</text>
+ </g>
+
+ <!-- shared memory -->
+ <g transform="translate(520, 70)">
+ <use xlink:href="#state_300x120" x="0" y="0" />
+ <text x="10" y="30" class="text_normal">shared_buffers (heap and index)</text>
+ <text x="10" y="70" class="text_normal">wal_buffers (WAL records)</text>
+ <text x="10" y="100" class="text_normal">...</text>
+ <use xlink:href="#note_250x20" x="40" y="-15" />
+ <text x="50" y="0" class="text_comment">Shared Memory (per Instance)</text>
+ </g>
+
+ <!-- postmaster -->
+ <g transform="translate(180, 215)">
+ <rect width="250" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Postmaster</text>
+ </g>
+ <path d="M 90,230 h 75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 230)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">1</text>
+ </g>
+
+ <!-- backend processes -->
+ <g transform="translate(150, 315)">
+ <rect width="370" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Backend processes (one per connection)</text>
+ <path d="M 5,0 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <path d="M 90,240 153,303" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 290)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">3</text>
+ </g>
+
+ <!-- connection between postmaster and backend processes -->
+ <path d="M 360,250 v 50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180, 255)">
+ <use xlink:href="#note_250x20" />
+ <text x="10" y="15" class="text_comment">Creates backend processes</text>
+ </g>
+ <g transform="translate(360, 281)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">2</text>
+ </g>
+
+ <!-- backend process' access to individual memory -->
+ <path d="M 460,300 v -100" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <!-- its access to shared buffers and WAL buffers -->
+ <path d="M 498,300 v -205 h 30" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M 508,300 v -165 h 20" stroke="black" fill="none"
+ marker-end="url(#arrowhead_end)"/>
+
+ <!-- WAL writer -->
+ <g transform="translate(550, 220)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Writer</text>
+ </g>
+ <path d="M 590,150 v 65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 590,255 v 230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Checkpoiner -->
+ <g transform="translate(610, 340)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Checkpointer</text>
+ </g>
+ <path d="M 740,110 v 220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,355 h -130 v 130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 700,330 v -180" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570, 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50" />
+ <text x="60" y="-35" class="text_comment">Checkpoint</text>
+ <text x="60" y="-20" class="text_comment">Record</text>
+ </g>
+
+ <!-- BG writer -->
+ <g transform="translate(610, 380)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Background Writer</text>
+ </g>
+ <path d="M 770,110 v 260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,395 h -120 v 90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Archiver -->
+ <g transform="translate(610, 420)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Archiver</text>
+ </g>
+ <path d="M 620,485 l 30,-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 690,455 l 30, 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Vacuum -->
+ <g transform="translate(135, 380)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Autovacuum</text>
+ <path d="M 5,0 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <!-- Log Writer -->
+ <g transform="translate(135, 430)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Logger</text>
+ </g>
+
+ <!-- Stats Collector -->
+ <g transform="translate(290, 370)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Stats Collector</text>
+ </g>
+
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g transform="translate(145, 490)">
+ <use xlink:href="#disc" />
+ <text x="35" y="45" class="text_normal">Log</text>
+ <text x="20" y="60" class="text_small">text lines,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+ <path d="M 195,465 v 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(410, 490)">
+ <use xlink:href="#disc" />
+ <text x="10" y="40" class="text_normal">Heap and</text>
+ <text x="25" y="55" class="text_normal">Index</text>
+ <text x="15" y="70" class="text_small">binary blocks,</text>
+ <text x="30" y="80" class="text_small">random</text>
+ </g>
+ <path d="M 450,485 v -135" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(295, 420)">
+ <use xlink:href="#note_170x50" />
+ <text x="5" y="15" class="text_comment">Read heap and index</text>
+ <text x="5" y="30" class="text_comment">pages and transfer</text>
+ <text x="5" y="45" class="text_comment">them to shared_buffers</text>
+ </g>
+
+ <g transform="translate(550, 490)">
+ <use xlink:href="#disc" />
+ <text x="30" y="45" class="text_normal">WAL</text>
+ <text x="10" y="60" class="text_small">binary records,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+
+ <g transform="translate(690, 490)">
+ <use xlink:href="#disc" />
+ <text x="16" y="45" class="text_normal">Archived</text>
+ <text x="36" y="60" class="text_normal">WAL</text>
+ </g>
+
+ <!-- boarder between client and server side -->
+ <path d="M 110,20 v 550" stroke="black" fill="none" />
+ <g transform="translate(123, 190) rotate(90)">
+ <use xlink:href="#note_200x20" />
+ <text class="text_comment" x="10" y ="15">Via TCP/IP or socket</text>
+ </g>
+
+ <!-- right side -->
+ <g transform="translate(850, 0) rotate(90)">
+ <text class="text_big" x="95">RAM</text>
+ <text class="text_big" x="250">PROCESSES</text>
+ <text class="text_big" x="500">FILES</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink-svgo.svg b/doc/src/sgml/images/wraparound-ink-svgo.svg
new file mode 100644
index 0000000000..9882d2be23
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink-svgo.svg
@@ -0,0 +1,40 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="280" viewBox="0 0 850 280">
+ <title>
+ Cyclic usage of XIDs
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="370" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ Cyclic usage of XIDs modulo 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan>
+ </text>
+ <g fill="none" transform="translate(170 150)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_095" startOffset="30.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="30%">(1)</textPath> <textPath xlink:href="#Path_095" startOffset="45.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(2)</textPath> <textPath xlink:href="#Path_095" startOffset="50.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="50%">(3)</textPath> <textPath xlink:href="#Path_095" startOffset="62.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="62%">(4)</textPath>
+ </text>
+ </g>
+ <g class="text_normal">
+ <text transform="translate(400 130)">
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25" transform="translate(400 130)">
+ 1: oldest <tspan font-weight="700">active</tspan> xid (pg_stat_activity.backend_xmin)
+ </text>
+ <text y="50" transform="translate(400 130)">
+ 2: xmin of one row version
+ </text>
+ <text y="75" transform="translate(400 130)">
+ 3: xmax of the same row version
+ </text>
+ <text y="100" transform="translate(400 130)">
+ 4: jungest xid (txid_current)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink.svg b/doc/src/sgml/images/wraparound-ink.svg
new file mode 100644
index 0000000000..a9c51f4e43
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="280px"
+ viewBox="0 0 850 280"
+ id="svg1072"
+ sodipodi:docname="wraparound-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata1076">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Cyclic usage of XIDs</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1193"
+ inkscape:window-height="788"
+ id="namedview1074"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="140"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg1072" />
+ <title
+ id="title1009">Cyclic usage of XIDs</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style1011">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs1016">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect1018" />
+ <text
+ class="text_big"
+ x="370"
+ y="40"
+ id="text1024">Cyclic usage of XIDs modulo 2
+ <tspan
+ dy="-5"
+ id="tspan1020">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1022">32</tspan>
+</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 150)"
+ id="g1052">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle1026" />
+ <text
+ class="text_normal"
+ id="text1050">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath1028">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath1030">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath1032">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="30.5%"
+ id="textPath1034">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="30%"
+ id="textPath1036">(1)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="45.5%"
+ id="textPath1038">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath1040">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="50.5%"
+ id="textPath1042">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="50%"
+ id="textPath1044">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="62.5%"
+ id="textPath1046">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="62%"
+ id="textPath1048">(4)</textPath>
+ </text>
+ </g>
+ <g
+ class="text_normal"
+ transform="translate(400 130)"
+ id="g1070">
+ <text
+ id="text1058">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan1054">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1056">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text1062">1: oldest <tspan
+ style="font-weight:bold"
+ id="tspan1060">active</tspan>
+ xid (pg_stat_activity.backend_xmin)</text>
+ <text
+ y="50"
+ id="text1064">2: xmin of one row version</text>
+ <text
+ y="75"
+ id="text1066">3: xmax of the same row version</text>
+ <text
+ y="100"
+ id="text1068">4: jungest xid (txid_current)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-raw.svg b/doc/src/sgml/images/wraparound-raw.svg
new file mode 100644
index 0000000000..9406f52970
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-raw.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="280px"
+ viewBox="0 0 850 280" >
+
+ <title>Cyclic usage of XIDs</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="370" y="40">Cyclic usage of XIDs modulo 2
+ <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan></text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 150)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_095" startOffset="30.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="30%" >(1)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="45.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(2)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="50.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="50%" >(3)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="62.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="62%" >(4)</textPath>
+ </text>
+ </g>
+
+ <g class="text_normal" transform="translate(400 130)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: oldest <tspan style="font-weight:bold">active</tspan> xid (pg_stat_activity.backend_xmin)</text>
+ <text y="50">2: xmin of one row version</text>
+ <text y="75">3: xmax of the same row version</text>
+ <text y="100">4: jungest xid (txid_current)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index c41ce9499b..7913f45897 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -62,6 +62,7 @@ break is not needed in a wider output rendering.
&start;
&query;
&advanced;
+ &architecture;
</part>
diff --git a/doc/src/sgml/query.sgml b/doc/src/sgml/query.sgml
index c0889743c4..b1906c6e36 100644
--- a/doc/src/sgml/query.sgml
+++ b/doc/src/sgml/query.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/query.sgml -->
<chapter id="tutorial-sql">
- <title>The <acronym>SQL</acronym> Language</title>
+ <title>Fundamentals of the <acronym>SQL</acronym> Language</title>
<sect1 id="tutorial-sql-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml
index 9bb5c1a6d5..8751410179 100644
--- a/doc/src/sgml/start.sgml
+++ b/doc/src/sgml/start.sgml
@@ -53,7 +53,7 @@
<sect1 id="tutorial-arch">
- <title>Architectural Fundamentals</title>
+ <title>Client/Server Model</title>
<para>
Before we proceed, you should understand the basic
@@ -68,34 +68,55 @@
client/server model. A <productname>PostgreSQL</productname>
session consists of the following cooperating processes
(programs):
+ </para>
- <itemizedlist>
- <listitem>
- <para>
- A server process, which manages the database files, accepts
- connections to the database from client applications, and
- performs database actions on behalf of the clients. The
- database server program is called
- <filename>postgres</filename>.
- <indexterm><primary>postgres</primary></indexterm>
- </para>
- </listitem>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A process at the server site with the name
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ <indexterm><primary>postgres</primary></indexterm>
+ It accepts connection requests from client applications, starts
+ (<quote>forks</quote>) a new <glossterm linkend="glossary-backend">
+ Backend process</glossterm> for each of them, and passes
+ the connection to it. From that point on, the client and the new
+ <firstterm>Backend process</firstterm>
+ communicate directly without intervention by the original
+ <firstterm>postgres</firstterm> process. Thus, the
+ <firstterm>postgres</firstterm> process is always running, waiting
+ for new client connections, whereas clients and associated
+ <firstterm>Backend processes</firstterm> come and go.
+ (All of this is of course invisible to the user. We only mention it
+ here for completeness.)
+ </para>
+ </listitem>
- <listitem>
- <para>
- The user's client (frontend) application that wants to perform
- database operations. Client applications can be very diverse
- in nature: a client could be a text-oriented tool, a graphical
- application, a web server that accesses the database to
- display web pages, or a specialized database maintenance tool.
- Some client applications are supplied with the
- <productname>PostgreSQL</productname> distribution; most are
- developed by users.
- </para>
- </listitem>
+ <listitem>
+ <para>
+ A group of processes at the server site, the <glossterm
+ linkend="glossary-instance">instance</glossterm>, to which also the
+ <firstterm>postgres</firstterm> process belongs. Their duties are
+ handling of central, common database activities like file access,
+ vacuum, <glossterm linkend="glossary-checkpoint">checkpoints</glossterm>,
+ replication, and more. The mentioned <firstterm>Backend processes</firstterm>
+ delegate those actions to the <firstterm>instance</firstterm>.
+ </para>
+ </listitem>
- </itemizedlist>
- </para>
+ <listitem>
+ <para>
+ The user's client (frontend) application that wants to perform
+ database operations. Client applications can be very diverse
+ in nature: a client could be a text-oriented tool, a graphical
+ application, a web server that accesses the database to
+ display web pages, or a specialized database maintenance tool.
+ Some client applications are supplied with the
+ <productname>PostgreSQL</productname> distribution; most are
+ developed by users.
+ </para>
+ </listitem>
+
+ </itemizedlist>
<para>
As is typical of client/server applications, the client and the
0007-01-architecture-DGJ-Collaboration-.patchapplication/octet-stream; name=0007-01-architecture-DGJ-Collaboration-.patchDownload
commit 8c7a1630516749a7eaa6aa4fc8f117962858dcea
Author: David G. Johnston <david.g.johnston@gmail.com>
Date: Wed Oct 21 20:07:35 2020 +0000
Review of the Collaboration of Processes section
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
index 2be9898d98..3fa896cefb 100644
--- a/doc/src/sgml/architecture.sgml
+++ b/doc/src/sgml/architecture.sgml
@@ -1,11 +1,11 @@
<!-- doc/src/sgml/architecture.sgml -->
<chapter id="tutorial-architecture">
- <title>Architectural and implementational Cornerstones</title>
+ <title>Architecture and Implementation</title>
<para>
- Every DBMS implements basic strategies for a fast and
- robust system. This chapter provides an overview of what
+ Every DBMS implements basic strategies to ensure a fast
+ and robust system. This chapter provides an overview of the
techniques <productname>PostgreSQL</productname> uses to
achieve this.
</para>
@@ -14,26 +14,35 @@
<title>Collaboration of Processes, RAM, and Files</title>
<para>
In a client/server architecture
- clients do not have direct access to the database. Instead,
+ clients do not have direct access to stored data. Instead,
they send requests to the server and receive
- the requested information. In the case of
- <productname>PostgreSQL</productname>, at the server-side
- there is one process per client, the so-called
+ the requested data in response. In the case of
+ <productname>PostgreSQL</productname>, the server launches a
+ single process for each connected client, referred to as a
<glossterm linkend="glossary-backend">Backend process</glossterm>.
+ <!-- DGJ: this whole next paragraph bothers me but I cannot justify
+ simply removing it nor have a possibly better suggestion.
+ In particular I disagree with categorizing this is a
+ "close" and "tightly-coupled" relationship -->
It acts in close cooperation with the
<glossterm linkend="glossary-instance">instance</glossterm> which
is a group of tightly coupled server-side processes plus a
<glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>
- area.
+ area located in RAM.
+ Notably, PostgreSQL does not utilize application threading within its
+ implementation.
</para>
+ <!-- DGJ: I've gotten the impression firstterm
+ is overused, probably as a result of copy-paste -->
+
<para>
- At startup time, an <firstterm>instance</firstterm> is initiated by the
- <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
- The <firstterm>Postmaster</firstterm> process loads the
+ During <firstterm>instance</firstterm> startup time, the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>
+ process loads the
configuration files, allocates
<firstterm>Shared Memory</firstterm>,
- and starts a network of processes:
+ and starts supporting background processes:
<glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
<glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
<glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
@@ -62,9 +71,11 @@
</figure>
<para>
- Whenever a client application tries to connect to a
+ <!-- DGJ: This is detailed, but wrong. Either use less detail or correct detail.
+ See header of postmaster.c -->
+ When a client application tries to connect to a
<glossterm linkend="glossary-database">database</glossterm>,
- this request is handled in a first step by the
+ this request is handled initially by the
<firstterm>Postmaster</firstterm> process. It checks authorization,
starts a new <firstterm>Backend process</firstterm>,
and instructs the client application to connect to it. All
@@ -75,123 +86,64 @@
<para>
Client requests like <command>SELECT</command> or
<command>UPDATE</command> usually lead to the
- necessity to read or write some data. In a first attempt
- the client's <firstterm>Backend process</firstterm> tries
- to get the information out of <firstterm>Shared
- Memory</firstterm>. This <firstterm>Shared
- Memory</firstterm> is a mirror of parts of the
- <glossterm linkend="glossary-heap">heap</glossterm> and
- <glossterm linkend="glossary-index">index</glossterm> files.
- Because files are often larger than memory, it's likely that
- the desired information is not (completely) available
- in RAM. In this case the <firstterm>Backend process</firstterm>
- must transfer additional file pages to
- <firstterm>Shared Memory</firstterm>. Files are physically
- organized in pages. Every transfer between files and
- RAM is performed in units of complete pages; such transfers
- do not change the size or layout of pages.
- </para>
-
- <para>
- Reading file pages is much slower than reading
- RAM. This is the primary motivation for the usage of
- <firstterm>Shared Memory</firstterm>. As soon as one
- of the <firstterm>Backend processes</firstterm> has
- read pages into memory, those pages become available for all
- other <firstterm>Backend processes</firstterm> for direct
- access in RAM.
+ necessity to read or write some data.
+ Reads involve a page-level cache housed in Shared Memory
+ for the benefit of all processes in the instance.
+ <!-- DGJ: provide internals documentation link -->
+ Writes also involve this cache, in additional to a journal,
+ called a write-ahead-log or WAL, in PostgreSQL.
</para>
<para>
<firstterm>Shared Memory</firstterm> is limited in size.
- Sooner or later, it becomes necessary to overwrite old RAM
- pages. As long as the content of such pages hasn't
+ thus it becomes necessary to evict pages.
+ As long as the content of such pages hasn't
changed, this is not a problem. But in
<firstterm>Shared Memory</firstterm> also write
- actions take place
- — performed by any of the <firstterm>Backend
- processes</firstterm> (or an
- <firstterm>autovacuum</firstterm> process,
- or other processes). Such modified pages are called
- <firstterm>dirty pages</firstterm>.
- Before <firstterm>dirty pages</firstterm> can be overwritten,
- they must be written back to disk. This is a two-step process.
- </para>
-
- <para>
- First, whenever the content of a page changes, a
- <glossterm linkend="glossary-wal-record">WAL record</glossterm>
- is created out
- of the delta-information (difference between the old and
- the new content) and stored in another area of
- <firstterm>Shared Memory</firstterm>. These
- <firstterm>WAL records</firstterm> are read by the
- <firstterm>WAL Writer</firstterm> process,
- which runs in parallel to the <firstterm>Backend
- processes</firstterm> and other processes of
- the <firstterm>Instance</firstterm>. It writes
- the continuously arising <firstterm>WAL records</firstterm> to
- the end of the current
- <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
- Because this writing is sequential, it is much
- faster than the more or less random access
- to data files with <firstterm>heap</firstterm>
- and <firstterm>index</firstterm> information.
- As mentioned, this WAL-writing happens
- in an independent process. All
- <firstterm>WAL records</firstterm> created out of one
- <firstterm>dirty page</firstterm> must be transferred
- to disk before the <firstterm>dirty page</firstterm>
- itself can be transferred to disk.
- </para>
-
- <para>
- Second, the transfer of <firstterm>dirty buffers</firstterm>
- from <firstterm>Shared Memory</firstterm> to file must
- take place. This is the primary task of the
- <firstterm>Background Writer</firstterm> process. Because
- I/O activities can block other processes significantly,
- it starts periodically and acts only for a short period.
- Doing so, its expensive I/O activities are spread over
- time, avoiding debilitating I/O peaks. Also, the <firstterm>
- Checkpointer</firstterm> process transfers
- <firstterm>dirty buffers</firstterm> to file —
- see next paragraph.
- </para>
-
- <para>
- The <firstterm>Checkpointer</firstterm> creates
- <glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
- A <firstterm>Checkpoint</firstterm>
- is a point in time when all older <firstterm>dirty buffers</firstterm>,
- all older <firstterm>WAL records</firstterm>, and
- finally a special <firstterm>Checkpoint record</firstterm>
- have been written and flushed to disk.
- After a <firstterm>Checkpoint</firstterm>, we say
- data files and <firstterm>WAL files</firstterm> are in sync.
- In case of a recovery (after a crash of the instance)
- it can be relied upon that the information of all
- <firstterm>WAL records</firstterm> preceding
- the last <firstterm>Checkpoint record</firstterm>
- were already integrated into the data files. This
- speeds up the recovery.
- </para>
-
- <para>
- As a result of data changes,
- <firstterm>WAL records</firstterm> arise and get written
- to <firstterm>WAL files</firstterm>.
- Those <firstterm>WAL files</firstterm> — in combination with
- a previously taken <firstterm>Base Backup</firstterm> —
- are necessary to restore a database after a crash of the
- disk on which data files have been stored. Therefore it is
- recommended to transfer a copy of the
- <firstterm> WAL files</firstterm>
- to a second, independent place. The purpose of the
- <firstterm>WAL Archiver</firstterm> process is to perform
- this copy action.
+ actions take place.
+ Modified pages are called
+ <firstterm>dirty pages</firstterm> or
+ <firstterm>dirty buffers</firstterm> and
+ before <firstterm>dirty pages</firstterm> can be evicted
+ they must be written back to disk. This also happens regularly
+ by the <firstterm>Background Writer</firstterm>
+ process to ensure that the disk version of
+ the page is kept up-to-date. Writes are only performed against
+ the pages in Shared Memory.
+ </para>
+
+ <!-- DGJ: WAL should already be done well before page eviction/overwriting
+ comes into play. This is good material but seems misplaced. -->
+
+
+ <para>
+ The <firstterm>Background Writer</firstterm> process spreads
+ its expensive I/O activity over time while coordinating with
+ the overall system through the Checkpointer process - which
+ places checkpoint records into the WAL noting instances in
+ time when all dirty pages in Shared Memory corresponding to
+ previously written WAL have been written to file. At these
+ checkpoints previous WAL is no longer required so long as
+ the data files on hand are current. In other words, recovery
+ happens by replaying WAL from the last recorded checkpoint
+ on top of the current data files.
+ </para>
+
+ <para>
+ While the Checkpointer ensures that a running system can crash
+ and restart itself in a valid state the administration needs to
+ handle the case where the data files themselves become corrupted
+ (and possibly the locally written WAL, though that is less common.)
+ The options and details are covered extensively in the backup
+ and restore section of the documentation.
+ <!-- DGJ: link -->
+ For our purposes here note just that the
+ <firstterm>WAL Archiver</firstterm> process can be enabled and configured
+ to run a script on a filled WAL file - usually to copy it to a remote location.
</para>
+ <!-- DGJ: after the heavy focus on client processes and data these two
+ seem to come out of left field. Skipping over for now. -->
<para>
The <firstterm>Statistics Collector</firstterm> collects
counters about accesses to <firstterm>SQL objects</firstterm>
@@ -202,7 +154,7 @@
<para>
The <firstterm>Logger</firstterm> writes
text lines about serious and less serious events which can happen
- during database access, e.g. wrong password, no permission,
+ during database access, e.g., wrong password, no permission,
long-running queries, etc.
</para>
On 21.10.20 22:33, David G. Johnston wrote:
I've begun looking at this and have included quite a few html comments
within the patch. However, the two main items that I have found so
far are:One, I agree with Peter that this seems misplaced in Tutorial. I
would create a new Internals Chapter and place this material there, or
maybe consider a sub-chapter under "Overview of PostgreSQL
Internals". If this is deemed to be of a more primary importance than
the content in the Internals section I would recommend placing it in
Reference. I feel it does fit there and given the general importance
of that section readers will be inclined to click into it and skim
over its content.
I like the idea of dividing the material into two different chapters.
The existing part "I. Tutorial" contains the first concrete steps:
installation, creating database and database objects, using SQL basic
and advanced features. Its typical audience consists of persons doing
their first steps with PG. The new material is aimed at persons
interested in implementation aspects of PG. Therefore, the part "VII.
Internals" seems to be the natural place to integrate it, something like
"Architecture and Implementation Aspects" or "Architecture and
Implementation Cornerstones".
Creating such a chapter in "VII. Internals" will increase the existing
chapter numbers 50 - 71, which may lead to some confusion. On the other
hand the content can possibly be applied to all supported PG versions at
the same time, which will lead to a consistent behavior. Extending one
of the existing chapters won't work because all of them handle their own
topic, eg.: "50. Overview of PostgreSQL Internals" (misleading title?)
focuses on the handling of SQL statements from parsing to execution.
What are your thoughts?
--
J. Purtz
On Fri, Oct 23, 2020 at 6:58 AM Jürgen Purtz <juergen@purtz.de> wrote:
Creating such a chapter in "VII. Internals" will increase the existing
chapter numbers 50 - 71, which may lead to some confusion. On the other
hand the content can possibly be applied to all supported PG versions at
the same time, which will lead to a consistent behavior. Extending one of
the existing chapters won't work because all of them handle their own
topic, eg.: "50. Overview of PostgreSQL Internals" (misleading title?)
focuses on the handling of SQL statements from parsing to execution.What are your thoughts?
v14 has already added a new chapter, installation from binaries. It was
not back-patched. To my knowledge no one brought up these points - numbers
changing or back-patching the new material. I don't see that this
enhancement needs to be treated any differently.
David J.
On 21.10.20 22:33, David G. Johnston wrote:
I've begun looking at this and have included quite a few html comments
within the patch. However, the two main items that I have found so
far are:One, I agree with Peter that this seems misplaced in Tutorial. I
would create a new Internals Chapter and place this material there, or
maybe consider a sub-chapter under "Overview of PostgreSQL
Internals". If this is deemed to be of a more primary importance than
the content in the Internals section I would recommend placing it in
Reference. I feel it does fit there and given the general importance
of that section readers will be inclined to click into it and skim
over its content.Two, I find the amount of detail being provided here to be on the
too-much side. A bit more judicious use of links into the appropriate
detail chapters seems warranted.I took a pretty heavy hand to the original section though aside from
the scope comment it can probably be considered a bit weighted toward
style preferences. Though I did note/rewrite a couple of things that
seemed factually incorrect - and seemingly not done intentionally in
the interest of simplification. Specifically the client connection
process and, I think, the relationship between the checkpointer and
background writer.I do like the idea and the general flow of the material so far -
though I haven't really looked at the overall structure yet, just
started reading and editing from the top of the new file.I've attached the original 0007 patch and my diff against it applied
to HEAD.Took a quick peek at the image (at the end) and while I will need a
second pass over this section regardless I figured I'd provide this
subset of feedback now in order to move things along a bit.David J.
The attached patch is an intermediate, mostly formal step. It includes:
- Moving the chapter to "Part VII. Internals".
- Changing the title of the current chapter "Chapter 50. Overview of
PostgreSQL Internals" to "Overview of Query Handling" because the old
title is too generic. This chapter is focused on the handling of queries.
- Integration of David's smaller suggestions. For the more important
suggestions I need some days.
The patch is intended to give every interested person an overall
impression of the chapter within its new position. Because it has moved
from part 'Tutorial' to 'Internals' the text should be very accurate
concerning technical issues - like all the other chapters in this part.
A tutorial chapter has a more superficial nature.
--
J. Purtz
Attachments:
0008-architecture.patchtext/x-patch; charset=UTF-8; name=0008-architecture.patchDownload
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
index 2d4ab85d45..5c3245c0ec 100644
--- a/doc/src/sgml/advanced.sgml
+++ b/doc/src/sgml/advanced.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/advanced.sgml -->
<chapter id="tutorial-advanced">
- <title>Advanced Features</title>
+ <title>Advanced SQL Features</title>
<sect1 id="tutorial-advanced-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/arch-dev.sgml b/doc/src/sgml/arch-dev.sgml
index 7883c3cd82..9db0ae2c78 100644
--- a/doc/src/sgml/arch-dev.sgml
+++ b/doc/src/sgml/arch-dev.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/arch-dev.sgml -->
<chapter id="overview">
- <title>Overview of PostgreSQL Internals</title>
+ <title>Overview of Query Handling</title>
<note>
<title>Author</title>
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
new file mode 100644
index 0000000000..b6c0eb4a31
--- /dev/null
+++ b/doc/src/sgml/architecture.sgml
@@ -0,0 +1,1585 @@
+<!-- doc/src/sgml/architecture.sgml -->
+
+ <chapter id="tutorial-architecture">
+ <title>Overview of Architecture and Implementation</title>
+
+ <para>
+ Every DBMS implements basic strategies to ensure a fast
+ and robust system. This chapter provides an overview of the
+ techniques <productname>PostgreSQL</productname> uses to
+ achieve this.
+ </para>
+
+ <sect1 id="tutorial-ram-proc-file">
+ <title>Collaboration of Processes, RAM, and Files</title>
+ <para>
+ In a client/server architecture
+ clients do not have direct access to stored data. Instead,
+ they send requests to the server and receive
+ the requested data in response. In the case of
+ <productname>PostgreSQL</productname>, the server launches a
+ single process for each connected client, referred to as a
+ <glossterm linkend="glossary-backend">Backend process</glossterm>.
+
+
+ <!-- DGJ: this whole next paragraph bothers me but I cannot justify
+ simply removing it nor have a possibly better suggestion.
+ In particular I disagree with categorizing this is a
+ "close" and "tightly-coupled" relationship -->
+
+
+ It acts in close cooperation with the
+ <glossterm linkend="glossary-instance">instance</glossterm> which
+ is a group of tightly coupled server-side processes plus a
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>
+ area located in RAM.
+ Notably, PostgreSQL does not utilize application threading within its
+ implementation.
+ </para>
+
+
+ <!-- DGJ: I've gotten the impression firstterm
+ is overused, probably as a result of copy-paste -->
+
+
+ <para>
+ During <firstterm>instance</firstterm> startup time, the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>
+ process loads the
+ configuration files, allocates
+ <firstterm>Shared Memory</firstterm>,
+ and starts supporting background processes:
+ <glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
+ <glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
+ <glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
+ <glossterm linkend="glossary-wal-archiver">WAL Archiver</glossterm>,
+ <glossterm linkend="glossary-autovacuum">Autovacuum</glossterm>,
+ <glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
+ <glossterm linkend="glossary-logger">Logger</glossterm>, and more.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes
+ the main aspects of their collaboration.
+ </para>
+
+ <figure id="tutorial-ram-proc-file-figure">
+ <title>Architecture</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+
+
+ <!-- DGJ: This is detailed, but wrong. Either use less detail or correct detail.
+ See header of postmaster.c
+ -->
+
+
+ When a client application tries to connect to a
+ <glossterm linkend="glossary-database">database</glossterm>,
+ this request is handled initially by the
+ <firstterm>Postmaster</firstterm> process. It checks authorization,
+ starts a new <firstterm>Backend process</firstterm>,
+ and instructs the client application to connect to it. All
+ further client requests go to this process and are handled
+ by it.
+ </para>
+
+ <para>
+ Client requests like <command>SELECT</command> or
+ <command>UPDATE</command> usually lead to the
+ necessity to read or write some data. In a first attempt
+ the client's <firstterm>Backend process</firstterm> tries
+ to get the information out of <firstterm>Shared
+ Memory</firstterm>. This <firstterm>Shared
+ Memory</firstterm> is a mirror of parts of the
+ <glossterm linkend="glossary-heap">heap</glossterm> and
+ <glossterm linkend="glossary-index">index</glossterm> files.
+ Because files are often larger than memory, it's likely that
+ the desired information is not (completely) available
+ in RAM. In this case the <firstterm>Backend process</firstterm>
+ must transfer additional file pages to
+ <firstterm>Shared Memory</firstterm>. Files are physically
+ organized in pages. Every transfer between files and
+ RAM is performed in units of complete pages; such transfers
+ do not change the size or layout of pages.
+ </para>
+
+ <para>
+ Reading file pages is much slower than reading
+ RAM. This is the primary motivation for the usage of
+ <firstterm>Shared Memory</firstterm>. As soon as one
+ of the <firstterm>Backend processes</firstterm> has
+ read pages into memory, those pages become available for all
+ other <firstterm>Backend processes</firstterm> for direct
+ access in RAM.
+ </para>
+
+ <para>
+ <firstterm>Shared Memory</firstterm> is limited in size.
+ Sooner or later, it becomes necessary to overwrite old RAM
+ pages. As long as the content of such pages hasn't
+ changed, this is not a problem. But in
+ <firstterm>Shared Memory</firstterm> also write
+ actions take place
+ — performed by any of the <firstterm>Backend
+ processes</firstterm> (or an
+ <firstterm>autovacuum</firstterm> process,
+ or other processes). Such modified pages are called
+ <firstterm>dirty pages</firstterm>.
+ Before <firstterm>dirty pages</firstterm> can be overwritten,
+ they must be written back to disk. This is a two-step process.
+ </para>
+
+ <para>
+ First, whenever the content of a page changes, a
+ <glossterm linkend="glossary-wal-record">WAL record</glossterm>
+ is created out
+ of the delta-information (difference between the old and
+ the new content) and stored in another area of
+ <firstterm>Shared Memory</firstterm>. These
+ <firstterm>WAL records</firstterm> are read by the
+ <firstterm>WAL Writer</firstterm> process,
+ which runs in parallel to the <firstterm>Backend
+ processes</firstterm> and other processes of
+ the <firstterm>Instance</firstterm>. It writes
+ the continuously arising <firstterm>WAL records</firstterm> to
+ the end of the current
+ <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
+ Because this writing is sequential, it is much
+ faster than the more or less random access
+ to data files with <firstterm>heap</firstterm>
+ and <firstterm>index</firstterm> information.
+ As mentioned, this WAL-writing happens
+ in an independent process. All
+ <firstterm>WAL records</firstterm> created out of one
+ <firstterm>dirty page</firstterm> must be transferred
+ to disk before the <firstterm>dirty page</firstterm>
+ itself can be transferred to disk.
+ </para>
+
+ <para>
+ Second, the transfer of <firstterm>dirty buffers</firstterm>
+ from <firstterm>Shared Memory</firstterm> to file must
+ take place. This is the primary task of the
+ <firstterm>Background Writer</firstterm> process. Because
+ I/O activities can block other processes significantly,
+ it starts periodically and acts only for a short period.
+ Doing so, its expensive I/O activities are spread over
+ time, avoiding debilitating I/O peaks. Also, the <firstterm>
+ Checkpointer</firstterm> process transfers
+ <firstterm>dirty buffers</firstterm> to file —
+ see next paragraph.
+ </para>
+
+ <para>
+ The <firstterm>Checkpointer</firstterm> creates
+ <glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
+ A <firstterm>Checkpoint</firstterm>
+ is a point in time when all older <firstterm>dirty buffers</firstterm>,
+ all older <firstterm>WAL records</firstterm>, and
+ finally a special <firstterm>Checkpoint record</firstterm>
+ have been written and flushed to disk.
+ After a <firstterm>Checkpoint</firstterm>, we say
+ data files and <firstterm>WAL files</firstterm> are in sync.
+ In case of a recovery (after a crash of the instance)
+ it can be relied upon that the information of all
+ <firstterm>WAL records</firstterm> preceding
+ the last <firstterm>Checkpoint record</firstterm>
+ were already integrated into the data files. This
+ speeds up the recovery.
+ </para>
+
+ <para>
+ As a result of data changes,
+ <firstterm>WAL records</firstterm> arise and get written
+ to <firstterm>WAL files</firstterm>.
+ Those <firstterm>WAL files</firstterm> — in combination with
+ a previously taken <firstterm>Base Backup</firstterm> —
+ are necessary to restore a database after a crash of the
+ disk on which data files have been stored. Therefore it is
+ recommended to transfer a copy of the
+ <firstterm> WAL files</firstterm>
+ to a second, independent place. The purpose of the
+ <firstterm>WAL Archiver</firstterm> process is to perform
+ this copy action.
+ </para>
+
+ <para>
+ The <firstterm>Statistics Collector</firstterm> collects
+ counters about accesses to <firstterm>SQL objects</firstterm>
+ like tables, rows, indexes, pages, and more. It stores the
+ obtained information in system tables.
+ </para>
+
+ <para>
+ The <firstterm>Logger</firstterm> writes
+ text lines about serious and less serious events which can happen
+ during database access, e.g., wrong password, no permission,
+ long-running queries, etc.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-cluster-db-schema">
+ <title>The logical Perspective: Cluster, Database, Schema</title>
+
+ <para>
+ A <glossterm linkend="glossary-server">server</glossterm> contains one or more
+ <glossterm linkend="glossary-db-cluster">database clusters</glossterm>
+ (<glossterm linkend="glossary-db-cluster">clusters</glossterm>
+ for short). Each cluster contains three or more
+ <glossterm linkend="glossary-database">databases</glossterm>.
+ Each database can contain many
+ <glossterm linkend="glossary-schema">schemas</glossterm>.
+ A schema can contain
+ <glossterm linkend="glossary-table">tables</glossterm>,
+ <glossterm linkend="glossary-view">views</glossterm>, and a lot
+ of other objects. Each table or view belongs to a single schema
+ only; they cannot belong to another schema as well. The same is
+ true for the schema/database and database/cluster relation.
+ <xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
+ this hierarchy.
+ </para>
+
+ <figure id="tutorial-cluster-db-schema-figure">
+ <title>Cluster, Database, Schema</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ A cluster is the outer container for a
+ collection of databases. Clusters are created by the command
+ <xref linkend="app-initdb"/>.
+ </para>
+
+ <para>
+ <literal>template0</literal> is the very first
+ database of any cluster. Database <literal>template0</literal>
+ is created during the initialization phase of the cluster.
+ In a second step, database <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal>, and finally database
+ <literal>postgres</literal> is generated as a copy of
+ <literal>template1</literal>. Any
+ <glossterm linkend="app-createdb">new databases</glossterm>
+ of the cluster that a user might need,
+ such as <literal>my_db</literal>, will be copied from the
+ <literal>template1</literal> database. Due to the unique
+ role of <literal>template0</literal> as the pristine original
+ of all other databases, no client
+ can connect to it.
+ </para>
+
+ <para>
+ Every database must contain <glossterm linkend="glossary-schema">
+ at least one schema</glossterm> because
+ schemas contain the other
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>.
+ Schemas are namespaces for
+ their SQL objects and ensure — with one
+ exception — that within their scope, names are used only once across all
+ types of SQL objects. E.g., it is not possible
+ to have a table <literal>employee</literal> and a view
+ <literal>employee</literal> within the same
+ schema. But it is possible to have
+ two tables <literal>employee</literal> in different
+ schemas. In this case, the two tables
+ are separate objects and independent of each
+ other. The only exception to this cross-type uniqueness is that
+ <glossterm linkend="glossary-unique-constraint">unique constraints
+ </glossterm> and the according <firstterm>unique index</firstterm>
+ use the same name.
+ </para>
+
+ <para>
+ Some schemas are predefined. <literal>public</literal>
+ acts as the default schema and contains all
+ <firstterm>SQL objects</firstterm> which are created
+ within <literal>public</literal> or without using an explicit schema
+ name. <literal>public</literal> should not contain user-defined
+ SQL objects. Instead, it is recommended to
+ create a separate schema that
+ holds individual objects like application-specific tables or
+ views. <literal>pg_catalog</literal> is a schema for all tables
+ and views of the <glossterm linkend="glossary-system-catalog">
+ System Catalog</glossterm>.
+ <literal>information_schema</literal> is a schema for several
+ tables and views of the <firstterm>System Catalog</firstterm>
+ in a way that conforms to the SQL standard.
+ </para>
+
+ <para>
+ There are many different SQL object
+ types: <firstterm>database, schema, table, view, materialized
+ view, index, constraint, sequence, function, procedure,
+ trigger, role, data type, operator, tablespace, extension,
+ foreign data wrapper</firstterm>, and more. A few of them, the
+ <firstterm>Global SQL Objects</firstterm>,
+ are outside of the strict hierarchy:
+ All database names, all tablespace names, and all role names
+ are automatically known and available throughout the
+ cluster, independent from
+ the database or schema in which they where defined originally.
+ <xref linkend="tutorial-internal-objects-hierarchy-figure"/>
+ shows the relation between the object types.
+ </para>
+
+ <figure id="tutorial-internal-objects-hierarchy-figure">
+ <title>Hierarchy of Internal Objects</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="720px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect1>
+
+ <sect1 id="tutorial-directories">
+ <title>The physical Perspective: Directories and Files</title>
+
+ <para>
+ <productname>PostgreSQL</productname> organizes long-lasting
+ data as well as volatile state information about transactions
+ or replication actions in the file system. Every
+ <firstterm>Cluster</firstterm> has its root directory
+ somewhere in the file system. In many cases, the environment
+ variable <literal>PGDATA</literal> points to this directory.
+ The example shown in
+ <xref linkend="tutorial-directories-figure"/> uses
+ <literal>data</literal> as the name of this root directory.
+ </para>
+
+ <figure id="tutorial-directories-figure">
+ <title>Directory Structure</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ <literal>data</literal> contains many subdirectories and
+ some files, all of which are necessary to store long-lasting
+ as well as temporary data. The following paragraphs
+ describe the files and subdirectories in
+ <literal>data</literal>.
+ </para>
+
+ <para>
+ <literal>base</literal> is a subdirectory in which one
+ subdirectory per database exists. The names of those
+ subdirectories consist of numbers. These are the internal
+ Object Identifiers (OID), which are numbers to identify
+ the database definition in the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ </para>
+
+ <para>
+ Within the database-specific
+ subdirectories, there are many files: one or more for
+ every table and every index to store heap and index
+ data. Those files are accompanied by files for the
+ <link linkend="storage-fsm">Free Space Maps</link>
+ (extension <literal>_fsm</literal>) and
+ <link linkend="storage-vm">Visibility Maps</link>
+ (extension <literal>_vm</literal>), which contain optimization information.
+ </para>
+
+ <para>
+ Another subdirectory is <literal>global</literal>.
+ In analogy to the database-specific
+ subdirectories, there are files containing information about
+ <glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
+ One type of such Global SQL Objects are
+ <firstterm>tablespaces</firstterm>. In
+ <literal>global</literal> there is information about
+ the tablespaces, not the tablespaces themselves.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_wal</literal> contains the
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
+ They arise and grow parallel to data changes in the
+ cluster and remain alive as long as
+ they are required for recovery, archiving, or replication.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_xact</literal> contains
+ information about the status of each transaction:
+ in_progress, committed, aborted, or sub_committed.
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal>, there are symbolic links
+ that point to directories containing such<firstterm>
+ SQL objects</firstterm> that are created within
+ tablespaces.
+ </para>
+
+ <para>
+ In the root directory <literal>data</literal>
+ there are also some files. In many cases, the configuration
+ files of the cluster are stored here. As long as the
+ instance is up and running, the file
+ <literal>postmaster.pid</literal> exists here
+ and contains the process ID (pid) of the
+ Postmaster which has started the instance.
+ </para>
+
+ <para>
+ For more details about the physical implementation
+ of database objects, see <xref linkend="storage"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-mvcc">
+ <title>MVCC — Multiversion Concurrency Control</title>
+
+ <para>
+ In most cases, <productname>PostgreSQL</productname> based applications
+ support many clients at the same time. Therefore, it is necessary to
+ protect concurrently running requests from unwanted overwriting
+ of other's data as well as from reading inconsistent data. Imagine an
+ online shop offering the last copy of an article. Two clients have the
+ article displayed at their user interface. After a while, but at the same time,
+ both users decide to put it to their shopping cart or even to buy it.
+ Both have seen the article, but only one can be allowed to get it.
+ The database must bring the two requests in a row, permit the access
+ to one of them, block the other, and inform the blocked client
+ that the data was changed by a different process.
+ </para>
+
+ <para>
+ A first approach to implement protections against concurrent
+ accesses to the same data may be the locking of critical
+ rows. Two such techniques are:
+ <emphasis>Optimistic Concurrency Control</emphasis> (OCC)
+ and <emphasis>Two Phase Locking</emphasis> (2PL).
+ <productname>PostgreSQL</productname> implements a third, more
+ sophisticated technique: <firstterm>Multiversion Concurrency
+ Control</firstterm> (MVCC). The crucial advantage of MVCC
+ over other technologies gets evident in multiuser OLTP
+ environments with a massive number of concurrent write
+ actions. There, MVCC generally performs better than solutions
+ using locks. In a <productname>PostgreSQL</productname>
+ database reading never blocks writing and writing never
+ blocks reading, even in the strictest level of transaction
+ isolation.
+ </para>
+
+ <para>
+ Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
+ a new version of the row when a data-change takes place. To
+ distinguish between these two versions and to track the timeline
+ of the row, each of the versions contains, in addition to their user-defined
+ columns, two special system columns, which are not visible
+ for the usual <command>SELECT * FROM ...</command> command.
+ The column <literal>xmin</literal> contains the transaction ID (xid)
+ of the transaction, which created this version of the row. Accordingly,
+ <literal>xmax</literal> contains the xid of the transaction, which has
+ deleted this version, or zero, if the version is not
+ deleted. You can read both with the command
+ <command>SELECT xmin, xmax, * FROM ... </command>.
+ </para>
+
+ <para>
+ When we speak about transaction IDs, you need to know that xids are like
+ sequences. Every new transaction receives the next number as its ID.
+ Therefore, this flow of xids represents the flow of transaction
+ start events over time. But keep in mind that xids are independent of
+ any time measurement — in milliseconds or whatever. If you dive
+ deeper into <productname>PostgreSQL</productname>, you will recognize
+ parameters with names such as 'xxx_age'. Despite their names,
+ these '_age' parameters do not specify a period of time but represent
+ a certain number of transactions, e.g., 100 million.
+ </para>
+
+ <para>
+ The description in this chapter simplifies by omitting detail.
+ When many transactions are running simultaneously, things can
+ get complicated. Sometimes transactions get aborted via
+ <command>ROLLBACK</command> immediately or after a lot of other activities, sometimes
+ a single row is involved in more than one transaction, sometimes
+ a client crashes, sometimes the sequence of xids restarts
+ from zero, ... . Therefore, every version of a row contains more
+ system columns and flags, not only <literal>xmin</literal>
+ and <literal>xmax</literal>.
+ </para>
+
+ <para>
+ So, what's going on in detail when write accesses take place?
+ <xref linkend="tutorial-mvcc-figure"/> shows details concerning
+ <literal>xmin</literal>, <literal>xmax</literal>, and user data.
+ </para>
+
+ <figure id="tutorial-mvcc-figure">
+ <title>Multiversion Concurrency Control</title>
+ <mediaobject>
+ <imageobject role="html">
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ An <command>INSERT</command> command creates the first
+ version of a row. Besides its user data <literal>'x'</literal>,
+ this version contains the ID of the creating transaction
+ <literal>123</literal> in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ <literal>xmin</literal> indicates that the version
+ exists since transaction <literal>123</literal> and
+ <literal>xmax</literal> that it is currently not deleted.
+ </para>
+
+ <para>
+ Somewhat later, transaction <literal>135</literal>
+ executes an <command>UPDATE</command> of this row by
+ changing the user data from <literal>'x'</literal> to
+ <literal>'y'</literal>. According to the MVCC principles,
+ the data in the old version of the row does not change!
+ The value <literal>'x'</literal> remains as it was before.
+ Only <literal>xmax</literal> changes to <literal>135</literal>.
+ Now, this version is treated as valid exclusively for
+ transactions with xids from <literal>123</literal> to
+ <literal>134</literal>. As a substitute for the non-occurring
+ data change in the old version, the <command>UPDATE</command>
+ creates a new version of the row with its xid in
+ <literal>xmin</literal>, <literal>0</literal> in
+ <literal>xmax</literal>, and <literal>'y'</literal> in the
+ user data (plus all the other user data from the old version).
+ This version is now valid for all coming transactions.
+ </para>
+
+ <para>
+ All subsequent <command>UPDATE</command> commands behave
+ in the same way as the first one: they put their xid to
+ <literal>xmax</literal> of the current version, create
+ the next version with their xid in <literal>xmin</literal>,
+ <literal>0</literal> in <literal>xmax</literal>, and the
+ new user data.
+ </para>
+
+ <para>
+ Finally, a row may be deleted by a <command>DELETE</command>
+ command. Even in this case, all versions of the row remain as
+ before. Nothing is thrown away so far! Only <literal>xmax</literal>
+ of the last version changes to the xid of the <command>DELETE</command>
+ transaction, which indicates that it is only valid for
+ transactions with xids older than its own (from
+ <literal>142</literal> to <literal>820</literal> in this
+ example).
+ </para>
+
+ <para>
+ In summary, the MVCC technology creates more and more versions
+ of the same row in the table's heap file and leaves them there,
+ even after a <command>DELETE</command> command. Only the youngest
+ version is relevant for all future transactions. But the
+ system must also preserve some of the older ones for a
+ certain amount of time because the possibility exists that
+ they are or could become relevant for any pending
+ transactions. Over time, also the older ones get out of scope
+ for ALL transactions and therefore become unnecessary.
+ Nevertheless, they do exist physically on the disk and occupy
+ space.
+ </para>
+
+ <para>
+ Please keep in mind:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> and <literal>xmax</literal>
+ indicate the range from where to where
+ row versions are valid (visible) for transactions.
+ This range doesn't imply any direct temporal meaning;
+ the sequence of xids reflects only the sequence of
+ transaction begin events. As
+ xids grow, old row versions get out of scope over time.
+ If an old row version is no longer valid for ALL existing
+ transactions, it's called <firstterm>dead</firstterm>. The
+ space occupied by all dead row versions is called
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Internally, an <command>UPDATE</command> command acts in the
+ same way as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Nothing gets wiped away — with the consequence that the database
+ occupies more and more disk space. It is obvious that
+ this behavior has to be corrected in some
+ way. The next chapter explains how <firstterm>autovacuum</firstterm>
+ fulfills this task.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ </sect1>
+
+ <sect1 id="tutorial-vacuum">
+ <title>Vacuum</title>
+
+ <para>
+ As we have seen in the previous chapter, the database
+ tends to occupy more and more disk space, the
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ This chapter explains how the SQL command
+ <command>VACUUM</command> and the automatically running
+ <firstterm>autovacuum</firstterm> processes clean up
+ by eliminating bloat.
+ </para>
+
+ <note>
+ <para>
+ <firstterm>Autovacuum</firstterm> runs automatically by
+ default. Its default parameters as well as such for
+ <command>VACUUM</command> fit well for most standard
+ situations. Therefore a novice database manager can
+ easily skip the rest of this chapter which explains
+ a lot of details.
+ </para>
+ </note>
+
+ <para>
+ Client processes can issue the SQL command <command>VACUUM</command> at arbitrary
+ points in time. DBAs do this when they recognize special situations,
+ or they start it in batch jobs which run periodically.
+ <firstterm>Autovacuum</firstterm> processes run as part of the
+ <link linkend="glossary-instance">instance</link> at the server.
+ There is a constantly running <firstterm>autovacuum</firstterm> daemon.
+ It permanently controls the state of all databases based on values that
+ are collected by the
+ <link linkend="glossary-stats-collector">Statistics Collector</link>
+ and starts <firstterm>autovacuum</firstterm> processes whenever it detects
+ certain situations. Thus, it's a dynamic behavior of
+ <productname>PostgreSQL</productname> with the intention to tidy
+ up — whenever it is appropriate.
+ </para>
+
+ <para>
+ <command>VACUUM</command>, as well as
+ <firstterm>autovacuum</firstterm>, don't just eliminate bloat.
+ They perform additional tasks for minimizing future
+ I/O activities of themselves as well as of other processes.
+ This extra work can be done in a very efficient way
+ since in most cases the expensive physical access to pages
+ has taken place anyway to eliminate bloat.
+ The additional operations are:
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <firstterm>Freeze</firstterm>: Mark the youngest row version
+ as frozen. This means that the version
+ is always treated as valid (visible) independent from
+ the <firstterm>wraparound problem</firstterm> (see below).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <firstterm>Visibility Map</firstterm> and
+ <firstterm>Free Space Map</firstterm>: Log information about
+ the state of the handled pages in two additional files, the
+ Visibility Map and the Free Space Map.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <emphasis>Statistics</emphasis>: Collect statistics about the
+ number of rows per table, the distribution of values, and so on,
+ as the basis for decisions of the query planner.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ The eagerness — you can call it 'aggression' — of the
+ operations <emphasis>eliminating bloat</emphasis> and
+ <emphasis>freeze</emphasis> is controlled by configuration
+ parameters, runtime flags, and in extreme situations by
+ the processes themselves. Because vacuum operations typically are I/O
+ intensive, which can hinder other activities, <firstterm>autovacuum</firstterm>
+ avoids performing many vacuum operations in bulk. Instead,
+ it carries out many small actions with time gaps in between.
+ The SQL command <command>VACUUM</command> runs immediately
+ and without any time gaps.
+ </para>
+
+ <bridgehead renderas="sect2">Eliminate Bloat</bridgehead>
+
+ <para>
+ To determine which of the row versions are superfluous, the
+ elimination operation must evaluate <literal>xmax</literal>
+ against several criteria which all must apply:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be different from zero because a
+ value of zero indicates that the row version is still valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must contain an xid which is older
+ than the oldest xid of all
+ currently running transactions (min(pg_stat_activity.backend_xmin)).
+ This criterion guarantees that no existing or upcoming transaction
+ will have read or write access to this row version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of <literal>xmax</literal> must be committed. If it was rollback-ed,
+ this row version is treated as valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there is the situation that the row version is part of
+ multiple transactions, special care and some more actions
+ must be taken, see: <xref linkend="vacuum-for-multixact-wraparound"/>.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ After the vacuum operation detects a superfluous row version, it
+ marks its space as free for future use of writing
+ actions. Only in rare situations (or in the case of <command>VACUUM FULL</command>),
+ is this space released to the operating system. In most cases,
+ it remains occupied by <productname>PostgreSQL</productname>
+ and will be used by future <command>INSERT</command> or
+ <command>UPDATE</command> commands concerning this row or a
+ completely different one.
+ </para>
+
+ <para>
+ Which actions start the elimination of bloat?
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ in its default format, i.e., without any option. To boost performance,
+ in this and the next case <command>VACUUM</command> does not
+ read and act on all pages of the heap.
+ The Visibility Map, which is very compact and therefore has a small
+ size, contains information about pages, where bloat-candidates might
+ be found. Only such pages are processed.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FREEZE</command>. (In this case,
+ it undertakes much more actions, see
+ <link linkend="tutorial-freeze">Freeze Row Versions</link>.)
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FULL</command>.
+ Also, in this mode, the bloat disappears, but the strategy used
+ is very different: In this case, the complete table is copied
+ to a different file skipping all outdated row versions. This
+ leads to a significant reduction of used disk space because
+ the new file contains only the actual data. The old file
+ is deleted.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When an <firstterm>autovacuum</firstterm> process acts. For optimization
+ purposes, it considers the Visibility Map in the same way as
+ <command>VACUUM</command>. Additionally, it ignores tables with few modifications;
+ see <xref linkend="guc-autovacuum-vacuum-threshold"/>,
+ which defaults to 50 rows and
+ <xref linkend="guc-autovacuum-vacuum-scale-factor"/>,
+ which defaults to 20%.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </para>
+
+ <para>
+ This logic only applies to row versions of the heap. Index entries
+ don't use <literal>xmin/xmax</literal>. Nevertheless, such index
+ entries, which would lead to outdated row versions, are released
+ accordingly. (??? more explanations ???)
+ </para>
+
+ <para>
+ The above descriptions omit the fact that xids on a real computer
+ have a limited size. They count up in the same way as sequences, and after
+ a certain number of new transactions they are forced to restart
+ from the beginning, which is called <firstterm>wraparound</firstterm>.
+ Therefore the terms 'old transaction' / 'young transaction' does
+ not always correlate with low / high values of xids. Near to the
+ wraparound point, there are cases where <literal>xmin</literal> has
+ a higher value than <literal>xmax</literal>, although their meaning
+ is said to be older than <literal>xmax</literal>.
+ </para>
+
+ <figure id="tutorial-wraparound-figure">
+ <title>Cyclic usage of XIDs</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2" id="tutorial-freeze">Freeze Row Versions</bridgehead>
+
+ <para>
+ The use of a limited range of IDs for transactions leads
+ to the necessity to restart the sequence sooner or later.
+ This does not only have the rare consequence previously
+ described that sometimes <literal>xmin</literal> is
+ higher than <literal>xmax</literal>. The far
+ more critical problem is that whenever the system has
+ to evaluate a WHERE condition, it must decide which row
+ version is valid (visible) from the perspective of the
+ transaction of this query. If a wraparound couldn't happen,
+ this decision would be relatively easy: the xid
+ must be between <literal>xmin</literal> and <literal>xmax</literal>,
+ and the corresponding transactions of <literal>xmin</literal>
+ and <literal>xmax</literal> must be committed. However,
+ <productname>PostgreSQL</productname> has to consider the
+ possibility of wraparounds.
+ Therefore the decision becomes more complex. The general
+ idea of the solution is to use the 'between
+ <literal>xmin</literal> and <literal>xmax</literal>'
+ comparison only during the youngest period of the row
+ versions lifetime and afterward replace it with a
+ 'valid forever' flag in its header.
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ As a first step, <productname>PostgreSQL</productname>
+ divides the complete range of
+ possible xids into two halves with the two split-points
+ 'txid_current' and 'txid_current + 2^31'. The half behind
+ 'txid_current' is considered to represent xids of the
+ 'past' and the half ahead of 'txid_current' those of the
+ 'future'. Those of the 'past' are valid (visible) and those
+ of the 'future' not.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ With each newly created transaction the two split-points
+ move forward. When 'txid_current + 2^31' would reach a
+ row version with <literal>xmin</literal> equal to that value, it would
+ immediately jump from 'past' to 'future' and would be
+ no longer visible!
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ To avoid this unacceptable extinction of data, the vacuum
+ operation <firstterm>freeze</firstterm> clears the situation
+ long before the split-point is reached. It sets a flag
+ in the header of the row version, which completely eliminates
+ the future use of <literal>xmin/xmax</literal> and indicates
+ that the version is valid not only in the 'past'-half
+ but also in the 'future'-half as well as in all coming
+ <glossterm linkend="glossary-xid">epochs</glossterm>.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Which row versions can be frozen by the vacuum operation?
+ Again, several criteria must be checked, and all must be met.
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be zero because only
+ non-deleted rows can be visible 'forever'.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> must be older than all currently
+ existing transactions. This guarantees that no existing
+ transaction can modify or delete the version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of <literal>xmin</literal> must be committed.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ At what point in time does the freeze operation take place?
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with its <command>FREEZE</command> option. In this case, all
+ pages are processed that are marked in the Visibility Map
+ to potentially have unfrozen rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command> without
+ any options but finds that there are xids older than
+ <xref linkend="guc-vacuum-freeze-table-age"/>
+ (default: 150 million) minus
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million).
+ As before, all pages are processed that are
+ marked in the Visibility Map to potentially have unfrozen
+ rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When an <firstterm>autovacuum</firstterm> process runs. Such
+ a process acts in one of two modes:
+ </simpara>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ In the <emphasis>normal mode</emphasis>, it skips
+ pages with row versions that are younger than
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million) and works only on pages where
+ all xids are older. The skipping of young xids prevents
+ work on such pages, which are likely to be changed
+ by one of the future SQL commands.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ The process switches
+ to an <emphasis>aggressive mode</emphasis> if it recognizes
+ that for the processed table their oldest xid exceeds
+ <xref linkend="guc-autovacuum-freeze-max-age"/>
+ (default: 200 million). The value of the oldest unfrozen
+ xid is stored per table in <literal>pg_class.relfrozenxid</literal>.
+ In this <emphasis>aggressive mode</emphasis> <firstterm>autovacuum</firstterm>
+ processes all such pages of the selected table that are marked
+ in the Visibility Map to potentially have bloat or unfrozen rows.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In the first two cases and with <firstterm>autovacuum</firstterm> in
+ <emphasis>aggressive mode</emphasis>, the system knows
+ to which value the oldest unfrozen xid has moved forward and
+ logs the value in <literal>pg_class.relfrozenxid</literal>.
+ The distance between this value and the 'txid_current' split
+ point becomes smaller, and the distance to 'txid_current + 2^31'
+ becomes larger than before.
+ </para>
+
+ <figure id="tutorial-freeze-figure">
+ <title>Freeze</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2">Protection against Wraparound Failure</bridgehead>
+
+ <para>
+ The <firstterm>autovacuum</firstterm> processes are initiated by the
+ constantly running <firstterm>autovacuum</firstterm> daemon.
+ If the daemon detects that for a table
+ <firstterm>autovacuum_freeze_max_age</firstterm> is exceeded, it
+ starts an <firstterm>autovacuum</firstterm> process in
+ <emphasis>aggressive mode</emphasis>
+ (see above) — even if <firstterm>autovacuum</firstterm> is disabled.
+ </para>
+
+ <bridgehead renderas="sect2">Visibility Map and Free Space Map</bridgehead>
+
+ <para>
+ The <link linkend="glossary-vm">Visibility Map</link>
+ (VM) contains two flags — stored as
+ two bits — for each page of the heap. If the first bit
+ is set, that indicates that the associated page does not
+ contain any bloat. If the second one is set, that indicates
+ that the page contains only frozen rows.
+ </para>
+
+ <para>
+ Please consider two details. First, in most cases a page
+ contains many rows, some of them in many versions.
+ However, the flags are associated with the page,
+ not with a row or a row version. The flags are set
+ only under the condition that they are valid for ALL
+ row versions of the page. Second, since there
+ are only two bits per page, the VM is considerably
+ smaller than the heap. Therefore it is buffered
+ in RAM in almost all cases.
+ </para>
+
+ <para>
+ The setting of the flags is silently done by <command>VACUUM</command>
+ and <firstterm>autovacuum</firstterm> during their bloat and freeze operations.
+ This is done to speed up future vacuum actions,
+ regular accesses to heap pages, and some accesses to
+ the index. Every data-modifying operation on any row
+ version of the page clears the flags.
+ </para>
+
+ <para>
+ The <link linkend="glossary-fsm">Free Space Map</link>
+ (FSM) tracks the amount of free space per page. It is
+ organized as a highly condensed b-tree of (rounded) sizes.
+ As long as <command>VACUUM</command> or
+ <firstterm>autovacuum</firstterm> change the free space
+ on any processed page, they log the new values in
+ the FSM in the same way as all other writing
+ processes.
+ </para>
+
+ <bridgehead renderas="sect2">Statistics</bridgehead>
+
+ <para>
+ Statistic information helps the <link
+ linkend="planner-stats">Query Planner</link> to make optimal
+ decisions for the generation of execution plans. This
+ information can be gathered with the SQL commands
+ <command>ANALYZE</command> or <command>VACUUM ANALYZE</command>.
+ But <firstterm>autovacuum</firstterm> processes also gather
+ such information. Depending on the percentage of changed rows
+ per table <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ the <firstterm>autovacuum</firstterm> daemon starts
+ <firstterm>autovacuum</firstterm> processes to collect
+ statistics per table. This dynamic invocation of analyze
+ operations allows <productname>PostgreSQL</productname> to
+ adopt queries to changing circumstances.
+ </para>
+
+ <para>
+ For more details about vacuum operations, especially for its
+ numerous parameters, see <xref linkend="routine-vacuuming"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-transactions-mvcc">
+ <title>Transactions</title>
+ <para>
+ <link linkend="tutorial-transactions">Transactions</link>
+ are a fundamental concept of relational database systems.
+ Their essential point is that they bundle multiple
+ read- or write-operations into a single all-or-nothing
+ operation. Furthermore, they separate and protect concurrent
+ actions of different connections from each other. Thereby
+ they implement the ACID paradigm.
+ </para>
+
+ <para>
+ In <productname>PostgreSQL</productname> there are two ways
+ to establish a transaction. The explicit way uses the keywords
+ <link linkend="sql-begin">BEGIN</link> and
+ <link linkend="sql-commit">COMMIT</link> (respectively
+ <link linkend="sql-rollback">ROLLBACK</link>) before
+ and after a sequence of SQL statements. The keywords mark
+ the transaction's start- and end-point. On the other hand, you
+ can omit the keywords. This is the implicit way, where
+ every single SQL command automatically establishes a new
+ transaction.
+
+ <programlisting>
+BEGIN; -- establish a new transaction
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+COMMIT; -- finish the transaction
+
+-- this UPDATE runs as the only command of a separate transaction ...
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+
+-- ... and this one runs in another transaction
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+ </programlisting>
+ </para>
+
+ <para>
+ As mentioned, the primary property of a transaction is its
+ atomicity: either all or none of its operations succeed,
+ regardless of the fact that it may consist of a lot of
+ different write-operations, and each such operation may
+ affect thousands or millions of rows. As soon as one of the
+ operations fails, all previous operations fail also, which
+ means that all modified rows retain their values as of the
+ beginning of the transaction.
+ </para>
+
+ <para>
+ The atomicity also affects the visibility of changes. No
+ connections running simultaneously to a data modifying
+ transaction will ever see any change before the
+ transaction successfully executes a <command>COMMIT</command>
+ — even in the lowest
+ <link linkend="transaction-iso">isolation level</link>
+ of transactions. <productname>PostgreSQL</productname>
+ does never show uncommitted changes to other connections.
+ </para>
+
+ <para>
+ The situation regarding visibility is somewhat different
+ from the point of view of the modifying transaction.
+ <command>SELECT</command> commands issued inside a
+ transaction delivers all changes done so far by this
+ transaction.
+ </para>
+
+ <bridgehead renderas="sect2">How does it work?</bridgehead>
+
+ <para>
+ Every <command>INSERT</command>, <command>UPDATE</command>,
+ and <command>DELETE</command> command creates new row
+ versions — according to the MVCC rules. This
+ creates the risk that other transactions may see the
+ new row versions, and after a while and some more
+ activities of the modifying transaction they may see the
+ next row versions. Results would be a kind of 'moving
+ target' in absolute contrast to the all-or-nothing
+ principle.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> overcomes this
+ problem by showing only such row versions to other
+ transactions whose originating transaction is
+ successfully committed. It skips all row versions of
+ uncommitted transactions. And
+ <productname>PostgreSQL</productname> solves one more
+ problem. Even the single <command>COMMIT</command>
+ command needs a short time interval for its execution.
+ Therefore its critical 'dead-or-survival' phase
+ runs in a priviledged mode where it cannot be
+ interrupted by other processes.
+ </para>
+
+ <bridgehead renderas="sect2">What are the benefits?</bridgehead>
+
+ <para>
+ Transactions relieve applications from many standard
+ actions that must be implemented for nearly every use case.
+ </para>
+
+ <para>
+ Business logic often contains strong, but for a computer,
+ relative abstract requirements. The above example shows
+ the transfers of some money from one account to another.
+ It is obvious
+ that the decrease of the one and the increase of the
+ other must be indivisible. Nevertheless, there is no particular
+ need for an application to do something to ensure the
+ <glossterm linkend="glossary-atomicity">atomicity</glossterm>
+ of this behavior. It's enough to surround them with
+ <command>BEGIN</command> and <command>COMMIT</command>.
+ </para>
+
+ <para>
+ Applications often demand the feature of 'undoing'
+ previously taken actions under some application-specific
+ conditions. In such cases, the application simply issues a
+ <command>ROLLBACK</command> command instead of a
+ <command>COMMIT</command>. The <command>ROLLBACK</command>
+ cancels the transaction, and all changes made so far remain
+ invisible forever; it's like they never happened. There
+ is no need for the application to log its activities and
+ undo every step of the transaction separately.
+ </para>
+
+ <para>
+ Transactions ensure that the
+ <glossterm linkend="glossary-consistency">consistency</glossterm>
+ of the complete database always keeps valid. Declarative
+ rules like
+ <link linkend="ddl-constraints-primary-keys">primary</link>- or
+ <link linkend="ddl-constraints-fk">foreign keys</link>,
+ <link linkend="ddl-constraints-check-constraints">checks</link>,
+ other constraints, or
+ <link linkend="trigger-definition">triggers</link>
+ are part of the all-or-nothing nature of transactions.
+ </para>
+
+ <para>
+ Also, all self-evident — but possibly not obvious
+ — low-level demands on the database system are
+ ensured; e.g. index entries for rows must become
+ visible at the same moment as the rows themselves.
+ </para>
+
+ <para>
+ There is an additional feature which defines transactions'
+ <link linkend="transaction-iso">isolation level</link>
+ to each other in a declarative way. It automatically
+ prevents applications from some strange situations.
+ </para>
+
+ <para>
+ Lastly, it is worth to notice that changes done by a
+ committed transaction will survive all future application,
+ instance, or hardware failures. The next chapter
+ explains this
+ <glossterm linkend="glossary-durability">durability</glossterm>.
+ </para>
+ </sect1>
+
+ <sect1 id="tutorial-reliability">
+ <title>Reliability</title>
+
+ <para>
+ Nothing is perfect and failures inevitably happen.
+ However, the most common types of failure are
+ well known and <productname>PostgreSQL</productname>
+ implements strategies to overcome them.
+ Such strategies use parts of the previously presented
+ techniques MVCC and transaction-rollback, plus additional
+ features.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the client side</bridgehead>
+ <para>
+ A <glossterm linkend="glossary-client">client</glossterm>
+ can fail in different ways. Its hardware can get damaged,
+ the power supply can fail, the network connection to the
+ server can break, or the client application may run into
+ a severe software error like a null pointer exception.
+ Because <productname>PostgreSQL</productname> uses a
+ client/server architecture, no direct problem for the
+ database will occur. In all of this cases, the
+ <glossterm linkend="glossary-backend">Backend process</glossterm>,
+ which is the client's counterpart at the server-side,
+ may recognize that the network connection is no longer
+ working, or it may run into a timeout after a while. It
+ terminates, and there is no harm to the database. As
+ usual, uncommitted data changes initiated by this client
+ are not visible to any other client.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the server-side</bridgehead>
+
+ <bridgehead renderas="sect3">Instance failure</bridgehead>
+ <para>
+ The instance may suddenly fail because of <emphasis>power off</emphasis>
+ or other problems. This will affect all running processes, the RAM,
+ and possibly the consistency of disk files.
+ </para>
+ <para>
+ After a restart, <productname>PostgreSQL</productname>
+ automatically recognizes that the last shutdown of the
+ instance did not happen as expected: files might not be
+ closed properly and the <literal>postmaster.pid</literal>
+ file exists. <productname>PostgreSQL</productname>
+ tries to clean up the situation. This is possible because
+ all changes in the database are stored twice. First,
+ the WAL files contain them as a chronology of
+ <glossterm linkend="glossary-wal-record">WAL records</glossterm>,
+ which include the new data values and information about commit
+ actions. The WAL records are written first. Second,
+ the data itself shall exist in the heap and index files.
+ In opposite to the WAL records, this part may or may
+ not have been transferred entirely from Shared Memory
+ to the files.
+ </para>
+ <para>
+ The automatic recovery searches within the WAL files for
+ the latest
+ <glossterm linkend="glossary-checkpoint">checkpoint</glossterm>.
+ This checkpoint signals that the database files are in
+ a consistent state, especially that all WAL records up to
+ this point were successfully stored in heap and index. Starting
+ here, the recovery process copies the following WAL records
+ to heap and index. As a result, the files contain all
+ changes and reach a consistent state. Changes of committed
+ transactions are visible; those of uncommited transactions
+ are also in the files, but - as usual - they are never seen
+ by any of the following transactions because uncommited
+ changes are never shown. Such recovery actions run
+ completely automatically, it is not necessary that you
+ configure or start anything by yourself.
+ </para>
+
+ <bridgehead renderas="sect3">Disk crash</bridgehead>
+ <para>
+ If a disk crashes, the course of action described previously
+ cannot work. It is likely that the WAL files and/or the
+ data and index files are no longer available. You need
+ to take special actions to overcome such situations.
+ </para>
+ <para>
+ You obviously need a backup. How to take such a backup
+ and use it as a starting point for a recovery of the
+ cluster is explained in more detail in the next
+ <link linkend="tutorial-backup">chapter</link>.
+ </para>
+
+ <bridgehead renderas="sect3">Disk full</bridgehead>
+ <para>
+ It is conceivable that over time the disk gets full,
+ and there is no room for additional data. In this case,
+ <productname>PostgreSQL</productname> stops accepting
+ commands which change the data or even terminates
+ completely. No data loss or data corruption will
+ occur.
+ </para>
+ <para>
+ To come out of such a situation, you should remove
+ unused files from this disk. But you should never
+ delete files from the
+ <glossterm linkend="glossary-data-directory">data directory</glossterm>.
+ Nearly all of them are necessary for the consistency
+ of the database.
+ </para>
+
+ <bridgehead renderas="sect2">High availability</bridgehead>
+ <para>
+ Database servers can work together to allow a second
+ server to quickly take over the workload if the
+ primary server fails for whatever reason
+ (<link linkend="high-availability">high availability</link>),
+ or to allow several computers to serve the same data
+ for the purpose of load balancing.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-backup">
+ <title>Backup</title>
+
+ <para>
+ Taking backups is a basic task of database maintenance.
+ <productname>PostgreSQL</productname> supports
+ three different strategies; each has its own
+ strengths and weaknesses.
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ File system level backup
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Logical backup via <command>pg_dump</command>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Continuous archiving based on <command>pg_basebackup</command>
+ and WAL files
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <bridgehead renderas="sect2">File system level backup</bridgehead>
+ <para>
+ You can use any appropriate OS tool to create a
+ <link linkend="backup-file">copy</link>
+ of the cluster's directory structure and files. In
+ case of severe problems such a copy can serve as
+ the source of recovery. But in order to get a
+ <emphasis>USABLE</emphasis> backup by this method,
+ the database server <emphasis>MUST</emphasis> be
+ shut down during the complete runtime of the copy
+ command!
+ </para>
+ <para>
+ The obvious disadvantage of this method is that there
+ is a downtime where no user interaction is possible.
+ The other two strategies run during regular operating
+ times.
+ </para>
+
+ <bridgehead renderas="sect2">Logical backup via pg_dump</bridgehead>
+ <para>
+ The tool <command>pg_dump</command> is able to take a
+ <link linkend="backup-dump">copy</link>
+ of the complete cluster or certain parts of it. It stores
+ the copy in the form of SQL <command>CREATE</command> and
+ <command>INSERT</command> commands. It runs in
+ parallel to other processes in its own transaction.
+ </para>
+ <para>
+ The output of <command>pg_dump</command> may be used as
+ input of <command>psql</command> to restore the data
+ (or to copy it to another database).
+ </para>
+ <para>
+ The main advantage over the other two methods is that it
+ can pick parts of the cluster, e.g., a single table or one
+ database. The other two methods work only at the level of
+ the complete cluster.
+ </para>
+
+ <bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
+ <para>
+ <link linkend="continuous-archiving">This method</link>
+ is the most sophisticated and complex one. It
+ consists of two phases.
+ </para>
+ <para>
+ First, you need to create a so called
+ <firstterm>basebackup</firstterm> with the tool
+ <command>pg_basebackup</command>. The result is a
+ directory structure plus files which contains a
+ consistent copy of the original cluster.
+ <command>pg_basebackup</command> runs in
+ parallel to other processes in its own transaction.
+ </para>
+ <para>
+ The second step is recommended but not necessary. All
+ changes to the data are stored in WAL files. If you
+ continuously save such WAL files, you have the history
+ of the cluster. This history can be applied to a
+ basebackup in order to recreate
+ any state of the cluster between the time of
+ <command>pg_basebackup</command>'s start time and
+ any later point in time. This technique
+ is called 'Point-in-Time Recovery (PITR)'.
+ </para>
+ <para>
+ If configured, the
+ <glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
+ will automatically copy every single WAL file to a save location.
+ <link linkend="backup-archiving-wal">Its configuration</link>
+ consists mainly of a string, which contains a copy command
+ in the operating system's syntax. In order to protect your
+ data against a disk crash, the destination location
+ of a basebackup as well as of the
+ <firstterm>archived WAL files</firstterm> should be on a
+ disk which is different from the data disk.
+ </para>
+ <para>
+ If it gets necessary to restore the cluster, you have to
+ copy the basebackup and the
+ archived WAL files to
+ their original directories. The configuration of this
+ <link linkend="backup-pitr-recovery">recovery procedure</link>
+ contains a string with the reverse copy command: from
+ archive location to database location.
+ </para>
+
+ </sect1>
+
+<!-- ToDo: replication, index-types, extension mechanism, ...
+ <sect1 id="tutorial-replication">
+ <title>Replication</title>
+
+ <para>
+...
+ </para>
+
+ </sect1>
+-->
+
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 38e8aa0bbf..7490d3c9c2 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -80,6 +80,7 @@
%allfiles;
<!-- developer's guide -->
+<!ENTITY architecture SYSTEM "architecture.sgml">
<!ENTITY arch-dev SYSTEM "arch-dev.sgml">
<!ENTITY bki SYSTEM "bki.sgml">
<!ENTITY catalogs SYSTEM "catalogs.sgml">
diff --git a/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
new file mode 100644
index 0000000000..7e13753d48
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
@@ -0,0 +1,160 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="685" viewBox="0 0 900 685">
+ <title>
+ Server (Hardware, Container, or VM)
+ </title>
+ <style>
+ .text_normal,.text_small{font-style:normal;font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_small{font-size:12px}.text_normal{font-size:16px}
+ </style>
+ <defs>
+ <symbol id="rectangle_special_0">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="rectangle_special_1">
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="125">
+ 'my_schema' (optional)
+ </text>
+ <text class="text_small" x="20" y="145">
+ tables, views, ...
+ </text>
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="190">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M450 10v230H0V0h440v10h10L440 0"/>
+ </symbol>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="270" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Server (Hardware, Container, or VM)
+ </text>
+ <path stroke="blue" stroke-width="2" fill="none" d="M20 110h790v555H20z"/>
+ <text class="text_normal" x="180" y="25" transform="translate(20 110)">
+ cluster 'data' (default, managed by one instance)
+ </text>
+ <path d="M50 110V80h790v555h-30" stroke="blue" stroke-width="2" fill="none"/>
+ <text class="text_normal" x="190" y="-10" transform="translate(45 110)">
+ cluster 'cluster_2' (optional, managed by a different instance)
+ </text>
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template0'
+ </text>
+ </g>
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template1'
+ </text>
+ </g>
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'my_db' (optional)
+ </text>
+ </g>
+ <g transform="translate(320 330)">
+ <rect width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4"/>
+ <text class="text_normal" x="15" y="27">
+ Global SQL objects
+ </text>
+ <path d="M0 5l-65-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M80 0v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M180 40h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M0 40l-45 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ </g>
+ <g transform="translate(335 405)">
+ <use xlink:href="#note"/>
+ <text class="text_small" x="10" y="20">
+ 1)
+ </text>
+ <text class="text_small" x="30" y="20">
+ By default, you work in the cluster 'data', database 'postgres',
+ </text>
+ <text class="text_small" x="30" y="35">
+ schema 'public'.
+ </text>
+ <text class="text_small" x="10" y="55">
+ 2)
+ </text>
+ <text class="text_small" x="30" y="55">
+ More system schemas: pg_catalog, information_schema,
+ </text>
+ <text class="text_small" x="30" y="70">
+ pg_temp, pg_toast.
+ </text>
+ <text class="text_small" x="10" y="90">
+ 3)
+ </text>
+ <text class="text_small" x="30" y="90">
+ Global SQL objects: Some SQL objects are automatically active
+ </text>
+ <text class="text_small" x="30" y="105">
+ and known database- or even cluster-wide.
+ </text>
+ <text class="text_small" x="10" y="125">
+ 4)
+ </text>
+ <text class="text_small" x="30" y="125">
+ The command 'initdb' creates a new cluster with the three
+ </text>
+ <text class="text_small" x="30" y="140">
+ databases 'template0', 'template1', and 'postgres'. The command
+ </text>
+ <text class="text_small" x="30" y="155">
+ 'createdb' creates a new database.
+ </text>
+ <text class="text_small" x="10" y="175">
+ 5)
+ </text>
+ <text class="text_small" x="30" y="175">
+ If multiple clusters are active on one server at the same time,
+ </text>
+ <text class="text_small" x="30" y="190">
+ each one is managed by an individual instance. Each such instance
+ </text>
+ <text class="text_small" x="30" y="205">
+ uses a different port.
+ </text>
+ <text class="text_small" x="10" y="225">
+ 6)
+ </text>
+ <text class="text_small" x="30" y="225">
+ No client application is allowed to connect to 'template0'.
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink.svg b/doc/src/sgml/images/cluster-db-schema-ink.svg
new file mode 100644
index 0000000000..1fffb9737a
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink.svg
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="685px"
+ viewBox="0 0 900 685"
+ id="svg147"
+ sodipodi:docname="cluster-db-schema-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Server (Hardware, Container, or VM)</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1129"
+ inkscape:window-height="922"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.68905109"
+ inkscape:cx="737.16805"
+ inkscape:cy="342.1375"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Server (Hardware, Container, or VM)</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs49">
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangle_special_0">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect6" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="195"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect8" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text10">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text12">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="195"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect14" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text16">(more system schemas)</text>
+ </symbol>
+ <!-- same as before, but one more schema -->
+ <symbol
+ id="rectangle_special_1">
+ <!-- the database -->
+ <rect
+ width="245"
+ height="225"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect19" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect21" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text23">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text25">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect27" />
+ <text
+ class="text_normal"
+ x="20"
+ y="125"
+ id="text29">'my_schema' (optional)</text>
+ <text
+ class="text_small"
+ x="20"
+ y="145"
+ id="text31">tables, views, ...</text>
+ <rect
+ x="15"
+ y="170"
+ width="205"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect33" />
+ <text
+ class="text_small"
+ x="20"
+ y="190"
+ id="text35">(more system schemas)</text>
+ </symbol>
+ <symbol
+ id="note"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title38">UML Note</title>
+ <path
+ d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10"
+ id="path40" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path43" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path46" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect51" />
+ <text
+ class="text_big"
+ x="270"
+ y="40"
+ id="text53">Server (Hardware, Container, or VM)</text>
+ <!-- two clusters -->
+ <g
+ transform="translate(20 110)"
+ id="g59">
+ <rect
+ x="0"
+ y="0"
+ width="790"
+ height="555"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="rect55" />
+ <text
+ class="text_normal"
+ x="180"
+ y="25"
+ id="text57">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g
+ transform="translate(45 110)"
+ id="g65">
+ <path
+ d="M 5,0 v -30 h 790 v 555 h -30"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="path61" />
+ <text
+ class="text_normal"
+ x="190"
+ y="-10"
+ id="text63">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+ <!-- database template 0 -->
+ <g
+ transform="translate(40 155)"
+ id="g71">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use67" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text69">database 'template0'</text>
+ </g>
+ <!-- database template 1 -->
+ <g
+ transform="translate(290 155)"
+ id="g77">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use73" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text75">database 'template1'</text>
+ </g>
+ <!-- database postgres -->
+ <g
+ transform="translate(540 155)"
+ id="g83">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use79" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text81">database 'postgres'</text>
+ </g>
+ <!-- database my_db -->
+ <g
+ transform="translate(40 350)"
+ id="g89">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use85" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text87">database 'my_db' (optional)</text>
+ </g>
+ <!-- global objects -->
+ <g
+ transform="translate(320 330)"
+ id="g103">
+ <rect
+ x="0"
+ y="0"
+ width="180"
+ height="45"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="10 4 4 4"
+ id="rect91" />
+ <text
+ class="text_normal"
+ x="15"
+ y="27"
+ id="text93">Global SQL objects</text>
+ <path
+ d="M 0,5 l-65,-35"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path95" />
+ <path
+ d="M 80,0 v-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path97" />
+ <path
+ d="M 180,40 h50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path99" />
+ <path
+ d="M 0,40 l-45,20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path101" />
+ </g>
+ <!-- Some comments -->
+ <g
+ transform="translate(335 405)"
+ id="g145">
+ <use
+ xlink:href="#note"
+ x="0"
+ y="0"
+ id="use105" />
+ <text
+ class="text_small"
+ x="10"
+ y="20"
+ id="text107">1)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="20"
+ id="text109">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text
+ class="text_small"
+ x="30"
+ y="35"
+ id="text111">schema 'public'.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="55"
+ id="text113">2)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="55"
+ id="text115">More system schemas: pg_catalog, information_schema,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="70"
+ id="text117">pg_temp, pg_toast.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="90"
+ id="text119">3)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="90"
+ id="text121">Global SQL objects: Some SQL objects are automatically active</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text123">and known database- or even cluster-wide.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="125"
+ id="text125">4)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="125"
+ id="text127">The command 'initdb' creates a new cluster with the three</text>
+ <text
+ class="text_small"
+ x="30"
+ y="140"
+ id="text129">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text
+ class="text_small"
+ x="30"
+ y="155"
+ id="text131">'createdb' creates a new database.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="175"
+ id="text133">5)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="175"
+ id="text135">If multiple clusters are active on one server at the same time,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="190"
+ id="text137">each one is managed by an individual instance. Each such instance</text>
+ <text
+ class="text_small"
+ x="30"
+ y="205"
+ id="text139">uses a different port.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="225"
+ id="text141">6)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="225"
+ id="text143">No client application is allowed to connect to 'template0'.</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
new file mode 100644
index 0000000000..af50c07330
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="685px"
+ viewBox="0 0 900 685" >
+
+ <title>Server (Hardware, Container, or VM)</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_0">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">(more system schemas)</text>
+ </symbol>
+
+ <!-- same as before, but one more schema -->
+ <symbol id="rectangle_special_1">
+ <!-- the database -->
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="125">'my_schema' (optional)</text>
+ <text class="text_small" x="20" y="145">tables, views, ...</text>
+
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="190">(more system schemas)</text>
+ </symbol>
+
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="270" y="40">Server (Hardware, Container, or VM)</text>
+
+ <!-- two clusters -->
+ <g transform="translate(20 110)">
+ <rect x="0" y="0" width="790" height="555" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="180" y="25">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g transform="translate(45 110)">
+ <path d="M 5,0 v -30 h 790 v 555 h -30" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="190" y="-10">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+
+
+ <!-- database template 0 -->
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template0'</text>
+ </g>
+
+ <!-- database template 1 -->
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template1'</text>
+ </g>
+
+ <!-- database postgres -->
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'postgres'</text>
+ </g>
+
+ <!-- database my_db -->
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
+ </g>
+
+ <!-- global objects -->
+ <g transform="translate(320 330)">
+ <rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
+ <text class="text_normal" x="15" y="27">Global SQL objects</text>
+ <path d="M 0,5 l-65,-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ </g>
+
+ <!-- Some comments -->
+ <g transform="translate(335 405)">
+ <use xlink:href="#note" x="0" y="0" />
+
+ <text class="text_small" x="10" y="20">1)</text>
+ <text class="text_small" x="30" y="20">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text class="text_small" x="30" y="35">schema 'public'.</text>
+
+ <text class="text_small" x="10" y="55">2)</text>
+ <text class="text_small" x="30" y="55">More system schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="70">pg_temp, pg_toast.</text>
+
+ <text class="text_small" x="10" y="90">3)</text>
+ <text class="text_small" x="30" y="90">Global SQL objects: Some SQL objects are automatically active</text>
+ <text class="text_small" x="30" y="105">and known database- or even cluster-wide.</text>
+
+ <text class="text_small" x="10" y="125">4)</text>
+ <text class="text_small" x="30" y="125">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="140">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="155">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="175">5)</text>
+ <text class="text_small" x="30" y="175">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="190">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="205">uses a different port.</text>
+
+ <text class="text_small" x="10" y="225">6)</text>
+ <text class="text_small" x="30" y="225">No client application is allowed to connect to 'template0'.</text>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/directories-ink-svgo.svg b/doc/src/sgml/images/directories-ink-svgo.svg
new file mode 100644
index 0000000000..95fa76b9c6
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink-svgo.svg
@@ -0,0 +1,164 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="640" viewBox="0 0 900 640">
+ <title>
+ Directory structure of a cluster
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <symbol id="directory" stroke="blue" stroke-width=".3" fill="aqua">
+ <title>
+ Directory
+ </title>
+ <path d="M0 10h110v20H0z"/>
+ <path d="M0 10V8l3-3h35l3 3v2"/>
+ </symbol>
+ <symbol id="file" stroke="black" fill="none">
+ <title>
+ File
+ </title>
+ <path stroke="blue" d="M0 0h40v50H0z"/>
+ <path d="M5 10h20" stroke-dasharray="4 2"/>
+ <path d="M5 17h15" stroke-dasharray="6 2"/>
+ <path d="M5 24h25" stroke-dasharray="4 2"/>
+ <path d="M5 31h20" stroke-dasharray="5 2"/>
+ </symbol>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="50" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Directory Structure
+ </text>
+ <g transform="translate(20 100)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /pg/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ An arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 130)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ data/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of cluster 'data' (see: PGDATA)
+ </text>
+ </g>
+ <g transform="translate(120 160)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ base/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing per-database subdirectories
+ </text>
+ </g>
+ <g transform="translate(170 190)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 1/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of first database 'template0'
+ </text>
+ </g>
+ <g transform="translate(170 220)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12992/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of second database 'template1'
+ </text>
+ </g>
+ <g transform="translate(170 250)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12999/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of third database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(170 280)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ nnnnn/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Optional: more subdirectories for databases, e.g. 'my_db'
+ </text>
+ </g>
+ <g transform="translate(120 310)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ global/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory with information about Global SQL Objects
+ </text>
+ </g>
+ <g transform="translate(120 340)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_wal/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 370)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_xact/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for transaction commit status ('pg_clog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 400)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_tblspc/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing symbolic links to tablespaces
+ </text>
+ </g>
+ <g transform="translate(120 430)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_... /
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Some more subdirectories
+ </text>
+ </g>
+ <g transform="translate(120 465)">
+ <use xlink:href="#file"/>
+ <use xlink:href="#file" x="50"/>
+ <text x="200" y="26" class="text_normal">
+ 'postmaster.pid' and other files with cluster-wide relevance
+ </text>
+ </g>
+ <g transform="translate(20 540)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /xyz/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ Same or another arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 570)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ cluster_2/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of another cluster 'cluster_2'
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-ink.svg b/doc/src/sgml/images/directories-ink.svg
new file mode 100644
index 0000000000..8151cf583a
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink.svg
@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="640px"
+ viewBox="0 0 900 640"
+ id="svg303"
+ sodipodi:docname="directories-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata307">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Directory structure of a cluster</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1083"
+ inkscape:window-height="808"
+ id="namedview305"
+ showgrid="false"
+ inkscape:zoom="0.36875"
+ inkscape:cx="450"
+ inkscape:cy="320"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg303" />
+ <title
+ id="title153">Directory structure of a cluster</title>
+ <style
+ type="text/css"
+ id="style155">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs177">
+ <!-- Directory -->
+ <symbol
+ id="directory"
+ stroke="blue"
+ stroke-width="0.3px"
+ fill="aqua">
+ <title
+ id="title157">Directory</title>
+ <rect
+ x="0"
+ y="10"
+ width="110"
+ height="20"
+ id="rect159" />
+ <path
+ d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2"
+ id="path161" />
+ </symbol>
+ <!-- File -->
+ <symbol
+ id="file"
+ stroke="black"
+ fill="none">
+ <title
+ id="title164">File</title>
+ <rect
+ x="0"
+ y="0"
+ width="40"
+ height="50"
+ stroke="blue"
+ id="rect166" />
+ <path
+ d="M 5,10 h 20"
+ stroke-dasharray="4 2"
+ id="path168" />
+ <path
+ d="M 5,17 h 15"
+ stroke-dasharray="6 2"
+ id="path170" />
+ <path
+ d="M 5,24 h 25"
+ stroke-dasharray="4 2"
+ id="path172" />
+ <path
+ d="M 5,31 h 20"
+ stroke-dasharray="5 2"
+ id="path174" />
+ </symbol>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect179" />
+ <!-- caption -->
+ <text
+ x="200"
+ y="50"
+ class="text_big"
+ id="text181">Directory Structure</text>
+ <!-- the directories -->
+ <g
+ transform="translate(20, 100)"
+ id="g189">
+ <use
+ xlink:href="#directory"
+ id="use183" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text185">... /pg/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text187">An arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 130)"
+ id="g197">
+ <use
+ xlink:href="#directory"
+ id="use191" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text193">data/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text195">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+ <g
+ transform="translate(120, 160)"
+ id="g205">
+ <use
+ xlink:href="#directory"
+ id="use199" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text201">base/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text203">Subdirectory containing per-database subdirectories</text>
+ </g>
+ <!-- -->
+ <g
+ transform="translate(170, 190)"
+ id="g213">
+ <use
+ xlink:href="#directory"
+ id="use207" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text209">1/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text211">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g
+ transform="translate(170, 220)"
+ id="g221">
+ <use
+ xlink:href="#directory"
+ id="use215" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text217">12992/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text219">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g
+ transform="translate(170, 250)"
+ id="g229">
+ <use
+ xlink:href="#directory"
+ id="use223" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text225">12999/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text227">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g
+ transform="translate(170, 280)"
+ id="g237">
+ <use
+ xlink:href="#directory"
+ id="use231" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text233">nnnnn/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text235">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+ <g
+ transform="translate(120, 310)"
+ id="g245">
+ <use
+ xlink:href="#directory"
+ id="use239" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text241">global/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text243">Subdirectory with information about Global SQL Objects</text>
+ </g>
+ <g
+ transform="translate(120, 340)"
+ id="g253">
+ <use
+ xlink:href="#directory"
+ id="use247" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text249">pg_wal/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text251">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 370)"
+ id="g261">
+ <use
+ xlink:href="#directory"
+ id="use255" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text257">pg_xact/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text259">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 400)"
+ id="g269">
+ <use
+ xlink:href="#directory"
+ id="use263" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text265">pg_tblspc/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text267">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+ <g
+ transform="translate(120, 430)"
+ id="g277">
+ <use
+ xlink:href="#directory"
+ id="use271" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text273">pg_... /</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text275">Some more subdirectories</text>
+ </g>
+ <g
+ transform="translate(120, 465)"
+ id="g285">
+ <use
+ xlink:href="#file"
+ x="0"
+ y="0"
+ id="use279" />
+ <use
+ xlink:href="#file"
+ x="50"
+ y="0"
+ id="use281" />
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text283">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+ <!-- next cluster -->
+ <g
+ transform="translate(20, 540)"
+ id="g293">
+ <use
+ xlink:href="#directory"
+ id="use287" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text289">... /xyz/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text291">Same or another arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 570)"
+ id="g301">
+ <use
+ xlink:href="#directory"
+ id="use295" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text297">cluster_2/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text299">Root of another cluster 'cluster_2'</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
new file mode 100644
index 0000000000..6d16a03169
--- /dev/null
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="640px"
+ viewBox="0 0 900 640">
+
+ <title>Directory structure of a cluster</title>
+
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Directory -->
+ <symbol id="directory" stroke="blue" stroke-width="0.3px" fill="aqua">
+ <title>Directory</title>
+ <rect x="0" y="10" width="110" height="20" />
+ <path d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2" />
+ </symbol>
+
+ <!-- File -->
+ <symbol id="file" stroke="black" fill="none" >
+ <title>File</title>
+ <rect x="0" y="0" width="40" height="50" stroke="blue" />
+ <path d="M 5,10 h 20" stroke-dasharray="4 2" />
+ <path d="M 5,17 h 15" stroke-dasharray="6 2" />
+ <path d="M 5,24 h 25" stroke-dasharray="4 2" />
+ <path d="M 5,31 h 20" stroke-dasharray="5 2" />
+ </symbol>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption -->
+ <text x="200" y="50" class="text_big">Directory Structure</text>
+
+ <!-- the directories -->
+ <g transform="translate(20, 100)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /pg/</text>
+ <text x="300" y="26" class="text_normal">An arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 130)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">data/</text>
+ <text x="250" y="26" class="text_normal">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+
+ <g transform="translate(120, 160)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">base/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing per-database subdirectories</text>
+ </g>
+
+ <!-- -->
+ <g transform="translate(170, 190)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">1/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g transform="translate(170, 220)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12992/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g transform="translate(170, 250)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12999/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g transform="translate(170, 280)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">nnnnn/</text>
+ <text x="150" y="26" class="text_normal">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+
+ <g transform="translate(120, 310)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">global/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory with information about Global SQL Objects</text>
+ </g>
+
+ <g transform="translate(120, 340)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 370)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 400)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+
+ <g transform="translate(120, 430)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_... /</text>
+ <text x="200" y="26" class="text_normal">Some more subdirectories</text>
+ </g>
+
+ <g transform="translate(120, 465)">
+ <use xlink:href="#file" x="0" y="0" />
+ <use xlink:href="#file" x="50" y="0" />
+ <text x="200" y="26" class="text_normal">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+
+ <!-- next cluster -->
+ <g transform="translate(20, 540)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /xyz/</text>
+ <text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 570)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster 'cluster_2'</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink-svgo.svg b/doc/src/sgml/images/freeze-ink-svgo.svg
new file mode 100644
index 0000000000..6fedfb7633
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink-svgo.svg
@@ -0,0 +1,84 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="320" viewBox="0 0 850 320">
+ <title>
+ Freeze
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100)"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="70" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ <tspan font-style="italic" font-weight="700">Freeze</tspan> to keep visible
+ </text>
+ <g fill="none" transform="translate(170 190)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_120" startOffset="11.2%">(1)</textPath> <textPath xlink:href="#Path_120" startOffset="61.2%">(5)</textPath> <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%">|</textPath> <textPath xlink:href="#Path_120" startOffset="34%">(2)</textPath> <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(3)</textPath> <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%">|</textPath> <textPath xlink:href="#Path_120" startOffset="55%">(4)</textPath>
+ </text>
+ <path d="M-80-80L80 80" stroke="black"/>
+ <text class="text_normal" letter-spacing="12" transform="rotate(45 40.78 -38.1)">
+ PAST
+ </text>
+ <text class="text_normal" letter-spacing="12" transform="rotate(-135 27.43 23.79)">
+ FUTURE
+ </text>
+ <use xlink:href="#frozenPoint" transform="rotate(10)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(25)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(40)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(55)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(70)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(85)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(100)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(115)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(130)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(145)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(160)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(175)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(190)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(205)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(220)"/>
+ </g>
+ <g class="text_normal" transform="translate(380 30)">
+ <text>
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25">
+ 1: txid_current + 2 ^ 31 (split-point)
+ </text>
+ <text y="50">
+ 2: autovacuum_freeze_max_age (200 mio.)
+ </text>
+ <text y="75">
+ 3: vacuum_freeze_table_age (150 mio.)
+ </text>
+ <text y="100">
+ 4: vacuum_freeze_min_age (50 mio.)
+ </text>
+ <text y="125">
+ 5: txid_current (split-point, jungest xid)
+ </text>
+ <text y="155">
+ per table: pg_class.relfrozenxid <tspan font-weight="700">must</tspan> be between (1) and (5);
+ </text>
+ <text y="175" x="75">
+ normally it is between (3) and (4)
+ </text>
+ <use xlink:href="#unfrozenPoint" transform="translate(106 200)"/>
+ <text y="205" x="20">
+ Unfrozen xid
+ </text>
+ <use xlink:href="#frozenPoint" transform="translate(106 224)"/>
+ <text y="230" x="20">
+ Frozen xid
+ </text>
+ <text y="260">
+ (figure is out of scale)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink.svg b/doc/src/sgml/images/freeze-ink.svg
new file mode 100644
index 0000000000..009cfe4b41
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink.svg
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="320px"
+ viewBox="0 0 850 320"
+ id="svg454"
+ sodipodi:docname="freeze-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata458">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Freeze</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="979"
+ inkscape:window-height="857"
+ id="namedview456"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="160"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg454" />
+ <title
+ id="title309">Freeze</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style311">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs318">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle
+ id="frozenPoint"
+ r="3"
+ stroke="green"
+ fill="green"
+ transform="translate(-100, 0)" />
+ <circle
+ id="unfrozenPoint"
+ r="3"
+ stroke="green"
+ fill="none"
+ transform="translate(-100, 0)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect320" />
+ <text
+ class="text_big"
+ x="70"
+ y="40"
+ id="text324"><tspan
+ style="font-style:italic;font-weight:bold"
+ id="tspan322">
+ Freeze</tspan>
+ to keep visible</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 190)"
+ id="g418">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle326" />
+ <text
+ class="text_normal"
+ id="text350">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath328">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath330">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath332">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="11.2%"
+ id="textPath334">(1)</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="61.2%"
+ id="textPath336">(5)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="red"
+ stroke-width="3"
+ startOffset="34%"
+ id="textPath338">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="34%"
+ id="textPath340">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="black"
+ stroke-width="3"
+ startOffset="45%"
+ id="textPath342">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath344">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="green"
+ stroke-width="3"
+ startOffset="55%"
+ id="textPath346">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="55%"
+ id="textPath348">(4)</textPath>
+ </text>
+ <!-- split it into 'past' and 'future' -->
+ <path
+ d="M -80 -80 l 160 160"
+ stroke="black"
+ id="path352" />
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(-15, -40) rotate(45)"
+ id="text354">PAST</text>
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(30, 60) rotate(225)"
+ id="text356">FUTURE</text>
+ <g
+ transform="rotate(10)"
+ id="g360">
+ <use
+ xlink:href="#frozenPoint"
+ id="use358" />
+ </g>
+ <g
+ transform="rotate(25)"
+ id="g364">
+ <use
+ xlink:href="#frozenPoint"
+ id="use362" />
+ </g>
+ <g
+ transform="rotate(40)"
+ id="g368">
+ <use
+ xlink:href="#frozenPoint"
+ id="use366" />
+ </g>
+ <g
+ transform="rotate(55)"
+ id="g372">
+ <use
+ xlink:href="#frozenPoint"
+ id="use370" />
+ </g>
+ <g
+ transform="rotate(70)"
+ id="g376">
+ <use
+ xlink:href="#frozenPoint"
+ id="use374" />
+ </g>
+ <g
+ transform="rotate(85)"
+ id="g380">
+ <use
+ xlink:href="#frozenPoint"
+ id="use378" />
+ </g>
+ <g
+ transform="rotate(100)"
+ id="g384">
+ <use
+ xlink:href="#frozenPoint"
+ id="use382" />
+ </g>
+ <g
+ transform="rotate(115)"
+ id="g388">
+ <use
+ xlink:href="#frozenPoint"
+ id="use386" />
+ </g>
+ <g
+ transform="rotate(130)"
+ id="g392">
+ <use
+ xlink:href="#frozenPoint"
+ id="use390" />
+ </g>
+ <g
+ transform="rotate(145)"
+ id="g396">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use394" />
+ </g>
+ <g
+ transform="rotate(160)"
+ id="g400">
+ <use
+ xlink:href="#frozenPoint"
+ id="use398" />
+ </g>
+ <g
+ transform="rotate(175)"
+ id="g404">
+ <use
+ xlink:href="#frozenPoint"
+ id="use402" />
+ </g>
+ <g
+ transform="rotate(190)"
+ id="g408">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use406" />
+ </g>
+ <g
+ transform="rotate(205)"
+ id="g412">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use410" />
+ </g>
+ <g
+ transform="rotate(220)"
+ id="g416">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use414" />
+ </g>
+ </g>
+ <!-- legend -->
+ <g
+ class="text_normal"
+ transform="translate(380 30)"
+ id="g452">
+ <text
+ id="text424">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan420">^</tspan>
+<tspan
+ dy="5"
+ id="tspan422">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text426">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text
+ y="50"
+ id="text428">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text
+ y="75"
+ id="text430">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text
+ y="100"
+ id="text432">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text
+ y="125"
+ id="text434">5: txid_current (split-point, jungest xid)</text>
+ <text
+ y="155"
+ id="text438">per table: pg_class.relfrozenxid
+ <tspan
+ style="font-weight:bold"
+ id="tspan436">must</tspan>
+ be between (1) and (5);</text>
+ <text
+ y="175"
+ x="75"
+ id="text440">normally it is between (3) and (4)</text>
+ <use
+ xlink:href="#unfrozenPoint"
+ transform="translate(106, 200)"
+ id="use442" />
+ <text
+ y="205"
+ x="20"
+ id="text444">Unfrozen xid</text>
+ <use
+ xlink:href="#frozenPoint"
+ transform="translate(106, 224)"
+ id="use446" />
+ <text
+ y="230"
+ x="20"
+ id="text448">Frozen xid</text>
+ <text
+ y="260"
+ id="text450">(figure is out of scale)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-raw.svg b/doc/src/sgml/images/freeze-raw.svg
new file mode 100644
index 0000000000..2d1d256184
--- /dev/null
+++ b/doc/src/sgml/images/freeze-raw.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="320px"
+ viewBox="0 0 850 320" >
+
+ <title>Freeze</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100, 0)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100, 0)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="70" y="40"><tspan style="font-style:italic;font-weight:bold">
+ Freeze</tspan> to keep visible</text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 190)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_120" startOffset="11.2%" >(1)</textPath>
+ <textPath xlink:href="#Path_120" startOffset="61.2%" >(5)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="34%" >(2)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(3)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="55%" >(4)</textPath>
+
+ </text>
+
+ <!-- split it into 'past' and 'future' -->
+ <path d="M -80 -80 l 160 160" stroke="black" />
+ <text class="text_normal" letter-spacing="12" transform="translate(-15, -40) rotate(45)">PAST</text>
+ <text class="text_normal" letter-spacing="12" transform="translate(30, 60) rotate(225)">FUTURE</text>
+
+ <g transform="rotate(10)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(25)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(40)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(55)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(70)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(85)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(100)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(115)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(130)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(145)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(160)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(175)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(190)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(205)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(220)"><use xlink:href="#unfrozenPoint"/></g>
+
+ </g>
+
+ <!-- legend -->
+ <g class="text_normal" transform="translate(380 30)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text y="50">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text y="75">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text y="100">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text y="125">5: txid_current (split-point, jungest xid)</text>
+ <text y="155">per table: pg_class.relfrozenxid
+ <tspan style="font-weight:bold">must</tspan> be between (1) and (5);</text>
+ <text y="175" x="75">normally it is between (3) and (4)</text>
+
+ <use xlink:href="#unfrozenPoint" transform="translate(106, 200)"/>
+ <text y="205" x="20">Unfrozen xid</text>
+
+ <use xlink:href="#frozenPoint" transform="translate(106, 224)"/>
+ <text y="230" x="20">Frozen xid</text>
+
+ <text y="260">(figure is out of scale)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
new file mode 100644
index 0000000000..26bce6176d
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
@@ -0,0 +1,83 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="720" height="430" viewBox="0 0 720 430">
+ <title>
+ Hierarchy of Internal Objects
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Hierarchy of internal Objects
+ </text>
+ <g fill="none">
+ <g transform="translate(350 240)">
+ <ellipse rx="320" ry="170" stroke="blue"/>
+ <text class="text_normal" x="-140" y="-130">
+ Cluster
+ </text>
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-60" y="5">
+ Database Names
+ </text>
+ </g>
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-40" y="5">
+ Tablespace
+ </text>
+ </g>
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-70" y="5">
+ Replication Origins
+ </text>
+ </g>
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue"/>
+ <text class="text_normal" x="-60" y="-3">
+ Subscription for
+ </text>
+ <text class="text_normal" x="-68" y="10">
+ Logical Replication
+ </text>
+ </g>
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-15" y="5">
+ Role
+ </text>
+ </g>
+ </g>
+ <g transform="translate(270 250)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2"/>
+ <text class="text_normal" x="-60" y="-80">
+ Database
+ </text>
+ <g transform="translate(-150 -30)">
+ <ellipse rx="50" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Extension
+ </text>
+ </g>
+ <g transform="translate(-155 35)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Collation
+ </text>
+ </g>
+ <g transform="translate(30 20)">
+ <ellipse rx="140" ry="70" stroke="blue"/>
+ <text class="text_normal" x="-80" y="-35">
+ Schema
+ </text>
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue"/>
+ <text class="text_normal" x="-50" y="5">
+ Table, View, ...
+ </text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
new file mode 100644
index 0000000000..e5745818d9
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="720px"
+ height="430px"
+ viewBox="0 0 720 430"
+ id="svg540"
+ sodipodi:docname="internal-objects-hierarchy-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata546">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Hierarchy of Internal Objects</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs544" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1050"
+ inkscape:window-height="838"
+ id="namedview542"
+ showgrid="false"
+ inkscape:zoom="0.51944444"
+ inkscape:cx="360"
+ inkscape:cy="215"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg540" />
+ <title
+ id="title460">Hierarchy of Internal Objects</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style462">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect464" />
+ <text
+ class="text_big"
+ x="200"
+ y="40"
+ id="text466">Hierarchy of internal Objects</text>
+ <!-- set centre of figure and default values -->
+ <g
+ transform="translate(350 240)"
+ fill="none"
+ id="g538">
+ <g
+ id="g504">
+ <ellipse
+ rx="320"
+ ry="170"
+ stroke="blue"
+ id="ellipse468" />
+ <text
+ class="text_normal"
+ x="-140"
+ y="-130"
+ id="text470">Cluster</text>
+ <g
+ transform="translate(40 -125)"
+ id="g476">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse472" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="5"
+ id="text474">Database Names</text>
+ </g>
+ <g
+ transform="translate(180 -70)"
+ id="g482">
+ <ellipse
+ rx="60"
+ ry="20"
+ stroke="blue"
+ id="ellipse478" />
+ <text
+ class="text_normal"
+ x="-40"
+ y="5"
+ id="text480">Tablespace</text>
+ </g>
+ <g
+ transform="translate(230 -5)"
+ id="g488">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse484" />
+ <text
+ class="text_normal"
+ x="-70"
+ y="5"
+ id="text486">Replication Origins</text>
+ </g>
+ <g
+ transform="translate(200 70)"
+ id="g496">
+ <ellipse
+ rx="78"
+ ry="27"
+ stroke="blue"
+ id="ellipse490" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-3"
+ id="text492">Subscription for</text>
+ <text
+ class="text_normal"
+ x="-68"
+ y="10"
+ id="text494">Logical Replication</text>
+ </g>
+ <g
+ transform="translate(100 120)"
+ id="g502">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse498" />
+ <text
+ class="text_normal"
+ x="-15"
+ y="5"
+ id="text500">Role</text>
+ </g>
+ </g>
+ <g
+ transform="translate(-80 10)"
+ id="g536">
+ <ellipse
+ rx="220"
+ ry="110"
+ stroke="blue"
+ stroke-width="2px"
+ id="ellipse506" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-80"
+ id="text508">Database</text>
+ <g
+ transform="translate(-120 -50)"
+ id="g534">
+ <g
+ transform="translate(-30 20)"
+ id="g514">
+ <ellipse
+ rx="50"
+ ry="20"
+ stroke="blue"
+ id="ellipse510" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text512">Extension</text>
+ </g>
+ <g
+ transform="translate(-35 85)"
+ id="g520">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse516" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text518">Collation</text>
+ </g>
+ <g
+ transform="translate(150 70)"
+ id="g532">
+ <ellipse
+ rx="140"
+ ry="70"
+ stroke="blue"
+ id="ellipse522" />
+ <text
+ class="text_normal"
+ x="-80"
+ y="-35"
+ id="text524">Schema</text>
+ <g
+ transform="translate(20 10)"
+ id="g530">
+ <ellipse
+ rx="90"
+ ry="30"
+ stroke="blue"
+ id="ellipse526" />
+ <text
+ class="text_normal"
+ x="-50"
+ y="5"
+ id="text528">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
new file mode 100644
index 0000000000..f0dc890f6b
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="720px" height="430px"
+ viewBox="0 0 720 430" >
+
+ <title>Hierarchy of Internal Objects</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="200" y="40">Hierarchy of internal Objects</text>
+
+
+ <!-- set centre of figure and default values -->
+ <g transform="translate(350 240)" fill="none">
+
+ <g>
+ <ellipse rx="320" ry="170" stroke="blue" />
+ <text class="text_normal" x="-140" y="-130">Cluster</text>
+
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-60" y="5">Database Names</text>
+ </g>
+
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue" />
+ <text class="text_normal" x="-40" y="5">Tablespace</text>
+ </g>
+
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-70" y="5">Replication Origins</text>
+ </g>
+
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue" />
+ <text class="text_normal" x="-60" y="-3">Subscription for</text>
+ <text class="text_normal" x="-68" y="10">Logical Replication</text>
+ </g>
+
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-15" y="5">Role</text>
+ </g>
+
+ </g>
+
+ <g transform="translate(-80 10)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2px" />
+ <text class="text_normal" x="-60" y="-80">Database</text>
+
+ <g transform="translate(-120 -50)">
+ <g transform="translate(-30 20)">
+ <ellipse rx="50" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Extension</text>
+ </g>
+
+ <g transform="translate(-35 85)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Collation</text>
+ </g>
+
+ <g transform="translate(150 70)">
+ <ellipse rx="140" ry="70" stroke="blue" />
+ <text class="text_normal" x="-80" y="-35">Schema</text>
+
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue" />
+ <text class="text_normal" x="-50" y="5">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink-svgo.svg b/doc/src/sgml/images/mvcc-ink-svgo.svg
new file mode 100644
index 0000000000..8e67da93d1
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink-svgo.svg
@@ -0,0 +1,151 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="150" viewBox="0 0 850 150">
+ <title>
+ MVCC
+ </title>
+ <style>
+ .text_small{font-style:normal;font-weight:400;font-size:10px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <marker id="triangle_1" markerWidth="10" markerHeight="10" refX="5" refY="5" orient="auto" stroke="black" fill="none">
+ <path d="M0 0l10 5-10 5"/>
+ </marker>
+ <path id="arrow" d="M0 0q20-15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+ <g id="tuple" stroke="black">
+ <path d="M80 0H0v20h80M29 0v20M60 0v20"/>
+ <path d="M80 0h15M80 20h15" stroke-dasharray="2 1"/>
+ </g>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <g fill="none">
+ <g transform="translate(20 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">123</tspan> <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)" fill="#00f">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 83)" fill="#00f">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(185 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">135</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 53)" fill="#00f">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(350 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">142</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 23)" fill="#00f">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(515 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">821</tspan> <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 821
+ </text>
+ <text class="text_small" transform="translate(125 23)">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(740 110)">
+ <path d="M102-20H-18v60" stroke="black"/>
+ <text font-weight="400" font-size="16" font-family=""Open Sans",sans-serif" fill="#000">
+ Legend
+ </text>
+ <use xlink:href="#tuple" transform="translate(0 10)"/>
+ <text class="text_small" transform="translate(3 23)">
+ xmin
+ </text>
+ <text class="text_small" transform="translate(32 23)">
+ xmax
+ </text>
+ <text class="text_small" transform="translate(65 23)">
+ data
+ </text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink.svg b/doc/src/sgml/images/mvcc-ink.svg
new file mode 100644
index 0000000000..f4161b3e79
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink.svg
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="150px"
+ viewBox="0 0 850 150"
+ id="svg147"
+ sodipodi:docname="mvcc-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>MVCC</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1256"
+ inkscape:window-height="801"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="75"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">MVCC</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs15">
+ <marker
+ id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto"
+ stroke="black"
+ fill="none">
+ <path
+ d="M 0,0 L 10,5 L 0,10"
+ id="path6" />
+ </marker>
+ <g
+ id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path
+ d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20"
+ stroke="black"
+ id="path9" />
+ <!-- prolong the rectangle -->
+ <path
+ d="M 80 0 h 15 M 80 20 h 15"
+ stroke="black"
+ stroke-dasharray="2 1"
+ id="path11" />
+ </g>
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path
+ id="arrow"
+ d="M 0 0 Q 20 -15 40 0"
+ stroke="black"
+ marker-end="url(#triangle_1)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect17" />
+ <!-- set default values -->
+ <g
+ fill="none"
+ id="g145">
+ <!-- start plus first INSERT -->
+ <g
+ transform="translate(20, 40)"
+ id="g35">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text23">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan19">123</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan21">: INSERT</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use25" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use27" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ style="fill:blue"
+ id="text29">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text31">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ style="fill:blue"
+ id="text33">'x'</text>
+ </g>
+ <!-- first UPDATE -->
+ <g
+ transform="translate(185, 40)"
+ id="g61">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text41">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan37">135</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan39">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use43" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use45" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ style="fill:blue"
+ id="text47">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text49">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ style="fill:blue"
+ id="text51">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use53" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text55">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text57">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text59">'x'</text>
+ </g>
+ <!-- next UPDATE -->
+ <g
+ transform="translate(350, 40)"
+ id="g95">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text67">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan63">142</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan65">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use69" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use71" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ style="fill:blue"
+ id="text73">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text75">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ style="fill:blue"
+ id="text77">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use79" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text81">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text83">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text85">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use87" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text89">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text91">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text93">'x'</text>
+ </g>
+ <!-- DELETE -->
+ <g
+ transform="translate(515, 40)"
+ id="g129">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text101">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan97">821</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan99">: DELTE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use103" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use105" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text107">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text109">821</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ id="text111">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use113" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text115">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ id="text117">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text119">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use121" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text123">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text125">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text127">'x'</text>
+ </g>
+ <!-- LEGEND -->
+ <g
+ transform="translate(740, 110)"
+ id="g143">
+ <path
+ d="M 102 -20 h -120 v 60"
+ stroke="black"
+ id="path131" />
+ <text
+ class="text_normal"
+ transform="translate(0, 0)"
+ id="text133">Legend</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(0, 10)"
+ id="use135" />
+ <text
+ class="text_small"
+ transform="translate(3, 23)"
+ id="text137">xmin</text>
+ <text
+ class="text_small"
+ transform="translate(32, 23)"
+ id="text139">xmax</text>
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text141">data</text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-raw.svg b/doc/src/sgml/images/mvcc-raw.svg
new file mode 100644
index 0000000000..0481c4c938
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-raw.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="150px"
+ viewBox="0 0 850 150" >
+
+ <title>MVCC</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <marker id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto" stroke="black" fill="none">
+ <path d="M 0,0 L 10,5 L 0,10" />
+ </marker>
+
+ <g id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20" stroke="black"/>
+ <!-- prolong the rectangle -->
+ <path d="M 80 0 h 15 M 80 20 h 15" stroke="black" stroke-dasharray="2 1"/>
+ </g>
+
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path id="arrow" d="M 0 0 Q 20 -15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- set default values -->
+ <g fill="none">
+
+ <!-- start plus first INSERT -->
+ <g transform="translate(20, 40)">
+
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">123</tspan>
+ <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)" style="fill:blue">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 83)" style="fill:blue">'x'</text>
+ </g>
+
+ <!-- first UPDATE -->
+ <g transform="translate(185, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">135</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 53)" style="fill:blue">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- next UPDATE -->
+ <g transform="translate(350, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">142</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 23)" style="fill:blue">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- DELETE -->
+ <g transform="translate(515, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">821</tspan>
+ <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">821</text>
+ <text class="text_small" transform="translate(125, 23)">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- LEGEND -->
+ <g transform="translate(740, 110)">
+ <path d="M 102 -20 h -120 v 60" stroke="black"/>
+ <text class="text_normal" transform="translate(0, 0)">Legend</text>
+ <use xlink:href="#tuple" transform="translate(0, 10)"/>
+ <text class="text_small" transform="translate(3, 23)">xmin</text>
+ <text class="text_small" transform="translate(32, 23)">xmax</text>
+ <text class="text_small" transform="translate(65, 23)">data</text>
+ </g>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink-svgo.svg b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
new file mode 100644
index 0000000000..723d67bd8d
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
@@ -0,0 +1,285 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 900 600">
+ <title>
+ PG Overall Server Architecture
+ </title>
+ <style>
+ .text_big{font-style:normal}.text_big,.text_comment,.text_normal,.text_small{font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_normal,.text_small{font-style:normal}.text_small{font-size:12px}.text_normal{font-size:16px}.text_big{font-size:24px}.text_comment{font-style:italic;font-size:16px}
+ </style>
+ <defs>
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (200 x 20 px)
+ </title>
+ <path d="M200 10v10H0V0h190v10h10L190 0"/>
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (250 x 20 px)
+ </title>
+ <path d="M250 10v10H0V0h240v10h10L240 0"/>
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (100 x 35 px)
+ </title>
+ <path d="M100 10v25H0V0h90v10h10L90 0"/>
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (170 x 50 px)
+ </title>
+ <path d="M170 10v40H0V0h160v10h10L160 0"/>
+ </symbol>
+ <symbol id="state_300x120">
+ <title>
+ UML State (300x120)
+ </title>
+ <rect width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>
+ UML State (350x120)
+ </title>
+ <rect width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="disc" stroke="blue" fill="none">
+ <title>
+ Disc
+ </title>
+ <ellipse cx="51" cy="13" rx="50" ry="12"/>
+ <path d="M1 13v60"/>
+ <path d="M101 13v60"/>
+ <path d="M1 73a50 12 0 00100 0"/>
+ </symbol>
+ <symbol id="laptop" stroke="black" fill="none">
+ <title>
+ Laptop
+ </title>
+ <path d="M20 40V0h54v40l15 15H5l15-15h54"/>
+ <path d="M23 3h48v34H23z"/>
+ <path d="M30 10h20"/>
+ <path d="M30 15h25"/>
+ <path d="M30 20h10"/>
+ <path d="M30 30h20"/>
+ <path d="M25 50h45l2 2H22z"/>
+ </symbol>
+ <marker id="arrowhead_start" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto">
+ <path d="M6 0L0 3l6 3" stroke="black" fill="none"/>
+ </marker>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="15" y="40" class="text_big">
+ Client
+ </text>
+ <text x="140" y="40" class="text_big">
+ Server
+ </text>
+ <use xlink:href="#laptop" x="5" y="210"/>
+ <g transform="translate(130 70)">
+ <use xlink:href="#state_350x120"/>
+ <text x="5" y="20" class="text_normal">
+ maintenance_work_mem (per connection)
+ </text>
+ <text x="5" y="45" class="text_normal">
+ work_mem (per query operation)
+ </text>
+ <text x="5" y="70" class="text_normal">
+ autovacuum_work_mem (per worker process)
+ </text>
+ <text x="5" y="95" class="text_normal">
+ temp_buffer (per connection)
+ </text>
+ <text x="5" y="110" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_200x20" x="140" y="-15"/>
+ <text x="150" class="text_comment">
+ Individual Memory
+ </text>
+ </g>
+ <g transform="translate(520 70)">
+ <use xlink:href="#state_300x120"/>
+ <text x="10" y="30" class="text_normal">
+ shared_buffers (heap and index)
+ </text>
+ <text x="10" y="70" class="text_normal">
+ wal_buffers (WAL records)
+ </text>
+ <text x="10" y="100" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_250x20" x="40" y="-15"/>
+ <text x="50" class="text_comment">
+ Shared Memory (per Instance)
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M180 215h250v30H180z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(180 215)">
+ Postmaster
+ </text>
+ <path d="M90 230h75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 230)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 1
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M150 315h370v30H150z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(150 315)">
+ Backend processes (one per connection)
+ </text>
+ <path d="M155 315v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M160 310v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M90 240l63 63" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 290)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 3
+ </text>
+ </g>
+ <path d="M360 250v50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180 255)">
+ <use xlink:href="#note_250x20"/>
+ <text x="10" y="15" class="text_comment">
+ Creates backend processes
+ </text>
+ </g>
+ <g transform="translate(360 281)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 2
+ </text>
+ </g>
+ <path d="M460 300V200" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M498 300V95h30" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M508 300V135h20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M550 220h120v30H550z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(550 220)">
+ WAL Writer
+ </text>
+ <path d="M590 150v65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M590 255v230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 340h140v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 340)">
+ Checkpointer
+ </text>
+ <path d="M740 110v220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 355H475v130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M700 330V150" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50"/>
+ <text x="60" y="-35" class="text_comment">
+ Checkpoint
+ </text>
+ <text x="60" y="-20" class="text_comment">
+ Record
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M610 380h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 380)">
+ Background Writer
+ </text>
+ <path d="M770 110v260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 395H485v90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 420h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 420)">
+ WAL Archiver
+ </text>
+ <path d="M620 485l30-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M690 455l30 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M135 380h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 380)">
+ Autovacuum
+ </text>
+ <path d="M140 380v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path d="M145 375v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path stroke="blue" fill="none" d="M135 430h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 430)">
+ Logger
+ </text>
+ <path stroke="blue" fill="none" d="M290 370h140v30H290z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(290 370)">
+ Stats Collector
+ </text>
+ <g transform="translate(145 490)">
+ <use xlink:href="#disc"/>
+ <text x="35" y="45" class="text_normal">
+ Log
+ </text>
+ <text x="20" y="60" class="text_small">
+ text lines,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <path d="M195 465v20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(410 490)">
+ <use xlink:href="#disc"/>
+ <text x="10" y="40" class="text_normal">
+ Heap and
+ </text>
+ <text x="25" y="55" class="text_normal">
+ Index
+ </text>
+ <text x="15" y="70" class="text_small">
+ binary blocks,
+ </text>
+ <text x="30" y="80" class="text_small">
+ random
+ </text>
+ </g>
+ <path d="M450 485V350" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(295 420)">
+ <use xlink:href="#note_170x50"/>
+ <text x="5" y="15" class="text_comment">
+ Read heap and index
+ </text>
+ <text x="5" y="30" class="text_comment">
+ pages and transfer
+ </text>
+ <text x="5" y="45" class="text_comment">
+ them to shared_buffers
+ </text>
+ </g>
+ <g transform="translate(550 490)">
+ <use xlink:href="#disc"/>
+ <text x="30" y="45" class="text_normal">
+ WAL
+ </text>
+ <text x="10" y="60" class="text_small">
+ binary records,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <g transform="translate(690 490)">
+ <use xlink:href="#disc"/>
+ <text x="16" y="45" class="text_normal">
+ Archived
+ </text>
+ <text x="36" y="60" class="text_normal">
+ WAL
+ </text>
+ </g>
+ <path d="M110 20v550" stroke="black" fill="none"/>
+ <g transform="rotate(90 -33.5 156.5)">
+ <use xlink:href="#note_200x20"/>
+ <text class="text_comment" x="10" y="15">
+ Via TCP/IP or socket
+ </text>
+ </g>
+ <text class="text_big" x="95" transform="rotate(90 425 425)">
+ RAM
+ </text>
+ <text class="text_big" x="250" transform="rotate(90 425 425)">
+ PROCESSES
+ </text>
+ <text class="text_big" x="500" transform="rotate(90 425 425)">
+ FILES
+ </text>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink.svg b/doc/src/sgml/images/ram-proc-file-ink.svg
new file mode 100644
index 0000000000..4490bf51e1
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink.svg
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="600px"
+ viewBox="0 0 900 600"
+ id="svg306"
+ sodipodi:docname="ram-proc-file-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata310">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>PG Overall Server Architecture</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1048"
+ inkscape:window-height="771"
+ id="namedview308"
+ showgrid="false"
+ inkscape:zoom="0.39333333"
+ inkscape:cx="450"
+ inkscape:cy="300"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg306" />
+ <title
+ id="title2">PG Overall Server Architecture</title>
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs70">
+ <!-- Some notes in different sizes -->
+ <symbol
+ id="note_200x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title6">UML Note (200 x 20 px)</title>
+ <path
+ d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10"
+ id="path8" />
+ </symbol>
+ <symbol
+ id="note_250x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title11">UML Note (250 x 20 px)</title>
+ <path
+ d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10"
+ id="path13" />
+ </symbol>
+ <symbol
+ id="note_100x35"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title16">UML Note (100 x 35 px)</title>
+ <path
+ d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10"
+ id="path18" />
+ </symbol>
+ <symbol
+ id="note_170x50"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title21">UML Note (170 x 50 px)</title>
+ <path
+ d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10"
+ id="path23" />
+ </symbol>
+ <!-- UML states (used for buffers) -->
+ <symbol
+ id="state_300x120">
+ <title
+ id="title26">UML State (300x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="300"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect28" />
+ </symbol>
+ <symbol
+ id="state_350x120">
+ <title
+ id="title31">UML State (350x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="350"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect33" />
+ </symbol>
+ <!-- Discs -->
+ <symbol
+ id="disc"
+ stroke="blue"
+ fill="none">
+ <title
+ id="title36">Disc</title>
+ <ellipse
+ cx="51"
+ cy="13"
+ rx="50"
+ ry="12"
+ id="ellipse38" />
+ <!-- top -->
+ <path
+ d="M 1,13 v 60"
+ id="path40" />
+ <!-- left -->
+ <path
+ d="M 101,13 v 60"
+ id="path42" />
+ <!-- right -->
+ <path
+ d="M 1,73 A 50, 12, 0, 0, 0, 101,73"
+ id="path44" />
+ <!-- bottom -->
+ </symbol>
+ <!-- Laptop -->
+ <symbol
+ id="laptop"
+ stroke="black"
+ fill="none">
+ <title
+ id="title47">Laptop</title>
+ <path
+ d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54"
+ id="path49" />
+ <rect
+ x="23"
+ y="3"
+ width="48"
+ height="34"
+ id="rect51" />
+ <!-- symbolize some lines -->
+ <path
+ d="M 30,10 h 20"
+ id="path53" />
+ <path
+ d="M 30,15 h 25"
+ id="path55" />
+ <path
+ d="M 30,20 h 10"
+ id="path57" />
+ <path
+ d="M 30,30 h 20"
+ id="path59" />
+ <!-- symbolize keyboard -->
+ <path
+ d="M 25,50 h 45 l 2,2 h -50 z "
+ id="path61" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path64" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path67" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect72" />
+ <!-- caption, client side -->
+ <text
+ x="15"
+ y="40"
+ class="text_big"
+ id="text74">Client</text>
+ <text
+ x="140"
+ y="40"
+ class="text_big"
+ id="text76">Server</text>
+ <use
+ xlink:href="#laptop"
+ x="5"
+ y="210"
+ id="use78" />
+ <!-- individual memory -->
+ <g
+ transform="translate(130, 70)"
+ id="g96">
+ <use
+ xlink:href="#state_350x120"
+ x="0"
+ y="0"
+ id="use80" />
+ <text
+ x="5"
+ y="20"
+ class="text_normal"
+ id="text82">maintenance_work_mem (per connection)</text>
+ <text
+ x="5"
+ y="45"
+ class="text_normal"
+ id="text84">work_mem (per query operation)</text>
+ <text
+ x="5"
+ y="70"
+ class="text_normal"
+ id="text86">autovacuum_work_mem (per worker process)</text>
+ <text
+ x="5"
+ y="95"
+ class="text_normal"
+ id="text88">temp_buffer (per connection)</text>
+ <text
+ x="5"
+ y="110"
+ class="text_normal"
+ id="text90">...</text>
+ <use
+ xlink:href="#note_200x20"
+ x="140"
+ y="-15"
+ id="use92" />
+ <text
+ x="150"
+ y="0"
+ class="text_comment"
+ id="text94">Individual Memory</text>
+ </g>
+ <!-- shared memory -->
+ <g
+ transform="translate(520, 70)"
+ id="g110">
+ <use
+ xlink:href="#state_300x120"
+ x="0"
+ y="0"
+ id="use98" />
+ <text
+ x="10"
+ y="30"
+ class="text_normal"
+ id="text100">shared_buffers (heap and index)</text>
+ <text
+ x="10"
+ y="70"
+ class="text_normal"
+ id="text102">wal_buffers (WAL records)</text>
+ <text
+ x="10"
+ y="100"
+ class="text_normal"
+ id="text104">...</text>
+ <use
+ xlink:href="#note_250x20"
+ x="40"
+ y="-15"
+ id="use106" />
+ <text
+ x="50"
+ y="0"
+ class="text_comment"
+ id="text108">Shared Memory (per Instance)</text>
+ </g>
+ <!-- postmaster -->
+ <g
+ transform="translate(180, 215)"
+ id="g116">
+ <rect
+ width="250"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect112" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text114">Postmaster</text>
+ </g>
+ <path
+ d="M 90,230 h 75"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path118" />
+ <g
+ transform="translate(140, 230)"
+ id="g124">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle120" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text122">1</text>
+ </g>
+ <!-- backend processes -->
+ <g
+ transform="translate(150, 315)"
+ id="g134">
+ <rect
+ width="370"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect126" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text128">Backend processes (one per connection)</text>
+ <path
+ d="M 5,0 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path130" />
+ <path
+ d="M 10,-5 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path132" />
+ </g>
+ <path
+ d="M 90,240 153,303"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path136" />
+ <g
+ transform="translate(140, 290)"
+ id="g142">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle138" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text140">3</text>
+ </g>
+ <!-- connection between postmaster and backend processes -->
+ <path
+ d="M 360,250 v 50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path144" />
+ <g
+ transform="translate(180, 255)"
+ id="g150">
+ <use
+ xlink:href="#note_250x20"
+ id="use146" />
+ <text
+ x="10"
+ y="15"
+ class="text_comment"
+ id="text148">Creates backend processes</text>
+ </g>
+ <g
+ transform="translate(360, 281)"
+ id="g156">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle152" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text154">2</text>
+ </g>
+ <!-- backend process' access to individual memory -->
+ <path
+ d="M 460,300 v -100"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path158" />
+ <!-- its access to shared buffers and WAL buffers -->
+ <path
+ d="M 498,300 v -205 h 30"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path160" />
+ <path
+ d="M 508,300 v -165 h 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path162" />
+ <!-- WAL writer -->
+ <g
+ transform="translate(550, 220)"
+ id="g168">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect164" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text166">WAL Writer</text>
+ </g>
+ <path
+ d="M 590,150 v 65"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path170" />
+ <path
+ d="M 590,255 v 230"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path172" />
+ <!-- Checkpoiner -->
+ <g
+ transform="translate(610, 340)"
+ id="g178">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect174" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text176">Checkpointer</text>
+ </g>
+ <path
+ d="M 740,110 v 220"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path180" />
+ <path
+ d="M 605,355 h -130 v 130"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path182" />
+ <path
+ d="M 700,330 v -180"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path184" />
+ <g
+ transform="translate(570, 330)"
+ id="g192">
+ <use
+ xlink:href="#note_100x35"
+ x="50"
+ y="-50"
+ id="use186" />
+ <text
+ x="60"
+ y="-35"
+ class="text_comment"
+ id="text188">Checkpoint</text>
+ <text
+ x="60"
+ y="-20"
+ class="text_comment"
+ id="text190">Record</text>
+ </g>
+ <!-- BG writer -->
+ <g
+ transform="translate(610, 380)"
+ id="g198">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect194" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text196">Background Writer</text>
+ </g>
+ <path
+ d="M 770,110 v 260"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path200" />
+ <path
+ d="M 605,395 h -120 v 90"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path202" />
+ <!-- Archiver -->
+ <g
+ transform="translate(610, 420)"
+ id="g208">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect204" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text206">WAL Archiver</text>
+ </g>
+ <path
+ d="M 620,485 l 30,-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path210" />
+ <path
+ d="M 690,455 l 30, 30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path212" />
+ <!-- Vacuum -->
+ <g
+ transform="translate(135, 380)"
+ id="g222">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect214" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text216">Autovacuum</text>
+ <path
+ d="M 5,0 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path218" />
+ <path
+ d="M 10,-5 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path220" />
+ </g>
+ <!-- Log Writer -->
+ <g
+ transform="translate(135, 430)"
+ id="g228">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect224" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text226">Logger</text>
+ </g>
+ <!-- Stats Collector -->
+ <g
+ transform="translate(290, 370)"
+ id="g234">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect230" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text232">Stats Collector</text>
+ </g>
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g
+ transform="translate(145, 490)"
+ id="g244">
+ <use
+ xlink:href="#disc"
+ id="use236" />
+ <text
+ x="35"
+ y="45"
+ class="text_normal"
+ id="text238">Log</text>
+ <text
+ x="20"
+ y="60"
+ class="text_small"
+ id="text240">text lines,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text242">sequential</text>
+ </g>
+ <path
+ d="M 195,465 v 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path246" />
+ <g
+ transform="translate(410, 490)"
+ id="g258">
+ <use
+ xlink:href="#disc"
+ id="use248" />
+ <text
+ x="10"
+ y="40"
+ class="text_normal"
+ id="text250">Heap and</text>
+ <text
+ x="25"
+ y="55"
+ class="text_normal"
+ id="text252">Index</text>
+ <text
+ x="15"
+ y="70"
+ class="text_small"
+ id="text254">binary blocks,</text>
+ <text
+ x="30"
+ y="80"
+ class="text_small"
+ id="text256">random</text>
+ </g>
+ <path
+ d="M 450,485 v -135"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path260" />
+ <g
+ transform="translate(295, 420)"
+ id="g270">
+ <use
+ xlink:href="#note_170x50"
+ id="use262" />
+ <text
+ x="5"
+ y="15"
+ class="text_comment"
+ id="text264">Read heap and index</text>
+ <text
+ x="5"
+ y="30"
+ class="text_comment"
+ id="text266">pages and transfer</text>
+ <text
+ x="5"
+ y="45"
+ class="text_comment"
+ id="text268">them to shared_buffers</text>
+ </g>
+ <g
+ transform="translate(550, 490)"
+ id="g280">
+ <use
+ xlink:href="#disc"
+ id="use272" />
+ <text
+ x="30"
+ y="45"
+ class="text_normal"
+ id="text274">WAL</text>
+ <text
+ x="10"
+ y="60"
+ class="text_small"
+ id="text276">binary records,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text278">sequential</text>
+ </g>
+ <g
+ transform="translate(690, 490)"
+ id="g288">
+ <use
+ xlink:href="#disc"
+ id="use282" />
+ <text
+ x="16"
+ y="45"
+ class="text_normal"
+ id="text284">Archived</text>
+ <text
+ x="36"
+ y="60"
+ class="text_normal"
+ id="text286">WAL</text>
+ </g>
+ <!-- boarder between client and server side -->
+ <path
+ d="M 110,20 v 550"
+ stroke="black"
+ fill="none"
+ id="path290" />
+ <g
+ transform="translate(123, 190) rotate(90)"
+ id="g296">
+ <use
+ xlink:href="#note_200x20"
+ id="use292" />
+ <text
+ class="text_comment"
+ x="10"
+ y="15"
+ id="text294">Via TCP/IP or socket</text>
+ </g>
+ <!-- right side -->
+ <g
+ transform="translate(850, 0) rotate(90)"
+ id="g304">
+ <text
+ class="text_big"
+ x="95"
+ id="text298">RAM</text>
+ <text
+ class="text_big"
+ x="250"
+ id="text300">PROCESSES</text>
+ <text
+ class="text_big"
+ x="500"
+ id="text302">FILES</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-raw.svg b/doc/src/sgml/images/ram-proc-file-raw.svg
new file mode 100644
index 0000000000..aec5811c54
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-raw.svg
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="600px"
+ viewBox="0 0 900 600">
+
+ <title>PG Overall Server Architecture</title>
+
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Some notes in different sizes -->
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>UML Note (200 x 20 px)</title>
+ <path d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>UML Note (250 x 20 px)</title>
+ <path d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>UML Note (100 x 35 px)</title>
+ <path d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>UML Note (170 x 50 px)</title>
+ <path d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- UML states (used for buffers) -->
+ <symbol id="state_300x120">
+ <title>UML State (300x120)</title>
+ <rect x="0" y="0" width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>UML State (350x120)</title>
+ <rect x="0" y="0" width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- Discs -->
+ <symbol id="disc" stroke="blue" fill="none" >
+ <title>Disc</title>
+ <ellipse cx="51" cy="13" rx="50" ry="12" /> <!-- top -->
+ <path d="M 1,13 v 60" /> <!-- left -->
+ <path d="M 101,13 v 60" /> <!-- right -->
+ <path d="M 1,73 A 50, 12, 0, 0, 0, 101,73" /> <!-- bottom -->
+ </symbol>
+
+ <!-- Laptop -->
+ <symbol id="laptop" stroke="black" fill="none" >
+ <title>Laptop</title>
+ <path d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54" />
+ <rect x="23" y="3" width="48" height="34" />
+ <!-- symbolize some lines -->
+ <path d="M 30,10 h 20" />
+ <path d="M 30,15 h 25" />
+ <path d="M 30,20 h 10" />
+ <path d="M 30,30 h 20" />
+ <!-- symbolize keyboard -->
+ <path d="M 25,50 h 45 l 2,2 h -50 z " />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption, client side -->
+ <text x="15" y="40" class="text_big">Client</text>
+ <text x="140" y="40" class="text_big">Server</text>
+ <use xlink:href="#laptop" x="5" y="210" />
+
+
+ <!-- individual memory -->
+ <g transform="translate(130, 70)">
+ <use xlink:href="#state_350x120" x="0" y="0" />
+ <text x="5" y="20" class="text_normal">maintenance_work_mem (per connection)</text>
+ <text x="5" y="45" class="text_normal">work_mem (per query operation)</text>
+ <text x="5" y="70" class="text_normal">autovacuum_work_mem (per worker process)</text>
+ <text x="5" y="95" class="text_normal">temp_buffer (per connection)</text>
+ <text x="5" y="110" class="text_normal">...</text>
+ <use xlink:href="#note_200x20" x="140" y="-15" />
+ <text x="150" y="0" class="text_comment">Individual Memory</text>
+ </g>
+
+ <!-- shared memory -->
+ <g transform="translate(520, 70)">
+ <use xlink:href="#state_300x120" x="0" y="0" />
+ <text x="10" y="30" class="text_normal">shared_buffers (heap and index)</text>
+ <text x="10" y="70" class="text_normal">wal_buffers (WAL records)</text>
+ <text x="10" y="100" class="text_normal">...</text>
+ <use xlink:href="#note_250x20" x="40" y="-15" />
+ <text x="50" y="0" class="text_comment">Shared Memory (per Instance)</text>
+ </g>
+
+ <!-- postmaster -->
+ <g transform="translate(180, 215)">
+ <rect width="250" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Postmaster</text>
+ </g>
+ <path d="M 90,230 h 75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 230)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">1</text>
+ </g>
+
+ <!-- backend processes -->
+ <g transform="translate(150, 315)">
+ <rect width="370" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Backend processes (one per connection)</text>
+ <path d="M 5,0 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <path d="M 90,240 153,303" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 290)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">3</text>
+ </g>
+
+ <!-- connection between postmaster and backend processes -->
+ <path d="M 360,250 v 50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180, 255)">
+ <use xlink:href="#note_250x20" />
+ <text x="10" y="15" class="text_comment">Creates backend processes</text>
+ </g>
+ <g transform="translate(360, 281)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">2</text>
+ </g>
+
+ <!-- backend process' access to individual memory -->
+ <path d="M 460,300 v -100" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <!-- its access to shared buffers and WAL buffers -->
+ <path d="M 498,300 v -205 h 30" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M 508,300 v -165 h 20" stroke="black" fill="none"
+ marker-end="url(#arrowhead_end)"/>
+
+ <!-- WAL writer -->
+ <g transform="translate(550, 220)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Writer</text>
+ </g>
+ <path d="M 590,150 v 65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 590,255 v 230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Checkpoiner -->
+ <g transform="translate(610, 340)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Checkpointer</text>
+ </g>
+ <path d="M 740,110 v 220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,355 h -130 v 130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 700,330 v -180" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570, 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50" />
+ <text x="60" y="-35" class="text_comment">Checkpoint</text>
+ <text x="60" y="-20" class="text_comment">Record</text>
+ </g>
+
+ <!-- BG writer -->
+ <g transform="translate(610, 380)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Background Writer</text>
+ </g>
+ <path d="M 770,110 v 260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,395 h -120 v 90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Archiver -->
+ <g transform="translate(610, 420)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Archiver</text>
+ </g>
+ <path d="M 620,485 l 30,-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 690,455 l 30, 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Vacuum -->
+ <g transform="translate(135, 380)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Autovacuum</text>
+ <path d="M 5,0 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <!-- Log Writer -->
+ <g transform="translate(135, 430)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Logger</text>
+ </g>
+
+ <!-- Stats Collector -->
+ <g transform="translate(290, 370)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Stats Collector</text>
+ </g>
+
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g transform="translate(145, 490)">
+ <use xlink:href="#disc" />
+ <text x="35" y="45" class="text_normal">Log</text>
+ <text x="20" y="60" class="text_small">text lines,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+ <path d="M 195,465 v 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(410, 490)">
+ <use xlink:href="#disc" />
+ <text x="10" y="40" class="text_normal">Heap and</text>
+ <text x="25" y="55" class="text_normal">Index</text>
+ <text x="15" y="70" class="text_small">binary blocks,</text>
+ <text x="30" y="80" class="text_small">random</text>
+ </g>
+ <path d="M 450,485 v -135" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(295, 420)">
+ <use xlink:href="#note_170x50" />
+ <text x="5" y="15" class="text_comment">Read heap and index</text>
+ <text x="5" y="30" class="text_comment">pages and transfer</text>
+ <text x="5" y="45" class="text_comment">them to shared_buffers</text>
+ </g>
+
+ <g transform="translate(550, 490)">
+ <use xlink:href="#disc" />
+ <text x="30" y="45" class="text_normal">WAL</text>
+ <text x="10" y="60" class="text_small">binary records,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+
+ <g transform="translate(690, 490)">
+ <use xlink:href="#disc" />
+ <text x="16" y="45" class="text_normal">Archived</text>
+ <text x="36" y="60" class="text_normal">WAL</text>
+ </g>
+
+ <!-- boarder between client and server side -->
+ <path d="M 110,20 v 550" stroke="black" fill="none" />
+ <g transform="translate(123, 190) rotate(90)">
+ <use xlink:href="#note_200x20" />
+ <text class="text_comment" x="10" y ="15">Via TCP/IP or socket</text>
+ </g>
+
+ <!-- right side -->
+ <g transform="translate(850, 0) rotate(90)">
+ <text class="text_big" x="95">RAM</text>
+ <text class="text_big" x="250">PROCESSES</text>
+ <text class="text_big" x="500">FILES</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink-svgo.svg b/doc/src/sgml/images/wraparound-ink-svgo.svg
new file mode 100644
index 0000000000..9882d2be23
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink-svgo.svg
@@ -0,0 +1,40 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="280" viewBox="0 0 850 280">
+ <title>
+ Cyclic usage of XIDs
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="370" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ Cyclic usage of XIDs modulo 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan>
+ </text>
+ <g fill="none" transform="translate(170 150)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_095" startOffset="30.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="30%">(1)</textPath> <textPath xlink:href="#Path_095" startOffset="45.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(2)</textPath> <textPath xlink:href="#Path_095" startOffset="50.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="50%">(3)</textPath> <textPath xlink:href="#Path_095" startOffset="62.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="62%">(4)</textPath>
+ </text>
+ </g>
+ <g class="text_normal">
+ <text transform="translate(400 130)">
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25" transform="translate(400 130)">
+ 1: oldest <tspan font-weight="700">active</tspan> xid (pg_stat_activity.backend_xmin)
+ </text>
+ <text y="50" transform="translate(400 130)">
+ 2: xmin of one row version
+ </text>
+ <text y="75" transform="translate(400 130)">
+ 3: xmax of the same row version
+ </text>
+ <text y="100" transform="translate(400 130)">
+ 4: jungest xid (txid_current)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink.svg b/doc/src/sgml/images/wraparound-ink.svg
new file mode 100644
index 0000000000..a9c51f4e43
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="280px"
+ viewBox="0 0 850 280"
+ id="svg1072"
+ sodipodi:docname="wraparound-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata1076">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Cyclic usage of XIDs</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1193"
+ inkscape:window-height="788"
+ id="namedview1074"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="140"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg1072" />
+ <title
+ id="title1009">Cyclic usage of XIDs</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style1011">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs1016">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect1018" />
+ <text
+ class="text_big"
+ x="370"
+ y="40"
+ id="text1024">Cyclic usage of XIDs modulo 2
+ <tspan
+ dy="-5"
+ id="tspan1020">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1022">32</tspan>
+</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 150)"
+ id="g1052">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle1026" />
+ <text
+ class="text_normal"
+ id="text1050">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath1028">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath1030">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath1032">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="30.5%"
+ id="textPath1034">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="30%"
+ id="textPath1036">(1)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="45.5%"
+ id="textPath1038">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath1040">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="50.5%"
+ id="textPath1042">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="50%"
+ id="textPath1044">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="62.5%"
+ id="textPath1046">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="62%"
+ id="textPath1048">(4)</textPath>
+ </text>
+ </g>
+ <g
+ class="text_normal"
+ transform="translate(400 130)"
+ id="g1070">
+ <text
+ id="text1058">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan1054">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1056">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text1062">1: oldest <tspan
+ style="font-weight:bold"
+ id="tspan1060">active</tspan>
+ xid (pg_stat_activity.backend_xmin)</text>
+ <text
+ y="50"
+ id="text1064">2: xmin of one row version</text>
+ <text
+ y="75"
+ id="text1066">3: xmax of the same row version</text>
+ <text
+ y="100"
+ id="text1068">4: jungest xid (txid_current)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-raw.svg b/doc/src/sgml/images/wraparound-raw.svg
new file mode 100644
index 0000000000..9406f52970
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-raw.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="280px"
+ viewBox="0 0 850 280" >
+
+ <title>Cyclic usage of XIDs</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="370" y="40">Cyclic usage of XIDs modulo 2
+ <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan></text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 150)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_095" startOffset="30.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="30%" >(1)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="45.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(2)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="50.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="50%" >(3)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="62.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="62%" >(4)</textPath>
+ </text>
+ </g>
+
+ <g class="text_normal" transform="translate(400 130)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: oldest <tspan style="font-weight:bold">active</tspan> xid (pg_stat_activity.backend_xmin)</text>
+ <text y="50">2: xmin of one row version</text>
+ <text y="75">3: xmax of the same row version</text>
+ <text y="100">4: jungest xid (txid_current)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 730d5fdc34..e9e9f9495f 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -248,6 +248,7 @@ break is not needed in a wider output rendering.
</para>
</partintro>
+ &architecture;
&arch-dev;
&catalogs;
&protocol;
diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml
index 9bb5c1a6d5..8751410179 100644
--- a/doc/src/sgml/start.sgml
+++ b/doc/src/sgml/start.sgml
@@ -53,7 +53,7 @@
<sect1 id="tutorial-arch">
- <title>Architectural Fundamentals</title>
+ <title>Client/Server Model</title>
<para>
Before we proceed, you should understand the basic
@@ -68,34 +68,55 @@
client/server model. A <productname>PostgreSQL</productname>
session consists of the following cooperating processes
(programs):
+ </para>
- <itemizedlist>
- <listitem>
- <para>
- A server process, which manages the database files, accepts
- connections to the database from client applications, and
- performs database actions on behalf of the clients. The
- database server program is called
- <filename>postgres</filename>.
- <indexterm><primary>postgres</primary></indexterm>
- </para>
- </listitem>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A process at the server site with the name
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ <indexterm><primary>postgres</primary></indexterm>
+ It accepts connection requests from client applications, starts
+ (<quote>forks</quote>) a new <glossterm linkend="glossary-backend">
+ Backend process</glossterm> for each of them, and passes
+ the connection to it. From that point on, the client and the new
+ <firstterm>Backend process</firstterm>
+ communicate directly without intervention by the original
+ <firstterm>postgres</firstterm> process. Thus, the
+ <firstterm>postgres</firstterm> process is always running, waiting
+ for new client connections, whereas clients and associated
+ <firstterm>Backend processes</firstterm> come and go.
+ (All of this is of course invisible to the user. We only mention it
+ here for completeness.)
+ </para>
+ </listitem>
- <listitem>
- <para>
- The user's client (frontend) application that wants to perform
- database operations. Client applications can be very diverse
- in nature: a client could be a text-oriented tool, a graphical
- application, a web server that accesses the database to
- display web pages, or a specialized database maintenance tool.
- Some client applications are supplied with the
- <productname>PostgreSQL</productname> distribution; most are
- developed by users.
- </para>
- </listitem>
+ <listitem>
+ <para>
+ A group of processes at the server site, the <glossterm
+ linkend="glossary-instance">instance</glossterm>, to which also the
+ <firstterm>postgres</firstterm> process belongs. Their duties are
+ handling of central, common database activities like file access,
+ vacuum, <glossterm linkend="glossary-checkpoint">checkpoints</glossterm>,
+ replication, and more. The mentioned <firstterm>Backend processes</firstterm>
+ delegate those actions to the <firstterm>instance</firstterm>.
+ </para>
+ </listitem>
- </itemizedlist>
- </para>
+ <listitem>
+ <para>
+ The user's client (frontend) application that wants to perform
+ database operations. Client applications can be very diverse
+ in nature: a client could be a text-oriented tool, a graphical
+ application, a web server that accesses the database to
+ display web pages, or a specialized database maintenance tool.
+ Some client applications are supplied with the
+ <productname>PostgreSQL</productname> distribution; most are
+ developed by users.
+ </para>
+ </listitem>
+
+ </itemizedlist>
<para>
As is typical of client/server applications, the client and the
Removing -docs as moderation won’t let me cross-post.
On Monday, October 26, 2020, David G. Johnston <david.g.johnston@gmail.com>
wrote:
Show quoted text
On Monday, October 26, 2020, Jürgen Purtz <juergen@purtz.de> wrote:
On 21.10.20 22:33, David G. Johnston wrote:
Two, I find the amount of detail being provided here to be on the
too-much side. A bit more judicious use of links into the appropriate
detail chapters seems warranted.The patch is intended to give every interested person an overall
impression of the chapter within its new position. Because it has moved
from part 'Tutorial' to 'Internals' the text should be very accurate
concerning technical issues - like all the other chapters in this part. A
tutorial chapter has a more superficial nature.Haven’t reviewed the patches yet but...
I still think that my comment applies even with the move to internals.
The value here is putting together a coherent narrative and making deeper
implementation details accessible. If those details are already covered
elsewhere in the documentation (not source code) links should be given
serious consideration.David J.
Import Notes
Reply to msg id not found: CAKFQuwbqiZ4Er_e21oXt8J_JDyNucLMcW7murkMr0vpTy10RA@mail.gmail.com
On 26.10.20 15:53, David G. Johnston wrote:
Removing -docs as moderation won’t let me cross-post.
On Monday, October 26, 2020, David G. Johnston
<david.g.johnston@gmail.com <mailto:david.g.johnston@gmail.com>> wrote:On Monday, October 26, 2020, Jürgen Purtz <juergen@purtz.de
<mailto:juergen@purtz.de>> wrote:On 21.10.20 22:33, David G. Johnston wrote:
Two, I find the amount of detail being provided here to be on
the too-much side. A bit more judicious use of links into
the appropriate detail chapters seems warranted.The patch is intended to give every interested person an
overall impression of the chapter within its new position.
Because it has moved from part 'Tutorial' to 'Internals' the
text should be very accurate concerning technical issues -
like all the other chapters in this part. A tutorial chapter
has a more superficial nature.Haven’t reviewed the patches yet but...
I still think that my comment applies even with the move to
internals. The value here is putting together a coherent
narrative and making deeper implementation details accessible. If
those details are already covered elsewhere in the documentation
(not source code) links should be given serious consideration.David J.
Please find the new patch in the attachment after integrating David's
suggestions: a) versus the last patch and b) versus master.
Notably it contains
* nearly all of his suggestions (see sgml file for comments 'DGJ')
* reduction of <firstterm>. This was a hangover from the
pre-glossary-times. I tried to emphasis standard terms. This is no
longer necessary because nowadays they are clearly defined in the
glossary.
--
J. Purtz
Attachments:
0009-architecture-vs-0008.patchtext/x-patch; charset=UTF-8; name=0009-architecture-vs-0008.patchDownload
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
index b6c0eb4a31..e547a87d08 100644
--- a/doc/src/sgml/architecture.sgml
+++ b/doc/src/sgml/architecture.sgml
@@ -13,42 +13,26 @@
<sect1 id="tutorial-ram-proc-file">
<title>Collaboration of Processes, RAM, and Files</title>
<para>
- In a client/server architecture
- clients do not have direct access to stored data. Instead,
- they send requests to the server and receive
- the requested data in response. In the case of
- <productname>PostgreSQL</productname>, the server launches a
- single process for each connected client, referred to as a
- <glossterm linkend="glossary-backend">Backend process</glossterm>.
-
-
- <!-- DGJ: this whole next paragraph bothers me but I cannot justify
- simply removing it nor have a possibly better suggestion.
- In particular I disagree with categorizing this is a
- "close" and "tightly-coupled" relationship -->
-
-
- It acts in close cooperation with the
- <glossterm linkend="glossary-instance">instance</glossterm> which
- is a group of tightly coupled server-side processes plus a
- <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>
- area located in RAM.
- Notably, PostgreSQL does not utilize application threading within its
- implementation.
- </para>
-
-
- <!-- DGJ: I've gotten the impression firstterm
- is overused, probably as a result of copy-paste -->
-
-
- <para>
- During <firstterm>instance</firstterm> startup time, the
- <glossterm linkend="glossary-postmaster">Postmaster</glossterm>
- process loads the
- configuration files, allocates
- <firstterm>Shared Memory</firstterm>,
- and starts supporting background processes:
+ In a client/server architecture clients do not have direct access
+ to database files and the data stored in them. Instead, they send
+ requests to the server and receive the requested data in the response.
+ In the case of <productname>PostgreSQL</productname>, the server
+ launches a single process for each client connection, referred to as a
+ <glossterm linkend="glossary-backend">Backend</glossterm> process.
+ Those Backend processes handle the client's requests by acting on the
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>.
+ This leads to other activities (file access, WAL, vacuum, ...) of the
+ <glossterm linkend="glossary-instance">Instance</glossterm>. The
+ Instance is a group of server-side processes acting on a common
+ Shared Memory. Notably, PostgreSQL does not utilize application
+ threading within its implementation.
+ </para>
+
+ <para>
+ The first step in an Instance start is the start of the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ He loads the configuration files, allocates Shared Memory, and
+ starts the other processes of the Instance:
<glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
<glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
<glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
@@ -56,8 +40,11 @@
<glossterm linkend="glossary-autovacuum">Autovacuum</glossterm>,
<glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
<glossterm linkend="glossary-logger">Logger</glossterm>, and more.
- <xref linkend="tutorial-ram-proc-file-figure"/> visualizes
- the main aspects of their collaboration.
+ Later, the Postmaster starts
+ <glossterm linkend="glossary-backend">Backend</glossterm> processes
+ which communicate with clients and handle their requests.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes the processes
+ of an Instance and the main aspects of their collaboration.
</para>
<figure id="tutorial-ram-proc-file-figure">
@@ -77,155 +64,110 @@
</figure>
<para>
-
-
- <!-- DGJ: This is detailed, but wrong. Either use less detail or correct detail.
- See header of postmaster.c
- -->
-
-
When a client application tries to connect to a
<glossterm linkend="glossary-database">database</glossterm>,
- this request is handled initially by the
- <firstterm>Postmaster</firstterm> process. It checks authorization,
- starts a new <firstterm>Backend process</firstterm>,
- and instructs the client application to connect to it. All
- further client requests go to this process and are handled
- by it.
+ this request is handled initially by the Postmaster. He
+ starts a new Backend process and instructs the client
+ application to connect to it. All further client requests
+ go to this process and are handled by it.
</para>
<para>
Client requests like <command>SELECT</command> or
<command>UPDATE</command> usually lead to the
- necessity to read or write some data. In a first attempt
- the client's <firstterm>Backend process</firstterm> tries
- to get the information out of <firstterm>Shared
- Memory</firstterm>. This <firstterm>Shared
- Memory</firstterm> is a mirror of parts of the
- <glossterm linkend="glossary-heap">heap</glossterm> and
- <glossterm linkend="glossary-index">index</glossterm> files.
- Because files are often larger than memory, it's likely that
- the desired information is not (completely) available
- in RAM. In this case the <firstterm>Backend process</firstterm>
- must transfer additional file pages to
- <firstterm>Shared Memory</firstterm>. Files are physically
- organized in pages. Every transfer between files and
- RAM is performed in units of complete pages; such transfers
- do not change the size or layout of pages.
- </para>
-
- <para>
- Reading file pages is much slower than reading
- RAM. This is the primary motivation for the usage of
- <firstterm>Shared Memory</firstterm>. As soon as one
- of the <firstterm>Backend processes</firstterm> has
- read pages into memory, those pages become available for all
- other <firstterm>Backend processes</firstterm> for direct
- access in RAM.
- </para>
-
- <para>
- <firstterm>Shared Memory</firstterm> is limited in size.
- Sooner or later, it becomes necessary to overwrite old RAM
- pages. As long as the content of such pages hasn't
- changed, this is not a problem. But in
- <firstterm>Shared Memory</firstterm> also write
- actions take place
- — performed by any of the <firstterm>Backend
- processes</firstterm> (or an
- <firstterm>autovacuum</firstterm> process,
- or other processes). Such modified pages are called
- <firstterm>dirty pages</firstterm>.
- Before <firstterm>dirty pages</firstterm> can be overwritten,
- they must be written back to disk. This is a two-step process.
- </para>
+ necessity to read or write some data. This is carried out
+ by the client's backend process. Reads involve a page-level
+ cache housed in Shared Memory (for details see:
+ <xref linkend="sysvipc"/>) for the benefit of all processes
+ in the instance. Writes also involve this cache, in additional
+ to a journal, called a write-ahead-log or WAL.
+ </para>
+
+ <para>
+ Shared Memory is limited in size. Thus, it becomes necessary
+ to evict pages. As long as the content of such pages hasn't
+ changed, this is not a problem. But in Shared Memory also
+ write actions take place. Modified pages are called dirty
+ pages or dirty buffers and before they can be evicted they
+ must be written back to disk. This happens regularly by the
+ Background Writer and the Checkpointer process to ensure
+ that the disk version of the pages are kept up-to-date.
+ The synchronisation from RAM to disk consists of two steps.
+ </para>
+
+<!-- DGJ: WAL should already be done well before page
+ eviction/overwriting comes into play.
+ This is good material but seems misplaced.
+ JuP: Really misplaced? Don't think so.
+-->
<para>
First, whenever the content of a page changes, a
<glossterm linkend="glossary-wal-record">WAL record</glossterm>
- is created out
- of the delta-information (difference between the old and
- the new content) and stored in another area of
- <firstterm>Shared Memory</firstterm>. These
- <firstterm>WAL records</firstterm> are read by the
- <firstterm>WAL Writer</firstterm> process,
- which runs in parallel to the <firstterm>Backend
- processes</firstterm> and other processes of
- the <firstterm>Instance</firstterm>. It writes
- the continuously arising <firstterm>WAL records</firstterm> to
- the end of the current
+ is created out of the delta-information (difference between the
+ old and the new content) and stored in another area of
+ Shared Memory. The parallel running WAL Writer process
+ reads them and appends them to the end of the current
<glossterm linkend="glossary-wal-record">WAL file</glossterm>.
- Because this writing is sequential, it is much
- faster than the more or less random access
- to data files with <firstterm>heap</firstterm>
- and <firstterm>index</firstterm> information.
- As mentioned, this WAL-writing happens
- in an independent process. All
- <firstterm>WAL records</firstterm> created out of one
- <firstterm>dirty page</firstterm> must be transferred
- to disk before the <firstterm>dirty page</firstterm>
- itself can be transferred to disk.
- </para>
-
- <para>
- Second, the transfer of <firstterm>dirty buffers</firstterm>
- from <firstterm>Shared Memory</firstterm> to file must
- take place. This is the primary task of the
- <firstterm>Background Writer</firstterm> process. Because
- I/O activities can block other processes significantly,
- it starts periodically and acts only for a short period.
- Doing so, its expensive I/O activities are spread over
- time, avoiding debilitating I/O peaks. Also, the <firstterm>
- Checkpointer</firstterm> process transfers
- <firstterm>dirty buffers</firstterm> to file —
- see next paragraph.
- </para>
-
- <para>
- The <firstterm>Checkpointer</firstterm> creates
+ Such sequential writes are much faster than writes to random
+ positions of heap and index files. All WAL records created
+ out of one dirty page must be transferred to disk before the
+ dirty page itself can be transferred to disk in the second step.
+ </para>
+
+ <para>
+ Second, the transfer of dirty buffers from Shared Memory to
+ files must take place. This is the primary task of the
+ Background Writer process. Because I/O activities can block
+ other processes significantly, it starts periodically and
+ acts only for a short period. Doing so, its extensive (and
+ expensive) I/O activities are spread over time, avoiding
+ debilitating I/O peaks. Also, the Checkpointer process
+ transfers dirty buffers to file.
+ </para>
+
+ <para>
+ The Checkpointer creates
<glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
- A <firstterm>Checkpoint</firstterm>
- is a point in time when all older <firstterm>dirty buffers</firstterm>,
- all older <firstterm>WAL records</firstterm>, and
- finally a special <firstterm>Checkpoint record</firstterm>
- have been written and flushed to disk.
- After a <firstterm>Checkpoint</firstterm>, we say
- data files and <firstterm>WAL files</firstterm> are in sync.
- In case of a recovery (after a crash of the instance)
- it can be relied upon that the information of all
- <firstterm>WAL records</firstterm> preceding
- the last <firstterm>Checkpoint record</firstterm>
- were already integrated into the data files. This
- speeds up the recovery.
+ A Checkpoint is a point in time when all older dirty buffers,
+ all older WAL records, and finally a special Checkpoint record
+ have been written and flushed to disk. Heap and index files
+ on the one hand and WAL files on the other hand are in sync.
+ Previous WAL is no longer required. In other words,
+ a possibly occurring recovery, which integrates the delta
+ information of WAL into heap and index files, will happen
+ by replaying only WAL past the last recorded checkpoint
+ on top of the current heap and files. This speeds up recovery.
</para>
<para>
- As a result of data changes,
- <firstterm>WAL records</firstterm> arise and get written
- to <firstterm>WAL files</firstterm>.
- Those <firstterm>WAL files</firstterm> — in combination with
- a previously taken <firstterm>Base Backup</firstterm> —
- are necessary to restore a database after a crash of the
- disk on which data files have been stored. Therefore it is
- recommended to transfer a copy of the
- <firstterm> WAL files</firstterm>
- to a second, independent place. The purpose of the
- <firstterm>WAL Archiver</firstterm> process is to perform
- this copy action.
+ While the Checkpointer ensures that a running system can crash
+ and restart itself in a valid state, the administrator needs
+ to handle the case where the heap and files themselves become
+ corrupted (and possibly the locally written WAL, though that is
+ less common). The options and details are covered extensively
+ in the backup and restore section (<xref linkend="backup"/>).
+ For our purposes here, note just that the WAL Archiver process
+ can be enabled and configured to run a script on filled WAL
+ files — usually to copy them to a remote location.
</para>
+
+<!-- DGJ: after the heavy focus on client processes and data these two
+ seem to come out of left field. Skipping over for now.
+ JuP: Don't skip, we want to explain all elements of the graphic.
+-->
+
<para>
- The <firstterm>Statistics Collector</firstterm> collects
- counters about accesses to <firstterm>SQL objects</firstterm>
- like tables, rows, indexes, pages, and more. It stores the
- obtained information in system tables.
+ The Statistics Collector collects counters about accesses to
+ SQL objects like tables, rows, indexes, pages, and more. It
+ stores the obtained information in system tables.
</para>
<para>
- The <firstterm>Logger</firstterm> writes
- text lines about serious and less serious events which can happen
- during database access, e.g., wrong password, no permission,
- long-running queries, etc.
+ The Logger writes text lines about serious and less serious
+ events which can happen during database access, e.g., wrong
+ password, no permission, long-running queries, etc.
</para>
</sect1>
@@ -286,46 +228,40 @@
such as <literal>my_db</literal>, will be copied from the
<literal>template1</literal> database. Due to the unique
role of <literal>template0</literal> as the pristine original
- of all other databases, no client
- can connect to it.
+ of all other databases, no client can connect to it.
</para>
<para>
- Every database must contain <glossterm linkend="glossary-schema">
- at least one schema</glossterm> because
- schemas contain the other
- <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>.
- Schemas are namespaces for
- their SQL objects and ensure — with one
- exception — that within their scope, names are used only once across all
- types of SQL objects. E.g., it is not possible
+ Every database must contain at least one schema because all
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>
+ are contained in a schema.
+ Schemas are namespaces for their SQL objects and ensure
+ (with one exception) that within their scope names are used
+ only once across all types of SQL objects. E.g., it is not possible
to have a table <literal>employee</literal> and a view
- <literal>employee</literal> within the same
- schema. But it is possible to have
- two tables <literal>employee</literal> in different
- schemas. In this case, the two tables
+ <literal>employee</literal> within the same schema. But it is
+ possible to have two tables <literal>employee</literal> in
+ different schemas. In this case, the two tables
are separate objects and independent of each
other. The only exception to this cross-type uniqueness is that
<glossterm linkend="glossary-unique-constraint">unique constraints
- </glossterm> and the according <firstterm>unique index</firstterm>
- use the same name.
+ </glossterm> and the according unique index
+ (<xref linkend="indexes-unique"/>) use the same name.
</para>
<para>
Some schemas are predefined. <literal>public</literal>
- acts as the default schema and contains all
- <firstterm>SQL objects</firstterm> which are created
- within <literal>public</literal> or without using an explicit schema
- name. <literal>public</literal> should not contain user-defined
- SQL objects. Instead, it is recommended to
- create a separate schema that
- holds individual objects like application-specific tables or
- views. <literal>pg_catalog</literal> is a schema for all tables
- and views of the <glossterm linkend="glossary-system-catalog">
- System Catalog</glossterm>.
+ acts as the default schema and contains all SQL objects
+ which are created within <literal>public</literal> or
+ without using an explicit schema name. <literal>public</literal>
+ should not contain user-defined SQL objects. Instead, it is
+ recommended to create a separate schema that holds individual
+ objects like application-specific tables or views.
+ <literal>pg_catalog</literal> is a schema for all tables and views of the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
<literal>information_schema</literal> is a schema for several
- tables and views of the <firstterm>System Catalog</firstterm>
- in a way that conforms to the SQL standard.
+ tables and views of the System Catalog in a way that conforms
+ to the SQL standard.
</para>
<para>
@@ -334,11 +270,11 @@
view, index, constraint, sequence, function, procedure,
trigger, role, data type, operator, tablespace, extension,
foreign data wrapper</firstterm>, and more. A few of them, the
- <firstterm>Global SQL Objects</firstterm>,
- are outside of the strict hierarchy:
- All database names, all tablespace names, and all role names
- are automatically known and available throughout the
- cluster, independent from
+ <firstterm>Global SQL Objects</firstterm>, are outside of the
+ strict hierarchy: All <firstterm>database names</firstterm>,
+ all <firstterm>tablespace names</firstterm>, and all
+ <firstterm>role names</firstterm> are automatically known and
+ available throughout the cluster, independent from
the database or schema in which they where defined originally.
<xref linkend="tutorial-internal-objects-hierarchy-figure"/>
shows the relation between the object types.
@@ -369,7 +305,7 @@
<productname>PostgreSQL</productname> organizes long-lasting
data as well as volatile state information about transactions
or replication actions in the file system. Every
- <firstterm>Cluster</firstterm> has its root directory
+ <xref linkend="glossary-db-cluster"/> has its root directory
somewhere in the file system. In many cases, the environment
variable <literal>PGDATA</literal> points to this directory.
The example shown in
@@ -427,8 +363,8 @@
subdirectories, there are files containing information about
<glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
One type of such Global SQL Objects are
- <firstterm>tablespaces</firstterm>. In
- <literal>global</literal> there is information about
+ <glossterm linkend="glossary-tablespace">tablespaces</glossterm>.
+ In <literal>global</literal> there is information about
the tablespaces, not the tablespaces themselves.
</para>
@@ -443,14 +379,14 @@
<para>
The subdirectory <literal>pg_xact</literal> contains
information about the status of each transaction:
- in_progress, committed, aborted, or sub_committed.
+ <literal>in_progress</literal>, <literal>committed</literal>,
+ <literal>aborted</literal>, or <literal>sub_committed</literal>.
</para>
<para>
In <literal>pg_tblspc</literal>, there are symbolic links
- that point to directories containing such<firstterm>
- SQL objects</firstterm> that are created within
- tablespaces.
+ that point to directories containing such SQL objects
+ that are created within tablespaces.
</para>
<para>
@@ -474,7 +410,7 @@
<title>MVCC — Multiversion Concurrency Control</title>
<para>
- In most cases, <productname>PostgreSQL</productname> based applications
+ In most cases, <productname>PostgreSQL</productname> databases
support many clients at the same time. Therefore, it is necessary to
protect concurrently running requests from unwanted overwriting
of other's data as well as from reading inconsistent data. Imagine an
@@ -533,7 +469,7 @@
</para>
<para>
- The description in this chapter simplifies by omitting detail.
+ The description in this chapter simplifies by omitting some details.
When many transactions are running simultaneously, things can
get complicated. Sometimes transactions get aborted via
<command>ROLLBACK</command> immediately or after a lot of other activities, sometimes
@@ -644,7 +580,7 @@
xids grow, old row versions get out of scope over time.
If an old row version is no longer valid for ALL existing
transactions, it's called <firstterm>dead</firstterm>. The
- space occupied by all dead row versions is called
+ space occupied by dead row versions is part of the
<glossterm linkend="glossary-bloat">bloat</glossterm>.
</simpara>
</listitem>
@@ -680,13 +616,13 @@
<glossterm linkend="glossary-bloat">bloat</glossterm>.
This chapter explains how the SQL command
<command>VACUUM</command> and the automatically running
- <firstterm>autovacuum</firstterm> processes clean up
+ <firstterm>Autovacuum</firstterm> processes clean up
by eliminating bloat.
</para>
<note>
<para>
- <firstterm>Autovacuum</firstterm> runs automatically by
+ Autovacuum runs automatically by
default. Its default parameters as well as such for
<command>VACUUM</command> fit well for most standard
situations. Therefore a novice database manager can
@@ -696,30 +632,27 @@
</note>
<para>
- Client processes can issue the SQL command <command>VACUUM</command> at arbitrary
- points in time. DBAs do this when they recognize special situations,
- or they start it in batch jobs which run periodically.
- <firstterm>Autovacuum</firstterm> processes run as part of the
- <link linkend="glossary-instance">instance</link> at the server.
- There is a constantly running <firstterm>autovacuum</firstterm> daemon.
- It permanently controls the state of all databases based on values that
- are collected by the
+ Client processes can issue the SQL command <command>VACUUM</command>
+ at arbitrary points in time. DBAs do this when they recognize
+ special situations, or they start it in batch jobs which run
+ periodically. Autovacuum processes run as part of the
+ <link linkend="glossary-instance">Instance</link> at the server.
+ There is a constantly running Autovacuum daemon. It permanently
+ controls the state of all databases based on values that are collected by the
<link linkend="glossary-stats-collector">Statistics Collector</link>
- and starts <firstterm>autovacuum</firstterm> processes whenever it detects
+ and starts Autovacuum processes whenever it detects
certain situations. Thus, it's a dynamic behavior of
<productname>PostgreSQL</productname> with the intention to tidy
up — whenever it is appropriate.
</para>
<para>
- <command>VACUUM</command>, as well as
- <firstterm>autovacuum</firstterm>, don't just eliminate bloat.
- They perform additional tasks for minimizing future
+ <command>VACUUM</command>, as well as Autovacuum, don't just eliminate
+ bloat. They perform additional tasks for minimizing future
I/O activities of themselves as well as of other processes.
- This extra work can be done in a very efficient way
- since in most cases the expensive physical access to pages
- has taken place anyway to eliminate bloat.
- The additional operations are:
+ This extra work can be done in a very efficient way since in most
+ cases the expensive physical access to pages has taken place anyway
+ to eliminate bloat. The additional operations are:
</para>
<itemizedlist>
@@ -758,7 +691,7 @@
<emphasis>freeze</emphasis> is controlled by configuration
parameters, runtime flags, and in extreme situations by
the processes themselves. Because vacuum operations typically are I/O
- intensive, which can hinder other activities, <firstterm>autovacuum</firstterm>
+ intensive, which can hinder other activities, Autovacuum
avoids performing many vacuum operations in bulk. Instead,
it carries out many small actions with time gaps in between.
The SQL command <command>VACUUM</command> runs immediately
@@ -784,8 +717,8 @@
<listitem>
<simpara>
<literal>xmax</literal> must contain an xid which is older
- than the oldest xid of all
- currently running transactions (min(pg_stat_activity.backend_xmin)).
+ than the oldest xid of all currently running transactions
+ <literal>(min(pg_stat_activity.backend_xmin))</literal>.
This criterion guarantees that no existing or upcoming transaction
will have read or write access to this row version.
</simpara>
@@ -810,9 +743,9 @@
<para>
After the vacuum operation detects a superfluous row version, it
- marks its space as free for future use of writing
- actions. Only in rare situations (or in the case of <command>VACUUM FULL</command>),
- is this space released to the operating system. In most cases,
+ marks its space as free for future use of writing actions. Only
+ in rare situations (or in the case of <command>VACUUM FULL</command>),
+ this space is released to the operating system. In most cases,
it remains occupied by <productname>PostgreSQL</productname>
and will be used by future <command>INSERT</command> or
<command>UPDATE</command> commands concerning this row or a
@@ -860,7 +793,7 @@
<listitem>
<simpara>
- When an <firstterm>autovacuum</firstterm> process acts. For optimization
+ When an Autovacuum process acts. For optimization
purposes, it considers the Visibility Map in the same way as
<command>VACUUM</command>. Additionally, it ignores tables with few modifications;
see <xref linkend="guc-autovacuum-vacuum-threshold"/>,
@@ -877,7 +810,7 @@
This logic only applies to row versions of the heap. Index entries
don't use <literal>xmin/xmax</literal>. Nevertheless, such index
entries, which would lead to outdated row versions, are released
- accordingly. (??? more explanations ???)
+ accordingly.
</para>
<para>
@@ -996,7 +929,8 @@
<listitem>
<simpara>
- The transaction of <literal>xmin</literal> must be committed.
+ The transactions of <literal>xmin</literal> and
+ <literal>xmax</literal> must be committed.
</simpara>
</listitem>
</itemizedlist>
@@ -1029,8 +963,8 @@
</listitem>
<listitem>
<simpara>
- When an <firstterm>autovacuum</firstterm> process runs. Such
- a process acts in one of two modes:
+ When an Autovacuum process runs. Such a process acts in one
+ of two modes:
</simpara>
<itemizedlist>
@@ -1053,7 +987,7 @@
<xref linkend="guc-autovacuum-freeze-max-age"/>
(default: 200 million). The value of the oldest unfrozen
xid is stored per table in <literal>pg_class.relfrozenxid</literal>.
- In this <emphasis>aggressive mode</emphasis> <firstterm>autovacuum</firstterm>
+ In this <emphasis>aggressive mode</emphasis> Autovacuum
processes all such pages of the selected table that are marked
in the Visibility Map to potentially have bloat or unfrozen rows.
</simpara>
@@ -1065,7 +999,7 @@
</para>
<para>
- In the first two cases and with <firstterm>autovacuum</firstterm> in
+ In the first two cases and with Autovacuum in
<emphasis>aggressive mode</emphasis>, the system knows
to which value the oldest unfrozen xid has moved forward and
logs the value in <literal>pg_class.relfrozenxid</literal>.
@@ -1093,13 +1027,11 @@
<bridgehead renderas="sect2">Protection against Wraparound Failure</bridgehead>
<para>
- The <firstterm>autovacuum</firstterm> processes are initiated by the
- constantly running <firstterm>autovacuum</firstterm> daemon.
- If the daemon detects that for a table
- <firstterm>autovacuum_freeze_max_age</firstterm> is exceeded, it
- starts an <firstterm>autovacuum</firstterm> process in
- <emphasis>aggressive mode</emphasis>
- (see above) — even if <firstterm>autovacuum</firstterm> is disabled.
+ The Autovacuum processes are initiated by the constantly running
+ Autovacuum daemon. If the daemon detects that for a table
+ <literal>autovacuum_freeze_max_age</literal> is exceeded, it
+ starts an Autovacuum process in <emphasis>aggressive mode</emphasis>
+ (see above) — even if Autovacuum is disabled.
</para>
<bridgehead renderas="sect2">Visibility Map and Free Space Map</bridgehead>
@@ -1127,7 +1059,7 @@
<para>
The setting of the flags is silently done by <command>VACUUM</command>
- and <firstterm>autovacuum</firstterm> during their bloat and freeze operations.
+ and Autovacuum during their bloat and freeze operations.
This is done to speed up future vacuum actions,
regular accesses to heap pages, and some accesses to
the index. Every data-modifying operation on any row
@@ -1138,10 +1070,9 @@
The <link linkend="glossary-fsm">Free Space Map</link>
(FSM) tracks the amount of free space per page. It is
organized as a highly condensed b-tree of (rounded) sizes.
- As long as <command>VACUUM</command> or
- <firstterm>autovacuum</firstterm> change the free space
- on any processed page, they log the new values in
- the FSM in the same way as all other writing
+ As long as <command>VACUUM</command> or Autovacuum change
+ the free space on any processed page, they log the new
+ values in the FSM in the same way as all other writing
processes.
</para>
@@ -1153,11 +1084,10 @@
decisions for the generation of execution plans. This
information can be gathered with the SQL commands
<command>ANALYZE</command> or <command>VACUUM ANALYZE</command>.
- But <firstterm>autovacuum</firstterm> processes also gather
+ But also Autovacuum processes gather
such information. Depending on the percentage of changed rows
per table <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
- the <firstterm>autovacuum</firstterm> daemon starts
- <firstterm>autovacuum</firstterm> processes to collect
+ the Autovacuum daemon starts Autovacuum processes to collect
statistics per table. This dynamic invocation of analyze
operations allows <productname>PostgreSQL</productname> to
adopt queries to changing circumstances.
@@ -1221,7 +1151,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<para>
The atomicity also affects the visibility of changes. No
- connections running simultaneously to a data modifying
+ connection running simultaneously to a data modifying
transaction will ever see any change before the
transaction successfully executes a <command>COMMIT</command>
— even in the lowest
@@ -1293,7 +1223,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<command>ROLLBACK</command> command instead of a
<command>COMMIT</command>. The <command>ROLLBACK</command>
cancels the transaction, and all changes made so far remain
- invisible forever; it's like they never happened. There
+ invisible forever; it is as if they had never happened. There
is no need for the application to log its activities and
undo every step of the transaction separately.
</para>
@@ -1319,10 +1249,11 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
</para>
<para>
- There is an additional feature which defines transactions'
- <link linkend="transaction-iso">isolation level</link>
- to each other in a declarative way. It automatically
- prevents applications from some strange situations.
+ There is the additional feature
+ '<link linkend="transaction-iso">isolation level</link>',
+ which separates transactions from each other in certain ways.
+ It automatically prevents applications from some strange
+ situations.
</para>
<para>
@@ -1405,19 +1336,21 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
are also in the files, but - as usual - they are never seen
by any of the following transactions because uncommited
changes are never shown. Such recovery actions run
- completely automatically, it is not necessary that you
- configure or start anything by yourself.
+ completely automatically, it is not necessary that a
+ database administrator configure or start anything by
+ himself.
</para>
<bridgehead renderas="sect3">Disk crash</bridgehead>
<para>
If a disk crashes, the course of action described previously
cannot work. It is likely that the WAL files and/or the
- data and index files are no longer available. You need
- to take special actions to overcome such situations.
+ data and index files are no longer available. The
+ database administrator must take special actions to
+ overcome such situations.
</para>
<para>
- You obviously need a backup. How to take such a backup
+ He obviously needs a backup. How to take such a backup
and use it as a starting point for a recovery of the
cluster is explained in more detail in the next
<link linkend="tutorial-backup">chapter</link>.
@@ -1428,13 +1361,12 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
It is conceivable that over time the disk gets full,
and there is no room for additional data. In this case,
<productname>PostgreSQL</productname> stops accepting
- commands which change the data or even terminates
- completely. No data loss or data corruption will
- occur.
+ data-modifying commands or even terminates completely.
+ No data loss or data corruption will occur.
</para>
<para>
- To come out of such a situation, you should remove
- unused files from this disk. But you should never
+ To come out of such a situation, the administrator should
+ remove unused files from this disk. But he should never
delete files from the
<glossterm linkend="glossary-data-directory">data directory</glossterm>.
Nearly all of them are necessary for the consistency
diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml
index 8751410179..abb61445f2 100644
--- a/doc/src/sgml/start.sgml
+++ b/doc/src/sgml/start.sgml
@@ -76,30 +76,27 @@
A process at the server site with the name
<glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
<indexterm><primary>postgres</primary></indexterm>
+ <indexterm><primary>postmaster</primary></indexterm>
It accepts connection requests from client applications, starts
(<quote>forks</quote>) a new <glossterm linkend="glossary-backend">
- Backend process</glossterm> for each of them, and passes
+ Backend</glossterm> process for each of them, and passes
the connection to it. From that point on, the client and the new
- <firstterm>Backend process</firstterm>
- communicate directly without intervention by the original
- <firstterm>postgres</firstterm> process. Thus, the
- <firstterm>postgres</firstterm> process is always running, waiting
- for new client connections, whereas clients and associated
- <firstterm>Backend processes</firstterm> come and go.
- (All of this is of course invisible to the user. We only mention it
- here for completeness.)
+ Backend process communicate directly without intervention by the original
+ Postmaster process. Thus, the Postmaster process is always running,
+ waiting for new client connections, whereas clients and associated
+ Backend processes come and go. (All of this is of course invisible
+ to the user. We only mention it here for completeness.)
</para>
</listitem>
<listitem>
<para>
A group of processes at the server site, the <glossterm
- linkend="glossary-instance">instance</glossterm>, to which also the
- <firstterm>postgres</firstterm> process belongs. Their duties are
- handling of central, common database activities like file access,
- vacuum, <glossterm linkend="glossary-checkpoint">checkpoints</glossterm>,
- replication, and more. The mentioned <firstterm>Backend processes</firstterm>
- delegate those actions to the <firstterm>instance</firstterm>.
+ linkend="glossary-instance">Instance</glossterm>, to which also
+ the Postmaster process belongs. Their duties are handling of
+ central, common database activities like file access, transaction
+ handling, vacuum, checkpoints, replication, and more. The mentioned
+ Backend processes delegate those actions to the instance.
</para>
</listitem>
@@ -127,18 +124,6 @@
file name) on the database server machine.
</para>
- <para>
- The <productname>PostgreSQL</productname> server can handle
- multiple concurrent connections from clients. To achieve this it
- starts (<quote>forks</quote>) a new process for each connection.
- From that point on, the client and the new server process
- communicate without intervention by the original
- <filename>postgres</filename> process. Thus, the
- supervisor server process is always running, waiting for
- client connections, whereas client and associated server processes
- come and go. (All of this is of course invisible to the user. We
- only mention it here for completeness.)
- </para>
</sect1>
0009-architecture-vs-master.patchtext/x-patch; charset=UTF-8; name=0009-architecture-vs-master.patchDownload
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
index 2d4ab85d45..5c3245c0ec 100644
--- a/doc/src/sgml/advanced.sgml
+++ b/doc/src/sgml/advanced.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/advanced.sgml -->
<chapter id="tutorial-advanced">
- <title>Advanced Features</title>
+ <title>Advanced SQL Features</title>
<sect1 id="tutorial-advanced-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/arch-dev.sgml b/doc/src/sgml/arch-dev.sgml
index 7883c3cd82..9db0ae2c78 100644
--- a/doc/src/sgml/arch-dev.sgml
+++ b/doc/src/sgml/arch-dev.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/arch-dev.sgml -->
<chapter id="overview">
- <title>Overview of PostgreSQL Internals</title>
+ <title>Overview of Query Handling</title>
<note>
<title>Author</title>
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
new file mode 100644
index 0000000000..e547a87d08
--- /dev/null
+++ b/doc/src/sgml/architecture.sgml
@@ -0,0 +1,1517 @@
+<!-- doc/src/sgml/architecture.sgml -->
+
+ <chapter id="tutorial-architecture">
+ <title>Overview of Architecture and Implementation</title>
+
+ <para>
+ Every DBMS implements basic strategies to ensure a fast
+ and robust system. This chapter provides an overview of the
+ techniques <productname>PostgreSQL</productname> uses to
+ achieve this.
+ </para>
+
+ <sect1 id="tutorial-ram-proc-file">
+ <title>Collaboration of Processes, RAM, and Files</title>
+ <para>
+ In a client/server architecture clients do not have direct access
+ to database files and the data stored in them. Instead, they send
+ requests to the server and receive the requested data in the response.
+ In the case of <productname>PostgreSQL</productname>, the server
+ launches a single process for each client connection, referred to as a
+ <glossterm linkend="glossary-backend">Backend</glossterm> process.
+ Those Backend processes handle the client's requests by acting on the
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>.
+ This leads to other activities (file access, WAL, vacuum, ...) of the
+ <glossterm linkend="glossary-instance">Instance</glossterm>. The
+ Instance is a group of server-side processes acting on a common
+ Shared Memory. Notably, PostgreSQL does not utilize application
+ threading within its implementation.
+ </para>
+
+ <para>
+ The first step in an Instance start is the start of the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ He loads the configuration files, allocates Shared Memory, and
+ starts the other processes of the Instance:
+ <glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
+ <glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
+ <glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
+ <glossterm linkend="glossary-wal-archiver">WAL Archiver</glossterm>,
+ <glossterm linkend="glossary-autovacuum">Autovacuum</glossterm>,
+ <glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
+ <glossterm linkend="glossary-logger">Logger</glossterm>, and more.
+ Later, the Postmaster starts
+ <glossterm linkend="glossary-backend">Backend</glossterm> processes
+ which communicate with clients and handle their requests.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes the processes
+ of an Instance and the main aspects of their collaboration.
+ </para>
+
+ <figure id="tutorial-ram-proc-file-figure">
+ <title>Architecture</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ When a client application tries to connect to a
+ <glossterm linkend="glossary-database">database</glossterm>,
+ this request is handled initially by the Postmaster. He
+ starts a new Backend process and instructs the client
+ application to connect to it. All further client requests
+ go to this process and are handled by it.
+ </para>
+
+ <para>
+ Client requests like <command>SELECT</command> or
+ <command>UPDATE</command> usually lead to the
+ necessity to read or write some data. This is carried out
+ by the client's backend process. Reads involve a page-level
+ cache housed in Shared Memory (for details see:
+ <xref linkend="sysvipc"/>) for the benefit of all processes
+ in the instance. Writes also involve this cache, in additional
+ to a journal, called a write-ahead-log or WAL.
+ </para>
+
+ <para>
+ Shared Memory is limited in size. Thus, it becomes necessary
+ to evict pages. As long as the content of such pages hasn't
+ changed, this is not a problem. But in Shared Memory also
+ write actions take place. Modified pages are called dirty
+ pages or dirty buffers and before they can be evicted they
+ must be written back to disk. This happens regularly by the
+ Background Writer and the Checkpointer process to ensure
+ that the disk version of the pages are kept up-to-date.
+ The synchronisation from RAM to disk consists of two steps.
+ </para>
+
+<!-- DGJ: WAL should already be done well before page
+ eviction/overwriting comes into play.
+ This is good material but seems misplaced.
+ JuP: Really misplaced? Don't think so.
+-->
+
+ <para>
+ First, whenever the content of a page changes, a
+ <glossterm linkend="glossary-wal-record">WAL record</glossterm>
+ is created out of the delta-information (difference between the
+ old and the new content) and stored in another area of
+ Shared Memory. The parallel running WAL Writer process
+ reads them and appends them to the end of the current
+ <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
+ Such sequential writes are much faster than writes to random
+ positions of heap and index files. All WAL records created
+ out of one dirty page must be transferred to disk before the
+ dirty page itself can be transferred to disk in the second step.
+ </para>
+
+ <para>
+ Second, the transfer of dirty buffers from Shared Memory to
+ files must take place. This is the primary task of the
+ Background Writer process. Because I/O activities can block
+ other processes significantly, it starts periodically and
+ acts only for a short period. Doing so, its extensive (and
+ expensive) I/O activities are spread over time, avoiding
+ debilitating I/O peaks. Also, the Checkpointer process
+ transfers dirty buffers to file.
+ </para>
+
+ <para>
+ The Checkpointer creates
+ <glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
+ A Checkpoint is a point in time when all older dirty buffers,
+ all older WAL records, and finally a special Checkpoint record
+ have been written and flushed to disk. Heap and index files
+ on the one hand and WAL files on the other hand are in sync.
+ Previous WAL is no longer required. In other words,
+ a possibly occurring recovery, which integrates the delta
+ information of WAL into heap and index files, will happen
+ by replaying only WAL past the last recorded checkpoint
+ on top of the current heap and files. This speeds up recovery.
+ </para>
+
+ <para>
+ While the Checkpointer ensures that a running system can crash
+ and restart itself in a valid state, the administrator needs
+ to handle the case where the heap and files themselves become
+ corrupted (and possibly the locally written WAL, though that is
+ less common). The options and details are covered extensively
+ in the backup and restore section (<xref linkend="backup"/>).
+ For our purposes here, note just that the WAL Archiver process
+ can be enabled and configured to run a script on filled WAL
+ files — usually to copy them to a remote location.
+ </para>
+
+
+<!-- DGJ: after the heavy focus on client processes and data these two
+ seem to come out of left field. Skipping over for now.
+ JuP: Don't skip, we want to explain all elements of the graphic.
+-->
+
+ <para>
+ The Statistics Collector collects counters about accesses to
+ SQL objects like tables, rows, indexes, pages, and more. It
+ stores the obtained information in system tables.
+ </para>
+
+ <para>
+ The Logger writes text lines about serious and less serious
+ events which can happen during database access, e.g., wrong
+ password, no permission, long-running queries, etc.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-cluster-db-schema">
+ <title>The logical Perspective: Cluster, Database, Schema</title>
+
+ <para>
+ A <glossterm linkend="glossary-server">server</glossterm> contains one or more
+ <glossterm linkend="glossary-db-cluster">database clusters</glossterm>
+ (<glossterm linkend="glossary-db-cluster">clusters</glossterm>
+ for short). Each cluster contains three or more
+ <glossterm linkend="glossary-database">databases</glossterm>.
+ Each database can contain many
+ <glossterm linkend="glossary-schema">schemas</glossterm>.
+ A schema can contain
+ <glossterm linkend="glossary-table">tables</glossterm>,
+ <glossterm linkend="glossary-view">views</glossterm>, and a lot
+ of other objects. Each table or view belongs to a single schema
+ only; they cannot belong to another schema as well. The same is
+ true for the schema/database and database/cluster relation.
+ <xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
+ this hierarchy.
+ </para>
+
+ <figure id="tutorial-cluster-db-schema-figure">
+ <title>Cluster, Database, Schema</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ A cluster is the outer container for a
+ collection of databases. Clusters are created by the command
+ <xref linkend="app-initdb"/>.
+ </para>
+
+ <para>
+ <literal>template0</literal> is the very first
+ database of any cluster. Database <literal>template0</literal>
+ is created during the initialization phase of the cluster.
+ In a second step, database <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal>, and finally database
+ <literal>postgres</literal> is generated as a copy of
+ <literal>template1</literal>. Any
+ <glossterm linkend="app-createdb">new databases</glossterm>
+ of the cluster that a user might need,
+ such as <literal>my_db</literal>, will be copied from the
+ <literal>template1</literal> database. Due to the unique
+ role of <literal>template0</literal> as the pristine original
+ of all other databases, no client can connect to it.
+ </para>
+
+ <para>
+ Every database must contain at least one schema because all
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>
+ are contained in a schema.
+ Schemas are namespaces for their SQL objects and ensure
+ (with one exception) that within their scope names are used
+ only once across all types of SQL objects. E.g., it is not possible
+ to have a table <literal>employee</literal> and a view
+ <literal>employee</literal> within the same schema. But it is
+ possible to have two tables <literal>employee</literal> in
+ different schemas. In this case, the two tables
+ are separate objects and independent of each
+ other. The only exception to this cross-type uniqueness is that
+ <glossterm linkend="glossary-unique-constraint">unique constraints
+ </glossterm> and the according unique index
+ (<xref linkend="indexes-unique"/>) use the same name.
+ </para>
+
+ <para>
+ Some schemas are predefined. <literal>public</literal>
+ acts as the default schema and contains all SQL objects
+ which are created within <literal>public</literal> or
+ without using an explicit schema name. <literal>public</literal>
+ should not contain user-defined SQL objects. Instead, it is
+ recommended to create a separate schema that holds individual
+ objects like application-specific tables or views.
+ <literal>pg_catalog</literal> is a schema for all tables and views of the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ <literal>information_schema</literal> is a schema for several
+ tables and views of the System Catalog in a way that conforms
+ to the SQL standard.
+ </para>
+
+ <para>
+ There are many different SQL object
+ types: <firstterm>database, schema, table, view, materialized
+ view, index, constraint, sequence, function, procedure,
+ trigger, role, data type, operator, tablespace, extension,
+ foreign data wrapper</firstterm>, and more. A few of them, the
+ <firstterm>Global SQL Objects</firstterm>, are outside of the
+ strict hierarchy: All <firstterm>database names</firstterm>,
+ all <firstterm>tablespace names</firstterm>, and all
+ <firstterm>role names</firstterm> are automatically known and
+ available throughout the cluster, independent from
+ the database or schema in which they where defined originally.
+ <xref linkend="tutorial-internal-objects-hierarchy-figure"/>
+ shows the relation between the object types.
+ </para>
+
+ <figure id="tutorial-internal-objects-hierarchy-figure">
+ <title>Hierarchy of Internal Objects</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="720px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect1>
+
+ <sect1 id="tutorial-directories">
+ <title>The physical Perspective: Directories and Files</title>
+
+ <para>
+ <productname>PostgreSQL</productname> organizes long-lasting
+ data as well as volatile state information about transactions
+ or replication actions in the file system. Every
+ <xref linkend="glossary-db-cluster"/> has its root directory
+ somewhere in the file system. In many cases, the environment
+ variable <literal>PGDATA</literal> points to this directory.
+ The example shown in
+ <xref linkend="tutorial-directories-figure"/> uses
+ <literal>data</literal> as the name of this root directory.
+ </para>
+
+ <figure id="tutorial-directories-figure">
+ <title>Directory Structure</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ <literal>data</literal> contains many subdirectories and
+ some files, all of which are necessary to store long-lasting
+ as well as temporary data. The following paragraphs
+ describe the files and subdirectories in
+ <literal>data</literal>.
+ </para>
+
+ <para>
+ <literal>base</literal> is a subdirectory in which one
+ subdirectory per database exists. The names of those
+ subdirectories consist of numbers. These are the internal
+ Object Identifiers (OID), which are numbers to identify
+ the database definition in the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ </para>
+
+ <para>
+ Within the database-specific
+ subdirectories, there are many files: one or more for
+ every table and every index to store heap and index
+ data. Those files are accompanied by files for the
+ <link linkend="storage-fsm">Free Space Maps</link>
+ (extension <literal>_fsm</literal>) and
+ <link linkend="storage-vm">Visibility Maps</link>
+ (extension <literal>_vm</literal>), which contain optimization information.
+ </para>
+
+ <para>
+ Another subdirectory is <literal>global</literal>.
+ In analogy to the database-specific
+ subdirectories, there are files containing information about
+ <glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
+ One type of such Global SQL Objects are
+ <glossterm linkend="glossary-tablespace">tablespaces</glossterm>.
+ In <literal>global</literal> there is information about
+ the tablespaces, not the tablespaces themselves.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_wal</literal> contains the
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
+ They arise and grow parallel to data changes in the
+ cluster and remain alive as long as
+ they are required for recovery, archiving, or replication.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_xact</literal> contains
+ information about the status of each transaction:
+ <literal>in_progress</literal>, <literal>committed</literal>,
+ <literal>aborted</literal>, or <literal>sub_committed</literal>.
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal>, there are symbolic links
+ that point to directories containing such SQL objects
+ that are created within tablespaces.
+ </para>
+
+ <para>
+ In the root directory <literal>data</literal>
+ there are also some files. In many cases, the configuration
+ files of the cluster are stored here. As long as the
+ instance is up and running, the file
+ <literal>postmaster.pid</literal> exists here
+ and contains the process ID (pid) of the
+ Postmaster which has started the instance.
+ </para>
+
+ <para>
+ For more details about the physical implementation
+ of database objects, see <xref linkend="storage"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-mvcc">
+ <title>MVCC — Multiversion Concurrency Control</title>
+
+ <para>
+ In most cases, <productname>PostgreSQL</productname> databases
+ support many clients at the same time. Therefore, it is necessary to
+ protect concurrently running requests from unwanted overwriting
+ of other's data as well as from reading inconsistent data. Imagine an
+ online shop offering the last copy of an article. Two clients have the
+ article displayed at their user interface. After a while, but at the same time,
+ both users decide to put it to their shopping cart or even to buy it.
+ Both have seen the article, but only one can be allowed to get it.
+ The database must bring the two requests in a row, permit the access
+ to one of them, block the other, and inform the blocked client
+ that the data was changed by a different process.
+ </para>
+
+ <para>
+ A first approach to implement protections against concurrent
+ accesses to the same data may be the locking of critical
+ rows. Two such techniques are:
+ <emphasis>Optimistic Concurrency Control</emphasis> (OCC)
+ and <emphasis>Two Phase Locking</emphasis> (2PL).
+ <productname>PostgreSQL</productname> implements a third, more
+ sophisticated technique: <firstterm>Multiversion Concurrency
+ Control</firstterm> (MVCC). The crucial advantage of MVCC
+ over other technologies gets evident in multiuser OLTP
+ environments with a massive number of concurrent write
+ actions. There, MVCC generally performs better than solutions
+ using locks. In a <productname>PostgreSQL</productname>
+ database reading never blocks writing and writing never
+ blocks reading, even in the strictest level of transaction
+ isolation.
+ </para>
+
+ <para>
+ Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
+ a new version of the row when a data-change takes place. To
+ distinguish between these two versions and to track the timeline
+ of the row, each of the versions contains, in addition to their user-defined
+ columns, two special system columns, which are not visible
+ for the usual <command>SELECT * FROM ...</command> command.
+ The column <literal>xmin</literal> contains the transaction ID (xid)
+ of the transaction, which created this version of the row. Accordingly,
+ <literal>xmax</literal> contains the xid of the transaction, which has
+ deleted this version, or zero, if the version is not
+ deleted. You can read both with the command
+ <command>SELECT xmin, xmax, * FROM ... </command>.
+ </para>
+
+ <para>
+ When we speak about transaction IDs, you need to know that xids are like
+ sequences. Every new transaction receives the next number as its ID.
+ Therefore, this flow of xids represents the flow of transaction
+ start events over time. But keep in mind that xids are independent of
+ any time measurement — in milliseconds or whatever. If you dive
+ deeper into <productname>PostgreSQL</productname>, you will recognize
+ parameters with names such as 'xxx_age'. Despite their names,
+ these '_age' parameters do not specify a period of time but represent
+ a certain number of transactions, e.g., 100 million.
+ </para>
+
+ <para>
+ The description in this chapter simplifies by omitting some details.
+ When many transactions are running simultaneously, things can
+ get complicated. Sometimes transactions get aborted via
+ <command>ROLLBACK</command> immediately or after a lot of other activities, sometimes
+ a single row is involved in more than one transaction, sometimes
+ a client crashes, sometimes the sequence of xids restarts
+ from zero, ... . Therefore, every version of a row contains more
+ system columns and flags, not only <literal>xmin</literal>
+ and <literal>xmax</literal>.
+ </para>
+
+ <para>
+ So, what's going on in detail when write accesses take place?
+ <xref linkend="tutorial-mvcc-figure"/> shows details concerning
+ <literal>xmin</literal>, <literal>xmax</literal>, and user data.
+ </para>
+
+ <figure id="tutorial-mvcc-figure">
+ <title>Multiversion Concurrency Control</title>
+ <mediaobject>
+ <imageobject role="html">
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ An <command>INSERT</command> command creates the first
+ version of a row. Besides its user data <literal>'x'</literal>,
+ this version contains the ID of the creating transaction
+ <literal>123</literal> in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ <literal>xmin</literal> indicates that the version
+ exists since transaction <literal>123</literal> and
+ <literal>xmax</literal> that it is currently not deleted.
+ </para>
+
+ <para>
+ Somewhat later, transaction <literal>135</literal>
+ executes an <command>UPDATE</command> of this row by
+ changing the user data from <literal>'x'</literal> to
+ <literal>'y'</literal>. According to the MVCC principles,
+ the data in the old version of the row does not change!
+ The value <literal>'x'</literal> remains as it was before.
+ Only <literal>xmax</literal> changes to <literal>135</literal>.
+ Now, this version is treated as valid exclusively for
+ transactions with xids from <literal>123</literal> to
+ <literal>134</literal>. As a substitute for the non-occurring
+ data change in the old version, the <command>UPDATE</command>
+ creates a new version of the row with its xid in
+ <literal>xmin</literal>, <literal>0</literal> in
+ <literal>xmax</literal>, and <literal>'y'</literal> in the
+ user data (plus all the other user data from the old version).
+ This version is now valid for all coming transactions.
+ </para>
+
+ <para>
+ All subsequent <command>UPDATE</command> commands behave
+ in the same way as the first one: they put their xid to
+ <literal>xmax</literal> of the current version, create
+ the next version with their xid in <literal>xmin</literal>,
+ <literal>0</literal> in <literal>xmax</literal>, and the
+ new user data.
+ </para>
+
+ <para>
+ Finally, a row may be deleted by a <command>DELETE</command>
+ command. Even in this case, all versions of the row remain as
+ before. Nothing is thrown away so far! Only <literal>xmax</literal>
+ of the last version changes to the xid of the <command>DELETE</command>
+ transaction, which indicates that it is only valid for
+ transactions with xids older than its own (from
+ <literal>142</literal> to <literal>820</literal> in this
+ example).
+ </para>
+
+ <para>
+ In summary, the MVCC technology creates more and more versions
+ of the same row in the table's heap file and leaves them there,
+ even after a <command>DELETE</command> command. Only the youngest
+ version is relevant for all future transactions. But the
+ system must also preserve some of the older ones for a
+ certain amount of time because the possibility exists that
+ they are or could become relevant for any pending
+ transactions. Over time, also the older ones get out of scope
+ for ALL transactions and therefore become unnecessary.
+ Nevertheless, they do exist physically on the disk and occupy
+ space.
+ </para>
+
+ <para>
+ Please keep in mind:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> and <literal>xmax</literal>
+ indicate the range from where to where
+ row versions are valid (visible) for transactions.
+ This range doesn't imply any direct temporal meaning;
+ the sequence of xids reflects only the sequence of
+ transaction begin events. As
+ xids grow, old row versions get out of scope over time.
+ If an old row version is no longer valid for ALL existing
+ transactions, it's called <firstterm>dead</firstterm>. The
+ space occupied by dead row versions is part of the
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Internally, an <command>UPDATE</command> command acts in the
+ same way as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Nothing gets wiped away — with the consequence that the database
+ occupies more and more disk space. It is obvious that
+ this behavior has to be corrected in some
+ way. The next chapter explains how <firstterm>autovacuum</firstterm>
+ fulfills this task.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ </sect1>
+
+ <sect1 id="tutorial-vacuum">
+ <title>Vacuum</title>
+
+ <para>
+ As we have seen in the previous chapter, the database
+ tends to occupy more and more disk space, the
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ This chapter explains how the SQL command
+ <command>VACUUM</command> and the automatically running
+ <firstterm>Autovacuum</firstterm> processes clean up
+ by eliminating bloat.
+ </para>
+
+ <note>
+ <para>
+ Autovacuum runs automatically by
+ default. Its default parameters as well as such for
+ <command>VACUUM</command> fit well for most standard
+ situations. Therefore a novice database manager can
+ easily skip the rest of this chapter which explains
+ a lot of details.
+ </para>
+ </note>
+
+ <para>
+ Client processes can issue the SQL command <command>VACUUM</command>
+ at arbitrary points in time. DBAs do this when they recognize
+ special situations, or they start it in batch jobs which run
+ periodically. Autovacuum processes run as part of the
+ <link linkend="glossary-instance">Instance</link> at the server.
+ There is a constantly running Autovacuum daemon. It permanently
+ controls the state of all databases based on values that are collected by the
+ <link linkend="glossary-stats-collector">Statistics Collector</link>
+ and starts Autovacuum processes whenever it detects
+ certain situations. Thus, it's a dynamic behavior of
+ <productname>PostgreSQL</productname> with the intention to tidy
+ up — whenever it is appropriate.
+ </para>
+
+ <para>
+ <command>VACUUM</command>, as well as Autovacuum, don't just eliminate
+ bloat. They perform additional tasks for minimizing future
+ I/O activities of themselves as well as of other processes.
+ This extra work can be done in a very efficient way since in most
+ cases the expensive physical access to pages has taken place anyway
+ to eliminate bloat. The additional operations are:
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <firstterm>Freeze</firstterm>: Mark the youngest row version
+ as frozen. This means that the version
+ is always treated as valid (visible) independent from
+ the <firstterm>wraparound problem</firstterm> (see below).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <firstterm>Visibility Map</firstterm> and
+ <firstterm>Free Space Map</firstterm>: Log information about
+ the state of the handled pages in two additional files, the
+ Visibility Map and the Free Space Map.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <emphasis>Statistics</emphasis>: Collect statistics about the
+ number of rows per table, the distribution of values, and so on,
+ as the basis for decisions of the query planner.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ The eagerness — you can call it 'aggression' — of the
+ operations <emphasis>eliminating bloat</emphasis> and
+ <emphasis>freeze</emphasis> is controlled by configuration
+ parameters, runtime flags, and in extreme situations by
+ the processes themselves. Because vacuum operations typically are I/O
+ intensive, which can hinder other activities, Autovacuum
+ avoids performing many vacuum operations in bulk. Instead,
+ it carries out many small actions with time gaps in between.
+ The SQL command <command>VACUUM</command> runs immediately
+ and without any time gaps.
+ </para>
+
+ <bridgehead renderas="sect2">Eliminate Bloat</bridgehead>
+
+ <para>
+ To determine which of the row versions are superfluous, the
+ elimination operation must evaluate <literal>xmax</literal>
+ against several criteria which all must apply:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be different from zero because a
+ value of zero indicates that the row version is still valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must contain an xid which is older
+ than the oldest xid of all currently running transactions
+ <literal>(min(pg_stat_activity.backend_xmin))</literal>.
+ This criterion guarantees that no existing or upcoming transaction
+ will have read or write access to this row version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of <literal>xmax</literal> must be committed. If it was rollback-ed,
+ this row version is treated as valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there is the situation that the row version is part of
+ multiple transactions, special care and some more actions
+ must be taken, see: <xref linkend="vacuum-for-multixact-wraparound"/>.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ After the vacuum operation detects a superfluous row version, it
+ marks its space as free for future use of writing actions. Only
+ in rare situations (or in the case of <command>VACUUM FULL</command>),
+ this space is released to the operating system. In most cases,
+ it remains occupied by <productname>PostgreSQL</productname>
+ and will be used by future <command>INSERT</command> or
+ <command>UPDATE</command> commands concerning this row or a
+ completely different one.
+ </para>
+
+ <para>
+ Which actions start the elimination of bloat?
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ in its default format, i.e., without any option. To boost performance,
+ in this and the next case <command>VACUUM</command> does not
+ read and act on all pages of the heap.
+ The Visibility Map, which is very compact and therefore has a small
+ size, contains information about pages, where bloat-candidates might
+ be found. Only such pages are processed.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FREEZE</command>. (In this case,
+ it undertakes much more actions, see
+ <link linkend="tutorial-freeze">Freeze Row Versions</link>.)
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FULL</command>.
+ Also, in this mode, the bloat disappears, but the strategy used
+ is very different: In this case, the complete table is copied
+ to a different file skipping all outdated row versions. This
+ leads to a significant reduction of used disk space because
+ the new file contains only the actual data. The old file
+ is deleted.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When an Autovacuum process acts. For optimization
+ purposes, it considers the Visibility Map in the same way as
+ <command>VACUUM</command>. Additionally, it ignores tables with few modifications;
+ see <xref linkend="guc-autovacuum-vacuum-threshold"/>,
+ which defaults to 50 rows and
+ <xref linkend="guc-autovacuum-vacuum-scale-factor"/>,
+ which defaults to 20%.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </para>
+
+ <para>
+ This logic only applies to row versions of the heap. Index entries
+ don't use <literal>xmin/xmax</literal>. Nevertheless, such index
+ entries, which would lead to outdated row versions, are released
+ accordingly.
+ </para>
+
+ <para>
+ The above descriptions omit the fact that xids on a real computer
+ have a limited size. They count up in the same way as sequences, and after
+ a certain number of new transactions they are forced to restart
+ from the beginning, which is called <firstterm>wraparound</firstterm>.
+ Therefore the terms 'old transaction' / 'young transaction' does
+ not always correlate with low / high values of xids. Near to the
+ wraparound point, there are cases where <literal>xmin</literal> has
+ a higher value than <literal>xmax</literal>, although their meaning
+ is said to be older than <literal>xmax</literal>.
+ </para>
+
+ <figure id="tutorial-wraparound-figure">
+ <title>Cyclic usage of XIDs</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2" id="tutorial-freeze">Freeze Row Versions</bridgehead>
+
+ <para>
+ The use of a limited range of IDs for transactions leads
+ to the necessity to restart the sequence sooner or later.
+ This does not only have the rare consequence previously
+ described that sometimes <literal>xmin</literal> is
+ higher than <literal>xmax</literal>. The far
+ more critical problem is that whenever the system has
+ to evaluate a WHERE condition, it must decide which row
+ version is valid (visible) from the perspective of the
+ transaction of this query. If a wraparound couldn't happen,
+ this decision would be relatively easy: the xid
+ must be between <literal>xmin</literal> and <literal>xmax</literal>,
+ and the corresponding transactions of <literal>xmin</literal>
+ and <literal>xmax</literal> must be committed. However,
+ <productname>PostgreSQL</productname> has to consider the
+ possibility of wraparounds.
+ Therefore the decision becomes more complex. The general
+ idea of the solution is to use the 'between
+ <literal>xmin</literal> and <literal>xmax</literal>'
+ comparison only during the youngest period of the row
+ versions lifetime and afterward replace it with a
+ 'valid forever' flag in its header.
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ As a first step, <productname>PostgreSQL</productname>
+ divides the complete range of
+ possible xids into two halves with the two split-points
+ 'txid_current' and 'txid_current + 2^31'. The half behind
+ 'txid_current' is considered to represent xids of the
+ 'past' and the half ahead of 'txid_current' those of the
+ 'future'. Those of the 'past' are valid (visible) and those
+ of the 'future' not.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ With each newly created transaction the two split-points
+ move forward. When 'txid_current + 2^31' would reach a
+ row version with <literal>xmin</literal> equal to that value, it would
+ immediately jump from 'past' to 'future' and would be
+ no longer visible!
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ To avoid this unacceptable extinction of data, the vacuum
+ operation <firstterm>freeze</firstterm> clears the situation
+ long before the split-point is reached. It sets a flag
+ in the header of the row version, which completely eliminates
+ the future use of <literal>xmin/xmax</literal> and indicates
+ that the version is valid not only in the 'past'-half
+ but also in the 'future'-half as well as in all coming
+ <glossterm linkend="glossary-xid">epochs</glossterm>.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Which row versions can be frozen by the vacuum operation?
+ Again, several criteria must be checked, and all must be met.
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be zero because only
+ non-deleted rows can be visible 'forever'.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> must be older than all currently
+ existing transactions. This guarantees that no existing
+ transaction can modify or delete the version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transactions of <literal>xmin</literal> and
+ <literal>xmax</literal> must be committed.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ At what point in time does the freeze operation take place?
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with its <command>FREEZE</command> option. In this case, all
+ pages are processed that are marked in the Visibility Map
+ to potentially have unfrozen rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command> without
+ any options but finds that there are xids older than
+ <xref linkend="guc-vacuum-freeze-table-age"/>
+ (default: 150 million) minus
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million).
+ As before, all pages are processed that are
+ marked in the Visibility Map to potentially have unfrozen
+ rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When an Autovacuum process runs. Such a process acts in one
+ of two modes:
+ </simpara>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ In the <emphasis>normal mode</emphasis>, it skips
+ pages with row versions that are younger than
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million) and works only on pages where
+ all xids are older. The skipping of young xids prevents
+ work on such pages, which are likely to be changed
+ by one of the future SQL commands.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ The process switches
+ to an <emphasis>aggressive mode</emphasis> if it recognizes
+ that for the processed table their oldest xid exceeds
+ <xref linkend="guc-autovacuum-freeze-max-age"/>
+ (default: 200 million). The value of the oldest unfrozen
+ xid is stored per table in <literal>pg_class.relfrozenxid</literal>.
+ In this <emphasis>aggressive mode</emphasis> Autovacuum
+ processes all such pages of the selected table that are marked
+ in the Visibility Map to potentially have bloat or unfrozen rows.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In the first two cases and with Autovacuum in
+ <emphasis>aggressive mode</emphasis>, the system knows
+ to which value the oldest unfrozen xid has moved forward and
+ logs the value in <literal>pg_class.relfrozenxid</literal>.
+ The distance between this value and the 'txid_current' split
+ point becomes smaller, and the distance to 'txid_current + 2^31'
+ becomes larger than before.
+ </para>
+
+ <figure id="tutorial-freeze-figure">
+ <title>Freeze</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2">Protection against Wraparound Failure</bridgehead>
+
+ <para>
+ The Autovacuum processes are initiated by the constantly running
+ Autovacuum daemon. If the daemon detects that for a table
+ <literal>autovacuum_freeze_max_age</literal> is exceeded, it
+ starts an Autovacuum process in <emphasis>aggressive mode</emphasis>
+ (see above) — even if Autovacuum is disabled.
+ </para>
+
+ <bridgehead renderas="sect2">Visibility Map and Free Space Map</bridgehead>
+
+ <para>
+ The <link linkend="glossary-vm">Visibility Map</link>
+ (VM) contains two flags — stored as
+ two bits — for each page of the heap. If the first bit
+ is set, that indicates that the associated page does not
+ contain any bloat. If the second one is set, that indicates
+ that the page contains only frozen rows.
+ </para>
+
+ <para>
+ Please consider two details. First, in most cases a page
+ contains many rows, some of them in many versions.
+ However, the flags are associated with the page,
+ not with a row or a row version. The flags are set
+ only under the condition that they are valid for ALL
+ row versions of the page. Second, since there
+ are only two bits per page, the VM is considerably
+ smaller than the heap. Therefore it is buffered
+ in RAM in almost all cases.
+ </para>
+
+ <para>
+ The setting of the flags is silently done by <command>VACUUM</command>
+ and Autovacuum during their bloat and freeze operations.
+ This is done to speed up future vacuum actions,
+ regular accesses to heap pages, and some accesses to
+ the index. Every data-modifying operation on any row
+ version of the page clears the flags.
+ </para>
+
+ <para>
+ The <link linkend="glossary-fsm">Free Space Map</link>
+ (FSM) tracks the amount of free space per page. It is
+ organized as a highly condensed b-tree of (rounded) sizes.
+ As long as <command>VACUUM</command> or Autovacuum change
+ the free space on any processed page, they log the new
+ values in the FSM in the same way as all other writing
+ processes.
+ </para>
+
+ <bridgehead renderas="sect2">Statistics</bridgehead>
+
+ <para>
+ Statistic information helps the <link
+ linkend="planner-stats">Query Planner</link> to make optimal
+ decisions for the generation of execution plans. This
+ information can be gathered with the SQL commands
+ <command>ANALYZE</command> or <command>VACUUM ANALYZE</command>.
+ But also Autovacuum processes gather
+ such information. Depending on the percentage of changed rows
+ per table <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ the Autovacuum daemon starts Autovacuum processes to collect
+ statistics per table. This dynamic invocation of analyze
+ operations allows <productname>PostgreSQL</productname> to
+ adopt queries to changing circumstances.
+ </para>
+
+ <para>
+ For more details about vacuum operations, especially for its
+ numerous parameters, see <xref linkend="routine-vacuuming"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-transactions-mvcc">
+ <title>Transactions</title>
+ <para>
+ <link linkend="tutorial-transactions">Transactions</link>
+ are a fundamental concept of relational database systems.
+ Their essential point is that they bundle multiple
+ read- or write-operations into a single all-or-nothing
+ operation. Furthermore, they separate and protect concurrent
+ actions of different connections from each other. Thereby
+ they implement the ACID paradigm.
+ </para>
+
+ <para>
+ In <productname>PostgreSQL</productname> there are two ways
+ to establish a transaction. The explicit way uses the keywords
+ <link linkend="sql-begin">BEGIN</link> and
+ <link linkend="sql-commit">COMMIT</link> (respectively
+ <link linkend="sql-rollback">ROLLBACK</link>) before
+ and after a sequence of SQL statements. The keywords mark
+ the transaction's start- and end-point. On the other hand, you
+ can omit the keywords. This is the implicit way, where
+ every single SQL command automatically establishes a new
+ transaction.
+
+ <programlisting>
+BEGIN; -- establish a new transaction
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+COMMIT; -- finish the transaction
+
+-- this UPDATE runs as the only command of a separate transaction ...
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+
+-- ... and this one runs in another transaction
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+ </programlisting>
+ </para>
+
+ <para>
+ As mentioned, the primary property of a transaction is its
+ atomicity: either all or none of its operations succeed,
+ regardless of the fact that it may consist of a lot of
+ different write-operations, and each such operation may
+ affect thousands or millions of rows. As soon as one of the
+ operations fails, all previous operations fail also, which
+ means that all modified rows retain their values as of the
+ beginning of the transaction.
+ </para>
+
+ <para>
+ The atomicity also affects the visibility of changes. No
+ connection running simultaneously to a data modifying
+ transaction will ever see any change before the
+ transaction successfully executes a <command>COMMIT</command>
+ — even in the lowest
+ <link linkend="transaction-iso">isolation level</link>
+ of transactions. <productname>PostgreSQL</productname>
+ does never show uncommitted changes to other connections.
+ </para>
+
+ <para>
+ The situation regarding visibility is somewhat different
+ from the point of view of the modifying transaction.
+ <command>SELECT</command> commands issued inside a
+ transaction delivers all changes done so far by this
+ transaction.
+ </para>
+
+ <bridgehead renderas="sect2">How does it work?</bridgehead>
+
+ <para>
+ Every <command>INSERT</command>, <command>UPDATE</command>,
+ and <command>DELETE</command> command creates new row
+ versions — according to the MVCC rules. This
+ creates the risk that other transactions may see the
+ new row versions, and after a while and some more
+ activities of the modifying transaction they may see the
+ next row versions. Results would be a kind of 'moving
+ target' in absolute contrast to the all-or-nothing
+ principle.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> overcomes this
+ problem by showing only such row versions to other
+ transactions whose originating transaction is
+ successfully committed. It skips all row versions of
+ uncommitted transactions. And
+ <productname>PostgreSQL</productname> solves one more
+ problem. Even the single <command>COMMIT</command>
+ command needs a short time interval for its execution.
+ Therefore its critical 'dead-or-survival' phase
+ runs in a priviledged mode where it cannot be
+ interrupted by other processes.
+ </para>
+
+ <bridgehead renderas="sect2">What are the benefits?</bridgehead>
+
+ <para>
+ Transactions relieve applications from many standard
+ actions that must be implemented for nearly every use case.
+ </para>
+
+ <para>
+ Business logic often contains strong, but for a computer,
+ relative abstract requirements. The above example shows
+ the transfers of some money from one account to another.
+ It is obvious
+ that the decrease of the one and the increase of the
+ other must be indivisible. Nevertheless, there is no particular
+ need for an application to do something to ensure the
+ <glossterm linkend="glossary-atomicity">atomicity</glossterm>
+ of this behavior. It's enough to surround them with
+ <command>BEGIN</command> and <command>COMMIT</command>.
+ </para>
+
+ <para>
+ Applications often demand the feature of 'undoing'
+ previously taken actions under some application-specific
+ conditions. In such cases, the application simply issues a
+ <command>ROLLBACK</command> command instead of a
+ <command>COMMIT</command>. The <command>ROLLBACK</command>
+ cancels the transaction, and all changes made so far remain
+ invisible forever; it is as if they had never happened. There
+ is no need for the application to log its activities and
+ undo every step of the transaction separately.
+ </para>
+
+ <para>
+ Transactions ensure that the
+ <glossterm linkend="glossary-consistency">consistency</glossterm>
+ of the complete database always keeps valid. Declarative
+ rules like
+ <link linkend="ddl-constraints-primary-keys">primary</link>- or
+ <link linkend="ddl-constraints-fk">foreign keys</link>,
+ <link linkend="ddl-constraints-check-constraints">checks</link>,
+ other constraints, or
+ <link linkend="trigger-definition">triggers</link>
+ are part of the all-or-nothing nature of transactions.
+ </para>
+
+ <para>
+ Also, all self-evident — but possibly not obvious
+ — low-level demands on the database system are
+ ensured; e.g. index entries for rows must become
+ visible at the same moment as the rows themselves.
+ </para>
+
+ <para>
+ There is the additional feature
+ '<link linkend="transaction-iso">isolation level</link>',
+ which separates transactions from each other in certain ways.
+ It automatically prevents applications from some strange
+ situations.
+ </para>
+
+ <para>
+ Lastly, it is worth to notice that changes done by a
+ committed transaction will survive all future application,
+ instance, or hardware failures. The next chapter
+ explains this
+ <glossterm linkend="glossary-durability">durability</glossterm>.
+ </para>
+ </sect1>
+
+ <sect1 id="tutorial-reliability">
+ <title>Reliability</title>
+
+ <para>
+ Nothing is perfect and failures inevitably happen.
+ However, the most common types of failure are
+ well known and <productname>PostgreSQL</productname>
+ implements strategies to overcome them.
+ Such strategies use parts of the previously presented
+ techniques MVCC and transaction-rollback, plus additional
+ features.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the client side</bridgehead>
+ <para>
+ A <glossterm linkend="glossary-client">client</glossterm>
+ can fail in different ways. Its hardware can get damaged,
+ the power supply can fail, the network connection to the
+ server can break, or the client application may run into
+ a severe software error like a null pointer exception.
+ Because <productname>PostgreSQL</productname> uses a
+ client/server architecture, no direct problem for the
+ database will occur. In all of this cases, the
+ <glossterm linkend="glossary-backend">Backend process</glossterm>,
+ which is the client's counterpart at the server-side,
+ may recognize that the network connection is no longer
+ working, or it may run into a timeout after a while. It
+ terminates, and there is no harm to the database. As
+ usual, uncommitted data changes initiated by this client
+ are not visible to any other client.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the server-side</bridgehead>
+
+ <bridgehead renderas="sect3">Instance failure</bridgehead>
+ <para>
+ The instance may suddenly fail because of <emphasis>power off</emphasis>
+ or other problems. This will affect all running processes, the RAM,
+ and possibly the consistency of disk files.
+ </para>
+ <para>
+ After a restart, <productname>PostgreSQL</productname>
+ automatically recognizes that the last shutdown of the
+ instance did not happen as expected: files might not be
+ closed properly and the <literal>postmaster.pid</literal>
+ file exists. <productname>PostgreSQL</productname>
+ tries to clean up the situation. This is possible because
+ all changes in the database are stored twice. First,
+ the WAL files contain them as a chronology of
+ <glossterm linkend="glossary-wal-record">WAL records</glossterm>,
+ which include the new data values and information about commit
+ actions. The WAL records are written first. Second,
+ the data itself shall exist in the heap and index files.
+ In opposite to the WAL records, this part may or may
+ not have been transferred entirely from Shared Memory
+ to the files.
+ </para>
+ <para>
+ The automatic recovery searches within the WAL files for
+ the latest
+ <glossterm linkend="glossary-checkpoint">checkpoint</glossterm>.
+ This checkpoint signals that the database files are in
+ a consistent state, especially that all WAL records up to
+ this point were successfully stored in heap and index. Starting
+ here, the recovery process copies the following WAL records
+ to heap and index. As a result, the files contain all
+ changes and reach a consistent state. Changes of committed
+ transactions are visible; those of uncommited transactions
+ are also in the files, but - as usual - they are never seen
+ by any of the following transactions because uncommited
+ changes are never shown. Such recovery actions run
+ completely automatically, it is not necessary that a
+ database administrator configure or start anything by
+ himself.
+ </para>
+
+ <bridgehead renderas="sect3">Disk crash</bridgehead>
+ <para>
+ If a disk crashes, the course of action described previously
+ cannot work. It is likely that the WAL files and/or the
+ data and index files are no longer available. The
+ database administrator must take special actions to
+ overcome such situations.
+ </para>
+ <para>
+ He obviously needs a backup. How to take such a backup
+ and use it as a starting point for a recovery of the
+ cluster is explained in more detail in the next
+ <link linkend="tutorial-backup">chapter</link>.
+ </para>
+
+ <bridgehead renderas="sect3">Disk full</bridgehead>
+ <para>
+ It is conceivable that over time the disk gets full,
+ and there is no room for additional data. In this case,
+ <productname>PostgreSQL</productname> stops accepting
+ data-modifying commands or even terminates completely.
+ No data loss or data corruption will occur.
+ </para>
+ <para>
+ To come out of such a situation, the administrator should
+ remove unused files from this disk. But he should never
+ delete files from the
+ <glossterm linkend="glossary-data-directory">data directory</glossterm>.
+ Nearly all of them are necessary for the consistency
+ of the database.
+ </para>
+
+ <bridgehead renderas="sect2">High availability</bridgehead>
+ <para>
+ Database servers can work together to allow a second
+ server to quickly take over the workload if the
+ primary server fails for whatever reason
+ (<link linkend="high-availability">high availability</link>),
+ or to allow several computers to serve the same data
+ for the purpose of load balancing.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-backup">
+ <title>Backup</title>
+
+ <para>
+ Taking backups is a basic task of database maintenance.
+ <productname>PostgreSQL</productname> supports
+ three different strategies; each has its own
+ strengths and weaknesses.
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ File system level backup
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Logical backup via <command>pg_dump</command>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Continuous archiving based on <command>pg_basebackup</command>
+ and WAL files
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <bridgehead renderas="sect2">File system level backup</bridgehead>
+ <para>
+ You can use any appropriate OS tool to create a
+ <link linkend="backup-file">copy</link>
+ of the cluster's directory structure and files. In
+ case of severe problems such a copy can serve as
+ the source of recovery. But in order to get a
+ <emphasis>USABLE</emphasis> backup by this method,
+ the database server <emphasis>MUST</emphasis> be
+ shut down during the complete runtime of the copy
+ command!
+ </para>
+ <para>
+ The obvious disadvantage of this method is that there
+ is a downtime where no user interaction is possible.
+ The other two strategies run during regular operating
+ times.
+ </para>
+
+ <bridgehead renderas="sect2">Logical backup via pg_dump</bridgehead>
+ <para>
+ The tool <command>pg_dump</command> is able to take a
+ <link linkend="backup-dump">copy</link>
+ of the complete cluster or certain parts of it. It stores
+ the copy in the form of SQL <command>CREATE</command> and
+ <command>INSERT</command> commands. It runs in
+ parallel to other processes in its own transaction.
+ </para>
+ <para>
+ The output of <command>pg_dump</command> may be used as
+ input of <command>psql</command> to restore the data
+ (or to copy it to another database).
+ </para>
+ <para>
+ The main advantage over the other two methods is that it
+ can pick parts of the cluster, e.g., a single table or one
+ database. The other two methods work only at the level of
+ the complete cluster.
+ </para>
+
+ <bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
+ <para>
+ <link linkend="continuous-archiving">This method</link>
+ is the most sophisticated and complex one. It
+ consists of two phases.
+ </para>
+ <para>
+ First, you need to create a so called
+ <firstterm>basebackup</firstterm> with the tool
+ <command>pg_basebackup</command>. The result is a
+ directory structure plus files which contains a
+ consistent copy of the original cluster.
+ <command>pg_basebackup</command> runs in
+ parallel to other processes in its own transaction.
+ </para>
+ <para>
+ The second step is recommended but not necessary. All
+ changes to the data are stored in WAL files. If you
+ continuously save such WAL files, you have the history
+ of the cluster. This history can be applied to a
+ basebackup in order to recreate
+ any state of the cluster between the time of
+ <command>pg_basebackup</command>'s start time and
+ any later point in time. This technique
+ is called 'Point-in-Time Recovery (PITR)'.
+ </para>
+ <para>
+ If configured, the
+ <glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
+ will automatically copy every single WAL file to a save location.
+ <link linkend="backup-archiving-wal">Its configuration</link>
+ consists mainly of a string, which contains a copy command
+ in the operating system's syntax. In order to protect your
+ data against a disk crash, the destination location
+ of a basebackup as well as of the
+ <firstterm>archived WAL files</firstterm> should be on a
+ disk which is different from the data disk.
+ </para>
+ <para>
+ If it gets necessary to restore the cluster, you have to
+ copy the basebackup and the
+ archived WAL files to
+ their original directories. The configuration of this
+ <link linkend="backup-pitr-recovery">recovery procedure</link>
+ contains a string with the reverse copy command: from
+ archive location to database location.
+ </para>
+
+ </sect1>
+
+<!-- ToDo: replication, index-types, extension mechanism, ...
+ <sect1 id="tutorial-replication">
+ <title>Replication</title>
+
+ <para>
+...
+ </para>
+
+ </sect1>
+-->
+
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 38e8aa0bbf..7490d3c9c2 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -80,6 +80,7 @@
%allfiles;
<!-- developer's guide -->
+<!ENTITY architecture SYSTEM "architecture.sgml">
<!ENTITY arch-dev SYSTEM "arch-dev.sgml">
<!ENTITY bki SYSTEM "bki.sgml">
<!ENTITY catalogs SYSTEM "catalogs.sgml">
diff --git a/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
new file mode 100644
index 0000000000..7e13753d48
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
@@ -0,0 +1,160 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="685" viewBox="0 0 900 685">
+ <title>
+ Server (Hardware, Container, or VM)
+ </title>
+ <style>
+ .text_normal,.text_small{font-style:normal;font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_small{font-size:12px}.text_normal{font-size:16px}
+ </style>
+ <defs>
+ <symbol id="rectangle_special_0">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="rectangle_special_1">
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="125">
+ 'my_schema' (optional)
+ </text>
+ <text class="text_small" x="20" y="145">
+ tables, views, ...
+ </text>
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="190">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M450 10v230H0V0h440v10h10L440 0"/>
+ </symbol>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="270" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Server (Hardware, Container, or VM)
+ </text>
+ <path stroke="blue" stroke-width="2" fill="none" d="M20 110h790v555H20z"/>
+ <text class="text_normal" x="180" y="25" transform="translate(20 110)">
+ cluster 'data' (default, managed by one instance)
+ </text>
+ <path d="M50 110V80h790v555h-30" stroke="blue" stroke-width="2" fill="none"/>
+ <text class="text_normal" x="190" y="-10" transform="translate(45 110)">
+ cluster 'cluster_2' (optional, managed by a different instance)
+ </text>
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template0'
+ </text>
+ </g>
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template1'
+ </text>
+ </g>
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'my_db' (optional)
+ </text>
+ </g>
+ <g transform="translate(320 330)">
+ <rect width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4"/>
+ <text class="text_normal" x="15" y="27">
+ Global SQL objects
+ </text>
+ <path d="M0 5l-65-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M80 0v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M180 40h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M0 40l-45 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ </g>
+ <g transform="translate(335 405)">
+ <use xlink:href="#note"/>
+ <text class="text_small" x="10" y="20">
+ 1)
+ </text>
+ <text class="text_small" x="30" y="20">
+ By default, you work in the cluster 'data', database 'postgres',
+ </text>
+ <text class="text_small" x="30" y="35">
+ schema 'public'.
+ </text>
+ <text class="text_small" x="10" y="55">
+ 2)
+ </text>
+ <text class="text_small" x="30" y="55">
+ More system schemas: pg_catalog, information_schema,
+ </text>
+ <text class="text_small" x="30" y="70">
+ pg_temp, pg_toast.
+ </text>
+ <text class="text_small" x="10" y="90">
+ 3)
+ </text>
+ <text class="text_small" x="30" y="90">
+ Global SQL objects: Some SQL objects are automatically active
+ </text>
+ <text class="text_small" x="30" y="105">
+ and known database- or even cluster-wide.
+ </text>
+ <text class="text_small" x="10" y="125">
+ 4)
+ </text>
+ <text class="text_small" x="30" y="125">
+ The command 'initdb' creates a new cluster with the three
+ </text>
+ <text class="text_small" x="30" y="140">
+ databases 'template0', 'template1', and 'postgres'. The command
+ </text>
+ <text class="text_small" x="30" y="155">
+ 'createdb' creates a new database.
+ </text>
+ <text class="text_small" x="10" y="175">
+ 5)
+ </text>
+ <text class="text_small" x="30" y="175">
+ If multiple clusters are active on one server at the same time,
+ </text>
+ <text class="text_small" x="30" y="190">
+ each one is managed by an individual instance. Each such instance
+ </text>
+ <text class="text_small" x="30" y="205">
+ uses a different port.
+ </text>
+ <text class="text_small" x="10" y="225">
+ 6)
+ </text>
+ <text class="text_small" x="30" y="225">
+ No client application is allowed to connect to 'template0'.
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink.svg b/doc/src/sgml/images/cluster-db-schema-ink.svg
new file mode 100644
index 0000000000..1fffb9737a
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink.svg
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="685px"
+ viewBox="0 0 900 685"
+ id="svg147"
+ sodipodi:docname="cluster-db-schema-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Server (Hardware, Container, or VM)</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1129"
+ inkscape:window-height="922"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.68905109"
+ inkscape:cx="737.16805"
+ inkscape:cy="342.1375"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Server (Hardware, Container, or VM)</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs49">
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangle_special_0">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect6" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="195"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect8" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text10">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text12">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="195"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect14" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text16">(more system schemas)</text>
+ </symbol>
+ <!-- same as before, but one more schema -->
+ <symbol
+ id="rectangle_special_1">
+ <!-- the database -->
+ <rect
+ width="245"
+ height="225"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect19" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect21" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text23">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text25">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect27" />
+ <text
+ class="text_normal"
+ x="20"
+ y="125"
+ id="text29">'my_schema' (optional)</text>
+ <text
+ class="text_small"
+ x="20"
+ y="145"
+ id="text31">tables, views, ...</text>
+ <rect
+ x="15"
+ y="170"
+ width="205"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect33" />
+ <text
+ class="text_small"
+ x="20"
+ y="190"
+ id="text35">(more system schemas)</text>
+ </symbol>
+ <symbol
+ id="note"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title38">UML Note</title>
+ <path
+ d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10"
+ id="path40" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path43" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path46" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect51" />
+ <text
+ class="text_big"
+ x="270"
+ y="40"
+ id="text53">Server (Hardware, Container, or VM)</text>
+ <!-- two clusters -->
+ <g
+ transform="translate(20 110)"
+ id="g59">
+ <rect
+ x="0"
+ y="0"
+ width="790"
+ height="555"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="rect55" />
+ <text
+ class="text_normal"
+ x="180"
+ y="25"
+ id="text57">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g
+ transform="translate(45 110)"
+ id="g65">
+ <path
+ d="M 5,0 v -30 h 790 v 555 h -30"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="path61" />
+ <text
+ class="text_normal"
+ x="190"
+ y="-10"
+ id="text63">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+ <!-- database template 0 -->
+ <g
+ transform="translate(40 155)"
+ id="g71">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use67" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text69">database 'template0'</text>
+ </g>
+ <!-- database template 1 -->
+ <g
+ transform="translate(290 155)"
+ id="g77">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use73" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text75">database 'template1'</text>
+ </g>
+ <!-- database postgres -->
+ <g
+ transform="translate(540 155)"
+ id="g83">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use79" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text81">database 'postgres'</text>
+ </g>
+ <!-- database my_db -->
+ <g
+ transform="translate(40 350)"
+ id="g89">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use85" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text87">database 'my_db' (optional)</text>
+ </g>
+ <!-- global objects -->
+ <g
+ transform="translate(320 330)"
+ id="g103">
+ <rect
+ x="0"
+ y="0"
+ width="180"
+ height="45"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="10 4 4 4"
+ id="rect91" />
+ <text
+ class="text_normal"
+ x="15"
+ y="27"
+ id="text93">Global SQL objects</text>
+ <path
+ d="M 0,5 l-65,-35"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path95" />
+ <path
+ d="M 80,0 v-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path97" />
+ <path
+ d="M 180,40 h50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path99" />
+ <path
+ d="M 0,40 l-45,20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path101" />
+ </g>
+ <!-- Some comments -->
+ <g
+ transform="translate(335 405)"
+ id="g145">
+ <use
+ xlink:href="#note"
+ x="0"
+ y="0"
+ id="use105" />
+ <text
+ class="text_small"
+ x="10"
+ y="20"
+ id="text107">1)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="20"
+ id="text109">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text
+ class="text_small"
+ x="30"
+ y="35"
+ id="text111">schema 'public'.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="55"
+ id="text113">2)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="55"
+ id="text115">More system schemas: pg_catalog, information_schema,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="70"
+ id="text117">pg_temp, pg_toast.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="90"
+ id="text119">3)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="90"
+ id="text121">Global SQL objects: Some SQL objects are automatically active</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text123">and known database- or even cluster-wide.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="125"
+ id="text125">4)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="125"
+ id="text127">The command 'initdb' creates a new cluster with the three</text>
+ <text
+ class="text_small"
+ x="30"
+ y="140"
+ id="text129">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text
+ class="text_small"
+ x="30"
+ y="155"
+ id="text131">'createdb' creates a new database.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="175"
+ id="text133">5)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="175"
+ id="text135">If multiple clusters are active on one server at the same time,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="190"
+ id="text137">each one is managed by an individual instance. Each such instance</text>
+ <text
+ class="text_small"
+ x="30"
+ y="205"
+ id="text139">uses a different port.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="225"
+ id="text141">6)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="225"
+ id="text143">No client application is allowed to connect to 'template0'.</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
new file mode 100644
index 0000000000..af50c07330
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="685px"
+ viewBox="0 0 900 685" >
+
+ <title>Server (Hardware, Container, or VM)</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_0">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">(more system schemas)</text>
+ </symbol>
+
+ <!-- same as before, but one more schema -->
+ <symbol id="rectangle_special_1">
+ <!-- the database -->
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="125">'my_schema' (optional)</text>
+ <text class="text_small" x="20" y="145">tables, views, ...</text>
+
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="190">(more system schemas)</text>
+ </symbol>
+
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="270" y="40">Server (Hardware, Container, or VM)</text>
+
+ <!-- two clusters -->
+ <g transform="translate(20 110)">
+ <rect x="0" y="0" width="790" height="555" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="180" y="25">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g transform="translate(45 110)">
+ <path d="M 5,0 v -30 h 790 v 555 h -30" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="190" y="-10">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+
+
+ <!-- database template 0 -->
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template0'</text>
+ </g>
+
+ <!-- database template 1 -->
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template1'</text>
+ </g>
+
+ <!-- database postgres -->
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'postgres'</text>
+ </g>
+
+ <!-- database my_db -->
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
+ </g>
+
+ <!-- global objects -->
+ <g transform="translate(320 330)">
+ <rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
+ <text class="text_normal" x="15" y="27">Global SQL objects</text>
+ <path d="M 0,5 l-65,-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ </g>
+
+ <!-- Some comments -->
+ <g transform="translate(335 405)">
+ <use xlink:href="#note" x="0" y="0" />
+
+ <text class="text_small" x="10" y="20">1)</text>
+ <text class="text_small" x="30" y="20">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text class="text_small" x="30" y="35">schema 'public'.</text>
+
+ <text class="text_small" x="10" y="55">2)</text>
+ <text class="text_small" x="30" y="55">More system schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="70">pg_temp, pg_toast.</text>
+
+ <text class="text_small" x="10" y="90">3)</text>
+ <text class="text_small" x="30" y="90">Global SQL objects: Some SQL objects are automatically active</text>
+ <text class="text_small" x="30" y="105">and known database- or even cluster-wide.</text>
+
+ <text class="text_small" x="10" y="125">4)</text>
+ <text class="text_small" x="30" y="125">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="140">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="155">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="175">5)</text>
+ <text class="text_small" x="30" y="175">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="190">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="205">uses a different port.</text>
+
+ <text class="text_small" x="10" y="225">6)</text>
+ <text class="text_small" x="30" y="225">No client application is allowed to connect to 'template0'.</text>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/directories-ink-svgo.svg b/doc/src/sgml/images/directories-ink-svgo.svg
new file mode 100644
index 0000000000..95fa76b9c6
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink-svgo.svg
@@ -0,0 +1,164 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="640" viewBox="0 0 900 640">
+ <title>
+ Directory structure of a cluster
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <symbol id="directory" stroke="blue" stroke-width=".3" fill="aqua">
+ <title>
+ Directory
+ </title>
+ <path d="M0 10h110v20H0z"/>
+ <path d="M0 10V8l3-3h35l3 3v2"/>
+ </symbol>
+ <symbol id="file" stroke="black" fill="none">
+ <title>
+ File
+ </title>
+ <path stroke="blue" d="M0 0h40v50H0z"/>
+ <path d="M5 10h20" stroke-dasharray="4 2"/>
+ <path d="M5 17h15" stroke-dasharray="6 2"/>
+ <path d="M5 24h25" stroke-dasharray="4 2"/>
+ <path d="M5 31h20" stroke-dasharray="5 2"/>
+ </symbol>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="50" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Directory Structure
+ </text>
+ <g transform="translate(20 100)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /pg/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ An arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 130)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ data/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of cluster 'data' (see: PGDATA)
+ </text>
+ </g>
+ <g transform="translate(120 160)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ base/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing per-database subdirectories
+ </text>
+ </g>
+ <g transform="translate(170 190)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 1/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of first database 'template0'
+ </text>
+ </g>
+ <g transform="translate(170 220)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12992/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of second database 'template1'
+ </text>
+ </g>
+ <g transform="translate(170 250)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12999/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of third database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(170 280)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ nnnnn/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Optional: more subdirectories for databases, e.g. 'my_db'
+ </text>
+ </g>
+ <g transform="translate(120 310)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ global/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory with information about Global SQL Objects
+ </text>
+ </g>
+ <g transform="translate(120 340)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_wal/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 370)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_xact/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for transaction commit status ('pg_clog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 400)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_tblspc/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing symbolic links to tablespaces
+ </text>
+ </g>
+ <g transform="translate(120 430)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_... /
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Some more subdirectories
+ </text>
+ </g>
+ <g transform="translate(120 465)">
+ <use xlink:href="#file"/>
+ <use xlink:href="#file" x="50"/>
+ <text x="200" y="26" class="text_normal">
+ 'postmaster.pid' and other files with cluster-wide relevance
+ </text>
+ </g>
+ <g transform="translate(20 540)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /xyz/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ Same or another arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 570)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ cluster_2/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of another cluster 'cluster_2'
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-ink.svg b/doc/src/sgml/images/directories-ink.svg
new file mode 100644
index 0000000000..8151cf583a
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink.svg
@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="640px"
+ viewBox="0 0 900 640"
+ id="svg303"
+ sodipodi:docname="directories-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata307">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Directory structure of a cluster</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1083"
+ inkscape:window-height="808"
+ id="namedview305"
+ showgrid="false"
+ inkscape:zoom="0.36875"
+ inkscape:cx="450"
+ inkscape:cy="320"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg303" />
+ <title
+ id="title153">Directory structure of a cluster</title>
+ <style
+ type="text/css"
+ id="style155">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs177">
+ <!-- Directory -->
+ <symbol
+ id="directory"
+ stroke="blue"
+ stroke-width="0.3px"
+ fill="aqua">
+ <title
+ id="title157">Directory</title>
+ <rect
+ x="0"
+ y="10"
+ width="110"
+ height="20"
+ id="rect159" />
+ <path
+ d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2"
+ id="path161" />
+ </symbol>
+ <!-- File -->
+ <symbol
+ id="file"
+ stroke="black"
+ fill="none">
+ <title
+ id="title164">File</title>
+ <rect
+ x="0"
+ y="0"
+ width="40"
+ height="50"
+ stroke="blue"
+ id="rect166" />
+ <path
+ d="M 5,10 h 20"
+ stroke-dasharray="4 2"
+ id="path168" />
+ <path
+ d="M 5,17 h 15"
+ stroke-dasharray="6 2"
+ id="path170" />
+ <path
+ d="M 5,24 h 25"
+ stroke-dasharray="4 2"
+ id="path172" />
+ <path
+ d="M 5,31 h 20"
+ stroke-dasharray="5 2"
+ id="path174" />
+ </symbol>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect179" />
+ <!-- caption -->
+ <text
+ x="200"
+ y="50"
+ class="text_big"
+ id="text181">Directory Structure</text>
+ <!-- the directories -->
+ <g
+ transform="translate(20, 100)"
+ id="g189">
+ <use
+ xlink:href="#directory"
+ id="use183" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text185">... /pg/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text187">An arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 130)"
+ id="g197">
+ <use
+ xlink:href="#directory"
+ id="use191" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text193">data/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text195">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+ <g
+ transform="translate(120, 160)"
+ id="g205">
+ <use
+ xlink:href="#directory"
+ id="use199" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text201">base/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text203">Subdirectory containing per-database subdirectories</text>
+ </g>
+ <!-- -->
+ <g
+ transform="translate(170, 190)"
+ id="g213">
+ <use
+ xlink:href="#directory"
+ id="use207" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text209">1/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text211">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g
+ transform="translate(170, 220)"
+ id="g221">
+ <use
+ xlink:href="#directory"
+ id="use215" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text217">12992/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text219">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g
+ transform="translate(170, 250)"
+ id="g229">
+ <use
+ xlink:href="#directory"
+ id="use223" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text225">12999/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text227">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g
+ transform="translate(170, 280)"
+ id="g237">
+ <use
+ xlink:href="#directory"
+ id="use231" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text233">nnnnn/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text235">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+ <g
+ transform="translate(120, 310)"
+ id="g245">
+ <use
+ xlink:href="#directory"
+ id="use239" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text241">global/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text243">Subdirectory with information about Global SQL Objects</text>
+ </g>
+ <g
+ transform="translate(120, 340)"
+ id="g253">
+ <use
+ xlink:href="#directory"
+ id="use247" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text249">pg_wal/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text251">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 370)"
+ id="g261">
+ <use
+ xlink:href="#directory"
+ id="use255" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text257">pg_xact/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text259">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 400)"
+ id="g269">
+ <use
+ xlink:href="#directory"
+ id="use263" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text265">pg_tblspc/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text267">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+ <g
+ transform="translate(120, 430)"
+ id="g277">
+ <use
+ xlink:href="#directory"
+ id="use271" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text273">pg_... /</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text275">Some more subdirectories</text>
+ </g>
+ <g
+ transform="translate(120, 465)"
+ id="g285">
+ <use
+ xlink:href="#file"
+ x="0"
+ y="0"
+ id="use279" />
+ <use
+ xlink:href="#file"
+ x="50"
+ y="0"
+ id="use281" />
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text283">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+ <!-- next cluster -->
+ <g
+ transform="translate(20, 540)"
+ id="g293">
+ <use
+ xlink:href="#directory"
+ id="use287" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text289">... /xyz/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text291">Same or another arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 570)"
+ id="g301">
+ <use
+ xlink:href="#directory"
+ id="use295" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text297">cluster_2/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text299">Root of another cluster 'cluster_2'</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
new file mode 100644
index 0000000000..6d16a03169
--- /dev/null
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="640px"
+ viewBox="0 0 900 640">
+
+ <title>Directory structure of a cluster</title>
+
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Directory -->
+ <symbol id="directory" stroke="blue" stroke-width="0.3px" fill="aqua">
+ <title>Directory</title>
+ <rect x="0" y="10" width="110" height="20" />
+ <path d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2" />
+ </symbol>
+
+ <!-- File -->
+ <symbol id="file" stroke="black" fill="none" >
+ <title>File</title>
+ <rect x="0" y="0" width="40" height="50" stroke="blue" />
+ <path d="M 5,10 h 20" stroke-dasharray="4 2" />
+ <path d="M 5,17 h 15" stroke-dasharray="6 2" />
+ <path d="M 5,24 h 25" stroke-dasharray="4 2" />
+ <path d="M 5,31 h 20" stroke-dasharray="5 2" />
+ </symbol>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption -->
+ <text x="200" y="50" class="text_big">Directory Structure</text>
+
+ <!-- the directories -->
+ <g transform="translate(20, 100)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /pg/</text>
+ <text x="300" y="26" class="text_normal">An arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 130)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">data/</text>
+ <text x="250" y="26" class="text_normal">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+
+ <g transform="translate(120, 160)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">base/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing per-database subdirectories</text>
+ </g>
+
+ <!-- -->
+ <g transform="translate(170, 190)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">1/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g transform="translate(170, 220)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12992/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g transform="translate(170, 250)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12999/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g transform="translate(170, 280)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">nnnnn/</text>
+ <text x="150" y="26" class="text_normal">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+
+ <g transform="translate(120, 310)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">global/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory with information about Global SQL Objects</text>
+ </g>
+
+ <g transform="translate(120, 340)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 370)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 400)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+
+ <g transform="translate(120, 430)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_... /</text>
+ <text x="200" y="26" class="text_normal">Some more subdirectories</text>
+ </g>
+
+ <g transform="translate(120, 465)">
+ <use xlink:href="#file" x="0" y="0" />
+ <use xlink:href="#file" x="50" y="0" />
+ <text x="200" y="26" class="text_normal">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+
+ <!-- next cluster -->
+ <g transform="translate(20, 540)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /xyz/</text>
+ <text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 570)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster 'cluster_2'</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink-svgo.svg b/doc/src/sgml/images/freeze-ink-svgo.svg
new file mode 100644
index 0000000000..6fedfb7633
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink-svgo.svg
@@ -0,0 +1,84 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="320" viewBox="0 0 850 320">
+ <title>
+ Freeze
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100)"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="70" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ <tspan font-style="italic" font-weight="700">Freeze</tspan> to keep visible
+ </text>
+ <g fill="none" transform="translate(170 190)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_120" startOffset="11.2%">(1)</textPath> <textPath xlink:href="#Path_120" startOffset="61.2%">(5)</textPath> <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%">|</textPath> <textPath xlink:href="#Path_120" startOffset="34%">(2)</textPath> <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(3)</textPath> <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%">|</textPath> <textPath xlink:href="#Path_120" startOffset="55%">(4)</textPath>
+ </text>
+ <path d="M-80-80L80 80" stroke="black"/>
+ <text class="text_normal" letter-spacing="12" transform="rotate(45 40.78 -38.1)">
+ PAST
+ </text>
+ <text class="text_normal" letter-spacing="12" transform="rotate(-135 27.43 23.79)">
+ FUTURE
+ </text>
+ <use xlink:href="#frozenPoint" transform="rotate(10)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(25)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(40)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(55)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(70)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(85)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(100)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(115)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(130)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(145)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(160)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(175)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(190)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(205)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(220)"/>
+ </g>
+ <g class="text_normal" transform="translate(380 30)">
+ <text>
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25">
+ 1: txid_current + 2 ^ 31 (split-point)
+ </text>
+ <text y="50">
+ 2: autovacuum_freeze_max_age (200 mio.)
+ </text>
+ <text y="75">
+ 3: vacuum_freeze_table_age (150 mio.)
+ </text>
+ <text y="100">
+ 4: vacuum_freeze_min_age (50 mio.)
+ </text>
+ <text y="125">
+ 5: txid_current (split-point, jungest xid)
+ </text>
+ <text y="155">
+ per table: pg_class.relfrozenxid <tspan font-weight="700">must</tspan> be between (1) and (5);
+ </text>
+ <text y="175" x="75">
+ normally it is between (3) and (4)
+ </text>
+ <use xlink:href="#unfrozenPoint" transform="translate(106 200)"/>
+ <text y="205" x="20">
+ Unfrozen xid
+ </text>
+ <use xlink:href="#frozenPoint" transform="translate(106 224)"/>
+ <text y="230" x="20">
+ Frozen xid
+ </text>
+ <text y="260">
+ (figure is out of scale)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink.svg b/doc/src/sgml/images/freeze-ink.svg
new file mode 100644
index 0000000000..009cfe4b41
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink.svg
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="320px"
+ viewBox="0 0 850 320"
+ id="svg454"
+ sodipodi:docname="freeze-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata458">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Freeze</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="979"
+ inkscape:window-height="857"
+ id="namedview456"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="160"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg454" />
+ <title
+ id="title309">Freeze</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style311">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs318">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle
+ id="frozenPoint"
+ r="3"
+ stroke="green"
+ fill="green"
+ transform="translate(-100, 0)" />
+ <circle
+ id="unfrozenPoint"
+ r="3"
+ stroke="green"
+ fill="none"
+ transform="translate(-100, 0)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect320" />
+ <text
+ class="text_big"
+ x="70"
+ y="40"
+ id="text324"><tspan
+ style="font-style:italic;font-weight:bold"
+ id="tspan322">
+ Freeze</tspan>
+ to keep visible</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 190)"
+ id="g418">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle326" />
+ <text
+ class="text_normal"
+ id="text350">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath328">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath330">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath332">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="11.2%"
+ id="textPath334">(1)</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="61.2%"
+ id="textPath336">(5)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="red"
+ stroke-width="3"
+ startOffset="34%"
+ id="textPath338">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="34%"
+ id="textPath340">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="black"
+ stroke-width="3"
+ startOffset="45%"
+ id="textPath342">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath344">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="green"
+ stroke-width="3"
+ startOffset="55%"
+ id="textPath346">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="55%"
+ id="textPath348">(4)</textPath>
+ </text>
+ <!-- split it into 'past' and 'future' -->
+ <path
+ d="M -80 -80 l 160 160"
+ stroke="black"
+ id="path352" />
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(-15, -40) rotate(45)"
+ id="text354">PAST</text>
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(30, 60) rotate(225)"
+ id="text356">FUTURE</text>
+ <g
+ transform="rotate(10)"
+ id="g360">
+ <use
+ xlink:href="#frozenPoint"
+ id="use358" />
+ </g>
+ <g
+ transform="rotate(25)"
+ id="g364">
+ <use
+ xlink:href="#frozenPoint"
+ id="use362" />
+ </g>
+ <g
+ transform="rotate(40)"
+ id="g368">
+ <use
+ xlink:href="#frozenPoint"
+ id="use366" />
+ </g>
+ <g
+ transform="rotate(55)"
+ id="g372">
+ <use
+ xlink:href="#frozenPoint"
+ id="use370" />
+ </g>
+ <g
+ transform="rotate(70)"
+ id="g376">
+ <use
+ xlink:href="#frozenPoint"
+ id="use374" />
+ </g>
+ <g
+ transform="rotate(85)"
+ id="g380">
+ <use
+ xlink:href="#frozenPoint"
+ id="use378" />
+ </g>
+ <g
+ transform="rotate(100)"
+ id="g384">
+ <use
+ xlink:href="#frozenPoint"
+ id="use382" />
+ </g>
+ <g
+ transform="rotate(115)"
+ id="g388">
+ <use
+ xlink:href="#frozenPoint"
+ id="use386" />
+ </g>
+ <g
+ transform="rotate(130)"
+ id="g392">
+ <use
+ xlink:href="#frozenPoint"
+ id="use390" />
+ </g>
+ <g
+ transform="rotate(145)"
+ id="g396">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use394" />
+ </g>
+ <g
+ transform="rotate(160)"
+ id="g400">
+ <use
+ xlink:href="#frozenPoint"
+ id="use398" />
+ </g>
+ <g
+ transform="rotate(175)"
+ id="g404">
+ <use
+ xlink:href="#frozenPoint"
+ id="use402" />
+ </g>
+ <g
+ transform="rotate(190)"
+ id="g408">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use406" />
+ </g>
+ <g
+ transform="rotate(205)"
+ id="g412">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use410" />
+ </g>
+ <g
+ transform="rotate(220)"
+ id="g416">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use414" />
+ </g>
+ </g>
+ <!-- legend -->
+ <g
+ class="text_normal"
+ transform="translate(380 30)"
+ id="g452">
+ <text
+ id="text424">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan420">^</tspan>
+<tspan
+ dy="5"
+ id="tspan422">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text426">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text
+ y="50"
+ id="text428">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text
+ y="75"
+ id="text430">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text
+ y="100"
+ id="text432">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text
+ y="125"
+ id="text434">5: txid_current (split-point, jungest xid)</text>
+ <text
+ y="155"
+ id="text438">per table: pg_class.relfrozenxid
+ <tspan
+ style="font-weight:bold"
+ id="tspan436">must</tspan>
+ be between (1) and (5);</text>
+ <text
+ y="175"
+ x="75"
+ id="text440">normally it is between (3) and (4)</text>
+ <use
+ xlink:href="#unfrozenPoint"
+ transform="translate(106, 200)"
+ id="use442" />
+ <text
+ y="205"
+ x="20"
+ id="text444">Unfrozen xid</text>
+ <use
+ xlink:href="#frozenPoint"
+ transform="translate(106, 224)"
+ id="use446" />
+ <text
+ y="230"
+ x="20"
+ id="text448">Frozen xid</text>
+ <text
+ y="260"
+ id="text450">(figure is out of scale)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-raw.svg b/doc/src/sgml/images/freeze-raw.svg
new file mode 100644
index 0000000000..2d1d256184
--- /dev/null
+++ b/doc/src/sgml/images/freeze-raw.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="320px"
+ viewBox="0 0 850 320" >
+
+ <title>Freeze</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100, 0)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100, 0)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="70" y="40"><tspan style="font-style:italic;font-weight:bold">
+ Freeze</tspan> to keep visible</text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 190)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_120" startOffset="11.2%" >(1)</textPath>
+ <textPath xlink:href="#Path_120" startOffset="61.2%" >(5)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="34%" >(2)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(3)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="55%" >(4)</textPath>
+
+ </text>
+
+ <!-- split it into 'past' and 'future' -->
+ <path d="M -80 -80 l 160 160" stroke="black" />
+ <text class="text_normal" letter-spacing="12" transform="translate(-15, -40) rotate(45)">PAST</text>
+ <text class="text_normal" letter-spacing="12" transform="translate(30, 60) rotate(225)">FUTURE</text>
+
+ <g transform="rotate(10)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(25)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(40)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(55)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(70)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(85)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(100)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(115)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(130)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(145)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(160)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(175)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(190)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(205)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(220)"><use xlink:href="#unfrozenPoint"/></g>
+
+ </g>
+
+ <!-- legend -->
+ <g class="text_normal" transform="translate(380 30)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text y="50">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text y="75">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text y="100">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text y="125">5: txid_current (split-point, jungest xid)</text>
+ <text y="155">per table: pg_class.relfrozenxid
+ <tspan style="font-weight:bold">must</tspan> be between (1) and (5);</text>
+ <text y="175" x="75">normally it is between (3) and (4)</text>
+
+ <use xlink:href="#unfrozenPoint" transform="translate(106, 200)"/>
+ <text y="205" x="20">Unfrozen xid</text>
+
+ <use xlink:href="#frozenPoint" transform="translate(106, 224)"/>
+ <text y="230" x="20">Frozen xid</text>
+
+ <text y="260">(figure is out of scale)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
new file mode 100644
index 0000000000..26bce6176d
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
@@ -0,0 +1,83 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="720" height="430" viewBox="0 0 720 430">
+ <title>
+ Hierarchy of Internal Objects
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Hierarchy of internal Objects
+ </text>
+ <g fill="none">
+ <g transform="translate(350 240)">
+ <ellipse rx="320" ry="170" stroke="blue"/>
+ <text class="text_normal" x="-140" y="-130">
+ Cluster
+ </text>
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-60" y="5">
+ Database Names
+ </text>
+ </g>
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-40" y="5">
+ Tablespace
+ </text>
+ </g>
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-70" y="5">
+ Replication Origins
+ </text>
+ </g>
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue"/>
+ <text class="text_normal" x="-60" y="-3">
+ Subscription for
+ </text>
+ <text class="text_normal" x="-68" y="10">
+ Logical Replication
+ </text>
+ </g>
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-15" y="5">
+ Role
+ </text>
+ </g>
+ </g>
+ <g transform="translate(270 250)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2"/>
+ <text class="text_normal" x="-60" y="-80">
+ Database
+ </text>
+ <g transform="translate(-150 -30)">
+ <ellipse rx="50" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Extension
+ </text>
+ </g>
+ <g transform="translate(-155 35)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Collation
+ </text>
+ </g>
+ <g transform="translate(30 20)">
+ <ellipse rx="140" ry="70" stroke="blue"/>
+ <text class="text_normal" x="-80" y="-35">
+ Schema
+ </text>
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue"/>
+ <text class="text_normal" x="-50" y="5">
+ Table, View, ...
+ </text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
new file mode 100644
index 0000000000..e5745818d9
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="720px"
+ height="430px"
+ viewBox="0 0 720 430"
+ id="svg540"
+ sodipodi:docname="internal-objects-hierarchy-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata546">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Hierarchy of Internal Objects</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs544" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1050"
+ inkscape:window-height="838"
+ id="namedview542"
+ showgrid="false"
+ inkscape:zoom="0.51944444"
+ inkscape:cx="360"
+ inkscape:cy="215"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg540" />
+ <title
+ id="title460">Hierarchy of Internal Objects</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style462">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect464" />
+ <text
+ class="text_big"
+ x="200"
+ y="40"
+ id="text466">Hierarchy of internal Objects</text>
+ <!-- set centre of figure and default values -->
+ <g
+ transform="translate(350 240)"
+ fill="none"
+ id="g538">
+ <g
+ id="g504">
+ <ellipse
+ rx="320"
+ ry="170"
+ stroke="blue"
+ id="ellipse468" />
+ <text
+ class="text_normal"
+ x="-140"
+ y="-130"
+ id="text470">Cluster</text>
+ <g
+ transform="translate(40 -125)"
+ id="g476">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse472" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="5"
+ id="text474">Database Names</text>
+ </g>
+ <g
+ transform="translate(180 -70)"
+ id="g482">
+ <ellipse
+ rx="60"
+ ry="20"
+ stroke="blue"
+ id="ellipse478" />
+ <text
+ class="text_normal"
+ x="-40"
+ y="5"
+ id="text480">Tablespace</text>
+ </g>
+ <g
+ transform="translate(230 -5)"
+ id="g488">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse484" />
+ <text
+ class="text_normal"
+ x="-70"
+ y="5"
+ id="text486">Replication Origins</text>
+ </g>
+ <g
+ transform="translate(200 70)"
+ id="g496">
+ <ellipse
+ rx="78"
+ ry="27"
+ stroke="blue"
+ id="ellipse490" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-3"
+ id="text492">Subscription for</text>
+ <text
+ class="text_normal"
+ x="-68"
+ y="10"
+ id="text494">Logical Replication</text>
+ </g>
+ <g
+ transform="translate(100 120)"
+ id="g502">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse498" />
+ <text
+ class="text_normal"
+ x="-15"
+ y="5"
+ id="text500">Role</text>
+ </g>
+ </g>
+ <g
+ transform="translate(-80 10)"
+ id="g536">
+ <ellipse
+ rx="220"
+ ry="110"
+ stroke="blue"
+ stroke-width="2px"
+ id="ellipse506" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-80"
+ id="text508">Database</text>
+ <g
+ transform="translate(-120 -50)"
+ id="g534">
+ <g
+ transform="translate(-30 20)"
+ id="g514">
+ <ellipse
+ rx="50"
+ ry="20"
+ stroke="blue"
+ id="ellipse510" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text512">Extension</text>
+ </g>
+ <g
+ transform="translate(-35 85)"
+ id="g520">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse516" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text518">Collation</text>
+ </g>
+ <g
+ transform="translate(150 70)"
+ id="g532">
+ <ellipse
+ rx="140"
+ ry="70"
+ stroke="blue"
+ id="ellipse522" />
+ <text
+ class="text_normal"
+ x="-80"
+ y="-35"
+ id="text524">Schema</text>
+ <g
+ transform="translate(20 10)"
+ id="g530">
+ <ellipse
+ rx="90"
+ ry="30"
+ stroke="blue"
+ id="ellipse526" />
+ <text
+ class="text_normal"
+ x="-50"
+ y="5"
+ id="text528">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
new file mode 100644
index 0000000000..f0dc890f6b
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="720px" height="430px"
+ viewBox="0 0 720 430" >
+
+ <title>Hierarchy of Internal Objects</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="200" y="40">Hierarchy of internal Objects</text>
+
+
+ <!-- set centre of figure and default values -->
+ <g transform="translate(350 240)" fill="none">
+
+ <g>
+ <ellipse rx="320" ry="170" stroke="blue" />
+ <text class="text_normal" x="-140" y="-130">Cluster</text>
+
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-60" y="5">Database Names</text>
+ </g>
+
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue" />
+ <text class="text_normal" x="-40" y="5">Tablespace</text>
+ </g>
+
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-70" y="5">Replication Origins</text>
+ </g>
+
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue" />
+ <text class="text_normal" x="-60" y="-3">Subscription for</text>
+ <text class="text_normal" x="-68" y="10">Logical Replication</text>
+ </g>
+
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-15" y="5">Role</text>
+ </g>
+
+ </g>
+
+ <g transform="translate(-80 10)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2px" />
+ <text class="text_normal" x="-60" y="-80">Database</text>
+
+ <g transform="translate(-120 -50)">
+ <g transform="translate(-30 20)">
+ <ellipse rx="50" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Extension</text>
+ </g>
+
+ <g transform="translate(-35 85)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Collation</text>
+ </g>
+
+ <g transform="translate(150 70)">
+ <ellipse rx="140" ry="70" stroke="blue" />
+ <text class="text_normal" x="-80" y="-35">Schema</text>
+
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue" />
+ <text class="text_normal" x="-50" y="5">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink-svgo.svg b/doc/src/sgml/images/mvcc-ink-svgo.svg
new file mode 100644
index 0000000000..8e67da93d1
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink-svgo.svg
@@ -0,0 +1,151 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="150" viewBox="0 0 850 150">
+ <title>
+ MVCC
+ </title>
+ <style>
+ .text_small{font-style:normal;font-weight:400;font-size:10px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <marker id="triangle_1" markerWidth="10" markerHeight="10" refX="5" refY="5" orient="auto" stroke="black" fill="none">
+ <path d="M0 0l10 5-10 5"/>
+ </marker>
+ <path id="arrow" d="M0 0q20-15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+ <g id="tuple" stroke="black">
+ <path d="M80 0H0v20h80M29 0v20M60 0v20"/>
+ <path d="M80 0h15M80 20h15" stroke-dasharray="2 1"/>
+ </g>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <g fill="none">
+ <g transform="translate(20 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">123</tspan> <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)" fill="#00f">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 83)" fill="#00f">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(185 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">135</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 53)" fill="#00f">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(350 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">142</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 23)" fill="#00f">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(515 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">821</tspan> <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 821
+ </text>
+ <text class="text_small" transform="translate(125 23)">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(740 110)">
+ <path d="M102-20H-18v60" stroke="black"/>
+ <text font-weight="400" font-size="16" font-family=""Open Sans",sans-serif" fill="#000">
+ Legend
+ </text>
+ <use xlink:href="#tuple" transform="translate(0 10)"/>
+ <text class="text_small" transform="translate(3 23)">
+ xmin
+ </text>
+ <text class="text_small" transform="translate(32 23)">
+ xmax
+ </text>
+ <text class="text_small" transform="translate(65 23)">
+ data
+ </text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink.svg b/doc/src/sgml/images/mvcc-ink.svg
new file mode 100644
index 0000000000..f4161b3e79
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink.svg
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="150px"
+ viewBox="0 0 850 150"
+ id="svg147"
+ sodipodi:docname="mvcc-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>MVCC</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1256"
+ inkscape:window-height="801"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="75"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">MVCC</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs15">
+ <marker
+ id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto"
+ stroke="black"
+ fill="none">
+ <path
+ d="M 0,0 L 10,5 L 0,10"
+ id="path6" />
+ </marker>
+ <g
+ id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path
+ d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20"
+ stroke="black"
+ id="path9" />
+ <!-- prolong the rectangle -->
+ <path
+ d="M 80 0 h 15 M 80 20 h 15"
+ stroke="black"
+ stroke-dasharray="2 1"
+ id="path11" />
+ </g>
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path
+ id="arrow"
+ d="M 0 0 Q 20 -15 40 0"
+ stroke="black"
+ marker-end="url(#triangle_1)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect17" />
+ <!-- set default values -->
+ <g
+ fill="none"
+ id="g145">
+ <!-- start plus first INSERT -->
+ <g
+ transform="translate(20, 40)"
+ id="g35">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text23">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan19">123</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan21">: INSERT</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use25" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use27" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ style="fill:blue"
+ id="text29">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text31">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ style="fill:blue"
+ id="text33">'x'</text>
+ </g>
+ <!-- first UPDATE -->
+ <g
+ transform="translate(185, 40)"
+ id="g61">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text41">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan37">135</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan39">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use43" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use45" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ style="fill:blue"
+ id="text47">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text49">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ style="fill:blue"
+ id="text51">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use53" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text55">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text57">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text59">'x'</text>
+ </g>
+ <!-- next UPDATE -->
+ <g
+ transform="translate(350, 40)"
+ id="g95">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text67">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan63">142</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan65">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use69" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use71" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ style="fill:blue"
+ id="text73">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text75">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ style="fill:blue"
+ id="text77">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use79" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text81">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text83">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text85">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use87" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text89">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text91">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text93">'x'</text>
+ </g>
+ <!-- DELETE -->
+ <g
+ transform="translate(515, 40)"
+ id="g129">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text101">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan97">821</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan99">: DELTE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use103" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use105" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text107">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text109">821</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ id="text111">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use113" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text115">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ id="text117">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text119">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use121" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text123">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text125">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text127">'x'</text>
+ </g>
+ <!-- LEGEND -->
+ <g
+ transform="translate(740, 110)"
+ id="g143">
+ <path
+ d="M 102 -20 h -120 v 60"
+ stroke="black"
+ id="path131" />
+ <text
+ class="text_normal"
+ transform="translate(0, 0)"
+ id="text133">Legend</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(0, 10)"
+ id="use135" />
+ <text
+ class="text_small"
+ transform="translate(3, 23)"
+ id="text137">xmin</text>
+ <text
+ class="text_small"
+ transform="translate(32, 23)"
+ id="text139">xmax</text>
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text141">data</text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-raw.svg b/doc/src/sgml/images/mvcc-raw.svg
new file mode 100644
index 0000000000..0481c4c938
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-raw.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="150px"
+ viewBox="0 0 850 150" >
+
+ <title>MVCC</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <marker id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto" stroke="black" fill="none">
+ <path d="M 0,0 L 10,5 L 0,10" />
+ </marker>
+
+ <g id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20" stroke="black"/>
+ <!-- prolong the rectangle -->
+ <path d="M 80 0 h 15 M 80 20 h 15" stroke="black" stroke-dasharray="2 1"/>
+ </g>
+
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path id="arrow" d="M 0 0 Q 20 -15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- set default values -->
+ <g fill="none">
+
+ <!-- start plus first INSERT -->
+ <g transform="translate(20, 40)">
+
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">123</tspan>
+ <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)" style="fill:blue">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 83)" style="fill:blue">'x'</text>
+ </g>
+
+ <!-- first UPDATE -->
+ <g transform="translate(185, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">135</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 53)" style="fill:blue">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- next UPDATE -->
+ <g transform="translate(350, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">142</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 23)" style="fill:blue">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- DELETE -->
+ <g transform="translate(515, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">821</tspan>
+ <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">821</text>
+ <text class="text_small" transform="translate(125, 23)">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- LEGEND -->
+ <g transform="translate(740, 110)">
+ <path d="M 102 -20 h -120 v 60" stroke="black"/>
+ <text class="text_normal" transform="translate(0, 0)">Legend</text>
+ <use xlink:href="#tuple" transform="translate(0, 10)"/>
+ <text class="text_small" transform="translate(3, 23)">xmin</text>
+ <text class="text_small" transform="translate(32, 23)">xmax</text>
+ <text class="text_small" transform="translate(65, 23)">data</text>
+ </g>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink-svgo.svg b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
new file mode 100644
index 0000000000..723d67bd8d
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
@@ -0,0 +1,285 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 900 600">
+ <title>
+ PG Overall Server Architecture
+ </title>
+ <style>
+ .text_big{font-style:normal}.text_big,.text_comment,.text_normal,.text_small{font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_normal,.text_small{font-style:normal}.text_small{font-size:12px}.text_normal{font-size:16px}.text_big{font-size:24px}.text_comment{font-style:italic;font-size:16px}
+ </style>
+ <defs>
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (200 x 20 px)
+ </title>
+ <path d="M200 10v10H0V0h190v10h10L190 0"/>
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (250 x 20 px)
+ </title>
+ <path d="M250 10v10H0V0h240v10h10L240 0"/>
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (100 x 35 px)
+ </title>
+ <path d="M100 10v25H0V0h90v10h10L90 0"/>
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (170 x 50 px)
+ </title>
+ <path d="M170 10v40H0V0h160v10h10L160 0"/>
+ </symbol>
+ <symbol id="state_300x120">
+ <title>
+ UML State (300x120)
+ </title>
+ <rect width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>
+ UML State (350x120)
+ </title>
+ <rect width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="disc" stroke="blue" fill="none">
+ <title>
+ Disc
+ </title>
+ <ellipse cx="51" cy="13" rx="50" ry="12"/>
+ <path d="M1 13v60"/>
+ <path d="M101 13v60"/>
+ <path d="M1 73a50 12 0 00100 0"/>
+ </symbol>
+ <symbol id="laptop" stroke="black" fill="none">
+ <title>
+ Laptop
+ </title>
+ <path d="M20 40V0h54v40l15 15H5l15-15h54"/>
+ <path d="M23 3h48v34H23z"/>
+ <path d="M30 10h20"/>
+ <path d="M30 15h25"/>
+ <path d="M30 20h10"/>
+ <path d="M30 30h20"/>
+ <path d="M25 50h45l2 2H22z"/>
+ </symbol>
+ <marker id="arrowhead_start" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto">
+ <path d="M6 0L0 3l6 3" stroke="black" fill="none"/>
+ </marker>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="15" y="40" class="text_big">
+ Client
+ </text>
+ <text x="140" y="40" class="text_big">
+ Server
+ </text>
+ <use xlink:href="#laptop" x="5" y="210"/>
+ <g transform="translate(130 70)">
+ <use xlink:href="#state_350x120"/>
+ <text x="5" y="20" class="text_normal">
+ maintenance_work_mem (per connection)
+ </text>
+ <text x="5" y="45" class="text_normal">
+ work_mem (per query operation)
+ </text>
+ <text x="5" y="70" class="text_normal">
+ autovacuum_work_mem (per worker process)
+ </text>
+ <text x="5" y="95" class="text_normal">
+ temp_buffer (per connection)
+ </text>
+ <text x="5" y="110" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_200x20" x="140" y="-15"/>
+ <text x="150" class="text_comment">
+ Individual Memory
+ </text>
+ </g>
+ <g transform="translate(520 70)">
+ <use xlink:href="#state_300x120"/>
+ <text x="10" y="30" class="text_normal">
+ shared_buffers (heap and index)
+ </text>
+ <text x="10" y="70" class="text_normal">
+ wal_buffers (WAL records)
+ </text>
+ <text x="10" y="100" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_250x20" x="40" y="-15"/>
+ <text x="50" class="text_comment">
+ Shared Memory (per Instance)
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M180 215h250v30H180z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(180 215)">
+ Postmaster
+ </text>
+ <path d="M90 230h75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 230)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 1
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M150 315h370v30H150z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(150 315)">
+ Backend processes (one per connection)
+ </text>
+ <path d="M155 315v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M160 310v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M90 240l63 63" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 290)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 3
+ </text>
+ </g>
+ <path d="M360 250v50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180 255)">
+ <use xlink:href="#note_250x20"/>
+ <text x="10" y="15" class="text_comment">
+ Creates backend processes
+ </text>
+ </g>
+ <g transform="translate(360 281)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 2
+ </text>
+ </g>
+ <path d="M460 300V200" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M498 300V95h30" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M508 300V135h20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M550 220h120v30H550z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(550 220)">
+ WAL Writer
+ </text>
+ <path d="M590 150v65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M590 255v230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 340h140v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 340)">
+ Checkpointer
+ </text>
+ <path d="M740 110v220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 355H475v130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M700 330V150" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50"/>
+ <text x="60" y="-35" class="text_comment">
+ Checkpoint
+ </text>
+ <text x="60" y="-20" class="text_comment">
+ Record
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M610 380h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 380)">
+ Background Writer
+ </text>
+ <path d="M770 110v260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 395H485v90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 420h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 420)">
+ WAL Archiver
+ </text>
+ <path d="M620 485l30-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M690 455l30 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M135 380h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 380)">
+ Autovacuum
+ </text>
+ <path d="M140 380v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path d="M145 375v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path stroke="blue" fill="none" d="M135 430h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 430)">
+ Logger
+ </text>
+ <path stroke="blue" fill="none" d="M290 370h140v30H290z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(290 370)">
+ Stats Collector
+ </text>
+ <g transform="translate(145 490)">
+ <use xlink:href="#disc"/>
+ <text x="35" y="45" class="text_normal">
+ Log
+ </text>
+ <text x="20" y="60" class="text_small">
+ text lines,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <path d="M195 465v20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(410 490)">
+ <use xlink:href="#disc"/>
+ <text x="10" y="40" class="text_normal">
+ Heap and
+ </text>
+ <text x="25" y="55" class="text_normal">
+ Index
+ </text>
+ <text x="15" y="70" class="text_small">
+ binary blocks,
+ </text>
+ <text x="30" y="80" class="text_small">
+ random
+ </text>
+ </g>
+ <path d="M450 485V350" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(295 420)">
+ <use xlink:href="#note_170x50"/>
+ <text x="5" y="15" class="text_comment">
+ Read heap and index
+ </text>
+ <text x="5" y="30" class="text_comment">
+ pages and transfer
+ </text>
+ <text x="5" y="45" class="text_comment">
+ them to shared_buffers
+ </text>
+ </g>
+ <g transform="translate(550 490)">
+ <use xlink:href="#disc"/>
+ <text x="30" y="45" class="text_normal">
+ WAL
+ </text>
+ <text x="10" y="60" class="text_small">
+ binary records,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <g transform="translate(690 490)">
+ <use xlink:href="#disc"/>
+ <text x="16" y="45" class="text_normal">
+ Archived
+ </text>
+ <text x="36" y="60" class="text_normal">
+ WAL
+ </text>
+ </g>
+ <path d="M110 20v550" stroke="black" fill="none"/>
+ <g transform="rotate(90 -33.5 156.5)">
+ <use xlink:href="#note_200x20"/>
+ <text class="text_comment" x="10" y="15">
+ Via TCP/IP or socket
+ </text>
+ </g>
+ <text class="text_big" x="95" transform="rotate(90 425 425)">
+ RAM
+ </text>
+ <text class="text_big" x="250" transform="rotate(90 425 425)">
+ PROCESSES
+ </text>
+ <text class="text_big" x="500" transform="rotate(90 425 425)">
+ FILES
+ </text>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink.svg b/doc/src/sgml/images/ram-proc-file-ink.svg
new file mode 100644
index 0000000000..4490bf51e1
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink.svg
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="600px"
+ viewBox="0 0 900 600"
+ id="svg306"
+ sodipodi:docname="ram-proc-file-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata310">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>PG Overall Server Architecture</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1048"
+ inkscape:window-height="771"
+ id="namedview308"
+ showgrid="false"
+ inkscape:zoom="0.39333333"
+ inkscape:cx="450"
+ inkscape:cy="300"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg306" />
+ <title
+ id="title2">PG Overall Server Architecture</title>
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs70">
+ <!-- Some notes in different sizes -->
+ <symbol
+ id="note_200x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title6">UML Note (200 x 20 px)</title>
+ <path
+ d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10"
+ id="path8" />
+ </symbol>
+ <symbol
+ id="note_250x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title11">UML Note (250 x 20 px)</title>
+ <path
+ d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10"
+ id="path13" />
+ </symbol>
+ <symbol
+ id="note_100x35"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title16">UML Note (100 x 35 px)</title>
+ <path
+ d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10"
+ id="path18" />
+ </symbol>
+ <symbol
+ id="note_170x50"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title21">UML Note (170 x 50 px)</title>
+ <path
+ d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10"
+ id="path23" />
+ </symbol>
+ <!-- UML states (used for buffers) -->
+ <symbol
+ id="state_300x120">
+ <title
+ id="title26">UML State (300x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="300"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect28" />
+ </symbol>
+ <symbol
+ id="state_350x120">
+ <title
+ id="title31">UML State (350x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="350"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect33" />
+ </symbol>
+ <!-- Discs -->
+ <symbol
+ id="disc"
+ stroke="blue"
+ fill="none">
+ <title
+ id="title36">Disc</title>
+ <ellipse
+ cx="51"
+ cy="13"
+ rx="50"
+ ry="12"
+ id="ellipse38" />
+ <!-- top -->
+ <path
+ d="M 1,13 v 60"
+ id="path40" />
+ <!-- left -->
+ <path
+ d="M 101,13 v 60"
+ id="path42" />
+ <!-- right -->
+ <path
+ d="M 1,73 A 50, 12, 0, 0, 0, 101,73"
+ id="path44" />
+ <!-- bottom -->
+ </symbol>
+ <!-- Laptop -->
+ <symbol
+ id="laptop"
+ stroke="black"
+ fill="none">
+ <title
+ id="title47">Laptop</title>
+ <path
+ d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54"
+ id="path49" />
+ <rect
+ x="23"
+ y="3"
+ width="48"
+ height="34"
+ id="rect51" />
+ <!-- symbolize some lines -->
+ <path
+ d="M 30,10 h 20"
+ id="path53" />
+ <path
+ d="M 30,15 h 25"
+ id="path55" />
+ <path
+ d="M 30,20 h 10"
+ id="path57" />
+ <path
+ d="M 30,30 h 20"
+ id="path59" />
+ <!-- symbolize keyboard -->
+ <path
+ d="M 25,50 h 45 l 2,2 h -50 z "
+ id="path61" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path64" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path67" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect72" />
+ <!-- caption, client side -->
+ <text
+ x="15"
+ y="40"
+ class="text_big"
+ id="text74">Client</text>
+ <text
+ x="140"
+ y="40"
+ class="text_big"
+ id="text76">Server</text>
+ <use
+ xlink:href="#laptop"
+ x="5"
+ y="210"
+ id="use78" />
+ <!-- individual memory -->
+ <g
+ transform="translate(130, 70)"
+ id="g96">
+ <use
+ xlink:href="#state_350x120"
+ x="0"
+ y="0"
+ id="use80" />
+ <text
+ x="5"
+ y="20"
+ class="text_normal"
+ id="text82">maintenance_work_mem (per connection)</text>
+ <text
+ x="5"
+ y="45"
+ class="text_normal"
+ id="text84">work_mem (per query operation)</text>
+ <text
+ x="5"
+ y="70"
+ class="text_normal"
+ id="text86">autovacuum_work_mem (per worker process)</text>
+ <text
+ x="5"
+ y="95"
+ class="text_normal"
+ id="text88">temp_buffer (per connection)</text>
+ <text
+ x="5"
+ y="110"
+ class="text_normal"
+ id="text90">...</text>
+ <use
+ xlink:href="#note_200x20"
+ x="140"
+ y="-15"
+ id="use92" />
+ <text
+ x="150"
+ y="0"
+ class="text_comment"
+ id="text94">Individual Memory</text>
+ </g>
+ <!-- shared memory -->
+ <g
+ transform="translate(520, 70)"
+ id="g110">
+ <use
+ xlink:href="#state_300x120"
+ x="0"
+ y="0"
+ id="use98" />
+ <text
+ x="10"
+ y="30"
+ class="text_normal"
+ id="text100">shared_buffers (heap and index)</text>
+ <text
+ x="10"
+ y="70"
+ class="text_normal"
+ id="text102">wal_buffers (WAL records)</text>
+ <text
+ x="10"
+ y="100"
+ class="text_normal"
+ id="text104">...</text>
+ <use
+ xlink:href="#note_250x20"
+ x="40"
+ y="-15"
+ id="use106" />
+ <text
+ x="50"
+ y="0"
+ class="text_comment"
+ id="text108">Shared Memory (per Instance)</text>
+ </g>
+ <!-- postmaster -->
+ <g
+ transform="translate(180, 215)"
+ id="g116">
+ <rect
+ width="250"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect112" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text114">Postmaster</text>
+ </g>
+ <path
+ d="M 90,230 h 75"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path118" />
+ <g
+ transform="translate(140, 230)"
+ id="g124">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle120" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text122">1</text>
+ </g>
+ <!-- backend processes -->
+ <g
+ transform="translate(150, 315)"
+ id="g134">
+ <rect
+ width="370"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect126" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text128">Backend processes (one per connection)</text>
+ <path
+ d="M 5,0 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path130" />
+ <path
+ d="M 10,-5 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path132" />
+ </g>
+ <path
+ d="M 90,240 153,303"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path136" />
+ <g
+ transform="translate(140, 290)"
+ id="g142">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle138" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text140">3</text>
+ </g>
+ <!-- connection between postmaster and backend processes -->
+ <path
+ d="M 360,250 v 50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path144" />
+ <g
+ transform="translate(180, 255)"
+ id="g150">
+ <use
+ xlink:href="#note_250x20"
+ id="use146" />
+ <text
+ x="10"
+ y="15"
+ class="text_comment"
+ id="text148">Creates backend processes</text>
+ </g>
+ <g
+ transform="translate(360, 281)"
+ id="g156">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle152" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text154">2</text>
+ </g>
+ <!-- backend process' access to individual memory -->
+ <path
+ d="M 460,300 v -100"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path158" />
+ <!-- its access to shared buffers and WAL buffers -->
+ <path
+ d="M 498,300 v -205 h 30"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path160" />
+ <path
+ d="M 508,300 v -165 h 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path162" />
+ <!-- WAL writer -->
+ <g
+ transform="translate(550, 220)"
+ id="g168">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect164" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text166">WAL Writer</text>
+ </g>
+ <path
+ d="M 590,150 v 65"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path170" />
+ <path
+ d="M 590,255 v 230"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path172" />
+ <!-- Checkpoiner -->
+ <g
+ transform="translate(610, 340)"
+ id="g178">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect174" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text176">Checkpointer</text>
+ </g>
+ <path
+ d="M 740,110 v 220"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path180" />
+ <path
+ d="M 605,355 h -130 v 130"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path182" />
+ <path
+ d="M 700,330 v -180"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path184" />
+ <g
+ transform="translate(570, 330)"
+ id="g192">
+ <use
+ xlink:href="#note_100x35"
+ x="50"
+ y="-50"
+ id="use186" />
+ <text
+ x="60"
+ y="-35"
+ class="text_comment"
+ id="text188">Checkpoint</text>
+ <text
+ x="60"
+ y="-20"
+ class="text_comment"
+ id="text190">Record</text>
+ </g>
+ <!-- BG writer -->
+ <g
+ transform="translate(610, 380)"
+ id="g198">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect194" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text196">Background Writer</text>
+ </g>
+ <path
+ d="M 770,110 v 260"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path200" />
+ <path
+ d="M 605,395 h -120 v 90"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path202" />
+ <!-- Archiver -->
+ <g
+ transform="translate(610, 420)"
+ id="g208">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect204" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text206">WAL Archiver</text>
+ </g>
+ <path
+ d="M 620,485 l 30,-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path210" />
+ <path
+ d="M 690,455 l 30, 30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path212" />
+ <!-- Vacuum -->
+ <g
+ transform="translate(135, 380)"
+ id="g222">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect214" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text216">Autovacuum</text>
+ <path
+ d="M 5,0 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path218" />
+ <path
+ d="M 10,-5 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path220" />
+ </g>
+ <!-- Log Writer -->
+ <g
+ transform="translate(135, 430)"
+ id="g228">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect224" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text226">Logger</text>
+ </g>
+ <!-- Stats Collector -->
+ <g
+ transform="translate(290, 370)"
+ id="g234">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect230" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text232">Stats Collector</text>
+ </g>
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g
+ transform="translate(145, 490)"
+ id="g244">
+ <use
+ xlink:href="#disc"
+ id="use236" />
+ <text
+ x="35"
+ y="45"
+ class="text_normal"
+ id="text238">Log</text>
+ <text
+ x="20"
+ y="60"
+ class="text_small"
+ id="text240">text lines,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text242">sequential</text>
+ </g>
+ <path
+ d="M 195,465 v 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path246" />
+ <g
+ transform="translate(410, 490)"
+ id="g258">
+ <use
+ xlink:href="#disc"
+ id="use248" />
+ <text
+ x="10"
+ y="40"
+ class="text_normal"
+ id="text250">Heap and</text>
+ <text
+ x="25"
+ y="55"
+ class="text_normal"
+ id="text252">Index</text>
+ <text
+ x="15"
+ y="70"
+ class="text_small"
+ id="text254">binary blocks,</text>
+ <text
+ x="30"
+ y="80"
+ class="text_small"
+ id="text256">random</text>
+ </g>
+ <path
+ d="M 450,485 v -135"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path260" />
+ <g
+ transform="translate(295, 420)"
+ id="g270">
+ <use
+ xlink:href="#note_170x50"
+ id="use262" />
+ <text
+ x="5"
+ y="15"
+ class="text_comment"
+ id="text264">Read heap and index</text>
+ <text
+ x="5"
+ y="30"
+ class="text_comment"
+ id="text266">pages and transfer</text>
+ <text
+ x="5"
+ y="45"
+ class="text_comment"
+ id="text268">them to shared_buffers</text>
+ </g>
+ <g
+ transform="translate(550, 490)"
+ id="g280">
+ <use
+ xlink:href="#disc"
+ id="use272" />
+ <text
+ x="30"
+ y="45"
+ class="text_normal"
+ id="text274">WAL</text>
+ <text
+ x="10"
+ y="60"
+ class="text_small"
+ id="text276">binary records,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text278">sequential</text>
+ </g>
+ <g
+ transform="translate(690, 490)"
+ id="g288">
+ <use
+ xlink:href="#disc"
+ id="use282" />
+ <text
+ x="16"
+ y="45"
+ class="text_normal"
+ id="text284">Archived</text>
+ <text
+ x="36"
+ y="60"
+ class="text_normal"
+ id="text286">WAL</text>
+ </g>
+ <!-- boarder between client and server side -->
+ <path
+ d="M 110,20 v 550"
+ stroke="black"
+ fill="none"
+ id="path290" />
+ <g
+ transform="translate(123, 190) rotate(90)"
+ id="g296">
+ <use
+ xlink:href="#note_200x20"
+ id="use292" />
+ <text
+ class="text_comment"
+ x="10"
+ y="15"
+ id="text294">Via TCP/IP or socket</text>
+ </g>
+ <!-- right side -->
+ <g
+ transform="translate(850, 0) rotate(90)"
+ id="g304">
+ <text
+ class="text_big"
+ x="95"
+ id="text298">RAM</text>
+ <text
+ class="text_big"
+ x="250"
+ id="text300">PROCESSES</text>
+ <text
+ class="text_big"
+ x="500"
+ id="text302">FILES</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-raw.svg b/doc/src/sgml/images/ram-proc-file-raw.svg
new file mode 100644
index 0000000000..aec5811c54
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-raw.svg
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="600px"
+ viewBox="0 0 900 600">
+
+ <title>PG Overall Server Architecture</title>
+
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Some notes in different sizes -->
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>UML Note (200 x 20 px)</title>
+ <path d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>UML Note (250 x 20 px)</title>
+ <path d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>UML Note (100 x 35 px)</title>
+ <path d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>UML Note (170 x 50 px)</title>
+ <path d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- UML states (used for buffers) -->
+ <symbol id="state_300x120">
+ <title>UML State (300x120)</title>
+ <rect x="0" y="0" width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>UML State (350x120)</title>
+ <rect x="0" y="0" width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- Discs -->
+ <symbol id="disc" stroke="blue" fill="none" >
+ <title>Disc</title>
+ <ellipse cx="51" cy="13" rx="50" ry="12" /> <!-- top -->
+ <path d="M 1,13 v 60" /> <!-- left -->
+ <path d="M 101,13 v 60" /> <!-- right -->
+ <path d="M 1,73 A 50, 12, 0, 0, 0, 101,73" /> <!-- bottom -->
+ </symbol>
+
+ <!-- Laptop -->
+ <symbol id="laptop" stroke="black" fill="none" >
+ <title>Laptop</title>
+ <path d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54" />
+ <rect x="23" y="3" width="48" height="34" />
+ <!-- symbolize some lines -->
+ <path d="M 30,10 h 20" />
+ <path d="M 30,15 h 25" />
+ <path d="M 30,20 h 10" />
+ <path d="M 30,30 h 20" />
+ <!-- symbolize keyboard -->
+ <path d="M 25,50 h 45 l 2,2 h -50 z " />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption, client side -->
+ <text x="15" y="40" class="text_big">Client</text>
+ <text x="140" y="40" class="text_big">Server</text>
+ <use xlink:href="#laptop" x="5" y="210" />
+
+
+ <!-- individual memory -->
+ <g transform="translate(130, 70)">
+ <use xlink:href="#state_350x120" x="0" y="0" />
+ <text x="5" y="20" class="text_normal">maintenance_work_mem (per connection)</text>
+ <text x="5" y="45" class="text_normal">work_mem (per query operation)</text>
+ <text x="5" y="70" class="text_normal">autovacuum_work_mem (per worker process)</text>
+ <text x="5" y="95" class="text_normal">temp_buffer (per connection)</text>
+ <text x="5" y="110" class="text_normal">...</text>
+ <use xlink:href="#note_200x20" x="140" y="-15" />
+ <text x="150" y="0" class="text_comment">Individual Memory</text>
+ </g>
+
+ <!-- shared memory -->
+ <g transform="translate(520, 70)">
+ <use xlink:href="#state_300x120" x="0" y="0" />
+ <text x="10" y="30" class="text_normal">shared_buffers (heap and index)</text>
+ <text x="10" y="70" class="text_normal">wal_buffers (WAL records)</text>
+ <text x="10" y="100" class="text_normal">...</text>
+ <use xlink:href="#note_250x20" x="40" y="-15" />
+ <text x="50" y="0" class="text_comment">Shared Memory (per Instance)</text>
+ </g>
+
+ <!-- postmaster -->
+ <g transform="translate(180, 215)">
+ <rect width="250" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Postmaster</text>
+ </g>
+ <path d="M 90,230 h 75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 230)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">1</text>
+ </g>
+
+ <!-- backend processes -->
+ <g transform="translate(150, 315)">
+ <rect width="370" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Backend processes (one per connection)</text>
+ <path d="M 5,0 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <path d="M 90,240 153,303" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 290)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">3</text>
+ </g>
+
+ <!-- connection between postmaster and backend processes -->
+ <path d="M 360,250 v 50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180, 255)">
+ <use xlink:href="#note_250x20" />
+ <text x="10" y="15" class="text_comment">Creates backend processes</text>
+ </g>
+ <g transform="translate(360, 281)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">2</text>
+ </g>
+
+ <!-- backend process' access to individual memory -->
+ <path d="M 460,300 v -100" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <!-- its access to shared buffers and WAL buffers -->
+ <path d="M 498,300 v -205 h 30" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M 508,300 v -165 h 20" stroke="black" fill="none"
+ marker-end="url(#arrowhead_end)"/>
+
+ <!-- WAL writer -->
+ <g transform="translate(550, 220)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Writer</text>
+ </g>
+ <path d="M 590,150 v 65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 590,255 v 230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Checkpoiner -->
+ <g transform="translate(610, 340)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Checkpointer</text>
+ </g>
+ <path d="M 740,110 v 220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,355 h -130 v 130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 700,330 v -180" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570, 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50" />
+ <text x="60" y="-35" class="text_comment">Checkpoint</text>
+ <text x="60" y="-20" class="text_comment">Record</text>
+ </g>
+
+ <!-- BG writer -->
+ <g transform="translate(610, 380)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Background Writer</text>
+ </g>
+ <path d="M 770,110 v 260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,395 h -120 v 90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Archiver -->
+ <g transform="translate(610, 420)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Archiver</text>
+ </g>
+ <path d="M 620,485 l 30,-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 690,455 l 30, 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Vacuum -->
+ <g transform="translate(135, 380)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Autovacuum</text>
+ <path d="M 5,0 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <!-- Log Writer -->
+ <g transform="translate(135, 430)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Logger</text>
+ </g>
+
+ <!-- Stats Collector -->
+ <g transform="translate(290, 370)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Stats Collector</text>
+ </g>
+
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g transform="translate(145, 490)">
+ <use xlink:href="#disc" />
+ <text x="35" y="45" class="text_normal">Log</text>
+ <text x="20" y="60" class="text_small">text lines,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+ <path d="M 195,465 v 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(410, 490)">
+ <use xlink:href="#disc" />
+ <text x="10" y="40" class="text_normal">Heap and</text>
+ <text x="25" y="55" class="text_normal">Index</text>
+ <text x="15" y="70" class="text_small">binary blocks,</text>
+ <text x="30" y="80" class="text_small">random</text>
+ </g>
+ <path d="M 450,485 v -135" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(295, 420)">
+ <use xlink:href="#note_170x50" />
+ <text x="5" y="15" class="text_comment">Read heap and index</text>
+ <text x="5" y="30" class="text_comment">pages and transfer</text>
+ <text x="5" y="45" class="text_comment">them to shared_buffers</text>
+ </g>
+
+ <g transform="translate(550, 490)">
+ <use xlink:href="#disc" />
+ <text x="30" y="45" class="text_normal">WAL</text>
+ <text x="10" y="60" class="text_small">binary records,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+
+ <g transform="translate(690, 490)">
+ <use xlink:href="#disc" />
+ <text x="16" y="45" class="text_normal">Archived</text>
+ <text x="36" y="60" class="text_normal">WAL</text>
+ </g>
+
+ <!-- boarder between client and server side -->
+ <path d="M 110,20 v 550" stroke="black" fill="none" />
+ <g transform="translate(123, 190) rotate(90)">
+ <use xlink:href="#note_200x20" />
+ <text class="text_comment" x="10" y ="15">Via TCP/IP or socket</text>
+ </g>
+
+ <!-- right side -->
+ <g transform="translate(850, 0) rotate(90)">
+ <text class="text_big" x="95">RAM</text>
+ <text class="text_big" x="250">PROCESSES</text>
+ <text class="text_big" x="500">FILES</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink-svgo.svg b/doc/src/sgml/images/wraparound-ink-svgo.svg
new file mode 100644
index 0000000000..9882d2be23
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink-svgo.svg
@@ -0,0 +1,40 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="280" viewBox="0 0 850 280">
+ <title>
+ Cyclic usage of XIDs
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="370" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ Cyclic usage of XIDs modulo 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan>
+ </text>
+ <g fill="none" transform="translate(170 150)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_095" startOffset="30.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="30%">(1)</textPath> <textPath xlink:href="#Path_095" startOffset="45.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(2)</textPath> <textPath xlink:href="#Path_095" startOffset="50.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="50%">(3)</textPath> <textPath xlink:href="#Path_095" startOffset="62.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="62%">(4)</textPath>
+ </text>
+ </g>
+ <g class="text_normal">
+ <text transform="translate(400 130)">
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25" transform="translate(400 130)">
+ 1: oldest <tspan font-weight="700">active</tspan> xid (pg_stat_activity.backend_xmin)
+ </text>
+ <text y="50" transform="translate(400 130)">
+ 2: xmin of one row version
+ </text>
+ <text y="75" transform="translate(400 130)">
+ 3: xmax of the same row version
+ </text>
+ <text y="100" transform="translate(400 130)">
+ 4: jungest xid (txid_current)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink.svg b/doc/src/sgml/images/wraparound-ink.svg
new file mode 100644
index 0000000000..a9c51f4e43
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="280px"
+ viewBox="0 0 850 280"
+ id="svg1072"
+ sodipodi:docname="wraparound-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata1076">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Cyclic usage of XIDs</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1193"
+ inkscape:window-height="788"
+ id="namedview1074"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="140"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg1072" />
+ <title
+ id="title1009">Cyclic usage of XIDs</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style1011">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs1016">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect1018" />
+ <text
+ class="text_big"
+ x="370"
+ y="40"
+ id="text1024">Cyclic usage of XIDs modulo 2
+ <tspan
+ dy="-5"
+ id="tspan1020">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1022">32</tspan>
+</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 150)"
+ id="g1052">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle1026" />
+ <text
+ class="text_normal"
+ id="text1050">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath1028">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath1030">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath1032">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="30.5%"
+ id="textPath1034">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="30%"
+ id="textPath1036">(1)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="45.5%"
+ id="textPath1038">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath1040">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="50.5%"
+ id="textPath1042">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="50%"
+ id="textPath1044">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="62.5%"
+ id="textPath1046">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="62%"
+ id="textPath1048">(4)</textPath>
+ </text>
+ </g>
+ <g
+ class="text_normal"
+ transform="translate(400 130)"
+ id="g1070">
+ <text
+ id="text1058">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan1054">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1056">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text1062">1: oldest <tspan
+ style="font-weight:bold"
+ id="tspan1060">active</tspan>
+ xid (pg_stat_activity.backend_xmin)</text>
+ <text
+ y="50"
+ id="text1064">2: xmin of one row version</text>
+ <text
+ y="75"
+ id="text1066">3: xmax of the same row version</text>
+ <text
+ y="100"
+ id="text1068">4: jungest xid (txid_current)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-raw.svg b/doc/src/sgml/images/wraparound-raw.svg
new file mode 100644
index 0000000000..9406f52970
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-raw.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="280px"
+ viewBox="0 0 850 280" >
+
+ <title>Cyclic usage of XIDs</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="370" y="40">Cyclic usage of XIDs modulo 2
+ <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan></text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 150)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_095" startOffset="30.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="30%" >(1)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="45.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(2)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="50.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="50%" >(3)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="62.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="62%" >(4)</textPath>
+ </text>
+ </g>
+
+ <g class="text_normal" transform="translate(400 130)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: oldest <tspan style="font-weight:bold">active</tspan> xid (pg_stat_activity.backend_xmin)</text>
+ <text y="50">2: xmin of one row version</text>
+ <text y="75">3: xmax of the same row version</text>
+ <text y="100">4: jungest xid (txid_current)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 730d5fdc34..e9e9f9495f 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -248,6 +248,7 @@ break is not needed in a wider output rendering.
</para>
</partintro>
+ &architecture;
&arch-dev;
&catalogs;
&protocol;
diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml
index 9bb5c1a6d5..abb61445f2 100644
--- a/doc/src/sgml/start.sgml
+++ b/doc/src/sgml/start.sgml
@@ -53,7 +53,7 @@
<sect1 id="tutorial-arch">
- <title>Architectural Fundamentals</title>
+ <title>Client/Server Model</title>
<para>
Before we proceed, you should understand the basic
@@ -68,34 +68,52 @@
client/server model. A <productname>PostgreSQL</productname>
session consists of the following cooperating processes
(programs):
+ </para>
- <itemizedlist>
- <listitem>
- <para>
- A server process, which manages the database files, accepts
- connections to the database from client applications, and
- performs database actions on behalf of the clients. The
- database server program is called
- <filename>postgres</filename>.
- <indexterm><primary>postgres</primary></indexterm>
- </para>
- </listitem>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A process at the server site with the name
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ <indexterm><primary>postgres</primary></indexterm>
+ <indexterm><primary>postmaster</primary></indexterm>
+ It accepts connection requests from client applications, starts
+ (<quote>forks</quote>) a new <glossterm linkend="glossary-backend">
+ Backend</glossterm> process for each of them, and passes
+ the connection to it. From that point on, the client and the new
+ Backend process communicate directly without intervention by the original
+ Postmaster process. Thus, the Postmaster process is always running,
+ waiting for new client connections, whereas clients and associated
+ Backend processes come and go. (All of this is of course invisible
+ to the user. We only mention it here for completeness.)
+ </para>
+ </listitem>
- <listitem>
- <para>
- The user's client (frontend) application that wants to perform
- database operations. Client applications can be very diverse
- in nature: a client could be a text-oriented tool, a graphical
- application, a web server that accesses the database to
- display web pages, or a specialized database maintenance tool.
- Some client applications are supplied with the
- <productname>PostgreSQL</productname> distribution; most are
- developed by users.
- </para>
- </listitem>
+ <listitem>
+ <para>
+ A group of processes at the server site, the <glossterm
+ linkend="glossary-instance">Instance</glossterm>, to which also
+ the Postmaster process belongs. Their duties are handling of
+ central, common database activities like file access, transaction
+ handling, vacuum, checkpoints, replication, and more. The mentioned
+ Backend processes delegate those actions to the instance.
+ </para>
+ </listitem>
- </itemizedlist>
- </para>
+ <listitem>
+ <para>
+ The user's client (frontend) application that wants to perform
+ database operations. Client applications can be very diverse
+ in nature: a client could be a text-oriented tool, a graphical
+ application, a web server that accesses the database to
+ display web pages, or a specialized database maintenance tool.
+ Some client applications are supplied with the
+ <productname>PostgreSQL</productname> distribution; most are
+ developed by users.
+ </para>
+ </listitem>
+
+ </itemizedlist>
<para>
As is typical of client/server applications, the client and the
@@ -106,18 +124,6 @@
file name) on the database server machine.
</para>
- <para>
- The <productname>PostgreSQL</productname> server can handle
- multiple concurrent connections from clients. To achieve this it
- starts (<quote>forks</quote>) a new process for each connection.
- From that point on, the client and the new server process
- communicate without intervention by the original
- <filename>postgres</filename> process. Thus, the
- supervisor server process is always running, waiting for
- client connections, whereas client and associated server processes
- come and go. (All of this is of course invisible to the user. We
- only mention it here for completeness.)
- </para>
</sect1>
On 2020-10-30 11:57, Jürgen Purtz wrote:
On 26.10.20 15:53, David G. Johnston wrote:
Removing -docs as moderation won’t let me cross-post.
Hi,
I applied 0009-architecture-vs-master.patch to head
and went through architecture.sgml (only that file),
then produced the attached .diff
And I wrote down some separate items:
1.
'Two Phase Locking' and 'TPL' should be, I think,
'Two-Phase Commit'. Please someone confirm.
(no changes made)
2.
To compare xid to sequence because they similarly 'count up' seems a bad
idea.
(I don't think it's always true in the case of sequences)
(no changes made)
3.
'accesses' seems a somewhat strange word most of the time just 'access'
may be better. Not sure - native speaker wanted. (no changes made)
4.
'heap', in postgres, means often (always?) files. But more generally,
the meaning is more associated with memory. Therefore it would be good
I think to explicitly use 'heap file' at least in the beginning once to
make clear that heap implies 'safely written away to disk'. Again, I'm
not quite sure if my understanding is correct - I have made no changes
in this regard.
Erik Rijkers
Attachments:
architecture.sgml.20201030.difftext/x-diff; name=architecture.sgml.20201030.diffDownload
--- doc/src/sgml/architecture.sgml.orig 2020-10-30 15:19:54.469275256 +0100
+++ doc/src/sgml/architecture.sgml 2020-10-30 17:28:24.835233482 +0100
@@ -19,19 +19,18 @@
In the case of <productname>PostgreSQL</productname>, the server
launches a single process for each client connection, referred to as a
<glossterm linkend="glossary-backend">Backend</glossterm> process.
- Those Backend processes handle the client's requests by acting on the
+ Such a Backend process handles the client's requests by acting on the
<glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>.
This leads to other activities (file access, WAL, vacuum, ...) of the
<glossterm linkend="glossary-instance">Instance</glossterm>. The
Instance is a group of server-side processes acting on a common
- Shared Memory. Notably, PostgreSQL does not utilize application
- threading within its implementation.
+ Shared Memory. PostgreSQL does not utilize threading.
</para>
<para>
- The first step in an Instance start is the start of the
+ The first step when an Instance starts is the start of the
<glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
- He loads the configuration files, allocates Shared Memory, and
+ It loads the configuration files, allocates Shared Memory, and
starts the other processes of the Instance:
<glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
<glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
@@ -66,32 +65,32 @@
<para>
When a client application tries to connect to a
<glossterm linkend="glossary-database">database</glossterm>,
- this request is handled initially by the Postmaster. He
+ this request is handled initially by the Postmaster. It
starts a new Backend process and instructs the client
application to connect to it. All further client requests
- go to this process and are handled by it.
+ are handled by this process.
</para>
<para>
Client requests like <command>SELECT</command> or
<command>UPDATE</command> usually lead to the
- necessity to read or write some data. This is carried out
+ necessity to read or write data. This is carried out
by the client's backend process. Reads involve a page-level
- cache housed in Shared Memory (for details see:
+ cache, located in Shared Memory (for details see:
<xref linkend="sysvipc"/>) for the benefit of all processes
- in the instance. Writes also involve this cache, in additional
+ in the instance. Writes also use this cache, in addition
to a journal, called a write-ahead-log or WAL.
</para>
<para>
- Shared Memory is limited in size. Thus, it becomes necessary
+ Shared Memory is limited in size and it can become necessary
to evict pages. As long as the content of such pages hasn't
changed, this is not a problem. But in Shared Memory also
write actions take place. Modified pages are called dirty
pages or dirty buffers and before they can be evicted they
- must be written back to disk. This happens regularly by the
+ must be written to disk. This happens regularly by the
Background Writer and the Checkpointer process to ensure
- that the disk version of the pages are kept up-to-date.
+ that the disk version of the pages are up-to-date.
The synchronisation from RAM to disk consists of two steps.
</para>
@@ -109,7 +108,7 @@
Shared Memory. The parallel running WAL Writer process
reads them and appends them to the end of the current
<glossterm linkend="glossary-wal-record">WAL file</glossterm>.
- Such sequential writes are much faster than writes to random
+ Such sequential writes are faster than writes to random
positions of heap and index files. All WAL records created
out of one dirty page must be transferred to disk before the
dirty page itself can be transferred to disk in the second step.
@@ -119,19 +118,19 @@
Second, the transfer of dirty buffers from Shared Memory to
files must take place. This is the primary task of the
Background Writer process. Because I/O activities can block
- other processes significantly, it starts periodically and
+ other processes, it starts periodically and
acts only for a short period. Doing so, its extensive (and
expensive) I/O activities are spread over time, avoiding
- debilitating I/O peaks. Also, the Checkpointer process
- transfers dirty buffers to file.
+ debilitating I/O peaks. The Checkpointer process
+ also transfers dirty buffers to file.
</para>
<para>
- The Checkpointer creates
+ The Checkpointer process creates
<glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
A Checkpoint is a point in time when all older dirty buffers,
all older WAL records, and finally a special Checkpoint record
- have been written and flushed to disk. Heap and index files
+ are written and flushed to disk. Heap and index files
on the one hand and WAL files on the other hand are in sync.
Previous WAL is no longer required. In other words,
a possibly occurring recovery, which integrates the delta
@@ -141,13 +140,13 @@
</para>
<para>
- While the Checkpointer ensures that a running system can crash
+ While the Checkpointer ensures that the database system can crash
and restart itself in a valid state, the administrator needs
to handle the case where the heap and files themselves become
corrupted (and possibly the locally written WAL, though that is
less common). The options and details are covered extensively
in the backup and restore section (<xref linkend="backup"/>).
- For our purposes here, note just that the WAL Archiver process
+ For our purposes here, just note that the WAL Archiver process
can be enabled and configured to run a script on filled WAL
files — usually to copy them to a remote location.
</para>
@@ -234,13 +233,13 @@
<para>
Every database must contain at least one schema because all
<glossterm linkend="glossary-sql-object">SQL Objects</glossterm>
- are contained in a schema.
- Schemas are namespaces for their SQL objects and ensure
- (with one exception) that within their scope names are used
- only once across all types of SQL objects. E.g., it is not possible
+ must be contained in a schema.
+ Schemas are namespaces for SQL objects and ensure
+ (with one exception) that the SQL object names are used only once within
+ their scope across all types of SQL objects. E.g., it is not possible
to have a table <literal>employee</literal> and a view
<literal>employee</literal> within the same schema. But it is
- possible to have two tables <literal>employee</literal> in
+ possible to have two tables <literal>employee</literal> in two
different schemas. In this case, the two tables
are separate objects and independent of each
other. The only exception to this cross-type uniqueness is that
@@ -273,7 +272,7 @@
<firstterm>Global SQL Objects</firstterm>, are outside of the
strict hierarchy: All <firstterm>database names</firstterm>,
all <firstterm>tablespace names</firstterm>, and all
- <firstterm>role names</firstterm> are automatically known and
+ <firstterm>role names</firstterm> are automatically
available throughout the cluster, independent from
the database or schema in which they where defined originally.
<xref linkend="tutorial-internal-objects-hierarchy-figure"/>
@@ -302,7 +301,7 @@
<title>The physical Perspective: Directories and Files</title>
<para>
- <productname>PostgreSQL</productname> organizes long-lasting
+ <productname>PostgreSQL</productname> organizes long-lasting (persistent)
data as well as volatile state information about transactions
or replication actions in the file system. Every
<xref linkend="glossary-db-cluster"/> has its root directory
@@ -352,20 +351,19 @@
every table and every index to store heap and index
data. Those files are accompanied by files for the
<link linkend="storage-fsm">Free Space Maps</link>
- (extension <literal>_fsm</literal>) and
+ (suffixed <literal>_fsm</literal>) and
<link linkend="storage-vm">Visibility Maps</link>
- (extension <literal>_vm</literal>), which contain optimization information.
+ (suffixed <literal>_vm</literal>), which contain optimization information.
</para>
<para>
- Another subdirectory is <literal>global</literal>.
- In analogy to the database-specific
- subdirectories, there are files containing information about
+ Another subdirectory is <literal>global</literal> which
+ contains files with information about
<glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
One type of such Global SQL Objects are
<glossterm linkend="glossary-tablespace">tablespaces</glossterm>.
In <literal>global</literal> there is information about
- the tablespaces, not the tablespaces themselves.
+ the tablespaces; not the tablespaces themselves.
</para>
<para>
@@ -392,11 +390,11 @@
<para>
In the root directory <literal>data</literal>
there are also some files. In many cases, the configuration
- files of the cluster are stored here. As long as the
+ files of the cluster are stored here. If the
instance is up and running, the file
<literal>postmaster.pid</literal> exists here
and contains the process ID (pid) of the
- Postmaster which has started the instance.
+ Postmaster which started the instance.
</para>
<para>
@@ -411,7 +409,7 @@
<para>
In most cases, <productname>PostgreSQL</productname> databases
- support many clients at the same time. Therefore, it is necessary to
+ support many clients at the same time which makes it necessary to
protect concurrently running requests from unwanted overwriting
of other's data as well as from reading inconsistent data. Imagine an
online shop offering the last copy of an article. Two clients have the
@@ -432,11 +430,11 @@
<productname>PostgreSQL</productname> implements a third, more
sophisticated technique: <firstterm>Multiversion Concurrency
Control</firstterm> (MVCC). The crucial advantage of MVCC
- over other technologies gets evident in multiuser OLTP
+ over other technologies becomes evident in multiuser OLTP
environments with a massive number of concurrent write
actions. There, MVCC generally performs better than solutions
using locks. In a <productname>PostgreSQL</productname>
- database reading never blocks writing and writing never
+ database, reading never blocks writing and writing never
blocks reading, even in the strictest level of transaction
isolation.
</para>
@@ -444,14 +442,14 @@
<para>
Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
a new version of the row when a data-change takes place. To
- distinguish between these two versions and to track the timeline
+ distinguish between these two versions, and to track the timeline
of the row, each of the versions contains, in addition to their user-defined
columns, two special system columns, which are not visible
for the usual <command>SELECT * FROM ...</command> command.
The column <literal>xmin</literal> contains the transaction ID (xid)
- of the transaction, which created this version of the row. Accordingly,
- <literal>xmax</literal> contains the xid of the transaction, which has
- deleted this version, or zero, if the version is not
+ of the transaction which created this version of the row.
+ <literal>xmax</literal> contains the xid of the transaction which has
+ deleted this version, or zero if the version is not
deleted. You can read both with the command
<command>SELECT xmin, xmax, * FROM ... </command>.
</para>
@@ -469,7 +467,7 @@
</para>
<para>
- The description in this chapter simplifies by omitting some details.
+ The description in this chapter simplifies by omitting details.
When many transactions are running simultaneously, things can
get complicated. Sometimes transactions get aborted via
<command>ROLLBACK</command> immediately or after a lot of other activities, sometimes
@@ -526,8 +524,8 @@
creates a new version of the row with its xid in
<literal>xmin</literal>, <literal>0</literal> in
<literal>xmax</literal>, and <literal>'y'</literal> in the
- user data (plus all the other user data from the old version).
- This version is now valid for all coming transactions.
+ user data (plus all other user data from the old version).
+ This version is now valid for all future transactions.
</para>
<para>
@@ -624,9 +622,9 @@
<para>
Autovacuum runs automatically by
default. Its default parameters as well as such for
- <command>VACUUM</command> fit well for most standard
+ <command>VACUUM</command> are appropriate for most standard
situations. Therefore a novice database manager can
- easily skip the rest of this chapter which explains
+ skip the rest of this chapter which explains
a lot of details.
</para>
</note>
@@ -687,7 +685,7 @@
<para>
The eagerness — you can call it 'aggression' — of the
- operations <emphasis>eliminating bloat</emphasis> and
+ operations for <emphasis>eliminating bloat</emphasis> and
<emphasis>freeze</emphasis> is controlled by configuration
parameters, runtime flags, and in extreme situations by
the processes themselves. Because vacuum operations typically are I/O
@@ -783,7 +781,7 @@
When a client issues the SQL command <command>VACUUM</command>
with the option <command>FULL</command>.
Also, in this mode, the bloat disappears, but the strategy used
- is very different: In this case, the complete table is copied
+ is very different: in this case, the complete table is copied
to a different file skipping all outdated row versions. This
leads to a significant reduction of used disk space because
the new file contains only the actual data. The old file
@@ -1143,7 +1141,7 @@
atomicity: either all or none of its operations succeed,
regardless of the fact that it may consist of a lot of
different write-operations, and each such operation may
- affect thousands or millions of rows. As soon as one of the
+ affect many rows. As soon as one of the
operations fails, all previous operations fail also, which
means that all modified rows retain their values as of the
beginning of the transaction.
@@ -1157,14 +1155,14 @@
— even in the lowest
<link linkend="transaction-iso">isolation level</link>
of transactions. <productname>PostgreSQL</productname>
- does never show uncommitted changes to other connections.
+ never shows uncommitted changes to other connections.
</para>
<para>
The situation regarding visibility is somewhat different
from the point of view of the modifying transaction.
- <command>SELECT</command> commands issued inside a
- transaction delivers all changes done so far by this
+ A <command>SELECT</command> command issued inside a
+ transaction shows all changes done so far by this
transaction.
</para>
@@ -1231,7 +1229,7 @@
<para>
Transactions ensure that the
<glossterm linkend="glossary-consistency">consistency</glossterm>
- of the complete database always keeps valid. Declarative
+ of the complete database always remains valid. Declarative
rules like
<link linkend="ddl-constraints-primary-keys">primary</link>- or
<link linkend="ddl-constraints-fk">foreign keys</link>,
@@ -1242,13 +1240,6 @@
</para>
<para>
- Also, all self-evident — but possibly not obvious
- — low-level demands on the database system are
- ensured; e.g. index entries for rows must become
- visible at the same moment as the rows themselves.
- </para>
-
- <para>
There is the additional feature
'<link linkend="transaction-iso">isolation level</link>',
which separates transactions from each other in certain ways.
@@ -1287,7 +1278,7 @@
a severe software error like a null pointer exception.
Because <productname>PostgreSQL</productname> uses a
client/server architecture, no direct problem for the
- database will occur. In all of this cases, the
+ database will occur. In all of these cases, the
<glossterm linkend="glossary-backend">Backend process</glossterm>,
which is the client's counterpart at the server-side,
may recognize that the network connection is no longer
@@ -1310,7 +1301,7 @@
automatically recognizes that the last shutdown of the
instance did not happen as expected: files might not be
closed properly and the <literal>postmaster.pid</literal>
- file exists. <productname>PostgreSQL</productname>
+ file unexpectedly exists. <productname>PostgreSQL</productname>
tries to clean up the situation. This is possible because
all changes in the database are stored twice. First,
the WAL files contain them as a chronology of
@@ -1328,8 +1319,8 @@
<glossterm linkend="glossary-checkpoint">checkpoint</glossterm>.
This checkpoint signals that the database files are in
a consistent state, especially that all WAL records up to
- this point were successfully stored in heap and index. Starting
- here, the recovery process copies the following WAL records
+ this point were successfully stored in heap and index files. Starting
+ here, the recovery process copies the remaining WAL records
to heap and index. As a result, the files contain all
changes and reach a consistent state. Changes of committed
transactions are visible; those of uncommited transactions
@@ -1344,10 +1335,10 @@
<bridgehead renderas="sect3">Disk crash</bridgehead>
<para>
If a disk crashes, the course of action described previously
- cannot work. It is likely that the WAL files and/or the
+ cannot work: it is likely that the WAL files and/or the
data and index files are no longer available. The
database administrator must take special actions to
- overcome such situations.
+ prepare for such a situation.
</para>
<para>
He obviously needs a backup. How to take such a backup
@@ -1427,7 +1418,7 @@
</para>
<para>
The obvious disadvantage of this method is that there
- is a downtime where no user interaction is possible.
+ is a downtime.
The other two strategies run during regular operating
times.
</para>
@@ -1456,14 +1447,14 @@
<bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
<para>
<link linkend="continuous-archiving">This method</link>
- is the most sophisticated and complex one. It
+ is the most sophisticated and most complex one. It
consists of two phases.
</para>
<para>
- First, you need to create a so called
+ First, you need to create a so-called
<firstterm>basebackup</firstterm> with the tool
<command>pg_basebackup</command>. The result is a
- directory structure plus files which contains a
+ directory structure plus files which contain a
consistent copy of the original cluster.
<command>pg_basebackup</command> runs in
parallel to other processes in its own transaction.
@@ -1484,7 +1475,7 @@
<glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
will automatically copy every single WAL file to a save location.
<link linkend="backup-archiving-wal">Its configuration</link>
- consists mainly of a string, which contains a copy command
+ consists mainly of a string that contains a copy command
in the operating system's syntax. In order to protect your
data against a disk crash, the destination location
of a basebackup as well as of the
@@ -1492,9 +1483,8 @@
disk which is different from the data disk.
</para>
<para>
- If it gets necessary to restore the cluster, you have to
- copy the basebackup and the
- archived WAL files to
+ If it becomes necessary to restore the cluster, you have to
+ copy the basebackup and the archived WAL files to
their original directories. The configuration of this
<link linkend="backup-pitr-recovery">recovery procedure</link>
contains a string with the reverse copy command: from
On Fri, Oct 30, 2020 at 05:45:00PM +0100, Erik Rijkers wrote:
On 2020-10-30 11:57, Jürgen Purtz wrote:
On 26.10.20 15:53, David G. Johnston wrote:
Removing -docs as moderation won’t let me cross-post.
Hi,
I applied 0009-architecture-vs-master.patch to head
and went through architecture.sgml (only that file),
then produced the attached .diff
Now I applied 0009 as well as Erik's changes and made some more of my own :)
I'm including all patches so CFBOT is happy.
3.
'accesses' seems a somewhat strange word most of the time just 'access' may
be better. Not sure - native speaker wanted. (no changes made)
You're right, and I included that part.
--
Justin
Attachments:
0001-Additional-Chapter-for-Tutorial.patchtext/x-diff; charset=us-asciiDownload
From 25cbdab1a1266861c23062501f7e2b9efd2675e3 Mon Sep 17 00:00:00 2001
From: Erik Rijkers <er@xs4all.nl>
Date: Fri, 30 Oct 2020 17:45:00 +0100
Subject: [PATCH 1/3] Additional Chapter for Tutorial
---
doc/src/sgml/architecture.sgml | 142 +++++++++++++++------------------
1 file changed, 66 insertions(+), 76 deletions(-)
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
index e547a87d08..ffdac61975 100644
--- a/doc/src/sgml/architecture.sgml
+++ b/doc/src/sgml/architecture.sgml
@@ -19,19 +19,18 @@
In the case of <productname>PostgreSQL</productname>, the server
launches a single process for each client connection, referred to as a
<glossterm linkend="glossary-backend">Backend</glossterm> process.
- Those Backend processes handle the client's requests by acting on the
+ Such a Backend process handles the client's requests by acting on the
<glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>.
This leads to other activities (file access, WAL, vacuum, ...) of the
<glossterm linkend="glossary-instance">Instance</glossterm>. The
Instance is a group of server-side processes acting on a common
- Shared Memory. Notably, PostgreSQL does not utilize application
- threading within its implementation.
+ Shared Memory. PostgreSQL does not utilize threading.
</para>
<para>
- The first step in an Instance start is the start of the
+ The first step when an Instance starts is the start of the
<glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
- He loads the configuration files, allocates Shared Memory, and
+ It loads the configuration files, allocates Shared Memory, and
starts the other processes of the Instance:
<glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
<glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
@@ -66,32 +65,32 @@
<para>
When a client application tries to connect to a
<glossterm linkend="glossary-database">database</glossterm>,
- this request is handled initially by the Postmaster. He
+ this request is handled initially by the Postmaster. It
starts a new Backend process and instructs the client
application to connect to it. All further client requests
- go to this process and are handled by it.
+ are handled by this process.
</para>
<para>
Client requests like <command>SELECT</command> or
<command>UPDATE</command> usually lead to the
- necessity to read or write some data. This is carried out
+ necessity to read or write data. This is carried out
by the client's backend process. Reads involve a page-level
- cache housed in Shared Memory (for details see:
+ cache, located in Shared Memory (for details see:
<xref linkend="sysvipc"/>) for the benefit of all processes
- in the instance. Writes also involve this cache, in additional
+ in the instance. Writes also use this cache, in addition
to a journal, called a write-ahead-log or WAL.
</para>
<para>
- Shared Memory is limited in size. Thus, it becomes necessary
+ Shared Memory is limited in size and it can become necessary
to evict pages. As long as the content of such pages hasn't
changed, this is not a problem. But in Shared Memory also
write actions take place. Modified pages are called dirty
pages or dirty buffers and before they can be evicted they
- must be written back to disk. This happens regularly by the
+ must be written to disk. This happens regularly by the
Background Writer and the Checkpointer process to ensure
- that the disk version of the pages are kept up-to-date.
+ that the disk version of the pages are up-to-date.
The synchronisation from RAM to disk consists of two steps.
</para>
@@ -109,7 +108,7 @@
Shared Memory. The parallel running WAL Writer process
reads them and appends them to the end of the current
<glossterm linkend="glossary-wal-record">WAL file</glossterm>.
- Such sequential writes are much faster than writes to random
+ Such sequential writes are faster than writes to random
positions of heap and index files. All WAL records created
out of one dirty page must be transferred to disk before the
dirty page itself can be transferred to disk in the second step.
@@ -119,19 +118,19 @@
Second, the transfer of dirty buffers from Shared Memory to
files must take place. This is the primary task of the
Background Writer process. Because I/O activities can block
- other processes significantly, it starts periodically and
+ other processes, it starts periodically and
acts only for a short period. Doing so, its extensive (and
expensive) I/O activities are spread over time, avoiding
- debilitating I/O peaks. Also, the Checkpointer process
- transfers dirty buffers to file.
+ debilitating I/O peaks. The Checkpointer process
+ also transfers dirty buffers to file.
</para>
<para>
- The Checkpointer creates
+ The Checkpointer process creates
<glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
A Checkpoint is a point in time when all older dirty buffers,
all older WAL records, and finally a special Checkpoint record
- have been written and flushed to disk. Heap and index files
+ are written and flushed to disk. Heap and index files
on the one hand and WAL files on the other hand are in sync.
Previous WAL is no longer required. In other words,
a possibly occurring recovery, which integrates the delta
@@ -141,13 +140,13 @@
</para>
<para>
- While the Checkpointer ensures that a running system can crash
+ While the Checkpointer ensures that the database system can crash
and restart itself in a valid state, the administrator needs
to handle the case where the heap and files themselves become
corrupted (and possibly the locally written WAL, though that is
less common). The options and details are covered extensively
in the backup and restore section (<xref linkend="backup"/>).
- For our purposes here, note just that the WAL Archiver process
+ For our purposes here, just note that the WAL Archiver process
can be enabled and configured to run a script on filled WAL
files — usually to copy them to a remote location.
</para>
@@ -234,13 +233,13 @@
<para>
Every database must contain at least one schema because all
<glossterm linkend="glossary-sql-object">SQL Objects</glossterm>
- are contained in a schema.
- Schemas are namespaces for their SQL objects and ensure
- (with one exception) that within their scope names are used
- only once across all types of SQL objects. E.g., it is not possible
+ must be contained in a schema.
+ Schemas are namespaces for SQL objects and ensure
+ (with one exception) that the SQL object names are used only once within
+ their scope across all types of SQL objects. E.g., it is not possible
to have a table <literal>employee</literal> and a view
<literal>employee</literal> within the same schema. But it is
- possible to have two tables <literal>employee</literal> in
+ possible to have two tables <literal>employee</literal> in two
different schemas. In this case, the two tables
are separate objects and independent of each
other. The only exception to this cross-type uniqueness is that
@@ -273,7 +272,7 @@
<firstterm>Global SQL Objects</firstterm>, are outside of the
strict hierarchy: All <firstterm>database names</firstterm>,
all <firstterm>tablespace names</firstterm>, and all
- <firstterm>role names</firstterm> are automatically known and
+ <firstterm>role names</firstterm> are automatically
available throughout the cluster, independent from
the database or schema in which they where defined originally.
<xref linkend="tutorial-internal-objects-hierarchy-figure"/>
@@ -302,7 +301,7 @@
<title>The physical Perspective: Directories and Files</title>
<para>
- <productname>PostgreSQL</productname> organizes long-lasting
+ <productname>PostgreSQL</productname> organizes long-lasting (persistent)
data as well as volatile state information about transactions
or replication actions in the file system. Every
<xref linkend="glossary-db-cluster"/> has its root directory
@@ -352,20 +351,19 @@
every table and every index to store heap and index
data. Those files are accompanied by files for the
<link linkend="storage-fsm">Free Space Maps</link>
- (extension <literal>_fsm</literal>) and
+ (suffixed <literal>_fsm</literal>) and
<link linkend="storage-vm">Visibility Maps</link>
- (extension <literal>_vm</literal>), which contain optimization information.
+ (suffixed <literal>_vm</literal>), which contain optimization information.
</para>
<para>
- Another subdirectory is <literal>global</literal>.
- In analogy to the database-specific
- subdirectories, there are files containing information about
+ Another subdirectory is <literal>global</literal> which
+ contains files with information about
<glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
One type of such Global SQL Objects are
<glossterm linkend="glossary-tablespace">tablespaces</glossterm>.
In <literal>global</literal> there is information about
- the tablespaces, not the tablespaces themselves.
+ the tablespaces; not the tablespaces themselves.
</para>
<para>
@@ -392,11 +390,11 @@
<para>
In the root directory <literal>data</literal>
there are also some files. In many cases, the configuration
- files of the cluster are stored here. As long as the
+ files of the cluster are stored here. If the
instance is up and running, the file
<literal>postmaster.pid</literal> exists here
and contains the process ID (pid) of the
- Postmaster which has started the instance.
+ Postmaster which started the instance.
</para>
<para>
@@ -411,7 +409,7 @@
<para>
In most cases, <productname>PostgreSQL</productname> databases
- support many clients at the same time. Therefore, it is necessary to
+ support many clients at the same time which makes it necessary to
protect concurrently running requests from unwanted overwriting
of other's data as well as from reading inconsistent data. Imagine an
online shop offering the last copy of an article. Two clients have the
@@ -432,11 +430,11 @@
<productname>PostgreSQL</productname> implements a third, more
sophisticated technique: <firstterm>Multiversion Concurrency
Control</firstterm> (MVCC). The crucial advantage of MVCC
- over other technologies gets evident in multiuser OLTP
+ over other technologies becomes evident in multiuser OLTP
environments with a massive number of concurrent write
actions. There, MVCC generally performs better than solutions
using locks. In a <productname>PostgreSQL</productname>
- database reading never blocks writing and writing never
+ database, reading never blocks writing and writing never
blocks reading, even in the strictest level of transaction
isolation.
</para>
@@ -444,14 +442,14 @@
<para>
Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
a new version of the row when a data-change takes place. To
- distinguish between these two versions and to track the timeline
+ distinguish between these two versions, and to track the timeline
of the row, each of the versions contains, in addition to their user-defined
columns, two special system columns, which are not visible
for the usual <command>SELECT * FROM ...</command> command.
The column <literal>xmin</literal> contains the transaction ID (xid)
- of the transaction, which created this version of the row. Accordingly,
- <literal>xmax</literal> contains the xid of the transaction, which has
- deleted this version, or zero, if the version is not
+ of the transaction which created this version of the row.
+ <literal>xmax</literal> contains the xid of the transaction which has
+ deleted this version, or zero if the version is not
deleted. You can read both with the command
<command>SELECT xmin, xmax, * FROM ... </command>.
</para>
@@ -469,7 +467,7 @@
</para>
<para>
- The description in this chapter simplifies by omitting some details.
+ The description in this chapter simplifies by omitting details.
When many transactions are running simultaneously, things can
get complicated. Sometimes transactions get aborted via
<command>ROLLBACK</command> immediately or after a lot of other activities, sometimes
@@ -526,8 +524,8 @@
creates a new version of the row with its xid in
<literal>xmin</literal>, <literal>0</literal> in
<literal>xmax</literal>, and <literal>'y'</literal> in the
- user data (plus all the other user data from the old version).
- This version is now valid for all coming transactions.
+ user data (plus all other user data from the old version).
+ This version is now valid for all future transactions.
</para>
<para>
@@ -624,9 +622,9 @@
<para>
Autovacuum runs automatically by
default. Its default parameters as well as such for
- <command>VACUUM</command> fit well for most standard
+ <command>VACUUM</command> are appropriate for most standard
situations. Therefore a novice database manager can
- easily skip the rest of this chapter which explains
+ skip the rest of this chapter which explains
a lot of details.
</para>
</note>
@@ -687,7 +685,7 @@
<para>
The eagerness — you can call it 'aggression' — of the
- operations <emphasis>eliminating bloat</emphasis> and
+ operations for <emphasis>eliminating bloat</emphasis> and
<emphasis>freeze</emphasis> is controlled by configuration
parameters, runtime flags, and in extreme situations by
the processes themselves. Because vacuum operations typically are I/O
@@ -783,7 +781,7 @@
When a client issues the SQL command <command>VACUUM</command>
with the option <command>FULL</command>.
Also, in this mode, the bloat disappears, but the strategy used
- is very different: In this case, the complete table is copied
+ is very different: in this case, the complete table is copied
to a different file skipping all outdated row versions. This
leads to a significant reduction of used disk space because
the new file contains only the actual data. The old file
@@ -1143,7 +1141,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
atomicity: either all or none of its operations succeed,
regardless of the fact that it may consist of a lot of
different write-operations, and each such operation may
- affect thousands or millions of rows. As soon as one of the
+ affect many rows. As soon as one of the
operations fails, all previous operations fail also, which
means that all modified rows retain their values as of the
beginning of the transaction.
@@ -1157,14 +1155,14 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
— even in the lowest
<link linkend="transaction-iso">isolation level</link>
of transactions. <productname>PostgreSQL</productname>
- does never show uncommitted changes to other connections.
+ never shows uncommitted changes to other connections.
</para>
<para>
The situation regarding visibility is somewhat different
from the point of view of the modifying transaction.
- <command>SELECT</command> commands issued inside a
- transaction delivers all changes done so far by this
+ A <command>SELECT</command> command issued inside a
+ transaction shows all changes done so far by this
transaction.
</para>
@@ -1231,7 +1229,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<para>
Transactions ensure that the
<glossterm linkend="glossary-consistency">consistency</glossterm>
- of the complete database always keeps valid. Declarative
+ of the complete database always remains valid. Declarative
rules like
<link linkend="ddl-constraints-primary-keys">primary</link>- or
<link linkend="ddl-constraints-fk">foreign keys</link>,
@@ -1241,13 +1239,6 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
are part of the all-or-nothing nature of transactions.
</para>
- <para>
- Also, all self-evident — but possibly not obvious
- — low-level demands on the database system are
- ensured; e.g. index entries for rows must become
- visible at the same moment as the rows themselves.
- </para>
-
<para>
There is the additional feature
'<link linkend="transaction-iso">isolation level</link>',
@@ -1287,7 +1278,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
a severe software error like a null pointer exception.
Because <productname>PostgreSQL</productname> uses a
client/server architecture, no direct problem for the
- database will occur. In all of this cases, the
+ database will occur. In all of these cases, the
<glossterm linkend="glossary-backend">Backend process</glossterm>,
which is the client's counterpart at the server-side,
may recognize that the network connection is no longer
@@ -1310,7 +1301,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
automatically recognizes that the last shutdown of the
instance did not happen as expected: files might not be
closed properly and the <literal>postmaster.pid</literal>
- file exists. <productname>PostgreSQL</productname>
+ file unexpectedly exists. <productname>PostgreSQL</productname>
tries to clean up the situation. This is possible because
all changes in the database are stored twice. First,
the WAL files contain them as a chronology of
@@ -1328,8 +1319,8 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<glossterm linkend="glossary-checkpoint">checkpoint</glossterm>.
This checkpoint signals that the database files are in
a consistent state, especially that all WAL records up to
- this point were successfully stored in heap and index. Starting
- here, the recovery process copies the following WAL records
+ this point were successfully stored in heap and index files. Starting
+ here, the recovery process copies the remaining WAL records
to heap and index. As a result, the files contain all
changes and reach a consistent state. Changes of committed
transactions are visible; those of uncommited transactions
@@ -1344,10 +1335,10 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<bridgehead renderas="sect3">Disk crash</bridgehead>
<para>
If a disk crashes, the course of action described previously
- cannot work. It is likely that the WAL files and/or the
+ cannot work: it is likely that the WAL files and/or the
data and index files are no longer available. The
database administrator must take special actions to
- overcome such situations.
+ prepare for such a situation.
</para>
<para>
He obviously needs a backup. How to take such a backup
@@ -1427,7 +1418,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
</para>
<para>
The obvious disadvantage of this method is that there
- is a downtime where no user interaction is possible.
+ is a downtime.
The other two strategies run during regular operating
times.
</para>
@@ -1456,14 +1447,14 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
<para>
<link linkend="continuous-archiving">This method</link>
- is the most sophisticated and complex one. It
+ is the most sophisticated and most complex one. It
consists of two phases.
</para>
<para>
- First, you need to create a so called
+ First, you need to create a so-called
<firstterm>basebackup</firstterm> with the tool
<command>pg_basebackup</command>. The result is a
- directory structure plus files which contains a
+ directory structure plus files which contain a
consistent copy of the original cluster.
<command>pg_basebackup</command> runs in
parallel to other processes in its own transaction.
@@ -1484,7 +1475,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
will automatically copy every single WAL file to a save location.
<link linkend="backup-archiving-wal">Its configuration</link>
- consists mainly of a string, which contains a copy command
+ consists mainly of a string that contains a copy command
in the operating system's syntax. In order to protect your
data against a disk crash, the destination location
of a basebackup as well as of the
@@ -1492,9 +1483,8 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
disk which is different from the data disk.
</para>
<para>
- If it gets necessary to restore the cluster, you have to
- copy the basebackup and the
- archived WAL files to
+ If it becomes necessary to restore the cluster, you have to
+ copy the basebackup and the archived WAL files to
their original directories. The configuration of this
<link linkend="backup-pitr-recovery">recovery procedure</link>
contains a string with the reverse copy command: from
--
2.17.0
0002-Fix-accesses-per-suggestion-from-Erik.patchtext/x-diff; charset=us-asciiDownload
From 7712793cd1be3ff17b3f32668f08101fbbaa6eda Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Sat, 31 Oct 2020 15:48:00 -0500
Subject: [PATCH 2/3] Fix "accesses" per suggestion from Erik
---
doc/src/sgml/architecture.sgml | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
index ffdac61975..6f819220dc 100644
--- a/doc/src/sgml/architecture.sgml
+++ b/doc/src/sgml/architecture.sgml
@@ -158,7 +158,7 @@
-->
<para>
- The Statistics Collector collects counters about accesses to
+ The Statistics Collector collects counters about access to
SQL objects like tables, rows, indexes, pages, and more. It
stores the obtained information in system tables.
</para>
@@ -423,7 +423,7 @@
<para>
A first approach to implement protections against concurrent
- accesses to the same data may be the locking of critical
+ access to the same data may be the locking of critical
rows. Two such techniques are:
<emphasis>Optimistic Concurrency Control</emphasis> (OCC)
and <emphasis>Two Phase Locking</emphasis> (2PL).
@@ -479,7 +479,7 @@
</para>
<para>
- So, what's going on in detail when write accesses take place?
+ So, what's going on in detail when write access takes place?
<xref linkend="tutorial-mvcc-figure"/> shows details concerning
<literal>xmin</literal>, <literal>xmax</literal>, and user data.
</para>
@@ -1059,7 +1059,7 @@
The setting of the flags is silently done by <command>VACUUM</command>
and Autovacuum during their bloat and freeze operations.
This is done to speed up future vacuum actions,
- regular accesses to heap pages, and some accesses to
+ regular access to heap pages, and some access to
the index. Every data-modifying operation on any row
version of the page clears the flags.
</para>
--
2.17.0
0003-More-fixes-on-top.patchtext/x-diff; charset=us-asciiDownload
From fec3a8f5722b41a15327a4c0eb18f68ba07a51fd Mon Sep 17 00:00:00 2001
From: Justin Pryzby <pryzbyj@telsasoft.com>
Date: Sat, 31 Oct 2020 15:44:22 -0500
Subject: [PATCH 3/3] More fixes on top
---
doc/src/sgml/architecture.sgml | 239 ++++++++++++++++-----------------
1 file changed, 114 insertions(+), 125 deletions(-)
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
index 6f819220dc..f3acdaa6b3 100644
--- a/doc/src/sgml/architecture.sgml
+++ b/doc/src/sgml/architecture.sgml
@@ -66,9 +66,7 @@
When a client application tries to connect to a
<glossterm linkend="glossary-database">database</glossterm>,
this request is handled initially by the Postmaster. It
- starts a new Backend process and instructs the client
- application to connect to it. All further client requests
- are handled by this process.
+ starts a new Backend process to service the client's requests.
</para>
<para>
@@ -89,7 +87,7 @@
write actions take place. Modified pages are called dirty
pages or dirty buffers and before they can be evicted they
must be written to disk. This happens regularly by the
- Background Writer and the Checkpointer process to ensure
+ Checkpointer and Background Writer processes to ensure
that the disk version of the pages are up-to-date.
The synchronisation from RAM to disk consists of two steps.
</para>
@@ -117,7 +115,7 @@
<para>
Second, the transfer of dirty buffers from Shared Memory to
files must take place. This is the primary task of the
- Background Writer process. Because I/O activities can block
+ Checkpointer process. Because I/O activities can block
other processes, it starts periodically and
acts only for a short period. Doing so, its extensive (and
expensive) I/O activities are spread over time, avoiding
@@ -136,7 +134,9 @@
a possibly occurring recovery, which integrates the delta
information of WAL into heap and index files, will happen
by replaying only WAL past the last recorded checkpoint
- on top of the current heap and files. This speeds up recovery.
+ on top of the current heap and files.
+ This limits the amount of WAL which needs to be replayed during recovery in
+ the event of a crash.
</para>
<para>
@@ -369,8 +369,8 @@
<para>
The subdirectory <literal>pg_wal</literal> contains the
<glossterm linkend="glossary-wal-file">WAL files</glossterm>.
- They arise and grow parallel to data changes in the
- cluster and remain alive as long as
+ They arise and grow in parallel with data changes in the
+ cluster and remain as long as
they are required for recovery, archiving, or replication.
</para>
@@ -383,8 +383,8 @@
<para>
In <literal>pg_tblspc</literal>, there are symbolic links
- that point to directories containing such SQL objects
- that are created within tablespaces.
+ that point to directories containing SQL objects
+ that exist within a non-default tablespace.
</para>
<para>
@@ -459,7 +459,7 @@
sequences. Every new transaction receives the next number as its ID.
Therefore, this flow of xids represents the flow of transaction
start events over time. But keep in mind that xids are independent of
- any time measurement — in milliseconds or whatever. If you dive
+ any time measurement — in milliseconds or otherwise. If you dive
deeper into <productname>PostgreSQL</productname>, you will recognize
parameters with names such as 'xxx_age'. Despite their names,
these '_age' parameters do not specify a period of time but represent
@@ -514,38 +514,36 @@
executes an <command>UPDATE</command> of this row by
changing the user data from <literal>'x'</literal> to
<literal>'y'</literal>. According to the MVCC principles,
- the data in the old version of the row does not change!
- The value <literal>'x'</literal> remains as it was before.
- Only <literal>xmax</literal> changes to <literal>135</literal>.
- Now, this version is treated as valid exclusively for
+ the old version of the row is not changed!
+ Internally, an <command>UPDATE</command> command acts
+ as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.
+ <literal>xmax</literal> of the old row version is changed to <literal>135</literal>,
+ and a new row version is added with
+ <literal>xmin</literal>=135,
+ <literal>xmax</literal>=0, and <literal>'y'</literal> in the
+ user data (plus any other user columns from the old version).
+ The old row version is visible only to
transactions with xids from <literal>123</literal> to
- <literal>134</literal>. As a substitute for the non-occurring
- data change in the old version, the <command>UPDATE</command>
- creates a new version of the row with its xid in
- <literal>xmin</literal>, <literal>0</literal> in
- <literal>xmax</literal>, and <literal>'y'</literal> in the
- user data (plus all other user data from the old version).
- This version is now valid for all future transactions.
+ <literal>134</literal>, and the new row version
+ is visible to all future transactions.
</para>
<para>
All subsequent <command>UPDATE</command> commands behave
- in the same way as the first one: they put their xid to
+ in the same way as the first one: they put their xid in
<literal>xmax</literal> of the current version, create
- the next version with their xid in <literal>xmin</literal>,
- <literal>0</literal> in <literal>xmax</literal>, and the
- new user data.
+ a new version with their xid in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
</para>
<para>
Finally, a row may be deleted by a <command>DELETE</command>
command. Even in this case, all versions of the row remain as
- before. Nothing is thrown away so far! Only <literal>xmax</literal>
- of the last version changes to the xid of the <command>DELETE</command>
- transaction, which indicates that it is only valid for
- transactions with xids older than its own (from
- <literal>142</literal> to <literal>820</literal> in this
- example).
+ before. Nothing is thrown away! Only <literal>xmax</literal>
+ of the last version is set to the xid of the <command>DELETE</command>
+ transaction, which indicates that (if committed) it is only visible to
+ transactions with xids older than that.
</para>
<para>
@@ -553,10 +551,10 @@
of the same row in the table's heap file and leaves them there,
even after a <command>DELETE</command> command. Only the youngest
version is relevant for all future transactions. But the
- system must also preserve some of the older ones for a
- certain amount of time because the possibility exists that
- they are or could become relevant for any pending
- transactions. Over time, also the older ones get out of scope
+ system must also preserve some of the older ones for
+ awhile, because they could still be needed by
+ transactions which started before the deleting transaction commits.
+ Over time, also the older ones get out of scope
for ALL transactions and therefore become unnecessary.
Nevertheless, they do exist physically on the disk and occupy
space.
@@ -571,26 +569,18 @@
<simpara>
<literal>xmin</literal> and <literal>xmax</literal>
indicate the range from where to where
- row versions are valid (visible) for transactions.
+ <firstterm>row versions</firstterm> are valid (visible) for transactions.
This range doesn't imply any direct temporal meaning;
the sequence of xids reflects only the sequence of
transaction begin events. As
xids grow, old row versions get out of scope over time.
- If an old row version is no longer valid for ALL existing
- transactions, it's called <firstterm>dead</firstterm>. The
- space occupied by dead row versions is part of the
+ If an old row version is no longer relevant for ANY existing
+ transactions, it can be marked <firstterm>dead</firstterm>. The
+ space occupied by dead row versions is wasted space called
<glossterm linkend="glossary-bloat">bloat</glossterm>.
</simpara>
</listitem>
- <listitem>
- <simpara>
- Internally, an <command>UPDATE</command> command acts in the
- same way as a <command>DELETE</command> command followed by
- an <command>INSERT</command> command.
- </simpara>
- </listitem>
-
<listitem>
<simpara>
Nothing gets wiped away — with the consequence that the database
@@ -610,12 +600,12 @@
<para>
As we have seen in the previous chapter, the database
- tends to occupy more and more disk space, the
+ tends to occupy more and more disk space, caused by
<glossterm linkend="glossary-bloat">bloat</glossterm>.
This chapter explains how the SQL command
<command>VACUUM</command> and the automatically running
<firstterm>Autovacuum</firstterm> processes clean up
- by eliminating bloat.
+ and avoid continued growth.
</para>
<note>
@@ -635,8 +625,8 @@
special situations, or they start it in batch jobs which run
periodically. Autovacuum processes run as part of the
<link linkend="glossary-instance">Instance</link> at the server.
- There is a constantly running Autovacuum daemon. It permanently
- controls the state of all databases based on values that are collected by the
+ There is a constantly running Autovacuum daemon. It continuously
+ monitors the state of all databases based on values that are collected by the
<link linkend="glossary-stats-collector">Statistics Collector</link>
and starts Autovacuum processes whenever it detects
certain situations. Thus, it's a dynamic behavior of
@@ -657,7 +647,7 @@
<listitem>
<simpara>
- <firstterm>Freeze</firstterm>: Mark the youngest row version
+ <firstterm>Freeze</firstterm>: Mark old row version
as frozen. This means that the version
is always treated as valid (visible) independent from
the <firstterm>wraparound problem</firstterm> (see below).
@@ -684,22 +674,22 @@
</itemizedlist>
<para>
- The eagerness — you can call it 'aggression' — of the
+ The eagerness — you can call it 'aggressiveness' — of the
operations for <emphasis>eliminating bloat</emphasis> and
<emphasis>freeze</emphasis> is controlled by configuration
parameters, runtime flags, and in extreme situations by
the processes themselves. Because vacuum operations typically are I/O
intensive, which can hinder other activities, Autovacuum
avoids performing many vacuum operations in bulk. Instead,
- it carries out many small actions with time gaps in between.
- The SQL command <command>VACUUM</command> runs immediately
- and without any time gaps.
+ it carries out many small actions with delay points in between.
+ When invoked manually, the SQL command <command>VACUUM</command>
+ runs immediately and (by default) without any time delay.
</para>
<bridgehead renderas="sect2">Eliminate Bloat</bridgehead>
<para>
- To determine which of the row versions are superfluous, the
+ To determine which of the row versions are no longer needed, the
elimination operation must evaluate <literal>xmax</literal>
against several criteria which all must apply:
</para>
@@ -740,14 +730,13 @@
</itemizedlist>
<para>
- After the vacuum operation detects a superfluous row version, it
+ After the vacuum operation detects an unused row version, it
marks its space as free for future use of writing actions. Only
in rare situations (or in the case of <command>VACUUM FULL</command>),
- this space is released to the operating system. In most cases,
+ is this space released to the operating system. In most cases,
it remains occupied by <productname>PostgreSQL</productname>
and will be used by future <command>INSERT</command> or
- <command>UPDATE</command> commands concerning this row or a
- completely different one.
+ <command>UPDATE</command> commands to this table.
</para>
<para>
@@ -761,9 +750,9 @@
in its default format, i.e., without any option. To boost performance,
in this and the next case <command>VACUUM</command> does not
read and act on all pages of the heap.
- The Visibility Map, which is very compact and therefore has a small
- size, contains information about pages, where bloat-candidates might
- be found. Only such pages are processed.
+ The Visibility Map, which is very compact and therefore fast to read,
+ contains information about which pages have no deleted row versions, and
+ can be skipped by vacuum.
</simpara>
</listitem>
@@ -771,7 +760,7 @@
<simpara>
When a client issues the SQL command <command>VACUUM</command>
with the option <command>FREEZE</command>. (In this case,
- it undertakes much more actions, see
+ it undertakes many more actions, see
<link linkend="tutorial-freeze">Freeze Row Versions</link>.)
</simpara>
</listitem>
@@ -780,12 +769,11 @@
<simpara>
When a client issues the SQL command <command>VACUUM</command>
with the option <command>FULL</command>.
- Also, in this mode, the bloat disappears, but the strategy used
- is very different: in this case, the complete table is copied
- to a different file skipping all outdated row versions. This
- leads to a significant reduction of used disk space because
- the new file contains only the actual data. The old file
- is deleted.
+ In this mode, an exclusive lock is taken, and
+ the whole table is copied to a different file, skipping all outdated row
+ versions. All bloat is thereby eliminated, which
+ may lead to a significant reduction of used disk space.
+ The old file is deleted.
</simpara>
</listitem>
@@ -807,17 +795,17 @@
<para>
This logic only applies to row versions of the heap. Index entries
don't use <literal>xmin/xmax</literal>. Nevertheless, such index
- entries, which would lead to outdated row versions, are released
+ entries, which would lead to outdated row versions, are cleaned up
accordingly.
</para>
<para>
The above descriptions omit the fact that xids on a real computer
- have a limited size. They count up in the same way as sequences, and after
- a certain number of new transactions they are forced to restart
+ have a limited size, and after
+ a certain number of transactions they are forced to restart
from the beginning, which is called <firstterm>wraparound</firstterm>.
Therefore the terms 'old transaction' / 'young transaction' does
- not always correlate with low / high values of xids. Near to the
+ not always correlate with low / high values of xids. Near the
wraparound point, there are cases where <literal>xmin</literal> has
a higher value than <literal>xmax</literal>, although their meaning
is said to be older than <literal>xmax</literal>.
@@ -856,7 +844,7 @@
and the corresponding transactions of <literal>xmin</literal>
and <literal>xmax</literal> must be committed. However,
<productname>PostgreSQL</productname> has to consider the
- possibility of wraparounds.
+ possibility of wraparound.
Therefore the decision becomes more complex. The general
idea of the solution is to use the 'between
<literal>xmin</literal> and <literal>xmax</literal>'
@@ -883,7 +871,7 @@
<listitem>
<simpara>
With each newly created transaction the two split-points
- move forward. When 'txid_current + 2^31' would reach a
+ move forward. If 'txid_current + 2^31' reached a
row version with <literal>xmin</literal> equal to that value, it would
immediately jump from 'past' to 'future' and would be
no longer visible!
@@ -892,11 +880,11 @@
<listitem>
<simpara>
- To avoid this unacceptable extinction of data, the vacuum
- operation <firstterm>freeze</firstterm> clears the situation
- long before the split-point is reached. It sets a flag
- in the header of the row version, which completely eliminates
- the future use of <literal>xmin/xmax</literal> and indicates
+ If not handled in some way, data inserted many transactions ago would become invisibile.
+ The vacuum operation <firstterm>freeze</firstterm> avoids this
+ long before the split-point is reached by setting a flag
+ in the header of the row version which avoids
+ future comparison of its <literal>xmin/xmax</literal> and indicates
that the version is valid not only in the 'past'-half
but also in the 'future'-half as well as in all coming
<glossterm linkend="glossary-xid">epochs</glossterm>.
@@ -943,19 +931,19 @@
When a client issues the SQL command <command>VACUUM</command>
with its <command>FREEZE</command> option. In this case, all
pages are processed that are marked in the Visibility Map
- to potentially have unfrozen rows.
+ as potentially having unfrozen rows.
</simpara>
</listitem>
<listitem>
<simpara>
When a client issues the SQL command <command>VACUUM</command> without
- any options but finds that there are xids older than
+ any options but there are xids older than
<xref linkend="guc-vacuum-freeze-table-age"/>
(default: 150 million) minus
<xref linkend="guc-vacuum-freeze-min-age"/>
(default: 50 million).
As before, all pages are processed that are
- marked in the Visibility Map to potentially have unfrozen
+ marked in the Visibility Map as potentially having unfrozen
rows.
</simpara>
</listitem>
@@ -981,7 +969,7 @@
<simpara>
The process switches
to an <emphasis>aggressive mode</emphasis> if it recognizes
- that for the processed table their oldest xid exceeds
+ that for the processed table the oldest xid exceeds
<xref linkend="guc-autovacuum-freeze-max-age"/>
(default: 200 million). The value of the oldest unfrozen
xid is stored per table in <literal>pg_class.relfrozenxid</literal>.
@@ -1037,22 +1025,21 @@
<para>
The <link linkend="glossary-vm">Visibility Map</link>
(VM) contains two flags — stored as
- two bits — for each page of the heap. If the first bit
- is set, that indicates that the associated page does not
- contain any bloat. If the second one is set, that indicates
- that the page contains only frozen rows.
+ two bits — for each page of the heap. The first bit
+ indicates that the associated page does not
+ contain any bloat. The second bit indicates
+ that the page contains only frozen row versions.
</para>
<para>
Please consider two details. First, in most cases a page
- contains many rows, some of them in many versions.
+ contains many rows or row-versions.
However, the flags are associated with the page,
- not with a row or a row version. The flags are set
+ not with an individual row version. The flags are set
only under the condition that they are valid for ALL
row versions of the page. Second, since there
are only two bits per page, the VM is considerably
- smaller than the heap. Therefore it is buffered
- in RAM in almost all cases.
+ smaller than the heap.
</para>
<para>
@@ -1068,7 +1055,7 @@
The <link linkend="glossary-fsm">Free Space Map</link>
(FSM) tracks the amount of free space per page. It is
organized as a highly condensed b-tree of (rounded) sizes.
- As long as <command>VACUUM</command> or Autovacuum change
+ Whenever <command>VACUUM</command> or Autovacuum changes
the free space on any processed page, they log the new
values in the FSM in the same way as all other writing
processes.
@@ -1077,18 +1064,19 @@
<bridgehead renderas="sect2">Statistics</bridgehead>
<para>
- Statistic information helps the <link
+ Statistical information helps the <link
linkend="planner-stats">Query Planner</link> to make optimal
decisions for the generation of execution plans. This
information can be gathered with the SQL commands
<command>ANALYZE</command> or <command>VACUUM ANALYZE</command>.
- But also Autovacuum processes gather
+ But Autovacuum processes also gather
such information. Depending on the percentage of changed rows
- per table <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ and minimum number of changed rows <xref linkend="guc-autovacuum-analyze-threshold"/>,
the Autovacuum daemon starts Autovacuum processes to collect
- statistics per table. This dynamic invocation of analyze
- operations allows <productname>PostgreSQL</productname> to
- adopt queries to changing circumstances.
+ statistics per table. The automatic analysis
+ allows <productname>PostgreSQL</productname> to
+ adapt query execution to changing circumstances.
</para>
<para>
@@ -1149,7 +1137,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<para>
The atomicity also affects the visibility of changes. No
- connection running simultaneously to a data modifying
+ connection running simultaneously with a data modifying
transaction will ever see any change before the
transaction successfully executes a <command>COMMIT</command>
— even in the lowest
@@ -1228,9 +1216,9 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<para>
Transactions ensure that the
- <glossterm linkend="glossary-consistency">consistency</glossterm>
- of the complete database always remains valid. Declarative
- rules like
+ database always remains
+ <glossterm linkend="glossary-consistency">consistent</glossterm>.
+ Declarative rules like
<link linkend="ddl-constraints-primary-keys">primary</link>- or
<link linkend="ddl-constraints-fk">foreign keys</link>,
<link linkend="ddl-constraints-check-constraints">checks</link>,
@@ -1248,11 +1236,12 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
</para>
<para>
- Lastly, it is worth to notice that changes done by a
- committed transaction will survive all future application,
- instance, or hardware failures. The next chapter
- explains this
- <glossterm linkend="glossary-durability">durability</glossterm>.
+ Lastly, it is worth noticing that changes done by a
+ committed transaction will survive all failures in the application or
+ database cluster.
+ The next chapter explains the
+ <glossterm linkend="glossary-durability">durability</glossterm>
+ guarantees.
</para>
</sect1>
@@ -1309,7 +1298,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
which include the new data values and information about commit
actions. The WAL records are written first. Second,
the data itself shall exist in the heap and index files.
- In opposite to the WAL records, this part may or may
+ In constrast with the WAL records, this part may or may
not have been transferred entirely from Shared Memory
to the files.
</para>
@@ -1321,15 +1310,15 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
a consistent state, especially that all WAL records up to
this point were successfully stored in heap and index files. Starting
here, the recovery process copies the remaining WAL records
- to heap and index. As a result, the files contain all
- changes and reach a consistent state. Changes of committed
- transactions are visible; those of uncommited transactions
+ to heap and index. As a result, the heap files contain all
+ changes recorded to the WAL and reach a consistent state. Changes of committed
+ transactions are visible; those of uncommitted transactions
are also in the files, but - as usual - they are never seen
- by any of the following transactions because uncommited
+ by any of the following transactions because uncommitted
changes are never shown. Such recovery actions run
completely automatically, it is not necessary that a
database administrator configure or start anything by
- himself.
+ themself.
</para>
<bridgehead renderas="sect3">Disk crash</bridgehead>
@@ -1341,7 +1330,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
prepare for such a situation.
</para>
<para>
- He obviously needs a backup. How to take such a backup
+ They obviously needs a backup. How to take such a backup
and use it as a starting point for a recovery of the
cluster is explained in more detail in the next
<link linkend="tutorial-backup">chapter</link>.
@@ -1353,11 +1342,11 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
and there is no room for additional data. In this case,
<productname>PostgreSQL</productname> stops accepting
data-modifying commands or even terminates completely.
- No data loss or data corruption will occur.
+ Committed data is neither lost nor corrupted.
</para>
<para>
- To come out of such a situation, the administrator should
- remove unused files from this disk. But he should never
+ To recover from such a situation, the administrator should
+ remove unused files from this disk. But they should never
delete files from the
<glossterm linkend="glossary-data-directory">data directory</glossterm>.
Nearly all of them are necessary for the consistency
@@ -1428,9 +1417,9 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
The tool <command>pg_dump</command> is able to take a
<link linkend="backup-dump">copy</link>
of the complete cluster or certain parts of it. It stores
- the copy in the form of SQL <command>CREATE</command> and
- <command>INSERT</command> commands. It runs in
- parallel to other processes in its own transaction.
+ the copy in the form of SQL commands like <command>CREATE</command> and
+ <command>COPY</command>. It runs in
+ parallel with other processes in its own transaction.
</para>
<para>
The output of <command>pg_dump</command> may be used as
@@ -1457,7 +1446,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
directory structure plus files which contain a
consistent copy of the original cluster.
<command>pg_basebackup</command> runs in
- parallel to other processes in its own transaction.
+ parallel with other processes in its own transaction.
</para>
<para>
The second step is recommended but not necessary. All
--
2.17.0
On 30.10.20 17:45, Erik Rijkers wrote:
Hi,
I applied 0009-architecture-vs-master.patch to head
and went through architecture.sgml (only that file),
then produced the attached .diffAnd I wrote down some separate items:
1.
'Two Phase Locking' and 'TPL' should be, I think,
'Two-Phase Commit'. Please someone confirm.
(no changes made)2.
To compare xid to sequence because they similarly 'count up' seems a
bad idea.
(I don't think it's always true in the case of sequences)
(no changes made)3.
'accesses' seems a somewhat strange word most of the time just
'access' may be better. Not sure - native speaker wanted. (no changes
made)4.
'heap', in postgres, means often (always?) files. But more generally,
the meaning is more associated with memory. Therefore it would be
good I think to explicitly use 'heap file' at least in the beginning
once to make clear that heap implies 'safely written away to disk'.
Again, I'm not quite sure if my understanding is correct - I have made
no changes in this regard.Erik Rijkers
All suggestions so far are summarized in the attached patch with the
following exceptions:
- 'Two Phase Locking' is the intended term.
- Not adopted:
Second, the transfer of dirty buffers from Shared Memory to
files must take place. This is the primary task of the
- Background Writer process. Because I/O activities can block
+ Checkpointer process. Because I/O activities can block
other processes, it starts periodically and
Partly adopted:
- the data in the old version of the row does not change! ...
- before. Nothing is thrown away so far! Only <literal>xmax</literal> ...
--
J. Purtz
Attachments:
0010-architecture-vs-master.patchtext/x-patch; charset=UTF-8; name=0010-architecture-vs-master.patchDownload
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
index 2d4ab85d45..5c3245c0ec 100644
--- a/doc/src/sgml/advanced.sgml
+++ b/doc/src/sgml/advanced.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/advanced.sgml -->
<chapter id="tutorial-advanced">
- <title>Advanced Features</title>
+ <title>Advanced SQL Features</title>
<sect1 id="tutorial-advanced-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/arch-dev.sgml b/doc/src/sgml/arch-dev.sgml
index 7883c3cd82..9db0ae2c78 100644
--- a/doc/src/sgml/arch-dev.sgml
+++ b/doc/src/sgml/arch-dev.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/arch-dev.sgml -->
<chapter id="overview">
- <title>Overview of PostgreSQL Internals</title>
+ <title>Overview of Query Handling</title>
<note>
<title>Author</title>
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
new file mode 100644
index 0000000000..0c663a9d80
--- /dev/null
+++ b/doc/src/sgml/architecture.sgml
@@ -0,0 +1,1507 @@
+<!-- doc/src/sgml/architecture.sgml -->
+
+ <chapter id="tutorial-architecture">
+ <title>Overview of Architecture and Implementation</title>
+
+ <para>
+ Every DBMS implements basic strategies to ensure a fast
+ and robust system. This chapter provides an overview of the
+ techniques <productname>PostgreSQL</productname> uses to
+ achieve this.
+ </para>
+
+ <sect1 id="tutorial-ram-proc-file">
+ <title>Collaboration of Processes, RAM, and Files</title>
+ <para>
+ In a client/server architecture clients do not have direct access
+ to database files and the data stored in them. Instead, they send
+ requests to the server and receive the requested data in the response.
+ In the case of <productname>PostgreSQL</productname>, the server
+ launches a single process for each client connection, referred to as a
+ <glossterm linkend="glossary-backend">Backend</glossterm> process.
+ Such a Backend process handles the client's requests by acting on the
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>.
+ This leads to other activities (file access, WAL, vacuum, ...) of the
+ <glossterm linkend="glossary-instance">Instance</glossterm>. The
+ Instance is a group of server-side processes acting on a common
+ Shared Memory. PostgreSQL does not utilize threading.
+ </para>
+
+ <para>
+ The first step when an Instance starts is the start of the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ It loads the configuration files, allocates Shared Memory, and
+ starts the other processes of the Instance:
+ <glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
+ <glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
+ <glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
+ <glossterm linkend="glossary-wal-archiver">WAL Archiver</glossterm>,
+ <glossterm linkend="glossary-autovacuum">Autovacuum</glossterm>,
+ <glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
+ <glossterm linkend="glossary-logger">Logger</glossterm>, and more.
+ Later, the Postmaster starts
+ <glossterm linkend="glossary-backend">Backend</glossterm> processes
+ which communicate with clients and handle their requests.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes the processes
+ of an Instance and the main aspects of their collaboration.
+ </para>
+
+ <figure id="tutorial-ram-proc-file-figure">
+ <title>Architecture</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ When a client application tries to connect to a
+ <glossterm linkend="glossary-database">database</glossterm>,
+ this request is handled initially by the Postmaster. It
+ starts a new Backend process, which handles all further
+ client's requests.
+ </para>
+
+ <para>
+ Client requests like <command>SELECT</command> or
+ <command>UPDATE</command> usually lead to the
+ necessity to read or write data. This is carried out
+ by the client's backend process. Reads involve a page-level
+ cache, located in Shared Memory (for details see:
+ <xref linkend="sysvipc"/>) for the benefit of all processes
+ in the instance. Writes also use this cache, in addition
+ to a journal, called a write-ahead-log or WAL.
+ </para>
+
+ <para>
+ Shared Memory is limited in size and it can become necessary
+ to evict pages. As long as the content of such pages hasn't
+ changed, this is not a problem. But in Shared Memory also
+ write actions take place. Modified pages are called dirty
+ pages or dirty buffers and before they can be evicted they
+ must be written to disk. This happens regularly by the
+ Checkpointer and the Background Writer processes to ensure
+ that the disk version of the pages are up-to-date.
+ The synchronisation from RAM to disk consists of two steps.
+ </para>
+
+<!-- DGJ: WAL should already be done well before page
+ eviction/overwriting comes into play.
+ This is good material but seems misplaced.
+ JuP: Really misplaced? Don't think so.
+-->
+
+ <para>
+ First, whenever the content of a page changes, a
+ <glossterm linkend="glossary-wal-record">WAL record</glossterm>
+ is created out of the delta-information (difference between the
+ old and the new content) and stored in another area of
+ Shared Memory. The parallel running WAL Writer process
+ reads them and appends them to the end of the current
+ <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
+ Such sequential writes are faster than writes to random
+ positions of heap and index files. All WAL records created
+ out of one dirty page must be transferred to disk before the
+ dirty page itself can be transferred to disk in the second step.
+ </para>
+
+ <para>
+ Second, the transfer of dirty buffers from Shared Memory to
+ files must take place. This is the primary task of the
+ Background Writer process. Because I/O activities can block
+ other processes, it starts periodically and
+ acts only for a short period. Doing so, its extensive (and
+ expensive) I/O activities are spread over time, avoiding
+ debilitating I/O peaks. The Checkpointer process
+ also transfers dirty buffers to file.
+ </para>
+
+ <para>
+ The Checkpointer process creates
+ <glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
+ A Checkpoint is a point in time when all older dirty buffers,
+ all older WAL records, and finally a special Checkpoint record
+ are written and flushed to disk. Heap and index files
+ on the one hand and WAL files on the other hand are in sync.
+ Previous WAL is no longer required. In other words,
+ a possibly occurring recovery, which integrates the delta
+ information of WAL into heap and index files, will happen
+ by replaying only WAL past the last recorded checkpoint.
+ This limits the amount of WAL which needs to be replayed
+ during recovery in the event of a crash.
+ </para>
+
+ <para>
+ While the Checkpointer ensures that the database system can crash
+ and restart itself in a valid state, the administrator needs
+ to handle the case where the heap or other files become
+ corrupted (and possibly the locally written WAL, though that is
+ less common). The options and details are covered extensively
+ in the backup and restore section (<xref linkend="backup"/>).
+ For our purposes here, just note that the WAL Archiver process
+ can be enabled and configured to run a script on filled WAL
+ files — usually to copy them to a remote location.
+ </para>
+
+
+<!-- DGJ: after the heavy focus on client processes and data these two
+ seem to come out of left field. Skipping over for now.
+ JuP: Don't skip, we want to explain all elements of the graphic.
+-->
+
+ <para>
+ The Statistics Collector collects counters about access to
+ SQL objects like tables, rows, indexes, pages, and more. It
+ stores the obtained information in system tables.
+ </para>
+
+ <para>
+ The Logger writes text lines about serious and less serious
+ events which can happen during database access, e.g., wrong
+ password, no permission, long-running queries, etc.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-cluster-db-schema">
+ <title>The logical Perspective: Cluster, Database, Schema</title>
+
+ <para>
+ A <glossterm linkend="glossary-server">server</glossterm> contains one or more
+ <glossterm linkend="glossary-db-cluster">database clusters</glossterm>
+ (<glossterm linkend="glossary-db-cluster">clusters</glossterm>
+ for short). Each cluster contains three or more
+ <glossterm linkend="glossary-database">databases</glossterm>.
+ Each database can contain many
+ <glossterm linkend="glossary-schema">schemas</glossterm>.
+ A schema can contain
+ <glossterm linkend="glossary-table">tables</glossterm>,
+ <glossterm linkend="glossary-view">views</glossterm>, and a lot
+ of other objects. Each table or view belongs to a single schema
+ only; they cannot belong to another schema as well. The same is
+ true for the schema/database and database/cluster relation.
+ <xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
+ this hierarchy.
+ </para>
+
+ <figure id="tutorial-cluster-db-schema-figure">
+ <title>Cluster, Database, Schema</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ A cluster is the outer container for a
+ collection of databases. Clusters are created by the command
+ <xref linkend="app-initdb"/>.
+ </para>
+
+ <para>
+ <literal>template0</literal> is the very first
+ database of any cluster. Database <literal>template0</literal>
+ is created during the initialization phase of the cluster.
+ In a second step, database <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal>, and finally database
+ <literal>postgres</literal> is generated as a copy of
+ <literal>template1</literal>. Any
+ <glossterm linkend="app-createdb">new databases</glossterm>
+ of the cluster that a user might need,
+ such as <literal>my_db</literal>, will be copied from the
+ <literal>template1</literal> database. Due to the unique
+ role of <literal>template0</literal> as the pristine original
+ of all other databases, no client can connect to it.
+ </para>
+
+ <para>
+ Every database must contain at least one schema because all
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>
+ must be contained in a schema.
+ Schemas are namespaces for SQL objects and ensure
+ (with one exception) that the SQL object names are used only once within
+ their scope across all types of SQL objects. E.g., it is not possible
+ to have a table <literal>employee</literal> and a view
+ <literal>employee</literal> within the same schema. But it is
+ possible to have two tables <literal>employee</literal> in two
+ different schemas. In this case, the two tables
+ are separate objects and independent of each
+ other. The only exception to this cross-type uniqueness is that
+ <glossterm linkend="glossary-unique-constraint">unique constraints
+ </glossterm> and the according unique index
+ (<xref linkend="indexes-unique"/>) use the same name.
+ </para>
+
+ <para>
+ Some schemas are predefined. <literal>public</literal>
+ acts as the default schema and contains all SQL objects
+ which are created within <literal>public</literal> or
+ without using an explicit schema name. <literal>public</literal>
+ should not contain user-defined SQL objects. Instead, it is
+ recommended to create a separate schema that holds individual
+ objects like application-specific tables or views.
+ <literal>pg_catalog</literal> is a schema for all tables and views of the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ <literal>information_schema</literal> is a schema for several
+ tables and views of the System Catalog in a way that conforms
+ to the SQL standard.
+ </para>
+
+ <para>
+ There are many different SQL object
+ types: <firstterm>database, schema, table, view, materialized
+ view, index, constraint, sequence, function, procedure,
+ trigger, role, data type, operator, tablespace, extension,
+ foreign data wrapper</firstterm>, and more. A few of them, the
+ <firstterm>Global SQL Objects</firstterm>, are outside of the
+ strict hierarchy: All <firstterm>database names</firstterm>,
+ all <firstterm>tablespace names</firstterm>, and all
+ <firstterm>role names</firstterm> are automatically
+ available throughout the cluster, independent from
+ the database or schema in which they where defined originally.
+ <xref linkend="tutorial-internal-objects-hierarchy-figure"/>
+ shows the relation between the object types.
+ </para>
+
+ <figure id="tutorial-internal-objects-hierarchy-figure">
+ <title>Hierarchy of Internal Objects</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="720px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect1>
+
+ <sect1 id="tutorial-directories">
+ <title>The physical Perspective: Directories and Files</title>
+
+ <para>
+ <productname>PostgreSQL</productname> organizes long-lasting (persistent)
+ data as well as volatile state information about transactions
+ or replication actions in the file system. Every
+ <xref linkend="glossary-db-cluster"/> has its root directory
+ somewhere in the file system. In many cases, the environment
+ variable <literal>PGDATA</literal> points to this directory.
+ The example shown in
+ <xref linkend="tutorial-directories-figure"/> uses
+ <literal>data</literal> as the name of this root directory.
+ </para>
+
+ <figure id="tutorial-directories-figure">
+ <title>Directory Structure</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ <literal>data</literal> contains many subdirectories and
+ some files, all of which are necessary to store long-lasting
+ as well as temporary data. The following paragraphs
+ describe the files and subdirectories in
+ <literal>data</literal>.
+ </para>
+
+ <para>
+ <literal>base</literal> is a subdirectory in which one
+ subdirectory per database exists. The names of those
+ subdirectories consist of numbers. These are the internal
+ Object Identifiers (OID), which are numbers to identify
+ the database definition in the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ </para>
+
+ <para>
+ Within the database-specific
+ subdirectories, there are many files: one or more for
+ every table and every index to store heap and index
+ data. Those files are accompanied by files for the
+ <link linkend="storage-fsm">Free Space Maps</link>
+ (suffixed <literal>_fsm</literal>) and
+ <link linkend="storage-vm">Visibility Maps</link>
+ (suffixed <literal>_vm</literal>), which contain optimization information.
+ </para>
+
+ <para>
+ Another subdirectory is <literal>global</literal> which
+ contains files with information about
+ <glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
+ One type of such Global SQL Objects are
+ <glossterm linkend="glossary-tablespace">tablespaces</glossterm>.
+ In <literal>global</literal> there is information about
+ the tablespaces; not the tablespaces themselves.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_wal</literal> contains the
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
+ They arise and grow in parallel with data changes in the
+ cluster and remain as long as
+ they are required for recovery, archiving, or replication.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_xact</literal> contains
+ information about the status of each transaction:
+ <literal>in_progress</literal>, <literal>committed</literal>,
+ <literal>aborted</literal>, or <literal>sub_committed</literal>.
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal>, there are symbolic links
+ that point to directories containing SQL objects
+ that exist within a non-default tablespace.
+ </para>
+
+ <para>
+ In the root directory <literal>data</literal>
+ there are also some files. In many cases, the configuration
+ files of the cluster are stored here. If the
+ instance is up and running, the file
+ <literal>postmaster.pid</literal> exists here
+ and contains the process ID (pid) of the
+ Postmaster which started the instance.
+ </para>
+
+ <para>
+ For more details about the physical implementation
+ of database objects, see <xref linkend="storage"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-mvcc">
+ <title>MVCC — Multiversion Concurrency Control</title>
+
+ <para>
+ In most cases, <productname>PostgreSQL</productname> databases
+ support many clients at the same time which makes it necessary to
+ protect concurrently running requests from unwanted overwriting
+ of other's data as well as from reading inconsistent data. Imagine an
+ online shop offering the last copy of an article. Two clients have the
+ article displayed at their user interface. After a while, but at the same time,
+ both users decide to put it to their shopping cart or even to buy it.
+ Both have seen the article, but only one can be allowed to get it.
+ The database must bring the two requests in a row, permit the access
+ to one of them, block the other, and inform the blocked client
+ that the data was changed by a different process.
+ </para>
+
+ <para>
+ A first approach to implement protections against concurrent
+ access to the same data may be the locking of critical
+ rows. Two such techniques are:
+ <emphasis>Optimistic Concurrency Control</emphasis> (OCC)
+ and <emphasis>Two Phase Locking</emphasis> (2PL).
+ <productname>PostgreSQL</productname> implements a third, more
+ sophisticated technique: <firstterm>Multiversion Concurrency
+ Control</firstterm> (MVCC). The crucial advantage of MVCC
+ over other technologies becomes evident in multiuser OLTP
+ environments with a massive number of concurrent write
+ actions. There, MVCC generally performs better than solutions
+ using locks. In a <productname>PostgreSQL</productname>
+ database, reading never blocks writing and writing never
+ blocks reading, even in the strictest level of transaction
+ isolation.
+ </para>
+
+ <para>
+ Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
+ a new version of the row when a data-change takes place. To
+ distinguish between these two versions, and to track the timeline
+ of the row, each of the versions contains, in addition to their user-defined
+ columns, two special system columns, which are not visible
+ for the usual <command>SELECT * FROM ...</command> command.
+ The column <literal>xmin</literal> contains the transaction ID (xid)
+ of the transaction which created this version of the row.
+ <literal>xmax</literal> contains the xid of the transaction which has
+ deleted this version, or zero if the version is not
+ deleted. You can read both with the command
+ <command>SELECT xmin, xmax, * FROM ... </command>.
+ </para>
+
+ <para>
+ When we speak about transaction IDs, you need to know that xids are like
+ sequences. Every new transaction receives the next number as its ID.
+ Therefore, this flow of xids represents the flow of transaction
+ start events over time. But keep in mind that xids are independent of
+ any time measurement — in milliseconds or otherwise. If you dive
+ deeper into <productname>PostgreSQL</productname>, you will recognize
+ parameters with names such as 'xxx_age'. Despite their names,
+ these '_age' parameters do not specify a period of time but represent
+ a certain number of transactions, e.g., 100 million.
+ </para>
+
+ <para>
+ The description in this chapter simplifies by omitting details.
+ When many transactions are running simultaneously, things can
+ get complicated. Sometimes transactions get aborted via
+ <command>ROLLBACK</command> immediately or after a lot of other activities, sometimes
+ a single row is involved in more than one transaction, sometimes
+ a client crashes, sometimes the sequence of xids restarts
+ from zero, ... . Therefore, every version of a row contains more
+ system columns and flags, not only <literal>xmin</literal>
+ and <literal>xmax</literal>.
+ </para>
+
+ <para>
+ So, what's going on in detail when write access takes place?
+ <xref linkend="tutorial-mvcc-figure"/> shows details concerning
+ <literal>xmin</literal>, <literal>xmax</literal>, and user data.
+ </para>
+
+ <figure id="tutorial-mvcc-figure">
+ <title>Multiversion Concurrency Control</title>
+ <mediaobject>
+ <imageobject role="html">
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="900px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ An <command>INSERT</command> command creates the first
+ version of a row. Besides its user data <literal>'x'</literal>,
+ this version contains the ID of the creating transaction
+ <literal>123</literal> in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ <literal>xmin</literal> indicates that the version
+ exists since transaction <literal>123</literal> and
+ <literal>xmax</literal> that it is currently not deleted.
+ </para>
+
+ <para>
+ Somewhat later, transaction <literal>135</literal>
+ executes an <command>UPDATE</command> of this row by
+ changing the user data from <literal>'x'</literal> to
+ <literal>'y'</literal>. According to the MVCC principles,
+ the data in the old version of the row is not changed!
+ The value <literal>'x'</literal> remains as it was before.
+ Only <literal>xmax</literal> changes to <literal>135</literal>.
+ Now, this version is treated as valid exclusively for
+ transactions with xids from <literal>123</literal> to
+ <literal>134</literal>. In addition to the non-occurring
+ data change in the old version, the <command>UPDATE</command>
+ creates a new version of the row with its xid in
+ <literal>xmin</literal>, <literal>0</literal> in
+ <literal>xmax</literal>, and <literal>'y'</literal> in the
+ user data (plus all other user data from the old version).
+ This new row version is visible to all future transactions.
+ (Internally, an <command>UPDATE</command> command acts
+ as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.)
+ </para>
+
+ <para>
+ All subsequent <command>UPDATE</command> commands behave
+ in the same way as the first one: they put their xid in
+ <literal>xmax</literal> of the current version, create
+ a new version with their xid in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ </para>
+
+ <para>
+ Finally, a row may be deleted by a <command>DELETE</command>
+ command. Even in this case, all versions of the row remain as
+ before. Nothing is thrown away! Only <literal>xmax</literal>
+ of the last version is set to the xid of the <command>DELETE</command>
+ transaction, which indicates that (if committed) it is only visible to
+ transactions with xids older than that (from
+ <literal>142</literal> to <literal>820</literal> in this
+ example).
+ </para>
+
+ <para>
+ In summary, the MVCC technology creates more and more versions
+ of the same row in the table's heap file and leaves them there,
+ even after a <command>DELETE</command> command. Only the youngest
+ version is relevant for all future transactions. But the
+ system must also preserve some of the older ones for
+ awhile, because they could still be needed by
+ transactions which started before the deleting transaction commits.
+ Over time, also the older ones get out of scope
+ for ALL transactions and therefore become unnecessary.
+ Nevertheless, they do exist physically on the disk and occupy
+ space.
+ </para>
+
+ <para>
+ Please keep in mind:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> and <literal>xmax</literal>
+ indicate the range from where to where
+ <firstterm>row versions</firstterm> are valid (visible) for transactions.
+ This range doesn't imply any direct temporal meaning;
+ the sequence of xids reflects only the sequence of
+ transaction begin events. As
+ xids grow, old row versions get out of scope over time.
+ If an old row version is no longer relevant for ANY existing
+ transactions, it can be marked <firstterm>dead</firstterm>. The
+ space occupied by dead row versions is part of the
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Internally, an <command>UPDATE</command> command acts in the
+ same way as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Nothing gets wiped away — with the consequence that the database
+ occupies more and more disk space. It is obvious that
+ this behavior has to be corrected in some
+ way. The next chapter explains how <firstterm>autovacuum</firstterm>
+ fulfills this task.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ </sect1>
+
+ <sect1 id="tutorial-vacuum">
+ <title>Vacuum</title>
+
+ <para>
+ As we have seen in the previous chapter, the database
+ tends to occupy more and more disk space, caused by
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ This chapter explains how the SQL command
+ <command>VACUUM</command> and the automatically running
+ <firstterm>Autovacuum</firstterm> processes clean up
+ and avoid continued growth.
+ </para>
+
+ <note>
+ <para>
+ Autovacuum runs automatically by
+ default. Its default parameters as well as such for
+ <command>VACUUM</command> are appropriate for most standard
+ situations. Therefore a novice database manager can
+ skip the rest of this chapter which explains
+ a lot of details.
+ </para>
+ </note>
+
+ <para>
+ Client processes can issue the SQL command <command>VACUUM</command>
+ at arbitrary points in time. DBAs do this when they recognize
+ special situations, or they start it in batch jobs which run
+ periodically. Autovacuum processes run as part of the
+ <link linkend="glossary-instance">Instance</link> at the server.
+ There is a constantly running Autovacuum daemon. It continuously
+ monitors the state of all databases based on values that are collected by the
+ <link linkend="glossary-stats-collector">Statistics Collector</link>
+ and starts Autovacuum processes whenever it detects
+ certain situations. Thus, it's a dynamic behavior of
+ <productname>PostgreSQL</productname> with the intention to tidy
+ up — whenever it is appropriate.
+ </para>
+
+ <para>
+ <command>VACUUM</command>, as well as Autovacuum, don't just eliminate
+ bloat. They perform additional tasks for minimizing future
+ I/O activities of themselves as well as of other processes.
+ This extra work can be done in a very efficient way since in most
+ cases the expensive physical access to pages has taken place anyway
+ to eliminate bloat. The additional operations are:
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <firstterm>Freeze</firstterm>: Mark certain row versions
+ as frozen. This means that they
+ are always treated as valid (visible) independent from
+ the <firstterm>wraparound problem</firstterm> (see below).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <firstterm>Visibility Map</firstterm> and
+ <firstterm>Free Space Map</firstterm>: Log information about
+ the state of the handled pages in two additional files, the
+ Visibility Map and the Free Space Map.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <emphasis>Statistics</emphasis>: Collect statistics about the
+ number of rows per table, the distribution of values, and so on,
+ as the basis for decisions of the query planner.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ The eagerness — you can call it 'aggressiveness' — of the
+ operations for <emphasis>eliminating bloat</emphasis> and
+ <emphasis>freeze</emphasis> is controlled by configuration
+ parameters, runtime flags, and in extreme situations by
+ the processes themselves. Because vacuum operations typically are I/O
+ intensive, which can hinder other activities, Autovacuum
+ avoids performing many vacuum operations in bulk. Instead,
+ it carries out many small actions with delay points in between.
+ The SQL command <command>VACUUM</command> runs immediately
+ and without any time delay.
+ </para>
+
+ <bridgehead renderas="sect2">Eliminate Bloat</bridgehead>
+
+ <para>
+ To determine which of the row versions are no longer needed, the
+ elimination operation must evaluate <literal>xmax</literal>
+ against several criteria which all must apply:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be different from zero because a
+ value of zero indicates that the row version is still valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must contain an xid which is older
+ than the oldest xid of all currently running transactions
+ <literal>(min(pg_stat_activity.backend_xmin))</literal>.
+ This criterion guarantees that no existing or upcoming transaction
+ will have read or write access to this row version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of <literal>xmax</literal> must be committed. If it was rollback-ed,
+ this row version is treated as valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there is the situation that the row version is part of
+ multiple transactions, special care and some more actions
+ must be taken, see: <xref linkend="vacuum-for-multixact-wraparound"/>.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ After the vacuum operation detects an unused row version, it
+ marks its space as free for future use of writing actions. Only
+ in rare situations (or in the case of <command>VACUUM FULL</command>),
+ is this space released to the operating system. In most cases,
+ it remains occupied by <productname>PostgreSQL</productname>
+ and will be used by future <command>INSERT</command> or
+ <command>UPDATE</command> commands to this table.
+ </para>
+
+ <para>
+ Which actions start the elimination of bloat?
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ in its default format, i.e., without any option. To boost performance,
+ in this and the next case <command>VACUUM</command> does not
+ read and act on all pages of the heap file.
+ The Visibility Map, which is very compact and therefore fast to read,
+ contains information about which pages have no deleted row versions, and
+ can be skipped by <command>VACUUM</command>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FREEZE</command>. (In this case,
+ it undertakes many more actions, see
+ <link linkend="tutorial-freeze">Freeze Row Versions</link>.)
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FULL</command>.
+ In this mode, an exclusive lock is taken, and
+ the whole table is copied to a different file, skipping all outdated row
+ versions. All bloat is thereby eliminated, which
+ may lead to a significant reduction of used disk space.
+ The old file is deleted.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When an Autovacuum process acts. For optimization
+ purposes, it considers the Visibility Map in the same way as
+ <command>VACUUM</command>. Additionally, it ignores tables with few modifications;
+ see <xref linkend="guc-autovacuum-vacuum-threshold"/>,
+ which defaults to 50 rows and
+ <xref linkend="guc-autovacuum-vacuum-scale-factor"/>,
+ which defaults to 20%.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </para>
+
+ <para>
+ This logic only applies to row versions of the heap. Index entries
+ don't use <literal>xmin/xmax</literal>. Nevertheless, such index
+ entries, which would lead to outdated row versions, are cleaned up
+ accordingly.
+ </para>
+
+ <para>
+ The above descriptions omit the fact that xids on a real computer
+ have a limited size, and after
+ a certain number of transactions they are forced to restart
+ from the beginning, which is called <firstterm>wraparound</firstterm>.
+ Therefore the terms 'old transaction' / 'young transaction' does
+ not always correlate with low / high values of xids. Near to
+ wraparound point, there are cases where <literal>xmin</literal> has
+ a higher value than <literal>xmax</literal>, although their meaning
+ is said to be older than <literal>xmax</literal>.
+ </para>
+
+ <figure id="tutorial-wraparound-figure">
+ <title>Cyclic usage of XIDs</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2" id="tutorial-freeze">Freeze Row Versions</bridgehead>
+
+ <para>
+ The use of a limited range of IDs for transactions leads
+ to the necessity to restart the sequence sooner or later.
+ This does not only have the rare consequence previously
+ described that sometimes <literal>xmin</literal> is
+ higher than <literal>xmax</literal>. The far
+ more critical problem is that whenever the system has
+ to evaluate a WHERE condition, it must decide which row
+ version is valid (visible) from the perspective of the
+ transaction of this query. If a wraparound couldn't happen,
+ this decision would be relatively easy: the xid
+ must be between <literal>xmin</literal> and <literal>xmax</literal>,
+ and the corresponding transactions of <literal>xmin</literal>
+ and <literal>xmax</literal> must be committed. However,
+ <productname>PostgreSQL</productname> has to consider the
+ possibility of wraparound.
+ Therefore the decision becomes more complex. The general
+ idea of the solution is to use the 'between
+ <literal>xmin</literal> and <literal>xmax</literal>'
+ comparison only during the youngest period of the row
+ versions lifetime and afterward replace it with a
+ 'valid forever' flag in its header.
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ As a first step, <productname>PostgreSQL</productname>
+ divides the complete range of
+ possible xids into two halves with the two split-points
+ 'txid_current' and 'txid_current + 2^31'. The half behind
+ 'txid_current' is considered to represent xids of the
+ 'past' and the half ahead of 'txid_current' those of the
+ 'future'. Those of the 'past' are valid (visible) and those
+ of the 'future' not.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ With each newly created transaction the two split-points
+ move forward. If 'txid_current + 2^31' reached a
+ row version with <literal>xmin</literal> equal to that value, it would
+ immediately jump from 'past' to 'future' and would be
+ no longer visible!
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If not handled in some way, data inserted many transactions ago
+ would become invisibile. The vacuum operation <firstterm>freeze</firstterm>
+ avoids this long before the split-point is reached by setting
+ a flag in the header of the row version which avoids
+ future comparison of its <literal>xmin/xmax</literal> and indicates
+ that the version is valid not only in the 'past'-half
+ but also in the 'future'-half as well as in all coming
+ <glossterm linkend="glossary-xid">epochs</glossterm>.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Which row versions can be frozen by the vacuum operation?
+ Again, several criteria must be checked, and all must be met.
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be zero because only
+ non-deleted rows can be visible 'forever'.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> must be older than all currently
+ existing transactions. This guarantees that no existing
+ transaction can modify or delete the version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transactions of <literal>xmin</literal> and
+ <literal>xmax</literal> must be committed.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ At what point in time does the freeze operation take place?
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with its <command>FREEZE</command> option. In this case, all
+ pages are processed that are marked in the Visibility Map
+ as potentially having unfrozen rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command> without
+ any options but there are xids older than
+ <xref linkend="guc-vacuum-freeze-table-age"/>
+ (default: 150 million) minus
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million).
+ As before, all pages are processed that are
+ marked in the Visibility Map to potentially having unfrozen
+ rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When an Autovacuum process runs. Such a process acts in one
+ of two modes:
+ </simpara>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ In the <emphasis>normal mode</emphasis>, it skips
+ pages with row versions that are younger than
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million) and works only on pages where
+ all xids are older. The skipping of young xids prevents
+ work on such pages, which are likely to be changed
+ by one of the future SQL commands.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ The process switches
+ to an <emphasis>aggressive mode</emphasis> if it recognizes
+ that for the processed table the oldest xid exceeds
+ <xref linkend="guc-autovacuum-freeze-max-age"/>
+ (default: 200 million). The value of the oldest unfrozen
+ xid is stored per table in <literal>pg_class.relfrozenxid</literal>.
+ In this <emphasis>aggressive mode</emphasis> Autovacuum
+ processes all such pages of the selected table that are marked
+ in the Visibility Map to potentially have bloat or unfrozen rows.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In the first two cases and with Autovacuum in
+ <emphasis>aggressive mode</emphasis>, the system knows
+ to which value the oldest unfrozen xid has moved forward and
+ logs the value in <literal>pg_class.relfrozenxid</literal>.
+ The distance between this value and the 'txid_current' split
+ point becomes smaller, and the distance to 'txid_current + 2^31'
+ becomes larger than before.
+ </para>
+
+ <figure id="tutorial-freeze-figure">
+ <title>Freeze</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- attribute 'width=..px' is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="850px" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2">Protection against Wraparound Failure</bridgehead>
+
+ <para>
+ The Autovacuum processes are initiated by the constantly running
+ Autovacuum daemon. If the daemon detects that for a table
+ <literal>autovacuum_freeze_max_age</literal> is exceeded, it
+ starts an Autovacuum process in <emphasis>aggressive mode</emphasis>
+ (see above) — even if Autovacuum is disabled.
+ </para>
+
+ <bridgehead renderas="sect2">Visibility Map and Free Space Map</bridgehead>
+
+ <para>
+ The <link linkend="glossary-vm">Visibility Map</link>
+ (VM) contains two flags — stored as
+ two bits — for each page of the heap file. The
+ first bit indicates that the associated page does
+ not contain any bloat. The second bit indicates
+ that the page contains only frozen row versions.
+ </para>
+
+ <para>
+ Please consider two details. First, in most cases a page
+ contains many rows or row versions.
+ However, the flags are associated with the page,
+ not with an individual row version. The flags are set
+ only under the condition that they are valid for ALL
+ row versions of the page. Second, since there
+ are only two bits per page, the VM is considerably
+ smaller than the heap.
+ </para>
+
+ <para>
+ The setting of the flags is silently done by <command>VACUUM</command>
+ and Autovacuum during their bloat and freeze operations.
+ This is done to speed up future vacuum actions,
+ regular access to heap pages, and some access to
+ the index. Every data-modifying operation on any row
+ version of the page clears the flags.
+ </para>
+
+ <para>
+ The <link linkend="glossary-fsm">Free Space Map</link>
+ (FSM) tracks the amount of free space per page. It is
+ organized as a highly condensed b-tree of (rounded) sizes.
+ Whenever <command>VACUUM</command> or Autovacuum changes
+ the free space on any processed page, they log the new
+ values in the FSM in the same way as all other writing
+ processes.
+ </para>
+
+ <bridgehead renderas="sect2">Statistics</bridgehead>
+
+ <para>
+ Statistical information helps the <link
+ linkend="planner-stats">Query Planner</link> to make optimal
+ decisions for the generation of execution plans. This
+ information can be gathered with the SQL commands
+ <command>ANALYZE</command> or <command>VACUUM ANALYZE</command>.
+ But Autovacuum processes also gather
+ such information. Depending on the percentage of changed rows
+ <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ and minimum number of changed rows <xref linkend="guc-autovacuum-analyze-threshold"/>,
+ the Autovacuum daemon starts Autovacuum processes to collect
+ statistics per table. The automatic analysis
+ allows <productname>PostgreSQL</productname> to
+ adapt query execution to changing circumstances.
+ </para>
+
+ <para>
+ For more details about vacuum operations, especially for its
+ numerous parameters, see <xref linkend="routine-vacuuming"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-transactions-mvcc">
+ <title>Transactions</title>
+ <para>
+ <link linkend="tutorial-transactions">Transactions</link>
+ are a fundamental concept of relational database systems.
+ Their essential point is that they bundle multiple
+ read- or write-operations into a single all-or-nothing
+ operation. Furthermore, they separate and protect concurrent
+ actions of different connections from each other. Thereby
+ they implement the ACID paradigm.
+ </para>
+
+ <para>
+ In <productname>PostgreSQL</productname> there are two ways
+ to establish a transaction. The explicit way uses the keywords
+ <link linkend="sql-begin">BEGIN</link> and
+ <link linkend="sql-commit">COMMIT</link> (respectively
+ <link linkend="sql-rollback">ROLLBACK</link>) before
+ and after a sequence of SQL statements. The keywords mark
+ the transaction's start- and end-point. On the other hand, you
+ can omit the keywords. This is the implicit way, where
+ every single SQL command automatically establishes a new
+ transaction.
+
+ <programlisting>
+BEGIN; -- establish a new transaction
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+COMMIT; -- finish the transaction
+
+-- this UPDATE runs as the only command of a separate transaction ...
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+
+-- ... and this one runs in another transaction
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+ </programlisting>
+ </para>
+
+ <para>
+ As mentioned, the primary property of a transaction is its
+ atomicity: either all or none of its operations succeed,
+ regardless of the fact that it may consist of a lot of
+ different write-operations, and each such operation may
+ affect many rows. As soon as one of the
+ operations fails, all previous operations fail also, which
+ means that all modified rows retain their values as of the
+ beginning of the transaction.
+ </para>
+
+ <para>
+ The atomicity also affects the visibility of changes. No
+ connection running simultaneously with a data modifying
+ transaction will ever see any change before the
+ transaction successfully executes a <command>COMMIT</command>
+ — even in the lowest
+ <link linkend="transaction-iso">isolation level</link>
+ of transactions. <productname>PostgreSQL</productname>
+ never shows uncommitted changes to other connections.
+ </para>
+
+ <para>
+ The situation regarding visibility is somewhat different
+ from the point of view of the modifying transaction.
+ A <command>SELECT</command> command issued inside a
+ transaction shows all changes done so far by this
+ transaction.
+ </para>
+
+ <bridgehead renderas="sect2">How does it work?</bridgehead>
+
+ <para>
+ Every <command>INSERT</command>, <command>UPDATE</command>,
+ and <command>DELETE</command> command creates new row
+ versions — according to the MVCC rules. This
+ creates the risk that other transactions may see the
+ new row versions, and after a while and some more
+ activities of the modifying transaction they may see the
+ next row versions. Results would be a kind of 'moving
+ target' in absolute contrast to the all-or-nothing
+ principle.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> overcomes this
+ problem by showing only such row versions to other
+ transactions whose originating transaction is
+ successfully committed. It skips all row versions of
+ uncommitted transactions. And
+ <productname>PostgreSQL</productname> solves one more
+ problem. Even the single <command>COMMIT</command>
+ command needs a short time interval for its execution.
+ Therefore its critical 'dead-or-survival' phase
+ runs in a priviledged mode where it cannot be
+ interrupted by other processes.
+ </para>
+
+ <bridgehead renderas="sect2">What are the benefits?</bridgehead>
+
+ <para>
+ Transactions relieve applications from many standard
+ actions that must be implemented for nearly every use case.
+ </para>
+
+ <para>
+ Business logic often contains strong, but for a computer,
+ relative abstract requirements. The above example shows
+ the transfers of some money from one account to another.
+ It is obvious
+ that the decrease of the one and the increase of the
+ other must be indivisible. Nevertheless, there is no particular
+ need for an application to do something to ensure the
+ <glossterm linkend="glossary-atomicity">atomicity</glossterm>
+ of this behavior. It's enough to surround them with
+ <command>BEGIN</command> and <command>COMMIT</command>.
+ </para>
+
+ <para>
+ Applications often demand the feature of 'undoing'
+ previously taken actions under some application-specific
+ conditions. In such cases, the application simply issues a
+ <command>ROLLBACK</command> command instead of a
+ <command>COMMIT</command>. The <command>ROLLBACK</command>
+ cancels the transaction, and all changes made so far remain
+ invisible forever; it is as if they had never happened. There
+ is no need for the application to log its activities and
+ undo every step of the transaction separately.
+ </para>
+
+ <para>
+ Transactions ensure that the
+ database always remains
+ <glossterm linkend="glossary-consistency">consistent</glossterm>.
+ Declarative rules like
+ <link linkend="ddl-constraints-primary-keys">primary</link>- or
+ <link linkend="ddl-constraints-fk">foreign keys</link>,
+ <link linkend="ddl-constraints-check-constraints">checks</link>,
+ other constraints, or
+ <link linkend="trigger-definition">triggers</link>
+ are part of the all-or-nothing nature of transactions.
+ </para>
+
+ <para>
+ There is the additional feature
+ '<link linkend="transaction-iso">isolation level</link>',
+ which separates transactions from each other in certain ways.
+ It automatically prevents applications from some strange
+ situations.
+ </para>
+
+ <para>
+ Lastly, it is worth noticing that changes done by a
+ committed transaction will survive all failures in the application or
+ database cluster. The next chapter explains the
+ <glossterm linkend="glossary-durability">durability</glossterm>
+ guarantees.
+ </para>
+ </sect1>
+
+ <sect1 id="tutorial-reliability">
+ <title>Reliability</title>
+
+ <para>
+ Nothing is perfect and failures inevitably happen.
+ However, the most common types of failure are
+ well known and <productname>PostgreSQL</productname>
+ implements strategies to overcome them.
+ Such strategies use parts of the previously presented
+ techniques MVCC and transaction-rollback, plus additional
+ features.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the client side</bridgehead>
+ <para>
+ A <glossterm linkend="glossary-client">client</glossterm>
+ can fail in different ways. Its hardware can get damaged,
+ the power supply can fail, the network connection to the
+ server can break, or the client application may run into
+ a severe software error like a null pointer exception.
+ Because <productname>PostgreSQL</productname> uses a
+ client/server architecture, no direct problem for the
+ database will occur. In all of these cases, the
+ <glossterm linkend="glossary-backend">Backend process</glossterm>,
+ which is the client's counterpart at the server-side,
+ may recognize that the network connection is no longer
+ working, or it may run into a timeout after a while. It
+ terminates, and there is no harm to the database. As
+ usual, uncommitted data changes initiated by this client
+ are not visible to any other client.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the server-side</bridgehead>
+
+ <bridgehead renderas="sect3">Instance failure</bridgehead>
+ <para>
+ The instance may suddenly fail because of <emphasis>power off</emphasis>
+ or other problems. This will affect all running processes, the RAM,
+ and possibly the consistency of disk files.
+ </para>
+ <para>
+ After a restart, <productname>PostgreSQL</productname>
+ automatically recognizes that the last shutdown of the
+ instance did not happen as expected: files might not be
+ closed properly and the <literal>postmaster.pid</literal>
+ file unexpectedly exists. <productname>PostgreSQL</productname>
+ tries to clean up the situation. This is possible because
+ all changes in the database are stored twice. First,
+ the WAL files contain them as a chronology of
+ <glossterm linkend="glossary-wal-record">WAL records</glossterm>,
+ which include the new data values and information about commit
+ actions. The WAL records are written first. Second,
+ the data itself shall exist in the heap and index files.
+ In constrast with the WAL records, this part may or may
+ not have been transferred entirely from Shared Memory
+ to the files.
+ </para>
+ <para>
+ The automatic recovery searches within the WAL files for
+ the latest
+ <glossterm linkend="glossary-checkpoint">checkpoint</glossterm>.
+ This checkpoint signals that the database files are in
+ a consistent state, especially that all WAL records up to
+ this point were successfully stored in heap and index files. Starting
+ here, the recovery process copies the remaining WAL records
+ to heap and index. As a result, the heap files contain all
+ changes recorded to the WAL and reach a consistent state. Changes of committed
+ transactions are visible; those of uncommitted transactions
+ are also in the files, but - as usual - they are never seen
+ by any of the following transactions because uncommitted
+ changes are never shown. Such recovery actions run
+ completely automatically, it is not necessary that a
+ database administrator configure or start anything by
+ himself.
+ </para>
+
+ <bridgehead renderas="sect3">Disk crash</bridgehead>
+ <para>
+ If a disk crashes, the course of action described previously
+ cannot work: it is likely that the WAL files and/or the
+ data and index files are no longer available. The
+ database administrator must take special actions to
+ prepare for such a situation.
+ </para>
+ <para>
+ They obviously needs a backup. How to take such a backup
+ and use it as a starting point for a recovery of the
+ cluster is explained in more detail in the next
+ <link linkend="tutorial-backup">chapter</link>.
+ </para>
+
+ <bridgehead renderas="sect3">Disk full</bridgehead>
+ <para>
+ It is conceivable that over time the disk gets full,
+ and there is no room for additional data. In this case,
+ <productname>PostgreSQL</productname> stops accepting
+ data-modifying commands or even terminates completely.
+ Committed data is neither lost nor corrupted.
+ </para>
+ <para>
+ To recover from such a situation, the administrator should
+ remove unused files from this disk. But they should never
+ delete files from the
+ <glossterm linkend="glossary-data-directory">data directory</glossterm>.
+ Nearly all of them are necessary for the consistency
+ of the database.
+ </para>
+
+ <bridgehead renderas="sect2">High availability</bridgehead>
+ <para>
+ Database servers can work together to allow a second
+ server to quickly take over the workload if the
+ primary server fails for whatever reason
+ (<link linkend="high-availability">high availability</link>),
+ or to allow several computers to serve the same data
+ for the purpose of load balancing.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-backup">
+ <title>Backup</title>
+
+ <para>
+ Taking backups is a basic task of database maintenance.
+ <productname>PostgreSQL</productname> supports
+ three different strategies; each has its own
+ strengths and weaknesses.
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ File system level backup
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Logical backup via <command>pg_dump</command>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Continuous archiving based on <command>pg_basebackup</command>
+ and WAL files
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <bridgehead renderas="sect2">File system level backup</bridgehead>
+ <para>
+ You can use any appropriate OS tool to create a
+ <link linkend="backup-file">copy</link>
+ of the cluster's directory structure and files. In
+ case of severe problems such a copy can serve as
+ the source of recovery. But in order to get a
+ <emphasis>USABLE</emphasis> backup by this method,
+ the database server <emphasis>MUST</emphasis> be
+ shut down during the complete runtime of the copy
+ command!
+ </para>
+ <para>
+ The obvious disadvantage of this method is that there
+ is a downtime.
+ The other two strategies run during regular operating
+ times.
+ </para>
+
+ <bridgehead renderas="sect2">Logical backup via pg_dump</bridgehead>
+ <para>
+ The tool <command>pg_dump</command> is able to take a
+ <link linkend="backup-dump">copy</link>
+ of the complete cluster or certain parts of it. It stores
+ the copy in the form of SQL commands like <command>CREATE</command>
+ and <command>COPY</command>. It runs in
+ parallel with other processes in its own transaction.
+ </para>
+ <para>
+ The output of <command>pg_dump</command> may be used as
+ input of <command>psql</command> to restore the data
+ (or to copy it to another database).
+ </para>
+ <para>
+ The main advantage over the other two methods is that it
+ can pick parts of the cluster, e.g., a single table or one
+ database. The other two methods work only at the level of
+ the complete cluster.
+ </para>
+
+ <bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
+ <para>
+ <link linkend="continuous-archiving">This method</link>
+ is the most sophisticated and most complex one. It
+ consists of two phases.
+ </para>
+ <para>
+ First, you need to create a so-called
+ <firstterm>basebackup</firstterm> with the tool
+ <command>pg_basebackup</command>. The result is a
+ directory structure plus files which contain a
+ consistent copy of the original cluster.
+ <command>pg_basebackup</command> runs in
+ parallel with other processes in its own transaction.
+ </para>
+ <para>
+ The second step is recommended but not necessary. All
+ changes to the data are stored in WAL files. If you
+ continuously save such WAL files, you have the history
+ of the cluster. This history can be applied to a
+ basebackup in order to recreate
+ any state of the cluster between the time of
+ <command>pg_basebackup</command>'s start time and
+ any later point in time. This technique
+ is called 'Point-in-Time Recovery (PITR)'.
+ </para>
+ <para>
+ If configured, the
+ <glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
+ will automatically copy every single WAL file to a save location.
+ <link linkend="backup-archiving-wal">Its configuration</link>
+ consists mainly of a string that contains a copy command
+ in the operating system's syntax. In order to protect your
+ data against a disk crash, the destination location
+ of a basebackup as well as of the
+ <firstterm>archived WAL files</firstterm> should be on a
+ disk which is different from the data disk.
+ </para>
+ <para>
+ If it becomes necessary to restore the cluster, you have to
+ copy the basebackup and the archived WAL files to
+ their original directories. The configuration of this
+ <link linkend="backup-pitr-recovery">recovery procedure</link>
+ contains a string with the reverse copy command: from
+ archive location to database location.
+ </para>
+
+ </sect1>
+
+<!-- ToDo: replication, index-types, extension mechanism, ...
+ <sect1 id="tutorial-replication">
+ <title>Replication</title>
+
+ <para>
+...
+ </para>
+
+ </sect1>
+-->
+
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 38e8aa0bbf..7490d3c9c2 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -80,6 +80,7 @@
%allfiles;
<!-- developer's guide -->
+<!ENTITY architecture SYSTEM "architecture.sgml">
<!ENTITY arch-dev SYSTEM "arch-dev.sgml">
<!ENTITY bki SYSTEM "bki.sgml">
<!ENTITY catalogs SYSTEM "catalogs.sgml">
diff --git a/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
new file mode 100644
index 0000000000..7e13753d48
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
@@ -0,0 +1,160 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="685" viewBox="0 0 900 685">
+ <title>
+ Server (Hardware, Container, or VM)
+ </title>
+ <style>
+ .text_normal,.text_small{font-style:normal;font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_small{font-size:12px}.text_normal{font-size:16px}
+ </style>
+ <defs>
+ <symbol id="rectangle_special_0">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="rectangle_special_1">
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="125">
+ 'my_schema' (optional)
+ </text>
+ <text class="text_small" x="20" y="145">
+ tables, views, ...
+ </text>
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="190">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M450 10v230H0V0h440v10h10L440 0"/>
+ </symbol>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="270" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Server (Hardware, Container, or VM)
+ </text>
+ <path stroke="blue" stroke-width="2" fill="none" d="M20 110h790v555H20z"/>
+ <text class="text_normal" x="180" y="25" transform="translate(20 110)">
+ cluster 'data' (default, managed by one instance)
+ </text>
+ <path d="M50 110V80h790v555h-30" stroke="blue" stroke-width="2" fill="none"/>
+ <text class="text_normal" x="190" y="-10" transform="translate(45 110)">
+ cluster 'cluster_2' (optional, managed by a different instance)
+ </text>
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template0'
+ </text>
+ </g>
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template1'
+ </text>
+ </g>
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'my_db' (optional)
+ </text>
+ </g>
+ <g transform="translate(320 330)">
+ <rect width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4"/>
+ <text class="text_normal" x="15" y="27">
+ Global SQL objects
+ </text>
+ <path d="M0 5l-65-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M80 0v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M180 40h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M0 40l-45 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ </g>
+ <g transform="translate(335 405)">
+ <use xlink:href="#note"/>
+ <text class="text_small" x="10" y="20">
+ 1)
+ </text>
+ <text class="text_small" x="30" y="20">
+ By default, you work in the cluster 'data', database 'postgres',
+ </text>
+ <text class="text_small" x="30" y="35">
+ schema 'public'.
+ </text>
+ <text class="text_small" x="10" y="55">
+ 2)
+ </text>
+ <text class="text_small" x="30" y="55">
+ More system schemas: pg_catalog, information_schema,
+ </text>
+ <text class="text_small" x="30" y="70">
+ pg_temp, pg_toast.
+ </text>
+ <text class="text_small" x="10" y="90">
+ 3)
+ </text>
+ <text class="text_small" x="30" y="90">
+ Global SQL objects: Some SQL objects are automatically active
+ </text>
+ <text class="text_small" x="30" y="105">
+ and known database- or even cluster-wide.
+ </text>
+ <text class="text_small" x="10" y="125">
+ 4)
+ </text>
+ <text class="text_small" x="30" y="125">
+ The command 'initdb' creates a new cluster with the three
+ </text>
+ <text class="text_small" x="30" y="140">
+ databases 'template0', 'template1', and 'postgres'. The command
+ </text>
+ <text class="text_small" x="30" y="155">
+ 'createdb' creates a new database.
+ </text>
+ <text class="text_small" x="10" y="175">
+ 5)
+ </text>
+ <text class="text_small" x="30" y="175">
+ If multiple clusters are active on one server at the same time,
+ </text>
+ <text class="text_small" x="30" y="190">
+ each one is managed by an individual instance. Each such instance
+ </text>
+ <text class="text_small" x="30" y="205">
+ uses a different port.
+ </text>
+ <text class="text_small" x="10" y="225">
+ 6)
+ </text>
+ <text class="text_small" x="30" y="225">
+ No client application is allowed to connect to 'template0'.
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink.svg b/doc/src/sgml/images/cluster-db-schema-ink.svg
new file mode 100644
index 0000000000..1fffb9737a
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink.svg
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="685px"
+ viewBox="0 0 900 685"
+ id="svg147"
+ sodipodi:docname="cluster-db-schema-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Server (Hardware, Container, or VM)</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1129"
+ inkscape:window-height="922"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.68905109"
+ inkscape:cx="737.16805"
+ inkscape:cy="342.1375"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Server (Hardware, Container, or VM)</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs49">
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangle_special_0">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect6" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="195"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect8" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text10">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text12">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="195"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect14" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text16">(more system schemas)</text>
+ </symbol>
+ <!-- same as before, but one more schema -->
+ <symbol
+ id="rectangle_special_1">
+ <!-- the database -->
+ <rect
+ width="245"
+ height="225"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect19" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect21" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text23">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text25">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect27" />
+ <text
+ class="text_normal"
+ x="20"
+ y="125"
+ id="text29">'my_schema' (optional)</text>
+ <text
+ class="text_small"
+ x="20"
+ y="145"
+ id="text31">tables, views, ...</text>
+ <rect
+ x="15"
+ y="170"
+ width="205"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect33" />
+ <text
+ class="text_small"
+ x="20"
+ y="190"
+ id="text35">(more system schemas)</text>
+ </symbol>
+ <symbol
+ id="note"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title38">UML Note</title>
+ <path
+ d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10"
+ id="path40" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path43" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path46" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect51" />
+ <text
+ class="text_big"
+ x="270"
+ y="40"
+ id="text53">Server (Hardware, Container, or VM)</text>
+ <!-- two clusters -->
+ <g
+ transform="translate(20 110)"
+ id="g59">
+ <rect
+ x="0"
+ y="0"
+ width="790"
+ height="555"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="rect55" />
+ <text
+ class="text_normal"
+ x="180"
+ y="25"
+ id="text57">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g
+ transform="translate(45 110)"
+ id="g65">
+ <path
+ d="M 5,0 v -30 h 790 v 555 h -30"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="path61" />
+ <text
+ class="text_normal"
+ x="190"
+ y="-10"
+ id="text63">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+ <!-- database template 0 -->
+ <g
+ transform="translate(40 155)"
+ id="g71">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use67" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text69">database 'template0'</text>
+ </g>
+ <!-- database template 1 -->
+ <g
+ transform="translate(290 155)"
+ id="g77">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use73" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text75">database 'template1'</text>
+ </g>
+ <!-- database postgres -->
+ <g
+ transform="translate(540 155)"
+ id="g83">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use79" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text81">database 'postgres'</text>
+ </g>
+ <!-- database my_db -->
+ <g
+ transform="translate(40 350)"
+ id="g89">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use85" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text87">database 'my_db' (optional)</text>
+ </g>
+ <!-- global objects -->
+ <g
+ transform="translate(320 330)"
+ id="g103">
+ <rect
+ x="0"
+ y="0"
+ width="180"
+ height="45"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="10 4 4 4"
+ id="rect91" />
+ <text
+ class="text_normal"
+ x="15"
+ y="27"
+ id="text93">Global SQL objects</text>
+ <path
+ d="M 0,5 l-65,-35"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path95" />
+ <path
+ d="M 80,0 v-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path97" />
+ <path
+ d="M 180,40 h50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path99" />
+ <path
+ d="M 0,40 l-45,20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path101" />
+ </g>
+ <!-- Some comments -->
+ <g
+ transform="translate(335 405)"
+ id="g145">
+ <use
+ xlink:href="#note"
+ x="0"
+ y="0"
+ id="use105" />
+ <text
+ class="text_small"
+ x="10"
+ y="20"
+ id="text107">1)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="20"
+ id="text109">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text
+ class="text_small"
+ x="30"
+ y="35"
+ id="text111">schema 'public'.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="55"
+ id="text113">2)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="55"
+ id="text115">More system schemas: pg_catalog, information_schema,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="70"
+ id="text117">pg_temp, pg_toast.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="90"
+ id="text119">3)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="90"
+ id="text121">Global SQL objects: Some SQL objects are automatically active</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text123">and known database- or even cluster-wide.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="125"
+ id="text125">4)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="125"
+ id="text127">The command 'initdb' creates a new cluster with the three</text>
+ <text
+ class="text_small"
+ x="30"
+ y="140"
+ id="text129">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text
+ class="text_small"
+ x="30"
+ y="155"
+ id="text131">'createdb' creates a new database.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="175"
+ id="text133">5)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="175"
+ id="text135">If multiple clusters are active on one server at the same time,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="190"
+ id="text137">each one is managed by an individual instance. Each such instance</text>
+ <text
+ class="text_small"
+ x="30"
+ y="205"
+ id="text139">uses a different port.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="225"
+ id="text141">6)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="225"
+ id="text143">No client application is allowed to connect to 'template0'.</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
new file mode 100644
index 0000000000..af50c07330
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="685px"
+ viewBox="0 0 900 685" >
+
+ <title>Server (Hardware, Container, or VM)</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_0">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">(more system schemas)</text>
+ </symbol>
+
+ <!-- same as before, but one more schema -->
+ <symbol id="rectangle_special_1">
+ <!-- the database -->
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="125">'my_schema' (optional)</text>
+ <text class="text_small" x="20" y="145">tables, views, ...</text>
+
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="190">(more system schemas)</text>
+ </symbol>
+
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="270" y="40">Server (Hardware, Container, or VM)</text>
+
+ <!-- two clusters -->
+ <g transform="translate(20 110)">
+ <rect x="0" y="0" width="790" height="555" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="180" y="25">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g transform="translate(45 110)">
+ <path d="M 5,0 v -30 h 790 v 555 h -30" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="190" y="-10">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+
+
+ <!-- database template 0 -->
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template0'</text>
+ </g>
+
+ <!-- database template 1 -->
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template1'</text>
+ </g>
+
+ <!-- database postgres -->
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'postgres'</text>
+ </g>
+
+ <!-- database my_db -->
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
+ </g>
+
+ <!-- global objects -->
+ <g transform="translate(320 330)">
+ <rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
+ <text class="text_normal" x="15" y="27">Global SQL objects</text>
+ <path d="M 0,5 l-65,-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ </g>
+
+ <!-- Some comments -->
+ <g transform="translate(335 405)">
+ <use xlink:href="#note" x="0" y="0" />
+
+ <text class="text_small" x="10" y="20">1)</text>
+ <text class="text_small" x="30" y="20">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text class="text_small" x="30" y="35">schema 'public'.</text>
+
+ <text class="text_small" x="10" y="55">2)</text>
+ <text class="text_small" x="30" y="55">More system schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="70">pg_temp, pg_toast.</text>
+
+ <text class="text_small" x="10" y="90">3)</text>
+ <text class="text_small" x="30" y="90">Global SQL objects: Some SQL objects are automatically active</text>
+ <text class="text_small" x="30" y="105">and known database- or even cluster-wide.</text>
+
+ <text class="text_small" x="10" y="125">4)</text>
+ <text class="text_small" x="30" y="125">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="140">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="155">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="175">5)</text>
+ <text class="text_small" x="30" y="175">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="190">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="205">uses a different port.</text>
+
+ <text class="text_small" x="10" y="225">6)</text>
+ <text class="text_small" x="30" y="225">No client application is allowed to connect to 'template0'.</text>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/directories-ink-svgo.svg b/doc/src/sgml/images/directories-ink-svgo.svg
new file mode 100644
index 0000000000..95fa76b9c6
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink-svgo.svg
@@ -0,0 +1,164 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="640" viewBox="0 0 900 640">
+ <title>
+ Directory structure of a cluster
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <symbol id="directory" stroke="blue" stroke-width=".3" fill="aqua">
+ <title>
+ Directory
+ </title>
+ <path d="M0 10h110v20H0z"/>
+ <path d="M0 10V8l3-3h35l3 3v2"/>
+ </symbol>
+ <symbol id="file" stroke="black" fill="none">
+ <title>
+ File
+ </title>
+ <path stroke="blue" d="M0 0h40v50H0z"/>
+ <path d="M5 10h20" stroke-dasharray="4 2"/>
+ <path d="M5 17h15" stroke-dasharray="6 2"/>
+ <path d="M5 24h25" stroke-dasharray="4 2"/>
+ <path d="M5 31h20" stroke-dasharray="5 2"/>
+ </symbol>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="50" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Directory Structure
+ </text>
+ <g transform="translate(20 100)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /pg/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ An arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 130)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ data/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of cluster 'data' (see: PGDATA)
+ </text>
+ </g>
+ <g transform="translate(120 160)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ base/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing per-database subdirectories
+ </text>
+ </g>
+ <g transform="translate(170 190)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 1/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of first database 'template0'
+ </text>
+ </g>
+ <g transform="translate(170 220)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12992/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of second database 'template1'
+ </text>
+ </g>
+ <g transform="translate(170 250)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12999/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of third database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(170 280)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ nnnnn/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Optional: more subdirectories for databases, e.g. 'my_db'
+ </text>
+ </g>
+ <g transform="translate(120 310)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ global/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory with information about Global SQL Objects
+ </text>
+ </g>
+ <g transform="translate(120 340)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_wal/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 370)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_xact/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for transaction commit status ('pg_clog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 400)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_tblspc/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing symbolic links to tablespaces
+ </text>
+ </g>
+ <g transform="translate(120 430)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_... /
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Some more subdirectories
+ </text>
+ </g>
+ <g transform="translate(120 465)">
+ <use xlink:href="#file"/>
+ <use xlink:href="#file" x="50"/>
+ <text x="200" y="26" class="text_normal">
+ 'postmaster.pid' and other files with cluster-wide relevance
+ </text>
+ </g>
+ <g transform="translate(20 540)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /xyz/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ Same or another arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 570)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ cluster_2/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of another cluster 'cluster_2'
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-ink.svg b/doc/src/sgml/images/directories-ink.svg
new file mode 100644
index 0000000000..8151cf583a
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink.svg
@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="640px"
+ viewBox="0 0 900 640"
+ id="svg303"
+ sodipodi:docname="directories-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata307">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Directory structure of a cluster</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1083"
+ inkscape:window-height="808"
+ id="namedview305"
+ showgrid="false"
+ inkscape:zoom="0.36875"
+ inkscape:cx="450"
+ inkscape:cy="320"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg303" />
+ <title
+ id="title153">Directory structure of a cluster</title>
+ <style
+ type="text/css"
+ id="style155">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs177">
+ <!-- Directory -->
+ <symbol
+ id="directory"
+ stroke="blue"
+ stroke-width="0.3px"
+ fill="aqua">
+ <title
+ id="title157">Directory</title>
+ <rect
+ x="0"
+ y="10"
+ width="110"
+ height="20"
+ id="rect159" />
+ <path
+ d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2"
+ id="path161" />
+ </symbol>
+ <!-- File -->
+ <symbol
+ id="file"
+ stroke="black"
+ fill="none">
+ <title
+ id="title164">File</title>
+ <rect
+ x="0"
+ y="0"
+ width="40"
+ height="50"
+ stroke="blue"
+ id="rect166" />
+ <path
+ d="M 5,10 h 20"
+ stroke-dasharray="4 2"
+ id="path168" />
+ <path
+ d="M 5,17 h 15"
+ stroke-dasharray="6 2"
+ id="path170" />
+ <path
+ d="M 5,24 h 25"
+ stroke-dasharray="4 2"
+ id="path172" />
+ <path
+ d="M 5,31 h 20"
+ stroke-dasharray="5 2"
+ id="path174" />
+ </symbol>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect179" />
+ <!-- caption -->
+ <text
+ x="200"
+ y="50"
+ class="text_big"
+ id="text181">Directory Structure</text>
+ <!-- the directories -->
+ <g
+ transform="translate(20, 100)"
+ id="g189">
+ <use
+ xlink:href="#directory"
+ id="use183" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text185">... /pg/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text187">An arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 130)"
+ id="g197">
+ <use
+ xlink:href="#directory"
+ id="use191" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text193">data/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text195">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+ <g
+ transform="translate(120, 160)"
+ id="g205">
+ <use
+ xlink:href="#directory"
+ id="use199" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text201">base/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text203">Subdirectory containing per-database subdirectories</text>
+ </g>
+ <!-- -->
+ <g
+ transform="translate(170, 190)"
+ id="g213">
+ <use
+ xlink:href="#directory"
+ id="use207" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text209">1/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text211">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g
+ transform="translate(170, 220)"
+ id="g221">
+ <use
+ xlink:href="#directory"
+ id="use215" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text217">12992/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text219">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g
+ transform="translate(170, 250)"
+ id="g229">
+ <use
+ xlink:href="#directory"
+ id="use223" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text225">12999/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text227">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g
+ transform="translate(170, 280)"
+ id="g237">
+ <use
+ xlink:href="#directory"
+ id="use231" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text233">nnnnn/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text235">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+ <g
+ transform="translate(120, 310)"
+ id="g245">
+ <use
+ xlink:href="#directory"
+ id="use239" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text241">global/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text243">Subdirectory with information about Global SQL Objects</text>
+ </g>
+ <g
+ transform="translate(120, 340)"
+ id="g253">
+ <use
+ xlink:href="#directory"
+ id="use247" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text249">pg_wal/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text251">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 370)"
+ id="g261">
+ <use
+ xlink:href="#directory"
+ id="use255" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text257">pg_xact/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text259">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 400)"
+ id="g269">
+ <use
+ xlink:href="#directory"
+ id="use263" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text265">pg_tblspc/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text267">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+ <g
+ transform="translate(120, 430)"
+ id="g277">
+ <use
+ xlink:href="#directory"
+ id="use271" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text273">pg_... /</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text275">Some more subdirectories</text>
+ </g>
+ <g
+ transform="translate(120, 465)"
+ id="g285">
+ <use
+ xlink:href="#file"
+ x="0"
+ y="0"
+ id="use279" />
+ <use
+ xlink:href="#file"
+ x="50"
+ y="0"
+ id="use281" />
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text283">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+ <!-- next cluster -->
+ <g
+ transform="translate(20, 540)"
+ id="g293">
+ <use
+ xlink:href="#directory"
+ id="use287" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text289">... /xyz/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text291">Same or another arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 570)"
+ id="g301">
+ <use
+ xlink:href="#directory"
+ id="use295" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text297">cluster_2/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text299">Root of another cluster 'cluster_2'</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
new file mode 100644
index 0000000000..6d16a03169
--- /dev/null
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="640px"
+ viewBox="0 0 900 640">
+
+ <title>Directory structure of a cluster</title>
+
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Directory -->
+ <symbol id="directory" stroke="blue" stroke-width="0.3px" fill="aqua">
+ <title>Directory</title>
+ <rect x="0" y="10" width="110" height="20" />
+ <path d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2" />
+ </symbol>
+
+ <!-- File -->
+ <symbol id="file" stroke="black" fill="none" >
+ <title>File</title>
+ <rect x="0" y="0" width="40" height="50" stroke="blue" />
+ <path d="M 5,10 h 20" stroke-dasharray="4 2" />
+ <path d="M 5,17 h 15" stroke-dasharray="6 2" />
+ <path d="M 5,24 h 25" stroke-dasharray="4 2" />
+ <path d="M 5,31 h 20" stroke-dasharray="5 2" />
+ </symbol>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption -->
+ <text x="200" y="50" class="text_big">Directory Structure</text>
+
+ <!-- the directories -->
+ <g transform="translate(20, 100)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /pg/</text>
+ <text x="300" y="26" class="text_normal">An arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 130)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">data/</text>
+ <text x="250" y="26" class="text_normal">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+
+ <g transform="translate(120, 160)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">base/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing per-database subdirectories</text>
+ </g>
+
+ <!-- -->
+ <g transform="translate(170, 190)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">1/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g transform="translate(170, 220)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12992/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g transform="translate(170, 250)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12999/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g transform="translate(170, 280)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">nnnnn/</text>
+ <text x="150" y="26" class="text_normal">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+
+ <g transform="translate(120, 310)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">global/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory with information about Global SQL Objects</text>
+ </g>
+
+ <g transform="translate(120, 340)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 370)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 400)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+
+ <g transform="translate(120, 430)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_... /</text>
+ <text x="200" y="26" class="text_normal">Some more subdirectories</text>
+ </g>
+
+ <g transform="translate(120, 465)">
+ <use xlink:href="#file" x="0" y="0" />
+ <use xlink:href="#file" x="50" y="0" />
+ <text x="200" y="26" class="text_normal">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+
+ <!-- next cluster -->
+ <g transform="translate(20, 540)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /xyz/</text>
+ <text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 570)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster 'cluster_2'</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink-svgo.svg b/doc/src/sgml/images/freeze-ink-svgo.svg
new file mode 100644
index 0000000000..6fedfb7633
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink-svgo.svg
@@ -0,0 +1,84 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="320" viewBox="0 0 850 320">
+ <title>
+ Freeze
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100)"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="70" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ <tspan font-style="italic" font-weight="700">Freeze</tspan> to keep visible
+ </text>
+ <g fill="none" transform="translate(170 190)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_120" startOffset="11.2%">(1)</textPath> <textPath xlink:href="#Path_120" startOffset="61.2%">(5)</textPath> <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%">|</textPath> <textPath xlink:href="#Path_120" startOffset="34%">(2)</textPath> <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(3)</textPath> <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%">|</textPath> <textPath xlink:href="#Path_120" startOffset="55%">(4)</textPath>
+ </text>
+ <path d="M-80-80L80 80" stroke="black"/>
+ <text class="text_normal" letter-spacing="12" transform="rotate(45 40.78 -38.1)">
+ PAST
+ </text>
+ <text class="text_normal" letter-spacing="12" transform="rotate(-135 27.43 23.79)">
+ FUTURE
+ </text>
+ <use xlink:href="#frozenPoint" transform="rotate(10)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(25)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(40)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(55)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(70)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(85)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(100)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(115)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(130)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(145)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(160)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(175)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(190)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(205)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(220)"/>
+ </g>
+ <g class="text_normal" transform="translate(380 30)">
+ <text>
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25">
+ 1: txid_current + 2 ^ 31 (split-point)
+ </text>
+ <text y="50">
+ 2: autovacuum_freeze_max_age (200 mio.)
+ </text>
+ <text y="75">
+ 3: vacuum_freeze_table_age (150 mio.)
+ </text>
+ <text y="100">
+ 4: vacuum_freeze_min_age (50 mio.)
+ </text>
+ <text y="125">
+ 5: txid_current (split-point, jungest xid)
+ </text>
+ <text y="155">
+ per table: pg_class.relfrozenxid <tspan font-weight="700">must</tspan> be between (1) and (5);
+ </text>
+ <text y="175" x="75">
+ normally it is between (3) and (4)
+ </text>
+ <use xlink:href="#unfrozenPoint" transform="translate(106 200)"/>
+ <text y="205" x="20">
+ Unfrozen xid
+ </text>
+ <use xlink:href="#frozenPoint" transform="translate(106 224)"/>
+ <text y="230" x="20">
+ Frozen xid
+ </text>
+ <text y="260">
+ (figure is out of scale)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink.svg b/doc/src/sgml/images/freeze-ink.svg
new file mode 100644
index 0000000000..009cfe4b41
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink.svg
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="320px"
+ viewBox="0 0 850 320"
+ id="svg454"
+ sodipodi:docname="freeze-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata458">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Freeze</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="979"
+ inkscape:window-height="857"
+ id="namedview456"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="160"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg454" />
+ <title
+ id="title309">Freeze</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style311">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs318">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle
+ id="frozenPoint"
+ r="3"
+ stroke="green"
+ fill="green"
+ transform="translate(-100, 0)" />
+ <circle
+ id="unfrozenPoint"
+ r="3"
+ stroke="green"
+ fill="none"
+ transform="translate(-100, 0)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect320" />
+ <text
+ class="text_big"
+ x="70"
+ y="40"
+ id="text324"><tspan
+ style="font-style:italic;font-weight:bold"
+ id="tspan322">
+ Freeze</tspan>
+ to keep visible</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 190)"
+ id="g418">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle326" />
+ <text
+ class="text_normal"
+ id="text350">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath328">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath330">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath332">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="11.2%"
+ id="textPath334">(1)</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="61.2%"
+ id="textPath336">(5)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="red"
+ stroke-width="3"
+ startOffset="34%"
+ id="textPath338">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="34%"
+ id="textPath340">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="black"
+ stroke-width="3"
+ startOffset="45%"
+ id="textPath342">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath344">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="green"
+ stroke-width="3"
+ startOffset="55%"
+ id="textPath346">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="55%"
+ id="textPath348">(4)</textPath>
+ </text>
+ <!-- split it into 'past' and 'future' -->
+ <path
+ d="M -80 -80 l 160 160"
+ stroke="black"
+ id="path352" />
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(-15, -40) rotate(45)"
+ id="text354">PAST</text>
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(30, 60) rotate(225)"
+ id="text356">FUTURE</text>
+ <g
+ transform="rotate(10)"
+ id="g360">
+ <use
+ xlink:href="#frozenPoint"
+ id="use358" />
+ </g>
+ <g
+ transform="rotate(25)"
+ id="g364">
+ <use
+ xlink:href="#frozenPoint"
+ id="use362" />
+ </g>
+ <g
+ transform="rotate(40)"
+ id="g368">
+ <use
+ xlink:href="#frozenPoint"
+ id="use366" />
+ </g>
+ <g
+ transform="rotate(55)"
+ id="g372">
+ <use
+ xlink:href="#frozenPoint"
+ id="use370" />
+ </g>
+ <g
+ transform="rotate(70)"
+ id="g376">
+ <use
+ xlink:href="#frozenPoint"
+ id="use374" />
+ </g>
+ <g
+ transform="rotate(85)"
+ id="g380">
+ <use
+ xlink:href="#frozenPoint"
+ id="use378" />
+ </g>
+ <g
+ transform="rotate(100)"
+ id="g384">
+ <use
+ xlink:href="#frozenPoint"
+ id="use382" />
+ </g>
+ <g
+ transform="rotate(115)"
+ id="g388">
+ <use
+ xlink:href="#frozenPoint"
+ id="use386" />
+ </g>
+ <g
+ transform="rotate(130)"
+ id="g392">
+ <use
+ xlink:href="#frozenPoint"
+ id="use390" />
+ </g>
+ <g
+ transform="rotate(145)"
+ id="g396">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use394" />
+ </g>
+ <g
+ transform="rotate(160)"
+ id="g400">
+ <use
+ xlink:href="#frozenPoint"
+ id="use398" />
+ </g>
+ <g
+ transform="rotate(175)"
+ id="g404">
+ <use
+ xlink:href="#frozenPoint"
+ id="use402" />
+ </g>
+ <g
+ transform="rotate(190)"
+ id="g408">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use406" />
+ </g>
+ <g
+ transform="rotate(205)"
+ id="g412">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use410" />
+ </g>
+ <g
+ transform="rotate(220)"
+ id="g416">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use414" />
+ </g>
+ </g>
+ <!-- legend -->
+ <g
+ class="text_normal"
+ transform="translate(380 30)"
+ id="g452">
+ <text
+ id="text424">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan420">^</tspan>
+<tspan
+ dy="5"
+ id="tspan422">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text426">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text
+ y="50"
+ id="text428">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text
+ y="75"
+ id="text430">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text
+ y="100"
+ id="text432">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text
+ y="125"
+ id="text434">5: txid_current (split-point, jungest xid)</text>
+ <text
+ y="155"
+ id="text438">per table: pg_class.relfrozenxid
+ <tspan
+ style="font-weight:bold"
+ id="tspan436">must</tspan>
+ be between (1) and (5);</text>
+ <text
+ y="175"
+ x="75"
+ id="text440">normally it is between (3) and (4)</text>
+ <use
+ xlink:href="#unfrozenPoint"
+ transform="translate(106, 200)"
+ id="use442" />
+ <text
+ y="205"
+ x="20"
+ id="text444">Unfrozen xid</text>
+ <use
+ xlink:href="#frozenPoint"
+ transform="translate(106, 224)"
+ id="use446" />
+ <text
+ y="230"
+ x="20"
+ id="text448">Frozen xid</text>
+ <text
+ y="260"
+ id="text450">(figure is out of scale)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-raw.svg b/doc/src/sgml/images/freeze-raw.svg
new file mode 100644
index 0000000000..2d1d256184
--- /dev/null
+++ b/doc/src/sgml/images/freeze-raw.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="320px"
+ viewBox="0 0 850 320" >
+
+ <title>Freeze</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100, 0)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100, 0)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="70" y="40"><tspan style="font-style:italic;font-weight:bold">
+ Freeze</tspan> to keep visible</text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 190)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_120" startOffset="11.2%" >(1)</textPath>
+ <textPath xlink:href="#Path_120" startOffset="61.2%" >(5)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="34%" >(2)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(3)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="55%" >(4)</textPath>
+
+ </text>
+
+ <!-- split it into 'past' and 'future' -->
+ <path d="M -80 -80 l 160 160" stroke="black" />
+ <text class="text_normal" letter-spacing="12" transform="translate(-15, -40) rotate(45)">PAST</text>
+ <text class="text_normal" letter-spacing="12" transform="translate(30, 60) rotate(225)">FUTURE</text>
+
+ <g transform="rotate(10)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(25)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(40)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(55)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(70)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(85)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(100)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(115)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(130)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(145)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(160)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(175)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(190)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(205)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(220)"><use xlink:href="#unfrozenPoint"/></g>
+
+ </g>
+
+ <!-- legend -->
+ <g class="text_normal" transform="translate(380 30)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text y="50">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text y="75">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text y="100">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text y="125">5: txid_current (split-point, jungest xid)</text>
+ <text y="155">per table: pg_class.relfrozenxid
+ <tspan style="font-weight:bold">must</tspan> be between (1) and (5);</text>
+ <text y="175" x="75">normally it is between (3) and (4)</text>
+
+ <use xlink:href="#unfrozenPoint" transform="translate(106, 200)"/>
+ <text y="205" x="20">Unfrozen xid</text>
+
+ <use xlink:href="#frozenPoint" transform="translate(106, 224)"/>
+ <text y="230" x="20">Frozen xid</text>
+
+ <text y="260">(figure is out of scale)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
new file mode 100644
index 0000000000..26bce6176d
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
@@ -0,0 +1,83 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="720" height="430" viewBox="0 0 720 430">
+ <title>
+ Hierarchy of Internal Objects
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Hierarchy of internal Objects
+ </text>
+ <g fill="none">
+ <g transform="translate(350 240)">
+ <ellipse rx="320" ry="170" stroke="blue"/>
+ <text class="text_normal" x="-140" y="-130">
+ Cluster
+ </text>
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-60" y="5">
+ Database Names
+ </text>
+ </g>
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-40" y="5">
+ Tablespace
+ </text>
+ </g>
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-70" y="5">
+ Replication Origins
+ </text>
+ </g>
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue"/>
+ <text class="text_normal" x="-60" y="-3">
+ Subscription for
+ </text>
+ <text class="text_normal" x="-68" y="10">
+ Logical Replication
+ </text>
+ </g>
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-15" y="5">
+ Role
+ </text>
+ </g>
+ </g>
+ <g transform="translate(270 250)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2"/>
+ <text class="text_normal" x="-60" y="-80">
+ Database
+ </text>
+ <g transform="translate(-150 -30)">
+ <ellipse rx="50" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Extension
+ </text>
+ </g>
+ <g transform="translate(-155 35)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Collation
+ </text>
+ </g>
+ <g transform="translate(30 20)">
+ <ellipse rx="140" ry="70" stroke="blue"/>
+ <text class="text_normal" x="-80" y="-35">
+ Schema
+ </text>
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue"/>
+ <text class="text_normal" x="-50" y="5">
+ Table, View, ...
+ </text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
new file mode 100644
index 0000000000..e5745818d9
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="720px"
+ height="430px"
+ viewBox="0 0 720 430"
+ id="svg540"
+ sodipodi:docname="internal-objects-hierarchy-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata546">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Hierarchy of Internal Objects</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs544" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1050"
+ inkscape:window-height="838"
+ id="namedview542"
+ showgrid="false"
+ inkscape:zoom="0.51944444"
+ inkscape:cx="360"
+ inkscape:cy="215"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg540" />
+ <title
+ id="title460">Hierarchy of Internal Objects</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style462">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect464" />
+ <text
+ class="text_big"
+ x="200"
+ y="40"
+ id="text466">Hierarchy of internal Objects</text>
+ <!-- set centre of figure and default values -->
+ <g
+ transform="translate(350 240)"
+ fill="none"
+ id="g538">
+ <g
+ id="g504">
+ <ellipse
+ rx="320"
+ ry="170"
+ stroke="blue"
+ id="ellipse468" />
+ <text
+ class="text_normal"
+ x="-140"
+ y="-130"
+ id="text470">Cluster</text>
+ <g
+ transform="translate(40 -125)"
+ id="g476">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse472" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="5"
+ id="text474">Database Names</text>
+ </g>
+ <g
+ transform="translate(180 -70)"
+ id="g482">
+ <ellipse
+ rx="60"
+ ry="20"
+ stroke="blue"
+ id="ellipse478" />
+ <text
+ class="text_normal"
+ x="-40"
+ y="5"
+ id="text480">Tablespace</text>
+ </g>
+ <g
+ transform="translate(230 -5)"
+ id="g488">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse484" />
+ <text
+ class="text_normal"
+ x="-70"
+ y="5"
+ id="text486">Replication Origins</text>
+ </g>
+ <g
+ transform="translate(200 70)"
+ id="g496">
+ <ellipse
+ rx="78"
+ ry="27"
+ stroke="blue"
+ id="ellipse490" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-3"
+ id="text492">Subscription for</text>
+ <text
+ class="text_normal"
+ x="-68"
+ y="10"
+ id="text494">Logical Replication</text>
+ </g>
+ <g
+ transform="translate(100 120)"
+ id="g502">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse498" />
+ <text
+ class="text_normal"
+ x="-15"
+ y="5"
+ id="text500">Role</text>
+ </g>
+ </g>
+ <g
+ transform="translate(-80 10)"
+ id="g536">
+ <ellipse
+ rx="220"
+ ry="110"
+ stroke="blue"
+ stroke-width="2px"
+ id="ellipse506" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-80"
+ id="text508">Database</text>
+ <g
+ transform="translate(-120 -50)"
+ id="g534">
+ <g
+ transform="translate(-30 20)"
+ id="g514">
+ <ellipse
+ rx="50"
+ ry="20"
+ stroke="blue"
+ id="ellipse510" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text512">Extension</text>
+ </g>
+ <g
+ transform="translate(-35 85)"
+ id="g520">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse516" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text518">Collation</text>
+ </g>
+ <g
+ transform="translate(150 70)"
+ id="g532">
+ <ellipse
+ rx="140"
+ ry="70"
+ stroke="blue"
+ id="ellipse522" />
+ <text
+ class="text_normal"
+ x="-80"
+ y="-35"
+ id="text524">Schema</text>
+ <g
+ transform="translate(20 10)"
+ id="g530">
+ <ellipse
+ rx="90"
+ ry="30"
+ stroke="blue"
+ id="ellipse526" />
+ <text
+ class="text_normal"
+ x="-50"
+ y="5"
+ id="text528">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
new file mode 100644
index 0000000000..f0dc890f6b
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="720px" height="430px"
+ viewBox="0 0 720 430" >
+
+ <title>Hierarchy of Internal Objects</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="200" y="40">Hierarchy of internal Objects</text>
+
+
+ <!-- set centre of figure and default values -->
+ <g transform="translate(350 240)" fill="none">
+
+ <g>
+ <ellipse rx="320" ry="170" stroke="blue" />
+ <text class="text_normal" x="-140" y="-130">Cluster</text>
+
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-60" y="5">Database Names</text>
+ </g>
+
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue" />
+ <text class="text_normal" x="-40" y="5">Tablespace</text>
+ </g>
+
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-70" y="5">Replication Origins</text>
+ </g>
+
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue" />
+ <text class="text_normal" x="-60" y="-3">Subscription for</text>
+ <text class="text_normal" x="-68" y="10">Logical Replication</text>
+ </g>
+
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-15" y="5">Role</text>
+ </g>
+
+ </g>
+
+ <g transform="translate(-80 10)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2px" />
+ <text class="text_normal" x="-60" y="-80">Database</text>
+
+ <g transform="translate(-120 -50)">
+ <g transform="translate(-30 20)">
+ <ellipse rx="50" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Extension</text>
+ </g>
+
+ <g transform="translate(-35 85)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Collation</text>
+ </g>
+
+ <g transform="translate(150 70)">
+ <ellipse rx="140" ry="70" stroke="blue" />
+ <text class="text_normal" x="-80" y="-35">Schema</text>
+
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue" />
+ <text class="text_normal" x="-50" y="5">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink-svgo.svg b/doc/src/sgml/images/mvcc-ink-svgo.svg
new file mode 100644
index 0000000000..8e67da93d1
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink-svgo.svg
@@ -0,0 +1,151 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="150" viewBox="0 0 850 150">
+ <title>
+ MVCC
+ </title>
+ <style>
+ .text_small{font-style:normal;font-weight:400;font-size:10px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <marker id="triangle_1" markerWidth="10" markerHeight="10" refX="5" refY="5" orient="auto" stroke="black" fill="none">
+ <path d="M0 0l10 5-10 5"/>
+ </marker>
+ <path id="arrow" d="M0 0q20-15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+ <g id="tuple" stroke="black">
+ <path d="M80 0H0v20h80M29 0v20M60 0v20"/>
+ <path d="M80 0h15M80 20h15" stroke-dasharray="2 1"/>
+ </g>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <g fill="none">
+ <g transform="translate(20 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">123</tspan> <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)" fill="#00f">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 83)" fill="#00f">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(185 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">135</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 53)" fill="#00f">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(350 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">142</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 23)" fill="#00f">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(515 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">821</tspan> <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 821
+ </text>
+ <text class="text_small" transform="translate(125 23)">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(740 110)">
+ <path d="M102-20H-18v60" stroke="black"/>
+ <text font-weight="400" font-size="16" font-family=""Open Sans",sans-serif" fill="#000">
+ Legend
+ </text>
+ <use xlink:href="#tuple" transform="translate(0 10)"/>
+ <text class="text_small" transform="translate(3 23)">
+ xmin
+ </text>
+ <text class="text_small" transform="translate(32 23)">
+ xmax
+ </text>
+ <text class="text_small" transform="translate(65 23)">
+ data
+ </text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink.svg b/doc/src/sgml/images/mvcc-ink.svg
new file mode 100644
index 0000000000..f4161b3e79
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink.svg
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="150px"
+ viewBox="0 0 850 150"
+ id="svg147"
+ sodipodi:docname="mvcc-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>MVCC</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1256"
+ inkscape:window-height="801"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="75"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">MVCC</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs15">
+ <marker
+ id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto"
+ stroke="black"
+ fill="none">
+ <path
+ d="M 0,0 L 10,5 L 0,10"
+ id="path6" />
+ </marker>
+ <g
+ id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path
+ d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20"
+ stroke="black"
+ id="path9" />
+ <!-- prolong the rectangle -->
+ <path
+ d="M 80 0 h 15 M 80 20 h 15"
+ stroke="black"
+ stroke-dasharray="2 1"
+ id="path11" />
+ </g>
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path
+ id="arrow"
+ d="M 0 0 Q 20 -15 40 0"
+ stroke="black"
+ marker-end="url(#triangle_1)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect17" />
+ <!-- set default values -->
+ <g
+ fill="none"
+ id="g145">
+ <!-- start plus first INSERT -->
+ <g
+ transform="translate(20, 40)"
+ id="g35">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text23">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan19">123</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan21">: INSERT</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use25" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use27" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ style="fill:blue"
+ id="text29">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text31">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ style="fill:blue"
+ id="text33">'x'</text>
+ </g>
+ <!-- first UPDATE -->
+ <g
+ transform="translate(185, 40)"
+ id="g61">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text41">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan37">135</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan39">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use43" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use45" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ style="fill:blue"
+ id="text47">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text49">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ style="fill:blue"
+ id="text51">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use53" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text55">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text57">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text59">'x'</text>
+ </g>
+ <!-- next UPDATE -->
+ <g
+ transform="translate(350, 40)"
+ id="g95">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text67">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan63">142</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan65">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use69" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use71" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ style="fill:blue"
+ id="text73">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text75">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ style="fill:blue"
+ id="text77">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use79" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text81">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text83">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text85">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use87" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text89">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text91">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text93">'x'</text>
+ </g>
+ <!-- DELETE -->
+ <g
+ transform="translate(515, 40)"
+ id="g129">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text101">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan97">821</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan99">: DELTE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use103" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use105" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text107">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text109">821</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ id="text111">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use113" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text115">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ id="text117">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text119">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use121" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text123">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text125">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text127">'x'</text>
+ </g>
+ <!-- LEGEND -->
+ <g
+ transform="translate(740, 110)"
+ id="g143">
+ <path
+ d="M 102 -20 h -120 v 60"
+ stroke="black"
+ id="path131" />
+ <text
+ class="text_normal"
+ transform="translate(0, 0)"
+ id="text133">Legend</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(0, 10)"
+ id="use135" />
+ <text
+ class="text_small"
+ transform="translate(3, 23)"
+ id="text137">xmin</text>
+ <text
+ class="text_small"
+ transform="translate(32, 23)"
+ id="text139">xmax</text>
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text141">data</text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-raw.svg b/doc/src/sgml/images/mvcc-raw.svg
new file mode 100644
index 0000000000..0481c4c938
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-raw.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="150px"
+ viewBox="0 0 850 150" >
+
+ <title>MVCC</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <marker id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto" stroke="black" fill="none">
+ <path d="M 0,0 L 10,5 L 0,10" />
+ </marker>
+
+ <g id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20" stroke="black"/>
+ <!-- prolong the rectangle -->
+ <path d="M 80 0 h 15 M 80 20 h 15" stroke="black" stroke-dasharray="2 1"/>
+ </g>
+
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path id="arrow" d="M 0 0 Q 20 -15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- set default values -->
+ <g fill="none">
+
+ <!-- start plus first INSERT -->
+ <g transform="translate(20, 40)">
+
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">123</tspan>
+ <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)" style="fill:blue">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 83)" style="fill:blue">'x'</text>
+ </g>
+
+ <!-- first UPDATE -->
+ <g transform="translate(185, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">135</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 53)" style="fill:blue">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- next UPDATE -->
+ <g transform="translate(350, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">142</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 23)" style="fill:blue">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- DELETE -->
+ <g transform="translate(515, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">821</tspan>
+ <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">821</text>
+ <text class="text_small" transform="translate(125, 23)">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- LEGEND -->
+ <g transform="translate(740, 110)">
+ <path d="M 102 -20 h -120 v 60" stroke="black"/>
+ <text class="text_normal" transform="translate(0, 0)">Legend</text>
+ <use xlink:href="#tuple" transform="translate(0, 10)"/>
+ <text class="text_small" transform="translate(3, 23)">xmin</text>
+ <text class="text_small" transform="translate(32, 23)">xmax</text>
+ <text class="text_small" transform="translate(65, 23)">data</text>
+ </g>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink-svgo.svg b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
new file mode 100644
index 0000000000..723d67bd8d
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
@@ -0,0 +1,285 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 900 600">
+ <title>
+ PG Overall Server Architecture
+ </title>
+ <style>
+ .text_big{font-style:normal}.text_big,.text_comment,.text_normal,.text_small{font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_normal,.text_small{font-style:normal}.text_small{font-size:12px}.text_normal{font-size:16px}.text_big{font-size:24px}.text_comment{font-style:italic;font-size:16px}
+ </style>
+ <defs>
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (200 x 20 px)
+ </title>
+ <path d="M200 10v10H0V0h190v10h10L190 0"/>
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (250 x 20 px)
+ </title>
+ <path d="M250 10v10H0V0h240v10h10L240 0"/>
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (100 x 35 px)
+ </title>
+ <path d="M100 10v25H0V0h90v10h10L90 0"/>
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (170 x 50 px)
+ </title>
+ <path d="M170 10v40H0V0h160v10h10L160 0"/>
+ </symbol>
+ <symbol id="state_300x120">
+ <title>
+ UML State (300x120)
+ </title>
+ <rect width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>
+ UML State (350x120)
+ </title>
+ <rect width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="disc" stroke="blue" fill="none">
+ <title>
+ Disc
+ </title>
+ <ellipse cx="51" cy="13" rx="50" ry="12"/>
+ <path d="M1 13v60"/>
+ <path d="M101 13v60"/>
+ <path d="M1 73a50 12 0 00100 0"/>
+ </symbol>
+ <symbol id="laptop" stroke="black" fill="none">
+ <title>
+ Laptop
+ </title>
+ <path d="M20 40V0h54v40l15 15H5l15-15h54"/>
+ <path d="M23 3h48v34H23z"/>
+ <path d="M30 10h20"/>
+ <path d="M30 15h25"/>
+ <path d="M30 20h10"/>
+ <path d="M30 30h20"/>
+ <path d="M25 50h45l2 2H22z"/>
+ </symbol>
+ <marker id="arrowhead_start" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto">
+ <path d="M6 0L0 3l6 3" stroke="black" fill="none"/>
+ </marker>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="15" y="40" class="text_big">
+ Client
+ </text>
+ <text x="140" y="40" class="text_big">
+ Server
+ </text>
+ <use xlink:href="#laptop" x="5" y="210"/>
+ <g transform="translate(130 70)">
+ <use xlink:href="#state_350x120"/>
+ <text x="5" y="20" class="text_normal">
+ maintenance_work_mem (per connection)
+ </text>
+ <text x="5" y="45" class="text_normal">
+ work_mem (per query operation)
+ </text>
+ <text x="5" y="70" class="text_normal">
+ autovacuum_work_mem (per worker process)
+ </text>
+ <text x="5" y="95" class="text_normal">
+ temp_buffer (per connection)
+ </text>
+ <text x="5" y="110" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_200x20" x="140" y="-15"/>
+ <text x="150" class="text_comment">
+ Individual Memory
+ </text>
+ </g>
+ <g transform="translate(520 70)">
+ <use xlink:href="#state_300x120"/>
+ <text x="10" y="30" class="text_normal">
+ shared_buffers (heap and index)
+ </text>
+ <text x="10" y="70" class="text_normal">
+ wal_buffers (WAL records)
+ </text>
+ <text x="10" y="100" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_250x20" x="40" y="-15"/>
+ <text x="50" class="text_comment">
+ Shared Memory (per Instance)
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M180 215h250v30H180z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(180 215)">
+ Postmaster
+ </text>
+ <path d="M90 230h75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 230)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 1
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M150 315h370v30H150z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(150 315)">
+ Backend processes (one per connection)
+ </text>
+ <path d="M155 315v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M160 310v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M90 240l63 63" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 290)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 3
+ </text>
+ </g>
+ <path d="M360 250v50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180 255)">
+ <use xlink:href="#note_250x20"/>
+ <text x="10" y="15" class="text_comment">
+ Creates backend processes
+ </text>
+ </g>
+ <g transform="translate(360 281)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 2
+ </text>
+ </g>
+ <path d="M460 300V200" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M498 300V95h30" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M508 300V135h20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M550 220h120v30H550z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(550 220)">
+ WAL Writer
+ </text>
+ <path d="M590 150v65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M590 255v230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 340h140v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 340)">
+ Checkpointer
+ </text>
+ <path d="M740 110v220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 355H475v130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M700 330V150" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50"/>
+ <text x="60" y="-35" class="text_comment">
+ Checkpoint
+ </text>
+ <text x="60" y="-20" class="text_comment">
+ Record
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M610 380h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 380)">
+ Background Writer
+ </text>
+ <path d="M770 110v260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 395H485v90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 420h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 420)">
+ WAL Archiver
+ </text>
+ <path d="M620 485l30-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M690 455l30 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M135 380h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 380)">
+ Autovacuum
+ </text>
+ <path d="M140 380v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path d="M145 375v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path stroke="blue" fill="none" d="M135 430h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 430)">
+ Logger
+ </text>
+ <path stroke="blue" fill="none" d="M290 370h140v30H290z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(290 370)">
+ Stats Collector
+ </text>
+ <g transform="translate(145 490)">
+ <use xlink:href="#disc"/>
+ <text x="35" y="45" class="text_normal">
+ Log
+ </text>
+ <text x="20" y="60" class="text_small">
+ text lines,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <path d="M195 465v20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(410 490)">
+ <use xlink:href="#disc"/>
+ <text x="10" y="40" class="text_normal">
+ Heap and
+ </text>
+ <text x="25" y="55" class="text_normal">
+ Index
+ </text>
+ <text x="15" y="70" class="text_small">
+ binary blocks,
+ </text>
+ <text x="30" y="80" class="text_small">
+ random
+ </text>
+ </g>
+ <path d="M450 485V350" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(295 420)">
+ <use xlink:href="#note_170x50"/>
+ <text x="5" y="15" class="text_comment">
+ Read heap and index
+ </text>
+ <text x="5" y="30" class="text_comment">
+ pages and transfer
+ </text>
+ <text x="5" y="45" class="text_comment">
+ them to shared_buffers
+ </text>
+ </g>
+ <g transform="translate(550 490)">
+ <use xlink:href="#disc"/>
+ <text x="30" y="45" class="text_normal">
+ WAL
+ </text>
+ <text x="10" y="60" class="text_small">
+ binary records,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <g transform="translate(690 490)">
+ <use xlink:href="#disc"/>
+ <text x="16" y="45" class="text_normal">
+ Archived
+ </text>
+ <text x="36" y="60" class="text_normal">
+ WAL
+ </text>
+ </g>
+ <path d="M110 20v550" stroke="black" fill="none"/>
+ <g transform="rotate(90 -33.5 156.5)">
+ <use xlink:href="#note_200x20"/>
+ <text class="text_comment" x="10" y="15">
+ Via TCP/IP or socket
+ </text>
+ </g>
+ <text class="text_big" x="95" transform="rotate(90 425 425)">
+ RAM
+ </text>
+ <text class="text_big" x="250" transform="rotate(90 425 425)">
+ PROCESSES
+ </text>
+ <text class="text_big" x="500" transform="rotate(90 425 425)">
+ FILES
+ </text>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink.svg b/doc/src/sgml/images/ram-proc-file-ink.svg
new file mode 100644
index 0000000000..4490bf51e1
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink.svg
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="600px"
+ viewBox="0 0 900 600"
+ id="svg306"
+ sodipodi:docname="ram-proc-file-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata310">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>PG Overall Server Architecture</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1048"
+ inkscape:window-height="771"
+ id="namedview308"
+ showgrid="false"
+ inkscape:zoom="0.39333333"
+ inkscape:cx="450"
+ inkscape:cy="300"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg306" />
+ <title
+ id="title2">PG Overall Server Architecture</title>
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs70">
+ <!-- Some notes in different sizes -->
+ <symbol
+ id="note_200x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title6">UML Note (200 x 20 px)</title>
+ <path
+ d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10"
+ id="path8" />
+ </symbol>
+ <symbol
+ id="note_250x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title11">UML Note (250 x 20 px)</title>
+ <path
+ d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10"
+ id="path13" />
+ </symbol>
+ <symbol
+ id="note_100x35"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title16">UML Note (100 x 35 px)</title>
+ <path
+ d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10"
+ id="path18" />
+ </symbol>
+ <symbol
+ id="note_170x50"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title21">UML Note (170 x 50 px)</title>
+ <path
+ d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10"
+ id="path23" />
+ </symbol>
+ <!-- UML states (used for buffers) -->
+ <symbol
+ id="state_300x120">
+ <title
+ id="title26">UML State (300x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="300"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect28" />
+ </symbol>
+ <symbol
+ id="state_350x120">
+ <title
+ id="title31">UML State (350x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="350"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect33" />
+ </symbol>
+ <!-- Discs -->
+ <symbol
+ id="disc"
+ stroke="blue"
+ fill="none">
+ <title
+ id="title36">Disc</title>
+ <ellipse
+ cx="51"
+ cy="13"
+ rx="50"
+ ry="12"
+ id="ellipse38" />
+ <!-- top -->
+ <path
+ d="M 1,13 v 60"
+ id="path40" />
+ <!-- left -->
+ <path
+ d="M 101,13 v 60"
+ id="path42" />
+ <!-- right -->
+ <path
+ d="M 1,73 A 50, 12, 0, 0, 0, 101,73"
+ id="path44" />
+ <!-- bottom -->
+ </symbol>
+ <!-- Laptop -->
+ <symbol
+ id="laptop"
+ stroke="black"
+ fill="none">
+ <title
+ id="title47">Laptop</title>
+ <path
+ d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54"
+ id="path49" />
+ <rect
+ x="23"
+ y="3"
+ width="48"
+ height="34"
+ id="rect51" />
+ <!-- symbolize some lines -->
+ <path
+ d="M 30,10 h 20"
+ id="path53" />
+ <path
+ d="M 30,15 h 25"
+ id="path55" />
+ <path
+ d="M 30,20 h 10"
+ id="path57" />
+ <path
+ d="M 30,30 h 20"
+ id="path59" />
+ <!-- symbolize keyboard -->
+ <path
+ d="M 25,50 h 45 l 2,2 h -50 z "
+ id="path61" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path64" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path67" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect72" />
+ <!-- caption, client side -->
+ <text
+ x="15"
+ y="40"
+ class="text_big"
+ id="text74">Client</text>
+ <text
+ x="140"
+ y="40"
+ class="text_big"
+ id="text76">Server</text>
+ <use
+ xlink:href="#laptop"
+ x="5"
+ y="210"
+ id="use78" />
+ <!-- individual memory -->
+ <g
+ transform="translate(130, 70)"
+ id="g96">
+ <use
+ xlink:href="#state_350x120"
+ x="0"
+ y="0"
+ id="use80" />
+ <text
+ x="5"
+ y="20"
+ class="text_normal"
+ id="text82">maintenance_work_mem (per connection)</text>
+ <text
+ x="5"
+ y="45"
+ class="text_normal"
+ id="text84">work_mem (per query operation)</text>
+ <text
+ x="5"
+ y="70"
+ class="text_normal"
+ id="text86">autovacuum_work_mem (per worker process)</text>
+ <text
+ x="5"
+ y="95"
+ class="text_normal"
+ id="text88">temp_buffer (per connection)</text>
+ <text
+ x="5"
+ y="110"
+ class="text_normal"
+ id="text90">...</text>
+ <use
+ xlink:href="#note_200x20"
+ x="140"
+ y="-15"
+ id="use92" />
+ <text
+ x="150"
+ y="0"
+ class="text_comment"
+ id="text94">Individual Memory</text>
+ </g>
+ <!-- shared memory -->
+ <g
+ transform="translate(520, 70)"
+ id="g110">
+ <use
+ xlink:href="#state_300x120"
+ x="0"
+ y="0"
+ id="use98" />
+ <text
+ x="10"
+ y="30"
+ class="text_normal"
+ id="text100">shared_buffers (heap and index)</text>
+ <text
+ x="10"
+ y="70"
+ class="text_normal"
+ id="text102">wal_buffers (WAL records)</text>
+ <text
+ x="10"
+ y="100"
+ class="text_normal"
+ id="text104">...</text>
+ <use
+ xlink:href="#note_250x20"
+ x="40"
+ y="-15"
+ id="use106" />
+ <text
+ x="50"
+ y="0"
+ class="text_comment"
+ id="text108">Shared Memory (per Instance)</text>
+ </g>
+ <!-- postmaster -->
+ <g
+ transform="translate(180, 215)"
+ id="g116">
+ <rect
+ width="250"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect112" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text114">Postmaster</text>
+ </g>
+ <path
+ d="M 90,230 h 75"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path118" />
+ <g
+ transform="translate(140, 230)"
+ id="g124">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle120" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text122">1</text>
+ </g>
+ <!-- backend processes -->
+ <g
+ transform="translate(150, 315)"
+ id="g134">
+ <rect
+ width="370"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect126" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text128">Backend processes (one per connection)</text>
+ <path
+ d="M 5,0 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path130" />
+ <path
+ d="M 10,-5 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path132" />
+ </g>
+ <path
+ d="M 90,240 153,303"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path136" />
+ <g
+ transform="translate(140, 290)"
+ id="g142">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle138" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text140">3</text>
+ </g>
+ <!-- connection between postmaster and backend processes -->
+ <path
+ d="M 360,250 v 50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path144" />
+ <g
+ transform="translate(180, 255)"
+ id="g150">
+ <use
+ xlink:href="#note_250x20"
+ id="use146" />
+ <text
+ x="10"
+ y="15"
+ class="text_comment"
+ id="text148">Creates backend processes</text>
+ </g>
+ <g
+ transform="translate(360, 281)"
+ id="g156">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle152" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text154">2</text>
+ </g>
+ <!-- backend process' access to individual memory -->
+ <path
+ d="M 460,300 v -100"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path158" />
+ <!-- its access to shared buffers and WAL buffers -->
+ <path
+ d="M 498,300 v -205 h 30"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path160" />
+ <path
+ d="M 508,300 v -165 h 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path162" />
+ <!-- WAL writer -->
+ <g
+ transform="translate(550, 220)"
+ id="g168">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect164" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text166">WAL Writer</text>
+ </g>
+ <path
+ d="M 590,150 v 65"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path170" />
+ <path
+ d="M 590,255 v 230"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path172" />
+ <!-- Checkpoiner -->
+ <g
+ transform="translate(610, 340)"
+ id="g178">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect174" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text176">Checkpointer</text>
+ </g>
+ <path
+ d="M 740,110 v 220"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path180" />
+ <path
+ d="M 605,355 h -130 v 130"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path182" />
+ <path
+ d="M 700,330 v -180"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path184" />
+ <g
+ transform="translate(570, 330)"
+ id="g192">
+ <use
+ xlink:href="#note_100x35"
+ x="50"
+ y="-50"
+ id="use186" />
+ <text
+ x="60"
+ y="-35"
+ class="text_comment"
+ id="text188">Checkpoint</text>
+ <text
+ x="60"
+ y="-20"
+ class="text_comment"
+ id="text190">Record</text>
+ </g>
+ <!-- BG writer -->
+ <g
+ transform="translate(610, 380)"
+ id="g198">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect194" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text196">Background Writer</text>
+ </g>
+ <path
+ d="M 770,110 v 260"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path200" />
+ <path
+ d="M 605,395 h -120 v 90"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path202" />
+ <!-- Archiver -->
+ <g
+ transform="translate(610, 420)"
+ id="g208">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect204" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text206">WAL Archiver</text>
+ </g>
+ <path
+ d="M 620,485 l 30,-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path210" />
+ <path
+ d="M 690,455 l 30, 30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path212" />
+ <!-- Vacuum -->
+ <g
+ transform="translate(135, 380)"
+ id="g222">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect214" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text216">Autovacuum</text>
+ <path
+ d="M 5,0 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path218" />
+ <path
+ d="M 10,-5 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path220" />
+ </g>
+ <!-- Log Writer -->
+ <g
+ transform="translate(135, 430)"
+ id="g228">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect224" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text226">Logger</text>
+ </g>
+ <!-- Stats Collector -->
+ <g
+ transform="translate(290, 370)"
+ id="g234">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect230" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text232">Stats Collector</text>
+ </g>
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g
+ transform="translate(145, 490)"
+ id="g244">
+ <use
+ xlink:href="#disc"
+ id="use236" />
+ <text
+ x="35"
+ y="45"
+ class="text_normal"
+ id="text238">Log</text>
+ <text
+ x="20"
+ y="60"
+ class="text_small"
+ id="text240">text lines,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text242">sequential</text>
+ </g>
+ <path
+ d="M 195,465 v 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path246" />
+ <g
+ transform="translate(410, 490)"
+ id="g258">
+ <use
+ xlink:href="#disc"
+ id="use248" />
+ <text
+ x="10"
+ y="40"
+ class="text_normal"
+ id="text250">Heap and</text>
+ <text
+ x="25"
+ y="55"
+ class="text_normal"
+ id="text252">Index</text>
+ <text
+ x="15"
+ y="70"
+ class="text_small"
+ id="text254">binary blocks,</text>
+ <text
+ x="30"
+ y="80"
+ class="text_small"
+ id="text256">random</text>
+ </g>
+ <path
+ d="M 450,485 v -135"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path260" />
+ <g
+ transform="translate(295, 420)"
+ id="g270">
+ <use
+ xlink:href="#note_170x50"
+ id="use262" />
+ <text
+ x="5"
+ y="15"
+ class="text_comment"
+ id="text264">Read heap and index</text>
+ <text
+ x="5"
+ y="30"
+ class="text_comment"
+ id="text266">pages and transfer</text>
+ <text
+ x="5"
+ y="45"
+ class="text_comment"
+ id="text268">them to shared_buffers</text>
+ </g>
+ <g
+ transform="translate(550, 490)"
+ id="g280">
+ <use
+ xlink:href="#disc"
+ id="use272" />
+ <text
+ x="30"
+ y="45"
+ class="text_normal"
+ id="text274">WAL</text>
+ <text
+ x="10"
+ y="60"
+ class="text_small"
+ id="text276">binary records,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text278">sequential</text>
+ </g>
+ <g
+ transform="translate(690, 490)"
+ id="g288">
+ <use
+ xlink:href="#disc"
+ id="use282" />
+ <text
+ x="16"
+ y="45"
+ class="text_normal"
+ id="text284">Archived</text>
+ <text
+ x="36"
+ y="60"
+ class="text_normal"
+ id="text286">WAL</text>
+ </g>
+ <!-- boarder between client and server side -->
+ <path
+ d="M 110,20 v 550"
+ stroke="black"
+ fill="none"
+ id="path290" />
+ <g
+ transform="translate(123, 190) rotate(90)"
+ id="g296">
+ <use
+ xlink:href="#note_200x20"
+ id="use292" />
+ <text
+ class="text_comment"
+ x="10"
+ y="15"
+ id="text294">Via TCP/IP or socket</text>
+ </g>
+ <!-- right side -->
+ <g
+ transform="translate(850, 0) rotate(90)"
+ id="g304">
+ <text
+ class="text_big"
+ x="95"
+ id="text298">RAM</text>
+ <text
+ class="text_big"
+ x="250"
+ id="text300">PROCESSES</text>
+ <text
+ class="text_big"
+ x="500"
+ id="text302">FILES</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-raw.svg b/doc/src/sgml/images/ram-proc-file-raw.svg
new file mode 100644
index 0000000000..aec5811c54
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-raw.svg
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="600px"
+ viewBox="0 0 900 600">
+
+ <title>PG Overall Server Architecture</title>
+
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Some notes in different sizes -->
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>UML Note (200 x 20 px)</title>
+ <path d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>UML Note (250 x 20 px)</title>
+ <path d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>UML Note (100 x 35 px)</title>
+ <path d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>UML Note (170 x 50 px)</title>
+ <path d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- UML states (used for buffers) -->
+ <symbol id="state_300x120">
+ <title>UML State (300x120)</title>
+ <rect x="0" y="0" width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>UML State (350x120)</title>
+ <rect x="0" y="0" width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- Discs -->
+ <symbol id="disc" stroke="blue" fill="none" >
+ <title>Disc</title>
+ <ellipse cx="51" cy="13" rx="50" ry="12" /> <!-- top -->
+ <path d="M 1,13 v 60" /> <!-- left -->
+ <path d="M 101,13 v 60" /> <!-- right -->
+ <path d="M 1,73 A 50, 12, 0, 0, 0, 101,73" /> <!-- bottom -->
+ </symbol>
+
+ <!-- Laptop -->
+ <symbol id="laptop" stroke="black" fill="none" >
+ <title>Laptop</title>
+ <path d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54" />
+ <rect x="23" y="3" width="48" height="34" />
+ <!-- symbolize some lines -->
+ <path d="M 30,10 h 20" />
+ <path d="M 30,15 h 25" />
+ <path d="M 30,20 h 10" />
+ <path d="M 30,30 h 20" />
+ <!-- symbolize keyboard -->
+ <path d="M 25,50 h 45 l 2,2 h -50 z " />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption, client side -->
+ <text x="15" y="40" class="text_big">Client</text>
+ <text x="140" y="40" class="text_big">Server</text>
+ <use xlink:href="#laptop" x="5" y="210" />
+
+
+ <!-- individual memory -->
+ <g transform="translate(130, 70)">
+ <use xlink:href="#state_350x120" x="0" y="0" />
+ <text x="5" y="20" class="text_normal">maintenance_work_mem (per connection)</text>
+ <text x="5" y="45" class="text_normal">work_mem (per query operation)</text>
+ <text x="5" y="70" class="text_normal">autovacuum_work_mem (per worker process)</text>
+ <text x="5" y="95" class="text_normal">temp_buffer (per connection)</text>
+ <text x="5" y="110" class="text_normal">...</text>
+ <use xlink:href="#note_200x20" x="140" y="-15" />
+ <text x="150" y="0" class="text_comment">Individual Memory</text>
+ </g>
+
+ <!-- shared memory -->
+ <g transform="translate(520, 70)">
+ <use xlink:href="#state_300x120" x="0" y="0" />
+ <text x="10" y="30" class="text_normal">shared_buffers (heap and index)</text>
+ <text x="10" y="70" class="text_normal">wal_buffers (WAL records)</text>
+ <text x="10" y="100" class="text_normal">...</text>
+ <use xlink:href="#note_250x20" x="40" y="-15" />
+ <text x="50" y="0" class="text_comment">Shared Memory (per Instance)</text>
+ </g>
+
+ <!-- postmaster -->
+ <g transform="translate(180, 215)">
+ <rect width="250" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Postmaster</text>
+ </g>
+ <path d="M 90,230 h 75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 230)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">1</text>
+ </g>
+
+ <!-- backend processes -->
+ <g transform="translate(150, 315)">
+ <rect width="370" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Backend processes (one per connection)</text>
+ <path d="M 5,0 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <path d="M 90,240 153,303" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 290)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">3</text>
+ </g>
+
+ <!-- connection between postmaster and backend processes -->
+ <path d="M 360,250 v 50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180, 255)">
+ <use xlink:href="#note_250x20" />
+ <text x="10" y="15" class="text_comment">Creates backend processes</text>
+ </g>
+ <g transform="translate(360, 281)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">2</text>
+ </g>
+
+ <!-- backend process' access to individual memory -->
+ <path d="M 460,300 v -100" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <!-- its access to shared buffers and WAL buffers -->
+ <path d="M 498,300 v -205 h 30" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M 508,300 v -165 h 20" stroke="black" fill="none"
+ marker-end="url(#arrowhead_end)"/>
+
+ <!-- WAL writer -->
+ <g transform="translate(550, 220)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Writer</text>
+ </g>
+ <path d="M 590,150 v 65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 590,255 v 230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Checkpoiner -->
+ <g transform="translate(610, 340)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Checkpointer</text>
+ </g>
+ <path d="M 740,110 v 220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,355 h -130 v 130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 700,330 v -180" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570, 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50" />
+ <text x="60" y="-35" class="text_comment">Checkpoint</text>
+ <text x="60" y="-20" class="text_comment">Record</text>
+ </g>
+
+ <!-- BG writer -->
+ <g transform="translate(610, 380)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Background Writer</text>
+ </g>
+ <path d="M 770,110 v 260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,395 h -120 v 90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Archiver -->
+ <g transform="translate(610, 420)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Archiver</text>
+ </g>
+ <path d="M 620,485 l 30,-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 690,455 l 30, 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Vacuum -->
+ <g transform="translate(135, 380)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Autovacuum</text>
+ <path d="M 5,0 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <!-- Log Writer -->
+ <g transform="translate(135, 430)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Logger</text>
+ </g>
+
+ <!-- Stats Collector -->
+ <g transform="translate(290, 370)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Stats Collector</text>
+ </g>
+
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g transform="translate(145, 490)">
+ <use xlink:href="#disc" />
+ <text x="35" y="45" class="text_normal">Log</text>
+ <text x="20" y="60" class="text_small">text lines,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+ <path d="M 195,465 v 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(410, 490)">
+ <use xlink:href="#disc" />
+ <text x="10" y="40" class="text_normal">Heap and</text>
+ <text x="25" y="55" class="text_normal">Index</text>
+ <text x="15" y="70" class="text_small">binary blocks,</text>
+ <text x="30" y="80" class="text_small">random</text>
+ </g>
+ <path d="M 450,485 v -135" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(295, 420)">
+ <use xlink:href="#note_170x50" />
+ <text x="5" y="15" class="text_comment">Read heap and index</text>
+ <text x="5" y="30" class="text_comment">pages and transfer</text>
+ <text x="5" y="45" class="text_comment">them to shared_buffers</text>
+ </g>
+
+ <g transform="translate(550, 490)">
+ <use xlink:href="#disc" />
+ <text x="30" y="45" class="text_normal">WAL</text>
+ <text x="10" y="60" class="text_small">binary records,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+
+ <g transform="translate(690, 490)">
+ <use xlink:href="#disc" />
+ <text x="16" y="45" class="text_normal">Archived</text>
+ <text x="36" y="60" class="text_normal">WAL</text>
+ </g>
+
+ <!-- boarder between client and server side -->
+ <path d="M 110,20 v 550" stroke="black" fill="none" />
+ <g transform="translate(123, 190) rotate(90)">
+ <use xlink:href="#note_200x20" />
+ <text class="text_comment" x="10" y ="15">Via TCP/IP or socket</text>
+ </g>
+
+ <!-- right side -->
+ <g transform="translate(850, 0) rotate(90)">
+ <text class="text_big" x="95">RAM</text>
+ <text class="text_big" x="250">PROCESSES</text>
+ <text class="text_big" x="500">FILES</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink-svgo.svg b/doc/src/sgml/images/wraparound-ink-svgo.svg
new file mode 100644
index 0000000000..9882d2be23
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink-svgo.svg
@@ -0,0 +1,40 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="280" viewBox="0 0 850 280">
+ <title>
+ Cyclic usage of XIDs
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:16px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="370" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ Cyclic usage of XIDs modulo 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan>
+ </text>
+ <g fill="none" transform="translate(170 150)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_095" startOffset="30.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="30%">(1)</textPath> <textPath xlink:href="#Path_095" startOffset="45.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(2)</textPath> <textPath xlink:href="#Path_095" startOffset="50.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="50%">(3)</textPath> <textPath xlink:href="#Path_095" startOffset="62.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="62%">(4)</textPath>
+ </text>
+ </g>
+ <g class="text_normal">
+ <text transform="translate(400 130)">
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25" transform="translate(400 130)">
+ 1: oldest <tspan font-weight="700">active</tspan> xid (pg_stat_activity.backend_xmin)
+ </text>
+ <text y="50" transform="translate(400 130)">
+ 2: xmin of one row version
+ </text>
+ <text y="75" transform="translate(400 130)">
+ 3: xmax of the same row version
+ </text>
+ <text y="100" transform="translate(400 130)">
+ 4: jungest xid (txid_current)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink.svg b/doc/src/sgml/images/wraparound-ink.svg
new file mode 100644
index 0000000000..a9c51f4e43
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="280px"
+ viewBox="0 0 850 280"
+ id="svg1072"
+ sodipodi:docname="wraparound-ink.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ <metadata
+ id="metadata1076">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Cyclic usage of XIDs</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1193"
+ inkscape:window-height="788"
+ id="namedview1074"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="140"
+ inkscape:window-x="61"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg1072" />
+ <title
+ id="title1009">Cyclic usage of XIDs</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style1011">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs1016">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect1018" />
+ <text
+ class="text_big"
+ x="370"
+ y="40"
+ id="text1024">Cyclic usage of XIDs modulo 2
+ <tspan
+ dy="-5"
+ id="tspan1020">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1022">32</tspan>
+</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 150)"
+ id="g1052">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle1026" />
+ <text
+ class="text_normal"
+ id="text1050">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath1028">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath1030">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath1032">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="30.5%"
+ id="textPath1034">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="30%"
+ id="textPath1036">(1)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="45.5%"
+ id="textPath1038">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath1040">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="50.5%"
+ id="textPath1042">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="50%"
+ id="textPath1044">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="62.5%"
+ id="textPath1046">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="62%"
+ id="textPath1048">(4)</textPath>
+ </text>
+ </g>
+ <g
+ class="text_normal"
+ transform="translate(400 130)"
+ id="g1070">
+ <text
+ id="text1058">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan1054">^</tspan>
+<tspan
+ dy="5"
+ id="tspan1056">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text1062">1: oldest <tspan
+ style="font-weight:bold"
+ id="tspan1060">active</tspan>
+ xid (pg_stat_activity.backend_xmin)</text>
+ <text
+ y="50"
+ id="text1064">2: xmin of one row version</text>
+ <text
+ y="75"
+ id="text1066">3: xmax of the same row version</text>
+ <text
+ y="100"
+ id="text1068">4: jungest xid (txid_current)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-raw.svg b/doc/src/sgml/images/wraparound-raw.svg
new file mode 100644
index 0000000000..9406f52970
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-raw.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="280px"
+ viewBox="0 0 850 280" >
+
+ <title>Cyclic usage of XIDs</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:16px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="370" y="40">Cyclic usage of XIDs modulo 2
+ <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan></text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 150)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_095" startOffset="30.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="30%" >(1)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="45.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(2)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="50.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="50%" >(3)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="62.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="62%" >(4)</textPath>
+ </text>
+ </g>
+
+ <g class="text_normal" transform="translate(400 130)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: oldest <tspan style="font-weight:bold">active</tspan> xid (pg_stat_activity.backend_xmin)</text>
+ <text y="50">2: xmin of one row version</text>
+ <text y="75">3: xmax of the same row version</text>
+ <text y="100">4: jungest xid (txid_current)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 730d5fdc34..e9e9f9495f 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -248,6 +248,7 @@ break is not needed in a wider output rendering.
</para>
</partintro>
+ &architecture;
&arch-dev;
&catalogs;
&protocol;
diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml
index 9bb5c1a6d5..abb61445f2 100644
--- a/doc/src/sgml/start.sgml
+++ b/doc/src/sgml/start.sgml
@@ -53,7 +53,7 @@
<sect1 id="tutorial-arch">
- <title>Architectural Fundamentals</title>
+ <title>Client/Server Model</title>
<para>
Before we proceed, you should understand the basic
@@ -68,34 +68,52 @@
client/server model. A <productname>PostgreSQL</productname>
session consists of the following cooperating processes
(programs):
+ </para>
- <itemizedlist>
- <listitem>
- <para>
- A server process, which manages the database files, accepts
- connections to the database from client applications, and
- performs database actions on behalf of the clients. The
- database server program is called
- <filename>postgres</filename>.
- <indexterm><primary>postgres</primary></indexterm>
- </para>
- </listitem>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A process at the server site with the name
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ <indexterm><primary>postgres</primary></indexterm>
+ <indexterm><primary>postmaster</primary></indexterm>
+ It accepts connection requests from client applications, starts
+ (<quote>forks</quote>) a new <glossterm linkend="glossary-backend">
+ Backend</glossterm> process for each of them, and passes
+ the connection to it. From that point on, the client and the new
+ Backend process communicate directly without intervention by the original
+ Postmaster process. Thus, the Postmaster process is always running,
+ waiting for new client connections, whereas clients and associated
+ Backend processes come and go. (All of this is of course invisible
+ to the user. We only mention it here for completeness.)
+ </para>
+ </listitem>
- <listitem>
- <para>
- The user's client (frontend) application that wants to perform
- database operations. Client applications can be very diverse
- in nature: a client could be a text-oriented tool, a graphical
- application, a web server that accesses the database to
- display web pages, or a specialized database maintenance tool.
- Some client applications are supplied with the
- <productname>PostgreSQL</productname> distribution; most are
- developed by users.
- </para>
- </listitem>
+ <listitem>
+ <para>
+ A group of processes at the server site, the <glossterm
+ linkend="glossary-instance">Instance</glossterm>, to which also
+ the Postmaster process belongs. Their duties are handling of
+ central, common database activities like file access, transaction
+ handling, vacuum, checkpoints, replication, and more. The mentioned
+ Backend processes delegate those actions to the instance.
+ </para>
+ </listitem>
- </itemizedlist>
- </para>
+ <listitem>
+ <para>
+ The user's client (frontend) application that wants to perform
+ database operations. Client applications can be very diverse
+ in nature: a client could be a text-oriented tool, a graphical
+ application, a web server that accesses the database to
+ display web pages, or a specialized database maintenance tool.
+ Some client applications are supplied with the
+ <productname>PostgreSQL</productname> distribution; most are
+ developed by users.
+ </para>
+ </listitem>
+
+ </itemizedlist>
<para>
As is typical of client/server applications, the client and the
@@ -106,18 +124,6 @@
file name) on the database server machine.
</para>
- <para>
- The <productname>PostgreSQL</productname> server can handle
- multiple concurrent connections from clients. To achieve this it
- starts (<quote>forks</quote>) a new process for each connection.
- From that point on, the client and the new server process
- communicate without intervention by the original
- <filename>postgres</filename> process. Thus, the
- supervisor server process is always running, waiting for
- client connections, whereas client and associated server processes
- come and go. (All of this is of course invisible to the user. We
- only mention it here for completeness.)
- </para>
</sect1>
0010-architecture-vs-0009.patchtext/x-patch; charset=UTF-8; name=0010-architecture-vs-0009.patchDownload
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
index e547a87d08..0c663a9d80 100644
--- a/doc/src/sgml/architecture.sgml
+++ b/doc/src/sgml/architecture.sgml
@@ -19,19 +19,18 @@
In the case of <productname>PostgreSQL</productname>, the server
launches a single process for each client connection, referred to as a
<glossterm linkend="glossary-backend">Backend</glossterm> process.
- Those Backend processes handle the client's requests by acting on the
+ Such a Backend process handles the client's requests by acting on the
<glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>.
This leads to other activities (file access, WAL, vacuum, ...) of the
<glossterm linkend="glossary-instance">Instance</glossterm>. The
Instance is a group of server-side processes acting on a common
- Shared Memory. Notably, PostgreSQL does not utilize application
- threading within its implementation.
+ Shared Memory. PostgreSQL does not utilize threading.
</para>
<para>
- The first step in an Instance start is the start of the
+ The first step when an Instance starts is the start of the
<glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
- He loads the configuration files, allocates Shared Memory, and
+ It loads the configuration files, allocates Shared Memory, and
starts the other processes of the Instance:
<glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
<glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
@@ -66,32 +65,31 @@
<para>
When a client application tries to connect to a
<glossterm linkend="glossary-database">database</glossterm>,
- this request is handled initially by the Postmaster. He
- starts a new Backend process and instructs the client
- application to connect to it. All further client requests
- go to this process and are handled by it.
+ this request is handled initially by the Postmaster. It
+ starts a new Backend process, which handles all further
+ client's requests.
</para>
<para>
Client requests like <command>SELECT</command> or
<command>UPDATE</command> usually lead to the
- necessity to read or write some data. This is carried out
+ necessity to read or write data. This is carried out
by the client's backend process. Reads involve a page-level
- cache housed in Shared Memory (for details see:
+ cache, located in Shared Memory (for details see:
<xref linkend="sysvipc"/>) for the benefit of all processes
- in the instance. Writes also involve this cache, in additional
+ in the instance. Writes also use this cache, in addition
to a journal, called a write-ahead-log or WAL.
</para>
<para>
- Shared Memory is limited in size. Thus, it becomes necessary
+ Shared Memory is limited in size and it can become necessary
to evict pages. As long as the content of such pages hasn't
changed, this is not a problem. But in Shared Memory also
write actions take place. Modified pages are called dirty
pages or dirty buffers and before they can be evicted they
- must be written back to disk. This happens regularly by the
- Background Writer and the Checkpointer process to ensure
- that the disk version of the pages are kept up-to-date.
+ must be written to disk. This happens regularly by the
+ Checkpointer and the Background Writer processes to ensure
+ that the disk version of the pages are up-to-date.
The synchronisation from RAM to disk consists of two steps.
</para>
@@ -109,7 +107,7 @@
Shared Memory. The parallel running WAL Writer process
reads them and appends them to the end of the current
<glossterm linkend="glossary-wal-record">WAL file</glossterm>.
- Such sequential writes are much faster than writes to random
+ Such sequential writes are faster than writes to random
positions of heap and index files. All WAL records created
out of one dirty page must be transferred to disk before the
dirty page itself can be transferred to disk in the second step.
@@ -119,35 +117,36 @@
Second, the transfer of dirty buffers from Shared Memory to
files must take place. This is the primary task of the
Background Writer process. Because I/O activities can block
- other processes significantly, it starts periodically and
+ other processes, it starts periodically and
acts only for a short period. Doing so, its extensive (and
expensive) I/O activities are spread over time, avoiding
- debilitating I/O peaks. Also, the Checkpointer process
- transfers dirty buffers to file.
+ debilitating I/O peaks. The Checkpointer process
+ also transfers dirty buffers to file.
</para>
<para>
- The Checkpointer creates
+ The Checkpointer process creates
<glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
A Checkpoint is a point in time when all older dirty buffers,
all older WAL records, and finally a special Checkpoint record
- have been written and flushed to disk. Heap and index files
+ are written and flushed to disk. Heap and index files
on the one hand and WAL files on the other hand are in sync.
Previous WAL is no longer required. In other words,
a possibly occurring recovery, which integrates the delta
information of WAL into heap and index files, will happen
- by replaying only WAL past the last recorded checkpoint
- on top of the current heap and files. This speeds up recovery.
+ by replaying only WAL past the last recorded checkpoint.
+ This limits the amount of WAL which needs to be replayed
+ during recovery in the event of a crash.
</para>
<para>
- While the Checkpointer ensures that a running system can crash
+ While the Checkpointer ensures that the database system can crash
and restart itself in a valid state, the administrator needs
- to handle the case where the heap and files themselves become
+ to handle the case where the heap or other files become
corrupted (and possibly the locally written WAL, though that is
less common). The options and details are covered extensively
in the backup and restore section (<xref linkend="backup"/>).
- For our purposes here, note just that the WAL Archiver process
+ For our purposes here, just note that the WAL Archiver process
can be enabled and configured to run a script on filled WAL
files — usually to copy them to a remote location.
</para>
@@ -159,7 +158,7 @@
-->
<para>
- The Statistics Collector collects counters about accesses to
+ The Statistics Collector collects counters about access to
SQL objects like tables, rows, indexes, pages, and more. It
stores the obtained information in system tables.
</para>
@@ -234,13 +233,13 @@
<para>
Every database must contain at least one schema because all
<glossterm linkend="glossary-sql-object">SQL Objects</glossterm>
- are contained in a schema.
- Schemas are namespaces for their SQL objects and ensure
- (with one exception) that within their scope names are used
- only once across all types of SQL objects. E.g., it is not possible
+ must be contained in a schema.
+ Schemas are namespaces for SQL objects and ensure
+ (with one exception) that the SQL object names are used only once within
+ their scope across all types of SQL objects. E.g., it is not possible
to have a table <literal>employee</literal> and a view
<literal>employee</literal> within the same schema. But it is
- possible to have two tables <literal>employee</literal> in
+ possible to have two tables <literal>employee</literal> in two
different schemas. In this case, the two tables
are separate objects and independent of each
other. The only exception to this cross-type uniqueness is that
@@ -273,7 +272,7 @@
<firstterm>Global SQL Objects</firstterm>, are outside of the
strict hierarchy: All <firstterm>database names</firstterm>,
all <firstterm>tablespace names</firstterm>, and all
- <firstterm>role names</firstterm> are automatically known and
+ <firstterm>role names</firstterm> are automatically
available throughout the cluster, independent from
the database or schema in which they where defined originally.
<xref linkend="tutorial-internal-objects-hierarchy-figure"/>
@@ -302,7 +301,7 @@
<title>The physical Perspective: Directories and Files</title>
<para>
- <productname>PostgreSQL</productname> organizes long-lasting
+ <productname>PostgreSQL</productname> organizes long-lasting (persistent)
data as well as volatile state information about transactions
or replication actions in the file system. Every
<xref linkend="glossary-db-cluster"/> has its root directory
@@ -352,27 +351,26 @@
every table and every index to store heap and index
data. Those files are accompanied by files for the
<link linkend="storage-fsm">Free Space Maps</link>
- (extension <literal>_fsm</literal>) and
+ (suffixed <literal>_fsm</literal>) and
<link linkend="storage-vm">Visibility Maps</link>
- (extension <literal>_vm</literal>), which contain optimization information.
+ (suffixed <literal>_vm</literal>), which contain optimization information.
</para>
<para>
- Another subdirectory is <literal>global</literal>.
- In analogy to the database-specific
- subdirectories, there are files containing information about
+ Another subdirectory is <literal>global</literal> which
+ contains files with information about
<glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
One type of such Global SQL Objects are
<glossterm linkend="glossary-tablespace">tablespaces</glossterm>.
In <literal>global</literal> there is information about
- the tablespaces, not the tablespaces themselves.
+ the tablespaces; not the tablespaces themselves.
</para>
<para>
The subdirectory <literal>pg_wal</literal> contains the
<glossterm linkend="glossary-wal-file">WAL files</glossterm>.
- They arise and grow parallel to data changes in the
- cluster and remain alive as long as
+ They arise and grow in parallel with data changes in the
+ cluster and remain as long as
they are required for recovery, archiving, or replication.
</para>
@@ -385,18 +383,18 @@
<para>
In <literal>pg_tblspc</literal>, there are symbolic links
- that point to directories containing such SQL objects
- that are created within tablespaces.
+ that point to directories containing SQL objects
+ that exist within a non-default tablespace.
</para>
<para>
In the root directory <literal>data</literal>
there are also some files. In many cases, the configuration
- files of the cluster are stored here. As long as the
+ files of the cluster are stored here. If the
instance is up and running, the file
<literal>postmaster.pid</literal> exists here
and contains the process ID (pid) of the
- Postmaster which has started the instance.
+ Postmaster which started the instance.
</para>
<para>
@@ -411,7 +409,7 @@
<para>
In most cases, <productname>PostgreSQL</productname> databases
- support many clients at the same time. Therefore, it is necessary to
+ support many clients at the same time which makes it necessary to
protect concurrently running requests from unwanted overwriting
of other's data as well as from reading inconsistent data. Imagine an
online shop offering the last copy of an article. Two clients have the
@@ -425,18 +423,18 @@
<para>
A first approach to implement protections against concurrent
- accesses to the same data may be the locking of critical
+ access to the same data may be the locking of critical
rows. Two such techniques are:
<emphasis>Optimistic Concurrency Control</emphasis> (OCC)
and <emphasis>Two Phase Locking</emphasis> (2PL).
<productname>PostgreSQL</productname> implements a third, more
sophisticated technique: <firstterm>Multiversion Concurrency
Control</firstterm> (MVCC). The crucial advantage of MVCC
- over other technologies gets evident in multiuser OLTP
+ over other technologies becomes evident in multiuser OLTP
environments with a massive number of concurrent write
actions. There, MVCC generally performs better than solutions
using locks. In a <productname>PostgreSQL</productname>
- database reading never blocks writing and writing never
+ database, reading never blocks writing and writing never
blocks reading, even in the strictest level of transaction
isolation.
</para>
@@ -444,14 +442,14 @@
<para>
Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
a new version of the row when a data-change takes place. To
- distinguish between these two versions and to track the timeline
+ distinguish between these two versions, and to track the timeline
of the row, each of the versions contains, in addition to their user-defined
columns, two special system columns, which are not visible
for the usual <command>SELECT * FROM ...</command> command.
The column <literal>xmin</literal> contains the transaction ID (xid)
- of the transaction, which created this version of the row. Accordingly,
- <literal>xmax</literal> contains the xid of the transaction, which has
- deleted this version, or zero, if the version is not
+ of the transaction which created this version of the row.
+ <literal>xmax</literal> contains the xid of the transaction which has
+ deleted this version, or zero if the version is not
deleted. You can read both with the command
<command>SELECT xmin, xmax, * FROM ... </command>.
</para>
@@ -461,7 +459,7 @@
sequences. Every new transaction receives the next number as its ID.
Therefore, this flow of xids represents the flow of transaction
start events over time. But keep in mind that xids are independent of
- any time measurement — in milliseconds or whatever. If you dive
+ any time measurement — in milliseconds or otherwise. If you dive
deeper into <productname>PostgreSQL</productname>, you will recognize
parameters with names such as 'xxx_age'. Despite their names,
these '_age' parameters do not specify a period of time but represent
@@ -469,7 +467,7 @@
</para>
<para>
- The description in this chapter simplifies by omitting some details.
+ The description in this chapter simplifies by omitting details.
When many transactions are running simultaneously, things can
get complicated. Sometimes transactions get aborted via
<command>ROLLBACK</command> immediately or after a lot of other activities, sometimes
@@ -481,7 +479,7 @@
</para>
<para>
- So, what's going on in detail when write accesses take place?
+ So, what's going on in detail when write access takes place?
<xref linkend="tutorial-mvcc-figure"/> shows details concerning
<literal>xmin</literal>, <literal>xmax</literal>, and user data.
</para>
@@ -516,36 +514,38 @@
executes an <command>UPDATE</command> of this row by
changing the user data from <literal>'x'</literal> to
<literal>'y'</literal>. According to the MVCC principles,
- the data in the old version of the row does not change!
+ the data in the old version of the row is not changed!
The value <literal>'x'</literal> remains as it was before.
Only <literal>xmax</literal> changes to <literal>135</literal>.
Now, this version is treated as valid exclusively for
transactions with xids from <literal>123</literal> to
- <literal>134</literal>. As a substitute for the non-occurring
+ <literal>134</literal>. In addition to the non-occurring
data change in the old version, the <command>UPDATE</command>
creates a new version of the row with its xid in
<literal>xmin</literal>, <literal>0</literal> in
<literal>xmax</literal>, and <literal>'y'</literal> in the
- user data (plus all the other user data from the old version).
- This version is now valid for all coming transactions.
+ user data (plus all other user data from the old version).
+ This new row version is visible to all future transactions.
+ (Internally, an <command>UPDATE</command> command acts
+ as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.)
</para>
<para>
All subsequent <command>UPDATE</command> commands behave
- in the same way as the first one: they put their xid to
+ in the same way as the first one: they put their xid in
<literal>xmax</literal> of the current version, create
- the next version with their xid in <literal>xmin</literal>,
- <literal>0</literal> in <literal>xmax</literal>, and the
- new user data.
+ a new version with their xid in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
</para>
<para>
Finally, a row may be deleted by a <command>DELETE</command>
command. Even in this case, all versions of the row remain as
- before. Nothing is thrown away so far! Only <literal>xmax</literal>
- of the last version changes to the xid of the <command>DELETE</command>
- transaction, which indicates that it is only valid for
- transactions with xids older than its own (from
+ before. Nothing is thrown away! Only <literal>xmax</literal>
+ of the last version is set to the xid of the <command>DELETE</command>
+ transaction, which indicates that (if committed) it is only visible to
+ transactions with xids older than that (from
<literal>142</literal> to <literal>820</literal> in this
example).
</para>
@@ -555,10 +555,10 @@
of the same row in the table's heap file and leaves them there,
even after a <command>DELETE</command> command. Only the youngest
version is relevant for all future transactions. But the
- system must also preserve some of the older ones for a
- certain amount of time because the possibility exists that
- they are or could become relevant for any pending
- transactions. Over time, also the older ones get out of scope
+ system must also preserve some of the older ones for
+ awhile, because they could still be needed by
+ transactions which started before the deleting transaction commits.
+ Over time, also the older ones get out of scope
for ALL transactions and therefore become unnecessary.
Nevertheless, they do exist physically on the disk and occupy
space.
@@ -573,13 +573,13 @@
<simpara>
<literal>xmin</literal> and <literal>xmax</literal>
indicate the range from where to where
- row versions are valid (visible) for transactions.
+ <firstterm>row versions</firstterm> are valid (visible) for transactions.
This range doesn't imply any direct temporal meaning;
the sequence of xids reflects only the sequence of
transaction begin events. As
xids grow, old row versions get out of scope over time.
- If an old row version is no longer valid for ALL existing
- transactions, it's called <firstterm>dead</firstterm>. The
+ If an old row version is no longer relevant for ANY existing
+ transactions, it can be marked <firstterm>dead</firstterm>. The
space occupied by dead row versions is part of the
<glossterm linkend="glossary-bloat">bloat</glossterm>.
</simpara>
@@ -612,21 +612,21 @@
<para>
As we have seen in the previous chapter, the database
- tends to occupy more and more disk space, the
+ tends to occupy more and more disk space, caused by
<glossterm linkend="glossary-bloat">bloat</glossterm>.
This chapter explains how the SQL command
<command>VACUUM</command> and the automatically running
<firstterm>Autovacuum</firstterm> processes clean up
- by eliminating bloat.
+ and avoid continued growth.
</para>
<note>
<para>
Autovacuum runs automatically by
default. Its default parameters as well as such for
- <command>VACUUM</command> fit well for most standard
+ <command>VACUUM</command> are appropriate for most standard
situations. Therefore a novice database manager can
- easily skip the rest of this chapter which explains
+ skip the rest of this chapter which explains
a lot of details.
</para>
</note>
@@ -637,8 +637,8 @@
special situations, or they start it in batch jobs which run
periodically. Autovacuum processes run as part of the
<link linkend="glossary-instance">Instance</link> at the server.
- There is a constantly running Autovacuum daemon. It permanently
- controls the state of all databases based on values that are collected by the
+ There is a constantly running Autovacuum daemon. It continuously
+ monitors the state of all databases based on values that are collected by the
<link linkend="glossary-stats-collector">Statistics Collector</link>
and starts Autovacuum processes whenever it detects
certain situations. Thus, it's a dynamic behavior of
@@ -659,9 +659,9 @@
<listitem>
<simpara>
- <firstterm>Freeze</firstterm>: Mark the youngest row version
- as frozen. This means that the version
- is always treated as valid (visible) independent from
+ <firstterm>Freeze</firstterm>: Mark certain row versions
+ as frozen. This means that they
+ are always treated as valid (visible) independent from
the <firstterm>wraparound problem</firstterm> (see below).
</simpara>
</listitem>
@@ -686,22 +686,22 @@
</itemizedlist>
<para>
- The eagerness — you can call it 'aggression' — of the
- operations <emphasis>eliminating bloat</emphasis> and
+ The eagerness — you can call it 'aggressiveness' — of the
+ operations for <emphasis>eliminating bloat</emphasis> and
<emphasis>freeze</emphasis> is controlled by configuration
parameters, runtime flags, and in extreme situations by
the processes themselves. Because vacuum operations typically are I/O
intensive, which can hinder other activities, Autovacuum
avoids performing many vacuum operations in bulk. Instead,
- it carries out many small actions with time gaps in between.
+ it carries out many small actions with delay points in between.
The SQL command <command>VACUUM</command> runs immediately
- and without any time gaps.
+ and without any time delay.
</para>
<bridgehead renderas="sect2">Eliminate Bloat</bridgehead>
<para>
- To determine which of the row versions are superfluous, the
+ To determine which of the row versions are no longer needed, the
elimination operation must evaluate <literal>xmax</literal>
against several criteria which all must apply:
</para>
@@ -742,14 +742,13 @@
</itemizedlist>
<para>
- After the vacuum operation detects a superfluous row version, it
+ After the vacuum operation detects an unused row version, it
marks its space as free for future use of writing actions. Only
in rare situations (or in the case of <command>VACUUM FULL</command>),
- this space is released to the operating system. In most cases,
+ is this space released to the operating system. In most cases,
it remains occupied by <productname>PostgreSQL</productname>
and will be used by future <command>INSERT</command> or
- <command>UPDATE</command> commands concerning this row or a
- completely different one.
+ <command>UPDATE</command> commands to this table.
</para>
<para>
@@ -762,10 +761,10 @@
When a client issues the SQL command <command>VACUUM</command>
in its default format, i.e., without any option. To boost performance,
in this and the next case <command>VACUUM</command> does not
- read and act on all pages of the heap.
- The Visibility Map, which is very compact and therefore has a small
- size, contains information about pages, where bloat-candidates might
- be found. Only such pages are processed.
+ read and act on all pages of the heap file.
+ The Visibility Map, which is very compact and therefore fast to read,
+ contains information about which pages have no deleted row versions, and
+ can be skipped by <command>VACUUM</command>.
</simpara>
</listitem>
@@ -773,7 +772,7 @@
<simpara>
When a client issues the SQL command <command>VACUUM</command>
with the option <command>FREEZE</command>. (In this case,
- it undertakes much more actions, see
+ it undertakes many more actions, see
<link linkend="tutorial-freeze">Freeze Row Versions</link>.)
</simpara>
</listitem>
@@ -782,12 +781,11 @@
<simpara>
When a client issues the SQL command <command>VACUUM</command>
with the option <command>FULL</command>.
- Also, in this mode, the bloat disappears, but the strategy used
- is very different: In this case, the complete table is copied
- to a different file skipping all outdated row versions. This
- leads to a significant reduction of used disk space because
- the new file contains only the actual data. The old file
- is deleted.
+ In this mode, an exclusive lock is taken, and
+ the whole table is copied to a different file, skipping all outdated row
+ versions. All bloat is thereby eliminated, which
+ may lead to a significant reduction of used disk space.
+ The old file is deleted.
</simpara>
</listitem>
@@ -809,17 +807,17 @@
<para>
This logic only applies to row versions of the heap. Index entries
don't use <literal>xmin/xmax</literal>. Nevertheless, such index
- entries, which would lead to outdated row versions, are released
+ entries, which would lead to outdated row versions, are cleaned up
accordingly.
</para>
<para>
The above descriptions omit the fact that xids on a real computer
- have a limited size. They count up in the same way as sequences, and after
- a certain number of new transactions they are forced to restart
+ have a limited size, and after
+ a certain number of transactions they are forced to restart
from the beginning, which is called <firstterm>wraparound</firstterm>.
Therefore the terms 'old transaction' / 'young transaction' does
- not always correlate with low / high values of xids. Near to the
+ not always correlate with low / high values of xids. Near to
wraparound point, there are cases where <literal>xmin</literal> has
a higher value than <literal>xmax</literal>, although their meaning
is said to be older than <literal>xmax</literal>.
@@ -858,7 +856,7 @@
and the corresponding transactions of <literal>xmin</literal>
and <literal>xmax</literal> must be committed. However,
<productname>PostgreSQL</productname> has to consider the
- possibility of wraparounds.
+ possibility of wraparound.
Therefore the decision becomes more complex. The general
idea of the solution is to use the 'between
<literal>xmin</literal> and <literal>xmax</literal>'
@@ -885,7 +883,7 @@
<listitem>
<simpara>
With each newly created transaction the two split-points
- move forward. When 'txid_current + 2^31' would reach a
+ move forward. If 'txid_current + 2^31' reached a
row version with <literal>xmin</literal> equal to that value, it would
immediately jump from 'past' to 'future' and would be
no longer visible!
@@ -894,11 +892,11 @@
<listitem>
<simpara>
- To avoid this unacceptable extinction of data, the vacuum
- operation <firstterm>freeze</firstterm> clears the situation
- long before the split-point is reached. It sets a flag
- in the header of the row version, which completely eliminates
- the future use of <literal>xmin/xmax</literal> and indicates
+ If not handled in some way, data inserted many transactions ago
+ would become invisibile. The vacuum operation <firstterm>freeze</firstterm>
+ avoids this long before the split-point is reached by setting
+ a flag in the header of the row version which avoids
+ future comparison of its <literal>xmin/xmax</literal> and indicates
that the version is valid not only in the 'past'-half
but also in the 'future'-half as well as in all coming
<glossterm linkend="glossary-xid">epochs</glossterm>.
@@ -945,19 +943,19 @@
When a client issues the SQL command <command>VACUUM</command>
with its <command>FREEZE</command> option. In this case, all
pages are processed that are marked in the Visibility Map
- to potentially have unfrozen rows.
+ as potentially having unfrozen rows.
</simpara>
</listitem>
<listitem>
<simpara>
When a client issues the SQL command <command>VACUUM</command> without
- any options but finds that there are xids older than
+ any options but there are xids older than
<xref linkend="guc-vacuum-freeze-table-age"/>
(default: 150 million) minus
<xref linkend="guc-vacuum-freeze-min-age"/>
(default: 50 million).
As before, all pages are processed that are
- marked in the Visibility Map to potentially have unfrozen
+ marked in the Visibility Map to potentially having unfrozen
rows.
</simpara>
</listitem>
@@ -983,7 +981,7 @@
<simpara>
The process switches
to an <emphasis>aggressive mode</emphasis> if it recognizes
- that for the processed table their oldest xid exceeds
+ that for the processed table the oldest xid exceeds
<xref linkend="guc-autovacuum-freeze-max-age"/>
(default: 200 million). The value of the oldest unfrozen
xid is stored per table in <literal>pg_class.relfrozenxid</literal>.
@@ -1039,29 +1037,28 @@
<para>
The <link linkend="glossary-vm">Visibility Map</link>
(VM) contains two flags — stored as
- two bits — for each page of the heap. If the first bit
- is set, that indicates that the associated page does not
- contain any bloat. If the second one is set, that indicates
- that the page contains only frozen rows.
+ two bits — for each page of the heap file. The
+ first bit indicates that the associated page does
+ not contain any bloat. The second bit indicates
+ that the page contains only frozen row versions.
</para>
<para>
Please consider two details. First, in most cases a page
- contains many rows, some of them in many versions.
+ contains many rows or row versions.
However, the flags are associated with the page,
- not with a row or a row version. The flags are set
+ not with an individual row version. The flags are set
only under the condition that they are valid for ALL
row versions of the page. Second, since there
are only two bits per page, the VM is considerably
- smaller than the heap. Therefore it is buffered
- in RAM in almost all cases.
+ smaller than the heap.
</para>
<para>
The setting of the flags is silently done by <command>VACUUM</command>
and Autovacuum during their bloat and freeze operations.
This is done to speed up future vacuum actions,
- regular accesses to heap pages, and some accesses to
+ regular access to heap pages, and some access to
the index. Every data-modifying operation on any row
version of the page clears the flags.
</para>
@@ -1070,7 +1067,7 @@
The <link linkend="glossary-fsm">Free Space Map</link>
(FSM) tracks the amount of free space per page. It is
organized as a highly condensed b-tree of (rounded) sizes.
- As long as <command>VACUUM</command> or Autovacuum change
+ Whenever <command>VACUUM</command> or Autovacuum changes
the free space on any processed page, they log the new
values in the FSM in the same way as all other writing
processes.
@@ -1079,18 +1076,19 @@
<bridgehead renderas="sect2">Statistics</bridgehead>
<para>
- Statistic information helps the <link
+ Statistical information helps the <link
linkend="planner-stats">Query Planner</link> to make optimal
decisions for the generation of execution plans. This
information can be gathered with the SQL commands
<command>ANALYZE</command> or <command>VACUUM ANALYZE</command>.
- But also Autovacuum processes gather
+ But Autovacuum processes also gather
such information. Depending on the percentage of changed rows
- per table <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ and minimum number of changed rows <xref linkend="guc-autovacuum-analyze-threshold"/>,
the Autovacuum daemon starts Autovacuum processes to collect
- statistics per table. This dynamic invocation of analyze
- operations allows <productname>PostgreSQL</productname> to
- adopt queries to changing circumstances.
+ statistics per table. The automatic analysis
+ allows <productname>PostgreSQL</productname> to
+ adapt query execution to changing circumstances.
</para>
<para>
@@ -1143,7 +1141,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
atomicity: either all or none of its operations succeed,
regardless of the fact that it may consist of a lot of
different write-operations, and each such operation may
- affect thousands or millions of rows. As soon as one of the
+ affect many rows. As soon as one of the
operations fails, all previous operations fail also, which
means that all modified rows retain their values as of the
beginning of the transaction.
@@ -1151,20 +1149,20 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<para>
The atomicity also affects the visibility of changes. No
- connection running simultaneously to a data modifying
+ connection running simultaneously with a data modifying
transaction will ever see any change before the
transaction successfully executes a <command>COMMIT</command>
— even in the lowest
<link linkend="transaction-iso">isolation level</link>
of transactions. <productname>PostgreSQL</productname>
- does never show uncommitted changes to other connections.
+ never shows uncommitted changes to other connections.
</para>
<para>
The situation regarding visibility is somewhat different
from the point of view of the modifying transaction.
- <command>SELECT</command> commands issued inside a
- transaction delivers all changes done so far by this
+ A <command>SELECT</command> command issued inside a
+ transaction shows all changes done so far by this
transaction.
</para>
@@ -1230,9 +1228,9 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<para>
Transactions ensure that the
- <glossterm linkend="glossary-consistency">consistency</glossterm>
- of the complete database always keeps valid. Declarative
- rules like
+ database always remains
+ <glossterm linkend="glossary-consistency">consistent</glossterm>.
+ Declarative rules like
<link linkend="ddl-constraints-primary-keys">primary</link>- or
<link linkend="ddl-constraints-fk">foreign keys</link>,
<link linkend="ddl-constraints-check-constraints">checks</link>,
@@ -1241,13 +1239,6 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
are part of the all-or-nothing nature of transactions.
</para>
- <para>
- Also, all self-evident — but possibly not obvious
- — low-level demands on the database system are
- ensured; e.g. index entries for rows must become
- visible at the same moment as the rows themselves.
- </para>
-
<para>
There is the additional feature
'<link linkend="transaction-iso">isolation level</link>',
@@ -1257,11 +1248,11 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
</para>
<para>
- Lastly, it is worth to notice that changes done by a
- committed transaction will survive all future application,
- instance, or hardware failures. The next chapter
- explains this
- <glossterm linkend="glossary-durability">durability</glossterm>.
+ Lastly, it is worth noticing that changes done by a
+ committed transaction will survive all failures in the application or
+ database cluster. The next chapter explains the
+ <glossterm linkend="glossary-durability">durability</glossterm>
+ guarantees.
</para>
</sect1>
@@ -1287,7 +1278,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
a severe software error like a null pointer exception.
Because <productname>PostgreSQL</productname> uses a
client/server architecture, no direct problem for the
- database will occur. In all of this cases, the
+ database will occur. In all of these cases, the
<glossterm linkend="glossary-backend">Backend process</glossterm>,
which is the client's counterpart at the server-side,
may recognize that the network connection is no longer
@@ -1310,7 +1301,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
automatically recognizes that the last shutdown of the
instance did not happen as expected: files might not be
closed properly and the <literal>postmaster.pid</literal>
- file exists. <productname>PostgreSQL</productname>
+ file unexpectedly exists. <productname>PostgreSQL</productname>
tries to clean up the situation. This is possible because
all changes in the database are stored twice. First,
the WAL files contain them as a chronology of
@@ -1318,7 +1309,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
which include the new data values and information about commit
actions. The WAL records are written first. Second,
the data itself shall exist in the heap and index files.
- In opposite to the WAL records, this part may or may
+ In constrast with the WAL records, this part may or may
not have been transferred entirely from Shared Memory
to the files.
</para>
@@ -1328,13 +1319,13 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<glossterm linkend="glossary-checkpoint">checkpoint</glossterm>.
This checkpoint signals that the database files are in
a consistent state, especially that all WAL records up to
- this point were successfully stored in heap and index. Starting
- here, the recovery process copies the following WAL records
- to heap and index. As a result, the files contain all
- changes and reach a consistent state. Changes of committed
- transactions are visible; those of uncommited transactions
+ this point were successfully stored in heap and index files. Starting
+ here, the recovery process copies the remaining WAL records
+ to heap and index. As a result, the heap files contain all
+ changes recorded to the WAL and reach a consistent state. Changes of committed
+ transactions are visible; those of uncommitted transactions
are also in the files, but - as usual - they are never seen
- by any of the following transactions because uncommited
+ by any of the following transactions because uncommitted
changes are never shown. Such recovery actions run
completely automatically, it is not necessary that a
database administrator configure or start anything by
@@ -1344,13 +1335,13 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<bridgehead renderas="sect3">Disk crash</bridgehead>
<para>
If a disk crashes, the course of action described previously
- cannot work. It is likely that the WAL files and/or the
+ cannot work: it is likely that the WAL files and/or the
data and index files are no longer available. The
database administrator must take special actions to
- overcome such situations.
+ prepare for such a situation.
</para>
<para>
- He obviously needs a backup. How to take such a backup
+ They obviously needs a backup. How to take such a backup
and use it as a starting point for a recovery of the
cluster is explained in more detail in the next
<link linkend="tutorial-backup">chapter</link>.
@@ -1362,11 +1353,11 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
and there is no room for additional data. In this case,
<productname>PostgreSQL</productname> stops accepting
data-modifying commands or even terminates completely.
- No data loss or data corruption will occur.
+ Committed data is neither lost nor corrupted.
</para>
<para>
- To come out of such a situation, the administrator should
- remove unused files from this disk. But he should never
+ To recover from such a situation, the administrator should
+ remove unused files from this disk. But they should never
delete files from the
<glossterm linkend="glossary-data-directory">data directory</glossterm>.
Nearly all of them are necessary for the consistency
@@ -1427,7 +1418,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
</para>
<para>
The obvious disadvantage of this method is that there
- is a downtime where no user interaction is possible.
+ is a downtime.
The other two strategies run during regular operating
times.
</para>
@@ -1437,9 +1428,9 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
The tool <command>pg_dump</command> is able to take a
<link linkend="backup-dump">copy</link>
of the complete cluster or certain parts of it. It stores
- the copy in the form of SQL <command>CREATE</command> and
- <command>INSERT</command> commands. It runs in
- parallel to other processes in its own transaction.
+ the copy in the form of SQL commands like <command>CREATE</command>
+ and <command>COPY</command>. It runs in
+ parallel with other processes in its own transaction.
</para>
<para>
The output of <command>pg_dump</command> may be used as
@@ -1456,17 +1447,17 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
<para>
<link linkend="continuous-archiving">This method</link>
- is the most sophisticated and complex one. It
+ is the most sophisticated and most complex one. It
consists of two phases.
</para>
<para>
- First, you need to create a so called
+ First, you need to create a so-called
<firstterm>basebackup</firstterm> with the tool
<command>pg_basebackup</command>. The result is a
- directory structure plus files which contains a
+ directory structure plus files which contain a
consistent copy of the original cluster.
<command>pg_basebackup</command> runs in
- parallel to other processes in its own transaction.
+ parallel with other processes in its own transaction.
</para>
<para>
The second step is recommended but not necessary. All
@@ -1484,7 +1475,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
will automatically copy every single WAL file to a save location.
<link linkend="backup-archiving-wal">Its configuration</link>
- consists mainly of a string, which contains a copy command
+ consists mainly of a string that contains a copy command
in the operating system's syntax. In order to protect your
data against a disk crash, the destination location
of a basebackup as well as of the
@@ -1492,9 +1483,8 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
disk which is different from the data disk.
</para>
<para>
- If it gets necessary to restore the cluster, you have to
- copy the basebackup and the
- archived WAL files to
+ If it becomes necessary to restore the cluster, you have to
+ copy the basebackup and the archived WAL files to
their original directories. The configuration of this
<link linkend="backup-pitr-recovery">recovery procedure</link>
contains a string with the reverse copy command: from
On 2020-11-01 16:38, Jürgen Purtz wrote:
On 30.10.20 17:45, Erik Rijkers wrote:
And I wrote down some separate items:
1.
'Two Phase Locking' and 'TPL' should be, I think,
'Two-Phase Commit'. Please someone confirm.
(no changes made)Erik Rijkers
All suggestions so far are summarized in the attached patch with the
following exceptions:- 'Two Phase Locking' is the intended term.
OK, so what is 'Two Phase Locking'? The term is not explained, and not
used anywhere else in the manual. You propose to introduce it here, in
the tutorial. I don't know what it means, and I am not really a
beginner.
'Two Phase Locking' should be explained somewhere, and how it relates
(or not) to Two-Phase Commit (2PC), don't you agree?
Erik Rijkers
On 02.11.20 07:15, Erik Rijkers wrote:
On 2020-11-01 16:38, Jürgen Purtz wrote:
On 30.10.20 17:45, Erik Rijkers wrote:
And I wrote down some separate items:
1.
'Two Phase Locking' and 'TPL' should be, I think,
'Two-Phase Commit'. Please someone confirm.
(no changes made)Erik Rijkers
All suggestions so far are summarized in the attached patch with the
following exceptions:- 'Two Phase Locking' is the intended term.
OK, so what is 'Two Phase Locking'? The term is not explained, and
not used anywhere else in the manual. You propose to introduce it
here, in the tutorial. I don't know what it means, and I am not
really a beginner.'Two Phase Locking' should be explained somewhere, and how it relates
(or not) to Two-Phase Commit (2PC), don't you agree?Erik Rijkers
It may be possible to explain OCC and 2PL in two or three sentences
within the glossary. But I think, we shall not try to explain such
general strategies. They are not specific to PG and even not
implemented. Instead, if the paragraph is too detailed, we can use a
more general formulation without explicitly naming locking strategies.
OLD:
A first approach to implement protections against concurrent
access to the same data may be the locking of critical
rows. Two such techniques are:
<emphasis>Optimistic Concurrency Control</emphasis> (OCC)
and <emphasis>Two Phase Locking</emphasis> (2PL).
<productname>PostgreSQL</productname> implements a third, more
sophisticated technique: <firstterm>Multiversion Concurrency
Control</firstterm> (MVCC). The crucial advantage of MVCC ...
Proposal:
A first approach to implement protections against concurrent
access to the same data may be the locking of critical
rows.
<productname>PostgreSQL</productname> implements a more
sophisticated technique which avoids any locking:
<firstterm>Multiversion Concurrency
Control</firstterm> (MVCC). The crucial advantage of MVCC ...
Any thoughts or other suggestions?
--
J. Purtz
On 2020-11-02 09:26, Jürgen Purtz wrote:
OLD:
A first approach to implement protections against concurrent
access to the same data may be the locking of critical
rows. Two such techniques are:
<emphasis>Optimistic Concurrency Control</emphasis> (OCC)
and <emphasis>Two Phase Locking</emphasis> (2PL).
<productname>PostgreSQL</productname> implements a third, more
sophisticated technique: <firstterm>Multiversion Concurrency
Control</firstterm> (MVCC). The crucial advantage of MVCC ...Proposal:
A first approach to implement protections against concurrent
access to the same data may be the locking of critical
rows.
<productname>PostgreSQL</productname> implements a more
sophisticated technique which avoids any locking:
<firstterm>Multiversion Concurrency
Control</firstterm> (MVCC). The crucial advantage of MVCC ...Any thoughts or other suggestions?
Yes, just leave it out. Much better, as far as I'm concerned.
Erik
On 02.11.20 09:44, Erik Rijkers wrote:
On 2020-11-02 09:26, Jürgen Purtz wrote:
OLD:
A first approach to implement protections against concurrent
access to the same data may be the locking of critical
rows. Two such techniques are:
<emphasis>Optimistic Concurrency Control</emphasis> (OCC)
and <emphasis>Two Phase Locking</emphasis> (2PL).
<productname>PostgreSQL</productname> implements a third, more
sophisticated technique: <firstterm>Multiversion Concurrency
Control</firstterm> (MVCC). The crucial advantage of MVCC ...Proposal:
A first approach to implement protections against concurrent
access to the same data may be the locking of critical
rows.
<productname>PostgreSQL</productname> implements a more
sophisticated technique which avoids any locking:
<firstterm>Multiversion Concurrency
Control</firstterm> (MVCC). The crucial advantage of MVCC ...Any thoughts or other suggestions?
Yes, just leave it out. Much better, as far as I'm concerned.
Erik
Because there have been no more comments in the last days I created a
consolidated patch. It contains Erik's suggestion and some tweaks for
the text size within graphics.
--
J. Purtz
Attachments:
0011-architecture.patchtext/x-patch; charset=UTF-8; name=0011-architecture.patchDownload
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
index 2d4ab85d45..5c3245c0ec 100644
--- a/doc/src/sgml/advanced.sgml
+++ b/doc/src/sgml/advanced.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/advanced.sgml -->
<chapter id="tutorial-advanced">
- <title>Advanced Features</title>
+ <title>Advanced SQL Features</title>
<sect1 id="tutorial-advanced-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/arch-dev.sgml b/doc/src/sgml/arch-dev.sgml
index 7883c3cd82..9db0ae2c78 100644
--- a/doc/src/sgml/arch-dev.sgml
+++ b/doc/src/sgml/arch-dev.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/arch-dev.sgml -->
<chapter id="overview">
- <title>Overview of PostgreSQL Internals</title>
+ <title>Overview of Query Handling</title>
<note>
<title>Author</title>
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
new file mode 100644
index 0000000000..b3446c2ea1
--- /dev/null
+++ b/doc/src/sgml/architecture.sgml
@@ -0,0 +1,1504 @@
+<!-- doc/src/sgml/architecture.sgml -->
+
+ <chapter id="tutorial-architecture">
+ <title>Overview of Architecture and Implementation</title>
+
+ <para>
+ Every DBMS implements basic strategies to ensure a fast
+ and robust system. This chapter provides an overview of the
+ techniques <productname>PostgreSQL</productname> uses to
+ achieve this.
+ </para>
+
+ <sect1 id="tutorial-ram-proc-file">
+ <title>Collaboration of Processes, RAM, and Files</title>
+ <para>
+ In a client/server architecture clients do not have direct access
+ to database files and the data stored in them. Instead, they send
+ requests to the server and receive the requested data in the response.
+ In the case of <productname>PostgreSQL</productname>, the server
+ launches a single process for each client connection, referred to as a
+ <glossterm linkend="glossary-backend">Backend</glossterm> process.
+ Such a Backend process handles the client's requests by acting on the
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>.
+ This leads to other activities (file access, WAL, vacuum, ...) of the
+ <glossterm linkend="glossary-instance">Instance</glossterm>. The
+ Instance is a group of server-side processes acting on a common
+ Shared Memory. PostgreSQL does not utilize threading.
+ </para>
+
+ <para>
+ The first step when an Instance starts is the start of the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ It loads the configuration files, allocates Shared Memory, and
+ starts the other processes of the Instance:
+ <glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
+ <glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
+ <glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
+ <glossterm linkend="glossary-wal-archiver">WAL Archiver</glossterm>,
+ <glossterm linkend="glossary-autovacuum">Autovacuum</glossterm>,
+ <glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
+ <glossterm linkend="glossary-logger">Logger</glossterm>, and more.
+ Later, the Postmaster starts
+ <glossterm linkend="glossary-backend">Backend</glossterm> processes
+ which communicate with clients and handle their requests.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes the processes
+ of an Instance and the main aspects of their collaboration.
+ </para>
+
+ <figure id="tutorial-ram-proc-file-figure">
+ <title>Architecture</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ When a client application tries to connect to a
+ <glossterm linkend="glossary-database">database</glossterm>,
+ this request is handled initially by the Postmaster. It
+ starts a new Backend process, which handles all further
+ client's requests.
+ </para>
+
+ <para>
+ Client requests like <command>SELECT</command> or
+ <command>UPDATE</command> usually lead to the
+ necessity to read or write data. This is carried out
+ by the client's backend process. Reads involve a page-level
+ cache, located in Shared Memory (for details see:
+ <xref linkend="sysvipc"/>) for the benefit of all processes
+ in the instance. Writes also use this cache, in addition
+ to a journal, called a write-ahead-log or WAL.
+ </para>
+
+ <para>
+ Shared Memory is limited in size and it can become necessary
+ to evict pages. As long as the content of such pages hasn't
+ changed, this is not a problem. But in Shared Memory also
+ write actions take place. Modified pages are called dirty
+ pages or dirty buffers and before they can be evicted they
+ must be written to disk. This happens regularly by the
+ Checkpointer and the Background Writer processes to ensure
+ that the disk version of the pages are up-to-date.
+ The synchronisation from RAM to disk consists of two steps.
+ </para>
+
+ <para>
+ First, whenever the content of a page changes, a
+ <glossterm linkend="glossary-wal-record">WAL record</glossterm>
+ is created out of the delta-information (difference between the
+ old and the new content) and stored in another area of
+ Shared Memory. The parallel running WAL Writer process
+ reads them and appends them to the end of the current
+ <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
+ Such sequential writes are faster than writes to random
+ positions of heap and index files. All WAL records created
+ out of one dirty page must be transferred to disk before the
+ dirty page itself can be transferred to disk in the second step.
+ </para>
+
+ <para>
+ Second, the transfer of dirty buffers from Shared Memory to
+ files must take place. This is the primary task of the
+ Background Writer process. Because I/O activities can block
+ other processes, it starts periodically and
+ acts only for a short period. Doing so, its extensive (and
+ expensive) I/O activities are spread over time, avoiding
+ debilitating I/O peaks. The Checkpointer process
+ also transfers dirty buffers to file.
+ </para>
+
+ <para>
+ The Checkpointer process creates
+ <glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
+ A Checkpoint is a point in time when all older dirty buffers,
+ all older WAL records, and finally a special Checkpoint record
+ are written and flushed to disk. Heap and index files
+ on the one hand and WAL files on the other hand are in sync.
+ Previous WAL is no longer required. In other words,
+ a possibly occurring recovery, which integrates the delta
+ information of WAL into heap and index files, will happen
+ by replaying only WAL past the last recorded checkpoint.
+ This limits the amount of WAL which needs to be replayed
+ during recovery in the event of a crash.
+ </para>
+
+ <para>
+ While the Checkpointer ensures that the database system can crash
+ and restart itself in a valid state, the administrator needs
+ to handle the case where the heap or other files become
+ corrupted (and possibly the locally written WAL, though that is
+ less common). The options and details are covered extensively
+ in the backup and restore section (<xref linkend="backup"/>).
+ For our purposes here, just note that the WAL Archiver process
+ can be enabled and configured to run a script on filled WAL
+ files — usually to copy them to a remote location.
+ </para>
+
+ <para>
+ The Statistics Collector collects counters about access to
+ SQL objects like tables, rows, indexes, pages, and more. It
+ stores the obtained information in system tables.
+ </para>
+
+ <para>
+ The Logger writes text lines about serious and less serious
+ events which can happen during database access, e.g., wrong
+ password, no permission, long-running queries, etc.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-cluster-db-schema">
+ <title>The logical Perspective: Cluster, Database, Schema</title>
+
+ <para>
+ A <glossterm linkend="glossary-server">server</glossterm> contains one or more
+ <glossterm linkend="glossary-db-cluster">database clusters</glossterm>
+ (<glossterm linkend="glossary-db-cluster">clusters</glossterm>
+ for short). Each cluster contains three or more
+ <glossterm linkend="glossary-database">databases</glossterm>.
+ Each database can contain many
+ <glossterm linkend="glossary-schema">schemas</glossterm>.
+ A schema can contain
+ <glossterm linkend="glossary-table">tables</glossterm>,
+ <glossterm linkend="glossary-view">views</glossterm>, and a lot
+ of other objects. Each table or view belongs to a single schema
+ only; they cannot belong to another schema as well. The same is
+ true for the schema/database and database/cluster relation.
+ <xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
+ this hierarchy.
+ </para>
+
+ <figure id="tutorial-cluster-db-schema-figure">
+ <title>Cluster, Database, Schema</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ A cluster is the outer container for a
+ collection of databases. Clusters are created by the command
+ <xref linkend="app-initdb"/>.
+ </para>
+
+ <para>
+ <literal>template0</literal> is the very first
+ database of any cluster. Database <literal>template0</literal>
+ is created during the initialization phase of the cluster.
+ In a second step, database <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal>, and finally database
+ <literal>postgres</literal> is generated as a copy of
+ <literal>template1</literal>. Any
+ <glossterm linkend="app-createdb">new databases</glossterm>
+ of the cluster that a user might need,
+ such as <literal>my_db</literal>, will be copied from the
+ <literal>template1</literal> database. Due to the unique
+ role of <literal>template0</literal> as the pristine original
+ of all other databases, no client can connect to it.
+ </para>
+
+ <para>
+ Every database must contain at least one schema because all
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>
+ must be contained in a schema.
+ Schemas are namespaces for SQL objects and ensure
+ (with one exception) that the SQL object names are used only once within
+ their scope across all types of SQL objects. E.g., it is not possible
+ to have a table <literal>employee</literal> and a view
+ <literal>employee</literal> within the same schema. But it is
+ possible to have two tables <literal>employee</literal> in two
+ different schemas. In this case, the two tables
+ are separate objects and independent of each
+ other. The only exception to this cross-type uniqueness is that
+ <glossterm linkend="glossary-unique-constraint">unique constraints
+ </glossterm> and the according unique index
+ (<xref linkend="indexes-unique"/>) use the same name.
+ </para>
+
+ <para>
+ Some schemas are predefined. <literal>public</literal>
+ acts as the default schema and contains all SQL objects
+ which are created within <literal>public</literal> or
+ without using an explicit schema name. <literal>public</literal>
+ should not contain user-defined SQL objects. Instead, it is
+ recommended to create a separate schema that holds individual
+ objects like application-specific tables or views.
+ <literal>pg_catalog</literal> is a schema for all tables and views of the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ <literal>information_schema</literal> is a schema for several
+ tables and views of the System Catalog in a way that conforms
+ to the SQL standard.
+ </para>
+
+ <para>
+ There are many different SQL object
+ types: <firstterm>database, schema, table, view, materialized
+ view, index, constraint, sequence, function, procedure,
+ trigger, role, data type, operator, tablespace, extension,
+ foreign data wrapper</firstterm>, and more. A few of them, the
+ <firstterm>Global SQL Objects</firstterm>, are outside of the
+ strict hierarchy: All <firstterm>database names</firstterm>,
+ all <firstterm>tablespace names</firstterm>, and all
+ <firstterm>role names</firstterm> are automatically
+ available throughout the cluster, independent from
+ the database or schema in which they where defined originally.
+ <xref linkend="tutorial-internal-objects-hierarchy-figure"/>
+ shows the relation between the object types.
+ </para>
+
+ <figure id="tutorial-internal-objects-hierarchy-figure">
+ <title>Hierarchy of Internal Objects</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect1>
+
+ <sect1 id="tutorial-directories">
+ <title>The physical Perspective: Directories and Files</title>
+
+ <para>
+ <productname>PostgreSQL</productname> organizes long-lasting (persistent)
+ data as well as volatile state information about transactions
+ or replication actions in the file system. Every
+ <xref linkend="glossary-db-cluster"/> has its root directory
+ somewhere in the file system. In many cases, the environment
+ variable <literal>PGDATA</literal> points to this directory.
+ The example shown in
+ <xref linkend="tutorial-directories-figure"/> uses
+ <literal>data</literal> as the name of this root directory.
+ </para>
+
+ <figure id="tutorial-directories-figure">
+ <title>Directory Structure</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ <literal>data</literal> contains many subdirectories and
+ some files, all of which are necessary to store long-lasting
+ as well as temporary data. The following paragraphs
+ describe the files and subdirectories in
+ <literal>data</literal>.
+ </para>
+
+ <para>
+ <literal>base</literal> is a subdirectory in which one
+ subdirectory per database exists. The names of those
+ subdirectories consist of numbers. These are the internal
+ Object Identifiers (OID), which are numbers to identify
+ the database definition in the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ </para>
+
+ <para>
+ Within the database-specific
+ subdirectories, there are many files: one or more for
+ every table and every index to store heap and index
+ data. Those files are accompanied by files for the
+ <link linkend="storage-fsm">Free Space Maps</link>
+ (suffixed <literal>_fsm</literal>) and
+ <link linkend="storage-vm">Visibility Maps</link>
+ (suffixed <literal>_vm</literal>), which contain optimization information.
+ </para>
+
+ <para>
+ Another subdirectory is <literal>global</literal> which
+ contains files with information about
+ <glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
+ One type of such Global SQL Objects are
+ <glossterm linkend="glossary-tablespace">tablespaces</glossterm>.
+ In <literal>global</literal> there is information about
+ the tablespaces; not the tablespaces themselves.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_wal</literal> contains the
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
+ They arise and grow in parallel with data changes in the
+ cluster and remain as long as
+ they are required for recovery, archiving, or replication.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_xact</literal> contains
+ information about the status of each transaction:
+ <literal>in_progress</literal>, <literal>committed</literal>,
+ <literal>aborted</literal>, or <literal>sub_committed</literal>.
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal>, there are symbolic links
+ that point to directories containing SQL objects
+ that exist within a non-default tablespace.
+ </para>
+
+ <para>
+ In the root directory <literal>data</literal>
+ there are also some files. In many cases, the configuration
+ files of the cluster are stored here. If the
+ instance is up and running, the file
+ <literal>postmaster.pid</literal> exists here
+ and contains the process ID (pid) of the
+ Postmaster which started the instance.
+ </para>
+
+ <para>
+ For more details about the physical implementation
+ of database objects, see <xref linkend="storage"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-mvcc">
+ <title>MVCC — Multiversion Concurrency Control</title>
+
+ <para>
+ In most cases, <productname>PostgreSQL</productname> databases
+ support many clients at the same time which makes it necessary to
+ protect concurrently running requests from unwanted overwriting
+ of other's data as well as from reading inconsistent data. Imagine an
+ online shop offering the last copy of an article. Two clients have the
+ article displayed at their user interface. After a while, but at the same time,
+ both users decide to put it to their shopping cart or even to buy it.
+ Both have seen the article, but only one can be allowed to get it.
+ The database must bring the two requests in a row, permit the access
+ to one of them, block the other, and inform the blocked client
+ that the data was changed by a different process.
+ </para>
+
+ <para>
+ A first approach to implement protections against concurrent
+ access to the same data may be the locking of critical rows.
+ <productname>PostgreSQL</productname> implements a more
+ sophisticated technique which avoids any locking:
+ <firstterm>Multiversion Concurrency Control</firstterm> (MVCC).
+ The crucial advantage of MVCC
+ over other technologies becomes evident in multiuser OLTP
+ environments with a massive number of concurrent write
+ actions. There, MVCC generally performs better than solutions
+ using locks. In a <productname>PostgreSQL</productname>
+ database, reading never blocks writing and writing never
+ blocks reading, even in the strictest level of transaction
+ isolation.
+ </para>
+
+ <para>
+ Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
+ a new version of the row when a data-change takes place. To
+ distinguish between these two versions, and to track the timeline
+ of the row, each of the versions contains, in addition to their user-defined
+ columns, two special system columns, which are not visible
+ for the usual <command>SELECT * FROM ...</command> command.
+ The column <literal>xmin</literal> contains the transaction ID (xid)
+ of the transaction which created this version of the row.
+ <literal>xmax</literal> contains the xid of the transaction which has
+ deleted this version, or zero if the version is not
+ deleted. You can read both with the command
+ <command>SELECT xmin, xmax, * FROM ... </command>.
+ </para>
+
+ <para>
+ When we speak about transaction IDs, you need to know that xids are like
+ sequences. Every new transaction receives the next number as its ID.
+ Therefore, this flow of xids represents the flow of transaction
+ start events over time. But keep in mind that xids are independent of
+ any time measurement — in milliseconds or otherwise. If you dive
+ deeper into <productname>PostgreSQL</productname>, you will recognize
+ parameters with names such as 'xxx_age'. Despite their names,
+ these '_age' parameters do not specify a period of time but represent
+ a certain number of transactions, e.g., 100 million.
+ </para>
+
+ <para>
+ The description in this chapter simplifies by omitting details.
+ When many transactions are running simultaneously, things can
+ get complicated. Sometimes transactions get aborted via
+ <command>ROLLBACK</command> immediately or after a lot of other activities, sometimes
+ a single row is involved in more than one transaction, sometimes
+ a client crashes, sometimes the sequence of xids restarts
+ from zero, ... . Therefore, every version of a row contains more
+ system columns and flags, not only <literal>xmin</literal>
+ and <literal>xmax</literal>.
+ </para>
+
+ <para>
+ So, what's going on in detail when write access takes place?
+ <xref linkend="tutorial-mvcc-figure"/> shows details concerning
+ <literal>xmin</literal>, <literal>xmax</literal>, and user data.
+ </para>
+
+ <figure id="tutorial-mvcc-figure">
+ <title>Multiversion Concurrency Control</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ An <command>INSERT</command> command creates the first
+ version of a row. Besides its user data <literal>'x'</literal>,
+ this version contains the ID of the creating transaction
+ <literal>123</literal> in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ <literal>xmin</literal> indicates that the version
+ exists since transaction <literal>123</literal> and
+ <literal>xmax</literal> that it is currently not deleted.
+ </para>
+
+ <para>
+ Somewhat later, transaction <literal>135</literal>
+ executes an <command>UPDATE</command> of this row by
+ changing the user data from <literal>'x'</literal> to
+ <literal>'y'</literal>. According to the MVCC principles,
+ the data in the old version of the row is not changed!
+ The value <literal>'x'</literal> remains as it was before.
+ Only <literal>xmax</literal> changes to <literal>135</literal>.
+ Now, this version is treated as valid exclusively for
+ transactions with xids from <literal>123</literal> to
+ <literal>134</literal>. In addition to the non-occurring
+ data change in the old version, the <command>UPDATE</command>
+ creates a new version of the row with its xid in
+ <literal>xmin</literal>, <literal>0</literal> in
+ <literal>xmax</literal>, and <literal>'y'</literal> in the
+ user data (plus all other user data from the old version).
+ This new row version is visible to all future transactions.
+ (Internally, an <command>UPDATE</command> command acts
+ as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.)
+ </para>
+
+ <para>
+ All subsequent <command>UPDATE</command> commands behave
+ in the same way as the first one: they put their xid in
+ <literal>xmax</literal> of the current version, create
+ a new version with their xid in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ </para>
+
+ <para>
+ Finally, a row may be deleted by a <command>DELETE</command>
+ command. Even in this case, all versions of the row remain as
+ before. Nothing is thrown away! Only <literal>xmax</literal>
+ of the last version is set to the xid of the <command>DELETE</command>
+ transaction, which indicates that (if committed) it is only visible to
+ transactions with xids older than that (from
+ <literal>142</literal> to <literal>820</literal> in this
+ example).
+ </para>
+
+ <para>
+ In summary, the MVCC technology creates more and more versions
+ of the same row in the table's heap file and leaves them there,
+ even after a <command>DELETE</command> command. Only the youngest
+ version is relevant for all future transactions. But the
+ system must also preserve some of the older ones for
+ awhile, because they could still be needed by
+ transactions which started before the deleting transaction commits.
+ Over time, also the older ones get out of scope
+ for ALL transactions and therefore become unnecessary.
+ Nevertheless, they do exist physically on the disk and occupy
+ space.
+ </para>
+
+ <para>
+ Please keep in mind:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> and <literal>xmax</literal>
+ indicate the range from where to where
+ <firstterm>row versions</firstterm> are valid (visible) for transactions.
+ This range doesn't imply any direct temporal meaning;
+ the sequence of xids reflects only the sequence of
+ transaction begin events. As
+ xids grow, old row versions get out of scope over time.
+ If an old row version is no longer relevant for ANY existing
+ transactions, it can be marked <firstterm>dead</firstterm>. The
+ space occupied by dead row versions is part of the
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Internally, an <command>UPDATE</command> command acts in the
+ same way as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Nothing gets wiped away — with the consequence that the database
+ occupies more and more disk space. It is obvious that
+ this behavior has to be corrected in some
+ way. The next chapter explains how <firstterm>autovacuum</firstterm>
+ fulfills this task.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ </sect1>
+
+ <sect1 id="tutorial-vacuum">
+ <title>Vacuum</title>
+
+ <para>
+ As we have seen in the previous chapter, the database
+ tends to occupy more and more disk space, caused by
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ This chapter explains how the SQL command
+ <command>VACUUM</command> and the automatically running
+ <firstterm>Autovacuum</firstterm> processes clean up
+ and avoid continued growth.
+ </para>
+
+ <note>
+ <para>
+ Autovacuum runs automatically by
+ default. Its default parameters as well as such for
+ <command>VACUUM</command> are appropriate for most standard
+ situations. Therefore a novice database manager can
+ skip the rest of this chapter which explains
+ a lot of details.
+ </para>
+ </note>
+
+ <para>
+ Client processes can issue the SQL command <command>VACUUM</command>
+ at arbitrary points in time. DBAs do this when they recognize
+ special situations, or they start it in batch jobs which run
+ periodically. Autovacuum processes run as part of the
+ <link linkend="glossary-instance">Instance</link> at the server.
+ There is a constantly running Autovacuum daemon. It continuously
+ monitors the state of all databases based on values that are collected by the
+ <link linkend="glossary-stats-collector">Statistics Collector</link>
+ and starts Autovacuum processes whenever it detects
+ certain situations. Thus, it's a dynamic behavior of
+ <productname>PostgreSQL</productname> with the intention to tidy
+ up — whenever it is appropriate.
+ </para>
+
+ <para>
+ <command>VACUUM</command>, as well as Autovacuum, don't just eliminate
+ bloat. They perform additional tasks for minimizing future
+ I/O activities of themselves as well as of other processes.
+ This extra work can be done in a very efficient way since in most
+ cases the expensive physical access to pages has taken place anyway
+ to eliminate bloat. The additional operations are:
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <firstterm>Freeze</firstterm>: Mark certain row versions
+ as frozen. This means that they
+ are always treated as valid (visible) independent from
+ the <firstterm>wraparound problem</firstterm> (see below).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <firstterm>Visibility Map</firstterm> and
+ <firstterm>Free Space Map</firstterm>: Log information about
+ the state of the handled pages in two additional files, the
+ Visibility Map and the Free Space Map.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <emphasis>Statistics</emphasis>: Collect statistics about the
+ number of rows per table, the distribution of values, and so on,
+ as the basis for decisions of the query planner.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ The eagerness — you can call it 'aggressiveness' — of the
+ operations for <emphasis>eliminating bloat</emphasis> and
+ <emphasis>freeze</emphasis> is controlled by configuration
+ parameters, runtime flags, and in extreme situations by
+ the processes themselves. Because vacuum operations typically are I/O
+ intensive, which can hinder other activities, Autovacuum
+ avoids performing many vacuum operations in bulk. Instead,
+ it carries out many small actions with delay points in between.
+ The SQL command <command>VACUUM</command> runs immediately
+ and without any time delay.
+ </para>
+
+ <bridgehead renderas="sect2">Eliminate Bloat</bridgehead>
+
+ <para>
+ To determine which of the row versions are no longer needed, the
+ elimination operation must evaluate <literal>xmax</literal>
+ against several criteria which all must apply:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be different from zero because a
+ value of zero indicates that the row version is still valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must contain an xid which is older
+ than the oldest xid of all currently running transactions
+ <literal>(min(pg_stat_activity.backend_xmin))</literal>.
+ This criterion guarantees that no existing or upcoming transaction
+ will have read or write access to this row version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of <literal>xmax</literal> must be committed. If it was rollback-ed,
+ this row version is treated as valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there is the situation that the row version is part of
+ multiple transactions, special care and some more actions
+ must be taken, see: <xref linkend="vacuum-for-multixact-wraparound"/>.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ After the vacuum operation detects an unused row version, it
+ marks its space as free for future use of writing actions. Only
+ in rare situations (or in the case of <command>VACUUM FULL</command>),
+ is this space released to the operating system. In most cases,
+ it remains occupied by <productname>PostgreSQL</productname>
+ and will be used by future <command>INSERT</command> or
+ <command>UPDATE</command> commands to this table.
+ </para>
+
+ <para>
+ Which actions start the elimination of bloat?
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ in its default format, i.e., without any option. To boost performance,
+ in this and the next case <command>VACUUM</command> does not
+ read and act on all pages of the heap file.
+ The Visibility Map, which is very compact and therefore fast to read,
+ contains information about which pages have no deleted row versions, and
+ can be skipped by <command>VACUUM</command>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FREEZE</command>. (In this case,
+ it undertakes many more actions, see
+ <link linkend="tutorial-freeze">Freeze Row Versions</link>.)
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FULL</command>.
+ In this mode, an exclusive lock is taken, and
+ the whole table is copied to a different file, skipping all outdated row
+ versions. All bloat is thereby eliminated, which
+ may lead to a significant reduction of used disk space.
+ The old file is deleted.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When an Autovacuum process acts. For optimization
+ purposes, it considers the Visibility Map in the same way as
+ <command>VACUUM</command>. Additionally, it ignores tables with few modifications;
+ see <xref linkend="guc-autovacuum-vacuum-threshold"/>,
+ which defaults to 50 rows and
+ <xref linkend="guc-autovacuum-vacuum-scale-factor"/>,
+ which defaults to 20%.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </para>
+
+ <para>
+ This logic only applies to row versions of the heap. Index entries
+ don't use <literal>xmin/xmax</literal>. Nevertheless, such index
+ entries, which would lead to outdated row versions, are cleaned up
+ accordingly.
+ </para>
+
+ <para>
+ The above descriptions omit the fact that xids on a real computer
+ have a limited size, and after
+ a certain number of transactions they are forced to restart
+ from the beginning, which is called <firstterm>wraparound</firstterm>.
+ Therefore the terms 'old transaction' / 'young transaction' does
+ not always correlate with low / high values of xids. Near to
+ wraparound point, there are cases where <literal>xmin</literal> has
+ a higher value than <literal>xmax</literal>, although their meaning
+ is said to be older than <literal>xmax</literal>.
+ </para>
+
+ <figure id="tutorial-wraparound-figure">
+ <title>Cyclic usage of XIDs</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2" id="tutorial-freeze">Freeze Row Versions</bridgehead>
+
+ <para>
+ The use of a limited range of IDs for transactions leads
+ to the necessity to restart the sequence sooner or later.
+ This does not only have the rare consequence previously
+ described that sometimes <literal>xmin</literal> is
+ higher than <literal>xmax</literal>. The far
+ more critical problem is that whenever the system has
+ to evaluate a WHERE condition, it must decide which row
+ version is valid (visible) from the perspective of the
+ transaction of this query. If a wraparound couldn't happen,
+ this decision would be relatively easy: the xid
+ must be between <literal>xmin</literal> and <literal>xmax</literal>,
+ and the corresponding transactions of <literal>xmin</literal>
+ and <literal>xmax</literal> must be committed. However,
+ <productname>PostgreSQL</productname> has to consider the
+ possibility of wraparound.
+ Therefore the decision becomes more complex. The general
+ idea of the solution is to use the 'between
+ <literal>xmin</literal> and <literal>xmax</literal>'
+ comparison only during the youngest period of the row
+ versions lifetime and afterward replace it with a
+ 'valid forever' flag in its header.
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ As a first step, <productname>PostgreSQL</productname>
+ divides the complete range of
+ possible xids into two halves with the two split-points
+ 'txid_current' and 'txid_current + 2^31'. The half behind
+ 'txid_current' is considered to represent xids of the
+ 'past' and the half ahead of 'txid_current' those of the
+ 'future'. Those of the 'past' are valid (visible) and those
+ of the 'future' not.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ With each newly created transaction the two split-points
+ move forward. If 'txid_current + 2^31' reached a
+ row version with <literal>xmin</literal> equal to that value, it would
+ immediately jump from 'past' to 'future' and would be
+ no longer visible!
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If not handled in some way, data inserted many transactions ago
+ would become invisibile. The vacuum operation <firstterm>freeze</firstterm>
+ avoids this long before the split-point is reached by setting
+ a flag in the header of the row version which avoids
+ future comparison of its <literal>xmin/xmax</literal> and indicates
+ that the version is valid not only in the 'past'-half
+ but also in the 'future'-half as well as in all coming
+ <glossterm linkend="glossary-xid">epochs</glossterm>.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Which row versions can be frozen by the vacuum operation?
+ Again, several criteria must be checked, and all must be met.
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be zero because only
+ non-deleted rows can be visible 'forever'.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> must be older than all currently
+ existing transactions. This guarantees that no existing
+ transaction can modify or delete the version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transactions of <literal>xmin</literal> and
+ <literal>xmax</literal> must be committed.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ At what point in time does the freeze operation take place?
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with its <command>FREEZE</command> option. In this case, all
+ pages are processed that are marked in the Visibility Map
+ as potentially having unfrozen rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command> without
+ any options but there are xids older than
+ <xref linkend="guc-vacuum-freeze-table-age"/>
+ (default: 150 million) minus
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million).
+ As before, all pages are processed that are
+ marked in the Visibility Map to potentially having unfrozen
+ rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When an Autovacuum process runs. Such a process acts in one
+ of two modes:
+ </simpara>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ In the <emphasis>normal mode</emphasis>, it skips
+ pages with row versions that are younger than
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million) and works only on pages where
+ all xids are older. The skipping of young xids prevents
+ work on such pages, which are likely to be changed
+ by one of the future SQL commands.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ The process switches
+ to an <emphasis>aggressive mode</emphasis> if it recognizes
+ that for the processed table the oldest xid exceeds
+ <xref linkend="guc-autovacuum-freeze-max-age"/>
+ (default: 200 million). The value of the oldest unfrozen
+ xid is stored per table in <literal>pg_class.relfrozenxid</literal>.
+ In this <emphasis>aggressive mode</emphasis> Autovacuum
+ processes all such pages of the selected table that are marked
+ in the Visibility Map to potentially have bloat or unfrozen rows.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In the first two cases and with Autovacuum in
+ <emphasis>aggressive mode</emphasis>, the system knows
+ to which value the oldest unfrozen xid has moved forward and
+ logs the value in <literal>pg_class.relfrozenxid</literal>.
+ The distance between this value and the 'txid_current' split
+ point becomes smaller, and the distance to 'txid_current + 2^31'
+ becomes larger than before.
+ </para>
+
+ <figure id="tutorial-freeze-figure">
+ <title>Freeze</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2">Protection against Wraparound Failure</bridgehead>
+
+ <para>
+ The Autovacuum processes are initiated by the constantly running
+ Autovacuum daemon. If the daemon detects that for a table
+ <literal>autovacuum_freeze_max_age</literal> is exceeded, it
+ starts an Autovacuum process in <emphasis>aggressive mode</emphasis>
+ (see above) — even if Autovacuum is disabled.
+ </para>
+
+ <bridgehead renderas="sect2">Visibility Map and Free Space Map</bridgehead>
+
+ <para>
+ The <link linkend="glossary-vm">Visibility Map</link>
+ (VM) contains two flags — stored as
+ two bits — for each page of the heap file. The
+ first bit indicates that the associated page does
+ not contain any bloat. The second bit indicates
+ that the page contains only frozen row versions.
+ </para>
+
+ <para>
+ Please consider two details. First, in most cases a page
+ contains many rows or row versions.
+ However, the flags are associated with the page,
+ not with an individual row version. The flags are set
+ only under the condition that they are valid for ALL
+ row versions of the page. Second, since there
+ are only two bits per page, the VM is considerably
+ smaller than the heap.
+ </para>
+
+ <para>
+ The setting of the flags is silently done by <command>VACUUM</command>
+ and Autovacuum during their bloat and freeze operations.
+ This is done to speed up future vacuum actions,
+ regular access to heap pages, and some access to
+ the index. Every data-modifying operation on any row
+ version of the page clears the flags.
+ </para>
+
+ <para>
+ The <link linkend="glossary-fsm">Free Space Map</link>
+ (FSM) tracks the amount of free space per page. It is
+ organized as a highly condensed b-tree of (rounded) sizes.
+ Whenever <command>VACUUM</command> or Autovacuum changes
+ the free space on any processed page, they log the new
+ values in the FSM in the same way as all other writing
+ processes.
+ </para>
+
+ <bridgehead renderas="sect2">Statistics</bridgehead>
+
+ <para>
+ Statistical information helps the <link
+ linkend="planner-stats">Query Planner</link> to make optimal
+ decisions for the generation of execution plans. This
+ information can be gathered with the SQL commands
+ <command>ANALYZE</command> or <command>VACUUM ANALYZE</command>.
+ But Autovacuum processes also gather
+ such information. Depending on the percentage of changed rows
+ <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ and minimum number of changed rows <xref linkend="guc-autovacuum-analyze-threshold"/>,
+ the Autovacuum daemon starts Autovacuum processes to collect
+ statistics per table. The automatic analysis
+ allows <productname>PostgreSQL</productname> to
+ adapt query execution to changing circumstances.
+ </para>
+
+ <para>
+ For more details about vacuum operations, especially for its
+ numerous parameters, see <xref linkend="routine-vacuuming"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-transactions-mvcc">
+ <title>Transactions</title>
+ <para>
+ <link linkend="tutorial-transactions">Transactions</link>
+ are a fundamental concept of relational database systems.
+ Their essential point is that they bundle multiple
+ read- or write-operations into a single all-or-nothing
+ operation. Furthermore, they separate and protect concurrent
+ actions of different connections from each other. Thereby
+ they implement the ACID paradigm.
+ </para>
+
+ <para>
+ In <productname>PostgreSQL</productname> there are two ways
+ to establish a transaction. The explicit way uses the keywords
+ <link linkend="sql-begin">BEGIN</link> and
+ <link linkend="sql-commit">COMMIT</link> (respectively
+ <link linkend="sql-rollback">ROLLBACK</link>) before
+ and after a sequence of SQL statements. The keywords mark
+ the transaction's start- and end-point. On the other hand, you
+ can omit the keywords. This is the implicit way, where
+ every single SQL command automatically establishes a new
+ transaction.
+
+ <programlisting>
+BEGIN; -- establish a new transaction
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+COMMIT; -- finish the transaction
+
+-- this UPDATE runs as the only command of a separate transaction ...
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+
+-- ... and this one runs in another transaction
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+ </programlisting>
+ </para>
+
+ <para>
+ As mentioned, the primary property of a transaction is its
+ atomicity: either all or none of its operations succeed,
+ regardless of the fact that it may consist of a lot of
+ different write-operations, and each such operation may
+ affect many rows. As soon as one of the
+ operations fails, all previous operations fail also, which
+ means that all modified rows retain their values as of the
+ beginning of the transaction.
+ </para>
+
+ <para>
+ The atomicity also affects the visibility of changes. No
+ connection running simultaneously with a data modifying
+ transaction will ever see any change before the
+ transaction successfully executes a <command>COMMIT</command>
+ — even in the lowest
+ <link linkend="transaction-iso">isolation level</link>
+ of transactions. <productname>PostgreSQL</productname>
+ never shows uncommitted changes to other connections.
+ </para>
+
+ <para>
+ The situation regarding visibility is somewhat different
+ from the point of view of the modifying transaction.
+ A <command>SELECT</command> command issued inside a
+ transaction shows all changes done so far by this
+ transaction.
+ </para>
+
+ <bridgehead renderas="sect2">How does it work?</bridgehead>
+
+ <para>
+ Every <command>INSERT</command>, <command>UPDATE</command>,
+ and <command>DELETE</command> command creates new row
+ versions — according to the MVCC rules. This
+ creates the risk that other transactions may see the
+ new row versions, and after a while and some more
+ activities of the modifying transaction they may see the
+ next row versions. Results would be a kind of 'moving
+ target' in absolute contrast to the all-or-nothing
+ principle.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> overcomes this
+ problem by showing only such row versions to other
+ transactions whose originating transaction is
+ successfully committed. It skips all row versions of
+ uncommitted transactions. And
+ <productname>PostgreSQL</productname> solves one more
+ problem. Even the single <command>COMMIT</command>
+ command needs a short time interval for its execution.
+ Therefore its critical 'dead-or-survival' phase
+ runs in a priviledged mode where it cannot be
+ interrupted by other processes.
+ </para>
+
+ <bridgehead renderas="sect2">What are the benefits?</bridgehead>
+
+ <para>
+ Transactions relieve applications from many standard
+ actions that must be implemented for nearly every use case.
+ </para>
+
+ <para>
+ Business logic often contains strong, but for a computer,
+ relative abstract requirements. The above example shows
+ the transfers of some money from one account to another.
+ It is obvious
+ that the decrease of the one and the increase of the
+ other must be indivisible. Nevertheless, there is no particular
+ need for an application to do something to ensure the
+ <glossterm linkend="glossary-atomicity">atomicity</glossterm>
+ of this behavior. It's enough to surround them with
+ <command>BEGIN</command> and <command>COMMIT</command>.
+ </para>
+
+ <para>
+ Applications often demand the feature of 'undoing'
+ previously taken actions under some application-specific
+ conditions. In such cases, the application simply issues a
+ <command>ROLLBACK</command> command instead of a
+ <command>COMMIT</command>. The <command>ROLLBACK</command>
+ cancels the transaction, and all changes made so far remain
+ invisible forever; it is as if they had never happened. There
+ is no need for the application to log its activities and
+ undo every step of the transaction separately.
+ </para>
+
+ <para>
+ Transactions ensure that the
+ database always remains
+ <glossterm linkend="glossary-consistency">consistent</glossterm>.
+ Declarative rules like
+ <link linkend="ddl-constraints-primary-keys">primary</link>- or
+ <link linkend="ddl-constraints-fk">foreign keys</link>,
+ <link linkend="ddl-constraints-check-constraints">checks</link>,
+ other constraints, or
+ <link linkend="trigger-definition">triggers</link>
+ are part of the all-or-nothing nature of transactions.
+ </para>
+
+ <para>
+ There is the additional feature
+ '<link linkend="transaction-iso">isolation level</link>',
+ which separates transactions from each other in certain ways.
+ It automatically prevents applications from some strange
+ situations.
+ </para>
+
+ <para>
+ Lastly, it is worth noticing that changes done by a
+ committed transaction will survive all failures in the application or
+ database cluster. The next chapter explains the
+ <glossterm linkend="glossary-durability">durability</glossterm>
+ guarantees.
+ </para>
+ </sect1>
+
+ <sect1 id="tutorial-reliability">
+ <title>Reliability</title>
+
+ <para>
+ Nothing is perfect and failures inevitably happen.
+ However, the most common types of failure are
+ well known and <productname>PostgreSQL</productname>
+ implements strategies to overcome them.
+ Such strategies use parts of the previously presented
+ techniques MVCC and transaction-rollback, plus additional
+ features.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the client side</bridgehead>
+ <para>
+ A <glossterm linkend="glossary-client">client</glossterm>
+ can fail in different ways. Its hardware can get damaged,
+ the power supply can fail, the network connection to the
+ server can break, or the client application may run into
+ a severe software error like a null pointer exception.
+ Because <productname>PostgreSQL</productname> uses a
+ client/server architecture, no direct problem for the
+ database will occur. In all of these cases, the
+ <glossterm linkend="glossary-backend">Backend process</glossterm>,
+ which is the client's counterpart at the server-side,
+ may recognize that the network connection is no longer
+ working, or it may run into a timeout after a while. It
+ terminates, and there is no harm to the database. As
+ usual, uncommitted data changes initiated by this client
+ are not visible to any other client.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the server-side</bridgehead>
+
+ <bridgehead renderas="sect3">Instance failure</bridgehead>
+ <para>
+ The instance may suddenly fail because of <emphasis>power off</emphasis>
+ or other problems. This will affect all running processes, the RAM,
+ and possibly the consistency of disk files.
+ </para>
+
+ <para>
+ After a restart, <productname>PostgreSQL</productname>
+ automatically recognizes that the last shutdown of the
+ instance did not happen as expected: files might not be
+ closed properly and the <literal>postmaster.pid</literal>
+ file unexpectedly exists. <productname>PostgreSQL</productname>
+ tries to clean up the situation. This is possible because
+ all changes in the database are stored twice. First,
+ the WAL files contain them as a chronology of
+ <glossterm linkend="glossary-wal-record">WAL records</glossterm>,
+ which include the new data values and information about commit
+ actions. The WAL records are written first. Second,
+ the data itself shall exist in the heap and index files.
+ In constrast with the WAL records, this part may or may
+ not have been transferred entirely from Shared Memory
+ to the files.
+ </para>
+
+ <para>
+ The automatic recovery searches within the WAL files for
+ the latest
+ <glossterm linkend="glossary-checkpoint">checkpoint</glossterm>.
+ This checkpoint signals that the database files are in
+ a consistent state, especially that all WAL records up to
+ this point were successfully stored in heap and index files. Starting
+ here, the recovery process copies the remaining WAL records
+ to heap and index. As a result, the heap files contain all
+ changes recorded to the WAL and reach a consistent state. Changes of committed
+ transactions are visible; those of uncommitted transactions
+ are also in the files, but - as usual - they are never seen
+ by any of the following transactions because uncommitted
+ changes are never shown. Such recovery actions run
+ completely automatically, it is not necessary that a
+ database administrator configure or start anything by
+ himself.
+ </para>
+
+ <bridgehead renderas="sect3">Disk crash</bridgehead>
+ <para>
+ If a disk crashes, the course of action described previously
+ cannot work: it is likely that the WAL files and/or the
+ data and index files are no longer available. The
+ database administrator must take special actions to
+ prepare for such a situation.
+ </para>
+
+ <para>
+ They obviously needs a backup. How to take such a backup
+ and use it as a starting point for a recovery of the
+ cluster is explained in more detail in the next
+ <link linkend="tutorial-backup">chapter</link>.
+ </para>
+
+ <bridgehead renderas="sect3">Disk full</bridgehead>
+ <para>
+ It is conceivable that over time the disk gets full,
+ and there is no room for additional data. In this case,
+ <productname>PostgreSQL</productname> stops accepting
+ data-modifying commands or even terminates completely.
+ Committed data is neither lost nor corrupted.
+ </para>
+
+ <para>
+ To recover from such a situation, the administrator should
+ remove unused files from this disk. But they should never
+ delete files from the
+ <glossterm linkend="glossary-data-directory">data directory</glossterm>.
+ Nearly all of them are necessary for the consistency
+ of the database.
+ </para>
+
+ <bridgehead renderas="sect2">High availability</bridgehead>
+ <para>
+ Database servers can work together to allow a second
+ server to quickly take over the workload if the
+ primary server fails for whatever reason
+ (<link linkend="high-availability">high availability</link>),
+ or to allow several computers to serve the same data
+ for the purpose of load balancing.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-backup">
+ <title>Backup</title>
+
+ <para>
+ Taking backups is a basic task of database maintenance.
+ <productname>PostgreSQL</productname> supports
+ three different strategies; each has its own
+ strengths and weaknesses.
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ File system level backup
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Logical backup via <command>pg_dump</command>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Continuous archiving based on <command>pg_basebackup</command>
+ and WAL files
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <bridgehead renderas="sect2">File system level backup</bridgehead>
+ <para>
+ You can use any appropriate OS tool to create a
+ <link linkend="backup-file">copy</link>
+ of the cluster's directory structure and files. In
+ case of severe problems such a copy can serve as
+ the source of recovery. But in order to get a
+ <emphasis>USABLE</emphasis> backup by this method,
+ the database server <emphasis>MUST</emphasis> be
+ shut down during the complete runtime of the copy
+ command!
+ </para>
+
+ <para>
+ The obvious disadvantage of this method is that there
+ is a downtime.
+ The other two strategies run during regular operating
+ times.
+ </para>
+
+ <bridgehead renderas="sect2">Logical backup via pg_dump</bridgehead>
+ <para>
+ The tool <command>pg_dump</command> is able to take a
+ <link linkend="backup-dump">copy</link>
+ of the complete cluster or certain parts of it. It stores
+ the copy in the form of SQL commands like <command>CREATE</command>
+ and <command>COPY</command>. It runs in
+ parallel with other processes in its own transaction.
+ </para>
+
+ <para>
+ The output of <command>pg_dump</command> may be used as
+ input of <command>psql</command> to restore the data
+ (or to copy it to another database).
+ </para>
+
+ <para>
+ The main advantage over the other two methods is that it
+ can pick parts of the cluster, e.g., a single table or one
+ database. The other two methods work only at the level of
+ the complete cluster.
+ </para>
+
+ <bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
+ <para>
+ <link linkend="continuous-archiving">This method</link>
+ is the most sophisticated and most complex one. It
+ consists of two phases.
+ </para>
+
+ <para>
+ First, you need to create a so-called
+ <firstterm>basebackup</firstterm> with the tool
+ <command>pg_basebackup</command>. The result is a
+ directory structure plus files which contain a
+ consistent copy of the original cluster.
+ <command>pg_basebackup</command> runs in
+ parallel with other processes in its own transaction.
+ </para>
+
+ <para>
+ The second step is recommended but not necessary. All
+ changes to the data are stored in WAL files. If you
+ continuously save such WAL files, you have the history
+ of the cluster. This history can be applied to a
+ basebackup in order to recreate
+ any state of the cluster between the time of
+ <command>pg_basebackup</command>'s start time and
+ any later point in time. This technique
+ is called 'Point-in-Time Recovery (PITR)'.
+ </para>
+
+ <para>
+ If configured, the
+ <glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
+ will automatically copy every single WAL file to a save location.
+ <link linkend="backup-archiving-wal">Its configuration</link>
+ consists mainly of a string that contains a copy command
+ in the operating system's syntax. In order to protect your
+ data against a disk crash, the destination location
+ of a basebackup as well as of the
+ <firstterm>archived WAL files</firstterm> should be on a
+ disk which is different from the data disk.
+ </para>
+
+ <para>
+ If it becomes necessary to restore the cluster, you have to
+ copy the basebackup and the archived WAL files to
+ their original directories. The configuration of this
+ <link linkend="backup-pitr-recovery">recovery procedure</link>
+ contains a string with the reverse copy command: from
+ archive location to database location.
+ </para>
+
+ </sect1>
+
+<!-- ToDo: replication, index-types, extension mechanism, ...
+ <sect1 id="tutorial-replication">
+ <title>Replication</title>
+
+ <para>
+...
+ </para>
+
+ </sect1>
+-->
+
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 38e8aa0bbf..7490d3c9c2 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -80,6 +80,7 @@
%allfiles;
<!-- developer's guide -->
+<!ENTITY architecture SYSTEM "architecture.sgml">
<!ENTITY arch-dev SYSTEM "arch-dev.sgml">
<!ENTITY bki SYSTEM "bki.sgml">
<!ENTITY catalogs SYSTEM "catalogs.sgml">
diff --git a/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
new file mode 100644
index 0000000000..bdbfc38387
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
@@ -0,0 +1,160 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="685" viewBox="0 0 900 685">
+ <title>
+ Server (Hardware, Container, or VM)
+ </title>
+ <style>
+ .text_normal,.text_small{font-style:normal;font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_small{font-size:12px}.text_normal{font-size:14px}
+ </style>
+ <defs>
+ <symbol id="rectangle_special_0">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="rectangle_special_1">
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="125">
+ 'my_schema' (optional)
+ </text>
+ <text class="text_small" x="20" y="145">
+ tables, views, ...
+ </text>
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="190">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M450 10v230H0V0h440v10h10L440 0"/>
+ </symbol>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="270" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Server (Hardware, Container, or VM)
+ </text>
+ <path stroke="blue" stroke-width="2" fill="none" d="M20 110h790v555H20z"/>
+ <text class="text_normal" x="180" y="25" transform="translate(20 110)">
+ cluster 'data' (default, managed by one instance)
+ </text>
+ <path d="M50 110V80h790v555h-30" stroke="blue" stroke-width="2" fill="none"/>
+ <text class="text_normal" x="190" y="-10" transform="translate(45 110)">
+ cluster 'cluster_2' (optional, managed by a different instance)
+ </text>
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template0'
+ </text>
+ </g>
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template1'
+ </text>
+ </g>
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'my_db' (optional)
+ </text>
+ </g>
+ <g transform="translate(320 330)">
+ <rect width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4"/>
+ <text class="text_normal" x="15" y="27">
+ Global SQL objects
+ </text>
+ <path d="M0 5l-65-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M80 0v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M180 40h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M0 40l-45 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ </g>
+ <g transform="translate(335 405)">
+ <use xlink:href="#note"/>
+ <text class="text_small" x="10" y="20">
+ 1)
+ </text>
+ <text class="text_small" x="30" y="20">
+ By default, you work in the cluster 'data', database 'postgres',
+ </text>
+ <text class="text_small" x="30" y="35">
+ schema 'public'.
+ </text>
+ <text class="text_small" x="10" y="55">
+ 2)
+ </text>
+ <text class="text_small" x="30" y="55">
+ More system schemas: pg_catalog, information_schema,
+ </text>
+ <text class="text_small" x="30" y="70">
+ pg_temp, pg_toast.
+ </text>
+ <text class="text_small" x="10" y="90">
+ 3)
+ </text>
+ <text class="text_small" x="30" y="90">
+ Global SQL objects: Some SQL objects are automatically active
+ </text>
+ <text class="text_small" x="30" y="105">
+ and known database- or even cluster-wide.
+ </text>
+ <text class="text_small" x="10" y="125">
+ 4)
+ </text>
+ <text class="text_small" x="30" y="125">
+ The command 'initdb' creates a new cluster with the three
+ </text>
+ <text class="text_small" x="30" y="140">
+ databases 'template0', 'template1', and 'postgres'. The command
+ </text>
+ <text class="text_small" x="30" y="155">
+ 'createdb' creates a new database.
+ </text>
+ <text class="text_small" x="10" y="175">
+ 5)
+ </text>
+ <text class="text_small" x="30" y="175">
+ If multiple clusters are active on one server at the same time,
+ </text>
+ <text class="text_small" x="30" y="190">
+ each one is managed by an individual instance. Each such instance
+ </text>
+ <text class="text_small" x="30" y="205">
+ uses a different port.
+ </text>
+ <text class="text_small" x="10" y="225">
+ 6)
+ </text>
+ <text class="text_small" x="30" y="225">
+ No client application is allowed to connect to 'template0'.
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink.svg b/doc/src/sgml/images/cluster-db-schema-ink.svg
new file mode 100644
index 0000000000..86f878a12d
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink.svg
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="685px"
+ viewBox="0 0 900 685"
+ id="svg147"
+ sodipodi:docname="cluster-db-schema-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Server (Hardware, Container, or VM)</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.34452555"
+ inkscape:cx="450"
+ inkscape:cy="342.5"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Server (Hardware, Container, or VM)</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs49">
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangle_special_0">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect6" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="195"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect8" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text10">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text12">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="195"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect14" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text16">(more system schemas)</text>
+ </symbol>
+ <!-- same as before, but one more schema -->
+ <symbol
+ id="rectangle_special_1">
+ <!-- the database -->
+ <rect
+ width="245"
+ height="225"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect19" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect21" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text23">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text25">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect27" />
+ <text
+ class="text_normal"
+ x="20"
+ y="125"
+ id="text29">'my_schema' (optional)</text>
+ <text
+ class="text_small"
+ x="20"
+ y="145"
+ id="text31">tables, views, ...</text>
+ <rect
+ x="15"
+ y="170"
+ width="205"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect33" />
+ <text
+ class="text_small"
+ x="20"
+ y="190"
+ id="text35">(more system schemas)</text>
+ </symbol>
+ <symbol
+ id="note"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title38">UML Note</title>
+ <path
+ d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10"
+ id="path40" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path43" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path46" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect51" />
+ <text
+ class="text_big"
+ x="270"
+ y="40"
+ id="text53">Server (Hardware, Container, or VM)</text>
+ <!-- two clusters -->
+ <g
+ transform="translate(20 110)"
+ id="g59">
+ <rect
+ x="0"
+ y="0"
+ width="790"
+ height="555"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="rect55" />
+ <text
+ class="text_normal"
+ x="180"
+ y="25"
+ id="text57">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g
+ transform="translate(45 110)"
+ id="g65">
+ <path
+ d="M 5,0 v -30 h 790 v 555 h -30"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="path61" />
+ <text
+ class="text_normal"
+ x="190"
+ y="-10"
+ id="text63">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+ <!-- database template 0 -->
+ <g
+ transform="translate(40 155)"
+ id="g71">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use67" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text69">database 'template0'</text>
+ </g>
+ <!-- database template 1 -->
+ <g
+ transform="translate(290 155)"
+ id="g77">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use73" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text75">database 'template1'</text>
+ </g>
+ <!-- database postgres -->
+ <g
+ transform="translate(540 155)"
+ id="g83">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use79" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text81">database 'postgres'</text>
+ </g>
+ <!-- database my_db -->
+ <g
+ transform="translate(40 350)"
+ id="g89">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use85" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text87">database 'my_db' (optional)</text>
+ </g>
+ <!-- global objects -->
+ <g
+ transform="translate(320 330)"
+ id="g103">
+ <rect
+ x="0"
+ y="0"
+ width="180"
+ height="45"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="10 4 4 4"
+ id="rect91" />
+ <text
+ class="text_normal"
+ x="15"
+ y="27"
+ id="text93">Global SQL objects</text>
+ <path
+ d="M 0,5 l-65,-35"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path95" />
+ <path
+ d="M 80,0 v-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path97" />
+ <path
+ d="M 180,40 h50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path99" />
+ <path
+ d="M 0,40 l-45,20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path101" />
+ </g>
+ <!-- Some comments -->
+ <g
+ transform="translate(335 405)"
+ id="g145">
+ <use
+ xlink:href="#note"
+ x="0"
+ y="0"
+ id="use105" />
+ <text
+ class="text_small"
+ x="10"
+ y="20"
+ id="text107">1)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="20"
+ id="text109">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text
+ class="text_small"
+ x="30"
+ y="35"
+ id="text111">schema 'public'.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="55"
+ id="text113">2)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="55"
+ id="text115">More system schemas: pg_catalog, information_schema,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="70"
+ id="text117">pg_temp, pg_toast.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="90"
+ id="text119">3)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="90"
+ id="text121">Global SQL objects: Some SQL objects are automatically active</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text123">and known database- or even cluster-wide.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="125"
+ id="text125">4)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="125"
+ id="text127">The command 'initdb' creates a new cluster with the three</text>
+ <text
+ class="text_small"
+ x="30"
+ y="140"
+ id="text129">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text
+ class="text_small"
+ x="30"
+ y="155"
+ id="text131">'createdb' creates a new database.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="175"
+ id="text133">5)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="175"
+ id="text135">If multiple clusters are active on one server at the same time,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="190"
+ id="text137">each one is managed by an individual instance. Each such instance</text>
+ <text
+ class="text_small"
+ x="30"
+ y="205"
+ id="text139">uses a different port.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="225"
+ id="text141">6)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="225"
+ id="text143">No client application is allowed to connect to 'template0'.</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
new file mode 100644
index 0000000000..022bc45560
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="685px"
+ viewBox="0 0 900 685" >
+
+ <title>Server (Hardware, Container, or VM)</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_0">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">(more system schemas)</text>
+ </symbol>
+
+ <!-- same as before, but one more schema -->
+ <symbol id="rectangle_special_1">
+ <!-- the database -->
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="125">'my_schema' (optional)</text>
+ <text class="text_small" x="20" y="145">tables, views, ...</text>
+
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="190">(more system schemas)</text>
+ </symbol>
+
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="270" y="40">Server (Hardware, Container, or VM)</text>
+
+ <!-- two clusters -->
+ <g transform="translate(20 110)">
+ <rect x="0" y="0" width="790" height="555" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="180" y="25">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g transform="translate(45 110)">
+ <path d="M 5,0 v -30 h 790 v 555 h -30" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="190" y="-10">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+
+
+ <!-- database template 0 -->
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template0'</text>
+ </g>
+
+ <!-- database template 1 -->
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template1'</text>
+ </g>
+
+ <!-- database postgres -->
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'postgres'</text>
+ </g>
+
+ <!-- database my_db -->
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
+ </g>
+
+ <!-- global objects -->
+ <g transform="translate(320 330)">
+ <rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
+ <text class="text_normal" x="15" y="27">Global SQL objects</text>
+ <path d="M 0,5 l-65,-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ </g>
+
+ <!-- Some comments -->
+ <g transform="translate(335 405)">
+ <use xlink:href="#note" x="0" y="0" />
+
+ <text class="text_small" x="10" y="20">1)</text>
+ <text class="text_small" x="30" y="20">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text class="text_small" x="30" y="35">schema 'public'.</text>
+
+ <text class="text_small" x="10" y="55">2)</text>
+ <text class="text_small" x="30" y="55">More system schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="70">pg_temp, pg_toast.</text>
+
+ <text class="text_small" x="10" y="90">3)</text>
+ <text class="text_small" x="30" y="90">Global SQL objects: Some SQL objects are automatically active</text>
+ <text class="text_small" x="30" y="105">and known database- or even cluster-wide.</text>
+
+ <text class="text_small" x="10" y="125">4)</text>
+ <text class="text_small" x="30" y="125">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="140">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="155">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="175">5)</text>
+ <text class="text_small" x="30" y="175">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="190">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="205">uses a different port.</text>
+
+ <text class="text_small" x="10" y="225">6)</text>
+ <text class="text_small" x="30" y="225">No client application is allowed to connect to 'template0'.</text>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/directories-ink-svgo.svg b/doc/src/sgml/images/directories-ink-svgo.svg
new file mode 100644
index 0000000000..c03c2607ee
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink-svgo.svg
@@ -0,0 +1,164 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="640" viewBox="0 0 900 640">
+ <title>
+ Directory structure of a cluster
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <symbol id="directory" stroke="blue" stroke-width=".3" fill="aqua">
+ <title>
+ Directory
+ </title>
+ <path d="M0 10h110v20H0z"/>
+ <path d="M0 10V8l3-3h35l3 3v2"/>
+ </symbol>
+ <symbol id="file" stroke="black" fill="none">
+ <title>
+ File
+ </title>
+ <path stroke="blue" d="M0 0h40v50H0z"/>
+ <path d="M5 10h20" stroke-dasharray="4 2"/>
+ <path d="M5 17h15" stroke-dasharray="6 2"/>
+ <path d="M5 24h25" stroke-dasharray="4 2"/>
+ <path d="M5 31h20" stroke-dasharray="5 2"/>
+ </symbol>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="50" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Directory Structure
+ </text>
+ <g transform="translate(20 100)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /pg/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ An arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 130)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ data/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of cluster 'data' (see: PGDATA)
+ </text>
+ </g>
+ <g transform="translate(120 160)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ base/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing per-database subdirectories
+ </text>
+ </g>
+ <g transform="translate(170 190)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 1/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of first database 'template0'
+ </text>
+ </g>
+ <g transform="translate(170 220)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12992/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of second database 'template1'
+ </text>
+ </g>
+ <g transform="translate(170 250)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12999/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of third database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(170 280)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ nnnnn/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Optional: more subdirectories for databases, e.g. 'my_db'
+ </text>
+ </g>
+ <g transform="translate(120 310)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ global/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory with information about Global SQL Objects
+ </text>
+ </g>
+ <g transform="translate(120 340)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_wal/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 370)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_xact/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for transaction commit status ('pg_clog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 400)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_tblspc/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing symbolic links to tablespaces
+ </text>
+ </g>
+ <g transform="translate(120 430)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_... /
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Some more subdirectories
+ </text>
+ </g>
+ <g transform="translate(120 465)">
+ <use xlink:href="#file"/>
+ <use xlink:href="#file" x="50"/>
+ <text x="200" y="26" class="text_normal">
+ 'postmaster.pid' and other files with cluster-wide relevance
+ </text>
+ </g>
+ <g transform="translate(20 540)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /xyz/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ Same or another arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 570)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ cluster_2/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of another cluster 'cluster_2'
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-ink.svg b/doc/src/sgml/images/directories-ink.svg
new file mode 100644
index 0000000000..238905cde8
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink.svg
@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="640px"
+ viewBox="0 0 900 640"
+ id="svg4006"
+ sodipodi:docname="directories-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata4010">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Directory structure of a cluster</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview4008"
+ showgrid="false"
+ inkscape:zoom="0.36875"
+ inkscape:cx="450"
+ inkscape:cy="320"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg4006" />
+ <title
+ id="title3856">Directory structure of a cluster</title>
+ <style
+ type="text/css"
+ id="style3858">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs3880">
+ <!-- Directory -->
+ <symbol
+ id="directory"
+ stroke="blue"
+ stroke-width="0.3px"
+ fill="aqua">
+ <title
+ id="title3860">Directory</title>
+ <rect
+ x="0"
+ y="10"
+ width="110"
+ height="20"
+ id="rect3862" />
+ <path
+ d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2"
+ id="path3864" />
+ </symbol>
+ <!-- File -->
+ <symbol
+ id="file"
+ stroke="black"
+ fill="none">
+ <title
+ id="title3867">File</title>
+ <rect
+ x="0"
+ y="0"
+ width="40"
+ height="50"
+ stroke="blue"
+ id="rect3869" />
+ <path
+ d="M 5,10 h 20"
+ stroke-dasharray="4 2"
+ id="path3871" />
+ <path
+ d="M 5,17 h 15"
+ stroke-dasharray="6 2"
+ id="path3873" />
+ <path
+ d="M 5,24 h 25"
+ stroke-dasharray="4 2"
+ id="path3875" />
+ <path
+ d="M 5,31 h 20"
+ stroke-dasharray="5 2"
+ id="path3877" />
+ </symbol>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect3882" />
+ <!-- caption -->
+ <text
+ x="200"
+ y="50"
+ class="text_big"
+ id="text3884">Directory Structure</text>
+ <!-- the directories -->
+ <g
+ transform="translate(20, 100)"
+ id="g3892">
+ <use
+ xlink:href="#directory"
+ id="use3886" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3888">... /pg/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text3890">An arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 130)"
+ id="g3900">
+ <use
+ xlink:href="#directory"
+ id="use3894" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3896">data/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text3898">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+ <g
+ transform="translate(120, 160)"
+ id="g3908">
+ <use
+ xlink:href="#directory"
+ id="use3902" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3904">base/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text3906">Subdirectory containing per-database subdirectories</text>
+ </g>
+ <!-- -->
+ <g
+ transform="translate(170, 190)"
+ id="g3916">
+ <use
+ xlink:href="#directory"
+ id="use3910" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3912">1/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text3914">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g
+ transform="translate(170, 220)"
+ id="g3924">
+ <use
+ xlink:href="#directory"
+ id="use3918" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3920">12992/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text3922">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g
+ transform="translate(170, 250)"
+ id="g3932">
+ <use
+ xlink:href="#directory"
+ id="use3926" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3928">12999/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text3930">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g
+ transform="translate(170, 280)"
+ id="g3940">
+ <use
+ xlink:href="#directory"
+ id="use3934" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3936">nnnnn/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text3938">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+ <g
+ transform="translate(120, 310)"
+ id="g3948">
+ <use
+ xlink:href="#directory"
+ id="use3942" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3944">global/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text3946">Subdirectory with information about Global SQL Objects</text>
+ </g>
+ <g
+ transform="translate(120, 340)"
+ id="g3956">
+ <use
+ xlink:href="#directory"
+ id="use3950" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3952">pg_wal/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text3954">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 370)"
+ id="g3964">
+ <use
+ xlink:href="#directory"
+ id="use3958" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3960">pg_xact/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text3962">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 400)"
+ id="g3972">
+ <use
+ xlink:href="#directory"
+ id="use3966" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3968">pg_tblspc/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text3970">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+ <g
+ transform="translate(120, 430)"
+ id="g3980">
+ <use
+ xlink:href="#directory"
+ id="use3974" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3976">pg_... /</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text3978">Some more subdirectories</text>
+ </g>
+ <g
+ transform="translate(120, 465)"
+ id="g3988">
+ <use
+ xlink:href="#file"
+ x="0"
+ y="0"
+ id="use3982" />
+ <use
+ xlink:href="#file"
+ x="50"
+ y="0"
+ id="use3984" />
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text3986">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+ <!-- next cluster -->
+ <g
+ transform="translate(20, 540)"
+ id="g3996">
+ <use
+ xlink:href="#directory"
+ id="use3990" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3992">... /xyz/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text3994">Same or another arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 570)"
+ id="g4004">
+ <use
+ xlink:href="#directory"
+ id="use3998" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text4000">cluster_2/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text4002">Root of another cluster 'cluster_2'</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
new file mode 100644
index 0000000000..757342a554
--- /dev/null
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="640px"
+ viewBox="0 0 900 640">
+
+ <title>Directory structure of a cluster</title>
+
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Directory -->
+ <symbol id="directory" stroke="blue" stroke-width="0.3px" fill="aqua">
+ <title>Directory</title>
+ <rect x="0" y="10" width="110" height="20" />
+ <path d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2" />
+ </symbol>
+
+ <!-- File -->
+ <symbol id="file" stroke="black" fill="none" >
+ <title>File</title>
+ <rect x="0" y="0" width="40" height="50" stroke="blue" />
+ <path d="M 5,10 h 20" stroke-dasharray="4 2" />
+ <path d="M 5,17 h 15" stroke-dasharray="6 2" />
+ <path d="M 5,24 h 25" stroke-dasharray="4 2" />
+ <path d="M 5,31 h 20" stroke-dasharray="5 2" />
+ </symbol>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption -->
+ <text x="200" y="50" class="text_big">Directory Structure</text>
+
+ <!-- the directories -->
+ <g transform="translate(20, 100)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /pg/</text>
+ <text x="300" y="26" class="text_normal">An arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 130)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">data/</text>
+ <text x="250" y="26" class="text_normal">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+
+ <g transform="translate(120, 160)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">base/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing per-database subdirectories</text>
+ </g>
+
+ <!-- -->
+ <g transform="translate(170, 190)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">1/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g transform="translate(170, 220)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12992/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g transform="translate(170, 250)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12999/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g transform="translate(170, 280)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">nnnnn/</text>
+ <text x="150" y="26" class="text_normal">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+
+ <g transform="translate(120, 310)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">global/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory with information about Global SQL Objects</text>
+ </g>
+
+ <g transform="translate(120, 340)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 370)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 400)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+
+ <g transform="translate(120, 430)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_... /</text>
+ <text x="200" y="26" class="text_normal">Some more subdirectories</text>
+ </g>
+
+ <g transform="translate(120, 465)">
+ <use xlink:href="#file" x="0" y="0" />
+ <use xlink:href="#file" x="50" y="0" />
+ <text x="200" y="26" class="text_normal">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+
+ <!-- next cluster -->
+ <g transform="translate(20, 540)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /xyz/</text>
+ <text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 570)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster 'cluster_2'</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink-svgo.svg b/doc/src/sgml/images/freeze-ink-svgo.svg
new file mode 100644
index 0000000000..fecefbeaf3
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink-svgo.svg
@@ -0,0 +1,84 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="320" viewBox="0 0 850 320">
+ <title>
+ Freeze
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100)"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="70" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ <tspan font-style="italic" font-weight="700">Freeze</tspan> to keep visible
+ </text>
+ <g fill="none" transform="translate(170 190)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_120" startOffset="11.2%">(1)</textPath> <textPath xlink:href="#Path_120" startOffset="61.2%">(5)</textPath> <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%">|</textPath> <textPath xlink:href="#Path_120" startOffset="34%">(2)</textPath> <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(3)</textPath> <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%">|</textPath> <textPath xlink:href="#Path_120" startOffset="55%">(4)</textPath>
+ </text>
+ <path d="M-80-80L80 80" stroke="black"/>
+ <text class="text_normal" letter-spacing="12" transform="rotate(45 40.78 -38.1)">
+ PAST
+ </text>
+ <text class="text_normal" letter-spacing="12" transform="rotate(-135 27.43 23.79)">
+ FUTURE
+ </text>
+ <use xlink:href="#frozenPoint" transform="rotate(10)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(25)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(40)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(55)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(70)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(85)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(100)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(115)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(130)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(145)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(160)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(175)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(190)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(205)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(220)"/>
+ </g>
+ <g class="text_normal" transform="translate(380 30)">
+ <text>
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25">
+ 1: txid_current + 2 ^ 31 (split-point)
+ </text>
+ <text y="50">
+ 2: autovacuum_freeze_max_age (200 mio.)
+ </text>
+ <text y="75">
+ 3: vacuum_freeze_table_age (150 mio.)
+ </text>
+ <text y="100">
+ 4: vacuum_freeze_min_age (50 mio.)
+ </text>
+ <text y="125">
+ 5: txid_current (split-point, jungest xid)
+ </text>
+ <text y="155">
+ per table: pg_class.relfrozenxid <tspan font-weight="700">must</tspan> be between (1) and (5);
+ </text>
+ <text y="175" x="75">
+ normally it is between (3) and (4)
+ </text>
+ <use xlink:href="#unfrozenPoint" transform="translate(106 200)"/>
+ <text y="205" x="20">
+ Unfrozen xid
+ </text>
+ <use xlink:href="#frozenPoint" transform="translate(106 224)"/>
+ <text y="230" x="20">
+ Frozen xid
+ </text>
+ <text y="260">
+ (figure is out of scale)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink.svg b/doc/src/sgml/images/freeze-ink.svg
new file mode 100644
index 0000000000..da1f510a5c
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink.svg
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="320px"
+ viewBox="0 0 850 320"
+ id="svg4157"
+ sodipodi:docname="freeze-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata4161">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Freeze</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview4159"
+ showgrid="false"
+ inkscape:zoom="0.44470588"
+ inkscape:cx="425"
+ inkscape:cy="160"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg4157" />
+ <title
+ id="title4012">Freeze</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4014">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs4021">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle
+ id="frozenPoint"
+ r="3"
+ stroke="green"
+ fill="green"
+ transform="translate(-100, 0)" />
+ <circle
+ id="unfrozenPoint"
+ r="3"
+ stroke="green"
+ fill="none"
+ transform="translate(-100, 0)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect4023" />
+ <text
+ class="text_big"
+ x="70"
+ y="40"
+ id="text4027"><tspan
+ style="font-style:italic;font-weight:bold"
+ id="tspan4025">
+ Freeze</tspan>
+ to keep visible</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 190)"
+ id="g4121">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle4029" />
+ <text
+ class="text_normal"
+ id="text4053">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath4031">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath4033">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath4035">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="11.2%"
+ id="textPath4037">(1)</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="61.2%"
+ id="textPath4039">(5)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="red"
+ stroke-width="3"
+ startOffset="34%"
+ id="textPath4041">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="34%"
+ id="textPath4043">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="black"
+ stroke-width="3"
+ startOffset="45%"
+ id="textPath4045">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath4047">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="green"
+ stroke-width="3"
+ startOffset="55%"
+ id="textPath4049">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="55%"
+ id="textPath4051">(4)</textPath>
+ </text>
+ <!-- split it into 'past' and 'future' -->
+ <path
+ d="M -80 -80 l 160 160"
+ stroke="black"
+ id="path4055" />
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(-15, -40) rotate(45)"
+ id="text4057">PAST</text>
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(30, 60) rotate(225)"
+ id="text4059">FUTURE</text>
+ <g
+ transform="rotate(10)"
+ id="g4063">
+ <use
+ xlink:href="#frozenPoint"
+ id="use4061" />
+ </g>
+ <g
+ transform="rotate(25)"
+ id="g4067">
+ <use
+ xlink:href="#frozenPoint"
+ id="use4065" />
+ </g>
+ <g
+ transform="rotate(40)"
+ id="g4071">
+ <use
+ xlink:href="#frozenPoint"
+ id="use4069" />
+ </g>
+ <g
+ transform="rotate(55)"
+ id="g4075">
+ <use
+ xlink:href="#frozenPoint"
+ id="use4073" />
+ </g>
+ <g
+ transform="rotate(70)"
+ id="g4079">
+ <use
+ xlink:href="#frozenPoint"
+ id="use4077" />
+ </g>
+ <g
+ transform="rotate(85)"
+ id="g4083">
+ <use
+ xlink:href="#frozenPoint"
+ id="use4081" />
+ </g>
+ <g
+ transform="rotate(100)"
+ id="g4087">
+ <use
+ xlink:href="#frozenPoint"
+ id="use4085" />
+ </g>
+ <g
+ transform="rotate(115)"
+ id="g4091">
+ <use
+ xlink:href="#frozenPoint"
+ id="use4089" />
+ </g>
+ <g
+ transform="rotate(130)"
+ id="g4095">
+ <use
+ xlink:href="#frozenPoint"
+ id="use4093" />
+ </g>
+ <g
+ transform="rotate(145)"
+ id="g4099">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use4097" />
+ </g>
+ <g
+ transform="rotate(160)"
+ id="g4103">
+ <use
+ xlink:href="#frozenPoint"
+ id="use4101" />
+ </g>
+ <g
+ transform="rotate(175)"
+ id="g4107">
+ <use
+ xlink:href="#frozenPoint"
+ id="use4105" />
+ </g>
+ <g
+ transform="rotate(190)"
+ id="g4111">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use4109" />
+ </g>
+ <g
+ transform="rotate(205)"
+ id="g4115">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use4113" />
+ </g>
+ <g
+ transform="rotate(220)"
+ id="g4119">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use4117" />
+ </g>
+ </g>
+ <!-- legend -->
+ <g
+ class="text_normal"
+ transform="translate(380 30)"
+ id="g4155">
+ <text
+ id="text4127">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan4123">^</tspan>
+<tspan
+ dy="5"
+ id="tspan4125">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text4129">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text
+ y="50"
+ id="text4131">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text
+ y="75"
+ id="text4133">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text
+ y="100"
+ id="text4135">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text
+ y="125"
+ id="text4137">5: txid_current (split-point, jungest xid)</text>
+ <text
+ y="155"
+ id="text4141">per table: pg_class.relfrozenxid
+ <tspan
+ style="font-weight:bold"
+ id="tspan4139">must</tspan>
+ be between (1) and (5);</text>
+ <text
+ y="175"
+ x="75"
+ id="text4143">normally it is between (3) and (4)</text>
+ <use
+ xlink:href="#unfrozenPoint"
+ transform="translate(106, 200)"
+ id="use4145" />
+ <text
+ y="205"
+ x="20"
+ id="text4147">Unfrozen xid</text>
+ <use
+ xlink:href="#frozenPoint"
+ transform="translate(106, 224)"
+ id="use4149" />
+ <text
+ y="230"
+ x="20"
+ id="text4151">Frozen xid</text>
+ <text
+ y="260"
+ id="text4153">(figure is out of scale)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-raw.svg b/doc/src/sgml/images/freeze-raw.svg
new file mode 100644
index 0000000000..7e556add2f
--- /dev/null
+++ b/doc/src/sgml/images/freeze-raw.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="320px"
+ viewBox="0 0 850 320" >
+
+ <title>Freeze</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100, 0)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100, 0)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="70" y="40"><tspan style="font-style:italic;font-weight:bold">
+ Freeze</tspan> to keep visible</text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 190)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_120" startOffset="11.2%" >(1)</textPath>
+ <textPath xlink:href="#Path_120" startOffset="61.2%" >(5)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="34%" >(2)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(3)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="55%" >(4)</textPath>
+
+ </text>
+
+ <!-- split it into 'past' and 'future' -->
+ <path d="M -80 -80 l 160 160" stroke="black" />
+ <text class="text_normal" letter-spacing="12" transform="translate(-15, -40) rotate(45)">PAST</text>
+ <text class="text_normal" letter-spacing="12" transform="translate(30, 60) rotate(225)">FUTURE</text>
+
+ <g transform="rotate(10)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(25)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(40)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(55)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(70)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(85)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(100)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(115)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(130)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(145)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(160)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(175)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(190)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(205)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(220)"><use xlink:href="#unfrozenPoint"/></g>
+
+ </g>
+
+ <!-- legend -->
+ <g class="text_normal" transform="translate(380 30)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text y="50">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text y="75">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text y="100">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text y="125">5: txid_current (split-point, jungest xid)</text>
+ <text y="155">per table: pg_class.relfrozenxid
+ <tspan style="font-weight:bold">must</tspan> be between (1) and (5);</text>
+ <text y="175" x="75">normally it is between (3) and (4)</text>
+
+ <use xlink:href="#unfrozenPoint" transform="translate(106, 200)"/>
+ <text y="205" x="20">Unfrozen xid</text>
+
+ <use xlink:href="#frozenPoint" transform="translate(106, 224)"/>
+ <text y="230" x="20">Frozen xid</text>
+
+ <text y="260">(figure is out of scale)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
new file mode 100644
index 0000000000..b5cdec9553
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
@@ -0,0 +1,83 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="720" height="430" viewBox="0 0 720 430">
+ <title>
+ Hierarchy of Internal Objects
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Hierarchy of internal Objects
+ </text>
+ <g fill="none">
+ <g transform="translate(350 240)">
+ <ellipse rx="320" ry="170" stroke="blue"/>
+ <text class="text_normal" x="-140" y="-130">
+ Cluster
+ </text>
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-60" y="5">
+ Database Names
+ </text>
+ </g>
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-40" y="5">
+ Tablespace
+ </text>
+ </g>
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-70" y="5">
+ Replication Origins
+ </text>
+ </g>
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue"/>
+ <text class="text_normal" x="-60" y="-3">
+ Subscription for
+ </text>
+ <text class="text_normal" x="-68" y="10">
+ Logical Replication
+ </text>
+ </g>
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-15" y="5">
+ Role
+ </text>
+ </g>
+ </g>
+ <g transform="translate(270 250)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2"/>
+ <text class="text_normal" x="-60" y="-80">
+ Database
+ </text>
+ <g transform="translate(-150 -30)">
+ <ellipse rx="50" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Extension
+ </text>
+ </g>
+ <g transform="translate(-155 35)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Collation
+ </text>
+ </g>
+ <g transform="translate(30 20)">
+ <ellipse rx="140" ry="70" stroke="blue"/>
+ <text class="text_normal" x="-80" y="-35">
+ Schema
+ </text>
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue"/>
+ <text class="text_normal" x="-50" y="5">
+ Table, View, ...
+ </text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
new file mode 100644
index 0000000000..1571df24fe
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="720px"
+ height="430px"
+ viewBox="0 0 720 430"
+ id="svg4243"
+ sodipodi:docname="internal-objects-hierarchy-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata4249">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Hierarchy of Internal Objects</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs4247" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview4245"
+ showgrid="false"
+ inkscape:zoom="0.525"
+ inkscape:cx="360"
+ inkscape:cy="215"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg4243" />
+ <title
+ id="title4163">Hierarchy of Internal Objects</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4165">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect4167" />
+ <text
+ class="text_big"
+ x="200"
+ y="40"
+ id="text4169">Hierarchy of internal Objects</text>
+ <!-- set centre of figure and default values -->
+ <g
+ transform="translate(350 240)"
+ fill="none"
+ id="g4241">
+ <g
+ id="g4207">
+ <ellipse
+ rx="320"
+ ry="170"
+ stroke="blue"
+ id="ellipse4171" />
+ <text
+ class="text_normal"
+ x="-140"
+ y="-130"
+ id="text4173">Cluster</text>
+ <g
+ transform="translate(40 -125)"
+ id="g4179">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse4175" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="5"
+ id="text4177">Database Names</text>
+ </g>
+ <g
+ transform="translate(180 -70)"
+ id="g4185">
+ <ellipse
+ rx="60"
+ ry="20"
+ stroke="blue"
+ id="ellipse4181" />
+ <text
+ class="text_normal"
+ x="-40"
+ y="5"
+ id="text4183">Tablespace</text>
+ </g>
+ <g
+ transform="translate(230 -5)"
+ id="g4191">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse4187" />
+ <text
+ class="text_normal"
+ x="-70"
+ y="5"
+ id="text4189">Replication Origins</text>
+ </g>
+ <g
+ transform="translate(200 70)"
+ id="g4199">
+ <ellipse
+ rx="78"
+ ry="27"
+ stroke="blue"
+ id="ellipse4193" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-3"
+ id="text4195">Subscription for</text>
+ <text
+ class="text_normal"
+ x="-68"
+ y="10"
+ id="text4197">Logical Replication</text>
+ </g>
+ <g
+ transform="translate(100 120)"
+ id="g4205">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse4201" />
+ <text
+ class="text_normal"
+ x="-15"
+ y="5"
+ id="text4203">Role</text>
+ </g>
+ </g>
+ <g
+ transform="translate(-80 10)"
+ id="g4239">
+ <ellipse
+ rx="220"
+ ry="110"
+ stroke="blue"
+ stroke-width="2px"
+ id="ellipse4209" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-80"
+ id="text4211">Database</text>
+ <g
+ transform="translate(-120 -50)"
+ id="g4237">
+ <g
+ transform="translate(-30 20)"
+ id="g4217">
+ <ellipse
+ rx="50"
+ ry="20"
+ stroke="blue"
+ id="ellipse4213" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text4215">Extension</text>
+ </g>
+ <g
+ transform="translate(-35 85)"
+ id="g4223">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse4219" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text4221">Collation</text>
+ </g>
+ <g
+ transform="translate(150 70)"
+ id="g4235">
+ <ellipse
+ rx="140"
+ ry="70"
+ stroke="blue"
+ id="ellipse4225" />
+ <text
+ class="text_normal"
+ x="-80"
+ y="-35"
+ id="text4227">Schema</text>
+ <g
+ transform="translate(20 10)"
+ id="g4233">
+ <ellipse
+ rx="90"
+ ry="30"
+ stroke="blue"
+ id="ellipse4229" />
+ <text
+ class="text_normal"
+ x="-50"
+ y="5"
+ id="text4231">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
new file mode 100644
index 0000000000..a58f334fe3
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="720px" height="430px"
+ viewBox="0 0 720 430" >
+
+ <title>Hierarchy of Internal Objects</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="200" y="40">Hierarchy of internal Objects</text>
+
+
+ <!-- set centre of figure and default values -->
+ <g transform="translate(350 240)" fill="none">
+
+ <g>
+ <ellipse rx="320" ry="170" stroke="blue" />
+ <text class="text_normal" x="-140" y="-130">Cluster</text>
+
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-60" y="5">Database Names</text>
+ </g>
+
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue" />
+ <text class="text_normal" x="-40" y="5">Tablespace</text>
+ </g>
+
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-70" y="5">Replication Origins</text>
+ </g>
+
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue" />
+ <text class="text_normal" x="-60" y="-3">Subscription for</text>
+ <text class="text_normal" x="-68" y="10">Logical Replication</text>
+ </g>
+
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-15" y="5">Role</text>
+ </g>
+
+ </g>
+
+ <g transform="translate(-80 10)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2px" />
+ <text class="text_normal" x="-60" y="-80">Database</text>
+
+ <g transform="translate(-120 -50)">
+ <g transform="translate(-30 20)">
+ <ellipse rx="50" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Extension</text>
+ </g>
+
+ <g transform="translate(-35 85)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Collation</text>
+ </g>
+
+ <g transform="translate(150 70)">
+ <ellipse rx="140" ry="70" stroke="blue" />
+ <text class="text_normal" x="-80" y="-35">Schema</text>
+
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue" />
+ <text class="text_normal" x="-50" y="5">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink-svgo.svg b/doc/src/sgml/images/mvcc-ink-svgo.svg
new file mode 100644
index 0000000000..6ff6a4da79
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink-svgo.svg
@@ -0,0 +1,151 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="150" viewBox="0 0 850 150">
+ <title>
+ MVCC
+ </title>
+ <style>
+ .text_small{font-style:normal;font-weight:400;font-size:10px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <marker id="triangle_1" markerWidth="10" markerHeight="10" refX="5" refY="5" orient="auto" stroke="black" fill="none">
+ <path d="M0 0l10 5-10 5"/>
+ </marker>
+ <path id="arrow" d="M0 0q20-15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+ <g id="tuple" stroke="black">
+ <path d="M80 0H0v20h80M29 0v20M60 0v20"/>
+ <path d="M80 0h15M80 20h15" stroke-dasharray="2 1"/>
+ </g>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <g fill="none">
+ <g transform="translate(20 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">123</tspan> <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)" fill="#00f">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 83)" fill="#00f">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(185 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">135</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 53)" fill="#00f">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(350 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">142</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 23)" fill="#00f">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(515 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">821</tspan> <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 821
+ </text>
+ <text class="text_small" transform="translate(125 23)">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(740 110)">
+ <path d="M102-20H-18v60" stroke="black"/>
+ <text font-weight="400" font-size="14" font-family=""Open Sans",sans-serif" fill="#000">
+ Legend
+ </text>
+ <use xlink:href="#tuple" transform="translate(0 10)"/>
+ <text class="text_small" transform="translate(3 23)">
+ xmin
+ </text>
+ <text class="text_small" transform="translate(32 23)">
+ xmax
+ </text>
+ <text class="text_small" transform="translate(65 23)">
+ data
+ </text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink.svg b/doc/src/sgml/images/mvcc-ink.svg
new file mode 100644
index 0000000000..80ae8d29e0
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink.svg
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="150px"
+ viewBox="0 0 850 150"
+ id="svg4396"
+ sodipodi:docname="mvcc-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata4400">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>MVCC</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1266"
+ inkscape:window-height="788"
+ id="namedview4398"
+ showgrid="false"
+ inkscape:zoom="0.44470588"
+ inkscape:cx="425"
+ inkscape:cy="68.253968"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg4396" />
+ <title
+ id="title4251">MVCC</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4253">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs4264">
+ <marker
+ id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto"
+ stroke="black"
+ fill="none">
+ <path
+ d="M 0,0 L 10,5 L 0,10"
+ id="path4255" />
+ </marker>
+ <g
+ id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path
+ d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20"
+ stroke="black"
+ id="path4258" />
+ <!-- prolong the rectangle -->
+ <path
+ d="M 80 0 h 15 M 80 20 h 15"
+ stroke="black"
+ stroke-dasharray="2 1"
+ id="path4260" />
+ </g>
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path
+ id="arrow"
+ d="M 0 0 Q 20 -15 40 0"
+ stroke="black"
+ marker-end="url(#triangle_1)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect4266" />
+ <!-- set default values -->
+ <g
+ fill="none"
+ id="g4394">
+ <!-- start plus first INSERT -->
+ <g
+ transform="translate(20, 40)"
+ id="g4284">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4272">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4268">123</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4270">: INSERT</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4274" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4276" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ style="fill:blue"
+ id="text4278">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text4280">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ style="fill:blue"
+ id="text4282">'x'</text>
+ </g>
+ <!-- first UPDATE -->
+ <g
+ transform="translate(185, 40)"
+ id="g4310">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4290">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4286">135</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4288">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4292" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use4294" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ style="fill:blue"
+ id="text4296">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text4298">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ style="fill:blue"
+ id="text4300">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4302" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text4304">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text4306">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text4308">'x'</text>
+ </g>
+ <!-- next UPDATE -->
+ <g
+ transform="translate(350, 40)"
+ id="g4344">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4316">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4312">142</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4314">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4318" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use4320" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ style="fill:blue"
+ id="text4322">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text4324">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ style="fill:blue"
+ id="text4326">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use4328" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text4330">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text4332">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text4334">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4336" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text4338">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text4340">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text4342">'x'</text>
+ </g>
+ <!-- DELETE -->
+ <g
+ transform="translate(515, 40)"
+ id="g4378">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4350">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4346">821</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4348">: DELTE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4352" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use4354" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text4356">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text4358">821</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ id="text4360">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use4362" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text4364">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ id="text4366">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text4368">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4370" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text4372">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text4374">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text4376">'x'</text>
+ </g>
+ <!-- LEGEND -->
+ <g
+ transform="translate(740, 110)"
+ id="g4392">
+ <path
+ d="M 102 -20 h -120 v 60"
+ stroke="black"
+ id="path4380" />
+ <text
+ class="text_normal"
+ transform="translate(0, 0)"
+ id="text4382">Legend</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(0, 10)"
+ id="use4384" />
+ <text
+ class="text_small"
+ transform="translate(3, 23)"
+ id="text4386">xmin</text>
+ <text
+ class="text_small"
+ transform="translate(32, 23)"
+ id="text4388">xmax</text>
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text4390">data</text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-raw.svg b/doc/src/sgml/images/mvcc-raw.svg
new file mode 100644
index 0000000000..ee27e3df7b
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-raw.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="150px"
+ viewBox="0 0 850 150" >
+
+ <title>MVCC</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <marker id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto" stroke="black" fill="none">
+ <path d="M 0,0 L 10,5 L 0,10" />
+ </marker>
+
+ <g id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20" stroke="black"/>
+ <!-- prolong the rectangle -->
+ <path d="M 80 0 h 15 M 80 20 h 15" stroke="black" stroke-dasharray="2 1"/>
+ </g>
+
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path id="arrow" d="M 0 0 Q 20 -15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- set default values -->
+ <g fill="none">
+
+ <!-- start plus first INSERT -->
+ <g transform="translate(20, 40)">
+
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">123</tspan>
+ <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)" style="fill:blue">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 83)" style="fill:blue">'x'</text>
+ </g>
+
+ <!-- first UPDATE -->
+ <g transform="translate(185, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">135</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 53)" style="fill:blue">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- next UPDATE -->
+ <g transform="translate(350, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">142</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 23)" style="fill:blue">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- DELETE -->
+ <g transform="translate(515, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">821</tspan>
+ <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">821</text>
+ <text class="text_small" transform="translate(125, 23)">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- LEGEND -->
+ <g transform="translate(740, 110)">
+ <path d="M 102 -20 h -120 v 60" stroke="black"/>
+ <text class="text_normal" transform="translate(0, 0)">Legend</text>
+ <use xlink:href="#tuple" transform="translate(0, 10)"/>
+ <text class="text_small" transform="translate(3, 23)">xmin</text>
+ <text class="text_small" transform="translate(32, 23)">xmax</text>
+ <text class="text_small" transform="translate(65, 23)">data</text>
+ </g>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink-svgo.svg b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
new file mode 100644
index 0000000000..aa0445352d
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
@@ -0,0 +1,285 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 900 600">
+ <title>
+ PG Overall Server Architecture
+ </title>
+ <style>
+ .text_big{font-style:normal}.text_big,.text_comment,.text_normal,.text_small{font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_normal,.text_small{font-style:normal}.text_small{font-size:12px}.text_normal{font-size:14px}.text_big{font-size:24px}.text_comment{font-style:italic;font-size:14px}
+ </style>
+ <defs>
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (200 x 20 px)
+ </title>
+ <path d="M200 10v10H0V0h190v10h10L190 0"/>
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (250 x 20 px)
+ </title>
+ <path d="M250 10v10H0V0h240v10h10L240 0"/>
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (100 x 35 px)
+ </title>
+ <path d="M100 10v25H0V0h90v10h10L90 0"/>
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (170 x 50 px)
+ </title>
+ <path d="M170 10v40H0V0h160v10h10L160 0"/>
+ </symbol>
+ <symbol id="state_300x120">
+ <title>
+ UML State (300x120)
+ </title>
+ <rect width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>
+ UML State (350x120)
+ </title>
+ <rect width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="disc" stroke="blue" fill="none">
+ <title>
+ Disc
+ </title>
+ <ellipse cx="51" cy="13" rx="50" ry="12"/>
+ <path d="M1 13v60"/>
+ <path d="M101 13v60"/>
+ <path d="M1 73a50 12 0 00100 0"/>
+ </symbol>
+ <symbol id="laptop" stroke="black" fill="none">
+ <title>
+ Laptop
+ </title>
+ <path d="M20 40V0h54v40l15 15H5l15-15h54"/>
+ <path d="M23 3h48v34H23z"/>
+ <path d="M30 10h20"/>
+ <path d="M30 15h25"/>
+ <path d="M30 20h10"/>
+ <path d="M30 30h20"/>
+ <path d="M25 50h45l2 2H22z"/>
+ </symbol>
+ <marker id="arrowhead_start" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto">
+ <path d="M6 0L0 3l6 3" stroke="black" fill="none"/>
+ </marker>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="15" y="40" class="text_big">
+ Client
+ </text>
+ <text x="140" y="40" class="text_big">
+ Server
+ </text>
+ <use xlink:href="#laptop" x="5" y="210"/>
+ <g transform="translate(130 70)">
+ <use xlink:href="#state_350x120"/>
+ <text x="5" y="20" class="text_normal">
+ maintenance_work_mem (per connection)
+ </text>
+ <text x="5" y="45" class="text_normal">
+ work_mem (per query operation)
+ </text>
+ <text x="5" y="70" class="text_normal">
+ autovacuum_work_mem (per worker process)
+ </text>
+ <text x="5" y="95" class="text_normal">
+ temp_buffer (per connection)
+ </text>
+ <text x="5" y="110" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_200x20" x="140" y="-15"/>
+ <text x="150" class="text_comment">
+ Individual Memory
+ </text>
+ </g>
+ <g transform="translate(520 70)">
+ <use xlink:href="#state_300x120"/>
+ <text x="10" y="30" class="text_normal">
+ shared_buffers (heap and index)
+ </text>
+ <text x="10" y="70" class="text_normal">
+ wal_buffers (WAL records)
+ </text>
+ <text x="10" y="100" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_250x20" x="40" y="-15"/>
+ <text x="50" class="text_comment">
+ Shared Memory (per Instance)
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M180 215h250v30H180z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(180 215)">
+ Postmaster
+ </text>
+ <path d="M90 230h75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 230)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 1
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M150 315h370v30H150z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(150 315)">
+ Backend processes (one per connection)
+ </text>
+ <path d="M155 315v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M160 310v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M90 240l63 63" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 290)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 3
+ </text>
+ </g>
+ <path d="M360 250v50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180 255)">
+ <use xlink:href="#note_250x20"/>
+ <text x="10" y="15" class="text_comment">
+ Creates backend processes
+ </text>
+ </g>
+ <g transform="translate(360 281)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 2
+ </text>
+ </g>
+ <path d="M460 300V200" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M498 300V95h30" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M508 300V135h20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M550 220h120v30H550z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(550 220)">
+ WAL Writer
+ </text>
+ <path d="M590 150v65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M590 255v230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 340h140v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 340)">
+ Checkpointer
+ </text>
+ <path d="M740 110v220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 355H475v130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M700 330V150" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50"/>
+ <text x="60" y="-35" class="text_comment">
+ Checkpoint
+ </text>
+ <text x="60" y="-20" class="text_comment">
+ Record
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M610 380h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 380)">
+ Background Writer
+ </text>
+ <path d="M770 110v260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 395H485v90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 420h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 420)">
+ WAL Archiver
+ </text>
+ <path d="M620 485l30-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M690 455l30 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M135 380h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 380)">
+ Autovacuum
+ </text>
+ <path d="M140 380v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path d="M145 375v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path stroke="blue" fill="none" d="M135 430h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 430)">
+ Logger
+ </text>
+ <path stroke="blue" fill="none" d="M290 370h140v30H290z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(290 370)">
+ Stats Collector
+ </text>
+ <g transform="translate(145 490)">
+ <use xlink:href="#disc"/>
+ <text x="35" y="45" class="text_normal">
+ Log
+ </text>
+ <text x="20" y="60" class="text_small">
+ text lines,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <path d="M195 465v20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(410 490)">
+ <use xlink:href="#disc"/>
+ <text x="10" y="40" class="text_normal">
+ Heap and
+ </text>
+ <text x="25" y="55" class="text_normal">
+ Index
+ </text>
+ <text x="15" y="70" class="text_small">
+ binary blocks,
+ </text>
+ <text x="30" y="80" class="text_small">
+ random
+ </text>
+ </g>
+ <path d="M450 485V350" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(295 420)">
+ <use xlink:href="#note_170x50"/>
+ <text x="5" y="15" class="text_comment">
+ Read heap and index
+ </text>
+ <text x="5" y="30" class="text_comment">
+ pages and transfer
+ </text>
+ <text x="5" y="45" class="text_comment">
+ them to shared_buffers
+ </text>
+ </g>
+ <g transform="translate(550 490)">
+ <use xlink:href="#disc"/>
+ <text x="30" y="45" class="text_normal">
+ WAL
+ </text>
+ <text x="10" y="60" class="text_small">
+ binary records,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <g transform="translate(690 490)">
+ <use xlink:href="#disc"/>
+ <text x="16" y="45" class="text_normal">
+ Archived
+ </text>
+ <text x="36" y="60" class="text_normal">
+ WAL
+ </text>
+ </g>
+ <path d="M110 20v550" stroke="black" fill="none"/>
+ <g transform="rotate(90 -33.5 156.5)">
+ <use xlink:href="#note_200x20"/>
+ <text class="text_comment" x="10" y="15">
+ Via TCP/IP or socket
+ </text>
+ </g>
+ <text class="text_big" x="95" transform="rotate(90 425 425)">
+ RAM
+ </text>
+ <text class="text_big" x="250" transform="rotate(90 425 425)">
+ PROCESSES
+ </text>
+ <text class="text_big" x="500" transform="rotate(90 425 425)">
+ FILES
+ </text>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink.svg b/doc/src/sgml/images/ram-proc-file-ink.svg
new file mode 100644
index 0000000000..9ef89639c4
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink.svg
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="600px"
+ viewBox="0 0 900 600"
+ id="svg4706"
+ sodipodi:docname="ram-proc-file-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata4710">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>PG Overall Server Architecture</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1282"
+ inkscape:window-height="733"
+ id="namedview4708"
+ showgrid="false"
+ inkscape:zoom="0.39333333"
+ inkscape:cx="450"
+ inkscape:cy="292.37288"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg4706" />
+ <title
+ id="title4402">PG Overall Server Architecture</title>
+ <style
+ type="text/css"
+ id="style4404">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs4470">
+ <!-- Some notes in different sizes -->
+ <symbol
+ id="note_200x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4406">UML Note (200 x 20 px)</title>
+ <path
+ d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10"
+ id="path4408" />
+ </symbol>
+ <symbol
+ id="note_250x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4411">UML Note (250 x 20 px)</title>
+ <path
+ d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10"
+ id="path4413" />
+ </symbol>
+ <symbol
+ id="note_100x35"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4416">UML Note (100 x 35 px)</title>
+ <path
+ d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10"
+ id="path4418" />
+ </symbol>
+ <symbol
+ id="note_170x50"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4421">UML Note (170 x 50 px)</title>
+ <path
+ d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10"
+ id="path4423" />
+ </symbol>
+ <!-- UML states (used for buffers) -->
+ <symbol
+ id="state_300x120">
+ <title
+ id="title4426">UML State (300x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="300"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect4428" />
+ </symbol>
+ <symbol
+ id="state_350x120">
+ <title
+ id="title4431">UML State (350x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="350"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect4433" />
+ </symbol>
+ <!-- Discs -->
+ <symbol
+ id="disc"
+ stroke="blue"
+ fill="none">
+ <title
+ id="title4436">Disc</title>
+ <ellipse
+ cx="51"
+ cy="13"
+ rx="50"
+ ry="12"
+ id="ellipse4438" />
+ <!-- top -->
+ <path
+ d="M 1,13 v 60"
+ id="path4440" />
+ <!-- left -->
+ <path
+ d="M 101,13 v 60"
+ id="path4442" />
+ <!-- right -->
+ <path
+ d="M 1,73 A 50, 12, 0, 0, 0, 101,73"
+ id="path4444" />
+ <!-- bottom -->
+ </symbol>
+ <!-- Laptop -->
+ <symbol
+ id="laptop"
+ stroke="black"
+ fill="none">
+ <title
+ id="title4447">Laptop</title>
+ <path
+ d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54"
+ id="path4449" />
+ <rect
+ x="23"
+ y="3"
+ width="48"
+ height="34"
+ id="rect4451" />
+ <!-- symbolize some lines -->
+ <path
+ d="M 30,10 h 20"
+ id="path4453" />
+ <path
+ d="M 30,15 h 25"
+ id="path4455" />
+ <path
+ d="M 30,20 h 10"
+ id="path4457" />
+ <path
+ d="M 30,30 h 20"
+ id="path4459" />
+ <!-- symbolize keyboard -->
+ <path
+ d="M 25,50 h 45 l 2,2 h -50 z "
+ id="path4461" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path4464" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path4467" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect4472" />
+ <!-- caption, client side -->
+ <text
+ x="15"
+ y="40"
+ class="text_big"
+ id="text4474">Client</text>
+ <text
+ x="140"
+ y="40"
+ class="text_big"
+ id="text4476">Server</text>
+ <use
+ xlink:href="#laptop"
+ x="5"
+ y="210"
+ id="use4478" />
+ <!-- individual memory -->
+ <g
+ transform="translate(130, 70)"
+ id="g4496">
+ <use
+ xlink:href="#state_350x120"
+ x="0"
+ y="0"
+ id="use4480" />
+ <text
+ x="5"
+ y="20"
+ class="text_normal"
+ id="text4482">maintenance_work_mem (per connection)</text>
+ <text
+ x="5"
+ y="45"
+ class="text_normal"
+ id="text4484">work_mem (per query operation)</text>
+ <text
+ x="5"
+ y="70"
+ class="text_normal"
+ id="text4486">autovacuum_work_mem (per worker process)</text>
+ <text
+ x="5"
+ y="95"
+ class="text_normal"
+ id="text4488">temp_buffer (per connection)</text>
+ <text
+ x="5"
+ y="110"
+ class="text_normal"
+ id="text4490">...</text>
+ <use
+ xlink:href="#note_200x20"
+ x="140"
+ y="-15"
+ id="use4492" />
+ <text
+ x="150"
+ y="0"
+ class="text_comment"
+ id="text4494">Individual Memory</text>
+ </g>
+ <!-- shared memory -->
+ <g
+ transform="translate(520, 70)"
+ id="g4510">
+ <use
+ xlink:href="#state_300x120"
+ x="0"
+ y="0"
+ id="use4498" />
+ <text
+ x="10"
+ y="30"
+ class="text_normal"
+ id="text4500">shared_buffers (heap and index)</text>
+ <text
+ x="10"
+ y="70"
+ class="text_normal"
+ id="text4502">wal_buffers (WAL records)</text>
+ <text
+ x="10"
+ y="100"
+ class="text_normal"
+ id="text4504">...</text>
+ <use
+ xlink:href="#note_250x20"
+ x="40"
+ y="-15"
+ id="use4506" />
+ <text
+ x="50"
+ y="0"
+ class="text_comment"
+ id="text4508">Shared Memory (per Instance)</text>
+ </g>
+ <!-- postmaster -->
+ <g
+ transform="translate(180, 215)"
+ id="g4516">
+ <rect
+ width="250"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4512" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4514">Postmaster</text>
+ </g>
+ <path
+ d="M 90,230 h 75"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4518" />
+ <g
+ transform="translate(140, 230)"
+ id="g4524">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle4520" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text4522">1</text>
+ </g>
+ <!-- backend processes -->
+ <g
+ transform="translate(150, 315)"
+ id="g4534">
+ <rect
+ width="370"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4526" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4528">Backend processes (one per connection)</text>
+ <path
+ d="M 5,0 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4530" />
+ <path
+ d="M 10,-5 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4532" />
+ </g>
+ <path
+ d="M 90,240 153,303"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path4536" />
+ <g
+ transform="translate(140, 290)"
+ id="g4542">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle4538" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text4540">3</text>
+ </g>
+ <!-- connection between postmaster and backend processes -->
+ <path
+ d="M 360,250 v 50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4544" />
+ <g
+ transform="translate(180, 255)"
+ id="g4550">
+ <use
+ xlink:href="#note_250x20"
+ id="use4546" />
+ <text
+ x="10"
+ y="15"
+ class="text_comment"
+ id="text4548">Creates backend processes</text>
+ </g>
+ <g
+ transform="translate(360, 281)"
+ id="g4556">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle4552" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text4554">2</text>
+ </g>
+ <!-- backend process' access to individual memory -->
+ <path
+ d="M 460,300 v -100"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path4558" />
+ <!-- its access to shared buffers and WAL buffers -->
+ <path
+ d="M 498,300 v -205 h 30"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path4560" />
+ <path
+ d="M 508,300 v -165 h 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4562" />
+ <!-- WAL writer -->
+ <g
+ transform="translate(550, 220)"
+ id="g4568">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4564" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4566">WAL Writer</text>
+ </g>
+ <path
+ d="M 590,150 v 65"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4570" />
+ <path
+ d="M 590,255 v 230"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4572" />
+ <!-- Checkpoiner -->
+ <g
+ transform="translate(610, 340)"
+ id="g4578">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4574" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4576">Checkpointer</text>
+ </g>
+ <path
+ d="M 740,110 v 220"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4580" />
+ <path
+ d="M 605,355 h -130 v 130"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4582" />
+ <path
+ d="M 700,330 v -180"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4584" />
+ <g
+ transform="translate(570, 330)"
+ id="g4592">
+ <use
+ xlink:href="#note_100x35"
+ x="50"
+ y="-50"
+ id="use4586" />
+ <text
+ x="60"
+ y="-35"
+ class="text_comment"
+ id="text4588">Checkpoint</text>
+ <text
+ x="60"
+ y="-20"
+ class="text_comment"
+ id="text4590">Record</text>
+ </g>
+ <!-- BG writer -->
+ <g
+ transform="translate(610, 380)"
+ id="g4598">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4594" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4596">Background Writer</text>
+ </g>
+ <path
+ d="M 770,110 v 260"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4600" />
+ <path
+ d="M 605,395 h -120 v 90"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4602" />
+ <!-- Archiver -->
+ <g
+ transform="translate(610, 420)"
+ id="g4608">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4604" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4606">WAL Archiver</text>
+ </g>
+ <path
+ d="M 620,485 l 30,-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4610" />
+ <path
+ d="M 690,455 l 30, 30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4612" />
+ <!-- Vacuum -->
+ <g
+ transform="translate(135, 380)"
+ id="g4622">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4614" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4616">Autovacuum</text>
+ <path
+ d="M 5,0 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4618" />
+ <path
+ d="M 10,-5 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4620" />
+ </g>
+ <!-- Log Writer -->
+ <g
+ transform="translate(135, 430)"
+ id="g4628">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4624" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4626">Logger</text>
+ </g>
+ <!-- Stats Collector -->
+ <g
+ transform="translate(290, 370)"
+ id="g4634">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4630" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4632">Stats Collector</text>
+ </g>
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g
+ transform="translate(145, 490)"
+ id="g4644">
+ <use
+ xlink:href="#disc"
+ id="use4636" />
+ <text
+ x="35"
+ y="45"
+ class="text_normal"
+ id="text4638">Log</text>
+ <text
+ x="20"
+ y="60"
+ class="text_small"
+ id="text4640">text lines,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text4642">sequential</text>
+ </g>
+ <path
+ d="M 195,465 v 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4646" />
+ <g
+ transform="translate(410, 490)"
+ id="g4658">
+ <use
+ xlink:href="#disc"
+ id="use4648" />
+ <text
+ x="10"
+ y="40"
+ class="text_normal"
+ id="text4650">Heap and</text>
+ <text
+ x="25"
+ y="55"
+ class="text_normal"
+ id="text4652">Index</text>
+ <text
+ x="15"
+ y="70"
+ class="text_small"
+ id="text4654">binary blocks,</text>
+ <text
+ x="30"
+ y="80"
+ class="text_small"
+ id="text4656">random</text>
+ </g>
+ <path
+ d="M 450,485 v -135"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4660" />
+ <g
+ transform="translate(295, 420)"
+ id="g4670">
+ <use
+ xlink:href="#note_170x50"
+ id="use4662" />
+ <text
+ x="5"
+ y="15"
+ class="text_comment"
+ id="text4664">Read heap and index</text>
+ <text
+ x="5"
+ y="30"
+ class="text_comment"
+ id="text4666">pages and transfer</text>
+ <text
+ x="5"
+ y="45"
+ class="text_comment"
+ id="text4668">them to shared_buffers</text>
+ </g>
+ <g
+ transform="translate(550, 490)"
+ id="g4680">
+ <use
+ xlink:href="#disc"
+ id="use4672" />
+ <text
+ x="30"
+ y="45"
+ class="text_normal"
+ id="text4674">WAL</text>
+ <text
+ x="10"
+ y="60"
+ class="text_small"
+ id="text4676">binary records,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text4678">sequential</text>
+ </g>
+ <g
+ transform="translate(690, 490)"
+ id="g4688">
+ <use
+ xlink:href="#disc"
+ id="use4682" />
+ <text
+ x="16"
+ y="45"
+ class="text_normal"
+ id="text4684">Archived</text>
+ <text
+ x="36"
+ y="60"
+ class="text_normal"
+ id="text4686">WAL</text>
+ </g>
+ <!-- boarder between client and server side -->
+ <path
+ d="M 110,20 v 550"
+ stroke="black"
+ fill="none"
+ id="path4690" />
+ <g
+ transform="translate(123, 190) rotate(90)"
+ id="g4696">
+ <use
+ xlink:href="#note_200x20"
+ id="use4692" />
+ <text
+ class="text_comment"
+ x="10"
+ y="15"
+ id="text4694">Via TCP/IP or socket</text>
+ </g>
+ <!-- right side -->
+ <g
+ transform="translate(850, 0) rotate(90)"
+ id="g4704">
+ <text
+ class="text_big"
+ x="95"
+ id="text4698">RAM</text>
+ <text
+ class="text_big"
+ x="250"
+ id="text4700">PROCESSES</text>
+ <text
+ class="text_big"
+ x="500"
+ id="text4702">FILES</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-raw.svg b/doc/src/sgml/images/ram-proc-file-raw.svg
new file mode 100644
index 0000000000..775ba91571
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-raw.svg
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="600px"
+ viewBox="0 0 900 600">
+
+ <title>PG Overall Server Architecture</title>
+
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Some notes in different sizes -->
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>UML Note (200 x 20 px)</title>
+ <path d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>UML Note (250 x 20 px)</title>
+ <path d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>UML Note (100 x 35 px)</title>
+ <path d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>UML Note (170 x 50 px)</title>
+ <path d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- UML states (used for buffers) -->
+ <symbol id="state_300x120">
+ <title>UML State (300x120)</title>
+ <rect x="0" y="0" width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>UML State (350x120)</title>
+ <rect x="0" y="0" width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- Discs -->
+ <symbol id="disc" stroke="blue" fill="none" >
+ <title>Disc</title>
+ <ellipse cx="51" cy="13" rx="50" ry="12" /> <!-- top -->
+ <path d="M 1,13 v 60" /> <!-- left -->
+ <path d="M 101,13 v 60" /> <!-- right -->
+ <path d="M 1,73 A 50, 12, 0, 0, 0, 101,73" /> <!-- bottom -->
+ </symbol>
+
+ <!-- Laptop -->
+ <symbol id="laptop" stroke="black" fill="none" >
+ <title>Laptop</title>
+ <path d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54" />
+ <rect x="23" y="3" width="48" height="34" />
+ <!-- symbolize some lines -->
+ <path d="M 30,10 h 20" />
+ <path d="M 30,15 h 25" />
+ <path d="M 30,20 h 10" />
+ <path d="M 30,30 h 20" />
+ <!-- symbolize keyboard -->
+ <path d="M 25,50 h 45 l 2,2 h -50 z " />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption, client side -->
+ <text x="15" y="40" class="text_big">Client</text>
+ <text x="140" y="40" class="text_big">Server</text>
+ <use xlink:href="#laptop" x="5" y="210" />
+
+
+ <!-- individual memory -->
+ <g transform="translate(130, 70)">
+ <use xlink:href="#state_350x120" x="0" y="0" />
+ <text x="5" y="20" class="text_normal">maintenance_work_mem (per connection)</text>
+ <text x="5" y="45" class="text_normal">work_mem (per query operation)</text>
+ <text x="5" y="70" class="text_normal">autovacuum_work_mem (per worker process)</text>
+ <text x="5" y="95" class="text_normal">temp_buffer (per connection)</text>
+ <text x="5" y="110" class="text_normal">...</text>
+ <use xlink:href="#note_200x20" x="140" y="-15" />
+ <text x="150" y="0" class="text_comment">Individual Memory</text>
+ </g>
+
+ <!-- shared memory -->
+ <g transform="translate(520, 70)">
+ <use xlink:href="#state_300x120" x="0" y="0" />
+ <text x="10" y="30" class="text_normal">shared_buffers (heap and index)</text>
+ <text x="10" y="70" class="text_normal">wal_buffers (WAL records)</text>
+ <text x="10" y="100" class="text_normal">...</text>
+ <use xlink:href="#note_250x20" x="40" y="-15" />
+ <text x="50" y="0" class="text_comment">Shared Memory (per Instance)</text>
+ </g>
+
+ <!-- postmaster -->
+ <g transform="translate(180, 215)">
+ <rect width="250" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Postmaster</text>
+ </g>
+ <path d="M 90,230 h 75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 230)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">1</text>
+ </g>
+
+ <!-- backend processes -->
+ <g transform="translate(150, 315)">
+ <rect width="370" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Backend processes (one per connection)</text>
+ <path d="M 5,0 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <path d="M 90,240 153,303" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 290)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">3</text>
+ </g>
+
+ <!-- connection between postmaster and backend processes -->
+ <path d="M 360,250 v 50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180, 255)">
+ <use xlink:href="#note_250x20" />
+ <text x="10" y="15" class="text_comment">Creates backend processes</text>
+ </g>
+ <g transform="translate(360, 281)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">2</text>
+ </g>
+
+ <!-- backend process' access to individual memory -->
+ <path d="M 460,300 v -100" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <!-- its access to shared buffers and WAL buffers -->
+ <path d="M 498,300 v -205 h 30" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M 508,300 v -165 h 20" stroke="black" fill="none"
+ marker-end="url(#arrowhead_end)"/>
+
+ <!-- WAL writer -->
+ <g transform="translate(550, 220)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Writer</text>
+ </g>
+ <path d="M 590,150 v 65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 590,255 v 230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Checkpoiner -->
+ <g transform="translate(610, 340)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Checkpointer</text>
+ </g>
+ <path d="M 740,110 v 220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,355 h -130 v 130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 700,330 v -180" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570, 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50" />
+ <text x="60" y="-35" class="text_comment">Checkpoint</text>
+ <text x="60" y="-20" class="text_comment">Record</text>
+ </g>
+
+ <!-- BG writer -->
+ <g transform="translate(610, 380)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Background Writer</text>
+ </g>
+ <path d="M 770,110 v 260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,395 h -120 v 90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Archiver -->
+ <g transform="translate(610, 420)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Archiver</text>
+ </g>
+ <path d="M 620,485 l 30,-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 690,455 l 30, 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Vacuum -->
+ <g transform="translate(135, 380)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Autovacuum</text>
+ <path d="M 5,0 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <!-- Log Writer -->
+ <g transform="translate(135, 430)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Logger</text>
+ </g>
+
+ <!-- Stats Collector -->
+ <g transform="translate(290, 370)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Stats Collector</text>
+ </g>
+
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g transform="translate(145, 490)">
+ <use xlink:href="#disc" />
+ <text x="35" y="45" class="text_normal">Log</text>
+ <text x="20" y="60" class="text_small">text lines,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+ <path d="M 195,465 v 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(410, 490)">
+ <use xlink:href="#disc" />
+ <text x="10" y="40" class="text_normal">Heap and</text>
+ <text x="25" y="55" class="text_normal">Index</text>
+ <text x="15" y="70" class="text_small">binary blocks,</text>
+ <text x="30" y="80" class="text_small">random</text>
+ </g>
+ <path d="M 450,485 v -135" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(295, 420)">
+ <use xlink:href="#note_170x50" />
+ <text x="5" y="15" class="text_comment">Read heap and index</text>
+ <text x="5" y="30" class="text_comment">pages and transfer</text>
+ <text x="5" y="45" class="text_comment">them to shared_buffers</text>
+ </g>
+
+ <g transform="translate(550, 490)">
+ <use xlink:href="#disc" />
+ <text x="30" y="45" class="text_normal">WAL</text>
+ <text x="10" y="60" class="text_small">binary records,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+
+ <g transform="translate(690, 490)">
+ <use xlink:href="#disc" />
+ <text x="16" y="45" class="text_normal">Archived</text>
+ <text x="36" y="60" class="text_normal">WAL</text>
+ </g>
+
+ <!-- boarder between client and server side -->
+ <path d="M 110,20 v 550" stroke="black" fill="none" />
+ <g transform="translate(123, 190) rotate(90)">
+ <use xlink:href="#note_200x20" />
+ <text class="text_comment" x="10" y ="15">Via TCP/IP or socket</text>
+ </g>
+
+ <!-- right side -->
+ <g transform="translate(850, 0) rotate(90)">
+ <text class="text_big" x="95">RAM</text>
+ <text class="text_big" x="250">PROCESSES</text>
+ <text class="text_big" x="500">FILES</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink-svgo.svg b/doc/src/sgml/images/wraparound-ink-svgo.svg
new file mode 100644
index 0000000000..440394d577
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink-svgo.svg
@@ -0,0 +1,40 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="280" viewBox="0 0 850 280">
+ <title>
+ Cyclic usage of XIDs
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="370" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ Cyclic usage of XIDs modulo 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan>
+ </text>
+ <g fill="none" transform="translate(170 150)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_095" startOffset="30.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="30%">(1)</textPath> <textPath xlink:href="#Path_095" startOffset="45.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(2)</textPath> <textPath xlink:href="#Path_095" startOffset="50.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="50%">(3)</textPath> <textPath xlink:href="#Path_095" startOffset="62.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="62%">(4)</textPath>
+ </text>
+ </g>
+ <g class="text_normal">
+ <text transform="translate(400 130)">
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25" transform="translate(400 130)">
+ 1: oldest <tspan font-weight="700">active</tspan> xid (pg_stat_activity.backend_xmin)
+ </text>
+ <text y="50" transform="translate(400 130)">
+ 2: xmin of one row version
+ </text>
+ <text y="75" transform="translate(400 130)">
+ 3: xmax of the same row version
+ </text>
+ <text y="100" transform="translate(400 130)">
+ 4: jungest xid (txid_current)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink.svg b/doc/src/sgml/images/wraparound-ink.svg
new file mode 100644
index 0000000000..8240ec7d59
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="280px"
+ viewBox="0 0 850 280"
+ id="svg4775"
+ sodipodi:docname="wraparound-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata4779">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Cyclic usage of XIDs</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1348"
+ inkscape:window-height="810"
+ id="namedview4777"
+ showgrid="false"
+ inkscape:zoom="0.44470588"
+ inkscape:cx="425"
+ inkscape:cy="133.25397"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg4775" />
+ <title
+ id="title4712">Cyclic usage of XIDs</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4714">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs4719">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect4721" />
+ <text
+ class="text_big"
+ x="370"
+ y="40"
+ id="text4727">Cyclic usage of XIDs modulo 2
+ <tspan
+ dy="-5"
+ id="tspan4723">^</tspan>
+<tspan
+ dy="5"
+ id="tspan4725">32</tspan>
+</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 150)"
+ id="g4755">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle4729" />
+ <text
+ class="text_normal"
+ id="text4753">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath4731">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath4733">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath4735">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="30.5%"
+ id="textPath4737">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="30%"
+ id="textPath4739">(1)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="45.5%"
+ id="textPath4741">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath4743">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="50.5%"
+ id="textPath4745">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="50%"
+ id="textPath4747">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="62.5%"
+ id="textPath4749">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="62%"
+ id="textPath4751">(4)</textPath>
+ </text>
+ </g>
+ <g
+ class="text_normal"
+ transform="translate(400 130)"
+ id="g4773">
+ <text
+ id="text4761">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan4757">^</tspan>
+<tspan
+ dy="5"
+ id="tspan4759">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text4765">1: oldest <tspan
+ style="font-weight:bold"
+ id="tspan4763">active</tspan>
+ xid (pg_stat_activity.backend_xmin)</text>
+ <text
+ y="50"
+ id="text4767">2: xmin of one row version</text>
+ <text
+ y="75"
+ id="text4769">3: xmax of the same row version</text>
+ <text
+ y="100"
+ id="text4771">4: jungest xid (txid_current)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-raw.svg b/doc/src/sgml/images/wraparound-raw.svg
new file mode 100644
index 0000000000..c6e86fd488
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-raw.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="280px"
+ viewBox="0 0 850 280" >
+
+ <title>Cyclic usage of XIDs</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="370" y="40">Cyclic usage of XIDs modulo 2
+ <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan></text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 150)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_095" startOffset="30.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="30%" >(1)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="45.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(2)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="50.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="50%" >(3)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="62.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="62%" >(4)</textPath>
+ </text>
+ </g>
+
+ <g class="text_normal" transform="translate(400 130)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: oldest <tspan style="font-weight:bold">active</tspan> xid (pg_stat_activity.backend_xmin)</text>
+ <text y="50">2: xmin of one row version</text>
+ <text y="75">3: xmax of the same row version</text>
+ <text y="100">4: jungest xid (txid_current)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 730d5fdc34..e9e9f9495f 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -248,6 +248,7 @@ break is not needed in a wider output rendering.
</para>
</partintro>
+ &architecture;
&arch-dev;
&catalogs;
&protocol;
diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml
index 9bb5c1a6d5..abb61445f2 100644
--- a/doc/src/sgml/start.sgml
+++ b/doc/src/sgml/start.sgml
@@ -53,7 +53,7 @@
<sect1 id="tutorial-arch">
- <title>Architectural Fundamentals</title>
+ <title>Client/Server Model</title>
<para>
Before we proceed, you should understand the basic
@@ -68,34 +68,52 @@
client/server model. A <productname>PostgreSQL</productname>
session consists of the following cooperating processes
(programs):
+ </para>
- <itemizedlist>
- <listitem>
- <para>
- A server process, which manages the database files, accepts
- connections to the database from client applications, and
- performs database actions on behalf of the clients. The
- database server program is called
- <filename>postgres</filename>.
- <indexterm><primary>postgres</primary></indexterm>
- </para>
- </listitem>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A process at the server site with the name
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ <indexterm><primary>postgres</primary></indexterm>
+ <indexterm><primary>postmaster</primary></indexterm>
+ It accepts connection requests from client applications, starts
+ (<quote>forks</quote>) a new <glossterm linkend="glossary-backend">
+ Backend</glossterm> process for each of them, and passes
+ the connection to it. From that point on, the client and the new
+ Backend process communicate directly without intervention by the original
+ Postmaster process. Thus, the Postmaster process is always running,
+ waiting for new client connections, whereas clients and associated
+ Backend processes come and go. (All of this is of course invisible
+ to the user. We only mention it here for completeness.)
+ </para>
+ </listitem>
- <listitem>
- <para>
- The user's client (frontend) application that wants to perform
- database operations. Client applications can be very diverse
- in nature: a client could be a text-oriented tool, a graphical
- application, a web server that accesses the database to
- display web pages, or a specialized database maintenance tool.
- Some client applications are supplied with the
- <productname>PostgreSQL</productname> distribution; most are
- developed by users.
- </para>
- </listitem>
+ <listitem>
+ <para>
+ A group of processes at the server site, the <glossterm
+ linkend="glossary-instance">Instance</glossterm>, to which also
+ the Postmaster process belongs. Their duties are handling of
+ central, common database activities like file access, transaction
+ handling, vacuum, checkpoints, replication, and more. The mentioned
+ Backend processes delegate those actions to the instance.
+ </para>
+ </listitem>
- </itemizedlist>
- </para>
+ <listitem>
+ <para>
+ The user's client (frontend) application that wants to perform
+ database operations. Client applications can be very diverse
+ in nature: a client could be a text-oriented tool, a graphical
+ application, a web server that accesses the database to
+ display web pages, or a specialized database maintenance tool.
+ Some client applications are supplied with the
+ <productname>PostgreSQL</productname> distribution; most are
+ developed by users.
+ </para>
+ </listitem>
+
+ </itemizedlist>
<para>
As is typical of client/server applications, the client and the
@@ -106,18 +124,6 @@
file name) on the database server machine.
</para>
- <para>
- The <productname>PostgreSQL</productname> server can handle
- multiple concurrent connections from clients. To achieve this it
- starts (<quote>forks</quote>) a new process for each connection.
- From that point on, the client and the new server process
- communicate without intervention by the original
- <filename>postgres</filename> process. Thus, the
- supervisor server process is always running, waiting for
- client connections, whereas client and associated server processes
- come and go. (All of this is of course invisible to the user. We
- only mention it here for completeness.)
- </para>
</sect1>
On 2020-11-07 13:24, Jürgen Purtz wrote:
Because there have been no more comments in the last days I created a
consolidated patch. It contains Erik's suggestion and some tweaks for
the text size within graphics.[0011-architecture.patch]
Hi,
I went through architecture.sgml once more; some proposed changes
attached.
And in some .svg files I noticed 'jungest' which should be 'youngest', I
suppose.
I did not change them but below is filelist of grep -l 'jung'.
./doc/src/sgml/images/freeze-ink.svg
./doc/src/sgml/images/freeze-ink-svgo.svg
./doc/src/sgml/images/freeze-raw.svg
./doc/src/sgml/images/wraparound-ink.svg
./doc/src/sgml/images/wraparound-ink-svgo.svg
./doc/src/sgml/images/wraparound-raw.svg
Thanks,
Erik
Attachments:
architecture.sgml.20201107.difftext/x-diff; name=architecture.sgml.20201107.diffDownload
--- doc/src/sgml/architecture.sgml.orig 2020-11-07 14:05:50.188396026 +0100
+++ doc/src/sgml/architecture.sgml 2020-11-07 20:04:27.890983873 +0100
@@ -24,7 +24,7 @@
This leads to other activities (file access, WAL, vacuum, ...) of the
<glossterm linkend="glossary-instance">Instance</glossterm>. The
Instance is a group of server-side processes acting on a common
- Shared Memory. PostgreSQL does not utilize threading.
+ Shared Memory. PostgreSQL does not use threading.
</para>
<para>
@@ -78,7 +78,7 @@
cache, located in Shared Memory (for details see:
<xref linkend="sysvipc"/>) for the benefit of all processes
in the instance. Writes also use this cache, in addition
- to a journal, called a write-ahead-log or WAL.
+ to a journal, called the write-ahead-log or WAL.
</para>
<para>
@@ -90,20 +90,20 @@
must be written to disk. This happens regularly by the
Checkpointer and the Background Writer processes to ensure
that the disk version of the pages are up-to-date.
- The synchronisation from RAM to disk consists of two steps.
+ The synchronization from RAM to disk consists of two steps.
</para>
<para>
First, whenever the content of a page changes, a
<glossterm linkend="glossary-wal-record">WAL record</glossterm>
- is created out of the delta-information (difference between the
+ is created from the delta-information (difference between the
old and the new content) and stored in another area of
Shared Memory. The parallel running WAL Writer process
reads them and appends them to the end of the current
<glossterm linkend="glossary-wal-record">WAL file</glossterm>.
Such sequential writes are faster than writes to random
positions of heap and index files. All WAL records created
- out of one dirty page must be transferred to disk before the
+ from one dirty page must be transferred to disk before the
dirty page itself can be transferred to disk in the second step.
</para>
@@ -123,22 +123,22 @@
<glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
A Checkpoint is a point in time when all older dirty buffers,
all older WAL records, and finally a special Checkpoint record
- are written and flushed to disk. Heap and index files
- on the one hand and WAL files on the other hand are in sync.
- Previous WAL is no longer required. In other words,
+ are written and flushed to disk. Heap and index files,
+ and WAL files are now in sync.
+ Older WAL is no longer required. In other words,
a possibly occurring recovery, which integrates the delta
information of WAL into heap and index files, will happen
- by replaying only WAL past the last recorded checkpoint.
- This limits the amount of WAL which needs to be replayed
+ by replaying only WAL past the last-recorded checkpoint.
+ This limits the amount of WAL to be replayed
during recovery in the event of a crash.
</para>
<para>
- While the Checkpointer ensures that the database system can crash
- and restart itself in a valid state, the administrator needs
+ While the Checkpointer ensures that the database system can,
+ after a crash, restart itself in a valid state, the administrator needs
to handle the case where the heap or other files become
corrupted (and possibly the locally written WAL, though that is
- less common). The options and details are covered extensively
+ less common). Options and details are covered
in the backup and restore section (<xref linkend="backup"/>).
For our purposes here, just note that the WAL Archiver process
can be enabled and configured to run a script on filled WAL
@@ -153,7 +153,7 @@
<para>
The Logger writes text lines about serious and less serious
- events which can happen during database access, e.g., wrong
+ events that may happen during database access, e.g., wrong
password, no permission, long-running queries, etc.
</para>
@@ -262,7 +262,7 @@
all <firstterm>tablespace names</firstterm>, and all
<firstterm>role names</firstterm> are automatically
available throughout the cluster, independent from
- the database or schema in which they where defined originally.
+ the database or schema in which they were defined originally.
<xref linkend="tutorial-internal-objects-hierarchy-figure"/>
shows the relation between the object types.
</para>
@@ -410,13 +410,11 @@
</para>
<para>
- A first approach to implement protections against concurrent
- access to the same data may be the locking of critical rows.
- <productname>PostgreSQL</productname> implements a more
- sophisticated technique which avoids any locking:
+ <productname>PostgreSQL</productname> implements a
+ sophisticated technique which avoids locking:
<firstterm>Multiversion Concurrency Control</firstterm> (MVCC).
- The crucial advantage of MVCC
- over other technologies becomes evident in multiuser OLTP
+ The advantage of MVCC
+ over technologies that use row locks becomes evident in multiuser OLTP
environments with a massive number of concurrent write
actions. There, MVCC generally performs better than solutions
using locks. In a <productname>PostgreSQL</productname>
@@ -455,7 +453,7 @@
<para>
The description in this chapter simplifies by omitting details.
When many transactions are running simultaneously, things can
- get complicated. Sometimes transactions get aborted via
+ get complicated. Sometimes transactions are aborted via
<command>ROLLBACK</command> immediately or after a lot of other activities, sometimes
a single row is involved in more than one transaction, sometimes
a client crashes, sometimes the sequence of xids restarts
@@ -551,14 +549,14 @@
</para>
<para>
- Please keep in mind:
+ Keep in mind:
</para>
<itemizedlist>
<listitem>
<simpara>
<literal>xmin</literal> and <literal>xmax</literal>
- indicate the range from where to where
+ indicate the range in which
<firstterm>row versions</firstterm> are valid (visible) for transactions.
This range doesn't imply any direct temporal meaning;
the sequence of xids reflects only the sequence of
@@ -581,7 +579,7 @@
<listitem>
<simpara>
- Nothing gets wiped away — with the consequence that the database
+ Nothing is removed — with the consequence that the database
occupies more and more disk space. It is obvious that
this behavior has to be corrected in some
way. The next chapter explains how <firstterm>autovacuum</firstterm>
@@ -609,7 +607,7 @@
<note>
<para>
Autovacuum runs automatically by
- default. Its default parameters as well as such for
+ default. Its default parameters as well as those for
<command>VACUUM</command> are appropriate for most standard
situations. Therefore a novice database manager can
skip the rest of this chapter which explains
@@ -629,7 +627,7 @@
and starts Autovacuum processes whenever it detects
certain situations. Thus, it's a dynamic behavior of
<productname>PostgreSQL</productname> with the intention to tidy
- up — whenever it is appropriate.
+ up whenever it is appropriate.
</para>
<para>
@@ -672,7 +670,7 @@
</itemizedlist>
<para>
- The eagerness — you can call it 'aggressiveness' — of the
+ The eagerness — or 'aggressiveness' — of the
operations for <emphasis>eliminating bloat</emphasis> and
<emphasis>freeze</emphasis> is controlled by configuration
parameters, runtime flags, and in extreme situations by
@@ -689,7 +687,7 @@
<para>
To determine which of the row versions are no longer needed, the
elimination operation must evaluate <literal>xmax</literal>
- against several criteria which all must apply:
+ against several criteria which must all apply:
</para>
<itemizedlist>
@@ -830,13 +828,13 @@
<para>
The use of a limited range of IDs for transactions leads
to the necessity to restart the sequence sooner or later.
- This does not only have the rare consequence previously
- described that sometimes <literal>xmin</literal> is
- higher than <literal>xmax</literal>. The far
+ This not only has the rare consequence, previously
+ described, that sometimes <literal>xmin</literal> is
+ higher than <literal>xmax</literal>. A far
more critical problem is that whenever the system has
to evaluate a WHERE condition, it must decide which row
version is valid (visible) from the perspective of the
- transaction of this query. If a wraparound couldn't happen,
+ transaction of the query. If a wraparound couldn't happen,
this decision would be relatively easy: the xid
must be between <literal>xmin</literal> and <literal>xmax</literal>,
and the corresponding transactions of <literal>xmin</literal>
@@ -884,7 +882,7 @@
a flag in the header of the row version which avoids
future comparison of its <literal>xmin/xmax</literal> and indicates
that the version is valid not only in the 'past'-half
- but also in the 'future'-half as well as in all coming
+ but also in the 'future'-half, as well as in all coming
<glossterm linkend="glossary-xid">epochs</glossterm>.
</simpara>
</listitem>
@@ -1162,21 +1160,21 @@
new row versions, and after a while and some more
activities of the modifying transaction they may see the
next row versions. Results would be a kind of 'moving
- target' in absolute contrast to the all-or-nothing
+ target' which would be contrary to the all-or-nothing
principle.
</para>
<para>
<productname>PostgreSQL</productname> overcomes this
problem by showing only such row versions to other
- transactions whose originating transaction is
+ transactions whose originating transaction has
successfully committed. It skips all row versions of
uncommitted transactions. And
<productname>PostgreSQL</productname> solves one more
problem. Even the single <command>COMMIT</command>
command needs a short time interval for its execution.
Therefore its critical 'dead-or-survival' phase
- runs in a priviledged mode where it cannot be
+ runs in a privileged mode that cannot be
interrupted by other processes.
</para>
@@ -1184,7 +1182,7 @@
<para>
Transactions relieve applications from many standard
- actions that must be implemented for nearly every use case.
+ actions that would otherwise need to be implemented for nearly every use case.
</para>
<para>
@@ -1192,7 +1190,7 @@
relative abstract requirements. The above example shows
the transfers of some money from one account to another.
It is obvious
- that the decrease of the one and the increase of the
+ that the decrease of the one account and the increase of the
other must be indivisible. Nevertheless, there is no particular
need for an application to do something to ensure the
<glossterm linkend="glossary-atomicity">atomicity</glossterm>
@@ -1266,7 +1264,7 @@
client/server architecture, no direct problem for the
database will occur. In all of these cases, the
<glossterm linkend="glossary-backend">Backend process</glossterm>,
- which is the client's counterpart at the server-side,
+ which is the client's counterpart at the server side,
may recognize that the network connection is no longer
working, or it may run into a timeout after a while. It
terminates, and there is no harm to the database. As
@@ -1294,9 +1292,9 @@
the WAL files contain them as a chronology of
<glossterm linkend="glossary-wal-record">WAL records</glossterm>,
which include the new data values and information about commit
- actions. The WAL records are written first. Second,
- the data itself shall exist in the heap and index files.
- In constrast with the WAL records, this part may or may
+ actions. The WAL records are written first. Only then is
+ the data itself written to the heap and index files.
+ In contrast to the WAL records, this part may or may
not have been transferred entirely from Shared Memory
to the files.
</para>
@@ -1308,14 +1306,14 @@
This checkpoint signals that the database files are in
a consistent state, especially that all WAL records up to
this point were successfully stored in heap and index files. Starting
- here, the recovery process copies the remaining WAL records
- to heap and index. As a result, the heap files contain all
+ here, the recovery process copies any remaining WAL records
+ to heap and index. The result is that the heap files contain all
changes recorded to the WAL and reach a consistent state. Changes of committed
transactions are visible; those of uncommitted transactions
are also in the files, but - as usual - they are never seen
by any of the following transactions because uncommitted
- changes are never shown. Such recovery actions run
- completely automatically, it is not necessary that a
+ changes are never shown. These recovery actions run
+ automatically; it is not necessary that a
database administrator configure or start anything by
himself.
</para>
@@ -1330,7 +1328,7 @@
</para>
<para>
- They obviously needs a backup. How to take such a backup
+ They obviously need a backup. How to take such a backup
and use it as a starting point for a recovery of the
cluster is explained in more detail in the next
<link linkend="tutorial-backup">chapter</link>.
@@ -1421,7 +1419,7 @@
of the complete cluster or certain parts of it. It stores
the copy in the form of SQL commands like <command>CREATE</command>
and <command>COPY</command>. It runs in
- parallel with other processes in its own transaction.
+ parallel with other processes, in its own transaction.
</para>
<para>
@@ -1484,7 +1482,7 @@
copy the basebackup and the archived WAL files to
their original directories. The configuration of this
<link linkend="backup-pitr-recovery">recovery procedure</link>
- contains a string with the reverse copy command: from
+ contains a string with the reversed copy command: from
archive location to database location.
</para>
On 07.11.20 20:15, Erik Rijkers wrote:
On 2020-11-07 13:24, Jürgen Purtz wrote:
Because there have been no more comments in the last days I created a
consolidated patch. It contains Erik's suggestion and some tweaks for
the text size within graphics.[0011-architecture.patch]
Hi,
I went through architecture.sgml once more; some proposed changes
attached.And in some .svg files I noticed 'jungest' which should be 'youngest',
I suppose.
I did not change them but below is filelist of grep -l 'jung'../doc/src/sgml/images/freeze-ink.svg
./doc/src/sgml/images/freeze-ink-svgo.svg
./doc/src/sgml/images/freeze-raw.svg
./doc/src/sgml/images/wraparound-ink.svg
./doc/src/sgml/images/wraparound-ink-svgo.svg
./doc/src/sgml/images/wraparound-raw.svgThanks,
Erik
Good catches. Everything applied.
--
J. Purtz
Attachments:
0012-architecture.patchtext/x-patch; charset=UTF-8; name=0012-architecture.patchDownload
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
index 2d4ab85d45..5c3245c0ec 100644
--- a/doc/src/sgml/advanced.sgml
+++ b/doc/src/sgml/advanced.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/advanced.sgml -->
<chapter id="tutorial-advanced">
- <title>Advanced Features</title>
+ <title>Advanced SQL Features</title>
<sect1 id="tutorial-advanced-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/arch-dev.sgml b/doc/src/sgml/arch-dev.sgml
index 7883c3cd82..9db0ae2c78 100644
--- a/doc/src/sgml/arch-dev.sgml
+++ b/doc/src/sgml/arch-dev.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/arch-dev.sgml -->
<chapter id="overview">
- <title>Overview of PostgreSQL Internals</title>
+ <title>Overview of Query Handling</title>
<note>
<title>Author</title>
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
new file mode 100644
index 0000000000..b7589f9a4f
--- /dev/null
+++ b/doc/src/sgml/architecture.sgml
@@ -0,0 +1,1502 @@
+<!-- doc/src/sgml/architecture.sgml -->
+
+ <chapter id="tutorial-architecture">
+ <title>Overview of Architecture and Implementation</title>
+
+ <para>
+ Every DBMS implements basic strategies to ensure a fast
+ and robust system. This chapter provides an overview of the
+ techniques <productname>PostgreSQL</productname> uses to
+ achieve this.
+ </para>
+
+ <sect1 id="tutorial-ram-proc-file">
+ <title>Collaboration of Processes, RAM, and Files</title>
+ <para>
+ In a client/server architecture clients do not have direct access
+ to database files and the data stored in them. Instead, they send
+ requests to the server and receive the requested data in the response.
+ In the case of <productname>PostgreSQL</productname>, the server
+ launches a single process for each client connection, referred to as a
+ <glossterm linkend="glossary-backend">Backend</glossterm> process.
+ Such a Backend process handles the client's requests by acting on the
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>.
+ This leads to other activities (file access, WAL, vacuum, ...) of the
+ <glossterm linkend="glossary-instance">Instance</glossterm>. The
+ Instance is a group of server-side processes acting on a common
+ Shared Memory. PostgreSQL does not use threading.
+ </para>
+
+ <para>
+ The first step when an Instance starts is the start of the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ It loads the configuration files, allocates Shared Memory, and
+ starts the other processes of the Instance:
+ <glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
+ <glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
+ <glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
+ <glossterm linkend="glossary-wal-archiver">WAL Archiver</glossterm>,
+ <glossterm linkend="glossary-autovacuum">Autovacuum</glossterm>,
+ <glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
+ <glossterm linkend="glossary-logger">Logger</glossterm>, and more.
+ Later, the Postmaster starts
+ <glossterm linkend="glossary-backend">Backend</glossterm> processes
+ which communicate with clients and handle their requests.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes the processes
+ of an Instance and the main aspects of their collaboration.
+ </para>
+
+ <figure id="tutorial-ram-proc-file-figure">
+ <title>Architecture</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ When a client application tries to connect to a
+ <glossterm linkend="glossary-database">database</glossterm>,
+ this request is handled initially by the Postmaster. It
+ starts a new Backend process, which handles all further
+ client's requests.
+ </para>
+
+ <para>
+ Client requests like <command>SELECT</command> or
+ <command>UPDATE</command> usually lead to the
+ necessity to read or write data. This is carried out
+ by the client's backend process. Reads involve a page-level
+ cache, located in Shared Memory (for details see:
+ <xref linkend="sysvipc"/>) for the benefit of all processes
+ in the instance. Writes also use this cache, in addition
+ to a journal, called the write-ahead-log or WAL.
+ </para>
+
+ <para>
+ Shared Memory is limited in size and it can become necessary
+ to evict pages. As long as the content of such pages hasn't
+ changed, this is not a problem. But in Shared Memory also
+ write actions take place. Modified pages are called dirty
+ pages or dirty buffers and before they can be evicted they
+ must be written to disk. This happens regularly by the
+ Checkpointer and the Background Writer processes to ensure
+ that the disk version of the pages are up-to-date.
+ The synchronization from RAM to disk consists of two steps.
+ </para>
+
+ <para>
+ First, whenever the content of a page changes, a
+ <glossterm linkend="glossary-wal-record">WAL record</glossterm>
+ is created from the delta-information (difference between the
+ old and the new content) and stored in another area of
+ Shared Memory. The parallel running WAL Writer process
+ reads them and appends them to the end of the current
+ <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
+ Such sequential writes are faster than writes to random
+ positions of heap and index files. All WAL records created
+ from one dirty page must be transferred to disk before the
+ dirty page itself can be transferred to disk in the second step.
+ </para>
+
+ <para>
+ Second, the transfer of dirty buffers from Shared Memory to
+ files must take place. This is the primary task of the
+ Background Writer process. Because I/O activities can block
+ other processes, it starts periodically and
+ acts only for a short period. Doing so, its extensive (and
+ expensive) I/O activities are spread over time, avoiding
+ debilitating I/O peaks. The Checkpointer process
+ also transfers dirty buffers to file.
+ </para>
+
+ <para>
+ The Checkpointer process creates
+ <glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
+ A Checkpoint is a point in time when all older dirty buffers,
+ all older WAL records, and finally a special Checkpoint record
+ are written and flushed to disk. Heap and index files,
+ and WAL files are now in sync.
+ Older WAL is no longer required. In other words,
+ a possibly occurring recovery, which integrates the delta
+ information of WAL into heap and index files, will happen
+ by replaying only WAL past the last-recorded checkpoint.
+ This limits the amount of WAL to be replayed
+ during recovery in the event of a crash.
+ </para>
+
+ <para>
+ While the Checkpointer ensures that the database system can,
+ after a crash, restart itself in a valid state, the administrator needs
+ to handle the case where the heap or other files become
+ corrupted (and possibly the locally written WAL, though that is
+ less common). Options and details are covered
+ in the backup and restore section (<xref linkend="backup"/>).
+ For our purposes here, just note that the WAL Archiver process
+ can be enabled and configured to run a script on filled WAL
+ files — usually to copy them to a remote location.
+ </para>
+
+ <para>
+ The Statistics Collector collects counters about access to
+ SQL objects like tables, rows, indexes, pages, and more. It
+ stores the obtained information in system tables.
+ </para>
+
+ <para>
+ The Logger writes text lines about serious and less serious
+ events that may happen during database access, e.g., wrong
+ password, no permission, long-running queries, etc.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-cluster-db-schema">
+ <title>The logical Perspective: Cluster, Database, Schema</title>
+
+ <para>
+ A <glossterm linkend="glossary-server">server</glossterm> contains one or more
+ <glossterm linkend="glossary-db-cluster">database clusters</glossterm>
+ (<glossterm linkend="glossary-db-cluster">clusters</glossterm>
+ for short). Each cluster contains three or more
+ <glossterm linkend="glossary-database">databases</glossterm>.
+ Each database can contain many
+ <glossterm linkend="glossary-schema">schemas</glossterm>.
+ A schema can contain
+ <glossterm linkend="glossary-table">tables</glossterm>,
+ <glossterm linkend="glossary-view">views</glossterm>, and a lot
+ of other objects. Each table or view belongs to a single schema
+ only; they cannot belong to another schema as well. The same is
+ true for the schema/database and database/cluster relation.
+ <xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
+ this hierarchy.
+ </para>
+
+ <figure id="tutorial-cluster-db-schema-figure">
+ <title>Cluster, Database, Schema</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ A cluster is the outer container for a
+ collection of databases. Clusters are created by the command
+ <xref linkend="app-initdb"/>.
+ </para>
+
+ <para>
+ <literal>template0</literal> is the very first
+ database of any cluster. Database <literal>template0</literal>
+ is created during the initialization phase of the cluster.
+ In a second step, database <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal>, and finally database
+ <literal>postgres</literal> is generated as a copy of
+ <literal>template1</literal>. Any
+ <glossterm linkend="app-createdb">new databases</glossterm>
+ of the cluster that a user might need,
+ such as <literal>my_db</literal>, will be copied from the
+ <literal>template1</literal> database. Due to the unique
+ role of <literal>template0</literal> as the pristine original
+ of all other databases, no client can connect to it.
+ </para>
+
+ <para>
+ Every database must contain at least one schema because all
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>
+ must be contained in a schema.
+ Schemas are namespaces for SQL objects and ensure
+ (with one exception) that the SQL object names are used only once within
+ their scope across all types of SQL objects. E.g., it is not possible
+ to have a table <literal>employee</literal> and a view
+ <literal>employee</literal> within the same schema. But it is
+ possible to have two tables <literal>employee</literal> in two
+ different schemas. In this case, the two tables
+ are separate objects and independent of each
+ other. The only exception to this cross-type uniqueness is that
+ <glossterm linkend="glossary-unique-constraint">unique constraints
+ </glossterm> and the according unique index
+ (<xref linkend="indexes-unique"/>) use the same name.
+ </para>
+
+ <para>
+ Some schemas are predefined. <literal>public</literal>
+ acts as the default schema and contains all SQL objects
+ which are created within <literal>public</literal> or
+ without using an explicit schema name. <literal>public</literal>
+ should not contain user-defined SQL objects. Instead, it is
+ recommended to create a separate schema that holds individual
+ objects like application-specific tables or views.
+ <literal>pg_catalog</literal> is a schema for all tables and views of the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ <literal>information_schema</literal> is a schema for several
+ tables and views of the System Catalog in a way that conforms
+ to the SQL standard.
+ </para>
+
+ <para>
+ There are many different SQL object
+ types: <firstterm>database, schema, table, view, materialized
+ view, index, constraint, sequence, function, procedure,
+ trigger, role, data type, operator, tablespace, extension,
+ foreign data wrapper</firstterm>, and more. A few of them, the
+ <firstterm>Global SQL Objects</firstterm>, are outside of the
+ strict hierarchy: All <firstterm>database names</firstterm>,
+ all <firstterm>tablespace names</firstterm>, and all
+ <firstterm>role names</firstterm> are automatically
+ available throughout the cluster, independent from
+ the database or schema in which they were defined originally.
+ <xref linkend="tutorial-internal-objects-hierarchy-figure"/>
+ shows the relation between the object types.
+ </para>
+
+ <figure id="tutorial-internal-objects-hierarchy-figure">
+ <title>Hierarchy of Internal Objects</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect1>
+
+ <sect1 id="tutorial-directories">
+ <title>The physical Perspective: Directories and Files</title>
+
+ <para>
+ <productname>PostgreSQL</productname> organizes long-lasting (persistent)
+ data as well as volatile state information about transactions
+ or replication actions in the file system. Every
+ <xref linkend="glossary-db-cluster"/> has its root directory
+ somewhere in the file system. In many cases, the environment
+ variable <literal>PGDATA</literal> points to this directory.
+ The example shown in
+ <xref linkend="tutorial-directories-figure"/> uses
+ <literal>data</literal> as the name of this root directory.
+ </para>
+
+ <figure id="tutorial-directories-figure">
+ <title>Directory Structure</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ <literal>data</literal> contains many subdirectories and
+ some files, all of which are necessary to store long-lasting
+ as well as temporary data. The following paragraphs
+ describe the files and subdirectories in
+ <literal>data</literal>.
+ </para>
+
+ <para>
+ <literal>base</literal> is a subdirectory in which one
+ subdirectory per database exists. The names of those
+ subdirectories consist of numbers. These are the internal
+ Object Identifiers (OID), which are numbers to identify
+ the database definition in the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ </para>
+
+ <para>
+ Within the database-specific
+ subdirectories, there are many files: one or more for
+ every table and every index to store heap and index
+ data. Those files are accompanied by files for the
+ <link linkend="storage-fsm">Free Space Maps</link>
+ (suffixed <literal>_fsm</literal>) and
+ <link linkend="storage-vm">Visibility Maps</link>
+ (suffixed <literal>_vm</literal>), which contain optimization information.
+ </para>
+
+ <para>
+ Another subdirectory is <literal>global</literal> which
+ contains files with information about
+ <glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
+ One type of such Global SQL Objects are
+ <glossterm linkend="glossary-tablespace">tablespaces</glossterm>.
+ In <literal>global</literal> there is information about
+ the tablespaces; not the tablespaces themselves.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_wal</literal> contains the
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
+ They arise and grow in parallel with data changes in the
+ cluster and remain as long as
+ they are required for recovery, archiving, or replication.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_xact</literal> contains
+ information about the status of each transaction:
+ <literal>in_progress</literal>, <literal>committed</literal>,
+ <literal>aborted</literal>, or <literal>sub_committed</literal>.
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal>, there are symbolic links
+ that point to directories containing SQL objects
+ that exist within a non-default tablespace.
+ </para>
+
+ <para>
+ In the root directory <literal>data</literal>
+ there are also some files. In many cases, the configuration
+ files of the cluster are stored here. If the
+ instance is up and running, the file
+ <literal>postmaster.pid</literal> exists here
+ and contains the process ID (pid) of the
+ Postmaster which started the instance.
+ </para>
+
+ <para>
+ For more details about the physical implementation
+ of database objects, see <xref linkend="storage"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-mvcc">
+ <title>MVCC — Multiversion Concurrency Control</title>
+
+ <para>
+ In most cases, <productname>PostgreSQL</productname> databases
+ support many clients at the same time which makes it necessary to
+ protect concurrently running requests from unwanted overwriting
+ of other's data as well as from reading inconsistent data. Imagine an
+ online shop offering the last copy of an article. Two clients have the
+ article displayed at their user interface. After a while, but at the same time,
+ both users decide to put it to their shopping cart or even to buy it.
+ Both have seen the article, but only one can be allowed to get it.
+ The database must bring the two requests in a row, permit the access
+ to one of them, block the other, and inform the blocked client
+ that the data was changed by a different process.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> implements a
+ sophisticated technique which avoids locking:
+ <firstterm>Multiversion Concurrency Control</firstterm> (MVCC).
+ The advantage of MVCC
+ over technologies that use row locks becomes evident in multiuser OLTP
+ environments with a massive number of concurrent write
+ actions. There, MVCC generally performs better than solutions
+ using locks. In a <productname>PostgreSQL</productname>
+ database, reading never blocks writing and writing never
+ blocks reading, even in the strictest level of transaction
+ isolation.
+ </para>
+
+ <para>
+ Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
+ a new version of the row when a data-change takes place. To
+ distinguish between these two versions, and to track the timeline
+ of the row, each of the versions contains, in addition to their user-defined
+ columns, two special system columns, which are not visible
+ for the usual <command>SELECT * FROM ...</command> command.
+ The column <literal>xmin</literal> contains the transaction ID (xid)
+ of the transaction which created this version of the row.
+ <literal>xmax</literal> contains the xid of the transaction which has
+ deleted this version, or zero if the version is not
+ deleted. You can read both with the command
+ <command>SELECT xmin, xmax, * FROM ... </command>.
+ </para>
+
+ <para>
+ When we speak about transaction IDs, you need to know that xids are like
+ sequences. Every new transaction receives the next number as its ID.
+ Therefore, this flow of xids represents the flow of transaction
+ start events over time. But keep in mind that xids are independent of
+ any time measurement — in milliseconds or otherwise. If you dive
+ deeper into <productname>PostgreSQL</productname>, you will recognize
+ parameters with names such as 'xxx_age'. Despite their names,
+ these '_age' parameters do not specify a period of time but represent
+ a certain number of transactions, e.g., 100 million.
+ </para>
+
+ <para>
+ The description in this chapter simplifies by omitting details.
+ When many transactions are running simultaneously, things can
+ get complicated. Sometimes transactions are aborted via
+ <command>ROLLBACK</command> immediately or after a lot of other activities, sometimes
+ a single row is involved in more than one transaction, sometimes
+ a client crashes, sometimes the sequence of xids restarts
+ from zero, ... . Therefore, every version of a row contains more
+ system columns and flags, not only <literal>xmin</literal>
+ and <literal>xmax</literal>.
+ </para>
+
+ <para>
+ So, what's going on in detail when write access takes place?
+ <xref linkend="tutorial-mvcc-figure"/> shows details concerning
+ <literal>xmin</literal>, <literal>xmax</literal>, and user data.
+ </para>
+
+ <figure id="tutorial-mvcc-figure">
+ <title>Multiversion Concurrency Control</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ An <command>INSERT</command> command creates the first
+ version of a row. Besides its user data <literal>'x'</literal>,
+ this version contains the ID of the creating transaction
+ <literal>123</literal> in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ <literal>xmin</literal> indicates that the version
+ exists since transaction <literal>123</literal> and
+ <literal>xmax</literal> that it is currently not deleted.
+ </para>
+
+ <para>
+ Somewhat later, transaction <literal>135</literal>
+ executes an <command>UPDATE</command> of this row by
+ changing the user data from <literal>'x'</literal> to
+ <literal>'y'</literal>. According to the MVCC principles,
+ the data in the old version of the row is not changed!
+ The value <literal>'x'</literal> remains as it was before.
+ Only <literal>xmax</literal> changes to <literal>135</literal>.
+ Now, this version is treated as valid exclusively for
+ transactions with xids from <literal>123</literal> to
+ <literal>134</literal>. In addition to the non-occurring
+ data change in the old version, the <command>UPDATE</command>
+ creates a new version of the row with its xid in
+ <literal>xmin</literal>, <literal>0</literal> in
+ <literal>xmax</literal>, and <literal>'y'</literal> in the
+ user data (plus all other user data from the old version).
+ This new row version is visible to all future transactions.
+ (Internally, an <command>UPDATE</command> command acts
+ as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.)
+ </para>
+
+ <para>
+ All subsequent <command>UPDATE</command> commands behave
+ in the same way as the first one: they put their xid in
+ <literal>xmax</literal> of the current version, create
+ a new version with their xid in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ </para>
+
+ <para>
+ Finally, a row may be deleted by a <command>DELETE</command>
+ command. Even in this case, all versions of the row remain as
+ before. Nothing is thrown away! Only <literal>xmax</literal>
+ of the last version is set to the xid of the <command>DELETE</command>
+ transaction, which indicates that (if committed) it is only visible to
+ transactions with xids older than that (from
+ <literal>142</literal> to <literal>820</literal> in this
+ example).
+ </para>
+
+ <para>
+ In summary, the MVCC technology creates more and more versions
+ of the same row in the table's heap file and leaves them there,
+ even after a <command>DELETE</command> command. Only the youngest
+ version is relevant for all future transactions. But the
+ system must also preserve some of the older ones for
+ awhile, because they could still be needed by
+ transactions which started before the deleting transaction commits.
+ Over time, also the older ones get out of scope
+ for ALL transactions and therefore become unnecessary.
+ Nevertheless, they do exist physically on the disk and occupy
+ space.
+ </para>
+
+ <para>
+ Keep in mind:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> and <literal>xmax</literal>
+ indicate the range in which
+ <firstterm>row versions</firstterm> are valid (visible) for transactions.
+ This range doesn't imply any direct temporal meaning;
+ the sequence of xids reflects only the sequence of
+ transaction begin events. As
+ xids grow, old row versions get out of scope over time.
+ If an old row version is no longer relevant for ANY existing
+ transactions, it can be marked <firstterm>dead</firstterm>. The
+ space occupied by dead row versions is part of the
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Internally, an <command>UPDATE</command> command acts in the
+ same way as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Nothing is removed — with the consequence that the database
+ occupies more and more disk space. It is obvious that
+ this behavior has to be corrected in some
+ way. The next chapter explains how <firstterm>autovacuum</firstterm>
+ fulfills this task.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ </sect1>
+
+ <sect1 id="tutorial-vacuum">
+ <title>Vacuum</title>
+
+ <para>
+ As we have seen in the previous chapter, the database
+ tends to occupy more and more disk space, caused by
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ This chapter explains how the SQL command
+ <command>VACUUM</command> and the automatically running
+ <firstterm>Autovacuum</firstterm> processes clean up
+ and avoid continued growth.
+ </para>
+
+ <note>
+ <para>
+ Autovacuum runs automatically by
+ default. Its default parameters as well as those for
+ <command>VACUUM</command> are appropriate for most standard
+ situations. Therefore a novice database manager can
+ skip the rest of this chapter which explains
+ a lot of details.
+ </para>
+ </note>
+
+ <para>
+ Client processes can issue the SQL command <command>VACUUM</command>
+ at arbitrary points in time. DBAs do this when they recognize
+ special situations, or they start it in batch jobs which run
+ periodically. Autovacuum processes run as part of the
+ <link linkend="glossary-instance">Instance</link> at the server.
+ There is a constantly running Autovacuum daemon. It continuously
+ monitors the state of all databases based on values that are collected by the
+ <link linkend="glossary-stats-collector">Statistics Collector</link>
+ and starts Autovacuum processes whenever it detects
+ certain situations. Thus, it's a dynamic behavior of
+ <productname>PostgreSQL</productname> with the intention to tidy
+ up whenever it is appropriate.
+ </para>
+
+ <para>
+ <command>VACUUM</command>, as well as Autovacuum, don't just eliminate
+ bloat. They perform additional tasks for minimizing future
+ I/O activities of themselves as well as of other processes.
+ This extra work can be done in a very efficient way since in most
+ cases the expensive physical access to pages has taken place anyway
+ to eliminate bloat. The additional operations are:
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <firstterm>Freeze</firstterm>: Mark certain row versions
+ as frozen. This means that they
+ are always treated as valid (visible) independent from
+ the <firstterm>wraparound problem</firstterm> (see below).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <firstterm>Visibility Map</firstterm> and
+ <firstterm>Free Space Map</firstterm>: Log information about
+ the state of the handled pages in two additional files, the
+ Visibility Map and the Free Space Map.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <emphasis>Statistics</emphasis>: Collect statistics about the
+ number of rows per table, the distribution of values, and so on,
+ as the basis for decisions of the query planner.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ The eagerness — or 'aggressiveness' — of the
+ operations for <emphasis>eliminating bloat</emphasis> and
+ <emphasis>freeze</emphasis> is controlled by configuration
+ parameters, runtime flags, and in extreme situations by
+ the processes themselves. Because vacuum operations typically are I/O
+ intensive, which can hinder other activities, Autovacuum
+ avoids performing many vacuum operations in bulk. Instead,
+ it carries out many small actions with delay points in between.
+ The SQL command <command>VACUUM</command> runs immediately
+ and without any time delay.
+ </para>
+
+ <bridgehead renderas="sect2">Eliminate Bloat</bridgehead>
+
+ <para>
+ To determine which of the row versions are no longer needed, the
+ elimination operation must evaluate <literal>xmax</literal>
+ against several criteria which must all apply:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be different from zero because a
+ value of zero indicates that the row version is still valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must contain an xid which is older
+ than the oldest xid of all currently running transactions
+ <literal>(min(pg_stat_activity.backend_xmin))</literal>.
+ This criterion guarantees that no existing or upcoming transaction
+ will have read or write access to this row version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of <literal>xmax</literal> must be committed. If it was rollback-ed,
+ this row version is treated as valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there is the situation that the row version is part of
+ multiple transactions, special care and some more actions
+ must be taken, see: <xref linkend="vacuum-for-multixact-wraparound"/>.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ After the vacuum operation detects an unused row version, it
+ marks its space as free for future use of writing actions. Only
+ in rare situations (or in the case of <command>VACUUM FULL</command>),
+ is this space released to the operating system. In most cases,
+ it remains occupied by <productname>PostgreSQL</productname>
+ and will be used by future <command>INSERT</command> or
+ <command>UPDATE</command> commands to this table.
+ </para>
+
+ <para>
+ Which actions start the elimination of bloat?
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ in its default format, i.e., without any option. To boost performance,
+ in this and the next case <command>VACUUM</command> does not
+ read and act on all pages of the heap file.
+ The Visibility Map, which is very compact and therefore fast to read,
+ contains information about which pages have no deleted row versions, and
+ can be skipped by <command>VACUUM</command>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FREEZE</command>. (In this case,
+ it undertakes many more actions, see
+ <link linkend="tutorial-freeze">Freeze Row Versions</link>.)
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FULL</command>.
+ In this mode, an exclusive lock is taken, and
+ the whole table is copied to a different file, skipping all outdated row
+ versions. All bloat is thereby eliminated, which
+ may lead to a significant reduction of used disk space.
+ The old file is deleted.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When an Autovacuum process acts. For optimization
+ purposes, it considers the Visibility Map in the same way as
+ <command>VACUUM</command>. Additionally, it ignores tables with few modifications;
+ see <xref linkend="guc-autovacuum-vacuum-threshold"/>,
+ which defaults to 50 rows and
+ <xref linkend="guc-autovacuum-vacuum-scale-factor"/>,
+ which defaults to 20%.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </para>
+
+ <para>
+ This logic only applies to row versions of the heap. Index entries
+ don't use <literal>xmin/xmax</literal>. Nevertheless, such index
+ entries, which would lead to outdated row versions, are cleaned up
+ accordingly.
+ </para>
+
+ <para>
+ The above descriptions omit the fact that xids on a real computer
+ have a limited size, and after
+ a certain number of transactions they are forced to restart
+ from the beginning, which is called <firstterm>wraparound</firstterm>.
+ Therefore the terms 'old transaction' / 'young transaction' does
+ not always correlate with low / high values of xids. Near to
+ wraparound point, there are cases where <literal>xmin</literal> has
+ a higher value than <literal>xmax</literal>, although their meaning
+ is said to be older than <literal>xmax</literal>.
+ </para>
+
+ <figure id="tutorial-wraparound-figure">
+ <title>Cyclic usage of XIDs</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2" id="tutorial-freeze">Freeze Row Versions</bridgehead>
+
+ <para>
+ The use of a limited range of IDs for transactions leads
+ to the necessity to restart the sequence sooner or later.
+ This not only has the rare consequence, previously
+ described, that sometimes <literal>xmin</literal> is
+ higher than <literal>xmax</literal>. A far
+ more critical problem is that whenever the system has
+ to evaluate a WHERE condition, it must decide which row
+ version is valid (visible) from the perspective of the
+ transaction of the query. If a wraparound couldn't happen,
+ this decision would be relatively easy: the xid
+ must be between <literal>xmin</literal> and <literal>xmax</literal>,
+ and the corresponding transactions of <literal>xmin</literal>
+ and <literal>xmax</literal> must be committed. However,
+ <productname>PostgreSQL</productname> has to consider the
+ possibility of wraparound.
+ Therefore the decision becomes more complex. The general
+ idea of the solution is to use the 'between
+ <literal>xmin</literal> and <literal>xmax</literal>'
+ comparison only during the youngest period of the row
+ versions lifetime and afterward replace it with a
+ 'valid forever' flag in its header.
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ As a first step, <productname>PostgreSQL</productname>
+ divides the complete range of
+ possible xids into two halves with the two split-points
+ 'txid_current' and 'txid_current + 2^31'. The half behind
+ 'txid_current' is considered to represent xids of the
+ 'past' and the half ahead of 'txid_current' those of the
+ 'future'. Those of the 'past' are valid (visible) and those
+ of the 'future' not.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ With each newly created transaction the two split-points
+ move forward. If 'txid_current + 2^31' reached a
+ row version with <literal>xmin</literal> equal to that value, it would
+ immediately jump from 'past' to 'future' and would be
+ no longer visible!
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If not handled in some way, data inserted many transactions ago
+ would become invisibile. The vacuum operation <firstterm>freeze</firstterm>
+ avoids this long before the split-point is reached by setting
+ a flag in the header of the row version which avoids
+ future comparison of its <literal>xmin/xmax</literal> and indicates
+ that the version is valid not only in the 'past'-half
+ but also in the 'future'-half, as well as in all coming
+ <glossterm linkend="glossary-xid">epochs</glossterm>.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Which row versions can be frozen by the vacuum operation?
+ Again, several criteria must be checked, and all must be met.
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be zero because only
+ non-deleted rows can be visible 'forever'.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> must be older than all currently
+ existing transactions. This guarantees that no existing
+ transaction can modify or delete the version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transactions of <literal>xmin</literal> and
+ <literal>xmax</literal> must be committed.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ At what point in time does the freeze operation take place?
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with its <command>FREEZE</command> option. In this case, all
+ pages are processed that are marked in the Visibility Map
+ as potentially having unfrozen rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command> without
+ any options but there are xids older than
+ <xref linkend="guc-vacuum-freeze-table-age"/>
+ (default: 150 million) minus
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million).
+ As before, all pages are processed that are
+ marked in the Visibility Map to potentially having unfrozen
+ rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When an Autovacuum process runs. Such a process acts in one
+ of two modes:
+ </simpara>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ In the <emphasis>normal mode</emphasis>, it skips
+ pages with row versions that are younger than
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million) and works only on pages where
+ all xids are older. The skipping of young xids prevents
+ work on such pages, which are likely to be changed
+ by one of the future SQL commands.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ The process switches
+ to an <emphasis>aggressive mode</emphasis> if it recognizes
+ that for the processed table the oldest xid exceeds
+ <xref linkend="guc-autovacuum-freeze-max-age"/>
+ (default: 200 million). The value of the oldest unfrozen
+ xid is stored per table in <literal>pg_class.relfrozenxid</literal>.
+ In this <emphasis>aggressive mode</emphasis> Autovacuum
+ processes all such pages of the selected table that are marked
+ in the Visibility Map to potentially have bloat or unfrozen rows.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In the first two cases and with Autovacuum in
+ <emphasis>aggressive mode</emphasis>, the system knows
+ to which value the oldest unfrozen xid has moved forward and
+ logs the value in <literal>pg_class.relfrozenxid</literal>.
+ The distance between this value and the 'txid_current' split
+ point becomes smaller, and the distance to 'txid_current + 2^31'
+ becomes larger than before.
+ </para>
+
+ <figure id="tutorial-freeze-figure">
+ <title>Freeze</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2">Protection against Wraparound Failure</bridgehead>
+
+ <para>
+ The Autovacuum processes are initiated by the constantly running
+ Autovacuum daemon. If the daemon detects that for a table
+ <literal>autovacuum_freeze_max_age</literal> is exceeded, it
+ starts an Autovacuum process in <emphasis>aggressive mode</emphasis>
+ (see above) — even if Autovacuum is disabled.
+ </para>
+
+ <bridgehead renderas="sect2">Visibility Map and Free Space Map</bridgehead>
+
+ <para>
+ The <link linkend="glossary-vm">Visibility Map</link>
+ (VM) contains two flags — stored as
+ two bits — for each page of the heap file. The
+ first bit indicates that the associated page does
+ not contain any bloat. The second bit indicates
+ that the page contains only frozen row versions.
+ </para>
+
+ <para>
+ Please consider two details. First, in most cases a page
+ contains many rows or row versions.
+ However, the flags are associated with the page,
+ not with an individual row version. The flags are set
+ only under the condition that they are valid for ALL
+ row versions of the page. Second, since there
+ are only two bits per page, the VM is considerably
+ smaller than the heap.
+ </para>
+
+ <para>
+ The setting of the flags is silently done by <command>VACUUM</command>
+ and Autovacuum during their bloat and freeze operations.
+ This is done to speed up future vacuum actions,
+ regular access to heap pages, and some access to
+ the index. Every data-modifying operation on any row
+ version of the page clears the flags.
+ </para>
+
+ <para>
+ The <link linkend="glossary-fsm">Free Space Map</link>
+ (FSM) tracks the amount of free space per page. It is
+ organized as a highly condensed b-tree of (rounded) sizes.
+ Whenever <command>VACUUM</command> or Autovacuum changes
+ the free space on any processed page, they log the new
+ values in the FSM in the same way as all other writing
+ processes.
+ </para>
+
+ <bridgehead renderas="sect2">Statistics</bridgehead>
+
+ <para>
+ Statistical information helps the <link
+ linkend="planner-stats">Query Planner</link> to make optimal
+ decisions for the generation of execution plans. This
+ information can be gathered with the SQL commands
+ <command>ANALYZE</command> or <command>VACUUM ANALYZE</command>.
+ But Autovacuum processes also gather
+ such information. Depending on the percentage of changed rows
+ <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ and minimum number of changed rows <xref linkend="guc-autovacuum-analyze-threshold"/>,
+ the Autovacuum daemon starts Autovacuum processes to collect
+ statistics per table. The automatic analysis
+ allows <productname>PostgreSQL</productname> to
+ adapt query execution to changing circumstances.
+ </para>
+
+ <para>
+ For more details about vacuum operations, especially for its
+ numerous parameters, see <xref linkend="routine-vacuuming"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-transactions-mvcc">
+ <title>Transactions</title>
+ <para>
+ <link linkend="tutorial-transactions">Transactions</link>
+ are a fundamental concept of relational database systems.
+ Their essential point is that they bundle multiple
+ read- or write-operations into a single all-or-nothing
+ operation. Furthermore, they separate and protect concurrent
+ actions of different connections from each other. Thereby
+ they implement the ACID paradigm.
+ </para>
+
+ <para>
+ In <productname>PostgreSQL</productname> there are two ways
+ to establish a transaction. The explicit way uses the keywords
+ <link linkend="sql-begin">BEGIN</link> and
+ <link linkend="sql-commit">COMMIT</link> (respectively
+ <link linkend="sql-rollback">ROLLBACK</link>) before
+ and after a sequence of SQL statements. The keywords mark
+ the transaction's start- and end-point. On the other hand, you
+ can omit the keywords. This is the implicit way, where
+ every single SQL command automatically establishes a new
+ transaction.
+
+ <programlisting>
+BEGIN; -- establish a new transaction
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+COMMIT; -- finish the transaction
+
+-- this UPDATE runs as the only command of a separate transaction ...
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+
+-- ... and this one runs in another transaction
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+ </programlisting>
+ </para>
+
+ <para>
+ As mentioned, the primary property of a transaction is its
+ atomicity: either all or none of its operations succeed,
+ regardless of the fact that it may consist of a lot of
+ different write-operations, and each such operation may
+ affect many rows. As soon as one of the
+ operations fails, all previous operations fail also, which
+ means that all modified rows retain their values as of the
+ beginning of the transaction.
+ </para>
+
+ <para>
+ The atomicity also affects the visibility of changes. No
+ connection running simultaneously with a data modifying
+ transaction will ever see any change before the
+ transaction successfully executes a <command>COMMIT</command>
+ — even in the lowest
+ <link linkend="transaction-iso">isolation level</link>
+ of transactions. <productname>PostgreSQL</productname>
+ never shows uncommitted changes to other connections.
+ </para>
+
+ <para>
+ The situation regarding visibility is somewhat different
+ from the point of view of the modifying transaction.
+ A <command>SELECT</command> command issued inside a
+ transaction shows all changes done so far by this
+ transaction.
+ </para>
+
+ <bridgehead renderas="sect2">How does it work?</bridgehead>
+
+ <para>
+ Every <command>INSERT</command>, <command>UPDATE</command>,
+ and <command>DELETE</command> command creates new row
+ versions — according to the MVCC rules. This
+ creates the risk that other transactions may see the
+ new row versions, and after a while and some more
+ activities of the modifying transaction they may see the
+ next row versions. Results would be a kind of 'moving
+ target' which would be contrary to the all-or-nothing
+ principle.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> overcomes this
+ problem by showing only such row versions to other
+ transactions whose originating transaction has
+ successfully committed. It skips all row versions of
+ uncommitted transactions. And
+ <productname>PostgreSQL</productname> solves one more
+ problem. Even the single <command>COMMIT</command>
+ command needs a short time interval for its execution.
+ Therefore its critical 'dead-or-survival' phase
+ runs in a privileged mode that cannot be
+ interrupted by other processes.
+ </para>
+
+ <bridgehead renderas="sect2">What are the benefits?</bridgehead>
+
+ <para>
+ Transactions relieve applications from many standard
+ actions that would otherwise need to be implemented for nearly every use case.
+ </para>
+
+ <para>
+ Business logic often contains strong, but for a computer,
+ relative abstract requirements. The above example shows
+ the transfers of some money from one account to another.
+ It is obvious
+ that the decrease of the one account and the increase of the
+ other must be indivisible. Nevertheless, there is no particular
+ need for an application to do something to ensure the
+ <glossterm linkend="glossary-atomicity">atomicity</glossterm>
+ of this behavior. It's enough to surround them with
+ <command>BEGIN</command> and <command>COMMIT</command>.
+ </para>
+
+ <para>
+ Applications often demand the feature of 'undoing'
+ previously taken actions under some application-specific
+ conditions. In such cases, the application simply issues a
+ <command>ROLLBACK</command> command instead of a
+ <command>COMMIT</command>. The <command>ROLLBACK</command>
+ cancels the transaction, and all changes made so far remain
+ invisible forever; it is as if they had never happened. There
+ is no need for the application to log its activities and
+ undo every step of the transaction separately.
+ </para>
+
+ <para>
+ Transactions ensure that the
+ database always remains
+ <glossterm linkend="glossary-consistency">consistent</glossterm>.
+ Declarative rules like
+ <link linkend="ddl-constraints-primary-keys">primary</link>- or
+ <link linkend="ddl-constraints-fk">foreign keys</link>,
+ <link linkend="ddl-constraints-check-constraints">checks</link>,
+ other constraints, or
+ <link linkend="trigger-definition">triggers</link>
+ are part of the all-or-nothing nature of transactions.
+ </para>
+
+ <para>
+ There is the additional feature
+ '<link linkend="transaction-iso">isolation level</link>',
+ which separates transactions from each other in certain ways.
+ It automatically prevents applications from some strange
+ situations.
+ </para>
+
+ <para>
+ Lastly, it is worth noticing that changes done by a
+ committed transaction will survive all failures in the application or
+ database cluster. The next chapter explains the
+ <glossterm linkend="glossary-durability">durability</glossterm>
+ guarantees.
+ </para>
+ </sect1>
+
+ <sect1 id="tutorial-reliability">
+ <title>Reliability</title>
+
+ <para>
+ Nothing is perfect and failures inevitably happen.
+ However, the most common types of failure are
+ well known and <productname>PostgreSQL</productname>
+ implements strategies to overcome them.
+ Such strategies use parts of the previously presented
+ techniques MVCC and transaction-rollback, plus additional
+ features.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the client side</bridgehead>
+ <para>
+ A <glossterm linkend="glossary-client">client</glossterm>
+ can fail in different ways. Its hardware can get damaged,
+ the power supply can fail, the network connection to the
+ server can break, or the client application may run into
+ a severe software error like a null pointer exception.
+ Because <productname>PostgreSQL</productname> uses a
+ client/server architecture, no direct problem for the
+ database will occur. In all of these cases, the
+ <glossterm linkend="glossary-backend">Backend process</glossterm>,
+ which is the client's counterpart at the server side,
+ may recognize that the network connection is no longer
+ working, or it may run into a timeout after a while. It
+ terminates, and there is no harm to the database. As
+ usual, uncommitted data changes initiated by this client
+ are not visible to any other client.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the server-side</bridgehead>
+
+ <bridgehead renderas="sect3">Instance failure</bridgehead>
+ <para>
+ The instance may suddenly fail because of <emphasis>power off</emphasis>
+ or other problems. This will affect all running processes, the RAM,
+ and possibly the consistency of disk files.
+ </para>
+
+ <para>
+ After a restart, <productname>PostgreSQL</productname>
+ automatically recognizes that the last shutdown of the
+ instance did not happen as expected: files might not be
+ closed properly and the <literal>postmaster.pid</literal>
+ file unexpectedly exists. <productname>PostgreSQL</productname>
+ tries to clean up the situation. This is possible because
+ all changes in the database are stored twice. First,
+ the WAL files contain them as a chronology of
+ <glossterm linkend="glossary-wal-record">WAL records</glossterm>,
+ which include the new data values and information about commit
+ actions. The WAL records are written first. Only then is
+ the data itself written to the heap and index files.
+ In contrast to the WAL records, this part may or may
+ not have been transferred entirely from Shared Memory
+ to the files.
+ </para>
+
+ <para>
+ The automatic recovery searches within the WAL files for
+ the latest
+ <glossterm linkend="glossary-checkpoint">checkpoint</glossterm>.
+ This checkpoint signals that the database files are in
+ a consistent state, especially that all WAL records up to
+ this point were successfully stored in heap and index files. Starting
+ here, the recovery process copies any remaining WAL records
+ to heap and index. The result is that the heap files contain all
+ changes recorded to the WAL and reach a consistent state. Changes of committed
+ transactions are visible; those of uncommitted transactions
+ are also in the files, but - as usual - they are never seen
+ by any of the following transactions because uncommitted
+ changes are never shown. These recovery actions run
+ automatically; it is not necessary that a
+ database administrator configure or start anything by
+ himself.
+ </para>
+
+ <bridgehead renderas="sect3">Disk crash</bridgehead>
+ <para>
+ If a disk crashes, the course of action described previously
+ cannot work: it is likely that the WAL files and/or the
+ data and index files are no longer available. The
+ database administrator must take special actions to
+ prepare for such a situation.
+ </para>
+
+ <para>
+ They obviously need a backup. How to take such a backup
+ and use it as a starting point for a recovery of the
+ cluster is explained in more detail in the next
+ <link linkend="tutorial-backup">chapter</link>.
+ </para>
+
+ <bridgehead renderas="sect3">Disk full</bridgehead>
+ <para>
+ It is conceivable that over time the disk gets full,
+ and there is no room for additional data. In this case,
+ <productname>PostgreSQL</productname> stops accepting
+ data-modifying commands or even terminates completely.
+ Committed data is neither lost nor corrupted.
+ </para>
+
+ <para>
+ To recover from such a situation, the administrator should
+ remove unused files from this disk. But they should never
+ delete files from the
+ <glossterm linkend="glossary-data-directory">data directory</glossterm>.
+ Nearly all of them are necessary for the consistency
+ of the database.
+ </para>
+
+ <bridgehead renderas="sect2">High availability</bridgehead>
+ <para>
+ Database servers can work together to allow a second
+ server to quickly take over the workload if the
+ primary server fails for whatever reason
+ (<link linkend="high-availability">high availability</link>),
+ or to allow several computers to serve the same data
+ for the purpose of load balancing.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-backup">
+ <title>Backup</title>
+
+ <para>
+ Taking backups is a basic task of database maintenance.
+ <productname>PostgreSQL</productname> supports
+ three different strategies; each has its own
+ strengths and weaknesses.
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ File system level backup
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Logical backup via <command>pg_dump</command>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Continuous archiving based on <command>pg_basebackup</command>
+ and WAL files
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <bridgehead renderas="sect2">File system level backup</bridgehead>
+ <para>
+ You can use any appropriate OS tool to create a
+ <link linkend="backup-file">copy</link>
+ of the cluster's directory structure and files. In
+ case of severe problems such a copy can serve as
+ the source of recovery. But in order to get a
+ <emphasis>USABLE</emphasis> backup by this method,
+ the database server <emphasis>MUST</emphasis> be
+ shut down during the complete runtime of the copy
+ command!
+ </para>
+
+ <para>
+ The obvious disadvantage of this method is that there
+ is a downtime.
+ The other two strategies run during regular operating
+ times.
+ </para>
+
+ <bridgehead renderas="sect2">Logical backup via pg_dump</bridgehead>
+ <para>
+ The tool <command>pg_dump</command> is able to take a
+ <link linkend="backup-dump">copy</link>
+ of the complete cluster or certain parts of it. It stores
+ the copy in the form of SQL commands like <command>CREATE</command>
+ and <command>COPY</command>. It runs in
+ parallel with other processes, in its own transaction.
+ </para>
+
+ <para>
+ The output of <command>pg_dump</command> may be used as
+ input of <command>psql</command> to restore the data
+ (or to copy it to another database).
+ </para>
+
+ <para>
+ The main advantage over the other two methods is that it
+ can pick parts of the cluster, e.g., a single table or one
+ database. The other two methods work only at the level of
+ the complete cluster.
+ </para>
+
+ <bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
+ <para>
+ <link linkend="continuous-archiving">This method</link>
+ is the most sophisticated and most complex one. It
+ consists of two phases.
+ </para>
+
+ <para>
+ First, you need to create a so-called
+ <firstterm>basebackup</firstterm> with the tool
+ <command>pg_basebackup</command>. The result is a
+ directory structure plus files which contain a
+ consistent copy of the original cluster.
+ <command>pg_basebackup</command> runs in
+ parallel with other processes in its own transaction.
+ </para>
+
+ <para>
+ The second step is recommended but not necessary. All
+ changes to the data are stored in WAL files. If you
+ continuously save such WAL files, you have the history
+ of the cluster. This history can be applied to a
+ basebackup in order to recreate
+ any state of the cluster between the time of
+ <command>pg_basebackup</command>'s start time and
+ any later point in time. This technique
+ is called 'Point-in-Time Recovery (PITR)'.
+ </para>
+
+ <para>
+ If configured, the
+ <glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
+ will automatically copy every single WAL file to a save location.
+ <link linkend="backup-archiving-wal">Its configuration</link>
+ consists mainly of a string that contains a copy command
+ in the operating system's syntax. In order to protect your
+ data against a disk crash, the destination location
+ of a basebackup as well as of the
+ <firstterm>archived WAL files</firstterm> should be on a
+ disk which is different from the data disk.
+ </para>
+
+ <para>
+ If it becomes necessary to restore the cluster, you have to
+ copy the basebackup and the archived WAL files to
+ their original directories. The configuration of this
+ <link linkend="backup-pitr-recovery">recovery procedure</link>
+ contains a string with the reversed copy command: from
+ archive location to database location.
+ </para>
+
+ </sect1>
+
+<!-- ToDo: replication, index-types, extension mechanism, ...
+ <sect1 id="tutorial-replication">
+ <title>Replication</title>
+
+ <para>
+...
+ </para>
+
+ </sect1>
+-->
+
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 38e8aa0bbf..7490d3c9c2 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -80,6 +80,7 @@
%allfiles;
<!-- developer's guide -->
+<!ENTITY architecture SYSTEM "architecture.sgml">
<!ENTITY arch-dev SYSTEM "arch-dev.sgml">
<!ENTITY bki SYSTEM "bki.sgml">
<!ENTITY catalogs SYSTEM "catalogs.sgml">
diff --git a/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
new file mode 100644
index 0000000000..bdbfc38387
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
@@ -0,0 +1,160 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="685" viewBox="0 0 900 685">
+ <title>
+ Server (Hardware, Container, or VM)
+ </title>
+ <style>
+ .text_normal,.text_small{font-style:normal;font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_small{font-size:12px}.text_normal{font-size:14px}
+ </style>
+ <defs>
+ <symbol id="rectangle_special_0">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="rectangle_special_1">
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="20" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="125">
+ 'my_schema' (optional)
+ </text>
+ <text class="text_small" x="20" y="145">
+ tables, views, ...
+ </text>
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="190">
+ (more system schemas)
+ </text>
+ </symbol>
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M450 10v230H0V0h440v10h10L440 0"/>
+ </symbol>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="270" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Server (Hardware, Container, or VM)
+ </text>
+ <path stroke="blue" stroke-width="2" fill="none" d="M20 110h790v555H20z"/>
+ <text class="text_normal" x="180" y="25" transform="translate(20 110)">
+ cluster 'data' (default, managed by one instance)
+ </text>
+ <path d="M50 110V80h790v555h-30" stroke="blue" stroke-width="2" fill="none"/>
+ <text class="text_normal" x="190" y="-10" transform="translate(45 110)">
+ cluster 'cluster_2' (optional, managed by a different instance)
+ </text>
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template0'
+ </text>
+ </g>
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template1'
+ </text>
+ </g>
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'my_db' (optional)
+ </text>
+ </g>
+ <g transform="translate(320 330)">
+ <rect width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4"/>
+ <text class="text_normal" x="15" y="27">
+ Global SQL objects
+ </text>
+ <path d="M0 5l-65-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M80 0v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M180 40h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M0 40l-45 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ </g>
+ <g transform="translate(335 405)">
+ <use xlink:href="#note"/>
+ <text class="text_small" x="10" y="20">
+ 1)
+ </text>
+ <text class="text_small" x="30" y="20">
+ By default, you work in the cluster 'data', database 'postgres',
+ </text>
+ <text class="text_small" x="30" y="35">
+ schema 'public'.
+ </text>
+ <text class="text_small" x="10" y="55">
+ 2)
+ </text>
+ <text class="text_small" x="30" y="55">
+ More system schemas: pg_catalog, information_schema,
+ </text>
+ <text class="text_small" x="30" y="70">
+ pg_temp, pg_toast.
+ </text>
+ <text class="text_small" x="10" y="90">
+ 3)
+ </text>
+ <text class="text_small" x="30" y="90">
+ Global SQL objects: Some SQL objects are automatically active
+ </text>
+ <text class="text_small" x="30" y="105">
+ and known database- or even cluster-wide.
+ </text>
+ <text class="text_small" x="10" y="125">
+ 4)
+ </text>
+ <text class="text_small" x="30" y="125">
+ The command 'initdb' creates a new cluster with the three
+ </text>
+ <text class="text_small" x="30" y="140">
+ databases 'template0', 'template1', and 'postgres'. The command
+ </text>
+ <text class="text_small" x="30" y="155">
+ 'createdb' creates a new database.
+ </text>
+ <text class="text_small" x="10" y="175">
+ 5)
+ </text>
+ <text class="text_small" x="30" y="175">
+ If multiple clusters are active on one server at the same time,
+ </text>
+ <text class="text_small" x="30" y="190">
+ each one is managed by an individual instance. Each such instance
+ </text>
+ <text class="text_small" x="30" y="205">
+ uses a different port.
+ </text>
+ <text class="text_small" x="10" y="225">
+ 6)
+ </text>
+ <text class="text_small" x="30" y="225">
+ No client application is allowed to connect to 'template0'.
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink.svg b/doc/src/sgml/images/cluster-db-schema-ink.svg
new file mode 100644
index 0000000000..86f878a12d
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink.svg
@@ -0,0 +1,482 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="685px"
+ viewBox="0 0 900 685"
+ id="svg147"
+ sodipodi:docname="cluster-db-schema-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Server (Hardware, Container, or VM)</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.34452555"
+ inkscape:cx="450"
+ inkscape:cy="342.5"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Server (Hardware, Container, or VM)</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs49">
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangle_special_0">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect6" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="195"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect8" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text10">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text12">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="195"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect14" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text16">(more system schemas)</text>
+ </symbol>
+ <!-- same as before, but one more schema -->
+ <symbol
+ id="rectangle_special_1">
+ <!-- the database -->
+ <rect
+ width="245"
+ height="225"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect19" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect21" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text23">schema 'public'</text>
+ <text
+ class="text_small"
+ x="20"
+ y="80"
+ id="text25">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect27" />
+ <text
+ class="text_normal"
+ x="20"
+ y="125"
+ id="text29">'my_schema' (optional)</text>
+ <text
+ class="text_small"
+ x="20"
+ y="145"
+ id="text31">tables, views, ...</text>
+ <rect
+ x="15"
+ y="170"
+ width="205"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect33" />
+ <text
+ class="text_small"
+ x="20"
+ y="190"
+ id="text35">(more system schemas)</text>
+ </symbol>
+ <symbol
+ id="note"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title38">UML Note</title>
+ <path
+ d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10"
+ id="path40" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path43" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path46" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect51" />
+ <text
+ class="text_big"
+ x="270"
+ y="40"
+ id="text53">Server (Hardware, Container, or VM)</text>
+ <!-- two clusters -->
+ <g
+ transform="translate(20 110)"
+ id="g59">
+ <rect
+ x="0"
+ y="0"
+ width="790"
+ height="555"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="rect55" />
+ <text
+ class="text_normal"
+ x="180"
+ y="25"
+ id="text57">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g
+ transform="translate(45 110)"
+ id="g65">
+ <path
+ d="M 5,0 v -30 h 790 v 555 h -30"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="path61" />
+ <text
+ class="text_normal"
+ x="190"
+ y="-10"
+ id="text63">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+ <!-- database template 0 -->
+ <g
+ transform="translate(40 155)"
+ id="g71">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use67" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text69">database 'template0'</text>
+ </g>
+ <!-- database template 1 -->
+ <g
+ transform="translate(290 155)"
+ id="g77">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use73" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text75">database 'template1'</text>
+ </g>
+ <!-- database postgres -->
+ <g
+ transform="translate(540 155)"
+ id="g83">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use79" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text81">database 'postgres'</text>
+ </g>
+ <!-- database my_db -->
+ <g
+ transform="translate(40 350)"
+ id="g89">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use85" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text87">database 'my_db' (optional)</text>
+ </g>
+ <!-- global objects -->
+ <g
+ transform="translate(320 330)"
+ id="g103">
+ <rect
+ x="0"
+ y="0"
+ width="180"
+ height="45"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="10 4 4 4"
+ id="rect91" />
+ <text
+ class="text_normal"
+ x="15"
+ y="27"
+ id="text93">Global SQL objects</text>
+ <path
+ d="M 0,5 l-65,-35"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path95" />
+ <path
+ d="M 80,0 v-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path97" />
+ <path
+ d="M 180,40 h50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path99" />
+ <path
+ d="M 0,40 l-45,20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path101" />
+ </g>
+ <!-- Some comments -->
+ <g
+ transform="translate(335 405)"
+ id="g145">
+ <use
+ xlink:href="#note"
+ x="0"
+ y="0"
+ id="use105" />
+ <text
+ class="text_small"
+ x="10"
+ y="20"
+ id="text107">1)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="20"
+ id="text109">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text
+ class="text_small"
+ x="30"
+ y="35"
+ id="text111">schema 'public'.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="55"
+ id="text113">2)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="55"
+ id="text115">More system schemas: pg_catalog, information_schema,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="70"
+ id="text117">pg_temp, pg_toast.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="90"
+ id="text119">3)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="90"
+ id="text121">Global SQL objects: Some SQL objects are automatically active</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text123">and known database- or even cluster-wide.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="125"
+ id="text125">4)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="125"
+ id="text127">The command 'initdb' creates a new cluster with the three</text>
+ <text
+ class="text_small"
+ x="30"
+ y="140"
+ id="text129">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text
+ class="text_small"
+ x="30"
+ y="155"
+ id="text131">'createdb' creates a new database.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="175"
+ id="text133">5)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="175"
+ id="text135">If multiple clusters are active on one server at the same time,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="190"
+ id="text137">each one is managed by an individual instance. Each such instance</text>
+ <text
+ class="text_small"
+ x="30"
+ y="205"
+ id="text139">uses a different port.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="225"
+ id="text141">6)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="225"
+ id="text143">No client application is allowed to connect to 'template0'.</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
new file mode 100644
index 0000000000..022bc45560
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -0,0 +1,173 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="685px"
+ viewBox="0 0 900 685" >
+
+ <title>Server (Hardware, Container, or VM)</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_0">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">(more system schemas)</text>
+ </symbol>
+
+ <!-- same as before, but one more schema -->
+ <symbol id="rectangle_special_1">
+ <!-- the database -->
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="20" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="125">'my_schema' (optional)</text>
+ <text class="text_small" x="20" y="145">tables, views, ...</text>
+
+ <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="190">(more system schemas)</text>
+ </symbol>
+
+ <symbol id="note" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="270" y="40">Server (Hardware, Container, or VM)</text>
+
+ <!-- two clusters -->
+ <g transform="translate(20 110)">
+ <rect x="0" y="0" width="790" height="555" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="180" y="25">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g transform="translate(45 110)">
+ <path d="M 5,0 v -30 h 790 v 555 h -30" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="190" y="-10">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+
+
+ <!-- database template 0 -->
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template0'</text>
+ </g>
+
+ <!-- database template 1 -->
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template1'</text>
+ </g>
+
+ <!-- database postgres -->
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'postgres'</text>
+ </g>
+
+ <!-- database my_db -->
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
+ </g>
+
+ <!-- global objects -->
+ <g transform="translate(320 330)">
+ <rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
+ <text class="text_normal" x="15" y="27">Global SQL objects</text>
+ <path d="M 0,5 l-65,-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ </g>
+
+ <!-- Some comments -->
+ <g transform="translate(335 405)">
+ <use xlink:href="#note" x="0" y="0" />
+
+ <text class="text_small" x="10" y="20">1)</text>
+ <text class="text_small" x="30" y="20">By default, you work in the cluster 'data', database 'postgres',</text>
+ <text class="text_small" x="30" y="35">schema 'public'.</text>
+
+ <text class="text_small" x="10" y="55">2)</text>
+ <text class="text_small" x="30" y="55">More system schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="70">pg_temp, pg_toast.</text>
+
+ <text class="text_small" x="10" y="90">3)</text>
+ <text class="text_small" x="30" y="90">Global SQL objects: Some SQL objects are automatically active</text>
+ <text class="text_small" x="30" y="105">and known database- or even cluster-wide.</text>
+
+ <text class="text_small" x="10" y="125">4)</text>
+ <text class="text_small" x="30" y="125">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="140">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="155">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="175">5)</text>
+ <text class="text_small" x="30" y="175">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="190">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="205">uses a different port.</text>
+
+ <text class="text_small" x="10" y="225">6)</text>
+ <text class="text_small" x="30" y="225">No client application is allowed to connect to 'template0'.</text>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/directories-ink-svgo.svg b/doc/src/sgml/images/directories-ink-svgo.svg
new file mode 100644
index 0000000000..c03c2607ee
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink-svgo.svg
@@ -0,0 +1,164 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="640" viewBox="0 0 900 640">
+ <title>
+ Directory structure of a cluster
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <symbol id="directory" stroke="blue" stroke-width=".3" fill="aqua">
+ <title>
+ Directory
+ </title>
+ <path d="M0 10h110v20H0z"/>
+ <path d="M0 10V8l3-3h35l3 3v2"/>
+ </symbol>
+ <symbol id="file" stroke="black" fill="none">
+ <title>
+ File
+ </title>
+ <path stroke="blue" d="M0 0h40v50H0z"/>
+ <path d="M5 10h20" stroke-dasharray="4 2"/>
+ <path d="M5 17h15" stroke-dasharray="6 2"/>
+ <path d="M5 24h25" stroke-dasharray="4 2"/>
+ <path d="M5 31h20" stroke-dasharray="5 2"/>
+ </symbol>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="50" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Directory Structure
+ </text>
+ <g transform="translate(20 100)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /pg/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ An arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 130)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ data/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of cluster 'data' (see: PGDATA)
+ </text>
+ </g>
+ <g transform="translate(120 160)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ base/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing per-database subdirectories
+ </text>
+ </g>
+ <g transform="translate(170 190)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 1/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of first database 'template0'
+ </text>
+ </g>
+ <g transform="translate(170 220)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12992/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of second database 'template1'
+ </text>
+ </g>
+ <g transform="translate(170 250)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12999/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data of third database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(170 280)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ nnnnn/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Optional: more subdirectories for databases, e.g. 'my_db'
+ </text>
+ </g>
+ <g transform="translate(120 310)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ global/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory with information about Global SQL Objects
+ </text>
+ </g>
+ <g transform="translate(120 340)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_wal/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 370)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_xact/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for transaction commit status ('pg_clog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 400)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_tblspc/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing symbolic links to tablespaces
+ </text>
+ </g>
+ <g transform="translate(120 430)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_... /
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Some more subdirectories
+ </text>
+ </g>
+ <g transform="translate(120 465)">
+ <use xlink:href="#file"/>
+ <use xlink:href="#file" x="50"/>
+ <text x="200" y="26" class="text_normal">
+ 'postmaster.pid' and other files with cluster-wide relevance
+ </text>
+ </g>
+ <g transform="translate(20 540)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ ... /xyz/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ Same or another arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 570)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ cluster_2/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of another cluster 'cluster_2'
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-ink.svg b/doc/src/sgml/images/directories-ink.svg
new file mode 100644
index 0000000000..238905cde8
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink.svg
@@ -0,0 +1,397 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="640px"
+ viewBox="0 0 900 640"
+ id="svg4006"
+ sodipodi:docname="directories-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata4010">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Directory structure of a cluster</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview4008"
+ showgrid="false"
+ inkscape:zoom="0.36875"
+ inkscape:cx="450"
+ inkscape:cy="320"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg4006" />
+ <title
+ id="title3856">Directory structure of a cluster</title>
+ <style
+ type="text/css"
+ id="style3858">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs3880">
+ <!-- Directory -->
+ <symbol
+ id="directory"
+ stroke="blue"
+ stroke-width="0.3px"
+ fill="aqua">
+ <title
+ id="title3860">Directory</title>
+ <rect
+ x="0"
+ y="10"
+ width="110"
+ height="20"
+ id="rect3862" />
+ <path
+ d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2"
+ id="path3864" />
+ </symbol>
+ <!-- File -->
+ <symbol
+ id="file"
+ stroke="black"
+ fill="none">
+ <title
+ id="title3867">File</title>
+ <rect
+ x="0"
+ y="0"
+ width="40"
+ height="50"
+ stroke="blue"
+ id="rect3869" />
+ <path
+ d="M 5,10 h 20"
+ stroke-dasharray="4 2"
+ id="path3871" />
+ <path
+ d="M 5,17 h 15"
+ stroke-dasharray="6 2"
+ id="path3873" />
+ <path
+ d="M 5,24 h 25"
+ stroke-dasharray="4 2"
+ id="path3875" />
+ <path
+ d="M 5,31 h 20"
+ stroke-dasharray="5 2"
+ id="path3877" />
+ </symbol>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect3882" />
+ <!-- caption -->
+ <text
+ x="200"
+ y="50"
+ class="text_big"
+ id="text3884">Directory Structure</text>
+ <!-- the directories -->
+ <g
+ transform="translate(20, 100)"
+ id="g3892">
+ <use
+ xlink:href="#directory"
+ id="use3886" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3888">... /pg/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text3890">An arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 130)"
+ id="g3900">
+ <use
+ xlink:href="#directory"
+ id="use3894" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3896">data/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text3898">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+ <g
+ transform="translate(120, 160)"
+ id="g3908">
+ <use
+ xlink:href="#directory"
+ id="use3902" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3904">base/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text3906">Subdirectory containing per-database subdirectories</text>
+ </g>
+ <!-- -->
+ <g
+ transform="translate(170, 190)"
+ id="g3916">
+ <use
+ xlink:href="#directory"
+ id="use3910" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3912">1/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text3914">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g
+ transform="translate(170, 220)"
+ id="g3924">
+ <use
+ xlink:href="#directory"
+ id="use3918" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3920">12992/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text3922">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g
+ transform="translate(170, 250)"
+ id="g3932">
+ <use
+ xlink:href="#directory"
+ id="use3926" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3928">12999/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text3930">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g
+ transform="translate(170, 280)"
+ id="g3940">
+ <use
+ xlink:href="#directory"
+ id="use3934" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3936">nnnnn/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text3938">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+ <g
+ transform="translate(120, 310)"
+ id="g3948">
+ <use
+ xlink:href="#directory"
+ id="use3942" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3944">global/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text3946">Subdirectory with information about Global SQL Objects</text>
+ </g>
+ <g
+ transform="translate(120, 340)"
+ id="g3956">
+ <use
+ xlink:href="#directory"
+ id="use3950" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3952">pg_wal/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text3954">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 370)"
+ id="g3964">
+ <use
+ xlink:href="#directory"
+ id="use3958" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3960">pg_xact/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text3962">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 400)"
+ id="g3972">
+ <use
+ xlink:href="#directory"
+ id="use3966" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3968">pg_tblspc/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text3970">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+ <g
+ transform="translate(120, 430)"
+ id="g3980">
+ <use
+ xlink:href="#directory"
+ id="use3974" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3976">pg_... /</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text3978">Some more subdirectories</text>
+ </g>
+ <g
+ transform="translate(120, 465)"
+ id="g3988">
+ <use
+ xlink:href="#file"
+ x="0"
+ y="0"
+ id="use3982" />
+ <use
+ xlink:href="#file"
+ x="50"
+ y="0"
+ id="use3984" />
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text3986">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+ <!-- next cluster -->
+ <g
+ transform="translate(20, 540)"
+ id="g3996">
+ <use
+ xlink:href="#directory"
+ id="use3990" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text3992">... /xyz/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text3994">Same or another arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 570)"
+ id="g4004">
+ <use
+ xlink:href="#directory"
+ id="use3998" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text4000">cluster_2/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text4002">Root of another cluster 'cluster_2'</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
new file mode 100644
index 0000000000..757342a554
--- /dev/null
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="640px"
+ viewBox="0 0 900 640">
+
+ <title>Directory structure of a cluster</title>
+
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Directory -->
+ <symbol id="directory" stroke="blue" stroke-width="0.3px" fill="aqua">
+ <title>Directory</title>
+ <rect x="0" y="10" width="110" height="20" />
+ <path d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2" />
+ </symbol>
+
+ <!-- File -->
+ <symbol id="file" stroke="black" fill="none" >
+ <title>File</title>
+ <rect x="0" y="0" width="40" height="50" stroke="blue" />
+ <path d="M 5,10 h 20" stroke-dasharray="4 2" />
+ <path d="M 5,17 h 15" stroke-dasharray="6 2" />
+ <path d="M 5,24 h 25" stroke-dasharray="4 2" />
+ <path d="M 5,31 h 20" stroke-dasharray="5 2" />
+ </symbol>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption -->
+ <text x="200" y="50" class="text_big">Directory Structure</text>
+
+ <!-- the directories -->
+ <g transform="translate(20, 100)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /pg/</text>
+ <text x="300" y="26" class="text_normal">An arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 130)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">data/</text>
+ <text x="250" y="26" class="text_normal">Root of cluster 'data' (see: PGDATA)</text>
+ </g>
+
+ <g transform="translate(120, 160)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">base/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing per-database subdirectories</text>
+ </g>
+
+ <!-- -->
+ <g transform="translate(170, 190)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">1/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of first database 'template0'</text>
+ </g>
+ <g transform="translate(170, 220)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12992/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of second database 'template1'</text>
+ </g>
+ <g transform="translate(170, 250)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12999/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data of third database 'postgres'</text>
+ </g>
+ <g transform="translate(170, 280)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">nnnnn/</text>
+ <text x="150" y="26" class="text_normal">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ </g>
+
+ <g transform="translate(120, 310)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">global/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory with information about Global SQL Objects</text>
+ </g>
+
+ <g transform="translate(120, 340)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 370)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 400)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing symbolic links to tablespaces</text>
+ </g>
+
+ <g transform="translate(120, 430)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_... /</text>
+ <text x="200" y="26" class="text_normal">Some more subdirectories</text>
+ </g>
+
+ <g transform="translate(120, 465)">
+ <use xlink:href="#file" x="0" y="0" />
+ <use xlink:href="#file" x="50" y="0" />
+ <text x="200" y="26" class="text_normal">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+
+ <!-- next cluster -->
+ <g transform="translate(20, 540)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">... /xyz/</text>
+ <text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 570)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster 'cluster_2'</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink-svgo.svg b/doc/src/sgml/images/freeze-ink-svgo.svg
new file mode 100644
index 0000000000..b1543ffae5
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink-svgo.svg
@@ -0,0 +1,84 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="320" viewBox="0 0 850 320">
+ <title>
+ Freeze
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100)"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="70" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ <tspan font-style="italic" font-weight="700">Freeze</tspan> to keep visible
+ </text>
+ <g fill="none" transform="translate(170 190)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_120" startOffset="11.2%">(1)</textPath> <textPath xlink:href="#Path_120" startOffset="61.2%">(5)</textPath> <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%">|</textPath> <textPath xlink:href="#Path_120" startOffset="34%">(2)</textPath> <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(3)</textPath> <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%">|</textPath> <textPath xlink:href="#Path_120" startOffset="55%">(4)</textPath>
+ </text>
+ <path d="M-80-80L80 80" stroke="black"/>
+ <text class="text_normal" letter-spacing="12" transform="rotate(45 40.78 -38.1)">
+ PAST
+ </text>
+ <text class="text_normal" letter-spacing="12" transform="rotate(-135 27.43 23.79)">
+ FUTURE
+ </text>
+ <use xlink:href="#frozenPoint" transform="rotate(10)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(25)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(40)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(55)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(70)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(85)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(100)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(115)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(130)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(145)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(160)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(175)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(190)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(205)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(220)"/>
+ </g>
+ <g class="text_normal" transform="translate(380 30)">
+ <text>
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25">
+ 1: txid_current + 2 ^ 31 (split-point)
+ </text>
+ <text y="50">
+ 2: autovacuum_freeze_max_age (200 mio.)
+ </text>
+ <text y="75">
+ 3: vacuum_freeze_table_age (150 mio.)
+ </text>
+ <text y="100">
+ 4: vacuum_freeze_min_age (50 mio.)
+ </text>
+ <text y="125">
+ 5: txid_current (split-point, youngest xid)
+ </text>
+ <text y="155">
+ per table: pg_class.relfrozenxid <tspan font-weight="700">must</tspan> be between (1) and (5);
+ </text>
+ <text y="175" x="75">
+ normally it is between (3) and (4)
+ </text>
+ <use xlink:href="#unfrozenPoint" transform="translate(106 200)"/>
+ <text y="205" x="20">
+ Unfrozen xid
+ </text>
+ <use xlink:href="#frozenPoint" transform="translate(106 224)"/>
+ <text y="230" x="20">
+ Frozen xid
+ </text>
+ <text y="260">
+ (figure is out of scale)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink.svg b/doc/src/sgml/images/freeze-ink.svg
new file mode 100644
index 0000000000..316703d069
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink.svg
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="320px"
+ viewBox="0 0 850 320"
+ id="svg147"
+ sodipodi:docname="freeze-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Freeze</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1295"
+ inkscape:window-height="803"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="153.18182"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Freeze</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs11">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle
+ id="frozenPoint"
+ r="3"
+ stroke="green"
+ fill="green"
+ transform="translate(-100, 0)" />
+ <circle
+ id="unfrozenPoint"
+ r="3"
+ stroke="green"
+ fill="none"
+ transform="translate(-100, 0)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect13" />
+ <text
+ class="text_big"
+ x="70"
+ y="40"
+ id="text17"><tspan
+ style="font-style:italic;font-weight:bold"
+ id="tspan15">
+ Freeze</tspan>
+ to keep visible</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 190)"
+ id="g111">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle19" />
+ <text
+ class="text_normal"
+ id="text43">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath21">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath23">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath25">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="11.2%"
+ id="textPath27">(1)</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="61.2%"
+ id="textPath29">(5)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="red"
+ stroke-width="3"
+ startOffset="34%"
+ id="textPath31">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="34%"
+ id="textPath33">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="black"
+ stroke-width="3"
+ startOffset="45%"
+ id="textPath35">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath37">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="green"
+ stroke-width="3"
+ startOffset="55%"
+ id="textPath39">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="55%"
+ id="textPath41">(4)</textPath>
+ </text>
+ <!-- split it into 'past' and 'future' -->
+ <path
+ d="M -80 -80 l 160 160"
+ stroke="black"
+ id="path45" />
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(-15, -40) rotate(45)"
+ id="text47">PAST</text>
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(30, 60) rotate(225)"
+ id="text49">FUTURE</text>
+ <g
+ transform="rotate(10)"
+ id="g53">
+ <use
+ xlink:href="#frozenPoint"
+ id="use51" />
+ </g>
+ <g
+ transform="rotate(25)"
+ id="g57">
+ <use
+ xlink:href="#frozenPoint"
+ id="use55" />
+ </g>
+ <g
+ transform="rotate(40)"
+ id="g61">
+ <use
+ xlink:href="#frozenPoint"
+ id="use59" />
+ </g>
+ <g
+ transform="rotate(55)"
+ id="g65">
+ <use
+ xlink:href="#frozenPoint"
+ id="use63" />
+ </g>
+ <g
+ transform="rotate(70)"
+ id="g69">
+ <use
+ xlink:href="#frozenPoint"
+ id="use67" />
+ </g>
+ <g
+ transform="rotate(85)"
+ id="g73">
+ <use
+ xlink:href="#frozenPoint"
+ id="use71" />
+ </g>
+ <g
+ transform="rotate(100)"
+ id="g77">
+ <use
+ xlink:href="#frozenPoint"
+ id="use75" />
+ </g>
+ <g
+ transform="rotate(115)"
+ id="g81">
+ <use
+ xlink:href="#frozenPoint"
+ id="use79" />
+ </g>
+ <g
+ transform="rotate(130)"
+ id="g85">
+ <use
+ xlink:href="#frozenPoint"
+ id="use83" />
+ </g>
+ <g
+ transform="rotate(145)"
+ id="g89">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use87" />
+ </g>
+ <g
+ transform="rotate(160)"
+ id="g93">
+ <use
+ xlink:href="#frozenPoint"
+ id="use91" />
+ </g>
+ <g
+ transform="rotate(175)"
+ id="g97">
+ <use
+ xlink:href="#frozenPoint"
+ id="use95" />
+ </g>
+ <g
+ transform="rotate(190)"
+ id="g101">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use99" />
+ </g>
+ <g
+ transform="rotate(205)"
+ id="g105">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use103" />
+ </g>
+ <g
+ transform="rotate(220)"
+ id="g109">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use107" />
+ </g>
+ </g>
+ <!-- legend -->
+ <g
+ class="text_normal"
+ transform="translate(380 30)"
+ id="g145">
+ <text
+ id="text117">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan113">^</tspan>
+<tspan
+ dy="5"
+ id="tspan115">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text119">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text
+ y="50"
+ id="text121">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text
+ y="75"
+ id="text123">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text
+ y="100"
+ id="text125">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text
+ y="125"
+ id="text127">5: txid_current (split-point, youngest xid)</text>
+ <text
+ y="155"
+ id="text131">per table: pg_class.relfrozenxid
+ <tspan
+ style="font-weight:bold"
+ id="tspan129">must</tspan>
+ be between (1) and (5);</text>
+ <text
+ y="175"
+ x="75"
+ id="text133">normally it is between (3) and (4)</text>
+ <use
+ xlink:href="#unfrozenPoint"
+ transform="translate(106, 200)"
+ id="use135" />
+ <text
+ y="205"
+ x="20"
+ id="text137">Unfrozen xid</text>
+ <use
+ xlink:href="#frozenPoint"
+ transform="translate(106, 224)"
+ id="use139" />
+ <text
+ y="230"
+ x="20"
+ id="text141">Frozen xid</text>
+ <text
+ y="260"
+ id="text143">(figure is out of scale)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-raw.svg b/doc/src/sgml/images/freeze-raw.svg
new file mode 100644
index 0000000000..9482167c3f
--- /dev/null
+++ b/doc/src/sgml/images/freeze-raw.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="320px"
+ viewBox="0 0 850 320" >
+
+ <title>Freeze</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100, 0)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100, 0)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="70" y="40"><tspan style="font-style:italic;font-weight:bold">
+ Freeze</tspan> to keep visible</text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 190)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_120" startOffset="11.2%" >(1)</textPath>
+ <textPath xlink:href="#Path_120" startOffset="61.2%" >(5)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="34%" >(2)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(3)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="55%" >(4)</textPath>
+
+ </text>
+
+ <!-- split it into 'past' and 'future' -->
+ <path d="M -80 -80 l 160 160" stroke="black" />
+ <text class="text_normal" letter-spacing="12" transform="translate(-15, -40) rotate(45)">PAST</text>
+ <text class="text_normal" letter-spacing="12" transform="translate(30, 60) rotate(225)">FUTURE</text>
+
+ <g transform="rotate(10)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(25)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(40)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(55)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(70)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(85)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(100)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(115)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(130)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(145)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(160)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(175)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(190)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(205)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(220)"><use xlink:href="#unfrozenPoint"/></g>
+
+ </g>
+
+ <!-- legend -->
+ <g class="text_normal" transform="translate(380 30)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text y="50">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text y="75">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text y="100">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text y="125">5: txid_current (split-point, youngest xid)</text>
+ <text y="155">per table: pg_class.relfrozenxid
+ <tspan style="font-weight:bold">must</tspan> be between (1) and (5);</text>
+ <text y="175" x="75">normally it is between (3) and (4)</text>
+
+ <use xlink:href="#unfrozenPoint" transform="translate(106, 200)"/>
+ <text y="205" x="20">Unfrozen xid</text>
+
+ <use xlink:href="#frozenPoint" transform="translate(106, 224)"/>
+ <text y="230" x="20">Frozen xid</text>
+
+ <text y="260">(figure is out of scale)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
new file mode 100644
index 0000000000..b5cdec9553
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
@@ -0,0 +1,83 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="720" height="430" viewBox="0 0 720 430">
+ <title>
+ Hierarchy of Internal Objects
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Hierarchy of internal Objects
+ </text>
+ <g fill="none">
+ <g transform="translate(350 240)">
+ <ellipse rx="320" ry="170" stroke="blue"/>
+ <text class="text_normal" x="-140" y="-130">
+ Cluster
+ </text>
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-60" y="5">
+ Database Names
+ </text>
+ </g>
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-40" y="5">
+ Tablespace
+ </text>
+ </g>
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-70" y="5">
+ Replication Origins
+ </text>
+ </g>
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue"/>
+ <text class="text_normal" x="-60" y="-3">
+ Subscription for
+ </text>
+ <text class="text_normal" x="-68" y="10">
+ Logical Replication
+ </text>
+ </g>
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-15" y="5">
+ Role
+ </text>
+ </g>
+ </g>
+ <g transform="translate(270 250)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2"/>
+ <text class="text_normal" x="-60" y="-80">
+ Database
+ </text>
+ <g transform="translate(-150 -30)">
+ <ellipse rx="50" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Extension
+ </text>
+ </g>
+ <g transform="translate(-155 35)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Collation
+ </text>
+ </g>
+ <g transform="translate(30 20)">
+ <ellipse rx="140" ry="70" stroke="blue"/>
+ <text class="text_normal" x="-80" y="-35">
+ Schema
+ </text>
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue"/>
+ <text class="text_normal" x="-50" y="5">
+ Table, View, ...
+ </text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
new file mode 100644
index 0000000000..1571df24fe
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="720px"
+ height="430px"
+ viewBox="0 0 720 430"
+ id="svg4243"
+ sodipodi:docname="internal-objects-hierarchy-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata4249">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Hierarchy of Internal Objects</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs4247" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="640"
+ inkscape:window-height="480"
+ id="namedview4245"
+ showgrid="false"
+ inkscape:zoom="0.525"
+ inkscape:cx="360"
+ inkscape:cy="215"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg4243" />
+ <title
+ id="title4163">Hierarchy of Internal Objects</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4165">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect4167" />
+ <text
+ class="text_big"
+ x="200"
+ y="40"
+ id="text4169">Hierarchy of internal Objects</text>
+ <!-- set centre of figure and default values -->
+ <g
+ transform="translate(350 240)"
+ fill="none"
+ id="g4241">
+ <g
+ id="g4207">
+ <ellipse
+ rx="320"
+ ry="170"
+ stroke="blue"
+ id="ellipse4171" />
+ <text
+ class="text_normal"
+ x="-140"
+ y="-130"
+ id="text4173">Cluster</text>
+ <g
+ transform="translate(40 -125)"
+ id="g4179">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse4175" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="5"
+ id="text4177">Database Names</text>
+ </g>
+ <g
+ transform="translate(180 -70)"
+ id="g4185">
+ <ellipse
+ rx="60"
+ ry="20"
+ stroke="blue"
+ id="ellipse4181" />
+ <text
+ class="text_normal"
+ x="-40"
+ y="5"
+ id="text4183">Tablespace</text>
+ </g>
+ <g
+ transform="translate(230 -5)"
+ id="g4191">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse4187" />
+ <text
+ class="text_normal"
+ x="-70"
+ y="5"
+ id="text4189">Replication Origins</text>
+ </g>
+ <g
+ transform="translate(200 70)"
+ id="g4199">
+ <ellipse
+ rx="78"
+ ry="27"
+ stroke="blue"
+ id="ellipse4193" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-3"
+ id="text4195">Subscription for</text>
+ <text
+ class="text_normal"
+ x="-68"
+ y="10"
+ id="text4197">Logical Replication</text>
+ </g>
+ <g
+ transform="translate(100 120)"
+ id="g4205">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse4201" />
+ <text
+ class="text_normal"
+ x="-15"
+ y="5"
+ id="text4203">Role</text>
+ </g>
+ </g>
+ <g
+ transform="translate(-80 10)"
+ id="g4239">
+ <ellipse
+ rx="220"
+ ry="110"
+ stroke="blue"
+ stroke-width="2px"
+ id="ellipse4209" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-80"
+ id="text4211">Database</text>
+ <g
+ transform="translate(-120 -50)"
+ id="g4237">
+ <g
+ transform="translate(-30 20)"
+ id="g4217">
+ <ellipse
+ rx="50"
+ ry="20"
+ stroke="blue"
+ id="ellipse4213" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text4215">Extension</text>
+ </g>
+ <g
+ transform="translate(-35 85)"
+ id="g4223">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse4219" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text4221">Collation</text>
+ </g>
+ <g
+ transform="translate(150 70)"
+ id="g4235">
+ <ellipse
+ rx="140"
+ ry="70"
+ stroke="blue"
+ id="ellipse4225" />
+ <text
+ class="text_normal"
+ x="-80"
+ y="-35"
+ id="text4227">Schema</text>
+ <g
+ transform="translate(20 10)"
+ id="g4233">
+ <ellipse
+ rx="90"
+ ry="30"
+ stroke="blue"
+ id="ellipse4229" />
+ <text
+ class="text_normal"
+ x="-50"
+ y="5"
+ id="text4231">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
new file mode 100644
index 0000000000..a58f334fe3
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="720px" height="430px"
+ viewBox="0 0 720 430" >
+
+ <title>Hierarchy of Internal Objects</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="200" y="40">Hierarchy of internal Objects</text>
+
+
+ <!-- set centre of figure and default values -->
+ <g transform="translate(350 240)" fill="none">
+
+ <g>
+ <ellipse rx="320" ry="170" stroke="blue" />
+ <text class="text_normal" x="-140" y="-130">Cluster</text>
+
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-60" y="5">Database Names</text>
+ </g>
+
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue" />
+ <text class="text_normal" x="-40" y="5">Tablespace</text>
+ </g>
+
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-70" y="5">Replication Origins</text>
+ </g>
+
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue" />
+ <text class="text_normal" x="-60" y="-3">Subscription for</text>
+ <text class="text_normal" x="-68" y="10">Logical Replication</text>
+ </g>
+
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-15" y="5">Role</text>
+ </g>
+
+ </g>
+
+ <g transform="translate(-80 10)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2px" />
+ <text class="text_normal" x="-60" y="-80">Database</text>
+
+ <g transform="translate(-120 -50)">
+ <g transform="translate(-30 20)">
+ <ellipse rx="50" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Extension</text>
+ </g>
+
+ <g transform="translate(-35 85)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Collation</text>
+ </g>
+
+ <g transform="translate(150 70)">
+ <ellipse rx="140" ry="70" stroke="blue" />
+ <text class="text_normal" x="-80" y="-35">Schema</text>
+
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue" />
+ <text class="text_normal" x="-50" y="5">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink-svgo.svg b/doc/src/sgml/images/mvcc-ink-svgo.svg
new file mode 100644
index 0000000000..6ff6a4da79
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink-svgo.svg
@@ -0,0 +1,151 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="150" viewBox="0 0 850 150">
+ <title>
+ MVCC
+ </title>
+ <style>
+ .text_small{font-style:normal;font-weight:400;font-size:10px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <marker id="triangle_1" markerWidth="10" markerHeight="10" refX="5" refY="5" orient="auto" stroke="black" fill="none">
+ <path d="M0 0l10 5-10 5"/>
+ </marker>
+ <path id="arrow" d="M0 0q20-15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+ <g id="tuple" stroke="black">
+ <path d="M80 0H0v20h80M29 0v20M60 0v20"/>
+ <path d="M80 0h15M80 20h15" stroke-dasharray="2 1"/>
+ </g>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <g fill="none">
+ <g transform="translate(20 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">123</tspan> <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)" fill="#00f">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 83)" fill="#00f">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(185 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">135</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 53)" fill="#00f">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(350 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">142</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 23)" fill="#00f">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(515 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">821</tspan> <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 821
+ </text>
+ <text class="text_small" transform="translate(125 23)">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(740 110)">
+ <path d="M102-20H-18v60" stroke="black"/>
+ <text font-weight="400" font-size="14" font-family=""Open Sans",sans-serif" fill="#000">
+ Legend
+ </text>
+ <use xlink:href="#tuple" transform="translate(0 10)"/>
+ <text class="text_small" transform="translate(3 23)">
+ xmin
+ </text>
+ <text class="text_small" transform="translate(32 23)">
+ xmax
+ </text>
+ <text class="text_small" transform="translate(65 23)">
+ data
+ </text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink.svg b/doc/src/sgml/images/mvcc-ink.svg
new file mode 100644
index 0000000000..80ae8d29e0
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink.svg
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="150px"
+ viewBox="0 0 850 150"
+ id="svg4396"
+ sodipodi:docname="mvcc-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata4400">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>MVCC</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1266"
+ inkscape:window-height="788"
+ id="namedview4398"
+ showgrid="false"
+ inkscape:zoom="0.44470588"
+ inkscape:cx="425"
+ inkscape:cy="68.253968"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg4396" />
+ <title
+ id="title4251">MVCC</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4253">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs4264">
+ <marker
+ id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto"
+ stroke="black"
+ fill="none">
+ <path
+ d="M 0,0 L 10,5 L 0,10"
+ id="path4255" />
+ </marker>
+ <g
+ id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path
+ d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20"
+ stroke="black"
+ id="path4258" />
+ <!-- prolong the rectangle -->
+ <path
+ d="M 80 0 h 15 M 80 20 h 15"
+ stroke="black"
+ stroke-dasharray="2 1"
+ id="path4260" />
+ </g>
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path
+ id="arrow"
+ d="M 0 0 Q 20 -15 40 0"
+ stroke="black"
+ marker-end="url(#triangle_1)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect4266" />
+ <!-- set default values -->
+ <g
+ fill="none"
+ id="g4394">
+ <!-- start plus first INSERT -->
+ <g
+ transform="translate(20, 40)"
+ id="g4284">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4272">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4268">123</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4270">: INSERT</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4274" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4276" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ style="fill:blue"
+ id="text4278">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text4280">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ style="fill:blue"
+ id="text4282">'x'</text>
+ </g>
+ <!-- first UPDATE -->
+ <g
+ transform="translate(185, 40)"
+ id="g4310">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4290">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4286">135</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4288">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4292" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use4294" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ style="fill:blue"
+ id="text4296">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text4298">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ style="fill:blue"
+ id="text4300">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4302" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text4304">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text4306">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text4308">'x'</text>
+ </g>
+ <!-- next UPDATE -->
+ <g
+ transform="translate(350, 40)"
+ id="g4344">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4316">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4312">142</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4314">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4318" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use4320" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ style="fill:blue"
+ id="text4322">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text4324">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ style="fill:blue"
+ id="text4326">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use4328" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text4330">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text4332">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text4334">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4336" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text4338">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text4340">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text4342">'x'</text>
+ </g>
+ <!-- DELETE -->
+ <g
+ transform="translate(515, 40)"
+ id="g4378">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4350">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4346">821</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4348">: DELTE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4352" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use4354" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text4356">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text4358">821</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ id="text4360">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use4362" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text4364">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ id="text4366">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text4368">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4370" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text4372">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text4374">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text4376">'x'</text>
+ </g>
+ <!-- LEGEND -->
+ <g
+ transform="translate(740, 110)"
+ id="g4392">
+ <path
+ d="M 102 -20 h -120 v 60"
+ stroke="black"
+ id="path4380" />
+ <text
+ class="text_normal"
+ transform="translate(0, 0)"
+ id="text4382">Legend</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(0, 10)"
+ id="use4384" />
+ <text
+ class="text_small"
+ transform="translate(3, 23)"
+ id="text4386">xmin</text>
+ <text
+ class="text_small"
+ transform="translate(32, 23)"
+ id="text4388">xmax</text>
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text4390">data</text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-raw.svg b/doc/src/sgml/images/mvcc-raw.svg
new file mode 100644
index 0000000000..ee27e3df7b
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-raw.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="150px"
+ viewBox="0 0 850 150" >
+
+ <title>MVCC</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <marker id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto" stroke="black" fill="none">
+ <path d="M 0,0 L 10,5 L 0,10" />
+ </marker>
+
+ <g id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20" stroke="black"/>
+ <!-- prolong the rectangle -->
+ <path d="M 80 0 h 15 M 80 20 h 15" stroke="black" stroke-dasharray="2 1"/>
+ </g>
+
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path id="arrow" d="M 0 0 Q 20 -15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- set default values -->
+ <g fill="none">
+
+ <!-- start plus first INSERT -->
+ <g transform="translate(20, 40)">
+
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">123</tspan>
+ <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)" style="fill:blue">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 83)" style="fill:blue">'x'</text>
+ </g>
+
+ <!-- first UPDATE -->
+ <g transform="translate(185, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">135</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 53)" style="fill:blue">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- next UPDATE -->
+ <g transform="translate(350, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">142</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 23)" style="fill:blue">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- DELETE -->
+ <g transform="translate(515, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">821</tspan>
+ <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">821</text>
+ <text class="text_small" transform="translate(125, 23)">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- LEGEND -->
+ <g transform="translate(740, 110)">
+ <path d="M 102 -20 h -120 v 60" stroke="black"/>
+ <text class="text_normal" transform="translate(0, 0)">Legend</text>
+ <use xlink:href="#tuple" transform="translate(0, 10)"/>
+ <text class="text_small" transform="translate(3, 23)">xmin</text>
+ <text class="text_small" transform="translate(32, 23)">xmax</text>
+ <text class="text_small" transform="translate(65, 23)">data</text>
+ </g>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink-svgo.svg b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
new file mode 100644
index 0000000000..aa0445352d
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
@@ -0,0 +1,285 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 900 600">
+ <title>
+ PG Overall Server Architecture
+ </title>
+ <style>
+ .text_big{font-style:normal}.text_big,.text_comment,.text_normal,.text_small{font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_normal,.text_small{font-style:normal}.text_small{font-size:12px}.text_normal{font-size:14px}.text_big{font-size:24px}.text_comment{font-style:italic;font-size:14px}
+ </style>
+ <defs>
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (200 x 20 px)
+ </title>
+ <path d="M200 10v10H0V0h190v10h10L190 0"/>
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (250 x 20 px)
+ </title>
+ <path d="M250 10v10H0V0h240v10h10L240 0"/>
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (100 x 35 px)
+ </title>
+ <path d="M100 10v25H0V0h90v10h10L90 0"/>
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (170 x 50 px)
+ </title>
+ <path d="M170 10v40H0V0h160v10h10L160 0"/>
+ </symbol>
+ <symbol id="state_300x120">
+ <title>
+ UML State (300x120)
+ </title>
+ <rect width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>
+ UML State (350x120)
+ </title>
+ <rect width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="disc" stroke="blue" fill="none">
+ <title>
+ Disc
+ </title>
+ <ellipse cx="51" cy="13" rx="50" ry="12"/>
+ <path d="M1 13v60"/>
+ <path d="M101 13v60"/>
+ <path d="M1 73a50 12 0 00100 0"/>
+ </symbol>
+ <symbol id="laptop" stroke="black" fill="none">
+ <title>
+ Laptop
+ </title>
+ <path d="M20 40V0h54v40l15 15H5l15-15h54"/>
+ <path d="M23 3h48v34H23z"/>
+ <path d="M30 10h20"/>
+ <path d="M30 15h25"/>
+ <path d="M30 20h10"/>
+ <path d="M30 30h20"/>
+ <path d="M25 50h45l2 2H22z"/>
+ </symbol>
+ <marker id="arrowhead_start" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto">
+ <path d="M6 0L0 3l6 3" stroke="black" fill="none"/>
+ </marker>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="15" y="40" class="text_big">
+ Client
+ </text>
+ <text x="140" y="40" class="text_big">
+ Server
+ </text>
+ <use xlink:href="#laptop" x="5" y="210"/>
+ <g transform="translate(130 70)">
+ <use xlink:href="#state_350x120"/>
+ <text x="5" y="20" class="text_normal">
+ maintenance_work_mem (per connection)
+ </text>
+ <text x="5" y="45" class="text_normal">
+ work_mem (per query operation)
+ </text>
+ <text x="5" y="70" class="text_normal">
+ autovacuum_work_mem (per worker process)
+ </text>
+ <text x="5" y="95" class="text_normal">
+ temp_buffer (per connection)
+ </text>
+ <text x="5" y="110" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_200x20" x="140" y="-15"/>
+ <text x="150" class="text_comment">
+ Individual Memory
+ </text>
+ </g>
+ <g transform="translate(520 70)">
+ <use xlink:href="#state_300x120"/>
+ <text x="10" y="30" class="text_normal">
+ shared_buffers (heap and index)
+ </text>
+ <text x="10" y="70" class="text_normal">
+ wal_buffers (WAL records)
+ </text>
+ <text x="10" y="100" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_250x20" x="40" y="-15"/>
+ <text x="50" class="text_comment">
+ Shared Memory (per Instance)
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M180 215h250v30H180z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(180 215)">
+ Postmaster
+ </text>
+ <path d="M90 230h75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 230)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 1
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M150 315h370v30H150z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(150 315)">
+ Backend processes (one per connection)
+ </text>
+ <path d="M155 315v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M160 310v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M90 240l63 63" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 290)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 3
+ </text>
+ </g>
+ <path d="M360 250v50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180 255)">
+ <use xlink:href="#note_250x20"/>
+ <text x="10" y="15" class="text_comment">
+ Creates backend processes
+ </text>
+ </g>
+ <g transform="translate(360 281)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 2
+ </text>
+ </g>
+ <path d="M460 300V200" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M498 300V95h30" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M508 300V135h20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M550 220h120v30H550z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(550 220)">
+ WAL Writer
+ </text>
+ <path d="M590 150v65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M590 255v230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 340h140v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 340)">
+ Checkpointer
+ </text>
+ <path d="M740 110v220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 355H475v130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M700 330V150" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50"/>
+ <text x="60" y="-35" class="text_comment">
+ Checkpoint
+ </text>
+ <text x="60" y="-20" class="text_comment">
+ Record
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M610 380h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 380)">
+ Background Writer
+ </text>
+ <path d="M770 110v260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 395H485v90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 420h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 420)">
+ WAL Archiver
+ </text>
+ <path d="M620 485l30-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M690 455l30 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M135 380h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 380)">
+ Autovacuum
+ </text>
+ <path d="M140 380v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path d="M145 375v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path stroke="blue" fill="none" d="M135 430h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 430)">
+ Logger
+ </text>
+ <path stroke="blue" fill="none" d="M290 370h140v30H290z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(290 370)">
+ Stats Collector
+ </text>
+ <g transform="translate(145 490)">
+ <use xlink:href="#disc"/>
+ <text x="35" y="45" class="text_normal">
+ Log
+ </text>
+ <text x="20" y="60" class="text_small">
+ text lines,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <path d="M195 465v20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(410 490)">
+ <use xlink:href="#disc"/>
+ <text x="10" y="40" class="text_normal">
+ Heap and
+ </text>
+ <text x="25" y="55" class="text_normal">
+ Index
+ </text>
+ <text x="15" y="70" class="text_small">
+ binary blocks,
+ </text>
+ <text x="30" y="80" class="text_small">
+ random
+ </text>
+ </g>
+ <path d="M450 485V350" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(295 420)">
+ <use xlink:href="#note_170x50"/>
+ <text x="5" y="15" class="text_comment">
+ Read heap and index
+ </text>
+ <text x="5" y="30" class="text_comment">
+ pages and transfer
+ </text>
+ <text x="5" y="45" class="text_comment">
+ them to shared_buffers
+ </text>
+ </g>
+ <g transform="translate(550 490)">
+ <use xlink:href="#disc"/>
+ <text x="30" y="45" class="text_normal">
+ WAL
+ </text>
+ <text x="10" y="60" class="text_small">
+ binary records,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <g transform="translate(690 490)">
+ <use xlink:href="#disc"/>
+ <text x="16" y="45" class="text_normal">
+ Archived
+ </text>
+ <text x="36" y="60" class="text_normal">
+ WAL
+ </text>
+ </g>
+ <path d="M110 20v550" stroke="black" fill="none"/>
+ <g transform="rotate(90 -33.5 156.5)">
+ <use xlink:href="#note_200x20"/>
+ <text class="text_comment" x="10" y="15">
+ Via TCP/IP or socket
+ </text>
+ </g>
+ <text class="text_big" x="95" transform="rotate(90 425 425)">
+ RAM
+ </text>
+ <text class="text_big" x="250" transform="rotate(90 425 425)">
+ PROCESSES
+ </text>
+ <text class="text_big" x="500" transform="rotate(90 425 425)">
+ FILES
+ </text>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink.svg b/doc/src/sgml/images/ram-proc-file-ink.svg
new file mode 100644
index 0000000000..9ef89639c4
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink.svg
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="600px"
+ viewBox="0 0 900 600"
+ id="svg4706"
+ sodipodi:docname="ram-proc-file-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata4710">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>PG Overall Server Architecture</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1282"
+ inkscape:window-height="733"
+ id="namedview4708"
+ showgrid="false"
+ inkscape:zoom="0.39333333"
+ inkscape:cx="450"
+ inkscape:cy="292.37288"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg4706" />
+ <title
+ id="title4402">PG Overall Server Architecture</title>
+ <style
+ type="text/css"
+ id="style4404">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs4470">
+ <!-- Some notes in different sizes -->
+ <symbol
+ id="note_200x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4406">UML Note (200 x 20 px)</title>
+ <path
+ d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10"
+ id="path4408" />
+ </symbol>
+ <symbol
+ id="note_250x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4411">UML Note (250 x 20 px)</title>
+ <path
+ d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10"
+ id="path4413" />
+ </symbol>
+ <symbol
+ id="note_100x35"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4416">UML Note (100 x 35 px)</title>
+ <path
+ d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10"
+ id="path4418" />
+ </symbol>
+ <symbol
+ id="note_170x50"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4421">UML Note (170 x 50 px)</title>
+ <path
+ d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10"
+ id="path4423" />
+ </symbol>
+ <!-- UML states (used for buffers) -->
+ <symbol
+ id="state_300x120">
+ <title
+ id="title4426">UML State (300x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="300"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect4428" />
+ </symbol>
+ <symbol
+ id="state_350x120">
+ <title
+ id="title4431">UML State (350x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="350"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect4433" />
+ </symbol>
+ <!-- Discs -->
+ <symbol
+ id="disc"
+ stroke="blue"
+ fill="none">
+ <title
+ id="title4436">Disc</title>
+ <ellipse
+ cx="51"
+ cy="13"
+ rx="50"
+ ry="12"
+ id="ellipse4438" />
+ <!-- top -->
+ <path
+ d="M 1,13 v 60"
+ id="path4440" />
+ <!-- left -->
+ <path
+ d="M 101,13 v 60"
+ id="path4442" />
+ <!-- right -->
+ <path
+ d="M 1,73 A 50, 12, 0, 0, 0, 101,73"
+ id="path4444" />
+ <!-- bottom -->
+ </symbol>
+ <!-- Laptop -->
+ <symbol
+ id="laptop"
+ stroke="black"
+ fill="none">
+ <title
+ id="title4447">Laptop</title>
+ <path
+ d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54"
+ id="path4449" />
+ <rect
+ x="23"
+ y="3"
+ width="48"
+ height="34"
+ id="rect4451" />
+ <!-- symbolize some lines -->
+ <path
+ d="M 30,10 h 20"
+ id="path4453" />
+ <path
+ d="M 30,15 h 25"
+ id="path4455" />
+ <path
+ d="M 30,20 h 10"
+ id="path4457" />
+ <path
+ d="M 30,30 h 20"
+ id="path4459" />
+ <!-- symbolize keyboard -->
+ <path
+ d="M 25,50 h 45 l 2,2 h -50 z "
+ id="path4461" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path4464" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path4467" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect4472" />
+ <!-- caption, client side -->
+ <text
+ x="15"
+ y="40"
+ class="text_big"
+ id="text4474">Client</text>
+ <text
+ x="140"
+ y="40"
+ class="text_big"
+ id="text4476">Server</text>
+ <use
+ xlink:href="#laptop"
+ x="5"
+ y="210"
+ id="use4478" />
+ <!-- individual memory -->
+ <g
+ transform="translate(130, 70)"
+ id="g4496">
+ <use
+ xlink:href="#state_350x120"
+ x="0"
+ y="0"
+ id="use4480" />
+ <text
+ x="5"
+ y="20"
+ class="text_normal"
+ id="text4482">maintenance_work_mem (per connection)</text>
+ <text
+ x="5"
+ y="45"
+ class="text_normal"
+ id="text4484">work_mem (per query operation)</text>
+ <text
+ x="5"
+ y="70"
+ class="text_normal"
+ id="text4486">autovacuum_work_mem (per worker process)</text>
+ <text
+ x="5"
+ y="95"
+ class="text_normal"
+ id="text4488">temp_buffer (per connection)</text>
+ <text
+ x="5"
+ y="110"
+ class="text_normal"
+ id="text4490">...</text>
+ <use
+ xlink:href="#note_200x20"
+ x="140"
+ y="-15"
+ id="use4492" />
+ <text
+ x="150"
+ y="0"
+ class="text_comment"
+ id="text4494">Individual Memory</text>
+ </g>
+ <!-- shared memory -->
+ <g
+ transform="translate(520, 70)"
+ id="g4510">
+ <use
+ xlink:href="#state_300x120"
+ x="0"
+ y="0"
+ id="use4498" />
+ <text
+ x="10"
+ y="30"
+ class="text_normal"
+ id="text4500">shared_buffers (heap and index)</text>
+ <text
+ x="10"
+ y="70"
+ class="text_normal"
+ id="text4502">wal_buffers (WAL records)</text>
+ <text
+ x="10"
+ y="100"
+ class="text_normal"
+ id="text4504">...</text>
+ <use
+ xlink:href="#note_250x20"
+ x="40"
+ y="-15"
+ id="use4506" />
+ <text
+ x="50"
+ y="0"
+ class="text_comment"
+ id="text4508">Shared Memory (per Instance)</text>
+ </g>
+ <!-- postmaster -->
+ <g
+ transform="translate(180, 215)"
+ id="g4516">
+ <rect
+ width="250"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4512" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4514">Postmaster</text>
+ </g>
+ <path
+ d="M 90,230 h 75"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4518" />
+ <g
+ transform="translate(140, 230)"
+ id="g4524">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle4520" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text4522">1</text>
+ </g>
+ <!-- backend processes -->
+ <g
+ transform="translate(150, 315)"
+ id="g4534">
+ <rect
+ width="370"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4526" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4528">Backend processes (one per connection)</text>
+ <path
+ d="M 5,0 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4530" />
+ <path
+ d="M 10,-5 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4532" />
+ </g>
+ <path
+ d="M 90,240 153,303"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path4536" />
+ <g
+ transform="translate(140, 290)"
+ id="g4542">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle4538" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text4540">3</text>
+ </g>
+ <!-- connection between postmaster and backend processes -->
+ <path
+ d="M 360,250 v 50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4544" />
+ <g
+ transform="translate(180, 255)"
+ id="g4550">
+ <use
+ xlink:href="#note_250x20"
+ id="use4546" />
+ <text
+ x="10"
+ y="15"
+ class="text_comment"
+ id="text4548">Creates backend processes</text>
+ </g>
+ <g
+ transform="translate(360, 281)"
+ id="g4556">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle4552" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text4554">2</text>
+ </g>
+ <!-- backend process' access to individual memory -->
+ <path
+ d="M 460,300 v -100"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path4558" />
+ <!-- its access to shared buffers and WAL buffers -->
+ <path
+ d="M 498,300 v -205 h 30"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path4560" />
+ <path
+ d="M 508,300 v -165 h 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4562" />
+ <!-- WAL writer -->
+ <g
+ transform="translate(550, 220)"
+ id="g4568">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4564" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4566">WAL Writer</text>
+ </g>
+ <path
+ d="M 590,150 v 65"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4570" />
+ <path
+ d="M 590,255 v 230"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4572" />
+ <!-- Checkpoiner -->
+ <g
+ transform="translate(610, 340)"
+ id="g4578">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4574" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4576">Checkpointer</text>
+ </g>
+ <path
+ d="M 740,110 v 220"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4580" />
+ <path
+ d="M 605,355 h -130 v 130"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4582" />
+ <path
+ d="M 700,330 v -180"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4584" />
+ <g
+ transform="translate(570, 330)"
+ id="g4592">
+ <use
+ xlink:href="#note_100x35"
+ x="50"
+ y="-50"
+ id="use4586" />
+ <text
+ x="60"
+ y="-35"
+ class="text_comment"
+ id="text4588">Checkpoint</text>
+ <text
+ x="60"
+ y="-20"
+ class="text_comment"
+ id="text4590">Record</text>
+ </g>
+ <!-- BG writer -->
+ <g
+ transform="translate(610, 380)"
+ id="g4598">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4594" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4596">Background Writer</text>
+ </g>
+ <path
+ d="M 770,110 v 260"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4600" />
+ <path
+ d="M 605,395 h -120 v 90"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4602" />
+ <!-- Archiver -->
+ <g
+ transform="translate(610, 420)"
+ id="g4608">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4604" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4606">WAL Archiver</text>
+ </g>
+ <path
+ d="M 620,485 l 30,-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4610" />
+ <path
+ d="M 690,455 l 30, 30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4612" />
+ <!-- Vacuum -->
+ <g
+ transform="translate(135, 380)"
+ id="g4622">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4614" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4616">Autovacuum</text>
+ <path
+ d="M 5,0 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4618" />
+ <path
+ d="M 10,-5 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4620" />
+ </g>
+ <!-- Log Writer -->
+ <g
+ transform="translate(135, 430)"
+ id="g4628">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4624" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4626">Logger</text>
+ </g>
+ <!-- Stats Collector -->
+ <g
+ transform="translate(290, 370)"
+ id="g4634">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4630" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4632">Stats Collector</text>
+ </g>
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g
+ transform="translate(145, 490)"
+ id="g4644">
+ <use
+ xlink:href="#disc"
+ id="use4636" />
+ <text
+ x="35"
+ y="45"
+ class="text_normal"
+ id="text4638">Log</text>
+ <text
+ x="20"
+ y="60"
+ class="text_small"
+ id="text4640">text lines,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text4642">sequential</text>
+ </g>
+ <path
+ d="M 195,465 v 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4646" />
+ <g
+ transform="translate(410, 490)"
+ id="g4658">
+ <use
+ xlink:href="#disc"
+ id="use4648" />
+ <text
+ x="10"
+ y="40"
+ class="text_normal"
+ id="text4650">Heap and</text>
+ <text
+ x="25"
+ y="55"
+ class="text_normal"
+ id="text4652">Index</text>
+ <text
+ x="15"
+ y="70"
+ class="text_small"
+ id="text4654">binary blocks,</text>
+ <text
+ x="30"
+ y="80"
+ class="text_small"
+ id="text4656">random</text>
+ </g>
+ <path
+ d="M 450,485 v -135"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4660" />
+ <g
+ transform="translate(295, 420)"
+ id="g4670">
+ <use
+ xlink:href="#note_170x50"
+ id="use4662" />
+ <text
+ x="5"
+ y="15"
+ class="text_comment"
+ id="text4664">Read heap and index</text>
+ <text
+ x="5"
+ y="30"
+ class="text_comment"
+ id="text4666">pages and transfer</text>
+ <text
+ x="5"
+ y="45"
+ class="text_comment"
+ id="text4668">them to shared_buffers</text>
+ </g>
+ <g
+ transform="translate(550, 490)"
+ id="g4680">
+ <use
+ xlink:href="#disc"
+ id="use4672" />
+ <text
+ x="30"
+ y="45"
+ class="text_normal"
+ id="text4674">WAL</text>
+ <text
+ x="10"
+ y="60"
+ class="text_small"
+ id="text4676">binary records,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text4678">sequential</text>
+ </g>
+ <g
+ transform="translate(690, 490)"
+ id="g4688">
+ <use
+ xlink:href="#disc"
+ id="use4682" />
+ <text
+ x="16"
+ y="45"
+ class="text_normal"
+ id="text4684">Archived</text>
+ <text
+ x="36"
+ y="60"
+ class="text_normal"
+ id="text4686">WAL</text>
+ </g>
+ <!-- boarder between client and server side -->
+ <path
+ d="M 110,20 v 550"
+ stroke="black"
+ fill="none"
+ id="path4690" />
+ <g
+ transform="translate(123, 190) rotate(90)"
+ id="g4696">
+ <use
+ xlink:href="#note_200x20"
+ id="use4692" />
+ <text
+ class="text_comment"
+ x="10"
+ y="15"
+ id="text4694">Via TCP/IP or socket</text>
+ </g>
+ <!-- right side -->
+ <g
+ transform="translate(850, 0) rotate(90)"
+ id="g4704">
+ <text
+ class="text_big"
+ x="95"
+ id="text4698">RAM</text>
+ <text
+ class="text_big"
+ x="250"
+ id="text4700">PROCESSES</text>
+ <text
+ class="text_big"
+ x="500"
+ id="text4702">FILES</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-raw.svg b/doc/src/sgml/images/ram-proc-file-raw.svg
new file mode 100644
index 0000000000..775ba91571
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-raw.svg
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="600px"
+ viewBox="0 0 900 600">
+
+ <title>PG Overall Server Architecture</title>
+
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Some notes in different sizes -->
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>UML Note (200 x 20 px)</title>
+ <path d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>UML Note (250 x 20 px)</title>
+ <path d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>UML Note (100 x 35 px)</title>
+ <path d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>UML Note (170 x 50 px)</title>
+ <path d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- UML states (used for buffers) -->
+ <symbol id="state_300x120">
+ <title>UML State (300x120)</title>
+ <rect x="0" y="0" width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>UML State (350x120)</title>
+ <rect x="0" y="0" width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- Discs -->
+ <symbol id="disc" stroke="blue" fill="none" >
+ <title>Disc</title>
+ <ellipse cx="51" cy="13" rx="50" ry="12" /> <!-- top -->
+ <path d="M 1,13 v 60" /> <!-- left -->
+ <path d="M 101,13 v 60" /> <!-- right -->
+ <path d="M 1,73 A 50, 12, 0, 0, 0, 101,73" /> <!-- bottom -->
+ </symbol>
+
+ <!-- Laptop -->
+ <symbol id="laptop" stroke="black" fill="none" >
+ <title>Laptop</title>
+ <path d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54" />
+ <rect x="23" y="3" width="48" height="34" />
+ <!-- symbolize some lines -->
+ <path d="M 30,10 h 20" />
+ <path d="M 30,15 h 25" />
+ <path d="M 30,20 h 10" />
+ <path d="M 30,30 h 20" />
+ <!-- symbolize keyboard -->
+ <path d="M 25,50 h 45 l 2,2 h -50 z " />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption, client side -->
+ <text x="15" y="40" class="text_big">Client</text>
+ <text x="140" y="40" class="text_big">Server</text>
+ <use xlink:href="#laptop" x="5" y="210" />
+
+
+ <!-- individual memory -->
+ <g transform="translate(130, 70)">
+ <use xlink:href="#state_350x120" x="0" y="0" />
+ <text x="5" y="20" class="text_normal">maintenance_work_mem (per connection)</text>
+ <text x="5" y="45" class="text_normal">work_mem (per query operation)</text>
+ <text x="5" y="70" class="text_normal">autovacuum_work_mem (per worker process)</text>
+ <text x="5" y="95" class="text_normal">temp_buffer (per connection)</text>
+ <text x="5" y="110" class="text_normal">...</text>
+ <use xlink:href="#note_200x20" x="140" y="-15" />
+ <text x="150" y="0" class="text_comment">Individual Memory</text>
+ </g>
+
+ <!-- shared memory -->
+ <g transform="translate(520, 70)">
+ <use xlink:href="#state_300x120" x="0" y="0" />
+ <text x="10" y="30" class="text_normal">shared_buffers (heap and index)</text>
+ <text x="10" y="70" class="text_normal">wal_buffers (WAL records)</text>
+ <text x="10" y="100" class="text_normal">...</text>
+ <use xlink:href="#note_250x20" x="40" y="-15" />
+ <text x="50" y="0" class="text_comment">Shared Memory (per Instance)</text>
+ </g>
+
+ <!-- postmaster -->
+ <g transform="translate(180, 215)">
+ <rect width="250" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Postmaster</text>
+ </g>
+ <path d="M 90,230 h 75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 230)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">1</text>
+ </g>
+
+ <!-- backend processes -->
+ <g transform="translate(150, 315)">
+ <rect width="370" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Backend processes (one per connection)</text>
+ <path d="M 5,0 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <path d="M 90,240 153,303" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 290)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">3</text>
+ </g>
+
+ <!-- connection between postmaster and backend processes -->
+ <path d="M 360,250 v 50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180, 255)">
+ <use xlink:href="#note_250x20" />
+ <text x="10" y="15" class="text_comment">Creates backend processes</text>
+ </g>
+ <g transform="translate(360, 281)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">2</text>
+ </g>
+
+ <!-- backend process' access to individual memory -->
+ <path d="M 460,300 v -100" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <!-- its access to shared buffers and WAL buffers -->
+ <path d="M 498,300 v -205 h 30" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M 508,300 v -165 h 20" stroke="black" fill="none"
+ marker-end="url(#arrowhead_end)"/>
+
+ <!-- WAL writer -->
+ <g transform="translate(550, 220)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Writer</text>
+ </g>
+ <path d="M 590,150 v 65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 590,255 v 230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Checkpoiner -->
+ <g transform="translate(610, 340)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Checkpointer</text>
+ </g>
+ <path d="M 740,110 v 220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,355 h -130 v 130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 700,330 v -180" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570, 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50" />
+ <text x="60" y="-35" class="text_comment">Checkpoint</text>
+ <text x="60" y="-20" class="text_comment">Record</text>
+ </g>
+
+ <!-- BG writer -->
+ <g transform="translate(610, 380)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Background Writer</text>
+ </g>
+ <path d="M 770,110 v 260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,395 h -120 v 90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Archiver -->
+ <g transform="translate(610, 420)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Archiver</text>
+ </g>
+ <path d="M 620,485 l 30,-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 690,455 l 30, 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Vacuum -->
+ <g transform="translate(135, 380)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Autovacuum</text>
+ <path d="M 5,0 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <!-- Log Writer -->
+ <g transform="translate(135, 430)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Logger</text>
+ </g>
+
+ <!-- Stats Collector -->
+ <g transform="translate(290, 370)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Stats Collector</text>
+ </g>
+
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g transform="translate(145, 490)">
+ <use xlink:href="#disc" />
+ <text x="35" y="45" class="text_normal">Log</text>
+ <text x="20" y="60" class="text_small">text lines,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+ <path d="M 195,465 v 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(410, 490)">
+ <use xlink:href="#disc" />
+ <text x="10" y="40" class="text_normal">Heap and</text>
+ <text x="25" y="55" class="text_normal">Index</text>
+ <text x="15" y="70" class="text_small">binary blocks,</text>
+ <text x="30" y="80" class="text_small">random</text>
+ </g>
+ <path d="M 450,485 v -135" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(295, 420)">
+ <use xlink:href="#note_170x50" />
+ <text x="5" y="15" class="text_comment">Read heap and index</text>
+ <text x="5" y="30" class="text_comment">pages and transfer</text>
+ <text x="5" y="45" class="text_comment">them to shared_buffers</text>
+ </g>
+
+ <g transform="translate(550, 490)">
+ <use xlink:href="#disc" />
+ <text x="30" y="45" class="text_normal">WAL</text>
+ <text x="10" y="60" class="text_small">binary records,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+
+ <g transform="translate(690, 490)">
+ <use xlink:href="#disc" />
+ <text x="16" y="45" class="text_normal">Archived</text>
+ <text x="36" y="60" class="text_normal">WAL</text>
+ </g>
+
+ <!-- boarder between client and server side -->
+ <path d="M 110,20 v 550" stroke="black" fill="none" />
+ <g transform="translate(123, 190) rotate(90)">
+ <use xlink:href="#note_200x20" />
+ <text class="text_comment" x="10" y ="15">Via TCP/IP or socket</text>
+ </g>
+
+ <!-- right side -->
+ <g transform="translate(850, 0) rotate(90)">
+ <text class="text_big" x="95">RAM</text>
+ <text class="text_big" x="250">PROCESSES</text>
+ <text class="text_big" x="500">FILES</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink-svgo.svg b/doc/src/sgml/images/wraparound-ink-svgo.svg
new file mode 100644
index 0000000000..d5af6ce0b8
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink-svgo.svg
@@ -0,0 +1,40 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="280" viewBox="0 0 850 280">
+ <title>
+ Cyclic usage of XIDs
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="370" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ Cyclic usage of XIDs modulo 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan>
+ </text>
+ <g fill="none" transform="translate(170 150)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_095" startOffset="30.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="30%">(1)</textPath> <textPath xlink:href="#Path_095" startOffset="45.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(2)</textPath> <textPath xlink:href="#Path_095" startOffset="50.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="50%">(3)</textPath> <textPath xlink:href="#Path_095" startOffset="62.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="62%">(4)</textPath>
+ </text>
+ </g>
+ <g class="text_normal">
+ <text transform="translate(400 130)">
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25" transform="translate(400 130)">
+ 1: oldest <tspan font-weight="700">active</tspan> xid (pg_stat_activity.backend_xmin)
+ </text>
+ <text y="50" transform="translate(400 130)">
+ 2: xmin of one row version
+ </text>
+ <text y="75" transform="translate(400 130)">
+ 3: xmax of the same row version
+ </text>
+ <text y="100" transform="translate(400 130)">
+ 4: youngest xid (txid_current)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink.svg b/doc/src/sgml/images/wraparound-ink.svg
new file mode 100644
index 0000000000..51d35a9f85
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="280px"
+ viewBox="0 0 850 280"
+ id="svg216"
+ sodipodi:docname="wraparound-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata220">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Cyclic usage of XIDs</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1247"
+ inkscape:window-height="650"
+ id="namedview218"
+ showgrid="false"
+ inkscape:zoom="0.44470588"
+ inkscape:cx="425"
+ inkscape:cy="133.25397"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg216" />
+ <title
+ id="title153">Cyclic usage of XIDs</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style155">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs160">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect162" />
+ <text
+ class="text_big"
+ x="370"
+ y="40"
+ id="text168">Cyclic usage of XIDs modulo 2
+ <tspan
+ dy="-5"
+ id="tspan164">^</tspan>
+<tspan
+ dy="5"
+ id="tspan166">32</tspan>
+</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 150)"
+ id="g196">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle170" />
+ <text
+ class="text_normal"
+ id="text194">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath172">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath174">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath176">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="30.5%"
+ id="textPath178">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="30%"
+ id="textPath180">(1)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="45.5%"
+ id="textPath182">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath184">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="50.5%"
+ id="textPath186">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="50%"
+ id="textPath188">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="62.5%"
+ id="textPath190">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="62%"
+ id="textPath192">(4)</textPath>
+ </text>
+ </g>
+ <g
+ class="text_normal"
+ transform="translate(400 130)"
+ id="g214">
+ <text
+ id="text202">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan198">^</tspan>
+<tspan
+ dy="5"
+ id="tspan200">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text206">1: oldest <tspan
+ style="font-weight:bold"
+ id="tspan204">active</tspan>
+ xid (pg_stat_activity.backend_xmin)</text>
+ <text
+ y="50"
+ id="text208">2: xmin of one row version</text>
+ <text
+ y="75"
+ id="text210">3: xmax of the same row version</text>
+ <text
+ y="100"
+ id="text212">4: youngest xid (txid_current)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-raw.svg b/doc/src/sgml/images/wraparound-raw.svg
new file mode 100644
index 0000000000..637e68bb82
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-raw.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="280px"
+ viewBox="0 0 850 280" >
+
+ <title>Cyclic usage of XIDs</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="370" y="40">Cyclic usage of XIDs modulo 2
+ <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan></text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 150)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_095" startOffset="30.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="30%" >(1)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="45.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(2)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="50.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="50%" >(3)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="62.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="62%" >(4)</textPath>
+ </text>
+ </g>
+
+ <g class="text_normal" transform="translate(400 130)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: oldest <tspan style="font-weight:bold">active</tspan> xid (pg_stat_activity.backend_xmin)</text>
+ <text y="50">2: xmin of one row version</text>
+ <text y="75">3: xmax of the same row version</text>
+ <text y="100">4: youngest xid (txid_current)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 730d5fdc34..e9e9f9495f 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -248,6 +248,7 @@ break is not needed in a wider output rendering.
</para>
</partintro>
+ &architecture;
&arch-dev;
&catalogs;
&protocol;
diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml
index 9bb5c1a6d5..abb61445f2 100644
--- a/doc/src/sgml/start.sgml
+++ b/doc/src/sgml/start.sgml
@@ -53,7 +53,7 @@
<sect1 id="tutorial-arch">
- <title>Architectural Fundamentals</title>
+ <title>Client/Server Model</title>
<para>
Before we proceed, you should understand the basic
@@ -68,34 +68,52 @@
client/server model. A <productname>PostgreSQL</productname>
session consists of the following cooperating processes
(programs):
+ </para>
- <itemizedlist>
- <listitem>
- <para>
- A server process, which manages the database files, accepts
- connections to the database from client applications, and
- performs database actions on behalf of the clients. The
- database server program is called
- <filename>postgres</filename>.
- <indexterm><primary>postgres</primary></indexterm>
- </para>
- </listitem>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A process at the server site with the name
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ <indexterm><primary>postgres</primary></indexterm>
+ <indexterm><primary>postmaster</primary></indexterm>
+ It accepts connection requests from client applications, starts
+ (<quote>forks</quote>) a new <glossterm linkend="glossary-backend">
+ Backend</glossterm> process for each of them, and passes
+ the connection to it. From that point on, the client and the new
+ Backend process communicate directly without intervention by the original
+ Postmaster process. Thus, the Postmaster process is always running,
+ waiting for new client connections, whereas clients and associated
+ Backend processes come and go. (All of this is of course invisible
+ to the user. We only mention it here for completeness.)
+ </para>
+ </listitem>
- <listitem>
- <para>
- The user's client (frontend) application that wants to perform
- database operations. Client applications can be very diverse
- in nature: a client could be a text-oriented tool, a graphical
- application, a web server that accesses the database to
- display web pages, or a specialized database maintenance tool.
- Some client applications are supplied with the
- <productname>PostgreSQL</productname> distribution; most are
- developed by users.
- </para>
- </listitem>
+ <listitem>
+ <para>
+ A group of processes at the server site, the <glossterm
+ linkend="glossary-instance">Instance</glossterm>, to which also
+ the Postmaster process belongs. Their duties are handling of
+ central, common database activities like file access, transaction
+ handling, vacuum, checkpoints, replication, and more. The mentioned
+ Backend processes delegate those actions to the instance.
+ </para>
+ </listitem>
- </itemizedlist>
- </para>
+ <listitem>
+ <para>
+ The user's client (frontend) application that wants to perform
+ database operations. Client applications can be very diverse
+ in nature: a client could be a text-oriented tool, a graphical
+ application, a web server that accesses the database to
+ display web pages, or a specialized database maintenance tool.
+ Some client applications are supplied with the
+ <productname>PostgreSQL</productname> distribution; most are
+ developed by users.
+ </para>
+ </listitem>
+
+ </itemizedlist>
<para>
As is typical of client/server applications, the client and the
@@ -106,18 +124,6 @@
file name) on the database server machine.
</para>
- <para>
- The <productname>PostgreSQL</productname> server can handle
- multiple concurrent connections from clients. To achieve this it
- starts (<quote>forks</quote>) a new process for each connection.
- From that point on, the client and the new server process
- communicate without intervention by the original
- <filename>postgres</filename> process. Thus, the
- supervisor server process is always running, waiting for
- client connections, whereas client and associated server processes
- come and go. (All of this is of course invisible to the user. We
- only mention it here for completeness.)
- </para>
</sect1>
On Sun, Nov 8, 2020 at 8:56 AM Jürgen Purtz <juergen@purtz.de> wrote:
Good catches. Everything applied.
Reviewed the first three sections.
template0 - I would remove the schema portions of this and simply note this
as being a pristine recovery database in the diagram.
I would drop the word "more" and just say "system schemas". I would drop
pg_toast from the list of system schema and focus on the three user-facing
ones.
Instead of "my_schema" (optional) I would do "my_schema" (example)
Server Graphic
#3 Global SQL Objects: Objects which are shared among all databases within
a cluster.
#6 Client applications are prohibited from connecting to template0
#1 If by you we mean "the client" saying that you work "in the cluster
data" doesn't really help. I would emphasize the point that the client
sees an endpoint the Postmaster publishes as a port or socket file and that
plus the database name defines the endpoint the client connects to (meld
with #5)
In lieu of some of the existing detail provided about structure I would add
information about configuration and search_path at this level.
I like the object type enumeration - I would suggest grouping them by type
in a manner consistent with the documentation and making each one a link to
its "primary" section - the SQL Command reference if all else fails.
The "i" in internal in 51.3 (the image) needs capitalization).
You correctly add both Extension and Collation as database-level objects
but they are not mentioned anywhere else. They do belong here and need to
be tied in properly in the text.
The whole thing needs a good pass focused on capitalization. Both for
typos and to decide when various primary concepts like Instance should be
capitalized and when not.
51.4 - When you look at the diagram seeing /pg/data/base looks really cool,
but when reading the prose where both the "pg" and the "base" are omitted
and all you get are repeated references to "data", the directory name
choice becomes an issue IMO. I suggest (and changed the attached) to name
the actual root directory "pgdata". You should change the /pg/ directory
name to something like ".../tutorial_project/".
Since you aren't following alphabetical order anyway I would place
pg_tblspc after globals since tablespaces are globals and thus proximity
links them here - and pointing out that pg_tblspc holds the data makes
stating that global doesn't contain tablespace data unnecessary.
Maybe point out somewhere the the "base/databaseOID" directory represents
the default tablespace for each database, which isn't "global", only the
non-default tablespaces are considered globals (or just get rid of the
mentioned on "non-default tablespace" for now).
David J.
Attachments:
0012-architecture-dgj-suggestions.patchapplication/octet-stream; name=0012-architecture-dgj-suggestions.patchDownload
commit d9e4657a17b5f2a32b37534f355737433770a88a
Author: David G. Johnston <david.g.johnston@gmail.com>
Date: Mon Nov 9 23:07:29 2020 +0000
v0012-architecture-suggestions
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
index b7589f9a4f..bd22ada939 100644
--- a/doc/src/sgml/architecture.sgml
+++ b/doc/src/sgml/architecture.sgml
@@ -28,10 +28,11 @@
</para>
<para>
- The first step when an Instance starts is the start of the
+ All aspects of an Instance are launched and managed using a single primary
+ process termed the
<glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
- It loads the configuration files, allocates Shared Memory, and
- starts the other processes of the Instance:
+ It loads configuration files, allocates Shared Memory, and
+ starts the other collaborating processes of the Instance:
<glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
<glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
<glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
@@ -39,9 +40,10 @@
<glossterm linkend="glossary-autovacuum">Autovacuum</glossterm>,
<glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
<glossterm linkend="glossary-logger">Logger</glossterm>, and more.
- Later, the Postmaster starts
+ Later, the Postmaster listens on its configured system port(s) and in response
+ to client connection attempts launches
<glossterm linkend="glossary-backend">Backend</glossterm> processes
- which communicate with clients and handle their requests.
+ to which it delegates authentication, communication, and the handling of their requests.
<xref linkend="tutorial-ram-proc-file-figure"/> visualizes the processes
of an Instance and the main aspects of their collaboration.
</para>
@@ -62,14 +64,6 @@
</mediaobject>
</figure>
- <para>
- When a client application tries to connect to a
- <glossterm linkend="glossary-database">database</glossterm>,
- this request is handled initially by the Postmaster. It
- starts a new Backend process, which handles all further
- client's requests.
- </para>
-
<para>
Client requests like <command>SELECT</command> or
<command>UPDATE</command> usually lead to the
@@ -84,9 +78,9 @@
<para>
Shared Memory is limited in size and it can become necessary
to evict pages. As long as the content of such pages hasn't
- changed, this is not a problem. But in Shared Memory also
- write actions take place. Modified pages are called dirty
- pages or dirty buffers and before they can be evicted they
+ changed, this is not a problem. But writes directly modify
+ the pages in Shared Memory. Modified pages are called dirty
+ pages (or dirty buffers) and before they can be evicted they
must be written to disk. This happens regularly by the
Checkpointer and the Background Writer processes to ensure
that the disk version of the pages are up-to-date.
@@ -98,7 +92,7 @@
<glossterm linkend="glossary-wal-record">WAL record</glossterm>
is created from the delta-information (difference between the
old and the new content) and stored in another area of
- Shared Memory. The parallel running WAL Writer process
+ Shared Memory. The concurrently running WAL Writer process
reads them and appends them to the end of the current
<glossterm linkend="glossary-wal-record">WAL file</glossterm>.
Such sequential writes are faster than writes to random
@@ -108,8 +102,8 @@
</para>
<para>
- Second, the transfer of dirty buffers from Shared Memory to
- files must take place. This is the primary task of the
+ Second, the instance transfers dirty buffers from Shared Memory to
+ files. This is the primary task of the
Background Writer process. Because I/O activities can block
other processes, it starts periodically and
acts only for a short period. Doing so, its extensive (and
@@ -123,14 +117,8 @@
<glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
A Checkpoint is a point in time when all older dirty buffers,
all older WAL records, and finally a special Checkpoint record
- are written and flushed to disk. Heap and index files,
- and WAL files are now in sync.
- Older WAL is no longer required. In other words,
- a possibly occurring recovery, which integrates the delta
- information of WAL into heap and index files, will happen
- by replaying only WAL past the last-recorded checkpoint.
- This limits the amount of WAL to be replayed
- during recovery in the event of a crash.
+ are written and flushed to disk.
+ Older WAL files are no longer required to recover the system from a crash.
</para>
<para>
@@ -141,8 +129,10 @@
less common). Options and details are covered
in the backup and restore section (<xref linkend="backup"/>).
For our purposes here, just note that the WAL Archiver process
- can be enabled and configured to run a script on filled WAL
- files — usually to copy them to a remote location.
+ can be enabled and configured to run a script on completed WAL
+ files — usually to copy them to a remote location. Note
+ that when a Checkpoint record is written to the WAL the current
+ file is immediately completed.
</para>
<para>
@@ -166,20 +156,29 @@
A <glossterm linkend="glossary-server">server</glossterm> contains one or more
<glossterm linkend="glossary-db-cluster">database clusters</glossterm>
(<glossterm linkend="glossary-db-cluster">clusters</glossterm>
- for short). Each cluster contains three or more
- <glossterm linkend="glossary-database">databases</glossterm>.
- Each database can contain many
- <glossterm linkend="glossary-schema">schemas</glossterm>.
- A schema can contain
+ for short). By default each newly initialized cluster contains three
+ <glossterm linkend="glossary-database">databases</glossterm>
+ (one interactive and two templates, see <xref linkend="app-initdb"/>).
+ Each database can contain many user-writable
+ <glossterm linkend="glossary-schema">schemas</glossterm>
+ (public, by name and permissiveness, by default) and three system generated
+ user-facing schemas (pg_catalog, pg_temp, and information_schema).
+ Schemas contain
<glossterm linkend="glossary-table">tables</glossterm>,
<glossterm linkend="glossary-view">views</glossterm>, and a lot
- of other objects. Each table or view belongs to a single schema
- only; they cannot belong to another schema as well. The same is
- true for the schema/database and database/cluster relation.
+ of other objects.
<xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
this hierarchy.
</para>
+ <para>
+ Every object uniquely resides in a single schema,
+ though a single client connection can access multiple schemas within
+ the same database simultaneously. Special configuration is required to
+ access multiple databases, even within the same cluster, from a single
+ client connection.
+ </para>
+
<figure id="tutorial-cluster-db-schema-figure">
<title>Cluster, Database, Schema</title>
<mediaobject>
@@ -196,61 +195,12 @@
</mediaobject>
</figure>
- <para>
- A cluster is the outer container for a
- collection of databases. Clusters are created by the command
- <xref linkend="app-initdb"/>.
- </para>
-
- <para>
- <literal>template0</literal> is the very first
- database of any cluster. Database <literal>template0</literal>
- is created during the initialization phase of the cluster.
- In a second step, database <literal>template1</literal> is generated
- as a copy of <literal>template0</literal>, and finally database
- <literal>postgres</literal> is generated as a copy of
- <literal>template1</literal>. Any
- <glossterm linkend="app-createdb">new databases</glossterm>
- of the cluster that a user might need,
- such as <literal>my_db</literal>, will be copied from the
- <literal>template1</literal> database. Due to the unique
- role of <literal>template0</literal> as the pristine original
- of all other databases, no client can connect to it.
- </para>
-
- <para>
- Every database must contain at least one schema because all
- <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>
- must be contained in a schema.
- Schemas are namespaces for SQL objects and ensure
- (with one exception) that the SQL object names are used only once within
- their scope across all types of SQL objects. E.g., it is not possible
- to have a table <literal>employee</literal> and a view
- <literal>employee</literal> within the same schema. But it is
- possible to have two tables <literal>employee</literal> in two
- different schemas. In this case, the two tables
- are separate objects and independent of each
- other. The only exception to this cross-type uniqueness is that
- <glossterm linkend="glossary-unique-constraint">unique constraints
- </glossterm> and the according unique index
- (<xref linkend="indexes-unique"/>) use the same name.
- </para>
-
- <para>
- Some schemas are predefined. <literal>public</literal>
- acts as the default schema and contains all SQL objects
- which are created within <literal>public</literal> or
- without using an explicit schema name. <literal>public</literal>
- should not contain user-defined SQL objects. Instead, it is
- recommended to create a separate schema that holds individual
- objects like application-specific tables or views.
- <literal>pg_catalog</literal> is a schema for all tables and views of the
- <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
- <literal>information_schema</literal> is a schema for several
- tables and views of the System Catalog in a way that conforms
- to the SQL standard.
- </para>
-
+ <!-- The reference to initdb should suffice here -->
+
+ <!-- DGJ: And these next two paragraphs probably can be trimmed down to usage
+ with the incorporation of the references to default objects above, which
+ ideally would point the user to reference material for the same -->
+
<para>
There are many different SQL object
types: <firstterm>database, schema, table, view, materialized
@@ -261,8 +211,8 @@
strict hierarchy: All <firstterm>database names</firstterm>,
all <firstterm>tablespace names</firstterm>, and all
<firstterm>role names</firstterm> are automatically
- available throughout the cluster, independent from
- the database or schema in which they were defined originally.
+ available throughout the cluster, not just the database in which
+ the SQL Command was executed.
<xref linkend="tutorial-internal-objects-hierarchy-figure"/>
shows the relation between the object types.
</para>
@@ -286,7 +236,7 @@
</sect1>
<sect1 id="tutorial-directories">
- <title>The physical Perspective: Directories and Files</title>
+ <title>The Physical Perspective: Directories and Files</title>
<para>
<productname>PostgreSQL</productname> organizes long-lasting (persistent)
@@ -297,7 +247,7 @@
variable <literal>PGDATA</literal> points to this directory.
The example shown in
<xref linkend="tutorial-directories-figure"/> uses
- <literal>data</literal> as the name of this root directory.
+ <literal>pgdata</literal> as the name of this root directory.
</para>
<figure id="tutorial-directories-figure">
@@ -317,16 +267,16 @@
</figure>
<para>
- <literal>data</literal> contains many subdirectories and
+ <literal>pgdata</literal> contains many subdirectories and
some files, all of which are necessary to store long-lasting
as well as temporary data. The following paragraphs
describe the files and subdirectories in
- <literal>data</literal>.
+ <literal>pgdata</literal>.
</para>
<para>
- <literal>base</literal> is a subdirectory in which one
- subdirectory per database exists. The names of those
+ <literal>base</literal> is a subdirectory containing one
+ subdirectory per database. The names of those
subdirectories consist of numbers. These are the internal
Object Identifiers (OID), which are numbers to identify
the database definition in the
@@ -335,7 +285,7 @@
<para>
Within the database-specific
- subdirectories, there are many files: one or more for
+ subdirectories there are many files: one or more for
every table and every index to store heap and index
data. Those files are accompanied by files for the
<link linkend="storage-fsm">Free Space Maps</link>
@@ -348,10 +298,12 @@
Another subdirectory is <literal>global</literal> which
contains files with information about
<glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
- One type of such Global SQL Objects are
- <glossterm linkend="glossary-tablespace">tablespaces</glossterm>.
- In <literal>global</literal> there is information about
- the tablespaces; not the tablespaces themselves.
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal>, there are symbolic links
+ that point to directories containing SQL objects
+ that exist within a non-default tablespace.
</para>
<para>
@@ -370,17 +322,12 @@
</para>
<para>
- In <literal>pg_tblspc</literal>, there are symbolic links
- that point to directories containing SQL objects
- that exist within a non-default tablespace.
- </para>
-
- <para>
- In the root directory <literal>data</literal>
+ In the root directory <literal>pgdata</literal>
there are also some files. In many cases, the configuration
files of the cluster are stored here. If the
instance is up and running, the file
<literal>postmaster.pid</literal> exists here
+ (by default)
and contains the process ID (pid) of the
Postmaster which started the instance.
</para>
On Sun, Nov 8, 2020 at 8:56 AM Jürgen Purtz <juergen@purtz.de> wrote:
Good catches. Everything applied.
MVCC Section
The first paragraph and example in the MVCC section is a good example but
seems misplaced - its relationship to MVCC generally is tenuous, rather I
would expect a discussion of the serializable isolation mode to follow.
I'm not sure how much detail this section wants to get into given the
coverage of concurrency elsewhere in the documentation. "Not much" would
be my baseline.
I would suggest spelling out what "OLTP" stands for and ideally pointing
the user to the glossary for the term.
Tending more toward a style gripe but the amount of leader phrases and
redundancy are at a level that I am noticing them when I read this but do
not have the same impression having read large portions of documentation.
In particular:
"When we speak about transaction IDs, you need to know that xids are like
sequences."
"But keep in mind that xids are independent of any time measurement — in
milliseconds or otherwise. If you dive deeper into PostgreSQL, you will
recognize parameters with names such as 'xxx_age'. Despite their names,
these '_age' parameters do not specify a period of time but represent a
certain number of transactions, e.g., 100 million."
Could just be: xids are sequences and age computations involving them
measure a transaction count as opposed to a time interval.
Then I would consider adding a bit more detail/context here.
xids are 32bit sequences, with a reserved value to handle wrap-around.
There are 4 billion values in the sequence but wrap-around handling must
occur every 2 billion transactions. Age computations involving xids measure
a transaction count as opposed to a time interval.
I would move the mentioning of "vacuum" to the main paragraph about delete
and not solely as a "keep in mind" note.
The part before the diagram seems like it should be much shorter, concise,
and provide links to the excellent documentation. The part after the
image, and the image itself, are good material, though possibly should be
in a main administration chapter instead of an internals chapter.
The first bullet of "keep in mind" is both wordy and wrong - in particular
"as xids grow old row versions get out of scope over time" doesn't make
sense (or rather it only does in the context of wrap-around, not normal
visibility). Having the only mention of bloat be here is also not ideal,
it too should be weaved into the main narrative. The "keep in mind"
section here should be a recap of already covered material in a succinct
form, nothing should be new to someone who just read the entire section.
I don't think that usage of exclamation marks (!) is warranted here, though
emphasis on the key phrase wouldn't hurt.
Vacuum Section
avoid -> prevent (continued growth)
Autovacuum is enabled by default. The whole note needs commas.
I'd try to get rid of "at arbitrary point in time"
"Instance." we've already described where instances are previously ("on the
server")
The other sections - these seem misplaced for the tutorial, update the main
documentation if this information is wholly missing or lacking. The MVCC
chapter can incorporate overview information as it is a strict consequence
of that implementation.
Statistics belong elsewhere - the tutorial should not use poor command
implementation choices as a guide for user education.
In short, this whole section should not exist and its content moved to more
appropriate areas (mainly MVCC). Vacuum is a tool that one must use but
the narrative should be about the system generally.
David J.
On 10.11.20 00:14, David G. Johnston wrote:
Reviewed the first three sections.
template0 - I would remove the schema portions of this and simply note
this as being a pristine recovery database in the diagram.
ok
I would drop the word "more" and just say "system schemas". I would
drop pg_toast from the list of system schema and focus on the three
user-facing ones.
ok
Instead of "my_schema" (optional) I would do "my_schema" (example)
The terms 'optional' and 'default' are used at various places with their
literal meaning. We shall not change them.
Server Graphic
#3 Global SQL Objects: Objects which are shared among all databases
within a cluster.
#6 Client applications are prohibited from connecting to template0
ok
#1 If by you we mean "the client" saying that you work "in the cluster
data" doesn't really help. I would emphasize the point that the
client sees an endpoint the Postmaster publishes as a port or socket
file and that plus the database name defines the endpoint the client
connects to (meld with #5)
ok, with some changes.
In lieu of some of the existing detail provided about structure I
would add information about configuration and search_path at this level.
Search path appended. But IMO configuration questions are out of scope
of this sub-chapter.
I like the object type enumeration - I would suggest grouping them by
type in a manner consistent with the documentation and making each one
a link to its "primary" section - the SQL Command reference if all
else fails.
ok. But don't how to group them in a better way.
The "i" in internal in 51.3 (the image) needs capitalization).
ok
You correctly add both Extension and Collation as database-level
objects but they are not mentioned anywhere else. They do belong here
and need to be tied in properly in the text.
Have some courage to the gap, it's an introductory chapter.
The whole thing needs a good pass focused on capitalization. Both for
typos and to decide when various primary concepts like Instance should
be capitalized and when not.
'Instance' and 'Cluster' are now uppercase because of their importance,
everything else lowercase for better reading.
51.4 - When you look at the diagram seeing /pg/data/base looks really
cool, but when reading the prose where both the "pg" and the "base"
are omitted and all you get are repeated references to "data", the
directory name choice becomes an issue IMO. I suggest (and changed
the attached) to name the actual root directory "pgdata". You should
change the /pg/ directory name to something like ".../tutorial_project/".
The graphic shall reflect the default behavior of PG. Without the
parameter -D, initdb creates the new cluster in the directory where
PGDATA points to. This is in many cases |/var/lib/pgsql/data|. Therefore
'data' and its subdirectory 'base' are not my invention but reflects the
default situation.
(Diving a little deeper into this issue I noticed that there is a
parameter 'cluster_name' in the config file. But it does not change the
name of the cluster's root directory, it only changes the names of the
running processes. Choosing 'instance_name' instead of 'cluster_name' as
the parameter's name would be a better choice imo - but that is not what
we are speaking about in the context of the new chapter).
I changed the very first directory in the graphic to visualize the
standard behavior; I reverted your recommendation to use 'pgdata'
instead of 'data' in the text part.
Since you aren't following alphabetical order anyway I would place
pg_tblspc after globals since tablespaces are globals and thus
proximity links them here - and pointing out that pg_tblspc holds the
data makes stating that global doesn't contain tablespace data
unnecessary.
ok
Maybe point out somewhere the the "base/databaseOID" directory
represents the default tablespace for each database, which isn't
"global", only the non-default tablespaces are considered globals (or
just get rid of the mentioned on "non-default tablespace" for now).
ok
more:
1) some changes concerning the nature of connections (52.2: logical
perspective). IMO accessing multiple databases within one connection is
not a question of configuring, you have to take more actions. But I'm
not sure we should mention this at all.
2) you propose to cancel or trim down the paragraphs behind figure 51.2.
(cluster, database, schema). I believe that a textual description of
this hierarchy is essential for the understanding of the system. Because
it isn't described explicitly at a different place, it should remain.
--- snipp -------- from other e-mail ----
MVCC Section
The first paragraph and example in the MVCC section is a good example
but seems misplaced - its relationship to MVCC generally is tenuous,
rather I would expect a discussion of the serializable isolation mode
to follow.I'm not sure how much detail this section wants to get into given the
coverage of concurrency elsewhere in the documentation. "Not much"
would be my baseline.
The paragraph focus on the fact that new row versions are generated
instead of locking something. Explaining serialization isolation modes
is imo very complicate and out of the scope of this subchapter. If we
want to give an overview - in addition to the exiting documentation - it
should be a separate subchapter.
I would suggest spelling out what "OLTP" stands for and ideally
pointing the user to the glossary for the term.
ok, but not added to glossary. The given explanation "... with a massive
number of concurrent write actions" should be sufficient.
Tending more toward a style gripe but the amount of leader phrases and
redundancy are at a level that I am noticing them when I read this but
do not have the same impression having read large portions of
documentation. In particular:
Because I'm not a native English speaker, orthographic and style hits
are always welcome.
"When we speak about transaction IDs, you need to know that xids are
like sequences.""But keep in mind that xids are independent of any time measurement —
in milliseconds or otherwise. If you dive deeper into PostgreSQL, you
will recognize parameters with names such as 'xxx_age'. Despite their
names, these '_age' parameters do not specify a period of time but
represent a certain number of transactions, e.g., 100 million."Could just be: xids are sequences and age computations involving them
measure a transaction count as opposed to a time interval.
ok
Then I would consider adding a bit more detail/context here.
xids are 32bit sequences, with a reserved value to handle
wrap-around. There are 4 billion values in the sequence but
wrap-around handling must occur every 2 billion transactions. Age
computations involving xids measure a transaction count as opposed to
a time interval.I would move the mentioning of "vacuum" to the main paragraph about
delete and not solely as a "keep in mind" note.
The mentioning here at the food of the page is a crossover to the next
subchapter.
The part before the diagram seems like it should be much shorter,
concise, and provide links to the excellent documentation. The part
after the image, and the image itself, are good material, though
possibly should be in a main administration chapter instead of an
internals chapter.
vacuum: The problem - and one reason for the existence of this
subchapter - is that vacuum's documentation is scattered across may pages:
19.4: parameters to configure the server, especially five parameters
'vacuum_cost_xxx'.
19.10: parameters to configure autovacuum.
19.11: parameters to configure client connections, especially five
parameters 'vacuum_xxx' concerning their freeze-behavior.
24.1: explains the general necessity of (auto)vacuum and their strategies.
The page about the SQL command VACUUM explains the different options
(FULL, FREEZE, ..) and their meaning.
Because of the structure of our documentation as well as the complexity
of the issue that's ok. The existing documentation describes every
parameter very well, but I'm missing a page where the 'big picture' of
vacuum is explained (not necessarily here). It shall show the
relationship between the huge number of parameters and an explanation
*why* they exists. As far as we don't have such a page within the vacuum
documentation the proposed subchapter fills the gap. (The provided
graphics can be included multiple times without generating redundancies
- here and at arbitrary other places.)
The first bullet of "keep in mind" is both wordy and wrong - in
particular "as xids grow old row versions get out of scope over time"
doesn't make sense (or rather it only does in the context of
wrap-around, not normal visibility). Having the only mention of bloat
be here is also not ideal, it too should be weaved into the main
narrative. The "keep in mind" section here should be a recap of
already covered material in a succinct form, nothing should be new to
someone who just read the entire section.
ok.
I don't think that usage of exclamation marks (!) is warranted here,
though emphasis on the key phrase wouldn't hurt.
ok
Vacuum Section
avoid -> prevent (continued growth)
ok
Autovacuum is enabled by default. The whole note needs commas.
ok
I'd try to get rid of "at arbitrary point in time"
ok
"Instance." we've already described where instances are previously
("on the server")
ok
The other sections - these seem misplaced for the tutorial, update the
main documentation if this information is wholly missing or lacking.
The MVCC chapter can incorporate overview information as it is a
strict consequence of that implementation.Statistics belong elsewhere - the tutorial should not use poor command
implementation choices as a guide for user education.In short, this whole section should not exist and its content moved to
more appropriate areas (mainly MVCC). Vacuum is a tool that one must
use but the narrative should be about the system generally.
concerning vacuum section: see my comments above
concerning 'the other sections' (transactions, reliability, backup
(plus: someone should add 'replication', I'm not familiar with this
issue)): The intention of the chapter is to give a *summary* about PG's
essential architecture and about central implementation aspects. This
implies that the chapters does not present any new information. They
shall only show (or repeat) essential things in their context and
explain *why* they are used. In this sense the three chapters may be
reasonable. Concerning this, I like to hear some comments from other people.
Attachments:
0013-architecture.patch: complete patch vs. master
0013-architecture.sgml.diff: changes in file architecture.sgml since 0012
0013-images.diff: changes in files *-raw.svg since 0012
--
J. Purtz
Attachments:
0013-architecture.patchtext/x-patch; charset=UTF-8; name=0013-architecture.patchDownload
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
index 2d4ab85d45..5c3245c0ec 100644
--- a/doc/src/sgml/advanced.sgml
+++ b/doc/src/sgml/advanced.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/advanced.sgml -->
<chapter id="tutorial-advanced">
- <title>Advanced Features</title>
+ <title>Advanced SQL Features</title>
<sect1 id="tutorial-advanced-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/arch-dev.sgml b/doc/src/sgml/arch-dev.sgml
index 7883c3cd82..9db0ae2c78 100644
--- a/doc/src/sgml/arch-dev.sgml
+++ b/doc/src/sgml/arch-dev.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/arch-dev.sgml -->
<chapter id="overview">
- <title>Overview of PostgreSQL Internals</title>
+ <title>Overview of Query Handling</title>
<note>
<title>Author</title>
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
new file mode 100644
index 0000000000..4bbd6abb8a
--- /dev/null
+++ b/doc/src/sgml/architecture.sgml
@@ -0,0 +1,1524 @@
+<!-- doc/src/sgml/architecture.sgml -->
+
+ <chapter id="tutorial-architecture">
+ <title>Overview of Architecture and Implementation</title>
+
+ <para>
+ Every DBMS implements basic strategies to ensure a fast
+ and robust system. This chapter provides an overview of the
+ basic techniques <productname>PostgreSQL</productname> uses to
+ achieve this aim. It does not offer anything which exceeds
+ the information content of other pages. Instead, it tries to
+ explain <emphasis>why</emphasis> certain implementation
+ decisions have been taken.
+ </para>
+
+ <sect1 id="tutorial-ram-proc-file">
+ <title>Collaboration of Processes, RAM, and Files</title>
+ <para>
+ In a client/server architecture clients do not have direct access
+ to database files and the data stored in them. Instead, they send
+ requests to the server and receive the requested data in the response.
+ In the case of <productname>PostgreSQL</productname>, the server
+ launches a single process for each client connection, referred to as a
+ <glossterm linkend="glossary-backend">Backend</glossterm> process.
+ Such a Backend process handles the client's requests by acting on the
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>.
+ This leads to other activities (file access, WAL, vacuum, ...) of the
+ <glossterm linkend="glossary-instance">Instance</glossterm>. The
+ Instance is a group of server-side processes acting on a common
+ Shared Memory. PostgreSQL does not use threading.
+ </para>
+
+ <para>
+ All aspects of an Instance are launched and managed using a single primary
+ process termed the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ It loads configuration files, allocates Shared Memory, and
+ starts the other collaborating processes of the Instance:
+ <glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
+ <glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
+ <glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
+ <glossterm linkend="glossary-wal-archiver">WAL Archiver</glossterm>,
+ <glossterm linkend="glossary-autovacuum">Autovacuum</glossterm>,
+ <glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
+ <glossterm linkend="glossary-logger">Logger</glossterm>, and more.
+ Later, the Postmaster listens on its configured system port and in response
+ to client connection attempts launches
+ <glossterm linkend="glossary-backend">Backend</glossterm> processes
+ to which it delegates authentication, communication, and the handling of their requests.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes the processes
+ of an Instance and the main aspects of their collaboration.
+ </para>
+
+ <figure id="tutorial-ram-proc-file-figure">
+ <title>Architecture</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ Client requests like <command>SELECT</command> or
+ <command>UPDATE</command> usually lead to the
+ necessity to read or write data. This is carried out
+ by the client's backend process. Reads involve a page-level
+ cache, located in Shared Memory (for details see:
+ <xref linkend="sysvipc"/>) for the benefit of all processes
+ in the Instance. Writes also use this cache, in addition
+ to a journal, called the write-ahead-log or WAL.
+ </para>
+
+ <para>
+ Shared Memory is limited in size and it can become necessary
+ to evict pages. As long as the content of such pages hasn't
+ changed, this is not a problem. But writes directly modify
+ the pages in Shared Memory. Modified pages are called dirty
+ pages (or dirty buffers) and before they can be evicted they
+ must be written to disk. This happens regularly by the
+ Checkpointer and the Background Writer processes to ensure
+ that the disk version of the pages are up-to-date.
+ The synchronization from RAM to disk consists of two steps.
+ </para>
+
+ <para>
+ First, whenever the content of a page changes, a
+ <glossterm linkend="glossary-wal-record">WAL record</glossterm>
+ is created from the delta-information (difference between the
+ old and the new content) and stored in another area of
+ Shared Memory. The concurrently running WAL Writer process
+ reads them and appends them to the end of the current
+ <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
+ Such sequential writes are faster than writes to random
+ positions of heap and index files. All WAL records created
+ from one dirty page must be transferred to disk before the
+ dirty page itself can be transferred to disk in the second step.
+ </para>
+
+ <para>
+ Second, the Instance transfers dirty buffers from Shared Memory to
+ files. This is the primary task of the
+ Background Writer process. Because I/O activities can block
+ other processes, it starts periodically and
+ acts only for a short period. Doing so, its extensive (and
+ expensive) I/O activities are spread over time, avoiding
+ debilitating I/O peaks. The Checkpointer process
+ also transfers dirty buffers to file.
+ </para>
+
+ <para>
+ The Checkpointer process creates
+ <glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
+ A Checkpoint is a point in time when all older dirty buffers,
+ all older WAL records, and finally a special Checkpoint record
+ are written and flushed to disk.
+ Older WAL files are no longer required to recover the system from a crash.
+ </para>
+
+ <para>
+ While the Checkpointer ensures that the database system can,
+ after a crash, restart itself in a valid state, the administrator needs
+ to handle the case where the heap or other files become
+ corrupted (and possibly the locally written WAL, though that is
+ less common). Options and details are covered
+ in the backup and restore section (<xref linkend="backup"/>).
+ For our purposes here, just note that the WAL Archiver process
+ can be enabled and configured to run a script on completed WAL
+ files — usually to copy them to a remote location. Note
+ that when a Checkpoint record is written to the WAL the current
+ file is immediately completed.
+ </para>
+
+ <para>
+ The Statistics Collector collects counters about access to
+ SQL objects like tables, rows, indexes, pages, and more. It
+ stores the obtained information in system tables.
+ </para>
+
+ <para>
+ The Logger writes text lines about serious and less serious
+ events that may happen during database access, e.g., wrong
+ password, no permission, long-running queries, etc.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-cluster-db-schema">
+ <title>The logical Perspective: Cluster, Database, Schema</title>
+
+ <para>
+ A <glossterm linkend="glossary-server">Server</glossterm> contains one or more
+ <glossterm linkend="glossary-db-cluster">Database Clusters</glossterm>
+ (<glossterm linkend="glossary-db-cluster">Clusters</glossterm>
+ for short). By default each newly initialized Cluster contains three
+ <glossterm linkend="glossary-database">databases</glossterm>
+ (one interactive and two templates, see <xref linkend="app-initdb"/>).
+ Each database can contain many user-writable
+ <glossterm linkend="glossary-schema">schemas</glossterm>
+ (public, by name and permissiveness, by default), the system
+ generated user-facing schemas <literal>pg_catalog</literal>,
+ <literal>pg_temp</literal>, and <literal>information_schema</literal>,
+ and some more system schemas.
+ <glossterm linkend="glossary-table">Tables</glossterm>,
+ <glossterm linkend="glossary-view">views</glossterm>, and a lot
+ of other objects uniquely reside in a single schema.
+ <xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
+ this hierarchy.
+ </para>
+
+ <para>
+ <!-- is the para helpful at this position? -->
+ Client connections act at the database level and can access
+ its schemas simultaneously. Special techniques like
+ <link linkend="sql-createforeigndatawrapper">foreing data wrapper</link>
+ or <link linkend="dblink">dblink</link> are required
+ to access multiple databases, even within the same Cluster,
+ from a single client connection.
+ </para>
+
+ <figure id="tutorial-cluster-db-schema-figure">
+ <title>Cluster, Database, Schema</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ A Cluster is the outer container for a
+ collection of databases. Clusters are created by the command
+ <xref linkend="app-initdb"/>.
+ </para>
+
+ <para>
+ <literal>template0</literal> is the very first
+ database of any Cluster. It
+ is created during the initialization phase of the Cluster.
+ In a second step, database <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal>, and finally database
+ <literal>postgres</literal> is generated as a copy of
+ <literal>template1</literal>. Any
+ <glossterm linkend="app-createdb">new databases</glossterm>
+ of the Cluster that a user might need,
+ such as <literal>my_db</literal>, will be copied from the
+ <literal>template1</literal> database. Due to the unique
+ role of <literal>template0</literal> as the pristine original
+ of all other databases, no client is allowed to connect to it.
+ </para>
+
+ <para>
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>
+ are contained in a schema.
+ Schemas are namespaces for SQL objects and ensure
+ (with one exception) that the SQL object names are used only once within
+ their scope across all types of SQL objects. E.g., it is not possible
+ to have a table <literal>employee</literal> and a view
+ <literal>employee</literal> within the same schema. But it is
+ possible to have two tables <literal>employee</literal> in two
+ different schemas. In this case, the two tables
+ are separate objects and independent of each
+ other. The only exception to this cross-type uniqueness is that
+ <glossterm linkend="glossary-unique-constraint">unique constraints
+ </glossterm> and the according unique index
+ (<xref linkend="indexes-unique"/>) use the same name.
+ </para>
+
+ <para>
+ Some schemas are predefined. <literal>public</literal>
+ acts as the default schema and contains all SQL objects
+ which are created within <literal>public</literal> or
+ without using an explicit schema name. <literal>public</literal>
+ should not contain user-defined SQL objects. Instead, it is
+ recommended to create a separate schema that holds individual
+ objects like application-specific tables or views. To access
+ objects in such a schema they can be fully qualified, e.g.
+ <literal>my_schema.my_table</literal>, or by changing the
+ <link linkend="ddl-schemas-path">schema search path</link>.
+ </para>
+
+ <para>
+ <literal>pg_catalog</literal> is a schema for all tables and views of the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ <literal>information_schema</literal> is a similar schema. It
+ contains several tables and views of the System Catalog in a
+ way that conforms to the SQL standard.
+ </para>
+
+ <para>
+ There are many different SQL object types:
+ <glossterm linkend="glossary-database">database</glossterm>,
+ <glossterm linkend="glossary-schema">schema</glossterm>,
+ <glossterm linkend="glossary-table">table</glossterm>,
+ <glossterm linkend="glossary-view">view</glossterm>,
+ <glossterm linkend="glossary-materialized-view">materialized view</glossterm>,
+ <glossterm linkend="glossary-index">index</glossterm>,
+ <glossterm linkend="glossary-constraint">constraint</glossterm>,
+ <glossterm linkend="glossary-sequence">sequence</glossterm>,
+ <glossterm linkend="glossary-function">function</glossterm>,
+ <glossterm linkend="glossary-procedure">procedure</glossterm>,
+ <glossterm linkend="glossary-trigger">trigger</glossterm>,
+ <glossterm linkend="glossary-role">role</glossterm>,
+ <glossterm linkend="datatype">data type</glossterm>,
+ <glossterm linkend="functions">operator</glossterm>,
+ <glossterm linkend="glossary-tablespace">tablespace</glossterm>,
+ <glossterm linkend="glossary-extension">extension</glossterm>,
+ <glossterm linkend="glossary-foreign-data-wrapper">foreign data wrapper</glossterm>,
+ and more. A few of them, the
+ <firstterm>Global SQL Objects</firstterm>, are outside of the
+ strict hierarchy: All <firstterm>database names</firstterm>,
+ all <firstterm>tablespace names</firstterm>, and all
+ <firstterm>role names</firstterm> are automatically
+ available throughout the Cluster, not just the database in which
+ the SQL command was executed.
+ <xref linkend="tutorial-internal-objects-hierarchy-figure"/>
+ shows the relation between the object types.
+ </para>
+
+ <figure id="tutorial-internal-objects-hierarchy-figure">
+ <title>Hierarchy of Internal Objects</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect1>
+
+ <sect1 id="tutorial-directories">
+ <title>The Physical Perspective: Directories and Files</title>
+
+ <para>
+ <productname>PostgreSQL</productname> organizes long-lasting (persistent)
+ data as well as volatile state information about transactions
+ or replication actions in the file system. Every
+ <xref linkend="glossary-db-cluster"/> has its root directory
+ somewhere in the file system. In many cases, the environment
+ variable <literal>PGDATA</literal> points to this directory.
+ The example shown in
+ <xref linkend="tutorial-directories-figure"/> uses
+ <literal>data</literal> as the name of the cluster's root directory.
+ </para>
+
+ <figure id="tutorial-directories-figure">
+ <title>Directory Structure</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ The cluster's root directory contains many subdirectories and
+ some files, all of which are necessary to store long-lasting
+ as well as temporary data. The root's name can be selected
+ as desired, but the names of its subdirectories and files
+ are more or less fix and detertermined by
+ <productname>PostgreSQL</productname>. The following
+ paragraphs describe the most important subdirectories
+ and files.
+ </para>
+
+ <para>
+ <literal>base</literal> contains one
+ subdirectory per database. The names of those
+ subdirectories consist of numbers. These are the internal
+ Object Identifiers (OID), which are numbers to identify
+ their definition in the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ </para>
+
+ <para>
+ Within the database-specific subdirectories of <literal>base</literal>
+ there are many files: one or more for every table
+ and every index. Those files are accompanied by files for the
+ <link linkend="storage-fsm">Free Space Maps</link>
+ (suffixed <literal>_fsm</literal>) and
+ <link linkend="storage-vm">Visibility Maps</link>
+ (suffixed <literal>_vm</literal>), which contain optimization information.
+ </para>
+
+ <para>
+ Another subdirectory is <literal>global</literal>. It
+ contains files with information about
+ <glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal>, there are symbolic links
+ that point to directories that are outside of the root
+ directory tree, e.g. at a different disc. Files for tables
+ and indexes of non-default tablespaces reside there. As
+ previously mentioned, those defined within the default
+ tablespace reside in the database-specific subdirectories.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_wal</literal> contains the
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
+ They arise and grow in parallel with data changes in the
+ Cluster and remain as long as
+ they are required for recovery, archiving, or replication.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_xact</literal> contains
+ information about the status of each transaction:
+ <literal>in_progress</literal>, <literal>committed</literal>,
+ <literal>aborted</literal>, or <literal>sub_committed</literal>.
+ </para>
+
+ <para>
+ In the root directory
+ there are also some files. In many cases, the configuration
+ files of the Cluster are stored here. If the
+ Instance is up and running, the file
+ <literal>postmaster.pid</literal> exists here
+ (by default)
+ and contains the process ID (pid) of the
+ Postmaster which started the Instance.
+ </para>
+
+ <para>
+ For more details about the physical implementation
+ of database objects, see <xref linkend="storage"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-mvcc">
+ <title>MVCC — Multiversion Concurrency Control</title>
+
+ <para>
+ In most cases, <productname>PostgreSQL</productname> databases
+ support many clients at the same time which makes it necessary to
+ protect concurrently running requests from unwanted overwriting
+ of other's data as well as from reading inconsistent data. Imagine an
+ online shop offering the last copy of an article. Two clients have the
+ article displayed at their user interface. After a while, but at the same time,
+ both users decide to put it to their shopping cart or even to buy it.
+ Both have seen the article, but only one can be allowed to get it.
+ The database must bring the two requests in a row, permit the access
+ to one of them, block the other, and inform the blocked client
+ that the data was changed by a different process.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> implements a
+ sophisticated technique which avoids locking:
+ <firstterm>Multiversion Concurrency Control</firstterm> (MVCC).
+ The advantage of MVCC over technologies that use row locks
+ becomes evident in multiuser Online Transaction Processing (OLTP)
+ environments with a massive number of concurrent write
+ actions. There, MVCC generally performs better than solutions
+ using locks. In a <productname>PostgreSQL</productname>
+ database, reading never blocks writing and writing never
+ blocks reading, even in the strictest level of transaction
+ isolation.
+ </para>
+
+ <para>
+ Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
+ a new version of the row when a data-change takes place. To
+ distinguish between these two versions, and to track the timeline
+ of the row, each of the versions contains, in addition to their user-defined
+ columns, two special system columns, which are not visible
+ for the usual <command>SELECT * FROM ...</command> command.
+ The column <literal>xmin</literal> contains the transaction ID (xid)
+ of the transaction which created this version of the row.
+ <literal>xmax</literal> contains the xid of the transaction which has
+ deleted this version, or zero if the version is not
+ deleted. You can read both with the command
+ <command>SELECT xmin, xmax, * FROM ... </command>.
+ </para>
+
+ <para>
+ Xids are sequences (with a reserved value to handle wrap-around
+ in pre-9.4 <productname>PostgreSQL</productname> versions).
+ Age computations involving them measure a transaction
+ count as opposed to a time interval (in milliseconds or otherwise).
+ If you dive deeper into <productname>PostgreSQL</productname>,
+ you will recognize parameters with names such as 'xxx_age'.
+ Despite their names, these '_age' parameters do not specify
+ a period of time but represent a certain number of transactions,
+ e.g., 100 million.
+ </para>
+
+ <para>
+ The description in this chapter simplifies by omitting details.
+ When many transactions are running simultaneously, things can
+ get complicated. Sometimes transactions are aborted via
+ <command>ROLLBACK</command> immediately or after a lot of other activities, sometimes
+ a single row is involved in more than one transaction, sometimes
+ a client crashes, sometimes the sequence of xids restarts
+ from zero, ... . Therefore, every version of a row contains more
+ system columns and flags, not only <literal>xmin</literal>
+ and <literal>xmax</literal>.
+ </para>
+
+ <para>
+ So, what's going on in detail when write access takes place?
+ <xref linkend="tutorial-mvcc-figure"/> shows details concerning
+ <literal>xmin</literal>, <literal>xmax</literal>, and user data.
+ </para>
+
+ <figure id="tutorial-mvcc-figure">
+ <title>Multiversion Concurrency Control</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ An <command>INSERT</command> command creates the first
+ version of a row. Besides its user data <literal>'x'</literal>,
+ this version contains the ID of the creating transaction
+ <literal>123</literal> in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ <literal>xmin</literal> indicates that the version
+ exists since transaction <literal>123</literal> and
+ <literal>xmax</literal> that it is currently not deleted.
+ </para>
+
+ <para>
+ Somewhat later, transaction <literal>135</literal>
+ executes an <command>UPDATE</command> of this row by
+ changing the user data from <literal>'x'</literal> to
+ <literal>'y'</literal>. According to the MVCC principles,
+ the data in the old version of the row is not changed.
+ The value <literal>'x'</literal> remains as it was before.
+ Only <literal>xmax</literal> changes to <literal>135</literal>.
+ Now, this version is treated as valid exclusively for
+ transactions with xids from <literal>123</literal> to
+ <literal>134</literal>. In addition to the non-occurring
+ data change in the old version, the <command>UPDATE</command>
+ creates a new version of the row with its xid in
+ <literal>xmin</literal>, <literal>0</literal> in
+ <literal>xmax</literal>, and <literal>'y'</literal> in the
+ user data (plus all other user data from the old version).
+ This new row version is visible to all future transactions.
+ (Internally, an <command>UPDATE</command> command acts
+ as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.)
+ </para>
+
+ <para>
+ All subsequent <command>UPDATE</command> commands behave
+ in the same way as the first one: they put their xid in
+ <literal>xmax</literal> of the current version, create
+ a new version with their xid in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ </para>
+
+ <para>
+ Finally, a row may be deleted by a <command>DELETE</command>
+ command. Even in this case, all versions of the row remain as
+ before; nothing is thrown away. Only <literal>xmax</literal>
+ of the last version is set to the xid of the <command>DELETE</command>
+ transaction, which indicates that (if committed) it is only visible to
+ transactions with xids older than that (from
+ <literal>142</literal> to <literal>820</literal> in this
+ example).
+ </para>
+
+ <para>
+ In summary, the MVCC technology creates more and more versions
+ of the same row in the table's heap file and leaves them there,
+ even after a <command>DELETE</command> command. Only the youngest
+ version is relevant for all future transactions. But the
+ system must also preserve some of the older ones for
+ awhile, because they could still be needed by
+ transactions which started before the deleting transaction commits.
+ Over time, also the older ones get out of scope
+ for ALL transactions and therefore become unnecessary.
+ Nevertheless, they do exist physically on the disk and occupy
+ space. They are called <firstterm>dead rows</firstterm> and are part
+ of the <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ </para>
+
+ <para>
+ Keep in mind:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> and <literal>xmax</literal>
+ indicate the range in which
+ <firstterm>row versions</firstterm> are valid (visible) for transactions.
+ This range doesn't imply any direct temporal meaning;
+ the sequence of xids reflects only the sequence of
+ transaction begin events.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Internally, an <command>UPDATE</command> command acts in the
+ same way as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Nothing is removed — with the consequence that the database
+ occupies more and more disk space. It is obvious that
+ this behavior has to be corrected in some way. The next
+ chapter explains how <firstterm>vacuum</firstterm> and
+ <firstterm>autovacuum</firstterm> fulfill this task.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ </sect1>
+
+ <sect1 id="tutorial-vacuum">
+ <title>Vacuum</title>
+
+ <para>
+ As we have seen in the previous chapter, the database
+ tends to occupy more and more disk space, caused by
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ This chapter explains how the SQL command
+ <command>VACUUM</command> and the automatically running
+ <firstterm>Autovacuum</firstterm> processes clean up
+ and prevent continued growth.
+ </para>
+
+ <note>
+ <para>
+ Autovacuum runs automatically, by
+ default. Its default parameters as well as those for
+ <command>VACUUM</command> are appropriate for most standard
+ situations. Therefore a novice database manager can
+ skip the rest of this chapter which explains
+ a lot of details.
+ </para>
+ </note>
+
+ <para>
+ Client processes can issue the SQL command <command>VACUUM</command>
+ at any time. DBAs do this when they recognize
+ special situations, or they start it in batch jobs which run
+ periodically. Additionally, there is a constantly running
+ Autovacuum daemon which is part of the
+ <link linkend="glossary-instance">Instance</link>. It continuously
+ monitors the state of all databases based on values that are collected by the
+ <link linkend="glossary-stats-collector">Statistics Collector</link>
+ and starts Autovacuum processes whenever it detects
+ certain situations. Thus, it's a dynamic behavior of
+ <productname>PostgreSQL</productname> with the intention to tidy
+ up whenever it is appropriate.
+ </para>
+
+ <para>
+ <command>VACUUM</command>, as well as Autovacuum, don't just eliminate
+ bloat. They perform additional tasks for minimizing future
+ I/O activities of themselves as well as of other processes.
+ This extra work can be done in a very efficient way since in most
+ cases the expensive physical access to pages has taken place anyway
+ to eliminate bloat. The additional operations are:
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <firstterm>Freeze</firstterm>: Mark certain row versions
+ as frozen. This means that they
+ are always treated as valid (visible) independent from
+ the <firstterm>wraparound problem</firstterm> (see below).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <firstterm>Visibility Map</firstterm> and
+ <firstterm>Free Space Map</firstterm>: Log information about
+ the state of the handled pages in two additional files, the
+ Visibility Map and the Free Space Map.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <emphasis>Statistics</emphasis>: Collect statistics about the
+ number of rows per table, the distribution of values, and so on,
+ as the basis for decisions of the query planner.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ The eagerness — or 'aggressiveness' — of the
+ operations for <emphasis>eliminating bloat</emphasis> and
+ <emphasis>freeze</emphasis> is controlled by configuration
+ parameters, runtime flags, and in extreme situations by
+ the processes themselves. Because vacuum operations typically are I/O
+ intensive, which can hinder other activities, Autovacuum
+ avoids performing many vacuum operations in bulk. Instead,
+ it carries out many small actions with delay points in between.
+ The SQL command <command>VACUUM</command> runs immediately
+ and without any time delay.
+ </para>
+
+ <bridgehead renderas="sect2">Eliminate Bloat</bridgehead>
+
+ <para>
+ To determine which of the row versions are no longer needed, the
+ elimination operation must evaluate <literal>xmax</literal>
+ against several criteria which must all apply:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be different from zero because a
+ value of zero indicates that the row version is still valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must contain an xid which is older
+ than the oldest xid of all currently running transactions
+ <literal>(min(pg_stat_activity.backend_xmin))</literal>.
+ This criterion guarantees that no existing or upcoming transaction
+ will have read or write access to this row version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of <literal>xmax</literal> must be committed. If it was rollback-ed,
+ this row version is treated as valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there is the situation that the row version is part of
+ multiple transactions, special care and some more actions
+ must be taken, see: <xref linkend="vacuum-for-multixact-wraparound"/>.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ After the vacuum operation detects an unused row version, it
+ marks its space as free for future use of writing actions. Only
+ in rare situations (or in the case of <command>VACUUM FULL</command>),
+ is this space released to the operating system. In most cases,
+ it remains occupied by <productname>PostgreSQL</productname>
+ and will be used by future <command>INSERT</command> or
+ <command>UPDATE</command> commands to this table.
+ </para>
+
+ <para>
+ Which actions start the elimination of bloat?
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ in its default format, i.e., without any option. To boost performance,
+ in this and the next case <command>VACUUM</command> does not
+ read and act on all pages of the heap file.
+ The Visibility Map, which is very compact and therefore fast to read,
+ contains information about which pages have no deleted row versions, and
+ can be skipped by <command>VACUUM</command>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FREEZE</command>. (In this case,
+ it undertakes many more actions, see
+ <link linkend="tutorial-freeze">Freeze Row Versions</link>.)
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FULL</command>.
+ In this mode, an exclusive lock is taken, and
+ the whole table is copied to a different file, skipping all outdated row
+ versions. All bloat is thereby eliminated, which
+ may lead to a significant reduction of used disk space.
+ The old file is deleted.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When an Autovacuum process acts. For optimization
+ purposes, it considers the Visibility Map in the same way as
+ <command>VACUUM</command>. Additionally, it ignores tables with few modifications;
+ see <xref linkend="guc-autovacuum-vacuum-threshold"/>,
+ which defaults to 50 rows and
+ <xref linkend="guc-autovacuum-vacuum-scale-factor"/>,
+ which defaults to 20%.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </para>
+
+ <para>
+ This logic only applies to row versions of the heap. Index entries
+ don't use <literal>xmin/xmax</literal>. Nevertheless, such index
+ entries, which would lead to outdated row versions, are cleaned up
+ accordingly.
+ </para>
+
+ <para>
+ The above descriptions omit the fact that xids on a real computer
+ have a limited size, and after
+ a certain number of transactions they are forced to restart
+ from the beginning, which is called <firstterm>wraparound</firstterm>.
+ Therefore the terms 'old transaction' / 'young transaction' does
+ not always correlate with low / high values of xids. Near to
+ wraparound point, there are cases where <literal>xmin</literal> has
+ a higher value than <literal>xmax</literal>, although their meaning
+ is said to be older than <literal>xmax</literal>.
+ </para>
+
+ <figure id="tutorial-wraparound-figure">
+ <title>Cyclic usage of XIDs</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2" id="tutorial-freeze">Freeze Row Versions</bridgehead>
+
+ <para>
+ The use of a limited range of IDs for transactions leads
+ to the necessity to restart the sequence sooner or later.
+ This not only has the rare consequence, previously
+ described, that sometimes <literal>xmin</literal> is
+ higher than <literal>xmax</literal>. A far
+ more critical problem is that whenever the system has
+ to evaluate a WHERE condition, it must decide which row
+ version is valid (visible) from the perspective of the
+ transaction of the query. If a wraparound couldn't happen,
+ this decision would be relatively easy: the xid
+ must be between <literal>xmin</literal> and <literal>xmax</literal>,
+ and the corresponding transactions of <literal>xmin</literal>
+ and <literal>xmax</literal> must be committed. However,
+ <productname>PostgreSQL</productname> has to consider the
+ possibility of wraparound.
+ Therefore the decision becomes more complex. The general
+ idea of the solution is to use the 'between
+ <literal>xmin</literal> and <literal>xmax</literal>'
+ comparison only during the youngest period of the row
+ versions lifetime and afterward replace it with a
+ 'valid forever' flag in its header.
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ As a first step, <productname>PostgreSQL</productname>
+ divides the complete range of
+ possible xids into two halves with the two split-points
+ 'txid_current' and 'txid_current + 2^31'. The half behind
+ 'txid_current' is considered to represent xids of the
+ 'past' and the half ahead of 'txid_current' those of the
+ 'future'. Those of the 'past' are valid (visible) and those
+ of the 'future' not.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ With each newly created transaction the two split-points
+ move forward. If 'txid_current + 2^31' reached a
+ row version with <literal>xmin</literal> equal to that value, it would
+ immediately jump from 'past' to 'future' and would be
+ no longer visible!
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If not handled in some way, data inserted many transactions ago
+ would become invisibile. The vacuum operation <firstterm>freeze</firstterm>
+ avoids this long before the split-point is reached by setting
+ a flag in the header of the row version which avoids
+ future comparison of its <literal>xmin/xmax</literal> and indicates
+ that the version is valid not only in the 'past'-half
+ but also in the 'future'-half, as well as in all coming
+ <glossterm linkend="glossary-xid">epochs</glossterm>.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Which row versions can be frozen by the vacuum operation?
+ Again, several criteria must be checked, and all must be met.
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be zero because only
+ non-deleted rows can be visible 'forever'.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> must be older than all currently
+ existing transactions. This guarantees that no existing
+ transaction can modify or delete the version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transactions of <literal>xmin</literal> and
+ <literal>xmax</literal> must be committed.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ At what point in time does the freeze operation take place?
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with its <command>FREEZE</command> option. In this case, all
+ pages are processed that are marked in the Visibility Map
+ as potentially having unfrozen rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command> without
+ any options but there are xids older than
+ <xref linkend="guc-vacuum-freeze-table-age"/>
+ (default: 150 million) minus
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million).
+ As before, all pages are processed that are
+ marked in the Visibility Map to potentially having unfrozen
+ rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When an Autovacuum process runs. Such a process acts in one
+ of two modes:
+ </simpara>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ In the <emphasis>normal mode</emphasis>, it skips
+ pages with row versions that are younger than
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million) and works only on pages where
+ all xids are older. The skipping of young xids prevents
+ work on such pages, which are likely to be changed
+ by one of the future SQL commands.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ The process switches
+ to an <emphasis>aggressive mode</emphasis> if it recognizes
+ that for the processed table the oldest xid exceeds
+ <xref linkend="guc-autovacuum-freeze-max-age"/>
+ (default: 200 million). The value of the oldest unfrozen
+ xid is stored per table in <literal>pg_class.relfrozenxid</literal>.
+ In this <emphasis>aggressive mode</emphasis> Autovacuum
+ processes all such pages of the selected table that are marked
+ in the Visibility Map to potentially have bloat or unfrozen rows.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In the first two cases and with Autovacuum in
+ <emphasis>aggressive mode</emphasis>, the system knows
+ to which value the oldest unfrozen xid has moved forward and
+ logs the value in <literal>pg_class.relfrozenxid</literal>.
+ The distance between this value and the 'txid_current' split
+ point becomes smaller, and the distance to 'txid_current + 2^31'
+ becomes larger than before.
+ </para>
+
+ <figure id="tutorial-freeze-figure">
+ <title>Freeze</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2">Protection against Wraparound Failure</bridgehead>
+
+ <para>
+ The Autovacuum processes are initiated by the constantly running
+ Autovacuum daemon. If the daemon detects that for a table
+ <literal>autovacuum_freeze_max_age</literal> is exceeded, it
+ starts an Autovacuum process in <emphasis>aggressive mode</emphasis>
+ (see above) — even if Autovacuum is disabled.
+ </para>
+
+ <bridgehead renderas="sect2">Visibility Map and Free Space Map</bridgehead>
+
+ <para>
+ The <link linkend="glossary-vm">Visibility Map</link>
+ (VM) contains two flags — stored as
+ two bits — for each page of the heap file. The
+ first bit indicates that the associated page does
+ not contain any bloat. The second bit indicates
+ that the page contains only frozen row versions.
+ </para>
+
+ <para>
+ Please consider two details. First, in most cases a page
+ contains many rows or row versions.
+ However, the flags are associated with the page,
+ not with an individual row version. The flags are set
+ only under the condition that they are valid for ALL
+ row versions of the page. Second, since there
+ are only two bits per page, the VM is considerably
+ smaller than the heap.
+ </para>
+
+ <para>
+ The setting of the flags is silently done by <command>VACUUM</command>
+ and Autovacuum during their bloat and freeze operations.
+ This is done to speed up future vacuum actions,
+ regular access to heap pages, and some access to
+ the index. Every data-modifying operation on any row
+ version of the page clears the flags.
+ </para>
+
+ <para>
+ The <link linkend="glossary-fsm">Free Space Map</link>
+ (FSM) tracks the amount of free space per page. It is
+ organized as a highly condensed b-tree of (rounded) sizes.
+ Whenever <command>VACUUM</command> or Autovacuum changes
+ the free space on any processed page, they log the new
+ values in the FSM in the same way as all other writing
+ processes.
+ </para>
+
+ <bridgehead renderas="sect2">Statistics</bridgehead>
+
+ <para>
+ Statistical information helps the <link
+ linkend="planner-stats">Query Planner</link> to make optimal
+ decisions for the generation of execution plans. This
+ information can be gathered with the SQL commands
+ <command>ANALYZE</command> or <command>VACUUM ANALYZE</command>.
+ But Autovacuum processes also gather
+ such information. Depending on the percentage of changed rows
+ <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ and minimum number of changed rows <xref linkend="guc-autovacuum-analyze-threshold"/>,
+ the Autovacuum daemon starts Autovacuum processes to collect
+ statistics per table. The automatic analysis
+ allows <productname>PostgreSQL</productname> to
+ adapt query execution to changing circumstances.
+ </para>
+
+ <para>
+ For more details about vacuum operations, especially for its
+ numerous parameters, see <xref linkend="routine-vacuuming"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-transactions-mvcc">
+ <title>Transactions</title>
+ <para>
+ <link linkend="tutorial-transactions">Transactions</link>
+ are a fundamental concept of relational database systems.
+ Their essential point is that they bundle multiple
+ read- or write-operations into a single all-or-nothing
+ operation. Furthermore, they separate and protect concurrent
+ actions of different connections from each other. Thereby
+ they implement the ACID paradigm.
+ </para>
+
+ <para>
+ In <productname>PostgreSQL</productname> there are two ways
+ to establish a transaction. The explicit way uses the keywords
+ <link linkend="sql-begin">BEGIN</link> and
+ <link linkend="sql-commit">COMMIT</link> (respectively
+ <link linkend="sql-rollback">ROLLBACK</link>) before
+ and after a sequence of SQL statements. The keywords mark
+ the transaction's start- and end-point. On the other hand, you
+ can omit the keywords. This is the implicit way, where
+ every single SQL command automatically establishes a new
+ transaction.
+
+ <programlisting>
+BEGIN; -- establish a new transaction
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+COMMIT; -- finish the transaction
+
+-- this UPDATE runs as the only command of a separate transaction ...
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+
+-- ... and this one runs in another transaction
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+ </programlisting>
+ </para>
+
+ <para>
+ As mentioned, the primary property of a transaction is its
+ atomicity: either all or none of its operations succeed,
+ regardless of the fact that it may consist of a lot of
+ different write-operations, and each such operation may
+ affect many rows. As soon as one of the
+ operations fails, all previous operations fail also, which
+ means that all modified rows retain their values as of the
+ beginning of the transaction.
+ </para>
+
+ <para>
+ The atomicity also affects the visibility of changes. No
+ connection running simultaneously with a data modifying
+ transaction will ever see any change before the
+ transaction successfully executes a <command>COMMIT</command>
+ — even in the lowest
+ <link linkend="transaction-iso">isolation level</link>
+ of transactions. <productname>PostgreSQL</productname>
+ never shows uncommitted changes to other connections.
+ </para>
+
+ <para>
+ The situation regarding visibility is somewhat different
+ from the point of view of the modifying transaction.
+ A <command>SELECT</command> command issued inside a
+ transaction shows all changes done so far by this
+ transaction.
+ </para>
+
+ <bridgehead renderas="sect2">How does it work?</bridgehead>
+
+ <para>
+ Every <command>INSERT</command>, <command>UPDATE</command>,
+ and <command>DELETE</command> command creates new row
+ versions — according to the MVCC rules. This
+ creates the risk that other transactions may see the
+ new row versions, and after a while and some more
+ activities of the modifying transaction they may see the
+ next row versions. Results would be a kind of 'moving
+ target' which would be contrary to the all-or-nothing
+ principle.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> overcomes this
+ problem by showing only such row versions to other
+ transactions whose originating transaction has
+ successfully committed. It skips all row versions of
+ uncommitted transactions. And
+ <productname>PostgreSQL</productname> solves one more
+ problem. Even the single <command>COMMIT</command>
+ command needs a short time interval for its execution.
+ Therefore its critical 'dead-or-survival' phase
+ runs in a privileged mode that cannot be
+ interrupted by other processes.
+ </para>
+
+ <bridgehead renderas="sect2">What are the benefits?</bridgehead>
+
+ <para>
+ Transactions relieve applications from many standard
+ actions that would otherwise need to be implemented for nearly every use case.
+ </para>
+
+ <para>
+ Business logic often contains strong, but for a computer,
+ relative abstract requirements. The above example shows
+ the transfers of some money from one account to another.
+ It is obvious
+ that the decrease of the one account and the increase of the
+ other must be indivisible. Nevertheless, there is no particular
+ need for an application to do something to ensure the
+ <glossterm linkend="glossary-atomicity">atomicity</glossterm>
+ of this behavior. It's enough to surround them with
+ <command>BEGIN</command> and <command>COMMIT</command>.
+ </para>
+
+ <para>
+ Applications often demand the feature of 'undoing'
+ previously taken actions under some application-specific
+ conditions. In such cases, the application simply issues a
+ <command>ROLLBACK</command> command instead of a
+ <command>COMMIT</command>. The <command>ROLLBACK</command>
+ cancels the transaction, and all changes made so far remain
+ invisible forever; it is as if they had never happened. There
+ is no need for the application to log its activities and
+ undo every step of the transaction separately.
+ </para>
+
+ <para>
+ Transactions ensure that the
+ database always remains
+ <glossterm linkend="glossary-consistency">consistent</glossterm>.
+ Declarative rules like
+ <link linkend="ddl-constraints-primary-keys">primary</link>- or
+ <link linkend="ddl-constraints-fk">foreign keys</link>,
+ <link linkend="ddl-constraints-check-constraints">checks</link>,
+ other constraints, or
+ <link linkend="trigger-definition">triggers</link>
+ are part of the all-or-nothing nature of transactions.
+ </para>
+
+ <para>
+ There is the additional feature
+ '<link linkend="transaction-iso">isolation level</link>',
+ which separates transactions from each other in certain ways.
+ It automatically prevents applications from some strange
+ situations.
+ </para>
+
+ <para>
+ Lastly, it is worth noticing that changes done by a
+ committed transaction will survive all failures in the application or
+ the Database Cluster. The next chapter explains the
+ <glossterm linkend="glossary-durability">durability</glossterm>
+ guarantees.
+ </para>
+ </sect1>
+
+ <sect1 id="tutorial-reliability">
+ <title>Reliability</title>
+
+ <para>
+ Nothing is perfect and failures inevitably happen.
+ However, the most common types of failure are
+ well known and <productname>PostgreSQL</productname>
+ implements strategies to overcome them.
+ Such strategies use parts of the previously presented
+ techniques MVCC and transaction-rollback, plus additional
+ features.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the client side</bridgehead>
+ <para>
+ A <glossterm linkend="glossary-client">client</glossterm>
+ can fail in different ways. Its hardware can get damaged,
+ the power supply can fail, the network connection to the
+ server can break, or the client application may run into
+ a severe software error like a null pointer exception.
+ Because <productname>PostgreSQL</productname> uses a
+ client/server architecture, no direct problem for the
+ database will occur. In all of these cases, the
+ <glossterm linkend="glossary-backend">Backend process</glossterm>,
+ which is the client's counterpart at the server side,
+ may recognize that the network connection is no longer
+ working, or it may run into a timeout after a while. It
+ terminates, and there is no harm to the database. As
+ usual, uncommitted data changes initiated by this client
+ are not visible to any other client.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the server-side</bridgehead>
+
+ <bridgehead renderas="sect3">Instance failure</bridgehead>
+ <para>
+ The Instance may suddenly fail because of <emphasis>power off</emphasis>
+ or other problems. This will affect all running processes, the RAM,
+ and possibly the consistency of disk files.
+ </para>
+
+ <para>
+ After a restart, <productname>PostgreSQL</productname>
+ automatically recognizes that the last shutdown of the
+ Instance did not happen as expected: files might not be
+ closed properly and the <literal>postmaster.pid</literal>
+ file unexpectedly exists. <productname>PostgreSQL</productname>
+ tries to clean up the situation. This is possible because
+ all changes in the database are stored twice. First,
+ the WAL files contain them as a chronology of
+ <glossterm linkend="glossary-wal-record">WAL records</glossterm>,
+ which include the new data values and information about commit
+ actions. The WAL records are written first. Only then is
+ the data itself written to the heap and index files.
+ In contrast to the WAL records, this part may or may
+ not have been transferred entirely from Shared Memory
+ to the files.
+ </para>
+
+ <para>
+ The automatic recovery searches within the WAL files for
+ the latest
+ <glossterm linkend="glossary-checkpoint">checkpoint</glossterm>.
+ This checkpoint signals that the database files are in
+ a consistent state, especially that all WAL records up to
+ this point were successfully stored in heap and index files. Starting
+ here, the recovery process copies any remaining WAL records
+ to heap and index. The result is that the heap files contain all
+ changes recorded to the WAL and reach a consistent state. Changes of committed
+ transactions are visible; those of uncommitted transactions
+ are also in the files, but - as usual - they are never seen
+ by any of the following transactions because uncommitted
+ changes are never shown. These recovery actions run
+ automatically; it is not necessary that a
+ database administrator configure or start anything by
+ himself.
+ </para>
+
+ <bridgehead renderas="sect3">Disk crash</bridgehead>
+ <para>
+ If a disk crashes, the course of action described previously
+ cannot work: it is likely that the WAL files and/or the
+ data and index files are no longer available. The
+ database administrator must take special actions to
+ prepare for such a situation.
+ </para>
+
+ <para>
+ They obviously need a backup. How to take such a backup
+ and use it as a starting point for a recovery of the
+ Cluster is explained in more detail in the next
+ <link linkend="tutorial-backup">chapter</link>.
+ </para>
+
+ <bridgehead renderas="sect3">Disk full</bridgehead>
+ <para>
+ It is conceivable that over time the disk gets full,
+ and there is no room for additional data. In this case,
+ <productname>PostgreSQL</productname> stops accepting
+ data-modifying commands or even terminates completely.
+ Committed data is neither lost nor corrupted.
+ </para>
+
+ <para>
+ To recover from such a situation, the administrator should
+ remove unused files from this disk. But they should never
+ delete files from the
+ <glossterm linkend="glossary-data-directory">data directory</glossterm>.
+ Nearly all of them are necessary for the consistency
+ of the database.
+ </para>
+
+ <bridgehead renderas="sect2">High availability</bridgehead>
+ <para>
+ Database servers can work together to allow a second
+ server to quickly take over the workload if the
+ primary server fails for whatever reason
+ (<link linkend="high-availability">high availability</link>),
+ or to allow several computers to serve the same data
+ for the purpose of load balancing.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-backup">
+ <title>Backup</title>
+
+ <para>
+ Taking backups is a basic task of database maintenance.
+ <productname>PostgreSQL</productname> supports
+ three different strategies; each has its own
+ strengths and weaknesses.
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ File system level backup
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Logical backup via <command>pg_dump</command>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Continuous archiving based on <command>pg_basebackup</command>
+ and WAL files
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <bridgehead renderas="sect2">File system level backup</bridgehead>
+ <para>
+ You can use any appropriate OS tool to create a
+ <link linkend="backup-file">copy</link>
+ of the Cluster's directory structure and files. In
+ case of severe problems such a copy can serve as
+ the source of recovery. But in order to get a
+ <emphasis>USABLE</emphasis> backup by this method,
+ the database server <emphasis>MUST</emphasis> be
+ shut down during the complete runtime of the copy
+ command!
+ </para>
+
+ <para>
+ The obvious disadvantage of this method is that there
+ is a downtime.
+ The other two strategies run during regular operating
+ times.
+ </para>
+
+ <bridgehead renderas="sect2">Logical backup via pg_dump</bridgehead>
+ <para>
+ The tool <command>pg_dump</command> is able to take a
+ <link linkend="backup-dump">copy</link>
+ of the complete Cluster or certain parts of it. It stores
+ the copy in the form of SQL commands like <command>CREATE</command>
+ and <command>COPY</command>. It runs in
+ parallel with other processes, in its own transaction.
+ </para>
+
+ <para>
+ The output of <command>pg_dump</command> may be used as
+ input of <command>psql</command> to restore the data
+ (or to copy it to another database).
+ </para>
+
+ <para>
+ The main advantage over the other two methods is that it
+ can pick parts of the Cluster, e.g., a single table or one
+ database. The other two methods work only at the level of
+ the complete Cluster.
+ </para>
+
+ <bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
+ <para>
+ <link linkend="continuous-archiving">This method</link>
+ is the most sophisticated and most complex one. It
+ consists of two phases.
+ </para>
+
+ <para>
+ First, you need to create a so-called
+ <firstterm>basebackup</firstterm> with the tool
+ <command>pg_basebackup</command>. The result is a
+ directory structure plus files which contain a
+ consistent copy of the original Cluster.
+ <command>pg_basebackup</command> runs in
+ parallel with other processes in its own transaction.
+ </para>
+
+ <para>
+ The second step is recommended but not necessary. All
+ changes to the data are stored in WAL files. If you
+ continuously save such WAL files, you have the history
+ of the Cluster. This history can be applied to a
+ basebackup in order to recreate
+ any state of the Cluster between the time of
+ <command>pg_basebackup</command>'s start time and
+ any later point in time. This technique
+ is called 'Point-in-Time Recovery (PITR)'.
+ </para>
+
+ <para>
+ If configured, the
+ <glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
+ will automatically copy every single WAL file to a save location.
+ <link linkend="backup-archiving-wal">Its configuration</link>
+ consists mainly of a string that contains a copy command
+ in the operating system's syntax. In order to protect your
+ data against a disk crash, the destination location
+ of a basebackup as well as of the
+ <firstterm>archived WAL files</firstterm> should be on a
+ disk which is different from the data disk.
+ </para>
+
+ <para>
+ If it becomes necessary to restore the Cluster, you have to
+ copy the basebackup and the archived WAL files to
+ their original directories. The configuration of this
+ <link linkend="backup-pitr-recovery">recovery procedure</link>
+ contains a string with the reversed copy command: from
+ archive location to database location.
+ </para>
+
+ </sect1>
+
+<!-- ToDo: replication, index-types, extension mechanism, ...
+ <sect1 id="tutorial-replication">
+ <title>Replication</title>
+
+ <para>
+...
+ </para>
+
+ </sect1>
+-->
+
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 38e8aa0bbf..7490d3c9c2 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -80,6 +80,7 @@
%allfiles;
<!-- developer's guide -->
+<!ENTITY architecture SYSTEM "architecture.sgml">
<!ENTITY arch-dev SYSTEM "arch-dev.sgml">
<!ENTITY bki SYSTEM "bki.sgml">
<!ENTITY catalogs SYSTEM "catalogs.sgml">
diff --git a/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
new file mode 100644
index 0000000000..487eec47e1
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
@@ -0,0 +1,184 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="685" viewBox="0 0 900 685">
+ <title>
+ Server (Hardware, Container, or VM)
+ </title>
+ <style>
+ .text_normal,.text_small{font-style:normal;font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_small{font-size:12px}.text_normal{font-size:14px}
+ </style>
+ <defs>
+ <symbol id="rectangle_special_0">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="rectangle_special_1">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="25" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ System schemas
+ </text>
+ </symbol>
+ <symbol id="rectangle_special_2">
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="25" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ System schemas
+ </text>
+ <rect x="15" y="150" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="170">
+ 'my_schema' (optional)
+ </text>
+ <text class="text_small" x="25" y="185">
+ tables, views, ...
+ </text>
+ </symbol>
+ <symbol id="note_0" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M190 10v70H0V0h180v10h10L180 0"/>
+ </symbol>
+ <symbol id="note_1" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M450 10v240H0V0h440v10h10L440 0"/>
+ </symbol>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="270" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Server (Hardware, Container, or VM)
+ </text>
+ <path stroke="blue" stroke-width="2" fill="none" d="M20 110h790v555H20z"/>
+ <text class="text_normal" x="180" y="25" transform="translate(20 110)">
+ cluster 'data' (default, managed by one instance)
+ </text>
+ <path d="M50 110V80h790v555h-30" stroke="blue" stroke-width="2" fill="none"/>
+ <text class="text_normal" x="190" y="-10" transform="translate(45 110)">
+ cluster 'cluster_2' (optional, managed by a different instance)
+ </text>
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template0'
+ </text>
+ <use xlink:href="#note_0" x="20" y="40"/>
+ <text class="text_small" x="30" y="60">
+ 'template0' is a pristine
+ </text>
+ <text class="text_small" x="30" y="75">
+ and unchangeable template.
+ </text>
+ <text class="text_small" x="30" y="90">
+ It is used to generate
+ </text>
+ <text class="text_small" x="30" y="105">
+ database 'template1'.
+ </text>
+ </g>
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template1'
+ </text>
+ </g>
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_2"/>
+ <text class="text_normal" x="10" y="25">
+ database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_2"/>
+ <text class="text_normal" x="10" y="25">
+ database 'my_db' (optional)
+ </text>
+ </g>
+ <g transform="translate(320 330)">
+ <rect width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4"/>
+ <text class="text_normal" x="15" y="27">
+ Global SQL objects
+ </text>
+ <path d="M80 0v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M180 40h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M0 40l-45 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ </g>
+ <g transform="translate(335 405)">
+ <use xlink:href="#note_1"/>
+ <text class="text_small" x="10" y="20">
+ 1)
+ </text>
+ <text class="text_small" x="30" y="20">
+ By default, clients connect via port '5432' to Cluster 'data',
+ </text>
+ <text class="text_small" x="30" y="35">
+ database 'postgres', schema 'public'. Of course, they can
+ </text>
+ <text class="text_small" x="30" y="50">
+ specify other connection properties.
+ </text>
+ <text class="text_small" x="10" y="70">
+ 2)
+ </text>
+ <text class="text_small" x="30" y="70">
+ System schemas: pg_catalog, information_schema,
+ </text>
+ <text class="text_small" x="30" y="85">
+ pg_temp, ...
+ </text>
+ <text class="text_small" x="10" y="105">
+ 3)
+ </text>
+ <text class="text_small" x="30" y="105">
+ Global SQL objects: Objects which are shared among all
+ </text>
+ <text class="text_small" x="30" y="120">
+ databases within a Cluster.
+ </text>
+ <text class="text_small" x="10" y="140">
+ 4)
+ </text>
+ <text class="text_small" x="30" y="140">
+ The command 'initdb' creates a new cluster with the three
+ </text>
+ <text class="text_small" x="30" y="155">
+ databases 'template0', 'template1', and 'postgres'. The command
+ </text>
+ <text class="text_small" x="30" y="170">
+ 'createdb' creates a new database.
+ </text>
+ <text class="text_small" x="10" y="190">
+ 5)
+ </text>
+ <text class="text_small" x="30" y="190">
+ If multiple clusters are active on one server at the same time,
+ </text>
+ <text class="text_small" x="30" y="205">
+ each one is managed by an individual instance. Each such instance
+ </text>
+ <text class="text_small" x="30" y="220">
+ uses a different port.
+ </text>
+ <text class="text_small" x="10" y="240">
+ 6)
+ </text>
+ <text class="text_small" x="30" y="240">
+ Client application are prohibited from connecting to 'template0'.
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink.svg b/doc/src/sgml/images/cluster-db-schema-ink.svg
new file mode 100644
index 0000000000..05623a4092
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink.svg
@@ -0,0 +1,528 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="685px"
+ viewBox="0 0 900 685"
+ id="svg165"
+ sodipodi:docname="cluster-db-schema-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata169">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Server (Hardware, Container, or VM)</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="780"
+ inkscape:window-height="480"
+ id="namedview167"
+ showgrid="false"
+ inkscape:zoom="0.34452555"
+ inkscape:cx="450"
+ inkscape:cy="342.5"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg165" />
+ <title
+ id="title2">Server (Hardware, Container, or VM)</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs57">
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangle_special_0">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect6" />
+ </symbol>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangle_special_1">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect9" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="195"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect11" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text13">schema 'public'</text>
+ <text
+ class="text_small"
+ x="25"
+ y="80"
+ id="text15">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="195"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect17" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text19">System schemas</text>
+ </symbol>
+ <!-- same as before, but one more schema -->
+ <symbol
+ id="rectangle_special_2">
+ <!-- the database -->
+ <rect
+ width="245"
+ height="225"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect22" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect24" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text26">schema 'public'</text>
+ <text
+ class="text_small"
+ x="25"
+ y="80"
+ id="text28">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="205"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect30" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text32">System schemas</text>
+ <rect
+ x="15"
+ y="150"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect34" />
+ <text
+ class="text_normal"
+ x="20"
+ y="170"
+ id="text36">'my_schema' (optional)</text>
+ <text
+ class="text_small"
+ x="25"
+ y="185"
+ id="text38">tables, views, ...</text>
+ </symbol>
+ <symbol
+ id="note_0"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title41">UML Note</title>
+ <path
+ d="M 190,10 v 70 h -190 v -80 h 180 v 10 h 10 l -10,-10"
+ id="path43" />
+ </symbol>
+ <symbol
+ id="note_1"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title46">UML Note</title>
+ <path
+ d="M 450,10 v 240 h -450 v -250 h 440 v 10 h 10 l -10,-10"
+ id="path48" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path51" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path54" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect59" />
+ <text
+ class="text_big"
+ x="270"
+ y="40"
+ id="text61">Server (Hardware, Container, or VM)</text>
+ <!-- two clusters -->
+ <g
+ transform="translate(20 110)"
+ id="g67">
+ <rect
+ x="0"
+ y="0"
+ width="790"
+ height="555"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="rect63" />
+ <text
+ class="text_normal"
+ x="180"
+ y="25"
+ id="text65">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g
+ transform="translate(45 110)"
+ id="g73">
+ <path
+ d="M 5,0 v -30 h 790 v 555 h -30"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="path69" />
+ <text
+ class="text_normal"
+ x="190"
+ y="-10"
+ id="text71">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+ <!-- database template 0 -->
+ <g
+ transform="translate(40 155)"
+ id="g89">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use75" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text77">database 'template0'</text>
+ <use
+ xlink:href="#note_0"
+ x="20"
+ y="40"
+ id="use79" />
+ <text
+ class="text_small"
+ x="30"
+ y="60"
+ id="text81">'template0' is a pristine</text>
+ <text
+ class="text_small"
+ x="30"
+ y="75"
+ id="text83">and unchangeable template.</text>
+ <text
+ class="text_small"
+ x="30"
+ y="90"
+ id="text85">It is used to generate</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text87">database 'template1'.</text>
+ </g>
+ <!-- database template 1 -->
+ <g
+ transform="translate(290 155)"
+ id="g95">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use91" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text93">database 'template1'</text>
+ </g>
+ <!-- database postgres -->
+ <g
+ transform="translate(540 155)"
+ id="g101">
+ <use
+ xlink:href="#rectangle_special_2"
+ id="use97" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text99">database 'postgres'</text>
+ </g>
+ <!-- database my_db -->
+ <g
+ transform="translate(40 350)"
+ id="g107">
+ <use
+ xlink:href="#rectangle_special_2"
+ id="use103" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text105">database 'my_db' (optional)</text>
+ </g>
+ <!-- global objects -->
+ <g
+ transform="translate(320 330)"
+ id="g119">
+ <rect
+ x="0"
+ y="0"
+ width="180"
+ height="45"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="10 4 4 4"
+ id="rect109" />
+ <text
+ class="text_normal"
+ x="15"
+ y="27"
+ id="text111">Global SQL objects</text>
+ <path
+ d="M 80,0 v-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path113" />
+ <path
+ d="M 180,40 h50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path115" />
+ <path
+ d="M 0,40 l-45,20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path117" />
+ </g>
+ <!-- Some comments -->
+ <g
+ transform="translate(335 405)"
+ id="g163">
+ <use
+ xlink:href="#note_1"
+ x="0"
+ y="0"
+ id="use121" />
+ <text
+ class="text_small"
+ x="10"
+ y="20"
+ id="text123">1)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="20"
+ id="text125">By default, clients connect via port '5432' to Cluster 'data',</text>
+ <text
+ class="text_small"
+ x="30"
+ y="35"
+ id="text127">database 'postgres', schema 'public'. Of course, they can</text>
+ <text
+ class="text_small"
+ x="30"
+ y="50"
+ id="text129">specify other connection properties.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="70"
+ id="text131">2)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="70"
+ id="text133">System schemas: pg_catalog, information_schema,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="85"
+ id="text135">pg_temp, ...</text>
+ <text
+ class="text_small"
+ x="10"
+ y="105"
+ id="text137">3)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text139">Global SQL objects: Objects which are shared among all</text>
+ <text
+ class="text_small"
+ x="30"
+ y="120"
+ id="text141">databases within a Cluster.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="140"
+ id="text143">4)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="140"
+ id="text145">The command 'initdb' creates a new cluster with the three</text>
+ <text
+ class="text_small"
+ x="30"
+ y="155"
+ id="text147">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text
+ class="text_small"
+ x="30"
+ y="170"
+ id="text149">'createdb' creates a new database.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="190"
+ id="text151">5)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="190"
+ id="text153">If multiple clusters are active on one server at the same time,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="205"
+ id="text155">each one is managed by an individual instance. Each such instance</text>
+ <text
+ class="text_small"
+ x="30"
+ y="220"
+ id="text157">uses a different port.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="240"
+ id="text159">6)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="240"
+ id="text161">Client application are prohibited from connecting to 'template0'.</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
new file mode 100644
index 0000000000..8534b18ec2
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="685px"
+ viewBox="0 0 900 685" >
+
+ <title>Server (Hardware, Container, or VM)</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_0">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ </symbol>
+
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_1">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="25" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">System schemas</text>
+ </symbol>
+
+ <!-- same as before, but one more schema -->
+ <symbol id="rectangle_special_2">
+ <!-- the database -->
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="25" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">System schemas</text>
+
+ <rect x="15" y="150" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="170">'my_schema' (optional)</text>
+ <text class="text_small" x="25" y="185">tables, views, ...</text>
+ </symbol>
+
+ <symbol id="note_0" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 190,10 v 70 h -190 v -80 h 180 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <symbol id="note_1" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 240 h -450 v -250 h 440 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="270" y="40">Server (Hardware, Container, or VM)</text>
+
+ <!-- two clusters -->
+ <g transform="translate(20 110)">
+ <rect x="0" y="0" width="790" height="555" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="180" y="25">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g transform="translate(45 110)">
+ <path d="M 5,0 v -30 h 790 v 555 h -30" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="190" y="-10">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+
+
+ <!-- database template 0 -->
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template0'</text>
+ <use xlink:href="#note_0" x="20" y="40" />
+ <text class="text_small" x="30" y="60">'template0' is a pristine</text>
+ <text class="text_small" x="30" y="75">and unchangeable template.</text>
+ <text class="text_small" x="30" y="90">It is used to generate</text>
+ <text class="text_small" x="30" y="105">database 'template1'.</text>
+ </g>
+
+ <!-- database template 1 -->
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'template1'</text>
+ </g>
+
+ <!-- database postgres -->
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_2" />
+ <text class="text_normal" x="10" y="25">database 'postgres'</text>
+ </g>
+
+ <!-- database my_db -->
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_2" />
+ <text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
+ </g>
+
+ <!-- global objects -->
+ <g transform="translate(320 330)">
+ <rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
+ <text class="text_normal" x="15" y="27">Global SQL objects</text>
+ <path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ </g>
+
+ <!-- Some comments -->
+ <g transform="translate(335 405)">
+ <use xlink:href="#note_1" x="0" y="0" />
+
+ <text class="text_small" x="10" y="20">1)</text>
+ <text class="text_small" x="30" y="20">By default, clients connect via port '5432' to Cluster 'data',</text>
+ <text class="text_small" x="30" y="35">database 'postgres', schema 'public'. Of course, they can</text>
+ <text class="text_small" x="30" y="50">specify other connection properties.</text>
+
+ <text class="text_small" x="10" y="70">2)</text>
+ <text class="text_small" x="30" y="70">System schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="85">pg_temp, ...</text>
+
+ <text class="text_small" x="10" y="105">3)</text>
+ <text class="text_small" x="30" y="105">Global SQL objects: Objects which are shared among all</text>
+ <text class="text_small" x="30" y="120">databases within a Cluster.</text>
+
+ <text class="text_small" x="10" y="140">4)</text>
+ <text class="text_small" x="30" y="140">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="155">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="170">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="190">5)</text>
+ <text class="text_small" x="30" y="190">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="205">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="220">uses a different port.</text>
+
+ <text class="text_small" x="10" y="240">6)</text>
+ <text class="text_small" x="30" y="240">Client application are prohibited from connecting to 'template0'.</text>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/directories-ink-svgo.svg b/doc/src/sgml/images/directories-ink-svgo.svg
new file mode 100644
index 0000000000..a59198c66f
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink-svgo.svg
@@ -0,0 +1,164 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="640" viewBox="0 0 900 640">
+ <title>
+ Directory structure of a cluster
+ </title>
+ <style>
+ .text_italic,.text_normal{font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif}.text_normal{font-style:normal;fill:#000}.text_italic{font-style:italic;fill:silver}
+ </style>
+ <defs>
+ <symbol id="directory" stroke="blue" stroke-width=".3" fill="aqua">
+ <title>
+ Directory
+ </title>
+ <path d="M0 10h110v20H0z"/>
+ <path d="M0 10V8l3-3h35l3 3v2"/>
+ </symbol>
+ <symbol id="file" stroke="black" fill="none">
+ <title>
+ File
+ </title>
+ <path stroke="blue" d="M0 0h40v50H0z"/>
+ <path d="M5 10h20" stroke-dasharray="4 2"/>
+ <path d="M5 17h15" stroke-dasharray="6 2"/>
+ <path d="M5 24h25" stroke-dasharray="4 2"/>
+ <path d="M5 31h20" stroke-dasharray="5 2"/>
+ </symbol>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="50" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Directory Structure
+ </text>
+ <g transform="translate(20 100)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_italic">
+ /var/lib/pgsql/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ An arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 130)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_italic">
+ data/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Cluster's root directory (with an arbitrary name; see: PGDATA)
+ </text>
+ </g>
+ <g transform="translate(120 160)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ base/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing per-database subdirectories
+ </text>
+ </g>
+ <g transform="translate(170 190)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 1/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data in default-tablespace of first database 'template0'
+ </text>
+ </g>
+ <g transform="translate(170 220)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12992/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data in default-tablespace of second database 'template1'
+ </text>
+ </g>
+ <g transform="translate(170 250)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12999/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data in default-tablespace of third database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(170 280)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ nnnnn/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Optional: one subdirectory for each new database, e.g. '23456' for 'my_db'
+ </text>
+ </g>
+ <g transform="translate(120 310)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ global/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for information about Global SQL Objects
+ </text>
+ </g>
+ <g transform="translate(120 340)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_tblspc/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for symbolic links to non-default tablespaces
+ </text>
+ </g>
+ <g transform="translate(120 370)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_wal/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 400)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_xact/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for transaction commit status ('pg_clog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 430)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_... /
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Some more subdirectories
+ </text>
+ </g>
+ <g transform="translate(120 465)">
+ <use xlink:href="#file"/>
+ <use xlink:href="#file" x="50"/>
+ <text x="200" y="26" class="text_normal">
+ 'postmaster.pid' and other files with cluster-wide relevance
+ </text>
+ </g>
+ <g transform="translate(20 540)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_italic">
+ ...
+ </text>
+ <text x="300" y="26" class="text_normal">
+ Same or another arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 570)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_italic">
+ cluster_2/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of another cluster
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-ink.svg b/doc/src/sgml/images/directories-ink.svg
new file mode 100644
index 0000000000..615a6d214a
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink.svg
@@ -0,0 +1,403 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="640px"
+ viewBox="0 0 900 640"
+ id="svg329"
+ sodipodi:docname="directories-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata333">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Directory structure of a cluster</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1106"
+ inkscape:window-height="813"
+ id="namedview331"
+ showgrid="false"
+ inkscape:zoom="0.36875"
+ inkscape:cx="450"
+ inkscape:cy="311.86441"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg329" />
+ <title
+ id="title179">Directory structure of a cluster</title>
+ <style
+ type="text/css"
+ id="style181">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_italic {font-style:italic;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:silver;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs203">
+ <!-- Directory -->
+ <symbol
+ id="directory"
+ stroke="blue"
+ stroke-width="0.3px"
+ fill="aqua">
+ <title
+ id="title183">Directory</title>
+ <rect
+ x="0"
+ y="10"
+ width="110"
+ height="20"
+ id="rect185" />
+ <path
+ d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2"
+ id="path187" />
+ </symbol>
+ <!-- File -->
+ <symbol
+ id="file"
+ stroke="black"
+ fill="none">
+ <title
+ id="title190">File</title>
+ <rect
+ x="0"
+ y="0"
+ width="40"
+ height="50"
+ stroke="blue"
+ id="rect192" />
+ <path
+ d="M 5,10 h 20"
+ stroke-dasharray="4 2"
+ id="path194" />
+ <path
+ d="M 5,17 h 15"
+ stroke-dasharray="6 2"
+ id="path196" />
+ <path
+ d="M 5,24 h 25"
+ stroke-dasharray="4 2"
+ id="path198" />
+ <path
+ d="M 5,31 h 20"
+ stroke-dasharray="5 2"
+ id="path200" />
+ </symbol>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect205" />
+ <!-- caption -->
+ <text
+ x="200"
+ y="50"
+ class="text_big"
+ id="text207">Directory Structure</text>
+ <!-- the directories -->
+ <g
+ transform="translate(20, 100)"
+ id="g215">
+ <use
+ xlink:href="#directory"
+ id="use209" />
+ <text
+ x="10"
+ y="26"
+ class="text_italic"
+ id="text211">/var/lib/pgsql/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text213">An arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 130)"
+ id="g223">
+ <use
+ xlink:href="#directory"
+ id="use217" />
+ <text
+ x="10"
+ y="26"
+ class="text_italic"
+ id="text219">data/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text221">Cluster's root directory (with an arbitrary name; see: PGDATA)</text>
+ </g>
+ <g
+ transform="translate(120, 160)"
+ id="g231">
+ <use
+ xlink:href="#directory"
+ id="use225" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text227">base/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text229">Subdirectory containing per-database subdirectories</text>
+ </g>
+ <!-- -->
+ <g
+ transform="translate(170, 190)"
+ id="g239">
+ <use
+ xlink:href="#directory"
+ id="use233" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text235">1/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text237">Subdirectory for data in default-tablespace of first database 'template0'</text>
+ </g>
+ <g
+ transform="translate(170, 220)"
+ id="g247">
+ <use
+ xlink:href="#directory"
+ id="use241" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text243">12992/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text245">Subdirectory for data in default-tablespace of second database 'template1'</text>
+ </g>
+ <g
+ transform="translate(170, 250)"
+ id="g255">
+ <use
+ xlink:href="#directory"
+ id="use249" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text251">12999/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text253">Subdirectory for data in default-tablespace of third database 'postgres'</text>
+ </g>
+ <g
+ transform="translate(170, 280)"
+ id="g263">
+ <use
+ xlink:href="#directory"
+ id="use257" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text259">nnnnn/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text261">Optional: one subdirectory for each new database, e.g. '23456' for 'my_db'</text>
+ </g>
+ <g
+ transform="translate(120, 310)"
+ id="g271">
+ <use
+ xlink:href="#directory"
+ id="use265" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text267">global/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text269">Subdirectory for information about Global SQL Objects</text>
+ </g>
+ <g
+ transform="translate(120, 340)"
+ id="g279">
+ <use
+ xlink:href="#directory"
+ id="use273" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text275">pg_tblspc/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text277">Subdirectory for symbolic links to non-default tablespaces</text>
+ </g>
+ <g
+ transform="translate(120, 370)"
+ id="g287">
+ <use
+ xlink:href="#directory"
+ id="use281" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text283">pg_wal/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text285">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 400)"
+ id="g295">
+ <use
+ xlink:href="#directory"
+ id="use289" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text291">pg_xact/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text293">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 430)"
+ id="g303">
+ <use
+ xlink:href="#directory"
+ id="use297" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text299">pg_... /</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text301">Some more subdirectories</text>
+ </g>
+ <g
+ transform="translate(120, 465)"
+ id="g311">
+ <use
+ xlink:href="#file"
+ x="0"
+ y="0"
+ id="use305" />
+ <use
+ xlink:href="#file"
+ x="50"
+ y="0"
+ id="use307" />
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text309">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+ <!-- next cluster -->
+ <g
+ transform="translate(20, 540)"
+ id="g319">
+ <use
+ xlink:href="#directory"
+ id="use313" />
+ <text
+ x="10"
+ y="26"
+ class="text_italic"
+ id="text315">...</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text317">Same or another arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 570)"
+ id="g327">
+ <use
+ xlink:href="#directory"
+ id="use321" />
+ <text
+ x="10"
+ y="26"
+ class="text_italic"
+ id="text323">cluster_2/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text325">Root of another cluster</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
new file mode 100644
index 0000000000..5cce551b0c
--- /dev/null
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="640px"
+ viewBox="0 0 900 640">
+
+ <title>Directory structure of a cluster</title>
+
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_italic {font-style:italic;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:silver;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Directory -->
+ <symbol id="directory" stroke="blue" stroke-width="0.3px" fill="aqua">
+ <title>Directory</title>
+ <rect x="0" y="10" width="110" height="20" />
+ <path d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2" />
+ </symbol>
+
+ <!-- File -->
+ <symbol id="file" stroke="black" fill="none" >
+ <title>File</title>
+ <rect x="0" y="0" width="40" height="50" stroke="blue" />
+ <path d="M 5,10 h 20" stroke-dasharray="4 2" />
+ <path d="M 5,17 h 15" stroke-dasharray="6 2" />
+ <path d="M 5,24 h 25" stroke-dasharray="4 2" />
+ <path d="M 5,31 h 20" stroke-dasharray="5 2" />
+ </symbol>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption -->
+ <text x="200" y="50" class="text_big">Directory Structure</text>
+
+ <!-- the directories -->
+ <g transform="translate(20, 100)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_italic">/var/lib/pgsql/</text>
+ <text x="300" y="26" class="text_normal">An arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 130)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_italic">data/</text>
+ <text x="250" y="26" class="text_normal">Cluster's root directory (with an arbitrary name; see: PGDATA)</text>
+ </g>
+
+ <g transform="translate(120, 160)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">base/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing per-database subdirectories</text>
+ </g>
+
+ <!-- -->
+ <g transform="translate(170, 190)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">1/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data in default-tablespace of first database 'template0'</text>
+ </g>
+ <g transform="translate(170, 220)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12992/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data in default-tablespace of second database 'template1'</text>
+ </g>
+ <g transform="translate(170, 250)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12999/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data in default-tablespace of third database 'postgres'</text>
+ </g>
+ <g transform="translate(170, 280)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">nnnnn/</text>
+ <text x="150" y="26" class="text_normal">Optional: one subdirectory for each new database, e.g. '23456' for 'my_db'</text>
+ </g>
+
+ <g transform="translate(120, 310)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">global/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for information about Global SQL Objects</text>
+ </g>
+
+ <g transform="translate(120, 340)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for symbolic links to non-default tablespaces</text>
+ </g>
+
+ <g transform="translate(120, 370)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 400)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 430)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_... /</text>
+ <text x="200" y="26" class="text_normal">Some more subdirectories</text>
+ </g>
+
+ <g transform="translate(120, 465)">
+ <use xlink:href="#file" x="0" y="0" />
+ <use xlink:href="#file" x="50" y="0" />
+ <text x="200" y="26" class="text_normal">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+
+ <!-- next cluster -->
+ <g transform="translate(20, 540)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_italic">...</text>
+ <text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 570)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_italic">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink-svgo.svg b/doc/src/sgml/images/freeze-ink-svgo.svg
new file mode 100644
index 0000000000..b1543ffae5
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink-svgo.svg
@@ -0,0 +1,84 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="320" viewBox="0 0 850 320">
+ <title>
+ Freeze
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100)"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="70" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ <tspan font-style="italic" font-weight="700">Freeze</tspan> to keep visible
+ </text>
+ <g fill="none" transform="translate(170 190)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_120" startOffset="11.2%">(1)</textPath> <textPath xlink:href="#Path_120" startOffset="61.2%">(5)</textPath> <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%">|</textPath> <textPath xlink:href="#Path_120" startOffset="34%">(2)</textPath> <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(3)</textPath> <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%">|</textPath> <textPath xlink:href="#Path_120" startOffset="55%">(4)</textPath>
+ </text>
+ <path d="M-80-80L80 80" stroke="black"/>
+ <text class="text_normal" letter-spacing="12" transform="rotate(45 40.78 -38.1)">
+ PAST
+ </text>
+ <text class="text_normal" letter-spacing="12" transform="rotate(-135 27.43 23.79)">
+ FUTURE
+ </text>
+ <use xlink:href="#frozenPoint" transform="rotate(10)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(25)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(40)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(55)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(70)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(85)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(100)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(115)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(130)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(145)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(160)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(175)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(190)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(205)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(220)"/>
+ </g>
+ <g class="text_normal" transform="translate(380 30)">
+ <text>
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25">
+ 1: txid_current + 2 ^ 31 (split-point)
+ </text>
+ <text y="50">
+ 2: autovacuum_freeze_max_age (200 mio.)
+ </text>
+ <text y="75">
+ 3: vacuum_freeze_table_age (150 mio.)
+ </text>
+ <text y="100">
+ 4: vacuum_freeze_min_age (50 mio.)
+ </text>
+ <text y="125">
+ 5: txid_current (split-point, youngest xid)
+ </text>
+ <text y="155">
+ per table: pg_class.relfrozenxid <tspan font-weight="700">must</tspan> be between (1) and (5);
+ </text>
+ <text y="175" x="75">
+ normally it is between (3) and (4)
+ </text>
+ <use xlink:href="#unfrozenPoint" transform="translate(106 200)"/>
+ <text y="205" x="20">
+ Unfrozen xid
+ </text>
+ <use xlink:href="#frozenPoint" transform="translate(106 224)"/>
+ <text y="230" x="20">
+ Frozen xid
+ </text>
+ <text y="260">
+ (figure is out of scale)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink.svg b/doc/src/sgml/images/freeze-ink.svg
new file mode 100644
index 0000000000..316703d069
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink.svg
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="320px"
+ viewBox="0 0 850 320"
+ id="svg147"
+ sodipodi:docname="freeze-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Freeze</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1295"
+ inkscape:window-height="803"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="153.18182"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Freeze</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs11">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle
+ id="frozenPoint"
+ r="3"
+ stroke="green"
+ fill="green"
+ transform="translate(-100, 0)" />
+ <circle
+ id="unfrozenPoint"
+ r="3"
+ stroke="green"
+ fill="none"
+ transform="translate(-100, 0)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect13" />
+ <text
+ class="text_big"
+ x="70"
+ y="40"
+ id="text17"><tspan
+ style="font-style:italic;font-weight:bold"
+ id="tspan15">
+ Freeze</tspan>
+ to keep visible</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 190)"
+ id="g111">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle19" />
+ <text
+ class="text_normal"
+ id="text43">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath21">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath23">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath25">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="11.2%"
+ id="textPath27">(1)</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="61.2%"
+ id="textPath29">(5)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="red"
+ stroke-width="3"
+ startOffset="34%"
+ id="textPath31">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="34%"
+ id="textPath33">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="black"
+ stroke-width="3"
+ startOffset="45%"
+ id="textPath35">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath37">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="green"
+ stroke-width="3"
+ startOffset="55%"
+ id="textPath39">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="55%"
+ id="textPath41">(4)</textPath>
+ </text>
+ <!-- split it into 'past' and 'future' -->
+ <path
+ d="M -80 -80 l 160 160"
+ stroke="black"
+ id="path45" />
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(-15, -40) rotate(45)"
+ id="text47">PAST</text>
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(30, 60) rotate(225)"
+ id="text49">FUTURE</text>
+ <g
+ transform="rotate(10)"
+ id="g53">
+ <use
+ xlink:href="#frozenPoint"
+ id="use51" />
+ </g>
+ <g
+ transform="rotate(25)"
+ id="g57">
+ <use
+ xlink:href="#frozenPoint"
+ id="use55" />
+ </g>
+ <g
+ transform="rotate(40)"
+ id="g61">
+ <use
+ xlink:href="#frozenPoint"
+ id="use59" />
+ </g>
+ <g
+ transform="rotate(55)"
+ id="g65">
+ <use
+ xlink:href="#frozenPoint"
+ id="use63" />
+ </g>
+ <g
+ transform="rotate(70)"
+ id="g69">
+ <use
+ xlink:href="#frozenPoint"
+ id="use67" />
+ </g>
+ <g
+ transform="rotate(85)"
+ id="g73">
+ <use
+ xlink:href="#frozenPoint"
+ id="use71" />
+ </g>
+ <g
+ transform="rotate(100)"
+ id="g77">
+ <use
+ xlink:href="#frozenPoint"
+ id="use75" />
+ </g>
+ <g
+ transform="rotate(115)"
+ id="g81">
+ <use
+ xlink:href="#frozenPoint"
+ id="use79" />
+ </g>
+ <g
+ transform="rotate(130)"
+ id="g85">
+ <use
+ xlink:href="#frozenPoint"
+ id="use83" />
+ </g>
+ <g
+ transform="rotate(145)"
+ id="g89">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use87" />
+ </g>
+ <g
+ transform="rotate(160)"
+ id="g93">
+ <use
+ xlink:href="#frozenPoint"
+ id="use91" />
+ </g>
+ <g
+ transform="rotate(175)"
+ id="g97">
+ <use
+ xlink:href="#frozenPoint"
+ id="use95" />
+ </g>
+ <g
+ transform="rotate(190)"
+ id="g101">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use99" />
+ </g>
+ <g
+ transform="rotate(205)"
+ id="g105">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use103" />
+ </g>
+ <g
+ transform="rotate(220)"
+ id="g109">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use107" />
+ </g>
+ </g>
+ <!-- legend -->
+ <g
+ class="text_normal"
+ transform="translate(380 30)"
+ id="g145">
+ <text
+ id="text117">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan113">^</tspan>
+<tspan
+ dy="5"
+ id="tspan115">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text119">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text
+ y="50"
+ id="text121">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text
+ y="75"
+ id="text123">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text
+ y="100"
+ id="text125">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text
+ y="125"
+ id="text127">5: txid_current (split-point, youngest xid)</text>
+ <text
+ y="155"
+ id="text131">per table: pg_class.relfrozenxid
+ <tspan
+ style="font-weight:bold"
+ id="tspan129">must</tspan>
+ be between (1) and (5);</text>
+ <text
+ y="175"
+ x="75"
+ id="text133">normally it is between (3) and (4)</text>
+ <use
+ xlink:href="#unfrozenPoint"
+ transform="translate(106, 200)"
+ id="use135" />
+ <text
+ y="205"
+ x="20"
+ id="text137">Unfrozen xid</text>
+ <use
+ xlink:href="#frozenPoint"
+ transform="translate(106, 224)"
+ id="use139" />
+ <text
+ y="230"
+ x="20"
+ id="text141">Frozen xid</text>
+ <text
+ y="260"
+ id="text143">(figure is out of scale)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-raw.svg b/doc/src/sgml/images/freeze-raw.svg
new file mode 100644
index 0000000000..9482167c3f
--- /dev/null
+++ b/doc/src/sgml/images/freeze-raw.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="320px"
+ viewBox="0 0 850 320" >
+
+ <title>Freeze</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100, 0)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100, 0)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="70" y="40"><tspan style="font-style:italic;font-weight:bold">
+ Freeze</tspan> to keep visible</text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 190)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_120" startOffset="11.2%" >(1)</textPath>
+ <textPath xlink:href="#Path_120" startOffset="61.2%" >(5)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="34%" >(2)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(3)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="55%" >(4)</textPath>
+
+ </text>
+
+ <!-- split it into 'past' and 'future' -->
+ <path d="M -80 -80 l 160 160" stroke="black" />
+ <text class="text_normal" letter-spacing="12" transform="translate(-15, -40) rotate(45)">PAST</text>
+ <text class="text_normal" letter-spacing="12" transform="translate(30, 60) rotate(225)">FUTURE</text>
+
+ <g transform="rotate(10)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(25)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(40)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(55)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(70)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(85)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(100)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(115)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(130)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(145)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(160)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(175)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(190)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(205)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(220)"><use xlink:href="#unfrozenPoint"/></g>
+
+ </g>
+
+ <!-- legend -->
+ <g class="text_normal" transform="translate(380 30)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text y="50">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text y="75">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text y="100">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text y="125">5: txid_current (split-point, youngest xid)</text>
+ <text y="155">per table: pg_class.relfrozenxid
+ <tspan style="font-weight:bold">must</tspan> be between (1) and (5);</text>
+ <text y="175" x="75">normally it is between (3) and (4)</text>
+
+ <use xlink:href="#unfrozenPoint" transform="translate(106, 200)"/>
+ <text y="205" x="20">Unfrozen xid</text>
+
+ <use xlink:href="#frozenPoint" transform="translate(106, 224)"/>
+ <text y="230" x="20">Frozen xid</text>
+
+ <text y="260">(figure is out of scale)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
new file mode 100644
index 0000000000..e353ce4d87
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
@@ -0,0 +1,83 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="720" height="430" viewBox="0 0 720 430">
+ <title>
+ Hierarchy of Internal Objects
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Hierarchy of Internal Objects
+ </text>
+ <g fill="none">
+ <g transform="translate(350 240)">
+ <ellipse rx="320" ry="170" stroke="blue"/>
+ <text class="text_normal" x="-140" y="-130">
+ Cluster
+ </text>
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-60" y="5">
+ Database Names
+ </text>
+ </g>
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-40" y="5">
+ Tablespace
+ </text>
+ </g>
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-70" y="5">
+ Replication Origins
+ </text>
+ </g>
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue"/>
+ <text class="text_normal" x="-60" y="-3">
+ Subscription for
+ </text>
+ <text class="text_normal" x="-68" y="10">
+ Logical Replication
+ </text>
+ </g>
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-15" y="5">
+ Role
+ </text>
+ </g>
+ </g>
+ <g transform="translate(270 250)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2"/>
+ <text class="text_normal" x="-60" y="-80">
+ Database
+ </text>
+ <g transform="translate(-150 -30)">
+ <ellipse rx="50" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Extension
+ </text>
+ </g>
+ <g transform="translate(-155 35)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Collation
+ </text>
+ </g>
+ <g transform="translate(30 20)">
+ <ellipse rx="140" ry="70" stroke="blue"/>
+ <text class="text_normal" x="-80" y="-35">
+ Schema
+ </text>
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue"/>
+ <text class="text_normal" x="-50" y="5">
+ Table, View, ...
+ </text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
new file mode 100644
index 0000000000..3429266782
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="720px"
+ height="430px"
+ viewBox="0 0 720 430"
+ id="svg82"
+ sodipodi:docname="internal-objects-hierarchy-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata88">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Hierarchy of Internal Objects</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs86" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="919"
+ inkscape:window-height="528"
+ id="namedview84"
+ showgrid="false"
+ inkscape:zoom="0.51944444"
+ inkscape:cx="360"
+ inkscape:cy="215"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg82" />
+ <title
+ id="title2">Hierarchy of Internal Objects</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect6" />
+ <text
+ class="text_big"
+ x="200"
+ y="40"
+ id="text8">Hierarchy of Internal Objects</text>
+ <!-- set centre of figure and default values -->
+ <g
+ transform="translate(350 240)"
+ fill="none"
+ id="g80">
+ <g
+ id="g46">
+ <ellipse
+ rx="320"
+ ry="170"
+ stroke="blue"
+ id="ellipse10" />
+ <text
+ class="text_normal"
+ x="-140"
+ y="-130"
+ id="text12">Cluster</text>
+ <g
+ transform="translate(40 -125)"
+ id="g18">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse14" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="5"
+ id="text16">Database Names</text>
+ </g>
+ <g
+ transform="translate(180 -70)"
+ id="g24">
+ <ellipse
+ rx="60"
+ ry="20"
+ stroke="blue"
+ id="ellipse20" />
+ <text
+ class="text_normal"
+ x="-40"
+ y="5"
+ id="text22">Tablespace</text>
+ </g>
+ <g
+ transform="translate(230 -5)"
+ id="g30">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse26" />
+ <text
+ class="text_normal"
+ x="-70"
+ y="5"
+ id="text28">Replication Origins</text>
+ </g>
+ <g
+ transform="translate(200 70)"
+ id="g38">
+ <ellipse
+ rx="78"
+ ry="27"
+ stroke="blue"
+ id="ellipse32" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-3"
+ id="text34">Subscription for</text>
+ <text
+ class="text_normal"
+ x="-68"
+ y="10"
+ id="text36">Logical Replication</text>
+ </g>
+ <g
+ transform="translate(100 120)"
+ id="g44">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse40" />
+ <text
+ class="text_normal"
+ x="-15"
+ y="5"
+ id="text42">Role</text>
+ </g>
+ </g>
+ <g
+ transform="translate(-80 10)"
+ id="g78">
+ <ellipse
+ rx="220"
+ ry="110"
+ stroke="blue"
+ stroke-width="2px"
+ id="ellipse48" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-80"
+ id="text50">Database</text>
+ <g
+ transform="translate(-120 -50)"
+ id="g76">
+ <g
+ transform="translate(-30 20)"
+ id="g56">
+ <ellipse
+ rx="50"
+ ry="20"
+ stroke="blue"
+ id="ellipse52" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text54">Extension</text>
+ </g>
+ <g
+ transform="translate(-35 85)"
+ id="g62">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse58" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text60">Collation</text>
+ </g>
+ <g
+ transform="translate(150 70)"
+ id="g74">
+ <ellipse
+ rx="140"
+ ry="70"
+ stroke="blue"
+ id="ellipse64" />
+ <text
+ class="text_normal"
+ x="-80"
+ y="-35"
+ id="text66">Schema</text>
+ <g
+ transform="translate(20 10)"
+ id="g72">
+ <ellipse
+ rx="90"
+ ry="30"
+ stroke="blue"
+ id="ellipse68" />
+ <text
+ class="text_normal"
+ x="-50"
+ y="5"
+ id="text70">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
new file mode 100644
index 0000000000..78850283d9
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="720px" height="430px"
+ viewBox="0 0 720 430" >
+
+ <title>Hierarchy of Internal Objects</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="200" y="40">Hierarchy of Internal Objects</text>
+
+
+ <!-- set centre of figure and default values -->
+ <g transform="translate(350 240)" fill="none">
+
+ <g>
+ <ellipse rx="320" ry="170" stroke="blue" />
+ <text class="text_normal" x="-140" y="-130">Cluster</text>
+
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-60" y="5">Database Names</text>
+ </g>
+
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue" />
+ <text class="text_normal" x="-40" y="5">Tablespace</text>
+ </g>
+
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-70" y="5">Replication Origins</text>
+ </g>
+
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue" />
+ <text class="text_normal" x="-60" y="-3">Subscription for</text>
+ <text class="text_normal" x="-68" y="10">Logical Replication</text>
+ </g>
+
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-15" y="5">Role</text>
+ </g>
+
+ </g>
+
+ <g transform="translate(-80 10)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2px" />
+ <text class="text_normal" x="-60" y="-80">Database</text>
+
+ <g transform="translate(-120 -50)">
+ <g transform="translate(-30 20)">
+ <ellipse rx="50" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Extension</text>
+ </g>
+
+ <g transform="translate(-35 85)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Collation</text>
+ </g>
+
+ <g transform="translate(150 70)">
+ <ellipse rx="140" ry="70" stroke="blue" />
+ <text class="text_normal" x="-80" y="-35">Schema</text>
+
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue" />
+ <text class="text_normal" x="-50" y="5">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink-svgo.svg b/doc/src/sgml/images/mvcc-ink-svgo.svg
new file mode 100644
index 0000000000..6ff6a4da79
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink-svgo.svg
@@ -0,0 +1,151 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="150" viewBox="0 0 850 150">
+ <title>
+ MVCC
+ </title>
+ <style>
+ .text_small{font-style:normal;font-weight:400;font-size:10px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <marker id="triangle_1" markerWidth="10" markerHeight="10" refX="5" refY="5" orient="auto" stroke="black" fill="none">
+ <path d="M0 0l10 5-10 5"/>
+ </marker>
+ <path id="arrow" d="M0 0q20-15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+ <g id="tuple" stroke="black">
+ <path d="M80 0H0v20h80M29 0v20M60 0v20"/>
+ <path d="M80 0h15M80 20h15" stroke-dasharray="2 1"/>
+ </g>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <g fill="none">
+ <g transform="translate(20 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">123</tspan> <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)" fill="#00f">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 83)" fill="#00f">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(185 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">135</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 53)" fill="#00f">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(350 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">142</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 23)" fill="#00f">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(515 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">821</tspan> <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 821
+ </text>
+ <text class="text_small" transform="translate(125 23)">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(740 110)">
+ <path d="M102-20H-18v60" stroke="black"/>
+ <text font-weight="400" font-size="14" font-family=""Open Sans",sans-serif" fill="#000">
+ Legend
+ </text>
+ <use xlink:href="#tuple" transform="translate(0 10)"/>
+ <text class="text_small" transform="translate(3 23)">
+ xmin
+ </text>
+ <text class="text_small" transform="translate(32 23)">
+ xmax
+ </text>
+ <text class="text_small" transform="translate(65 23)">
+ data
+ </text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink.svg b/doc/src/sgml/images/mvcc-ink.svg
new file mode 100644
index 0000000000..80ae8d29e0
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink.svg
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="150px"
+ viewBox="0 0 850 150"
+ id="svg4396"
+ sodipodi:docname="mvcc-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata4400">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>MVCC</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1266"
+ inkscape:window-height="788"
+ id="namedview4398"
+ showgrid="false"
+ inkscape:zoom="0.44470588"
+ inkscape:cx="425"
+ inkscape:cy="68.253968"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg4396" />
+ <title
+ id="title4251">MVCC</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4253">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs4264">
+ <marker
+ id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto"
+ stroke="black"
+ fill="none">
+ <path
+ d="M 0,0 L 10,5 L 0,10"
+ id="path4255" />
+ </marker>
+ <g
+ id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path
+ d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20"
+ stroke="black"
+ id="path4258" />
+ <!-- prolong the rectangle -->
+ <path
+ d="M 80 0 h 15 M 80 20 h 15"
+ stroke="black"
+ stroke-dasharray="2 1"
+ id="path4260" />
+ </g>
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path
+ id="arrow"
+ d="M 0 0 Q 20 -15 40 0"
+ stroke="black"
+ marker-end="url(#triangle_1)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect4266" />
+ <!-- set default values -->
+ <g
+ fill="none"
+ id="g4394">
+ <!-- start plus first INSERT -->
+ <g
+ transform="translate(20, 40)"
+ id="g4284">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4272">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4268">123</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4270">: INSERT</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4274" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4276" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ style="fill:blue"
+ id="text4278">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text4280">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ style="fill:blue"
+ id="text4282">'x'</text>
+ </g>
+ <!-- first UPDATE -->
+ <g
+ transform="translate(185, 40)"
+ id="g4310">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4290">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4286">135</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4288">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4292" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use4294" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ style="fill:blue"
+ id="text4296">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text4298">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ style="fill:blue"
+ id="text4300">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4302" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text4304">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text4306">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text4308">'x'</text>
+ </g>
+ <!-- next UPDATE -->
+ <g
+ transform="translate(350, 40)"
+ id="g4344">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4316">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4312">142</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4314">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4318" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use4320" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ style="fill:blue"
+ id="text4322">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text4324">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ style="fill:blue"
+ id="text4326">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use4328" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text4330">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text4332">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text4334">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4336" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text4338">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text4340">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text4342">'x'</text>
+ </g>
+ <!-- DELETE -->
+ <g
+ transform="translate(515, 40)"
+ id="g4378">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4350">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4346">821</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4348">: DELTE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4352" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use4354" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text4356">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text4358">821</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ id="text4360">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use4362" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text4364">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ id="text4366">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text4368">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4370" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text4372">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text4374">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text4376">'x'</text>
+ </g>
+ <!-- LEGEND -->
+ <g
+ transform="translate(740, 110)"
+ id="g4392">
+ <path
+ d="M 102 -20 h -120 v 60"
+ stroke="black"
+ id="path4380" />
+ <text
+ class="text_normal"
+ transform="translate(0, 0)"
+ id="text4382">Legend</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(0, 10)"
+ id="use4384" />
+ <text
+ class="text_small"
+ transform="translate(3, 23)"
+ id="text4386">xmin</text>
+ <text
+ class="text_small"
+ transform="translate(32, 23)"
+ id="text4388">xmax</text>
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text4390">data</text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-raw.svg b/doc/src/sgml/images/mvcc-raw.svg
new file mode 100644
index 0000000000..ee27e3df7b
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-raw.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="150px"
+ viewBox="0 0 850 150" >
+
+ <title>MVCC</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <marker id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto" stroke="black" fill="none">
+ <path d="M 0,0 L 10,5 L 0,10" />
+ </marker>
+
+ <g id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20" stroke="black"/>
+ <!-- prolong the rectangle -->
+ <path d="M 80 0 h 15 M 80 20 h 15" stroke="black" stroke-dasharray="2 1"/>
+ </g>
+
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path id="arrow" d="M 0 0 Q 20 -15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- set default values -->
+ <g fill="none">
+
+ <!-- start plus first INSERT -->
+ <g transform="translate(20, 40)">
+
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">123</tspan>
+ <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)" style="fill:blue">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 83)" style="fill:blue">'x'</text>
+ </g>
+
+ <!-- first UPDATE -->
+ <g transform="translate(185, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">135</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 53)" style="fill:blue">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- next UPDATE -->
+ <g transform="translate(350, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">142</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 23)" style="fill:blue">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- DELETE -->
+ <g transform="translate(515, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">821</tspan>
+ <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">821</text>
+ <text class="text_small" transform="translate(125, 23)">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- LEGEND -->
+ <g transform="translate(740, 110)">
+ <path d="M 102 -20 h -120 v 60" stroke="black"/>
+ <text class="text_normal" transform="translate(0, 0)">Legend</text>
+ <use xlink:href="#tuple" transform="translate(0, 10)"/>
+ <text class="text_small" transform="translate(3, 23)">xmin</text>
+ <text class="text_small" transform="translate(32, 23)">xmax</text>
+ <text class="text_small" transform="translate(65, 23)">data</text>
+ </g>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink-svgo.svg b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
new file mode 100644
index 0000000000..aa0445352d
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
@@ -0,0 +1,285 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 900 600">
+ <title>
+ PG Overall Server Architecture
+ </title>
+ <style>
+ .text_big{font-style:normal}.text_big,.text_comment,.text_normal,.text_small{font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_normal,.text_small{font-style:normal}.text_small{font-size:12px}.text_normal{font-size:14px}.text_big{font-size:24px}.text_comment{font-style:italic;font-size:14px}
+ </style>
+ <defs>
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (200 x 20 px)
+ </title>
+ <path d="M200 10v10H0V0h190v10h10L190 0"/>
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (250 x 20 px)
+ </title>
+ <path d="M250 10v10H0V0h240v10h10L240 0"/>
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (100 x 35 px)
+ </title>
+ <path d="M100 10v25H0V0h90v10h10L90 0"/>
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (170 x 50 px)
+ </title>
+ <path d="M170 10v40H0V0h160v10h10L160 0"/>
+ </symbol>
+ <symbol id="state_300x120">
+ <title>
+ UML State (300x120)
+ </title>
+ <rect width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>
+ UML State (350x120)
+ </title>
+ <rect width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="disc" stroke="blue" fill="none">
+ <title>
+ Disc
+ </title>
+ <ellipse cx="51" cy="13" rx="50" ry="12"/>
+ <path d="M1 13v60"/>
+ <path d="M101 13v60"/>
+ <path d="M1 73a50 12 0 00100 0"/>
+ </symbol>
+ <symbol id="laptop" stroke="black" fill="none">
+ <title>
+ Laptop
+ </title>
+ <path d="M20 40V0h54v40l15 15H5l15-15h54"/>
+ <path d="M23 3h48v34H23z"/>
+ <path d="M30 10h20"/>
+ <path d="M30 15h25"/>
+ <path d="M30 20h10"/>
+ <path d="M30 30h20"/>
+ <path d="M25 50h45l2 2H22z"/>
+ </symbol>
+ <marker id="arrowhead_start" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto">
+ <path d="M6 0L0 3l6 3" stroke="black" fill="none"/>
+ </marker>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="15" y="40" class="text_big">
+ Client
+ </text>
+ <text x="140" y="40" class="text_big">
+ Server
+ </text>
+ <use xlink:href="#laptop" x="5" y="210"/>
+ <g transform="translate(130 70)">
+ <use xlink:href="#state_350x120"/>
+ <text x="5" y="20" class="text_normal">
+ maintenance_work_mem (per connection)
+ </text>
+ <text x="5" y="45" class="text_normal">
+ work_mem (per query operation)
+ </text>
+ <text x="5" y="70" class="text_normal">
+ autovacuum_work_mem (per worker process)
+ </text>
+ <text x="5" y="95" class="text_normal">
+ temp_buffer (per connection)
+ </text>
+ <text x="5" y="110" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_200x20" x="140" y="-15"/>
+ <text x="150" class="text_comment">
+ Individual Memory
+ </text>
+ </g>
+ <g transform="translate(520 70)">
+ <use xlink:href="#state_300x120"/>
+ <text x="10" y="30" class="text_normal">
+ shared_buffers (heap and index)
+ </text>
+ <text x="10" y="70" class="text_normal">
+ wal_buffers (WAL records)
+ </text>
+ <text x="10" y="100" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_250x20" x="40" y="-15"/>
+ <text x="50" class="text_comment">
+ Shared Memory (per Instance)
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M180 215h250v30H180z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(180 215)">
+ Postmaster
+ </text>
+ <path d="M90 230h75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 230)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 1
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M150 315h370v30H150z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(150 315)">
+ Backend processes (one per connection)
+ </text>
+ <path d="M155 315v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M160 310v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M90 240l63 63" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 290)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 3
+ </text>
+ </g>
+ <path d="M360 250v50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180 255)">
+ <use xlink:href="#note_250x20"/>
+ <text x="10" y="15" class="text_comment">
+ Creates backend processes
+ </text>
+ </g>
+ <g transform="translate(360 281)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 2
+ </text>
+ </g>
+ <path d="M460 300V200" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M498 300V95h30" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M508 300V135h20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M550 220h120v30H550z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(550 220)">
+ WAL Writer
+ </text>
+ <path d="M590 150v65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M590 255v230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 340h140v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 340)">
+ Checkpointer
+ </text>
+ <path d="M740 110v220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 355H475v130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M700 330V150" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50"/>
+ <text x="60" y="-35" class="text_comment">
+ Checkpoint
+ </text>
+ <text x="60" y="-20" class="text_comment">
+ Record
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M610 380h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 380)">
+ Background Writer
+ </text>
+ <path d="M770 110v260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 395H485v90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 420h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 420)">
+ WAL Archiver
+ </text>
+ <path d="M620 485l30-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M690 455l30 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M135 380h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 380)">
+ Autovacuum
+ </text>
+ <path d="M140 380v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path d="M145 375v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path stroke="blue" fill="none" d="M135 430h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 430)">
+ Logger
+ </text>
+ <path stroke="blue" fill="none" d="M290 370h140v30H290z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(290 370)">
+ Stats Collector
+ </text>
+ <g transform="translate(145 490)">
+ <use xlink:href="#disc"/>
+ <text x="35" y="45" class="text_normal">
+ Log
+ </text>
+ <text x="20" y="60" class="text_small">
+ text lines,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <path d="M195 465v20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(410 490)">
+ <use xlink:href="#disc"/>
+ <text x="10" y="40" class="text_normal">
+ Heap and
+ </text>
+ <text x="25" y="55" class="text_normal">
+ Index
+ </text>
+ <text x="15" y="70" class="text_small">
+ binary blocks,
+ </text>
+ <text x="30" y="80" class="text_small">
+ random
+ </text>
+ </g>
+ <path d="M450 485V350" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(295 420)">
+ <use xlink:href="#note_170x50"/>
+ <text x="5" y="15" class="text_comment">
+ Read heap and index
+ </text>
+ <text x="5" y="30" class="text_comment">
+ pages and transfer
+ </text>
+ <text x="5" y="45" class="text_comment">
+ them to shared_buffers
+ </text>
+ </g>
+ <g transform="translate(550 490)">
+ <use xlink:href="#disc"/>
+ <text x="30" y="45" class="text_normal">
+ WAL
+ </text>
+ <text x="10" y="60" class="text_small">
+ binary records,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <g transform="translate(690 490)">
+ <use xlink:href="#disc"/>
+ <text x="16" y="45" class="text_normal">
+ Archived
+ </text>
+ <text x="36" y="60" class="text_normal">
+ WAL
+ </text>
+ </g>
+ <path d="M110 20v550" stroke="black" fill="none"/>
+ <g transform="rotate(90 -33.5 156.5)">
+ <use xlink:href="#note_200x20"/>
+ <text class="text_comment" x="10" y="15">
+ Via TCP/IP or socket
+ </text>
+ </g>
+ <text class="text_big" x="95" transform="rotate(90 425 425)">
+ RAM
+ </text>
+ <text class="text_big" x="250" transform="rotate(90 425 425)">
+ PROCESSES
+ </text>
+ <text class="text_big" x="500" transform="rotate(90 425 425)">
+ FILES
+ </text>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink.svg b/doc/src/sgml/images/ram-proc-file-ink.svg
new file mode 100644
index 0000000000..9ef89639c4
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink.svg
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="600px"
+ viewBox="0 0 900 600"
+ id="svg4706"
+ sodipodi:docname="ram-proc-file-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata4710">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>PG Overall Server Architecture</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1282"
+ inkscape:window-height="733"
+ id="namedview4708"
+ showgrid="false"
+ inkscape:zoom="0.39333333"
+ inkscape:cx="450"
+ inkscape:cy="292.37288"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg4706" />
+ <title
+ id="title4402">PG Overall Server Architecture</title>
+ <style
+ type="text/css"
+ id="style4404">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs4470">
+ <!-- Some notes in different sizes -->
+ <symbol
+ id="note_200x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4406">UML Note (200 x 20 px)</title>
+ <path
+ d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10"
+ id="path4408" />
+ </symbol>
+ <symbol
+ id="note_250x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4411">UML Note (250 x 20 px)</title>
+ <path
+ d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10"
+ id="path4413" />
+ </symbol>
+ <symbol
+ id="note_100x35"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4416">UML Note (100 x 35 px)</title>
+ <path
+ d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10"
+ id="path4418" />
+ </symbol>
+ <symbol
+ id="note_170x50"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4421">UML Note (170 x 50 px)</title>
+ <path
+ d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10"
+ id="path4423" />
+ </symbol>
+ <!-- UML states (used for buffers) -->
+ <symbol
+ id="state_300x120">
+ <title
+ id="title4426">UML State (300x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="300"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect4428" />
+ </symbol>
+ <symbol
+ id="state_350x120">
+ <title
+ id="title4431">UML State (350x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="350"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect4433" />
+ </symbol>
+ <!-- Discs -->
+ <symbol
+ id="disc"
+ stroke="blue"
+ fill="none">
+ <title
+ id="title4436">Disc</title>
+ <ellipse
+ cx="51"
+ cy="13"
+ rx="50"
+ ry="12"
+ id="ellipse4438" />
+ <!-- top -->
+ <path
+ d="M 1,13 v 60"
+ id="path4440" />
+ <!-- left -->
+ <path
+ d="M 101,13 v 60"
+ id="path4442" />
+ <!-- right -->
+ <path
+ d="M 1,73 A 50, 12, 0, 0, 0, 101,73"
+ id="path4444" />
+ <!-- bottom -->
+ </symbol>
+ <!-- Laptop -->
+ <symbol
+ id="laptop"
+ stroke="black"
+ fill="none">
+ <title
+ id="title4447">Laptop</title>
+ <path
+ d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54"
+ id="path4449" />
+ <rect
+ x="23"
+ y="3"
+ width="48"
+ height="34"
+ id="rect4451" />
+ <!-- symbolize some lines -->
+ <path
+ d="M 30,10 h 20"
+ id="path4453" />
+ <path
+ d="M 30,15 h 25"
+ id="path4455" />
+ <path
+ d="M 30,20 h 10"
+ id="path4457" />
+ <path
+ d="M 30,30 h 20"
+ id="path4459" />
+ <!-- symbolize keyboard -->
+ <path
+ d="M 25,50 h 45 l 2,2 h -50 z "
+ id="path4461" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path4464" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path4467" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect4472" />
+ <!-- caption, client side -->
+ <text
+ x="15"
+ y="40"
+ class="text_big"
+ id="text4474">Client</text>
+ <text
+ x="140"
+ y="40"
+ class="text_big"
+ id="text4476">Server</text>
+ <use
+ xlink:href="#laptop"
+ x="5"
+ y="210"
+ id="use4478" />
+ <!-- individual memory -->
+ <g
+ transform="translate(130, 70)"
+ id="g4496">
+ <use
+ xlink:href="#state_350x120"
+ x="0"
+ y="0"
+ id="use4480" />
+ <text
+ x="5"
+ y="20"
+ class="text_normal"
+ id="text4482">maintenance_work_mem (per connection)</text>
+ <text
+ x="5"
+ y="45"
+ class="text_normal"
+ id="text4484">work_mem (per query operation)</text>
+ <text
+ x="5"
+ y="70"
+ class="text_normal"
+ id="text4486">autovacuum_work_mem (per worker process)</text>
+ <text
+ x="5"
+ y="95"
+ class="text_normal"
+ id="text4488">temp_buffer (per connection)</text>
+ <text
+ x="5"
+ y="110"
+ class="text_normal"
+ id="text4490">...</text>
+ <use
+ xlink:href="#note_200x20"
+ x="140"
+ y="-15"
+ id="use4492" />
+ <text
+ x="150"
+ y="0"
+ class="text_comment"
+ id="text4494">Individual Memory</text>
+ </g>
+ <!-- shared memory -->
+ <g
+ transform="translate(520, 70)"
+ id="g4510">
+ <use
+ xlink:href="#state_300x120"
+ x="0"
+ y="0"
+ id="use4498" />
+ <text
+ x="10"
+ y="30"
+ class="text_normal"
+ id="text4500">shared_buffers (heap and index)</text>
+ <text
+ x="10"
+ y="70"
+ class="text_normal"
+ id="text4502">wal_buffers (WAL records)</text>
+ <text
+ x="10"
+ y="100"
+ class="text_normal"
+ id="text4504">...</text>
+ <use
+ xlink:href="#note_250x20"
+ x="40"
+ y="-15"
+ id="use4506" />
+ <text
+ x="50"
+ y="0"
+ class="text_comment"
+ id="text4508">Shared Memory (per Instance)</text>
+ </g>
+ <!-- postmaster -->
+ <g
+ transform="translate(180, 215)"
+ id="g4516">
+ <rect
+ width="250"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4512" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4514">Postmaster</text>
+ </g>
+ <path
+ d="M 90,230 h 75"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4518" />
+ <g
+ transform="translate(140, 230)"
+ id="g4524">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle4520" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text4522">1</text>
+ </g>
+ <!-- backend processes -->
+ <g
+ transform="translate(150, 315)"
+ id="g4534">
+ <rect
+ width="370"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4526" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4528">Backend processes (one per connection)</text>
+ <path
+ d="M 5,0 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4530" />
+ <path
+ d="M 10,-5 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4532" />
+ </g>
+ <path
+ d="M 90,240 153,303"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path4536" />
+ <g
+ transform="translate(140, 290)"
+ id="g4542">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle4538" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text4540">3</text>
+ </g>
+ <!-- connection between postmaster and backend processes -->
+ <path
+ d="M 360,250 v 50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4544" />
+ <g
+ transform="translate(180, 255)"
+ id="g4550">
+ <use
+ xlink:href="#note_250x20"
+ id="use4546" />
+ <text
+ x="10"
+ y="15"
+ class="text_comment"
+ id="text4548">Creates backend processes</text>
+ </g>
+ <g
+ transform="translate(360, 281)"
+ id="g4556">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle4552" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text4554">2</text>
+ </g>
+ <!-- backend process' access to individual memory -->
+ <path
+ d="M 460,300 v -100"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path4558" />
+ <!-- its access to shared buffers and WAL buffers -->
+ <path
+ d="M 498,300 v -205 h 30"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path4560" />
+ <path
+ d="M 508,300 v -165 h 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4562" />
+ <!-- WAL writer -->
+ <g
+ transform="translate(550, 220)"
+ id="g4568">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4564" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4566">WAL Writer</text>
+ </g>
+ <path
+ d="M 590,150 v 65"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4570" />
+ <path
+ d="M 590,255 v 230"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4572" />
+ <!-- Checkpoiner -->
+ <g
+ transform="translate(610, 340)"
+ id="g4578">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4574" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4576">Checkpointer</text>
+ </g>
+ <path
+ d="M 740,110 v 220"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4580" />
+ <path
+ d="M 605,355 h -130 v 130"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4582" />
+ <path
+ d="M 700,330 v -180"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4584" />
+ <g
+ transform="translate(570, 330)"
+ id="g4592">
+ <use
+ xlink:href="#note_100x35"
+ x="50"
+ y="-50"
+ id="use4586" />
+ <text
+ x="60"
+ y="-35"
+ class="text_comment"
+ id="text4588">Checkpoint</text>
+ <text
+ x="60"
+ y="-20"
+ class="text_comment"
+ id="text4590">Record</text>
+ </g>
+ <!-- BG writer -->
+ <g
+ transform="translate(610, 380)"
+ id="g4598">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4594" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4596">Background Writer</text>
+ </g>
+ <path
+ d="M 770,110 v 260"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4600" />
+ <path
+ d="M 605,395 h -120 v 90"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4602" />
+ <!-- Archiver -->
+ <g
+ transform="translate(610, 420)"
+ id="g4608">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4604" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4606">WAL Archiver</text>
+ </g>
+ <path
+ d="M 620,485 l 30,-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4610" />
+ <path
+ d="M 690,455 l 30, 30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4612" />
+ <!-- Vacuum -->
+ <g
+ transform="translate(135, 380)"
+ id="g4622">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4614" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4616">Autovacuum</text>
+ <path
+ d="M 5,0 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4618" />
+ <path
+ d="M 10,-5 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4620" />
+ </g>
+ <!-- Log Writer -->
+ <g
+ transform="translate(135, 430)"
+ id="g4628">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4624" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4626">Logger</text>
+ </g>
+ <!-- Stats Collector -->
+ <g
+ transform="translate(290, 370)"
+ id="g4634">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4630" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4632">Stats Collector</text>
+ </g>
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g
+ transform="translate(145, 490)"
+ id="g4644">
+ <use
+ xlink:href="#disc"
+ id="use4636" />
+ <text
+ x="35"
+ y="45"
+ class="text_normal"
+ id="text4638">Log</text>
+ <text
+ x="20"
+ y="60"
+ class="text_small"
+ id="text4640">text lines,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text4642">sequential</text>
+ </g>
+ <path
+ d="M 195,465 v 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4646" />
+ <g
+ transform="translate(410, 490)"
+ id="g4658">
+ <use
+ xlink:href="#disc"
+ id="use4648" />
+ <text
+ x="10"
+ y="40"
+ class="text_normal"
+ id="text4650">Heap and</text>
+ <text
+ x="25"
+ y="55"
+ class="text_normal"
+ id="text4652">Index</text>
+ <text
+ x="15"
+ y="70"
+ class="text_small"
+ id="text4654">binary blocks,</text>
+ <text
+ x="30"
+ y="80"
+ class="text_small"
+ id="text4656">random</text>
+ </g>
+ <path
+ d="M 450,485 v -135"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4660" />
+ <g
+ transform="translate(295, 420)"
+ id="g4670">
+ <use
+ xlink:href="#note_170x50"
+ id="use4662" />
+ <text
+ x="5"
+ y="15"
+ class="text_comment"
+ id="text4664">Read heap and index</text>
+ <text
+ x="5"
+ y="30"
+ class="text_comment"
+ id="text4666">pages and transfer</text>
+ <text
+ x="5"
+ y="45"
+ class="text_comment"
+ id="text4668">them to shared_buffers</text>
+ </g>
+ <g
+ transform="translate(550, 490)"
+ id="g4680">
+ <use
+ xlink:href="#disc"
+ id="use4672" />
+ <text
+ x="30"
+ y="45"
+ class="text_normal"
+ id="text4674">WAL</text>
+ <text
+ x="10"
+ y="60"
+ class="text_small"
+ id="text4676">binary records,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text4678">sequential</text>
+ </g>
+ <g
+ transform="translate(690, 490)"
+ id="g4688">
+ <use
+ xlink:href="#disc"
+ id="use4682" />
+ <text
+ x="16"
+ y="45"
+ class="text_normal"
+ id="text4684">Archived</text>
+ <text
+ x="36"
+ y="60"
+ class="text_normal"
+ id="text4686">WAL</text>
+ </g>
+ <!-- boarder between client and server side -->
+ <path
+ d="M 110,20 v 550"
+ stroke="black"
+ fill="none"
+ id="path4690" />
+ <g
+ transform="translate(123, 190) rotate(90)"
+ id="g4696">
+ <use
+ xlink:href="#note_200x20"
+ id="use4692" />
+ <text
+ class="text_comment"
+ x="10"
+ y="15"
+ id="text4694">Via TCP/IP or socket</text>
+ </g>
+ <!-- right side -->
+ <g
+ transform="translate(850, 0) rotate(90)"
+ id="g4704">
+ <text
+ class="text_big"
+ x="95"
+ id="text4698">RAM</text>
+ <text
+ class="text_big"
+ x="250"
+ id="text4700">PROCESSES</text>
+ <text
+ class="text_big"
+ x="500"
+ id="text4702">FILES</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-raw.svg b/doc/src/sgml/images/ram-proc-file-raw.svg
new file mode 100644
index 0000000000..775ba91571
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-raw.svg
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="600px"
+ viewBox="0 0 900 600">
+
+ <title>PG Overall Server Architecture</title>
+
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Some notes in different sizes -->
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>UML Note (200 x 20 px)</title>
+ <path d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>UML Note (250 x 20 px)</title>
+ <path d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>UML Note (100 x 35 px)</title>
+ <path d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>UML Note (170 x 50 px)</title>
+ <path d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- UML states (used for buffers) -->
+ <symbol id="state_300x120">
+ <title>UML State (300x120)</title>
+ <rect x="0" y="0" width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>UML State (350x120)</title>
+ <rect x="0" y="0" width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- Discs -->
+ <symbol id="disc" stroke="blue" fill="none" >
+ <title>Disc</title>
+ <ellipse cx="51" cy="13" rx="50" ry="12" /> <!-- top -->
+ <path d="M 1,13 v 60" /> <!-- left -->
+ <path d="M 101,13 v 60" /> <!-- right -->
+ <path d="M 1,73 A 50, 12, 0, 0, 0, 101,73" /> <!-- bottom -->
+ </symbol>
+
+ <!-- Laptop -->
+ <symbol id="laptop" stroke="black" fill="none" >
+ <title>Laptop</title>
+ <path d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54" />
+ <rect x="23" y="3" width="48" height="34" />
+ <!-- symbolize some lines -->
+ <path d="M 30,10 h 20" />
+ <path d="M 30,15 h 25" />
+ <path d="M 30,20 h 10" />
+ <path d="M 30,30 h 20" />
+ <!-- symbolize keyboard -->
+ <path d="M 25,50 h 45 l 2,2 h -50 z " />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption, client side -->
+ <text x="15" y="40" class="text_big">Client</text>
+ <text x="140" y="40" class="text_big">Server</text>
+ <use xlink:href="#laptop" x="5" y="210" />
+
+
+ <!-- individual memory -->
+ <g transform="translate(130, 70)">
+ <use xlink:href="#state_350x120" x="0" y="0" />
+ <text x="5" y="20" class="text_normal">maintenance_work_mem (per connection)</text>
+ <text x="5" y="45" class="text_normal">work_mem (per query operation)</text>
+ <text x="5" y="70" class="text_normal">autovacuum_work_mem (per worker process)</text>
+ <text x="5" y="95" class="text_normal">temp_buffer (per connection)</text>
+ <text x="5" y="110" class="text_normal">...</text>
+ <use xlink:href="#note_200x20" x="140" y="-15" />
+ <text x="150" y="0" class="text_comment">Individual Memory</text>
+ </g>
+
+ <!-- shared memory -->
+ <g transform="translate(520, 70)">
+ <use xlink:href="#state_300x120" x="0" y="0" />
+ <text x="10" y="30" class="text_normal">shared_buffers (heap and index)</text>
+ <text x="10" y="70" class="text_normal">wal_buffers (WAL records)</text>
+ <text x="10" y="100" class="text_normal">...</text>
+ <use xlink:href="#note_250x20" x="40" y="-15" />
+ <text x="50" y="0" class="text_comment">Shared Memory (per Instance)</text>
+ </g>
+
+ <!-- postmaster -->
+ <g transform="translate(180, 215)">
+ <rect width="250" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Postmaster</text>
+ </g>
+ <path d="M 90,230 h 75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 230)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">1</text>
+ </g>
+
+ <!-- backend processes -->
+ <g transform="translate(150, 315)">
+ <rect width="370" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Backend processes (one per connection)</text>
+ <path d="M 5,0 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <path d="M 90,240 153,303" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 290)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">3</text>
+ </g>
+
+ <!-- connection between postmaster and backend processes -->
+ <path d="M 360,250 v 50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180, 255)">
+ <use xlink:href="#note_250x20" />
+ <text x="10" y="15" class="text_comment">Creates backend processes</text>
+ </g>
+ <g transform="translate(360, 281)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">2</text>
+ </g>
+
+ <!-- backend process' access to individual memory -->
+ <path d="M 460,300 v -100" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <!-- its access to shared buffers and WAL buffers -->
+ <path d="M 498,300 v -205 h 30" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M 508,300 v -165 h 20" stroke="black" fill="none"
+ marker-end="url(#arrowhead_end)"/>
+
+ <!-- WAL writer -->
+ <g transform="translate(550, 220)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Writer</text>
+ </g>
+ <path d="M 590,150 v 65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 590,255 v 230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Checkpoiner -->
+ <g transform="translate(610, 340)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Checkpointer</text>
+ </g>
+ <path d="M 740,110 v 220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,355 h -130 v 130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 700,330 v -180" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570, 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50" />
+ <text x="60" y="-35" class="text_comment">Checkpoint</text>
+ <text x="60" y="-20" class="text_comment">Record</text>
+ </g>
+
+ <!-- BG writer -->
+ <g transform="translate(610, 380)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Background Writer</text>
+ </g>
+ <path d="M 770,110 v 260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,395 h -120 v 90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Archiver -->
+ <g transform="translate(610, 420)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Archiver</text>
+ </g>
+ <path d="M 620,485 l 30,-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 690,455 l 30, 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Vacuum -->
+ <g transform="translate(135, 380)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Autovacuum</text>
+ <path d="M 5,0 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <!-- Log Writer -->
+ <g transform="translate(135, 430)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Logger</text>
+ </g>
+
+ <!-- Stats Collector -->
+ <g transform="translate(290, 370)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Stats Collector</text>
+ </g>
+
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g transform="translate(145, 490)">
+ <use xlink:href="#disc" />
+ <text x="35" y="45" class="text_normal">Log</text>
+ <text x="20" y="60" class="text_small">text lines,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+ <path d="M 195,465 v 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(410, 490)">
+ <use xlink:href="#disc" />
+ <text x="10" y="40" class="text_normal">Heap and</text>
+ <text x="25" y="55" class="text_normal">Index</text>
+ <text x="15" y="70" class="text_small">binary blocks,</text>
+ <text x="30" y="80" class="text_small">random</text>
+ </g>
+ <path d="M 450,485 v -135" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(295, 420)">
+ <use xlink:href="#note_170x50" />
+ <text x="5" y="15" class="text_comment">Read heap and index</text>
+ <text x="5" y="30" class="text_comment">pages and transfer</text>
+ <text x="5" y="45" class="text_comment">them to shared_buffers</text>
+ </g>
+
+ <g transform="translate(550, 490)">
+ <use xlink:href="#disc" />
+ <text x="30" y="45" class="text_normal">WAL</text>
+ <text x="10" y="60" class="text_small">binary records,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+
+ <g transform="translate(690, 490)">
+ <use xlink:href="#disc" />
+ <text x="16" y="45" class="text_normal">Archived</text>
+ <text x="36" y="60" class="text_normal">WAL</text>
+ </g>
+
+ <!-- boarder between client and server side -->
+ <path d="M 110,20 v 550" stroke="black" fill="none" />
+ <g transform="translate(123, 190) rotate(90)">
+ <use xlink:href="#note_200x20" />
+ <text class="text_comment" x="10" y ="15">Via TCP/IP or socket</text>
+ </g>
+
+ <!-- right side -->
+ <g transform="translate(850, 0) rotate(90)">
+ <text class="text_big" x="95">RAM</text>
+ <text class="text_big" x="250">PROCESSES</text>
+ <text class="text_big" x="500">FILES</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink-svgo.svg b/doc/src/sgml/images/wraparound-ink-svgo.svg
new file mode 100644
index 0000000000..d5af6ce0b8
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink-svgo.svg
@@ -0,0 +1,40 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="280" viewBox="0 0 850 280">
+ <title>
+ Cyclic usage of XIDs
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="370" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ Cyclic usage of XIDs modulo 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan>
+ </text>
+ <g fill="none" transform="translate(170 150)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_095" startOffset="30.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="30%">(1)</textPath> <textPath xlink:href="#Path_095" startOffset="45.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(2)</textPath> <textPath xlink:href="#Path_095" startOffset="50.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="50%">(3)</textPath> <textPath xlink:href="#Path_095" startOffset="62.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="62%">(4)</textPath>
+ </text>
+ </g>
+ <g class="text_normal">
+ <text transform="translate(400 130)">
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25" transform="translate(400 130)">
+ 1: oldest <tspan font-weight="700">active</tspan> xid (pg_stat_activity.backend_xmin)
+ </text>
+ <text y="50" transform="translate(400 130)">
+ 2: xmin of one row version
+ </text>
+ <text y="75" transform="translate(400 130)">
+ 3: xmax of the same row version
+ </text>
+ <text y="100" transform="translate(400 130)">
+ 4: youngest xid (txid_current)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink.svg b/doc/src/sgml/images/wraparound-ink.svg
new file mode 100644
index 0000000000..51d35a9f85
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="280px"
+ viewBox="0 0 850 280"
+ id="svg216"
+ sodipodi:docname="wraparound-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata220">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Cyclic usage of XIDs</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1247"
+ inkscape:window-height="650"
+ id="namedview218"
+ showgrid="false"
+ inkscape:zoom="0.44470588"
+ inkscape:cx="425"
+ inkscape:cy="133.25397"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg216" />
+ <title
+ id="title153">Cyclic usage of XIDs</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style155">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs160">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect162" />
+ <text
+ class="text_big"
+ x="370"
+ y="40"
+ id="text168">Cyclic usage of XIDs modulo 2
+ <tspan
+ dy="-5"
+ id="tspan164">^</tspan>
+<tspan
+ dy="5"
+ id="tspan166">32</tspan>
+</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 150)"
+ id="g196">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle170" />
+ <text
+ class="text_normal"
+ id="text194">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath172">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath174">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath176">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="30.5%"
+ id="textPath178">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="30%"
+ id="textPath180">(1)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="45.5%"
+ id="textPath182">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath184">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="50.5%"
+ id="textPath186">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="50%"
+ id="textPath188">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="62.5%"
+ id="textPath190">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="62%"
+ id="textPath192">(4)</textPath>
+ </text>
+ </g>
+ <g
+ class="text_normal"
+ transform="translate(400 130)"
+ id="g214">
+ <text
+ id="text202">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan198">^</tspan>
+<tspan
+ dy="5"
+ id="tspan200">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text206">1: oldest <tspan
+ style="font-weight:bold"
+ id="tspan204">active</tspan>
+ xid (pg_stat_activity.backend_xmin)</text>
+ <text
+ y="50"
+ id="text208">2: xmin of one row version</text>
+ <text
+ y="75"
+ id="text210">3: xmax of the same row version</text>
+ <text
+ y="100"
+ id="text212">4: youngest xid (txid_current)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-raw.svg b/doc/src/sgml/images/wraparound-raw.svg
new file mode 100644
index 0000000000..637e68bb82
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-raw.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="280px"
+ viewBox="0 0 850 280" >
+
+ <title>Cyclic usage of XIDs</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="370" y="40">Cyclic usage of XIDs modulo 2
+ <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan></text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 150)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_095" startOffset="30.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="30%" >(1)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="45.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(2)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="50.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="50%" >(3)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="62.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="62%" >(4)</textPath>
+ </text>
+ </g>
+
+ <g class="text_normal" transform="translate(400 130)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: oldest <tspan style="font-weight:bold">active</tspan> xid (pg_stat_activity.backend_xmin)</text>
+ <text y="50">2: xmin of one row version</text>
+ <text y="75">3: xmax of the same row version</text>
+ <text y="100">4: youngest xid (txid_current)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 730d5fdc34..e9e9f9495f 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -248,6 +248,7 @@ break is not needed in a wider output rendering.
</para>
</partintro>
+ &architecture;
&arch-dev;
&catalogs;
&protocol;
diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml
index 9bb5c1a6d5..abb61445f2 100644
--- a/doc/src/sgml/start.sgml
+++ b/doc/src/sgml/start.sgml
@@ -53,7 +53,7 @@
<sect1 id="tutorial-arch">
- <title>Architectural Fundamentals</title>
+ <title>Client/Server Model</title>
<para>
Before we proceed, you should understand the basic
@@ -68,34 +68,52 @@
client/server model. A <productname>PostgreSQL</productname>
session consists of the following cooperating processes
(programs):
+ </para>
- <itemizedlist>
- <listitem>
- <para>
- A server process, which manages the database files, accepts
- connections to the database from client applications, and
- performs database actions on behalf of the clients. The
- database server program is called
- <filename>postgres</filename>.
- <indexterm><primary>postgres</primary></indexterm>
- </para>
- </listitem>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A process at the server site with the name
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ <indexterm><primary>postgres</primary></indexterm>
+ <indexterm><primary>postmaster</primary></indexterm>
+ It accepts connection requests from client applications, starts
+ (<quote>forks</quote>) a new <glossterm linkend="glossary-backend">
+ Backend</glossterm> process for each of them, and passes
+ the connection to it. From that point on, the client and the new
+ Backend process communicate directly without intervention by the original
+ Postmaster process. Thus, the Postmaster process is always running,
+ waiting for new client connections, whereas clients and associated
+ Backend processes come and go. (All of this is of course invisible
+ to the user. We only mention it here for completeness.)
+ </para>
+ </listitem>
- <listitem>
- <para>
- The user's client (frontend) application that wants to perform
- database operations. Client applications can be very diverse
- in nature: a client could be a text-oriented tool, a graphical
- application, a web server that accesses the database to
- display web pages, or a specialized database maintenance tool.
- Some client applications are supplied with the
- <productname>PostgreSQL</productname> distribution; most are
- developed by users.
- </para>
- </listitem>
+ <listitem>
+ <para>
+ A group of processes at the server site, the <glossterm
+ linkend="glossary-instance">Instance</glossterm>, to which also
+ the Postmaster process belongs. Their duties are handling of
+ central, common database activities like file access, transaction
+ handling, vacuum, checkpoints, replication, and more. The mentioned
+ Backend processes delegate those actions to the instance.
+ </para>
+ </listitem>
- </itemizedlist>
- </para>
+ <listitem>
+ <para>
+ The user's client (frontend) application that wants to perform
+ database operations. Client applications can be very diverse
+ in nature: a client could be a text-oriented tool, a graphical
+ application, a web server that accesses the database to
+ display web pages, or a specialized database maintenance tool.
+ Some client applications are supplied with the
+ <productname>PostgreSQL</productname> distribution; most are
+ developed by users.
+ </para>
+ </listitem>
+
+ </itemizedlist>
<para>
As is typical of client/server applications, the client and the
@@ -106,18 +124,6 @@
file name) on the database server machine.
</para>
- <para>
- The <productname>PostgreSQL</productname> server can handle
- multiple concurrent connections from clients. To achieve this it
- starts (<quote>forks</quote>) a new process for each connection.
- From that point on, the client and the new server process
- communicate without intervention by the original
- <filename>postgres</filename> process. Thus, the
- supervisor server process is always running, waiting for
- client connections, whereas client and associated server processes
- come and go. (All of this is of course invisible to the user. We
- only mention it here for completeness.)
- </para>
</sect1>
0013-architecture.sgml.difftext/x-patch; charset=UTF-8; name=0013-architecture.sgml.diffDownload
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
index b7589f9a4f..4bbd6abb8a 100644
--- a/doc/src/sgml/architecture.sgml
+++ b/doc/src/sgml/architecture.sgml
@@ -6,8 +6,11 @@
<para>
Every DBMS implements basic strategies to ensure a fast
and robust system. This chapter provides an overview of the
- techniques <productname>PostgreSQL</productname> uses to
- achieve this.
+ basic techniques <productname>PostgreSQL</productname> uses to
+ achieve this aim. It does not offer anything which exceeds
+ the information content of other pages. Instead, it tries to
+ explain <emphasis>why</emphasis> certain implementation
+ decisions have been taken.
</para>
<sect1 id="tutorial-ram-proc-file">
@@ -28,10 +31,11 @@
</para>
<para>
- The first step when an Instance starts is the start of the
+ All aspects of an Instance are launched and managed using a single primary
+ process termed the
<glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
- It loads the configuration files, allocates Shared Memory, and
- starts the other processes of the Instance:
+ It loads configuration files, allocates Shared Memory, and
+ starts the other collaborating processes of the Instance:
<glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
<glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
<glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
@@ -39,9 +43,10 @@
<glossterm linkend="glossary-autovacuum">Autovacuum</glossterm>,
<glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
<glossterm linkend="glossary-logger">Logger</glossterm>, and more.
- Later, the Postmaster starts
+ Later, the Postmaster listens on its configured system port and in response
+ to client connection attempts launches
<glossterm linkend="glossary-backend">Backend</glossterm> processes
- which communicate with clients and handle their requests.
+ to which it delegates authentication, communication, and the handling of their requests.
<xref linkend="tutorial-ram-proc-file-figure"/> visualizes the processes
of an Instance and the main aspects of their collaboration.
</para>
@@ -62,14 +67,6 @@
</mediaobject>
</figure>
- <para>
- When a client application tries to connect to a
- <glossterm linkend="glossary-database">database</glossterm>,
- this request is handled initially by the Postmaster. It
- starts a new Backend process, which handles all further
- client's requests.
- </para>
-
<para>
Client requests like <command>SELECT</command> or
<command>UPDATE</command> usually lead to the
@@ -77,16 +74,16 @@
by the client's backend process. Reads involve a page-level
cache, located in Shared Memory (for details see:
<xref linkend="sysvipc"/>) for the benefit of all processes
- in the instance. Writes also use this cache, in addition
+ in the Instance. Writes also use this cache, in addition
to a journal, called the write-ahead-log or WAL.
</para>
<para>
Shared Memory is limited in size and it can become necessary
to evict pages. As long as the content of such pages hasn't
- changed, this is not a problem. But in Shared Memory also
- write actions take place. Modified pages are called dirty
- pages or dirty buffers and before they can be evicted they
+ changed, this is not a problem. But writes directly modify
+ the pages in Shared Memory. Modified pages are called dirty
+ pages (or dirty buffers) and before they can be evicted they
must be written to disk. This happens regularly by the
Checkpointer and the Background Writer processes to ensure
that the disk version of the pages are up-to-date.
@@ -98,7 +95,7 @@
<glossterm linkend="glossary-wal-record">WAL record</glossterm>
is created from the delta-information (difference between the
old and the new content) and stored in another area of
- Shared Memory. The parallel running WAL Writer process
+ Shared Memory. The concurrently running WAL Writer process
reads them and appends them to the end of the current
<glossterm linkend="glossary-wal-record">WAL file</glossterm>.
Such sequential writes are faster than writes to random
@@ -108,8 +105,8 @@
</para>
<para>
- Second, the transfer of dirty buffers from Shared Memory to
- files must take place. This is the primary task of the
+ Second, the Instance transfers dirty buffers from Shared Memory to
+ files. This is the primary task of the
Background Writer process. Because I/O activities can block
other processes, it starts periodically and
acts only for a short period. Doing so, its extensive (and
@@ -123,14 +120,8 @@
<glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
A Checkpoint is a point in time when all older dirty buffers,
all older WAL records, and finally a special Checkpoint record
- are written and flushed to disk. Heap and index files,
- and WAL files are now in sync.
- Older WAL is no longer required. In other words,
- a possibly occurring recovery, which integrates the delta
- information of WAL into heap and index files, will happen
- by replaying only WAL past the last-recorded checkpoint.
- This limits the amount of WAL to be replayed
- during recovery in the event of a crash.
+ are written and flushed to disk.
+ Older WAL files are no longer required to recover the system from a crash.
</para>
<para>
@@ -141,8 +132,10 @@
less common). Options and details are covered
in the backup and restore section (<xref linkend="backup"/>).
For our purposes here, just note that the WAL Archiver process
- can be enabled and configured to run a script on filled WAL
- files — usually to copy them to a remote location.
+ can be enabled and configured to run a script on completed WAL
+ files — usually to copy them to a remote location. Note
+ that when a Checkpoint record is written to the WAL the current
+ file is immediately completed.
</para>
<para>
@@ -163,23 +156,35 @@
<title>The logical Perspective: Cluster, Database, Schema</title>
<para>
- A <glossterm linkend="glossary-server">server</glossterm> contains one or more
- <glossterm linkend="glossary-db-cluster">database clusters</glossterm>
- (<glossterm linkend="glossary-db-cluster">clusters</glossterm>
- for short). Each cluster contains three or more
- <glossterm linkend="glossary-database">databases</glossterm>.
- Each database can contain many
- <glossterm linkend="glossary-schema">schemas</glossterm>.
- A schema can contain
- <glossterm linkend="glossary-table">tables</glossterm>,
+ A <glossterm linkend="glossary-server">Server</glossterm> contains one or more
+ <glossterm linkend="glossary-db-cluster">Database Clusters</glossterm>
+ (<glossterm linkend="glossary-db-cluster">Clusters</glossterm>
+ for short). By default each newly initialized Cluster contains three
+ <glossterm linkend="glossary-database">databases</glossterm>
+ (one interactive and two templates, see <xref linkend="app-initdb"/>).
+ Each database can contain many user-writable
+ <glossterm linkend="glossary-schema">schemas</glossterm>
+ (public, by name and permissiveness, by default), the system
+ generated user-facing schemas <literal>pg_catalog</literal>,
+ <literal>pg_temp</literal>, and <literal>information_schema</literal>,
+ and some more system schemas.
+ <glossterm linkend="glossary-table">Tables</glossterm>,
<glossterm linkend="glossary-view">views</glossterm>, and a lot
- of other objects. Each table or view belongs to a single schema
- only; they cannot belong to another schema as well. The same is
- true for the schema/database and database/cluster relation.
+ of other objects uniquely reside in a single schema.
<xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
this hierarchy.
</para>
+ <para>
+ <!-- is the para helpful at this position? -->
+ Client connections act at the database level and can access
+ its schemas simultaneously. Special techniques like
+ <link linkend="sql-createforeigndatawrapper">foreing data wrapper</link>
+ or <link linkend="dblink">dblink</link> are required
+ to access multiple databases, even within the same Cluster,
+ from a single client connection.
+ </para>
+
<figure id="tutorial-cluster-db-schema-figure">
<title>Cluster, Database, Schema</title>
<mediaobject>
@@ -197,31 +202,30 @@
</figure>
<para>
- A cluster is the outer container for a
+ A Cluster is the outer container for a
collection of databases. Clusters are created by the command
<xref linkend="app-initdb"/>.
</para>
<para>
<literal>template0</literal> is the very first
- database of any cluster. Database <literal>template0</literal>
- is created during the initialization phase of the cluster.
+ database of any Cluster. It
+ is created during the initialization phase of the Cluster.
In a second step, database <literal>template1</literal> is generated
as a copy of <literal>template0</literal>, and finally database
<literal>postgres</literal> is generated as a copy of
<literal>template1</literal>. Any
<glossterm linkend="app-createdb">new databases</glossterm>
- of the cluster that a user might need,
+ of the Cluster that a user might need,
such as <literal>my_db</literal>, will be copied from the
<literal>template1</literal> database. Due to the unique
role of <literal>template0</literal> as the pristine original
- of all other databases, no client can connect to it.
+ of all other databases, no client is allowed to connect to it.
</para>
<para>
- Every database must contain at least one schema because all
<glossterm linkend="glossary-sql-object">SQL Objects</glossterm>
- must be contained in a schema.
+ are contained in a schema.
Schemas are namespaces for SQL objects and ensure
(with one exception) that the SQL object names are used only once within
their scope across all types of SQL objects. E.g., it is not possible
@@ -243,26 +247,46 @@
without using an explicit schema name. <literal>public</literal>
should not contain user-defined SQL objects. Instead, it is
recommended to create a separate schema that holds individual
- objects like application-specific tables or views.
+ objects like application-specific tables or views. To access
+ objects in such a schema they can be fully qualified, e.g.
+ <literal>my_schema.my_table</literal>, or by changing the
+ <link linkend="ddl-schemas-path">schema search path</link>.
+ </para>
+
+ <para>
<literal>pg_catalog</literal> is a schema for all tables and views of the
<glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
- <literal>information_schema</literal> is a schema for several
- tables and views of the System Catalog in a way that conforms
- to the SQL standard.
+ <literal>information_schema</literal> is a similar schema. It
+ contains several tables and views of the System Catalog in a
+ way that conforms to the SQL standard.
</para>
<para>
- There are many different SQL object
- types: <firstterm>database, schema, table, view, materialized
- view, index, constraint, sequence, function, procedure,
- trigger, role, data type, operator, tablespace, extension,
- foreign data wrapper</firstterm>, and more. A few of them, the
+ There are many different SQL object types:
+ <glossterm linkend="glossary-database">database</glossterm>,
+ <glossterm linkend="glossary-schema">schema</glossterm>,
+ <glossterm linkend="glossary-table">table</glossterm>,
+ <glossterm linkend="glossary-view">view</glossterm>,
+ <glossterm linkend="glossary-materialized-view">materialized view</glossterm>,
+ <glossterm linkend="glossary-index">index</glossterm>,
+ <glossterm linkend="glossary-constraint">constraint</glossterm>,
+ <glossterm linkend="glossary-sequence">sequence</glossterm>,
+ <glossterm linkend="glossary-function">function</glossterm>,
+ <glossterm linkend="glossary-procedure">procedure</glossterm>,
+ <glossterm linkend="glossary-trigger">trigger</glossterm>,
+ <glossterm linkend="glossary-role">role</glossterm>,
+ <glossterm linkend="datatype">data type</glossterm>,
+ <glossterm linkend="functions">operator</glossterm>,
+ <glossterm linkend="glossary-tablespace">tablespace</glossterm>,
+ <glossterm linkend="glossary-extension">extension</glossterm>,
+ <glossterm linkend="glossary-foreign-data-wrapper">foreign data wrapper</glossterm>,
+ and more. A few of them, the
<firstterm>Global SQL Objects</firstterm>, are outside of the
strict hierarchy: All <firstterm>database names</firstterm>,
all <firstterm>tablespace names</firstterm>, and all
<firstterm>role names</firstterm> are automatically
- available throughout the cluster, independent from
- the database or schema in which they were defined originally.
+ available throughout the Cluster, not just the database in which
+ the SQL command was executed.
<xref linkend="tutorial-internal-objects-hierarchy-figure"/>
shows the relation between the object types.
</para>
@@ -286,7 +310,7 @@
</sect1>
<sect1 id="tutorial-directories">
- <title>The physical Perspective: Directories and Files</title>
+ <title>The Physical Perspective: Directories and Files</title>
<para>
<productname>PostgreSQL</productname> organizes long-lasting (persistent)
@@ -297,7 +321,7 @@
variable <literal>PGDATA</literal> points to this directory.
The example shown in
<xref linkend="tutorial-directories-figure"/> uses
- <literal>data</literal> as the name of this root directory.
+ <literal>data</literal> as the name of the cluster's root directory.
</para>
<figure id="tutorial-directories-figure">
@@ -317,27 +341,29 @@
</figure>
<para>
- <literal>data</literal> contains many subdirectories and
+ The cluster's root directory contains many subdirectories and
some files, all of which are necessary to store long-lasting
- as well as temporary data. The following paragraphs
- describe the files and subdirectories in
- <literal>data</literal>.
+ as well as temporary data. The root's name can be selected
+ as desired, but the names of its subdirectories and files
+ are more or less fix and detertermined by
+ <productname>PostgreSQL</productname>. The following
+ paragraphs describe the most important subdirectories
+ and files.
</para>
<para>
- <literal>base</literal> is a subdirectory in which one
- subdirectory per database exists. The names of those
+ <literal>base</literal> contains one
+ subdirectory per database. The names of those
subdirectories consist of numbers. These are the internal
Object Identifiers (OID), which are numbers to identify
- the database definition in the
+ their definition in the
<glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
</para>
<para>
- Within the database-specific
- subdirectories, there are many files: one or more for
- every table and every index to store heap and index
- data. Those files are accompanied by files for the
+ Within the database-specific subdirectories of <literal>base</literal>
+ there are many files: one or more for every table
+ and every index. Those files are accompanied by files for the
<link linkend="storage-fsm">Free Space Maps</link>
(suffixed <literal>_fsm</literal>) and
<link linkend="storage-vm">Visibility Maps</link>
@@ -345,20 +371,25 @@
</para>
<para>
- Another subdirectory is <literal>global</literal> which
+ Another subdirectory is <literal>global</literal>. It
contains files with information about
<glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
- One type of such Global SQL Objects are
- <glossterm linkend="glossary-tablespace">tablespaces</glossterm>.
- In <literal>global</literal> there is information about
- the tablespaces; not the tablespaces themselves.
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal>, there are symbolic links
+ that point to directories that are outside of the root
+ directory tree, e.g. at a different disc. Files for tables
+ and indexes of non-default tablespaces reside there. As
+ previously mentioned, those defined within the default
+ tablespace reside in the database-specific subdirectories.
</para>
<para>
The subdirectory <literal>pg_wal</literal> contains the
<glossterm linkend="glossary-wal-file">WAL files</glossterm>.
They arise and grow in parallel with data changes in the
- cluster and remain as long as
+ Cluster and remain as long as
they are required for recovery, archiving, or replication.
</para>
@@ -370,19 +401,14 @@
</para>
<para>
- In <literal>pg_tblspc</literal>, there are symbolic links
- that point to directories containing SQL objects
- that exist within a non-default tablespace.
- </para>
-
- <para>
- In the root directory <literal>data</literal>
+ In the root directory
there are also some files. In many cases, the configuration
- files of the cluster are stored here. If the
- instance is up and running, the file
+ files of the Cluster are stored here. If the
+ Instance is up and running, the file
<literal>postmaster.pid</literal> exists here
+ (by default)
and contains the process ID (pid) of the
- Postmaster which started the instance.
+ Postmaster which started the Instance.
</para>
<para>
@@ -413,8 +439,8 @@
<productname>PostgreSQL</productname> implements a
sophisticated technique which avoids locking:
<firstterm>Multiversion Concurrency Control</firstterm> (MVCC).
- The advantage of MVCC
- over technologies that use row locks becomes evident in multiuser OLTP
+ The advantage of MVCC over technologies that use row locks
+ becomes evident in multiuser Online Transaction Processing (OLTP)
environments with a massive number of concurrent write
actions. There, MVCC generally performs better than solutions
using locks. In a <productname>PostgreSQL</productname>
@@ -439,15 +465,15 @@
</para>
<para>
- When we speak about transaction IDs, you need to know that xids are like
- sequences. Every new transaction receives the next number as its ID.
- Therefore, this flow of xids represents the flow of transaction
- start events over time. But keep in mind that xids are independent of
- any time measurement — in milliseconds or otherwise. If you dive
- deeper into <productname>PostgreSQL</productname>, you will recognize
- parameters with names such as 'xxx_age'. Despite their names,
- these '_age' parameters do not specify a period of time but represent
- a certain number of transactions, e.g., 100 million.
+ Xids are sequences (with a reserved value to handle wrap-around
+ in pre-9.4 <productname>PostgreSQL</productname> versions).
+ Age computations involving them measure a transaction
+ count as opposed to a time interval (in milliseconds or otherwise).
+ If you dive deeper into <productname>PostgreSQL</productname>,
+ you will recognize parameters with names such as 'xxx_age'.
+ Despite their names, these '_age' parameters do not specify
+ a period of time but represent a certain number of transactions,
+ e.g., 100 million.
</para>
<para>
@@ -498,7 +524,7 @@
executes an <command>UPDATE</command> of this row by
changing the user data from <literal>'x'</literal> to
<literal>'y'</literal>. According to the MVCC principles,
- the data in the old version of the row is not changed!
+ the data in the old version of the row is not changed.
The value <literal>'x'</literal> remains as it was before.
Only <literal>xmax</literal> changes to <literal>135</literal>.
Now, this version is treated as valid exclusively for
@@ -526,7 +552,7 @@
<para>
Finally, a row may be deleted by a <command>DELETE</command>
command. Even in this case, all versions of the row remain as
- before. Nothing is thrown away! Only <literal>xmax</literal>
+ before; nothing is thrown away. Only <literal>xmax</literal>
of the last version is set to the xid of the <command>DELETE</command>
transaction, which indicates that (if committed) it is only visible to
transactions with xids older than that (from
@@ -545,7 +571,8 @@
Over time, also the older ones get out of scope
for ALL transactions and therefore become unnecessary.
Nevertheless, they do exist physically on the disk and occupy
- space.
+ space. They are called <firstterm>dead rows</firstterm> and are part
+ of the <glossterm linkend="glossary-bloat">bloat</glossterm>.
</para>
<para>
@@ -560,12 +587,7 @@
<firstterm>row versions</firstterm> are valid (visible) for transactions.
This range doesn't imply any direct temporal meaning;
the sequence of xids reflects only the sequence of
- transaction begin events. As
- xids grow, old row versions get out of scope over time.
- If an old row version is no longer relevant for ANY existing
- transactions, it can be marked <firstterm>dead</firstterm>. The
- space occupied by dead row versions is part of the
- <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ transaction begin events.
</simpara>
</listitem>
@@ -581,9 +603,9 @@
<simpara>
Nothing is removed — with the consequence that the database
occupies more and more disk space. It is obvious that
- this behavior has to be corrected in some
- way. The next chapter explains how <firstterm>autovacuum</firstterm>
- fulfills this task.
+ this behavior has to be corrected in some way. The next
+ chapter explains how <firstterm>vacuum</firstterm> and
+ <firstterm>autovacuum</firstterm> fulfill this task.
</simpara>
</listitem>
@@ -601,12 +623,12 @@
This chapter explains how the SQL command
<command>VACUUM</command> and the automatically running
<firstterm>Autovacuum</firstterm> processes clean up
- and avoid continued growth.
+ and prevent continued growth.
</para>
<note>
<para>
- Autovacuum runs automatically by
+ Autovacuum runs automatically, by
default. Its default parameters as well as those for
<command>VACUUM</command> are appropriate for most standard
situations. Therefore a novice database manager can
@@ -617,11 +639,11 @@
<para>
Client processes can issue the SQL command <command>VACUUM</command>
- at arbitrary points in time. DBAs do this when they recognize
+ at any time. DBAs do this when they recognize
special situations, or they start it in batch jobs which run
- periodically. Autovacuum processes run as part of the
- <link linkend="glossary-instance">Instance</link> at the server.
- There is a constantly running Autovacuum daemon. It continuously
+ periodically. Additionally, there is a constantly running
+ Autovacuum daemon which is part of the
+ <link linkend="glossary-instance">Instance</link>. It continuously
monitors the state of all databases based on values that are collected by the
<link linkend="glossary-stats-collector">Statistics Collector</link>
and starts Autovacuum processes whenever it detects
@@ -1234,7 +1256,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<para>
Lastly, it is worth noticing that changes done by a
committed transaction will survive all failures in the application or
- database cluster. The next chapter explains the
+ the Database Cluster. The next chapter explains the
<glossterm linkend="glossary-durability">durability</glossterm>
guarantees.
</para>
@@ -1276,7 +1298,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<bridgehead renderas="sect3">Instance failure</bridgehead>
<para>
- The instance may suddenly fail because of <emphasis>power off</emphasis>
+ The Instance may suddenly fail because of <emphasis>power off</emphasis>
or other problems. This will affect all running processes, the RAM,
and possibly the consistency of disk files.
</para>
@@ -1284,7 +1306,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<para>
After a restart, <productname>PostgreSQL</productname>
automatically recognizes that the last shutdown of the
- instance did not happen as expected: files might not be
+ Instance did not happen as expected: files might not be
closed properly and the <literal>postmaster.pid</literal>
file unexpectedly exists. <productname>PostgreSQL</productname>
tries to clean up the situation. This is possible because
@@ -1330,7 +1352,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<para>
They obviously need a backup. How to take such a backup
and use it as a starting point for a recovery of the
- cluster is explained in more detail in the next
+ Cluster is explained in more detail in the next
<link linkend="tutorial-backup">chapter</link>.
</para>
@@ -1396,7 +1418,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<para>
You can use any appropriate OS tool to create a
<link linkend="backup-file">copy</link>
- of the cluster's directory structure and files. In
+ of the Cluster's directory structure and files. In
case of severe problems such a copy can serve as
the source of recovery. But in order to get a
<emphasis>USABLE</emphasis> backup by this method,
@@ -1416,7 +1438,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<para>
The tool <command>pg_dump</command> is able to take a
<link linkend="backup-dump">copy</link>
- of the complete cluster or certain parts of it. It stores
+ of the complete Cluster or certain parts of it. It stores
the copy in the form of SQL commands like <command>CREATE</command>
and <command>COPY</command>. It runs in
parallel with other processes, in its own transaction.
@@ -1430,9 +1452,9 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<para>
The main advantage over the other two methods is that it
- can pick parts of the cluster, e.g., a single table or one
+ can pick parts of the Cluster, e.g., a single table or one
database. The other two methods work only at the level of
- the complete cluster.
+ the complete Cluster.
</para>
<bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
@@ -1447,7 +1469,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
<firstterm>basebackup</firstterm> with the tool
<command>pg_basebackup</command>. The result is a
directory structure plus files which contain a
- consistent copy of the original cluster.
+ consistent copy of the original Cluster.
<command>pg_basebackup</command> runs in
parallel with other processes in its own transaction.
</para>
@@ -1456,9 +1478,9 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
The second step is recommended but not necessary. All
changes to the data are stored in WAL files. If you
continuously save such WAL files, you have the history
- of the cluster. This history can be applied to a
+ of the Cluster. This history can be applied to a
basebackup in order to recreate
- any state of the cluster between the time of
+ any state of the Cluster between the time of
<command>pg_basebackup</command>'s start time and
any later point in time. This technique
is called 'Point-in-Time Recovery (PITR)'.
@@ -1478,7 +1500,7 @@ UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
</para>
<para>
- If it becomes necessary to restore the cluster, you have to
+ If it becomes necessary to restore the Cluster, you have to
copy the basebackup and the archived WAL files to
their original directories. The configuration of this
<link linkend="backup-pitr-recovery">recovery procedure</link>
0013-images.difftext/x-patch; charset=UTF-8; name=0013-images.diffDownload
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
index 022bc45560..8534b18ec2 100644
--- a/doc/src/sgml/images/cluster-db-schema-raw.svg
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -36,36 +36,49 @@
<!-- the database -->
<rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_1">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
<!-- schemas -->
<rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
<text class="text_normal" x="20" y="60">schema 'public'</text>
- <text class="text_small" x="20" y="80">tables, views, ...</text>
+ <text class="text_small" x="25" y="80">tables, views, ...</text>
<rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
- <text class="text_small" x="20" y="125">(more system schemas)</text>
+ <text class="text_small" x="20" y="125">System schemas</text>
</symbol>
<!-- same as before, but one more schema -->
- <symbol id="rectangle_special_1">
+ <symbol id="rectangle_special_2">
<!-- the database -->
<rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
<!-- schemas -->
<rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
<text class="text_normal" x="20" y="60">schema 'public'</text>
- <text class="text_small" x="20" y="80">tables, views, ...</text>
+ <text class="text_small" x="25" y="80">tables, views, ...</text>
- <rect x="15" y="105" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
- <text class="text_normal" x="20" y="125">'my_schema' (optional)</text>
- <text class="text_small" x="20" y="145">tables, views, ...</text>
+ <rect x="15" y="105" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">System schemas</text>
- <rect x="15" y="170" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
- <text class="text_small" x="20" y="190">(more system schemas)</text>
+ <rect x="15" y="150" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="170">'my_schema' (optional)</text>
+ <text class="text_small" x="25" y="185">tables, views, ...</text>
</symbol>
- <symbol id="note" stroke="black" fill="lightyellow">
+ <symbol id="note_0" stroke="black" fill="lightyellow">
<title>UML Note</title>
- <path d="M 450,10 v 230 h -450 v -240 h 440 v 10 h 10 l -10,-10" />
+ <path d="M 190,10 v 70 h -190 v -80 h 180 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <symbol id="note_1" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 240 h -450 v -250 h 440 v 10 h 10 l -10,-10" />
</symbol>
<!-- marker start/end -->
@@ -109,23 +122,28 @@
<g transform="translate(40 155)">
<use xlink:href="#rectangle_special_0" />
<text class="text_normal" x="10" y="25">database 'template0'</text>
+ <use xlink:href="#note_0" x="20" y="40" />
+ <text class="text_small" x="30" y="60">'template0' is a pristine</text>
+ <text class="text_small" x="30" y="75">and unchangeable template.</text>
+ <text class="text_small" x="30" y="90">It is used to generate</text>
+ <text class="text_small" x="30" y="105">database 'template1'.</text>
</g>
<!-- database template 1 -->
<g transform="translate(290 155)">
- <use xlink:href="#rectangle_special_0" />
+ <use xlink:href="#rectangle_special_1" />
<text class="text_normal" x="10" y="25">database 'template1'</text>
</g>
<!-- database postgres -->
<g transform="translate(540 155)">
- <use xlink:href="#rectangle_special_1" />
+ <use xlink:href="#rectangle_special_2" />
<text class="text_normal" x="10" y="25">database 'postgres'</text>
</g>
<!-- database my_db -->
<g transform="translate(40 350)">
- <use xlink:href="#rectangle_special_1" />
+ <use xlink:href="#rectangle_special_2" />
<text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
</g>
@@ -133,7 +151,6 @@
<g transform="translate(320 330)">
<rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
<text class="text_normal" x="15" y="27">Global SQL objects</text>
- <path d="M 0,5 l-65,-35" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
<path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
<path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
<path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
@@ -141,32 +158,33 @@
<!-- Some comments -->
<g transform="translate(335 405)">
- <use xlink:href="#note" x="0" y="0" />
+ <use xlink:href="#note_1" x="0" y="0" />
<text class="text_small" x="10" y="20">1)</text>
- <text class="text_small" x="30" y="20">By default, you work in the cluster 'data', database 'postgres',</text>
- <text class="text_small" x="30" y="35">schema 'public'.</text>
-
- <text class="text_small" x="10" y="55">2)</text>
- <text class="text_small" x="30" y="55">More system schemas: pg_catalog, information_schema,</text>
- <text class="text_small" x="30" y="70">pg_temp, pg_toast.</text>
-
- <text class="text_small" x="10" y="90">3)</text>
- <text class="text_small" x="30" y="90">Global SQL objects: Some SQL objects are automatically active</text>
- <text class="text_small" x="30" y="105">and known database- or even cluster-wide.</text>
-
- <text class="text_small" x="10" y="125">4)</text>
- <text class="text_small" x="30" y="125">The command 'initdb' creates a new cluster with the three</text>
- <text class="text_small" x="30" y="140">databases 'template0', 'template1', and 'postgres'. The command</text>
- <text class="text_small" x="30" y="155">'createdb' creates a new database.</text>
-
- <text class="text_small" x="10" y="175">5)</text>
- <text class="text_small" x="30" y="175">If multiple clusters are active on one server at the same time,</text>
- <text class="text_small" x="30" y="190">each one is managed by an individual instance. Each such instance</text>
- <text class="text_small" x="30" y="205">uses a different port.</text>
-
- <text class="text_small" x="10" y="225">6)</text>
- <text class="text_small" x="30" y="225">No client application is allowed to connect to 'template0'.</text>
+ <text class="text_small" x="30" y="20">By default, clients connect via port '5432' to Cluster 'data',</text>
+ <text class="text_small" x="30" y="35">database 'postgres', schema 'public'. Of course, they can</text>
+ <text class="text_small" x="30" y="50">specify other connection properties.</text>
+
+ <text class="text_small" x="10" y="70">2)</text>
+ <text class="text_small" x="30" y="70">System schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="85">pg_temp, ...</text>
+
+ <text class="text_small" x="10" y="105">3)</text>
+ <text class="text_small" x="30" y="105">Global SQL objects: Objects which are shared among all</text>
+ <text class="text_small" x="30" y="120">databases within a Cluster.</text>
+
+ <text class="text_small" x="10" y="140">4)</text>
+ <text class="text_small" x="30" y="140">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="155">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="170">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="190">5)</text>
+ <text class="text_small" x="30" y="190">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="205">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="220">uses a different port.</text>
+
+ <text class="text_small" x="10" y="240">6)</text>
+ <text class="text_small" x="30" y="240">Client application are prohibited from connecting to 'template0'.</text>
</g>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
index 757342a554..5cce551b0c 100644
--- a/doc/src/sgml/images/directories-raw.svg
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -14,6 +14,12 @@
font-family:"Open Sans", sans-serif;
fill:black;
}
+ .text_italic {font-style:italic;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:silver;
+ }
.text_big {font-style:normal;
font-weight:normal;
font-size:24px;
@@ -54,14 +60,14 @@
<!-- the directories -->
<g transform="translate(20, 100)">
<use xlink:href="#directory" />
- <text x="10" y="26" class="text_normal">... /pg/</text>
+ <text x="10" y="26" class="text_italic">/var/lib/pgsql/</text>
<text x="300" y="26" class="text_normal">An arbitrary directory</text>
</g>
<g transform="translate(70, 130)">
<use xlink:href="#directory" />
- <text x="10" y="26" class="text_normal">data/</text>
- <text x="250" y="26" class="text_normal">Root of cluster 'data' (see: PGDATA)</text>
+ <text x="10" y="26" class="text_italic">data/</text>
+ <text x="250" y="26" class="text_normal">Cluster's root directory (with an arbitrary name; see: PGDATA)</text>
</g>
<g transform="translate(120, 160)">
@@ -74,46 +80,46 @@
<g transform="translate(170, 190)">
<use xlink:href="#directory" />
<text x="10" y="26" class="text_normal">1/</text>
- <text x="150" y="26" class="text_normal">Subdirectory for data of first database 'template0'</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data in default-tablespace of first database 'template0'</text>
</g>
<g transform="translate(170, 220)">
<use xlink:href="#directory" />
<text x="10" y="26" class="text_normal">12992/</text>
- <text x="150" y="26" class="text_normal">Subdirectory for data of second database 'template1'</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data in default-tablespace of second database 'template1'</text>
</g>
<g transform="translate(170, 250)">
<use xlink:href="#directory" />
<text x="10" y="26" class="text_normal">12999/</text>
- <text x="150" y="26" class="text_normal">Subdirectory for data of third database 'postgres'</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data in default-tablespace of third database 'postgres'</text>
</g>
<g transform="translate(170, 280)">
<use xlink:href="#directory" />
<text x="10" y="26" class="text_normal">nnnnn/</text>
- <text x="150" y="26" class="text_normal">Optional: more subdirectories for databases, e.g. 'my_db'</text>
+ <text x="150" y="26" class="text_normal">Optional: one subdirectory for each new database, e.g. '23456' for 'my_db'</text>
</g>
<g transform="translate(120, 310)">
<use xlink:href="#directory" />
<text x="10" y="26" class="text_normal">global/</text>
- <text x="200" y="26" class="text_normal">Subdirectory with information about Global SQL Objects</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for information about Global SQL Objects</text>
</g>
<g transform="translate(120, 340)">
<use xlink:href="#directory" />
- <text x="10" y="26" class="text_normal">pg_wal/</text>
- <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for symbolic links to non-default tablespaces</text>
</g>
<g transform="translate(120, 370)">
<use xlink:href="#directory" />
- <text x="10" y="26" class="text_normal">pg_xact/</text>
- <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
</g>
<g transform="translate(120, 400)">
<use xlink:href="#directory" />
- <text x="10" y="26" class="text_normal">pg_tblspc/</text>
- <text x="200" y="26" class="text_normal">Subdirectory containing symbolic links to tablespaces</text>
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
</g>
<g transform="translate(120, 430)">
@@ -131,14 +137,14 @@
<!-- next cluster -->
<g transform="translate(20, 540)">
<use xlink:href="#directory" />
- <text x="10" y="26" class="text_normal">... /xyz/</text>
+ <text x="10" y="26" class="text_italic">...</text>
<text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
</g>
<g transform="translate(70, 570)">
<use xlink:href="#directory" />
- <text x="10" y="26" class="text_normal">cluster_2/</text>
- <text x="250" y="26" class="text_normal">Root of another cluster 'cluster_2'</text>
+ <text x="10" y="26" class="text_italic">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster</text>
</g>
</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
index a58f334fe3..78850283d9 100644
--- a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -26,7 +26,7 @@
<!-- start of rendering area -->
<!-- enclosing rectangle -->
<rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
- <text class="text_big" x="200" y="40">Hierarchy of internal Objects</text>
+ <text class="text_big" x="200" y="40">Hierarchy of Internal Objects</text>
<!-- set centre of figure and default values -->
On 2020-11-15 19:45, Jürgen Purtz wrote:
(smallish) Changes to arch-dev.sgml
Erik
Attachments:
arch-dev.sgml.20201120.difftext/x-diff; name=arch-dev.sgml.20201120.diffDownload
--- ./doc/src/sgml/arch-dev.sgml.orig 2020-11-20 19:14:21.576775798 +0100
+++ ./doc/src/sgml/arch-dev.sgml 2020-11-20 21:43:10.435370787 +0100
@@ -7,7 +7,7 @@
<title>Author</title>
<para>
This chapter originated as part of
- <xref linkend="sim98"/>, Stefan Simkovics'
+ <xref linkend="sim98"/> Stefan Simkovics'
Master's Thesis prepared at Vienna University of Technology under the direction
of O.Univ.Prof.Dr. Georg Gottlob and Univ.Ass. Mag. Katrin Seyr.
</para>
@@ -17,10 +17,7 @@
This chapter gives an overview of the internal structure of the
backend of <productname>PostgreSQL</productname>. After having
read the following sections you should have an idea of how a query
- is processed. This chapter does not aim to provide a detailed
- description of the internal operation of
- <productname>PostgreSQL</productname>, as such a document would be
- very extensive. Rather, this chapter is intended to help the reader
+ is processed. This chapter is intended to help the reader
understand the general sequence of operations that occur within the
backend from the point at which a query is received, to the point
at which the results are returned to the client.
@@ -30,8 +27,8 @@
<title>The Path of a Query</title>
<para>
- Here we give a short overview of the stages a query has to pass in
- order to obtain a result.
+ Here we give a short overview of the stages a query has to pass
+ to obtain a result.
</para>
<procedure>
@@ -125,7 +122,7 @@
use a <firstterm>supervisor process</firstterm> (also
<firstterm>master process</firstterm>) that spawns a new
server process every time a connection is requested. This supervisor
- process is called <literal>postgres</literal> and listens at a
+ process is called <literal>postgres</literal> (formerly 'postmaster') and listens at a
specified TCP/IP port for incoming connections. Whenever a request
for a connection is detected the <literal>postgres</literal>
process spawns a new server process. The server tasks
@@ -230,7 +227,7 @@
<para>
A detailed description of <application>bison</application> or
the grammar rules given in <filename>gram.y</filename> would be
- beyond the scope of this paper. There are many books and
+ beyond the scope of this manual. There are many books and
documents dealing with <application>flex</application> and
<application>bison</application>. You should be familiar with
<application>bison</application> before you start to study the
@@ -343,8 +340,8 @@
<note>
<para>
In some situations, examining each possible way in which a query
- can be executed would take an excessive amount of time and memory
- space. In particular, this occurs when executing queries
+ can be executed would take an excessive amount of time and memory.
+ In particular, this occurs when executing queries
involving large numbers of join operations. In order to determine
a reasonable (not necessarily optimal) query plan in a reasonable amount
of time, <productname>PostgreSQL</productname> uses a <firstterm>Genetic
@@ -411,7 +408,7 @@
<firstterm>merge join</firstterm>: Each relation is sorted on the join
attributes before the join starts. Then the two relations are
scanned in parallel, and matching rows are combined to form
- join rows. This kind of join is more
+ join rows. This kind of join is
attractive because each relation has to be scanned only once.
The required sorting might be achieved either by an explicit sort
step, or by scanning the relation in the proper order using an
@@ -442,7 +439,7 @@
If the query uses fewer than <xref linkend="guc-geqo-threshold"/>
relations, a near-exhaustive search is conducted to find the best
join sequence. The planner preferentially considers joins between any
- two relations for which there exist a corresponding join clause in the
+ two relations for which there exists a corresponding join clause in the
<literal>WHERE</literal> qualification (i.e., for
which a restriction like <literal>where rel1.attr1=rel2.attr2</literal>
exists). Join pairs with no join clause are considered only when there
On 20/11/2020 23:52, Erik Rijkers wrote:
(smallish) Changes to arch-dev.sgml
This looks good to me. One little complaint:
@@ -125,7 +122,7 @@ use a <firstterm>supervisor process</firstterm> (also <firstterm>master process</firstterm>) that spawns a new server process every time a connection is requested. This supervisor - process is called <literal>postgres</literal> and listens at a + process is called <literal>postgres</literal> (formerly 'postmaster') and listens at a specified TCP/IP port for incoming connections. Whenever a request for a connection is detected the <literal>postgres</literal> process spawns a new server process. The server tasks
I believe we still call it the postmaster process. We renamed the binary
a long time ago (commit 5266f221a2), and the above text was changed as
part of that commit. I think that was a mistake, and this should say simply:
... This supervisor process is called <literal>postmaster</literal> and ...
like it did before we renamed the binary.
Barring objections, I'll commit this with that change (as attached).
- Heikki
Attachments:
arch-dev.sgml.20210118-heikki.difftext/x-patch; charset=UTF-8; name=arch-dev.sgml.20210118-heikki.diffDownload
diff --git a/doc/src/sgml/arch-dev.sgml b/doc/src/sgml/arch-dev.sgml
index ade0ad97d8..a27c8477c2 100644
--- a/doc/src/sgml/arch-dev.sgml
+++ b/doc/src/sgml/arch-dev.sgml
@@ -7,7 +7,7 @@
<title>Author</title>
<para>
This chapter originated as part of
- <xref linkend="sim98"/>, Stefan Simkovics'
+ <xref linkend="sim98"/> Stefan Simkovics'
Master's Thesis prepared at Vienna University of Technology under the direction
of O.Univ.Prof.Dr. Georg Gottlob and Univ.Ass. Mag. Katrin Seyr.
</para>
@@ -17,10 +17,7 @@
This chapter gives an overview of the internal structure of the
backend of <productname>PostgreSQL</productname>. After having
read the following sections you should have an idea of how a query
- is processed. This chapter does not aim to provide a detailed
- description of the internal operation of
- <productname>PostgreSQL</productname>, as such a document would be
- very extensive. Rather, this chapter is intended to help the reader
+ is processed. This chapter is intended to help the reader
understand the general sequence of operations that occur within the
backend from the point at which a query is received, to the point
at which the results are returned to the client.
@@ -30,8 +27,8 @@
<title>The Path of a Query</title>
<para>
- Here we give a short overview of the stages a query has to pass in
- order to obtain a result.
+ Here we give a short overview of the stages a query has to pass
+ to obtain a result.
</para>
<procedure>
@@ -125,9 +122,9 @@
use a <firstterm>supervisor process</firstterm> (also
<firstterm>master process</firstterm>) that spawns a new
server process every time a connection is requested. This supervisor
- process is called <literal>postgres</literal> and listens at a
+ process is called <literal>postmaster</literal> and listens at a
specified TCP/IP port for incoming connections. Whenever a request
- for a connection is detected the <literal>postgres</literal>
+ for a connection is detected the <literal>postmaster</literal>
process spawns a new server process. The server tasks
communicate with each other using <firstterm>semaphores</firstterm> and
<firstterm>shared memory</firstterm> to ensure data integrity
@@ -230,7 +227,7 @@
<para>
A detailed description of <application>bison</application> or
the grammar rules given in <filename>gram.y</filename> would be
- beyond the scope of this paper. There are many books and
+ beyond the scope of this manual. There are many books and
documents dealing with <application>flex</application> and
<application>bison</application>. You should be familiar with
<application>bison</application> before you start to study the
@@ -343,8 +340,8 @@
<note>
<para>
In some situations, examining each possible way in which a query
- can be executed would take an excessive amount of time and memory
- space. In particular, this occurs when executing queries
+ can be executed would take an excessive amount of time and memory.
+ In particular, this occurs when executing queries
involving large numbers of join operations. In order to determine
a reasonable (not necessarily optimal) query plan in a reasonable amount
of time, <productname>PostgreSQL</productname> uses a <firstterm>Genetic
@@ -411,7 +408,7 @@
<firstterm>merge join</firstterm>: Each relation is sorted on the join
attributes before the join starts. Then the two relations are
scanned in parallel, and matching rows are combined to form
- join rows. This kind of join is more
+ join rows. This kind of join is
attractive because each relation has to be scanned only once.
The required sorting might be achieved either by an explicit sort
step, or by scanning the relation in the proper order using an
@@ -442,7 +439,7 @@
If the query uses fewer than <xref linkend="guc-geqo-threshold"/>
relations, a near-exhaustive search is conducted to find the best
join sequence. The planner preferentially considers joins between any
- two relations for which there exist a corresponding join clause in the
+ two relations for which there exists a corresponding join clause in the
<literal>WHERE</literal> qualification (i.e., for
which a restriction like <literal>where rel1.attr1=rel2.attr2</literal>
exists). Join pairs with no join clause are considered only when there
On 18.01.21 15:13, Heikki Linnakangas wrote:
On 20/11/2020 23:52, Erik Rijkers wrote:
(smallish) Changes to arch-dev.sgml
This looks good to me. One little complaint:
@@ -125,7 +122,7 @@ use a <firstterm>supervisor process</firstterm> (also <firstterm>master process</firstterm>) that spawns a new server process every time a connection is requested. This supervisor - process is called <literal>postgres</literal> and listens at a + process is called <literal>postgres</literal> (formerly 'postmaster') and listens at a specified TCP/IP port for incoming connections. Whenever a request for a connection is detected the <literal>postgres</literal> process spawns a new server process. The server tasksI believe we still call it the postmaster process. We renamed the
binary a long time ago (commit 5266f221a2), and the above text was
changed as part of that commit. I think that was a mistake, and this
should say simply:... This supervisor process is called <literal>postmaster</literal>
and ...like it did before we renamed the binary.
Barring objections, I'll commit this with that change (as attached).
- Heikki
I fear that the patch 'Additional chapter for Tutorial' grows beyond
manageable limits. It runs since nearly one year, the size of 228 KB is
very huge, many people havemade significant contributions. But a commit
seems to be in far distance. Having said that, I'm pleased with Heikki's
proposal to split changes in the existing file 'arch-dev.sgml' from the
rest of the patch and commit them separately.
But I have some concerns with the chapter '51.2. How Connections Are
Established'. It uses central terms like 'client process', 'server
process','supervisor process', 'master process', 'server tasks',
'backend (server)', 'frontend (client)', 'server', 'client'. Some month
ago, we have cleared his terminology in the new chapter 'glossary'. As
long as it leads to readable text, we shall use the glossary-terms
instead of the current ones. And we shall include some links to the
glossary.
I propose to start a new thread which contains only changes to
'arch-dev.sgml'. In pgsql-hackers or in pgsql-docs list? Initialized by
Heikki or by me?
--
Jürgen Purtz
On 18.01.21 15:13, Heikki Linnakangas wrote:
On 20/11/2020 23:52, Erik Rijkers wrote:
(smallish) Changes to arch-dev.sgml
This looks good to me. One little complaint:
@@ -125,7 +122,7 @@ use a <firstterm>supervisor process</firstterm> (also <firstterm>master process</firstterm>) that spawns a new server process every time a connection is requested. This supervisor - process is called <literal>postgres</literal> and listens at a + process is called <literal>postgres</literal> (formerly 'postmaster') and listens at a specified TCP/IP port for incoming connections. Whenever a request for a connection is detected the <literal>postgres</literal> process spawns a new server process. The server tasksI believe we still call it the postmaster process. We renamed the
binary a long time ago (commit 5266f221a2), and the above text was
changed as part of that commit. I think that was a mistake, and this
should say simply:... This supervisor process is called <literal>postmaster</literal>
and ...like it did before we renamed the binary.
Barring objections, I'll commit this with that change (as attached).
- Heikki
Some additional changes in 51.2:
- smaller number of different terms
- aligning with Glossary
- active voice instead of passive voice
- commas
---
J. Purtz
Attachments:
arch-dev.sgml.20210121.difftext/x-patch; charset=UTF-8; name=arch-dev.sgml.20210121.diffDownload
diff --git a/doc/src/sgml/arch-dev.sgml b/doc/src/sgml/arch-dev.sgml
index ade0ad97d8..7ced927c9d 100644
--- a/doc/src/sgml/arch-dev.sgml
+++ b/doc/src/sgml/arch-dev.sgml
@@ -7,7 +7,7 @@
<title>Author</title>
<para>
This chapter originated as part of
- <xref linkend="sim98"/>, Stefan Simkovics'
+ <xref linkend="sim98"/> Stefan Simkovics'
Master's Thesis prepared at Vienna University of Technology under the direction
of O.Univ.Prof.Dr. Georg Gottlob and Univ.Ass. Mag. Katrin Seyr.
</para>
@@ -17,10 +17,7 @@
This chapter gives an overview of the internal structure of the
backend of <productname>PostgreSQL</productname>. After having
read the following sections you should have an idea of how a query
- is processed. This chapter does not aim to provide a detailed
- description of the internal operation of
- <productname>PostgreSQL</productname>, as such a document would be
- very extensive. Rather, this chapter is intended to help the reader
+ is processed. This chapter is intended to help the reader
understand the general sequence of operations that occur within the
backend from the point at which a query is received, to the point
at which the results are returned to the client.
@@ -30,8 +27,8 @@
<title>The Path of a Query</title>
<para>
- Here we give a short overview of the stages a query has to pass in
- order to obtain a result.
+ Here we give a short overview of the stages a query has to pass
+ to obtain a result.
</para>
<procedure>
@@ -117,21 +114,28 @@
<title>How Connections Are Established</title>
<para>
- <productname>PostgreSQL</productname> is implemented using a
- simple <quote>process per user</quote> client/server model. In this model
- there is one <firstterm>client process</firstterm> connected to
- exactly one <firstterm>server process</firstterm>. As we do not
+ <productname>PostgreSQL</productname> implements a
+ <quote>process per user</quote> client/server model.
+ In this model, every
+ <glossterm linkend="glossary-client">client process</glossterm>
+ connects to exactly one
+ <glossterm linkend="glossary-backend">backend process</glossterm>.
+ As we do not
know ahead of time how many connections will be made, we have to
- use a <firstterm>supervisor process</firstterm> (also
- <firstterm>master process</firstterm>) that spawns a new
- server process every time a connection is requested. This supervisor
- process is called <literal>postgres</literal> and listens at a
- specified TCP/IP port for incoming connections. Whenever a request
- for a connection is detected the <literal>postgres</literal>
- process spawns a new server process. The server tasks
- communicate with each other using <firstterm>semaphores</firstterm> and
- <firstterm>shared memory</firstterm> to ensure data integrity
- throughout concurrent data access.
+ use a <quote>supervisor process</quote>
+ that spawns a new
+ backend process every time a connection is requested. This supervisor
+ process is called
+ <glossterm linkend="glossary-postmaster">postmaster</glossterm>
+ and listens at a
+ specified TCP/IP port for incoming connections. Whenever he detects
+ a request for a connection, he spawns a new backend process.
+ Those backend processes communicate with each other and with other
+ processes of the
+ <glossterm linkend="glossary-instance">instance</glossterm>
+ using <firstterm>semaphores</firstterm> and
+ <glossterm linkend="glossary-shared-memory">shared memory</glossterm>
+ to ensure data integrity throughout concurrent data access.
</para>
<para>
@@ -144,11 +148,11 @@
</para>
<para>
- Once a connection is established the client process can send a query
- to the <firstterm>backend</firstterm> (server). The query is transmitted using plain text,
- i.e., there is no parsing done in the <firstterm>frontend</firstterm> (client). The
- server parses the query, creates an <firstterm>execution plan</firstterm>,
- executes the plan and returns the retrieved rows to the client
+ Once a connection is established, the client process can send a query
+ to his backend process. The query is transmitted using plain text,
+ i.e., there is no parsing done in the client. The backend
+ process parses the query, creates an <firstterm>execution plan</firstterm>,
+ executes the plan, and returns the retrieved rows to the client
by transmitting them over the established connection.
</para>
</sect1>
@@ -230,7 +234,7 @@
<para>
A detailed description of <application>bison</application> or
the grammar rules given in <filename>gram.y</filename> would be
- beyond the scope of this paper. There are many books and
+ beyond the scope of this manual. There are many books and
documents dealing with <application>flex</application> and
<application>bison</application>. You should be familiar with
<application>bison</application> before you start to study the
@@ -343,8 +347,8 @@
<note>
<para>
In some situations, examining each possible way in which a query
- can be executed would take an excessive amount of time and memory
- space. In particular, this occurs when executing queries
+ can be executed would take an excessive amount of time and memory.
+ In particular, this occurs when executing queries
involving large numbers of join operations. In order to determine
a reasonable (not necessarily optimal) query plan in a reasonable amount
of time, <productname>PostgreSQL</productname> uses a <firstterm>Genetic
@@ -411,7 +415,7 @@
<firstterm>merge join</firstterm>: Each relation is sorted on the join
attributes before the join starts. Then the two relations are
scanned in parallel, and matching rows are combined to form
- join rows. This kind of join is more
+ join rows. This kind of join is
attractive because each relation has to be scanned only once.
The required sorting might be achieved either by an explicit sort
step, or by scanning the relation in the proper order using an
@@ -442,7 +446,7 @@
If the query uses fewer than <xref linkend="guc-geqo-threshold"/>
relations, a near-exhaustive search is conducted to find the best
join sequence. The planner preferentially considers joins between any
- two relations for which there exist a corresponding join clause in the
+ two relations for which there exists a corresponding join clause in the
<literal>WHERE</literal> qualification (i.e., for
which a restriction like <literal>where rel1.attr1=rel2.attr2</literal>
exists). Join pairs with no join clause are considered only when there
On 21/01/2021 14:38, Jürgen Purtz wrote:
This supervisor process is called <glossterm
linkend="glossary-postmaster">postmaster</glossterm> and listens at
a specified TCP/IP port for incoming connections. Whenever he
detects a request for a connection, he spawns a new backend process.
It sounds weird to refer to a process with "he". I left out this hunk,
and the other with similar changes.
Committed the rest, thanks!.
- Heikki
On 1/22/21 4:15 AM, Heikki Linnakangas wrote:
On 21/01/2021 14:38, Jürgen Purtz wrote:
This supervisor process is called <glossterm
linkend="glossary-postmaster">postmaster</glossterm> and listens at
a specified TCP/IP port for incoming connections. Whenever he
detects a request for a connection, he spawns a new backend process.It sounds weird to refer to a process with "he". I left out this hunk,
and the other with similar changes.Committed the rest, thanks!.
So it looks like this was committed. Is there anything left to do?
If not, we should close the CF entry.
Regards,
--
-David
david@pgmasters.net
On 2021-Mar-25, David Steele wrote:
On 1/22/21 4:15 AM, Heikki Linnakangas wrote:
On 21/01/2021 14:38, J�rgen Purtz wrote:
This supervisor process is called <glossterm
linkend="glossary-postmaster">postmaster</glossterm> and listens at
a specified TCP/IP port for incoming connections. Whenever he
detects a request for a connection, he spawns a new backend process.It sounds weird to refer to a process with "he". I left out this hunk,
and the other with similar changes.Committed the rest, thanks!.
So it looks like this was committed. Is there anything left to do?
Yes, there is. AFAICS Heikki committed a small wordsmithing patch --
not the large patch with the additional chapter.
--
�lvaro Herrera 39�49'30"S 73�17'W
"Ed is the standard text editor."
http://groups.google.com/group/alt.religion.emacs/msg/8d94ddab6a9b0ad3
On 03.04.21 15:39, Alvaro Herrera wrote:
Yes, there is. AFAICS Heikki committed a small wordsmithing patch --
not the large patch with the additional chapter.
What can i do to move the matter forward?
--
J. Purtz
On 2021-Apr-03, J�rgen Purtz wrote:
On 03.04.21 15:39, Alvaro Herrera wrote:
Yes, there is. AFAICS Heikki committed a small wordsmithing patch --
not the large patch with the additional chapter.What can i do to move the matter forward?
Please post a version that applies to the current sources. If the
latest version posted does, please state so.
--
�lvaro Herrera 39�49'30"S 73�17'W
On 03.04.21 21:01, Alvaro Herrera wrote:
On 2021-Apr-03, Jürgen Purtz wrote:
On 03.04.21 15:39, Alvaro Herrera wrote:
Yes, there is. AFAICS Heikki committed a small wordsmithing patch --
not the large patch with the additional chapter.What can i do to move the matter forward?
Please post a version that applies to the current sources. If the
latest version posted does, please state so.
The small patch 'arch-dev.sgml.20210121.diff' contains only some
clearing up concerning the used terminology and its alignments with the
glossary. The patch was rejected by Heikki.
The latest version of the huge patch '0013-architecture.patch' is valid
and doesn't contain merge conflicts.
--
Jürgen Purtz
On 2021-Apr-04, J�rgen Purtz wrote:
The small patch 'arch-dev.sgml.20210121.diff' contains only some clearing up
concerning the used terminology and its alignments with the glossary. The
patch was rejected by Heikki.
This comment is not helpful, because it's not obvious where would I find
that patch. Also, you say "the patch was rejected by Heikki" but
upthread he said he committed it. His comment was that he left out some
paragraphs because of a style issue. Did you re-post that patch after
fixing the style issues? If you did, I couldn't find it.
The latest version of the huge patch '0013-architecture.patch' is valid and
doesn't contain merge conflicts.
Yeah, OK, but I have to dive deep in the thread to find it. Please post
it again. When you have a patch series, please post it as a whole every
time -- that makes it easier for a committer to review it.
You seem to be making your life hard by not using git to assist you. Do
you know you can have several commits in a branch of your own, rebase it
to latest master, merge master to it, rebase on top of master, commit
fixups, "rebase -i" and change commit ordering to remove unnecessary
fixup commits, and so on? Such techniques are extremely helpful when
dealing with a patch series. When you want to post a new version to the
list, you can just do "git format-patch -v14 origin/master" to produce a
set of patch files. You don't need to manually give names to your patch
files, or come up with a versioning scheme. Just increment the argument
to -v by +1 each time you (or somebody else) posts a new version of the
patch series.
--
�lvaro Herrera Valdivia, Chile
On 04.04.21 19:02, Alvaro Herrera wrote:
On 2021-Apr-04, Jürgen Purtz wrote:
The small patch 'arch-dev.sgml.20210121.diff' contains only some clearing up
concerning the used terminology and its alignments with the glossary. The
patch was rejected by Heikki.This comment is not helpful, because it's not obvious where would I find
that patch. Also, you say "the patch was rejected by Heikki" but
upthread he said he committed it. His comment was that he left out some
paragraphs because of a style issue. Did you re-post that patch after
fixing the style issues? If you did, I couldn't find it.The latest version of the huge patch '0013-architecture.patch' is valid and
doesn't contain merge conflicts.Yeah, OK, but I have to dive deep in the thread to find it. Please post
it again. When you have a patch series, please post it as a whole every
time -- that makes it easier for a committer to review it.You seem to be making your life hard by not using git to assist you. Do
you know you can have several commits in a branch of your own, rebase it
to latest master, merge master to it, rebase on top of master, commit
fixups, "rebase -i" and change commit ordering to remove unnecessary
fixup commits, and so on? Such techniques are extremely helpful when
dealing with a patch series. When you want to post a new version to the
list, you can just do "git format-patch -v14 origin/master" to produce a
set of patch files. You don't need to manually give names to your patch
files, or come up with a versioning scheme. Just increment the argument
to -v by +1 each time you (or somebody else) posts a new version of the
patch series.
The thread contains a sequence of files '0001_architecture.patch' to
'0013_architecture.patch' (with gaps in the numbering) created by me and
other authors over the last 12 month. This is what I call the 'huge
patch'. Indeed, the files are created more or less manually without the
format-patch option. I welcome the reference to rebase and format-patch
and I'm considering to use it in the future.
In addition to this chain Erik introduced in November within the same
thread some changes to the chapter "Overview of Query Handling", which
subsequently was expanded by Heikki and me with the sequence of
'arch-dev.sgml.xxxxx.diff' files. This is what I call the 'small patch'.
It's independent from the 'huge patch'. That 'small patch' is partly
committed by Heikki. In case that a committer gives the uncommitted part
a second chance, I append a patch. Because I'm not a native English
speaker, every improvement in the linguistic is highly welcome.
--
Jürgen Purtz
Attachments:
0013-architecture.patchtext/x-patch; charset=UTF-8; name=0013-architecture.patchDownload
diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml
index 2d4ab85d45..5c3245c0ec 100644
--- a/doc/src/sgml/advanced.sgml
+++ b/doc/src/sgml/advanced.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/advanced.sgml -->
<chapter id="tutorial-advanced">
- <title>Advanced Features</title>
+ <title>Advanced SQL Features</title>
<sect1 id="tutorial-advanced-intro">
<title>Introduction</title>
diff --git a/doc/src/sgml/arch-dev.sgml b/doc/src/sgml/arch-dev.sgml
index 7883c3cd82..9db0ae2c78 100644
--- a/doc/src/sgml/arch-dev.sgml
+++ b/doc/src/sgml/arch-dev.sgml
@@ -1,7 +1,7 @@
<!-- doc/src/sgml/arch-dev.sgml -->
<chapter id="overview">
- <title>Overview of PostgreSQL Internals</title>
+ <title>Overview of Query Handling</title>
<note>
<title>Author</title>
diff --git a/doc/src/sgml/architecture.sgml b/doc/src/sgml/architecture.sgml
new file mode 100644
index 0000000000..4bbd6abb8a
--- /dev/null
+++ b/doc/src/sgml/architecture.sgml
@@ -0,0 +1,1524 @@
+<!-- doc/src/sgml/architecture.sgml -->
+
+ <chapter id="tutorial-architecture">
+ <title>Overview of Architecture and Implementation</title>
+
+ <para>
+ Every DBMS implements basic strategies to ensure a fast
+ and robust system. This chapter provides an overview of the
+ basic techniques <productname>PostgreSQL</productname> uses to
+ achieve this aim. It does not offer anything which exceeds
+ the information content of other pages. Instead, it tries to
+ explain <emphasis>why</emphasis> certain implementation
+ decisions have been taken.
+ </para>
+
+ <sect1 id="tutorial-ram-proc-file">
+ <title>Collaboration of Processes, RAM, and Files</title>
+ <para>
+ In a client/server architecture clients do not have direct access
+ to database files and the data stored in them. Instead, they send
+ requests to the server and receive the requested data in the response.
+ In the case of <productname>PostgreSQL</productname>, the server
+ launches a single process for each client connection, referred to as a
+ <glossterm linkend="glossary-backend">Backend</glossterm> process.
+ Such a Backend process handles the client's requests by acting on the
+ <glossterm linkend="glossary-shared-memory">Shared Memory</glossterm>.
+ This leads to other activities (file access, WAL, vacuum, ...) of the
+ <glossterm linkend="glossary-instance">Instance</glossterm>. The
+ Instance is a group of server-side processes acting on a common
+ Shared Memory. PostgreSQL does not use threading.
+ </para>
+
+ <para>
+ All aspects of an Instance are launched and managed using a single primary
+ process termed the
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ It loads configuration files, allocates Shared Memory, and
+ starts the other collaborating processes of the Instance:
+ <glossterm linkend="glossary-background-writer">Background Writer</glossterm>,
+ <glossterm linkend="glossary-checkpointer">Checkpointer</glossterm>,
+ <glossterm linkend="glossary-wal-writer">WAL Writer</glossterm>,
+ <glossterm linkend="glossary-wal-archiver">WAL Archiver</glossterm>,
+ <glossterm linkend="glossary-autovacuum">Autovacuum</glossterm>,
+ <glossterm linkend="glossary-stats-collector">Statistics Collector</glossterm>,
+ <glossterm linkend="glossary-logger">Logger</glossterm>, and more.
+ Later, the Postmaster listens on its configured system port and in response
+ to client connection attempts launches
+ <glossterm linkend="glossary-backend">Backend</glossterm> processes
+ to which it delegates authentication, communication, and the handling of their requests.
+ <xref linkend="tutorial-ram-proc-file-figure"/> visualizes the processes
+ of an Instance and the main aspects of their collaboration.
+ </para>
+
+ <figure id="tutorial-ram-proc-file-figure">
+ <title>Architecture</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/ram-proc-file-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ Client requests like <command>SELECT</command> or
+ <command>UPDATE</command> usually lead to the
+ necessity to read or write data. This is carried out
+ by the client's backend process. Reads involve a page-level
+ cache, located in Shared Memory (for details see:
+ <xref linkend="sysvipc"/>) for the benefit of all processes
+ in the Instance. Writes also use this cache, in addition
+ to a journal, called the write-ahead-log or WAL.
+ </para>
+
+ <para>
+ Shared Memory is limited in size and it can become necessary
+ to evict pages. As long as the content of such pages hasn't
+ changed, this is not a problem. But writes directly modify
+ the pages in Shared Memory. Modified pages are called dirty
+ pages (or dirty buffers) and before they can be evicted they
+ must be written to disk. This happens regularly by the
+ Checkpointer and the Background Writer processes to ensure
+ that the disk version of the pages are up-to-date.
+ The synchronization from RAM to disk consists of two steps.
+ </para>
+
+ <para>
+ First, whenever the content of a page changes, a
+ <glossterm linkend="glossary-wal-record">WAL record</glossterm>
+ is created from the delta-information (difference between the
+ old and the new content) and stored in another area of
+ Shared Memory. The concurrently running WAL Writer process
+ reads them and appends them to the end of the current
+ <glossterm linkend="glossary-wal-record">WAL file</glossterm>.
+ Such sequential writes are faster than writes to random
+ positions of heap and index files. All WAL records created
+ from one dirty page must be transferred to disk before the
+ dirty page itself can be transferred to disk in the second step.
+ </para>
+
+ <para>
+ Second, the Instance transfers dirty buffers from Shared Memory to
+ files. This is the primary task of the
+ Background Writer process. Because I/O activities can block
+ other processes, it starts periodically and
+ acts only for a short period. Doing so, its extensive (and
+ expensive) I/O activities are spread over time, avoiding
+ debilitating I/O peaks. The Checkpointer process
+ also transfers dirty buffers to file.
+ </para>
+
+ <para>
+ The Checkpointer process creates
+ <glossterm linkend="glossary-checkpoint">Checkpoints</glossterm>.
+ A Checkpoint is a point in time when all older dirty buffers,
+ all older WAL records, and finally a special Checkpoint record
+ are written and flushed to disk.
+ Older WAL files are no longer required to recover the system from a crash.
+ </para>
+
+ <para>
+ While the Checkpointer ensures that the database system can,
+ after a crash, restart itself in a valid state, the administrator needs
+ to handle the case where the heap or other files become
+ corrupted (and possibly the locally written WAL, though that is
+ less common). Options and details are covered
+ in the backup and restore section (<xref linkend="backup"/>).
+ For our purposes here, just note that the WAL Archiver process
+ can be enabled and configured to run a script on completed WAL
+ files — usually to copy them to a remote location. Note
+ that when a Checkpoint record is written to the WAL the current
+ file is immediately completed.
+ </para>
+
+ <para>
+ The Statistics Collector collects counters about access to
+ SQL objects like tables, rows, indexes, pages, and more. It
+ stores the obtained information in system tables.
+ </para>
+
+ <para>
+ The Logger writes text lines about serious and less serious
+ events that may happen during database access, e.g., wrong
+ password, no permission, long-running queries, etc.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-cluster-db-schema">
+ <title>The logical Perspective: Cluster, Database, Schema</title>
+
+ <para>
+ A <glossterm linkend="glossary-server">Server</glossterm> contains one or more
+ <glossterm linkend="glossary-db-cluster">Database Clusters</glossterm>
+ (<glossterm linkend="glossary-db-cluster">Clusters</glossterm>
+ for short). By default each newly initialized Cluster contains three
+ <glossterm linkend="glossary-database">databases</glossterm>
+ (one interactive and two templates, see <xref linkend="app-initdb"/>).
+ Each database can contain many user-writable
+ <glossterm linkend="glossary-schema">schemas</glossterm>
+ (public, by name and permissiveness, by default), the system
+ generated user-facing schemas <literal>pg_catalog</literal>,
+ <literal>pg_temp</literal>, and <literal>information_schema</literal>,
+ and some more system schemas.
+ <glossterm linkend="glossary-table">Tables</glossterm>,
+ <glossterm linkend="glossary-view">views</glossterm>, and a lot
+ of other objects uniquely reside in a single schema.
+ <xref linkend="tutorial-cluster-db-schema-figure"/> visualizes
+ this hierarchy.
+ </para>
+
+ <para>
+ <!-- is the para helpful at this position? -->
+ Client connections act at the database level and can access
+ its schemas simultaneously. Special techniques like
+ <link linkend="sql-createforeigndatawrapper">foreing data wrapper</link>
+ or <link linkend="dblink">dblink</link> are required
+ to access multiple databases, even within the same Cluster,
+ from a single client connection.
+ </para>
+
+ <figure id="tutorial-cluster-db-schema-figure">
+ <title>Cluster, Database, Schema</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/cluster-db-schema-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ A Cluster is the outer container for a
+ collection of databases. Clusters are created by the command
+ <xref linkend="app-initdb"/>.
+ </para>
+
+ <para>
+ <literal>template0</literal> is the very first
+ database of any Cluster. It
+ is created during the initialization phase of the Cluster.
+ In a second step, database <literal>template1</literal> is generated
+ as a copy of <literal>template0</literal>, and finally database
+ <literal>postgres</literal> is generated as a copy of
+ <literal>template1</literal>. Any
+ <glossterm linkend="app-createdb">new databases</glossterm>
+ of the Cluster that a user might need,
+ such as <literal>my_db</literal>, will be copied from the
+ <literal>template1</literal> database. Due to the unique
+ role of <literal>template0</literal> as the pristine original
+ of all other databases, no client is allowed to connect to it.
+ </para>
+
+ <para>
+ <glossterm linkend="glossary-sql-object">SQL Objects</glossterm>
+ are contained in a schema.
+ Schemas are namespaces for SQL objects and ensure
+ (with one exception) that the SQL object names are used only once within
+ their scope across all types of SQL objects. E.g., it is not possible
+ to have a table <literal>employee</literal> and a view
+ <literal>employee</literal> within the same schema. But it is
+ possible to have two tables <literal>employee</literal> in two
+ different schemas. In this case, the two tables
+ are separate objects and independent of each
+ other. The only exception to this cross-type uniqueness is that
+ <glossterm linkend="glossary-unique-constraint">unique constraints
+ </glossterm> and the according unique index
+ (<xref linkend="indexes-unique"/>) use the same name.
+ </para>
+
+ <para>
+ Some schemas are predefined. <literal>public</literal>
+ acts as the default schema and contains all SQL objects
+ which are created within <literal>public</literal> or
+ without using an explicit schema name. <literal>public</literal>
+ should not contain user-defined SQL objects. Instead, it is
+ recommended to create a separate schema that holds individual
+ objects like application-specific tables or views. To access
+ objects in such a schema they can be fully qualified, e.g.
+ <literal>my_schema.my_table</literal>, or by changing the
+ <link linkend="ddl-schemas-path">schema search path</link>.
+ </para>
+
+ <para>
+ <literal>pg_catalog</literal> is a schema for all tables and views of the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ <literal>information_schema</literal> is a similar schema. It
+ contains several tables and views of the System Catalog in a
+ way that conforms to the SQL standard.
+ </para>
+
+ <para>
+ There are many different SQL object types:
+ <glossterm linkend="glossary-database">database</glossterm>,
+ <glossterm linkend="glossary-schema">schema</glossterm>,
+ <glossterm linkend="glossary-table">table</glossterm>,
+ <glossterm linkend="glossary-view">view</glossterm>,
+ <glossterm linkend="glossary-materialized-view">materialized view</glossterm>,
+ <glossterm linkend="glossary-index">index</glossterm>,
+ <glossterm linkend="glossary-constraint">constraint</glossterm>,
+ <glossterm linkend="glossary-sequence">sequence</glossterm>,
+ <glossterm linkend="glossary-function">function</glossterm>,
+ <glossterm linkend="glossary-procedure">procedure</glossterm>,
+ <glossterm linkend="glossary-trigger">trigger</glossterm>,
+ <glossterm linkend="glossary-role">role</glossterm>,
+ <glossterm linkend="datatype">data type</glossterm>,
+ <glossterm linkend="functions">operator</glossterm>,
+ <glossterm linkend="glossary-tablespace">tablespace</glossterm>,
+ <glossterm linkend="glossary-extension">extension</glossterm>,
+ <glossterm linkend="glossary-foreign-data-wrapper">foreign data wrapper</glossterm>,
+ and more. A few of them, the
+ <firstterm>Global SQL Objects</firstterm>, are outside of the
+ strict hierarchy: All <firstterm>database names</firstterm>,
+ all <firstterm>tablespace names</firstterm>, and all
+ <firstterm>role names</firstterm> are automatically
+ available throughout the Cluster, not just the database in which
+ the SQL command was executed.
+ <xref linkend="tutorial-internal-objects-hierarchy-figure"/>
+ shows the relation between the object types.
+ </para>
+
+ <figure id="tutorial-internal-objects-hierarchy-figure">
+ <title>Hierarchy of Internal Objects</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/internal-objects-hierarchy-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ </sect1>
+
+ <sect1 id="tutorial-directories">
+ <title>The Physical Perspective: Directories and Files</title>
+
+ <para>
+ <productname>PostgreSQL</productname> organizes long-lasting (persistent)
+ data as well as volatile state information about transactions
+ or replication actions in the file system. Every
+ <xref linkend="glossary-db-cluster"/> has its root directory
+ somewhere in the file system. In many cases, the environment
+ variable <literal>PGDATA</literal> points to this directory.
+ The example shown in
+ <xref linkend="tutorial-directories-figure"/> uses
+ <literal>data</literal> as the name of the cluster's root directory.
+ </para>
+
+ <figure id="tutorial-directories-figure">
+ <title>Directory Structure</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/directories-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ The cluster's root directory contains many subdirectories and
+ some files, all of which are necessary to store long-lasting
+ as well as temporary data. The root's name can be selected
+ as desired, but the names of its subdirectories and files
+ are more or less fix and detertermined by
+ <productname>PostgreSQL</productname>. The following
+ paragraphs describe the most important subdirectories
+ and files.
+ </para>
+
+ <para>
+ <literal>base</literal> contains one
+ subdirectory per database. The names of those
+ subdirectories consist of numbers. These are the internal
+ Object Identifiers (OID), which are numbers to identify
+ their definition in the
+ <glossterm linkend="glossary-system-catalog">System Catalog</glossterm>.
+ </para>
+
+ <para>
+ Within the database-specific subdirectories of <literal>base</literal>
+ there are many files: one or more for every table
+ and every index. Those files are accompanied by files for the
+ <link linkend="storage-fsm">Free Space Maps</link>
+ (suffixed <literal>_fsm</literal>) and
+ <link linkend="storage-vm">Visibility Maps</link>
+ (suffixed <literal>_vm</literal>), which contain optimization information.
+ </para>
+
+ <para>
+ Another subdirectory is <literal>global</literal>. It
+ contains files with information about
+ <glossterm linkend="glossary-sql-object">Global SQL Objects</glossterm>.
+ </para>
+
+ <para>
+ In <literal>pg_tblspc</literal>, there are symbolic links
+ that point to directories that are outside of the root
+ directory tree, e.g. at a different disc. Files for tables
+ and indexes of non-default tablespaces reside there. As
+ previously mentioned, those defined within the default
+ tablespace reside in the database-specific subdirectories.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_wal</literal> contains the
+ <glossterm linkend="glossary-wal-file">WAL files</glossterm>.
+ They arise and grow in parallel with data changes in the
+ Cluster and remain as long as
+ they are required for recovery, archiving, or replication.
+ </para>
+
+ <para>
+ The subdirectory <literal>pg_xact</literal> contains
+ information about the status of each transaction:
+ <literal>in_progress</literal>, <literal>committed</literal>,
+ <literal>aborted</literal>, or <literal>sub_committed</literal>.
+ </para>
+
+ <para>
+ In the root directory
+ there are also some files. In many cases, the configuration
+ files of the Cluster are stored here. If the
+ Instance is up and running, the file
+ <literal>postmaster.pid</literal> exists here
+ (by default)
+ and contains the process ID (pid) of the
+ Postmaster which started the Instance.
+ </para>
+
+ <para>
+ For more details about the physical implementation
+ of database objects, see <xref linkend="storage"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-mvcc">
+ <title>MVCC — Multiversion Concurrency Control</title>
+
+ <para>
+ In most cases, <productname>PostgreSQL</productname> databases
+ support many clients at the same time which makes it necessary to
+ protect concurrently running requests from unwanted overwriting
+ of other's data as well as from reading inconsistent data. Imagine an
+ online shop offering the last copy of an article. Two clients have the
+ article displayed at their user interface. After a while, but at the same time,
+ both users decide to put it to their shopping cart or even to buy it.
+ Both have seen the article, but only one can be allowed to get it.
+ The database must bring the two requests in a row, permit the access
+ to one of them, block the other, and inform the blocked client
+ that the data was changed by a different process.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> implements a
+ sophisticated technique which avoids locking:
+ <firstterm>Multiversion Concurrency Control</firstterm> (MVCC).
+ The advantage of MVCC over technologies that use row locks
+ becomes evident in multiuser Online Transaction Processing (OLTP)
+ environments with a massive number of concurrent write
+ actions. There, MVCC generally performs better than solutions
+ using locks. In a <productname>PostgreSQL</productname>
+ database, reading never blocks writing and writing never
+ blocks reading, even in the strictest level of transaction
+ isolation.
+ </para>
+
+ <para>
+ Instead of locking rows, the <firstterm>MVCC</firstterm> technique creates
+ a new version of the row when a data-change takes place. To
+ distinguish between these two versions, and to track the timeline
+ of the row, each of the versions contains, in addition to their user-defined
+ columns, two special system columns, which are not visible
+ for the usual <command>SELECT * FROM ...</command> command.
+ The column <literal>xmin</literal> contains the transaction ID (xid)
+ of the transaction which created this version of the row.
+ <literal>xmax</literal> contains the xid of the transaction which has
+ deleted this version, or zero if the version is not
+ deleted. You can read both with the command
+ <command>SELECT xmin, xmax, * FROM ... </command>.
+ </para>
+
+ <para>
+ Xids are sequences (with a reserved value to handle wrap-around
+ in pre-9.4 <productname>PostgreSQL</productname> versions).
+ Age computations involving them measure a transaction
+ count as opposed to a time interval (in milliseconds or otherwise).
+ If you dive deeper into <productname>PostgreSQL</productname>,
+ you will recognize parameters with names such as 'xxx_age'.
+ Despite their names, these '_age' parameters do not specify
+ a period of time but represent a certain number of transactions,
+ e.g., 100 million.
+ </para>
+
+ <para>
+ The description in this chapter simplifies by omitting details.
+ When many transactions are running simultaneously, things can
+ get complicated. Sometimes transactions are aborted via
+ <command>ROLLBACK</command> immediately or after a lot of other activities, sometimes
+ a single row is involved in more than one transaction, sometimes
+ a client crashes, sometimes the sequence of xids restarts
+ from zero, ... . Therefore, every version of a row contains more
+ system columns and flags, not only <literal>xmin</literal>
+ and <literal>xmax</literal>.
+ </para>
+
+ <para>
+ So, what's going on in detail when write access takes place?
+ <xref linkend="tutorial-mvcc-figure"/> shows details concerning
+ <literal>xmin</literal>, <literal>xmax</literal>, and user data.
+ </para>
+
+ <figure id="tutorial-mvcc-figure">
+ <title>Multiversion Concurrency Control</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <imagedata fileref="images/mvcc-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <para>
+ An <command>INSERT</command> command creates the first
+ version of a row. Besides its user data <literal>'x'</literal>,
+ this version contains the ID of the creating transaction
+ <literal>123</literal> in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ <literal>xmin</literal> indicates that the version
+ exists since transaction <literal>123</literal> and
+ <literal>xmax</literal> that it is currently not deleted.
+ </para>
+
+ <para>
+ Somewhat later, transaction <literal>135</literal>
+ executes an <command>UPDATE</command> of this row by
+ changing the user data from <literal>'x'</literal> to
+ <literal>'y'</literal>. According to the MVCC principles,
+ the data in the old version of the row is not changed.
+ The value <literal>'x'</literal> remains as it was before.
+ Only <literal>xmax</literal> changes to <literal>135</literal>.
+ Now, this version is treated as valid exclusively for
+ transactions with xids from <literal>123</literal> to
+ <literal>134</literal>. In addition to the non-occurring
+ data change in the old version, the <command>UPDATE</command>
+ creates a new version of the row with its xid in
+ <literal>xmin</literal>, <literal>0</literal> in
+ <literal>xmax</literal>, and <literal>'y'</literal> in the
+ user data (plus all other user data from the old version).
+ This new row version is visible to all future transactions.
+ (Internally, an <command>UPDATE</command> command acts
+ as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.)
+ </para>
+
+ <para>
+ All subsequent <command>UPDATE</command> commands behave
+ in the same way as the first one: they put their xid in
+ <literal>xmax</literal> of the current version, create
+ a new version with their xid in <literal>xmin</literal> and
+ <literal>0</literal> in <literal>xmax</literal>.
+ </para>
+
+ <para>
+ Finally, a row may be deleted by a <command>DELETE</command>
+ command. Even in this case, all versions of the row remain as
+ before; nothing is thrown away. Only <literal>xmax</literal>
+ of the last version is set to the xid of the <command>DELETE</command>
+ transaction, which indicates that (if committed) it is only visible to
+ transactions with xids older than that (from
+ <literal>142</literal> to <literal>820</literal> in this
+ example).
+ </para>
+
+ <para>
+ In summary, the MVCC technology creates more and more versions
+ of the same row in the table's heap file and leaves them there,
+ even after a <command>DELETE</command> command. Only the youngest
+ version is relevant for all future transactions. But the
+ system must also preserve some of the older ones for
+ awhile, because they could still be needed by
+ transactions which started before the deleting transaction commits.
+ Over time, also the older ones get out of scope
+ for ALL transactions and therefore become unnecessary.
+ Nevertheless, they do exist physically on the disk and occupy
+ space. They are called <firstterm>dead rows</firstterm> and are part
+ of the <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ </para>
+
+ <para>
+ Keep in mind:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> and <literal>xmax</literal>
+ indicate the range in which
+ <firstterm>row versions</firstterm> are valid (visible) for transactions.
+ This range doesn't imply any direct temporal meaning;
+ the sequence of xids reflects only the sequence of
+ transaction begin events.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Internally, an <command>UPDATE</command> command acts in the
+ same way as a <command>DELETE</command> command followed by
+ an <command>INSERT</command> command.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ Nothing is removed — with the consequence that the database
+ occupies more and more disk space. It is obvious that
+ this behavior has to be corrected in some way. The next
+ chapter explains how <firstterm>vacuum</firstterm> and
+ <firstterm>autovacuum</firstterm> fulfill this task.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ </sect1>
+
+ <sect1 id="tutorial-vacuum">
+ <title>Vacuum</title>
+
+ <para>
+ As we have seen in the previous chapter, the database
+ tends to occupy more and more disk space, caused by
+ <glossterm linkend="glossary-bloat">bloat</glossterm>.
+ This chapter explains how the SQL command
+ <command>VACUUM</command> and the automatically running
+ <firstterm>Autovacuum</firstterm> processes clean up
+ and prevent continued growth.
+ </para>
+
+ <note>
+ <para>
+ Autovacuum runs automatically, by
+ default. Its default parameters as well as those for
+ <command>VACUUM</command> are appropriate for most standard
+ situations. Therefore a novice database manager can
+ skip the rest of this chapter which explains
+ a lot of details.
+ </para>
+ </note>
+
+ <para>
+ Client processes can issue the SQL command <command>VACUUM</command>
+ at any time. DBAs do this when they recognize
+ special situations, or they start it in batch jobs which run
+ periodically. Additionally, there is a constantly running
+ Autovacuum daemon which is part of the
+ <link linkend="glossary-instance">Instance</link>. It continuously
+ monitors the state of all databases based on values that are collected by the
+ <link linkend="glossary-stats-collector">Statistics Collector</link>
+ and starts Autovacuum processes whenever it detects
+ certain situations. Thus, it's a dynamic behavior of
+ <productname>PostgreSQL</productname> with the intention to tidy
+ up whenever it is appropriate.
+ </para>
+
+ <para>
+ <command>VACUUM</command>, as well as Autovacuum, don't just eliminate
+ bloat. They perform additional tasks for minimizing future
+ I/O activities of themselves as well as of other processes.
+ This extra work can be done in a very efficient way since in most
+ cases the expensive physical access to pages has taken place anyway
+ to eliminate bloat. The additional operations are:
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <firstterm>Freeze</firstterm>: Mark certain row versions
+ as frozen. This means that they
+ are always treated as valid (visible) independent from
+ the <firstterm>wraparound problem</firstterm> (see below).
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <firstterm>Visibility Map</firstterm> and
+ <firstterm>Free Space Map</firstterm>: Log information about
+ the state of the handled pages in two additional files, the
+ Visibility Map and the Free Space Map.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <emphasis>Statistics</emphasis>: Collect statistics about the
+ number of rows per table, the distribution of values, and so on,
+ as the basis for decisions of the query planner.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ The eagerness — or 'aggressiveness' — of the
+ operations for <emphasis>eliminating bloat</emphasis> and
+ <emphasis>freeze</emphasis> is controlled by configuration
+ parameters, runtime flags, and in extreme situations by
+ the processes themselves. Because vacuum operations typically are I/O
+ intensive, which can hinder other activities, Autovacuum
+ avoids performing many vacuum operations in bulk. Instead,
+ it carries out many small actions with delay points in between.
+ The SQL command <command>VACUUM</command> runs immediately
+ and without any time delay.
+ </para>
+
+ <bridgehead renderas="sect2">Eliminate Bloat</bridgehead>
+
+ <para>
+ To determine which of the row versions are no longer needed, the
+ elimination operation must evaluate <literal>xmax</literal>
+ against several criteria which must all apply:
+ </para>
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be different from zero because a
+ value of zero indicates that the row version is still valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must contain an xid which is older
+ than the oldest xid of all currently running transactions
+ <literal>(min(pg_stat_activity.backend_xmin))</literal>.
+ This criterion guarantees that no existing or upcoming transaction
+ will have read or write access to this row version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transaction of <literal>xmax</literal> must be committed. If it was rollback-ed,
+ this row version is treated as valid.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If there is the situation that the row version is part of
+ multiple transactions, special care and some more actions
+ must be taken, see: <xref linkend="vacuum-for-multixact-wraparound"/>.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+
+ <para>
+ After the vacuum operation detects an unused row version, it
+ marks its space as free for future use of writing actions. Only
+ in rare situations (or in the case of <command>VACUUM FULL</command>),
+ is this space released to the operating system. In most cases,
+ it remains occupied by <productname>PostgreSQL</productname>
+ and will be used by future <command>INSERT</command> or
+ <command>UPDATE</command> commands to this table.
+ </para>
+
+ <para>
+ Which actions start the elimination of bloat?
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ in its default format, i.e., without any option. To boost performance,
+ in this and the next case <command>VACUUM</command> does not
+ read and act on all pages of the heap file.
+ The Visibility Map, which is very compact and therefore fast to read,
+ contains information about which pages have no deleted row versions, and
+ can be skipped by <command>VACUUM</command>.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FREEZE</command>. (In this case,
+ it undertakes many more actions, see
+ <link linkend="tutorial-freeze">Freeze Row Versions</link>.)
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with the option <command>FULL</command>.
+ In this mode, an exclusive lock is taken, and
+ the whole table is copied to a different file, skipping all outdated row
+ versions. All bloat is thereby eliminated, which
+ may lead to a significant reduction of used disk space.
+ The old file is deleted.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ When an Autovacuum process acts. For optimization
+ purposes, it considers the Visibility Map in the same way as
+ <command>VACUUM</command>. Additionally, it ignores tables with few modifications;
+ see <xref linkend="guc-autovacuum-vacuum-threshold"/>,
+ which defaults to 50 rows and
+ <xref linkend="guc-autovacuum-vacuum-scale-factor"/>,
+ which defaults to 20%.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </para>
+
+ <para>
+ This logic only applies to row versions of the heap. Index entries
+ don't use <literal>xmin/xmax</literal>. Nevertheless, such index
+ entries, which would lead to outdated row versions, are cleaned up
+ accordingly.
+ </para>
+
+ <para>
+ The above descriptions omit the fact that xids on a real computer
+ have a limited size, and after
+ a certain number of transactions they are forced to restart
+ from the beginning, which is called <firstterm>wraparound</firstterm>.
+ Therefore the terms 'old transaction' / 'young transaction' does
+ not always correlate with low / high values of xids. Near to
+ wraparound point, there are cases where <literal>xmin</literal> has
+ a higher value than <literal>xmax</literal>, although their meaning
+ is said to be older than <literal>xmax</literal>.
+ </para>
+
+ <figure id="tutorial-wraparound-figure">
+ <title>Cyclic usage of XIDs</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/wraparound-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2" id="tutorial-freeze">Freeze Row Versions</bridgehead>
+
+ <para>
+ The use of a limited range of IDs for transactions leads
+ to the necessity to restart the sequence sooner or later.
+ This not only has the rare consequence, previously
+ described, that sometimes <literal>xmin</literal> is
+ higher than <literal>xmax</literal>. A far
+ more critical problem is that whenever the system has
+ to evaluate a WHERE condition, it must decide which row
+ version is valid (visible) from the perspective of the
+ transaction of the query. If a wraparound couldn't happen,
+ this decision would be relatively easy: the xid
+ must be between <literal>xmin</literal> and <literal>xmax</literal>,
+ and the corresponding transactions of <literal>xmin</literal>
+ and <literal>xmax</literal> must be committed. However,
+ <productname>PostgreSQL</productname> has to consider the
+ possibility of wraparound.
+ Therefore the decision becomes more complex. The general
+ idea of the solution is to use the 'between
+ <literal>xmin</literal> and <literal>xmax</literal>'
+ comparison only during the youngest period of the row
+ versions lifetime and afterward replace it with a
+ 'valid forever' flag in its header.
+ </para>
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ As a first step, <productname>PostgreSQL</productname>
+ divides the complete range of
+ possible xids into two halves with the two split-points
+ 'txid_current' and 'txid_current + 2^31'. The half behind
+ 'txid_current' is considered to represent xids of the
+ 'past' and the half ahead of 'txid_current' those of the
+ 'future'. Those of the 'past' are valid (visible) and those
+ of the 'future' not.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ With each newly created transaction the two split-points
+ move forward. If 'txid_current + 2^31' reached a
+ row version with <literal>xmin</literal> equal to that value, it would
+ immediately jump from 'past' to 'future' and would be
+ no longer visible!
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ If not handled in some way, data inserted many transactions ago
+ would become invisibile. The vacuum operation <firstterm>freeze</firstterm>
+ avoids this long before the split-point is reached by setting
+ a flag in the header of the row version which avoids
+ future comparison of its <literal>xmin/xmax</literal> and indicates
+ that the version is valid not only in the 'past'-half
+ but also in the 'future'-half, as well as in all coming
+ <glossterm linkend="glossary-xid">epochs</glossterm>.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+
+ <para>
+ Which row versions can be frozen by the vacuum operation?
+ Again, several criteria must be checked, and all must be met.
+
+ <itemizedlist>
+
+ <listitem>
+ <simpara>
+ <literal>xmax</literal> must be zero because only
+ non-deleted rows can be visible 'forever'.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ <literal>xmin</literal> must be older than all currently
+ existing transactions. This guarantees that no existing
+ transaction can modify or delete the version.
+ </simpara>
+ </listitem>
+
+ <listitem>
+ <simpara>
+ The transactions of <literal>xmin</literal> and
+ <literal>xmax</literal> must be committed.
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ At what point in time does the freeze operation take place?
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command>
+ with its <command>FREEZE</command> option. In this case, all
+ pages are processed that are marked in the Visibility Map
+ as potentially having unfrozen rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When a client issues the SQL command <command>VACUUM</command> without
+ any options but there are xids older than
+ <xref linkend="guc-vacuum-freeze-table-age"/>
+ (default: 150 million) minus
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million).
+ As before, all pages are processed that are
+ marked in the Visibility Map to potentially having unfrozen
+ rows.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ When an Autovacuum process runs. Such a process acts in one
+ of two modes:
+ </simpara>
+
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ In the <emphasis>normal mode</emphasis>, it skips
+ pages with row versions that are younger than
+ <xref linkend="guc-vacuum-freeze-min-age"/>
+ (default: 50 million) and works only on pages where
+ all xids are older. The skipping of young xids prevents
+ work on such pages, which are likely to be changed
+ by one of the future SQL commands.
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ The process switches
+ to an <emphasis>aggressive mode</emphasis> if it recognizes
+ that for the processed table the oldest xid exceeds
+ <xref linkend="guc-autovacuum-freeze-max-age"/>
+ (default: 200 million). The value of the oldest unfrozen
+ xid is stored per table in <literal>pg_class.relfrozenxid</literal>.
+ In this <emphasis>aggressive mode</emphasis> Autovacuum
+ processes all such pages of the selected table that are marked
+ in the Visibility Map to potentially have bloat or unfrozen rows.
+ </simpara>
+ </listitem>
+
+ </itemizedlist>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <para>
+ In the first two cases and with Autovacuum in
+ <emphasis>aggressive mode</emphasis>, the system knows
+ to which value the oldest unfrozen xid has moved forward and
+ logs the value in <literal>pg_class.relfrozenxid</literal>.
+ The distance between this value and the 'txid_current' split
+ point becomes smaller, and the distance to 'txid_current + 2^31'
+ becomes larger than before.
+ </para>
+
+ <figure id="tutorial-freeze-figure">
+ <title>Freeze</title>
+ <mediaobject>
+ <imageobject role="html">
+ <!-- distinction html/pdf is necessary to keep font-size of SVG text
+ in correlation with font-size of surrounding HTML -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" />
+ </imageobject>
+ <imageobject role="fo">
+ <!-- For PDF attribute 'width=100%' is necessary to keep complete SVG visible
+ on the page, which has a fixed width. Font sizes will be adopted. -->
+ <imagedata fileref="images/freeze-raw.svg" format="SVG" width="100%" />
+ </imageobject>
+ </mediaobject>
+ </figure>
+
+ <bridgehead renderas="sect2">Protection against Wraparound Failure</bridgehead>
+
+ <para>
+ The Autovacuum processes are initiated by the constantly running
+ Autovacuum daemon. If the daemon detects that for a table
+ <literal>autovacuum_freeze_max_age</literal> is exceeded, it
+ starts an Autovacuum process in <emphasis>aggressive mode</emphasis>
+ (see above) — even if Autovacuum is disabled.
+ </para>
+
+ <bridgehead renderas="sect2">Visibility Map and Free Space Map</bridgehead>
+
+ <para>
+ The <link linkend="glossary-vm">Visibility Map</link>
+ (VM) contains two flags — stored as
+ two bits — for each page of the heap file. The
+ first bit indicates that the associated page does
+ not contain any bloat. The second bit indicates
+ that the page contains only frozen row versions.
+ </para>
+
+ <para>
+ Please consider two details. First, in most cases a page
+ contains many rows or row versions.
+ However, the flags are associated with the page,
+ not with an individual row version. The flags are set
+ only under the condition that they are valid for ALL
+ row versions of the page. Second, since there
+ are only two bits per page, the VM is considerably
+ smaller than the heap.
+ </para>
+
+ <para>
+ The setting of the flags is silently done by <command>VACUUM</command>
+ and Autovacuum during their bloat and freeze operations.
+ This is done to speed up future vacuum actions,
+ regular access to heap pages, and some access to
+ the index. Every data-modifying operation on any row
+ version of the page clears the flags.
+ </para>
+
+ <para>
+ The <link linkend="glossary-fsm">Free Space Map</link>
+ (FSM) tracks the amount of free space per page. It is
+ organized as a highly condensed b-tree of (rounded) sizes.
+ Whenever <command>VACUUM</command> or Autovacuum changes
+ the free space on any processed page, they log the new
+ values in the FSM in the same way as all other writing
+ processes.
+ </para>
+
+ <bridgehead renderas="sect2">Statistics</bridgehead>
+
+ <para>
+ Statistical information helps the <link
+ linkend="planner-stats">Query Planner</link> to make optimal
+ decisions for the generation of execution plans. This
+ information can be gathered with the SQL commands
+ <command>ANALYZE</command> or <command>VACUUM ANALYZE</command>.
+ But Autovacuum processes also gather
+ such information. Depending on the percentage of changed rows
+ <xref linkend="guc-autovacuum-analyze-scale-factor"/>,
+ and minimum number of changed rows <xref linkend="guc-autovacuum-analyze-threshold"/>,
+ the Autovacuum daemon starts Autovacuum processes to collect
+ statistics per table. The automatic analysis
+ allows <productname>PostgreSQL</productname> to
+ adapt query execution to changing circumstances.
+ </para>
+
+ <para>
+ For more details about vacuum operations, especially for its
+ numerous parameters, see <xref linkend="routine-vacuuming"/>.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-transactions-mvcc">
+ <title>Transactions</title>
+ <para>
+ <link linkend="tutorial-transactions">Transactions</link>
+ are a fundamental concept of relational database systems.
+ Their essential point is that they bundle multiple
+ read- or write-operations into a single all-or-nothing
+ operation. Furthermore, they separate and protect concurrent
+ actions of different connections from each other. Thereby
+ they implement the ACID paradigm.
+ </para>
+
+ <para>
+ In <productname>PostgreSQL</productname> there are two ways
+ to establish a transaction. The explicit way uses the keywords
+ <link linkend="sql-begin">BEGIN</link> and
+ <link linkend="sql-commit">COMMIT</link> (respectively
+ <link linkend="sql-rollback">ROLLBACK</link>) before
+ and after a sequence of SQL statements. The keywords mark
+ the transaction's start- and end-point. On the other hand, you
+ can omit the keywords. This is the implicit way, where
+ every single SQL command automatically establishes a new
+ transaction.
+
+ <programlisting>
+BEGIN; -- establish a new transaction
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+COMMIT; -- finish the transaction
+
+-- this UPDATE runs as the only command of a separate transaction ...
+UPDATE accounts SET balance = balance - 100.00 WHERE name = 'Alice';
+
+-- ... and this one runs in another transaction
+UPDATE accounts SET balance = balance + 100.00 WHERE name = 'Bob';
+ </programlisting>
+ </para>
+
+ <para>
+ As mentioned, the primary property of a transaction is its
+ atomicity: either all or none of its operations succeed,
+ regardless of the fact that it may consist of a lot of
+ different write-operations, and each such operation may
+ affect many rows. As soon as one of the
+ operations fails, all previous operations fail also, which
+ means that all modified rows retain their values as of the
+ beginning of the transaction.
+ </para>
+
+ <para>
+ The atomicity also affects the visibility of changes. No
+ connection running simultaneously with a data modifying
+ transaction will ever see any change before the
+ transaction successfully executes a <command>COMMIT</command>
+ — even in the lowest
+ <link linkend="transaction-iso">isolation level</link>
+ of transactions. <productname>PostgreSQL</productname>
+ never shows uncommitted changes to other connections.
+ </para>
+
+ <para>
+ The situation regarding visibility is somewhat different
+ from the point of view of the modifying transaction.
+ A <command>SELECT</command> command issued inside a
+ transaction shows all changes done so far by this
+ transaction.
+ </para>
+
+ <bridgehead renderas="sect2">How does it work?</bridgehead>
+
+ <para>
+ Every <command>INSERT</command>, <command>UPDATE</command>,
+ and <command>DELETE</command> command creates new row
+ versions — according to the MVCC rules. This
+ creates the risk that other transactions may see the
+ new row versions, and after a while and some more
+ activities of the modifying transaction they may see the
+ next row versions. Results would be a kind of 'moving
+ target' which would be contrary to the all-or-nothing
+ principle.
+ </para>
+
+ <para>
+ <productname>PostgreSQL</productname> overcomes this
+ problem by showing only such row versions to other
+ transactions whose originating transaction has
+ successfully committed. It skips all row versions of
+ uncommitted transactions. And
+ <productname>PostgreSQL</productname> solves one more
+ problem. Even the single <command>COMMIT</command>
+ command needs a short time interval for its execution.
+ Therefore its critical 'dead-or-survival' phase
+ runs in a privileged mode that cannot be
+ interrupted by other processes.
+ </para>
+
+ <bridgehead renderas="sect2">What are the benefits?</bridgehead>
+
+ <para>
+ Transactions relieve applications from many standard
+ actions that would otherwise need to be implemented for nearly every use case.
+ </para>
+
+ <para>
+ Business logic often contains strong, but for a computer,
+ relative abstract requirements. The above example shows
+ the transfers of some money from one account to another.
+ It is obvious
+ that the decrease of the one account and the increase of the
+ other must be indivisible. Nevertheless, there is no particular
+ need for an application to do something to ensure the
+ <glossterm linkend="glossary-atomicity">atomicity</glossterm>
+ of this behavior. It's enough to surround them with
+ <command>BEGIN</command> and <command>COMMIT</command>.
+ </para>
+
+ <para>
+ Applications often demand the feature of 'undoing'
+ previously taken actions under some application-specific
+ conditions. In such cases, the application simply issues a
+ <command>ROLLBACK</command> command instead of a
+ <command>COMMIT</command>. The <command>ROLLBACK</command>
+ cancels the transaction, and all changes made so far remain
+ invisible forever; it is as if they had never happened. There
+ is no need for the application to log its activities and
+ undo every step of the transaction separately.
+ </para>
+
+ <para>
+ Transactions ensure that the
+ database always remains
+ <glossterm linkend="glossary-consistency">consistent</glossterm>.
+ Declarative rules like
+ <link linkend="ddl-constraints-primary-keys">primary</link>- or
+ <link linkend="ddl-constraints-fk">foreign keys</link>,
+ <link linkend="ddl-constraints-check-constraints">checks</link>,
+ other constraints, or
+ <link linkend="trigger-definition">triggers</link>
+ are part of the all-or-nothing nature of transactions.
+ </para>
+
+ <para>
+ There is the additional feature
+ '<link linkend="transaction-iso">isolation level</link>',
+ which separates transactions from each other in certain ways.
+ It automatically prevents applications from some strange
+ situations.
+ </para>
+
+ <para>
+ Lastly, it is worth noticing that changes done by a
+ committed transaction will survive all failures in the application or
+ the Database Cluster. The next chapter explains the
+ <glossterm linkend="glossary-durability">durability</glossterm>
+ guarantees.
+ </para>
+ </sect1>
+
+ <sect1 id="tutorial-reliability">
+ <title>Reliability</title>
+
+ <para>
+ Nothing is perfect and failures inevitably happen.
+ However, the most common types of failure are
+ well known and <productname>PostgreSQL</productname>
+ implements strategies to overcome them.
+ Such strategies use parts of the previously presented
+ techniques MVCC and transaction-rollback, plus additional
+ features.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the client side</bridgehead>
+ <para>
+ A <glossterm linkend="glossary-client">client</glossterm>
+ can fail in different ways. Its hardware can get damaged,
+ the power supply can fail, the network connection to the
+ server can break, or the client application may run into
+ a severe software error like a null pointer exception.
+ Because <productname>PostgreSQL</productname> uses a
+ client/server architecture, no direct problem for the
+ database will occur. In all of these cases, the
+ <glossterm linkend="glossary-backend">Backend process</glossterm>,
+ which is the client's counterpart at the server side,
+ may recognize that the network connection is no longer
+ working, or it may run into a timeout after a while. It
+ terminates, and there is no harm to the database. As
+ usual, uncommitted data changes initiated by this client
+ are not visible to any other client.
+ </para>
+
+ <bridgehead renderas="sect2">Failures at the server-side</bridgehead>
+
+ <bridgehead renderas="sect3">Instance failure</bridgehead>
+ <para>
+ The Instance may suddenly fail because of <emphasis>power off</emphasis>
+ or other problems. This will affect all running processes, the RAM,
+ and possibly the consistency of disk files.
+ </para>
+
+ <para>
+ After a restart, <productname>PostgreSQL</productname>
+ automatically recognizes that the last shutdown of the
+ Instance did not happen as expected: files might not be
+ closed properly and the <literal>postmaster.pid</literal>
+ file unexpectedly exists. <productname>PostgreSQL</productname>
+ tries to clean up the situation. This is possible because
+ all changes in the database are stored twice. First,
+ the WAL files contain them as a chronology of
+ <glossterm linkend="glossary-wal-record">WAL records</glossterm>,
+ which include the new data values and information about commit
+ actions. The WAL records are written first. Only then is
+ the data itself written to the heap and index files.
+ In contrast to the WAL records, this part may or may
+ not have been transferred entirely from Shared Memory
+ to the files.
+ </para>
+
+ <para>
+ The automatic recovery searches within the WAL files for
+ the latest
+ <glossterm linkend="glossary-checkpoint">checkpoint</glossterm>.
+ This checkpoint signals that the database files are in
+ a consistent state, especially that all WAL records up to
+ this point were successfully stored in heap and index files. Starting
+ here, the recovery process copies any remaining WAL records
+ to heap and index. The result is that the heap files contain all
+ changes recorded to the WAL and reach a consistent state. Changes of committed
+ transactions are visible; those of uncommitted transactions
+ are also in the files, but - as usual - they are never seen
+ by any of the following transactions because uncommitted
+ changes are never shown. These recovery actions run
+ automatically; it is not necessary that a
+ database administrator configure or start anything by
+ himself.
+ </para>
+
+ <bridgehead renderas="sect3">Disk crash</bridgehead>
+ <para>
+ If a disk crashes, the course of action described previously
+ cannot work: it is likely that the WAL files and/or the
+ data and index files are no longer available. The
+ database administrator must take special actions to
+ prepare for such a situation.
+ </para>
+
+ <para>
+ They obviously need a backup. How to take such a backup
+ and use it as a starting point for a recovery of the
+ Cluster is explained in more detail in the next
+ <link linkend="tutorial-backup">chapter</link>.
+ </para>
+
+ <bridgehead renderas="sect3">Disk full</bridgehead>
+ <para>
+ It is conceivable that over time the disk gets full,
+ and there is no room for additional data. In this case,
+ <productname>PostgreSQL</productname> stops accepting
+ data-modifying commands or even terminates completely.
+ Committed data is neither lost nor corrupted.
+ </para>
+
+ <para>
+ To recover from such a situation, the administrator should
+ remove unused files from this disk. But they should never
+ delete files from the
+ <glossterm linkend="glossary-data-directory">data directory</glossterm>.
+ Nearly all of them are necessary for the consistency
+ of the database.
+ </para>
+
+ <bridgehead renderas="sect2">High availability</bridgehead>
+ <para>
+ Database servers can work together to allow a second
+ server to quickly take over the workload if the
+ primary server fails for whatever reason
+ (<link linkend="high-availability">high availability</link>),
+ or to allow several computers to serve the same data
+ for the purpose of load balancing.
+ </para>
+
+ </sect1>
+
+ <sect1 id="tutorial-backup">
+ <title>Backup</title>
+
+ <para>
+ Taking backups is a basic task of database maintenance.
+ <productname>PostgreSQL</productname> supports
+ three different strategies; each has its own
+ strengths and weaknesses.
+ <itemizedlist>
+ <listitem>
+ <simpara>
+ File system level backup
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Logical backup via <command>pg_dump</command>
+ </simpara>
+ </listitem>
+ <listitem>
+ <simpara>
+ Continuous archiving based on <command>pg_basebackup</command>
+ and WAL files
+ </simpara>
+ </listitem>
+ </itemizedlist>
+ </para>
+
+ <bridgehead renderas="sect2">File system level backup</bridgehead>
+ <para>
+ You can use any appropriate OS tool to create a
+ <link linkend="backup-file">copy</link>
+ of the Cluster's directory structure and files. In
+ case of severe problems such a copy can serve as
+ the source of recovery. But in order to get a
+ <emphasis>USABLE</emphasis> backup by this method,
+ the database server <emphasis>MUST</emphasis> be
+ shut down during the complete runtime of the copy
+ command!
+ </para>
+
+ <para>
+ The obvious disadvantage of this method is that there
+ is a downtime.
+ The other two strategies run during regular operating
+ times.
+ </para>
+
+ <bridgehead renderas="sect2">Logical backup via pg_dump</bridgehead>
+ <para>
+ The tool <command>pg_dump</command> is able to take a
+ <link linkend="backup-dump">copy</link>
+ of the complete Cluster or certain parts of it. It stores
+ the copy in the form of SQL commands like <command>CREATE</command>
+ and <command>COPY</command>. It runs in
+ parallel with other processes, in its own transaction.
+ </para>
+
+ <para>
+ The output of <command>pg_dump</command> may be used as
+ input of <command>psql</command> to restore the data
+ (or to copy it to another database).
+ </para>
+
+ <para>
+ The main advantage over the other two methods is that it
+ can pick parts of the Cluster, e.g., a single table or one
+ database. The other two methods work only at the level of
+ the complete Cluster.
+ </para>
+
+ <bridgehead renderas="sect2">Continuous archiving based on pg_basebackup and WAL files</bridgehead>
+ <para>
+ <link linkend="continuous-archiving">This method</link>
+ is the most sophisticated and most complex one. It
+ consists of two phases.
+ </para>
+
+ <para>
+ First, you need to create a so-called
+ <firstterm>basebackup</firstterm> with the tool
+ <command>pg_basebackup</command>. The result is a
+ directory structure plus files which contain a
+ consistent copy of the original Cluster.
+ <command>pg_basebackup</command> runs in
+ parallel with other processes in its own transaction.
+ </para>
+
+ <para>
+ The second step is recommended but not necessary. All
+ changes to the data are stored in WAL files. If you
+ continuously save such WAL files, you have the history
+ of the Cluster. This history can be applied to a
+ basebackup in order to recreate
+ any state of the Cluster between the time of
+ <command>pg_basebackup</command>'s start time and
+ any later point in time. This technique
+ is called 'Point-in-Time Recovery (PITR)'.
+ </para>
+
+ <para>
+ If configured, the
+ <glossterm linkend="glossary-wal-archiver">Archiver process</glossterm>
+ will automatically copy every single WAL file to a save location.
+ <link linkend="backup-archiving-wal">Its configuration</link>
+ consists mainly of a string that contains a copy command
+ in the operating system's syntax. In order to protect your
+ data against a disk crash, the destination location
+ of a basebackup as well as of the
+ <firstterm>archived WAL files</firstterm> should be on a
+ disk which is different from the data disk.
+ </para>
+
+ <para>
+ If it becomes necessary to restore the Cluster, you have to
+ copy the basebackup and the archived WAL files to
+ their original directories. The configuration of this
+ <link linkend="backup-pitr-recovery">recovery procedure</link>
+ contains a string with the reversed copy command: from
+ archive location to database location.
+ </para>
+
+ </sect1>
+
+<!-- ToDo: replication, index-types, extension mechanism, ...
+ <sect1 id="tutorial-replication">
+ <title>Replication</title>
+
+ <para>
+...
+ </para>
+
+ </sect1>
+-->
+
+ </chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 38e8aa0bbf..7490d3c9c2 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -80,6 +80,7 @@
%allfiles;
<!-- developer's guide -->
+<!ENTITY architecture SYSTEM "architecture.sgml">
<!ENTITY arch-dev SYSTEM "arch-dev.sgml">
<!ENTITY bki SYSTEM "bki.sgml">
<!ENTITY catalogs SYSTEM "catalogs.sgml">
diff --git a/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
new file mode 100644
index 0000000000..487eec47e1
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink-svgo.svg
@@ -0,0 +1,184 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="685" viewBox="0 0 900 685">
+ <title>
+ Server (Hardware, Container, or VM)
+ </title>
+ <style>
+ .text_normal,.text_small{font-style:normal;font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_small{font-size:12px}.text_normal{font-size:14px}
+ </style>
+ <defs>
+ <symbol id="rectangle_special_0">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="rectangle_special_1">
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="25" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ System schemas
+ </text>
+ </symbol>
+ <symbol id="rectangle_special_2">
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="60">
+ schema 'public'
+ </text>
+ <text class="text_small" x="25" y="80">
+ tables, views, ...
+ </text>
+ <rect x="15" y="105" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_small" x="20" y="125">
+ System schemas
+ </text>
+ <rect x="15" y="150" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2"/>
+ <text class="text_normal" x="20" y="170">
+ 'my_schema' (optional)
+ </text>
+ <text class="text_small" x="25" y="185">
+ tables, views, ...
+ </text>
+ </symbol>
+ <symbol id="note_0" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M190 10v70H0V0h180v10h10L180 0"/>
+ </symbol>
+ <symbol id="note_1" stroke="black" fill="lightyellow">
+ <title>
+ UML Note
+ </title>
+ <path d="M450 10v240H0V0h440v10h10L440 0"/>
+ </symbol>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="270" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Server (Hardware, Container, or VM)
+ </text>
+ <path stroke="blue" stroke-width="2" fill="none" d="M20 110h790v555H20z"/>
+ <text class="text_normal" x="180" y="25" transform="translate(20 110)">
+ cluster 'data' (default, managed by one instance)
+ </text>
+ <path d="M50 110V80h790v555h-30" stroke="blue" stroke-width="2" fill="none"/>
+ <text class="text_normal" x="190" y="-10" transform="translate(45 110)">
+ cluster 'cluster_2' (optional, managed by a different instance)
+ </text>
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template0'
+ </text>
+ <use xlink:href="#note_0" x="20" y="40"/>
+ <text class="text_small" x="30" y="60">
+ 'template0' is a pristine
+ </text>
+ <text class="text_small" x="30" y="75">
+ and unchangeable template.
+ </text>
+ <text class="text_small" x="30" y="90">
+ It is used to generate
+ </text>
+ <text class="text_small" x="30" y="105">
+ database 'template1'.
+ </text>
+ </g>
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_1"/>
+ <text class="text_normal" x="10" y="25">
+ database 'template1'
+ </text>
+ </g>
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_2"/>
+ <text class="text_normal" x="10" y="25">
+ database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_2"/>
+ <text class="text_normal" x="10" y="25">
+ database 'my_db' (optional)
+ </text>
+ </g>
+ <g transform="translate(320 330)">
+ <rect width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4"/>
+ <text class="text_normal" x="15" y="27">
+ Global SQL objects
+ </text>
+ <path d="M80 0v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M180 40h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M0 40l-45 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ </g>
+ <g transform="translate(335 405)">
+ <use xlink:href="#note_1"/>
+ <text class="text_small" x="10" y="20">
+ 1)
+ </text>
+ <text class="text_small" x="30" y="20">
+ By default, clients connect via port '5432' to Cluster 'data',
+ </text>
+ <text class="text_small" x="30" y="35">
+ database 'postgres', schema 'public'. Of course, they can
+ </text>
+ <text class="text_small" x="30" y="50">
+ specify other connection properties.
+ </text>
+ <text class="text_small" x="10" y="70">
+ 2)
+ </text>
+ <text class="text_small" x="30" y="70">
+ System schemas: pg_catalog, information_schema,
+ </text>
+ <text class="text_small" x="30" y="85">
+ pg_temp, ...
+ </text>
+ <text class="text_small" x="10" y="105">
+ 3)
+ </text>
+ <text class="text_small" x="30" y="105">
+ Global SQL objects: Objects which are shared among all
+ </text>
+ <text class="text_small" x="30" y="120">
+ databases within a Cluster.
+ </text>
+ <text class="text_small" x="10" y="140">
+ 4)
+ </text>
+ <text class="text_small" x="30" y="140">
+ The command 'initdb' creates a new cluster with the three
+ </text>
+ <text class="text_small" x="30" y="155">
+ databases 'template0', 'template1', and 'postgres'. The command
+ </text>
+ <text class="text_small" x="30" y="170">
+ 'createdb' creates a new database.
+ </text>
+ <text class="text_small" x="10" y="190">
+ 5)
+ </text>
+ <text class="text_small" x="30" y="190">
+ If multiple clusters are active on one server at the same time,
+ </text>
+ <text class="text_small" x="30" y="205">
+ each one is managed by an individual instance. Each such instance
+ </text>
+ <text class="text_small" x="30" y="220">
+ uses a different port.
+ </text>
+ <text class="text_small" x="10" y="240">
+ 6)
+ </text>
+ <text class="text_small" x="30" y="240">
+ Client application are prohibited from connecting to 'template0'.
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-ink.svg b/doc/src/sgml/images/cluster-db-schema-ink.svg
new file mode 100644
index 0000000000..05623a4092
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-ink.svg
@@ -0,0 +1,528 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="685px"
+ viewBox="0 0 900 685"
+ id="svg165"
+ sodipodi:docname="cluster-db-schema-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata169">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Server (Hardware, Container, or VM)</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="780"
+ inkscape:window-height="480"
+ id="namedview167"
+ showgrid="false"
+ inkscape:zoom="0.34452555"
+ inkscape:cx="450"
+ inkscape:cy="342.5"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg165" />
+ <title
+ id="title2">Server (Hardware, Container, or VM)</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs57">
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangle_special_0">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect6" />
+ </symbol>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol
+ id="rectangle_special_1">
+ <!-- the database -->
+ <rect
+ width="225"
+ height="155"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect9" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="195"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect11" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text13">schema 'public'</text>
+ <text
+ class="text_small"
+ x="25"
+ y="80"
+ id="text15">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="195"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect17" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text19">System schemas</text>
+ </symbol>
+ <!-- same as before, but one more schema -->
+ <symbol
+ id="rectangle_special_2">
+ <!-- the database -->
+ <rect
+ width="245"
+ height="225"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect22" />
+ <!-- schemas -->
+ <rect
+ x="15"
+ y="40"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect24" />
+ <text
+ class="text_normal"
+ x="20"
+ y="60"
+ id="text26">schema 'public'</text>
+ <text
+ class="text_small"
+ x="25"
+ y="80"
+ id="text28">tables, views, ...</text>
+ <rect
+ x="15"
+ y="105"
+ width="205"
+ height="30"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect30" />
+ <text
+ class="text_small"
+ x="20"
+ y="125"
+ id="text32">System schemas</text>
+ <rect
+ x="15"
+ y="150"
+ width="205"
+ height="50"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="4 2"
+ id="rect34" />
+ <text
+ class="text_normal"
+ x="20"
+ y="170"
+ id="text36">'my_schema' (optional)</text>
+ <text
+ class="text_small"
+ x="25"
+ y="185"
+ id="text38">tables, views, ...</text>
+ </symbol>
+ <symbol
+ id="note_0"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title41">UML Note</title>
+ <path
+ d="M 190,10 v 70 h -190 v -80 h 180 v 10 h 10 l -10,-10"
+ id="path43" />
+ </symbol>
+ <symbol
+ id="note_1"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title46">UML Note</title>
+ <path
+ d="M 450,10 v 240 h -450 v -250 h 440 v 10 h 10 l -10,-10"
+ id="path48" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path51" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path54" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect59" />
+ <text
+ class="text_big"
+ x="270"
+ y="40"
+ id="text61">Server (Hardware, Container, or VM)</text>
+ <!-- two clusters -->
+ <g
+ transform="translate(20 110)"
+ id="g67">
+ <rect
+ x="0"
+ y="0"
+ width="790"
+ height="555"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="rect63" />
+ <text
+ class="text_normal"
+ x="180"
+ y="25"
+ id="text65">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g
+ transform="translate(45 110)"
+ id="g73">
+ <path
+ d="M 5,0 v -30 h 790 v 555 h -30"
+ stroke="blue"
+ stroke-width="2px"
+ fill="none"
+ id="path69" />
+ <text
+ class="text_normal"
+ x="190"
+ y="-10"
+ id="text71">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+ <!-- database template 0 -->
+ <g
+ transform="translate(40 155)"
+ id="g89">
+ <use
+ xlink:href="#rectangle_special_0"
+ id="use75" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text77">database 'template0'</text>
+ <use
+ xlink:href="#note_0"
+ x="20"
+ y="40"
+ id="use79" />
+ <text
+ class="text_small"
+ x="30"
+ y="60"
+ id="text81">'template0' is a pristine</text>
+ <text
+ class="text_small"
+ x="30"
+ y="75"
+ id="text83">and unchangeable template.</text>
+ <text
+ class="text_small"
+ x="30"
+ y="90"
+ id="text85">It is used to generate</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text87">database 'template1'.</text>
+ </g>
+ <!-- database template 1 -->
+ <g
+ transform="translate(290 155)"
+ id="g95">
+ <use
+ xlink:href="#rectangle_special_1"
+ id="use91" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text93">database 'template1'</text>
+ </g>
+ <!-- database postgres -->
+ <g
+ transform="translate(540 155)"
+ id="g101">
+ <use
+ xlink:href="#rectangle_special_2"
+ id="use97" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text99">database 'postgres'</text>
+ </g>
+ <!-- database my_db -->
+ <g
+ transform="translate(40 350)"
+ id="g107">
+ <use
+ xlink:href="#rectangle_special_2"
+ id="use103" />
+ <text
+ class="text_normal"
+ x="10"
+ y="25"
+ id="text105">database 'my_db' (optional)</text>
+ </g>
+ <!-- global objects -->
+ <g
+ transform="translate(320 330)"
+ id="g119">
+ <rect
+ x="0"
+ y="0"
+ width="180"
+ height="45"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ stroke-dasharray="10 4 4 4"
+ id="rect109" />
+ <text
+ class="text_normal"
+ x="15"
+ y="27"
+ id="text111">Global SQL objects</text>
+ <path
+ d="M 80,0 v-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path113" />
+ <path
+ d="M 180,40 h50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path115" />
+ <path
+ d="M 0,40 l-45,20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path117" />
+ </g>
+ <!-- Some comments -->
+ <g
+ transform="translate(335 405)"
+ id="g163">
+ <use
+ xlink:href="#note_1"
+ x="0"
+ y="0"
+ id="use121" />
+ <text
+ class="text_small"
+ x="10"
+ y="20"
+ id="text123">1)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="20"
+ id="text125">By default, clients connect via port '5432' to Cluster 'data',</text>
+ <text
+ class="text_small"
+ x="30"
+ y="35"
+ id="text127">database 'postgres', schema 'public'. Of course, they can</text>
+ <text
+ class="text_small"
+ x="30"
+ y="50"
+ id="text129">specify other connection properties.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="70"
+ id="text131">2)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="70"
+ id="text133">System schemas: pg_catalog, information_schema,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="85"
+ id="text135">pg_temp, ...</text>
+ <text
+ class="text_small"
+ x="10"
+ y="105"
+ id="text137">3)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="105"
+ id="text139">Global SQL objects: Objects which are shared among all</text>
+ <text
+ class="text_small"
+ x="30"
+ y="120"
+ id="text141">databases within a Cluster.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="140"
+ id="text143">4)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="140"
+ id="text145">The command 'initdb' creates a new cluster with the three</text>
+ <text
+ class="text_small"
+ x="30"
+ y="155"
+ id="text147">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text
+ class="text_small"
+ x="30"
+ y="170"
+ id="text149">'createdb' creates a new database.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="190"
+ id="text151">5)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="190"
+ id="text153">If multiple clusters are active on one server at the same time,</text>
+ <text
+ class="text_small"
+ x="30"
+ y="205"
+ id="text155">each one is managed by an individual instance. Each such instance</text>
+ <text
+ class="text_small"
+ x="30"
+ y="220"
+ id="text157">uses a different port.</text>
+ <text
+ class="text_small"
+ x="10"
+ y="240"
+ id="text159">6)</text>
+ <text
+ class="text_small"
+ x="30"
+ y="240"
+ id="text161">Client application are prohibited from connecting to 'template0'.</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/cluster-db-schema-raw.svg b/doc/src/sgml/images/cluster-db-schema-raw.svg
new file mode 100644
index 0000000000..8534b18ec2
--- /dev/null
+++ b/doc/src/sgml/images/cluster-db-schema-raw.svg
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="685px"
+ viewBox="0 0 900 685" >
+
+ <title>Server (Hardware, Container, or VM)</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_0">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ </symbol>
+
+ <!-- a rectangle with rounded corners and inner definitions for schemas -->
+ <symbol id="rectangle_special_1">
+
+ <!-- the database -->
+ <rect width="225" height="155" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="195" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="25" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="195" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">System schemas</text>
+ </symbol>
+
+ <!-- same as before, but one more schema -->
+ <symbol id="rectangle_special_2">
+ <!-- the database -->
+ <rect width="245" height="225" rx="10" stroke="blue" fill="none"/>
+
+ <!-- schemas -->
+ <rect x="15" y="40" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="60">schema 'public'</text>
+ <text class="text_small" x="25" y="80">tables, views, ...</text>
+
+ <rect x="15" y="105" width="205" height="30" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_small" x="20" y="125">System schemas</text>
+
+ <rect x="15" y="150" width="205" height="50" rx="10" stroke="blue" fill="none" stroke-dasharray="4 2" />
+ <text class="text_normal" x="20" y="170">'my_schema' (optional)</text>
+ <text class="text_small" x="25" y="185">tables, views, ...</text>
+ </symbol>
+
+ <symbol id="note_0" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 190,10 v 70 h -190 v -80 h 180 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <symbol id="note_1" stroke="black" fill="lightyellow">
+ <title>UML Note</title>
+ <path d="M 450,10 v 240 h -450 v -250 h 440 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="270" y="40">Server (Hardware, Container, or VM)</text>
+
+ <!-- two clusters -->
+ <g transform="translate(20 110)">
+ <rect x="0" y="0" width="790" height="555" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="180" y="25">cluster 'data' (default, managed by one instance)</text>
+ </g>
+ <g transform="translate(45 110)">
+ <path d="M 5,0 v -30 h 790 v 555 h -30" stroke="blue" stroke-width="2px" fill="none" />
+ <text class="text_normal" x="190" y="-10">cluster 'cluster_2' (optional, managed by a different instance)</text>
+ </g>
+
+
+ <!-- database template 0 -->
+ <g transform="translate(40 155)">
+ <use xlink:href="#rectangle_special_0" />
+ <text class="text_normal" x="10" y="25">database 'template0'</text>
+ <use xlink:href="#note_0" x="20" y="40" />
+ <text class="text_small" x="30" y="60">'template0' is a pristine</text>
+ <text class="text_small" x="30" y="75">and unchangeable template.</text>
+ <text class="text_small" x="30" y="90">It is used to generate</text>
+ <text class="text_small" x="30" y="105">database 'template1'.</text>
+ </g>
+
+ <!-- database template 1 -->
+ <g transform="translate(290 155)">
+ <use xlink:href="#rectangle_special_1" />
+ <text class="text_normal" x="10" y="25">database 'template1'</text>
+ </g>
+
+ <!-- database postgres -->
+ <g transform="translate(540 155)">
+ <use xlink:href="#rectangle_special_2" />
+ <text class="text_normal" x="10" y="25">database 'postgres'</text>
+ </g>
+
+ <!-- database my_db -->
+ <g transform="translate(40 350)">
+ <use xlink:href="#rectangle_special_2" />
+ <text class="text_normal" x="10" y="25">database 'my_db' (optional)</text>
+ </g>
+
+ <!-- global objects -->
+ <g transform="translate(320 330)">
+ <rect x="0" y="0" width="180" height="45" rx="10" stroke="blue" fill="none" stroke-dasharray="10 4 4 4" />
+ <text class="text_normal" x="15" y="27">Global SQL objects</text>
+ <path d="M 80,0 v-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 180,40 h50" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ <path d="M 0,40 l-45,20" stroke="black" fill="none" marker-end="url(#arrowhead_end)" />
+ </g>
+
+ <!-- Some comments -->
+ <g transform="translate(335 405)">
+ <use xlink:href="#note_1" x="0" y="0" />
+
+ <text class="text_small" x="10" y="20">1)</text>
+ <text class="text_small" x="30" y="20">By default, clients connect via port '5432' to Cluster 'data',</text>
+ <text class="text_small" x="30" y="35">database 'postgres', schema 'public'. Of course, they can</text>
+ <text class="text_small" x="30" y="50">specify other connection properties.</text>
+
+ <text class="text_small" x="10" y="70">2)</text>
+ <text class="text_small" x="30" y="70">System schemas: pg_catalog, information_schema,</text>
+ <text class="text_small" x="30" y="85">pg_temp, ...</text>
+
+ <text class="text_small" x="10" y="105">3)</text>
+ <text class="text_small" x="30" y="105">Global SQL objects: Objects which are shared among all</text>
+ <text class="text_small" x="30" y="120">databases within a Cluster.</text>
+
+ <text class="text_small" x="10" y="140">4)</text>
+ <text class="text_small" x="30" y="140">The command 'initdb' creates a new cluster with the three</text>
+ <text class="text_small" x="30" y="155">databases 'template0', 'template1', and 'postgres'. The command</text>
+ <text class="text_small" x="30" y="170">'createdb' creates a new database.</text>
+
+ <text class="text_small" x="10" y="190">5)</text>
+ <text class="text_small" x="30" y="190">If multiple clusters are active on one server at the same time,</text>
+ <text class="text_small" x="30" y="205">each one is managed by an individual instance. Each such instance</text>
+ <text class="text_small" x="30" y="220">uses a different port.</text>
+
+ <text class="text_small" x="10" y="240">6)</text>
+ <text class="text_small" x="30" y="240">Client application are prohibited from connecting to 'template0'.</text>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/directories-ink-svgo.svg b/doc/src/sgml/images/directories-ink-svgo.svg
new file mode 100644
index 0000000000..a59198c66f
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink-svgo.svg
@@ -0,0 +1,164 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="640" viewBox="0 0 900 640">
+ <title>
+ Directory structure of a cluster
+ </title>
+ <style>
+ .text_italic,.text_normal{font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif}.text_normal{font-style:normal;fill:#000}.text_italic{font-style:italic;fill:silver}
+ </style>
+ <defs>
+ <symbol id="directory" stroke="blue" stroke-width=".3" fill="aqua">
+ <title>
+ Directory
+ </title>
+ <path d="M0 10h110v20H0z"/>
+ <path d="M0 10V8l3-3h35l3 3v2"/>
+ </symbol>
+ <symbol id="file" stroke="black" fill="none">
+ <title>
+ File
+ </title>
+ <path stroke="blue" d="M0 0h40v50H0z"/>
+ <path d="M5 10h20" stroke-dasharray="4 2"/>
+ <path d="M5 17h15" stroke-dasharray="6 2"/>
+ <path d="M5 24h25" stroke-dasharray="4 2"/>
+ <path d="M5 31h20" stroke-dasharray="5 2"/>
+ </symbol>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="50" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Directory Structure
+ </text>
+ <g transform="translate(20 100)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_italic">
+ /var/lib/pgsql/
+ </text>
+ <text x="300" y="26" class="text_normal">
+ An arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 130)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_italic">
+ data/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Cluster's root directory (with an arbitrary name; see: PGDATA)
+ </text>
+ </g>
+ <g transform="translate(120 160)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ base/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory containing per-database subdirectories
+ </text>
+ </g>
+ <g transform="translate(170 190)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 1/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data in default-tablespace of first database 'template0'
+ </text>
+ </g>
+ <g transform="translate(170 220)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12992/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data in default-tablespace of second database 'template1'
+ </text>
+ </g>
+ <g transform="translate(170 250)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ 12999/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Subdirectory for data in default-tablespace of third database 'postgres'
+ </text>
+ </g>
+ <g transform="translate(170 280)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ nnnnn/
+ </text>
+ <text x="150" y="26" class="text_normal">
+ Optional: one subdirectory for each new database, e.g. '23456' for 'my_db'
+ </text>
+ </g>
+ <g transform="translate(120 310)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ global/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for information about Global SQL Objects
+ </text>
+ </g>
+ <g transform="translate(120 340)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_tblspc/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for symbolic links to non-default tablespaces
+ </text>
+ </g>
+ <g transform="translate(120 370)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_wal/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 400)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_xact/
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Subdirectory for transaction commit status ('pg_clog' before version 10)
+ </text>
+ </g>
+ <g transform="translate(120 430)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_normal">
+ pg_... /
+ </text>
+ <text x="200" y="26" class="text_normal">
+ Some more subdirectories
+ </text>
+ </g>
+ <g transform="translate(120 465)">
+ <use xlink:href="#file"/>
+ <use xlink:href="#file" x="50"/>
+ <text x="200" y="26" class="text_normal">
+ 'postmaster.pid' and other files with cluster-wide relevance
+ </text>
+ </g>
+ <g transform="translate(20 540)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_italic">
+ ...
+ </text>
+ <text x="300" y="26" class="text_normal">
+ Same or another arbitrary directory
+ </text>
+ </g>
+ <g transform="translate(70 570)">
+ <use xlink:href="#directory"/>
+ <text x="10" y="26" class="text_italic">
+ cluster_2/
+ </text>
+ <text x="250" y="26" class="text_normal">
+ Root of another cluster
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-ink.svg b/doc/src/sgml/images/directories-ink.svg
new file mode 100644
index 0000000000..615a6d214a
--- /dev/null
+++ b/doc/src/sgml/images/directories-ink.svg
@@ -0,0 +1,403 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="640px"
+ viewBox="0 0 900 640"
+ id="svg329"
+ sodipodi:docname="directories-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata333">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Directory structure of a cluster</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1106"
+ inkscape:window-height="813"
+ id="namedview331"
+ showgrid="false"
+ inkscape:zoom="0.36875"
+ inkscape:cx="450"
+ inkscape:cy="311.86441"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg329" />
+ <title
+ id="title179">Directory structure of a cluster</title>
+ <style
+ type="text/css"
+ id="style181">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_italic {font-style:italic;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:silver;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs203">
+ <!-- Directory -->
+ <symbol
+ id="directory"
+ stroke="blue"
+ stroke-width="0.3px"
+ fill="aqua">
+ <title
+ id="title183">Directory</title>
+ <rect
+ x="0"
+ y="10"
+ width="110"
+ height="20"
+ id="rect185" />
+ <path
+ d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2"
+ id="path187" />
+ </symbol>
+ <!-- File -->
+ <symbol
+ id="file"
+ stroke="black"
+ fill="none">
+ <title
+ id="title190">File</title>
+ <rect
+ x="0"
+ y="0"
+ width="40"
+ height="50"
+ stroke="blue"
+ id="rect192" />
+ <path
+ d="M 5,10 h 20"
+ stroke-dasharray="4 2"
+ id="path194" />
+ <path
+ d="M 5,17 h 15"
+ stroke-dasharray="6 2"
+ id="path196" />
+ <path
+ d="M 5,24 h 25"
+ stroke-dasharray="4 2"
+ id="path198" />
+ <path
+ d="M 5,31 h 20"
+ stroke-dasharray="5 2"
+ id="path200" />
+ </symbol>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect205" />
+ <!-- caption -->
+ <text
+ x="200"
+ y="50"
+ class="text_big"
+ id="text207">Directory Structure</text>
+ <!-- the directories -->
+ <g
+ transform="translate(20, 100)"
+ id="g215">
+ <use
+ xlink:href="#directory"
+ id="use209" />
+ <text
+ x="10"
+ y="26"
+ class="text_italic"
+ id="text211">/var/lib/pgsql/</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text213">An arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 130)"
+ id="g223">
+ <use
+ xlink:href="#directory"
+ id="use217" />
+ <text
+ x="10"
+ y="26"
+ class="text_italic"
+ id="text219">data/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text221">Cluster's root directory (with an arbitrary name; see: PGDATA)</text>
+ </g>
+ <g
+ transform="translate(120, 160)"
+ id="g231">
+ <use
+ xlink:href="#directory"
+ id="use225" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text227">base/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text229">Subdirectory containing per-database subdirectories</text>
+ </g>
+ <!-- -->
+ <g
+ transform="translate(170, 190)"
+ id="g239">
+ <use
+ xlink:href="#directory"
+ id="use233" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text235">1/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text237">Subdirectory for data in default-tablespace of first database 'template0'</text>
+ </g>
+ <g
+ transform="translate(170, 220)"
+ id="g247">
+ <use
+ xlink:href="#directory"
+ id="use241" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text243">12992/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text245">Subdirectory for data in default-tablespace of second database 'template1'</text>
+ </g>
+ <g
+ transform="translate(170, 250)"
+ id="g255">
+ <use
+ xlink:href="#directory"
+ id="use249" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text251">12999/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text253">Subdirectory for data in default-tablespace of third database 'postgres'</text>
+ </g>
+ <g
+ transform="translate(170, 280)"
+ id="g263">
+ <use
+ xlink:href="#directory"
+ id="use257" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text259">nnnnn/</text>
+ <text
+ x="150"
+ y="26"
+ class="text_normal"
+ id="text261">Optional: one subdirectory for each new database, e.g. '23456' for 'my_db'</text>
+ </g>
+ <g
+ transform="translate(120, 310)"
+ id="g271">
+ <use
+ xlink:href="#directory"
+ id="use265" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text267">global/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text269">Subdirectory for information about Global SQL Objects</text>
+ </g>
+ <g
+ transform="translate(120, 340)"
+ id="g279">
+ <use
+ xlink:href="#directory"
+ id="use273" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text275">pg_tblspc/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text277">Subdirectory for symbolic links to non-default tablespaces</text>
+ </g>
+ <g
+ transform="translate(120, 370)"
+ id="g287">
+ <use
+ xlink:href="#directory"
+ id="use281" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text283">pg_wal/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text285">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 400)"
+ id="g295">
+ <use
+ xlink:href="#directory"
+ id="use289" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text291">pg_xact/</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text293">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+ <g
+ transform="translate(120, 430)"
+ id="g303">
+ <use
+ xlink:href="#directory"
+ id="use297" />
+ <text
+ x="10"
+ y="26"
+ class="text_normal"
+ id="text299">pg_... /</text>
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text301">Some more subdirectories</text>
+ </g>
+ <g
+ transform="translate(120, 465)"
+ id="g311">
+ <use
+ xlink:href="#file"
+ x="0"
+ y="0"
+ id="use305" />
+ <use
+ xlink:href="#file"
+ x="50"
+ y="0"
+ id="use307" />
+ <text
+ x="200"
+ y="26"
+ class="text_normal"
+ id="text309">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+ <!-- next cluster -->
+ <g
+ transform="translate(20, 540)"
+ id="g319">
+ <use
+ xlink:href="#directory"
+ id="use313" />
+ <text
+ x="10"
+ y="26"
+ class="text_italic"
+ id="text315">...</text>
+ <text
+ x="300"
+ y="26"
+ class="text_normal"
+ id="text317">Same or another arbitrary directory</text>
+ </g>
+ <g
+ transform="translate(70, 570)"
+ id="g327">
+ <use
+ xlink:href="#directory"
+ id="use321" />
+ <text
+ x="10"
+ y="26"
+ class="text_italic"
+ id="text323">cluster_2/</text>
+ <text
+ x="250"
+ y="26"
+ class="text_normal"
+ id="text325">Root of another cluster</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/directories-raw.svg b/doc/src/sgml/images/directories-raw.svg
new file mode 100644
index 0000000000..5cce551b0c
--- /dev/null
+++ b/doc/src/sgml/images/directories-raw.svg
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="640px"
+ viewBox="0 0 900 640">
+
+ <title>Directory structure of a cluster</title>
+
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_italic {font-style:italic;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:silver;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Directory -->
+ <symbol id="directory" stroke="blue" stroke-width="0.3px" fill="aqua">
+ <title>Directory</title>
+ <rect x="0" y="10" width="110" height="20" />
+ <path d="M 0,10 l 0,-2 3,-3 35,0, 3,3 0,2" />
+ </symbol>
+
+ <!-- File -->
+ <symbol id="file" stroke="black" fill="none" >
+ <title>File</title>
+ <rect x="0" y="0" width="40" height="50" stroke="blue" />
+ <path d="M 5,10 h 20" stroke-dasharray="4 2" />
+ <path d="M 5,17 h 15" stroke-dasharray="6 2" />
+ <path d="M 5,24 h 25" stroke-dasharray="4 2" />
+ <path d="M 5,31 h 20" stroke-dasharray="5 2" />
+ </symbol>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption -->
+ <text x="200" y="50" class="text_big">Directory Structure</text>
+
+ <!-- the directories -->
+ <g transform="translate(20, 100)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_italic">/var/lib/pgsql/</text>
+ <text x="300" y="26" class="text_normal">An arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 130)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_italic">data/</text>
+ <text x="250" y="26" class="text_normal">Cluster's root directory (with an arbitrary name; see: PGDATA)</text>
+ </g>
+
+ <g transform="translate(120, 160)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">base/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory containing per-database subdirectories</text>
+ </g>
+
+ <!-- -->
+ <g transform="translate(170, 190)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">1/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data in default-tablespace of first database 'template0'</text>
+ </g>
+ <g transform="translate(170, 220)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12992/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data in default-tablespace of second database 'template1'</text>
+ </g>
+ <g transform="translate(170, 250)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">12999/</text>
+ <text x="150" y="26" class="text_normal">Subdirectory for data in default-tablespace of third database 'postgres'</text>
+ </g>
+ <g transform="translate(170, 280)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">nnnnn/</text>
+ <text x="150" y="26" class="text_normal">Optional: one subdirectory for each new database, e.g. '23456' for 'my_db'</text>
+ </g>
+
+ <g transform="translate(120, 310)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">global/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for information about Global SQL Objects</text>
+ </g>
+
+ <g transform="translate(120, 340)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_tblspc/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for symbolic links to non-default tablespaces</text>
+ </g>
+
+ <g transform="translate(120, 370)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_wal/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for Write Ahead Log files ('pg_xlog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 400)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_xact/</text>
+ <text x="200" y="26" class="text_normal">Subdirectory for transaction commit status ('pg_clog' before version 10)</text>
+ </g>
+
+ <g transform="translate(120, 430)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_normal">pg_... /</text>
+ <text x="200" y="26" class="text_normal">Some more subdirectories</text>
+ </g>
+
+ <g transform="translate(120, 465)">
+ <use xlink:href="#file" x="0" y="0" />
+ <use xlink:href="#file" x="50" y="0" />
+ <text x="200" y="26" class="text_normal">'postmaster.pid' and other files with cluster-wide relevance</text>
+ </g>
+
+ <!-- next cluster -->
+ <g transform="translate(20, 540)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_italic">...</text>
+ <text x="300" y="26" class="text_normal">Same or another arbitrary directory</text>
+ </g>
+
+ <g transform="translate(70, 570)">
+ <use xlink:href="#directory" />
+ <text x="10" y="26" class="text_italic">cluster_2/</text>
+ <text x="250" y="26" class="text_normal">Root of another cluster</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink-svgo.svg b/doc/src/sgml/images/freeze-ink-svgo.svg
new file mode 100644
index 0000000000..b1543ffae5
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink-svgo.svg
@@ -0,0 +1,84 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="320" viewBox="0 0 850 320">
+ <title>
+ Freeze
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100)"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="70" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ <tspan font-style="italic" font-weight="700">Freeze</tspan> to keep visible
+ </text>
+ <g fill="none" transform="translate(170 190)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_120" startOffset="11.2%">(1)</textPath> <textPath xlink:href="#Path_120" startOffset="61.2%">(5)</textPath> <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%">|</textPath> <textPath xlink:href="#Path_120" startOffset="34%">(2)</textPath> <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(3)</textPath> <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%">|</textPath> <textPath xlink:href="#Path_120" startOffset="55%">(4)</textPath>
+ </text>
+ <path d="M-80-80L80 80" stroke="black"/>
+ <text class="text_normal" letter-spacing="12" transform="rotate(45 40.78 -38.1)">
+ PAST
+ </text>
+ <text class="text_normal" letter-spacing="12" transform="rotate(-135 27.43 23.79)">
+ FUTURE
+ </text>
+ <use xlink:href="#frozenPoint" transform="rotate(10)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(25)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(40)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(55)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(70)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(85)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(100)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(115)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(130)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(145)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(160)"/>
+ <use xlink:href="#frozenPoint" transform="rotate(175)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(190)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(205)"/>
+ <use xlink:href="#unfrozenPoint" transform="rotate(220)"/>
+ </g>
+ <g class="text_normal" transform="translate(380 30)">
+ <text>
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25">
+ 1: txid_current + 2 ^ 31 (split-point)
+ </text>
+ <text y="50">
+ 2: autovacuum_freeze_max_age (200 mio.)
+ </text>
+ <text y="75">
+ 3: vacuum_freeze_table_age (150 mio.)
+ </text>
+ <text y="100">
+ 4: vacuum_freeze_min_age (50 mio.)
+ </text>
+ <text y="125">
+ 5: txid_current (split-point, youngest xid)
+ </text>
+ <text y="155">
+ per table: pg_class.relfrozenxid <tspan font-weight="700">must</tspan> be between (1) and (5);
+ </text>
+ <text y="175" x="75">
+ normally it is between (3) and (4)
+ </text>
+ <use xlink:href="#unfrozenPoint" transform="translate(106 200)"/>
+ <text y="205" x="20">
+ Unfrozen xid
+ </text>
+ <use xlink:href="#frozenPoint" transform="translate(106 224)"/>
+ <text y="230" x="20">
+ Frozen xid
+ </text>
+ <text y="260">
+ (figure is out of scale)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-ink.svg b/doc/src/sgml/images/freeze-ink.svg
new file mode 100644
index 0000000000..316703d069
--- /dev/null
+++ b/doc/src/sgml/images/freeze-ink.svg
@@ -0,0 +1,365 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="320px"
+ viewBox="0 0 850 320"
+ id="svg147"
+ sodipodi:docname="freeze-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata151">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Freeze</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1295"
+ inkscape:window-height="803"
+ id="namedview149"
+ showgrid="false"
+ inkscape:zoom="0.44"
+ inkscape:cx="425"
+ inkscape:cy="153.18182"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg147" />
+ <title
+ id="title2">Freeze</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs11">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle
+ id="frozenPoint"
+ r="3"
+ stroke="green"
+ fill="green"
+ transform="translate(-100, 0)" />
+ <circle
+ id="unfrozenPoint"
+ r="3"
+ stroke="green"
+ fill="none"
+ transform="translate(-100, 0)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect13" />
+ <text
+ class="text_big"
+ x="70"
+ y="40"
+ id="text17"><tspan
+ style="font-style:italic;font-weight:bold"
+ id="tspan15">
+ Freeze</tspan>
+ to keep visible</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 190)"
+ id="g111">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle19" />
+ <text
+ class="text_normal"
+ id="text43">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath21">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath23">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath25">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="11.2%"
+ id="textPath27">(1)</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="61.2%"
+ id="textPath29">(5)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="red"
+ stroke-width="3"
+ startOffset="34%"
+ id="textPath31">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="34%"
+ id="textPath33">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="black"
+ stroke-width="3"
+ startOffset="45%"
+ id="textPath35">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath37">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ stroke="green"
+ stroke-width="3"
+ startOffset="55%"
+ id="textPath39">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="55%"
+ id="textPath41">(4)</textPath>
+ </text>
+ <!-- split it into 'past' and 'future' -->
+ <path
+ d="M -80 -80 l 160 160"
+ stroke="black"
+ id="path45" />
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(-15, -40) rotate(45)"
+ id="text47">PAST</text>
+ <text
+ class="text_normal"
+ letter-spacing="12"
+ transform="translate(30, 60) rotate(225)"
+ id="text49">FUTURE</text>
+ <g
+ transform="rotate(10)"
+ id="g53">
+ <use
+ xlink:href="#frozenPoint"
+ id="use51" />
+ </g>
+ <g
+ transform="rotate(25)"
+ id="g57">
+ <use
+ xlink:href="#frozenPoint"
+ id="use55" />
+ </g>
+ <g
+ transform="rotate(40)"
+ id="g61">
+ <use
+ xlink:href="#frozenPoint"
+ id="use59" />
+ </g>
+ <g
+ transform="rotate(55)"
+ id="g65">
+ <use
+ xlink:href="#frozenPoint"
+ id="use63" />
+ </g>
+ <g
+ transform="rotate(70)"
+ id="g69">
+ <use
+ xlink:href="#frozenPoint"
+ id="use67" />
+ </g>
+ <g
+ transform="rotate(85)"
+ id="g73">
+ <use
+ xlink:href="#frozenPoint"
+ id="use71" />
+ </g>
+ <g
+ transform="rotate(100)"
+ id="g77">
+ <use
+ xlink:href="#frozenPoint"
+ id="use75" />
+ </g>
+ <g
+ transform="rotate(115)"
+ id="g81">
+ <use
+ xlink:href="#frozenPoint"
+ id="use79" />
+ </g>
+ <g
+ transform="rotate(130)"
+ id="g85">
+ <use
+ xlink:href="#frozenPoint"
+ id="use83" />
+ </g>
+ <g
+ transform="rotate(145)"
+ id="g89">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use87" />
+ </g>
+ <g
+ transform="rotate(160)"
+ id="g93">
+ <use
+ xlink:href="#frozenPoint"
+ id="use91" />
+ </g>
+ <g
+ transform="rotate(175)"
+ id="g97">
+ <use
+ xlink:href="#frozenPoint"
+ id="use95" />
+ </g>
+ <g
+ transform="rotate(190)"
+ id="g101">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use99" />
+ </g>
+ <g
+ transform="rotate(205)"
+ id="g105">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use103" />
+ </g>
+ <g
+ transform="rotate(220)"
+ id="g109">
+ <use
+ xlink:href="#unfrozenPoint"
+ id="use107" />
+ </g>
+ </g>
+ <!-- legend -->
+ <g
+ class="text_normal"
+ transform="translate(380 30)"
+ id="g145">
+ <text
+ id="text117">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan113">^</tspan>
+<tspan
+ dy="5"
+ id="tspan115">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text119">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text
+ y="50"
+ id="text121">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text
+ y="75"
+ id="text123">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text
+ y="100"
+ id="text125">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text
+ y="125"
+ id="text127">5: txid_current (split-point, youngest xid)</text>
+ <text
+ y="155"
+ id="text131">per table: pg_class.relfrozenxid
+ <tspan
+ style="font-weight:bold"
+ id="tspan129">must</tspan>
+ be between (1) and (5);</text>
+ <text
+ y="175"
+ x="75"
+ id="text133">normally it is between (3) and (4)</text>
+ <use
+ xlink:href="#unfrozenPoint"
+ transform="translate(106, 200)"
+ id="use135" />
+ <text
+ y="205"
+ x="20"
+ id="text137">Unfrozen xid</text>
+ <use
+ xlink:href="#frozenPoint"
+ transform="translate(106, 224)"
+ id="use139" />
+ <text
+ y="230"
+ x="20"
+ id="text141">Frozen xid</text>
+ <text
+ y="260"
+ id="text143">(figure is out of scale)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/freeze-raw.svg b/doc/src/sgml/images/freeze-raw.svg
new file mode 100644
index 0000000000..9482167c3f
--- /dev/null
+++ b/doc/src/sgml/images/freeze-raw.svg
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="320px"
+ viewBox="0 0 850 320" >
+
+ <title>Freeze</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows it with
+ every shape element, especially with <circle>. As of 2020 we must restrict ourselves
+ to SVG 1. Therefore we simulate a circle by defining two arcs, each of them is
+ a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+
+ <!-- split transform="translate(x y) rotate(arc)" into two steps for clarity -->
+ <circle id="frozenPoint" r="3" stroke="green" fill="green" transform="translate(-100, 0)"/>
+ <circle id="unfrozenPoint" r="3" stroke="green" fill="none" transform="translate(-100, 0)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="70" y="40"><tspan style="font-style:italic;font-weight:bold">
+ Freeze</tspan> to keep visible</text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 190)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_120" startOffset="11.2%" >(1)</textPath>
+ <textPath xlink:href="#Path_120" startOffset="61.2%" >(5)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="red" stroke-width="3" startOffset="34%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="34%" >(2)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="black" stroke-width="3" startOffset="45%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(3)</textPath>
+
+ <textPath xlink:href="#Path_095" stroke="green" stroke-width="3" startOffset="55%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="55%" >(4)</textPath>
+
+ </text>
+
+ <!-- split it into 'past' and 'future' -->
+ <path d="M -80 -80 l 160 160" stroke="black" />
+ <text class="text_normal" letter-spacing="12" transform="translate(-15, -40) rotate(45)">PAST</text>
+ <text class="text_normal" letter-spacing="12" transform="translate(30, 60) rotate(225)">FUTURE</text>
+
+ <g transform="rotate(10)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(25)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(40)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(55)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(70)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(85)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(100)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(115)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(130)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(145)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(160)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(175)"><use xlink:href="#frozenPoint"/></g>
+ <g transform="rotate(190)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(205)"><use xlink:href="#unfrozenPoint"/></g>
+ <g transform="rotate(220)"><use xlink:href="#unfrozenPoint"/></g>
+
+ </g>
+
+ <!-- legend -->
+ <g class="text_normal" transform="translate(380 30)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: txid_current + 2 ^ 31 (split-point)</text>
+ <text y="50">2: autovacuum_freeze_max_age (200 mio.)</text>
+ <text y="75">3: vacuum_freeze_table_age (150 mio.)</text>
+ <text y="100">4: vacuum_freeze_min_age (50 mio.)</text>
+ <text y="125">5: txid_current (split-point, youngest xid)</text>
+ <text y="155">per table: pg_class.relfrozenxid
+ <tspan style="font-weight:bold">must</tspan> be between (1) and (5);</text>
+ <text y="175" x="75">normally it is between (3) and (4)</text>
+
+ <use xlink:href="#unfrozenPoint" transform="translate(106, 200)"/>
+ <text y="205" x="20">Unfrozen xid</text>
+
+ <use xlink:href="#frozenPoint" transform="translate(106, 224)"/>
+ <text y="230" x="20">Frozen xid</text>
+
+ <text y="260">(figure is out of scale)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
new file mode 100644
index 0000000000..e353ce4d87
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink-svgo.svg
@@ -0,0 +1,83 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="720" height="430" viewBox="0 0 720 430">
+ <title>
+ Hierarchy of Internal Objects
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="200" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif">
+ Hierarchy of Internal Objects
+ </text>
+ <g fill="none">
+ <g transform="translate(350 240)">
+ <ellipse rx="320" ry="170" stroke="blue"/>
+ <text class="text_normal" x="-140" y="-130">
+ Cluster
+ </text>
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-60" y="5">
+ Database Names
+ </text>
+ </g>
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-40" y="5">
+ Tablespace
+ </text>
+ </g>
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-70" y="5">
+ Replication Origins
+ </text>
+ </g>
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue"/>
+ <text class="text_normal" x="-60" y="-3">
+ Subscription for
+ </text>
+ <text class="text_normal" x="-68" y="10">
+ Logical Replication
+ </text>
+ </g>
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-15" y="5">
+ Role
+ </text>
+ </g>
+ </g>
+ <g transform="translate(270 250)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2"/>
+ <text class="text_normal" x="-60" y="-80">
+ Database
+ </text>
+ <g transform="translate(-150 -30)">
+ <ellipse rx="50" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Extension
+ </text>
+ </g>
+ <g transform="translate(-155 35)">
+ <ellipse rx="40" ry="20" stroke="blue"/>
+ <text class="text_normal" x="-35" y="5">
+ Collation
+ </text>
+ </g>
+ <g transform="translate(30 20)">
+ <ellipse rx="140" ry="70" stroke="blue"/>
+ <text class="text_normal" x="-80" y="-35">
+ Schema
+ </text>
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue"/>
+ <text class="text_normal" x="-50" y="5">
+ Table, View, ...
+ </text>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-ink.svg b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
new file mode 100644
index 0000000000..3429266782
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-ink.svg
@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="720px"
+ height="430px"
+ viewBox="0 0 720 430"
+ id="svg82"
+ sodipodi:docname="internal-objects-hierarchy-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata88">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Hierarchy of Internal Objects</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs86" />
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="919"
+ inkscape:window-height="528"
+ id="namedview84"
+ showgrid="false"
+ inkscape:zoom="0.51944444"
+ inkscape:cx="360"
+ inkscape:cy="215"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg82" />
+ <title
+ id="title2">Hierarchy of Internal Objects</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect6" />
+ <text
+ class="text_big"
+ x="200"
+ y="40"
+ id="text8">Hierarchy of Internal Objects</text>
+ <!-- set centre of figure and default values -->
+ <g
+ transform="translate(350 240)"
+ fill="none"
+ id="g80">
+ <g
+ id="g46">
+ <ellipse
+ rx="320"
+ ry="170"
+ stroke="blue"
+ id="ellipse10" />
+ <text
+ class="text_normal"
+ x="-140"
+ y="-130"
+ id="text12">Cluster</text>
+ <g
+ transform="translate(40 -125)"
+ id="g18">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse14" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="5"
+ id="text16">Database Names</text>
+ </g>
+ <g
+ transform="translate(180 -70)"
+ id="g24">
+ <ellipse
+ rx="60"
+ ry="20"
+ stroke="blue"
+ id="ellipse20" />
+ <text
+ class="text_normal"
+ x="-40"
+ y="5"
+ id="text22">Tablespace</text>
+ </g>
+ <g
+ transform="translate(230 -5)"
+ id="g30">
+ <ellipse
+ rx="80"
+ ry="20"
+ stroke="blue"
+ id="ellipse26" />
+ <text
+ class="text_normal"
+ x="-70"
+ y="5"
+ id="text28">Replication Origins</text>
+ </g>
+ <g
+ transform="translate(200 70)"
+ id="g38">
+ <ellipse
+ rx="78"
+ ry="27"
+ stroke="blue"
+ id="ellipse32" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-3"
+ id="text34">Subscription for</text>
+ <text
+ class="text_normal"
+ x="-68"
+ y="10"
+ id="text36">Logical Replication</text>
+ </g>
+ <g
+ transform="translate(100 120)"
+ id="g44">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse40" />
+ <text
+ class="text_normal"
+ x="-15"
+ y="5"
+ id="text42">Role</text>
+ </g>
+ </g>
+ <g
+ transform="translate(-80 10)"
+ id="g78">
+ <ellipse
+ rx="220"
+ ry="110"
+ stroke="blue"
+ stroke-width="2px"
+ id="ellipse48" />
+ <text
+ class="text_normal"
+ x="-60"
+ y="-80"
+ id="text50">Database</text>
+ <g
+ transform="translate(-120 -50)"
+ id="g76">
+ <g
+ transform="translate(-30 20)"
+ id="g56">
+ <ellipse
+ rx="50"
+ ry="20"
+ stroke="blue"
+ id="ellipse52" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text54">Extension</text>
+ </g>
+ <g
+ transform="translate(-35 85)"
+ id="g62">
+ <ellipse
+ rx="40"
+ ry="20"
+ stroke="blue"
+ id="ellipse58" />
+ <text
+ class="text_normal"
+ x="-35"
+ y="5"
+ id="text60">Collation</text>
+ </g>
+ <g
+ transform="translate(150 70)"
+ id="g74">
+ <ellipse
+ rx="140"
+ ry="70"
+ stroke="blue"
+ id="ellipse64" />
+ <text
+ class="text_normal"
+ x="-80"
+ y="-35"
+ id="text66">Schema</text>
+ <g
+ transform="translate(20 10)"
+ id="g72">
+ <ellipse
+ rx="90"
+ ry="30"
+ stroke="blue"
+ id="ellipse68" />
+ <text
+ class="text_normal"
+ x="-50"
+ y="5"
+ id="text70">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/internal-objects-hierarchy-raw.svg b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
new file mode 100644
index 0000000000..78850283d9
--- /dev/null
+++ b/doc/src/sgml/images/internal-objects-hierarchy-raw.svg
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="720px" height="430px"
+ viewBox="0 0 720 430" >
+
+ <title>Hierarchy of Internal Objects</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="200" y="40">Hierarchy of Internal Objects</text>
+
+
+ <!-- set centre of figure and default values -->
+ <g transform="translate(350 240)" fill="none">
+
+ <g>
+ <ellipse rx="320" ry="170" stroke="blue" />
+ <text class="text_normal" x="-140" y="-130">Cluster</text>
+
+ <g transform="translate(40 -125)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-60" y="5">Database Names</text>
+ </g>
+
+ <g transform="translate(180 -70)">
+ <ellipse rx="60" ry="20" stroke="blue" />
+ <text class="text_normal" x="-40" y="5">Tablespace</text>
+ </g>
+
+ <g transform="translate(230 -5)">
+ <ellipse rx="80" ry="20" stroke="blue" />
+ <text class="text_normal" x="-70" y="5">Replication Origins</text>
+ </g>
+
+ <g transform="translate(200 70)">
+ <ellipse rx="78" ry="27" stroke="blue" />
+ <text class="text_normal" x="-60" y="-3">Subscription for</text>
+ <text class="text_normal" x="-68" y="10">Logical Replication</text>
+ </g>
+
+ <g transform="translate(100 120)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-15" y="5">Role</text>
+ </g>
+
+ </g>
+
+ <g transform="translate(-80 10)">
+ <ellipse rx="220" ry="110" stroke="blue" stroke-width="2px" />
+ <text class="text_normal" x="-60" y="-80">Database</text>
+
+ <g transform="translate(-120 -50)">
+ <g transform="translate(-30 20)">
+ <ellipse rx="50" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Extension</text>
+ </g>
+
+ <g transform="translate(-35 85)">
+ <ellipse rx="40" ry="20" stroke="blue" />
+ <text class="text_normal" x="-35" y="5">Collation</text>
+ </g>
+
+ <g transform="translate(150 70)">
+ <ellipse rx="140" ry="70" stroke="blue" />
+ <text class="text_normal" x="-80" y="-35">Schema</text>
+
+ <g transform="translate(20 10)">
+ <ellipse rx="90" ry="30" stroke="blue" />
+ <text class="text_normal" x="-50" y="5">Table, View, ...</text>
+ </g>
+ </g>
+ </g>
+ </g>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink-svgo.svg b/doc/src/sgml/images/mvcc-ink-svgo.svg
new file mode 100644
index 0000000000..6ff6a4da79
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink-svgo.svg
@@ -0,0 +1,151 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="150" viewBox="0 0 850 150">
+ <title>
+ MVCC
+ </title>
+ <style>
+ .text_small{font-style:normal;font-weight:400;font-size:10px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <marker id="triangle_1" markerWidth="10" markerHeight="10" refX="5" refY="5" orient="auto" stroke="black" fill="none">
+ <path d="M0 0l10 5-10 5"/>
+ </marker>
+ <path id="arrow" d="M0 0q20-15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+ <g id="tuple" stroke="black">
+ <path d="M80 0H0v20h80M29 0v20M60 0v20"/>
+ <path d="M80 0h15M80 20h15" stroke-dasharray="2 1"/>
+ </g>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <g fill="none">
+ <g transform="translate(20 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">123</tspan> <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)" fill="#00f">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 83)" fill="#00f">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(185 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">135</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 53)" fill="#00f">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)" fill="#00f">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(350 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">142</tspan> <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 0
+ </text>
+ <text class="text_small" transform="translate(125 23)" fill="#00f">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)" fill="#00f">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(515 40)">
+ <text class="text_small" transform="translate(0 -18)">
+ T <tspan dx="-3" dy="5" font-size="8">821</tspan> <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5)"/>
+ <use xlink:href="#tuple" transform="translate(60 10)"/>
+ <text class="text_small" transform="translate(65 23)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(95 23)" fill="#00f">
+ 821
+ </text>
+ <text class="text_small" transform="translate(125 23)">
+ 'z'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 40)"/>
+ <text class="text_small" transform="translate(65 53)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(95 53)">
+ 142
+ </text>
+ <text class="text_small" transform="translate(125 53)">
+ 'y'
+ </text>
+ <use xlink:href="#tuple" transform="translate(60 70)"/>
+ <text class="text_small" transform="translate(65 83)">
+ 123
+ </text>
+ <text class="text_small" transform="translate(95 83)">
+ 135
+ </text>
+ <text class="text_small" transform="translate(125 83)">
+ 'x'
+ </text>
+ </g>
+ <g transform="translate(740 110)">
+ <path d="M102-20H-18v60" stroke="black"/>
+ <text font-weight="400" font-size="14" font-family=""Open Sans",sans-serif" fill="#000">
+ Legend
+ </text>
+ <use xlink:href="#tuple" transform="translate(0 10)"/>
+ <text class="text_small" transform="translate(3 23)">
+ xmin
+ </text>
+ <text class="text_small" transform="translate(32 23)">
+ xmax
+ </text>
+ <text class="text_small" transform="translate(65 23)">
+ data
+ </text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-ink.svg b/doc/src/sgml/images/mvcc-ink.svg
new file mode 100644
index 0000000000..80ae8d29e0
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-ink.svg
@@ -0,0 +1,398 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="150px"
+ viewBox="0 0 850 150"
+ id="svg4396"
+ sodipodi:docname="mvcc-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata4400">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>MVCC</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1266"
+ inkscape:window-height="788"
+ id="namedview4398"
+ showgrid="false"
+ inkscape:zoom="0.44470588"
+ inkscape:cx="425"
+ inkscape:cy="68.253968"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg4396" />
+ <title
+ id="title4251">MVCC</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style4253">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs4264">
+ <marker
+ id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto"
+ stroke="black"
+ fill="none">
+ <path
+ d="M 0,0 L 10,5 L 0,10"
+ id="path4255" />
+ </marker>
+ <g
+ id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path
+ d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20"
+ stroke="black"
+ id="path4258" />
+ <!-- prolong the rectangle -->
+ <path
+ d="M 80 0 h 15 M 80 20 h 15"
+ stroke="black"
+ stroke-dasharray="2 1"
+ id="path4260" />
+ </g>
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path
+ id="arrow"
+ d="M 0 0 Q 20 -15 40 0"
+ stroke="black"
+ marker-end="url(#triangle_1)" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect4266" />
+ <!-- set default values -->
+ <g
+ fill="none"
+ id="g4394">
+ <!-- start plus first INSERT -->
+ <g
+ transform="translate(20, 40)"
+ id="g4284">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4272">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4268">123</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4270">: INSERT</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4274" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4276" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ style="fill:blue"
+ id="text4278">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text4280">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ style="fill:blue"
+ id="text4282">'x'</text>
+ </g>
+ <!-- first UPDATE -->
+ <g
+ transform="translate(185, 40)"
+ id="g4310">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4290">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4286">135</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4288">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4292" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use4294" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ style="fill:blue"
+ id="text4296">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text4298">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ style="fill:blue"
+ id="text4300">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4302" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text4304">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ style="fill:blue"
+ id="text4306">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text4308">'x'</text>
+ </g>
+ <!-- next UPDATE -->
+ <g
+ transform="translate(350, 40)"
+ id="g4344">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4316">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4312">142</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4314">: UPDATE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4318" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use4320" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ style="fill:blue"
+ id="text4322">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text4324">0</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ style="fill:blue"
+ id="text4326">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use4328" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text4330">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ style="fill:blue"
+ id="text4332">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text4334">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4336" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text4338">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text4340">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text4342">'x'</text>
+ </g>
+ <!-- DELETE -->
+ <g
+ transform="translate(515, 40)"
+ id="g4378">
+ <text
+ class="text_small"
+ transform="translate(0, -18)"
+ id="text4350">T
+ <tspan
+ style="font-size:8px"
+ dx="-3"
+ dy="5"
+ id="tspan4346">821</tspan>
+<tspan
+ dx="-2"
+ dy="-5"
+ id="tspan4348">: DELTE</tspan>
+</text>
+ <use
+ xlink:href="#arrow"
+ transform="translate(5, 0)"
+ id="use4352" />
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 10)"
+ id="use4354" />
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text4356">142</text>
+ <text
+ class="text_small"
+ transform="translate(95, 23)"
+ style="fill:blue"
+ id="text4358">821</text>
+ <text
+ class="text_small"
+ transform="translate(125, 23)"
+ id="text4360">'z'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 40)"
+ id="use4362" />
+ <text
+ class="text_small"
+ transform="translate(65, 53)"
+ id="text4364">135</text>
+ <text
+ class="text_small"
+ transform="translate(95, 53)"
+ id="text4366">142</text>
+ <text
+ class="text_small"
+ transform="translate(125, 53)"
+ id="text4368">'y'</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(60, 70)"
+ id="use4370" />
+ <text
+ class="text_small"
+ transform="translate(65, 83)"
+ id="text4372">123</text>
+ <text
+ class="text_small"
+ transform="translate(95, 83)"
+ id="text4374">135</text>
+ <text
+ class="text_small"
+ transform="translate(125, 83)"
+ id="text4376">'x'</text>
+ </g>
+ <!-- LEGEND -->
+ <g
+ transform="translate(740, 110)"
+ id="g4392">
+ <path
+ d="M 102 -20 h -120 v 60"
+ stroke="black"
+ id="path4380" />
+ <text
+ class="text_normal"
+ transform="translate(0, 0)"
+ id="text4382">Legend</text>
+ <use
+ xlink:href="#tuple"
+ transform="translate(0, 10)"
+ id="use4384" />
+ <text
+ class="text_small"
+ transform="translate(3, 23)"
+ id="text4386">xmin</text>
+ <text
+ class="text_small"
+ transform="translate(32, 23)"
+ id="text4388">xmax</text>
+ <text
+ class="text_small"
+ transform="translate(65, 23)"
+ id="text4390">data</text>
+ </g>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/mvcc-raw.svg b/doc/src/sgml/images/mvcc-raw.svg
new file mode 100644
index 0000000000..ee27e3df7b
--- /dev/null
+++ b/doc/src/sgml/images/mvcc-raw.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="150px"
+ viewBox="0 0 850 150" >
+
+ <title>MVCC</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:10px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <marker id="triangle_1"
+ markerWidth="10"
+ markerHeight="10"
+ refX="5"
+ refY="5"
+ orient="auto" stroke="black" fill="none">
+ <path d="M 0,0 L 10,5 L 0,10" />
+ </marker>
+
+ <g id="tuple">
+ <!-- an rectangle, open at the right side -->
+ <path d="M 80 0 h -80 v 20 h 80 M 29 0 v 20 M 60 0 v 20" stroke="black"/>
+ <!-- prolong the rectangle -->
+ <path d="M 80 0 h 15 M 80 20 h 15" stroke="black" stroke-dasharray="2 1"/>
+ </g>
+
+ <!-- an arrow in the form of a quadratic bezier curve -->
+ <path id="arrow" d="M 0 0 Q 20 -15 40 0" stroke="black" marker-end="url(#triangle_1)"/>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- set default values -->
+ <g fill="none">
+
+ <!-- start plus first INSERT -->
+ <g transform="translate(20, 40)">
+
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">123</tspan>
+ <tspan dx="-2" dy="-5">: INSERT</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)" style="fill:blue">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 83)" style="fill:blue">'x'</text>
+ </g>
+
+ <!-- first UPDATE -->
+ <g transform="translate(185, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">135</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 53)" style="fill:blue">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)" style="fill:blue">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- next UPDATE -->
+ <g transform="translate(350, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">142</tspan>
+ <tspan dx="-2" dy="-5">: UPDATE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">0</text>
+ <text class="text_small" transform="translate(125, 23)" style="fill:blue">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)" style="fill:blue">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- DELETE -->
+ <g transform="translate(515, 40)">
+ <text class="text_small" transform="translate(0, -18)">T
+ <tspan style="font-size:8px" dx="-3" dy="5">821</tspan>
+ <tspan dx="-2" dy="-5">: DELTE</tspan>
+ </text>
+ <use xlink:href="#arrow" transform="translate(5, 0)"/>
+
+ <use xlink:href="#tuple" transform="translate(60, 10)"/>
+ <text class="text_small" transform="translate(65, 23)">142</text>
+ <text class="text_small" transform="translate(95, 23)" style="fill:blue">821</text>
+ <text class="text_small" transform="translate(125, 23)">'z'</text>
+ <use xlink:href="#tuple" transform="translate(60, 40)"/>
+ <text class="text_small" transform="translate(65, 53)">135</text>
+ <text class="text_small" transform="translate(95, 53)">142</text>
+ <text class="text_small" transform="translate(125, 53)">'y'</text>
+ <use xlink:href="#tuple" transform="translate(60, 70)"/>
+ <text class="text_small" transform="translate(65, 83)">123</text>
+ <text class="text_small" transform="translate(95, 83)">135</text>
+ <text class="text_small" transform="translate(125, 83)">'x'</text>
+ </g>
+
+ <!-- LEGEND -->
+ <g transform="translate(740, 110)">
+ <path d="M 102 -20 h -120 v 60" stroke="black"/>
+ <text class="text_normal" transform="translate(0, 0)">Legend</text>
+ <use xlink:href="#tuple" transform="translate(0, 10)"/>
+ <text class="text_small" transform="translate(3, 23)">xmin</text>
+ <text class="text_small" transform="translate(32, 23)">xmax</text>
+ <text class="text_small" transform="translate(65, 23)">data</text>
+ </g>
+
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink-svgo.svg b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
new file mode 100644
index 0000000000..aa0445352d
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink-svgo.svg
@@ -0,0 +1,285 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="900" height="600" viewBox="0 0 900 600">
+ <title>
+ PG Overall Server Architecture
+ </title>
+ <style>
+ .text_big{font-style:normal}.text_big,.text_comment,.text_normal,.text_small{font-weight:400;font-family:"Open Sans",sans-serif;fill:#000}.text_normal,.text_small{font-style:normal}.text_small{font-size:12px}.text_normal{font-size:14px}.text_big{font-size:24px}.text_comment{font-style:italic;font-size:14px}
+ </style>
+ <defs>
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (200 x 20 px)
+ </title>
+ <path d="M200 10v10H0V0h190v10h10L190 0"/>
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (250 x 20 px)
+ </title>
+ <path d="M250 10v10H0V0h240v10h10L240 0"/>
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (100 x 35 px)
+ </title>
+ <path d="M100 10v25H0V0h90v10h10L90 0"/>
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>
+ UML Note (170 x 50 px)
+ </title>
+ <path d="M170 10v40H0V0h160v10h10L160 0"/>
+ </symbol>
+ <symbol id="state_300x120">
+ <title>
+ UML State (300x120)
+ </title>
+ <rect width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>
+ UML State (350x120)
+ </title>
+ <rect width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="disc" stroke="blue" fill="none">
+ <title>
+ Disc
+ </title>
+ <ellipse cx="51" cy="13" rx="50" ry="12"/>
+ <path d="M1 13v60"/>
+ <path d="M101 13v60"/>
+ <path d="M1 73a50 12 0 00100 0"/>
+ </symbol>
+ <symbol id="laptop" stroke="black" fill="none">
+ <title>
+ Laptop
+ </title>
+ <path d="M20 40V0h54v40l15 15H5l15-15h54"/>
+ <path d="M23 3h48v34H23z"/>
+ <path d="M30 10h20"/>
+ <path d="M30 15h25"/>
+ <path d="M30 20h10"/>
+ <path d="M30 30h20"/>
+ <path d="M25 50h45l2 2H22z"/>
+ </symbol>
+ <marker id="arrowhead_start" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto">
+ <path d="M6 0L0 3l6 3" stroke="black" fill="none"/>
+ </marker>
+ <marker id="arrowhead_end" markerWidth="10" markerHeight="10" refX="6" refY="3" orient="auto">
+ <path d="M0 0l6 3-6 3" stroke="black" fill="none"/>
+ </marker>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="15" y="40" class="text_big">
+ Client
+ </text>
+ <text x="140" y="40" class="text_big">
+ Server
+ </text>
+ <use xlink:href="#laptop" x="5" y="210"/>
+ <g transform="translate(130 70)">
+ <use xlink:href="#state_350x120"/>
+ <text x="5" y="20" class="text_normal">
+ maintenance_work_mem (per connection)
+ </text>
+ <text x="5" y="45" class="text_normal">
+ work_mem (per query operation)
+ </text>
+ <text x="5" y="70" class="text_normal">
+ autovacuum_work_mem (per worker process)
+ </text>
+ <text x="5" y="95" class="text_normal">
+ temp_buffer (per connection)
+ </text>
+ <text x="5" y="110" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_200x20" x="140" y="-15"/>
+ <text x="150" class="text_comment">
+ Individual Memory
+ </text>
+ </g>
+ <g transform="translate(520 70)">
+ <use xlink:href="#state_300x120"/>
+ <text x="10" y="30" class="text_normal">
+ shared_buffers (heap and index)
+ </text>
+ <text x="10" y="70" class="text_normal">
+ wal_buffers (WAL records)
+ </text>
+ <text x="10" y="100" class="text_normal">
+ ...
+ </text>
+ <use xlink:href="#note_250x20" x="40" y="-15"/>
+ <text x="50" class="text_comment">
+ Shared Memory (per Instance)
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M180 215h250v30H180z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(180 215)">
+ Postmaster
+ </text>
+ <path d="M90 230h75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 230)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 1
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M150 315h370v30H150z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(150 315)">
+ Backend processes (one per connection)
+ </text>
+ <path d="M155 315v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M160 310v-5h370v30h-5" stroke="blue" fill="none"/>
+ <path d="M90 240l63 63" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140 290)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 3
+ </text>
+ </g>
+ <path d="M360 250v50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180 255)">
+ <use xlink:href="#note_250x20"/>
+ <text x="10" y="15" class="text_comment">
+ Creates backend processes
+ </text>
+ </g>
+ <g transform="translate(360 281)">
+ <circle r="8" stroke="black" fill="lightyellow"/>
+ <text x="-4" y="4" class="text_small">
+ 2
+ </text>
+ </g>
+ <path d="M460 300V200" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M498 300V95h30" stroke="black" fill="none" marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M508 300V135h20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M550 220h120v30H550z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(550 220)">
+ WAL Writer
+ </text>
+ <path d="M590 150v65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M590 255v230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 340h140v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 340)">
+ Checkpointer
+ </text>
+ <path d="M740 110v220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 355H475v130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M700 330V150" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50"/>
+ <text x="60" y="-35" class="text_comment">
+ Checkpoint
+ </text>
+ <text x="60" y="-20" class="text_comment">
+ Record
+ </text>
+ </g>
+ <path stroke="blue" fill="none" d="M610 380h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 380)">
+ Background Writer
+ </text>
+ <path d="M770 110v260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M605 395H485v90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M610 420h180v30H610z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(610 420)">
+ WAL Archiver
+ </text>
+ <path d="M620 485l30-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M690 455l30 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path stroke="blue" fill="none" d="M135 380h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 380)">
+ Autovacuum
+ </text>
+ <path d="M140 380v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path d="M145 375v-5h120v30h-5" stroke="blue" fill="none"/>
+ <path stroke="blue" fill="none" d="M135 430h120v30H135z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(135 430)">
+ Logger
+ </text>
+ <path stroke="blue" fill="none" d="M290 370h140v30H290z"/>
+ <text x="10" y="20" class="text_normal" transform="translate(290 370)">
+ Stats Collector
+ </text>
+ <g transform="translate(145 490)">
+ <use xlink:href="#disc"/>
+ <text x="35" y="45" class="text_normal">
+ Log
+ </text>
+ <text x="20" y="60" class="text_small">
+ text lines,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <path d="M195 465v20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(410 490)">
+ <use xlink:href="#disc"/>
+ <text x="10" y="40" class="text_normal">
+ Heap and
+ </text>
+ <text x="25" y="55" class="text_normal">
+ Index
+ </text>
+ <text x="15" y="70" class="text_small">
+ binary blocks,
+ </text>
+ <text x="30" y="80" class="text_small">
+ random
+ </text>
+ </g>
+ <path d="M450 485V350" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(295 420)">
+ <use xlink:href="#note_170x50"/>
+ <text x="5" y="15" class="text_comment">
+ Read heap and index
+ </text>
+ <text x="5" y="30" class="text_comment">
+ pages and transfer
+ </text>
+ <text x="5" y="45" class="text_comment">
+ them to shared_buffers
+ </text>
+ </g>
+ <g transform="translate(550 490)">
+ <use xlink:href="#disc"/>
+ <text x="30" y="45" class="text_normal">
+ WAL
+ </text>
+ <text x="10" y="60" class="text_small">
+ binary records,
+ </text>
+ <text x="20" y="75" class="text_small">
+ sequential
+ </text>
+ </g>
+ <g transform="translate(690 490)">
+ <use xlink:href="#disc"/>
+ <text x="16" y="45" class="text_normal">
+ Archived
+ </text>
+ <text x="36" y="60" class="text_normal">
+ WAL
+ </text>
+ </g>
+ <path d="M110 20v550" stroke="black" fill="none"/>
+ <g transform="rotate(90 -33.5 156.5)">
+ <use xlink:href="#note_200x20"/>
+ <text class="text_comment" x="10" y="15">
+ Via TCP/IP or socket
+ </text>
+ </g>
+ <text class="text_big" x="95" transform="rotate(90 425 425)">
+ RAM
+ </text>
+ <text class="text_big" x="250" transform="rotate(90 425 425)">
+ PROCESSES
+ </text>
+ <text class="text_big" x="500" transform="rotate(90 425 425)">
+ FILES
+ </text>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-ink.svg b/doc/src/sgml/images/ram-proc-file-ink.svg
new file mode 100644
index 0000000000..9ef89639c4
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-ink.svg
@@ -0,0 +1,841 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="900px"
+ height="600px"
+ viewBox="0 0 900 600"
+ id="svg4706"
+ sodipodi:docname="ram-proc-file-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata4710">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>PG Overall Server Architecture</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1282"
+ inkscape:window-height="733"
+ id="namedview4708"
+ showgrid="false"
+ inkscape:zoom="0.39333333"
+ inkscape:cx="450"
+ inkscape:cy="292.37288"
+ inkscape:window-x="66"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg4706" />
+ <title
+ id="title4402">PG Overall Server Architecture</title>
+ <style
+ type="text/css"
+ id="style4404">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs4470">
+ <!-- Some notes in different sizes -->
+ <symbol
+ id="note_200x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4406">UML Note (200 x 20 px)</title>
+ <path
+ d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10"
+ id="path4408" />
+ </symbol>
+ <symbol
+ id="note_250x20"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4411">UML Note (250 x 20 px)</title>
+ <path
+ d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10"
+ id="path4413" />
+ </symbol>
+ <symbol
+ id="note_100x35"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4416">UML Note (100 x 35 px)</title>
+ <path
+ d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10"
+ id="path4418" />
+ </symbol>
+ <symbol
+ id="note_170x50"
+ stroke="black"
+ fill="lightyellow">
+ <title
+ id="title4421">UML Note (170 x 50 px)</title>
+ <path
+ d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10"
+ id="path4423" />
+ </symbol>
+ <!-- UML states (used for buffers) -->
+ <symbol
+ id="state_300x120">
+ <title
+ id="title4426">UML State (300x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="300"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect4428" />
+ </symbol>
+ <symbol
+ id="state_350x120">
+ <title
+ id="title4431">UML State (350x120)</title>
+ <rect
+ x="0"
+ y="0"
+ width="350"
+ height="120"
+ rx="10"
+ stroke="blue"
+ fill="none"
+ id="rect4433" />
+ </symbol>
+ <!-- Discs -->
+ <symbol
+ id="disc"
+ stroke="blue"
+ fill="none">
+ <title
+ id="title4436">Disc</title>
+ <ellipse
+ cx="51"
+ cy="13"
+ rx="50"
+ ry="12"
+ id="ellipse4438" />
+ <!-- top -->
+ <path
+ d="M 1,13 v 60"
+ id="path4440" />
+ <!-- left -->
+ <path
+ d="M 101,13 v 60"
+ id="path4442" />
+ <!-- right -->
+ <path
+ d="M 1,73 A 50, 12, 0, 0, 0, 101,73"
+ id="path4444" />
+ <!-- bottom -->
+ </symbol>
+ <!-- Laptop -->
+ <symbol
+ id="laptop"
+ stroke="black"
+ fill="none">
+ <title
+ id="title4447">Laptop</title>
+ <path
+ d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54"
+ id="path4449" />
+ <rect
+ x="23"
+ y="3"
+ width="48"
+ height="34"
+ id="rect4451" />
+ <!-- symbolize some lines -->
+ <path
+ d="M 30,10 h 20"
+ id="path4453" />
+ <path
+ d="M 30,15 h 25"
+ id="path4455" />
+ <path
+ d="M 30,20 h 10"
+ id="path4457" />
+ <path
+ d="M 30,30 h 20"
+ id="path4459" />
+ <!-- symbolize keyboard -->
+ <path
+ d="M 25,50 h 45 l 2,2 h -50 z "
+ id="path4461" />
+ </symbol>
+ <!-- marker start/end -->
+ <marker
+ id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 6,0 l -6,3 l 6,3"
+ stroke="black"
+ fill="none"
+ id="path4464" />
+ </marker>
+ <marker
+ id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path
+ d="M 0,0 l 6,3 l -6,3"
+ stroke="black"
+ fill="none"
+ id="path4467" />
+ </marker>
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect4472" />
+ <!-- caption, client side -->
+ <text
+ x="15"
+ y="40"
+ class="text_big"
+ id="text4474">Client</text>
+ <text
+ x="140"
+ y="40"
+ class="text_big"
+ id="text4476">Server</text>
+ <use
+ xlink:href="#laptop"
+ x="5"
+ y="210"
+ id="use4478" />
+ <!-- individual memory -->
+ <g
+ transform="translate(130, 70)"
+ id="g4496">
+ <use
+ xlink:href="#state_350x120"
+ x="0"
+ y="0"
+ id="use4480" />
+ <text
+ x="5"
+ y="20"
+ class="text_normal"
+ id="text4482">maintenance_work_mem (per connection)</text>
+ <text
+ x="5"
+ y="45"
+ class="text_normal"
+ id="text4484">work_mem (per query operation)</text>
+ <text
+ x="5"
+ y="70"
+ class="text_normal"
+ id="text4486">autovacuum_work_mem (per worker process)</text>
+ <text
+ x="5"
+ y="95"
+ class="text_normal"
+ id="text4488">temp_buffer (per connection)</text>
+ <text
+ x="5"
+ y="110"
+ class="text_normal"
+ id="text4490">...</text>
+ <use
+ xlink:href="#note_200x20"
+ x="140"
+ y="-15"
+ id="use4492" />
+ <text
+ x="150"
+ y="0"
+ class="text_comment"
+ id="text4494">Individual Memory</text>
+ </g>
+ <!-- shared memory -->
+ <g
+ transform="translate(520, 70)"
+ id="g4510">
+ <use
+ xlink:href="#state_300x120"
+ x="0"
+ y="0"
+ id="use4498" />
+ <text
+ x="10"
+ y="30"
+ class="text_normal"
+ id="text4500">shared_buffers (heap and index)</text>
+ <text
+ x="10"
+ y="70"
+ class="text_normal"
+ id="text4502">wal_buffers (WAL records)</text>
+ <text
+ x="10"
+ y="100"
+ class="text_normal"
+ id="text4504">...</text>
+ <use
+ xlink:href="#note_250x20"
+ x="40"
+ y="-15"
+ id="use4506" />
+ <text
+ x="50"
+ y="0"
+ class="text_comment"
+ id="text4508">Shared Memory (per Instance)</text>
+ </g>
+ <!-- postmaster -->
+ <g
+ transform="translate(180, 215)"
+ id="g4516">
+ <rect
+ width="250"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4512" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4514">Postmaster</text>
+ </g>
+ <path
+ d="M 90,230 h 75"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4518" />
+ <g
+ transform="translate(140, 230)"
+ id="g4524">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle4520" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text4522">1</text>
+ </g>
+ <!-- backend processes -->
+ <g
+ transform="translate(150, 315)"
+ id="g4534">
+ <rect
+ width="370"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4526" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4528">Backend processes (one per connection)</text>
+ <path
+ d="M 5,0 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4530" />
+ <path
+ d="M 10,-5 v -5 h 370 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4532" />
+ </g>
+ <path
+ d="M 90,240 153,303"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path4536" />
+ <g
+ transform="translate(140, 290)"
+ id="g4542">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle4538" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text4540">3</text>
+ </g>
+ <!-- connection between postmaster and backend processes -->
+ <path
+ d="M 360,250 v 50"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4544" />
+ <g
+ transform="translate(180, 255)"
+ id="g4550">
+ <use
+ xlink:href="#note_250x20"
+ id="use4546" />
+ <text
+ x="10"
+ y="15"
+ class="text_comment"
+ id="text4548">Creates backend processes</text>
+ </g>
+ <g
+ transform="translate(360, 281)"
+ id="g4556">
+ <circle
+ r="8"
+ stroke="black"
+ fill="lightyellow"
+ id="circle4552" />
+ <text
+ x="-4"
+ y="4"
+ class="text_small"
+ id="text4554">2</text>
+ </g>
+ <!-- backend process' access to individual memory -->
+ <path
+ d="M 460,300 v -100"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path4558" />
+ <!-- its access to shared buffers and WAL buffers -->
+ <path
+ d="M 498,300 v -205 h 30"
+ stroke="black"
+ fill="none"
+ marker-start="url(#arrowhead_start)"
+ marker-end="url(#arrowhead_end)"
+ id="path4560" />
+ <path
+ d="M 508,300 v -165 h 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4562" />
+ <!-- WAL writer -->
+ <g
+ transform="translate(550, 220)"
+ id="g4568">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4564" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4566">WAL Writer</text>
+ </g>
+ <path
+ d="M 590,150 v 65"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4570" />
+ <path
+ d="M 590,255 v 230"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4572" />
+ <!-- Checkpoiner -->
+ <g
+ transform="translate(610, 340)"
+ id="g4578">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4574" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4576">Checkpointer</text>
+ </g>
+ <path
+ d="M 740,110 v 220"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4580" />
+ <path
+ d="M 605,355 h -130 v 130"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4582" />
+ <path
+ d="M 700,330 v -180"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4584" />
+ <g
+ transform="translate(570, 330)"
+ id="g4592">
+ <use
+ xlink:href="#note_100x35"
+ x="50"
+ y="-50"
+ id="use4586" />
+ <text
+ x="60"
+ y="-35"
+ class="text_comment"
+ id="text4588">Checkpoint</text>
+ <text
+ x="60"
+ y="-20"
+ class="text_comment"
+ id="text4590">Record</text>
+ </g>
+ <!-- BG writer -->
+ <g
+ transform="translate(610, 380)"
+ id="g4598">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4594" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4596">Background Writer</text>
+ </g>
+ <path
+ d="M 770,110 v 260"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4600" />
+ <path
+ d="M 605,395 h -120 v 90"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4602" />
+ <!-- Archiver -->
+ <g
+ transform="translate(610, 420)"
+ id="g4608">
+ <rect
+ width="180"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4604" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4606">WAL Archiver</text>
+ </g>
+ <path
+ d="M 620,485 l 30,-30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4610" />
+ <path
+ d="M 690,455 l 30, 30"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4612" />
+ <!-- Vacuum -->
+ <g
+ transform="translate(135, 380)"
+ id="g4622">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4614" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4616">Autovacuum</text>
+ <path
+ d="M 5,0 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4618" />
+ <path
+ d="M 10,-5 v -5 h 120 v 30 h -5"
+ stroke="blue"
+ fill="none"
+ id="path4620" />
+ </g>
+ <!-- Log Writer -->
+ <g
+ transform="translate(135, 430)"
+ id="g4628">
+ <rect
+ width="120"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4624" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4626">Logger</text>
+ </g>
+ <!-- Stats Collector -->
+ <g
+ transform="translate(290, 370)"
+ id="g4634">
+ <rect
+ width="140"
+ height="30"
+ stroke="blue"
+ fill="none"
+ id="rect4630" />
+ <text
+ x="10"
+ y="20"
+ class="text_normal"
+ id="text4632">Stats Collector</text>
+ </g>
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g
+ transform="translate(145, 490)"
+ id="g4644">
+ <use
+ xlink:href="#disc"
+ id="use4636" />
+ <text
+ x="35"
+ y="45"
+ class="text_normal"
+ id="text4638">Log</text>
+ <text
+ x="20"
+ y="60"
+ class="text_small"
+ id="text4640">text lines,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text4642">sequential</text>
+ </g>
+ <path
+ d="M 195,465 v 20"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4646" />
+ <g
+ transform="translate(410, 490)"
+ id="g4658">
+ <use
+ xlink:href="#disc"
+ id="use4648" />
+ <text
+ x="10"
+ y="40"
+ class="text_normal"
+ id="text4650">Heap and</text>
+ <text
+ x="25"
+ y="55"
+ class="text_normal"
+ id="text4652">Index</text>
+ <text
+ x="15"
+ y="70"
+ class="text_small"
+ id="text4654">binary blocks,</text>
+ <text
+ x="30"
+ y="80"
+ class="text_small"
+ id="text4656">random</text>
+ </g>
+ <path
+ d="M 450,485 v -135"
+ stroke="black"
+ fill="none"
+ marker-end="url(#arrowhead_end)"
+ id="path4660" />
+ <g
+ transform="translate(295, 420)"
+ id="g4670">
+ <use
+ xlink:href="#note_170x50"
+ id="use4662" />
+ <text
+ x="5"
+ y="15"
+ class="text_comment"
+ id="text4664">Read heap and index</text>
+ <text
+ x="5"
+ y="30"
+ class="text_comment"
+ id="text4666">pages and transfer</text>
+ <text
+ x="5"
+ y="45"
+ class="text_comment"
+ id="text4668">them to shared_buffers</text>
+ </g>
+ <g
+ transform="translate(550, 490)"
+ id="g4680">
+ <use
+ xlink:href="#disc"
+ id="use4672" />
+ <text
+ x="30"
+ y="45"
+ class="text_normal"
+ id="text4674">WAL</text>
+ <text
+ x="10"
+ y="60"
+ class="text_small"
+ id="text4676">binary records,</text>
+ <text
+ x="20"
+ y="75"
+ class="text_small"
+ id="text4678">sequential</text>
+ </g>
+ <g
+ transform="translate(690, 490)"
+ id="g4688">
+ <use
+ xlink:href="#disc"
+ id="use4682" />
+ <text
+ x="16"
+ y="45"
+ class="text_normal"
+ id="text4684">Archived</text>
+ <text
+ x="36"
+ y="60"
+ class="text_normal"
+ id="text4686">WAL</text>
+ </g>
+ <!-- boarder between client and server side -->
+ <path
+ d="M 110,20 v 550"
+ stroke="black"
+ fill="none"
+ id="path4690" />
+ <g
+ transform="translate(123, 190) rotate(90)"
+ id="g4696">
+ <use
+ xlink:href="#note_200x20"
+ id="use4692" />
+ <text
+ class="text_comment"
+ x="10"
+ y="15"
+ id="text4694">Via TCP/IP or socket</text>
+ </g>
+ <!-- right side -->
+ <g
+ transform="translate(850, 0) rotate(90)"
+ id="g4704">
+ <text
+ class="text_big"
+ x="95"
+ id="text4698">RAM</text>
+ <text
+ class="text_big"
+ x="250"
+ id="text4700">PROCESSES</text>
+ <text
+ class="text_big"
+ x="500"
+ id="text4702">FILES</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/ram-proc-file-raw.svg b/doc/src/sgml/images/ram-proc-file-raw.svg
new file mode 100644
index 0000000000..775ba91571
--- /dev/null
+++ b/doc/src/sgml/images/ram-proc-file-raw.svg
@@ -0,0 +1,301 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="900px" height="600px"
+ viewBox="0 0 900 600">
+
+ <title>PG Overall Server Architecture</title>
+
+ <style type="text/css">
+ .text_small {font-style:normal;
+ font-weight:normal;
+ font-size:12px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_comment {font-style:italic;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+
+ <!-- Some notes in different sizes -->
+ <symbol id="note_200x20" stroke="black" fill="lightyellow">
+ <title>UML Note (200 x 20 px)</title>
+ <path d="M 200,10 v 10 h -200 v -20 h 190 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_250x20" stroke="black" fill="lightyellow">
+ <title>UML Note (250 x 20 px)</title>
+ <path d="M 250,10 v 10 h -250 v -20 h 240 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_100x35" stroke="black" fill="lightyellow">
+ <title>UML Note (100 x 35 px)</title>
+ <path d="M 100,10 v 25 h -100 v -35 h 90 v 10 h 10 l -10,-10" />
+ </symbol>
+ <symbol id="note_170x50" stroke="black" fill="lightyellow">
+ <title>UML Note (170 x 50 px)</title>
+ <path d="M 170,10 v 40 h -170 v -50 h 160 v 10 h 10 l -10,-10" />
+ </symbol>
+
+ <!-- UML states (used for buffers) -->
+ <symbol id="state_300x120">
+ <title>UML State (300x120)</title>
+ <rect x="0" y="0" width="300" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+ <symbol id="state_350x120">
+ <title>UML State (350x120)</title>
+ <rect x="0" y="0" width="350" height="120" rx="10" stroke="blue" fill="none"/>
+ </symbol>
+
+ <!-- Discs -->
+ <symbol id="disc" stroke="blue" fill="none" >
+ <title>Disc</title>
+ <ellipse cx="51" cy="13" rx="50" ry="12" /> <!-- top -->
+ <path d="M 1,13 v 60" /> <!-- left -->
+ <path d="M 101,13 v 60" /> <!-- right -->
+ <path d="M 1,73 A 50, 12, 0, 0, 0, 101,73" /> <!-- bottom -->
+ </symbol>
+
+ <!-- Laptop -->
+ <symbol id="laptop" stroke="black" fill="none" >
+ <title>Laptop</title>
+ <path d="M 20,40 v -40 h 54 v 40 l 15,15 h -84 l 15,-15 h 54" />
+ <rect x="23" y="3" width="48" height="34" />
+ <!-- symbolize some lines -->
+ <path d="M 30,10 h 20" />
+ <path d="M 30,15 h 25" />
+ <path d="M 30,20 h 10" />
+ <path d="M 30,30 h 20" />
+ <!-- symbolize keyboard -->
+ <path d="M 25,50 h 45 l 2,2 h -50 z " />
+ </symbol>
+
+ <!-- marker start/end -->
+ <marker id="arrowhead_start"
+ markerWidth="10"
+ markerHeight="10"
+ refX="0"
+ refY="3"
+ orient="auto">
+ <path d="M 6,0 l -6,3 l 6,3" stroke="black" fill="none" />
+ </marker>
+ <marker id="arrowhead_end"
+ markerWidth="10"
+ markerHeight="10"
+ refX="6"
+ refY="3"
+ orient="auto">
+ <path d="M 0,0 l 6,3 l -6,3" stroke="black" fill="none" />
+ </marker>
+
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+
+ <!-- caption, client side -->
+ <text x="15" y="40" class="text_big">Client</text>
+ <text x="140" y="40" class="text_big">Server</text>
+ <use xlink:href="#laptop" x="5" y="210" />
+
+
+ <!-- individual memory -->
+ <g transform="translate(130, 70)">
+ <use xlink:href="#state_350x120" x="0" y="0" />
+ <text x="5" y="20" class="text_normal">maintenance_work_mem (per connection)</text>
+ <text x="5" y="45" class="text_normal">work_mem (per query operation)</text>
+ <text x="5" y="70" class="text_normal">autovacuum_work_mem (per worker process)</text>
+ <text x="5" y="95" class="text_normal">temp_buffer (per connection)</text>
+ <text x="5" y="110" class="text_normal">...</text>
+ <use xlink:href="#note_200x20" x="140" y="-15" />
+ <text x="150" y="0" class="text_comment">Individual Memory</text>
+ </g>
+
+ <!-- shared memory -->
+ <g transform="translate(520, 70)">
+ <use xlink:href="#state_300x120" x="0" y="0" />
+ <text x="10" y="30" class="text_normal">shared_buffers (heap and index)</text>
+ <text x="10" y="70" class="text_normal">wal_buffers (WAL records)</text>
+ <text x="10" y="100" class="text_normal">...</text>
+ <use xlink:href="#note_250x20" x="40" y="-15" />
+ <text x="50" y="0" class="text_comment">Shared Memory (per Instance)</text>
+ </g>
+
+ <!-- postmaster -->
+ <g transform="translate(180, 215)">
+ <rect width="250" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Postmaster</text>
+ </g>
+ <path d="M 90,230 h 75" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 230)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">1</text>
+ </g>
+
+ <!-- backend processes -->
+ <g transform="translate(150, 315)">
+ <rect width="370" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Backend processes (one per connection)</text>
+ <path d="M 5,0 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 370 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <path d="M 90,240 153,303" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(140, 290)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">3</text>
+ </g>
+
+ <!-- connection between postmaster and backend processes -->
+ <path d="M 360,250 v 50" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(180, 255)">
+ <use xlink:href="#note_250x20" />
+ <text x="10" y="15" class="text_comment">Creates backend processes</text>
+ </g>
+ <g transform="translate(360, 281)">
+ <circle r="8" stroke="black" fill="lightyellow" />
+ <text x="-4" y="4" class="text_small">2</text>
+ </g>
+
+ <!-- backend process' access to individual memory -->
+ <path d="M 460,300 v -100" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <!-- its access to shared buffers and WAL buffers -->
+ <path d="M 498,300 v -205 h 30" stroke="black" fill="none"
+ marker-start="url(#arrowhead_start)" marker-end="url(#arrowhead_end)"/>
+ <path d="M 508,300 v -165 h 20" stroke="black" fill="none"
+ marker-end="url(#arrowhead_end)"/>
+
+ <!-- WAL writer -->
+ <g transform="translate(550, 220)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Writer</text>
+ </g>
+ <path d="M 590,150 v 65" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 590,255 v 230" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Checkpoiner -->
+ <g transform="translate(610, 340)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Checkpointer</text>
+ </g>
+ <path d="M 740,110 v 220" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,355 h -130 v 130" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 700,330 v -180" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <g transform="translate(570, 330)">
+ <use xlink:href="#note_100x35" x="50" y="-50" />
+ <text x="60" y="-35" class="text_comment">Checkpoint</text>
+ <text x="60" y="-20" class="text_comment">Record</text>
+ </g>
+
+ <!-- BG writer -->
+ <g transform="translate(610, 380)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Background Writer</text>
+ </g>
+ <path d="M 770,110 v 260" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 605,395 h -120 v 90" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Archiver -->
+ <g transform="translate(610, 420)">
+ <rect width="180" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">WAL Archiver</text>
+ </g>
+ <path d="M 620,485 l 30,-30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+ <path d="M 690,455 l 30, 30" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <!-- Vacuum -->
+ <g transform="translate(135, 380)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Autovacuum</text>
+ <path d="M 5,0 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ <path d="M 10,-5 v -5 h 120 v 30 h -5" stroke="blue" fill="none" />
+ </g>
+
+ <!-- Log Writer -->
+ <g transform="translate(135, 430)">
+ <rect width="120" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Logger</text>
+ </g>
+
+ <!-- Stats Collector -->
+ <g transform="translate(290, 370)">
+ <rect width="140" height="30" stroke="blue" fill="none" />
+ <text x="10" y="20" class="text_normal">Stats Collector</text>
+ </g>
+
+ <!-- -->
+ <!-- files -->
+ <!-- -->
+ <g transform="translate(145, 490)">
+ <use xlink:href="#disc" />
+ <text x="35" y="45" class="text_normal">Log</text>
+ <text x="20" y="60" class="text_small">text lines,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+ <path d="M 195,465 v 20" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(410, 490)">
+ <use xlink:href="#disc" />
+ <text x="10" y="40" class="text_normal">Heap and</text>
+ <text x="25" y="55" class="text_normal">Index</text>
+ <text x="15" y="70" class="text_small">binary blocks,</text>
+ <text x="30" y="80" class="text_small">random</text>
+ </g>
+ <path d="M 450,485 v -135" stroke="black" fill="none" marker-end="url(#arrowhead_end)"/>
+
+ <g transform="translate(295, 420)">
+ <use xlink:href="#note_170x50" />
+ <text x="5" y="15" class="text_comment">Read heap and index</text>
+ <text x="5" y="30" class="text_comment">pages and transfer</text>
+ <text x="5" y="45" class="text_comment">them to shared_buffers</text>
+ </g>
+
+ <g transform="translate(550, 490)">
+ <use xlink:href="#disc" />
+ <text x="30" y="45" class="text_normal">WAL</text>
+ <text x="10" y="60" class="text_small">binary records,</text>
+ <text x="20" y="75" class="text_small">sequential</text>
+ </g>
+
+ <g transform="translate(690, 490)">
+ <use xlink:href="#disc" />
+ <text x="16" y="45" class="text_normal">Archived</text>
+ <text x="36" y="60" class="text_normal">WAL</text>
+ </g>
+
+ <!-- boarder between client and server side -->
+ <path d="M 110,20 v 550" stroke="black" fill="none" />
+ <g transform="translate(123, 190) rotate(90)">
+ <use xlink:href="#note_200x20" />
+ <text class="text_comment" x="10" y ="15">Via TCP/IP or socket</text>
+ </g>
+
+ <!-- right side -->
+ <g transform="translate(850, 0) rotate(90)">
+ <text class="text_big" x="95">RAM</text>
+ <text class="text_big" x="250">PROCESSES</text>
+ <text class="text_big" x="500">FILES</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink-svgo.svg b/doc/src/sgml/images/wraparound-ink-svgo.svg
new file mode 100644
index 0000000000..d5af6ce0b8
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink-svgo.svg
@@ -0,0 +1,40 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="850" height="280" viewBox="0 0 850 280">
+ <title>
+ Cyclic usage of XIDs
+ </title>
+ <style>
+ .text_normal{font-style:normal;font-weight:400;font-size:14px;font-family:"Open Sans",sans-serif;fill:#000}
+ </style>
+ <defs>
+ <path id="Path_080" d="M-80 0A80 80 0 1180 0 80 80 0 11-80 0"/>
+ <path id="Path_095" d="M-95 0A95 95 0 1195 0 95 95 0 11-95 0"/>
+ <path id="Path_120" d="M-120 0a120 120 0 11240 0 120 120 0 11-240 0"/>
+ </defs>
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none"/>
+ <text x="370" y="40" font-weight="400" font-size="24" font-family=""Open Sans",sans-serif,Helvetica">
+ Cyclic usage of XIDs modulo 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan>
+ </text>
+ <g fill="none" transform="translate(170 150)">
+ <circle r="100" stroke="blue"/>
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset=".5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="0%">(0)</textPath> <textPath xlink:href="#Path_080" startOffset="1%" stroke="blue" stroke-width=".5"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath> <textPath xlink:href="#Path_095" startOffset="30.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="30%">(1)</textPath> <textPath xlink:href="#Path_095" startOffset="45.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="45%">(2)</textPath> <textPath xlink:href="#Path_095" startOffset="50.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="50%">(3)</textPath> <textPath xlink:href="#Path_095" startOffset="62.5%">|</textPath> <textPath xlink:href="#Path_120" startOffset="62%">(4)</textPath>
+ </text>
+ </g>
+ <g class="text_normal">
+ <text transform="translate(400 130)">
+ 0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1
+ </text>
+ <text y="25" transform="translate(400 130)">
+ 1: oldest <tspan font-weight="700">active</tspan> xid (pg_stat_activity.backend_xmin)
+ </text>
+ <text y="50" transform="translate(400 130)">
+ 2: xmin of one row version
+ </text>
+ <text y="75" transform="translate(400 130)">
+ 3: xmax of the same row version
+ </text>
+ <text y="100" transform="translate(400 130)">
+ 4: youngest xid (txid_current)
+ </text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-ink.svg b/doc/src/sgml/images/wraparound-ink.svg
new file mode 100644
index 0000000000..51d35a9f85
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-ink.svg
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="850px"
+ height="280px"
+ viewBox="0 0 850 280"
+ id="svg216"
+ sodipodi:docname="wraparound-ink.svg"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
+ <metadata
+ id="metadata220">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title>Cyclic usage of XIDs</dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1247"
+ inkscape:window-height="650"
+ id="namedview218"
+ showgrid="false"
+ inkscape:zoom="0.44470588"
+ inkscape:cx="425"
+ inkscape:cy="133.25397"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="svg216" />
+ <title
+ id="title153">Cyclic usage of XIDs</title>
+ <!-- common text classes -->
+ <style
+ type="text/css"
+ id="style155">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+ <defs
+ id="defs160">
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path
+ id="Path_080"
+ d="m -80 0 a 80 80 0 1 1 160 0 a 80 80 0 1 1 -160 0" />
+ <path
+ id="Path_095"
+ d="m -95 0 a 95 95 0 1 1 190 0 a 95 95 0 1 1 -190 0" />
+ <path
+ id="Path_120"
+ d="m -120 0 a 120 120 0 1 1 240 0 a 120 120 0 1 1 -240 0" />
+ </defs>
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect
+ x="1"
+ y="1"
+ rx="5"
+ width="99%"
+ height="99%"
+ stroke="black"
+ fill="none"
+ id="rect162" />
+ <text
+ class="text_big"
+ x="370"
+ y="40"
+ id="text168">Cyclic usage of XIDs modulo 2
+ <tspan
+ dy="-5"
+ id="tspan164">^</tspan>
+<tspan
+ dy="5"
+ id="tspan166">32</tspan>
+</text>
+ <!-- set default values -->
+ <g
+ fill="none"
+ transform="translate(170 150)"
+ id="g196">
+ <circle
+ r="100"
+ stroke="blue"
+ id="circle170" />
+ <text
+ class="text_normal"
+ id="text194">
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="0.5%"
+ id="textPath172">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="00%"
+ id="textPath174">(0)</textPath>
+ <textPath
+ xlink:href="#Path_080"
+ startOffset="01%"
+ stroke="blue"
+ stroke-width="0.5px"
+ id="textPath176">
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="30.5%"
+ id="textPath178">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="30%"
+ id="textPath180">(1)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="45.5%"
+ id="textPath182">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="45%"
+ id="textPath184">(2)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="50.5%"
+ id="textPath186">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="50%"
+ id="textPath188">(3)</textPath>
+ <textPath
+ xlink:href="#Path_095"
+ startOffset="62.5%"
+ id="textPath190">|</textPath>
+ <textPath
+ xlink:href="#Path_120"
+ startOffset="62%"
+ id="textPath192">(4)</textPath>
+ </text>
+ </g>
+ <g
+ class="text_normal"
+ transform="translate(400 130)"
+ id="g214">
+ <text
+ id="text202">0: 0 .. 2 <tspan
+ dy="-5"
+ id="tspan198">^</tspan>
+<tspan
+ dy="5"
+ id="tspan200">32</tspan>
+ - 1</text>
+ <text
+ y="25"
+ id="text206">1: oldest <tspan
+ style="font-weight:bold"
+ id="tspan204">active</tspan>
+ xid (pg_stat_activity.backend_xmin)</text>
+ <text
+ y="50"
+ id="text208">2: xmin of one row version</text>
+ <text
+ y="75"
+ id="text210">3: xmax of the same row version</text>
+ <text
+ y="100"
+ id="text212">4: youngest xid (txid_current)</text>
+ </g>
+</svg>
diff --git a/doc/src/sgml/images/wraparound-raw.svg b/doc/src/sgml/images/wraparound-raw.svg
new file mode 100644
index 0000000000..637e68bb82
--- /dev/null
+++ b/doc/src/sgml/images/wraparound-raw.svg
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+ xmlns:xlink="http://www.w3.org/1999/xlink"
+ version="1.1"
+ width="850px" height="280px"
+ viewBox="0 0 850 280" >
+
+ <title>Cyclic usage of XIDs</title>
+
+ <!-- common text classes -->
+ <style type="text/css">
+ .text_normal {font-style:normal;
+ font-weight:normal;
+ font-size:14px;
+ font-family:"Open Sans", sans-serif;
+ fill:black;
+ }
+ .text_big {font-style:normal;
+ font-weight:normal;
+ font-size:24px;
+ font-family:"Open Sans", sans-serif, Helvetica;
+ fill:black;
+ }
+ </style>
+
+ <defs>
+ <!-- SVG 1.x supports <texPath> only in combination with <path>. SVG 2 allows the
+ combination with every shape element, especially with <circle>. As of 2020
+ we must restrict ourselves to SVG 1. Therefore: we simulate a circle by
+ defining two arcs, each of them is a half-circle.
+ -->
+ <path id="Path_080" d="m -80 0
+ a 80 80 0 1 1 160 0
+ a 80 80 0 1 1 -160 0"/>
+ <path id="Path_095" d="m -95 0
+ a 95 95 0 1 1 190 0
+ a 95 95 0 1 1 -190 0"/>
+ <path id="Path_120" d="m -120 0
+ a 120 120 0 1 1 240 0
+ a 120 120 0 1 1 -240 0"/>
+ </defs>
+
+
+ <!-- start of rendering area -->
+ <!-- enclosing rectangle -->
+ <rect x="1" y="1" rx="5" width="99%" height="99%" stroke="black" fill="none" />
+ <text class="text_big" x="370" y="40">Cyclic usage of XIDs modulo 2
+ <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan></text>
+
+ <!-- set default values -->
+ <g fill="none" transform="translate(170 150)">
+
+ <circle r="100" stroke="blue" />
+
+ <text class="text_normal">
+ <textPath xlink:href="#Path_095" startOffset="0.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="00%" >(0)</textPath>
+ <textPath xlink:href="#Path_080" startOffset="01%" stroke="blue" stroke-width="0.5px" >
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ></textPath>
+ <textPath xlink:href="#Path_095" startOffset="30.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="30%" >(1)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="45.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="45%" >(2)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="50.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="50%" >(3)</textPath>
+ <textPath xlink:href="#Path_095" startOffset="62.5%" >|</textPath>
+ <textPath xlink:href="#Path_120" startOffset="62%" >(4)</textPath>
+ </text>
+ </g>
+
+ <g class="text_normal" transform="translate(400 130)">
+ <text>0: 0 .. 2 <tspan dy="-5">^</tspan> <tspan dy="5">32</tspan> - 1</text>
+ <text y="25">1: oldest <tspan style="font-weight:bold">active</tspan> xid (pg_stat_activity.backend_xmin)</text>
+ <text y="50">2: xmin of one row version</text>
+ <text y="75">3: xmax of the same row version</text>
+ <text y="100">4: youngest xid (txid_current)</text>
+ </g>
+
+</svg>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 730d5fdc34..e9e9f9495f 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -248,6 +248,7 @@ break is not needed in a wider output rendering.
</para>
</partintro>
+ &architecture;
&arch-dev;
&catalogs;
&protocol;
diff --git a/doc/src/sgml/start.sgml b/doc/src/sgml/start.sgml
index 9bb5c1a6d5..abb61445f2 100644
--- a/doc/src/sgml/start.sgml
+++ b/doc/src/sgml/start.sgml
@@ -53,7 +53,7 @@
<sect1 id="tutorial-arch">
- <title>Architectural Fundamentals</title>
+ <title>Client/Server Model</title>
<para>
Before we proceed, you should understand the basic
@@ -68,34 +68,52 @@
client/server model. A <productname>PostgreSQL</productname>
session consists of the following cooperating processes
(programs):
+ </para>
- <itemizedlist>
- <listitem>
- <para>
- A server process, which manages the database files, accepts
- connections to the database from client applications, and
- performs database actions on behalf of the clients. The
- database server program is called
- <filename>postgres</filename>.
- <indexterm><primary>postgres</primary></indexterm>
- </para>
- </listitem>
+ <itemizedlist>
+ <listitem>
+ <para>
+ A process at the server site with the name
+ <glossterm linkend="glossary-postmaster">Postmaster</glossterm>.
+ <indexterm><primary>postgres</primary></indexterm>
+ <indexterm><primary>postmaster</primary></indexterm>
+ It accepts connection requests from client applications, starts
+ (<quote>forks</quote>) a new <glossterm linkend="glossary-backend">
+ Backend</glossterm> process for each of them, and passes
+ the connection to it. From that point on, the client and the new
+ Backend process communicate directly without intervention by the original
+ Postmaster process. Thus, the Postmaster process is always running,
+ waiting for new client connections, whereas clients and associated
+ Backend processes come and go. (All of this is of course invisible
+ to the user. We only mention it here for completeness.)
+ </para>
+ </listitem>
- <listitem>
- <para>
- The user's client (frontend) application that wants to perform
- database operations. Client applications can be very diverse
- in nature: a client could be a text-oriented tool, a graphical
- application, a web server that accesses the database to
- display web pages, or a specialized database maintenance tool.
- Some client applications are supplied with the
- <productname>PostgreSQL</productname> distribution; most are
- developed by users.
- </para>
- </listitem>
+ <listitem>
+ <para>
+ A group of processes at the server site, the <glossterm
+ linkend="glossary-instance">Instance</glossterm>, to which also
+ the Postmaster process belongs. Their duties are handling of
+ central, common database activities like file access, transaction
+ handling, vacuum, checkpoints, replication, and more. The mentioned
+ Backend processes delegate those actions to the instance.
+ </para>
+ </listitem>
- </itemizedlist>
- </para>
+ <listitem>
+ <para>
+ The user's client (frontend) application that wants to perform
+ database operations. Client applications can be very diverse
+ in nature: a client could be a text-oriented tool, a graphical
+ application, a web server that accesses the database to
+ display web pages, or a specialized database maintenance tool.
+ Some client applications are supplied with the
+ <productname>PostgreSQL</productname> distribution; most are
+ developed by users.
+ </para>
+ </listitem>
+
+ </itemizedlist>
<para>
As is typical of client/server applications, the client and the
@@ -106,18 +124,6 @@
file name) on the database server machine.
</para>
- <para>
- The <productname>PostgreSQL</productname> server can handle
- multiple concurrent connections from clients. To achieve this it
- starts (<quote>forks</quote>) a new process for each connection.
- From that point on, the client and the new server process
- communicate without intervention by the original
- <filename>postgres</filename> process. Thus, the
- supervisor server process is always running, waiting for
- client connections, whereas client and associated server processes
- come and go. (All of this is of course invisible to the user. We
- only mention it here for completeness.)
- </para>
</sect1>
0001-Aligning-terms-to-Glossary.patchtext/x-patch; charset=UTF-8; name=0001-Aligning-terms-to-Glossary.patchDownload
From 5785a5f873f1212249d2e2699a10d7b8b618250f Mon Sep 17 00:00:00 2001
From: juergen <juergen@purtz.de>
Date: Mon, 5 Apr 2021 14:18:21 +0200
Subject: [PATCH] Aligning terms to Glossary
---
doc/src/sgml/arch-dev.sgml | 45 ++++++++++++++++++++++----------------
1 file changed, 26 insertions(+), 19 deletions(-)
diff --git a/doc/src/sgml/arch-dev.sgml b/doc/src/sgml/arch-dev.sgml
index e56a13283f..3230264d91 100644
--- a/doc/src/sgml/arch-dev.sgml
+++ b/doc/src/sgml/arch-dev.sgml
@@ -114,21 +114,28 @@
<title>How Connections Are Established</title>
<para>
- <productname>PostgreSQL</productname> is implemented using a
- simple <quote>process per user</quote> client/server model. In this model
- there is one <firstterm>client process</firstterm> connected to
- exactly one <firstterm>server process</firstterm>. As we do not
+ <productname>PostgreSQL</productname> implements a
+ <quote>process per user</quote> client/server model.
+ In this model, every
+ <glossterm linkend="glossary-client">client process</glossterm>
+ connects to exactly one
+ <glossterm linkend="glossary-backend">backend process</glossterm>.
+ As we do not
know ahead of time how many connections will be made, we have to
- use a <firstterm>supervisor process</firstterm> (also
- <firstterm>master process</firstterm>) that spawns a new
- server process every time a connection is requested. This supervisor
- process is called <literal>postmaster</literal> and listens at a
- specified TCP/IP port for incoming connections. Whenever a request
- for a connection is detected the <literal>postmaster</literal>
- process spawns a new server process. The server processes
- communicate with each other using <firstterm>semaphores</firstterm> and
- <firstterm>shared memory</firstterm> to ensure data integrity
- throughout concurrent data access.
+ use a <quote>supervisor process</quote>
+ that spawns a new
+ backend process every time a connection is requested. This supervisor
+ process is called
+ <glossterm linkend="glossary-postmaster">postmaster</glossterm>
+ and listens at a
+ specified TCP/IP port for incoming connections. Whenever it detects
+ a request for a connection, it spawns a new backend process.
+ Those backend processes communicate with each other and with other
+ processes of the
+ <glossterm linkend="glossary-instance">instance</glossterm>
+ using <firstterm>semaphores</firstterm> and
+ <glossterm linkend="glossary-shared-memory">shared memory</glossterm>
+ to ensure data integrity throughout concurrent data access.
</para>
<para>
@@ -141,11 +148,11 @@
</para>
<para>
- Once a connection is established the client process can send a query
- to the <firstterm>backend</firstterm> (server). The query is transmitted using plain text,
- i.e., there is no parsing done in the <firstterm>frontend</firstterm> (client). The
- server parses the query, creates an <firstterm>execution plan</firstterm>,
- executes the plan and returns the retrieved rows to the client
+ Once a connection is established, the client process can send a query
+ to his backend process. The query is transmitted using plain text,
+ i.e., there is no parsing done in the client. The backend
+ process parses the query, creates an <firstterm>execution plan</firstterm>,
+ executes the plan, and returns the retrieved rows to the client
by transmitting them over the established connection.
</para>
</sect1>
--
2.25.1
On 2021-Apr-05, J�rgen Purtz wrote:
In addition to this chain Erik introduced in November within the same thread
some changes to the chapter "Overview of Query Handling", which subsequently
was expanded by Heikki and me with the sequence of
'arch-dev.sgml.xxxxx.diff' files. This is what I call the 'small patch'.
It's independent from the 'huge patch'. That 'small patch' is partly
committed by Heikki. In case that a committer gives the uncommitted part a
second chance, I append a patch. Because I'm not a native English speaker,
every improvement in the linguistic is highly welcome.
Pushed this one with cosmetic adjustments.
--
�lvaro Herrera Valdivia, Chile
"Cuando ma�ana llegue pelearemos segun lo que ma�ana exija" (Mowgli)
Hi Jürgen,
What's going to happen with this work?
If you intend to have it eventually committed, I think it will be
necessary to make the patches smaller, and bring them into the
commitfest app, so that others can follow progress.
I for one, cannot see/remember/understand what has been done, or even
whether you intend to continue with it.
Thanks,
Erik
Hi Jürgen,
What's going to happen with this work?
If you intend to have it eventually committed, I think it will be
necessary to make the patches smaller, and bring them into the
commitfest app, so that others can follow progress.I for one, cannot see/remember/understand what has been done, or even
whether you intend to continue with it.Thanks,
Erik
Peter changed the status to 'Returned with feedback' at the end of the
last commit fest. I'm not absolutely sure, but my understanding is that
the patch is rejected.
--
Jürgen Purtz
On Fri, 2021-05-21 at 08:47 +0200, Jürgen Purtz wrote:
Peter changed the status to 'Returned with feedback' at the end of the
last commit fest. I'm not absolutely sure, but my understanding is that
the patch is rejected.
There is a different status for that.
"Returned with feedback" means: there was review, and further work by
the author is needed, or we need more discussion if we want that or not
or how it should be, but there hasn't been a lot of feedback from the author
lately, so it seems that just moving it on to the next commitfest is not
the right thing to do.
You are welcome to re-submit the patch if you address the feedback.
Yours,
Laurenz Albe