From 7df17ca8aae723c5bcfac3c044fb0435199fc9cd Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 10 Jul 2019 13:21:40 +0530 Subject: [PATCH] MDEV-19974 InnoDB: Cannot load compressed BLOB Problem: ======= During online alter, fts tokenization thread uses new table page size to read the externally stored page from old table. If the alter changes the page size then it leads to failure of alter table. Solution: ========= fts tokenization thread should use old table page size to read the externally stored page from old table. --- .../suite/innodb_fts/r/innodb_fts_misc.result | 5 +++ .../suite/innodb_fts/t/innodb_fts_misc.test | 8 ++++ storage/innobase/include/row0ftsort.h | 33 +++++++++------- storage/innobase/row/row0ftsort.cc | 39 ++++++++++--------- storage/innobase/row/row0merge.cc | 1 + 5 files changed, 53 insertions(+), 33 deletions(-) diff --git a/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result b/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result index 1322867551f..bc9548b7d8e 100644 --- a/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result +++ b/mysql-test/suite/innodb_fts/r/innodb_fts_misc.result @@ -1384,3 +1384,8 @@ SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+"good database"' IN BOOLEAN MODE); id a 1 know mysql good database DROP TABLE t1; +CREATE TABLE t1(f1 TEXT, FULLTEXT KEY(f1))ENGINE=InnoDB; +INSERT INTO t1 VALUES(repeat("this is the test case", 500)); +ALTER TABLE t1 KEY_BLOCK_SIZE=4; +ALTER TABLE t1 KEY_BLOCK_SIZE=0; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test b/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test index 150d632b26f..6fa4f25c60e 100644 --- a/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test +++ b/mysql-test/suite/innodb_fts/t/innodb_fts_misc.test @@ -1331,3 +1331,11 @@ INSERT INTO t1 (a) VALUES SELECT * FROM t1 WHERE MATCH (a) AGAINST ('+"good database"' IN BOOLEAN MODE); DROP TABLE t1; + +# MDEV-19974 InnoDB: Cannot load compressed BLOB +CREATE TABLE t1(f1 TEXT, FULLTEXT KEY(f1))ENGINE=InnoDB; +INSERT INTO t1 VALUES(repeat("this is the test case", 500)); +ALTER TABLE t1 KEY_BLOCK_SIZE=4; +ALTER TABLE t1 KEY_BLOCK_SIZE=0; +DROP TABLE t1; + diff --git a/storage/innobase/include/row0ftsort.h b/storage/innobase/include/row0ftsort.h index b2c5651c9c5..b735576fbbb 100644 --- a/storage/innobase/include/row0ftsort.h +++ b/storage/innobase/include/row0ftsort.h @@ -59,6 +59,8 @@ struct fts_psort_t; struct fts_psort_common_t { row_merge_dup_t* dup; /*!< descriptor of FTS index */ dict_table_t* new_table; /*!< source table */ + /* Old table page size */ + page_size_t old_page_size; trx_t* trx; /*!< transaction */ fts_psort_t* all_info; /*!< all parallel sort info */ os_event_t sort_event; /*!< sort event */ @@ -190,26 +192,27 @@ row_merge_create_fts_sort_index( instead of 8 bytes integer to store Doc ID during sort */ -/********************************************************************//** -Initialize FTS parallel sort structures. +/** Initialize FTS parallel sort structures. +@param[in] trx transaction +@param[in,out] dup descriptor of FTS index being created +@param[in] new_table table where indexes are created +@param[in] opt_doc_id_size whether to use 4 bytes instead of 8 bytes + integer to store Doc ID during sort +@param[in] old_page_size page size of the old table during alter +@param[out] psort parallel sort info to be instantiated +@param[out] merge parallel merge info to be instantiated @return TRUE if all successful */ ibool row_fts_psort_info_init( -/*====================*/ - trx_t* trx, /*!< in: transaction */ - row_merge_dup_t* dup, /*!< in,own: descriptor of - FTS index being created */ - const dict_table_t* new_table,/*!< in: table where indexes are - created */ + trx_t* trx, + row_merge_dup_t* dup, + const dict_table_t* new_table, ibool opt_doc_id_size, - /*!< in: whether to use 4 bytes - instead of 8 bytes integer to - store Doc ID during sort */ - fts_psort_t** psort, /*!< out: parallel sort info to be - instantiated */ - fts_psort_t** merge) /*!< out: parallel merge info - to be instantiated */ + const page_size_t old_page_size, + fts_psort_t** psort, + fts_psort_t** merge) MY_ATTRIBUTE((nonnull)); + /********************************************************************//** Clean up and deallocate FTS parallel sort structures, and close temparary merge sort files */ diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index e8ffabca142..f40d6772536 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -159,25 +159,26 @@ row_merge_create_fts_sort_index( return(new_index); } -/*********************************************************************//** -Initialize FTS parallel sort structures. + +/** Initialize FTS parallel sort structures. +@param[in] trx transaction +@param[in,out] dup descriptor of FTS index being created +@param[in] new_table table where indexes are created +@param[in] opt_doc_id_size whether to use 4 bytes instead of 8 bytes + integer to store Doc ID during sort +@param[in] old_page_size page size of the old table during alter +@param[out] psort parallel sort info to be instantiated +@param[out] merge parallel merge info to be instantiated @return TRUE if all successful */ ibool row_fts_psort_info_init( -/*====================*/ - trx_t* trx, /*!< in: transaction */ - row_merge_dup_t* dup, /*!< in,own: descriptor of - FTS index being created */ - const dict_table_t* new_table,/*!< in: table on which indexes are - created */ - ibool opt_doc_id_size, - /*!< in: whether to use 4 bytes - instead of 8 bytes integer to - store Doc ID during sort */ - fts_psort_t** psort, /*!< out: parallel sort info to be - instantiated */ - fts_psort_t** merge) /*!< out: parallel merge info - to be instantiated */ + trx_t* trx, + row_merge_dup_t* dup, + const dict_table_t* new_table, + ibool opt_doc_id_size, + const page_size_t old_page_size, + fts_psort_t** psort, + fts_psort_t** merge) { ulint i; ulint j; @@ -210,6 +211,7 @@ row_fts_psort_info_init( common_info->dup = dup; common_info->new_table = (dict_table_t*) new_table; + common_info->old_page_size = old_page_size; common_info->trx = trx; common_info->all_info = psort_info; common_info->sort_event = os_event_create(0); @@ -803,7 +805,8 @@ DECLARE_THREAD(fts_parallel_tokenization)( block = psort_info->merge_block; crypt_block = psort_info->crypt_block; - const page_size_t& page_size = dict_table_page_size(table); + const page_size_t old_page_size = + psort_info->psort_common->old_page_size; row_merge_fts_get_next_doc_item(psort_info, &doc_item); @@ -833,7 +836,7 @@ loop: doc.text.f_str = btr_copy_externally_stored_field( &doc.text.f_len, data, - page_size, data_len, blob_heap); + old_page_size, data_len, blob_heap); } else { doc.text.f_str = data; doc.text.f_len = data_len; diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index fa85a511ba6..73d4a836d98 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -4678,6 +4678,7 @@ row_merge_build_indexes( created */ if (!row_fts_psort_info_init( trx, dup, new_table, opt_doc_id_size, + dict_table_page_size(old_table), &psort_info, &merge_info)) { error = DB_CORRUPTION; goto func_exit;