diff options
Diffstat (limited to 'sql/log_event.cc')
-rw-r--r-- | sql/log_event.cc | 98 |
1 files changed, 88 insertions, 10 deletions
diff --git a/sql/log_event.cc b/sql/log_event.cc index 6610c436302..9846bade696 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1,6 +1,6 @@ /* - Copyright (c) 2000, 2013, Oracle and/or its affiliates. - Copyright (c) 2009, 2013, Monty Program Ab. + 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 @@ -41,6 +41,7 @@ #include "transaction.h" #include <my_dir.h> #include "sql_show.h" // append_identifier +#include <mysql/psi/mysql_statement.h> #include <strfunc.h> #include "compat56.h" @@ -4086,7 +4087,7 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi, if ((error= rows_event_stmt_cleanup(rgi, thd))) { const_cast<Relay_log_info*>(rli)->report(ERROR_LEVEL, error, - "Error in cleaning up after an event preceeding the commit; " + "Error in cleaning up after an event preceding the commit; " "the group log file/position: %s %s", const_cast<Relay_log_info*>(rli)->group_master_log_name, llstr(const_cast<Relay_log_info*>(rli)->group_master_log_pos, @@ -4272,6 +4273,13 @@ int Query_log_event::do_apply_event(rpl_group_info *rgi, Parser_state parser_state; if (!parser_state.init(thd, thd->query(), thd->query_length())) { + thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state, + stmt_info_rpl.m_key, + thd->db, thd->db_length, + thd->charset()); + THD_STAGE_INFO(thd, stage_init); + MYSQL_SET_STATEMENT_TEXT(thd->m_statement_psi, thd->query(), thd->query_length()); + mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); /* Finalize server status flags after executing a statement. */ thd->update_server_status(); @@ -4455,6 +4463,11 @@ end: thd->set_db(NULL, 0); /* will free the current database */ thd->reset_query(); DBUG_PRINT("info", ("end: query= 0")); + + /* Mark the statement completed. */ + MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da()); + thd->m_statement_psi= NULL; + /* As a disk space optimization, future masters will not log an event for LAST_INSERT_ID() if that function returned 0 (and thus they will be able @@ -9432,8 +9445,31 @@ int Rows_log_event::do_add_row_data(uchar *row_data, size_t length) if (static_cast<size_t>(m_rows_end - m_rows_cur) <= length) { size_t const block_size= 1024; - my_ptrdiff_t const cur_size= m_rows_cur - m_rows_buf; - my_ptrdiff_t const new_alloc= + ulong cur_size= m_rows_cur - m_rows_buf; + DBUG_EXECUTE_IF("simulate_too_big_row_case1", + cur_size= UINT_MAX32 - (block_size * 10); + length= UINT_MAX32 - (block_size * 10);); + DBUG_EXECUTE_IF("simulate_too_big_row_case2", + cur_size= UINT_MAX32 - (block_size * 10); + length= block_size * 10;); + DBUG_EXECUTE_IF("simulate_too_big_row_case3", + cur_size= block_size * 10; + length= UINT_MAX32 - (block_size * 10);); + DBUG_EXECUTE_IF("simulate_too_big_row_case4", + cur_size= UINT_MAX32 - (block_size * 10); + length= (block_size * 10) - block_size + 1;); + ulong remaining_space= UINT_MAX32 - cur_size; + /* Check that the new data fits within remaining space and we can add + block_size without wrapping. + */ + if (length > remaining_space || + ((length + block_size) > remaining_space)) + { + sql_print_error("The row data is greater than 4GB, which is too big to " + "write to the binary log."); + DBUG_RETURN(ER_BINLOG_ROW_LOGGING_FAILED); + } + ulong const new_alloc= block_size * ((cur_size + length + block_size - 1) / block_size); uchar* const new_buf= (uchar*)my_realloc((uchar*)m_rows_buf, (uint) new_alloc, @@ -9753,10 +9789,14 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi) /* Bug#56662 Assertion failed: next_insert_id == 0, file handler.cc Don't allow generation of auto_increment value when processing - rows event by setting 'MODE_NO_AUTO_VALUE_ON_ZERO'. + rows event by setting 'MODE_NO_AUTO_VALUE_ON_ZERO'. The exception + to this rule happens when the auto_inc column exists on some + extra columns on the slave. In that case, do not force + MODE_NO_AUTO_VALUE_ON_ZERO. */ ulonglong saved_sql_mode= thd->variables.sql_mode; - thd->variables.sql_mode= MODE_NO_AUTO_VALUE_ON_ZERO; + if (!is_auto_inc_in_extra_columns()) + thd->variables.sql_mode= MODE_NO_AUTO_VALUE_ON_ZERO; // row processing loop @@ -11085,9 +11125,28 @@ Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability * table->auto_increment_field_not_null and SQL_MODE(if includes * MODE_NO_AUTO_VALUE_ON_ZERO) in update_auto_increment function. * SQL_MODE of slave sql thread is always consistency with master's. - * In RBR, auto_increment fields never are NULL. + * In RBR, auto_increment fields never are NULL, except if the auto_inc + * column exists only on the slave side (i.e., in an extra column + * on the slave's table). */ - m_table->auto_increment_field_not_null= TRUE; + if (!is_auto_inc_in_extra_columns()) + m_table->auto_increment_field_not_null= TRUE; + else + { + /* + Here we have checked that there is an extra field + on this server's table that has an auto_inc column. + + Mark that the auto_increment field is null and mark + the read and write set bits. + + (There can only be one AUTO_INC column, it is always + indexed and it cannot have a DEFAULT value). + */ + m_table->auto_increment_field_not_null= FALSE; + m_table->mark_auto_increment_column(); + } + return error; } @@ -11096,6 +11155,19 @@ Write_rows_log_event::do_after_row_operations(const Slave_reporting_capability * int error) { int local_error= 0; + + /** + Clear the write_set bit for auto_inc field that only + existed on the destination table as an extra column. + */ + if (is_auto_inc_in_extra_columns()) + { + bitmap_clear_bit(m_table->write_set, m_table->next_number_field->field_index); + bitmap_clear_bit( m_table->read_set, m_table->next_number_field->field_index); + + if (get_flags(STMT_END_F)) + m_table->file->ha_release_auto_increment(); + } m_table->next_number_field=0; m_table->auto_increment_field_not_null= FALSE; if ((slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT) || @@ -11248,7 +11320,13 @@ Rows_log_event::write_row(rpl_group_info *rgi, ulong estimated_rows= (m_rows_end - m_curr_row) / (m_curr_row_end - m_curr_row); table->file->ha_start_bulk_insert(estimated_rows); } - + + /* + Explicitly set the auto_inc to null to make sure that + it gets an auto_generated value. + */ + if (is_auto_inc_in_extra_columns()) + m_table->next_number_field->set_null(); #ifndef DBUG_OFF DBUG_DUMP("record[0]", table->record[0], table->s->reclength); |