| <!-- 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. |
| </para> |
| |
| <para> |
| In comparison with <link linkend="custom-rmgr">Custom WAL Resource |
| Managers</link>, Generic WAL is simpler for an extension to implement and |
| does not require the extension library to be loaded in order to apply the |
| records. |
| </para> |
| |
| <note> |
| <para> |
| Generic WAL records are ignored during <link |
| linkend="logicaldecoding">Logical Decoding</link>. If logical decoding is |
| required for your extension, consider a Custom WAL Resource Manager. |
| </para> |
| </note> |
| |
| <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> |