2016-04-01 11:21:48 +02:00
|
|
|
<!-- doc/src/sgml/generic-wal.sgml -->
|
|
|
|
|
|
|
|
<chapter id="generic-wal">
|
2016-04-09 22:39:30 +02:00
|
|
|
<title>Generic WAL Records</title>
|
2016-04-01 11:21:48 +02:00
|
|
|
|
|
|
|
<para>
|
2016-04-09 22:39:30 +02:00
|
|
|
Although all built-in WAL-logged modules have their own types of WAL
|
|
|
|
records, there is also a generic WAL record type, which describes changes
|
|
|
|
to pages in a generic way. This is useful for extensions that provide
|
|
|
|
custom access methods, because they cannot register their own WAL redo
|
|
|
|
routines.
|
2016-04-01 11:21:48 +02:00
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2016-04-04 12:15:24 +02:00
|
|
|
The API for constructing generic WAL records is defined in
|
2016-04-09 22:39:30 +02:00
|
|
|
<filename>access/generic_xlog.h</> and implemented
|
|
|
|
in <filename>access/transam/generic_xlog.c</>.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
To perform a WAL-logged data update using the generic WAL record
|
|
|
|
facility, follow these steps:
|
2016-04-01 11:21:48 +02:00
|
|
|
|
|
|
|
<orderedlist>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
<function>state = GenericXLogStart(relation)</> — start
|
2016-04-09 22:39:30 +02:00
|
|
|
construction of a generic WAL record for the given relation.
|
2016-04-01 11:21:48 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
<function>page = GenericXLogRegister(state, buffer, isNew)</> —
|
2016-04-09 22:39:30 +02:00
|
|
|
register a buffer to be modified within the current generic WAL
|
|
|
|
record. This function returns a pointer to a temporary copy of the
|
|
|
|
buffer's page, where modifications should be made. (Do not modify the
|
|
|
|
buffer's contents directly.) The third argument indicates if the page
|
|
|
|
is new; if true, this will result in a full-page image rather than a
|
|
|
|
delta update being included in the WAL record.
|
|
|
|
<function>GenericXLogRegister</> can be repeated if the WAL-logged
|
|
|
|
action needs to modify multiple pages.
|
2016-04-01 11:21:48 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2016-04-09 22:39:30 +02:00
|
|
|
Apply modifications to the page images obtained in the previous step.
|
2016-04-01 11:21:48 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2016-04-09 22:39:30 +02:00
|
|
|
<function>GenericXLogFinish(state)</> — apply the changes to
|
|
|
|
the buffers and emit the generic WAL record.
|
2016-04-01 11:21:48 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</orderedlist>
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2016-04-09 22:39:30 +02:00
|
|
|
WAL record construction can be canceled between any of the above steps by
|
|
|
|
calling <function>GenericXLogAbort(state)</>. This will discard all
|
2016-04-01 11:21:48 +02:00
|
|
|
changes to the page image copies.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
2016-04-09 22:39:30 +02:00
|
|
|
Please note the following points when using the generic WAL record
|
|
|
|
facility:
|
|
|
|
|
2016-04-01 11:21:48 +02:00
|
|
|
<itemizedlist>
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2016-04-09 22:39:30 +02:00
|
|
|
No direct modifications of buffers are allowed! All modifications
|
2016-04-01 11:21:48 +02:00
|
|
|
must be done in copies acquired from <function>GenericXLogRegister()</>.
|
2016-04-09 22:39:30 +02:00
|
|
|
In other words, code that makes generic WAL records should never call
|
|
|
|
<function>BufferGetPage()</> for itself. However, it remains the
|
|
|
|
caller's responsibility to pin/unpin and lock/unlock the buffers at
|
|
|
|
appropriate times. Exclusive lock must be held on each target buffer
|
|
|
|
from before <function>GenericXLogRegister()</> until after
|
|
|
|
<function>GenericXLogFinish()</>.
|
2016-04-01 11:21:48 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
<para>
|
|
|
|
Registrations of buffers (step 2) and modifications of page images
|
|
|
|
(step 3) can be mixed freely, i.e., both steps may be repeated in any
|
2016-04-09 22:39:30 +02:00
|
|
|
sequence. Keep in mind that buffers should be registered in the same
|
|
|
|
order in which locks are to be obtained on them during replay.
|
2016-04-01 11:21:48 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2016-04-09 22:39:30 +02:00
|
|
|
The maximum number of buffers that can be registered for a generic WAL
|
|
|
|
record is <literal>MAX_GENERIC_XLOG_PAGES</>. An error will be thrown
|
|
|
|
if this limit is exceeded.
|
2016-04-01 11:21:48 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2016-04-09 22:39:30 +02:00
|
|
|
Generic WAL assumes that the pages to be modified have standard
|
|
|
|
layout, and in particular that there is no useful data between
|
|
|
|
<structfield>pd_lower</> and <structfield>pd_upper</>.
|
2016-04-01 11:21:48 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
|
|
|
|
<listitem>
|
|
|
|
<para>
|
2016-04-09 22:39:30 +02:00
|
|
|
Since you are modifying copies of buffer
|
|
|
|
pages, <function>GenericXLogStart()</> does not start a critical
|
|
|
|
section. Thus, you can safely do memory allocation, error throwing,
|
|
|
|
etc. between <function>GenericXLogStart()</> and
|
|
|
|
<function>GenericXLogFinish()</>. The only actual critical section is
|
|
|
|
present inside <function>GenericXLogFinish()</>. There is no need to
|
|
|
|
worry about calling <function>GenericXLogAbort()</> during an error
|
|
|
|
exit, either.
|
2016-04-01 11:21:48 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
2016-04-09 22:39:30 +02:00
|
|
|
|
2016-04-01 11:21:48 +02:00
|
|
|
<listitem>
|
|
|
|
<para>
|
2016-04-09 22:39:30 +02:00
|
|
|
<function>GenericXLogFinish()</> takes care of marking buffers dirty
|
2016-04-01 11:21:48 +02:00
|
|
|
and setting their LSNs. You do not need to do this explicitly.
|
|
|
|
</para>
|
|
|
|
</listitem>
|
2016-04-09 22:39:30 +02:00
|
|
|
|
2016-04-01 11:21:48 +02:00
|
|
|
<listitem>
|
|
|
|
<para>
|
2016-04-09 22:39:30 +02:00
|
|
|
For unlogged relations, everything works the same except that no
|
|
|
|
actual WAL record is emitted. Thus, you typically do not need to do
|
|
|
|
any explicit checks for unlogged relations.
|
2016-04-01 11:21:48 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
2016-04-09 22:39:30 +02:00
|
|
|
|
2016-04-01 11:21:48 +02:00
|
|
|
<listitem>
|
|
|
|
<para>
|
2016-04-09 22:39:30 +02:00
|
|
|
The generic WAL redo function will acquire exclusive locks to buffers
|
|
|
|
in the same order as they were registered. After redoing all changes,
|
|
|
|
the locks will be released in the same order.
|
2016-04-01 11:21:48 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
2016-04-09 22:39:30 +02:00
|
|
|
|
2016-04-01 11:21:48 +02:00
|
|
|
<listitem>
|
|
|
|
<para>
|
2016-04-09 22:39:30 +02:00
|
|
|
If a registered buffer is not new, the generic WAL record contains
|
|
|
|
a delta between the old and the new page images. This delta is based
|
|
|
|
on byte-by-byte comparison. This is not very compact for the case of
|
|
|
|
moving data within a page, and might be improved in the future.
|
2016-04-01 11:21:48 +02:00
|
|
|
</para>
|
|
|
|
</listitem>
|
|
|
|
</itemizedlist>
|
|
|
|
</para>
|
|
|
|
</chapter>
|