MySQL 8.3.0
Source Code Documentation
clone0repl.h
Go to the documentation of this file.
1/*****************************************************************************
2
3Copyright (c) 2018, 2023, Oracle and/or its affiliates.
4
5This program is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License, version 2.0, as published by the
7Free Software Foundation.
8
9This program is also distributed with certain software (including but not
10limited to OpenSSL) that is licensed under separate terms, as designated in a
11particular file or component or in included license documentation. The authors
12of MySQL hereby grant you an additional permission to link the program and
13your derivative works with the separately licensed software that they have
14included with MySQL.
15
16This program is distributed in the hope that it will be useful, but WITHOUT
17ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0,
19for more details.
20
21You should have received a copy of the GNU General Public License along with
22this program; if not, write to the Free Software Foundation, Inc.,
2351 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
25*****************************************************************************/
26
27/** @file include/clone0repl.h
28 GTID persistence interface
29
30 *******************************************************/
31
32#ifndef CLONE_REPL_INCLUDE
33#define CLONE_REPL_INCLUDE
34
35#include <vector>
36#include "clone0monitor.h"
37#include "os0thread-create.h"
38#include "sql/rpl_gtid.h"
39#include "srv0srv.h"
40#include "srv0start.h"
41#include "trx0sys.h"
42
44
45/** Serialized GTID information size */
46inline constexpr size_t GTID_INFO_SIZE = 64;
47
48/** GTID format version. */
49inline constexpr uint32_t GTID_VERSION = 2;
50
51/** Serialized GTID */
52using Gtid_info = std::array<unsigned char, GTID_INFO_SIZE>;
53
54struct Gtid_desc;
55
56/** List of GTIDs */
57using Gtid_info_list = std::vector<Gtid_desc>;
58
59/** GTID descriptor with version information. */
60struct Gtid_desc {
61 /** If GTID descriptor is set. */
63 /** Serialized GTID information. */
65 /* GTID version. */
66 uint32_t m_version;
67};
68
69/** Persist GTID along with transaction commit */
71 public:
72 /** Constructor: start gtid thread */
75 /* No background is created yet. */
76 m_thread_active.store(false);
77 m_gtid_trx_no.store(0);
78 m_flush_number.store(0);
79 m_explicit_request.store(false);
80 m_active_number.store(m_flush_number.load() + 1);
81 /* We accept GTID even before the background service is started. This
82 is needed because we add GTIDs from undo log during recovery. */
83 m_active.store(true);
84 m_num_gtid_mem.store(0);
85 m_flush_in_progress.store(false);
86 m_close_thread.store(false);
87 }
88
89 /** Destructor: stop gtid thread */
91 ut_ad(!m_thread_active.load());
92 stop();
94 }
95
96 /** Start GTID persistence and background thread.
97 @return true, if successful. */
98 bool start();
99
100 /* Stop GTID persistence. */
101 void stop();
102
103 /* Wait for immediate flush.
104 @param[in] compress_gtid request GTID compression.
105 @param[in] early_timeout don't wait long if flush is blocked.
106 @param[in] cbk alert callback for long wait. */
107 void wait_flush(bool compress_gtid, bool early_timeout, Clone_Alert_Func cbk);
108
109 /**@return true, if GTID persistence is active. */
110 bool is_active() const { return (m_active.load()); }
111
112 /**@return true, if GTID thread is active. */
113 bool is_thread_active() const { return (m_thread_active.load()); }
114
115 /** Get oldest transaction number for which GTID is not persisted to table.
116 Transactions committed after this point should not be purged.
117 @return oldest transaction number. */
119 trx_id_t ret_no = m_gtid_trx_no.load();
120 /* Should never be zero. It can be set to max only before
121 GTID persister is active and no GTID is persisted. */
123 if (ret_no == TRX_ID_MAX) {
125 ut_ad(m_num_gtid_mem.load() == 0);
126 } else if (m_num_gtid_mem.load() == 0) {
127 /* For all transactions that are committed before this function is called
128 have their GTID flushed if flush is not in progress. "flush not in
129 progress" is sufficient but not necessary condition here. This is mainly
130 for cases when there is no GTID and purge doesn't need to wait. */
131 if (!m_flush_in_progress.load()) {
132 ret_no = TRX_ID_MAX;
133 }
134 }
135 return (ret_no);
136 }
137
138 /** Set oldest transaction number for which GTID is not persisted to table.
139 This is set during recovery from persisted value.
140 @param[in] max_trx_no transaction number */
142 ib::info(ER_IB_CLONE_GTID_PERSIST)
143 << "GTID recovery trx_no: " << max_trx_no;
144 /* Zero is special value. It is from old database without GTID
145 persistence. */
146 if (max_trx_no == 0) {
147 max_trx_no = TRX_ID_MAX;
148 }
149 m_gtid_trx_no.store(max_trx_no);
150 }
151
152 /** Get transaction GTID information.
153 @param[in,out] trx innodb transaction
154 @param[out] gtid_desc descriptor with serialized GTID */
155 void get_gtid_info(trx_t *trx, Gtid_desc &gtid_desc);
156
157 /** Set transaction flag to persist GTID and check if space need to be
158 allocated for GTID.
159 @param[in,out] trx current innodb transaction
160 @param[in] prepare if operation is Prepare
161 @param[in] rollback if operation is Rollback
162 @param[out] set_explicit if explicitly set to persist GTID
163 @return true, if undo space needs to be allocated. */
164 bool trx_check_set(trx_t *trx, bool prepare, bool rollback,
165 bool &set_explicit);
166
167 /** Check if current transaction has GTID.
168 @param[in] trx innodb transaction
169 @param[in,out] thd session THD
170 @param[out] passed_check true if transaction is good for GTID
171 @return true, if transaction has valid GTID. */
172 bool has_gtid(trx_t *trx, THD *&thd, bool &passed_check);
173
174 /** Check if GTID persistence is set
175 @param[in] trx current innnodb transaction
176 @return GTID storage type. */
178
179 /** Set or reset GTID persist flag in THD.
180 @param[in,out] trx current innnodb transaction
181 @param[in] set true, if need to set */
182 void set_persist_gtid(trx_t *trx, bool set);
183
184 /** Add GTID to in memory list.
185 @param[in] gtid_desc Descriptor with serialized GTID */
186 void add(const Gtid_desc &gtid_desc);
187
188 /** Write GTIDs periodically to disk table. */
189 void periodic_write();
190
191 /** Write GTIDs of non Innodb transactions to table. */
192 int write_other_gtids();
193
194 /** Disable copy construction */
196
197 /** Disable assignment */
199
200 private:
201 /** Check if GTID needs to persist at XA prepare.
202 @param[in] thd session THD
203 @param[in,out] trx current innnodb transaction
204 @param[in] found_gtid session is owning GTID
205 @param[in,out] alloc in:transaction checks are passed
206 out:GTID space need to be allocated
207 @return true, if GTID needs to be persisted */
208 bool check_gtid_prepare(THD *thd, trx_t *trx, bool found_gtid, bool &alloc);
209
210 /** Check if GTID needs to persist at commit.
211 @param[in] thd session THD
212 @param[in] found_gtid session is owning GTID
213 @param[out] set_explicit if explicitly set to persist GTID
214 @return true, if GTID needs to be persisted */
215 bool check_gtid_commit(THD *thd, bool found_gtid, bool &set_explicit);
216
217 /** Check if GTID needs to persist at rollback.
218 @param[in] thd session THD
219 @param[in,out] trx current innnodb transaction
220 @param[in] found_gtid session is owning GTID
221 @return true, if GTID needs to be persisted */
222 bool check_gtid_rollback(THD *thd, trx_t *trx, bool found_gtid);
223
224 /** Wait for gtid thread to start, finish or flush.
225 @param[in] start if waiting for start
226 @param[in] flush wait for immediate flush
227 @param[in] flush_number wait flush to reach this number
228 @param[in] compress wait also for compression
229 @param[in] early_timeout don't wait long if flush is blocked
230 @param[in] cbk alert callback for long wait
231 @return true if successful. */
232 bool wait_thread(bool start, bool flush, uint64_t flush_number, bool compress,
233 bool early_timeout, Clone_Alert_Func cbk);
234
235 /** @return current active GTID list */
238 return (get_list(m_active_number));
239 }
240
241 /** @return GTID list by number.
242 @param[in] list_number list number
243 @return GTID list reference. */
244 Gtid_info_list &get_list(uint64_t list_number) {
245 int list_index = (list_number & static_cast<uint64_t>(1));
246 return (m_gtids[list_index]);
247 }
248
249 /** Check if we need to skip write or compression based on debug variables.
250 @param[in] compression check for compression
251 @return true, if we should skip. */
252 bool debug_skip_write(bool compression);
253
254 /** Request immediate flush of all GTIDs accumulated.
255 @param[in] compress request compression of GTID table
256 @return flush list number to track and wait for flush to complete. */
259 /* We want to flush all GTIDs. */
260 uint64_t request_number = m_active_number.load();
261 /* If no GTIDs added to active, wait for previous index. */
262 if (m_num_gtid_mem.load() == 0) {
263 ut_a(request_number > 0);
264 --request_number;
265 }
266 m_flush_request_number = request_number;
268
269 if (compress) {
270 m_explicit_request.store(true);
271 }
272 return (request_number);
273 }
274
275 /** Check if flush has finished up to a list number.
276 @param[in] request_number flush request number
277 @return true, if it is already flushed. */
278 bool check_flushed(uint64_t request_number) const {
279 return (m_flush_number >= request_number);
280 }
281
282 /** @return true, iff background needs to flush immediately. */
283 bool flush_immediate() const {
285 }
286
287 /** Check if GTID compression is necessary based on threshold.
288 @return true, if GTID table needs to be compressed. */
289 bool check_compress();
290
291 /** Switch active GTID list. */
293 /* Switch active list under transaction system mutex. */
295 uint64_t flush_number = m_active_number;
298 m_num_gtid_mem.store(0);
299#ifdef UNIV_DEBUG
300 /* The new active list must have no elements. */
301 auto &active_list = get_active_list();
302 ut_ad(active_list.size() == 0);
303#endif
304 return (flush_number);
305 }
306
307 /** Persist GTID to gtid_executed table.
308 @param[in] flush_list_number list number to flush
309 @param[in,out] table_gtid_set GTIDs in table during recovery
310 @param[in,out] tsid_map TSID map for GTIDs
311 @return mysql error code. */
312 int write_to_table(uint64_t flush_list_number, Gtid_set &table_gtid_set,
313 Tsid_map &tsid_map);
314
315 /** Update transaction number up to which GTIDs are flushed to table.
316 @param[in] new_gtid_trx_no GTID transaction number */
317 void update_gtid_trx_no(trx_id_t new_gtid_trx_no);
318
319 /** Write all GTIDs to table and update GTID transaction number.
320 @param[in,out] thd current session thread */
321 void flush_gtids(THD *thd);
322
323 /** @return true iff number of GTIDs in active list exceeded threshold. */
325
326 private:
327 /** Time threshold to trigger persisting GTID. Insert GTID once per 1k
328 transactions or every 100 millisecond. */
329 static constexpr std::chrono::milliseconds s_time_threshold{100};
330
331 /** Threshold for the count for compressing GTID. */
332 const static uint32_t s_compression_threshold = 50;
333
334 /** Number of transaction/GTID threshold for writing to disk table. */
335 const static int s_gtid_threshold = 1024;
336
337 /** Maximum Number of transaction/GTID to hold. Transaction commits
338 must wait beyond this point. Not expected to happen as GTIDs are
339 compressed and written together. */
340 const static int s_max_gtid_threshold = 1024 * 1024;
341
342 /** Two lists of GTID. One of them is active where running transactions
343 add their GTIDs. Other list is used to persist them to table from time
344 to time. */
346
347 /** Number of the current GTID list. Increased when list is switched */
348 std::atomic<uint64_t> m_active_number;
349
350 /** Number up to which GTIDs are flushed. Increased when list is flushed.*/
351 std::atomic<uint64_t> m_flush_number;
352
353 /** If explicit request to flush is made. */
354 std::atomic<bool> m_explicit_request;
355
356 /** Number for which last flush request was made. */
358
359 /** Event for GTID background thread. */
361
362 /** Counter to keep track of the number of writes till it reaches
363 compression threshold. */
365
366 /** Counter to keep number of GTIDs flushed before compression. */
368
369 /* Oldest transaction number for which GTID is not persisted. */
370 std::atomic<uint64_t> m_gtid_trx_no;
371
372 /** Number of GTID accumulated in memory */
373 std::atomic<int> m_num_gtid_mem;
374
375 /** Flush of GTID is in progress. */
376 std::atomic<bool> m_flush_in_progress;
377
378 /** Set to true, when the background thread is asked to exit. */
379 std::atomic<bool> m_close_thread;
380
381 /** true, if background thread is active.*/
382 std::atomic<bool> m_thread_active;
383
384 /** true, if GTID persistence is active.*/
385 std::atomic<bool> m_active;
386};
387
388#endif /* CLONE_REPL_INCLUDE */
Persist GTID along with transaction commit.
Definition: clone0repl.h:70
std::atomic< bool > m_flush_in_progress
Flush of GTID is in progress.
Definition: clone0repl.h:376
trx_id_t get_oldest_trx_no()
Get oldest transaction number for which GTID is not persisted to table.
Definition: clone0repl.h:118
static const int s_max_gtid_threshold
Maximum Number of transaction/GTID to hold.
Definition: clone0repl.h:340
Clone_persist_gtid & operator=(Clone_persist_gtid const &)=delete
Disable assignment.
bool wait_thread(bool start, bool flush, uint64_t flush_number, bool compress, bool early_timeout, Clone_Alert_Func cbk)
Wait for gtid thread to start, finish or flush.
Definition: clone0repl.cc:650
bool start()
Start GTID persistence and background thread.
Definition: clone0repl.cc:718
void stop()
Definition: clone0repl.cc:737
bool has_gtid(trx_t *trx, THD *&thd, bool &passed_check)
Check if current transaction has GTID.
Definition: clone0repl.cc:279
trx_undo_t::Gtid_storage persists_gtid(const trx_t *trx)
Check if GTID persistence is set.
Definition: clone0repl.cc:86
static const int s_gtid_threshold
Number of transaction/GTID threshold for writing to disk table.
Definition: clone0repl.h:335
void set_persist_gtid(trx_t *trx, bool set)
Set or reset GTID persist flag in THD.
Definition: clone0repl.cc:107
std::atomic< bool > m_explicit_request
If explicit request to flush is made.
Definition: clone0repl.h:354
bool is_active() const
Definition: clone0repl.h:110
void update_gtid_trx_no(trx_id_t new_gtid_trx_no)
Update transaction number up to which GTIDs are flushed to table.
Definition: clone0repl.cc:483
static constexpr std::chrono::milliseconds s_time_threshold
Time threshold to trigger persisting GTID.
Definition: clone0repl.h:329
std::atomic< int > m_num_gtid_mem
Number of GTID accumulated in memory.
Definition: clone0repl.h:373
Gtid_info_list & get_active_list()
Definition: clone0repl.h:236
Gtid_info_list m_gtids[2]
Two lists of GTID.
Definition: clone0repl.h:345
bool check_gtid_rollback(THD *thd, trx_t *trx, bool found_gtid)
Check if GTID needs to persist at rollback.
Definition: clone0repl.cc:241
bool check_flushed(uint64_t request_number) const
Check if flush has finished up to a list number.
Definition: clone0repl.h:278
bool debug_skip_write(bool compression)
Check if we need to skip write or compression based on debug variables.
Definition: clone0repl.cc:407
void periodic_write()
Write GTIDs periodically to disk table.
Definition: clone0repl.cc:586
Clone_persist_gtid()
Constructor: start gtid thread.
Definition: clone0repl.h:73
std::atomic< uint64_t > m_active_number
Number of the current GTID list.
Definition: clone0repl.h:348
os_event_t m_event
Event for GTID background thread.
Definition: clone0repl.h:360
uint64_t m_flush_request_number
Number for which last flush request was made.
Definition: clone0repl.h:357
bool check_compress()
Check if GTID compression is necessary based on threshold.
Definition: clone0repl.cc:383
void set_oldest_trx_no_recovery(trx_id_t max_trx_no)
Set oldest transaction number for which GTID is not persisted to table.
Definition: clone0repl.h:141
uint32_t m_compression_counter
Counter to keep track of the number of writes till it reaches compression threshold.
Definition: clone0repl.h:364
static const uint32_t s_compression_threshold
Threshold for the count for compressing GTID.
Definition: clone0repl.h:332
void flush_gtids(THD *thd)
Write all GTIDs to table and update GTID transaction number.
Definition: clone0repl.cc:500
bool check_max_gtid_threshold()
Definition: clone0repl.cc:578
bool trx_check_set(trx_t *trx, bool prepare, bool rollback, bool &set_explicit)
Set transaction flag to persist GTID and check if space need to be allocated for GTID.
Definition: clone0repl.cc:161
bool check_gtid_prepare(THD *thd, trx_t *trx, bool found_gtid, bool &alloc)
Check if GTID needs to persist at XA prepare.
Definition: clone0repl.cc:190
std::atomic< bool > m_thread_active
true, if background thread is active.
Definition: clone0repl.h:382
std::atomic< uint64_t > m_gtid_trx_no
Definition: clone0repl.h:370
~Clone_persist_gtid()
Destructor: stop gtid thread.
Definition: clone0repl.h:90
Clone_persist_gtid(Clone_persist_gtid const &)=delete
Disable copy construction.
void add(const Gtid_desc &gtid_desc)
Add GTID to in memory list.
Definition: clone0repl.cc:44
std::atomic< bool > m_close_thread
Set to true, when the background thread is asked to exit.
Definition: clone0repl.h:379
uint64_t request_immediate_flush(bool compress)
Request immediate flush of all GTIDs accumulated.
Definition: clone0repl.h:257
uint64_t switch_active_list()
Switch active GTID list.
Definition: clone0repl.h:292
void get_gtid_info(trx_t *trx, Gtid_desc &gtid_desc)
Get transaction GTID information.
Definition: clone0repl.cc:335
int write_other_gtids()
Write GTIDs of non Innodb transactions to table.
Definition: clone0repl.cc:375
bool flush_immediate() const
Definition: clone0repl.h:283
std::atomic< bool > m_active
true, if GTID persistence is active.
Definition: clone0repl.h:385
Gtid_info_list & get_list(uint64_t list_number)
Definition: clone0repl.h:244
int write_to_table(uint64_t flush_list_number, Gtid_set &table_gtid_set, Tsid_map &tsid_map)
Persist GTID to gtid_executed table.
Definition: clone0repl.cc:418
std::atomic< uint64_t > m_flush_number
Number up to which GTIDs are flushed.
Definition: clone0repl.h:351
void wait_flush(bool compress_gtid, bool early_timeout, Clone_Alert_Func cbk)
Definition: clone0repl.cc:746
bool check_gtid_commit(THD *thd, bool found_gtid, bool &set_explicit)
Check if GTID needs to persist at commit.
Definition: clone0repl.cc:228
uint32_t m_compression_gtid_counter
Counter to keep number of GTIDs flushed before compression.
Definition: clone0repl.h:367
bool is_thread_active() const
Definition: clone0repl.h:113
Represents a set of GTIDs.
Definition: rpl_gtid.h:1555
For each client connection we create a separate thread with THD serving as a thread/connection descri...
Definition: sql_lexer_thd.h:35
Represents a bidirectional map between TSID and SIDNO.
Definition: rpl_gtid.h:748
Performance Schema stage instrumentation to monitor clone progress.
std::function< int()> Clone_Alert_Func
Function to alert caller for long wait.
Definition: clone0monitor.h:42
constexpr uint32_t GTID_VERSION
GTID format version.
Definition: clone0repl.h:49
std::vector< Gtid_desc > Gtid_info_list
List of GTIDs.
Definition: clone0repl.h:57
constexpr size_t GTID_INFO_SIZE
Serialized GTID information size.
Definition: clone0repl.h:46
std::array< unsigned char, GTID_INFO_SIZE > Gtid_info
Serialized GTID.
Definition: clone0repl.h:52
static int compress(PACK_MRG_INFO *file, char *join_name)
Definition: myisampack.cc:466
static mysql_service_status_t flush(reference_caching_cache cache) noexcept
Definition: component.cc:113
std::set< Key, Compare, ut::allocator< Key > > set
Specialization of set which uses ut_allocator.
Definition: ut0new.h:2881
os_event_t os_event_create()
Creates an event semaphore, i.e., a semaphore which may just have two states: signaled and nonsignale...
Definition: os0event.cc:527
void os_event_destroy(os_event_t &event)
Frees an event object.
Definition: os0event.cc:594
The interface to the threading wrapper.
static bool rollback(THD *thd)
Abort the current statement and transaction.
Definition: sql_cmd_srs.cc:139
The server main program.
@ SRV_FORCE_NO_UNDO_LOG_SCAN
do not look at undo logs when starting the database: InnoDB will treat even incomplete transactions a...
Definition: srv0srv.h:935
ulong srv_force_recovery
Normally 0.
Definition: srv0srv.cc:534
Starts the Innobase database server.
GTID descriptor with version information.
Definition: clone0repl.h:60
uint32_t m_version
Definition: clone0repl.h:66
bool m_is_set
If GTID descriptor is set.
Definition: clone0repl.h:62
Gtid_info m_info
Serialized GTID information.
Definition: clone0repl.h:64
InnoDB condition variable.
Definition: os0event.cc:62
Definition: trx0trx.h:683
Gtid_storage
Undo log may could be allocated to store transaction GTIDs.
Definition: trx0undo.h:340
Transaction system.
static void trx_sys_serialisation_mutex_exit()
Release the trx_sys->serialisation_mutex.
Definition: trx0sys.h:620
static void trx_sys_serialisation_mutex_enter()
Acquire the trx_sys->serialisation_mutex.
Definition: trx0sys.h:615
static bool trx_sys_serialisation_mutex_own()
Test if trx_sys->serialisation_mutex is owned.
Definition: trx0sys.h:609
constexpr trx_id_t TRX_ID_MAX
Maximum transaction identifier.
Definition: trx0types.h:144
ib_id_t trx_id_t
Transaction identifier (DB_TRX_ID, DATA_TRX_ID)
Definition: trx0types.h:137
#define ut_ad(EXPR)
Debug assertion.
Definition: ut0dbg.h:104
#define ut_a(EXPR)
Abort execution if EXPR does not evaluate to nonzero.
Definition: ut0dbg.h:92
static void prepare(pax_msg *p, pax_op op)
Definition: xcom_base.cc:1587