mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-08-23 09:40:40 +02:00
Rename this function to GenericXLogRegisterBuffer() to make it clearer what it does, and leave room for other sorts of "register" actions in future. Also, replace its "bool isNew" argument with an integer flags argument, so as to allow adding more flags in future without an API break. Alexander Korotkov, adjusted slightly by me
161 lines
5.5 KiB
Plaintext
161 lines
5.5 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</> 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:
|
|
|
|
<orderedlist>
|
|
<listitem>
|
|
<para>
|
|
<function>state = GenericXLogStart(relation)</> — start
|
|
construction of a generic WAL record for the given relation.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
<function>page = GenericXLogRegisterBuffer(state, buffer, flags)</>
|
|
— 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 bitmask of flags
|
|
applicable to the operation. Currently the only such flag is
|
|
<literal>GENERIC_XLOG_FULL_IMAGE</>, 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</> 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)</> — 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)</>. 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()</>.
|
|
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>GenericXLogRegisterBuffer()</> until after
|
|
<function>GenericXLogFinish()</>.
|
|
</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</>. 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</> and <structfield>pd_upper</>.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
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.
|
|
</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>
|
|
<function>GenericXLogFinish()</> 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</> 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>
|