Skip to content

Commit 3c38c37

Browse files
committed
MDEV-33957 UPDATE fails on replica replicating blob virtual column in NOBLOB mode when replica logging is off
The sequence that causes the issue: 1. file->row_logging is false because slave-bin was not open; 2. TABLE::mark_columns_per_binlog_row_image() didn't mark column for read because file->row_logginbg is false. This was implemented in e53ad95 (MDEV-6877); 3. TABLE::update_virtual_fields() didn't update virtual field value because column is not marked for read; 4. calc_row_difference() sees o_len as UNIV_SQL_NULL, but new row value is "1". The virtual column is added to update vector; 5. row_upd() tries to update secondary index, but row_upd_sec_step() doesn't see old value in the index. The patch does mark_virtual_column_with_deps() via column_bitmaps_signal() in case of rgi_slave in mark_columns_per_binlog_row_image() so that non-stored virtual columns are marked for update in slave thread. Also fixed column_bitmaps_signal() for partitioning where the signal did not reach the partition storage engine.
1 parent c8cf8d3 commit 3c38c37

File tree

5 files changed

+94
-4
lines changed

5 files changed

+94
-4
lines changed
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
include/master-slave.inc
2+
[connection master]
3+
#
4+
# MDEV-33957 UPDATE fails on replica replicating blob virtual column in
5+
# NOBLOB mode when replica logging is off
6+
#
7+
connection slave;
8+
select @@log_slave_updates;
9+
@@log_slave_updates
10+
0
11+
connection master;
12+
set binlog_row_image= 'NOBLOB';
13+
create table t (
14+
c int primary key, d int,
15+
i blob generated always as (c), key k(i)) engine=innodb;
16+
Warnings:
17+
Note 1071 Specified key was too long; max key length is 3072 bytes
18+
insert into t (c) values (1);
19+
update t set d= 0;
20+
connection slave;
21+
connection master;
22+
drop table t;
23+
create table t (
24+
c int primary key, d int,
25+
i blob generated always as (c), key k(i)) engine=innodb
26+
partition by key (c) partitions 2;
27+
Warnings:
28+
Note 1071 Specified key was too long; max key length is 3072 bytes
29+
insert into t (c) values (1);
30+
update t set d= 0;
31+
connection slave;
32+
connection master;
33+
drop table t;
34+
include/rpl_end.inc
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
--log-slave-updates=0
2+
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--source include/have_innodb.inc
2+
--source include/have_partition.inc
3+
--source include/have_binlog_format_row.inc
4+
--source include/master-slave.inc
5+
6+
--echo #
7+
--echo # MDEV-33957 UPDATE fails on replica replicating blob virtual column in
8+
--echo # NOBLOB mode when replica logging is off
9+
--echo #
10+
11+
--connection slave
12+
select @@log_slave_updates;
13+
--connection master
14+
set binlog_row_image= 'NOBLOB';
15+
create table t (
16+
c int primary key, d int,
17+
i blob generated always as (c), key k(i)) engine=innodb;
18+
insert into t (c) values (1);
19+
update t set d= 0;
20+
--sync_slave_with_master
21+
22+
--connection master
23+
drop table t;
24+
create table t (
25+
c int primary key, d int,
26+
i blob generated always as (c), key k(i)) engine=innodb
27+
partition by key (c) partitions 2;
28+
insert into t (c) values (1);
29+
update t set d= 0;
30+
--sync_slave_with_master
31+
32+
--connection master
33+
drop table t;
34+
35+
--source include/rpl_end.inc

sql/ha_partition.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,17 @@ class ha_partition final :public handler
576576
{
577577
m_file[part_id]->update_create_info(create_info);
578578
}
579+
580+
void column_bitmaps_signal() override
581+
{
582+
for (uint i= bitmap_get_first_set(&m_opened_partitions);
583+
i < m_tot_parts;
584+
i= bitmap_get_next_set(&m_opened_partitions, i))
585+
{
586+
m_file[i]->column_bitmaps_signal();
587+
}
588+
}
589+
579590
private:
580591
int copy_partitions(ulonglong * const copied, ulonglong * const deleted);
581592
void cleanup_new_partition(uint part_count);

sql/table.cc

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7900,7 +7900,8 @@ void TABLE::mark_columns_needed_for_insert()
79007900
}
79017901

79027902
/*
7903-
Mark columns according the binlog row image option.
7903+
Mark columns according the binlog row image option
7904+
or mark virtual columns for slave.
79047905
79057906
Columns to be written are stored in 'rpl_write_set'
79067907
@@ -7931,6 +7932,10 @@ void TABLE::mark_columns_needed_for_insert()
79317932
the read_set at binlogging time (for those cases that
79327933
we only want to log a PK and we needed other fields for
79337934
execution).
7935+
7936+
If binlog row image is off on slave we mark virtual columns
7937+
for read as InnoDB requires correct field metadata which is set
7938+
by update_virtual_fields().
79347939
*/
79357940

79367941
void TABLE::mark_columns_per_binlog_row_image()
@@ -7940,9 +7945,6 @@ void TABLE::mark_columns_per_binlog_row_image()
79407945
DBUG_ASSERT(read_set->bitmap);
79417946
DBUG_ASSERT(write_set->bitmap);
79427947

7943-
/* If not using row format */
7944-
rpl_write_set= write_set;
7945-
79467948
/**
79477949
If in RBR we may need to mark some extra columns,
79487950
depending on the binlog-row-image command line argument.
@@ -8018,6 +8020,12 @@ void TABLE::mark_columns_per_binlog_row_image()
80188020
}
80198021
file->column_bitmaps_signal();
80208022
}
8023+
else
8024+
{
8025+
/* If not using row format */
8026+
rpl_write_set= write_set;
8027+
file->column_bitmaps_signal();
8028+
}
80218029

80228030
DBUG_VOID_RETURN;
80238031
}

0 commit comments

Comments
 (0)