mirror of
https://github.com/postgres/postgres.git
synced 2025-05-28 05:21:27 +03:00
For DocBook XML compatibility, don't use SGML empty tags (</>) anymore, replace by the full tag name. Add a warning option to catch future occurrences. Alexander Lakhin, Jürgen Purtz
161 lines
5.7 KiB
Plaintext
161 lines
5.7 KiB
Plaintext
<!-- doc/src/sgml/generic-wal.sgml -->
|
|
|
|
<chapter id="generic-wal">
|
|
<title>Generic WAL Records</title>
|
|
|
|
<para>
|
|
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.
|
|
</para>
|
|
|
|
<para>
|
|
The API for constructing generic WAL records is defined in
|
|
<filename>access/generic_xlog.h</filename> and implemented
|
|
in <filename>access/transam/generic_xlog.c</filename>.
|
|
</para>
|
|
|
|
<para>
|
|
To perform a WAL-logged data update using the generic WAL record
|
|
facility, follow these steps:
|
|
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>
|
|
<function>state = GenericXLogStart(relation)</function> — start
|
|
construction of a generic WAL record for the given relation.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
<function>page = GenericXLogRegisterBuffer(state, buffer, flags)</function>
|
|
— 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 is a bit mask of flags
|
|
applicable to the operation. Currently the only such flag is
|
|
<literal>GENERIC_XLOG_FULL_IMAGE</literal>, which indicates that a full-page
|
|
image rather than a delta update should be included in the WAL record.
|
|
Typically this flag would be set if the page is new or has been
|
|
rewritten completely.
|
|
<function>GenericXLogRegisterBuffer</function> can be repeated if the
|
|
WAL-logged action needs to modify multiple pages.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Apply modifications to the page images obtained in the previous step.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
<function>GenericXLogFinish(state)</function> — apply the changes to
|
|
the buffers and emit the generic WAL record.
|
|
</para>
|
|
</listitem>
|
|
</orderedlist>
|
|
</para>
|
|
|
|
<para>
|
|
WAL record construction can be canceled between any of the above steps by
|
|
calling <function>GenericXLogAbort(state)</function>. This will discard all
|
|
changes to the page image copies.
|
|
</para>
|
|
|
|
<para>
|
|
Please note the following points when using the generic WAL record
|
|
facility:
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
No direct modifications of buffers are allowed! All modifications must
|
|
be done in copies acquired from <function>GenericXLogRegisterBuffer()</function>.
|
|
In other words, code that makes generic WAL records should never call
|
|
<function>BufferGetPage()</function> 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>GenericXLogRegisterBuffer()</function> until after
|
|
<function>GenericXLogFinish()</function>.
|
|
</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
|
|
sequence. Keep in mind that buffers should be registered in the same
|
|
order in which locks are to be obtained on them during replay.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
The maximum number of buffers that can be registered for a generic WAL
|
|
record is <literal>MAX_GENERIC_XLOG_PAGES</literal>. An error will be thrown
|
|
if this limit is exceeded.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
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</structfield> and <structfield>pd_upper</structfield>.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
Since you are modifying copies of buffer
|
|
pages, <function>GenericXLogStart()</function> does not start a critical
|
|
section. Thus, you can safely do memory allocation, error throwing,
|
|
etc. between <function>GenericXLogStart()</function> and
|
|
<function>GenericXLogFinish()</function>. The only actual critical section is
|
|
present inside <function>GenericXLogFinish()</function>. There is no need to
|
|
worry about calling <function>GenericXLogAbort()</function> during an error
|
|
exit, either.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
<function>GenericXLogFinish()</function> takes care of marking buffers dirty
|
|
and setting their LSNs. You do not need to do this explicitly.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
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.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
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.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
If <literal>GENERIC_XLOG_FULL_IMAGE</literal> is not specified for a
|
|
registered buffer, 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.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</para>
|
|
</chapter>
|