diff options
author | Aleksey Midenkov <midenok@gmail.com> | 2019-12-02 11:48:37 +0300 |
---|---|---|
committer | Aleksey Midenkov <midenok@gmail.com> | 2019-12-02 11:48:37 +0300 |
commit | 97aa07abf544870faa0956784f33f158b092b2e5 (patch) | |
tree | efcffbe5a3a123d2701522838de8180108a15092 | |
parent | 498a96a4789e58549ce87b5843e804e055ab327f (diff) | |
download | mariadb-git-97aa07abf544870faa0956784f33f158b092b2e5.tar.gz |
MDEV-21147 Assertion `marked_for_read()' upon UPDATE on versioned table via view
"write set" for replication finally got its correct place
(mark_columns_per_binlog_row_image()). When done generally in
mark_columns_needed_for_update() it affects optimization
algorithm. used_key_is_modified, query_plan.using_io_buffer are
wrongly set and that leads to wrong prepare_for_keyread() which limits
read_set.
-rw-r--r-- | mysql-test/suite/versioning/r/update.result | 12 | ||||
-rw-r--r-- | mysql-test/suite/versioning/t/update.test | 16 | ||||
-rw-r--r-- | sql/table.cc | 16 |
3 files changed, 38 insertions, 6 deletions
diff --git a/mysql-test/suite/versioning/r/update.result b/mysql-test/suite/versioning/r/update.result index 08b105e952b..64aa7c7068c 100644 --- a/mysql-test/suite/versioning/r/update.result +++ b/mysql-test/suite/versioning/r/update.result @@ -285,3 +285,15 @@ with system versioning; insert into t1 (a) values ('foo'); update t1 set a = 'bar'; drop table t1; +# +# MDEV-21147 Assertion `marked_for_read()' upon UPDATE on versioned table via view +# +create or replace table t1 ( +pk int, a char(8), b char(8), +primary key (pk) +) with system versioning; +create or replace view v1 as select * from t1; +insert into t1 values (1, null, 'd') , (2, null, 'i') ; +update v1 set a= null where b = ''; +drop view v1; +drop table t1; diff --git a/mysql-test/suite/versioning/t/update.test b/mysql-test/suite/versioning/t/update.test index 148cbbdc707..baf3c1ec876 100644 --- a/mysql-test/suite/versioning/t/update.test +++ b/mysql-test/suite/versioning/t/update.test @@ -202,4 +202,20 @@ insert into t1 (a) values ('foo'); update t1 set a = 'bar'; drop table t1; +--echo # +--echo # MDEV-21147 Assertion `marked_for_read()' upon UPDATE on versioned table via view +--echo # +create or replace table t1 ( + pk int, a char(8), b char(8), + primary key (pk) +) with system versioning; + +create or replace view v1 as select * from t1; +insert into t1 values (1, null, 'd') , (2, null, 'i') ; +update v1 set a= null where b = ''; + +# cleanup +drop view v1; +drop table t1; + source suite/versioning/common_finish.inc; diff --git a/sql/table.cc b/sql/table.cc index 291418f55fe..cbf26031658 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -6613,12 +6613,8 @@ void TABLE::mark_columns_needed_for_update() /* For System Versioning we have to read all columns since we store a copy of previous row with modified row_end back to a table. - - Without write_set versioning.rpl,row is unstable until MDEV-16370 is - applied. */ bitmap_union(read_set, &s->all_set); - bitmap_union(write_set, &s->all_set); need_signal= true; } if (check_constraints) @@ -6781,8 +6777,16 @@ void TABLE::mark_columns_per_binlog_row_image() 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; + if (versioned()) + { + // TODO: After MDEV-18432 we don't pass history rows, so remove this: + rpl_write_set= &s->all_set; + } + else + { + /* Only write columns that have changed */ + rpl_write_set= write_set; + } break; default: |