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/trx0undo.h
22Transaction undo log
23
24Created 3/26/1996 Heikki Tuuri
25*******************************************************/
26
27#ifndef trx0undo_h
28#define trx0undo_h
29
30#ifndef UNIV_INNOCHECKSUM
31#include "trx0sys.h"
32
33/** The LSB of the "is insert" flag in DB_ROLL_PTR */
34#define ROLL_PTR_INSERT_FLAG_POS 55
35/** The LSB of the 7-bit trx_rseg_t::id in DB_ROLL_PTR */
36#define ROLL_PTR_RSEG_ID_POS 48
37/** The LSB of the 32-bit undo log page number in DB_ROLL_PTR */
38#define ROLL_PTR_PAGE_POS 16
39/** The LSB of the 16-bit byte offset within an undo log page in DB_ROLL_PTR */
40#define ROLL_PTR_BYTE_POS 0
41
42/***********************************************************************//**
43Builds a roll pointer.
44@return roll pointer */
45UNIV_INLINE
46roll_ptr_t
47trx_undo_build_roll_ptr(
48/*====================*/
49 ibool is_insert, /*!< in: TRUE if insert undo log */
50 ulint rseg_id, /*!< in: rollback segment id */
51 ulint page_no, /*!< in: page number */
52 ulint offset); /*!< in: offset of the undo entry within page */
53/***********************************************************************//**
54Decodes a roll pointer. */
55UNIV_INLINE
56void
57trx_undo_decode_roll_ptr(
58/*=====================*/
59 roll_ptr_t roll_ptr, /*!< in: roll pointer */
60 ibool* is_insert, /*!< out: TRUE if insert undo log */
61 ulint* rseg_id, /*!< out: rollback segment id */
62 ulint* page_no, /*!< out: page number */
63 ulint* offset); /*!< out: offset of the undo
64 entry within page */
65/***********************************************************************//**
66Returns TRUE if the roll pointer is of the insert type.
67@return TRUE if insert undo log */
68UNIV_INLINE
69ibool
70trx_undo_roll_ptr_is_insert(
71/*========================*/
72 roll_ptr_t roll_ptr); /*!< in: roll pointer */
73/***********************************************************************//**
74Returns true if the record is of the insert type.
75@return true if the record was freshly inserted (not updated). */
76UNIV_INLINE
77bool
78trx_undo_trx_id_is_insert(
79/*======================*/
80 const byte* trx_id) /*!< in: DB_TRX_ID, followed by DB_ROLL_PTR */
81 MY_ATTRIBUTE((warn_unused_result));
82/*****************************************************************//**
83Writes a roll ptr to an index page. In case that the size changes in
84some future version, this function should be used instead of
85mach_write_... */
86UNIV_INLINE
87void
88trx_write_roll_ptr(
89/*===============*/
90 byte* ptr, /*!< in: pointer to memory where
91 written */
92 roll_ptr_t roll_ptr); /*!< in: roll ptr */
93/*****************************************************************//**
94Reads a roll ptr from an index page. In case that the roll ptr size
95changes in some future version, this function should be used instead of
96mach_read_...
97@return roll ptr */
98UNIV_INLINE
99roll_ptr_t
100trx_read_roll_ptr(
101/*==============*/
102 const byte* ptr); /*!< in: pointer to memory from where to read */
103
104/** Gets an undo log page and x-latches it.
105@param[in] page_id page id
106@param[in,out] mtr mini-transaction
107@return pointer to page x-latched */
108UNIV_INLINE
109page_t*
110trx_undo_page_get(const page_id_t& page_id, mtr_t* mtr);
111
112/** Gets an undo log page and s-latches it.
113@param[in] page_id page id
114@param[in,out] mtr mini-transaction
115@return pointer to page s-latched */
116UNIV_INLINE
117page_t*
118trx_undo_page_get_s_latched(const page_id_t& page_id, mtr_t* mtr);
119
120/******************************************************************//**
121Returns the next undo log record on the page in the specified log, or
122NULL if none exists.
123@return pointer to record, NULL if none */
124UNIV_INLINE
125trx_undo_rec_t*
126trx_undo_page_get_next_rec(
127/*=======================*/
128 trx_undo_rec_t* rec, /*!< in: undo log record */
129 ulint page_no,/*!< in: undo log header page number */
130 ulint offset);/*!< in: undo log header offset on page */
131/***********************************************************************//**
132Gets the previous record in an undo log.
133@return undo log record, the page s-latched, NULL if none */
134trx_undo_rec_t*
135trx_undo_get_prev_rec(
136/*==================*/
137 trx_undo_rec_t* rec, /*!< in: undo record */
138 ulint page_no,/*!< in: undo log header page number */
139 ulint offset, /*!< in: undo log header offset on page */
140 bool shared, /*!< in: true=S-latch, false=X-latch */
141 mtr_t* mtr); /*!< in: mtr */
142/***********************************************************************//**
143Gets the next record in an undo log.
144@return undo log record, the page s-latched, NULL if none */
145trx_undo_rec_t*
146trx_undo_get_next_rec(
147/*==================*/
148 trx_undo_rec_t* rec, /*!< in: undo record */
149 ulint page_no,/*!< in: undo log header page number */
150 ulint offset, /*!< in: undo log header offset on page */
151 mtr_t* mtr); /*!< in: mtr */
152
153/** Gets the first record in an undo log.
154@param[in] space undo log header space
155@param[in] page_no undo log header page number
156@param[in] offset undo log header offset on page
157@param[in] mode latching mode: RW_S_LATCH or RW_X_LATCH
158@param[in,out] mtr mini-transaction
159@return undo log record, the page latched, NULL if none */
160trx_undo_rec_t*
161trx_undo_get_first_rec(
162 fil_space_t* space,
163 ulint page_no,
164 ulint offset,
165 ulint mode,
166 mtr_t* mtr);
167
168/** Allocate an undo log page.
169@param[in,out] undo undo log
170@param[in,out] mtr mini-transaction that does not hold any page latch
171@return X-latched block if success
172@retval NULL on failure */
173buf_block_t* trx_undo_add_page(trx_undo_t* undo, mtr_t* mtr)
174 MY_ATTRIBUTE((nonnull, warn_unused_result));
175
176/** Free the last undo log page. The caller must hold the rseg mutex.
177@param[in,out] undo undo log
178@param[in,out] mtr mini-transaction that does not hold any undo log page
179 or that has allocated the undo log page */
180void
181trx_undo_free_last_page(trx_undo_t* undo, mtr_t* mtr)
182 MY_ATTRIBUTE((nonnull));
183
184/** Truncate the tail of an undo log during rollback.
185@param[in,out] undo undo log
186@param[in] limit all undo logs after this limit will be discarded
187@param[in] is_temp whether this is temporary undo log */
188void
189trx_undo_truncate_end(trx_undo_t* undo, undo_no_t limit, bool is_temp)
190 MY_ATTRIBUTE((nonnull));
191
192/** Truncate the head of an undo log.
193NOTE that only whole pages are freed; the header page is not
194freed, but emptied, if all the records there are below the limit.
195@param[in,out] rseg rollback segment
196@param[in] hdr_page_no header page number
197@param[in] hdr_offset header offset on the page
198@param[in] limit first undo number to preserve
199(everything below the limit will be truncated) */
200void
201trx_undo_truncate_start(
202 trx_rseg_t* rseg,
203 ulint hdr_page_no,
204 ulint hdr_offset,
205 undo_no_t limit);
206/** Assign an undo log for a persistent transaction.
207A new undo log is created or a cached undo log reused.
208@param[in,out] trx transaction
209@param[out] err error code
210@param[in,out] mtr mini-transaction
211@return the undo log block
212@retval NULL on error */
213buf_block_t*
214trx_undo_assign(trx_t* trx, dberr_t* err, mtr_t* mtr)
215 MY_ATTRIBUTE((nonnull));
216/** Assign an undo log for a transaction.
217A new undo log is created or a cached undo log reused.
218@param[in,out] trx transaction
219@param[in] rseg rollback segment
220@param[out] undo the undo log
221@param[out] err error code
222@param[in,out] mtr mini-transaction
223@return the undo log block
224@retval NULL on error */
225buf_block_t*
226trx_undo_assign_low(trx_t* trx, trx_rseg_t* rseg, trx_undo_t** undo,
227 dberr_t* err, mtr_t* mtr)
228 MY_ATTRIBUTE((nonnull, warn_unused_result));
229/******************************************************************//**
230Sets the state of the undo log segment at a transaction finish.
231@return undo log segment header page, x-latched */
232page_t*
233trx_undo_set_state_at_finish(
234/*=========================*/
235 trx_undo_t* undo, /*!< in: undo log memory copy */
236 mtr_t* mtr); /*!< in: mtr */
237
238/** Set the state of the undo log segment at a XA PREPARE or XA ROLLBACK.
239@param[in,out] trx transaction
240@param[in,out] undo undo log
241@param[in] rollback false=XA PREPARE, true=XA ROLLBACK
242@param[in,out] mtr mini-transaction
243@return undo log segment header page, x-latched */
244page_t*
245trx_undo_set_state_at_prepare(
246 trx_t* trx,
247 trx_undo_t* undo,
248 bool rollback,
249 mtr_t* mtr);
250
251/** Free an old insert or temporary undo log after commit or rollback.
252The information is not needed after a commit or rollback, therefore
253the data can be discarded.
254@param[in,out] undo undo log
255@param[in] is_temp whether this is temporary undo log */
256void
257trx_undo_commit_cleanup(trx_undo_t* undo, bool is_temp);
258
259/** At shutdown, frees the undo logs of a transaction. */
260void
261trx_undo_free_at_shutdown(trx_t *trx);
262
263/* Forward declaration. */
264namespace undo {
265 class Truncate;
266};
267
268/** Truncate UNDO tablespace, reinitialize header and rseg.
269@param[in] undo_trunc UNDO tablespace handler
270@return true if success else false. */
271bool
272trx_undo_truncate_tablespace(
273 undo::Truncate* undo_trunc);
274
275/** Parse MLOG_UNDO_INIT.
276@param[in] ptr log record
277@param[in] end_ptr end of log record buffer
278@param[in,out] page page or NULL
279@param[in,out] mtr mini-transaction
280@return end of log record
281@retval NULL if the log record is incomplete */
282byte*
283trx_undo_parse_page_init(const byte* ptr, const byte* end_ptr, page_t* page);
284/** Parse MLOG_UNDO_HDR_REUSE for crash-upgrade from MariaDB 10.2.
285@param[in] ptr redo log record
286@param[in] end_ptr end of log buffer
287@param[in,out] page undo page or NULL
288@return end of log record or NULL */
289byte*
290trx_undo_parse_page_header_reuse(
291 const byte* ptr,
292 const byte* end_ptr,
293 page_t* page);
294
295/** Parse the redo log entry of an undo log page header create.
296@param[in] ptr redo log record
297@param[in] end_ptr end of log buffer
298@param[in,out] page page frame or NULL
299@param[in,out] mtr mini-transaction or NULL
300@return end of log record or NULL */
301byte*
302trx_undo_parse_page_header(
303 const byte* ptr,
304 const byte* end_ptr,
305 page_t* page,
306 mtr_t* mtr);
307/** Read an undo log when starting up the database.
308@param[in,out] rseg rollback segment
309@param[in] id rollback segment slot
310@param[in] page_no undo log segment page number
311@param[in,out] max_trx_id the largest observed transaction ID
312@return size of the undo log in pages */
313ulint
314trx_undo_mem_create_at_db_start(trx_rseg_t* rseg, ulint id, ulint page_no,
315 trx_id_t& max_trx_id);
316
317#endif /* !UNIV_INNOCHECKSUM */
318
319/* Types of an undo log segment */
320#define TRX_UNDO_INSERT 1 /* contains undo entries for inserts */
321#define TRX_UNDO_UPDATE 2 /* contains undo entries for updates
322 and delete markings: in short,
323 modifys (the name 'UPDATE' is a
324 historical relic) */
325/* States of an undo log segment */
326#define TRX_UNDO_ACTIVE 1 /* contains an undo log of an active
327 transaction */
328#define TRX_UNDO_CACHED 2 /* cached for quick reuse */
329#define TRX_UNDO_TO_FREE 3 /* insert undo segment can be freed */
330#define TRX_UNDO_TO_PURGE 4 /* update undo segment will not be
331 reused: it can be freed in purge when
332 all undo data in it is removed */
333#define TRX_UNDO_PREPARED 5 /* contains an undo log of an
334 prepared transaction */
335
336#ifndef UNIV_INNOCHECKSUM
337
338/** Transaction undo log memory object; modified by the thread associated
339with the transaction. */
340
341struct trx_undo_t {
342 /*-----------------------------*/
343 ulint id; /*!< undo log slot number within the
344 rollback segment */
345 ulint state; /*!< state of the corresponding undo log
346 segment */
347 trx_id_t trx_id; /*!< id of the trx assigned to the undo
348 log */
349 XID xid; /*!< X/Open XA transaction
350 identification */
351 ibool dict_operation; /*!< TRUE if a dict operation trx */
352 table_id_t table_id; /*!< if a dict operation, then the table
353 id */
354 trx_rseg_t* rseg; /*!< rseg where the undo log belongs */
355 /*-----------------------------*/
356 ulint hdr_page_no; /*!< page number of the header page in
357 the undo log */
358 ulint hdr_offset; /*!< header offset of the undo log on
359 the page */
360 ulint last_page_no; /*!< page number of the last page in the
361 undo log; this may differ from
362 top_page_no during a rollback */
363 ulint size; /*!< current size in pages */
364 /*-----------------------------*/
365 ulint top_page_no; /*!< page number where the latest undo
366 log record was catenated; during
367 rollback the page from which the latest
368 undo record was chosen */
369 ulint top_offset; /*!< offset of the latest undo record,
370 i.e., the topmost element in the undo
371 log if we think of it as a stack */
372 undo_no_t top_undo_no; /*!< undo number of the latest record
373 (IB_ID_MAX if the undo log is empty) */
374 buf_block_t* guess_block; /*!< guess for the buffer block where
375 the top page might reside */
376 ulint withdraw_clock; /*!< the withdraw clock value of the
377 buffer pool when guess_block was stored */
378
379 /** @return whether the undo log is empty */
380 bool empty() const { return top_undo_no == IB_ID_MAX; }
381
382 /*-----------------------------*/
383 UT_LIST_NODE_T(trx_undo_t) undo_list;
384 /*!< undo log objects in the rollback
385 segment are chained into lists */
386};
387#endif /* !UNIV_INNOCHECKSUM */
388
389/** The offset of the undo log page header on pages of the undo log */
390#define TRX_UNDO_PAGE_HDR FSEG_PAGE_DATA
391/*-------------------------------------------------------------*/
392/** Transaction undo log page header offsets */
393/* @{ */
394#define TRX_UNDO_PAGE_TYPE 0 /*!< unused; 0 (before MariaDB 10.3.1:
395 TRX_UNDO_INSERT or TRX_UNDO_UPDATE) */
396#define TRX_UNDO_PAGE_START 2 /*!< Byte offset where the undo log
397 records for the LATEST transaction
398 start on this page (remember that
399 in an update undo log, the first page
400 can contain several undo logs) */
401#define TRX_UNDO_PAGE_FREE 4 /*!< On each page of the undo log this
402 field contains the byte offset of the
403 first free byte on the page */
404#define TRX_UNDO_PAGE_NODE 6 /*!< The file list node in the chain
405 of undo log pages */
406/*-------------------------------------------------------------*/
407#define TRX_UNDO_PAGE_HDR_SIZE (6 + FLST_NODE_SIZE)
408 /*!< Size of the transaction undo
409 log page header, in bytes */
410/* @} */
411
412/** An update undo segment with just one page can be reused if it has
413at most this many bytes used; we must leave space at least for one new undo
414log header on the page */
415
416#define TRX_UNDO_PAGE_REUSE_LIMIT (3 << (srv_page_size_shift - 2))
417
418/* An update undo log segment may contain several undo logs on its first page
419if the undo logs took so little space that the segment could be cached and
420reused. All the undo log headers are then on the first page, and the last one
421owns the undo log records on subsequent pages if the segment is bigger than
422one page. If an undo log is stored in a segment, then on the first page it is
423allowed to have zero undo records, but if the segment extends to several
424pages, then all the rest of the pages must contain at least one undo log
425record. */
426
427/** The offset of the undo log segment header on the first page of the undo
428log segment */
429
430#define TRX_UNDO_SEG_HDR (TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE)
431/** Undo log segment header */
432/* @{ */
433/*-------------------------------------------------------------*/
434#define TRX_UNDO_STATE 0 /*!< TRX_UNDO_ACTIVE, ... */
435
436#ifndef UNIV_INNOCHECKSUM
437
438#define TRX_UNDO_LAST_LOG 2 /*!< Offset of the last undo log header
439 on the segment header page, 0 if
440 none */
441#define TRX_UNDO_FSEG_HEADER 4 /*!< Header for the file segment which
442 the undo log segment occupies */
443#define TRX_UNDO_PAGE_LIST (4 + FSEG_HEADER_SIZE)
444 /*!< Base node for the list of pages in
445 the undo log segment; defined only on
446 the undo log segment's first page */
447/*-------------------------------------------------------------*/
448/** Size of the undo log segment header */
449#define TRX_UNDO_SEG_HDR_SIZE (4 + FSEG_HEADER_SIZE + FLST_BASE_NODE_SIZE)
450/* @} */
451
452/** The undo log header. There can be several undo log headers on the first
453page of an update undo log segment. */
454/* @{ */
455/*-------------------------------------------------------------*/
456/** Transaction start identifier, or 0 if the undo log segment has been
457completely purged and trx_purge_free_segment() has started freeing it */
458#define TRX_UNDO_TRX_ID 0
459/** Transaction end identifier (if the log is in a history list),
460or 0 if the transaction has not been committed */
461#define TRX_UNDO_TRX_NO 8
462/** Before MariaDB 10.3.1, when purge did not reset DB_TRX_ID of
463surviving user records, this used to be called TRX_UNDO_DEL_MARKS.
464
465The value 1 indicates that purge needs to process the undo log segment.
466The value 0 indicates that all of it has been processed, and
467trx_purge_free_segment() has been invoked, so the log is not safe to access.
468
469Before MariaDB 10.3.1, a log segment may carry the value 0 even before
470trx_purge_free_segment() was called, for those undo log records for
471which purge would not result in removing delete-marked records. */
472#define TRX_UNDO_NEEDS_PURGE 16
473#define TRX_UNDO_LOG_START 18 /*!< Offset of the first undo log record
474 of this log on the header page; purge
475 may remove undo log record from the
476 log start, and therefore this is not
477 necessarily the same as this log
478 header end offset */
479#define TRX_UNDO_XID_EXISTS 20 /*!< TRUE if undo log header includes
480 X/Open XA transaction identification
481 XID */
482#define TRX_UNDO_DICT_TRANS 21 /*!< TRUE if the transaction is a table
483 create, index create, or drop
484 transaction: in recovery
485 the transaction cannot be rolled back
486 in the usual way: a 'rollback' rather
487 means dropping the created or dropped
488 table, if it still exists */
489#define TRX_UNDO_TABLE_ID 22 /*!< Id of the table if the preceding
490 field is TRUE */
491#define TRX_UNDO_NEXT_LOG 30 /*!< Offset of the next undo log header
492 on this page, 0 if none */
493#define TRX_UNDO_PREV_LOG 32 /*!< Offset of the previous undo log
494 header on this page, 0 if none */
495#define TRX_UNDO_HISTORY_NODE 34 /*!< If the log is put to the history
496 list, the file list node is here */
497/*-------------------------------------------------------------*/
498/** Size of the undo log header without XID information */
499#define TRX_UNDO_LOG_OLD_HDR_SIZE (34 + FLST_NODE_SIZE)
500
501/* Note: the writing of the undo log old header is coded by a log record
502MLOG_UNDO_HDR_CREATE. The appending of an XID to the
503header is logged separately. In this sense, the XID is not really a member
504of the undo log header. TODO: do not append the XID to the log header if XA
505is not needed by the user. The XID wastes about 150 bytes of space in every
506undo log. In the history list we may have millions of undo logs, which means
507quite a large overhead. */
508
509/** X/Open XA Transaction Identification (XID) */
510/* @{ */
511/** xid_t::formatID */
512#define TRX_UNDO_XA_FORMAT (TRX_UNDO_LOG_OLD_HDR_SIZE)
513/** xid_t::gtrid_length */
514#define TRX_UNDO_XA_TRID_LEN (TRX_UNDO_XA_FORMAT + 4)
515/** xid_t::bqual_length */
516#define TRX_UNDO_XA_BQUAL_LEN (TRX_UNDO_XA_TRID_LEN + 4)
517/** Distributed transaction identifier data */
518#define TRX_UNDO_XA_XID (TRX_UNDO_XA_BQUAL_LEN + 4)
519/*--------------------------------------------------------------*/
520#define TRX_UNDO_LOG_XA_HDR_SIZE (TRX_UNDO_XA_XID + XIDDATASIZE)
521 /*!< Total size of the undo log header
522 with the XA XID */
523/* @} */
524
525#include "trx0undo.ic"
526#endif /* !UNIV_INNOCHECKSUM */
527
528#endif
529