Skip to content

Commit b1fec60

Browse files
Removing unchanged columns from AI when when row image is not FULL
Summary: Some update and upsert (insert ... on duplicate key update) queries used to log columns which have not changed in the after image (when using RBR) even when the image format is not FULL. Test Plan: Extended rpl_row_img_sanity to check these special cases Reviewers: santoshb Reviewed By: santoshb Subscribers: webscalesql-eng Differential Revision: https://reviews.facebook.net/D65133
1 parent a704b91 commit b1fec60

File tree

6 files changed

+123
-31
lines changed

6 files changed

+123
-31
lines changed

mysql-test/suite/rpl/r/rpl_row_img_sanity.result

+6
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,9 @@ include/rpl_reset.inc
448448
include/sync_slave_sql_with_master.inc
449449
####### MINIMAL OTHER PARTICULAR SCENARIO ######
450450
include/sync_slave_sql_with_master.inc
451+
####### MINIMAL AND COMPLETE PARTICULAR SCENARIO SETTING SAME VALUE ######
452+
include/sync_slave_sql_with_master.inc
453+
include/sync_slave_sql_with_master.inc
451454
CON: 'master', IMG: 'NOBLOB', RESTART SLAVE: 'N'
452455
Variable_name Value
453456
binlog_row_image NOBLOB
@@ -489,6 +492,9 @@ include/rpl_reset.inc
489492
include/sync_slave_sql_with_master.inc
490493
include/sync_slave_sql_with_master.inc
491494
include/rpl_reset.inc
495+
####### MINIMAL AND COMPLETE PARTICULAR SCENARIO SETTING SAME VALUE ######
496+
include/sync_slave_sql_with_master.inc
497+
include/sync_slave_sql_with_master.inc
492498
################## SPECIAL CASES #########################
493499
include/rpl_reset.inc
494500
CON: 'master', IMG: 'NOBLOB', RESTART SLAVE: 'N'

mysql-test/suite/rpl/t/rpl_row_img_sanity.test

+68-24
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ while (`SELECT HEX(@img_types) != HEX('')`)
333333
# 1. columns that are set to default value are in AI
334334
#
335335
# UPDATE/MINIMAL:
336-
# 2. columns that are set to the same value are in AI
336+
# 2. columns that are set to the same value are not in AI
337337
# 3. columns that are not in WHERE clause but in PKE are in BI
338338
# 4. on slave, columns that are not in master's BI but are in slave's
339339
# PKE are in slave's BI
@@ -359,11 +359,11 @@ while (`SELECT HEX(@img_types) != HEX('')`)
359359
-- source include/rpl_row_img_parts_master_slave.inc
360360

361361
-- let $row_img_query= UPDATE t SET c2=100, c3=1000 WHERE c2=100;
362-
# 2. columns that are set to the same value are in AI
362+
# 2. columns that are set to the same value are not in AI
363363
# 3. columns that are not in WHERE clause but in PKE are in BI
364364
# 4. on slave, columns that are not in master's BI but are in slave's PKE are in slave's BI
365-
-- let $row_img_expected_master= 1:1 | 2:100 3:1000
366-
-- let $row_img_expected_slave = 2:100 3:1 | 2:100 3:1000
365+
-- let $row_img_expected_master= 1:1 | 3:1000
366+
-- let $row_img_expected_slave = 2:100 3:1 | 3:1000
367367
-- source include/rpl_row_img_parts_master_slave.inc
368368

369369
-- let $row_img_query= DELETE FROM t WHERE c1=1
@@ -410,6 +410,54 @@ while (`SELECT HEX(@img_types) != HEX('')`)
410410
--source include/sync_slave_sql_with_master.inc
411411
}
412412

413+
if (`SELECT @@binlog_row_image = "MINIMAL" OR (SELECT @@binlog_row_image = "COMPLETE")`)
414+
{
415+
-- echo ####### MINIMAL AND COMPLETE PARTICULAR SCENARIO SETTING SAME VALUE ######
416+
417+
# ASSERTIONS:
418+
# 1. columns that are set to the same value are not in AI
419+
# 2. columns that are set to the same value by INSERT ... DUPLICATE KEY
420+
# are not in AI
421+
#
422+
423+
-- connection master
424+
CREATE TABLE t (c1 int, c2 int, c3 blob, primary key(c1));
425+
INSERT INTO t VALUES (1,2,"a");
426+
427+
428+
--source include/sync_slave_sql_with_master.inc
429+
-- connection master
430+
431+
# Issue some statements
432+
-- let $row_img_query= UPDATE t SET c1 = 1, c2 = 4 WHERE c3 = "a";
433+
if (`SELECT @@binlog_row_image = "MINIMAL"`)
434+
{
435+
-- let $row_img_expected_master= 1:1 | 2:4
436+
}
437+
if (`SELECT @@binlog_row_image = "COMPLETE"`)
438+
{
439+
-- let $row_img_expected_master= 1:1 2:2 3:'a' | 2:4
440+
}
441+
-- let $row_img_expected_slave = $row_img_expected_master
442+
-- source include/rpl_row_img_parts_master_slave.inc
443+
444+
-- let $row_img_query= INSERT INTO t VALUES (1, 4, "a") ON DUPLICATE KEY UPDATE c2 = c2 + 2, c3 = values(c3);
445+
if (`SELECT @@binlog_row_image = "MINIMAL"`)
446+
{
447+
-- let $row_img_expected_master= 1:1 | 2:6
448+
}
449+
if (`SELECT @@binlog_row_image = "COMPLETE"`)
450+
{
451+
-- let $row_img_expected_master= 1:1 2:4 3:'a' | 2:6
452+
}
453+
-- let $row_img_expected_slave = $row_img_expected_master
454+
-- source include/rpl_row_img_parts_master_slave.inc
455+
456+
-- connection master
457+
DROP TABLE t;
458+
--source include/sync_slave_sql_with_master.inc
459+
}
460+
413461
if (`SELECT @@binlog_row_image = "NOBLOB"`)
414462
{
415463
-- echo ####### NOBLOB PARTICULAR SCENARIO ######
@@ -419,19 +467,17 @@ while (`SELECT HEX(@img_types) != HEX('')`)
419467
# 1 non-blob columns that are set to default value are in AI
420468
#
421469
# UPDATE/NOBLOB:
422-
# 2 non-blob columns that are set to default value are in AI
423-
# 3 blob columns that are set to default value are in AI
424-
# 4 blob columns that are in WHERE clause but not in PKE are not in BI
425-
# 5 blob columns that are in NON-NULL UK but not in PK are not in BI
426-
# 6 on slave, blob columns that are in master's BI clause but not in
470+
# 2 blob columns that are in WHERE clause but not in PKE are not in BI
471+
# 3 blob columns that are in NON-NULL UK but not in PK are not in BI
472+
# 4 on slave, blob columns that are in master's BI clause but not in
427473
# slave's PKE are not in BI
428474
#
429475
# DELETE
430-
# 7 non-blob columns that are not in WHERE clause but in PKE are in BI
431-
# 8 blob columns that are used in WHERE clause but not in PKE are not
476+
# 5 non-blob columns that are not in WHERE clause but in PKE are in BI
477+
# 6 blob columns that are used in WHERE clause but not in PKE are not
432478
# in BI
433-
# 9 blob columns that are NOT NULL UK but not in PK are not in BI
434-
# 10 on slave, blob columns that are in master's BI but not in slave's PKE
479+
# 7 blob columns that are NOT NULL UK but not in PK are not in BI
480+
# 8 on slave, blob columns that are in master's BI but not in slave's PKE
435481
# are not in slave's BI
436482

437483
-- connection master
@@ -454,23 +500,21 @@ while (`SELECT HEX(@img_types) != HEX('')`)
454500
-- connection master
455501
-- let $row_img_query= UPDATE t SET c2='aaa', c3=1000, c5=10000 WHERE c1=1 AND c4='bbb'
456502
# asserts that:
457-
# 2. non-blob columns that are set to default value are in AI
458-
# 3. blob columns that are set to default value are in AI
459-
# 4. blob columns that are in WHERE clause but not in PKE are not in BI
460-
# 5. blob columns that are in NON-NULL UK but not in PK are not in BI
461-
# 6. on slave, blob columns that are in master's BI clause but not in
503+
# 2. blob columns that are in WHERE clause but not in PKE are not in BI
504+
# 3. blob columns that are in NON-NULL UK but not in PK are not in BI
505+
# 4. on slave, blob columns that are in master's BI clause but not in
462506
# slave's PKE are not in BI
463-
-- let $row_img_expected_master= 1:1 2:'aaa' 3:1000 5:1 | 1:1 2:'aaa' 3:1000 5:10000
464-
-- let $row_img_expected_slave = 1:1 3:1000 5:1 | 1:1 2:'aaa' 3:1000 5:10000
507+
-- let $row_img_expected_master= 1:1 2:'aaa' 3:1000 5:1 | 1:1 3:1000 5:10000
508+
-- let $row_img_expected_slave = 1:1 3:1000 5:1 | 1:1 3:1000 5:10000
465509
-- source include/rpl_row_img_parts_master_slave.inc
466510

467511
-- connection master
468512
-- let $row_img_query= DELETE FROM t WHERE c1=1 AND c4='bbb'
469513
# asserts that:
470-
# 7. non-blob columns that are not in WHERE clause but in PKE are in BI
471-
# 8. blob columns that are used in WHERE clause but not in PKE are not n BI
472-
# 9. blob columns that are NOT NULL UK but not in PK are not in BI
473-
# 10. on slave, blob columns that are in master's BI but not in slave's PKE are not in slave's BI
514+
# 5. non-blob columns that are not in WHERE clause but in PKE are in BI
515+
# 6. blob columns that are used in WHERE clause but not in PKE are not n BI
516+
# 7. blob columns that are NOT NULL UK but not in PK are not in BI
517+
# 8. on slave, blob columns that are in master's BI but not in slave's PKE are not in slave's BI
474518
-- let $row_img_expected_master= 1:1 2:'aaa' 3:1000 5:10000 |
475519
-- let $row_img_expected_slave = 1:1 3:1000 5:10000 |
476520
-- source include/rpl_row_img_parts_master_slave.inc

sql/binlog.cc

+43-4
Original file line numberDiff line numberDiff line change
@@ -9158,7 +9158,7 @@ int THD::binlog_update_row(TABLE* table, bool is_trans,
91589158
not needed for binlogging. This is done according to the:
91599159
binlog-row-image option.
91609160
*/
9161-
binlog_prepare_row_images(table);
9161+
binlog_prepare_row_images(table, true);
91629162

91639163
size_t const before_maxlen = max_row_length(table, before_record);
91649164
size_t const after_maxlen = max_row_length(table, after_record);
@@ -9224,7 +9224,7 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans,
92249224
not needed for binlogging. This is done according to the:
92259225
binlog-row-image option.
92269226
*/
9227-
binlog_prepare_row_images(table);
9227+
binlog_prepare_row_images(table, false);
92289228

92299229
/*
92309230
Pack records into format for transfer. We are allocating more
@@ -9256,17 +9256,18 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans,
92569256
return error;
92579257
}
92589258

9259-
void THD::binlog_prepare_row_images(TABLE *table)
9259+
void THD::binlog_prepare_row_images(TABLE *table, bool is_update)
92609260
{
92619261
DBUG_ENTER("THD::binlog_prepare_row_images");
92629262
/**
9263-
Remove from read_set spurious columns. The write_set has been
9263+
Remove spurious columns. The write_set has been partially
92649264
handled before in table->mark_columns_needed_for_update.
92659265
*/
92669266

92679267
DBUG_PRINT_BITSET("debug", "table->read_set (before preparing): %s", table->read_set);
92689268
THD *thd= table->in_use;
92699269

9270+
/* Handle the read set */
92709271
/**
92719272
if there is a primary key in the table (ie, user declared PK or a
92729273
non-null unique index) and we dont want to ship the entire image,
@@ -9314,6 +9315,44 @@ void THD::binlog_prepare_row_images(TABLE *table)
93149315
table->write_set);
93159316
}
93169317

9318+
/* Now, handle the write set */
9319+
if (is_update &&
9320+
thd->variables.binlog_row_image != BINLOG_ROW_IMAGE_FULL &&
9321+
!ha_check_storage_engine_flag(table->s->db_type(),
9322+
HTON_NO_BINLOG_ROW_OPT))
9323+
{
9324+
/**
9325+
Just to be sure that tmp_write_set is currently not in use as
9326+
the write_set already.
9327+
*/
9328+
DBUG_ASSERT(table->write_set != &table->tmp_write_set);
9329+
9330+
bitmap_copy(&table->tmp_write_set, table->write_set);
9331+
9332+
for (Field **ptr=table->field ; *ptr ; ptr++)
9333+
{
9334+
Field *field= (*ptr);
9335+
if (bitmap_is_set(&table->tmp_write_set, field->field_index))
9336+
{
9337+
/* When image type is NOBLOB, we prune only BLOB fields */
9338+
if (thd->variables.binlog_row_image == BINLOG_ROW_IMAGE_NOBLOB &&
9339+
field->type() != MYSQL_TYPE_BLOB)
9340+
continue;
9341+
9342+
/* compare null bit */
9343+
if (field->is_null() && field->is_null_in_record(table->record[1]))
9344+
bitmap_clear_bit(&table->tmp_write_set, field->field_index);
9345+
9346+
/* compare content, only if fields are not set to NULL */
9347+
else if (!field->is_null() &&
9348+
!field->cmp_binary_offset(table->s->rec_buff_length))
9349+
bitmap_clear_bit(&table->tmp_write_set, field->field_index);
9350+
}
9351+
}
9352+
table->column_bitmaps_set_no_signal(table->read_set,
9353+
&table->tmp_write_set);
9354+
}
9355+
93179356
DBUG_PRINT_BITSET("debug", "table->read_set (after preparing): %s", table->read_set);
93189357
DBUG_VOID_RETURN;
93199358
}

sql/sql_class.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -2623,7 +2623,7 @@ class THD :public MDL_context_owner,
26232623
int binlog_update_row(TABLE* table, bool is_transactional,
26242624
const uchar *old_data, const uchar *new_data,
26252625
const uchar* extra_row_info);
2626-
void binlog_prepare_row_images(TABLE* table);
2626+
void binlog_prepare_row_images(TABLE* table, bool is_update);
26272627

26282628
void set_server_id(uint32 sid) { server_id = sid; }
26292629

sql/table.cc

+3-1
Original file line numberDiff line numberDiff line change
@@ -2657,14 +2657,16 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
26572657
/* Allocate bitmaps */
26582658

26592659
bitmap_size= share->column_bitmap_size;
2660-
if (!(bitmaps= (uchar*) alloc_root(&outparam->mem_root, bitmap_size*3)))
2660+
if (!(bitmaps= (uchar*) alloc_root(&outparam->mem_root, bitmap_size*4)))
26612661
goto err;
26622662
bitmap_init(&outparam->def_read_set,
26632663
(my_bitmap_map*) bitmaps, share->fields, FALSE);
26642664
bitmap_init(&outparam->def_write_set,
26652665
(my_bitmap_map*) (bitmaps+bitmap_size), share->fields, FALSE);
26662666
bitmap_init(&outparam->tmp_set,
26672667
(my_bitmap_map*) (bitmaps+bitmap_size*2), share->fields, FALSE);
2668+
bitmap_init(&outparam->tmp_write_set,
2669+
(my_bitmap_map*) (bitmaps+bitmap_size*3), share->fields, FALSE);
26682670
outparam->default_column_bitmaps();
26692671

26702672
/* The table struct is now initialized; Open the table */

sql/table.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -1170,7 +1170,8 @@ struct TABLE
11701170
const char *alias; /* alias or table name */
11711171
uchar *null_flags;
11721172
my_bitmap_map *bitmap_init_value;
1173-
MY_BITMAP def_read_set, def_write_set, tmp_set; /* containers */
1173+
MY_BITMAP def_read_set, def_write_set; /* containers */
1174+
MY_BITMAP tmp_set, tmp_write_set; /* containers */
11741175
MY_BITMAP *read_set, *write_set; /* Active column sets */
11751176
/*
11761177
The ID of the query that opened and is using this table. Has different

0 commit comments

Comments
 (0)