mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Clean up and speed up interfaces for binary row logging
MDEV-21605 Clean up and speed up interfaces for binary row logging MDEV-21617 Bug fix for previous version of this code The intention is to have as few 'if' as possible in ha_write() and related functions. This is done by pre-calculating once per statement the row_logging state for all tables. Benefits are simpler and faster code both when binary logging is disabled and when it's enabled. Changes: - Added handler->row_logging to make it easy to check it table should be row logged. This also made it easier to disabling row logging for system, internal and temporary tables. - The tables row_logging capabilities are checked once per "statements that updates tables" in THD::binlog_prepare_for_row_logging() which is called when needed from THD::decide_logging_format(). - Removed most usage of tmp_disable_binlog(), reenable_binlog() and temporary saving and setting of thd->variables.option_bits. - Moved checks that can't change during a statement from check_table_binlog_row_based() to check_table_binlog_row_based_internal() - Removed flag row_already_logged (used by sequence engine) - Moved binlog_log_row() to a handler:: - Moved write_locked_table_maps() to THD::binlog_write_table_maps() as most other related binlog functions are in THD. - Removed binlog_write_table_map() and binlog_log_row_internal() as they are now obsolete as 'has_transactions()' is pre-calculated in prepare_for_row_logging(). - Remove 'is_transactional' argument from binlog_write_table_map() as this can now be read from handler. - Changed order of 'if's in handler::external_lock() and wsrep_mysqld.h to first evaluate fast and likely cases before more complex ones. - Added error checking in ha_write_row() and related functions if binlog_log_row() failed. - Don't clear check_table_binlog_row_based_result in clear_cached_table_binlog_row_based_flag() as it's not needed. - THD::clear_binlog_table_maps() has been replaced with THD::reset_binlog_for_next_statement() - Added 'MYSQL_OPEN_IGNORE_LOGGING_FORMAT' flag to open_and_lock_tables() to avoid calculating of binary log format for internal opens. This flag is also used to avoid reading statistics tables for internal tables. - Added OPTION_BINLOG_LOG_OFF as a simple way to turn of binlog temporary for create (instead of using THD::sql_log_bin_off. - Removed flag THD::sql_log_bin_off (not needed anymore) - Speed up THD::decide_logging_format() by remembering if blackhole engine is used and avoid a loop over all tables if it's not used (the common case). - THD::decide_logging_format() is not called anymore if no tables are used for the statement. This will speed up pure stored procedure code with about 5%+ according to some simple tests. - We now get annotated events on slave if a CREATE ... SELECT statement is transformed on the slave from statement to row logging. - In the original code, the master could come into a state where row logging is enforced for all future events if statement could be used. This is now partly fixed. Other changes: - Ensure that all tables used by a statement has query_id set. - Had to restore the row_logging flag for not used tables in THD::binlog_write_table_maps (not normal scenario) - Removed injector::transaction::use_table(server_id_type sid, table tbl) as it's not used. - Cleaned up set_slave_thread_options() - Some more DBUG_ENTER/DBUG_RETURN, code comments and minor indentation changes. - Ensure we only call THD::decide_logging_format_low() once in mysql_insert() (inefficiency). - Don't annotate INSERT DELAYED - Removed zeroing pos_in_table_list in THD::open_temporary_table() as it's already 0
This commit is contained in:
@ -959,6 +959,7 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
|
||||
goto values_loop_end;
|
||||
|
||||
THD_STAGE_INFO(thd, stage_update);
|
||||
thd->decide_logging_format_low(table);
|
||||
do
|
||||
{
|
||||
DBUG_PRINT("info", ("iteration %llu", iteration));
|
||||
@ -1071,7 +1072,6 @@ bool mysql_insert(THD *thd, TABLE_LIST *table_list,
|
||||
break;
|
||||
}
|
||||
|
||||
thd->decide_logging_format_low(table);
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
if (lock_type == TL_WRITE_DELAYED)
|
||||
{
|
||||
@ -3051,6 +3051,8 @@ bool Delayed_insert::open_and_lock_table()
|
||||
return TRUE;
|
||||
}
|
||||
table->copy_blobs= 1;
|
||||
|
||||
table->file->prepare_for_row_logging();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -3110,6 +3112,8 @@ pthread_handler_t handle_delayed_insert(void *arg)
|
||||
at which rows are inserted cannot be determined in mixed mode.
|
||||
*/
|
||||
thd->set_current_stmt_binlog_format_row_if_mixed();
|
||||
/* Don't annotate insert delayed binlog events */
|
||||
thd->variables.binlog_annotate_row_events= 0;
|
||||
|
||||
/*
|
||||
Clone tickets representing protection against GRL and the lock on
|
||||
@ -3314,8 +3318,19 @@ pthread_handler_t handle_delayed_insert(void *arg)
|
||||
di->table->file->delete_update_handler();
|
||||
di->group_count=0;
|
||||
mysql_audit_release(thd);
|
||||
/*
|
||||
Reset binlog. We can't call ha_reset() for the table as this will
|
||||
reset the table maps we have calculated earlier.
|
||||
*/
|
||||
mysql_mutex_lock(&di->mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
Reset binlog. We can't call ha_reset() for the table as this will
|
||||
reset the table maps we have calculated earlier.
|
||||
*/
|
||||
thd->reset_binlog_for_next_statement();
|
||||
|
||||
if (di->tables_in_use)
|
||||
mysql_cond_broadcast(&di->cond_client); // If waiting clients
|
||||
}
|
||||
@ -3407,9 +3422,7 @@ bool Delayed_insert::handle_inserts(void)
|
||||
{
|
||||
int error;
|
||||
ulong max_rows;
|
||||
bool has_trans = TRUE;
|
||||
bool using_ignore= 0, using_opt_replace= 0,
|
||||
using_bin_log= mysql_bin_log.is_open();
|
||||
bool using_ignore= 0, using_opt_replace= 0, using_bin_log;
|
||||
delayed_row *row;
|
||||
DBUG_ENTER("handle_inserts");
|
||||
|
||||
@ -3443,7 +3456,13 @@ bool Delayed_insert::handle_inserts(void)
|
||||
|
||||
if (table->file->ha_rnd_init_with_error(0))
|
||||
goto err;
|
||||
/*
|
||||
We have to call prepare_for_row_logging() as the second call to
|
||||
handler_writes() will not have called decide_logging_format.
|
||||
*/
|
||||
table->file->prepare_for_row_logging();
|
||||
table->file->prepare_for_insert();
|
||||
using_bin_log= table->file->row_logging;
|
||||
|
||||
/*
|
||||
We can't use row caching when using the binary log because if
|
||||
@ -3452,6 +3471,7 @@ bool Delayed_insert::handle_inserts(void)
|
||||
*/
|
||||
if (!using_bin_log)
|
||||
table->file->extra(HA_EXTRA_WRITE_CACHE);
|
||||
|
||||
mysql_mutex_lock(&mutex);
|
||||
|
||||
while ((row=rows.get()))
|
||||
@ -3480,8 +3500,8 @@ bool Delayed_insert::handle_inserts(void)
|
||||
Guaranteed that the INSERT DELAYED STMT will not be here
|
||||
in SBR when mysql binlog is enabled.
|
||||
*/
|
||||
DBUG_ASSERT(!(mysql_bin_log.is_open() &&
|
||||
!thd.is_current_stmt_binlog_format_row()));
|
||||
DBUG_ASSERT(!mysql_bin_log.is_open() ||
|
||||
thd.is_current_stmt_binlog_format_row());
|
||||
|
||||
/*
|
||||
This is the first value of an INSERT statement.
|
||||
@ -3639,10 +3659,9 @@ bool Delayed_insert::handle_inserts(void)
|
||||
|
||||
TODO: Move the logging to last in the sequence of rows.
|
||||
*/
|
||||
has_trans= thd.lex->sql_command == SQLCOM_CREATE_TABLE ||
|
||||
table->file->has_transactions();
|
||||
if (thd.is_current_stmt_binlog_format_row() &&
|
||||
thd.binlog_flush_pending_rows_event(TRUE, has_trans))
|
||||
if (table->file->row_logging &&
|
||||
thd.binlog_flush_pending_rows_event(TRUE,
|
||||
table->file->row_logging_has_trans))
|
||||
goto err;
|
||||
|
||||
if (unlikely((error=table->file->extra(HA_EXTRA_NO_CACHE))))
|
||||
@ -4548,6 +4567,18 @@ TABLE *select_create::create_table_from_items(THD *thd, List<Item> *items,
|
||||
/* purecov: end */
|
||||
}
|
||||
table->s->table_creation_was_logged= save_table_creation_was_logged;
|
||||
if (!table->s->tmp_table)
|
||||
table->file->prepare_for_row_logging();
|
||||
|
||||
/*
|
||||
If slave is converting a statement event to row events, log the original
|
||||
create statement as an annotated row
|
||||
*/
|
||||
#ifdef HAVE_REPLICATION
|
||||
if (thd->slave_thread && opt_replicate_annotate_row_events &&
|
||||
thd->is_current_stmt_binlog_format_row())
|
||||
thd->variables.binlog_annotate_row_events= 1;
|
||||
#endif
|
||||
DBUG_RETURN(table);
|
||||
}
|
||||
|
||||
@ -4792,6 +4823,7 @@ bool binlog_create_table(THD *thd, TABLE *table)
|
||||
logged
|
||||
*/
|
||||
thd->set_current_stmt_binlog_format_row();
|
||||
table->file->prepare_for_row_logging();
|
||||
return binlog_show_create_table(thd, table, 0) != 0;
|
||||
}
|
||||
|
||||
@ -4854,6 +4886,9 @@ bool select_create::send_eof()
|
||||
if (table->s->tmp_table)
|
||||
thd->transaction.stmt.mark_created_temp_table();
|
||||
|
||||
if (thd->slave_thread)
|
||||
thd->variables.binlog_annotate_row_events= 0;
|
||||
|
||||
if (prepare_eof())
|
||||
{
|
||||
abort_result_set();
|
||||
|
Reference in New Issue
Block a user