summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/field.h2
-rw-r--r--sql/log_event.cc17
-rw-r--r--sql/log_event.h6
-rw-r--r--sql/log_event_old.cc6
-rw-r--r--sql/opt_range.cc39
-rw-r--r--sql/rpl_record.cc5
-rw-r--r--sql/sql_class.cc29
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/table.cc88
-rw-r--r--sql/table.h7
10 files changed, 110 insertions, 91 deletions
diff --git a/sql/field.h b/sql/field.h
index e3f2fa5b1ca..cb7f94b6437 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -3093,8 +3093,6 @@ public:
uint32 max_display_length();
uint32 char_length();
uint is_equal(Create_field *new_field);
- inline bool in_read_set() { return bitmap_is_set(table->read_set, field_index); }
- inline bool in_write_set() { return bitmap_is_set(table->write_set, field_index); }
private:
int do_save_field_metadata(uchar *first_byte);
};
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 289d8339728..5e8825e5280 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -9851,6 +9851,7 @@ int Rows_log_event::do_apply_event(rpl_group_info *rgi)
bitmap_intersect(table->read_set,&m_cols);
bitmap_set_all(table->write_set);
+ table->rpl_write_set= table->write_set;
/* WRITE ROWS EVENTS store the bitmap in m_cols instead of m_cols_ai */
MY_BITMAP *after_image= ((get_general_type_code() == UPDATE_ROWS_EVENT) ?
@@ -11109,8 +11110,8 @@ void Table_map_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info)
Write_rows_log_event::Write_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
ulong tid_arg,
bool is_transactional)
- : Rows_log_event(thd_arg, tbl_arg, tid_arg, tbl_arg->write_set,
- is_transactional, WRITE_ROWS_EVENT_V1)
+ :Rows_log_event(thd_arg, tbl_arg, tid_arg, tbl_arg->rpl_write_set,
+ is_transactional, WRITE_ROWS_EVENT_V1)
{
}
#endif
@@ -11218,8 +11219,10 @@ Write_rows_log_event::do_after_row_operations(const Slave_reporting_capability *
*/
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);
+ bitmap_clear_bit(m_table->rpl_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();
@@ -11388,8 +11391,8 @@ Rows_log_event::write_row(rpl_group_info *rgi,
m_table->next_number_field->set_null();
DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
- DBUG_PRINT_BITSET("debug", "write_set = %s", table->write_set);
- DBUG_PRINT_BITSET("debug", "read_set = %s", table->read_set);
+ DBUG_PRINT_BITSET("debug", "rpl_write_set: %s", table->rpl_write_set);
+ DBUG_PRINT_BITSET("debug", "read_set: %s", table->read_set);
if (invoke_triggers &&
process_triggers(TRG_EVENT_INSERT, TRG_ACTION_BEFORE, TRUE))
@@ -12259,7 +12262,7 @@ Update_rows_log_event::Update_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
: Rows_log_event(thd_arg, tbl_arg, tid, tbl_arg->read_set, is_transactional,
UPDATE_ROWS_EVENT_V1)
{
- init(tbl_arg->write_set);
+ init(tbl_arg->rpl_write_set);
}
void Update_rows_log_event::init(MY_BITMAP const *cols)
diff --git a/sql/log_event.h b/sql/log_event.h
index 94f54d6ccc3..498aa8d8d28 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -4304,7 +4304,7 @@ public:
bitmap_cmp return logic).
*/
- virtual bool read_write_bitmaps_cmp(TABLE *table)
+ bool read_write_bitmaps_cmp(TABLE *table)
{
bool res= FALSE;
@@ -4315,10 +4315,10 @@ public:
break;
case UPDATE_ROWS_EVENT:
res= (bitmap_cmp(get_cols(), table->read_set) &&
- bitmap_cmp(get_cols_ai(), table->write_set));
+ bitmap_cmp(get_cols_ai(), table->rpl_write_set));
break;
case WRITE_ROWS_EVENT:
- res= bitmap_cmp(get_cols(), table->write_set);
+ res= bitmap_cmp(get_cols(), table->rpl_write_set);
break;
default:
/*
diff --git a/sql/log_event_old.cc b/sql/log_event_old.cc
index ba844c8ce9b..387534b1bed 100644
--- a/sql/log_event_old.cc
+++ b/sql/log_event_old.cc
@@ -1522,6 +1522,7 @@ int Old_rows_log_event::do_apply_event(rpl_group_info *rgi)
bitmap_set_all(table->write_set);
if (!get_flags(COMPLETE_ROWS_F))
bitmap_intersect(table->write_set,&m_cols);
+ table->rpl_write_set= table->write_set;
// Do event specific preparations
@@ -1896,8 +1897,9 @@ Old_rows_log_event::write_row(rpl_group_info *rgi, const bool overwrite)
DBUG_RETURN(error);
/* unpack row into table->record[0] */
- error= unpack_current_row(rgi); // TODO: how to handle errors?
-
+ if ((error= unpack_current_row(rgi)))
+ DBUG_RETURN(error);
+
#ifndef DBUG_OFF
DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
DBUG_PRINT_BITSET("debug", "write_set = %s", table->write_set);
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 513f76a06f3..7e6753e9bf6 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1519,15 +1519,14 @@ end:
DBUG_ASSERT(head->read_set == &column_bitmap);
/*
We are only going to read key fields and call position() on 'file'
- The following sets head->tmp_set to only use this key and then updates
- head->read_set and head->write_set to use this bitmap.
- The now bitmap is stored in 'column_bitmap' which is used in ::get_next()
+ The following sets head->read_set (== column_bitmap) to only use this
+ key. The 'column_bitmap' is used in ::get_next()
*/
org_file= head->file;
org_key_read= head->key_read;
head->file= file;
head->key_read= 0;
- head->mark_columns_used_by_index_no_reset(index, head->read_set);
+ head->mark_columns_used_by_index_no_reset(index, &column_bitmap);
if (!head->no_keyread)
{
@@ -1551,8 +1550,7 @@ end:
file->ha_close();
goto failure;
}
- else
- DBUG_RETURN(1);
+ DBUG_RETURN(1);
}
DBUG_RETURN(0);
@@ -11141,26 +11139,21 @@ err:
int QUICK_RANGE_SELECT::get_next()
{
range_id_t dummy;
- MY_BITMAP * const save_read_set= head->read_set;
- MY_BITMAP * const save_write_set= head->write_set;
-
+ int result;
DBUG_ENTER("QUICK_RANGE_SELECT::get_next");
- if (in_ror_merged_scan)
- {
- /*
- We don't need to signal the bitmap change as the bitmap is always the
- same for this head->file
- */
- head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap);
- }
- int result= file->multi_range_read_next(&dummy);
+ if (!in_ror_merged_scan)
+ DBUG_RETURN(file->multi_range_read_next(&dummy));
- if (in_ror_merged_scan)
- {
- /* Restore bitmaps set on entry */
- head->column_bitmaps_set_no_signal(save_read_set, save_write_set);
- }
+ MY_BITMAP * const save_read_set= head->read_set;
+ MY_BITMAP * const save_write_set= head->write_set;
+ /*
+ We don't need to signal the bitmap change as the bitmap is always the
+ same for this head->file
+ */
+ head->column_bitmaps_set_no_signal(&column_bitmap, &column_bitmap);
+ result= file->multi_range_read_next(&dummy);
+ head->column_bitmaps_set_no_signal(save_read_set, save_write_set);
DBUG_RETURN(result);
}
diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc
index ee222f02f07..208b2b61704 100644
--- a/sql/rpl_record.cc
+++ b/sql/rpl_record.cc
@@ -200,7 +200,6 @@ unpack_row(rpl_group_info *rgi,
DBUG_ASSERT(row_data);
DBUG_ASSERT(table);
size_t const master_null_byte_count= (bitmap_bits_set(cols) + 7) / 8;
- int error= 0;
uchar const *null_ptr= row_data;
uchar const *pack_ptr= row_data + master_null_byte_count;
@@ -217,7 +216,7 @@ unpack_row(rpl_group_info *rgi,
*/
*current_row_end= pack_ptr;
*master_reclength= 0;
- DBUG_RETURN(error);
+ DBUG_RETURN(0);
}
DBUG_ASSERT(null_ptr < row_data + master_null_byte_count);
@@ -434,7 +433,7 @@ unpack_row(rpl_group_info *rgi,
*master_reclength = table->s->reclength;
}
- DBUG_RETURN(error);
+ DBUG_RETURN(0);
}
/**
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 5054357cadb..1bf48921998 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -6173,7 +6173,7 @@ int THD::binlog_write_row(TABLE* table, bool is_trans,
uchar *row_data= memory.slot(0);
- size_t const len= pack_row(table, table->write_set, row_data, record);
+ size_t const len= pack_row(table, table->rpl_write_set, row_data, record);
/* Ensure that all events in a GTID group are in the same cache */
if (variables.option_bits & OPTION_GTID_BEGIN)
@@ -6197,13 +6197,6 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
((WSREP(this) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()));
- /**
- Save a reference to the original read and write set bitmaps.
- We will need this to restore the bitmaps at the end.
- */
- MY_BITMAP *old_read_set= table->read_set;
- MY_BITMAP *old_write_set= table->write_set;
-
size_t const before_maxlen = max_row_length(table, before_record);
size_t const after_maxlen = max_row_length(table, after_record);
@@ -6216,7 +6209,7 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
size_t const before_size= pack_row(table, table->read_set, before_row,
before_record);
- size_t const after_size= pack_row(table, table->write_set, after_row,
+ size_t const after_size= pack_row(table, table->rpl_write_set, after_row,
after_record);
/* Ensure that all events in a GTID group are in the same cache */
@@ -6245,10 +6238,6 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
int error= ev->add_row_data(before_row, before_size) ||
ev->add_row_data(after_row, after_size);
- /* restore read/write set for the rest of execution */
- table->column_bitmaps_set_no_signal(old_read_set,
- old_write_set);
-
return error;
}
@@ -6259,11 +6248,13 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans,
DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
((WSREP(this) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()));
/**
- Save a reference to the original read and write set bitmaps.
- We will need this to restore the bitmaps at the end.
- */
+ Save a reference to the original read bitmaps
+ We will need this to restore the bitmaps at the end as
+ binlog_prepare_row_images() may change table->read_set.
+ table->read_set is used by pack_row and deep in
+ binlog_prepare_pending_events().
+ */
MY_BITMAP *old_read_set= table->read_set;
- MY_BITMAP *old_write_set= table->write_set;
/**
This will remove spurious fields required during execution but
@@ -6300,9 +6291,9 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans,
int error= ev->add_row_data(row_data, len);
- /* restore read/write set for the rest of execution */
+ /* restore read set for the rest of execution */
table->column_bitmaps_set_no_signal(old_read_set,
- old_write_set);
+ table->write_set);
return error;
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 488826acd70..8d36a763b90 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -2867,6 +2867,8 @@ pthread_handler_t handle_delayed_insert(void *arg)
/* Tell client that the thread is initialized */
mysql_cond_signal(&di->cond_client);
+ di->table->mark_columns_needed_for_insert();
+
/* Now wait until we get an insert or lock to handle */
/* We will not abort as long as a client thread uses this thread */
diff --git a/sql/table.cc b/sql/table.cc
index 573ae0105b6..4604a9a6958 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -2885,20 +2885,28 @@ partititon_err:
/* Allocate bitmaps */
bitmap_size= share->column_bitmap_size;
- if (!(bitmaps= (uchar*) alloc_root(&outparam->mem_root, bitmap_size*6)))
+ if (!(bitmaps= (uchar*) alloc_root(&outparam->mem_root, bitmap_size*7)))
goto err;
my_bitmap_init(&outparam->def_read_set,
- (my_bitmap_map*) bitmaps, share->fields, FALSE);
+ (my_bitmap_map*) bitmaps, share->fields, FALSE);
my_bitmap_init(&outparam->def_write_set,
- (my_bitmap_map*) (bitmaps+bitmap_size), share->fields, FALSE);
+ (my_bitmap_map*) (bitmaps+bitmap_size), share->fields,
+ FALSE);
my_bitmap_init(&outparam->def_vcol_set,
- (my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields, FALSE);
+ (my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields,
+ FALSE);
my_bitmap_init(&outparam->tmp_set,
- (my_bitmap_map*) (bitmaps+bitmap_size*3), share->fields, FALSE);
+ (my_bitmap_map*) (bitmaps+bitmap_size*3), share->fields,
+ FALSE);
my_bitmap_init(&outparam->eq_join_set,
- (my_bitmap_map*) (bitmaps+bitmap_size*4), share->fields, FALSE);
+ (my_bitmap_map*) (bitmaps+bitmap_size*4), share->fields,
+ FALSE);
my_bitmap_init(&outparam->cond_set,
- (my_bitmap_map*) (bitmaps+bitmap_size*5), share->fields, FALSE);
+ (my_bitmap_map*) (bitmaps+bitmap_size*5), share->fields,
+ FALSE);
+ my_bitmap_init(&outparam->def_rpl_write_set,
+ (my_bitmap_map*) (bitmaps+bitmap_size*6), share->fields,
+ FALSE);
outparam->default_column_bitmaps();
outparam->cond_selectivity= 1.0;
@@ -5679,6 +5687,7 @@ void TABLE::clear_column_bitmaps()
*/
bzero((char*) def_read_set.bitmap, s->column_bitmap_size*3);
column_bitmaps_set(&def_read_set, &def_write_set, &def_vcol_set);
+ rpl_write_set= 0; // Safety
}
@@ -5959,6 +5968,8 @@ void TABLE::mark_columns_needed_for_insert()
/*
Mark columns according the binlog row image option.
+ Columns to be written are stored in 'rpl_write_set'
+
When logging in RBR, the user can select whether to
log partial or full rows, depending on the table
definition, and the value of binlog_row_image.
@@ -5970,16 +5981,16 @@ void TABLE::mark_columns_needed_for_insert()
binlog_row_image= MINIMAL
- This marks the PKE fields in the read_set
- This marks all fields where a value was specified
- in the write_set
+ in the rpl_write_set
binlog_row_image= NOBLOB
- This marks PKE + all non-blob fields in the read_set
- This marks all fields where a value was specified
- and all non-blob fields in the write_set
+ and all non-blob fields in the rpl_write_set
binlog_row_image= FULL
- all columns in the read_set
- - all columns in the write_set
+ - all columns in the rpl_write_set
This marking is done without resetting the original
bitmaps. This means that we will strip extra fields in
@@ -5987,36 +5998,48 @@ void TABLE::mark_columns_needed_for_insert()
we only want to log a PK and we needed other fields for
execution).
*/
+
void TABLE::mark_columns_per_binlog_row_image()
{
+ THD *thd= in_use;
DBUG_ENTER("mark_columns_per_binlog_row_image");
DBUG_ASSERT(read_set->bitmap);
DBUG_ASSERT(write_set->bitmap);
- THD *thd= current_thd;
+ /* If not using row format */
+ rpl_write_set= write_set;
/**
If in RBR we may need to mark some extra columns,
depending on the binlog-row-image command line argument.
*/
if ((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) &&
- in_use &&
- in_use->is_current_stmt_binlog_format_row() &&
+ thd->is_current_stmt_binlog_format_row() &&
!ha_check_storage_engine_flag(s->db_type(), HTON_NO_BINLOG_ROW_OPT))
{
/* if there is no PK, then mark all columns for the BI. */
if (s->primary_key >= MAX_KEY)
+ {
bitmap_set_all(read_set);
-
- switch (thd->variables.binlog_row_image)
+ rpl_write_set= read_set;
+ }
+ else
{
+ switch (thd->variables.binlog_row_image) {
case BINLOG_ROW_IMAGE_FULL:
- if (s->primary_key < MAX_KEY)
- bitmap_set_all(read_set);
- bitmap_set_all(write_set);
+ bitmap_set_all(read_set);
+ /* Set of columns that should be written (all) */
+ rpl_write_set= read_set;
break;
case BINLOG_ROW_IMAGE_NOBLOB:
- /* for every field that is not set, mark it unless it is a blob */
+ /* Only write changed columns + not blobs */
+ rpl_write_set= &def_rpl_write_set;
+ bitmap_copy(rpl_write_set, write_set);
+
+ /*
+ for every field that is not set, mark it unless it is a blob or
+ part of a primary key
+ */
for (Field **ptr=field ; *ptr ; ptr++)
{
Field *my_field= *ptr;
@@ -6027,24 +6050,30 @@ void TABLE::mark_columns_per_binlog_row_image()
If set in the AI, then the blob is really needed, there is
nothing we can do about it.
- */
- if ((s->primary_key < MAX_KEY) &&
- ((my_field->flags & PRI_KEY_FLAG) ||
- (my_field->type() != MYSQL_TYPE_BLOB)))
+ */
+ if ((my_field->flags & PRI_KEY_FLAG) ||
+ (my_field->type() != MYSQL_TYPE_BLOB))
+ {
bitmap_set_bit(read_set, my_field->field_index);
-
- if (my_field->type() != MYSQL_TYPE_BLOB)
- bitmap_set_bit(write_set, my_field->field_index);
+ bitmap_set_bit(rpl_write_set, my_field->field_index);
+ }
}
break;
case BINLOG_ROW_IMAGE_MINIMAL:
- /* mark the primary key if available in the read_set */
- if (s->primary_key < MAX_KEY)
- mark_columns_used_by_index_no_reset(s->primary_key, read_set);
+ /*
+ mark the primary key in the read set so that we can find the row
+ that is updated / deleted.
+ We don't need to mark the primary key in the rpl_write_set as the
+ binary log will include all columns read anyway.
+ */
+ mark_columns_used_by_index_no_reset(s->primary_key, read_set);
+ /* Only write columns that have changed */
+ rpl_write_set= write_set;
break;
default:
DBUG_ASSERT(FALSE);
+ }
}
file->column_bitmaps_signal();
}
@@ -7389,4 +7418,3 @@ double KEY::actual_rec_per_key(uint i)
return (is_statistics_from_stat_tables ?
read_stats->get_avg_frequency(i) : (double) rec_per_key[i]);
}
-
diff --git a/sql/table.h b/sql/table.h
index b150e4f2238..6ecfdefc088 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1065,10 +1065,12 @@ public:
ORDER *group;
String alias; /* alias or table name */
uchar *null_flags;
- MY_BITMAP def_read_set, def_write_set, def_vcol_set, tmp_set;
+ MY_BITMAP def_read_set, def_write_set, def_vcol_set, tmp_set;
+ MY_BITMAP def_rpl_write_set;
MY_BITMAP eq_join_set; /* used to mark equi-joined fields */
MY_BITMAP cond_set; /* used to mark fields from sargable conditions*/
- MY_BITMAP *read_set, *write_set, *vcol_set; /* Active column sets */
+ /* Active column sets */
+ MY_BITMAP *read_set, *write_set, *vcol_set, *rpl_write_set;
/*
The ID of the query that opened and is using this table. Has different
meanings depending on the table type.
@@ -1321,6 +1323,7 @@ public:
read_set= &def_read_set;
write_set= &def_write_set;
vcol_set= &def_vcol_set;
+ rpl_write_set= 0;
}
/** Should this instance of the table be reopened? */
inline bool needs_reopen()