From 50a8beedfe59f97d381e8f506344a6197b8b5702 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Fri, 15 Sep 2017 15:02:24 +0200 Subject: [PATCH] MDEV-13708 Crash with indexed virtual columns and FK cascading deletes InnoDB was too eager to forget the open table (m_mysql_table=NULL) and that caused it to try to open a table which was opened by the user not FK-prelocked. The server didn't expect that. After fixing this, it crashed in gcol.innodb_virtual_fk test, trying to compute virtual columns for a table that didn't have them. Because row_upd_store_row() was deleting a row from node->table, while computing virtual columns in thr->prebuilt->m_mysql_table. Which wasn't necessarily the same table, and might've not even had virtual columns, even if node->table did. --- mysql-test/suite/vcol/r/innodb_virtual_fk.result | 12 ++++++++++++ mysql-test/suite/vcol/t/innodb_virtual_fk.test | 16 ++++++++++++++++ storage/innobase/row/row0mysql.cc | 1 - storage/innobase/row/row0upd.cc | 3 ++- 4 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/vcol/r/innodb_virtual_fk.result create mode 100644 mysql-test/suite/vcol/t/innodb_virtual_fk.test diff --git a/mysql-test/suite/vcol/r/innodb_virtual_fk.result b/mysql-test/suite/vcol/r/innodb_virtual_fk.result new file mode 100644 index 00000000000..58db12583e2 --- /dev/null +++ b/mysql-test/suite/vcol/r/innodb_virtual_fk.result @@ -0,0 +1,12 @@ +set default_storage_engine=innodb; +create table t1 (id int primary key, id2 int as (id) virtual, key id2 (id2)); +create table t2 (id int key, constraint fk_id foreign key (id) references t1 (id) on delete cascade); +insert into t1 (id) values (1), (2); +insert into t2 (id) values (1), (2); +delete from t1; +select * from t1; +id id2 +select * from t2; +id +drop table t2; +drop table t1; diff --git a/mysql-test/suite/vcol/t/innodb_virtual_fk.test b/mysql-test/suite/vcol/t/innodb_virtual_fk.test new file mode 100644 index 00000000000..c364adaa613 --- /dev/null +++ b/mysql-test/suite/vcol/t/innodb_virtual_fk.test @@ -0,0 +1,16 @@ +source include/have_innodb.inc; +set default_storage_engine=innodb; + +# +# MDEV-13708 Crash with indexed virtual columns and FK cascading deletes +# + +create table t1 (id int primary key, id2 int as (id) virtual, key id2 (id2)); +create table t2 (id int key, constraint fk_id foreign key (id) references t1 (id) on delete cascade); +insert into t1 (id) values (1), (2); +insert into t2 (id) values (1), (2); +delete from t1; +select * from t1; +select * from t2; +drop table t2; +drop table t1; diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index 4ceef6c918f..4452960dbc9 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -2029,7 +2029,6 @@ run_again: node->cascade_upd_nodes = cascade_upd_nodes; cascade_upd_nodes->pop_front(); thr->fk_cascade_depth++; - prebuilt->m_mysql_table = NULL; goto run_again; } diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 8ba3da255a4..a2be9a69a56 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -2966,7 +2966,8 @@ row_upd_del_mark_clust_rec( entries */ row_upd_store_row(node, trx->mysql_thd, - thr->prebuilt ? thr->prebuilt->m_mysql_table : NULL); + thr->prebuilt && thr->prebuilt->table == node->table + ? thr->prebuilt->m_mysql_table : NULL); /* Mark the clustered index record deleted; we do not have to check locks, because we assume that we have an x-lock on the record */