1 | /***************************************************************************** |
2 | |
3 | Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. |
4 | Copyright (c) 2017, 2018, MariaDB Corporation. |
5 | |
6 | This program is free software; you can redistribute it and/or modify it under |
7 | the terms of the GNU General Public License as published by the Free Software |
8 | Foundation; version 2 of the License. |
9 | |
10 | This program is distributed in the hope that it will be useful, but WITHOUT |
11 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
12 | FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU General Public License along with |
15 | this program; if not, write to the Free Software Foundation, Inc., |
16 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA |
17 | |
18 | *****************************************************************************/ |
19 | |
20 | /**************************************************//** |
21 | @file include/trx0rseg.h |
22 | Rollback segment |
23 | |
24 | Created 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 */ |
38 | UNIV_INLINE |
39 | trx_rsegf_t* |
40 | trx_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 */ |
47 | UNIV_INLINE |
48 | trx_rsegf_t* |
49 | trx_rsegf_get_new( |
50 | ulint space, |
51 | ulint page_no, |
52 | mtr_t* mtr); |
53 | |
54 | /***************************************************************//** |
55 | Sets the file page number of the nth undo log slot. */ |
56 | UNIV_INLINE |
57 | void |
58 | trx_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 | /****************************************************************//** |
65 | Looks for a free slot for an undo log segment. |
66 | @return slot index or ULINT_UNDEFINED if not found */ |
67 | UNIV_INLINE |
68 | ulint |
69 | trx_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 */ |
77 | ulint |
78 | ( |
79 | fil_space_t* space, |
80 | ulint rseg_id, |
81 | buf_block_t* , |
82 | mtr_t* mtr); |
83 | |
84 | /** Initialize the rollback segments in memory at database startup. */ |
85 | void |
86 | trx_rseg_array_init(); |
87 | |
88 | /** Free a rollback segment in memory. */ |
89 | void |
90 | trx_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 */ |
96 | trx_rseg_t* |
97 | trx_rseg_create(ulint space_id) |
98 | MY_ATTRIBUTE((warn_unused_result)); |
99 | |
100 | /** Create the temporary rollback segments. */ |
101 | void |
102 | trx_temp_rseg_create(); |
103 | |
104 | /******************************************************************** |
105 | Get the number of unique rollback tablespaces in use except space id 0. |
106 | The last space id will be the sentinel value ULINT_UNDEFINED. The array |
107 | will be sorted on space id. Note: space_ids should have have space for |
108 | TRX_SYS_N_RSEGS + 1 elements. |
109 | @return number of unique rollback tablespaces in use. */ |
110 | ulint |
111 | trx_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 */ |
122 | struct 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 (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). |
235 | If 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 */ |
259 | inline |
260 | uint32_t |
261 | trx_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 */ |
273 | void |
274 | trx_rseg_update_wsrep_checkpoint( |
275 | trx_rsegf_t* , |
276 | const XID* xid, |
277 | mtr_t* mtr); |
278 | |
279 | /** Update WSREP checkpoint XID in first rollback segment header |
280 | as part of wsrep_set_SE_checkpoint() when it is guaranteed that there |
281 | are no wsrep transactions committing. |
282 | If the UUID part of the WSREP XID does not match to the UUIDs of XIDs already |
283 | stored into rollback segments, the WSREP XID in all the remaining rollback |
284 | segments will be reset. |
285 | @param[in] xid WSREP XID */ |
286 | void 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 */ |
291 | bool 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 */ |
297 | void trx_rseg_format_upgrade(trx_rsegf_t* , mtr_t* mtr); |
298 | |
299 | /** Update the offset information about the end of the binlog entry |
300 | which corresponds to the transaction just being committed. |
301 | In a replication slave, this updates the master binlog position |
302 | up 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 */ |
306 | void |
307 | trx_rseg_update_binlog_offset(byte* , const trx_t* trx, mtr_t* mtr); |
308 | |
309 | #include "trx0rseg.ic" |
310 | |
311 | #endif |
312 | |