BUG#17066269: AUTO_INC VALUE NOT PROPERLY GENERATED WITH RBR AND
AUTO_INC COLUMN ONLY ON SLAVE In RBR, if the slave's table as one additional auto_inc column, then, it will insert the value 0 instead of generating the next auto_inc number. We fix this by checking that if an auto_inc extra column exists, when compared to column data of the row event, we explicitly set it to NULL and flag the engine that a nulled auto_inc column will be inserted.
This commit is contained in:
parent
afd24eb63d
commit
7481cf6c29
@ -8030,10 +8030,14 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
ulong 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
|
||||
|
||||
@ -9088,9 +9092,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;
|
||||
}
|
||||
|
||||
@ -9099,6 +9122,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) ||
|
||||
@ -9222,7 +9258,13 @@ Rows_log_event::write_row(const Relay_log_info *const rli,
|
||||
ulong estimated_rows= (m_rows_end - m_curr_row) / (m_curr_row_end - m_curr_row);
|
||||
m_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);
|
||||
|
@ -3739,6 +3739,20 @@ protected:
|
||||
ASSERT_OR_RETURN_ERROR(m_curr_row_end <= m_rows_end, HA_ERR_CORRUPT_EVENT);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Helper function to check whether there is an auto increment
|
||||
column on the table where the event is to be applied.
|
||||
|
||||
@return true if there is an autoincrement field on the extra
|
||||
columns, false otherwise.
|
||||
*/
|
||||
inline bool is_auto_inc_in_extra_columns()
|
||||
{
|
||||
DBUG_ASSERT(m_table);
|
||||
return (m_table->next_number_field &&
|
||||
m_table->next_number_field->field_index >= m_width);
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
Loading…
x
Reference in New Issue
Block a user