diff --git a/mysql-test/suite/binlog_in_engine/binlog_in_engine.result b/mysql-test/suite/binlog_in_engine/binlog_in_engine.result index 037af9b92ca..23fc305feb8 100644 --- a/mysql-test/suite/binlog_in_engine/binlog_in_engine.result +++ b/mysql-test/suite/binlog_in_engine/binlog_in_engine.result @@ -14,6 +14,9 @@ DROP TABLE t1; SELECT @@GLOBAL.binlog_checksum; @@GLOBAL.binlog_checksum NONE +SHOW MASTER STATUS; +File Position Binlog_Do_DB Binlog_Ignore_DB +binlog-000000.ibb 767 CREATE TABLE t2 (a INT PRIMARY KEY, b VARCHAR(2048)) ENGINE=InnoDB; SET SESSION binlog_format= ROW; *** Do 1500 transactions ... diff --git a/mysql-test/suite/binlog_in_engine/binlog_in_engine.test b/mysql-test/suite/binlog_in_engine/binlog_in_engine.test index f591eea4dae..946e5eb8609 100644 --- a/mysql-test/suite/binlog_in_engine/binlog_in_engine.test +++ b/mysql-test/suite/binlog_in_engine/binlog_in_engine.test @@ -19,6 +19,16 @@ SELECT * FROM t1 ORDER BY a; DROP TABLE t1; SELECT @@GLOBAL.binlog_checksum; +# This output will depend on exact size of events, which might change over time. +# If it changes, make the test abort after the SHOW MASTER STATUS, and check +# that the reported new binlog position is correct, it should be the point +# where the file starts containing only zero bytes. +# +# If this gets too annoying to do, we can replace this with something that +# checks that the reported file and position is within some reasonable range +# of the value left by current code. +SHOW MASTER STATUS; + CREATE TABLE t2 (a INT PRIMARY KEY, b VARCHAR(2048)) ENGINE=InnoDB; SET SESSION binlog_format= ROW; diff --git a/sql/handler.h b/sql/handler.h index 49b54b41c05..802fb87bfa9 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1564,7 +1564,12 @@ struct handlerton void (*binlog_oob_free)(THD *thd, void *engine_data); /* Obtain an object to allow reading from the binlog. */ handler_binlog_reader * (*get_binlog_reader)(); - /* Obtain list of binlog files (SHOw BINARY LOGS). */ + /* + Obtain the current position in the binlog. + Used to support legacy SHOW MASTER STATUS. + */ + void (*binlog_status)(char out_filename[FN_REFLEN], ulonglong *out_pos); + /* Obtain list of binlog files (SHOW BINARY LOGS). */ binlog_file_entry * (*get_binlog_file_list)(MEM_ROOT *mem_root); /* End the current binlog file, and create and switch to a new one. diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc index 2da28dc553b..ce1327fd6de 100644 --- a/sql/sql_repl.cc +++ b/sql/sql_repl.cc @@ -5154,13 +5154,27 @@ bool show_binlog_info(THD* thd) if (mysql_bin_log.is_open()) { - LOG_INFO li; - mysql_bin_log.get_current_log(&li); - size_t dir_len = dirname_length(li.log_file_name); - const char *base= li.log_file_name + dir_len; + const char *base; + ulonglong pos; + if (opt_binlog_engine_hton) + { + char buf[FN_REFLEN]; + mysql_mutex_lock(mysql_bin_log.get_log_lock()); + (*opt_binlog_engine_hton->binlog_status)(buf, &pos); + mysql_mutex_unlock(mysql_bin_log.get_log_lock()); + base= buf; + } + else + { + LOG_INFO li; + mysql_bin_log.get_current_log(&li); + pos= (ulonglong) li.pos; + size_t dir_len = dirname_length(li.log_file_name); + base= li.log_file_name + dir_len; + } protocol->store(base, strlen(base), &my_charset_bin); - protocol->store((ulonglong) li.pos); + protocol->store(pos); protocol->store(binlog_filter->get_do_db()); protocol->store(binlog_filter->get_ignore_db()); if (protocol->write()) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index bcdf712cccc..4b24be95c53 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4135,6 +4135,7 @@ static int innodb_init(void* p) innobase_hton->binlog_oob_free= innodb_free_oob; innobase_hton->get_binlog_reader= innodb_get_binlog_reader; innobase_hton->get_binlog_file_list= innodb_get_binlog_file_list; + innobase_hton->binlog_status= innodb_binlog_status; innobase_hton->binlog_flush= innodb_binlog_flush; innobase_hton->binlog_get_init_state= innodb_binlog_get_init_state; innobase_hton->reset_binlogs= innodb_reset_binlogs; diff --git a/storage/innobase/handler/innodb_binlog.cc b/storage/innobase/handler/innodb_binlog.cc index 16d199b0445..e35c438b275 100644 --- a/storage/innobase/handler/innodb_binlog.cc +++ b/storage/innobase/handler/innodb_binlog.cc @@ -2219,6 +2219,19 @@ innodb_find_binlogs(uint64_t *out_first, uint64_t *out_last) } +void +innodb_binlog_status(char out_filename[FN_REFLEN], ulonglong *out_pos) +{ + static_assert(BINLOG_NAME_MAX_LEN <= FN_REFLEN, + "FN_REFLEN too shot to hold InnoDB binlog name"); + uint64_t file_no= active_binlog_file_no.load(std::memory_order_relaxed); + uint32_t page_no= binlog_cur_page_no; + uint32_t in_page_offset= binlog_cur_page_offset; + binlog_name_make_short(out_filename, file_no); + *out_pos= ((ulonglong)page_no << srv_page_size_shift) | in_page_offset; +} + + bool innodb_binlog_get_init_state(rpl_binlog_state_base *out_state) { diff --git a/storage/innobase/include/innodb_binlog.h b/storage/innobase/include/innodb_binlog.h index 795f4f1371e..80c3a53f074 100644 --- a/storage/innobase/include/innodb_binlog.h +++ b/storage/innobase/include/innodb_binlog.h @@ -135,6 +135,8 @@ extern bool innobase_binlog_write_direct (IO_CACHE *cache, handler_binlog_event_group_info *binlog_info, const rpl_gtid *gtid); extern bool innodb_find_binlogs(uint64_t *out_first, uint64_t *out_last); +extern void innodb_binlog_status(char out_filename[FN_REFLEN], + ulonglong *out_pos); extern bool innodb_binlog_get_init_state(rpl_binlog_state_base *out_state); extern bool innodb_reset_binlogs(); extern int innodb_binlog_purge(handler_binlog_purge_info *purge_info);