-
Notifications
You must be signed in to change notification settings - Fork 212
Feature: Support custom wal rmgr #189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,98 @@ | ||
| <!-- doc/src/sgml/custom-rmgr.sgml --> | ||
|
|
||
| <chapter id="custom-rmgr"> | ||
| <title>Custom WAL Resource Managers</title> | ||
|
|
||
| <para> | ||
| This chapter explains the interface between the core | ||
| <productname>PostgreSQL</productname> system and custom WAL resource | ||
| managers, which enable extensions to integrate directly with the <link | ||
| linkend="wal"><acronym>WAL</acronym></link>. | ||
| </para> | ||
| <para> | ||
| An extension, especially a <link linkend="tableam">Table Access | ||
| Method</link> or <link linkend="indexam">Index Access Method</link>, may | ||
| need to use WAL for recovery, replication, and/or <link | ||
| linkend="logicaldecoding">Logical Decoding</link>. Custom resource managers | ||
| are a more flexible alternative to <link linkend="generic-wal">Generic | ||
| WAL</link> (which does not support logical decoding), but more complex for | ||
| an extension to implement. | ||
| </para> | ||
| <para> | ||
| To create a new custom WAL resouce manager, first define an | ||
| <structname>RmgrData</structname> structure with implementations for the | ||
| resource manager methods. Refer to | ||
| <filename>src/backend/access/transam/README</filename> and | ||
| <filename>src/include/access/xlog_internal.h</filename> in the | ||
| <productname>PostgreSQL</productname> source. | ||
| <programlisting> | ||
| /* | ||
| * Method table for resource managers. | ||
| * | ||
| * This struct must be kept in sync with the PG_RMGR definition in | ||
| * rmgr.c. | ||
| * | ||
| * rm_identify must return a name for the record based on xl_info (without | ||
| * reference to the rmid). For example, XLOG_BTREE_VACUUM would be named | ||
| * "VACUUM". rm_desc can then be called to obtain additional detail for the | ||
| * record, if available (e.g. the last block). | ||
| * | ||
| * rm_mask takes as input a page modified by the resource manager and masks | ||
| * out bits that shouldn't be flagged by wal_consistency_checking. | ||
| * | ||
| * RmgrTable[] is indexed by RmgrId values (see rmgrlist.h). If rm_name is | ||
| * NULL, the corresponding RmgrTable entry is considered invalid. | ||
| */ | ||
| typedef struct RmgrData | ||
| { | ||
| const char *rm_name; | ||
| void (*rm_redo) (XLogReaderState *record); | ||
| void (*rm_desc) (StringInfo buf, XLogReaderState *record); | ||
| const char *(*rm_identify) (uint8 info); | ||
| void (*rm_startup) (void); | ||
|
my-ship-it marked this conversation as resolved.
|
||
| void (*rm_cleanup) (void); | ||
| void (*rm_mask) (char *pagedata, BlockNumber blkno); | ||
| void (*rm_decode) (struct LogicalDecodingContext *ctx, | ||
| struct XLogRecordBuffer *buf); | ||
| } RmgrData; | ||
| </programlisting> | ||
| </para> | ||
| <para> | ||
| Then, register your new resource | ||
| manager. | ||
|
|
||
| <programlisting> | ||
| /* | ||
| * Register a new custom WAL resource manager. | ||
| * | ||
| * Resource manager IDs must be globally unique across all extensions. Refer | ||
| * to https://wiki.postgresql.org/wiki/CustomWALResourceManager to reserve a | ||
| * unique RmgrId for your extension, to avoid conflicts with other extension | ||
| * developers. During development, use RM_EXPERIMENTAL_ID to avoid needlessly | ||
| * reserving a new ID. | ||
| */ | ||
| extern void RegisterCustomRmgr(RmgrId rmid, RmgrData *rmgr); | ||
| </programlisting> | ||
| <function>RegisterCustomRmgr</function> must be called from the | ||
| extension module's <link linkend="xfunc-c-dynload">_PG_init</link> function. | ||
| While developing a new extension, use <literal>RM_EXPERIMENTAL_ID</literal> | ||
| for <parameter>rmid</parameter>. When you ready to release the extension to | ||
| users, reserve a new resource manager ID at the <ulink | ||
| url="https://wiki.postgresql.org/wiki/CustomWALResourceManagers">Custom WAL | ||
| Resource Manager</ulink> page. | ||
| </para> | ||
|
|
||
| <para> | ||
| Place the extension module implementing the custom resource manager in <xref | ||
| linkend="guc-shared-preload-libraries"/> so that it will be loaded early | ||
| during <productname>PostgreSQL</productname> startup. | ||
| </para> | ||
| <note> | ||
| <para> | ||
| The extension must remain in shared_preload_libraries as long as any | ||
| custom WAL records may exist in the system. Otherwise | ||
| <productname>PostgreSQL</productname> will not be able to apply or decode | ||
| the custom WAL records, which may prevent the server from starting. | ||
| </para> | ||
| </note> | ||
| </chapter> | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,174 @@ | ||
| <!-- 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> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.