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 | 498a96a4789e58549ce87b5843e804e055ab327f (patch) | |
tree | 36da2d9f9c8180fbad55e0413c70f8c0702b68f0 | |
parent | 57cab7cd5114d3ef47203118cddd3ad0a22f2861 (diff) | |
download | mariadb-git-498a96a4789e58549ce87b5843e804e055ab327f.tar.gz |
MDEV-20441 ER_CRASHED_ON_USAGE upon update on versioned Aria table
Turn read cache off for update and multi-update for versioned
table. no_cache is reinited on each TABLE open because it is
applicable for specific algorithms.
As a side fix vers_insert_history_row() honors vers_write setting.
Aria with row_format=fixed uses IO_CACHE of type READ_CACHE for
sequential read in update loop. When history row is inserted inside
this loop the cache misses it and fails with error.
TODO:
Currently maria_extra() does not support SEQ_READ_APPEND. Probably it
might be possible to use this type of cache.
-rw-r--r-- | mysql-test/suite/versioning/r/update.result | 9 | ||||
-rw-r--r-- | mysql-test/suite/versioning/t/update.test | 12 | ||||
-rw-r--r-- | sql/sql_insert.cc | 2 | ||||
-rw-r--r-- | sql/sql_update.cc | 15 | ||||
-rw-r--r-- | sql/table.cc | 1 | ||||
-rw-r--r-- | sql/table.h | 11 | ||||
-rw-r--r-- | storage/maria/ma_check.c | 2 |
7 files changed, 43 insertions, 9 deletions
diff --git a/mysql-test/suite/versioning/r/update.result b/mysql-test/suite/versioning/r/update.result index eaa8549b38a..08b105e952b 100644 --- a/mysql-test/suite/versioning/r/update.result +++ b/mysql-test/suite/versioning/r/update.result @@ -276,3 +276,12 @@ update t1 set a= '2012-12-12'; update v set a= '2000-01-01' order by b limit 1; drop view v; drop table t1, t2; +# +# MDEV-20441 ER_CRASHED_ON_USAGE upon update on versioned Aria table +# +create or replace table t1 (a varchar(8)) +engine=aria row_format=fixed +with system versioning; +insert into t1 (a) values ('foo'); +update t1 set a = 'bar'; +drop table t1; diff --git a/mysql-test/suite/versioning/t/update.test b/mysql-test/suite/versioning/t/update.test index e41c7d15995..148cbbdc707 100644 --- a/mysql-test/suite/versioning/t/update.test +++ b/mysql-test/suite/versioning/t/update.test @@ -157,7 +157,6 @@ replace t1 values (1,2),(1,3),(2,4); --echo # --echo # MDEV-14829 Assertion `0' failed in Protocol::end_statement upon concurrent UPDATE --echo # - create or replace table t1 (pk int, a char(3), b char(3), primary key(pk)) engine=innodb with system versioning; @@ -192,4 +191,15 @@ drop view v; drop table t1, t2; --enable_warnings +--echo # +--echo # MDEV-20441 ER_CRASHED_ON_USAGE upon update on versioned Aria table +--echo # +create or replace table t1 (a varchar(8)) +engine=aria row_format=fixed +with system versioning; + +insert into t1 (a) values ('foo'); +update t1 set a = 'bar'; +drop table t1; + source suite/versioning/common_finish.inc; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 334b6b2d667..e747b645e9d 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1646,6 +1646,8 @@ static int last_uniq_key(TABLE *table,uint keynr) int vers_insert_history_row(TABLE *table) { DBUG_ASSERT(table->versioned(VERS_TIMESTAMP)); + if (!table->vers_write) + return 0; restore_record(table,record[1]); // Set Sys_end to now() diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 1e5440ee4fe..d3b771acdad 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -184,10 +184,10 @@ static bool check_fields(THD *thd, List<Item> &items, bool update_view) return FALSE; } -static bool check_has_vers_fields(TABLE *table, List<Item> &items) +bool TABLE::vers_check_update(List<Item> &items) { List_iterator<Item> it(items); - if (!table->versioned()) + if (!versioned_write()) return false; while (Item *item= it++) @@ -195,8 +195,11 @@ static bool check_has_vers_fields(TABLE *table, List<Item> &items) if (Item_field *item_field= item->field_for_view_update()) { Field *field= item_field->field; - if (field->table == table && !field->vers_update_unversioned()) + if (field->table == this && !field->vers_update_unversioned()) + { + no_cache= true; return true; + } } } return false; @@ -415,7 +418,7 @@ int mysql_update(THD *thd, { DBUG_RETURN(1); } - bool has_vers_fields= check_has_vers_fields(table, fields); + bool has_vers_fields= table->vers_check_update(fields); if (check_key_in_view(thd, table_list)) { my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias.str, "UPDATE"); @@ -2133,7 +2136,7 @@ multi_update::initialize_tables(JOIN *join) if (safe_update_on_fly(thd, join->join_tab, table_ref, all_tables)) { table_to_update= table; // Update table on the fly - has_vers_fields= check_has_vers_fields(table, *fields); + has_vers_fields= table->vers_check_update(*fields); continue; } } @@ -2609,7 +2612,7 @@ int multi_update::do_updates() if (table->vfield) empty_record(table); - has_vers_fields= check_has_vers_fields(table, *fields); + has_vers_fields= table->vers_check_update(*fields); check_opt_it.rewind(); while(TABLE *tbl= check_opt_it++) diff --git a/sql/table.cc b/sql/table.cc index e008e6a3ded..291418f55fe 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -4688,6 +4688,7 @@ void TABLE::init(THD *thd, TABLE_LIST *tl) cond_selectivity_sampling_explain= NULL; vers_write= s->versioned; quick_condition_rows=0; + no_cache= false; initialize_quick_structures(); #ifdef HAVE_REPLICATION /* used in RBR Triggers */ diff --git a/sql/table.h b/sql/table.h index 1dda70ae0da..ca5565250de 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1536,9 +1536,16 @@ public: return s->versioned == type; } - bool versioned_write(vers_sys_type_t type= VERS_UNDEFINED) const + bool versioned_write() const { DBUG_ASSERT(versioned() || !vers_write); + return versioned() ? vers_write : false; + } + + bool versioned_write(vers_sys_type_t type) const + { + DBUG_ASSERT(type); + DBUG_ASSERT(versioned() || !vers_write); return versioned(type) ? vers_write : false; } @@ -1557,6 +1564,8 @@ public: ulonglong vers_start_id() const; ulonglong vers_end_id() const; + bool vers_check_update(List<Item> &items); + int delete_row(); void vers_update_fields(); void vers_update_end(); diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index eadac5b04eb..101c33b7802 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -6183,7 +6183,7 @@ end: } - /* write suffix to data file if neaded */ +/* Write suffix to data file if needed */ int maria_write_data_suffix(MARIA_SORT_INFO *sort_info, my_bool fix_datafile) { |