|
1 | 1 | <!-- doc/src/sgml/generic-wal.sgml -->
|
2 | 2 |
|
3 | 3 | <chapter id="generic-wal">
|
4 |
| - <title>Generic WAL records</title> |
| 4 | + <title>Generic WAL Records</title> |
5 | 5 |
|
6 | 6 | <para>
|
7 |
| - Despite all built-in access methods and WAL-logged modules having their own |
8 |
| - types of WAL records, there is also a generic WAL record type, which describes |
9 |
| - changes to pages in a generic way. This is useful for extensions that |
10 |
| - provide custom access methods, because they cannot register their own |
11 |
| - WAL redo routines. |
| 7 | + Although all built-in WAL-logged modules have their own types of WAL |
| 8 | + 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. |
12 | 12 | </para>
|
13 | 13 |
|
14 | 14 | <para>
|
15 | 15 | The API for constructing generic WAL records is defined in
|
16 |
| - <filename>generic_xlog.h</> and implemented in <filename>generic_xlog.c</>. |
17 |
| - Each generic WAL record must be constructed by following these steps: |
| 16 | + <filename>access/generic_xlog.h</> and implemented |
| 17 | + in <filename>access/transam/generic_xlog.c</>. |
| 18 | + </para> |
| 19 | + |
| 20 | + <para> |
| 21 | + To perform a WAL-logged data update using the generic WAL record |
| 22 | + facility, follow these steps: |
18 | 23 |
|
19 | 24 | <orderedlist>
|
20 | 25 | <listitem>
|
21 | 26 | <para>
|
22 | 27 | <function>state = GenericXLogStart(relation)</> — start
|
23 |
| - construction of a generic xlog record for the given relation. |
| 28 | + construction of a generic WAL record for the given relation. |
24 | 29 | </para>
|
25 | 30 | </listitem>
|
26 | 31 |
|
27 | 32 | <listitem>
|
28 | 33 | <para>
|
29 | 34 | <function>page = GenericXLogRegister(state, buffer, isNew)</> —
|
30 |
| - register one or more buffers (one at a time) for the current generic |
31 |
| - xlog record. This function returns a copy of the page image, where |
32 |
| - modifications can be made. The second argument indicates if the page |
33 |
| - is new (eventually, this will result in a full page image being put into |
34 |
| - the xlog record). |
| 35 | + register a buffer to be modified within the current generic WAL |
| 36 | + record. This function returns a pointer to a temporary copy of the |
| 37 | + buffer's page, where modifications should be made. (Do not modify the |
| 38 | + buffer's contents directly.) The third argument indicates if the page |
| 39 | + is new; if true, this will result in a full-page image rather than a |
| 40 | + delta update being included in the WAL record. |
| 41 | + <function>GenericXLogRegister</> can be repeated if the WAL-logged |
| 42 | + action needs to modify multiple pages. |
35 | 43 | </para>
|
36 | 44 | </listitem>
|
37 | 45 |
|
38 | 46 | <listitem>
|
39 | 47 | <para>
|
40 |
| - Apply modifications to page images obtained in the previous step. |
| 48 | + Apply modifications to the page images obtained in the previous step. |
41 | 49 | </para>
|
42 | 50 | </listitem>
|
43 | 51 |
|
44 | 52 | <listitem>
|
45 | 53 | <para>
|
46 |
| - <function>GenericXLogFinish(state)</> — finish construction of |
47 |
| - a generic xlog record. |
| 54 | + <function>GenericXLogFinish(state)</> — apply the changes to |
| 55 | + the buffers and emit the generic WAL record. |
48 | 56 | </para>
|
49 | 57 | </listitem>
|
50 | 58 | </orderedlist>
|
51 | 59 | </para>
|
52 | 60 |
|
53 | 61 | <para>
|
54 |
| - The xlog record construction can be canceled between any of the above |
55 |
| - steps by calling <function>GenericXLogAbort(state)</>. This will discard all |
| 62 | + WAL record construction can be canceled between any of the above steps by |
| 63 | + calling <function>GenericXLogAbort(state)</>. This will discard all |
56 | 64 | changes to the page image copies.
|
57 | 65 | </para>
|
58 | 66 |
|
59 | 67 | <para>
|
60 |
| - Please note the following points when constructing generic xlog records: |
| 68 | + Please note the following points when using the generic WAL record |
| 69 | + facility: |
| 70 | + |
61 | 71 | <itemizedlist>
|
62 | 72 | <listitem>
|
63 | 73 | <para>
|
64 |
| - No direct modifications of page images are allowed! All modifications |
| 74 | + No direct modifications of buffers are allowed! All modifications |
65 | 75 | must be done in copies acquired from <function>GenericXLogRegister()</>.
|
66 |
| - In other words, code which makes generic xlog records must never call |
67 |
| - <function>BufferGetPage()</>. |
| 76 | + In other words, code that makes generic WAL records should never call |
| 77 | + <function>BufferGetPage()</> for itself. However, it remains the |
| 78 | + caller's responsibility to pin/unpin and lock/unlock the buffers at |
| 79 | + appropriate times. Exclusive lock must be held on each target buffer |
| 80 | + from before <function>GenericXLogRegister()</> until after |
| 81 | + <function>GenericXLogFinish()</>. |
68 | 82 | </para>
|
69 | 83 | </listitem>
|
70 | 84 |
|
71 | 85 | <listitem>
|
72 | 86 | <para>
|
73 | 87 | Registrations of buffers (step 2) and modifications of page images
|
74 | 88 | (step 3) can be mixed freely, i.e., both steps may be repeated in any
|
75 |
| - sequence. The only restriction is that you can modify a page image |
76 |
| - only after the registration of the corresponding buffer. |
| 89 | + sequence. Keep in mind that buffers should be registered in the same |
| 90 | + order in which locks are to be obtained on them during replay. |
77 | 91 | </para>
|
78 | 92 | </listitem>
|
79 | 93 |
|
80 | 94 | <listitem>
|
81 | 95 | <para>
|
82 |
| - After registration, the buffer can also be unregistered by calling |
83 |
| - <function>GenericXLogUnregister(buffer)</>. In this case, the changes |
84 |
| - made to that particular page image copy will be discarded. |
| 96 | + The maximum number of buffers that can be registered for a generic WAL |
| 97 | + record is <literal>MAX_GENERIC_XLOG_PAGES</>. An error will be thrown |
| 98 | + if this limit is exceeded. |
85 | 99 | </para>
|
86 | 100 | </listitem>
|
87 | 101 |
|
88 | 102 | <listitem>
|
89 | 103 | <para>
|
90 |
| - Generic xlog assumes that pages are using standard layout. I.e., all |
91 |
| - information between pd_lower and pd_upper will be discarded. |
| 104 | + Generic WAL assumes that the pages to be modified have standard |
| 105 | + layout, and in particular that there is no useful data between |
| 106 | + <structfield>pd_lower</> and <structfield>pd_upper</>. |
92 | 107 | </para>
|
93 | 108 | </listitem>
|
94 | 109 |
|
95 | 110 | <listitem>
|
96 | 111 | <para>
|
97 |
| - The maximum number of buffers that can be simultaneously registered |
98 |
| - for a generic xlog is <literal>MAX_GENERIC_XLOG_PAGES</>. An error will |
99 |
| - be thrown if this limit is exceeded. |
100 |
| - </para> |
101 |
| - </listitem> |
102 |
| - <listitem> |
103 |
| - <para> |
104 |
| - Since you modify copies of page images, <function>GenericXLogStart()</> |
105 |
| - does not start a critical section. Thus, you can do memory allocation, |
106 |
| - error throwing, etc. between <function>GenericXLogStart()</> and |
107 |
| - <function>GenericXLogFinish()</>. The actual critical section is present |
108 |
| - inside <function>GenericXLogFinish()</>. |
| 112 | + Since you are modifying copies of buffer |
| 113 | + pages, <function>GenericXLogStart()</> does not start a critical |
| 114 | + section. Thus, you can safely do memory allocation, error throwing, |
| 115 | + etc. between <function>GenericXLogStart()</> and |
| 116 | + <function>GenericXLogFinish()</>. The only actual critical section is |
| 117 | + present inside <function>GenericXLogFinish()</>. There is no need to |
| 118 | + worry about calling <function>GenericXLogAbort()</> during an error |
| 119 | + exit, either. |
109 | 120 | </para>
|
110 | 121 | </listitem>
|
| 122 | + |
111 | 123 | <listitem>
|
112 | 124 | <para>
|
113 |
| - <function>GenericXLogFinish()</> takes care of marking buffers as dirty |
| 125 | + <function>GenericXLogFinish()</> takes care of marking buffers dirty |
114 | 126 | and setting their LSNs. You do not need to do this explicitly.
|
115 | 127 | </para>
|
116 | 128 | </listitem>
|
| 129 | + |
117 | 130 | <listitem>
|
118 | 131 | <para>
|
119 |
| - For unlogged relations, everything works the same except there is no |
120 |
| - WAL record produced. Thus, you typically do not need to do any explicit |
121 |
| - checks for unlogged relations. |
| 132 | + For unlogged relations, everything works the same except that no |
| 133 | + actual WAL record is emitted. Thus, you typically do not need to do |
| 134 | + any explicit checks for unlogged relations. |
122 | 135 | </para>
|
123 | 136 | </listitem>
|
| 137 | + |
124 | 138 | <listitem>
|
125 | 139 | <para>
|
126 |
| - If a registered buffer is not new, the generic xlog record contains |
127 |
| - a delta between the old and the new page images. This delta is produced |
128 |
| - using per byte comparison. The current delta mechanism is not effective |
129 |
| - for moving data within a page and may be improved in the future. |
| 140 | + The generic WAL redo function will acquire exclusive locks to buffers |
| 141 | + in the same order as they were registered. After redoing all changes, |
| 142 | + the locks will be released in the same order. |
130 | 143 | </para>
|
131 | 144 | </listitem>
|
| 145 | + |
132 | 146 | <listitem>
|
133 | 147 | <para>
|
134 |
| - The generic xlog redo function will acquire exclusive locks to buffers |
135 |
| - in the same order as they were registered. After redoing all changes, |
136 |
| - the locks will be released in the same order. |
| 148 | + If a registered buffer is not new, the generic WAL record contains |
| 149 | + a delta between the old and the new page images. This delta is based |
| 150 | + on byte-by-byte comparison. This is not very compact for the case of |
| 151 | + moving data within a page, and might be improved in the future. |
137 | 152 | </para>
|
138 | 153 | </listitem>
|
139 | 154 | </itemizedlist>
|
|
0 commit comments