-
Notifications
You must be signed in to change notification settings - Fork 4k
/
Copy pathlog_event.h
4702 lines (3943 loc) · 153 KB
/
log_event.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
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* Copyright (c) 2000, 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 */
/**
@file sql/log_event.h
@brief Binary log event definitions. This includes generic code
common to all types of log events, as well as specific code for each
type of log event.
@addtogroup Replication
@{
*/
#ifndef _log_event_h
#define _log_event_h
#include <atomic>
#include <cstdint>
#include <functional>
#include <list>
#include <map>
#include <set>
#include <string>
#include <string_view>
#include "m_string.h" // native_strncasecmp
#include "my_bitmap.h" // MY_BITMAP
#include "my_checksum.h" // ha_checksum
#include "my_dbug.h"
#include "my_inttypes.h"
#include "my_psi_config.h"
#include "my_sharedlib.h"
#include "my_sys.h"
#include "my_thread_local.h"
#include "mysql/binlog/event/binlog_event.h"
#include "mysql/binlog/event/control_events.h"
#include "mysql/binlog/event/load_data_events.h"
#include "mysql/binlog/event/rows_event.h"
#include "mysql/binlog/event/statement_events.h"
#include "mysql/components/services/bits/psi_stage_bits.h"
#include "mysql/gtid/uuid.h"
#include "mysql/service_mysql_alloc.h"
#include "mysql/udf_registration_types.h"
#include "mysql_com.h" // SERVER_VERSION_LENGTH
#include "partition_info.h"
#include "sql/query_options.h" // OPTION_AUTO_IS_NULL
#include "sql/rpl_gtid.h" // enum_gtid_type
#include "sql/rpl_utility.h" // Hash_slave_rows
#include "sql/sql_const.h"
#include "sql/thr_malloc.h"
#include "sql_string.h"
#include "string_with_len.h"
#include "strmake.h"
#include "typelib.h" // TYPELIB
namespace mysql::binlog::event {
class Table_id;
} // namespace mysql::binlog::event
class THD;
struct CHARSET_INFO;
enum class enum_row_image_type;
class Basic_ostream;
#ifdef MYSQL_SERVER
#include <stdio.h>
#include "my_compiler.h"
#include "sql/changestreams/misc/replicated_columns_view.h" // ReplicatedColumnsView
#include "sql/key.h"
#include "sql/rpl_filter.h" // rpl_filter
#include "sql/table.h"
#include "sql/xa.h"
#endif
#ifndef MYSQL_SERVER
#include "sql/rpl_tblmap.h" // table_mapping
#endif
#include <limits.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#ifdef HAVE_PSI_STAGE_INTERFACE
#include "mysql/psi/mysql_stage.h"
#endif
#ifndef MYSQL_SERVER
class Format_description_log_event;
#endif
extern PSI_memory_key key_memory_Incident_log_event_message;
extern PSI_memory_key key_memory_Rows_query_log_event_rows_query;
extern "C" MYSQL_PLUGIN_IMPORT ulong server_id;
#if defined(MYSQL_SERVER)
using ColumnViewPtr = std::unique_ptr<cs::util::ReplicatedColumnsView>;
#endif
using sql_mode_t = uint64_t;
struct db_worker_hash_entry;
extern "C" MYSQL_PLUGIN_IMPORT char server_version[SERVER_VERSION_LENGTH];
#if defined(MYSQL_SERVER)
int ignored_error_code(int err_code);
#endif
#define PREFIX_SQL_LOAD "SQL_LOAD-"
/**
Maximum length of the name of a temporary file
PREFIX LENGTH - 9
UUID - UUID_LENGTH
SEPARATORS - 2
SERVER ID - 10 (range of server ID 1 to (2^32)-1 = 4,294,967,295)
FILE ID - 10 (uint)
EXTENSION - 7 (Assuming that the extension is always less than 7
characters)
*/
#define TEMP_FILE_MAX_LEN UUID_LENGTH + 38
/**
Either assert or return an error.
In debug build, the condition will be checked, but in non-debug
builds, the error code given will be returned instead.
@param COND Condition to check
@param ERRNO Error number to return in non-debug builds
*/
#ifdef NDEBUG
#define ASSERT_OR_RETURN_ERROR(COND, ERRNO) \
do { \
if (!(COND)) return ERRNO; \
} while (0)
#else
#define ASSERT_OR_RETURN_ERROR(COND, ERRNO) assert(COND)
#endif
#define LOG_EVENT_OFFSET 4
#define NUM_LOAD_DELIM_STRS 5
/*****************************************************************************
MySQL Binary Log
This log consists of events. Each event has a fixed-length header,
possibly followed by a variable length data body.
The data body consists of an optional fixed length segment (post-header)
and an optional variable length segment.
See the #defines below for the format specifics.
The events which really update data are Query_log_event,
Execute_load_query_log_event and old Load_log_event and
Execute_load_log_event events (Execute_load_query is used together with
Begin_load_query and Append_block events to replicate LOAD DATA INFILE.
Create_file/Append_block/Execute_load (which includes Load_log_event)
were used to replicate LOAD DATA before the 5.0.3).
****************************************************************************/
#define MAX_LOG_EVENT_HEADER \
( /* in order of Query_log_event::write */ \
(LOG_EVENT_HEADER_LEN + /* write_header */ \
mysql::binlog::event::Binary_log_event::QUERY_HEADER_LEN + /* write_data \
*/ \
mysql::binlog::event::Binary_log_event:: \
EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN) + /*write_post_header_for_derived \
*/ \
MAX_SIZE_LOG_EVENT_STATUS + /* status */ \
NAME_LEN + \
1)
/* slave event post-header (this event is never written) */
#define SL_MASTER_PORT_OFFSET 8
#define SL_MASTER_POS_OFFSET 0
#define SL_MASTER_HOST_OFFSET 10
/* Intvar event post-header */
/* Intvar event data */
#define I_TYPE_OFFSET 0
#define I_VAL_OFFSET 1
/* 4 bytes which all binlogs should begin with */
#define BINLOG_MAGIC "\xfe\x62\x69\x6e"
#define BINLOG_MAGIC_SIZE 4
/**
@addtogroup group_cs_binglog_event_header_flags Binlog Event Header Flags
@ingroup group_cs
@{
*/
/*
The 2 flags below were useless :
- the first one was never set
- the second one was set in all Rotate events on the master, but not used for
anything useful.
So they are now removed and their place may later be reused for other
flags. Then one must remember that Rotate events in 4.x have
LOG_EVENT_FORCED_ROTATE_F set, so one should not rely on the value of the
replacing flag when reading a Rotate event.
I keep the defines here just to remember what they were.
#define LOG_EVENT_TIME_F 0x1
#define LOG_EVENT_FORCED_ROTATE_F 0x2
*/
/**
@def LOG_EVENT_THREAD_SPECIFIC_F
If the query depends on the thread (for example: TEMPORARY TABLE).
Currently this is used by mysqlbinlog to know it must print
SET @@PSEUDO_THREAD_ID=xx; before the query (it would not hurt to print it
for every query but this would be slow).
*/
#define LOG_EVENT_THREAD_SPECIFIC_F 0x4
/**
@def LOG_EVENT_SUPPRESS_USE_F
Suppress the generation of 'USE' statements before the actual
statement. This flag should be set for any events that does not need
the current database set to function correctly. Most notable cases
are 'CREATE DATABASE' and 'DROP DATABASE'.
This flags should only be used in exceptional circumstances, since
it introduce a significant change in behaviour regarding the
replication logic together with the flags --binlog-do-db and
--replicated-do-db.
*/
#define LOG_EVENT_SUPPRESS_USE_F 0x8
/*
Note: this is a place holder for the flag
LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F (0x10), which is not used any
more, please do not reused this value for other flags.
*/
/**
@def LOG_EVENT_ARTIFICIAL_F
Artificial events are created arbitrarily and not written to binary
log
These events should not update the master log position when slave
SQL thread executes them.
*/
#define LOG_EVENT_ARTIFICIAL_F 0x20
/**
@def LOG_EVENT_RELAY_LOG_F
Events with this flag set are created by slave IO thread and written
to relay log
*/
#define LOG_EVENT_RELAY_LOG_F 0x40
/**
@def LOG_EVENT_IGNORABLE_F
For an event, 'e', carrying a type code, that a slave,
's', does not recognize, 's' will check 'e' for
LOG_EVENT_IGNORABLE_F, and if the flag is set, then 'e'
is ignored. Otherwise, 's' acknowledges that it has
found an unknown event in the relay log.
*/
#define LOG_EVENT_IGNORABLE_F 0x80
/**
@def LOG_EVENT_NO_FILTER_F
Events with this flag are not filtered (e.g. on the current
database) and are always written to the binary log regardless of
filters.
*/
#define LOG_EVENT_NO_FILTER_F 0x100
/**
MTS: group of events can be marked to force its execution
in isolation from any other Workers.
So it's a marker for Coordinator to memorize and perform necessary
operations in order to guarantee no interference from other Workers.
The flag can be set ON only for an event that terminates its group.
Typically that is done for a transaction that contains
a query accessing more than OVER_MAX_DBS_IN_EVENT_MTS databases.
*/
#define LOG_EVENT_MTS_ISOLATE_F 0x200
/** @}*/
/**
@def OPTIONS_WRITTEN_TO_BIN_LOG
OPTIONS_WRITTEN_TO_BIN_LOG are the bits of thd->options which must
be written to the binlog. OPTIONS_WRITTEN_TO_BIN_LOG could be
written into the Format_description_log_event, so that if later we
don't want to replicate a variable we did replicate, or the
contrary, it's doable. But it should not be too hard to decide once
for all of what we replicate and what we don't, among the fixed 32
bits of thd->options.
I (Guilhem) have read through every option's usage, and it looks
like OPTION_AUTO_IS_NULL and OPTION_NO_FOREIGN_KEYS are the only
ones which alter how the query modifies the table. It's good to
replicate OPTION_RELAXED_UNIQUE_CHECKS too because otherwise, the
slave may insert data slower than the master, in InnoDB.
OPTION_BIG_SELECTS is not needed (the slave thread runs with
max_join_size=HA_POS_ERROR) and OPTION_BIG_TABLES is not needed
either, as the manual says (because a too big in-memory temp table
is automatically written to disk).
*/
#define OPTIONS_WRITTEN_TO_BIN_LOG \
(OPTION_AUTO_IS_NULL | OPTION_NO_FOREIGN_KEY_CHECKS | \
OPTION_RELAXED_UNIQUE_CHECKS | OPTION_NOT_AUTOCOMMIT)
/* Shouldn't be defined before */
#define EXPECTED_OPTIONS \
((1ULL << 14) | (1ULL << 26) | (1ULL << 27) | (1ULL << 19))
#if OPTIONS_WRITTEN_TO_BIN_LOG != EXPECTED_OPTIONS
#error OPTIONS_WRITTEN_TO_BIN_LOG must NOT change their values!
#endif
#undef EXPECTED_OPTIONS /* You shouldn't use this one */
/**
Maximum value of binlog logical timestamp.
*/
const int64 SEQ_MAX_TIMESTAMP = LLONG_MAX;
/**
This method is used to extract the partition_id
from a partitioned table.
@param part_info an object of class partition_info it will be used
to call the methods responsible for returning the
value of partition_id
@retval The return value is the partition_id.
*/
int get_rpl_part_id(partition_info *part_info);
#ifdef MYSQL_SERVER
class Item;
class Protocol;
class Slave_reporting_capability;
class Slave_worker;
class sql_exchange;
template <class T>
class List;
#endif
class Relay_log_info;
class Gtid_log_event;
#ifndef MYSQL_SERVER
enum enum_base64_output_mode {
BASE64_OUTPUT_NEVER = 0,
BASE64_OUTPUT_AUTO = 1,
BASE64_OUTPUT_UNSPEC = 2,
BASE64_OUTPUT_DECODE_ROWS = 3,
/* insert new output modes here */
BASE64_OUTPUT_MODE_COUNT
};
/*
A structure for mysqlbinlog to know how to print events
This structure is passed to the event's print() methods,
There are two types of settings stored here:
1. Last db, flags2, sql_mode etc comes from the last printed event.
They are stored so that only the necessary USE and SET commands
are printed.
2. Other information on how to print the events, e.g. short_form,
hexdump_from. These are not dependent on the last event.
*/
struct PRINT_EVENT_INFO {
/*
Settings for database, sql_mode etc that comes from the last event
that was printed. We cache these so that we don't have to print
them if they are unchanged.
*/
// TODO: have the last catalog here ??
char db[FN_REFLEN + 1]; // TODO: make this a LEX_STRING when thd->db is
bool flags2_inited;
uint32 flags2;
bool sql_mode_inited;
sql_mode_t sql_mode; /* must be same as THD.variables.sql_mode */
ulong auto_increment_increment, auto_increment_offset;
bool charset_inited;
char charset[6]; // 3 variables, each of them storable in 2 bytes
char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH];
uint lc_time_names_number;
uint charset_database_number;
uint default_collation_for_utf8mb4_number;
uint8_t sql_require_primary_key;
my_thread_id thread_id;
bool thread_id_printed;
uint8_t default_table_encryption;
PRINT_EVENT_INFO();
~PRINT_EVENT_INFO() {
close_cached_file(&head_cache);
close_cached_file(&body_cache);
close_cached_file(&footer_cache);
}
bool init_ok() /* tells if construction was successful */
{
return my_b_inited(&head_cache) && my_b_inited(&body_cache) &&
my_b_inited(&footer_cache);
}
/* Settings on how to print the events */
// True if the --short-form flag was specified
bool short_form;
// The X in --base64-output=X
enum_base64_output_mode base64_output_mode;
// True if the --skip-gtids flag was specified.
bool skip_gtids;
/*
This is set whenever a Format_description_event is printed.
Later, when an event is printed in base64, this flag is tested: if
no Format_description_event has been seen, it is unsafe to print
the base64 event, so an error message is generated.
*/
bool printed_fd_event;
my_off_t hexdump_from;
uint8 common_header_len;
char delimiter[16];
uint verbose;
table_mapping m_table_map;
table_mapping m_table_map_ignored;
/*
These three caches are used by the row-based replication events to
collect the header information and the main body of the events
making up a statement and in footer section any verbose related details
or comments related to the statement.
*/
IO_CACHE head_cache;
IO_CACHE body_cache;
IO_CACHE footer_cache;
/* Indicate if the body cache has unflushed events */
bool have_unflushed_events;
/*
True if an event was skipped while printing the events of
a transaction and no COMMIT statement or XID event was ever
output (ie, was filtered out as well). This can be triggered
by the --database option of mysqlbinlog.
False, otherwise.
*/
bool skipped_event_in_transaction;
bool print_table_metadata;
/**
True if --require_row_format is passed.
If true
It prints at start SET @@session.require_row_format = 1
It omits the SET @@session.pseudo_thread_id printed on Query events
*/
bool require_row_format;
/**
The version of the last server that sent the transaction
*/
uint32_t immediate_server_version;
};
#endif
/*
A specific to the database-scheduled MTS type.
*/
struct Mts_db_names {
const char *name[MAX_DBS_IN_EVENT_MTS]{nullptr};
int num{0};
Mts_db_names() = default;
void reset_and_dispose() {
for (int i = 0; i < MAX_DBS_IN_EVENT_MTS; i++) {
free(const_cast<char *>(name[i]));
name[i] = nullptr;
}
num = 0;
}
};
/**
@class Log_event
This is the abstract base class for binary log events.
@section Log_event_binary_format Binary Format
The format of the event is described @ref Binary_log_event_format "here".
@subsection Log_event_format_of_atomic_primitives Format of Atomic Primitives
- All numbers, whether they are 16-, 24-, 32-, or 64-bit numbers,
are stored in little endian, i.e., the least significant byte first,
unless otherwise specified.
*/
class Log_event {
public:
/**
Enumeration of what kinds of skipping (and non-skipping) that can
occur when the slave executes an event.
@see shall_skip
@see do_shall_skip
*/
enum enum_skip_reason {
/**
Don't skip event.
*/
EVENT_SKIP_NOT,
/**
Skip event by ignoring it.
This means that the slave skip counter will not be changed.
*/
EVENT_SKIP_IGNORE,
/**
Skip event and decrease skip counter.
*/
EVENT_SKIP_COUNT
};
protected:
enum enum_event_cache_type {
EVENT_INVALID_CACHE = 0,
/*
If possible the event should use a non-transactional cache before
being flushed to the binary log. This means that it must be flushed
right after its correspondent statement is completed.
*/
EVENT_STMT_CACHE,
/*
The event should use a transactional cache before being flushed to
the binary log. This means that it must be flushed upon commit or
rollback.
*/
EVENT_TRANSACTIONAL_CACHE,
/*
The event must be written directly to the binary log without going
through any cache.
*/
EVENT_NO_CACHE,
/*
If there is a need for different types, introduce them before this.
*/
EVENT_CACHE_COUNT
};
enum enum_event_logging_type {
EVENT_INVALID_LOGGING = 0,
/*
The event must be written to a cache and upon commit or rollback
written to the binary log.
*/
EVENT_NORMAL_LOGGING,
/*
The event must be written to an empty cache and immediately written
to the binary log without waiting for any other event.
*/
EVENT_IMMEDIATE_LOGGING,
/*
If there is a need for different types, introduce them before this.
*/
EVENT_CACHE_LOGGING_COUNT
};
/**
Writes the common header of this event to the given memory buffer.
This does not update the checksum.
@note This has the following form:
+---------+---------+---------+------------+-----------+-------+
|timestamp|type code|server_id|event_length|end_log_pos|flags |
|4 bytes |1 byte |4 bytes |4 bytes |4 bytes |2 bytes|
+---------+---------+---------+------------+-----------+-------+
@param buf Memory buffer to write to. This must be at least
LOG_EVENT_HEADER_LEN bytes long.
@return The number of bytes written, i.e., always
LOG_EVENT_HEADER_LEN.
*/
uint32 write_header_to_memory(uchar *buf);
/**
Writes the common-header of this event to the given output stream and
updates the checksum.
@param ostream The event will be written to this output stream.
@param data_length The length of the post-header section plus the
length of the data section; i.e., the length of the event minus
the common-header and the checksum.
*/
bool write_header(Basic_ostream *ostream, size_t data_length);
bool write_footer(Basic_ostream *ostream);
bool need_checksum();
public:
/*
A temp buffer for read_log_event; it is later analysed according to the
event's type, and its content is distributed in the event-specific fields.
*/
char *temp_buf;
/*
This variable determines whether the event is responsible for deallocating
the memory pointed by temp_buf. When set to true temp_buf is deallocated
and when it is set to false just make temp_buf point to NULL.
*/
bool m_free_temp_buf_in_destructor;
/* The number of seconds the query took to run on the master. */
ulong exec_time;
/*
The master's server id (is preserved in the relay log; used to
prevent from infinite loops in circular replication).
*/
uint32 server_id;
/**
A storage to cache the global system variable's value.
Handling of a separate event will be governed its member.
*/
ulong rbr_exec_mode;
/**
Defines the type of the cache, if any, where the event will be
stored before being flushed to disk.
*/
enum_event_cache_type event_cache_type;
/**
Defines when information, i.e. event or cache, will be flushed
to disk.
*/
enum_event_logging_type event_logging_type;
/**
Placeholder for event checksum while writing to binlog.
*/
ha_checksum crc;
/**
Index in @c rli->gaq array to indicate a group that this event is
purging. The index is set by Coordinator to a group terminator
event is checked by Worker at the event execution. The indexed
data represent the Worker progress status.
*/
ulong mts_group_idx;
/**
The Log_event_header class contains the variable present
in the common header
*/
mysql::binlog::event::Log_event_header *common_header;
/**
The Log_event_footer class contains the variable present
in the common footer. Currently, footer contains only the checksum_alg.
*/
mysql::binlog::event::Log_event_footer *common_footer;
/**
MTS: associating the event with either an assigned Worker or Coordinator.
Additionally the member serves to tag deferred (IRU) events to avoid
the event regular time destruction.
*/
Relay_log_info *worker;
/**
A copy of the main rli value stored into event to pass to MTS worker rli
*/
ulonglong future_event_relay_log_pos;
#ifdef MYSQL_SERVER
THD *thd;
/**
Partition info associate with event to deliver to MTS event applier
*/
db_worker_hash_entry *mts_assigned_partitions[MAX_DBS_IN_EVENT_MTS];
Log_event(mysql::binlog::event::Log_event_header *header,
mysql::binlog::event::Log_event_footer *footer,
enum_event_cache_type cache_type_arg,
enum_event_logging_type logging_type_arg);
Log_event(THD *thd_arg, uint16 flags_arg,
enum_event_cache_type cache_type_arg,
enum_event_logging_type logging_type_arg,
mysql::binlog::event::Log_event_header *header,
mysql::binlog::event::Log_event_footer *footer);
/*
init_show_field_list() prepares the column names and types for the
output of SHOW BINLOG EVENTS; it is used only by SHOW BINLOG
EVENTS.
*/
static void init_show_field_list(mem_root_deque<Item *> *field_list);
int net_send(Protocol *protocol, const char *log_name, my_off_t pos);
/**
Stores a string representation of this event in the Protocol.
This is used by SHOW BINLOG EVENTS.
@retval 0 success
@retval nonzero error
*/
virtual int pack_info(Protocol *protocol);
virtual const char *get_db();
#else // ifdef MYSQL_SERVER
/* print*() functions are used by mysqlbinlog */
virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info) const = 0;
void print_timestamp(IO_CACHE *file, time_t *ts) const;
void print_header(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info,
bool is_more) const;
void print_base64(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info,
bool is_more) const;
#endif // ifdef MYSQL_SERVER ... else
void *operator new(size_t size);
static void operator delete(void *ptr, size_t) { my_free(ptr); }
/* Placement version of the above operators */
static void *operator new(size_t, void *ptr) { return ptr; }
static void operator delete(void *, void *) {}
/**
Write the given buffer to the given output stream, updating the
checksum if checksums are enabled.
@param ostream The output stream to write to.
@param buf The buffer to write.
@param data_length The number of bytes to write.
@retval false Success.
@retval true Error.
*/
bool wrapper_my_b_safe_write(Basic_ostream *ostream, const uchar *buf,
size_t data_length);
#ifdef MYSQL_SERVER
virtual bool write(Basic_ostream *ostream) {
return (write_header(ostream, get_data_size()) ||
write_data_header(ostream) || write_data_body(ostream) ||
write_footer(ostream));
}
time_t get_time();
virtual bool write_data_header(Basic_ostream *) { return false; }
virtual bool write_data_body(Basic_ostream *) { return false; }
#endif
virtual mysql::binlog::event::Log_event_type get_type_code() const {
return common_header->type_code;
}
/**
Return true if the event has to be logged using SBR for DMLs.
*/
virtual bool is_sbr_logging_format() const { return false; }
/**
Return true if the event has to be logged using RBR for DMLs.
*/
virtual bool is_rbr_logging_format() const { return false; }
/*
is_valid is event specific sanity checks to determine that the
object is correctly initialized.
*/
bool is_valid();
void set_artificial_event() {
common_header->flags |= LOG_EVENT_ARTIFICIAL_F;
/*
Artificial events are automatically generated and do not exist
in master's binary log, so log_pos should be set to 0.
*/
common_header->log_pos = 0;
}
void set_relay_log_event() { common_header->flags |= LOG_EVENT_RELAY_LOG_F; }
bool is_artificial_event() const {
return common_header->flags & LOG_EVENT_ARTIFICIAL_F;
}
bool is_relay_log_event() const {
return common_header->flags & LOG_EVENT_RELAY_LOG_F;
}
bool is_ignorable_event() const {
return common_header->flags & LOG_EVENT_IGNORABLE_F;
}
bool is_no_filter_event() const {
return common_header->flags & LOG_EVENT_NO_FILTER_F;
}
inline bool is_using_trans_cache() const {
return (event_cache_type == EVENT_TRANSACTIONAL_CACHE);
}
inline bool is_using_stmt_cache() const {
return (event_cache_type == EVENT_STMT_CACHE);
}
inline bool is_using_immediate_logging() const {
return (event_logging_type == EVENT_IMMEDIATE_LOGGING);
}
/*
For the events being decoded in BAPI, common_header should
point to the header object which is contained within the class
Binary_log_event.
*/
Log_event(mysql::binlog::event::Log_event_header *header,
mysql::binlog::event::Log_event_footer *footer);
/**
Allow thread to CLAIM or DISCLAIM the ownership of this object
depends on the parameter value passed
@param claim
True - claim ownership of the memory
False - disclaim ownership of the memory
*/
virtual void claim_memory_ownership([[maybe_unused]] bool claim) {}
virtual ~Log_event() { free_temp_buf(); }
void register_temp_buf(char *buf, bool free_in_destructor = true) {
m_free_temp_buf_in_destructor = free_in_destructor;
temp_buf = buf;
}
void free_temp_buf() {
if (temp_buf) {
if (m_free_temp_buf_in_destructor) my_free(temp_buf);
temp_buf = nullptr;
}
}
/*
Get event length for simple events. For complicated events the length
is calculated during write()
*/
virtual size_t get_data_size() { return 0; }
/**
Returns the human readable name of the given event type.
*/
static const char *get_type_str(mysql::binlog::event::Log_event_type type);
/// Get the name of an event type, or "Unknown" if out of range.
/// @param type The type as an int
/// @retval name of an event type, if it is one
/// @retval "Unknown" if the value is out of range
static const char *get_type_str(uint type);
/**
Returns the human readable name of this event's type.
*/
const char *get_type_str() const;
/* Return start of query time or current time */
#if defined(MYSQL_SERVER)
/**
Is called from get_mts_execution_mode() to
@return true if the event needs applying with synchronization
against Workers, otherwise
false
@note There are incompatile combinations such as referred further events
are wrapped with BEGIN/COMMIT. Such cases should be identified
by the caller and treats correspondingly.
todo: to mts-support Old master Load-data related events
*/
bool is_mts_sequential_exec() const {
return is_mts_sequential_exec(get_type_code());
}
static bool is_mts_sequential_exec(
mysql::binlog::event::Log_event_type type_code) {
switch (type_code) {
case mysql::binlog::event::STOP_EVENT:
case mysql::binlog::event::ROTATE_EVENT:
case mysql::binlog::event::SLAVE_EVENT:
case mysql::binlog::event::FORMAT_DESCRIPTION_EVENT:
case mysql::binlog::event::INCIDENT_EVENT:
return true;
default:
return false;
}
}
/*
possible decisions by get_mts_execution_mode().
The execution mode can be PARALLEL or not (thereby sequential
unless impossible at all). When it's sequential it further breaks into
ASYNChronous and SYNChronous.
*/
enum enum_mts_event_exec_mode {
/*
Event is run by a Worker.
*/
EVENT_EXEC_PARALLEL,
/*
Event is run by Coordinator.
*/
EVENT_EXEC_ASYNC,
/*
Event is run by Coordinator and requires synchronization with Workers.
*/
EVENT_EXEC_SYNC,
/*
Event can't be executed neither by Workers nor Coordinator.
*/
EVENT_EXEC_CAN_NOT
};
static enum enum_mts_event_exec_mode get_mts_execution_mode(
bool mts_in_group, mysql::binlog::event::Log_event_type type_code,
uint32 server_id, uint32 log_pos) {
/*
Slave workers are unable to handle Format_description_log_event,
Rotate_log_event and Previous_gtids_log_event correctly.
However, when a transaction spans multiple relay logs, these
events occur in the middle of a transaction. The way we handle
this is by marking the events as 'ASYNC', meaning that the
coordinator thread will handle the events without stopping the
worker threads.
@todo Refactor this: make Log_event::get_slave_worker handle
transaction boundaries in a more robust way, so that it is able
to process Format_description_log_event, Rotate_log_event, and
Previous_gtids_log_event. Then, when these events occur in the
middle of a transaction, make them part of the transaction so
that the worker that handles the transaction handles these
events too. /Sven
*/
if (
/*
When a Format_description_log_event occurs in the middle of
a transaction, it either has the slave's server_id, or has
end_log_pos==0.
@todo This does not work when master and slave have the same
server_id and replicate-same-server-id is enabled, since
events that are not in the middle of a transaction will be
executed in ASYNC mode in that case.
*/
(type_code == mysql::binlog::event::FORMAT_DESCRIPTION_EVENT &&
((server_id == (uint32)::server_id) || (log_pos == 0))) ||
/*
All Previous_gtids_log_events in the relay log are generated
by the slave. They don't have any meaning to the applier, so
they can always be ignored by the applier. So we can process
them asynchronously by the coordinator. It is also important
to not feed them to workers because that confuses
get_slave_worker.
*/
(type_code == mysql::binlog::event::PREVIOUS_GTIDS_LOG_EVENT) ||
/*
Rotate_log_event can occur in the middle of a transaction.
When this happens, either it is a Rotate event generated on
the slave which has the slave's server_id, or it is a Rotate
event that originates from a master but has end_log_pos==0.