public inbox for [email protected]
help / color / mirror / Atom feedFrom: Jürgen Purtz <[email protected]>
To: [email protected]
Subject: Re: Additional Chapter for Tutorial
Date: Tue, 2 Jun 2020 17:01:31 +0200
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
References: <[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
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:
[text/x-patch] 0004-architecture.patch (225.9K, 2-0004-architecture.patch)
download | inline diff:
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>
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected]
Subject: Re: Additional Chapter for Tutorial
In-Reply-To: <[email protected]>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox