1 /*****************************************************************************
2 
3 Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
4 Copyright (c) 2017, 2021, 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, Fifth Floor, Boston, MA 02110-1335 USA
17 
18 *****************************************************************************/
19 
20 /**************************************************//**
21 @file include/row0log.h
22 Modification log for online index creation and online table rebuild
23 
24 Created 2011-05-26 Marko Makela
25 *******************************************************/
26 
27 #ifndef row0log_h
28 #define row0log_h
29 
30 #include "que0types.h"
31 #include "mtr0types.h"
32 #include "row0types.h"
33 #include "rem0types.h"
34 #include "data0types.h"
35 #include "trx0types.h"
36 
37 class ut_stage_alter_t;
38 
39 extern Atomic_counter<ulint> onlineddl_rowlog_rows;
40 extern ulint onlineddl_rowlog_pct_used;
41 extern ulint onlineddl_pct_progress;
42 
43 /******************************************************//**
44 Allocate the row log for an index and flag the index
45 for online creation.
46 @retval true if success, false if not */
47 bool
48 row_log_allocate(
49 /*=============*/
50 	const trx_t*	trx,	/*!< in: the ALTER TABLE transaction */
51 	dict_index_t*	index,	/*!< in/out: index */
52 	dict_table_t*	table,	/*!< in/out: new table being rebuilt,
53 				or NULL when creating a secondary index */
54 	bool		same_pk,/*!< in: whether the definition of the
55 				PRIMARY KEY has remained the same */
56 	const dtuple_t*	defaults,
57 				/*!< in: default values of
58 				added, changed columns, or NULL */
59 	const ulint*	col_map,/*!< in: mapping of old column
60 				numbers to new ones, or NULL if !table */
61 	const char*	path,	/*!< in: where to create temporary file */
62 	const TABLE*	old_table,	/*!< in:table definition before alter */
63 	bool		allow_not_null) /*!< in: allow null to non-null
64 					conversion */
65 	MY_ATTRIBUTE((nonnull(1), warn_unused_result));
66 
67 /******************************************************//**
68 Free the row log for an index that was being created online. */
69 void
70 row_log_free(
71 /*=========*/
72 	row_log_t*	log)	/*!< in,own: row log */
73 	MY_ATTRIBUTE((nonnull));
74 
75 /******************************************************//**
76 Free the row log for an index on which online creation was aborted. */
77 UNIV_INLINE
78 void
79 row_log_abort_sec(
80 /*==============*/
81 	dict_index_t*	index)	/*!< in/out: index (x-latched) */
82 	MY_ATTRIBUTE((nonnull));
83 
84 /******************************************************//**
85 Try to log an operation to a secondary index that is
86 (or was) being created.
87 @retval true if the operation was logged or can be ignored
88 @retval false if online index creation is not taking place */
89 UNIV_INLINE
90 bool
91 row_log_online_op_try(
92 /*==================*/
93 	dict_index_t*	index,	/*!< in/out: index, S or X latched */
94 	const dtuple_t* tuple,	/*!< in: index tuple */
95 	trx_id_t	trx_id)	/*!< in: transaction ID for insert,
96 				or 0 for delete */
97 	MY_ATTRIBUTE((nonnull, warn_unused_result));
98 /******************************************************//**
99 Logs an operation to a secondary index that is (or was) being created. */
100 void
101 row_log_online_op(
102 /*==============*/
103 	dict_index_t*	index,	/*!< in/out: index, S or X latched */
104 	const dtuple_t*	tuple,	/*!< in: index tuple */
105 	trx_id_t	trx_id)	/*!< in: transaction ID for insert,
106 				or 0 for delete */
107 	ATTRIBUTE_COLD __attribute__((nonnull));
108 
109 /******************************************************//**
110 Gets the error status of the online index rebuild log.
111 @return DB_SUCCESS or error code */
112 dberr_t
113 row_log_table_get_error(
114 /*====================*/
115 	const dict_index_t*	index)	/*!< in: clustered index of a table
116 					that is being rebuilt online */
117 	MY_ATTRIBUTE((nonnull, warn_unused_result));
118 
119 /** Check whether a virtual column is indexed in the new table being
120 created during alter table
121 @param[in]	index	cluster index
122 @param[in]	v_no	virtual column number
123 @return true if it is indexed, else false */
124 bool
125 row_log_col_is_indexed(
126 	const dict_index_t*	index,
127 	ulint			v_no);
128 
129 /******************************************************//**
130 Logs a delete operation to a table that is being rebuilt.
131 This will be merged in row_log_table_apply_delete(). */
132 void
133 row_log_table_delete(
134 /*=================*/
135 	const rec_t*	rec,	/*!< in: clustered index leaf page record,
136 				page X-latched */
137 	dict_index_t*	index,	/*!< in/out: clustered index, S-latched
138 				or X-latched */
139 	const rec_offs*	offsets,/*!< in: rec_get_offsets(rec,index) */
140 	const byte*	sys)	/*!< in: DB_TRX_ID,DB_ROLL_PTR that should
141 				be logged, or NULL to use those in rec */
142 	ATTRIBUTE_COLD __attribute__((nonnull(1,2,3)));
143 
144 /******************************************************//**
145 Logs an update operation to a table that is being rebuilt.
146 This will be merged in row_log_table_apply_update(). */
147 void
148 row_log_table_update(
149 /*=================*/
150 	const rec_t*	rec,	/*!< in: clustered index leaf page record,
151 				page X-latched */
152 	dict_index_t*	index,	/*!< in/out: clustered index, S-latched
153 				or X-latched */
154 	const rec_offs*	offsets,/*!< in: rec_get_offsets(rec,index) */
155 	const dtuple_t*	old_pk);/*!< in: row_log_table_get_pk()
156 				before the update */
157 
158 /******************************************************//**
159 Constructs the old PRIMARY KEY and DB_TRX_ID,DB_ROLL_PTR
160 of a table that is being rebuilt.
161 @return tuple of PRIMARY KEY,DB_TRX_ID,DB_ROLL_PTR in the rebuilt table,
162 or NULL if the PRIMARY KEY definition does not change */
163 const dtuple_t*
164 row_log_table_get_pk(
165 /*=================*/
166 	const rec_t*	rec,	/*!< in: clustered index leaf page record,
167 				page X-latched */
168 	dict_index_t*	index,	/*!< in/out: clustered index, S-latched
169 				or X-latched */
170 	const rec_offs*	offsets,/*!< in: rec_get_offsets(rec,index),
171 				or NULL */
172 	byte*		sys,	/*!< out: DB_TRX_ID,DB_ROLL_PTR for
173 				row_log_table_delete(), or NULL */
174 	mem_heap_t**	heap)	/*!< in/out: memory heap where allocated */
175 	ATTRIBUTE_COLD __attribute__((nonnull(1,2,5), warn_unused_result));
176 
177 /******************************************************//**
178 Logs an insert to a table that is being rebuilt.
179 This will be merged in row_log_table_apply_insert(). */
180 void
181 row_log_table_insert(
182 /*=================*/
183 	const rec_t*	rec,	/*!< in: clustered index leaf page record,
184 				page X-latched */
185 	dict_index_t*	index,	/*!< in/out: clustered index, S-latched
186 				or X-latched */
187 	const rec_offs*	offsets);/*!< in: rec_get_offsets(rec,index) */
188 /******************************************************//**
189 Notes that a BLOB is being freed during online ALTER TABLE. */
190 void
191 row_log_table_blob_free(
192 /*====================*/
193 	dict_index_t*	index,	/*!< in/out: clustered index, X-latched */
194 	ulint		page_no)/*!< in: starting page number of the BLOB */
195 	ATTRIBUTE_COLD __attribute__((nonnull));
196 /******************************************************//**
197 Notes that a BLOB is being allocated during online ALTER TABLE. */
198 void
199 row_log_table_blob_alloc(
200 /*=====================*/
201 	dict_index_t*	index,	/*!< in/out: clustered index, X-latched */
202 	ulint		page_no)/*!< in: starting page number of the BLOB */
203 	ATTRIBUTE_COLD __attribute__((nonnull));
204 
205 /** Apply the row_log_table log to a table upon completing rebuild.
206 @param[in]	thr		query graph
207 @param[in]	old_table	old table
208 @param[in,out]	table		MySQL table (for reporting duplicates)
209 @param[in,out]	stage		performance schema accounting object, used by
210 ALTER TABLE. stage->begin_phase_log_table() will be called initially and then
211 stage->inc() will be called for each block of log that is applied.
212 @param[in]	new_table	Altered table
213 @return DB_SUCCESS, or error code on failure */
214 dberr_t
215 row_log_table_apply(
216 	que_thr_t*		thr,
217 	dict_table_t*		old_table,
218 	struct TABLE*		table,
219 	ut_stage_alter_t*	stage,
220 	dict_table_t*		new_table)
221 	MY_ATTRIBUTE((warn_unused_result));
222 
223 /******************************************************//**
224 Get the latest transaction ID that has invoked row_log_online_op()
225 during online creation.
226 @return latest transaction ID, or 0 if nothing was logged */
227 trx_id_t
228 row_log_get_max_trx(
229 /*================*/
230 	dict_index_t*	index)	/*!< in: index, must be locked */
231 	MY_ATTRIBUTE((nonnull, warn_unused_result));
232 
233 /** Apply the row log to the index upon completing index creation.
234 @param[in]	trx	transaction (for checking if the operation was
235 interrupted)
236 @param[in,out]	index	secondary index
237 @param[in,out]	table	MySQL table (for reporting duplicates)
238 @param[in,out]	stage	performance schema accounting object, used by
239 ALTER TABLE. stage->begin_phase_log_index() will be called initially and then
240 stage->inc() will be called for each block of log that is applied.
241 @return DB_SUCCESS, or error code on failure */
242 dberr_t
243 row_log_apply(
244 	const trx_t*		trx,
245 	dict_index_t*		index,
246 	struct TABLE*		table,
247 	ut_stage_alter_t*	stage)
248 	MY_ATTRIBUTE((warn_unused_result));
249 
250 /** Get the n_core_fields of online log for the index
251 @param	 index	index whose n_core_fields of log to be accessed
252 @return number of n_core_fields */
253 unsigned row_log_get_n_core_fields(const dict_index_t *index);
254 
255 #ifdef HAVE_PSI_STAGE_INTERFACE
256 /** Estimate how much work is to be done by the log apply phase
257 of an ALTER TABLE for this index.
258 @param[in]	index	index whose log to assess
259 @return work to be done by log-apply in abstract units
260 */
261 ulint
262 row_log_estimate_work(
263 	const dict_index_t*	index);
264 #endif /* HAVE_PSI_STAGE_INTERFACE */
265 
266 #include "row0log.inl"
267 
268 #endif /* row0log.h */
269