| 1 | /***************************************************************************** |
| 2 | |
| 3 | Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved. |
| 4 | Copyright (c) 2017, 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/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 "univ.i" |
| 31 | #include "mtr0types.h" |
| 32 | #include "row0types.h" |
| 33 | #include "rem0types.h" |
| 34 | #include "data0types.h" |
| 35 | #include "dict0types.h" |
| 36 | #include "trx0types.h" |
| 37 | #include "que0types.h" |
| 38 | |
| 39 | class ut_stage_alter_t; |
| 40 | |
| 41 | extern ulint onlineddl_rowlog_rows; |
| 42 | extern ulint onlineddl_rowlog_pct_used; |
| 43 | extern ulint onlineddl_pct_progress; |
| 44 | |
| 45 | /******************************************************//** |
| 46 | Allocate the row log for an index and flag the index |
| 47 | for online creation. |
| 48 | @retval true if success, false if not */ |
| 49 | bool |
| 50 | row_log_allocate( |
| 51 | /*=============*/ |
| 52 | const trx_t* trx, /*!< in: the ALTER TABLE transaction */ |
| 53 | dict_index_t* index, /*!< in/out: index */ |
| 54 | dict_table_t* table, /*!< in/out: new table being rebuilt, |
| 55 | or NULL when creating a secondary index */ |
| 56 | bool same_pk,/*!< in: whether the definition of the |
| 57 | PRIMARY KEY has remained the same */ |
| 58 | const dtuple_t* defaults, |
| 59 | /*!< in: default values of |
| 60 | added, changed columns, or NULL */ |
| 61 | const ulint* col_map,/*!< in: mapping of old column |
| 62 | numbers to new ones, or NULL if !table */ |
| 63 | const char* path, /*!< in: where to create temporary file */ |
| 64 | bool ignore) /*!< in: Whether alter ignore issued */ |
| 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 ulint* 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 ulint* 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 ulint* 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 ulint* 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 | @return DB_SUCCESS, or error code on failure */ |
| 213 | dberr_t |
| 214 | row_log_table_apply( |
| 215 | que_thr_t* thr, |
| 216 | dict_table_t* old_table, |
| 217 | struct TABLE* table, |
| 218 | ut_stage_alter_t* stage) |
| 219 | MY_ATTRIBUTE((warn_unused_result)); |
| 220 | |
| 221 | /******************************************************//** |
| 222 | Get the latest transaction ID that has invoked row_log_online_op() |
| 223 | during online creation. |
| 224 | @return latest transaction ID, or 0 if nothing was logged */ |
| 225 | trx_id_t |
| 226 | row_log_get_max_trx( |
| 227 | /*================*/ |
| 228 | dict_index_t* index) /*!< in: index, must be locked */ |
| 229 | MY_ATTRIBUTE((nonnull, warn_unused_result)); |
| 230 | |
| 231 | /** Apply the row log to the index upon completing index creation. |
| 232 | @param[in] trx transaction (for checking if the operation was |
| 233 | interrupted) |
| 234 | @param[in,out] index secondary index |
| 235 | @param[in,out] table MySQL table (for reporting duplicates) |
| 236 | @param[in,out] stage performance schema accounting object, used by |
| 237 | ALTER TABLE. stage->begin_phase_log_index() will be called initially and then |
| 238 | stage->inc() will be called for each block of log that is applied. |
| 239 | @return DB_SUCCESS, or error code on failure */ |
| 240 | dberr_t |
| 241 | row_log_apply( |
| 242 | const trx_t* trx, |
| 243 | dict_index_t* index, |
| 244 | struct TABLE* table, |
| 245 | ut_stage_alter_t* stage) |
| 246 | MY_ATTRIBUTE((warn_unused_result)); |
| 247 | |
| 248 | #ifdef HAVE_PSI_STAGE_INTERFACE |
| 249 | /** Estimate how much work is to be done by the log apply phase |
| 250 | of an ALTER TABLE for this index. |
| 251 | @param[in] index index whose log to assess |
| 252 | @return work to be done by log-apply in abstract units |
| 253 | */ |
| 254 | ulint |
| 255 | row_log_estimate_work( |
| 256 | const dict_index_t* index); |
| 257 | #endif /* HAVE_PSI_STAGE_INTERFACE */ |
| 258 | |
| 259 | #include "row0log.ic" |
| 260 | |
| 261 | #endif /* row0log.h */ |
| 262 | |