Merge 10.8 into 10.9

This commit is contained in:
Marko Mäkelä 2022-06-15 10:01:51 +03:00
commit 9fe784ff7e
36 changed files with 390 additions and 612 deletions

View file

@ -1,6 +1,13 @@
# These should be moved, see https://jira.mariadb.org/browse/MDEV-21654 # These should be moved, see https://jira.mariadb.org/browse/MDEV-21654
arch-dependent-file-in-usr-share usr/share/mysql/mysql-test/suite/plugins/pam/pam_mariadb_mtr.so arch-dependent-file-in-usr-share usr/share/mysql/mysql-test/suite/plugins/pam/pam_mariadb_mtr.so
arch-independent-package-contains-binary-or-object usr/share/mysql/mysql-test/suite/plugins/pam/pam_mariadb_mtr.so arch-independent-package-contains-binary-or-object usr/share/mysql/mysql-test/suite/plugins/pam/pam_mariadb_mtr.so
# Mainly for support for *BSD family. Not right way to do but this is test package and not for production
incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/std_data/checkDBI_DBD-MariaDB.pl]
incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/suite/engines/rr_trx/run_stress_tx_rr.pl]
incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/suite/funcs_1/lib/DataGen_local.pl]
incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/suite/funcs_1/lib/DataGen_modify.pl]
incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/suite/funcs_2/lib/gen_charset_utf8.pl]
incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/suite/rpl/extension/checksum.pl]
# Intentional for test files # Intentional for test files
national-encoding usr/share/mysql/mysql-test/* national-encoding usr/share/mysql/mysql-test/*
# Extra test documentation files that really need to be kept in context in test directory # Extra test documentation files that really need to be kept in context in test directory

View file

@ -1,3 +1,8 @@
# These should be moved, see https://jira.mariadb.org/browse/MDEV-21653 # These should be moved, see https://jira.mariadb.org/browse/MDEV-21653
arch-dependent-file-in-usr-share usr/share/mysql/mysql-test/lib/My/SafeProcess/my_safe_process arch-dependent-file-in-usr-share usr/share/mysql/mysql-test/lib/My/SafeProcess/my_safe_process
arch-dependent-file-in-usr-share usr/share/mysql/mysql-test/lib/My/SafeProcess/wsrep_check_version arch-dependent-file-in-usr-share usr/share/mysql/mysql-test/lib/My/SafeProcess/wsrep_check_version
# Mainly for support for *BSD family. Not right way to do but this is test package and not for production
incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/lib/process-purecov-annotations.pl]
incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/lib/v1/mysql-test-run.pl]
incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/mysql-stress-test.pl]
incorrect-path-for-interpreter /usr/bin/env perl != /usr/bin/perl [usr/share/mysql/mysql-test/mysql-test-run.pl]

View file

@ -4,15 +4,10 @@ version-substvar-for-external-package mariadb-client-core -> mysql-client-5.5
version-substvar-for-external-package mariadb-server -> mysql-server version-substvar-for-external-package mariadb-server -> mysql-server
version-substvar-for-external-package libmariadb-dev -> libmysqlclient-dev version-substvar-for-external-package libmariadb-dev -> libmysqlclient-dev
version-substvar-for-external-package libmariadb-dev -> libmysqld-dev version-substvar-for-external-package libmariadb-dev -> libmysqld-dev
version-substvar-for-external-package mariadb-server -> mysql-client-5.5 version-substvar-for-external-package mariadb-server-10.9 -> mysql-client-5.*
version-substvar-for-external-package mariadb-server -> mysql-client-5.6 version-substvar-for-external-package mariadb-server-10.9 -> mysql-client-8.*
version-substvar-for-external-package mariadb-server -> mysql-client-5.7 version-substvar-for-external-package mariadb-client-10.9 -> mysql-client-core-5.*
version-substvar-for-external-package mariadb-server -> mysql-client-8.0 version-substvar-for-external-package mariadb-client-10.9 -> mysql-client-core-8.*
version-substvar-for-external-package mariadb-client -> mysql-client-core-5.1
version-substvar-for-external-package mariadb-client -> mysql-client-core-5.5
version-substvar-for-external-package mariadb-client -> mysql-client-core-5.6
version-substvar-for-external-package mariadb-client -> mysql-client-core-5.7
version-substvar-for-external-package mariadb-client -> mysql-client-core-8.0
version-substvar-for-external-package libmariadbd-dev -> libmariadbclient-dev version-substvar-for-external-package libmariadbd-dev -> libmariadbclient-dev
# Intentional version-substvar-for-external-package as long as mariadb-server # Intentional version-substvar-for-external-package as long as mariadb-server
# provides mariadb-server-10.9 and mariadb-client provides mariadb-client-10.9 # provides mariadb-server-10.9 and mariadb-client provides mariadb-client-10.9
@ -34,10 +29,72 @@ version-substvar-for-external-package Replaces (line 748) ${source:Version} mari
# ColumnStore not used in Debian, safe to ignore. Reported upstream in https://jira.mariadb.org/browse/MDEV-24124 # ColumnStore not used in Debian, safe to ignore. Reported upstream in https://jira.mariadb.org/browse/MDEV-24124
source-is-missing storage/columnstore/columnstore/utils/jemalloc/libjemalloc.so.2 source-is-missing storage/columnstore/columnstore/utils/jemalloc/libjemalloc.so.2
# Must be fixed upstream # Must be fixed upstream
source-is-missing storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-1.8.18.custom.js* source-is-missing storage/mroonga/vendor/groonga/examples/dictionary/html/js/jquery-ui-*.custom.js
# Intentional control relationships # Intentional control relationships
version-substvar-for-external-package Replaces * ${source:Version} libmariadbd-dev -> libmariadbclient-dev version-substvar-for-external-package Replaces * libmariadbd-dev -> libmariadbclient-dev
version-substvar-for-external-package Replaces * ${source:Version} libmariadb-dev -> libmysqlclient-dev version-substvar-for-external-package Replaces * libmariadb-dev -> libmysqlclient-dev
version-substvar-for-external-package Replaces * ${source:Version} libmariadb-dev -> libmysqld-dev version-substvar-for-external-package Replaces * libmariadb-dev -> libmysqld-dev
# We can't change build dependencies on a stable branch (10.5..10.8) so just override this # Data or test files where long lines are justified
missing-build-dependency-for-dh-addon systemd * very-long-line-length-in-source-file *.test *
very-long-line-length-in-source-file *.result *
very-long-line-length-in-source-file BUILD/compile-*
very-long-line-length-in-source-file *COPYING.rtf *
# These are mainly found under extra/wolfssl
very-long-line-length-in-source-file *.cproject *
very-long-line-length-in-source-file *.md *
very-long-line-length-in-source-file *.scfg *
very-long-line-length-in-source-file *.launch *
very-long-line-length-in-source-file extra/wolfssl/wolfssl/IDE/Espressif/ESP-IDF/test/test_wolfssl.c *
very-long-line-length-in-source-file extra/wolfssl/wolfssl/configure.ac *
very-long-line-length-in-source-file extra/wolfssl/wolfssl/doc/formats/html/html_changes/tabs.css *
# Preprocessed C files which have long lines
very-long-line-length-in-source-file extra/wolfssl/wolfssl/wolfcrypt/src/*.i *
# These are all results for test cases and similar so they can be
# especially formatted to be too long
very-long-line-length-in-source-file mysql-test/*.dump *
very-long-line-length-in-source-file mysql-test/*.inc *
very-long-line-length-in-source-file mysql-test/*.rdiff *
very-long-line-length-in-source-file mysql-test/*.txt *
very-long-line-length-in-source-file mysql-test/*.weekly *
# Test file
very-long-line-length-in-source-file plugin/handler_socket/regtest/test_01_lib/test19.expected *
# SQL source file that has very long inserts/selects
very-long-line-length-in-source-file mysql-test/std_data/init_file_longline_3816.sql *
very-long-line-length-in-source-file scripts/fill_help_tables.sql *
very-long-line-length-in-source-file scripts/mysql_system_tables.sql *
very-long-line-length-in-source-file scripts/mysql_test_data_timezone.sql *
# Machine formated HTML
very-long-line-length-in-source-file sql/share/charsets/languages.html *
very-long-line-length-in-source-file sql/share/errmsg-utf8.txt *
# Very long test string
very-long-line-length-in-source-file storage/archive/archive_test.c line 30 is 1051 characters long (>512)
# autogenerated thrift file
very-long-line-length-in-source-file storage/cassandra/gen-cpp/cassandra_types.h *
# ColumnStore ignores
# In Directory mysql-test are some long test includes
very-long-line-length-in-source-file storage/columnstore/columnstore/.drone.jsonnet *
very-long-line-length-in-source-file storage/columnstore/columnstore/CMakeLists.txt *
very-long-line-length-in-source-file storage/columnstore/columnstore/mysql-test/columnstore/csinternal/include/autopilot_create_datatypetestm_tables.inc *
very-long-line-length-in-source-file storage/columnstore/columnstore/mysql-test/columnstore/csinternal/include/autopilot_create_datatypeupdate_table.inc *
very-long-line-length-in-source-file storage/columnstore/columnstore/*.xmi *
very-long-line-length-in-source-file storage/columnstore/columnstore/dbcon/doc/q19_plan.txt *
very-long-line-length-in-source-file storage/columnstore/columnstore/utils/udfsdk/docs/source/reference/mcsv1Context.rst *
very-long-line-length-in-source-file storage/columnstore/columnstore/utils/winport/win_setup_mysql_part1.sql *
# Minified CSS files. These appear in several places
very-long-line-length-in-source-file *badge_only.css *
very-long-line-length-in-source-file *theme.css line *
# General storage ignores
very-long-line-length-in-source-file storage/mroonga/vendor/groonga/examples/dictionary/html/css/smoothness/jquery-ui-1.8.12.custom.css *
very-long-line-length-in-source-file storage/rocksdb/mysql-test/rocksdb/t/bypass_select_basic_bloom-master.opt *
very-long-line-length-in-source-file storage/rocksdb/mysql-test/rocksdb/t/type_enum.inc *
very-long-line-length-in-source-file storage/rocksdb/mysql-test/rocksdb/t/type_set.inc *
very-long-line-length-in-source-file storage/rocksdb/rocksdb/docs/_includes/footer.html *
very-long-line-length-in-source-file storage/rocksdb/rocksdb/docs/_posts/*.markdown line *
very-long-line-length-in-source-file storage/spider/mysql-test/spider/bugfix/include/sql_mode_init.inc *
very-long-line-length-in-source-file storage/tokudb/PerconaFT/cmake_modules/TokuBuildTagDatabases.cmake *
very-long-line-length-in-source-file storage/tokudb/PerconaFT/third_party/xz-4.999.9beta/m4/po.m4 *
# These are generated files which should not make any harm
source-contains-autogenerated-visual-c++-file storage/columnstore/columnstore/*.rc
source-contains-autogenerated-visual-c++-file storage/columnstore/columnstore/*.h
source-contains-autogenerated-visual-c++-file win/upgrade_wizard/resource.h
source-contains-autogenerated-visual-c++-file win/upgrade_wizard/upgrade.rc

View file

@ -0,0 +1,16 @@
#
# MDEV-28802 DROP DATABASE in InnoDB still is case-insensitive
#
SET @save_fpt=@@GLOBAL.innodb_file_per_table;
SET GLOBAL innodb_file_per_table=0;
CREATE DATABASE Db;
CREATE TABLE Db.t1 (c1 INT KEY) ENGINE=InnoDB;
CREATE DATABASE DB;
DROP DATABASE DB;
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'D%';
NAME
Db/t1
DROP DATABASE Db;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'D%';
TABLE_ID NAME FLAG N_COLS SPACE ROW_FORMAT ZIP_PAGE_SIZE SPACE_TYPE
SET GLOBAL innodb_file_per_table=@save_fpt;

View file

@ -0,0 +1,17 @@
--source include/have_innodb.inc
--source include/have_case_sensitive_file_system.inc
--echo #
--echo # MDEV-28802 DROP DATABASE in InnoDB still is case-insensitive
--echo #
SET @save_fpt=@@GLOBAL.innodb_file_per_table;
SET GLOBAL innodb_file_per_table=0;
CREATE DATABASE Db;
CREATE TABLE Db.t1 (c1 INT KEY) ENGINE=InnoDB;
CREATE DATABASE DB;
DROP DATABASE DB;
SELECT NAME FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'D%';
DROP DATABASE Db;
SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'D%';
SET GLOBAL innodb_file_per_table=@save_fpt;

View file

@ -19,7 +19,7 @@ INSERT INTO t2 VALUES('mariadb');
connection default; connection default;
SET @saved_dbug = @@GLOBAL.debug_dbug; SET @saved_dbug = @@GLOBAL.debug_dbug;
SET GLOBAL debug_dbug ='+d,fts_instrument_sync_request,ib_optimize_wq_hang'; SET GLOBAL debug_dbug ='+d,fts_instrument_sync_request,ib_optimize_wq_hang';
SET DEBUG_SYNC= 'fts_instrument_sync_request SET DEBUG_SYNC= 'fts_sync_end
SIGNAL drop_index_start WAIT_FOR sync_op'; SIGNAL drop_index_start WAIT_FOR sync_op';
INSERT INTO t1 VALUES('Keyword'); INSERT INTO t1 VALUES('Keyword');
connect con1,localhost,root,,,; connect con1,localhost,root,,,;

View file

@ -11,19 +11,19 @@ INSERT INTO t1(title) VALUES('database');
connection con1; connection con1;
SET @old_dbug = @@SESSION.debug_dbug; SET @old_dbug = @@SESSION.debug_dbug;
SET debug_dbug = '+d,fts_instrument_sync_debug'; SET debug_dbug = '+d,fts_instrument_sync_debug';
SET DEBUG_SYNC= 'fts_write_node SIGNAL written WAIT_FOR selected'; SET DEBUG_SYNC= 'fts_sync_end SIGNAL written WAIT_FOR selected';
INSERT INTO t1(title) VALUES('mysql database'); INSERT INTO t1(title) VALUES('mysql database');
connection default; connection default;
SET DEBUG_SYNC= 'now WAIT_FOR written'; SET DEBUG_SYNC= 'now WAIT_FOR written';
SET GLOBAL innodb_ft_aux_table="test/t1"; SET GLOBAL innodb_ft_aux_table="test/t1";
SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE;
WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION
SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE;
WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION
database 2 3 2 2 0 database 2 3 2 2 0
database 2 3 2 3 6 database 2 3 2 3 6
mysql 1 3 2 1 0 mysql 1 3 2 1 0
mysql 1 3 2 3 0 mysql 1 3 2 3 0
SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE;
WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION
SET GLOBAL innodb_ft_aux_table=default; SET GLOBAL innodb_ft_aux_table=default;
SELECT * FROM t1 WHERE MATCH(title) AGAINST('mysql database'); SELECT * FROM t1 WHERE MATCH(title) AGAINST('mysql database');
FTS_DOC_ID title FTS_DOC_ID title
@ -59,7 +59,7 @@ INSERT INTO t1(title) VALUES('mysql');
INSERT INTO t1(title) VALUES('database'); INSERT INTO t1(title) VALUES('database');
connection con1; connection con1;
SET debug_dbug = '+d,fts_instrument_sync_debug'; SET debug_dbug = '+d,fts_instrument_sync_debug';
SET DEBUG_SYNC= 'fts_write_node SIGNAL written WAIT_FOR inserted'; SET DEBUG_SYNC= 'fts_sync_end SIGNAL written WAIT_FOR inserted';
INSERT INTO t1(title) VALUES('mysql database'); INSERT INTO t1(title) VALUES('mysql database');
connection default; connection default;
SET DEBUG_SYNC= 'now WAIT_FOR written'; SET DEBUG_SYNC= 'now WAIT_FOR written';
@ -70,14 +70,14 @@ SET debug_dbug = @old_dbug;
SET GLOBAL innodb_ft_aux_table="test/t1"; SET GLOBAL innodb_ft_aux_table="test/t1";
SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE; SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE;
WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION
database 4 4 1 4 6
mysql 4 4 1 4 0
SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE; SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_INDEX_TABLE;
WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION WORD FIRST_DOC_ID LAST_DOC_ID DOC_COUNT DOC_ID POSITION
database 2 3 2 2 0 database 2 3 2 2 0
database 2 3 2 3 6 database 2 3 2 3 6
database 4 4 1 4 6 mysql 1 3 2 1 0
mysql 1 4 3 1 0 mysql 1 3 2 3 0
mysql 1 4 3 3 0
mysql 1 4 3 4 0
SET GLOBAL innodb_ft_aux_table=default; SET GLOBAL innodb_ft_aux_table=default;
SELECT * FROM t1 WHERE MATCH(title) AGAINST('mysql database'); SELECT * FROM t1 WHERE MATCH(title) AGAINST('mysql database');
FTS_DOC_ID title FTS_DOC_ID title

View file

@ -1,83 +0,0 @@
SET @old_log_output = @@global.log_output;
SET @old_slow_query_log = @@global.slow_query_log;
SET @old_general_log = @@global.general_log;
SET @old_long_query_time = @@global.long_query_time;
SET @old_debug = @@global.debug_dbug;
SET GLOBAL log_output = 'TABLE';
SET GLOBAL general_log = 1;
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 1;
connect con1,localhost,root,,;
connect con2,localhost,root,,;
connection default;
# Case 1: Sync blocks DML(insert) on the same table.
CREATE TABLE t1 (
FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
FULLTEXT(title)
) ENGINE = InnoDB;
connection con1;
SET GLOBAL debug_dbug='+d,fts_instrument_sync_debug,fts_instrument_sync_sleep';
SET DEBUG_SYNC= 'fts_sync_begin SIGNAL begin WAIT_FOR continue';
INSERT INTO t1(title) VALUES('mysql database');
connection con2;
SET DEBUG_SYNC= 'now WAIT_FOR begin';
SELECT * FROM t1 WHERE MATCH(title) AGAINST('mysql database');
connection default;
SET DEBUG_SYNC= 'now SIGNAL continue';
connection con1;
/* connection con1 */ INSERT INTO t1(title) VALUES('mysql database');
connection con2;
/* conneciton con2 */ SELECT * FROM t1 WHERE MATCH(title) AGAINST('mysql database');
FTS_DOC_ID title
connection default;
# make con1 & con2 show up in mysql.slow_log
SELECT SLEEP(2);
SLEEP(2)
0
# slow log results should only contain INSERT INTO t1.
SELECT sql_text FROM mysql.slow_log WHERE query_time >= '00:00:02';
sql_text
INSERT INTO t1(title) VALUES('mysql database')
SET GLOBAL debug_dbug = @old_debug;
TRUNCATE TABLE mysql.slow_log;
DROP TABLE t1;
# Case 2: Sync blocks DML(insert) on other tables.
CREATE TABLE t1 (
FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
FULLTEXT(title)
) ENGINE = InnoDB;
CREATE TABLE t2(id INT);
connection con1;
SET GLOBAL debug_dbug='+d,fts_instrument_sync_request,fts_instrument_sync_sleep';
SET DEBUG_SYNC= 'fts_instrument_sync_request SIGNAL begin WAIT_FOR continue';
INSERT INTO t1(title) VALUES('mysql database');
connection con2;
SET DEBUG_SYNC= 'now WAIT_FOR begin';
INSERT INTO t2 VALUES(1);
connection default;
SET DEBUG_SYNC= 'now SIGNAL continue';
connection con1;
/* connection con1 */ INSERT INTO t1(title) VALUES('mysql database');
connection con2;
/* conneciton con2 */ INSERT INTO t2 VALUES(1);
connection default;
SET DEBUG_SYNC = 'RESET';
# make con1 & con2 show up in mysql.slow_log
SELECT SLEEP(2);
SLEEP(2)
0
# slow log results should be empty here.
SELECT sql_text FROM mysql.slow_log WHERE query_time >= '00:00:02';
sql_text
SET GLOBAL debug_dbug = @old_debug;
TRUNCATE TABLE mysql.slow_log;
DROP TABLE t1,t2;
disconnect con1;
disconnect con2;
# Restore slow log settings.
SET GLOBAL log_output = @old_log_output;
SET GLOBAL general_log = @old_general_log;
SET GLOBAL slow_query_log = @old_slow_query_log;
SET GLOBAL long_query_time = @old_long_query_time;

View file

@ -31,7 +31,7 @@ INSERT INTO t2 VALUES('mariadb');
connection default; connection default;
SET @saved_dbug = @@GLOBAL.debug_dbug; SET @saved_dbug = @@GLOBAL.debug_dbug;
SET GLOBAL debug_dbug ='+d,fts_instrument_sync_request,ib_optimize_wq_hang'; SET GLOBAL debug_dbug ='+d,fts_instrument_sync_request,ib_optimize_wq_hang';
SET DEBUG_SYNC= 'fts_instrument_sync_request SET DEBUG_SYNC= 'fts_sync_end
SIGNAL drop_index_start WAIT_FOR sync_op'; SIGNAL drop_index_start WAIT_FOR sync_op';
send INSERT INTO t1 VALUES('Keyword'); send INSERT INTO t1 VALUES('Keyword');

View file

@ -26,7 +26,7 @@ connection con1;
SET @old_dbug = @@SESSION.debug_dbug; SET @old_dbug = @@SESSION.debug_dbug;
SET debug_dbug = '+d,fts_instrument_sync_debug'; SET debug_dbug = '+d,fts_instrument_sync_debug';
SET DEBUG_SYNC= 'fts_write_node SIGNAL written WAIT_FOR selected'; SET DEBUG_SYNC= 'fts_sync_end SIGNAL written WAIT_FOR selected';
send INSERT INTO t1(title) VALUES('mysql database'); send INSERT INTO t1(title) VALUES('mysql database');
@ -73,7 +73,7 @@ connection con1;
SET debug_dbug = '+d,fts_instrument_sync_debug'; SET debug_dbug = '+d,fts_instrument_sync_debug';
SET DEBUG_SYNC= 'fts_write_node SIGNAL written WAIT_FOR inserted'; SET DEBUG_SYNC= 'fts_sync_end SIGNAL written WAIT_FOR inserted';
send INSERT INTO t1(title) VALUES('mysql database'); send INSERT INTO t1(title) VALUES('mysql database');

View file

@ -1,124 +0,0 @@
#
# BUG#22516559 MYSQL INSTANCE STALLS WHEN SYNCING FTS INDEX
#
--source include/have_innodb.inc
--source include/have_debug.inc
--source include/have_debug_sync.inc
--source include/have_log_bin.inc
--source include/count_sessions.inc
SET @old_log_output = @@global.log_output;
SET @old_slow_query_log = @@global.slow_query_log;
SET @old_general_log = @@global.general_log;
SET @old_long_query_time = @@global.long_query_time;
SET @old_debug = @@global.debug_dbug;
SET GLOBAL log_output = 'TABLE';
SET GLOBAL general_log = 1;
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 1;
connect (con1,localhost,root,,);
connect (con2,localhost,root,,);
connection default;
--echo # Case 1: Sync blocks DML(insert) on the same table.
CREATE TABLE t1 (
FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
FULLTEXT(title)
) ENGINE = InnoDB;
connection con1;
SET GLOBAL debug_dbug='+d,fts_instrument_sync_debug,fts_instrument_sync_sleep';
SET DEBUG_SYNC= 'fts_sync_begin SIGNAL begin WAIT_FOR continue';
send INSERT INTO t1(title) VALUES('mysql database');
connection con2;
SET DEBUG_SYNC= 'now WAIT_FOR begin';
send SELECT * FROM t1 WHERE MATCH(title) AGAINST('mysql database');
connection default;
SET DEBUG_SYNC= 'now SIGNAL continue';
connection con1;
--echo /* connection con1 */ INSERT INTO t1(title) VALUES('mysql database');
--reap
connection con2;
--echo /* conneciton con2 */ SELECT * FROM t1 WHERE MATCH(title) AGAINST('mysql database');
--reap
connection default;
-- echo # make con1 & con2 show up in mysql.slow_log
SELECT SLEEP(2);
-- echo # slow log results should only contain INSERT INTO t1.
SELECT sql_text FROM mysql.slow_log WHERE query_time >= '00:00:02';
SET GLOBAL debug_dbug = @old_debug;
TRUNCATE TABLE mysql.slow_log;
DROP TABLE t1;
--echo # Case 2: Sync blocks DML(insert) on other tables.
CREATE TABLE t1 (
FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
FULLTEXT(title)
) ENGINE = InnoDB;
CREATE TABLE t2(id INT);
connection con1;
SET GLOBAL debug_dbug='+d,fts_instrument_sync_request,fts_instrument_sync_sleep';
SET DEBUG_SYNC= 'fts_instrument_sync_request SIGNAL begin WAIT_FOR continue';
send INSERT INTO t1(title) VALUES('mysql database');
connection con2;
SET DEBUG_SYNC= 'now WAIT_FOR begin';
send INSERT INTO t2 VALUES(1);
connection default;
SET DEBUG_SYNC= 'now SIGNAL continue';
connection con1;
--echo /* connection con1 */ INSERT INTO t1(title) VALUES('mysql database');
--reap
connection con2;
--echo /* conneciton con2 */ INSERT INTO t2 VALUES(1);
--reap
connection default;
SET DEBUG_SYNC = 'RESET';
-- echo # make con1 & con2 show up in mysql.slow_log
SELECT SLEEP(2);
-- echo # slow log results should be empty here.
SELECT sql_text FROM mysql.slow_log WHERE query_time >= '00:00:02';
SET GLOBAL debug_dbug = @old_debug;
TRUNCATE TABLE mysql.slow_log;
DROP TABLE t1,t2;
disconnect con1;
disconnect con2;
--source include/wait_until_count_sessions.inc
-- echo # Restore slow log settings.
SET GLOBAL log_output = @old_log_output;
SET GLOBAL general_log = @old_general_log;
SET GLOBAL slow_query_log = @old_slow_query_log;
SET GLOBAL long_query_time = @old_long_query_time;

View file

@ -6,12 +6,12 @@ create table t1 (pk int primary key, a int, key(a)) engine=aria transactional=1;
alter table t1 disable keys; alter table t1 disable keys;
insert into t1 values (1,1); insert into t1 values (1,1);
alter table t1 enable keys; alter table t1 enable keys;
ERROR HY000: Unknown key id 1 for ./test/t1. Can't continue! ERROR HY000: Unknown key id 1 for test/t1. Can't continue!
repair table t1 use_frm; repair table t1 use_frm;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 repair warning Number of rows changed from 0 to 1 test.t1 repair warning Number of rows changed from 0 to 1
test.t1 repair Error Unknown key id 1 for ./test/t1. Can't continue! test.t1 repair Error Unknown key id 1 for test/t1. Can't continue!
test.t1 repair Error Unknown key id 1 for ./test/t1. Can't continue! test.t1 repair Error Unknown key id 1 for test/t1. Can't continue!
test.t1 repair status OK test.t1 repair status OK
drop table t1; drop table t1;
set global aria_encrypt_tables= default; set global aria_encrypt_tables= default;

View file

@ -10,9 +10,11 @@ create table t1 (pk int primary key, a int, key(a)) engine=aria transactional=1;
alter table t1 disable keys; alter table t1 disable keys;
insert into t1 values (1,1); insert into t1 values (1,1);
--replace_result \\ / --replace_result \\ /
--replace_regex /for .*test/for test/
--error 192 --error 192
alter table t1 enable keys; alter table t1 enable keys;
--replace_result \\ / --replace_result \\ /
--replace_regex /for .*test/for test/
repair table t1 use_frm; repair table t1 use_frm;
drop table t1; drop table t1;
set global aria_encrypt_tables= default; set global aria_encrypt_tables= default;

View file

@ -26,9 +26,9 @@ a
ThursdayMorningsMarket ThursdayMorningsMarket
ThursdayMorningsMarketb ThursdayMorningsMarketb
Warnings: Warnings:
Error 145 Got error '145 "Table was marked as crashed and should be repaired"' for './mysqltest/t_corrupted2' Error 145 Got error '145 "Table was marked as crashed and should be repaired"' for 't_corrupted2'
Warning 1034 1 client is using or hasn't closed the table properly Warning 1034 1 client is using or hasn't closed the table properly
Error 176 Got error '176 "Read page with wrong checksum"' for './mysqltest/t_corrupted2.MAI' Error 176 Got error '176 "Read page with wrong checksum"' for 't_corrupted2.MAI'
Error 1034 Can't read indexpage from page: 1, error: 176 Error 1034 Can't read indexpage from page: 1, error: 176
select * from t_corrupted2; select * from t_corrupted2;
a a

View file

@ -79,6 +79,7 @@ perl;
close FILE; close FILE;
EOF EOF
--replace_result \\ / --replace_result \\ /
--replace_regex /for '.*t_corrupted2/for 't_corrupted2/
--enable_prepare_warnings --enable_prepare_warnings
select * from t_corrupted2; # should show corruption and repair messages select * from t_corrupted2; # should show corruption and repair messages
--disable_prepare_warnings --disable_prepare_warnings

View file

@ -78,3 +78,11 @@ if (`SELECT IF('$engine' != 'InnoDB', 1, 0)`)
--remove_files_wildcard $MYSQLTEST_VARDIR/tmp/mdev_27065 * --remove_files_wildcard $MYSQLTEST_VARDIR/tmp/mdev_27065 *
--rmdir $MYSQLTEST_VARDIR/tmp/mdev_27065 --rmdir $MYSQLTEST_VARDIR/tmp/mdev_27065
--echo #
--echo # MDEV-26127 Assertion `err != DB_DUPLICATE_KEY' failed or InnoDB: Failing assertion: id != 0 on ALTER ... REBUILD PARTITION
--echo #
--eval CREATE TABLE t1 (c INT) ENGINE=$engine PARTITION BY KEY(c) PARTITIONS 4;
LOCK TABLES t1 WRITE, t1 AS a READ;
ALTER TABLE t1 REBUILD PARTITION p0;
DROP TABLE t1;

View file

@ -62,6 +62,13 @@ Warnings:
Warning 1618 <DATA DIRECTORY> table option of old schema is ignored Warning 1618 <DATA DIRECTORY> table option of old schema is ignored
DROP TABLE t1; DROP TABLE t1;
# #
# MDEV-26127 Assertion `err != DB_DUPLICATE_KEY' failed or InnoDB: Failing assertion: id != 0 on ALTER ... REBUILD PARTITION
#
CREATE TABLE t1 (c INT) ENGINE=InnoDB PARTITION BY KEY(c) PARTITIONS 4;;
LOCK TABLES t1 WRITE, t1 AS a READ;
ALTER TABLE t1 REBUILD PARTITION p0;
DROP TABLE t1;
#
# MDEV-28079 Shutdown hangs after altering innodb partition fts table # MDEV-28079 Shutdown hangs after altering innodb partition fts table
# #
CREATE TABLE t1(f1 INT, f2 CHAR(100))ENGINE=InnoDB PARTITION BY HASH(f1) PARTITIONS 2; CREATE TABLE t1(f1 INT, f2 CHAR(100))ENGINE=InnoDB PARTITION BY HASH(f1) PARTITIONS 2;

View file

@ -95,3 +95,10 @@ PARTITION p1 VALUES LESS THAN MAXVALUE
Warnings: Warnings:
Warning 1618 <INDEX DIRECTORY> table option of old schema is ignored Warning 1618 <INDEX DIRECTORY> table option of old schema is ignored
DROP TABLE t2; DROP TABLE t2;
#
# MDEV-26127 Assertion `err != DB_DUPLICATE_KEY' failed or InnoDB: Failing assertion: id != 0 on ALTER ... REBUILD PARTITION
#
CREATE TABLE t1 (c INT) ENGINE=Aria PARTITION BY KEY(c) PARTITIONS 4;;
LOCK TABLES t1 WRITE, t1 AS a READ;
ALTER TABLE t1 REBUILD PARTITION p0;
DROP TABLE t1;

View file

@ -68,6 +68,13 @@ PARTITION p1 VALUES LESS THAN MAXVALUE
Warnings: Warnings:
Warning 1618 <INDEX DIRECTORY> table option of old schema is ignored Warning 1618 <INDEX DIRECTORY> table option of old schema is ignored
DROP TABLE t2; DROP TABLE t2;
#
# MDEV-26127 Assertion `err != DB_DUPLICATE_KEY' failed or InnoDB: Failing assertion: id != 0 on ALTER ... REBUILD PARTITION
#
CREATE TABLE t1 (c INT) ENGINE=MyISAM PARTITION BY KEY(c) PARTITIONS 4;;
LOCK TABLES t1 WRITE, t1 AS a READ;
ALTER TABLE t1 REBUILD PARTITION p0;
DROP TABLE t1;
create table t1 ( c1 int, c2 int, c3 varchar(100)) delay_key_write=1 create table t1 ( c1 int, c2 int, c3 varchar(100)) delay_key_write=1
partition by key(c1) ( partition by key(c1) (
partition p01 data directory = 'MYSQL_TMP_DIR' partition p01 data directory = 'MYSQL_TMP_DIR'

View file

@ -5,6 +5,7 @@ variable_name not in (
'innodb_numa_interleave', # only available WITH_NUMA 'innodb_numa_interleave', # only available WITH_NUMA
'innodb_evict_tables_on_commit_debug', # one may want to override this 'innodb_evict_tables_on_commit_debug', # one may want to override this
'innodb_use_native_aio', # default value depends on OS 'innodb_use_native_aio', # default value depends on OS
'innodb_log_file_buffering', # only available on Linux and Windows
'innodb_buffer_pool_load_pages_abort') # debug build only, and is only for testing 'innodb_buffer_pool_load_pages_abort') # debug build only, and is only for testing
order by variable_name; order by variable_name;
VARIABLE_NAME INNODB_ADAPTIVE_FLUSHING VARIABLE_NAME INNODB_ADAPTIVE_FLUSHING
@ -1020,7 +1021,7 @@ SESSION_VALUE NULL
DEFAULT_VALUE DEFAULT_VALUE
VARIABLE_SCOPE GLOBAL VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE VARCHAR VARIABLE_TYPE VARCHAR
VARIABLE_COMMENT Path to InnoDB log files. VARIABLE_COMMENT Path to ib_logfile0
NUMERIC_MIN_VALUE NULL NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL NUMERIC_BLOCK_SIZE NULL

View file

@ -12,5 +12,6 @@ select VARIABLE_NAME, SESSION_VALUE, DEFAULT_VALUE, VARIABLE_SCOPE, VARIABLE_TYP
'innodb_numa_interleave', # only available WITH_NUMA 'innodb_numa_interleave', # only available WITH_NUMA
'innodb_evict_tables_on_commit_debug', # one may want to override this 'innodb_evict_tables_on_commit_debug', # one may want to override this
'innodb_use_native_aio', # default value depends on OS 'innodb_use_native_aio', # default value depends on OS
'innodb_log_file_buffering', # only available on Linux and Windows
'innodb_buffer_pool_load_pages_abort') # debug build only, and is only for testing 'innodb_buffer_pool_load_pages_abort') # debug build only, and is only for testing
order by variable_name; order by variable_name;

View file

@ -1,5 +1,5 @@
/* Copyright (c) 2005, 2017, Oracle and/or its affiliates. /* Copyright (c) 2005, 2017, Oracle and/or its affiliates.
Copyright (c) 2009, 2020, 2021, MariaDB Copyright (c) 2009, 2022, MariaDB
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
@ -7027,16 +7027,33 @@ static bool alter_partition_lock_handling(ALTER_PARTITION_PARAM_TYPE *lpt)
static int alter_close_table(ALTER_PARTITION_PARAM_TYPE *lpt) static int alter_close_table(ALTER_PARTITION_PARAM_TYPE *lpt)
{ {
int error= 0; THD *thd= lpt->thd;
TABLE_SHARE *share= lpt->table->s;
DBUG_ENTER("alter_close_table"); DBUG_ENTER("alter_close_table");
if (lpt->table->db_stat) TABLE *table= thd->open_tables;
{ do {
error= mysql_lock_remove(lpt->thd, lpt->thd->lock, lpt->table); table= find_locked_table(table, share->db.str, share->table_name.str);
error= lpt->table->file->ha_close(); if (!table)
lpt->table->db_stat= 0; // Mark file closed {
} DBUG_RETURN(0);
DBUG_RETURN(error); }
if (table->db_stat)
{
if (int error= mysql_lock_remove(thd, thd->lock, table))
{
DBUG_RETURN(error);
}
if (int error= table->file->ha_close())
{
DBUG_RETURN(error);
}
table->db_stat= 0; // Mark file closed
}
} while ((table= table->next));
DBUG_RETURN(0);
} }

View file

@ -1206,7 +1206,6 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n)
n->flushed + n->evicted < max) || n->flushed + n->evicted < max) ||
recv_recovery_is_on()); ++scanned) recv_recovery_is_on()); ++scanned)
{ {
retry:
buf_page_t *prev= UT_LIST_GET_PREV(LRU, bpage); buf_page_t *prev= UT_LIST_GET_PREV(LRU, bpage);
const lsn_t oldest_modification= bpage->oldest_modification(); const lsn_t oldest_modification= bpage->oldest_modification();
buf_pool.lru_hp.set(prev); buf_pool.lru_hp.set(prev);
@ -1242,7 +1241,6 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n)
mysql_mutex_lock(&buf_pool.mutex); mysql_mutex_lock(&buf_pool.mutex);
if (p.second) if (p.second)
buf_pool.stat.n_pages_written+= p.second; buf_pool.stat.n_pages_written+= p.second;
bpage= buf_pool.lru_hp.get();
goto retry; goto retry;
} }
else else
@ -1274,6 +1272,7 @@ reacquire_mutex:
must_skip: must_skip:
/* Can't evict or dispatch this block. Go to previous. */ /* Can't evict or dispatch this block. Go to previous. */
ut_ad(buf_pool.lru_hp.is_hp(prev)); ut_ad(buf_pool.lru_hp.is_hp(prev));
retry:
bpage= buf_pool.lru_hp.get(); bpage= buf_pool.lru_hp.get();
} }

View file

@ -38,6 +38,22 @@ Full Text Search interface
#include "dict0stats.h" #include "dict0stats.h"
#include "btr0pcur.h" #include "btr0pcur.h"
/** The SYNC state of the cache. There is one instance of this struct
associated with each ADD thread. */
struct fts_sync_t {
/** Transaction used for SYNCing the cache to disk */
trx_t *trx;
/** Table with FTS index(es) */
dict_table_t *table;
/** Max size in bytes of the cache */
ulint max_cache_size;
/** The doc id at which the cache was noted as being
full, we use this to set the upper_limit field */
doc_id_t max_doc_id;
/** SYNC start time; only used if fts_enable_diag_print */
time_t start_time;
};
static const ulint FTS_MAX_ID_LEN = 32; static const ulint FTS_MAX_ID_LEN = 32;
/** Column name from the FTS config table */ /** Column name from the FTS config table */
@ -185,15 +201,8 @@ struct fts_tokenize_param_t {
/** Run SYNC on the table, i.e., write out data from the cache to the /** Run SYNC on the table, i.e., write out data from the cache to the
FTS auxiliary INDEX table and clear the cache at the end. FTS auxiliary INDEX table and clear the cache at the end.
@param[in,out] sync sync state @param[in,out] sync sync state
@param[in] unlock_cache whether unlock cache lock when write node
@param[in] wait whether wait when a sync is in progress
@return DB_SUCCESS if all OK */ @return DB_SUCCESS if all OK */
static static dberr_t fts_sync(fts_sync_t *sync);
dberr_t
fts_sync(
fts_sync_t* sync,
bool unlock_cache,
bool wait);
/****************************************************************//** /****************************************************************//**
Release all resources help by the words rb tree e.g., the node ilist. */ Release all resources help by the words rb tree e.g., the node ilist. */
@ -266,7 +275,6 @@ fts_cache_destroy(fts_cache_t* cache)
mysql_mutex_destroy(&cache->init_lock); mysql_mutex_destroy(&cache->init_lock);
mysql_mutex_destroy(&cache->deleted_lock); mysql_mutex_destroy(&cache->deleted_lock);
mysql_mutex_destroy(&cache->doc_id_lock); mysql_mutex_destroy(&cache->doc_id_lock);
pthread_cond_destroy(&cache->sync->cond);
if (cache->stopword_info.cached_stopword) { if (cache->stopword_info.cached_stopword) {
rbt_free(cache->stopword_info.cached_stopword); rbt_free(cache->stopword_info.cached_stopword);
@ -540,7 +548,6 @@ fts_index_cache_init(
for (i = 0; i < FTS_NUM_AUX_INDEX; ++i) { for (i = 0; i < FTS_NUM_AUX_INDEX; ++i) {
ut_a(index_cache->ins_graph[i] == NULL); ut_a(index_cache->ins_graph[i] == NULL);
ut_a(index_cache->sel_graph[i] == NULL);
} }
} }
@ -610,7 +617,6 @@ fts_cache_create(
mem_heap_zalloc(heap, sizeof(fts_sync_t))); mem_heap_zalloc(heap, sizeof(fts_sync_t)));
cache->sync->table = table; cache->sync->table = table;
pthread_cond_init(&cache->sync->cond, nullptr);
/* Create the index cache vector that will hold the inverted indexes. */ /* Create the index cache vector that will hold the inverted indexes. */
cache->indexes = ib_vector_create( cache->indexes = ib_vector_create(
@ -935,10 +941,6 @@ fts_cache_index_cache_create(
mem_heap_zalloc(static_cast<mem_heap_t*>( mem_heap_zalloc(static_cast<mem_heap_t*>(
cache->self_heap->arg), n_bytes)); cache->self_heap->arg), n_bytes));
index_cache->sel_graph = static_cast<que_t**>(
mem_heap_zalloc(static_cast<mem_heap_t*>(
cache->self_heap->arg), n_bytes));
fts_index_cache_init(cache->sync_heap, index_cache); fts_index_cache_init(cache->sync_heap, index_cache);
if (cache->get_docs) { if (cache->get_docs) {
@ -1012,13 +1014,6 @@ fts_cache_clear(
index_cache->ins_graph[j] = NULL; index_cache->ins_graph[j] = NULL;
} }
if (index_cache->sel_graph[j] != NULL) {
que_graph_free(index_cache->sel_graph[j]);
index_cache->sel_graph[j] = NULL;
}
} }
index_cache->doc_stats = NULL; index_cache->doc_stats = NULL;
@ -1311,8 +1306,7 @@ fts_cache_add_doc(
ib_vector_last(word->nodes)); ib_vector_last(word->nodes));
} }
if (fts_node == NULL || fts_node->synced if (!fts_node || fts_node->ilist_size > FTS_ILIST_MAX_SIZE
|| fts_node->ilist_size > FTS_ILIST_MAX_SIZE
|| doc_id < fts_node->last_doc_id) { || doc_id < fts_node->last_doc_id) {
fts_node = static_cast<fts_node_t*>( fts_node = static_cast<fts_node_t*>(
@ -3284,7 +3278,7 @@ fts_add_doc_from_tuple(
if (cache->total_size > fts_max_cache_size / 5 if (cache->total_size > fts_max_cache_size / 5
|| fts_need_sync) { || fts_need_sync) {
fts_sync(cache->sync, true, false); fts_sync(cache->sync);
} }
mtr_start(&mtr); mtr_start(&mtr);
@ -3444,42 +3438,34 @@ fts_add_doc_by_id(
get_doc->index_cache, get_doc->index_cache,
doc_id, doc.tokens); doc_id, doc.tokens);
bool need_sync = !cache->sync->in_progress /** FTS cache sync should happen
&& (fts_need_sync frequently. Because user thread
|| (cache->total_size shouldn't hold the cache lock for
- cache->total_size_at_sync) longer time. So cache should sync
> fts_max_cache_size / 10); whenever cache size exceeds 512 KB */
if (need_sync) { bool need_sync =
cache->total_size_at_sync = cache->total_size > 512*1024;
cache->total_size;
}
mysql_mutex_unlock(&table->fts->cache->lock); mysql_mutex_unlock(&table->fts->cache->lock);
DBUG_EXECUTE_IF( DBUG_EXECUTE_IF(
"fts_instrument_sync", "fts_instrument_sync",
fts_optimize_request_sync_table(table); fts_sync_table(table);
mysql_mutex_lock(&cache->lock);
if (cache->sync->in_progress)
my_cond_wait(
&cache->sync->cond,
&cache->lock.m_mutex);
mysql_mutex_unlock(&cache->lock);
); );
DBUG_EXECUTE_IF( DBUG_EXECUTE_IF(
"fts_instrument_sync_debug", "fts_instrument_sync_debug",
fts_sync(cache->sync, true, true); fts_sync(cache->sync);
); );
DEBUG_SYNC_C("fts_instrument_sync_request"); DEBUG_SYNC_C("fts_instrument_sync_request");
DBUG_EXECUTE_IF( DBUG_EXECUTE_IF(
"fts_instrument_sync_request", "fts_instrument_sync_request",
fts_optimize_request_sync_table(table); need_sync= true;
); );
if (need_sync) { if (need_sync) {
fts_optimize_request_sync_table(table); fts_sync_table(table);
} }
mtr_start(&mtr); mtr_start(&mtr);
@ -3846,15 +3832,13 @@ static MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t dberr_t
fts_sync_write_words( fts_sync_write_words(
trx_t* trx, trx_t* trx,
fts_index_cache_t* index_cache, fts_index_cache_t* index_cache)
bool unlock_cache)
{ {
fts_table_t fts_table; fts_table_t fts_table;
ulint n_nodes = 0; ulint n_nodes = 0;
ulint n_words = 0; ulint n_words = 0;
const ib_rbt_node_t* rbt_node; const ib_rbt_node_t* rbt_node;
dberr_t error = DB_SUCCESS; dberr_t error = DB_SUCCESS;
ibool print_error = FALSE;
dict_table_t* table = index_cache->index->table; dict_table_t* table = index_cache->index->table;
FTS_INIT_INDEX_TABLE( FTS_INIT_INDEX_TABLE(
@ -3885,53 +3869,35 @@ fts_sync_write_words(
fts_table.suffix = fts_get_suffix(selected); fts_table.suffix = fts_get_suffix(selected);
/* We iterate over all the nodes even if there was an error */
for (i = 0; i < ib_vector_size(word->nodes); ++i) { for (i = 0; i < ib_vector_size(word->nodes); ++i) {
fts_node_t* fts_node = static_cast<fts_node_t*>( fts_node_t* fts_node = static_cast<fts_node_t*>(
ib_vector_get(word->nodes, i)); ib_vector_get(word->nodes, i));
if (fts_node->synced) { error = fts_write_node(
continue; trx, &index_cache->ins_graph[selected],
} else { &fts_table, &word->text, fts_node);
fts_node->synced = true;
}
/*FIXME: we need to handle the error properly. */ DEBUG_SYNC_C("fts_write_node");
if (error == DB_SUCCESS) { DBUG_EXECUTE_IF("fts_write_node_crash",
if (unlock_cache) {
mysql_mutex_unlock(
&table->fts->cache->lock);
}
error = fts_write_node(
trx,
&index_cache->ins_graph[selected],
&fts_table, &word->text, fts_node);
DEBUG_SYNC_C("fts_write_node");
DBUG_EXECUTE_IF("fts_write_node_crash",
DBUG_SUICIDE();); DBUG_SUICIDE(););
DBUG_EXECUTE_IF( DBUG_EXECUTE_IF("fts_instrument_sync_sleep",
"fts_instrument_sync_sleep",
std::this_thread::sleep_for( std::this_thread::sleep_for(
std::chrono::seconds(1));); std::chrono::seconds(1)););
if (unlock_cache) { if (error != DB_SUCCESS) {
mysql_mutex_lock( goto err_exit;
&table->fts->cache->lock);
}
} }
} }
n_nodes += ib_vector_size(word->nodes); n_nodes += ib_vector_size(word->nodes);
if (UNIV_UNLIKELY(error != DB_SUCCESS) && !print_error) { if (UNIV_UNLIKELY(error != DB_SUCCESS)) {
err_exit:
ib::error() << "(" << error << ") writing" ib::error() << "(" << error << ") writing"
" word node to FTS auxiliary index table " " word node to FTS auxiliary index table "
<< table->name; << table->name;
print_error = TRUE;
} }
} }
@ -3990,58 +3956,7 @@ fts_sync_index(
ut_ad(rbt_validate(index_cache->words)); ut_ad(rbt_validate(index_cache->words));
return(fts_sync_write_words(trx, index_cache, sync->unlock_cache)); return(fts_sync_write_words(trx, index_cache));
}
/** Check if index cache has been synced completely
@param[in,out] index_cache index cache
@return true if index is synced, otherwise false. */
static
bool
fts_sync_index_check(
fts_index_cache_t* index_cache)
{
const ib_rbt_node_t* rbt_node;
for (rbt_node = rbt_first(index_cache->words);
rbt_node != NULL;
rbt_node = rbt_next(index_cache->words, rbt_node)) {
fts_tokenizer_word_t* word;
word = rbt_value(fts_tokenizer_word_t, rbt_node);
fts_node_t* fts_node;
fts_node = static_cast<fts_node_t*>(ib_vector_last(word->nodes));
if (!fts_node->synced) {
return(false);
}
}
return(true);
}
/** Reset synced flag in index cache when rollback
@param[in,out] index_cache index cache */
static
void
fts_sync_index_reset(
fts_index_cache_t* index_cache)
{
const ib_rbt_node_t* rbt_node;
for (rbt_node = rbt_first(index_cache->words);
rbt_node != NULL;
rbt_node = rbt_next(index_cache->words, rbt_node)) {
fts_tokenizer_word_t* word;
word = rbt_value(fts_tokenizer_word_t, rbt_node);
fts_node_t* fts_node;
fts_node = static_cast<fts_node_t*>(ib_vector_last(word->nodes));
fts_node->synced = false;
}
} }
/** Commit the SYNC, change state of processed doc ids etc. /** Commit the SYNC, change state of processed doc ids etc.
@ -4074,14 +3989,14 @@ fts_sync_commit(
sync, cache->deleted_doc_ids); sync, cache->deleted_doc_ids);
} }
/* We need to do this within the deleted lock since fts_delete() can
attempt to add a deleted doc id to the cache deleted id array. */
fts_cache_clear(cache);
DEBUG_SYNC_C("fts_deleted_doc_ids_clear");
fts_cache_init(cache);
mysql_mutex_unlock(&cache->lock);
if (UNIV_LIKELY(error == DB_SUCCESS)) { if (UNIV_LIKELY(error == DB_SUCCESS)) {
/* We need to do this within the deleted lock
since fts_delete() can attempt to add a deleted
doc id to the cache deleted id array. */
fts_cache_clear(cache);
DEBUG_SYNC_C("fts_deleted_doc_ids_clear");
fts_cache_init(cache);
mysql_mutex_unlock(&cache->lock);
fts_sql_commit(trx); fts_sql_commit(trx);
} else { } else {
fts_sql_rollback(trx); fts_sql_rollback(trx);
@ -4123,10 +4038,6 @@ fts_sync_rollback(
index_cache = static_cast<fts_index_cache_t*>( index_cache = static_cast<fts_index_cache_t*>(
ib_vector_get(cache->indexes, i)); ib_vector_get(cache->indexes, i));
/* Reset synced flag so nodes will not be skipped
in the next sync, see fts_sync_write_words(). */
fts_sync_index_reset(index_cache);
for (j = 0; fts_index_selector[j].value; ++j) { for (j = 0; fts_index_selector[j].value; ++j) {
if (index_cache->ins_graph[j] != NULL) { if (index_cache->ins_graph[j] != NULL) {
@ -4135,13 +4046,6 @@ fts_sync_rollback(
index_cache->ins_graph[j] = NULL; index_cache->ins_graph[j] = NULL;
} }
if (index_cache->sel_graph[j] != NULL) {
que_graph_free(index_cache->sel_graph[j]);
index_cache->sel_graph[j] = NULL;
}
} }
} }
@ -4160,12 +4064,7 @@ FTS auxiliary INDEX table and clear the cache at the end.
@param[in] unlock_cache whether unlock cache lock when write node @param[in] unlock_cache whether unlock cache lock when write node
@param[in] wait whether wait when a sync is in progress @param[in] wait whether wait when a sync is in progress
@return DB_SUCCESS if all OK */ @return DB_SUCCESS if all OK */
static static dberr_t fts_sync(fts_sync_t *sync)
dberr_t
fts_sync(
fts_sync_t* sync,
bool unlock_cache,
bool wait)
{ {
if (srv_read_only_mode) { if (srv_read_only_mode) {
return DB_READ_ONLY; return DB_READ_ONLY;
@ -4176,33 +4075,13 @@ fts_sync(
fts_cache_t* cache = sync->table->fts->cache; fts_cache_t* cache = sync->table->fts->cache;
mysql_mutex_lock(&cache->lock); mysql_mutex_lock(&cache->lock);
/* Check if cache is being synced.
Note: we release cache lock in fts_sync_write_words() to
avoid long wait for the lock by other threads. */
if (sync->in_progress) {
if (!wait) {
mysql_mutex_unlock(&cache->lock);
return(DB_SUCCESS);
}
do {
my_cond_wait(&sync->cond, &cache->lock.m_mutex);
} while (sync->in_progress);
}
sync->unlock_cache = unlock_cache;
sync->in_progress = true;
DEBUG_SYNC_C("fts_sync_begin"); DEBUG_SYNC_C("fts_sync_begin");
fts_sync_begin(sync); fts_sync_begin(sync);
begin_sync:
const size_t fts_cache_size= fts_max_cache_size; const size_t fts_cache_size= fts_max_cache_size;
if (cache->total_size > fts_cache_size) { if (cache->total_size > fts_cache_size) {
/* Avoid the case: sync never finish when /* Avoid the case: sync never finish when
insert/update keeps comming. */ insert/update keeps comming. */
ut_ad(sync->unlock_cache);
sync->unlock_cache = false;
ib::warn() << "Total InnoDB FTS size " ib::warn() << "Total InnoDB FTS size "
<< cache->total_size << " for the table " << cache->total_size << " for the table "
<< cache->sync->table->name << cache->sync->table->name
@ -4226,52 +4105,23 @@ begin_sync:
error = fts_sync_index(sync, index_cache); error = fts_sync_index(sync, index_cache);
if (error != DB_SUCCESS) { if (error != DB_SUCCESS) {
goto end_sync; goto err_exit;
}
if (!sync->unlock_cache
&& cache->total_size < fts_max_cache_size) {
/* Reset the unlock cache if the value
is less than innodb_ft_cache_size */
sync->unlock_cache = true;
} }
} }
DBUG_EXECUTE_IF("fts_instrument_sync_interrupted", DBUG_EXECUTE_IF("fts_instrument_sync_interrupted",
sync->interrupted = true;
error = DB_INTERRUPTED; error = DB_INTERRUPTED;
goto end_sync; goto err_exit;
); );
/* Make sure all the caches are synced. */ if (error == DB_SUCCESS) {
for (i = 0; i < ib_vector_size(cache->indexes); ++i) {
fts_index_cache_t* index_cache;
index_cache = static_cast<fts_index_cache_t*>(
ib_vector_get(cache->indexes, i));
if (index_cache->index->to_be_dropped
|| fts_sync_index_check(index_cache)) {
continue;
}
goto begin_sync;
}
end_sync:
if (error == DB_SUCCESS && !sync->interrupted) {
error = fts_sync_commit(sync); error = fts_sync_commit(sync);
} else { } else {
err_exit:
fts_sync_rollback(sync); fts_sync_rollback(sync);
return error;
} }
mysql_mutex_lock(&cache->lock);
ut_ad(sync->in_progress);
sync->interrupted = false;
sync->in_progress = false;
pthread_cond_broadcast(&sync->cond);
mysql_mutex_unlock(&cache->lock);
/* We need to check whether an optimize is required, for that /* We need to check whether an optimize is required, for that
we make copies of the two variables that control the trigger. These we make copies of the two variables that control the trigger. These
variables can change behind our back and we don't want to hold the variables can change behind our back and we don't want to hold the
@ -4283,6 +4133,7 @@ end_sync:
mysql_mutex_unlock(&cache->deleted_lock); mysql_mutex_unlock(&cache->deleted_lock);
DEBUG_SYNC_C("fts_sync_end");
return(error); return(error);
} }
@ -4291,12 +4142,12 @@ FTS auxiliary INDEX table and clear the cache at the end.
@param[in,out] table fts table @param[in,out] table fts table
@param[in] wait whether wait for existing sync to finish @param[in] wait whether wait for existing sync to finish
@return DB_SUCCESS on success, error code on failure. */ @return DB_SUCCESS on success, error code on failure. */
dberr_t fts_sync_table(dict_table_t* table, bool wait) dberr_t fts_sync_table(dict_table_t* table)
{ {
ut_ad(table->fts); ut_ad(table->fts);
return table->space && !table->corrupted && table->fts->cache return table->space && !table->corrupted && table->fts->cache
? fts_sync(table->fts->cache->sync, !wait, wait) ? fts_sync(table->fts->cache->sync)
: DB_SUCCESS; : DB_SUCCESS;
} }

View file

@ -83,9 +83,8 @@ enum fts_msg_type_t {
FTS_MSG_ADD_TABLE, /*!< Add table to the optimize thread's FTS_MSG_ADD_TABLE, /*!< Add table to the optimize thread's
work queue */ work queue */
FTS_MSG_DEL_TABLE, /*!< Remove a table from the optimize FTS_MSG_DEL_TABLE /*!< Remove a table from the optimize
threads work queue */ threads work queue */
FTS_MSG_SYNC_TABLE /*!< Sync fts cache of a table */
}; };
/** Compressed list of words that have been read from FTS INDEX /** Compressed list of words that have been read from FTS INDEX
@ -2625,36 +2624,6 @@ fts_optimize_remove_table(
mysql_mutex_unlock(&fts_optimize_wq->mutex); mysql_mutex_unlock(&fts_optimize_wq->mutex);
} }
/** Send sync fts cache for the table.
@param[in] table table to sync */
void
fts_optimize_request_sync_table(
dict_table_t* table)
{
/* if the optimize system not yet initialized, return */
if (!fts_optimize_wq) {
return;
}
mysql_mutex_lock(&fts_optimize_wq->mutex);
/* FTS optimizer thread is already exited */
if (fts_opt_start_shutdown) {
ib::info() << "Try to sync table " << table->name
<< " after FTS optimize thread exiting.";
} else if (table->fts->sync_message) {
/* If the table already has SYNC message in
fts_optimize_wq queue then ignore it */
} else {
add_msg(fts_optimize_create_msg(FTS_MSG_SYNC_TABLE, table));
table->fts->sync_message = true;
DBUG_EXECUTE_IF("fts_optimize_wq_count_check",
DBUG_ASSERT(fts_optimize_wq->length <= 1000););
}
mysql_mutex_unlock(&fts_optimize_wq->mutex);
}
/** Add a table to fts_slots if it doesn't already exist. */ /** Add a table to fts_slots if it doesn't already exist. */
static bool fts_optimize_new_table(dict_table_t* table) static bool fts_optimize_new_table(dict_table_t* table)
{ {
@ -2796,7 +2765,8 @@ static void fts_optimize_sync_table(dict_table_t *table,
if (sync_table->fts && sync_table->fts->cache && sync_table->is_accessible()) if (sync_table->fts && sync_table->fts->cache && sync_table->is_accessible())
{ {
fts_sync_table(sync_table, false); fts_sync_table(sync_table);
if (process_message) if (process_message)
{ {
mysql_mutex_lock(&fts_optimize_wq->mutex); mysql_mutex_lock(&fts_optimize_wq->mutex);
@ -2896,24 +2866,6 @@ retry_later:
--n_tables; --n_tables;
} }
break; break;
case FTS_MSG_SYNC_TABLE:
if (UNIV_UNLIKELY(wsrep_sst_disable_writes)) {
add_msg(msg);
goto retry_later;
}
DBUG_EXECUTE_IF(
"fts_instrument_msg_sync_sleep",
std::this_thread::sleep_for(
std::chrono::milliseconds(
300)););
fts_optimize_sync_table(
static_cast<dict_table_t*>(msg->ptr),
true);
break;
default: default:
ut_error; ut_error;
} }
@ -3046,7 +2998,7 @@ void fts_sync_during_ddl(dict_table_t* table)
if (!sync_message) if (!sync_message)
return; return;
fts_sync_table(table, false); fts_sync_table(table);
mysql_mutex_lock(&fts_optimize_wq->mutex); mysql_mutex_lock(&fts_optimize_wq->mutex);
table->fts->sync_message = false; table->fts->sync_message = false;

View file

@ -1470,7 +1470,8 @@ static void innodb_drop_database(handlerton*, char *path)
"WHILE 1 = 1 LOOP\n" "WHILE 1 = 1 LOOP\n"
" FETCH tab INTO tid,name;\n" " FETCH tab INTO tid,name;\n"
" IF (SQL % NOTFOUND) THEN EXIT; END IF;\n" " IF (SQL % NOTFOUND) THEN EXIT; END IF;\n"
" IF SUBSTR(name, 0, LENGTH(:db)) <> :db THEN EXIT; END IF;\n" " IF TO_BINARY(SUBSTR(name, 0, LENGTH(:db))) <> TO_BINARY(:db)"
" THEN EXIT; END IF;\n"
" DELETE FROM SYS_COLUMNS WHERE TABLE_ID=tid;\n" " DELETE FROM SYS_COLUMNS WHERE TABLE_ID=tid;\n"
" DELETE FROM SYS_TABLES WHERE ID=tid;\n" " DELETE FROM SYS_TABLES WHERE ID=tid;\n"
" OPEN idx;\n" " OPEN idx;\n"
@ -4065,6 +4066,14 @@ static int innodb_init_params()
} }
#endif #endif
#if defined __linux__ || defined _WIN32
if (srv_flush_log_at_trx_commit == 2) {
/* Do not disable the file system cache if
innodb_flush_log_at_trx_commit=2. */
log_sys.log_buffered = true;
}
#endif
if (srv_read_only_mode) { if (srv_read_only_mode) {
ib::info() << "Started in read only mode"; ib::info() << "Started in read only mode";
srv_use_doublewrite_buf = FALSE; srv_use_doublewrite_buf = FALSE;
@ -18441,6 +18450,16 @@ buffer_pool_load_abort(
} }
} }
#if defined __linux__ || defined _WIN32
static void innodb_log_file_buffering_update(THD *thd, st_mysql_sys_var*,
void *, const void *save)
{
mysql_mutex_unlock(&LOCK_global_system_variables);
log_sys.set_buffered(*static_cast<const my_bool*>(save));
mysql_mutex_lock(&LOCK_global_system_variables);
}
#endif
static void innodb_log_file_size_update(THD *thd, st_mysql_sys_var*, static void innodb_log_file_size_update(THD *thd, st_mysql_sys_var*,
void *var, const void *save) void *var, const void *save)
{ {
@ -18908,7 +18927,7 @@ static MYSQL_SYSVAR_ENUM(flush_method, srv_file_flush_method,
static MYSQL_SYSVAR_STR(log_group_home_dir, srv_log_group_home_dir, static MYSQL_SYSVAR_STR(log_group_home_dir, srv_log_group_home_dir,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Path to InnoDB log files.", NULL, NULL, NULL); "Path to ib_logfile0", NULL, NULL, NULL);
static MYSQL_SYSVAR_DOUBLE(max_dirty_pages_pct, srv_max_buf_pool_modified_pct, static MYSQL_SYSVAR_DOUBLE(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
PLUGIN_VAR_RQCMDARG, PLUGIN_VAR_RQCMDARG,
@ -19300,6 +19319,13 @@ static MYSQL_SYSVAR_SIZE_T(log_buffer_size, log_sys.buf_size,
"Redo log buffer size in bytes.", "Redo log buffer size in bytes.",
NULL, NULL, 16U << 20, 2U << 20, SIZE_T_MAX, 4096); NULL, NULL, 16U << 20, 2U << 20, SIZE_T_MAX, 4096);
#if defined __linux__ || defined _WIN32
static MYSQL_SYSVAR_BOOL(log_file_buffering, log_sys.log_buffered,
PLUGIN_VAR_OPCMDARG,
"Whether the file system cache for ib_logfile0 is enabled",
nullptr, innodb_log_file_buffering_update, FALSE);
#endif
static MYSQL_SYSVAR_ULONGLONG(log_file_size, srv_log_file_size, static MYSQL_SYSVAR_ULONGLONG(log_file_size, srv_log_file_size,
PLUGIN_VAR_RQCMDARG, PLUGIN_VAR_RQCMDARG,
"Redo log size in bytes.", "Redo log size in bytes.",
@ -19743,6 +19769,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(deadlock_report), MYSQL_SYSVAR(deadlock_report),
MYSQL_SYSVAR(page_size), MYSQL_SYSVAR(page_size),
MYSQL_SYSVAR(log_buffer_size), MYSQL_SYSVAR(log_buffer_size),
#if defined __linux__ || defined _WIN32
MYSQL_SYSVAR(log_file_buffering),
#endif
MYSQL_SYSVAR(log_file_size), MYSQL_SYSVAR(log_file_size),
MYSQL_SYSVAR(log_group_home_dir), MYSQL_SYSVAR(log_group_home_dir),
MYSQL_SYSVAR(max_dirty_pages_pct), MYSQL_SYSVAR(max_dirty_pages_pct),

View file

@ -11434,12 +11434,8 @@ foreign_fail:
ut_d(dict_table_check_for_dup_indexes( ut_d(dict_table_check_for_dup_indexes(
ctx->new_table, CHECK_ABORTED_OK)); ctx->new_table, CHECK_ABORTED_OK));
#ifdef UNIV_DEBUG ut_ad(!ctx->new_table->fts
if (!(ctx->new_table->fts != NULL || fts_check_cached_index(ctx->new_table));
&& ctx->new_table->fts->cache->sync->in_progress)) {
ut_a(fts_check_cached_index(ctx->new_table));
}
#endif
} }
unlock_and_close_files(deleted, trx); unlock_and_close_files(deleted, trx);

View file

@ -656,12 +656,6 @@ fts_optimize_remove_table(
void void
fts_optimize_shutdown(); fts_optimize_shutdown();
/** Send sync fts cache for the table.
@param[in] table table to sync */
void
fts_optimize_request_sync_table(
dict_table_t* table);
/**********************************************************************//** /**********************************************************************//**
Take a FTS savepoint. */ Take a FTS savepoint. */
void void
@ -716,9 +710,8 @@ fts_savepoint_rollback_last_stmt(
/** Run SYNC on the table, i.e., write out data from the cache to the /** Run SYNC on the table, i.e., write out data from the cache to the
FTS auxiliary INDEX table and clear the cache at the end. FTS auxiliary INDEX table and clear the cache at the end.
@param[in,out] table fts table @param[in,out] table fts table
@param[in] wait whether to wait for existing sync to finish
@return DB_SUCCESS on success, error code on failure. */ @return DB_SUCCESS on success, error code on failure. */
dberr_t fts_sync_table(dict_table_t* table, bool wait = true); dberr_t fts_sync_table(dict_table_t* table);
/****************************************************************//** /****************************************************************//**
Create an FTS index cache. */ Create an FTS index cache. */

View file

@ -75,7 +75,6 @@ struct fts_index_cache_t {
que_t** ins_graph; /*!< Insert query graphs */ que_t** ins_graph; /*!< Insert query graphs */
que_t** sel_graph; /*!< Select query graphs */
CHARSET_INFO* charset; /*!< charset */ CHARSET_INFO* charset; /*!< charset */
}; };
@ -87,35 +86,7 @@ struct fts_stopword_t {
CHARSET_INFO* charset; /*!< charset for stopword */ CHARSET_INFO* charset; /*!< charset for stopword */
}; };
/** The SYNC state of the cache. There is one instance of this struct struct fts_sync_t;
associated with each ADD thread. */
struct fts_sync_t {
trx_t* trx; /*!< The transaction used for SYNCing
the cache to disk */
dict_table_t* table; /*!< Table with FTS index(es) */
ulint max_cache_size; /*!< Max size in bytes of the cache */
ibool cache_full; /*!< flag, when true it indicates that
we need to sync the cache to disk */
ulint lower_index; /*!< the start index of the doc id
vector from where to start adding
documents to the FTS cache */
ulint upper_index; /*!< max index of the doc id vector to
add to the FTS cache */
ibool interrupted; /*!< TRUE if SYNC was interrupted */
doc_id_t min_doc_id; /*!< The smallest doc id added to the
cache. It should equal to
doc_ids[lower_index] */
doc_id_t max_doc_id; /*!< The doc id at which the cache was
noted as being full, we use this to
set the upper_limit field */
time_t start_time; /*!< SYNC start time; only used if
fts_enable_diag_print */
bool in_progress; /*!< flag whether sync is in progress.*/
bool unlock_cache; /*!< flag whether unlock cache when
write fts node */
/** condition variable for in_progress; used with table->fts->cache->lock */
pthread_cond_t cond;
};
/** The cache for the FTS system. It is a memory-based inverted index /** The cache for the FTS system. It is a memory-based inverted index
that new entries are added to, until it grows over the configured maximum that new entries are added to, until it grows over the configured maximum
@ -204,7 +175,6 @@ struct fts_node_t {
ulint ilist_size_alloc; ulint ilist_size_alloc;
/*!< Allocated size of ilist in /*!< Allocated size of ilist in
bytes */ bytes */
bool synced; /*!< flag whether the node is synced */
}; };
/** A tokenizer word. Contains information about one word. */ /** A tokenizer word. Contains information about one word. */

View file

@ -260,6 +260,16 @@ public:
uint32_t format; uint32_t format;
/** Log file */ /** Log file */
log_file_t log; log_file_t log;
#if defined __linux__ || defined _WIN32
/** whether file system caching is enabled for the log */
my_bool log_buffered;
# ifdef _WIN32
static constexpr bool log_maybe_unbuffered= true;
# else
/** whether file system caching may be disabled */
bool log_maybe_unbuffered;
# endif
#endif
/** Fields involved in checkpoints @{ */ /** Fields involved in checkpoints @{ */
lsn_t log_capacity; /*!< capacity of the log; if lsn_t log_capacity; /*!< capacity of the log; if
@ -343,6 +353,11 @@ public:
{ return resize_buf + resize_target; } { return resize_buf + resize_target; }
#endif #endif
#if defined __linux__ || defined _WIN32
/** Try to enable or disable file system caching (update log_buffered) */
void set_buffered(bool buffered);
#endif
void attach(log_file_t file, os_offset_t size); void attach(log_file_t file, os_offset_t size);
void close_file(); void close_file();

View file

@ -291,9 +291,9 @@ struct mtr_t {
@param[in] type object type: MTR_MEMO_PAGE_X_FIX, ... */ @param[in] type object type: MTR_MEMO_PAGE_X_FIX, ... */
void release_page(const void *ptr, mtr_memo_type_t type); void release_page(const void *ptr, mtr_memo_type_t type);
private:
/** Note that the mini-transaction will modify data. */ /** Note that the mini-transaction will modify data. */
void flag_modified() { m_modifications = true; } void flag_modified() { m_modifications = true; }
private:
/** Mark the given latched page as modified. /** Mark the given latched page as modified.
@param block page that will be modified */ @param block page that will be modified */
void modify(const buf_block_t& block); void modify(const buf_block_t& block);

View file

@ -46,7 +46,7 @@ mtr_t::memo_push(void* object, mtr_memo_type_t type)
ut_ad(object != NULL); ut_ad(object != NULL);
ut_ad(type >= MTR_MEMO_PAGE_S_FIX); ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
ut_ad(type <= MTR_MEMO_SPACE_S_LOCK); ut_ad(type <= MTR_MEMO_SPACE_S_LOCK);
ut_ad(ut_is_2pow(type)); ut_ad(type == MTR_MEMO_PAGE_X_MODIFY || ut_is_2pow(type));
/* If this mtr has x-fixed a clean page then we set /* If this mtr has x-fixed a clean page then we set
the made_dirty flag. This tells mtr_t::commit() the made_dirty flag. This tells mtr_t::commit()

View file

@ -220,6 +220,8 @@ void log_t::attach(log_file_t file, os_offset_t size)
#if defined __linux__ || defined _WIN32 #if defined __linux__ || defined _WIN32
set_block_size(CPU_LEVEL1_DCACHE_LINESIZE); set_block_size(CPU_LEVEL1_DCACHE_LINESIZE);
#endif #endif
log_maybe_unbuffered= true;
log_buffered= false;
return; return;
} }
} }
@ -231,18 +233,11 @@ void log_t::attach(log_file_t file, os_offset_t size)
#endif #endif
#if defined __linux__ || defined _WIN32 #if defined __linux__ || defined _WIN32
if (!block_size) sql_print_information("InnoDB: %s (block size=%u bytes)",
set_block_size(512); log_buffered
# ifdef __linux__ ? "Buffered log writes"
else if (srv_file_flush_method != SRV_O_DSYNC && : "File system buffers for log disabled",
srv_file_flush_method != SRV_O_DIRECT && block_size);
srv_file_flush_method != SRV_O_DIRECT_NO_FSYNC)
sql_print_information("InnoDB: Buffered log writes (block size=%u bytes)",
block_size);
#endif
else
sql_print_information("InnoDB: File system buffers for log"
" disabled (block size=%u bytes)", block_size);
#endif #endif
#ifdef HAVE_PMEM #ifdef HAVE_PMEM
@ -347,7 +342,7 @@ void log_t::close_file()
ib::fatal() << "closing ib_logfile0 failed: " << err; ib::fatal() << "closing ib_logfile0 failed: " << err;
} }
/** Acquire the latches that protect log resizing. */ /** Acquire all latches that protect the log. */
static void log_resize_acquire() static void log_resize_acquire()
{ {
if (!log_sys.is_pmem()) if (!log_sys.is_pmem())
@ -361,7 +356,7 @@ static void log_resize_acquire()
log_sys.latch.wr_lock(SRW_LOCK_CALL); log_sys.latch.wr_lock(SRW_LOCK_CALL);
} }
/** Release the latches that protect log resizing. */ /** Release the latches that protect the log. */
void log_resize_release() void log_resize_release()
{ {
log_sys.latch.wr_unlock(); log_sys.latch.wr_unlock();
@ -375,6 +370,34 @@ void log_resize_release()
} }
} }
#if defined __linux__ || defined _WIN32
/** Try to enable or disable file system caching (update log_buffered) */
void log_t::set_buffered(bool buffered)
{
if (!log_maybe_unbuffered || is_pmem() || high_level_read_only)
return;
log_resize_acquire();
if (!resize_in_progress() && is_opened() && bool(log_buffered) != buffered)
{
os_file_close_func(log.m_file);
log.m_file= OS_FILE_CLOSED;
std::string path{get_log_file_path()};
log_buffered= buffered;
bool success;
log.m_file= os_file_create_func(path.c_str(),
OS_FILE_OPEN, OS_FILE_NORMAL, OS_LOG_FILE,
false, &success);
ut_a(log.m_file != OS_FILE_CLOSED);
sql_print_information("InnoDB: %s (block size=%u bytes)",
log_buffered
? "Buffered log writes"
: "File system buffers for log disabled",
block_size);
}
log_resize_release();
}
#endif
/** Start resizing the log and release the exclusive latch. /** Start resizing the log and release the exclusive latch.
@param size requested new file_size @param size requested new file_size
@return whether the resizing was started successfully */ @return whether the resizing was started successfully */

View file

@ -1055,6 +1055,7 @@ os_file_create_simple_func(
we open the same file in the same mode, see man page of open(2). */ we open the same file in the same mode, see man page of open(2). */
if (!srv_read_only_mode && *success) { if (!srv_read_only_mode && *success) {
switch (srv_file_flush_method) { switch (srv_file_flush_method) {
case SRV_O_DSYNC:
case SRV_O_DIRECT: case SRV_O_DIRECT:
case SRV_O_DIRECT_NO_FSYNC: case SRV_O_DIRECT_NO_FSYNC:
os_file_set_nocache(file, name, mode_str); os_file_set_nocache(file, name, mode_str);
@ -1240,13 +1241,13 @@ os_file_create_func(
#if (defined(UNIV_SOLARIS) && defined(DIRECTIO_ON)) || defined O_DIRECT #if (defined(UNIV_SOLARIS) && defined(DIRECTIO_ON)) || defined O_DIRECT
if (type == OS_DATA_FILE) { if (type == OS_DATA_FILE) {
# ifdef __linux__
use_o_direct:
# endif
switch (srv_file_flush_method) { switch (srv_file_flush_method) {
case SRV_O_DSYNC: case SRV_O_DSYNC:
case SRV_O_DIRECT: case SRV_O_DIRECT:
case SRV_O_DIRECT_NO_FSYNC: case SRV_O_DIRECT_NO_FSYNC:
# ifdef __linux__
use_o_direct:
# endif
os_file_set_nocache(file, name, mode_str); os_file_set_nocache(file, name, mode_str);
break; break;
default: default:
@ -1263,9 +1264,6 @@ use_o_direct:
goto skip_o_direct; goto skip_o_direct;
} }
MSAN_STAT_WORKAROUND(&st); MSAN_STAT_WORKAROUND(&st);
if (st.st_size & 4095) {
goto skip_o_direct;
}
if (snprintf(b, sizeof b, if (snprintf(b, sizeof b,
"/sys/dev/block/%u:%u/queue/physical_block_size", "/sys/dev/block/%u:%u/queue/physical_block_size",
major(st.st_dev), minor(st.st_dev)) major(st.st_dev), minor(st.st_dev))
@ -1298,11 +1296,16 @@ use_o_direct:
if (s > 4096 || s < 64 || !ut_is_2pow(s)) { if (s > 4096 || s < 64 || !ut_is_2pow(s)) {
goto skip_o_direct; goto skip_o_direct;
} }
log_sys.log_maybe_unbuffered= true;
log_sys.set_block_size(uint32_t(s)); log_sys.set_block_size(uint32_t(s));
goto use_o_direct; if (!log_sys.log_buffered && !(st.st_size & (s - 1))) {
goto use_o_direct;
}
} else { } else {
skip_o_direct: skip_o_direct:
log_sys.set_block_size(0); log_sys.log_maybe_unbuffered= false;
log_sys.log_buffered= true;
log_sys.set_block_size(512);
} }
} }
# endif # endif
@ -2057,7 +2060,7 @@ os_file_create_directory(
} }
/** Get disk sector size for a file. */ /** Get disk sector size for a file. */
size_t get_sector_size(HANDLE file) static size_t get_sector_size(HANDLE file)
{ {
FILE_STORAGE_INFO fsi; FILE_STORAGE_INFO fsi;
ULONG s= 4096; ULONG s= 4096;
@ -2065,9 +2068,7 @@ size_t get_sector_size(HANDLE file)
{ {
s= fsi.PhysicalBytesPerSectorForPerformance; s= fsi.PhysicalBytesPerSectorForPerformance;
if (s > 4096 || s < 64 || !ut_is_2pow(s)) if (s > 4096 || s < 64 || !ut_is_2pow(s))
{
return 4096; return 4096;
}
} }
return s; return s;
} }
@ -2165,8 +2166,9 @@ os_file_create_func(
? FILE_FLAG_OVERLAPPED : 0; ? FILE_FLAG_OVERLAPPED : 0;
if (type == OS_LOG_FILE) { if (type == OS_LOG_FILE) {
if(srv_flush_log_at_trx_commit != 2 && !log_sys.is_opened()) if (!log_sys.is_opened() && !log_sys.log_buffered) {
attributes|= FILE_FLAG_NO_BUFFERING; attributes|= FILE_FLAG_NO_BUFFERING;
}
if (srv_file_flush_method == SRV_O_DSYNC) if (srv_file_flush_method == SRV_O_DSYNC)
attributes|= FILE_FLAG_WRITE_THROUGH; attributes|= FILE_FLAG_WRITE_THROUGH;
} }
@ -2197,21 +2199,22 @@ os_file_create_func(
name, access, share_mode, my_win_file_secattr(), name, access, share_mode, my_win_file_secattr(),
create_flag, attributes, NULL); create_flag, attributes, NULL);
if (file != INVALID_HANDLE_VALUE && type == OS_LOG_FILE *success = file != INVALID_HANDLE_VALUE;
&& (attributes & FILE_FLAG_NO_BUFFERING)) {
uint32 s= (uint32_t) get_sector_size(file); if (*success && type == OS_LOG_FILE) {
log_sys.set_block_size(uint32_t(s)); uint32_t s = uint32_t(get_sector_size(file));
/* FIXME! remove it when backup is fixed, so that it log_sys.set_block_size(s);
does not produce redo with irregular sizes.*/ if (attributes & FILE_FLAG_NO_BUFFERING) {
if (os_file_get_size(file) % s) { if (os_file_get_size(file) % s) {
attributes &= ~FILE_FLAG_NO_BUFFERING; attributes &= ~FILE_FLAG_NO_BUFFERING;
create_flag = OPEN_ALWAYS; create_flag = OPEN_ALWAYS;
CloseHandle(file); CloseHandle(file);
continue; continue;
}
log_sys.log_buffered = false;
} }
} }
*success = (file != INVALID_HANDLE_VALUE);
if (*success) { if (*success) {
break; break;
} }

View file

@ -402,8 +402,9 @@ static dberr_t trx_purge_free_segment(trx_rseg_t *rseg, fil_addr_t hdr_addr)
block->fix(); block->fix();
mtr.commit(); mtr.commit();
mtr.start(); mtr.start();
mtr.flag_modified();
mtr.memo_push(rseg_hdr, MTR_MEMO_PAGE_X_FIX); mtr.memo_push(rseg_hdr, MTR_MEMO_PAGE_X_FIX);
mtr.memo_push(block, MTR_MEMO_PAGE_X_FIX); mtr.memo_push(block, MTR_MEMO_PAGE_X_MODIFY);
rseg->latch.wr_lock(SRW_LOCK_CALL); rseg->latch.wr_lock(SRW_LOCK_CALL);
rseg_hdr->page.lock.x_lock(); rseg_hdr->page.lock.x_lock();
block->page.lock.x_lock(); block->page.lock.x_lock();

View file

@ -1,26 +1,26 @@
# #
# Add the following to the end of your /etc/magic file to get the 'file' # Add the following to the end of your /etc/magic file to get the 'file'
# command to recognize some MySQL files. # command to recognize some MariaDB / MySQL files.
# #
0 beshort 0xfe01 MySQL table definition file 0 beshort 0xfe01 MariaDB/MySQL table definition file
>2 byte x Version %d >2 byte x Version %d
0 belong&0xffffff00 0xfefe0700 MySQL MyISAM index file 0 belong&0xffffff00 0xfefe0700 MariaDB/MySQL MyISAM index file
>3 byte x Version %d >3 byte x Version %d
0 belong&0xffffff00 0xfefe0800 MySQL MyISAM compressed data file 0 belong&0xffffff00 0xfefe0800 MariaDB/MySQL MyISAM compressed data file
>3 byte x Version %d >3 byte x Version %d
0 belong&0xffffff00 0xfefe0900 MySQL Maria index file 0 belong&0xffffff00 0xfefe0900 MariaDB Aaria index file
>3 byte x Version %d >3 byte x Version %d
0 belong&0xffffff00 0xfefe0A00 MySQL Maria compressed data file 0 belong&0xffffff00 0xfefe0A00 MariaDB Aaria compressed data file
>3 byte x Version %d >3 byte x Version %d
0 belong&0xffffff00 0xfefe0500 MySQL ISAM index file 0 belong&0xffffff00 0xfefe0500 MariaDB/MySQL ISAM index file
>3 byte x Version %d >3 byte x Version %d
0 belong&0xffffff00 0xfefe0600 MySQL ISAM compressed data file 0 belong&0xffffff00 0xfefe0600 MariaDB/MySQL ISAM compressed data file
>3 byte x Version %d >3 byte x Version %d
0 string \376bin MySQL replication log 0 string \376bin MariaDB/MySQL replication log
0 belong&0xffffff00 0xfefe0b00 0 belong&0xffffff00 0xfefe0b00
>4 string MARIALOG MySQL Maria transaction log file >4 string MARIALOG MariaDB Aria transaction log file
>>3 byte x Version %d >>3 byte x Version %d
0 belong&0xffffff00 0xfefe0c00 0 belong&0xffffff00 0xfefe0c00 MariaDB Aria control file
>4 string MACF MySQL Maria control file >3 byte x Version %d
>>3 byte x Version %d 0 belong&0xffffff00 0xfefe0b00 MariaDB DDL recovery log
>3 byte x Version %d