mariadb/mysql-test/suite/innodb_fts/t/versioning.test
Thirunarayanan Balathandayuthapani 687b18648c MDEV-35163 InnoDB persistent statistics fail to update after ALTER TABLE...ALGORITHM=COPY
Problem:
=======
- InnoDB statistics calculation for the table is done after
every 10 seconds by default in background thread dict_stats_thread()

- Doing multiple ALTER TABLE..ALGORITHM=COPY causes the
dict_stats_thread() to lag behind, therefore calculation of stats
for newly created intermediate table gets delayed

Fix:
====
- Stats calculation for newly created intermediate table is made
independent of background thread. After copying gets completed,
stats for new table is calculated as part of ALTER TABLE ... ALGORITHM=COPY.

dict_stats_rename_table(): Rename the table statistics from
intermediate table to new table

alter_stats_rebuild(): Removes the table name from the warning.
Because this warning can print for intermediate table as well.

Alter table using copy algorithm now calls alter_stats_rebuild()
under a shared MDL lock on a temporary #sql-alter- table,
differing from its previous use only during ALGORITHM=INPLACE
operations on user-visible tables.

dict_stats_schema_check(): Added a separate check for table
readability before checking for tablespace existence.
This could lead to detect of existence of persistent statistics
storage eariler and fallback to transient statistics.

This is a cherry-pick fix of mysql commit@cfe5f287ae99d004e8532a30003a7e8e77d379e3
2025-09-22 17:39:47 +05:30

134 lines
4.3 KiB
Text

--source include/have_innodb.inc
--source include/have_gzip.inc
--source include/not_embedded.inc
# Combinations
#
# upgrade: test upgrade on prepared databases from std_data.
# prepare: requires $OLD_BINDIR, test upgrade and downgrade with old-version
# server. Also prepare std_data files during the run in the source
# directory (you just have to commit or reject them).
#
# Examples
#
# export OLD_BINDIR="/home/midenok/src/mariadb/10.3b/build"
# ./mtr innodb_fts.versioning,prepare
#
if ($MTR_COMBINATION_PREPARE)
{
if (!$OLD_BINDIR)
{
--skip Requires OLD_BINDIR parameter (see test comment)
}
}
--let $server_id= `select @@server_id`
--let $datadir= `select @@datadir`
--let $std_dir= $MYSQL_TEST_DIR/std_data/versioning
--let $restart_noprint= 3
--echo # Upgrade test
let $stopword_table= articles2;
if ($MTR_COMBINATION_PREPARE)
{
let $restart_bindir= $OLD_BINDIR;
--source include/restart_mysqld.inc
let $create_options= with system versioning;
let $basic_stage= create_table;
--source basic.inc
let $basic_stage= insert_1;
--source basic.inc
let $basic_stage= insert_2;
--source basic.inc
let $basic_stage= insert_3;
--source basic.inc
let $stopword_stage= create_table;
--source stopword.inc
eval insert into $stopword_table (title, body)
values ('test for stopwords','this is it...');
insert into user_stopword values("the");
delete from user_stopword;
insert into user_stopword values("this");
--source include/shutdown_mysqld.inc
--exec mkdir -p $std_dir
--exec cp -af $datadir/ibdata1 $datadir/test/*.frm $std_dir
# zero out the doublewrite buffer
--exec dd if=/dev/zero of=$std_dir/ibdata1 bs=16k seek=64 count=128 conv=notrunc
--exec gzip -9f $std_dir/ibdata1 $std_dir/*.frm
}
if ($MTR_COMBINATION_UPGRADE)
{
--disable_query_log
call mtr.add_suppression("InnoDB: Table `mysql`.\`innodb_(table|index)_stats`");
call mtr.add_suppression("InnoDB: Table mysql\\.innodb_table_stats is not readable");
call mtr.add_suppression("InnoDB: Fetch of persistent statistics requested for table `test`\\.`articles[0-9]*` but the required system tables mysql.innodb_table_stats and mysql.innodb_index_stats are not present or have unexpected structure. Using transient stats instead.");
call mtr.add_suppression("InnoDB: Recalculation of persistent statistics requested for table `test`\\.`#sql-alter.*` but the required persistent statistics storage is not present or is corrupted. Using transient stats instead.");
--enable_query_log
--source include/shutdown_mysqld.inc
--exec rm -f $datadir/test/*.ibd $datadir/ib*
--exec cp -af $std_dir/ibdata1.gz $datadir
--exec cp -af $std_dir/*.frm.gz $datadir/test
--exec gzip -df $datadir/ibdata1.gz $datadir/test/*.frm.gz
}
let $restart_bindir=;
--source include/start_mysqld.inc
--error ER_INDEX_CORRUPT
SELECT * FROM articles WHERE MATCH (title,body)
AGAINST ('Database' IN NATURAL LANGUAGE MODE);
call mtr.add_suppression("test/articles.? contains 3 indexes inside InnoDB");
alter table articles force;
flush tables;
show create table articles;
let $basic_stage= select_1;
source basic.inc;
let $basic_stage= select_2;
source basic.inc;
let $basic_stage= select_3;
source basic.inc;
set global innodb_ft_server_stopword_table= "test/user_stopword";
let $stopword_stage= select_1;
--source stopword.inc
eval drop index idx on $stopword_table;
eval create fulltext index idx on $stopword_table(title, body);
--source stopword.inc
if ($MTR_COMBINATION_PREPARE)
{
--echo # Downgrade test
let $restart_bindir= $OLD_BINDIR;
--source include/restart_mysqld.inc
alter table articles force;
flush tables;
show create table articles;
let $basic_stage= select_1;
source basic.inc;
let $basic_stage= select_2;
source basic.inc;
let $basic_stage= select_3;
source basic.inc;
set global innodb_ft_server_stopword_table= "test/user_stopword";
let $stopword_stage= select_1;
# Downgrade faults with assertion "dict_index_get_n_unique(index) == 1"
# until we rebuilt the index:
eval drop index idx on $stopword_table;
eval create fulltext index idx on $stopword_table(title, body);
source stopword.inc;
let $restart_bindir=;
--source include/restart_mysqld.inc
}
--echo # Cleanup
eval drop tables articles, $stopword_table, user_stopword;
set global innodb_ft_server_stopword_table= default;