diff options
Diffstat (limited to 'sql/log_event.h')
-rw-r--r-- | sql/log_event.h | 703 |
1 files changed, 608 insertions, 95 deletions
diff --git a/sql/log_event.h b/sql/log_event.h index c181b5ce4c6..1a7ffd9e829 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -1,4 +1,5 @@ /* Copyright (c) 2000, 2014, Oracle and/or its affiliates. + Copyright (c) 2009, 2014, Monty Program Ab. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -48,6 +49,8 @@ #include "sql_class.h" /* THD */ #endif +#include "rpl_gtid.h" + /* Forward declarations */ class String; @@ -251,13 +254,18 @@ struct sql_ex_info #define FORMAT_DESCRIPTION_HEADER_LEN (START_V3_HEADER_LEN+1+LOG_EVENT_TYPES) #define XID_HEADER_LEN 0 #define BEGIN_LOAD_QUERY_HEADER_LEN APPEND_BLOCK_HEADER_LEN -#define ROWS_HEADER_LEN 8 +#define ROWS_HEADER_LEN_V1 8 #define TABLE_MAP_HEADER_LEN 8 #define EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN (4 + 4 + 4 + 1) #define EXECUTE_LOAD_QUERY_HEADER_LEN (QUERY_HEADER_LEN + EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN) #define INCIDENT_HEADER_LEN 2 #define HEARTBEAT_HEADER_LEN 0 +#define IGNORABLE_HEADER_LEN 0 +#define ROWS_HEADER_LEN_V2 10 #define ANNOTATE_ROWS_HEADER_LEN 0 +#define BINLOG_CHECKPOINT_HEADER_LEN 4 +#define GTID_HEADER_LEN 19 +#define GTID_LIST_HEADER_LEN 4 /* Max number of possible extra bytes in a replication event compared to a @@ -288,7 +296,7 @@ struct sql_ex_info to the slave. It is used to increase the thd(max_allowed) for both the DUMP thread on the master and the SQL/IO thread on the slave. */ -#define MAX_MAX_ALLOWED_PACKET 1024*1024*1024 +#define MAX_MAX_ALLOWED_PACKET (1024*1024*1024) /* Event header offsets; @@ -409,6 +417,9 @@ struct sql_ex_info /* RW = "RoWs" */ #define RW_MAPID_OFFSET 0 #define RW_FLAGS_OFFSET 6 +#define RW_VHLEN_OFFSET 8 +#define RW_V_TAG_LEN 1 +#define RW_V_EXTRAINFO_TAG 0 /* ELQ = "Execute Load Query" */ #define ELQ_FILE_ID_OFFSET QUERY_HEADER_LEN @@ -510,6 +521,17 @@ struct sql_ex_info #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_SKIP_REPLICATION_F Flag set by application creating the event (with @@skip_replication); the @@ -549,7 +571,7 @@ struct sql_ex_info /* Shouldn't be defined before */ #define EXPECTED_OPTIONS \ - ((ULL(1) << 14) | (ULL(1) << 26) | (ULL(1) << 27) | (ULL(1) << 19)) + ((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! @@ -572,6 +594,40 @@ enum enum_binlog_checksum_alg { #define BINLOG_CHECKSUM_LEN CHECKSUM_CRC32_SIGNATURE_LEN #define BINLOG_CHECKSUM_ALG_DESC_LEN 1 /* 1 byte checksum alg descriptor */ +/* + These are capability numbers for MariaDB slave servers. + + Newer MariaDB slaves set this to inform the master about their capabilities. + This allows the master to decide which events it can send to the slave + without breaking replication on old slaves that maybe do not understand + all events from newer masters. + + As new releases are backwards compatible, a given capability implies also + all capabilities with smaller number. + + Older MariaDB slaves and other MySQL slave servers do not set this, so they + are recorded with capability 0. +*/ + +/* MySQL or old MariaDB slave with no announced capability. */ +#define MARIA_SLAVE_CAPABILITY_UNKNOWN 0 +/* MariaDB >= 5.3, which understands ANNOTATE_ROWS_EVENT. */ +#define MARIA_SLAVE_CAPABILITY_ANNOTATE 1 +/* + MariaDB >= 5.5. This version has the capability to tolerate events omitted + from the binlog stream without breaking replication (MySQL slaves fail + because they mis-compute the offsets into the master's binlog). +*/ +#define MARIA_SLAVE_CAPABILITY_TOLERATE_HOLES 2 +/* MariaDB >= 10.0, which knows about binlog_checkpoint_log_event. */ +#define MARIA_SLAVE_CAPABILITY_BINLOG_CHECKPOINT 3 +/* MariaDB >= 10.0.1, which knows about global transaction id events. */ +#define MARIA_SLAVE_CAPABILITY_GTID 4 + +/* Our capability. */ +#define MARIA_SLAVE_CAPABILITY_MINE MARIA_SLAVE_CAPABILITY_GTID + + /** @enum Log_event_type @@ -619,11 +675,12 @@ enum Log_event_type PRE_GA_DELETE_ROWS_EVENT = 22, /* - These event numbers are used from 5.1.16 and forward + These event numbers are used from 5.1.16 until mysql-5.6.6, + and in MariaDB */ - WRITE_ROWS_EVENT = 23, - UPDATE_ROWS_EVENT = 24, - DELETE_ROWS_EVENT = 25, + WRITE_ROWS_EVENT_V1 = 23, + UPDATE_ROWS_EVENT_V1 = 24, + DELETE_ROWS_EVENT_V1 = 25, /* Something out of the ordinary happened on the master @@ -637,6 +694,27 @@ enum Log_event_type HEARTBEAT_LOG_EVENT= 27, /* + In some situations, it is necessary to send over ignorable + data to the slave: data that a slave can handle in case there + is code for handling it, but which can be ignored if it is not + recognized. + + These mysql-5.6 events are not recognized (and ignored) by MariaDB + */ + IGNORABLE_LOG_EVENT= 28, + ROWS_QUERY_LOG_EVENT= 29, + + /* Version 2 of the Row events, generated only by mysql-5.6.6+ */ + WRITE_ROWS_EVENT = 30, + UPDATE_ROWS_EVENT = 31, + DELETE_ROWS_EVENT = 32, + + /* MySQL 5.6 GTID events, ignored by MariaDB */ + GTID_LOG_EVENT= 33, + ANONYMOUS_GTID_LOG_EVENT= 34, + PREVIOUS_GTIDS_LOG_EVENT= 35, + + /* Add new events here - right above this comment! Existing events (except ENUM_END_EVENT) should never change their numbers */ @@ -647,6 +725,26 @@ enum Log_event_type MARIA_EVENTS_BEGIN= 160, /* New Maria event numbers start from here */ ANNOTATE_ROWS_EVENT= 160, + /* + Binlog checkpoint event. Used for XA crash recovery on the master, not used + in replication. + A binlog checkpoint event specifies a binlog file such that XA crash + recovery can start from that file - and it is guaranteed to find all XIDs + that are prepared in storage engines but not yet committed. + */ + BINLOG_CHECKPOINT_EVENT= 161, + /* + Gtid event. For global transaction ID, used to start a new event group, + instead of the old BEGIN query event, and also to mark stand-alone + events. + */ + GTID_EVENT= 162, + /* + Gtid list event. Logged at the start of every binlog, to record the + current replication state. This consists of the last GTID seen for + each replication domain. + */ + GTID_LIST_EVENT= 163, /* Add new MariaDB events here - right above this comment! */ @@ -719,6 +817,11 @@ typedef struct st_print_event_info uint charset_database_number; uint thread_id; bool thread_id_printed; + uint32 server_id; + bool server_id_printed; + uint32 domain_id; + bool domain_id_printed; + /* Track when @@skip_replication changes so we need to output a SET statement for it. @@ -1187,6 +1290,7 @@ public: #endif virtual Log_event_type get_type_code() = 0; virtual bool is_valid() const = 0; + virtual my_off_t get_header_len(my_off_t len) { return len; } void set_artificial_event() { flags |= LOG_EVENT_ARTIFICIAL_F; } void set_relay_log_event() { flags |= LOG_EVENT_RELAY_LOG_F; } bool is_artificial_event() const { return flags & LOG_EVENT_ARTIFICIAL_F; } @@ -1251,9 +1355,9 @@ public: @see do_apply_event */ - int apply_event(Relay_log_info const *rli) + int apply_event(rpl_group_info *rgi) { - return do_apply_event(rli); + return do_apply_event(rgi); } @@ -1265,9 +1369,9 @@ public: @see do_update_pos */ - int update_pos(Relay_log_info *rli) + int update_pos(rpl_group_info *rgi) { - return do_update_pos(rli); + return do_update_pos(rgi); } /** @@ -1276,11 +1380,66 @@ public: @see do_shall_skip */ - enum_skip_reason shall_skip(Relay_log_info *rli) + enum_skip_reason shall_skip(rpl_group_info *rgi) + { + return do_shall_skip(rgi); + } + + + /* + Check if an event is non-final part of a stand-alone event group, + such as Intvar_log_event (such events should be processed as part + of the following event group, not individually). + See also is_part_of_group() + */ + static bool is_part_of_group(enum Log_event_type ev_type) { - return do_shall_skip(rli); + switch (ev_type) + { + case GTID_EVENT: + case INTVAR_EVENT: + case RAND_EVENT: + case USER_VAR_EVENT: + case TABLE_MAP_EVENT: + case ANNOTATE_ROWS_EVENT: + return true; + case DELETE_ROWS_EVENT: + case UPDATE_ROWS_EVENT: + case WRITE_ROWS_EVENT: + /* + ToDo: also check for non-final Rows_log_event (though such events + are usually in a BEGIN-COMMIT group). + */ + default: + return false; + } } + /* + Same as above, but works on the object. In addition this is true for all + rows event except the last one. + */ + virtual bool is_part_of_group() { return 0; } + static bool is_group_event(enum Log_event_type ev_type) + { + switch (ev_type) + { + case START_EVENT_V3: + case STOP_EVENT: + case ROTATE_EVENT: + case SLAVE_EVENT: + case FORMAT_DESCRIPTION_EVENT: + case INCIDENT_EVENT: + case HEARTBEAT_LOG_EVENT: + case BINLOG_CHECKPOINT_EVENT: + case GTID_LIST_EVENT: + return false; + + default: + return true; + } + } + protected: /** @@ -1293,14 +1452,14 @@ protected: A typical usage is: @code - enum_skip_reason do_shall_skip(Relay_log_info *rli) { - return continue_group(rli); + enum_skip_reason do_shall_skip(rpl_group_info *rgi) { + return continue_group(rgi); } @endcode @return Skip reason */ - enum_skip_reason continue_group(Relay_log_info *rli); + enum_skip_reason continue_group(rpl_group_info *rgi); /** Primitive to apply an event to the database. @@ -1317,7 +1476,7 @@ protected: @retval 0 Event applied successfully @retval errno Error code if event application failed */ - virtual int do_apply_event(Relay_log_info const *rli) + virtual int do_apply_event(rpl_group_info *rgi) { return 0; /* Default implementation does nothing */ } @@ -1346,7 +1505,7 @@ protected: 1). Observe that handler errors are returned by the do_apply_event() function, and not by this one. */ - virtual int do_update_pos(Relay_log_info *rli); + virtual int do_update_pos(rpl_group_info *rgi); /** @@ -1378,7 +1537,7 @@ protected: The event shall be skipped because the slave skip counter was non-zero. The caller shall decrease the counter by one. */ - virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); + virtual enum_skip_reason do_shall_skip(rpl_group_info *rgi); #endif }; @@ -1853,6 +2012,8 @@ public: my_free(data_buf); } Log_event_type get_type_code() { return QUERY_EVENT; } + static int dummy_event(String *packet, ulong ev_offset, uint8 checksum_alg); + static int begin_event(String *packet, ulong ev_offset, uint8 checksum_alg); #ifdef MYSQL_SERVER bool write(IO_CACHE* file); virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; } @@ -1860,7 +2021,7 @@ public: bool is_valid() const { return query != 0; } /* - Returns number of bytes additionaly written to post header by derived + Returns number of bytes additionally written to post header by derived events (so far it is only Execute_load_query event). */ virtual ulong get_post_header_size_for_derived() { return 0; } @@ -1868,13 +2029,15 @@ public: public: /* !!! Public in this patch to allow old usage */ #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); - virtual int do_apply_event(Relay_log_info const *rli); - virtual int do_update_pos(Relay_log_info *rli); + virtual enum_skip_reason do_shall_skip(rpl_group_info *rgi); + virtual int do_apply_event(rpl_group_info *rgi); + virtual int do_update_pos(rpl_group_info *rgi); - int do_apply_event(Relay_log_info const *rli, + int do_apply_event(rpl_group_info *rgi, const char *query_arg, uint32 q_len_arg); + static bool peek_is_commit_rollback(const char *event_start, + size_t event_len, uint8 checksum_alg); #endif /* HAVE_REPLICATION */ /* If true, the event always be applied by slave SQL thread or be printed by @@ -1898,6 +2061,9 @@ public: /* !!! Public in this patch to allow old usage */ !strncasecmp(query, "SAVEPOINT", 9) || !strncasecmp(query, "ROLLBACK", 8); } + bool is_begin() { return !strcmp(query, "BEGIN"); } + bool is_commit() { return !strcmp(query, "COMMIT"); } + bool is_rollback() { return !strcmp(query, "ROLLBACK"); } }; @@ -1984,7 +2150,7 @@ public: private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const* rli); + virtual int do_apply_event(rpl_group_info *rgi); #endif }; @@ -2297,12 +2463,12 @@ public: public: /* !!! Public in this patch to allow old usage */ #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const* rli) + virtual int do_apply_event(rpl_group_info *rgi) { - return do_apply_event(thd->slave_net,rli,0); + return do_apply_event(thd->slave_net,rgi,0); } - int do_apply_event(NET *net, Relay_log_info const *rli, + int do_apply_event(NET *net, rpl_group_info *rgi, bool use_rli_only_for_errors); #endif }; @@ -2370,6 +2536,8 @@ public: const Format_description_log_event* description_event); ~Start_log_event_v3() {} Log_event_type get_type_code() { return START_EVENT_V3;} + my_off_t get_header_len(my_off_t l __attribute__((unused))) + { return LOG_EVENT_MINIMAL_HEADER_LEN; } #ifdef MYSQL_SERVER bool write(IO_CACHE* file); #endif @@ -2381,14 +2549,14 @@ public: protected: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const *rli); - virtual enum_skip_reason do_shall_skip(Relay_log_info*) + virtual int do_apply_event(rpl_group_info *rgi); + virtual enum_skip_reason do_shall_skip(rpl_group_info*) { /* Events from ourself should be skipped, but they should not decrease the slave skip counter. */ - if (this->server_id == ::server_id) + if (this->server_id == global_system_variables.server_id) return Log_event::EVENT_SKIP_IGNORE; else return Log_event::EVENT_SKIP_NOT; @@ -2477,9 +2645,9 @@ public: static bool is_version_before_checksum(const master_version_split *version_split); protected: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const *rli); - virtual int do_update_pos(Relay_log_info *rli); - virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); + virtual int do_apply_event(rpl_group_info *rgi); + virtual int do_update_pos(rpl_group_info *rgi); + virtual enum_skip_reason do_shall_skip(rpl_group_info *rgi); #endif }; @@ -2553,12 +2721,13 @@ Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg, bool write(IO_CACHE* file); #endif bool is_valid() const { return 1; } + bool is_part_of_group() { return 1; } private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const *rli); - virtual int do_update_pos(Relay_log_info *rli); - virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); + virtual int do_apply_event(rpl_group_info *rgi); + virtual int do_update_pos(rpl_group_info *rgi); + virtual enum_skip_reason do_shall_skip(rpl_group_info *rgi); #endif }; @@ -2632,12 +2801,13 @@ class Rand_log_event: public Log_event bool write(IO_CACHE* file); #endif bool is_valid() const { return 1; } + bool is_part_of_group() { return 1; } private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const *rli); - virtual int do_update_pos(Relay_log_info *rli); - virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); + virtual int do_apply_event(rpl_group_info *rgi); + virtual int do_update_pos(rpl_group_info *rgi); + virtual enum_skip_reason do_shall_skip(rpl_group_info *rgi); #endif }; @@ -2684,8 +2854,8 @@ class Xid_log_event: public Log_event private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const *rli); - enum_skip_reason do_shall_skip(Relay_log_info *rli); + virtual int do_apply_event(rpl_group_info *rgi); + enum_skip_reason do_shall_skip(rpl_group_info *rgi); #endif }; @@ -2753,12 +2923,13 @@ public: void set_deferred(query_id_t qid) { deferred= true; query_id= qid; } #endif bool is_valid() const { return name != 0; } + bool is_part_of_group() { return 1; } private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const *rli); - virtual int do_update_pos(Relay_log_info *rli); - virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); + virtual int do_apply_event(rpl_group_info *rgi); + virtual int do_update_pos(rpl_group_info *rgi); + virtual enum_skip_reason do_shall_skip(rpl_group_info *rgi); #endif }; @@ -2791,14 +2962,14 @@ public: private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_update_pos(Relay_log_info *rli); - virtual enum_skip_reason do_shall_skip(Relay_log_info *rli) + virtual int do_update_pos(rpl_group_info *rgi); + virtual enum_skip_reason do_shall_skip(rpl_group_info *rgi) { /* Events from ourself should be skipped, but they should not decrease the slave skip counter. */ - if (this->server_id == ::server_id) + if (this->server_id == global_system_variables.server_id) return Log_event::EVENT_SKIP_IGNORE; else return Log_event::EVENT_SKIP_NOT; @@ -2885,6 +3056,8 @@ public: my_free((void*) new_log_ident); } Log_event_type get_type_code() { return ROTATE_EVENT;} + my_off_t get_header_len(my_off_t l __attribute__((unused))) + { return LOG_EVENT_MINIMAL_HEADER_LEN; } int get_data_size() { return ident_len + ROTATE_HEADER_LEN;} bool is_valid() const { return new_log_ident != 0; } #ifdef MYSQL_SERVER @@ -2893,9 +3066,262 @@ public: private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_update_pos(Relay_log_info *rli); - virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); + virtual int do_update_pos(rpl_group_info *rgi); + virtual enum_skip_reason do_shall_skip(rpl_group_info *rgi); +#endif +}; + + +class Binlog_checkpoint_log_event: public Log_event +{ +public: + char *binlog_file_name; + uint binlog_file_len; + +#ifdef MYSQL_SERVER + Binlog_checkpoint_log_event(const char *binlog_file_name_arg, + uint binlog_file_len_arg); +#ifdef HAVE_REPLICATION + void pack_info(THD *thd, Protocol *protocol); +#endif +#else + void print(FILE *file, PRINT_EVENT_INFO *print_event_info); +#endif + Binlog_checkpoint_log_event(const char *buf, uint event_len, + const Format_description_log_event *description_event); + ~Binlog_checkpoint_log_event() { my_free(binlog_file_name); } + Log_event_type get_type_code() { return BINLOG_CHECKPOINT_EVENT;} + int get_data_size() { return binlog_file_len + BINLOG_CHECKPOINT_HEADER_LEN;} + bool is_valid() const { return binlog_file_name != 0; } +#ifdef MYSQL_SERVER + bool write(IO_CACHE* file); + enum_skip_reason do_shall_skip(rpl_group_info *rgi); +#endif +}; + + +/** + @class Gtid_log_event + + This event is logged as part of every event group to give the global + transaction id (GTID) of that group. + + It replaces the BEGIN query event used in earlier versions to begin most + event groups, but is also used for events that used to be stand-alone. + + @section Gtid_log_event_binary_format Binary Format + + The binary format for Gtid_log_event has 6 extra reserved bytes to make the + length a total of 19 byte (+ 19 bytes of header in common with all events). + This is just the minimal size for a BEGIN query event, which makes it easy + to replace this event with such BEGIN event to remain compatible with old + slave servers. + + <table> + <caption>Post-Header</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>seq_no</td> + <td>8 byte unsigned integer</td> + <td>increasing id within one server_id. Starts at 1, holes in the sequence + may occur</td> + </tr> + + <tr> + <td>domain_id</td> + <td>4 byte unsigned integer</td> + <td>Replication domain id, identifying independent replication streams></td> + </tr> + + <tr> + <td>flags</td> + <td>1 byte bitfield</td> + <td>Bit 0 set indicates stand-alone event (no terminating COMMIT)</td> + <td>Bit 1 set indicates group commit, and that commit id exists</td> + </tr> + + <tr> + <td>Reserved (no group commit) / commit id (group commit) (see flags bit 1)</td> + <td>6 bytes / 8 bytes</td> + <td>Reserved bytes, set to 0. Maybe be used for future expansion (no + group commit). OR commit id, same for all GTIDs in the same group + commit (see flags bit 1).</td> + </tr> + </table> + + The Body of Gtid_log_event is empty. The total event size is 19 bytes + + the normal 19 bytes common-header. +*/ + +class Gtid_log_event: public Log_event +{ +public: + uint64 seq_no; + uint64 commit_id; + uint32 domain_id; + uchar flags2; + + /* Flags2. */ + + /* FL_STANDALONE is set when there is no terminating COMMIT event. */ + static const uchar FL_STANDALONE= 1; + /* + FL_GROUP_COMMIT_ID is set when event group is part of a group commit on the + master. Groups with same commit_id are part of the same group commit. + */ + static const uchar FL_GROUP_COMMIT_ID= 2; + +#ifdef MYSQL_SERVER + Gtid_log_event(THD *thd_arg, uint64 seq_no, uint32 domain_id, bool standalone, + uint16 flags, bool is_transactional, uint64 commit_id); +#ifdef HAVE_REPLICATION + void pack_info(THD *thd, Protocol *protocol); + virtual int do_apply_event(rpl_group_info *rgi); + virtual int do_update_pos(rpl_group_info *rgi); + virtual enum_skip_reason do_shall_skip(rpl_group_info *rgi); +#endif +#else + void print(FILE *file, PRINT_EVENT_INFO *print_event_info); +#endif + Gtid_log_event(const char *buf, uint event_len, + const Format_description_log_event *description_event); + ~Gtid_log_event() { } + Log_event_type get_type_code() { return GTID_EVENT; } + int get_data_size() + { + return GTID_HEADER_LEN + ((flags2 & FL_GROUP_COMMIT_ID) ? 2 : 0); + } + bool is_valid() const { return seq_no != 0; } +#ifdef MYSQL_SERVER + bool write(IO_CACHE *file); + static int make_compatible_event(String *packet, bool *need_dummy_event, + ulong ev_offset, uint8 checksum_alg); + static bool peek(const char *event_start, size_t event_len, + uint8 checksum_alg, + uint32 *domain_id, uint32 *server_id, uint64 *seq_no, + uchar *flags2, const Format_description_log_event *fdev); +#endif +}; + + +/** + @class Gtid_list_log_event + + This event is logged at the start of every binlog file to record the + current replication state: the last global transaction id (GTID) applied + on the server within each replication domain. + + It consists of a list of GTIDs, one for each replication domain ever seen + on the server. + + @section Gtid_list_log_event_binary_format Binary Format + + <table> + <caption>Post-Header</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>count</td> + <td>4 byte unsigned integer</td> + <td>The lower 28 bits are the number of GTIDs. The upper 4 bits are + flags bits.</td> + </tr> + </table> + + <table> + <caption>Body</caption> + + <tr> + <th>Name</th> + <th>Format</th> + <th>Description</th> + </tr> + + <tr> + <td>domain_id</td> + <td>4 byte unsigned integer</td> + <td>Replication domain id of one GTID</td> + </tr> + + <tr> + <td>server_id</td> + <td>4 byte unsigned integer</td> + <td>Server id of one GTID</td> + </tr> + + <tr> + <td>seq_no</td> + <td>8 byte unsigned integer</td> + <td>sequence number of one GTID</td> + </tr> + </table> + + The three elements in the body repeat COUNT times to form the GTID list. + + At the time of writing, only one flag bit is in use. + + Bit 28 of `count' is used for flag FLAG_UNTIL_REACHED, which is sent in a + Gtid_list event from the master to the slave to indicate that the START + SLAVE UNTIL master_gtid_pos=xxx condition has been reached. (This flag is + only sent in "fake" events generated on the fly, it is not written into + the binlog). +*/ + +class Gtid_list_log_event: public Log_event +{ +public: + uint32 count; + uint32 gl_flags; + struct rpl_gtid *list; + uint64 *sub_id_list; + + static const uint element_size= 4+4+8; + static const uint32 FLAG_UNTIL_REACHED= (1<<28); + static const uint32 FLAG_IGN_GTIDS= (1<<29); + +#ifdef MYSQL_SERVER + Gtid_list_log_event(rpl_binlog_state *gtid_set, uint32 gl_flags); + Gtid_list_log_event(slave_connection_state *gtid_set, uint32 gl_flags); +#ifdef HAVE_REPLICATION + void pack_info(THD *thd, Protocol *protocol); +#endif +#else + void print(FILE *file, PRINT_EVENT_INFO *print_event_info); +#endif + Gtid_list_log_event(const char *buf, uint event_len, + const Format_description_log_event *description_event); + ~Gtid_list_log_event() { my_free(list); my_free(sub_id_list); } + Log_event_type get_type_code() { return GTID_LIST_EVENT; } + int get_data_size() { + /* + Replacing with dummy event, needed for older slaves, requires a minimum + of 6 bytes in the body. + */ + return (count==0 ? + GTID_LIST_HEADER_LEN+2 : GTID_LIST_HEADER_LEN+count*element_size); + } + bool is_valid() const { return list != NULL; } +#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) + bool to_packet(String *packet); + bool write(IO_CACHE *file); + virtual int do_apply_event(rpl_group_info *rgi); + enum_skip_reason do_shall_skip(rpl_group_info *rgi); #endif + static bool peek(const char *event_start, uint32 event_len, + uint8 checksum_alg, + rpl_gtid **out_gtid_list, uint32 *out_list_len, + const Format_description_log_event *fdev); }; @@ -2970,7 +3396,7 @@ public: private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const *rli); + virtual int do_apply_event(rpl_group_info *rgi); #endif }; @@ -3025,7 +3451,7 @@ public: private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const *rli); + virtual int do_apply_event(rpl_group_info *rgi); #endif }; @@ -3066,7 +3492,7 @@ public: private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const *rli); + virtual int do_apply_event(rpl_group_info *rgi); #endif }; @@ -3106,7 +3532,7 @@ public: private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const *rli); + virtual int do_apply_event(rpl_group_info *rgi); #endif }; @@ -3139,7 +3565,7 @@ public: Log_event_type get_type_code() { return BEGIN_LOAD_QUERY_EVENT; } private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); + virtual enum_skip_reason do_shall_skip(rpl_group_info *rgi); #endif }; @@ -3205,7 +3631,7 @@ public: private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const *rli); + virtual int do_apply_event(rpl_group_info *rgi); #endif }; @@ -3261,6 +3687,7 @@ public: virtual int get_data_size(); virtual Log_event_type get_type_code(); virtual bool is_valid() const; + virtual bool is_part_of_group() { return 1; } #ifndef MYSQL_CLIENT virtual bool write_data_header(IO_CACHE*); @@ -3277,9 +3704,9 @@ public: #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) private: - virtual int do_apply_event(Relay_log_info const*); - virtual int do_update_pos(Relay_log_info*); - virtual enum_skip_reason do_shall_skip(Relay_log_info*); + virtual int do_apply_event(rpl_group_info *rgi); + virtual int do_update_pos(rpl_group_info *rgi); + virtual enum_skip_reason do_shall_skip(rpl_group_info*); #endif private: @@ -3642,7 +4069,9 @@ public: enum { TM_NO_FLAGS = 0U, - TM_BIT_LEN_EXACT_F = (1U << 0) + TM_BIT_LEN_EXACT_F = (1U << 0), + // MariaDB flags (we starts from the other end) + TM_BIT_HAS_TRIGGERS_F= (1U << 14) }; flag_set get_flags(flag_set flag) const { return m_flags & flag; } @@ -3672,6 +4101,7 @@ public: virtual Log_event_type get_type_code() { return TABLE_MAP_EVENT; } virtual bool is_valid() const { return m_memory != NULL; /* we check malloc */ } + virtual bool is_part_of_group() { return 1; } virtual int get_data_size() { return (uint) m_data_size; } #ifdef MYSQL_SERVER @@ -3692,9 +4122,9 @@ public: private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const *rli); - virtual int do_update_pos(Relay_log_info *rli); - virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); + virtual int do_apply_event(rpl_group_info *rgi); + virtual int do_update_pos(rpl_group_info *rgi); + virtual enum_skip_reason do_shall_skip(rpl_group_info *rgi); #endif #ifdef MYSQL_SERVER @@ -3793,6 +4223,9 @@ public: void clear_flags(flag_set flags_arg) { m_flags &= ~flags_arg; } flag_set get_flags(flag_set flags_arg) const { return m_flags & flags_arg; } + Log_event_type get_type_code() { return m_type; } /* Specific type (_V1 etc) */ + virtual Log_event_type get_general_type_code() = 0; /* General rows op type, no version */ + #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) virtual void pack_info(THD *thd, Protocol *protocol); #endif @@ -3837,9 +4270,16 @@ public: { return m_rows_buf && m_cols.bitmap; } + bool is_part_of_group() { return get_flags(STMT_END_F) != 0; } uint m_row_count; /* The number of rows added to the event */ + const uchar* get_extra_row_data() const { return m_extra_row_data; } + +#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) + virtual uint8 get_trg_event_map()= 0; +#endif + protected: /* The constructors are protected since you're supposed to inherit @@ -3847,10 +4287,10 @@ protected: */ #ifdef MYSQL_SERVER Rows_log_event(THD*, TABLE*, ulong table_id, - MY_BITMAP const *cols, bool is_transactional); + MY_BITMAP const *cols, bool is_transactional, + Log_event_type event_type); #endif Rows_log_event(const char *row_data, uint event_len, - Log_event_type event_type, const Format_description_log_event *description_event); #ifdef MYSQL_CLIENT @@ -3888,6 +4328,12 @@ protected: flag_set m_flags; /* Flags for row-level events */ + Log_event_type m_type; /* Actual event type */ + + uchar *m_extra_row_data; /* Pointer to extra row data if any */ + /* If non null, first byte is length */ + + /* helper functions */ #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) @@ -3896,20 +4342,24 @@ protected: uchar *m_key; /* Buffer to keep key value during searches */ KEY *m_key_info; /* Pointer to KEY info for m_key_nr */ uint m_key_nr; /* Key number */ + bool master_had_triggers; /* set after tables opening */ int find_key(); // Find a best key to use in find_row() - int find_row(const Relay_log_info *const); - int write_row(const Relay_log_info *const, const bool); + int find_row(rpl_group_info *); + int write_row(rpl_group_info *, const bool); // Unpack the current row into m_table->record[0] - int unpack_current_row(const Relay_log_info *const rli) + int unpack_current_row(rpl_group_info *rgi) { DBUG_ASSERT(m_table); ASSERT_OR_RETURN_ERROR(m_curr_row < m_rows_end, HA_ERR_CORRUPT_EVENT); - return ::unpack_row(rli, m_table, m_width, m_curr_row, &m_cols, + return ::unpack_row(rgi, m_table, m_width, m_curr_row, &m_cols, &m_curr_row_end, &m_master_reclength, m_rows_end); } + bool process_triggers(trg_event_type event, + trg_action_time_type time_type, + bool old_row_is_record1); /** Helper function to check whether there is an auto increment @@ -3929,9 +4379,9 @@ protected: private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const *rli); - virtual int do_update_pos(Relay_log_info *rli); - virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); + virtual int do_apply_event(rpl_group_info *rgi); + virtual int do_update_pos(rpl_group_info *rgi); + virtual enum_skip_reason do_shall_skip(rpl_group_info *rgi); /* Primitive to prepare for a sequence of row executions. @@ -3982,7 +4432,7 @@ private: 0 if execution succeeded, 1 if execution failed. */ - virtual int do_exec_row(const Relay_log_info *const rli) = 0; + virtual int do_exec_row(rpl_group_info *rli) = 0; #endif /* defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) */ friend class Old_rows_log_event; @@ -4028,8 +4478,12 @@ public: } #endif +#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) + uint8 get_trg_event_map(); +#endif + private: - virtual Log_event_type get_type_code() { return (Log_event_type)TYPE_CODE; } + virtual Log_event_type get_general_type_code() { return (Log_event_type)TYPE_CODE; } #ifdef MYSQL_CLIENT void print(FILE *file, PRINT_EVENT_INFO *print_event_info); @@ -4038,7 +4492,7 @@ private: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) virtual int do_before_row_operations(const Slave_reporting_capability *const); virtual int do_after_row_operations(const Slave_reporting_capability *const,int); - virtual int do_exec_row(const Relay_log_info *const); + virtual int do_exec_row(rpl_group_info *); #endif }; @@ -4102,8 +4556,12 @@ public: return Rows_log_event::is_valid() && m_cols_ai.bitmap; } +#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) + uint8 get_trg_event_map(); +#endif + protected: - virtual Log_event_type get_type_code() { return (Log_event_type)TYPE_CODE; } + virtual Log_event_type get_general_type_code() { return (Log_event_type)TYPE_CODE; } #ifdef MYSQL_CLIENT void print(FILE *file, PRINT_EVENT_INFO *print_event_info); @@ -4112,7 +4570,7 @@ protected: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) virtual int do_before_row_operations(const Slave_reporting_capability *const); virtual int do_after_row_operations(const Slave_reporting_capability *const,int); - virtual int do_exec_row(const Relay_log_info *const); + virtual int do_exec_row(rpl_group_info *); #endif /* defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) */ }; @@ -4166,9 +4624,13 @@ public: cols, fields, before_record); } #endif - + +#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) + uint8 get_trg_event_map(); +#endif + protected: - virtual Log_event_type get_type_code() { return (Log_event_type)TYPE_CODE; } + virtual Log_event_type get_general_type_code() { return (Log_event_type)TYPE_CODE; } #ifdef MYSQL_CLIENT void print(FILE *file, PRINT_EVENT_INFO *print_event_info); @@ -4177,7 +4639,7 @@ protected: #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) virtual int do_before_row_operations(const Slave_reporting_capability *const); virtual int do_after_row_operations(const Slave_reporting_capability *const,int); - virtual int do_exec_row(const Relay_log_info *const); + virtual int do_exec_row(rpl_group_info *); #endif }; @@ -4241,7 +4703,16 @@ public: { DBUG_ENTER("Incident_log_event::Incident_log_event"); DBUG_PRINT("enter", ("m_incident: %d", m_incident)); - m_message= msg; + m_message.str= NULL; + m_message.length= 0; + if (!(m_message.str= (char*) my_malloc(msg.length+1, MYF(MY_WME)))) + { + /* Mark this event invalid */ + m_incident= INCIDENT_NONE; + DBUG_VOID_RETURN; + } + strmake(m_message.str, msg.str, msg.length); + m_message.length= msg.length; set_direct_logging(); /* Replicate the incident irregardless of @@skip_replication. */ flags&= ~LOG_EVENT_SKIP_REPLICATION_F; @@ -4263,7 +4734,7 @@ public: #endif #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION) - virtual int do_apply_event(Relay_log_info const *rli); + virtual int do_apply_event(rpl_group_info *rgi); #endif virtual bool write_data_header(IO_CACHE *file); @@ -4286,6 +4757,60 @@ private: LEX_STRING m_message; }; +/** + @class Ignorable_log_event + + Base class for ignorable log events. Events deriving from + this class can be safely ignored by slaves that cannot + recognize them. Newer slaves, will be able to read and + handle them. This has been designed to be an open-ended + architecture, so adding new derived events shall not harm + the old slaves that support ignorable log event mechanism + (they will just ignore unrecognized ignorable events). + + @note The only thing that makes an event ignorable is that it has + the LOG_EVENT_IGNORABLE_F flag set. It is not strictly necessary + that ignorable event types derive from Ignorable_log_event; they may + just as well derive from Log_event and pass LOG_EVENT_IGNORABLE_F as + argument to the Log_event constructor. +**/ + +class Ignorable_log_event : public Log_event { +public: + int number; + const char *description; + +#ifndef MYSQL_CLIENT + Ignorable_log_event(THD *thd_arg) + :Log_event(thd_arg, LOG_EVENT_IGNORABLE_F, FALSE), + number(0), description("internal") + { + DBUG_ENTER("Ignorable_log_event::Ignorable_log_event"); + DBUG_VOID_RETURN; + } +#endif + + Ignorable_log_event(const char *buf, + const Format_description_log_event *descr_event, + const char *event_name); + virtual ~Ignorable_log_event(); + +#ifndef MYSQL_CLIENT + void pack_info(THD *, Protocol*); +#endif + +#ifdef MYSQL_CLIENT + virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info); +#endif + + virtual Log_event_type get_type_code() { return IGNORABLE_LOG_EVENT; } + + virtual bool is_valid() const { return 1; } + + virtual int get_data_size() { return IGNORABLE_HEADER_LEN; } +}; + + static inline bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache, FILE *file) { @@ -4338,27 +4863,15 @@ private: bool slave_execute_deferred_events(THD *thd); #endif -int append_query_string(THD *thd, CHARSET_INFO *csinfo, - String const *from, String *to); - bool rpl_get_position_info(const char **log_file_name, ulonglong *log_pos, const char **group_relay_log_name, ulonglong *relay_log_pos); bool event_checksum_test(uchar *buf, ulong event_len, uint8 alg); +bool event_that_should_be_ignored(const char *buf); uint8 get_checksum_alg(const char* buf, ulong len); extern TYPELIB binlog_checksum_typelib; -#ifndef MYSQL_CLIENT -/** - The function is called by slave applier in case there are - active table filtering rules to force gathering events associated - with Query-log-event into an array to execute - them once the fate of the Query is determined for execution. -*/ -bool slave_execute_deferred_events(THD *thd); -#endif - /** @} (end of group Replication) */ |