1 #ifndef BINLOG_H_INCLUDED
2 /* Copyright (c) 2010, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software Foundation,
22 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
23
24 #define BINLOG_H_INCLUDED
25
26 #include "sql_class.h"
27 #include "my_global.h"
28 #include "m_string.h" // llstr
29 #include "binlog_event.h" // enum_binlog_checksum_alg
30 #include "mysqld.h" // opt_relay_logname
31 #include "tc_log.h" // TC_LOG
32 #include "atomic_class.h"
33 #include "rpl_gtid.h" // Gtid_set, Sid_map
34 #include "rpl_trx_tracking.h"
35 #include "rpl_constants.h"
36 #include "binlog_crypt_data.h"
37
38
39 class Relay_log_info;
40 class Master_info;
41 class Slave_worker;
42 class Format_description_log_event;
43 class Transaction_boundary_parser;
44 class Rows_log_event;
45 class Rows_query_log_event;
46 class Incident_log_event;
47 class Log_event;
48 class Gtid_set;
49 struct Gtid;
50
51 typedef int64 query_id_t;
52
53
54 /**
55 Class for maintaining the commit stages for binary log group commit.
56 */
57 class Stage_manager {
58 public:
59 class Mutex_queue {
60 friend class Stage_manager;
61 public:
Mutex_queue()62 Mutex_queue()
63 : m_first(NULL), m_last(&m_first), m_size(0)
64 {
65 }
66
init(PSI_mutex_key key_LOCK_queue)67 void init(
68 #ifdef HAVE_PSI_INTERFACE
69 PSI_mutex_key key_LOCK_queue
70 #endif
71 ) {
72 mysql_mutex_init(key_LOCK_queue, &m_lock, MY_MUTEX_INIT_FAST);
73 }
74
deinit()75 void deinit() {
76 mysql_mutex_destroy(&m_lock);
77 }
78
is_empty()79 bool is_empty() const {
80 return m_first == NULL;
81 }
82
83 /**
84 Append a linked list of threads to the queue.
85 @retval true The queue was empty before this operation.
86 @retval false The queue was non-empty before this operation.
87 */
88 bool append(THD *first);
89
90 /**
91 Fetch the entire queue for a stage.
92
93 This will fetch the entire queue in one go.
94 */
95 THD *fetch_and_empty();
96
97 std::pair<bool,THD*> pop_front();
98
get_size()99 inline int32 get_size()
100 {
101 return my_atomic_load32(&m_size);
102 }
103
104 private:
lock()105 void lock() { mysql_mutex_lock(&m_lock); }
unlock()106 void unlock() { mysql_mutex_unlock(&m_lock); }
107
108 /**
109 Pointer to the first thread in the queue, or NULL if the queue is
110 empty.
111 */
112 THD *m_first;
113
114 /**
115 Pointer to the location holding the end of the queue.
116
117 This is either @c &first, or a pointer to the @c next_to_commit of
118 the last thread that is enqueued.
119 */
120 THD **m_last;
121
122 /** size of the queue */
123 int32 m_size;
124
125 /** Lock for protecting the queue. */
126 mysql_mutex_t m_lock;
127 /*
128 This attribute did not have the desired effect, at least not according
129 to -fsanitize=undefined with gcc 5.2.1
130 Also: it fails to compile with gcc 7.2
131 */
132 }; // MY_ATTRIBUTE((aligned(CPU_LEVEL1_DCACHE_LINESIZE)));
133
134 public:
Stage_manager()135 Stage_manager()
136 {
137 }
138
~Stage_manager()139 ~Stage_manager()
140 {
141 }
142
143 /**
144 Constants for queues for different stages.
145 */
146 enum StageID {
147 FLUSH_STAGE,
148 SYNC_STAGE,
149 COMMIT_STAGE,
150 STAGE_COUNTER
151 };
152
init(PSI_mutex_key key_LOCK_flush_queue,PSI_mutex_key key_LOCK_sync_queue,PSI_mutex_key key_LOCK_commit_queue,PSI_mutex_key key_LOCK_done,PSI_cond_key key_COND_done)153 void init(
154 #ifdef HAVE_PSI_INTERFACE
155 PSI_mutex_key key_LOCK_flush_queue,
156 PSI_mutex_key key_LOCK_sync_queue,
157 PSI_mutex_key key_LOCK_commit_queue,
158 PSI_mutex_key key_LOCK_done,
159 PSI_cond_key key_COND_done
160 #endif
161 )
162 {
163 mysql_mutex_init(key_LOCK_done, &m_lock_done, MY_MUTEX_INIT_FAST);
164 mysql_cond_init(key_COND_done, &m_cond_done);
165 #ifndef NDEBUG
166 /* reuse key_COND_done 'cos a new PSI object would be wasteful in !NDEBUG */
167 mysql_cond_init(key_COND_done, &m_cond_preempt);
168 #endif
169 m_queue[FLUSH_STAGE].init(
170 #ifdef HAVE_PSI_INTERFACE
171 key_LOCK_flush_queue
172 #endif
173 );
174 m_queue[SYNC_STAGE].init(
175 #ifdef HAVE_PSI_INTERFACE
176 key_LOCK_sync_queue
177 #endif
178 );
179 m_queue[COMMIT_STAGE].init(
180 #ifdef HAVE_PSI_INTERFACE
181 key_LOCK_commit_queue
182 #endif
183 );
184 }
185
deinit()186 void deinit()
187 {
188 for (size_t i = 0 ; i < STAGE_COUNTER ; ++i)
189 m_queue[i].deinit();
190 mysql_cond_destroy(&m_cond_done);
191 mysql_mutex_destroy(&m_lock_done);
192 }
193
194 /**
195 Enroll a set of sessions for a stage.
196
197 This will queue the session thread for writing and flushing.
198
199 If the thread being queued is assigned as stage leader, it will
200 return immediately.
201
202 If wait_if_follower is true the thread is not the stage leader,
203 the thread will be wait for the queue to be processed by the
204 leader before it returns.
205 In DBUG-ON version the follower marks is preempt status as ready.
206
207 @param stage Stage identifier for the queue to append to.
208 @param first Queue to append.
209 @param stage_mutex
210 Pointer to the currently held stage mutex, or NULL if
211 we're not in a stage.
212
213 @retval true Thread is stage leader.
214 @retval false Thread was not stage leader and processing has been done.
215 */
216 bool enroll_for(StageID stage, THD *first, mysql_mutex_t *stage_mutex);
217
pop_front(StageID stage)218 std::pair<bool,THD*> pop_front(StageID stage)
219 {
220 return m_queue[stage].pop_front();
221 }
222
223 #ifndef NDEBUG
224 /**
225 The method ensures the follower's execution path can be preempted
226 by the leader's thread.
227 Preempt status of @c head follower is checked to engange the leader
228 into waiting when set.
229
230 @param head THD* of a follower thread
231 */
232 void clear_preempt_status(THD *head);
233 #endif
234
235 /**
236 Fetch the entire queue and empty it.
237
238 @return Pointer to the first session of the queue.
239 */
fetch_queue_for(StageID stage)240 THD *fetch_queue_for(StageID stage) {
241 DBUG_PRINT("debug", ("Fetching queue for stage %d", stage));
242 return m_queue[stage].fetch_and_empty();
243 }
244
245 /**
246 Introduces a wait operation on the executing thread. The
247 waiting is done until the timeout elapses or count is
248 reached (whichever comes first).
249
250 If count == 0, then the session will wait until the timeout
251 elapses. If timeout == 0, then there is no waiting.
252
253 @param usec the number of microseconds to wait.
254 @param count wait for as many as count to join the queue the
255 session is waiting on
256 @param stage which stage queue size to compare count against.
257 */
258 void wait_count_or_timeout(ulong count, long usec, StageID stage);
259
260 void signal_done(THD *queue);
261
262 private:
263 /**
264 Queues for sessions.
265
266 We need two queues:
267 - Waiting. Threads waiting to be processed
268 - Committing. Threads waiting to be committed.
269 */
270 Mutex_queue m_queue[STAGE_COUNTER];
271
272 /** Condition variable to indicate that the commit was processed */
273 mysql_cond_t m_cond_done;
274
275 /** Mutex used for the condition variable above */
276 mysql_mutex_t m_lock_done;
277 #ifndef NDEBUG
278 /** Flag is set by Leader when it starts waiting for follower's all-clear */
279 bool leader_await_preempt_status;
280
281 /** Condition variable to indicate a follower started waiting for commit */
282 mysql_cond_t m_cond_preempt;
283 #endif
284 };
285
286 /* log info errors */
287 #define LOG_INFO_EOF -1
288 #define LOG_INFO_IO -2
289 #define LOG_INFO_INVALID -3
290 #define LOG_INFO_SEEK -4
291 #define LOG_INFO_MEM -6
292 #define LOG_INFO_FATAL -7
293 #define LOG_INFO_IN_USE -8
294 #define LOG_INFO_EMFILE -9
295
296 /* bitmap to MYSQL_BIN_LOG::close() */
297 #define LOG_CLOSE_INDEX 1
298 #define LOG_CLOSE_TO_BE_OPENED 2
299 #define LOG_CLOSE_STOP_EVENT 4
300
301
302 /*
303 Note that we destroy the lock mutex in the destructor here.
304 This means that object instances cannot be destroyed/go out of scope
305 until we have reset thd->current_linfo to NULL;
306 */
307 typedef struct st_log_info
308 {
309 char log_file_name[FN_REFLEN];
310 my_off_t index_file_offset, index_file_start_offset;
311 my_off_t pos;
312 bool fatal; // if the purge happens to give us a negative offset
313 int entry_index; //used in purge_logs(), calculatd in find_log_pos().
st_log_infost_log_info314 st_log_info()
315 : index_file_offset(0), index_file_start_offset(0),
316 pos(0), fatal(0), entry_index(0)
317 {
318 memset(log_file_name, 0, FN_REFLEN);
319 }
320 } LOG_INFO;
321
322 /*
323 TODO use mmap instead of IO_CACHE for binlog
324 (mmap+fsync is two times faster than write+fsync)
325 */
326
327 class MYSQL_BIN_LOG: public TC_LOG
328 {
329 enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED };
330
331 /* LOCK_log is inited by init_pthread_objects() */
332 mysql_mutex_t LOCK_log;
333 char *name;
334 char log_file_name[FN_REFLEN];
335 char db[NAME_LEN + 1];
336 bool write_error, inited;
337 IO_CACHE log_file;
338 const enum cache_type io_cache_type;
339 #ifdef HAVE_PSI_INTERFACE
340 /** Instrumentation key to use for file io in @c log_file */
341 PSI_file_key m_log_file_key;
342 /** The instrumentation key to use for @ LOCK_log. */
343 PSI_mutex_key m_key_LOCK_log;
344 /** The instrumentation key to use for @ LOCK_index. */
345 PSI_mutex_key m_key_LOCK_index;
346 /** The instrumentation key to use for @ LOCK_binlog_end_pos. */
347 PSI_mutex_key m_key_LOCK_binlog_end_pos;
348
349 PSI_mutex_key m_key_COND_done;
350
351 PSI_mutex_key m_key_LOCK_commit_queue;
352 PSI_mutex_key m_key_LOCK_done;
353 PSI_mutex_key m_key_LOCK_flush_queue;
354 PSI_mutex_key m_key_LOCK_sync_queue;
355 /** The instrumentation key to use for @ LOCK_commit. */
356 PSI_mutex_key m_key_LOCK_commit;
357 /** The instrumentation key to use for @ LOCK_sync. */
358 PSI_mutex_key m_key_LOCK_sync;
359 /** The instrumentation key to use for @ LOCK_xids. */
360 PSI_mutex_key m_key_LOCK_xids;
361 /** The instrumentation key to use for @ update_cond. */
362 PSI_cond_key m_key_update_cond;
363 /** The instrumentation key to use for @ prep_xids_cond. */
364 PSI_cond_key m_key_prep_xids_cond;
365 /** The instrumentation key to use for opening the log file. */
366 PSI_file_key m_key_file_log;
367 /** The instrumentation key to use for opening the log index file. */
368 PSI_file_key m_key_file_log_index;
369 /** The instrumentation key to use for opening a log cache file. */
370 PSI_file_key m_key_file_log_cache;
371 /** The instrumentation key to use for opening a log index cache file. */
372 PSI_file_key m_key_file_log_index_cache;
373 #endif
374 /* POSIX thread objects are inited by init_pthread_objects() */
375 mysql_mutex_t LOCK_index;
376 mysql_mutex_t LOCK_commit;
377 mysql_mutex_t LOCK_sync;
378 mysql_mutex_t LOCK_binlog_end_pos;
379 mysql_mutex_t LOCK_xids;
380 mysql_cond_t update_cond;
381
382 my_off_t binlog_end_pos;
383 ulonglong bytes_written;
384 ulonglong binlog_space_total;
385 IO_CACHE index_file;
386 char index_file_name[FN_REFLEN];
387 /*
388 crash_safe_index_file is temp file used for guaranteeing
389 index file crash safe when master server restarts.
390 */
391 IO_CACHE crash_safe_index_file;
392 char crash_safe_index_file_name[FN_REFLEN];
393 /*
394 purge_file is a temp file used in purge_logs so that the index file
395 can be updated before deleting files from disk, yielding better crash
396 recovery. It is created on demand the first time purge_logs is called
397 and then reused for subsequent calls. It is cleaned up in cleanup().
398 */
399 IO_CACHE purge_index_file;
400 char purge_index_file_name[FN_REFLEN];
401 /*
402 The max size before rotation (usable only if log_type == LOG_BIN: binary
403 logs and relay logs).
404 For a binlog, max_size should be max_binlog_size.
405 For a relay log, it should be max_relay_log_size if this is non-zero,
406 max_binlog_size otherwise.
407 max_size is set in init(), and dynamically changed (when one does SET
408 GLOBAL MAX_BINLOG_SIZE|MAX_RELAY_LOG_SIZE) by fix_max_binlog_size and
409 fix_max_relay_log_size).
410 */
411 ulong max_size;
412
413 // current file sequence number for load data infile binary logging
414 uint file_id;
415 uint open_count; // For replication
416 int readers_count;
417
418 /* binlog encryption data */
419 Binlog_crypt_data crypto;
420
421 /* pointer to the sync period variable, for binlog this will be
422 sync_binlog_period, for relay log this will be
423 sync_relay_log_period
424 */
425 uint *sync_period_ptr;
426 uint sync_counter;
427
428 mysql_cond_t m_prep_xids_cond;
429 Atomic_int32 m_prep_xids;
430
431 /**
432 Increment the prepared XID counter.
433 */
434 void inc_prep_xids(THD *thd);
435
436 /**
437 Decrement the prepared XID counter.
438
439 Signal m_prep_xids_cond if the counter reaches zero.
440 */
441 void dec_prep_xids(THD *thd);
442
get_prep_xids()443 int32 get_prep_xids() {
444 int32 result= m_prep_xids.atomic_get();
445 return result;
446 }
447
get_sync_period()448 inline uint get_sync_period()
449 {
450 return *sync_period_ptr;
451 }
452
453 int write_to_file(Log_event* event);
454
455 int write_to_file(IO_CACHE *cache);
456 /*
457 This is used to start writing to a new log file. The difference from
458 new_file() is locking. new_file_without_locking() does not acquire
459 LOCK_log.
460 */
461 int new_file_without_locking(Format_description_log_event *extra_description_event);
462 int new_file_impl(bool need_lock, Format_description_log_event *extra_description_event);
463
464 /** Manage the stages in ordered_commit. */
465 Stage_manager stage_manager;
466 void do_flush(THD *thd);
467
468 bool open(
469 #ifdef HAVE_PSI_INTERFACE
470 PSI_file_key log_file_key,
471 #endif
472 const char *log_name,
473 const char *new_name);
474 bool init_and_set_log_file_name(const char *log_name,
475 const char *new_name);
476 int generate_new_name(char *new_name, const char *log_name);
477
478 public:
479 const char *generate_name(const char *log_name, const char *suffix,
480 char *buff);
is_open()481 bool is_open() { return log_state.atomic_get() != LOG_CLOSED; }
482
483 /* This is relay log */
484 bool is_relay_log;
485 ulong signal_cnt; // update of the counter is checked by heartbeat
486 uint8 checksum_alg_reset; // to contain a new value when binlog is rotated
487 /*
488 Holds the last seen in Relay-Log FD's checksum alg value.
489 The initial value comes from the slave's local FD that heads
490 the very first Relay-Log file. In the following the value may change
491 with each received master's FD_m.
492 Besides to be used in verification events that IO thread receives
493 (except the 1st fake Rotate, see @c Master_info:: checksum_alg_before_fd),
494 the value specifies if/how to compute checksum for slave's local events
495 and the first fake Rotate (R_f^1) coming from the master.
496 R_f^1 needs logging checksum-compatibly with the RL's heading FD_s.
497
498 Legends for the checksum related comments:
499
500 FD - Format-Description event,
501 R - Rotate event
502 R_f - the fake Rotate event
503 E - an arbirary event
504
505 The underscore indexes for any event
506 `_s' indicates the event is generated by Slave
507 `_m' - by Master
508
509 Two special underscore indexes of FD:
510 FD_q - Format Description event for queuing (relay-logging)
511 FD_e - Format Description event for executing (relay-logging)
512
513 Upper indexes:
514 E^n - n:th event is a sequence
515
516 RL - Relay Log
517 (A) - checksum algorithm descriptor value
518 FD.(A) - the value of (A) in FD
519 */
520 binary_log::enum_binlog_checksum_alg relay_log_checksum_alg;
521
522 MYSQL_BIN_LOG(uint *sync_period,
523 enum cache_type io_cache_type_arg);
524 /*
525 note that there's no destructor ~MYSQL_BIN_LOG() !
526 The reason is that we don't want it to be automatically called
527 on exit() - but only during the correct shutdown process
528 */
529
530 #ifdef HAVE_PSI_INTERFACE
set_psi_keys(PSI_mutex_key key_LOCK_index,PSI_mutex_key key_LOCK_commit,PSI_mutex_key key_LOCK_commit_queue,PSI_mutex_key key_LOCK_done,PSI_mutex_key key_LOCK_flush_queue,PSI_mutex_key key_LOCK_log,PSI_mutex_key key_LOCK_binlog_end_pos,PSI_mutex_key key_LOCK_sync,PSI_mutex_key key_LOCK_sync_queue,PSI_mutex_key key_LOCK_xids,PSI_cond_key key_COND_done,PSI_cond_key key_update_cond,PSI_cond_key key_prep_xids_cond,PSI_file_key key_file_log,PSI_file_key key_file_log_index,PSI_file_key key_file_log_cache,PSI_file_key key_file_log_index_cache)531 void set_psi_keys(PSI_mutex_key key_LOCK_index,
532 PSI_mutex_key key_LOCK_commit,
533 PSI_mutex_key key_LOCK_commit_queue,
534 PSI_mutex_key key_LOCK_done,
535 PSI_mutex_key key_LOCK_flush_queue,
536 PSI_mutex_key key_LOCK_log,
537 PSI_mutex_key key_LOCK_binlog_end_pos,
538 PSI_mutex_key key_LOCK_sync,
539 PSI_mutex_key key_LOCK_sync_queue,
540 PSI_mutex_key key_LOCK_xids,
541 PSI_cond_key key_COND_done,
542 PSI_cond_key key_update_cond,
543 PSI_cond_key key_prep_xids_cond,
544 PSI_file_key key_file_log,
545 PSI_file_key key_file_log_index,
546 PSI_file_key key_file_log_cache,
547 PSI_file_key key_file_log_index_cache)
548 {
549 m_key_COND_done= key_COND_done;
550
551 m_key_LOCK_commit_queue= key_LOCK_commit_queue;
552 m_key_LOCK_done= key_LOCK_done;
553 m_key_LOCK_flush_queue= key_LOCK_flush_queue;
554 m_key_LOCK_sync_queue= key_LOCK_sync_queue;
555
556 m_key_LOCK_index= key_LOCK_index;
557 m_key_LOCK_log= key_LOCK_log;
558 m_key_LOCK_binlog_end_pos= key_LOCK_binlog_end_pos;
559 m_key_LOCK_commit= key_LOCK_commit;
560 m_key_LOCK_sync= key_LOCK_sync;
561 m_key_LOCK_xids= key_LOCK_xids;
562 m_key_update_cond= key_update_cond;
563 m_key_prep_xids_cond= key_prep_xids_cond;
564 m_key_file_log= key_file_log;
565 m_key_file_log_index= key_file_log_index;
566 m_key_file_log_cache= key_file_log_cache;
567 m_key_file_log_index_cache= key_file_log_index_cache;
568 }
569 #endif
570
571 public:
572 /** Manage the MTS dependency tracking */
573 Transaction_dependency_tracker m_dependency_tracker;
574
575 /**
576 Find the oldest binary log that contains any GTID that
577 is not in the given gtid set.
578
579 @param[out] binlog_file_name, the file name of oldest binary log found
580 @param[in] gtid_set, the given gtid set
581 @param[out] first_gtid, the first GTID information from the binary log
582 file returned at binlog_file_name
583 @param[out] errmsg, the error message outputted, which is left untouched
584 if the function returns false
585 @return false on success, true on error.
586 */
587 bool find_first_log_not_in_gtid_set(char *binlog_file_name,
588 const Gtid_set *gtid_set,
589 Gtid *first_gtid, std::string &errmsg);
590
591 /**
592 Reads the set of all GTIDs in the binary/relay log, and the set
593 of all lost GTIDs in the binary log, and stores each set in
594 respective argument.
595
596 @param gtid_set Will be filled with all GTIDs in this binary/relay
597 log.
598 @param lost_groups Will be filled with all GTIDs in the
599 Previous_gtids_log_event of the first binary log that has a
600 Previous_gtids_log_event. This is requested to binary logs but not
601 to relay logs.
602 @param verify_checksum If true, checksums will be checked.
603 @param need_lock If true, LOCK_log, LOCK_index, and
604 global_sid_lock->wrlock are acquired; otherwise they are asserted
605 to be taken already.
606 @param trx_parser [out] This will be used to return the actual
607 relaylog transaction parser state because of the possibility
608 of partial transactions.
609 @param [out] gtid_partial_trx If a transaction was left incomplete
610 on the relaylog, it's GTID should be returned to be used in the
611 case of the rest of the transaction be added to the relaylog.
612 @param is_server_starting True if the server is starting.
613 @return false on success, true on error.
614 */
615 bool init_gtid_sets(Gtid_set *gtid_set, Gtid_set *lost_groups,
616 bool verify_checksum,
617 bool need_lock,
618 Transaction_boundary_parser *trx_parser,
619 Gtid *gtid_partial_trx,
620 bool is_server_starting= false);
621
set_previous_gtid_set_relaylog(Gtid_set * previous_gtid_set_param)622 void set_previous_gtid_set_relaylog(Gtid_set *previous_gtid_set_param)
623 {
624 assert(is_relay_log);
625 previous_gtid_set_relaylog= previous_gtid_set_param;
626 }
627 /**
628 If the thread owns a GTID, this function generates an empty
629 transaction and releases ownership of the GTID.
630
631 - If the binary log is disabled for this thread, the GTID is
632 inserted directly into the mysql.gtid_executed table and the
633 GTID is included in @@global.gtid_executed. (This only happens
634 for DDL, since DML will save the GTID into table and release
635 ownership inside ha_commit_trans.)
636
637 - If the binary log is enabled for this thread, an empty
638 transaction consisting of GTID, BEGIN, COMMIT is written to the
639 binary log, the GTID is included in @@global.gtid_executed, and
640 the GTID is added to the mysql.gtid_executed table on the next
641 binlog rotation.
642
643 This function must be called by any committing statement (COMMIT,
644 implicitly committing statements, or Xid_log_event), after the
645 statement has completed execution, regardless of whether the
646 statement updated the database.
647
648 This logic ensures that an empty transaction is generated for the
649 following cases:
650
651 - Explicit empty transaction:
652 SET GTID_NEXT = 'UUID:NUMBER'; BEGIN; COMMIT;
653
654 - Transaction or DDL that gets completely filtered out in the
655 slave thread.
656
657 @param thd The committing thread
658
659 @retval 0 Success
660 @retval nonzero Error
661 */
662 int gtid_end_transaction(THD *thd);
663 private:
664 Atomic_int32 log_state; /* atomic enum_log_state */
665
666 /* The previous gtid set in relay log. */
667 Gtid_set* previous_gtid_set_relaylog;
668
669 bool snapshot_lock_acquired;
670
open(const char * opt_name)671 int open(const char *opt_name) { return open_binlog(opt_name); }
672 bool change_stage(THD *thd, Stage_manager::StageID stage,
673 THD* queue, mysql_mutex_t *leave,
674 mysql_mutex_t *enter);
675 std::pair<int,my_off_t> flush_thread_caches(THD *thd);
676 int flush_cache_to_file(my_off_t *flush_end_pos);
677 int finish_commit(THD *thd);
678 std::pair<bool, bool> sync_binlog_file(bool force);
679 void process_commit_stage_queue(THD *thd, THD *queue);
680 void process_after_commit_stage_queue(THD *thd, THD *first);
681 int process_flush_stage_queue(my_off_t *total_bytes_var, bool *rotate_var,
682 THD **out_queue_var);
683 int prepare_ordered_commit(THD *thd, bool all, bool skip_commit= false);
684 int ordered_commit(THD *thd);
685 void handle_binlog_flush_or_sync_error(THD *thd, bool need_lock_log,
686 const char *message);
687 public:
688 int open_binlog(const char *opt_name);
689 void close();
690 enum_result commit(THD *thd, bool all);
691 int rollback(THD *thd, bool all);
692 int prepare(THD *thd, bool all);
693 int recover(IO_CACHE *log, Format_description_log_event *fdle,
694 my_off_t *valid_pos);
695 int recover(IO_CACHE *log, Format_description_log_event *fdle);
696 #if !defined(MYSQL_CLIENT)
697
698 void update_thd_next_event_pos(THD *thd);
699 int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event,
700 bool is_transactional);
701 void xlock(void);
702 void xunlock(void);
slock(void)703 void slock(void) { mysql_rwlock_rdlock(&LOCK_consistent_snapshot); }
sunlock(void)704 void sunlock(void) { mysql_rwlock_unlock(&LOCK_consistent_snapshot); }
705 #else
xlock(void)706 void xlock(void) { }
xunlock(void)707 void xunlock(void) { }
slock(void)708 void slock(void) { }
sunlock(void)709 void sunlock(void) { }
710 #endif /* !defined(MYSQL_CLIENT) */
add_bytes_written(ulonglong inc)711 void add_bytes_written(ulonglong inc)
712 {
713 bytes_written += inc;
714 }
reset_bytes_written()715 void reset_bytes_written()
716 {
717 bytes_written = 0;
718 }
719 void harvest_bytes_written(Relay_log_info *rli, bool need_log_space_lock);
720 void set_max_size(ulong max_size_arg);
signal_update()721 void signal_update()
722 {
723 DBUG_ENTER("MYSQL_BIN_LOG::signal_update");
724 signal_cnt++;
725 mysql_cond_broadcast(&update_cond);
726 DBUG_VOID_RETURN;
727 }
728
update_binlog_end_pos()729 void update_binlog_end_pos()
730 {
731 /*
732 binlog_end_pos is used only on master's binlog right now. It is possible
733 to use it on relay log.
734 */
735 if (is_relay_log)
736 signal_update();
737 else
738 {
739 lock_binlog_end_pos();
740 binlog_end_pos= my_b_tell(&log_file);
741 signal_update();
742 unlock_binlog_end_pos();
743 }
744 }
745
update_binlog_end_pos(const char * file,my_off_t pos)746 void update_binlog_end_pos(const char *file, my_off_t pos)
747 {
748 lock_binlog_end_pos();
749 if (is_active(file) && pos > binlog_end_pos)
750 binlog_end_pos= pos;
751 signal_update();
752 unlock_binlog_end_pos();
753 }
754
755 int wait_for_update_relay_log(THD* thd, const struct timespec * timeout);
756 int wait_for_update_bin_log(THD* thd, const struct timespec * timeout);
757 bool do_write_cache(IO_CACHE *cache, class Binlog_event_writer *writer);
758 public:
759 void init_pthread_objects();
760 void cleanup();
761 /**
762 Create a new binary log.
763 @param log_name Name of binlog
764 @param new_name Name of binlog, too. todo: what's the difference
765 between new_name and log_name?
766 @param max_size The size at which this binlog will be rotated.
767 @param null_created If false, and a Format_description_log_event
768 is written, then the Format_description_log_event will have the
769 timestamp 0. Otherwise, it the timestamp will be the time when the
770 event was written to the log.
771 @param need_lock_index If true, LOCK_index is acquired; otherwise
772 LOCK_index must be taken by the caller.
773 @param need_sid_lock If true, the read lock on global_sid_lock
774 will be acquired. Otherwise, the caller must hold the read lock
775 on global_sid_lock.
776 */
777 bool open_binlog(const char *log_name,
778 const char *new_name,
779 ulong max_size,
780 bool null_created,
781 bool need_lock_index, bool need_sid_lock,
782 Format_description_log_event *extra_description_event);
783 bool open_index_file(const char *index_file_name_arg,
784 const char *log_name, bool need_lock_index);
785 /* Use this to start writing a new log file */
786 int new_file(Format_description_log_event *extra_description_event);
787
788 bool write_event(Log_event* event_info);
789 bool write_cache(THD *thd, class binlog_cache_data *binlog_cache_data,
790 class Binlog_event_writer *writer);
791 /**
792 Assign automatic generated GTIDs for all commit group threads in the flush
793 stage having gtid_next.type == AUTOMATIC_GROUP.
794
795 @param first_seen The first thread seen entering the flush stage.
796 @return Returns false if succeeds, otherwise true is returned.
797 */
798 bool assign_automatic_gtids_to_flush_group(THD *first_seen);
799 bool write_gtid(THD *thd, binlog_cache_data *cache_data,
800 class Binlog_event_writer *writer);
801
802 /**
803 Write a dml into statement cache and then flush it into binlog. It writes
804 Gtid_log_event and BEGIN, COMMIT automatically.
805
806 It is aimed to handle cases of "background" logging where a statement is
807 logged indirectly, like "TRUNCATE TABLE a_memory_table". So don't use it on any
808 normal statement.
809
810 @param[IN] thd the THD object of current thread.
811 @param[IN] stmt the DML statement.
812 @param[IN] stmt_len the length of the DML statement.
813 @param[IN] sql_command the type of SQL command.
814
815 @return Returns false if succeeds, otherwise true is returned.
816 */
817 bool write_stmt_directly(THD* thd, const char *stmt, size_t stmt_len,
818 enum enum_sql_command sql_command);
819
820 void set_write_error(THD *thd, bool is_transactional);
821 bool check_write_error(THD *thd);
822 bool write_incident(THD *thd, bool need_lock_log,
823 const char* err_msg,
824 bool do_flush_and_sync= true);
825 bool write_incident(Incident_log_event *ev, THD *thd,
826 bool need_lock_log,
827 const char* err_msg,
828 bool do_flush_and_sync= true);
829
830 void start_union_events(THD *thd, query_id_t query_id_param);
831 void stop_union_events(THD *thd);
832 bool is_query_in_union(THD *thd, query_id_t query_id_param);
833
834 #ifdef HAVE_REPLICATION
835 bool append_buffer(uchar* buf, size_t len, Master_info *mi);
836 bool append_event(Log_event* ev, Master_info *mi);
837 private:
838 bool after_append_to_relay_log(Master_info *mi);
839 #endif // ifdef HAVE_REPLICATION
840 public:
841
842 void make_log_name(char* buf, const char* log_ident);
843 bool is_active(const char* log_file_name);
844 int remove_logs_from_index(LOG_INFO* linfo, bool need_update_threads);
845 int rotate(bool force_rotate, bool* check_purge);
846 void purge();
847 int rotate_and_purge(THD* thd, bool force_rotate);
848 /**
849 Flush binlog cache and synchronize to disk.
850
851 This function flushes events in binlog cache to binary log file,
852 it will do synchronizing according to the setting of system
853 variable 'sync_binlog'. If file is synchronized, @c synced will
854 be set to 1, otherwise 0.
855
856 @param[out] synced if not NULL, set to 1 if file is synchronized, otherwise 0
857 @param[in] force if TRUE, ignores the 'sync_binlog' and synchronizes the file.
858
859 @retval 0 Success
860 @retval other Failure
861 */
862 bool flush_and_sync(const bool force= false);
863 int purge_logs(const char *to_log, bool included,
864 bool need_lock_index, bool need_update_threads,
865 ulonglong *decrease_log_space, bool auto_purge);
866 int count_binlog_space(bool need_lock_index);
867 int purge_logs_by_size(bool need_lock_index);
868 int purge_logs_maximum_number(ulong max_nr_files);
869 int purge_logs_before_date(time_t purge_time, bool auto_purge);
870 int purge_first_log(Relay_log_info* rli, bool included);
871 int set_crash_safe_index_file_name(const char *base_file_name);
872 int open_crash_safe_index_file();
873 int close_crash_safe_index_file();
874 int add_log_to_index(uchar* log_file_name, size_t name_len,
875 bool need_lock_index);
876 int move_crash_safe_index_file_to_index_file(bool need_lock_index);
877 int set_purge_index_file_name(const char *base_file_name);
878 int open_purge_index_file(bool destroy);
879 bool is_inited_purge_index_file();
880 int close_purge_index_file();
881 int clean_purge_index_file();
882 int sync_purge_index_file();
883 int register_purge_index_entry(const char* entry);
884 int register_create_index_entry(const char* entry);
885 int purge_index_entry(THD *thd, ulonglong *decrease_log_space,
886 bool need_lock_index);
887 bool reset_logs(THD* thd, bool delete_only= false);
888 void close(uint exiting, bool need_lock_log, bool need_lock_index);
889
890 // iterating through the log index file
891 int find_log_pos(LOG_INFO* linfo, const char* log_name,
892 bool need_lock_index);
893 int find_next_log(LOG_INFO* linfo, bool need_lock_index);
894 int find_next_relay_log(char log_name[FN_REFLEN+1]);
895 int get_current_log(LOG_INFO* linfo, bool need_lock_log= true);
896 int raw_get_current_log(LOG_INFO* linfo);
897 uint next_file_id();
get_index_fname()898 inline char* get_index_fname() { return index_file_name;}
get_log_fname()899 inline char* get_log_fname() { return log_file_name; }
get_name()900 inline char* get_name() { return name; }
get_log_lock()901 inline mysql_mutex_t* get_log_lock() { return &LOCK_log; }
get_log_cond()902 inline mysql_cond_t* get_log_cond() { return &update_cond; }
get_log_file()903 inline IO_CACHE* get_log_file() { return &log_file; }
904
lock_index()905 inline void lock_index() { mysql_mutex_lock(&LOCK_index);}
unlock_index()906 inline void unlock_index() { mysql_mutex_unlock(&LOCK_index);}
get_index_file()907 inline IO_CACHE *get_index_file() { return &index_file;}
get_open_count()908 inline uint32 get_open_count() { return open_count; }
909
910 /**
911 Function to report the missing GTIDs.
912
913 This function logs the missing transactions on master to its error log
914 as a warning. If the missing GTIDs are too long to print in a message,
915 it suggests the steps to extract the missing transactions.
916
917 This function also informs slave about the GTID set sent by the slave,
918 transactions missing on the master and few suggestions to recover from
919 the error. This message shall be wrapped by
920 ER_MASTER_FATAL_ERROR_READING_BINLOG on slave and will be logged as an
921 error.
922
923 This function will be called from mysql_binlog_send() function.
924
925 @param slave_executed_gtid_set GTID set executed by slave
926 @param errmsg Pointer to the error message
927
928 @return void
929 */
930 void report_missing_purged_gtids(const Gtid_set *slave_executed_gtid_set,
931 std::string &errmsg);
932
933 /**
934 Function to report the missing GTIDs.
935
936 This function logs the missing transactions on master to its error log
937 as a warning. If the missing GTIDs are too long to print in a message,
938 it suggests the steps to extract the missing transactions.
939
940 This function also informs slave about the GTID set sent by the slave,
941 transactions missing on the master and few suggestions to recover from
942 the error. This message shall be wrapped by
943 ER_MASTER_FATAL_ERROR_READING_BINLOG on slave and will be logged as an
944 error.
945
946 This function will be called from find_first_log_not_in_gtid_set()
947 function.
948
949 @param previous_gtid_set Previous GTID set found
950 @param slave_executed_gtid_set GTID set executed by slave
951 @param errmsg Pointer to the error message
952
953 @return void
954 */
955 void report_missing_gtids(const Gtid_set *previous_gtid_set,
956 const Gtid_set *slave_executed_gtid_set,
957 std::string &errmsg);
958 static const int MAX_RETRIES_FOR_DELETE_RENAME_FAILURE= 5;
959 /*
960 It is called by the threads(e.g. dump thread) which want to read
961 hot log without LOCK_log protection.
962 */
get_binlog_end_pos()963 my_off_t get_binlog_end_pos() const
964 {
965 mysql_mutex_assert_not_owner(&LOCK_log);
966 mysql_mutex_assert_owner(&LOCK_binlog_end_pos);
967 return binlog_end_pos;
968 }
get_binlog_end_pos_lock()969 mysql_mutex_t* get_binlog_end_pos_lock() { return &LOCK_binlog_end_pos; }
lock_binlog_end_pos()970 void lock_binlog_end_pos() { mysql_mutex_lock(&LOCK_binlog_end_pos); }
unlock_binlog_end_pos()971 void unlock_binlog_end_pos() { mysql_mutex_unlock(&LOCK_binlog_end_pos); }
972
973 /**
974 Deep copy global_sid_map to @param sid_map and
975 gtid_state->get_executed_gtids() to @param gtid_set
976 Both operations are done under LOCK_commit and global_sid_lock
977 protection.
978
979 @param[out] sid_map The Sid_map to which global_sid_map will
980 be copied.
981 @param[out] gtid_set The Gtid_set to which gtid_executed will
982 be copied.
983
984 @return the operation status
985 @retval 0 OK
986 @retval !=0 Error
987 */
988 int get_gtid_executed(Sid_map *sid_map, Gtid_set *gtid_set);
989
990 /*
991 True while rotating binlog, which is caused by logging Incident_log_event.
992 */
993 bool is_rotating_caused_by_incident;
994
get_crypto_data()995 Binlog_crypt_data* get_crypto_data()
996 {
997 return &crypto;
998 }
999 private:
1000 void publish_coordinates_for_global_status(void) const;
1001 };
1002
1003 typedef struct st_load_file_info
1004 {
1005 THD* thd;
1006 my_off_t last_pos_in_file;
1007 bool wrote_create_file, log_delayed;
1008 } LOAD_FILE_INFO;
1009
1010 extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log;
1011
1012 /**
1013 Check if the the transaction is empty.
1014
1015 @param thd The client thread that executed the current statement.
1016
1017 @retval true No changes found in any storage engine
1018 @retval false Otherwise.
1019
1020 **/
1021 bool is_transaction_empty(THD* thd);
1022 /**
1023 Check if the transaction has no rw flag set for any of the storage engines.
1024
1025 @param thd The client thread that executed the current statement.
1026 @param trx_scope The transaction scope to look into.
1027
1028 @retval the number of engines which have actual changes.
1029 */
1030 int check_trx_rw_engines(THD *thd, Transaction_ctx::enum_trx_scope trx_scope);
1031
1032 /**
1033 Check if at least one of transacaction and statement binlog caches contains
1034 an empty transaction, other one is empty or contains an empty transaction,
1035 which has two binlog events "BEGIN" and "COMMIT".
1036
1037 @param thd The client thread that executed the current statement.
1038
1039 @retval true At least one of transacaction and statement binlog caches
1040 contains an empty transaction, other one is empty or
1041 contains an empty transaction.
1042 @retval false Otherwise.
1043 */
1044 bool is_empty_transaction_in_binlog_cache(const THD* thd);
1045 bool trans_has_updated_trans_table(const THD* thd);
1046 bool stmt_has_updated_trans_table(Ha_trx_info* ha_list);
1047 /**
1048 This function checks if the transaction has no operation dml.
1049
1050 @param ha_list Registered storage engine handler list.
1051 @return true if the transaction has no operation dml.
1052 false otherwise.
1053 */
1054 bool trans_has_noop_dml(Ha_trx_info* ha_list);
1055 bool ending_trans(THD* thd, const bool all);
1056 bool ending_single_stmt_trans(THD* thd, const bool all);
1057 bool trans_cannot_safely_rollback(const THD* thd);
1058 bool stmt_cannot_safely_rollback(const THD* thd);
1059
1060 int log_loaded_block(IO_CACHE* file);
1061
1062 /**
1063 Open a single binary log file for reading.
1064 */
1065 File open_binlog_file(IO_CACHE *log, const char *log_file_name,
1066 const char **errmsg);
1067 int check_binlog_magic(IO_CACHE* log, const char** errmsg);
1068 bool purge_master_logs(THD* thd, const char* to_log);
1069 bool purge_master_logs_before_date(THD* thd, time_t purge_time);
1070 bool show_binlog_events(THD *thd, MYSQL_BIN_LOG *binary_log);
1071 bool mysql_show_binlog_events(THD* thd);
1072 void check_binlog_cache_size(THD *thd);
1073 void check_binlog_stmt_cache_size(THD *thd);
1074 bool binlog_enabled();
1075 void register_binlog_handler(THD *thd, bool trx);
1076 int query_error_code(THD *thd, bool not_killed);
1077
1078 bool handle_gtid_consistency_violation(THD *thd, int error_code);
1079
1080 extern const char *log_bin_index;
1081 extern const char *log_bin_basename;
1082 extern bool opt_binlog_order_commits;
1083
1084 /*
1085 Maximum unique log filename extension.
1086 Note: setting to 0x7FFFFFFF due to atol windows
1087 overflow/truncate.
1088 */
1089 #define MAX_LOG_UNIQUE_FN_EXT 0x7FFFFFFF
1090
1091 /**
1092 Turns a relative log binary log path into a full path, based on the
1093 opt_bin_logname or opt_relay_logname. Also trims the cr-lf at the
1094 end of the full_path before return to avoid any server startup
1095 problem on windows.
1096
1097 @param from The log name we want to make into an absolute path.
1098 @param to The buffer where to put the results of the
1099 normalization.
1100 @param is_relay_log Switch that makes is used inside to choose which
1101 option (opt_bin_logname or opt_relay_logname) to
1102 use when calculating the base path.
1103
1104 @returns true if a problem occurs, false otherwise.
1105 */
1106
normalize_binlog_name(char * to,const char * from,bool is_relay_log)1107 inline bool normalize_binlog_name(char *to, const char *from, bool is_relay_log)
1108 {
1109 DBUG_ENTER("normalize_binlog_name");
1110 bool error= false;
1111 char buff[FN_REFLEN];
1112 char *ptr= (char*) from;
1113 char *opt_name= is_relay_log ? opt_relay_logname : opt_bin_logname;
1114
1115 assert(from);
1116
1117 /* opt_name is not null and not empty and from is a relative path */
1118 if (opt_name && opt_name[0] && from && !test_if_hard_path(from))
1119 {
1120 // take the path from opt_name
1121 // take the filename from from
1122 char log_dirpart[FN_REFLEN], log_dirname[FN_REFLEN];
1123 size_t log_dirpart_len, log_dirname_len;
1124 dirname_part(log_dirpart, opt_name, &log_dirpart_len);
1125 dirname_part(log_dirname, from, &log_dirname_len);
1126
1127 /* log may be empty => relay-log or log-bin did not
1128 hold paths, just filename pattern */
1129 if (log_dirpart_len > 0)
1130 {
1131 /* create the new path name */
1132 if(fn_format(buff, from+log_dirname_len, log_dirpart, "",
1133 MYF(MY_UNPACK_FILENAME | MY_SAFE_PATH)) == NULL)
1134 {
1135 error= true;
1136 goto end;
1137 }
1138
1139 ptr= buff;
1140 }
1141 }
1142
1143 assert(ptr);
1144 if (ptr)
1145 {
1146 size_t length= strlen(ptr);
1147
1148 // Strips the CR+LF at the end of log name and \0-terminates it.
1149 if (length && ptr[length-1] == '\n')
1150 {
1151 ptr[length-1]= 0;
1152 length--;
1153 if (length && ptr[length-1] == '\r')
1154 {
1155 ptr[length-1]= 0;
1156 length--;
1157 }
1158 }
1159 if (!length)
1160 {
1161 error= true;
1162 goto end;
1163 }
1164 strmake(to, ptr, length);
1165 }
1166 end:
1167 DBUG_RETURN(error);
1168 }
1169 #endif /* BINLOG_H_INCLUDED */
1170