diff options
author | Sergei Golubchik <serg@mariadb.org> | 2018-11-03 21:17:17 +0100 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2018-11-04 08:12:28 +0100 |
commit | af9649c722810eb1754953eb406a84ec876ce693 (patch) | |
tree | 20089193150bac2119ca6a0a8a31c7e92321241f /sql/table.cc | |
parent | 8a346f31b913daa011085afec2b2d38450c73e00 (diff) | |
download | mariadb-git-af9649c722810eb1754953eb406a84ec876ce693.tar.gz |
MDEV-17349 Assertion `!table || (!table->read_set || bitmap_is_set(table->read_set, field_index))' failed on concurrent SELECT and DELETE after RENAME from table with index on virtual column
Race condition. field->flags were copied from s->field->flags during
field->clone(), early in open_table_from_share(). But s->field->flags
were getting their PART_INDIRECT_KEY_FLAG bit much later in
TABLE::mark_columns_used_by_virtual_fields() and only once per share.
If two threads were executing the code between field->clone()
and mark_columns_used_by_virtual_fields() at the same time, only
one would get PART_INDIRECT_KEY_FLAG bits in field[].
Diffstat (limited to 'sql/table.cc')
-rw-r--r-- | sql/table.cc | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/sql/table.cc b/sql/table.cc index f557799e7dd..2b278288784 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3013,6 +3013,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, uchar *record, *bitmaps; Field **field_ptr; uint8 save_context_analysis_only= thd->lex->context_analysis_only; + TABLE_SHARE::enum_v_keys check_set_initialized= share->check_set_initialized; DBUG_ENTER("open_table_from_share"); DBUG_PRINT("enter",("name: '%s.%s' form: %p", share->db.str, share->table_name.str, outparam)); @@ -3116,6 +3117,8 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, } (*field_ptr)= 0; // End marker + DEBUG_SYNC(thd, "TABLE_after_field_clone"); + if (share->found_next_number_field) outparam->found_next_number_field= outparam->field[(uint) (share->found_next_number_field - share->field)]; @@ -3371,6 +3374,16 @@ partititon_err: } outparam->mark_columns_used_by_virtual_fields(); + if (!check_set_initialized && + share->check_set_initialized == TABLE_SHARE::V_KEYS) + { + // copy PART_INDIRECT_KEY_FLAG that was set meanwhile by *some* thread + for (uint i= 0 ; i < share->fields ; i++) + { + if (share->field[i]->flags & PART_INDIRECT_KEY_FLAG) + outparam->field[i]->flags|= PART_INDIRECT_KEY_FLAG; + } + } if (share->table_category == TABLE_CATEGORY_LOG) { @@ -6708,6 +6721,7 @@ void TABLE::mark_columns_used_by_virtual_fields(void) { MY_BITMAP *save_read_set; Field **vfield_ptr; + TABLE_SHARE::enum_v_keys v_keys= TABLE_SHARE::NO_V_KEYS; /* If there is virtual fields are already initialized */ if (s->check_set_initialized) @@ -6748,12 +6762,12 @@ void TABLE::mark_columns_used_by_virtual_fields(void) if (bitmap_is_set(&tmp_set, i)) { s->field[i]->flags|= PART_INDIRECT_KEY_FLAG; - field[i]->flags|= PART_INDIRECT_KEY_FLAG; + v_keys= TABLE_SHARE::V_KEYS; } } bitmap_clear_all(&tmp_set); } - s->check_set_initialized= 1; + s->check_set_initialized= v_keys; if (s->tmp_table == NO_TMP_TABLE) mysql_mutex_unlock(&s->LOCK_share); } |