Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5c279a6

Browse files
committed
Custom WAL Resource Managers.
Allow extensions to specify a new custom resource manager (rmgr),which allows specialized WAL. This is meant to be used by a TableAccess Method or Index Access Method.Prior to this commit, only Generic WAL was available, which offerssupport for recovery and physical replication but not logicalreplication.Reviewed-by: Julien Rouhaud, Bharath Rupireddy, Andres FreundDiscussion:https://postgr.es/m/ed1fb2e22d15d3563ae0eb610f7b61bb15999c0a.camel%40j-davis.com
1 parenta8cfb0c commit5c279a6

File tree

24 files changed

+526
-70
lines changed

24 files changed

+526
-70
lines changed

‎doc/src/sgml/config.sgml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11189,8 +11189,8 @@ LOG: CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
1118911189
<literal>heap2</literal>, <literal>btree</literal>, <literal>hash</literal>,
1119011190
<literal>gin</literal>, <literal>gist</literal>, <literal>sequence</literal>,
1119111191
<literal>spgist</literal>, <literal>brin</literal>, and <literal>generic</literal>.
11192-
Only superusers and users with the appropriate <literal>SET</literal>
11193-
privilege can change this setting.
11192+
Extensions may define additional resource managers.Only superusers and users with
11193+
the appropriate <literal>SET</literal>privilege can change this setting.
1119411194
</para>
1119511195
</listitem>
1119611196
</varlistentry>

‎doc/src/sgml/custom-rmgr.sgml

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<!-- doc/src/sgml/custom-rmgr.sgml -->
2+
3+
<chapter id="custom-rmgr">
4+
<title>Custom WAL Resource Managers</title>
5+
6+
<para>
7+
This chapter explains the interface between the core
8+
<productname>PostgreSQL</productname> system and custom WAL resource
9+
managers, which enable extensions to integrate directly with the <link
10+
linkend="wal"><acronym>WAL</acronym></link>.
11+
</para>
12+
<para>
13+
An extension, especially a <link linkend="tableam">Table Access
14+
Method</link> or <link linkend="indexam">Index Access Method</link>, may
15+
need to use WAL for recovery, replication, and/or <link
16+
linkend="logicaldecoding">Logical Decoding</link>. Custom resource managers
17+
are a more flexible alternative to <link linkend="generic-wal">Generic
18+
WAL</link> (which does not support logical decoding), but more complex for
19+
an extension to implement.
20+
</para>
21+
<para>
22+
To create a new custom WAL resouce manager, first define an
23+
<structname>RmgrData</structname> structure with implementations for the
24+
resource manager methods. Refer to
25+
<filename>src/backend/access/transam/README</filename> and
26+
<filename>src/include/access/xlog_internal.h</filename> in the
27+
<productname>PostgreSQL</productname> source.
28+
<programlisting>
29+
/*
30+
* Method table for resource managers.
31+
*
32+
* This struct must be kept in sync with the PG_RMGR definition in
33+
* rmgr.c.
34+
*
35+
* rm_identify must return a name for the record based on xl_info (without
36+
* reference to the rmid). For example, XLOG_BTREE_VACUUM would be named
37+
* "VACUUM". rm_desc can then be called to obtain additional detail for the
38+
* record, if available (e.g. the last block).
39+
*
40+
* rm_mask takes as input a page modified by the resource manager and masks
41+
* out bits that shouldn't be flagged by wal_consistency_checking.
42+
*
43+
* RmgrTable[] is indexed by RmgrId values (see rmgrlist.h). If rm_name is
44+
* NULL, the corresponding RmgrTable entry is considered invalid.
45+
*/
46+
typedef struct RmgrData
47+
{
48+
const char *rm_name;
49+
void (*rm_redo) (XLogReaderState *record);
50+
void (*rm_desc) (StringInfo buf, XLogReaderState *record);
51+
const char *(*rm_identify) (uint8 info);
52+
void (*rm_startup) (void);
53+
void (*rm_cleanup) (void);
54+
void (*rm_mask) (char *pagedata, BlockNumber blkno);
55+
void (*rm_decode) (struct LogicalDecodingContext *ctx,
56+
struct XLogRecordBuffer *buf);
57+
} RmgrData;
58+
</programlisting>
59+
</para>
60+
<para>
61+
Then, register your new resource
62+
manager.
63+
64+
<programlisting>
65+
/*
66+
* Register a new custom WAL resource manager.
67+
*
68+
* Resource manager IDs must be globally unique across all extensions. Refer
69+
* to https://wiki.postgresql.org/wiki/CustomWALResourceManager to reserve a
70+
* unique RmgrId for your extension, to avoid conflicts with other extension
71+
* developers. During development, use RM_EXPERIMENTAL_ID to avoid needlessly
72+
* reserving a new ID.
73+
*/
74+
extern void RegisterCustomRmgr(RmgrId rmid, RmgrData *rmgr);
75+
</programlisting>
76+
<function>RegisterCustomRmgr</function> must be called from the
77+
extension module's <link linkend="xfunc-c-dynload">_PG_init</link> function.
78+
While developing a new extension, use <literal>RM_EXPERIMENTAL_ID</literal>
79+
for <parameter>rmid</parameter>. When you ready to release the extension to
80+
users, reserve a new resource manager ID at the <ulink
81+
url="https://wiki.postgresql.org/wiki/CustomWALResourceManagers">Custom WAL
82+
Resource Manager</ulink> page.
83+
</para>
84+
85+
<para>
86+
Place the extension module implementing the custom resource manager in <xref
87+
linkend="guc-shared-preload-libraries"/> so that it will be loaded early
88+
during <productname>PostgreSQL</productname> startup.
89+
</para>
90+
<note>
91+
<para>
92+
The extension must remain in shared_preload_libraries as long as any
93+
custom WAL records may exist in the system. Otherwise
94+
<productname>PostgreSQL</productname> will not be able to apply or decode
95+
the custom WAL records, which may prevent the server from starting.
96+
</para>
97+
</note>
98+
</chapter>

‎doc/src/sgml/filelist.sgml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
<!ENTITY storage SYSTEM "storage.sgml">
106106
<!ENTITY tablesample-method SYSTEM "tablesample-method.sgml">
107107
<!ENTITY generic-wal SYSTEM "generic-wal.sgml">
108+
<!ENTITY custom-rmgr SYSTEM "custom-rmgr.sgml">
108109
<!ENTITY backup-manifest SYSTEM "backup-manifest.sgml">
109110

110111
<!-- contrib information -->

‎doc/src/sgml/func.sgml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26001,6 +26001,25 @@ postgres=# SELECT * FROM pg_walfile_name_offset((pg_backup_stop()).lsn);
2600126001
without recovery, the function returns <literal>NULL</literal>.
2600226002
</para></entry>
2600326003
</row>
26004+
26005+
<row>
26006+
<entry role="func_table_entry"><para role="func_signature">
26007+
<indexterm>
26008+
<primary>pg_get_wal_resource_managers</primary>
26009+
</indexterm>
26010+
<function>pg_get_wal_resource_managers</function> ()
26011+
<returnvalue>setof record</returnvalue>
26012+
( <parameter>rm_id</parameter> <type>integer</type>,
26013+
<parameter>rm_name</parameter> <type>text</type>,
26014+
<parameter>rm_builtin</parameter> <type>boolean</type> )
26015+
</para>
26016+
<para>
26017+
Returns the currently-loaded WAL resource managers in the system. The
26018+
column <parameter>rm_builtin</parameter> indicates whether it's a
26019+
built-in resource manager, or a custom resource manager loaded by an
26020+
extension.
26021+
</para></entry>
26022+
</row>
2600426023
</tbody>
2600526024
</tgroup>
2600626025
</table>

‎doc/src/sgml/generic-wal.sgml

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,25 @@
66
<para>
77
Although all built-in WAL-logged modules have their own types of WAL
88
records, there is also a generic WAL record type, which describes changes
9-
to pages in a generic way. This is useful for extensions that provide
10-
custom access methods, because they cannot register their own WAL redo
11-
routines.
9+
to pages in a generic way. This is useful for extensions that provide
10+
custom access methods.
1211
</para>
1312

13+
<para>
14+
In comparison with <link linkend="custom-rmgr">Custom WAL Resource
15+
Managers</link>, Generic WAL is simpler for an extension to implement and
16+
does not require the extension library to be loaded in order to apply the
17+
records.
18+
</para>
19+
20+
<note>
21+
<para>
22+
Generic WAL records are ignored during <link
23+
linkend="logicaldecoding">Logical Decoding</link>. If logical decoding is
24+
required for your extension, consider a Custom WAL Resource Manager.
25+
</para>
26+
</note>
27+
1428
<para>
1529
The API for constructing generic WAL records is defined in
1630
<filename>access/generic_xlog.h</filename> and implemented

‎doc/src/sgml/postgres.sgml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ break is not needed in a wider output rendering.
262262
&tableam;
263263
&indexam;
264264
&generic-wal;
265+
&custom-rmgr;
265266
&btree;
266267
&gist;
267268
&spgist;

‎doc/src/sgml/ref/pg_waldump.sgml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,14 @@ PostgreSQL documentation
173173
If <literal>list</literal> is passed as name, print a list of valid resource manager
174174
names, and exit.
175175
</para>
176+
<para>
177+
Extensions may define custom resource managers, but pg_waldump does
178+
not load the extension module and therefore does not recognize custom
179+
resource managers by name. Instead, you can specify the custom
180+
resource managers as <literal>custom###</literal> where
181+
"<literal>###</literal>" is the three-digit resource manager ID. Names
182+
of this form will always be considered valid.
183+
</para>
176184
</listitem>
177185
</varlistentry>
178186

‎src/backend/access/transam/rmgr.c

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,138 @@
2424
#include"commands/dbcommands_xlog.h"
2525
#include"commands/sequence.h"
2626
#include"commands/tablespace.h"
27+
#include"fmgr.h"
28+
#include"funcapi.h"
29+
#include"miscadmin.h"
2730
#include"replication/decode.h"
2831
#include"replication/message.h"
2932
#include"replication/origin.h"
3033
#include"storage/standby.h"
34+
#include"utils/builtins.h"
3135
#include"utils/relmapper.h"
3236

3337
/* must be kept in sync with RmgrData definition in xlog_internal.h */
3438
#definePG_RMGR(symname,name,redo,desc,identify,startup,cleanup,mask,decode) \
3539
{ name, redo, desc, identify, startup, cleanup, mask, decode },
3640

37-
constRmgrDataRmgrTable[RM_MAX_ID+1]= {
41+
RmgrDataRmgrTable[RM_MAX_ID+1]= {
3842
#include"access/rmgrlist.h"
3943
};
44+
45+
/*
46+
* Start up all resource managers.
47+
*/
48+
void
49+
RmgrStartup(void)
50+
{
51+
for (intrmid=0;rmid <=RM_MAX_ID;rmid++)
52+
{
53+
if (!RmgrIdExists(rmid))
54+
continue;
55+
56+
if (RmgrTable[rmid].rm_startup!=NULL)
57+
RmgrTable[rmid].rm_startup();
58+
}
59+
}
60+
61+
/*
62+
* Clean up all resource managers.
63+
*/
64+
void
65+
RmgrCleanup(void)
66+
{
67+
for (intrmid=0;rmid <=RM_MAX_ID;rmid++)
68+
{
69+
if (!RmgrIdExists(rmid))
70+
continue;
71+
72+
if (RmgrTable[rmid].rm_cleanup!=NULL)
73+
RmgrTable[rmid].rm_cleanup();
74+
}
75+
}
76+
77+
/*
78+
* Emit ERROR when we encounter a record with an RmgrId we don't
79+
* recognize.
80+
*/
81+
void
82+
RmgrNotFound(RmgrIdrmid)
83+
{
84+
ereport(ERROR, (errmsg("resource manager with ID %d not registered",rmid),
85+
errhint("Include the extension module that implements this resource manager in shared_preload_libraries.")));
86+
}
87+
88+
/*
89+
* Register a new custom WAL resource manager.
90+
*
91+
* Resource manager IDs must be globally unique across all extensions. Refer
92+
* to https://wiki.postgresql.org/wiki/CustomWALResourceManager to reserve a
93+
* unique RmgrId for your extension, to avoid conflicts with other extension
94+
* developers. During development, use RM_EXPERIMENTAL_ID to avoid needlessly
95+
* reserving a new ID.
96+
*/
97+
void
98+
RegisterCustomRmgr(RmgrIdrmid,RmgrData*rmgr)
99+
{
100+
if (rmgr->rm_name==NULL||strlen(rmgr->rm_name)==0)
101+
ereport(ERROR, (errmsg("custom resource manager name is invalid"),
102+
errhint("Provide a non-empty name for the custom resource manager.")));
103+
104+
if (!RMID_IS_CUSTOM(rmid))
105+
ereport(ERROR, (errmsg("custom resource manager ID %d is out of range",rmid),
106+
errhint("Provide a custom resource manager ID between %d and %d.",
107+
RM_MIN_CUSTOM_ID,RM_MAX_CUSTOM_ID)));
108+
109+
if (!process_shared_preload_libraries_in_progress)
110+
ereport(ERROR,
111+
(errmsg("failed to register custom resource manager \"%s\" with ID %d",rmgr->rm_name,rmid),
112+
errdetail("Custom resource manager must be registered while initializing modules in shared_preload_libraries.")));
113+
114+
if (RmgrTable[rmid].rm_name!=NULL)
115+
ereport(ERROR,
116+
(errmsg("failed to register custom resource manager \"%s\" with ID %d",rmgr->rm_name,rmid),
117+
errdetail("Custom resource manager \"%s\" already registered with the same ID.",
118+
RmgrTable[rmid].rm_name)));
119+
120+
/* check for existing rmgr with the same name */
121+
for (intexisting_rmid=0;existing_rmid <=RM_MAX_ID;existing_rmid++)
122+
{
123+
if (!RmgrIdExists(existing_rmid))
124+
continue;
125+
126+
if (!pg_strcasecmp(RmgrTable[existing_rmid].rm_name,rmgr->rm_name))
127+
ereport(ERROR,
128+
(errmsg("failed to register custom resource manager \"%s\" with ID %d",rmgr->rm_name,rmid),
129+
errdetail("Existing resource manager with ID %d has the same name.",existing_rmid)));
130+
}
131+
132+
/* register it */
133+
RmgrTable[rmid]=*rmgr;
134+
ereport(LOG,
135+
(errmsg("registered custom resource manager \"%s\" with ID %d",
136+
rmgr->rm_name,rmid)));
137+
}
138+
139+
/* SQL SRF showing loaded resource managers */
140+
Datum
141+
pg_get_wal_resource_managers(PG_FUNCTION_ARGS)
142+
{
143+
#definePG_GET_RESOURCE_MANAGERS_COLS 3
144+
ReturnSetInfo*rsinfo= (ReturnSetInfo*)fcinfo->resultinfo;
145+
Datumvalues[PG_GET_RESOURCE_MANAGERS_COLS];
146+
boolnulls[PG_GET_RESOURCE_MANAGERS_COLS]= {0};
147+
148+
SetSingleFuncCall(fcinfo,0);
149+
150+
for (intrmid=0;rmid <=RM_MAX_ID;rmid++)
151+
{
152+
if (!RmgrIdExists(rmid))
153+
continue;
154+
values[0]=Int32GetDatum(rmid);
155+
values[1]=CStringGetTextDatum(GetRmgr(rmid).rm_name);
156+
values[2]=BoolGetDatum(RMID_IS_BUILTIN(rmid));
157+
tuplestore_putvalues(rsinfo->setResult,rsinfo->setDesc,values,nulls);
158+
}
159+
160+
return (Datum)0;
161+
}

‎src/backend/access/transam/xlogreader.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,7 @@ ValidXLogRecordHeader(XLogReaderState *state, XLogRecPtr RecPtr,
11021102
(uint32)SizeOfXLogRecord,record->xl_tot_len);
11031103
return false;
11041104
}
1105-
if (record->xl_rmid>RM_MAX_ID)
1105+
if (!RMID_IS_VALID(record->xl_rmid))
11061106
{
11071107
report_invalid_record(state,
11081108
"invalid resource manager ID %u at %X/%X",

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp