1 /* Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 22 02110-1301 USA */ 23 24 #ifndef RPL_GTID_PERSIST_H_ 25 #define RPL_GTID_PERSIST_H_ 26 27 #include "my_global.h" 28 #include "rpl_table_access.h" // System_table_access 29 #include "sql_class.h" // Open_tables_backup 30 31 #include <string> 32 33 34 class Gtid_table_access_context : public System_table_access 35 { 36 37 public: 38 static const LEX_STRING DB_NAME; 39 static const LEX_STRING TABLE_NAME; 40 Gtid_table_access_context()41 Gtid_table_access_context() : m_drop_thd_object(NULL) { }; ~Gtid_table_access_context()42 virtual ~Gtid_table_access_context() { }; 43 44 /** 45 Initialize the gtid_executed table access context as following: 46 - Create a new THD if current_thd is NULL 47 - Disable binlog temporarily if we are going to modify the table 48 - Open and lock a table. 49 50 @param[in/out] thd Thread requesting to open the table 51 @param lock_type How to lock the table 52 @param[out] table We will store the open table here 53 54 @return 55 @retval TRUE failed 56 @retval FALSE success 57 */ 58 bool init(THD **thd, TABLE **table, bool is_write); 59 /** 60 De-initialize the gtid_executed table access context as following: 61 - Close the table 62 - Reenable binlog if needed 63 - Destroy the created THD if needed. 64 65 @param thd Thread requesting to close the table 66 @param table Table to be closed 67 @param error If there was an error while updating the table 68 @param need_commit Need to commit current transaction if it is true 69 70 @return 71 @retval true failed 72 @retval false success 73 */ 74 bool deinit(THD *thd, TABLE *table, bool error, bool need_commit); 75 /** 76 Prepares before opening table. 77 - set flags 78 79 @param[in] thd Thread requesting to open the table 80 */ 81 void before_open(THD* thd); 82 /** 83 Creates a new thread in the bootstrap process or in the mysqld startup, 84 a thread is created in order to be able to access a table. And reset a 85 new "statement". 86 87 @return 88 @retval THD* Pointer to thread structure 89 */ 90 THD *create_thd(); 91 void drop_thd(THD* thd); 92 private: 93 /* Pointer to new created THD. */ 94 THD *m_drop_thd_object; 95 /* Modify the table if it is true. */ 96 bool m_is_write; 97 /* Save the lock info. */ 98 Open_tables_backup m_backup; 99 /* Save binlog options. */ 100 ulonglong m_tmp_disable_binlog__save_options; 101 102 /* Prevent user from invoking default assignment function. */ 103 Gtid_table_access_context &operator=(const Gtid_table_access_context &info); 104 /* Prevent user from invoking default constructor function. */ 105 Gtid_table_access_context(const Gtid_table_access_context &info); 106 }; 107 108 109 class Gtid_table_persistor 110 { 111 112 public: 113 static const uint number_fields= 3; 114 Gtid_table_persistor()115 Gtid_table_persistor() 116 { 117 m_count.atomic_set(0); 118 }; ~Gtid_table_persistor()119 virtual ~Gtid_table_persistor() { }; 120 121 /** 122 Insert the gtid into table. 123 124 @param thd Thread requesting to save gtid into the table 125 @param gtid holds the sidno and the gno. 126 127 @retval 128 0 OK 129 @retval 130 1 The table was not found. 131 @retval 132 -1 Error 133 */ 134 int save(THD *thd, const Gtid *gtid); 135 /** 136 Insert the gtid set into table. 137 138 @param gtid_set contains a set of gtid, which holds 139 the sidno and the gno. 140 141 @retval 142 0 OK 143 @retval 144 -1 Error 145 */ 146 int save(const Gtid_set *gtid_set); 147 /** 148 Delete all rows from the table. 149 150 @param thd Thread requesting to reset the table 151 152 @retval 153 0 OK 154 @retval 155 1 The table was not found. 156 @retval 157 -1 Error 158 */ 159 int reset(THD *thd); 160 161 /** 162 Fetch gtids from gtid_executed table and store them into 163 gtid_executed set. 164 165 @param[out] gtid_set store gtids fetched from the gtid_executed table. 166 167 @retval 168 0 OK 169 @retval 170 1 The table was not found. 171 @retval 172 -1 Error 173 */ 174 int fetch_gtids(Gtid_set *gtid_set); 175 /** 176 Compress the gtid_executed table completely by employing one 177 or more transactions. 178 179 @param thd Thread requesting to compress the table 180 181 @retval 182 0 OK 183 @retval 184 1 The table was not found. 185 @retval 186 -1 Error 187 */ 188 int compress(THD *thd); 189 /** 190 Push a warning to client if user is modifying the gtid_executed 191 table explicitly by a non-XA transaction. Push an error to client 192 if user is modifying it explicitly by a XA transaction. 193 194 @param thd Thread requesting to access the table 195 @param table The table is being accessed. 196 197 @retval 0 No warning or error was pushed to the client. 198 @retval 1 Push a warning to client. 199 @retval 2 Push an error to client. 200 */ warn_or_err_on_explicit_modification(THD * thd,TABLE_LIST * table)201 int warn_or_err_on_explicit_modification(THD *thd, TABLE_LIST *table) 202 { 203 DBUG_ENTER("Gtid_table_persistor::warn_or_err_on_explicit_modification"); 204 205 if (!thd->is_operating_gtid_table_implicitly && 206 table->lock_type >= TL_WRITE_ALLOW_WRITE && 207 !strcmp(table->table_name, Gtid_table_access_context::TABLE_NAME.str)) 208 { 209 if (thd->get_transaction()->xid_state()->has_state(XID_STATE::XA_ACTIVE)) 210 { 211 /* 212 Push an error to client if user is modifying the gtid_executed 213 table explicitly by a XA transaction. 214 */ 215 thd->raise_error_printf(ER_ERROR_ON_MODIFYING_GTID_EXECUTED_TABLE, 216 table->table_name); 217 DBUG_RETURN(2); 218 } 219 else 220 { 221 /* 222 Push a warning to client if user is modifying the gtid_executed 223 table explicitly by a non-XA transaction. 224 */ 225 thd->raise_warning_printf(ER_WARN_ON_MODIFYING_GTID_EXECUTED_TABLE, 226 table->table_name); 227 DBUG_RETURN(1); 228 } 229 } 230 231 DBUG_RETURN(0); 232 } 233 234 private: 235 /* Count the append size of the table */ 236 Atomic_int64 m_count; 237 /** 238 Compress the gtid_executed table, read each row by the 239 PK(sid, gno_start) in increasing order, compress the first 240 consecutive range of gtids within a single transaction. 241 242 @param thd Thread requesting to compress the table 243 @param[out] is_complete True if the gtid_executed table is 244 compressd completely. 245 246 @retval 247 0 OK 248 @retval 249 1 The table was not found. 250 @retval 251 -1 Error 252 */ 253 int compress_in_single_transaction(THD *thd, bool &is_complete); 254 /** 255 Read each row by the PK(sid, gno_start) in increasing order, 256 compress the first consecutive range of gtids. 257 For example, 258 1 1 259 2 2 260 3 3 261 6 6 262 7 7 263 8 8 264 After the compression, the gtids in the table is compressed as following: 265 1 3 266 6 6 267 7 7 268 8 8 269 270 @param table Reference to a table object. 271 @param[out] is_complete True if the gtid_executed table 272 is compressd completely. 273 274 @return 275 @retval 0 OK. 276 @retval -1 Error. 277 */ 278 int compress_first_consecutive_range(TABLE *table, bool &is_complete); 279 /** 280 Fill a gtid interval into fields of the gtid_executed table. 281 282 @param fields Reference to table fileds. 283 @param sid The source id of the gtid interval. 284 @param gno_star The first GNO of the gtid interval. 285 @param gno_end The last GNO of the gtid interval. 286 287 @return 288 @retval 0 OK. 289 @retval -1 Error. 290 */ 291 int fill_fields(Field **fields, const char *sid, 292 rpl_gno gno_start, rpl_gno gno_end); 293 /** 294 Write a gtid interval into the gtid_executed table. 295 296 @param table Reference to a table object. 297 @param sid The source id of the gtid interval. 298 @param gno_star The first GNO of the gtid interval. 299 @param gno_end The last GNO of the gtid interval. 300 301 @return 302 @retval 0 OK. 303 @retval -1 Error. 304 */ 305 int write_row(TABLE *table, const char *sid, 306 rpl_gno gno_start, rpl_gno gno_end); 307 /** 308 Update a gtid interval in the gtid_executed table. 309 - locate the gtid interval by primary key (sid, gno_start) 310 to update it with the new_gno_end. 311 312 @param table Reference to a table object. 313 @param sid The source id of the gtid interval. 314 @param gno_star The first GNO of the gtid interval. 315 @param new_gno_end The new last GNO of the gtid interval. 316 317 @return 318 @retval 0 OK. 319 @retval -1 Error. 320 */ 321 int update_row(TABLE *table, const char *sid, 322 rpl_gno gno_start, rpl_gno new_gno_end); 323 /** 324 Delete all rows in the gtid_executed table. 325 326 @param table Reference to a table object. 327 328 @return 329 @retval 0 OK. 330 @retval -1 Error. 331 */ 332 int delete_all(TABLE *table); 333 /** 334 Encode the current row fetched from the table into gtid text. 335 336 @param table Reference to a table object. 337 @retval Return the encoded gtid text. 338 */ 339 std::string encode_gtid_text(TABLE *table); 340 /** 341 Get gtid interval from the the current row of the table. 342 343 @param table Reference to a table object. 344 @param sid[out] The source id of the gtid interval. 345 @param gno_star[out] The first GNO of the gtid interval. 346 @param gno_end[out] The last GNO of the gtid interval. 347 */ 348 void get_gtid_interval(TABLE *table, std::string &sid, 349 rpl_gno &gno_start, rpl_gno &gno_end); 350 /** 351 Insert the gtid set into table. 352 353 @param table The gtid_executed table. 354 @param gtid_executed Contains a set of gtid, which holds 355 the sidno and the gno. 356 357 @retval 358 0 OK 359 @retval 360 -1 Error 361 */ 362 int save(TABLE *table, const Gtid_set *gtid_set); 363 /* Prevent user from invoking default assignment function. */ 364 Gtid_table_persistor &operator=(const Gtid_table_persistor &info); 365 /* Prevent user from invoking default constructor function. */ 366 Gtid_table_persistor(const Gtid_table_persistor &info); 367 }; 368 369 extern Gtid_table_persistor *gtid_table_persistor; 370 void create_compress_gtid_table_thread(); 371 void terminate_compress_gtid_table_thread(); 372 373 #endif /* RPL_GTID_PERSIST_H_ */ 374