Skip to content

Commit

Permalink
FB8-79: Add option to mysqlbinlog to print encountered gtids on exit (#…
Browse files Browse the repository at this point in the history
…994)

Summary:
Jira ticket: https://jira.percona.com/browse/FB8-79

Reference commit: 49f77bd
Reference commit: 2306b6e
Reference commit: eaa782f
Pull Request resolved: #994

Differential Revision: D14883835

fbshipit-source-id: afbe989
  • Loading branch information
dutow authored and facebook-github-bot committed Nov 18, 2019
1 parent 4a32bcc commit 3bf4433
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 3 deletions.
1 change: 1 addition & 0 deletions client/client_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ enum options_client {
OPT_INNODB_STATS_ON_METADATA,
OPT_DUMP_FBOBJ_STATS,
OPT_MYSQLBINLOG_SKIP_EMPTY_TRANS,
OPT_PRINT_GTIDS,
/* Add new option above this */
OPT_MAX_CLIENT_OPTION
};
Expand Down
56 changes: 53 additions & 3 deletions client/mysqlbinlog.cc
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ Checkable_rwlock *global_sid_lock = nullptr;
Gtid_set *gtid_set_included = nullptr;
Gtid_set *gtid_set_excluded = nullptr;
Gtid_set *gtid_set_stop = nullptr;
static bool opt_print_gtids = false;

static bool opt_print_table_metadata;

Expand Down Expand Up @@ -731,19 +732,23 @@ static bool shall_stop_gtids(Log_event *ev) {
according to the include-gtids, exclude-gtids and
skip-gtids options.
@param ev Pointer to the event to be checked.
@param[in] ev Pointer to the event to be checked.
@param[out] cached_gtid Store the gtid here.
@return true if the event should be filtered out,
false, otherwise.
*/
static bool shall_skip_gtids(const Log_event *ev) {
static bool shall_skip_gtids(const Log_event *ev, Gtid *cached_gtid) {
bool filtered = false;

switch (ev->get_type_code()) {
case binary_log::GTID_LOG_EVENT:
case binary_log::ANONYMOUS_GTID_LOG_EVENT: {
Gtid_log_event *gtid =
const_cast<Gtid_log_event *>(down_cast<const Gtid_log_event *>(ev));
if (gtid->get_sidno(true) > 0 && gtid->get_gno() != 0) {
cached_gtid->set(gtid->get_sidno(true), gtid->get_gno());
}
if (opt_include_gtids_str != nullptr) {
filtered = filtered || !gtid_set_included->contains_gtid(
gtid->get_sidno(true), gtid->get_gno());
Expand All @@ -759,6 +764,12 @@ static bool shall_skip_gtids(const Log_event *ev) {
/* Skip previous gtids if --skip-gtids is set. */
case binary_log::PREVIOUS_GTIDS_LOG_EVENT:
filtered = opt_skip_gtids;
if (opt_print_gtids) {
Previous_gtids_log_event *pgev = (Previous_gtids_log_event *)ev;
global_sid_lock->rdlock();
pgev->add_to_set(gtid_set_excluded);
global_sid_lock->unlock();
}
break;

/*
Expand Down Expand Up @@ -1069,6 +1080,21 @@ void handle_last_rows_query_event(bool print,
last_rows_query_event.event_pos = 0;
}

// Helper for next function
static bool encounter_gtid(Gtid const &cached_gtid) {
global_sid_lock->rdlock();
if (!cached_gtid.is_empty()) {
if (gtid_set_excluded->ensure_sidno(cached_gtid.sidno) !=
RETURN_STATUS_OK) {
global_sid_lock->unlock();
return true;
}
gtid_set_excluded->_add_gtid(cached_gtid);
}
global_sid_lock->unlock();
return false;
}

/**
Print the given event, and either delete it or delegate the deletion
to someone else.
Expand Down Expand Up @@ -1098,6 +1124,7 @@ static Exit_status process_event(PRINT_EVENT_INFO *print_event_info,
DBUG_ENTER("process_event");
Exit_status retval = OK_CONTINUE;
IO_CACHE *const head = &print_event_info->head_cache;
static Gtid cached_gtid;

/*
Format events are not concerned by --offset and such, we always need to
Expand Down Expand Up @@ -1143,7 +1170,7 @@ static Exit_status process_event(PRINT_EVENT_INFO *print_event_info,

DBUG_PRINT("debug", ("event_type: %s", ev->get_type_str()));

if (shall_skip_gtids(ev)) goto end;
if (shall_skip_gtids(ev, &cached_gtid)) goto end;

switch (ev_type) {
case binary_log::QUERY_EVENT: {
Expand Down Expand Up @@ -1228,6 +1255,7 @@ static Exit_status process_event(PRINT_EVENT_INFO *print_event_info,
cur_database = "";
if (skip) break;
}
if (opt_print_gtids && encounter_gtid(cached_gtid)) goto err;
} else if (starts_group) {
in_transaction = true;

Expand Down Expand Up @@ -1302,6 +1330,9 @@ static Exit_status process_event(PRINT_EVENT_INFO *print_event_info,
output of Append_block_log_event::print is only a comment.
*/
ev->print(result_file, print_event_info);

if (opt_print_gtids && encounter_gtid(cached_gtid)) goto err;

if (head->error == -1) goto err;
if ((retval = load_processor.process((Append_block_log_event *)ev)) !=
OK_CONTINUE)
Expand Down Expand Up @@ -1725,6 +1756,8 @@ static struct my_option my_long_options[] = {
#endif
"built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
&port, &port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"print_gtids", OPT_PRINT_GTIDS, "Print encountered gtid set to stderr.",
&opt_print_gtids, &opt_print_gtids, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"protocol", OPT_MYSQL_PROTOCOL,
"The protocol to use for connection (tcp, socket, pipe, memory).", 0, 0, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
Expand Down Expand Up @@ -3391,6 +3424,23 @@ int main(int argc, char **argv) {
fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;\n");
}

// print encountered gtids to stderr
if (opt_print_gtids) {
global_sid_lock->rdlock();
char *encountered_gtids = nullptr;
gtid_set_excluded->to_string(&encountered_gtids);
if (encountered_gtids) {
// Replace new lines with spaces. Easy for parsing the output.
for (char *ptr = encountered_gtids; *ptr; ++ptr) {
if (*ptr == '\n') *ptr = ' ';
}
// NO_LINT_DEBUG
fprintf(stderr, "Executed gtids: %s\n", encountered_gtids);
my_free(encountered_gtids);
}
global_sid_lock->unlock();
}

/*
We should unset the RBR_EXEC_MODE since the user may concatenate output of
multiple runs of mysqlbinlog, all of which may not run in idempotent mode.
Expand Down
1 change: 1 addition & 0 deletions mysql-test/r/mysqlbinlog.result
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,7 @@ DROP TABLE t1;
shell> mysqlbinlog std_data/corrupt-relay-bin.000624 > var/tmp/bug31793.sql
set timestamp= default;
FLUSH LOGS;
Executed gtids:
Bug#31611 Security risk with BINLOG statement
SET BINLOG_FORMAT='ROW';
CREATE DATABASE mysqltest1;
Expand Down
4 changes: 4 additions & 0 deletions mysql-test/r/mysqlbinlog_gtid.result
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,10 @@ include/mysqlbinlog.inc
include/mysqlbinlog.inc
** --stop-gtid without --index-file nor --read-from-remote-master **
include/mysqlbinlog.inc
WARNING: --short-form is deprecated and will be removed in a future version

Executed gtids: uuid:1-5

PURGE BINARY LOGS TO 'master-bin.000002';
include/mysqlbinlog.inc
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
Expand Down
3 changes: 3 additions & 0 deletions mysql-test/t/mysqlbinlog.test
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,9 @@ let $master_binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
--exec $MYSQL_BINLOG --disable-force-if-open $MYSQLD_DATADIR/$master_binlog_file >/dev/null 2>/dev/null
--exec $MYSQL_BINLOG --force-if-open $MYSQLD_DATADIR/$master_binlog_file >/dev/null 2>/dev/null

# Test --print-gtids with gtids disabled
--exec $MYSQL_BINLOG --force-if-open --print-gtids $MYSQLD_DATADIR/$master_binlog_file 2>&1 1>&-

--echo Bug#31611 Security risk with BINLOG statement

SET BINLOG_FORMAT='ROW';
Expand Down
4 changes: 4 additions & 0 deletions mysql-test/t/mysqlbinlog_gtid.test
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ FLUSH LOGS;

-- let $mysqlbinlog_allow_error= 0

# Printing encountered gtids
-- replace_result $MASTER_UUID uuid
-- exec $MYSQL_BINLOG --force-if-open --short_form --index-file=$MYSQLD_DATADIR/master-bin.index --start-gtid=$MASTER_UUID:3 --print-gtids 2>&1 >&-
-- echo

PURGE BINARY LOGS TO 'master-bin.000002';

Expand Down

0 comments on commit 3bf4433

Please sign in to comment.