MDEV-15249 Crash in MVCC read after IMPORT TABLESPACE

PageConverter::adjust_cluster_record(): Instead of writing
the invalid value DB_ROLL_PTR=0, write a value that indicates
a fresh insert, that is, prevents the DB_ROLL_PTR from being
dereferenced in any circumstances.

It can be argued that IMPORT TABLESPACE should actually
update the dict_index_t::trx_id to prevent older transactions
from accessing the table, similar to what I did on table
rebuild in MySQL 5.6.6 in
03f81a55f2
This commit is contained in:
Marko Mäkelä 2018-02-08 12:51:19 +02:00
parent b6455479e5
commit 5421e3aee7
8 changed files with 88 additions and 10 deletions

View File

@ -0,0 +1,26 @@
SET @save_per_table= @@GLOBAL.innodb_file_per_table;
SET GLOBAL innodb_file_per_table= 1;
#
# MDEV-15249 Crash in MVCC read after IMPORT TABLESPACE
#
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(0);
FLUSH TABLES t1 WITH READ LOCK;
UNLOCK TABLES;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
ALTER TABLE t1 FORCE, ALGORITHM=COPY;
SELECT * FROM t1;
ERROR HY000: Table definition has changed, please retry transaction
COMMIT;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
ALTER TABLE t1 DISCARD TABLESPACE;
ALTER TABLE t1 IMPORT TABLESPACE;
# FIXME: Block this with ER_TABLE_DEF_CHANGED
SELECT * FROM t1;
a
COMMIT;
SELECT * FROM t1;
a
0
DROP TABLE t1;
SET GLOBAL innodb_file_per_table= @save_per_table;

View File

@ -0,0 +1,52 @@
--source include/have_innodb.inc
SET @save_per_table= @@GLOBAL.innodb_file_per_table;
SET GLOBAL innodb_file_per_table= 1;
let MYSQLD_DATADIR =`SELECT @@datadir`;
--echo #
--echo # MDEV-15249 Crash in MVCC read after IMPORT TABLESPACE
--echo #
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
INSERT INTO t1 VALUES(0);
FLUSH TABLES t1 WITH READ LOCK;
perl;
do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl";
ib_backup_tablespace("test", "t1");
EOF
UNLOCK TABLES;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connect (con1,localhost,root,,);
ALTER TABLE t1 FORCE, ALGORITHM=COPY;
connection default;
--error ER_TABLE_DEF_CHANGED
SELECT * FROM t1;
COMMIT;
START TRANSACTION WITH CONSISTENT SNAPSHOT;
connection con1;
ALTER TABLE t1 DISCARD TABLESPACE;
perl;
do "$ENV{MTR_SUITE_DIR}/include/innodb-util.pl";
ib_restore_tablespace("test", "t1");
EOF
ALTER TABLE t1 IMPORT TABLESPACE;
disconnect con1;
connection default;
--echo # FIXME: Block this with ER_TABLE_DEF_CHANGED
SELECT * FROM t1;
COMMIT;
SELECT * FROM t1;
DROP TABLE t1;
SET GLOBAL innodb_file_per_table= @save_per_table;

View File

@ -1,6 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -119,8 +120,7 @@ row_upd_rec_sys_fields(
dict_index_t* index, /*!< in: clustered index */ dict_index_t* index, /*!< in: clustered index */
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
const trx_t* trx, /*!< in: transaction */ const trx_t* trx, /*!< in: transaction */
roll_ptr_t roll_ptr);/*!< in: roll ptr of the undo log record, roll_ptr_t roll_ptr);/*!< in: DB_ROLL_PTR to the undo log */
can be 0 during IMPORT */
/*********************************************************************//** /*********************************************************************//**
Sets the trx id or roll ptr field of a clustered index entry. */ Sets the trx id or roll ptr field of a clustered index entry. */
UNIV_INTERN UNIV_INTERN

View File

@ -1,6 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -153,8 +154,7 @@ row_upd_rec_sys_fields(
dict_index_t* index, /*!< in: clustered index */ dict_index_t* index, /*!< in: clustered index */
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
const trx_t* trx, /*!< in: transaction */ const trx_t* trx, /*!< in: transaction */
roll_ptr_t roll_ptr)/*!< in: roll ptr of the undo log record, roll_ptr_t roll_ptr)/*!< in: DB_ROLL_PTR to the undo log */
can be 0 during IMPORT */
{ {
ut_ad(dict_index_is_clust(index)); ut_ad(dict_index_is_clust(index));
ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_validate(rec, index, offsets));

View File

@ -1798,7 +1798,7 @@ PageConverter::adjust_cluster_record(
row_upd_rec_sys_fields( row_upd_rec_sys_fields(
rec, m_page_zip_ptr, m_cluster_index, m_offsets, rec, m_page_zip_ptr, m_cluster_index, m_offsets,
m_trx, 0); m_trx, roll_ptr_t(1) << 55);
} }
return(err); return(err);

View File

@ -1,6 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -119,8 +120,7 @@ row_upd_rec_sys_fields(
dict_index_t* index, /*!< in: clustered index */ dict_index_t* index, /*!< in: clustered index */
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
const trx_t* trx, /*!< in: transaction */ const trx_t* trx, /*!< in: transaction */
roll_ptr_t roll_ptr);/*!< in: roll ptr of the undo log record, roll_ptr_t roll_ptr);/*!< in: DB_ROLL_PTR to the undo log */
can be 0 during IMPORT */
/*********************************************************************//** /*********************************************************************//**
Sets the trx id or roll ptr field of a clustered index entry. */ Sets the trx id or roll ptr field of a clustered index entry. */
UNIV_INTERN UNIV_INTERN

View File

@ -1,6 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -153,8 +154,7 @@ row_upd_rec_sys_fields(
dict_index_t* index, /*!< in: clustered index */ dict_index_t* index, /*!< in: clustered index */
const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */ const ulint* offsets,/*!< in: rec_get_offsets(rec, index) */
const trx_t* trx, /*!< in: transaction */ const trx_t* trx, /*!< in: transaction */
roll_ptr_t roll_ptr)/*!< in: roll ptr of the undo log record, roll_ptr_t roll_ptr)/*!< in: DB_ROLL_PTR to the undo log */
can be 0 during IMPORT */
{ {
ut_ad(dict_index_is_clust(index)); ut_ad(dict_index_is_clust(index));
ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_validate(rec, index, offsets));

View File

@ -1798,7 +1798,7 @@ PageConverter::adjust_cluster_record(
row_upd_rec_sys_fields( row_upd_rec_sys_fields(
rec, m_page_zip_ptr, m_cluster_index, m_offsets, rec, m_page_zip_ptr, m_cluster_index, m_offsets,
m_trx, 0); m_trx, roll_ptr_t(1) << 55);
} }
return(err); return(err);