1 /*****************************************************************************
2 
3 Copyright (c) 1996, 2019, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License, version 2.0, as published by the
7 Free Software Foundation.
8 
9 This program is also distributed with certain software (including but not
10 limited to OpenSSL) that is licensed under separate terms, as designated in a
11 particular file or component or in included license documentation. The authors
12 of MySQL hereby grant you an additional permission to link the program and
13 your derivative works with the separately licensed software that they have
14 included with MySQL.
15 
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19 for more details.
20 
21 You should have received a copy of the GNU General Public License along with
22 this program; if not, write to the Free Software Foundation, Inc.,
23 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24 
25 *****************************************************************************/
26 
27 /** @file include/trx0rec.h
28  Transaction undo log record
29 
30  Created 3/26/1996 Heikki Tuuri
31  *******************************************************/
32 
33 #ifndef trx0rec_h
34 #define trx0rec_h
35 
36 #include "univ.i"
37 
38 #include "data0data.h"
39 #include "dict0types.h"
40 #include "lob0undo.h"
41 #include "mtr0mtr.h"
42 #include "page0types.h"
43 #include "rem0types.h"
44 #include "row0log.h"
45 #include "row0types.h"
46 #include "trx0types.h"
47 
48 #ifndef UNIV_HOTBACKUP
49 #include "que0types.h"
50 
51 /** Copies the undo record to the heap.
52 @param[in]	undo_page	Undo Page
53 @param[in]	undo_offset	offset of the undo record in the page
54 @param[in]	heap		heap where copied
55 @return copy of undo log record */
56 UNIV_INLINE
57 trx_undo_rec_t *trx_undo_rec_copy(const page_t *undo_page, uint32_t undo_offset,
58                                   mem_heap_t *heap);
59 
60 /** Reads the undo log record type.
61  @return record type */
62 UNIV_INLINE
63 ulint trx_undo_rec_get_type(
64     const trx_undo_rec_t *undo_rec); /*!< in: undo log record */
65 /** Reads from an undo log record the record compiler info.
66  @return compiler info */
67 UNIV_INLINE
68 ulint trx_undo_rec_get_cmpl_info(
69     const trx_undo_rec_t *undo_rec); /*!< in: undo log record */
70 /** Returns TRUE if an undo log record contains an extern storage field.
71  @return true if extern */
72 UNIV_INLINE
73 ibool trx_undo_rec_get_extern_storage(
74     const trx_undo_rec_t *undo_rec); /*!< in: undo log record */
75 /** Reads the undo log record number.
76  @return undo no */
77 UNIV_INLINE
78 undo_no_t trx_undo_rec_get_undo_no(
79     const trx_undo_rec_t *undo_rec); /*!< in: undo log record */
80 
81 /** Returns the start of the undo record data area. */
82 #define trx_undo_rec_get_ptr(undo_rec, undo_no) \
83   ((undo_rec) + trx_undo_rec_get_offset(undo_no))
84 
85 /** Reads from an undo log record the table ID
86 @param[in]	undo_rec	Undo log record
87 @return the table ID */
88 table_id_t trx_undo_rec_get_table_id(const trx_undo_rec_t *undo_rec)
89     MY_ATTRIBUTE((warn_unused_result));
90 
91 /** Builds a row reference from an undo log record.
92  @return pointer to remaining part of undo record */
93 byte *trx_undo_rec_get_row_ref(
94     byte *ptr,           /*!< in: remaining part of a copy of an undo log
95                          record, at the start of the row reference;
96                          NOTE that this copy of the undo log record must
97                          be preserved as long as the row reference is
98                          used, as we do NOT copy the data in the
99                          record! */
100     dict_index_t *index, /*!< in: clustered index */
101     dtuple_t **ref,      /*!< out, own: row reference */
102     mem_heap_t *heap);   /*!< in: memory heap from which the memory
103                          needed is allocated */
104 /** Reads from an undo log update record the system field values of the old
105  version.
106  @return remaining part of undo log record after reading these values */
107 byte *trx_undo_update_rec_get_sys_cols(
108     const byte *ptr,      /*!< in: remaining part of undo
109                           log record after reading
110                           general parameters */
111     trx_id_t *trx_id,     /*!< out: trx id */
112     roll_ptr_t *roll_ptr, /*!< out: roll ptr */
113     ulint *info_bits);    /*!< out: info bits state */
114 
115 struct type_cmpl_t;
116 
117 /** Builds an update vector based on a remaining part of an undo log record.
118  @return remaining part of the record, NULL if an error detected, which
119  means that the record is corrupted. */
120 byte *trx_undo_update_rec_get_update(
121     const byte *ptr,            /*!< in: remaining part in update undo log
122                                 record, after reading the row reference
123                                 NOTE that this copy of the undo log record must
124                                 be preserved as long as the update vector is
125                                 used, as we do NOT copy the data in the
126                                 record! */
127     const dict_index_t *index,  /*!< in: clustered index */
128     ulint type,                 /*!< in: TRX_UNDO_UPD_EXIST_REC,
129                                 TRX_UNDO_UPD_DEL_REC, or
130                                 TRX_UNDO_DEL_MARK_REC; in the last case,
131                                 only trx id and roll ptr fields are added to
132                                 the update vector */
133     trx_id_t trx_id,            /*!< in: transaction id from this undo record */
134     roll_ptr_t roll_ptr,        /*!< in: roll pointer from this undo record */
135     ulint info_bits,            /*!< in: info bits from this undo record */
136     trx_t *trx,                 /*!< in: transaction */
137     mem_heap_t *heap,           /*!< in: memory heap from which the memory
138                                 needed is allocated */
139     upd_t **upd,                /*!< out, own: update vector */
140     lob::undo_vers_t *lob_undo, /*!< out: LOB undo information. */
141     type_cmpl_t &type_cmpl);    /*!< out: type compilation info */
142 
143 /** Builds a partial row from an update undo log record, for purge.
144  It contains the columns which occur as ordering in any index of the table.
145  Any missing columns are indicated by col->mtype == DATA_MISSING.
146  @return pointer to remaining part of undo record */
147 byte *trx_undo_rec_get_partial_row(
148     const byte *ptr,     /*!< in: remaining part in update undo log
149                          record of a suitable type, at the start of
150                          the stored index columns;
151                          NOTE that this copy of the undo log record must
152                          be preserved as long as the partial row is
153                          used, as we do NOT copy the data in the
154                          record! */
155     dict_index_t *index, /*!< in: clustered index */
156     dtuple_t **row,      /*!< out, own: partial row */
157     ibool ignore_prefix, /*!< in: flag to indicate if we
158                   expect blob prefixes in undo. Used
159                   only in the assertion. */
160     mem_heap_t *heap)    /*!< in: memory heap from which the memory
161                          needed is allocated */
162     MY_ATTRIBUTE((warn_unused_result));
163 /** Writes information to an undo log about an insert, update, or a delete
164  marking of a clustered index record. This information is used in a rollback of
165  the transaction and in consistent reads that must look to the history of this
166  transaction.
167  @return DB_SUCCESS or error code */
168 dberr_t trx_undo_report_row_operation(
169     ulint flags,                 /*!< in: if BTR_NO_UNDO_LOG_FLAG bit is
170                                  set, does nothing */
171     ulint op_type,               /*!< in: TRX_UNDO_INSERT_OP or
172                                  TRX_UNDO_MODIFY_OP */
173     que_thr_t *thr,              /*!< in: query thread */
174     dict_index_t *index,         /*!< in: clustered index */
175     const dtuple_t *clust_entry, /*!< in: in the case of an insert,
176                                  index entry to insert into the
177                                  clustered index, otherwise NULL */
178     const upd_t *update,         /*!< in: in the case of an update,
179                                  the update vector, otherwise NULL */
180     ulint cmpl_info,             /*!< in: compiler info on secondary
181                                  index updates */
182     const rec_t *rec,            /*!< in: case of an update or delete
183                                  marking, the record in the clustered
184                                  index, otherwise NULL */
185     const ulint *offsets,        /*!< in: rec_get_offsets(rec) */
186     roll_ptr_t *roll_ptr)        /*!< out: rollback pointer to the
187                                  inserted undo log record,
188                                  0 if BTR_NO_UNDO_LOG
189                                  flag was specified */
190     MY_ATTRIBUTE((warn_unused_result));
191 
192 /** status bit used for trx_undo_prev_version_build() */
193 
194 /** TRX_UNDO_PREV_IN_PURGE tells trx_undo_prev_version_build() that it
195 is being called purge view and we would like to get the purge record
196 even it is in the purge view (in normal case, it will return without
197 fetching the purge record */
198 #define TRX_UNDO_PREV_IN_PURGE 0x1
199 
200 /** This tells trx_undo_prev_version_build() to fetch the old value in
201 the undo log (which is the after image for an update) */
202 #define TRX_UNDO_GET_OLD_V_VALUE 0x2
203 
204 /** Build a previous version of a clustered index record. The caller must hold
205 a latch on the index page of the clustered index record.
206 If the vrow passed to this function is not null, then this function will store
207 information about virtual columns from the requested version in vrow, unless the
208 change did not affect any secondary index nor ordering field of clustered index
209 (the change has UPD_NODE_NO_ORD_CHANGE flag) in which case the requested
210 information can not be reconstructed from undo log, and the caller may assume
211 that the (virtual) columns of secondary index have the same values they have in
212 the more recent version (the one `rec` comes from).
213 Equivalently, if the vrow is not returned, it is either because it was not
214 requested, or not available due to UPD_NODE_NO_ORD_CHANGE.
215 Obviously vrow is also not set in case rec is the oldest version in history,
216 in which case we also set old_vers to NULL.
217 @param[in]	index_rec	clustered index record in the index tree
218 @param[in]	index_mtr	mtr which contains the latch to index_rec page
219                                 and purge_view
220 @param[in]	rec		version of a clustered index record
221 @param[in]	index		clustered index
222 @param[in,out]	offsets		rec_get_offsets(rec, index)
223 @param[in]	heap		memory heap from which the memory needed is
224                                 allocated
225 @param[out]	old_vers	previous version, or NULL if rec is the first
226                                 inserted version, or if history data has been
227                                 deleted
228 @param[in]	v_heap		memory heap used to create vrow dtuple if it is
229                                 not yet created. This heap diffs from "heap"
230                                 above in that it could be
231                                 prebuilt->old_vers_heap for selection
232 @param[out]	vrow		virtual column info, if any
233 @param[in]	v_status	status determine if it is going into this
234                                 function by purge thread or not. And if we read
235                                 "after image" of undo log has been rebuilt
236 @param[in]	lob_undo	LOB undo information.
237 @retval true if previous version was built, or if it was an insert or the table
238 has been rebuilt
239 @retval false if the previous version is earlier than purge_view, or being
240 purged, which means that it may have been removed */
241 bool trx_undo_prev_version_build(const rec_t *index_rec, mtr_t *index_mtr,
242                                  const rec_t *rec, const dict_index_t *index,
243                                  ulint *offsets, mem_heap_t *heap,
244                                  rec_t **old_vers, mem_heap_t *v_heap,
245                                  const dtuple_t **vrow, ulint v_status,
246                                  lob::undo_vers_t *lob_undo);
247 
248 #endif /* !UNIV_HOTBACKUP */
249 /** Parses a redo log record of adding an undo log record.
250  @return end of log record or NULL */
251 byte *trx_undo_parse_add_undo_rec(byte *ptr,     /*!< in: buffer */
252                                   byte *end_ptr, /*!< in: buffer end */
253                                   page_t *page); /*!< in: page or NULL */
254 /** Parses a redo log record of erasing of an undo page end.
255  @return end of log record or NULL */
256 byte *trx_undo_parse_erase_page_end(byte *ptr,     /*!< in: buffer */
257                                     byte *end_ptr, /*!< in: buffer end */
258                                     page_t *page,  /*!< in: page or NULL */
259                                     mtr_t *mtr);   /*!< in: mtr or NULL */
260 
261 /** Read from an undo log record a non-virtual column value.
262 @param[in,out]	ptr		pointer to remaining part of the undo record
263 @param[in,out]	field		stored field
264 @param[in,out]	len		length of the field, or UNIV_SQL_NULL
265 @param[in,out]	orig_len	original length of the locally stored part
266 of an externally stored column, or 0
267 @return remaining part of undo log record after reading these values */
268 byte *trx_undo_rec_get_col_val(const byte *ptr, const byte **field, ulint *len,
269                                ulint *orig_len);
270 
271 /** Read virtual column value from undo log
272 @param[in]	table		the table
273 @param[in]	ptr		undo log pointer
274 @param[in,out]	row		the dtuple to fill
275 @param[in]	in_purge        called by purge thread
276 @param[in]	online		true if this is from online DDL log
277 @param[in]	col_map		online rebuild column map
278 @param[in,out]	heap		memory heap to keep value when necessary */
279 void trx_undo_read_v_cols(const dict_table_t *table, const byte *ptr,
280                           const dtuple_t *row, bool in_purge, bool online,
281                           const ulint *col_map, mem_heap_t *heap);
282 
283 /** Read virtual column index from undo log if the undo log contains such
284 info, and verify the column is still indexed, and output its position
285 @param[in]	table		the table
286 @param[in]	ptr		undo log pointer
287 @param[in]	first_v_col	if this is the first virtual column, which
288                                 has the version marker
289 @param[in,out]	is_undo_log	his function is used to parse both undo log,
290                                 and online log for virtual columns. So
291                                 check to see if this is undo log
292 @param[out]	field_no	the column number
293 @return remaining part of undo log record after reading these values */
294 const byte *trx_undo_read_v_idx(const dict_table_t *table, const byte *ptr,
295                                 bool first_v_col, bool *is_undo_log,
296                                 ulint *field_no);
297 
298 #ifndef UNIV_HOTBACKUP
299 
300 /* Types of an undo log record: these have to be smaller than 16, as the
301 compilation info multiplied by 16 is ORed to this value in an undo log
302 record */
303 
304 #define TRX_UNDO_INSERT_REC 11 /* fresh insert into clustered index */
305 #define TRX_UNDO_UPD_EXIST_REC        \
306   12 /* update of a non-delete-marked \
307      record */
308 #define TRX_UNDO_UPD_DEL_REC                \
309   13 /* update of a delete marked record to \
310      a not delete marked record; also the   \
311      fields of the record can change */
312 #define TRX_UNDO_DEL_MARK_REC              \
313   14 /* delete marking of a record; fields \
314      do not change */
315 #define TRX_UNDO_CMPL_INFO_MULT           \
316   16 /* compilation info is multiplied by \
317      this and ORed to the type above */
318 
319 #define TRX_UNDO_MODIFY_BLOB              \
320   64 /* If this bit is set in type_cmpl,  \
321      then the undo log record has support \
322      for partial update of BLOBs. Also to \
323      make the undo log format extensible, \
324      introducing a new flag next to the   \
325      type_cmpl flag. */
326 
327 #define TRX_UNDO_UPD_EXTERN                \
328   128 /* This bit can be ORed to type_cmpl \
329       to denote that we updated external   \
330       storage fields: used by purge to     \
331       free the external storage */
332 
333 /* Operation type flags used in trx_undo_report_row_operation */
334 #define TRX_UNDO_INSERT_OP 1
335 #define TRX_UNDO_MODIFY_OP 2
336 
337 /** The type and compilation info flag in the undo record for update.
338 For easier understanding let the 8 bits be numbered as
339 7, 6, 5, 4, 3, 2, 1, 0. */
340 struct type_cmpl_t {
type_cmpl_ttype_cmpl_t341   type_cmpl_t() : m_flag(0) {}
342 
readtype_cmpl_t343   const byte *read(const byte *ptr) {
344     m_flag = mach_read_from_1(ptr);
345     return (ptr + 1);
346   }
347 
type_infotype_cmpl_t348   ulint type_info() {
349     /* Get 0-3 */
350     return (m_flag & 0x0F);
351   }
352 
cmpl_infotype_cmpl_t353   ulint cmpl_info() {
354     /* Get bits 5 and 4 */
355     return ((m_flag >> 4) & 0x03);
356   }
357 
358   /** Is an LOB updated by this update operation.
359   @return true if LOB is updated, false otherwise. */
is_lob_updatedtype_cmpl_t360   bool is_lob_updated() {
361     /* Check if bit 7 is set. */
362     return (m_flag & TRX_UNDO_UPD_EXTERN);
363   }
364 
365   /** Does the undo log record contains information about LOB partial
366   update vector.
367   @return true if undo contains LOB update info. */
is_lob_undotype_cmpl_t368   bool is_lob_undo() const {
369     /* Check if bit 6 is set. */
370     return (m_flag & TRX_UNDO_MODIFY_BLOB);
371   }
372 
373  private:
374   uint8_t m_flag;
375 };
376 
377 /** Reads from an undo log record the general parameters.
378  @return remaining part of undo log record after reading these values */
379 byte *trx_undo_rec_get_pars(
380     trx_undo_rec_t *undo_rec, /*!< in: undo log record */
381     ulint *type,              /*!< out: undo record type:
382                               TRX_UNDO_INSERT_REC, ... */
383     ulint *cmpl_info,         /*!< out: compiler info, relevant only
384                               for update type records */
385     bool *updated_extern,     /*!< out: true if we updated an
386                               externally stored fild */
387     undo_no_t *undo_no,       /*!< out: undo log record number */
388     table_id_t *table_id,     /*!< out: table id */
389     type_cmpl_t &type_cmpl);  /*!< out: type compilation info. */
390 
391 /** Get the max free space of undo log by assuming it's a fresh new page
392 and the free space doesn't count for the undo log header too. */
393 size_t trx_undo_max_free_space();
394 
395 /** Decide if the following undo log record is a multi-value virtual column
396 @param[in]     undo_rec        undo log record
397 @return true if this is a multi-value virtual column log, otherwise false */
398 bool trx_undo_rec_is_multi_value(const byte *undo_rec);
399 
400 /** Read from an undo log record a non-virtual column value.
401 @param[in,out]	ptr	pointer to remaining part of the undo record
402 @param[in,out]	field	stored field
403 @param[in,out]	heap	memory heap
404 @return remaining part of undo log record after reading these values */
405 const byte *trx_undo_rec_get_multi_value(const byte *ptr, dfield_t *field,
406                                          mem_heap_t *heap);
407 #include "trx0rec.ic"
408 
409 #endif /* !UNIV_HOTBACKUP */
410 
411 #endif /* trx0rec_h */
412