diff options
Diffstat (limited to 'doc/src/sgml/generic-wal.sgml')
-rw-r--r-- | doc/src/sgml/generic-wal.sgml | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/doc/src/sgml/generic-wal.sgml b/doc/src/sgml/generic-wal.sgml new file mode 100644 index 0000000..7a02849 --- /dev/null +++ b/doc/src/sgml/generic-wal.sgml @@ -0,0 +1,160 @@ +<!-- 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> |