1/*****************************************************************************
2
3Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4Copyright (c) 2017, 2018, MariaDB Corporation.
5
6This program is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free Software
8Foundation; version 2 of the License.
9
10This program is distributed in the hope that it will be useful, but WITHOUT
11ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License along with
15this program; if not, write to the Free Software Foundation, Inc.,
1651 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
17
18*****************************************************************************/
19
20/**************************************************//**
21@file include/trx0rseg.h
22Rollback segment
23
24Created 3/26/1996 Heikki Tuuri
25*******************************************************/
26
27#ifndef trx0rseg_h
28#define trx0rseg_h
29
30#include "trx0sys.h"
31#include "fut0lst.h"
32
33/** Gets a rollback segment header.
34@param[in] space space where placed
35@param[in] page_no page number of the header
36@param[in,out] mtr mini-transaction
37@return rollback segment header, page x-latched */
38UNIV_INLINE
39trx_rsegf_t*
40trx_rsegf_get(fil_space_t* space, ulint page_no, mtr_t* mtr);
41
42/** Gets a newly created rollback segment header.
43@param[in] space space where placed
44@param[in] page_no page number of the header
45@param[in,out] mtr mini-transaction
46@return rollback segment header, page x-latched */
47UNIV_INLINE
48trx_rsegf_t*
49trx_rsegf_get_new(
50 ulint space,
51 ulint page_no,
52 mtr_t* mtr);
53
54/***************************************************************//**
55Sets the file page number of the nth undo log slot. */
56UNIV_INLINE
57void
58trx_rsegf_set_nth_undo(
59/*===================*/
60 trx_rsegf_t* rsegf, /*!< in: rollback segment header */
61 ulint n, /*!< in: index of slot */
62 ulint page_no,/*!< in: page number of the undo log segment */
63 mtr_t* mtr); /*!< in: mtr */
64/****************************************************************//**
65Looks for a free slot for an undo log segment.
66@return slot index or ULINT_UNDEFINED if not found */
67UNIV_INLINE
68ulint
69trx_rsegf_undo_find_free(const trx_rsegf_t* rsegf);
70
71/** Create a rollback segment header.
72@param[in,out] space system, undo, or temporary tablespace
73@param[in] rseg_id rollback segment identifier
74@param[in,out] sys_header the TRX_SYS page (NULL for temporary rseg)
75@param[in,out] mtr mini-transaction
76@return page number of the created segment, FIL_NULL if fail */
77ulint
78trx_rseg_header_create(
79 fil_space_t* space,
80 ulint rseg_id,
81 buf_block_t* sys_header,
82 mtr_t* mtr);
83
84/** Initialize the rollback segments in memory at database startup. */
85void
86trx_rseg_array_init();
87
88/** Free a rollback segment in memory. */
89void
90trx_rseg_mem_free(trx_rseg_t* rseg);
91
92/** Create a persistent rollback segment.
93@param[in] space_id system or undo tablespace id
94@return pointer to new rollback segment
95@retval NULL on failure */
96trx_rseg_t*
97trx_rseg_create(ulint space_id)
98 MY_ATTRIBUTE((warn_unused_result));
99
100/** Create the temporary rollback segments. */
101void
102trx_temp_rseg_create();
103
104/********************************************************************
105Get the number of unique rollback tablespaces in use except space id 0.
106The last space id will be the sentinel value ULINT_UNDEFINED. The array
107will be sorted on space id. Note: space_ids should have have space for
108TRX_SYS_N_RSEGS + 1 elements.
109@return number of unique rollback tablespaces in use. */
110ulint
111trx_rseg_get_n_undo_tablespaces(
112/*============================*/
113 ulint* space_ids); /*!< out: array of space ids of
114 UNDO tablespaces */
115/* Number of undo log slots in a rollback segment file copy */
116#define TRX_RSEG_N_SLOTS (srv_page_size / 16)
117
118/* Maximum number of transactions supported by a single rollback segment */
119#define TRX_RSEG_MAX_N_TRXS (TRX_RSEG_N_SLOTS / 2)
120
121/** The rollback segment memory object */
122struct trx_rseg_t {
123 /*--------------------------------------------------------*/
124 /** rollback segment id == the index of its slot in the trx
125 system file copy */
126 ulint id;
127
128 /** mutex protecting the fields in this struct except id,space,page_no
129 which are constant */
130 RsegMutex mutex;
131
132 /** space where the rollback segment header is placed */
133 fil_space_t* space;
134
135 /** page number of the rollback segment header */
136 ulint page_no;
137
138 /** current size in pages */
139 ulint curr_size;
140
141 /*--------------------------------------------------------*/
142 /* Fields for undo logs */
143 /** List of undo logs */
144 UT_LIST_BASE_NODE_T(trx_undo_t) undo_list;
145
146 /** List of undo log segments cached for fast reuse */
147 UT_LIST_BASE_NODE_T(trx_undo_t) undo_cached;
148
149 /** List of recovered old insert_undo logs of incomplete
150 transactions (to roll back or XA COMMIT & purge) */
151 UT_LIST_BASE_NODE_T(trx_undo_t) old_insert_list;
152
153 /*--------------------------------------------------------*/
154
155 /** Page number of the last not yet purged log header in the history
156 list; FIL_NULL if all list purged */
157 ulint last_page_no;
158
159 /** Byte offset of the last not yet purged log header */
160 ulint last_offset;
161
162 /** trx_t::no * 2 + old_insert of the last not yet purged log */
163 trx_id_t last_commit;
164
165 /** Whether the log segment needs purge */
166 bool needs_purge;
167
168 /** Reference counter to track rseg allocated transactions. */
169 ulint trx_ref_count;
170
171 /** If true, then skip allocating this rseg as it reside in
172 UNDO-tablespace marked for truncate. */
173 bool skip_allocation;
174
175 /** @return the commit ID of the last committed transaction */
176 trx_id_t last_trx_no() const { return last_commit >> 1; }
177
178 void set_last_trx_no(trx_id_t trx_no, bool is_update)
179 {
180 last_commit = trx_no << 1 | trx_id_t(is_update);
181 }
182
183 /** @return whether the rollback segment is persistent */
184 bool is_persistent() const
185 {
186 ut_ad(space == fil_system.temp_space
187 || space == fil_system.sys_space
188 || (srv_undo_space_id_start > 0
189 && space->id >= srv_undo_space_id_start
190 && space->id <= srv_undo_space_id_start
191 + TRX_SYS_MAX_UNDO_SPACES));
192 ut_ad(space == fil_system.temp_space
193 || space == fil_system.sys_space
194 || (srv_undo_space_id_start > 0
195 && space->id >= srv_undo_space_id_start
196 && space->id <= srv_undo_space_id_start
197 + srv_undo_tablespaces_active)
198 || !srv_was_started);
199 return(space->id != SRV_TMP_SPACE_ID);
200 }
201};
202
203/* Undo log segment slot in a rollback segment header */
204/*-------------------------------------------------------------*/
205#define TRX_RSEG_SLOT_PAGE_NO 0 /* Page number of the header page of
206 an undo log segment */
207/*-------------------------------------------------------------*/
208/* Slot size */
209#define TRX_RSEG_SLOT_SIZE 4
210
211/* The offset of the rollback segment header on its page */
212#define TRX_RSEG FSEG_PAGE_DATA
213
214/* Transaction rollback segment header */
215/*-------------------------------------------------------------*/
216/** 0xfffffffe = pre-MariaDB 10.3.5 format; 0=MariaDB 10.3.5 or later */
217#define TRX_RSEG_FORMAT 0
218/** Number of pages in the TRX_RSEG_HISTORY list */
219#define TRX_RSEG_HISTORY_SIZE 4
220/** Committed transaction logs that have not been purged yet */
221#define TRX_RSEG_HISTORY 8
222#define TRX_RSEG_FSEG_HEADER (8 + FLST_BASE_NODE_SIZE)
223 /* Header for the file segment where
224 this page is placed */
225#define TRX_RSEG_UNDO_SLOTS (8 + FLST_BASE_NODE_SIZE + FSEG_HEADER_SIZE)
226 /* Undo log segment slots */
227/** Maximum transaction ID (valid only if TRX_RSEG_FORMAT is 0) */
228#define TRX_RSEG_MAX_TRX_ID (TRX_RSEG_UNDO_SLOTS + TRX_RSEG_N_SLOTS \
229 * TRX_RSEG_SLOT_SIZE)
230
231/** 8 bytes offset within the binlog file */
232#define TRX_RSEG_BINLOG_OFFSET TRX_RSEG_MAX_TRX_ID + 8
233/** MySQL log file name, 512 bytes, including terminating NUL
234(valid only if TRX_RSEG_FORMAT is 0).
235If no binlog information is present, the first byte is NUL. */
236#define TRX_RSEG_BINLOG_NAME TRX_RSEG_MAX_TRX_ID + 16
237/** Maximum length of binlog file name, including terminating NUL, in bytes */
238#define TRX_RSEG_BINLOG_NAME_LEN 512
239
240#ifdef WITH_WSREP
241/** The offset to WSREP XID headers */
242#define TRX_RSEG_WSREP_XID_INFO TRX_RSEG_MAX_TRX_ID + 16 + 512
243
244/** WSREP XID format (1 if present and valid, 0 if not present) */
245#define TRX_RSEG_WSREP_XID_FORMAT TRX_RSEG_WSREP_XID_INFO
246/** WSREP XID GTRID length */
247#define TRX_RSEG_WSREP_XID_GTRID_LEN TRX_RSEG_WSREP_XID_INFO + 4
248/** WSREP XID bqual length */
249#define TRX_RSEG_WSREP_XID_BQUAL_LEN TRX_RSEG_WSREP_XID_INFO + 8
250/** WSREP XID data (XIDDATASIZE bytes) */
251#define TRX_RSEG_WSREP_XID_DATA TRX_RSEG_WSREP_XID_INFO + 12
252#endif /* WITH_WSREP*/
253
254/*-------------------------------------------------------------*/
255
256/** Read the page number of an undo log slot.
257@param[in] rsegf rollback segment header
258@param[in] n slot number */
259inline
260uint32_t
261trx_rsegf_get_nth_undo(const trx_rsegf_t* rsegf, ulint n)
262{
263 ut_ad(n < TRX_RSEG_N_SLOTS);
264 return mach_read_from_4(rsegf + TRX_RSEG_UNDO_SLOTS
265 + n * TRX_RSEG_SLOT_SIZE);
266}
267
268#ifdef WITH_WSREP
269/** Update the WSREP XID information in rollback segment header.
270@param[in,out] rseg_header rollback segment header
271@param[in] xid WSREP XID
272@param[in,out] mtr mini-transaction */
273void
274trx_rseg_update_wsrep_checkpoint(
275 trx_rsegf_t* rseg_header,
276 const XID* xid,
277 mtr_t* mtr);
278
279/** Update WSREP checkpoint XID in first rollback segment header
280as part of wsrep_set_SE_checkpoint() when it is guaranteed that there
281are no wsrep transactions committing.
282If the UUID part of the WSREP XID does not match to the UUIDs of XIDs already
283stored into rollback segments, the WSREP XID in all the remaining rollback
284segments will be reset.
285@param[in] xid WSREP XID */
286void trx_rseg_update_wsrep_checkpoint(const XID* xid);
287
288/** Recover the latest WSREP checkpoint XID.
289@param[out] xid WSREP XID
290@return whether the WSREP XID was found */
291bool trx_rseg_read_wsrep_checkpoint(XID& xid);
292#endif /* WITH_WSREP */
293
294/** Upgrade a rollback segment header page to MariaDB 10.3 format.
295@param[in,out] rseg_header rollback segment header page
296@param[in,out] mtr mini-transaction */
297void trx_rseg_format_upgrade(trx_rsegf_t* rseg_header, mtr_t* mtr);
298
299/** Update the offset information about the end of the binlog entry
300which corresponds to the transaction just being committed.
301In a replication slave, this updates the master binlog position
302up to which replication has proceeded.
303@param[in,out] rseg_header rollback segment header
304@param[in] trx committing transaction
305@param[in,out] mtr mini-transaction */
306void
307trx_rseg_update_binlog_offset(byte* rseg_header, const trx_t* trx, mtr_t* mtr);
308
309#include "trx0rseg.ic"
310
311#endif
312