|
24 | 24 | * since it would get completely confused if someone inquired about a bogus
|
25 | 25 | * MultiXactId that pointed to an intermediate slot containing an XID.)
|
26 | 26 | *
|
27 |
| - * XLOG interactions: this module generates an XLOG record whenever a new |
28 |
| - * OFFSETs or MEMBERs page is initialized to zeroes, as well as an XLOG record |
29 |
| - * whenever a new MultiXactId is defined. This allows us to completely |
30 |
| - * rebuild the data entered since the last checkpoint during XLOG replay. |
31 |
| - * Because this is possible, we need not follow the normal rule of |
32 |
| - * "write WAL before data"; the only correctness guarantee needed is that |
33 |
| - * we flush and sync all dirty OFFSETs and MEMBERs pages to disk before a |
34 |
| - * checkpoint is considered complete. If a page does make it to disk ahead |
35 |
| - * of corresponding WAL records, it will be forcibly zeroed before use anyway. |
36 |
| - * Therefore, we don't need to mark our pages with LSN information; we have |
37 |
| - * enough synchronization already. |
| 27 | + * XLOG interactions: this module generates a record whenever a new OFFSETs or |
| 28 | + * MEMBERs page is initialized to zeroes, as well as an |
| 29 | + * XLOG_MULTIXACT_CREATE_ID record whenever a new MultiXactId is defined. |
| 30 | + * This module ignores the WAL rule "write xlog before data," because it |
| 31 | + * suffices that actions recording a MultiXactId in a heap xmax do follow that |
| 32 | + * rule. The only way for the MXID to be referenced from any data page is for |
| 33 | + * heap_lock_tuple() or heap_update() to have put it there, and each generates |
| 34 | + * an XLOG record that must follow ours. The normal LSN interlock between the |
| 35 | + * data page and that XLOG record will ensure that our XLOG record reaches |
| 36 | + * disk first. If the SLRU members/offsets data reaches disk sooner than the |
| 37 | + * XLOG records, we do not care; after recovery, no xmax will refer to it. On |
| 38 | + * the flip side, to ensure that all referenced entries _do_ reach disk, this |
| 39 | + * module's XLOG records completely rebuild the data entered since the last |
| 40 | + * checkpoint. We flush and sync all dirty OFFSETs and MEMBERs pages to disk |
| 41 | + * before each checkpoint is considered complete. |
38 | 42 | *
|
39 | 43 | * Like clog.c, and unlike subtrans.c, we have to preserve state across
|
40 | 44 | * crashes and ensure that MXID and offset numbering increases monotonically
|
@@ -795,19 +799,7 @@ MultiXactIdCreateFromMembers(int nmembers, MultiXactMember *members)
|
795 | 799 | */
|
796 | 800 | multi = GetNewMultiXactId(nmembers, &offset);
|
797 | 801 |
|
798 |
| - /* |
799 |
| - * Make an XLOG entry describing the new MXID. |
800 |
| - * |
801 |
| - * Note: we need not flush this XLOG entry to disk before proceeding. The |
802 |
| - * only way for the MXID to be referenced from any data page is for |
803 |
| - * heap_lock_tuple() to have put it there, and heap_lock_tuple() generates |
804 |
| - * an XLOG record that must follow ours. The normal LSN interlock between |
805 |
| - * the data page and that XLOG record will ensure that our XLOG record |
806 |
| - * reaches disk first. If the SLRU members/offsets data reaches disk |
807 |
| - * sooner than the XLOG record, we do not care because we'll overwrite it |
808 |
| - * with zeroes unless the XLOG record is there too; see notes at top of |
809 |
| - * this file. |
810 |
| - */ |
| 802 | + /* Make an XLOG entry describing the new MXID. */ |
811 | 803 | xlrec.mid = multi;
|
812 | 804 | xlrec.moff = offset;
|
813 | 805 | xlrec.nmembers = nmembers;
|
@@ -2037,7 +2029,11 @@ TrimMultiXact(void)
|
2037 | 2029 |
|
2038 | 2030 | /*
|
2039 | 2031 | * Zero out the remainder of the current offsets page. See notes in
|
2040 |
| - * TrimCLOG() for motivation. |
| 2032 | + * TrimCLOG() for background. Unlike CLOG, some WAL record covers every |
| 2033 | + * pg_multixact SLRU mutation. Since, also unlike CLOG, we ignore the WAL |
| 2034 | + * rule "write xlog before data," nextMXact successors may carry obsolete, |
| 2035 | + * nonzero offset values. Zero those so case 2 of GetMultiXactIdMembers() |
| 2036 | + * operates normally. |
2041 | 2037 | */
|
2042 | 2038 | entryno = MultiXactIdToOffsetEntry(nextMXact);
|
2043 | 2039 | if (entryno != 0)
|
|
0 commit comments