1 /* Copyright (c) 2014, 2021, Oracle and/or its affiliates. 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 02110-1301 USA */ 22 23 #ifndef RPL_TRANSACTION_WRITE_SET_CTX_H 24 #define RPL_TRANSACTION_WRITE_SET_CTX_H 25 26 #include "my_global.h" 27 #include <vector> 28 #include <map> 29 #include <list> 30 #include <set> 31 #include <string> 32 33 /** 34 Thread class responsible for the collection of write sets associated 35 to a transaction. 36 37 It also includes suport for save points where information will be discarded 38 on rollbacks to a savepoint. 39 40 Write set and flags are reset on 41 Rpl_transaction_write_set_ctx::reset_state(). 42 43 The write set collection by an executing transaction is capped to a limit. 44 The limit can be "soft" or "hard": 45 - when a writeset grows above a "soft" limit, the transaction is allowed to 46 execute and commit, but the write set is discarded, and the transaction 47 declared to not have a usable write set. 48 - when a write set grows above a "hard" limit, the transaction is forced 49 to abort and rollback. 50 51 We cannot use a soft limit for transactions that will be certified in GR, 52 since a writeset is required for correct certification. But when GR is 53 disabled, we can use a soft limit, because the writeset is only used to 54 compute transaction dependencies, and we can pessimistically mark the 55 transaction as conflicting with all other transcations when the writeset 56 is discarded. 57 A soft limit can also be used for transactions executed by the GR recovery 58 channel, since they will not be certified, and the GR applier channel, 59 since those transactions have already passed the certification stage. 60 61 For the soft limit, we use 62 - binlog_transaction_dependency_history_size. 63 Transactions bigger than that cannot be added to the writeset history 64 since they do not fit, and therefore are marked as conflicting with all 65 *subsequent* transactions anyways. 66 Therefore much of the parallelization for the transaction is already 67 destroyed, and it is unlikely that also marking it as conflicting with 68 *previous* transactions makes a significant difference. 69 70 For the hard limit, when using Group Replication, we use 71 - group_replication_transaction_size_limit. 72 Since the writeset is a subset of the transaction, and the transaction 73 is limited to this size anyways, a transaction whose writeset exceeds 74 this limit will fail anyways. 75 So failing it when generating the writeset is merely a fail-fast mechanism, 76 and it is not a restriction to apply this limit to the writeset of all 77 transactions for which the full transaction data is also subject to the limit. 78 The transactions that are subject to this limit are exactly those executed 79 when GR is enabled, except by the GR applier channel and GR recovery channel. 80 81 We expose the following interfaces so that components such as GR 82 can control the limit. 83 There is an interface to *globally* 84 disable/enable the soft limit: 85 static void set_global_require_full_write_set(bool requires_ws); 86 set/alter/remove a hard limit: 87 static void set_global_write_set_memory_size_limit(uint64 limit) 88 static void update_global_write_set_memory_size_limit(uint64 limit); 89 90 There is another interface to override the global limits for a thread: 91 void set_local_ignore_write_set_memory_limit(bool ignore_limit); 92 void set_local_allow_drop_write_set(bool allow_drop_write_set); 93 94 The local methods are used for example for Group Replication applier and 95 recovery threads as group_replication_transaction_size_limit only applies 96 to client sessions and non group replication replica threads. 97 */ 98 class Rpl_transaction_write_set_ctx 99 { 100 public: 101 Rpl_transaction_write_set_ctx(); ~Rpl_transaction_write_set_ctx()102 virtual ~Rpl_transaction_write_set_ctx() {} 103 104 /** 105 Function to add the write set of the hash of the PKE in the std::vector 106 in the transaction_ctx object. 107 108 @param[in] hash - the uint64 type hash value of the PKE. 109 */ 110 bool add_write_set(uint64 hash); 111 112 /* 113 Function to get the pointer of the write set in the 114 transaction_ctx object. 115 */ 116 std::set<uint64> *get_write_set(); 117 118 /** 119 Reset the object so it can be used for a new transaction. 120 */ 121 void reset_state(); 122 123 /* 124 mark transactions that include tables with no pk 125 */ 126 void set_has_missing_keys(); 127 128 /* 129 check if the transaction was marked as having missing keys. 130 131 @retval true The transaction accesses tables with no PK. 132 @retval false All tables referenced in transaction have PK. 133 */ 134 bool get_has_missing_keys(); 135 136 /* 137 mark transactions that include tables referenced by foreign keys 138 */ 139 void set_has_related_foreign_keys(); 140 141 /* 142 function to check if the transaction was marked as having missing keys. 143 144 @retval true If the transaction was marked as being referenced by a foreign key 145 */ 146 bool get_has_related_foreign_keys(); 147 148 /** 149 Identifies situations where the limit for number of write set entries 150 already exceeded the configure limit. 151 152 @retval true if too many write set entries exist, false otherwise 153 */ 154 bool was_write_set_limit_reached(); 155 156 /** 157 @returns the size of the write_set field in bytes 158 */ 159 size_t write_set_memory_size(); 160 161 /** 162 Function to add a new SAVEPOINT identifier in the savepoint map in the 163 transaction_ctx object. 164 165 @param[in] name - the identifier name of the SAVEPOINT. 166 */ 167 void add_savepoint(char* name); 168 169 /** 170 Function to delete a SAVEPOINT identifier in the savepoint map in the 171 transaction_ctx object. 172 173 @param[in] name - the identifier name of the SAVEPOINT. 174 */ 175 void del_savepoint(char* name); 176 177 /** 178 Function to delete all data added to write set and savepoint since 179 SAVEPOINT identifier was added to savepoinbt in the transaction_ctx object. 180 181 @param[in] name - the identifier name of the SAVEPOINT. 182 */ 183 void rollback_to_savepoint(char* name); 184 185 /** 186 Function to push savepoint data to a list and clear the savepoint map in 187 order to create another identifier context, needed on functions ant trigger. 188 */ 189 void reset_savepoint_list(); 190 191 /** 192 Restore previous savepoint map context, called after executed trigger or 193 function. 194 */ 195 void restore_savepoint_list(); 196 197 /** 198 Adds a memory limit for write sets. 199 200 @note currently only one component can set this limit a time. 201 202 @param limit the limit to be added 203 */ 204 static void set_global_write_set_memory_size_limit(int64 limit); 205 206 /** 207 Updates the memory limit for write sets. 208 209 @note Using the value 0 disables the limit 210 211 @param limit the limit to be added 212 */ 213 static void update_global_write_set_memory_size_limit(int64 limit); 214 215 /** 216 Prevent or allow this class to discard writesets exceeding a size limit 217 If true, a transaction will never discard its write sets 218 219 @param requires_ws if who invoked the method needs or not write sets 220 */ 221 static void set_global_require_full_write_set(bool requires_ws); 222 223 /** 224 Set if the thread shall ignore any configured memory limit 225 for write set collection 226 227 @param ignore_limit if the limit should be ignored 228 */ 229 void set_local_ignore_write_set_memory_limit(bool ignore_limit); 230 231 /** 232 Set if the thread shall if needed discard write sets 233 234 @param allow_drop_write_set if full write sets are not critical 235 */ 236 void set_local_allow_drop_write_set(bool allow_drop_write_set); 237 238 private: 239 /* 240 Clear the vector that stores the PKEs, and clear the savepoints, but do not 241 restore all the flags. Outside transaction cleanup, this is used when 242 discarding a writeset of excessive size, without aborting the transaction. 243 */ 244 void clear_write_set(); 245 246 std::vector<uint64> write_set; 247 std::set<uint64> write_set_unique; 248 249 bool m_has_missing_keys; 250 bool m_has_related_foreign_keys; 251 252 /** 253 Contains information related to SAVEPOINTs. The key on map is the 254 identifier and the value is the size of write set when command was 255 executed. 256 */ 257 std::map<std::string, size_t> savepoint; 258 259 /** 260 Create a savepoint context hierarchy to support encapsulation of 261 identifier name when function or trigger are executed. 262 */ 263 std::list<std::map<std::string, size_t> > savepoint_list; 264 265 // Write set restriction variables 266 267 /** There is a component requiring write sets on transactions */ 268 static int32 m_global_component_requires_write_sets; 269 /** Memory size limit enforced for write set collection */ 270 static int64 m_global_write_set_memory_size_limit; 271 272 /** 273 If the thread should or not ignore the set limit for 274 write set collection 275 */ 276 bool m_ignore_write_set_memory_limit; 277 /** 278 Even if a component says all transactions require write sets, 279 this variable says this thread should discard them when they are 280 bigger than m_opt_max_history_size 281 */ 282 bool m_local_allow_drop_write_set; 283 284 /** True if the write set size is over the configure limit */ 285 bool m_local_has_reached_write_set_limit; 286 }; 287 288 #endif /* RPL_TRANSACTION_WRITE_SET_CTX_H */ 289