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