Commit 8bd5301a authored by Vicențiu Ciorbaru's avatar Vicențiu Ciorbaru

[MDEV-6877] Add binlog writing according to columns

The logging function now writes to the binlog according
to the bitmap columns implied by the binlog_row_image variable.
parent edff3f3f
...@@ -5658,8 +5658,7 @@ static int write_locked_table_maps(THD *thd) ...@@ -5658,8 +5658,7 @@ static int write_locked_table_maps(THD *thd)
} }
typedef bool Log_func(THD*, TABLE*, bool, MY_BITMAP*, typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*);
uint, const uchar*, const uchar*);
static int binlog_log_row(TABLE* table, static int binlog_log_row(TABLE* table,
const uchar *before_record, const uchar *before_record,
...@@ -5705,8 +5704,7 @@ static int binlog_log_row(TABLE* table, ...@@ -5705,8 +5704,7 @@ static int binlog_log_row(TABLE* table,
*/ */
bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE || bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
table->file->has_transactions(); table->file->has_transactions();
error= (*log_func)(thd, table, has_trans, &cols, table->s->fields, error= (*log_func)(thd, table, has_trans, before_record, after_record);
before_record, after_record);
} }
if (!use_bitbuf) if (!use_bitbuf)
my_bitmap_free(&cols); my_bitmap_free(&cols);
......
...@@ -4528,14 +4528,11 @@ public: ...@@ -4528,14 +4528,11 @@ public:
#if defined(MYSQL_SERVER) #if defined(MYSQL_SERVER)
static bool binlog_row_logging_function(THD *thd, TABLE *table, static bool binlog_row_logging_function(THD *thd, TABLE *table,
bool is_transactional, bool is_transactional,
MY_BITMAP *cols,
uint fields,
const uchar *before_record const uchar *before_record
__attribute__((unused)), __attribute__((unused)),
const uchar *after_record) const uchar *after_record)
{ {
return thd->binlog_write_row(table, is_transactional, return thd->binlog_write_row(table, is_transactional, after_record);
cols, fields, after_record);
} }
#endif #endif
...@@ -4596,13 +4593,11 @@ public: ...@@ -4596,13 +4593,11 @@ public:
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
static bool binlog_row_logging_function(THD *thd, TABLE *table, static bool binlog_row_logging_function(THD *thd, TABLE *table,
bool is_transactional, bool is_transactional,
MY_BITMAP *cols,
uint fields,
const uchar *before_record, const uchar *before_record,
const uchar *after_record) const uchar *after_record)
{ {
return thd->binlog_update_row(table, is_transactional, return thd->binlog_update_row(table, is_transactional,
cols, fields, before_record, after_record); before_record, after_record);
} }
#endif #endif
...@@ -4668,14 +4663,12 @@ public: ...@@ -4668,14 +4663,12 @@ public:
#ifdef MYSQL_SERVER #ifdef MYSQL_SERVER
static bool binlog_row_logging_function(THD *thd, TABLE *table, static bool binlog_row_logging_function(THD *thd, TABLE *table,
bool is_transactional, bool is_transactional,
MY_BITMAP *cols,
uint fields,
const uchar *before_record, const uchar *before_record,
const uchar *after_record const uchar *after_record
__attribute__((unused))) __attribute__((unused)))
{ {
return thd->binlog_delete_row(table, is_transactional, return thd->binlog_delete_row(table, is_transactional,
cols, fields, before_record); before_record);
} }
#endif #endif
......
...@@ -369,14 +369,11 @@ public: ...@@ -369,14 +369,11 @@ public:
#if !defined(MYSQL_CLIENT) #if !defined(MYSQL_CLIENT)
static bool binlog_row_logging_function(THD *thd, TABLE *table, static bool binlog_row_logging_function(THD *thd, TABLE *table,
bool is_transactional, bool is_transactional,
MY_BITMAP *cols,
uint fields,
const uchar *before_record const uchar *before_record
__attribute__((unused)), __attribute__((unused)),
const uchar *after_record) const uchar *after_record)
{ {
return thd->binlog_write_row(table, is_transactional, return thd->binlog_write_row(table, is_transactional, after_record);
cols, fields, after_record);
} }
#endif #endif
...@@ -452,7 +449,7 @@ public: ...@@ -452,7 +449,7 @@ public:
const uchar *after_record) const uchar *after_record)
{ {
return thd->binlog_update_row(table, is_transactional, return thd->binlog_update_row(table, is_transactional,
cols, fields, before_record, after_record); before_record, after_record);
} }
#endif #endif
...@@ -526,8 +523,7 @@ public: ...@@ -526,8 +523,7 @@ public:
const uchar *after_record const uchar *after_record
__attribute__((unused))) __attribute__((unused)))
{ {
return thd->binlog_delete_row(table, is_transactional, return thd->binlog_delete_row(table, is_transactional, before_record);
cols, fields, before_record);
} }
#endif #endif
......
...@@ -6112,9 +6112,8 @@ CPP_UNNAMED_NS_START ...@@ -6112,9 +6112,8 @@ CPP_UNNAMED_NS_START
CPP_UNNAMED_NS_END CPP_UNNAMED_NS_END
int THD::binlog_write_row(TABLE* table, bool is_trans, int THD::binlog_write_row(TABLE* table, bool is_trans,
MY_BITMAP const* cols, size_t colcnt, uchar const *record)
uchar const *record)
{ {
DBUG_ASSERT(is_current_stmt_binlog_format_row() && DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
...@@ -6129,7 +6128,7 @@ int THD::binlog_write_row(TABLE* table, bool is_trans, ...@@ -6129,7 +6128,7 @@ int THD::binlog_write_row(TABLE* table, bool is_trans,
uchar *row_data= memory.slot(0); uchar *row_data= memory.slot(0);
size_t const len= pack_row(table, cols, row_data, record); size_t const len= pack_row(table, table->write_set, row_data, record);
/* Ensure that all events in a GTID group are in the same cache */ /* Ensure that all events in a GTID group are in the same cache */
if (variables.option_bits & OPTION_GTID_BEGIN) if (variables.option_bits & OPTION_GTID_BEGIN)
...@@ -6147,13 +6146,19 @@ int THD::binlog_write_row(TABLE* table, bool is_trans, ...@@ -6147,13 +6146,19 @@ int THD::binlog_write_row(TABLE* table, bool is_trans,
} }
int THD::binlog_update_row(TABLE* table, bool is_trans, int THD::binlog_update_row(TABLE* table, bool is_trans,
MY_BITMAP const* cols, size_t colcnt,
const uchar *before_record, const uchar *before_record,
const uchar *after_record) const uchar *after_record)
{ {
DBUG_ASSERT(is_current_stmt_binlog_format_row() && DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
((WSREP(this) && wsrep_emulate_bin_log) || mysql_bin_log.is_open())); ((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 before_maxlen = max_row_length(table, before_record);
size_t const after_maxlen = max_row_length(table, after_record); size_t const after_maxlen = max_row_length(table, after_record);
...@@ -6164,9 +6169,9 @@ int THD::binlog_update_row(TABLE* table, bool is_trans, ...@@ -6164,9 +6169,9 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
uchar *before_row= row_data.slot(0); uchar *before_row= row_data.slot(0);
uchar *after_row= row_data.slot(1); uchar *after_row= row_data.slot(1);
size_t const before_size= pack_row(table, cols, before_row, size_t const before_size= pack_row(table, table->read_set, before_row,
before_record); before_record);
size_t const after_size= pack_row(table, cols, after_row, size_t const after_size= pack_row(table, table->write_set, after_row,
after_record); after_record);
/* Ensure that all events in a GTID group are in the same cache */ /* Ensure that all events in a GTID group are in the same cache */
...@@ -6192,19 +6197,37 @@ int THD::binlog_update_row(TABLE* table, bool is_trans, ...@@ -6192,19 +6197,37 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
if (unlikely(ev == 0)) if (unlikely(ev == 0))
return HA_ERR_OUT_OF_MEM; return HA_ERR_OUT_OF_MEM;
return int error= ev->add_row_data(before_row, before_size) ||
ev->add_row_data(before_row, before_size) || ev->add_row_data(after_row, after_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;
} }
int THD::binlog_delete_row(TABLE* table, bool is_trans, int THD::binlog_delete_row(TABLE* table, bool is_trans,
MY_BITMAP const* cols, size_t colcnt,
uchar const *record) uchar const *record)
{ {
DBUG_ASSERT(is_current_stmt_binlog_format_row() && DBUG_ASSERT(is_current_stmt_binlog_format_row() &&
((WSREP(this) && wsrep_emulate_bin_log) || mysql_bin_log.is_open())); ((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;
/* /**
This will remove spurious fields required during execution but
not needed for binlogging. This is done according to the:
binlog-row-image option.
*/
binlog_prepare_row_images(table);
/*
Pack records into format for transfer. We are allocating more Pack records into format for transfer. We are allocating more
memory than needed, but that doesn't matter. memory than needed, but that doesn't matter.
*/ */
...@@ -6214,7 +6237,8 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans, ...@@ -6214,7 +6237,8 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans,
uchar *row_data= memory.slot(0); uchar *row_data= memory.slot(0);
size_t const len= pack_row(table, cols, row_data, record); DBUG_DUMP("table->read_set", (uchar*) table->read_set->bitmap, (table->s->fields + 7) / 8);
size_t const len= pack_row(table, table->read_set, row_data, record);
/* Ensure that all events in a GTID group are in the same cache */ /* Ensure that all events in a GTID group are in the same cache */
if (variables.option_bits & OPTION_GTID_BEGIN) if (variables.option_bits & OPTION_GTID_BEGIN)
...@@ -6228,10 +6252,81 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans, ...@@ -6228,10 +6252,81 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans,
if (unlikely(ev == 0)) if (unlikely(ev == 0))
return HA_ERR_OUT_OF_MEM; return HA_ERR_OUT_OF_MEM;
return ev->add_row_data(row_data, len);
int error= ev->add_row_data(row_data, len);
/* restore read/write set for the rest of execution */
table->column_bitmaps_set_no_signal(old_read_set,
old_write_set);
return error;
}
void THD::binlog_prepare_row_images(TABLE *table)
{
DBUG_ENTER("THD::binlog_prepare_row_images");
/**
Remove from read_set spurious columns. The write_set has been
handled before in table->mark_columns_needed_for_update.
*/
DBUG_PRINT_BITSET("debug", "table->read_set (before preparing): %s", table->read_set);
THD *thd= table->in_use;
/**
if there is a primary key in the table (ie, user declared PK or a
non-null unique index) and we dont want to ship the entire image,
and the handler involved supports this.
*/
if (table->s->primary_key < MAX_KEY &&
(thd->variables.binlog_row_image < BINLOG_ROW_IMAGE_FULL) &&
!ha_check_storage_engine_flag(table->s->db_type(), HTON_NO_BINLOG_ROW_OPT))
{
/**
Just to be sure that tmp_set is currently not in use as
the read_set already.
*/
DBUG_ASSERT(table->read_set != &table->tmp_set);
bitmap_clear_all(&table->tmp_set);
switch(thd->variables.binlog_row_image)
{
case BINLOG_ROW_IMAGE_MINIMAL:
/* MINIMAL: Mark only PK */
table->mark_columns_used_by_index_no_reset(table->s->primary_key,
&table->tmp_set);
break;
case BINLOG_ROW_IMAGE_NOBLOB:
/**
NOBLOB: Remove unnecessary BLOB fields from read_set
(the ones that are not part of PK).
*/
bitmap_union(&table->tmp_set, table->read_set);
for (Field **ptr=table->field ; *ptr ; ptr++)
{
Field *field= (*ptr);
if ((field->type() == MYSQL_TYPE_BLOB) &&
!(field->flags & PRI_KEY_FLAG))
bitmap_clear_bit(&table->tmp_set, field->field_index);
}
break;
default:
DBUG_ASSERT(0); // impossible.
}
/* set the temporary read_set */
table->column_bitmaps_set_no_signal(&table->tmp_set,
table->write_set);
}
DBUG_PRINT_BITSET("debug", "table->read_set (after preparing): %s", table->read_set);
DBUG_VOID_RETURN;
} }
int THD::binlog_remove_pending_rows_event(bool clear_maps, int THD::binlog_remove_pending_rows_event(bool clear_maps,
bool is_transactional) bool is_transactional)
{ {
......
...@@ -2127,14 +2127,12 @@ public: ...@@ -2127,14 +2127,12 @@ public:
int binlog_write_table_map(TABLE *table, bool is_transactional, int binlog_write_table_map(TABLE *table, bool is_transactional,
my_bool *with_annotate= 0); my_bool *with_annotate= 0);
int binlog_write_row(TABLE* table, bool is_transactional, int binlog_write_row(TABLE* table, bool is_transactional,
MY_BITMAP const* cols, size_t colcnt,
const uchar *buf); const uchar *buf);
int binlog_delete_row(TABLE* table, bool is_transactional, int binlog_delete_row(TABLE* table, bool is_transactional,
MY_BITMAP const* cols, size_t colcnt,
const uchar *buf); const uchar *buf);
int binlog_update_row(TABLE* table, bool is_transactional, int binlog_update_row(TABLE* table, bool is_transactional,
MY_BITMAP const* cols, size_t colcnt,
const uchar *old_data, const uchar *new_data); const uchar *old_data, const uchar *new_data);
void binlog_prepare_row_images(TABLE* table);
void set_server_id(uint32 sid) { variables.server_id = sid; } void set_server_id(uint32 sid) { variables.server_id = sid; }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment