Skip to content
/ server Public
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions mysql-test/suite/vcol/r/vcol_keys_innodb.result
Original file line number Diff line number Diff line change
Expand Up @@ -303,3 +303,23 @@ IF(@@innodb_sort_buffer_size < count(*)*200, 'GOOD', 'WRONG SIZE')
GOOD
alter table t1 drop column va;
drop table t1;
#
# MDEV-39081 InnoDB: tried to purge non-delete-marked record,
# assertion fails in row_purge_del_mark_error
#
CREATE TABLE t1(
pk INT AUTO_INCREMENT,
f1 INT DEFAULT 0,
f2 INT as (1 + 1) VIRTUAL,
KEY (f1), PRIMARY KEY (pk), UNIQUE (f2)) ENGINE=InnoDB;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
CONNECT con1,localhost,root,,;
INSERT INTO t1 (pk) VALUES(1);
DELETE FROM t1;
INSERT INTO t1 (pk) VALUES(1);
UPDATE t1 set f1 = 2;
disconnect con1;
connection default;
COMMIT;
InnoDB 0 transactions not purged
DROP TABLE t1;
22 changes: 22 additions & 0 deletions mysql-test/suite/vcol/t/vcol_keys_innodb.test
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,25 @@ insert t1 (id,a,c) select seq,seq,seq from seq_1_to_330;
select IF(@@innodb_sort_buffer_size < count(*)*200, 'GOOD', 'WRONG SIZE') from t1;
alter table t1 drop column va;
drop table t1;

--echo #
--echo # MDEV-39081 InnoDB: tried to purge non-delete-marked record,
--echo # assertion fails in row_purge_del_mark_error
--echo #
CREATE TABLE t1(
pk INT AUTO_INCREMENT,
f1 INT DEFAULT 0,
f2 INT as (1 + 1) VIRTUAL,
KEY (f1), PRIMARY KEY (pk), UNIQUE (f2)) ENGINE=InnoDB;
START TRANSACTION WITH CONSISTENT SNAPSHOT;

CONNECT(con1,localhost,root,,);
INSERT INTO t1 (pk) VALUES(1);
DELETE FROM t1;
INSERT INTO t1 (pk) VALUES(1);
UPDATE t1 set f1 = 2;
DISCONNECT con1;
CONNECTION default;
COMMIT;
--source ../innodb/include/wait_all_purged.inc
DROP TABLE t1;
4 changes: 2 additions & 2 deletions sql/ha_partition.h
Original file line number Diff line number Diff line change
Expand Up @@ -577,13 +577,13 @@ class ha_partition final :public handler
m_file[part_id]->update_create_info(create_info);
}

void column_bitmaps_signal() override
void column_bitmaps_signal(bool mark_for_update) override
{
for (uint i= bitmap_get_first_set(&m_opened_partitions);
i < m_tot_parts;
i= bitmap_get_next_set(&m_opened_partitions, i))
{
m_file[i]->column_bitmaps_signal();
m_file[i]->column_bitmaps_signal(mark_for_update);
}
}

Expand Down
4 changes: 2 additions & 2 deletions sql/ha_sequence.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ class ha_sequence :public handler
{ return file->check_and_repair(thd); }
bool is_crashed() const override
{ return file->is_crashed(); }
void column_bitmaps_signal() override
{ return file->column_bitmaps_signal(); }
void column_bitmaps_signal(bool mark_for_update) override
{ return file->column_bitmaps_signal(mark_for_update); }

/* New methods */
void register_original_handler(handler *file_arg)
Expand Down
4 changes: 3 additions & 1 deletion sql/handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4482,6 +4482,8 @@ int handler::update_auto_increment()
/** @brief
MySQL signal that it changed the column bitmap

@param mark_for_update whether to mark indexed virtual columns
for UPDATE operations
USAGE
This is for handlers that needs to setup their own column bitmaps.
Normally the handler should set up their own column bitmaps in
Expand All @@ -4492,7 +4494,7 @@ int handler::update_auto_increment()
rnd_init() call is made as after this, MySQL will not use the bitmap
for any program logic checking.
*/
void handler::column_bitmaps_signal()
void handler::column_bitmaps_signal(bool mark_for_update)
{
DBUG_ENTER("column_bitmaps_signal");
if (table)
Expand Down
2 changes: 1 addition & 1 deletion sql/handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4055,7 +4055,7 @@ class handler :public Sql_alloc
a ha_rnd_init() or ha_index_init(), write_row(), update_row or delete_row()
as there may be several calls to this routine.
*/
virtual void column_bitmaps_signal();
virtual void column_bitmaps_signal(bool mark_for_update= false);
/*
We have to check for inited as some engines, like innodb, sets
active_index during table scan.
Expand Down
2 changes: 1 addition & 1 deletion sql/table.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7956,7 +7956,7 @@ void TABLE::mark_columns_needed_for_update()
}
mark_columns_per_binlog_row_image();
if (need_signal)
file->column_bitmaps_signal();
file->column_bitmaps_signal(true);
DBUG_VOID_RETURN;
}

Expand Down
72 changes: 40 additions & 32 deletions storage/innobase/handler/ha_innodb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5045,53 +5045,61 @@ ha_innobase::keys_to_use_for_scanning()
return(&key_map_full);
}

/** Mark all indexed virtual columns for computation during
online DDL. Virtual columns that are part of any index must be
computed and logged in the row log so their values are available
for index building and concurrent DML replay during ALTER TABLE
operations.
@param table InnoDB table handle
@param mysql_table MySQL table object */
ATTRIBUTE_COLD
static
void row_log_mark_virtual_cols(const dict_table_t *table,
TABLE *mysql_table) noexcept
{
dict_index_t *clust_index= dict_table_get_first_index(table);
ut_ad(clust_index->online_log);
for (uint j= mysql_table->s->virtual_fields, num_v = 0; j--; )
{
Field *vf= mysql_table->vfield[j];
if (vf->stored_in_db())
continue;
if (table->v_cols[num_v].m_col.ord_part ||
row_log_col_is_indexed(
dict_table_get_first_index(table), num_v))
mysql_table->mark_virtual_column_with_deps(vf);
num_v++;
}
}

/****************************************************************//**
Ensure that indexed virtual columns will be computed.
Needs to be done for indexes that are being added with inplace ALTER
in a different thread, because from the server point of view these
columns are not yet indexed.
Also needed if the primary key is being updated.
For update statement: Mark all indexed virtual column
@param mark_for_update whether to mark indexed virtual columns
for UPDATE operations
*/
void ha_innobase::column_bitmaps_signal()
void ha_innobase::column_bitmaps_signal(bool mark_for_update)
{
if (!table->vfield || table->current_lock != F_WRLCK)
return;

dict_index_t* clust_index= dict_table_get_first_index(m_prebuilt->table);
bool is_online_log= clust_index->online_log;

/*
Check if the clustered index is being updated.
If so, it is necessary to compute virtual columns that are part of
secondary indexes, to be able to re-compute those indexes.
*/
bool upd_pk= false;
for (uint j= 0; j < clust_index->n_user_defined_cols; ++j)
if (UNIV_UNLIKELY(dict_index_is_online_ddl(
dict_table_get_first_index(m_prebuilt->table))))
row_log_mark_virtual_cols(m_prebuilt->table, table);
else if (mark_for_update)
{
dict_col_t *col= clust_index->fields[j].col;
if (bitmap_is_set(table->write_set, static_cast<uint>(col->ind)))
for (uint j = 0, num_v= 0; j < table->s->virtual_fields; j++)
{
upd_pk= 1;
break;
Field *vf= table->vfield[j];
if (!vf->stored_in_db() &&
m_prebuilt->table->v_cols[num_v++].m_col.ord_part)
table->mark_virtual_column_with_deps(vf);
}
}

if (!is_online_log && !upd_pk)
return;

uint num_v= 0;
for (uint j = 0; j < table->s->virtual_fields; j++)
{
if (table->vfield[j]->stored_in_db())
continue;

dict_col_t *col= &m_prebuilt->table->v_cols[num_v].m_col;
if (col->ord_part ||
(is_online_log && dict_index_is_online_ddl(clust_index) &&
row_log_col_is_indexed(clust_index, num_v)))
table->mark_virtual_column_with_deps(table->vfield[j]);
num_v++;
}
}


Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/handler/ha_innodb.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class ha_innobase final : public handler

const key_map* keys_to_use_for_scanning() override;

void column_bitmaps_signal() override;
void column_bitmaps_signal(bool mark_for_update) override;

/** Opens dictionary table object using table name. For partition, we need to
try alternative lower/upper case names to support moving data files across
Expand Down
Loading