Post-Header for Query_log_event
| Name |
Format |
Description |
| slave_proxy_id |
4 byte unsigned integer |
An integer identifying the client thread that issued the
query. The id is unique per server. (Note, however, that two
threads on different servers may have the same slave_proxy_id.)
This is used when a client thread creates a temporary table local
to the client. The slave_proxy_id is used to distinguish
temporary tables that belong to different clients.
|
| exec_time |
4 byte unsigned integer |
The time from when the query started to when it was logged in
the binlog, in seconds. |
| db_len |
1 byte integer |
The length of the name of the currently selected database. |
| error_code |
2 byte unsigned integer |
Error code generated by the master. If the master fails, the
slave will fail with the same error code, except for the error
codes ER_DB_CREATE_EXISTS == 1007 and ER_DB_DROP_EXISTS == 1008.
|
| status_vars_len |
2 byte unsigned integer |
The length of the status_vars block of the Body, in bytes. See
@ref query_log_event_status_vars "below".
|
The Body has the following components:
Status variables for Query_log_event
| Status variable |
1 byte identifier |
Format |
Description |
| flags2 |
Q_FLAGS2_CODE == 0 |
4 byte bitfield |
The flags in @c thd->options, binary AND-ed with @c
OPTIONS_WRITTEN_TO_BIN_LOG. The @c thd->options bitfield contains
options for "SELECT". @c OPTIONS_WRITTEN identifies those options
that need to be written to the binlog (not all do).
These flags correspond to the SQL variables SQL_AUTO_IS_NULL,
FOREIGN_KEY_CHECKS, UNIQUE_CHECKS, and AUTOCOMMIT, documented in
the "SET Syntax" section of the MySQL Manual.
This field is always written to the binlog in version >= 5.0, and
never written in version < 5.0.
|
| sql_mode |
Q_SQL_MODE_CODE == 1 |
8 byte bitfield |
The @c sql_mode variable. See the section "SQL Modes" in the
MySQL manual, and see sql_priv.h for a list of the possible
flags. Currently (2007-10-04), the following flags are available:
MODE_REAL_AS_FLOAT==0x1
MODE_PIPES_AS_CONCAT==0x2
MODE_ANSI_QUOTES==0x4
MODE_IGNORE_SPACE==0x8
MODE_IGNORE_BAD_TABLE_OPTIONS==0x10
MODE_ONLY_FULL_GROUP_BY==0x20
MODE_NO_UNSIGNED_SUBTRACTION==0x40
MODE_NO_DIR_IN_CREATE==0x80
MODE_POSTGRESQL==0x100
MODE_ORACLE==0x200
MODE_MSSQL==0x400
MODE_DB2==0x800
MODE_MAXDB==0x1000
MODE_NO_KEY_OPTIONS==0x2000
MODE_NO_TABLE_OPTIONS==0x4000
MODE_NO_FIELD_OPTIONS==0x8000
MODE_MYSQL323==0x10000
MODE_MYSQL323==0x20000
MODE_MYSQL40==0x40000
MODE_ANSI==0x80000
MODE_NO_AUTO_VALUE_ON_ZERO==0x100000
MODE_NO_BACKSLASH_ESCAPES==0x200000
MODE_STRICT_TRANS_TABLES==0x400000
MODE_STRICT_ALL_TABLES==0x800000
MODE_NO_ZERO_IN_DATE==0x1000000
MODE_NO_ZERO_DATE==0x2000000
MODE_INVALID_DATES==0x4000000
MODE_ERROR_FOR_DIVISION_BY_ZERO==0x8000000
MODE_TRADITIONAL==0x10000000
MODE_NO_AUTO_CREATE_USER==0x20000000
MODE_HIGH_NOT_PRECEDENCE==0x40000000
MODE_PAD_CHAR_TO_FULL_LENGTH==0x80000000
All these flags are replicated from the server. However, all
flags except @c MODE_NO_DIR_IN_CREATE are honored by the slave;
the slave always preserves its old value of @c
MODE_NO_DIR_IN_CREATE. For a rationale, see comment in
@c Query_log_event::do_apply_event in @c log_event.cc.
This field is always written to the binlog.
|
| catalog |
Q_CATALOG_NZ_CODE == 6 |
Variable-length string: the length in bytes (1 byte) followed
by the characters (at most 255 bytes)
|
Stores the client's current catalog. Every database belongs
to a catalog, the same way that every table belongs to a
database. Currently, there is only one catalog, "std".
This field is written if the length of the catalog is > 0;
otherwise it is not written.
|
| auto_increment |
Q_AUTO_INCREMENT == 3 |
two 2 byte unsigned integers, totally 2+2=4 bytes |
The two variables auto_increment_increment and
auto_increment_offset, in that order. For more information, see
"System variables" in the MySQL manual.
This field is written if auto_increment > 1. Otherwise, it is not
written.
|
| charset |
Q_CHARSET_CODE == 4 |
three 2 byte unsigned integers, totally 2+2+2=6 bytes |
The three variables character_set_client,
collation_connection, and collation_server, in that order.
character_set_client is a code identifying the character set and
collation used by the client to encode the query.
collation_connection identifies the character set and collation
that the master converts the query to when it receives it; this is
useful when comparing literal strings. collation_server is the
default character set and collation used when a new database is
created.
See also "Connection Character Sets and Collations" in the MySQL
5.1 manual.
All three variables are codes identifying a (character set,
collation) pair. To see which codes map to which pairs, run the
query "SELECT id, character_set_name, collation_name FROM
COLLATIONS".
Cf. Q_CHARSET_DATABASE_CODE below.
This field is always written.
|
| time_zone |
Q_TIME_ZONE_CODE == 5 |
Variable-length string: the length in bytes (1 byte) followed
by the characters (at most 255 bytes).
| The time_zone of the master.
See also "System Variables" and "MySQL Server Time Zone Support"
in the MySQL manual.
This field is written if the length of the time zone string is >
0; otherwise, it is not written.
|
| lc_time_names_number |
Q_LC_TIME_NAMES_CODE == 7 |
2 byte integer |
A code identifying a table of month and day names. The
mapping from codes to languages is defined in @c sql_locale.cc.
This field is written if it is not 0, i.e., if the locale is not
en_US.
|
| charset_database_number |
Q_CHARSET_DATABASE_CODE == 8 |
2 byte integer |
The value of the collation_database system variable (in the
source code stored in @c thd->variables.collation_database), which
holds the code for a (character set, collation) pair as described
above (see Q_CHARSET_CODE).
collation_database was used in old versions (???WHEN). Its value
was loaded when issuing a "use db" query and could be changed by
issuing a "SET collation_database=xxx" query. It used to affect
the "LOAD DATA INFILE" and "CREATE TABLE" commands.
In newer versions, "CREATE TABLE" has been changed to take the
character set from the database of the created table, rather than
the character set of the current database. This makes a
difference when creating a table in another database than the
current one. "LOAD DATA INFILE" has not yet changed to do this,
but there are plans to eventually do it, and to make
collation_database read-only.
This field is written if it is not 0.
|
| table_map_for_update |
Q_TABLE_MAP_FOR_UPDATE_CODE == 9 |
8 byte integer |
The value of the table map that is to be updated by the
multi-table update query statement. Every bit of this variable
represents a table, and is set to 1 if the corresponding table is
to be updated by this statement.
The value of this variable is set when executing a multi-table update
statement and used by slave to apply filter rules without opening
all the tables on slave. This is required because some tables may
not exist on slave because of the filter rules.
|
@subsection Query_log_event_notes_on_previous_versions Notes on Previous Versions
* Status vars were introduced in version 5.0. To read earlier
versions correctly, check the length of the Post-Header.
* The status variable Q_CATALOG_CODE == 2 existed in MySQL 5.0.x,
where 0<=x<=3. It was identical to Q_CATALOG_CODE, except that the
string had a trailing '\0'. The '\0' was removed in 5.0.4 since it
was redundant (the string length is stored before the string). The
Q_CATALOG_CODE will never be written by a new master, but can still
be understood by a new slave.
* See Q_CHARSET_DATABASE_CODE in the table above.
* When adding new status vars, please don't forget to update the
MAX_SIZE_LOG_EVENT_STATUS, and update function code_name
*/
class Query_log_event: public Log_event
{
LEX_CSTRING user;
LEX_CSTRING host;
protected:
Log_event::Byte* data_buf;
public:
const char* query;
const char* catalog;
const char* db;
/*
If we already know the length of the query string
we pass it with q_len, so we would not have to call strlen()
otherwise, set it to 0, in which case, we compute it with strlen()
*/
uint32 q_len;
uint32 db_len;
uint16 error_code;
my_thread_id thread_id;
/*
For events created by Query_log_event::do_apply_event we need the
*original* thread id, to be able to log the event with the original
(=master's) thread id (fix for BUG#1686).
*/
ulong slave_proxy_id;
/*
Binlog format 3 and 4 start to differ (as far as class members are
concerned) from here.
*/
uint catalog_len; // <= 255 char; 0 means uninited
/*
We want to be able to store a variable number of N-bit status vars:
(generally N=32; but N=64 for SQL_MODE) a user may want to log the number
of affected rows (for debugging) while another does not want to lose 4
bytes in this.
The storage on disk is the following:
status_vars_len is part of the post-header,
status_vars are in the variable-length part, after the post-header, before
the db & query.
status_vars on disk is a sequence of pairs (code, value) where 'code' means
'sql_mode', 'affected' etc. Sometimes 'value' must be a short string, so
its first byte is its length. For now the order of status vars is:
flags2 - sql_mode - catalog - autoinc - charset
*/
uint16 status_vars_len;
/*
'flags2' is a second set of flags (on top of those in Log_event), for
session variables. These are thd->options which is & against a mask
(OPTIONS_WRITTEN_TO_BIN_LOG).
flags2_inited helps make a difference between flags2==0 (3.23 or 4.x
master, we don't know flags2, so use the slave server's global options) and
flags2==0 (5.0 master, we know this has a meaning of flags all down which
must influence the query).
*/
uint32 flags2_inited;
bool sql_mode_inited;
bool charset_inited;
LEX_CSTRING character_set_collations;
uint32 flags2;
sql_mode_t sql_mode;
ulong auto_increment_increment, auto_increment_offset;
char charset[6];
uint time_zone_len; /* 0 means uninited */
const char *time_zone_str;
uint lc_time_names_number; /* 0 means en_US */
uint charset_database_number;
/*
map for tables that will be updated for a multi-table update query
statement, for other query statements, this will be zero.
*/
ulonglong table_map_for_update;
/* Xid for the event, if such exists */
ulonglong xid;
/*
A copy of Gtid event's extra flags that is relevant for two-phase
logged ALTER.
*/
uchar gtid_flags_extra;
decltype(rpl_gtid::seq_no) sa_seq_no; /* data part for CA/RA flags */
#ifdef MYSQL_SERVER
Query_log_event(THD* thd_arg, const char* query_arg, size_t query_length,
bool using_trans, bool direct, bool suppress_use, int error);
const char* get_db() override { return db; }
#ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol) override;
#endif /* HAVE_REPLICATION */
#else
bool print_query_header(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info);
bool print_verbose(IO_CACHE* cache, PRINT_EVENT_INFO* print_event_info);
bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override;
#endif
Query_log_event();
Query_log_event(const uchar *buf, uint event_len,
const Format_description_log_event *description_event,
Log_event_type event_type);
~Query_log_event()
{
if (data_buf)
my_free(data_buf);
}
Log_event_type get_type_code() override { return QUERY_EVENT; }
static int dummy_event(String *packet, ulong ev_offset,
enum_binlog_checksum_alg checksum_alg);
static int begin_event(String *packet, ulong ev_offset,
enum_binlog_checksum_alg checksum_alg);
#ifdef MYSQL_SERVER
bool write(Log_event_writer *writer) override;
virtual bool write_post_header_for_derived(Log_event_writer *writer) { return FALSE; }
#endif
bool is_valid() const override { return query != 0; }
/*
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; }
/* Writes derived event-specific part of post header. */
public: /* !!! Public in this patch to allow old usage */
#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
enum_skip_reason do_shall_skip(rpl_group_info *rgi) override;
int do_apply_event(rpl_group_info *rgi) override;
int do_apply_event(rpl_group_info *rgi,
const char *query_arg,
uint32 q_len_arg);
static bool peek_is_commit_rollback(const uchar *event_start,
size_t event_len,
enum_binlog_checksum_alg
checksum_alg);
int handle_split_alter_query_log_event(rpl_group_info *rgi,
bool &skip_error_check);
#endif /* HAVE_REPLICATION */
/*
If true, the event always be applied by slave SQL thread or be printed by
mysqlbinlog
*/
bool is_trans_keyword(bool is_xa)
{
/*
Before the patch for bug#50407, The 'SAVEPOINT and ROLLBACK TO'
queries input by user was written into log events directly.
So the keywords can be written in both upper case and lower case
together, strncasecmp is used to check both cases. they also could be
binlogged with comments in the front of these keywords. for examples:
/ * bla bla * / SAVEPOINT a;
/ * bla bla * / ROLLBACK TO a;
but we don't handle these cases and after the patch, both quiries are
binlogged in upper case with no comments.
*/
return is_xa ? !strncasecmp(query, C_STRING_WITH_LEN("XA "))
: (!strncmp(query, "BEGIN", q_len) ||
!strncmp(query, "COMMIT", q_len) ||
!strncasecmp(query, "SAVEPOINT", 9) ||
!strncasecmp(query, "ROLLBACK", 8));
}
virtual bool is_begin() { return !strcmp(query, "BEGIN"); }
virtual bool is_commit() { return !strcmp(query, "COMMIT"); }
virtual bool is_rollback() { return !strcmp(query, "ROLLBACK"); }
};
class Query_compressed_log_event:public Query_log_event{
protected:
Log_event::Byte* query_buf; // point to the uncompressed query
public:
Query_compressed_log_event(const uchar *buf, uint event_len,
const Format_description_log_event *description_event,
Log_event_type event_type);
~Query_compressed_log_event()
{
if (query_buf)
my_free(query_buf);
}
Log_event_type get_type_code() override { return QUERY_COMPRESSED_EVENT; }
/*
the min length of log_bin_compress_min_len is 10,
means that Begin/Commit/Rollback would never be compressed!
*/
bool is_begin() override { return false; }
bool is_commit() override { return false; }
bool is_rollback() override { return false; }
#ifdef MYSQL_SERVER
Query_compressed_log_event(THD* thd_arg, const char* query_arg,
ulong query_length,
bool using_trans, bool direct, bool suppress_use,
int error);
bool write(Log_event_writer *writer) override;
#endif
};
/*****************************************************************************
sql_ex_info struct
****************************************************************************/
struct sql_ex_info
{
const char* field_term;
const char* enclosed;
const char* line_term;
const char* line_start;
const char* escaped;
int cached_new_format= -1;
uint8 field_term_len= 0, enclosed_len= 0, line_term_len= 0,
line_start_len= 0, escaped_len= 0;
char opt_flags;
char empty_flags= 0;
// store in new format even if old is possible
void force_new_format() { cached_new_format = 1;}
int data_size()
{
return (new_format() ?
field_term_len + enclosed_len + line_term_len +
line_start_len + escaped_len + 6 : 7);
}
bool write_data(Log_event_writer *writer);
const uchar *init(const uchar *buf, const uchar* buf_end, bool use_new_format);
bool new_format()
{
return ((cached_new_format != -1) ? cached_new_format :
(cached_new_format=(field_term_len > 1 ||
enclosed_len > 1 ||
line_term_len > 1 || line_start_len > 1 ||
escaped_len > 1)));
}
};
/**
@class Start_encryption_log_event
Start_encryption_log_event marks the beginning of encrypted data (all events
after this event are encrypted).
It contains the cryptographic scheme used for the encryption as well as any
data required to decrypt (except the actual key).
For binlog cryptoscheme 1: key version, and nonce for iv generation.
*/
class Start_encryption_log_event : public Log_event
{
public:
#ifdef MYSQL_SERVER
Start_encryption_log_event(uint crypto_scheme_arg, uint key_version_arg,
const uchar* nonce_arg)
: crypto_scheme(crypto_scheme_arg), key_version(key_version_arg)
{
cache_type = EVENT_NO_CACHE;
DBUG_ASSERT(crypto_scheme == 1);
memcpy(nonce, nonce_arg, BINLOG_NONCE_LENGTH);
}
bool write_data_body(Log_event_writer *writer) override
{
uchar scheme_buf= crypto_scheme;
uchar key_version_buf[BINLOG_KEY_VERSION_LENGTH];
int4store(key_version_buf, key_version);
return write_data(writer, &scheme_buf, sizeof(scheme_buf)) ||
write_data(writer, key_version_buf, sizeof(key_version_buf)) ||
write_data(writer, nonce, BINLOG_NONCE_LENGTH);
}
#else
bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override;
#endif
Start_encryption_log_event(const uchar *buf, uint event_len,
const Format_description_log_event
*description_event);
bool is_valid() const override { return crypto_scheme == 1; }
Log_event_type get_type_code() override { return START_ENCRYPTION_EVENT; }
int get_data_size() override
{
return BINLOG_CRYPTO_SCHEME_LENGTH + BINLOG_KEY_VERSION_LENGTH +
BINLOG_NONCE_LENGTH;
}
uint crypto_scheme;
uint key_version;
uchar nonce[BINLOG_NONCE_LENGTH];
protected:
#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
int do_apply_event(rpl_group_info* rgi) override;
int do_update_pos(rpl_group_info *rgi) override;
enum_skip_reason do_shall_skip(rpl_group_info* rgi) override
{
return Log_event::EVENT_SKIP_NOT;
}
#endif
};
class Version
{
protected:
uchar m_ver[3];
int cmp(const Version &other) const
{
return memcmp(m_ver, other.m_ver, 3);
}
public:
Version()
{
m_ver[0]= m_ver[1]= m_ver[2]= '\0';
}
Version(uchar v0, uchar v1, uchar v2)
{
m_ver[0]= v0;
m_ver[1]= v1;
m_ver[2]= v2;
}
Version(const char *version, const char **endptr);
const uchar& operator [] (size_t i) const
{
DBUG_ASSERT(i < 3);
return m_ver[i];
}
bool operator<(const Version &other) const { return cmp(other) < 0; }
bool operator>(const Version &other) const { return cmp(other) > 0; }
bool operator<=(const Version &other) const { return cmp(other) <= 0; }
bool operator>=(const Version &other) const { return cmp(other) >= 0; }
};
/**
@class Format_description_log_event
For binlog version 4.
This event is saved by threads which read it, as they need it for future
use (to decode the ordinary events).
@section Format_description_log_event_binary_format Binary Format
*/
class Format_description_log_event: public Log_event
{
public:
/*
If this event is at the start of the first binary log since server
startup 'created' should be the timestamp when the event (and the
binary log) was created. In the other case (i.e. this event is at
the start of a binary log created by FLUSH LOGS or automatic
rotation), 'created' should be 0. This "trick" is used by MySQL
>=4.0.14 slaves to know whether they must drop stale temporary
tables and whether they should abort unfinished transaction.
Note that when 'created'!=0, it is always equal to the event's
timestamp; indeed Start_log_event is written only in log.cc where
the first constructor below is called, in which 'created' is set
to 'when'. So in fact 'created' is a useless variable. When it is
0 we can read the actual value from timestamp ('when') and when it
is non-zero we can read the same value from timestamp
('when'). Conclusion:
- we use timestamp to print when the binlog was created.
- we use 'created' only to know if this is a first binlog or not.
In 3.23.57 we did not pay attention to this identity, so mysqlbinlog in
3.23.57 does not print 'created the_date' if created was zero. This is now
fixed.
*/
time_t created;
uint16 binlog_version;
char server_version[ST_SERVER_VER_LEN];
/*
We set this to 1 if we don't want to have the created time in the log,
which is the case when we rollover to a new log.
*/
bool dont_set_created;
/*
The size of the fixed header which _all_ events have
(for binlogs written by this version, this is equal to
LOG_EVENT_HEADER_LEN), except FORMAT_DESCRIPTION_EVENT and ROTATE_EVENT
(those have a header of size LOG_EVENT_MINIMAL_HEADER_LEN).
*/
uint8 common_header_len;
uint8 number_of_event_types;
/*
The list of post-headers' lengths followed
by the checksum alg description byte
*/
uint8 *post_header_len;
class master_version_split: public Version {
public:
enum {KIND_MYSQL, KIND_MARIADB};
int kind;
master_version_split() :kind(KIND_MARIADB) { }
master_version_split(const char *version);
bool version_is_valid() const
{
/* It is invalid only when all version numbers are 0 */
return !(m_ver[0] == 0 && m_ver[1] == 0 && m_ver[2] == 0);
}
};
master_version_split server_version_split;
const uint8 *event_type_permutation;
uint32 options_written_to_bin_log;
/*
The checksum algorithm used in the binlog or relaylog following this
Format_description_event. Or BINLOG_CHECKSUM_ALG_UNDEF for a
Format_description_event which is not part of a binlog or relaylog file.
*/
enum_binlog_checksum_alg used_checksum_alg;
Format_description_log_event(uint8 binlog_ver, const char* server_ver= 0,
enum_binlog_checksum_alg checksum_alg= BINLOG_CHECKSUM_ALG_UNDEF);
Format_description_log_event(const uchar *buf, uint event_len,
const Format_description_log_event
*description_event);
~Format_description_log_event()
{
my_free(post_header_len);
}
Log_event_type get_type_code() override { return FORMAT_DESCRIPTION_EVENT;}
my_off_t get_header_len(my_off_t) override
{ return LOG_EVENT_MINIMAL_HEADER_LEN; }
#ifdef MYSQL_SERVER
bool write(Log_event_writer *writer) override;
#ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol) override;
#endif /* HAVE_REPLICATION */
#else
bool print(FILE* file, PRINT_EVENT_INFO* print_event_info) override;
#endif
bool header_is_valid() const
{
return common_header_len >= LOG_EVENT_MINIMAL_HEADER_LEN && post_header_len;
}
bool is_valid() const override
{
return header_is_valid() && server_version_split.version_is_valid();
}
int get_data_size() override
{
/*
The vector of post-header lengths is considered as part of the
post-header, because in a given version it never changes (contrary to the
query in a Query_log_event).
*/
return FORMAT_DESCRIPTION_HEADER_LEN;
}
Binlog_crypt_data crypto_data;
bool start_decryption(Start_encryption_log_event* sele);
void copy_crypto_data(const Format_description_log_event* o)
{
crypto_data= o->crypto_data;
}
void reset_crypto()
{
crypto_data.scheme= 0;
}
void calc_server_version_split();
void deduct_options_written_to_bin_log();
static bool is_version_before_checksum(const master_version_split *version_split);
protected:
#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
int do_apply_event(rpl_group_info *rgi) override;
int do_update_pos(rpl_group_info *rgi) override;
enum_skip_reason do_shall_skip(rpl_group_info *rgi) override;
#endif
};
/**
@class Intvar_log_event
An Intvar_log_event will be created just before a Query_log_event,
if the query uses one of the variables LAST_INSERT_ID or INSERT_ID.
Each Intvar_log_event holds the value of one of these variables.
@section Intvar_log_event_binary_format Binary Format
The Post-Header for this event type is empty. The Body has two
components:
Post-Header
| Name |
Format |
Description |
| seq_no |
8 byte unsigned integer |
increasing id within one server_id. Starts at 1, holes in the sequence
may occur |
| domain_id |
4 byte unsigned integer |
Replication domain id, identifying independent replication streams> |
| flags |
1 byte bitfield |
Bit 0 set indicates stand-alone event (no terminating COMMIT) |
Bit 1 set indicates group commit, and that commit id exists |
Bit 2 set indicates a transactional event group (can be safely rolled
back). |
Bit 3 set indicates that user allowed optimistic parallel apply (the
@@SESSION.replicate_allow_parallel value was true at commit). |
Bit 4 set indicates that this transaction encountered a row (or other)
lock wait during execution. |
| Reserved (no group commit) / commit id (group commit) (see flags bit 1) |
6 bytes / 8 bytes |
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). |
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;
uint64 sa_seq_no; // start alter identifier for CA/RA
#ifdef MYSQL_SERVER
event_xid_t xid;
#else
event_mysql_xid_t xid;
#endif
uchar flags2;
/*
More flags area placed after the regular flags2's area. The type
is declared to be in agreement with Query_log_event's member that
may copy the flags_extra value.
*/
decltype(Query_log_event::gtid_flags_extra) flags_extra;
/*
Number of engine participants in transaction minus 1.
When zero the event does not contain that information.
*/
uint8 extra_engines;
/* 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;
/*
FL_TRANSACTIONAL is set for an event group that can be safely rolled back
(no MyISAM, eg.).
*/
static const uchar FL_TRANSACTIONAL= 4;
/*
FL_ALLOW_PARALLEL reflects the (negation of the) value of
@@SESSION.skip_parallel_replication at the time of commit.
*/
static const uchar FL_ALLOW_PARALLEL= 8;
/*
FL_WAITED is set if a row lock wait (or other wait) is detected during the
execution of the transaction.
*/
static const uchar FL_WAITED= 16;
/* FL_DDL is set for event group containing DDL. */
static const uchar FL_DDL= 32;
/* FL_PREPARED_XA is set for XA transaction. */
static const uchar FL_PREPARED_XA= 64;
/* FL_"COMMITTED or ROLLED-BACK"_XA is set for XA transaction. */
static const uchar FL_COMPLETED_XA= 128;
/*
flags_extra 's bit values.
_E1 suffix below stands for Extra to infer the extra flags,
their "1st" generation (more *generations* can come when necessary).
FL_EXTRA_MULTI_ENGINE_E1 is set for event group comprising a transaction
involving multiple storage engines. No flag and extra data are added
to the event when the transaction involves only one engine.
*/
static const uchar FL_EXTRA_MULTI_ENGINE_E1= 1;
static const uchar FL_START_ALTER_E1= 2;
static const uchar FL_COMMIT_ALTER_E1= 4;
static const uchar FL_ROLLBACK_ALTER_E1= 8;
#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,
bool has_xid= false, bool is_ro_1pc= false);
#ifdef HAVE_REPLICATION
void pack_info(Protocol *protocol) override;
int do_apply_event(rpl_group_info *rgi) override;
int do_update_pos(rpl_group_info *rgi) override;
enum_skip_reason do_shall_skip(rpl_group_info *rgi) override;
#endif
#else
bool print(FILE *file, PRINT_EVENT_INFO *print_event_info) override;
#endif
Gtid_log_event(const uchar *buf, uint event_len,
const Format_description_log_event *description_event);
~Gtid_log_event() = default;
Log_event_type get_type_code() override { return GTID_EVENT; }
enum_logged_status logged_status() override { return LOGGED_NO_DATA; }
int get_data_size() override
{
return GTID_HEADER_LEN + ((flags2 & FL_GROUP_COMMIT_ID) ? 2 : 0);
}
bool is_valid() const override
{
/*
seq_no is set to 0 if the structure of a serialized GTID event does not
align with that as indicated by flags and extra_flags.
*/
return seq_no != 0;
}
#ifdef MYSQL_SERVER
bool write(Log_event_writer *writer) override;
static int make_compatible_event(String *packet, bool *need_dummy_event,
ulong ev_offset, enum_binlog_checksum_alg checksum_alg);
static bool peek(const uchar *event_start, size_t event_len,
enum_binlog_checksum_alg 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
Body for Table_map_log_event
| Name |
Format |
Description |
| database_name |
one byte string length, followed by null-terminated string |
The name of the database in which the table resides. The name
is represented as a one byte unsigned integer representing the
number of bytes in the name, followed by length bytes containing
the database name, followed by a terminating 0 byte. (Note the
redundancy in the representation of the length.) |
| table_name |
one byte string length, followed by null-terminated string |
The name of the table, encoded the same way as the database
name above. |
| column_count |
@ref packed_integer "Packed Integer" |
The number of columns in the table, represented as a packed
variable-length integer. |
| column_type |
List of column_count 1 byte enumeration values |
The type of each column in the table, listed from left to
right. Each byte is mapped to a column type according to the
enumeration type enum_field_types defined in mysql_com.h. The
mapping of types to numbers is listed in the table @ref
Table_table_map_log_event_column_types "below" (along with
description of the associated metadata field). |
| metadata_length |
@ref packed_integer "Packed Integer" |
The length of the following metadata block |
| metadata |
list of metadata for each column |
For each column from left to right, a chunk of data who's
length and semantics depends on the type of the column. The
length and semantics for the metadata for each column are listed
in the table @ref Table_table_map_log_event_column_types
"below". |
| null_bits |
column_count bits, rounded up to nearest byte |
For each column, a bit indicating whether data in the column
can be NULL or not. The number of bytes needed for this is
int((column_count+7)/8). The flag for the first column from the
left is in the least-significant bit of the first byte, the second
is in the second least significant bit of the first byte, the
ninth is in the least significant bit of the second byte, and so
on. |
| optional metadata fields |
optional metadata fields are stored in Type, Length, Value(TLV) format.
Type takes 1 byte. Length is a packed integer value. Values takes
Length bytes.
|
There are some optional metadata defined. They are listed in the table
@ref Table_table_map_event_optional_metadata. Optional metadata fields
follow null_bits. Whether binlogging an optional metadata is decided by the
server. The order is not defined, so they can be binlogged in any order.
|
The table below lists all column types, along with the numerical
identifier for it and the size and interpretation of meta-data used
to describe the type.
@anchor Table_table_map_log_event_column_types
Table_map_log_event column types: numerical identifier and
metadata
| Name |
Identifier |
Size of metadata in bytes |
Description of metadata |
| MYSQL_TYPE_DECIMAL | 0 |
0 |
No column metadata. |
| MYSQL_TYPE_TINY | 1 |
0 |
No column metadata. |
| MYSQL_TYPE_SHORT | 2 |
0 |
No column metadata. |
| MYSQL_TYPE_LONG | 3 |
0 |
No column metadata. |
| MYSQL_TYPE_FLOAT | 4 |
1 byte |
1 byte unsigned integer, representing the "pack_length", which
is equal to sizeof(float) on the server from which the event
originates. |
| MYSQL_TYPE_DOUBLE | 5 |
1 byte |
1 byte unsigned integer, representing the "pack_length", which
is equal to sizeof(double) on the server from which the event
originates. |
| MYSQL_TYPE_NULL | 6 |
0 |
No column metadata. |
| MYSQL_TYPE_TIMESTAMP | 7 |
0 |
No column metadata. |
| MYSQL_TYPE_LONGLONG | 8 |
0 |
No column metadata. |
| MYSQL_TYPE_INT24 | 9 |
0 |
No column metadata. |
| MYSQL_TYPE_DATE | 10 |
0 |
No column metadata. |
| MYSQL_TYPE_TIME | 11 |
0 |
No column metadata. |
| MYSQL_TYPE_DATETIME | 12 |
0 |
No column metadata. |
| MYSQL_TYPE_YEAR | 13 |
0 |
No column metadata. |
| MYSQL_TYPE_NEWDATE | 14 |
– |
This enumeration value is only used internally and cannot
exist in a binlog. |
| MYSQL_TYPE_VARCHAR | 15 |
2 bytes |
2 byte unsigned integer representing the maximum length of
the string. |
| MYSQL_TYPE_BIT | 16 |
2 bytes |
A 1 byte unsigned int representing the length in bits of the
bitfield (0 to 64), followed by a 1 byte unsigned int
representing the number of bytes occupied by the bitfield. The
number of bytes is either int((length+7)/8) or int(length/8). |
| MYSQL_TYPE_NEWDECIMAL | 246 |
2 bytes |
A 1 byte unsigned int representing the precision, followed
by a 1 byte unsigned int representing the number of decimals. |
| MYSQL_TYPE_ENUM | 247 |
– |
This enumeration value is only used internally and cannot
exist in a binlog. |
| MYSQL_TYPE_SET | 248 |
– |
This enumeration value is only used internally and cannot
exist in a binlog. |
| MYSQL_TYPE_TINY_BLOB | 249 |
– |
This enumeration value is only used internally and cannot
exist in a binlog. |
| MYSQL_TYPE_MEDIUM_BLOB | 250 |
– |
This enumeration value is only used internally and cannot
exist in a binlog. |
| MYSQL_TYPE_LONG_BLOB | 251 |
– |
This enumeration value is only used internally and cannot
exist in a binlog. |
| MYSQL_TYPE_BLOB | 252 |
1 byte |
The pack length, i.e., the number of bytes needed to represent
the length of the blob: 1, 2, 3, or 4. |
| MYSQL_TYPE_VAR_STRING | 253 |
2 bytes |
This is used to store both strings and enumeration values.
The first byte is a enumeration value storing the real
type, which may be either MYSQL_TYPE_VAR_STRING or
MYSQL_TYPE_ENUM. The second byte is a 1 byte unsigned integer
representing the field size, i.e., the number of bytes needed to
store the length of the string. |
| MYSQL_TYPE_STRING | 254 |
2 bytes |
The first byte is always MYSQL_TYPE_VAR_STRING (i.e., 253).
The second byte is the field size, i.e., the number of bytes in
the representation of size of the string: 3 or 4. |
| MYSQL_TYPE_GEOMETRY | 255 |
1 byte |
The pack length, i.e., the number of bytes needed to represent
the length of the geometry: 1, 2, 3, or 4. |
The table below lists all optional metadata types, along with the numerical
identifier for it and the size and interpretation of meta-data used
to describe the type.
@anchor Table_table_map_event_optional_metadata
Table_map_event optional metadata types: numerical identifier and
metadata. Optional metadata fields are stored in TLV fields.
Format of values are described in this table.
| Type |
Description |
Format |
| SIGNEDNESS |
signedness of numeric colums. This is included for all values of
binlog_row_metadata. |
For each numeric column, a bit indicates whether the numeric
colunm has unsigned flag. 1 means it is unsigned. The number of
bytes needed for this is int((column_count + 7) / 8). The order is
the same as the order of column_type field. |
| DEFAULT_CHARSET |
Charsets of character columns. It has a default charset for
the case that most of character columns have same charset and the
most used charset is binlogged as default charset.Collation
numbers are binlogged for identifying charsets. They are stored in
packed length format. Either DEFAULT_CHARSET or COLUMN_CHARSET is
included for all values of binlog_row_metadata. |
Default charset's collation is logged first. The charsets which are not
same to default charset are logged following default charset. They are
logged as column index and charset collation number pair sequence. The
column index is counted only in all character columns. The order is same to
the order of column_type
field. |
| COLUMN_CHARSET |
Charsets of character columns. For the case that most of columns have
different charsets, this field is logged. It is never logged with
DEFAULT_CHARSET together. Either DEFAULT_CHARSET or COLUMN_CHARSET is
included for all values of binlog_row_metadata. |
It is a collation number sequence for all character columns. |
| COLUMN_NAME |
Names of columns. This is only included if
binlog_row_metadata=FULL. |
A sequence of column names. For each column name, 1 byte for
the string length in bytes is followed by a string without null
terminator. |
| SET_STR_VALUE |
The string values of SET columns. This is only included if
binlog_row_metadata=FULL. |
For each SET column, a pack_length representing the value
count is followed by a sequence of length and string pairs. length
is the byte count in pack_length format. The string has no null
terminator. |
| ENUM_STR_VALUE |
The string values is ENUM columns. This is only included
if binlog_row_metadata=FULL. |
The format is the same as SET_STR_VALUE. |
| GEOMETRY_TYPE |
The real type of geometry columns. This is only included
if binlog_row_metadata=FULL. |
A sequence of real type of geometry columns are stored in pack_length
format. |
| SIMPLE_PRIMARY_KEY |
The primary key without any prefix. This is only included
if binlog_row_metadata=FULL and there is a primary key where every
key part covers an entire column. |
A sequence of column indexes. The indexes are stored in pack_length
format. |
| PRIMARY_KEY_WITH_PREFIX |
The primary key with some prefix. It doesn't appear together with
SIMPLE_PRIMARY_KEY. This is only included if
binlog_row_metadata=FULL and there is a primary key where some key
part covers a prefix of the column. |
A sequence of column index and prefix length pairs. Both
column index and prefix length are in pack_length format. Prefix length
0 means that the whole column value is used. |
| ENUM_AND_SET_DEFAULT_CHARSET |
Charsets of ENUM and SET columns. It has the same layout as
DEFAULT_CHARSET. If there are SET or ENUM columns and
binlog_row_metadata=FULL, exactly one of
ENUM_AND_SET_DEFAULT_CHARSET and ENUM_AND_SET_COLUMN_CHARSET
appears (the encoder chooses the representation that uses the
least amount of space). Otherwise, none of them appears. |
The same format as for DEFAULT_CHARSET, except it counts ENUM
and SET columns rather than character columns. |
| ENUM_AND_SET_COLUMN_CHARSET |
Charsets of ENUM and SET columns. It has the same layout as
COLUMN_CHARSET. If there are SET or ENUM columns and
binlog_row_metadata=FULL, exactly one of
ENUM_AND_SET_DEFAULT_CHARSET and ENUM_AND_SET_COLUMN_CHARSET
appears (the encoder chooses the representation that uses the
least amount of space). Otherwise, none of them appears. |
The same format as for COLUMN_CHARSET, except it counts ENUM
and SET columns rather than character columns. |
*/
class Table_map_log_event : public Log_event
{
public:
/* Constants */
enum
{
TYPE_CODE = TABLE_MAP_EVENT
};
/**
Enumeration of the errors that can be returned.
*/
enum enum_error
{
ERR_OPEN_FAILURE = -1, /**< Failure to open table */
ERR_OK = 0, /**< No error */
ERR_TABLE_LIMIT_EXCEEDED = 1, /**< No more room for tables */
ERR_OUT_OF_MEM = 2, /**< Out of memory */
ERR_BAD_TABLE_DEF = 3, /**< Table definition does not match */
ERR_RBR_TO_SBR = 4 /**< daisy-chanining RBR to SBR not allowed */
};
enum enum_flag
{
/*
Nothing here right now, but the flags support is there in
preparation for changes that are coming. Need to add a
constant to make it compile under HP-UX: aCC does not like
empty enumerations.
*/
ENUM_FLAG_COUNT
};
typedef uint16 flag_set;
/**
DEFAULT_CHARSET and COLUMN_CHARSET don't appear together, and
ENUM_AND_SET_DEFAULT_CHARSET and ENUM_AND_SET_COLUMN_CHARSET don't
appear together. They are just alternative ways to pack character
set information. When binlogging, it logs character sets in the
way that occupies least storage.
SIMPLE_PRIMARY_KEY and PRIMARY_KEY_WITH_PREFIX don't appear together.
SIMPLE_PRIMARY_KEY is for the primary keys which only use whole values of
pk columns. PRIMARY_KEY_WITH_PREFIX is
for the primary keys which just use part value of pk columns.
*/
enum Optional_metadata_field_type
{
SIGNEDNESS = 1, // UNSIGNED flag of numeric columns
DEFAULT_CHARSET, /* Character set of string columns, optimized to
minimize space when many columns have the
same charset. */
COLUMN_CHARSET, /* Character set of string columns, optimized to
minimize space when columns have many
different charsets. */
COLUMN_NAME,
SET_STR_VALUE, // String value of SET columns
ENUM_STR_VALUE, // String value of ENUM columns
GEOMETRY_TYPE, // Real type of geometry columns
SIMPLE_PRIMARY_KEY, // Primary key without prefix
PRIMARY_KEY_WITH_PREFIX, // Primary key with prefix
ENUM_AND_SET_DEFAULT_CHARSET, /* Character set of enum and set
columns, optimized to minimize
space when many columns have the
same charset. */
ENUM_AND_SET_COLUMN_CHARSET, /* Character set of enum and set
columns, optimized to minimize
space when many columns have the
same charset. */
};
/**
Metadata_fields organizes m_optional_metadata into a structured format which
is easy to access.
*/
// Values for binlog_row_metadata sysvar
enum enum_binlog_row_metadata
{
BINLOG_ROW_METADATA_NO_LOG= 0,
BINLOG_ROW_METADATA_MINIMAL= 1,
BINLOG_ROW_METADATA_FULL= 2
};
struct Optional_metadata_fields
{
typedef std::pair