1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge 10.6 into 10.7

This commit is contained in:
Marko Mäkelä
2021-09-06 16:23:49 +03:00
63 changed files with 685 additions and 308 deletions

View File

@@ -33,22 +33,11 @@ PROJECT(MySQL)
# in RPM's: # in RPM's:
#set(CPACK_RPM_SPEC_MORE_DEFINE "%define __spec_install_post /bin/true") #set(CPACK_RPM_SPEC_MORE_DEFINE "%define __spec_install_post /bin/true")
FOREACH(p CMP0022 CMP0046 CMP0040 CMP0048 CMP0054 CMP0075 CMP0069)
IF(POLICY CMP0022) IF(POLICY ${p})
CMAKE_POLICY(SET CMP0022 NEW) CMAKE_POLICY(SET ${p} NEW)
ENDIF() ENDIF()
IF(POLICY CMP0048) ENDFOREACH()
CMAKE_POLICY(SET CMP0048 NEW)
ENDIF()
IF(POLICY CMP0054)
CMAKE_POLICY(SET CMP0054 NEW)
ENDIF()
IF(POLICY CMP0075)
CMAKE_POLICY(SET CMP0075 NEW)
ENDIF()
IF(POLICY CMP0069)
CMAKE_POLICY(SET CMP0069 NEW)
ENDIF()
MESSAGE(STATUS "Running cmake version ${CMAKE_VERSION}") MESSAGE(STATUS "Running cmake version ${CMAKE_VERSION}")
@@ -563,3 +552,41 @@ IF(NON_DISTRIBUTABLE_WARNING)
MESSAGE(WARNING " MESSAGE(WARNING "
You have linked MariaDB with ${NON_DISTRIBUTABLE_WARNING} libraries! You may not distribute the resulting binary. If you do, you will put yourself into a legal problem with the Free Software Foundation.") You have linked MariaDB with ${NON_DISTRIBUTABLE_WARNING} libraries! You may not distribute the resulting binary. If you do, you will put yourself into a legal problem with the Free Software Foundation.")
ENDIF() ENDIF()
IF(NOT WITHOUT_SERVER)
# Define target for minimal mtr-testable build
ADD_CUSTOM_TARGET(minbuild)
ADD_DEPENDENCIES(minbuild
aria_chk
aria_pack
mariadb
mariadb-admin
mariadb-binlog
mariadb-check
mariadb-client-test
mariadb-conv
mariadb-dump
mariadb-import
mariadb-plugin
mariadb-show
mariadb-slap
mariadb-test
mariadb-tzinfo-to-sql
mariadb-upgrade
mariadbd
my_print_defaults
my_safe_process
myisam_ftdump
myisamchk
myisamlog
myisampack
perror
replace)
IF(WIN32)
ADD_DEPENDENCIES(minbuild echo mariadb-install-db my_safe_kill)
ENDIF()
ADD_CUSTOM_TARGET(smoketest
COMMAND perl ./mysql-test-run.pl main.1st
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/mysql-test)
ADD_DEPENDENCIES(smoketest minbuild)
ENDIF()

View File

@@ -1,21 +1,24 @@
version: build-{build}~branch-{branch} version: build-{build}~branch-{branch}
before_build: clone_depth: 1
- md %APPVEYOR_BUILD_FOLDER%\win_build
- cd %APPVEYOR_BUILD_FOLDER%\win_build
- cmake .. -DWITH_UNIT_TESTS=0 -DWITH_MARIABACKUP=0 -DMYSQL_MAINTAINER_MODE=ERR -DPLUGIN_ROCKSDB=NO -DPLUGIN_CONNECT=NO -DBISON_EXECUTABLE=C:\cygwin64\bin\bison
build: build_script:
project: win_build\MySQL.sln # dump some system info
parallel: true - echo processor='%PROCESSOR_IDENTIFIER%' , processor count= %NUMBER_OF_PROCESSORS%
verbosity: minimal - cd %APPVEYOR_BUILD_FOLDER%
- mkdir _build
configuration: RelWithDebInfo - cd _build
platform: x64 - set BUILD_TYPE=MinSizeRel
- set GENERATOR=-GNinja
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
- cmake -E time cmake %GENERATOR% .. -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DMYSQL_MAINTAINER_MODE=ERR -DFAST_BUILD=1 -DBISON_EXECUTABLE=C:\cygwin64\bin\bison -DPLUGIN_PERFSCHEMA=NO -DPLUGIN_FEEDBACK=NO
- set /A jobs=2*%NUMBER_OF_PROCESSORS%
- cmake -E time cmake --build . -j %jobs% --config %BUILD_TYPE% --target minbuild
test_script: test_script:
- set PATH=C:\Strawberry\perl\bin;%PATH%;C:\Program Files (x86)\Windows Kits\10\Debuggers\x64 - set PATH=C:\Strawberry\perl\bin;%PATH%;C:\Program Files (x86)\Windows Kits\10\Debuggers\x64
- cd %APPVEYOR_BUILD_FOLDER%\win_build\mysql-test - cd %APPVEYOR_BUILD_FOLDER%\_build\mysql-test
- perl mysql-test-run.pl --force --max-test-fail=10 --parallel=4 --testcase-timeout=10 --suite=main - set /A parallel=4*%NUMBER_OF_PROCESSORS%
- perl mysql-test-run.pl --force --max-test-fail=10 --retry=2 -parallel=%parallel% --testcase-timeout=3 --suite=main --skip-test-list=%APPVEYOR_BUILD_FOLDER%\win\appveyor_skip_tests.txt --mysqld=--loose-innodb-flush-log-at-trx-commit=2
image: Visual Studio 2019 image: Visual Studio 2019

View File

@@ -116,7 +116,7 @@ ENDMACRO()
IF(MSVC) IF(MSVC)
IF(MSVC_VERSION LESS 1920) IF(MSVC_VERSION LESS 1920)
MESSAGE(FATAL_ERROR "Visual Studio q2019 or later is required") MESSAGE(FATAL_ERROR "Visual Studio 2019 or later is required")
ENDIF() ENDIF()
# Disable mingw based pkg-config found in Strawberry perl # Disable mingw based pkg-config found in Strawberry perl
SET(PKG_CONFIG_EXECUTABLE 0 CACHE INTERNAL "") SET(PKG_CONFIG_EXECUTABLE 0 CACHE INTERNAL "")
@@ -254,12 +254,12 @@ IF(MSVC)
ENDFOREACH() ENDFOREACH()
ENDFOREACH() ENDFOREACH()
ENDIF() ENDIF()
IF(MSVC_VERSION LESS 1910)
# Noisy warning C4800: 'type': forcing value to bool 'true' or 'false' (performance warning), IF(FAST_BUILD)
# removed in VS2017 STRING (REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
STRING(APPEND CMAKE_CXX_FLAGS " /wd4800")
ELSEIF (NOT CLANG_CL) ELSEIF (NOT CLANG_CL)
STRING(APPEND CMAKE_CXX_FLAGS " /d2OptimizeHugeFunctions") STRING(APPEND CMAKE_CXX_FLAGS_RELEASE " /d2OptimizeHugeFunctions")
STRING(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " /d2OptimizeHugeFunctions")
ENDIF() ENDIF()
ENDIF() ENDIF()

View File

@@ -2,23 +2,28 @@
# Testing which locks we get from all stages # Testing which locks we get from all stages
# #
BACKUP STAGE START; BACKUP STAGE START;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
MDL_BACKUP_START Backup lock MDL_BACKUP_START Backup lock
BACKUP STAGE FLUSH; BACKUP STAGE FLUSH;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
MDL_BACKUP_FLUSH Backup lock MDL_BACKUP_FLUSH Backup lock
BACKUP STAGE BLOCK_DDL; BACKUP STAGE BLOCK_DDL;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
MDL_BACKUP_WAIT_DDL Backup lock MDL_BACKUP_WAIT_DDL Backup lock
BACKUP STAGE BLOCK_COMMIT; BACKUP STAGE BLOCK_COMMIT;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
MDL_BACKUP_WAIT_COMMIT Backup lock MDL_BACKUP_WAIT_COMMIT Backup lock
BACKUP STAGE END; BACKUP STAGE END;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
# #
# testing BACKUP STAGE LOCK's # testing BACKUP STAGE LOCK's
@@ -39,7 +44,8 @@ connection con1;
alter table t1 add column (j int), algorithm copy; alter table t1 add column (j int), algorithm copy;
connection con2; connection con2;
backup stage flush; backup stage flush;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
MDL_BACKUP_DDL Backup lock MDL_BACKUP_DDL Backup lock
MDL_BACKUP_FLUSH Backup lock MDL_BACKUP_FLUSH Backup lock
@@ -75,7 +81,8 @@ alter table t1 add column (j int);
connection con2; connection con2;
backup stage start; backup stage start;
backup stage flush; backup stage flush;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
MDL_BACKUP_ALTER_COPY Backup lock MDL_BACKUP_ALTER_COPY Backup lock
MDL_BACKUP_FLUSH Backup lock MDL_BACKUP_FLUSH Backup lock
@@ -110,7 +117,8 @@ backup stage flush;
SET STATEMENT lock_wait_timeout=0 FOR SELECT * FROM t1; SET STATEMENT lock_wait_timeout=0 FOR SELECT * FROM t1;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction ERROR HY000: Lock wait timeout exceeded; try restarting transaction
backup stage block_ddl; backup stage block_ddl;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
MDL_BACKUP_WAIT_DDL Backup lock MDL_BACKUP_WAIT_DDL Backup lock
MDL_SHARED_WRITE Table metadata lock test t1 MDL_SHARED_WRITE Table metadata lock test t1
@@ -130,7 +138,8 @@ connection con1;
DROP TABLE t1; DROP TABLE t1;
connection con2; connection con2;
connection con2; connection con2;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME LOCK_MODE LOCK_TYPE TABLE_SCHEMA TABLE_NAME
MDL_BACKUP_WAIT_DDL Backup lock MDL_BACKUP_WAIT_DDL Backup lock
SELECT * FROM t1; SELECT * FROM t1;

View File

@@ -10,16 +10,19 @@
--echo # Testing which locks we get from all stages --echo # Testing which locks we get from all stages
--echo # --echo #
let $mdl= LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info
WHERE TABLE_NAME NOT LIKE 'innodb_%_stats';
BACKUP STAGE START; BACKUP STAGE START;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; eval SELECT $mdl;
BACKUP STAGE FLUSH; BACKUP STAGE FLUSH;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; eval SELECT $mdl;
BACKUP STAGE BLOCK_DDL; BACKUP STAGE BLOCK_DDL;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; eval SELECT $mdl;
BACKUP STAGE BLOCK_COMMIT; BACKUP STAGE BLOCK_COMMIT;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; eval SELECT $mdl;
BACKUP STAGE END; BACKUP STAGE END;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; eval SELECT $mdl;
--echo # --echo #
--echo # testing BACKUP STAGE LOCK's --echo # testing BACKUP STAGE LOCK's
@@ -54,7 +57,7 @@ let $wait_condition=
where state = "Waiting for table metadata lock"; where state = "Waiting for table metadata lock";
--source include/wait_condition.inc --source include/wait_condition.inc
backup stage flush; backup stage flush;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; eval SELECT $mdl;
# #
# Do first test with max_statement_time, other tests later are done with # Do first test with max_statement_time, other tests later are done with
# lock_wait_timeout. This is mostly to ensure that both methods works # lock_wait_timeout. This is mostly to ensure that both methods works
@@ -103,7 +106,7 @@ let $wait_condition=
--source include/wait_condition.inc --source include/wait_condition.inc
backup stage start; backup stage start;
backup stage flush; backup stage flush;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; eval SELECT $mdl;
backup stage block_ddl; backup stage block_ddl;
backup stage block_commit; backup stage block_commit;
connection default; connection default;
@@ -146,7 +149,7 @@ let $wait_condition=
SET STATEMENT lock_wait_timeout=0 FOR SELECT * FROM t1; SET STATEMENT lock_wait_timeout=0 FOR SELECT * FROM t1;
backup stage block_ddl; backup stage block_ddl;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; eval SELECT $mdl;
backup stage end; backup stage end;
connection default; connection default;
@@ -170,7 +173,7 @@ let $wait_condition=
where state = "Waiting for backup lock"; where state = "Waiting for backup lock";
--source include/wait_condition.inc --source include/wait_condition.inc
connection con2; connection con2;
SELECT LOCK_MODE, LOCK_TYPE, TABLE_SCHEMA, TABLE_NAME FROM information_schema.metadata_lock_info; eval SELECT $mdl;
# Check that select's are not blocked # Check that select's are not blocked
SELECT * FROM t1; SELECT * FROM t1;
connection default; connection default;

View File

@@ -1,7 +1,5 @@
# This test should work in embedded server after we fix mysqltest # This test should work in embedded server after we fix mysqltest
-- source include/not_embedded.inc -- source include/not_embedded.inc
# need to have the dynamic loading turned on for the client plugin tests
--source include/have_plugin_auth.inc
# Run test with default character set # Run test with default character set
--source include/default_charset.inc --source include/default_charset.inc

View File

@@ -26,12 +26,6 @@ tmpdir=BASEDIR/temp
innodb_data_file_path=ibdata1:10M;ibdata2:10M:autoextend innodb_data_file_path=ibdata1:10M;ibdata2:10M:autoextend
innodb_log_group_home_dir=BASEDIR/data innodb_log_group_home_dir=BASEDIR/data
skip-name-resolve skip-name-resolve
#*********************************************************
# performance_schema
#*********************************************************
performance_schema=OFF
[client] [client]
port=3307 port=3307
# restart # restart

View File

@@ -1,6 +1,7 @@
# #
# MDEV-11942 BLACKHOLE is no longer active in 10.1 by default, mysql_upgrade not handling the situation # MDEV-11942 BLACKHOLE is no longer active in 10.1 by default, mysql_upgrade not handling the situation
# #
source include/mysql_upgrade_preparation.inc;
source include/have_innodb.inc; source include/have_innodb.inc;
source include/not_embedded.inc; source include/not_embedded.inc;

View File

@@ -10,9 +10,3 @@ tmpdir=BASEDIR/temp
innodb_data_file_path=ibdata1:10M;ibdata2:10M:autoextend innodb_data_file_path=ibdata1:10M;ibdata2:10M:autoextend
innodb_log_group_home_dir=BASEDIR/data innodb_log_group_home_dir=BASEDIR/data
skip-name-resolve skip-name-resolve
#*********************************************************
# performance_schema
#*********************************************************
performance_schema=OFF

View File

@@ -2,23 +2,25 @@ drop table if exists t1;
# #
# Test simple create of s3 table # Test simple create of s3 table
# #
create or replace table t1 (a int, b int, key (a)) engine=aria; create or replace table t1 (a int, b int, c varchar(1000), key (a), key(c)) engine=aria;
insert into t1 select seq,seq+10 from seq_1_to_10000; insert into t1 select seq, seq+10, repeat(char(65+ mod(seq, 20)),mod(seq,1000)) from seq_1_to_10000;
alter table t1 engine=s3; alter table t1 engine=s3;
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL, `a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL,
KEY `a` (`a`) `c` varchar(1000) DEFAULT NULL,
KEY `a` (`a`),
KEY `c` (`c`)
) ENGINE=S3 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 ) ENGINE=S3 DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
select * from information_schema.tables where table_schema="database" and table_name="t1";; select * from information_schema.tables where table_schema="database" and table_name="t1";;
TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT MAX_INDEX_LENGTH TEMPORARY TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE ENGINE VERSION ROW_FORMAT TABLE_ROWS AVG_ROW_LENGTH DATA_LENGTH MAX_DATA_LENGTH INDEX_LENGTH DATA_FREE AUTO_INCREMENT CREATE_TIME UPDATE_TIME CHECK_TIME TABLE_COLLATION CHECKSUM CREATE_OPTIONS TABLE_COMMENT MAX_INDEX_LENGTH TEMPORARY
def # t1 BASE TABLE S3 10 Page 10000 33 335872 # 122880 0 NULL # # # latin1_swedish_ci NULL page_checksum=1 9007199254732800 # def # t1 BASE TABLE S3 10 Page 10000 567 5677056 # 761856 0 NULL # # # latin1_swedish_ci NULL page_checksum=1 2305843009213685760 #
show table status like "t1"; show table status like "t1";
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Max_index_length Temporary
t1 S3 10 Page 10000 33 335872 # 122880 0 NULL # # # latin1_swedish_ci NULL page_checksum=1 # N t1 S3 10 Page 10000 567 5677056 # 761856 0 NULL # # # latin1_swedish_ci NULL page_checksum=1 # N
select * from t1 limit 10; select a,b from t1 limit 10;
a b a b
1 11 1 11
2 12 2 12
@@ -33,7 +35,7 @@ a b
select count(*) from t1; select count(*) from t1;
count(*) count(*)
10000 10000
select * from t1 where a between 10 and 20; select a,b from t1 where a between 10 and 20;
a b a b
10 20 10 20
11 21 11 21
@@ -55,15 +57,53 @@ update t1 set b=100 where a=1;
ERROR HY000: Table 't1' is read only ERROR HY000: Table 't1' is read only
delete from t1 where a>10; delete from t1 where a>10;
ERROR HY000: Table 't1' is read only ERROR HY000: Table 't1' is read only
#
# Analyze, repair, optimize and check table
#
set @@use_stat_tables='never';
truncate mysql.table_stats;
check table t1 fast;
Table Op Msg_type Msg_text
database.t1 check status Table is already up to date
check table t1 quick;
Table Op Msg_type Msg_text
database.t1 check status OK
check table t1 extended;
Table Op Msg_type Msg_text
database.t1 check status OK
analyze table t1;
Table Op Msg_type Msg_text
database.t1 analyze status Table 'database.t1' is read only
analyze table t1 persistent for all;
Table Op Msg_type Msg_text
database.t1 analyze status Table 'database.t1' is read only
database.t1 analyze status Engine-independent statistics collected
database.t1 analyze status OK
repair table t1;
Table Op Msg_type Msg_text
database.t1 repair Error Table 't1' is read only
database.t1 repair status Operation failed
optimize table t1;
Table Op Msg_type Msg_text
database.t1 optimize Error Table 't1' is read only
database.t1 optimize status Operation failed
select * from mysql.table_stats;
db_name table_name cardinality
database t1 10000
#
# Converting table back to Aria
#
alter table t1 engine=aria; alter table t1 engine=aria;
show create table t1; show create table t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL, `a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL,
KEY `a` (`a`) `c` varchar(1000) DEFAULT NULL,
KEY `a` (`a`),
KEY `c` (`c`)
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 ) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1
select * from t1 limit 10; select a,b from t1 limit 10;
a b a b
1 11 1 11
2 12 2 12

View File

@@ -13,8 +13,8 @@ drop table if exists t1;
--echo # Test simple create of s3 table --echo # Test simple create of s3 table
--echo # --echo #
create or replace table t1 (a int, b int, key (a)) engine=aria; create or replace table t1 (a int, b int, c varchar(1000), key (a), key(c)) engine=aria;
insert into t1 select seq,seq+10 from seq_1_to_10000; insert into t1 select seq, seq+10, repeat(char(65+ mod(seq, 20)),mod(seq,1000)) from seq_1_to_10000;
alter table t1 engine=s3; alter table t1 engine=s3;
show create table t1; show create table t1;
@@ -23,9 +23,9 @@ show create table t1;
--eval select * from information_schema.tables where table_schema="$database" and table_name="t1"; --eval select * from information_schema.tables where table_schema="$database" and table_name="t1";
--replace_column 8 # 12 # 13 # 14 # 19 # --replace_column 8 # 12 # 13 # 14 # 19 #
show table status like "t1"; show table status like "t1";
select * from t1 limit 10; select a,b from t1 limit 10;
select count(*) from t1; select count(*) from t1;
select * from t1 where a between 10 and 20; select a,b from t1 where a between 10 and 20;
--replace_column 9 # --replace_column 9 #
explain select * from t1 where a between 10 and 20; explain select * from t1 where a between 10 and 20;
--error ER_OPEN_AS_READONLY --error ER_OPEN_AS_READONLY
@@ -34,9 +34,38 @@ insert into t1 values (1,1);
update t1 set b=100 where a=1; update t1 set b=100 where a=1;
--error ER_OPEN_AS_READONLY --error ER_OPEN_AS_READONLY
delete from t1 where a>10; delete from t1 where a>10;
--echo #
--echo # Analyze, repair, optimize and check table
--echo #
set @@use_stat_tables='never';
truncate mysql.table_stats;
--replace_result $database database
check table t1 fast;
--replace_result $database database
check table t1 quick;
--replace_result $database database
check table t1 extended;
--replace_result $database database
analyze table t1;
--replace_result $database database
analyze table t1 persistent for all;
--replace_result $database database
repair table t1;
--replace_result $database database
optimize table t1;
--replace_result $database database
select * from mysql.table_stats;
--echo #
--echo # Converting table back to Aria
--echo #
alter table t1 engine=aria; alter table t1 engine=aria;
show create table t1; show create table t1;
select * from t1 limit 10; select a,b from t1 limit 10;
select count(*) from t1; select count(*) from t1;
delete from t1 where a=1; delete from t1 where a=1;
drop table t1; drop table t1;

View File

@@ -54,14 +54,15 @@ ALTER TABLE t2 TRUNCATE PARTITION p3;
ERROR HY000: Table 't2' is read only ERROR HY000: Table 't2' is read only
ALTER TABLE t2 ANALYZE PARTITION p3; ALTER TABLE t2 ANALYZE PARTITION p3;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
s3.t2 analyze error Table 's3.t2' is read only s3.t2 analyze status Table 's3.t2' is read only
s3.t2 analyze status Engine-independent statistics collected
s3.t2 analyze status OK
SELECT count(*) FROM t2; SELECT count(*) FROM t2;
count(*) count(*)
6 6
ALTER TABLE t2 CHECK PARTITION p3; ALTER TABLE t2 CHECK PARTITION p3;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
s3.t2 check error Subpartition p3sp0 returned error s3.t2 check status OK
s3.t2 check error Unknown - internal error 165 during operation
SELECT count(*) FROM t2; SELECT count(*) FROM t2;
count(*) count(*)
6 6

View File

@@ -164,18 +164,18 @@ typedef struct st_simple_key_cache_cb
size_t key_cache_mem_size; /* specified size of the cache memory */ size_t key_cache_mem_size; /* specified size of the cache memory */
size_t allocated_mem_size; /* size of the memory actually allocated */ size_t allocated_mem_size; /* size of the memory actually allocated */
uint key_cache_block_size; /* size of the page buffer of a cache block */ uint key_cache_block_size; /* size of the page buffer of a cache block */
ulong min_warm_blocks; /* min number of warm blocks; */ size_t min_warm_blocks; /* min number of warm blocks; */
ulong age_threshold; /* age threshold for hot blocks */ size_t age_threshold; /* age threshold for hot blocks */
ulonglong keycache_time; /* total number of block link operations */ ulonglong keycache_time; /* total number of block link operations */
uint hash_entries; /* max number of entries in the hash table */ uint hash_entries; /* max number of entries in the hash table */
uint changed_blocks_hash_size; /* Number of hash buckets for file blocks */ uint changed_blocks_hash_size; /* Number of hash buckets for file blocks */
int hash_links; /* max number of hash links */ int hash_links; /* max number of hash links */
int hash_links_used; /* number of hash links currently used */ int hash_links_used; /* number of hash links currently used */
int disk_blocks; /* max number of blocks in the cache */ int disk_blocks; /* max number of blocks in the cache */
ulong blocks_used; /* maximum number of concurrently used blocks */ size_t blocks_used; /* maximum number of concurrently used blocks */
ulong blocks_unused; /* number of currently unused blocks */ size_t blocks_unused; /* number of currently unused blocks */
ulong blocks_changed; /* number of currently dirty blocks */ size_t blocks_changed; /* number of currently dirty blocks */
ulong warm_blocks; /* number of blocks in warm sub-chain */ size_t warm_blocks; /* number of blocks in warm sub-chain */
ulong cnt_for_resize_op; /* counter to block resize operation */ ulong cnt_for_resize_op; /* counter to block resize operation */
long blocks_available; /* number of blocks available in the LRU chain */ long blocks_available; /* number of blocks available in the LRU chain */
HASH_LINK **hash_root; /* arr. of entries into hash table buckets */ HASH_LINK **hash_root; /* arr. of entries into hash table buckets */
@@ -478,7 +478,7 @@ int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
size_t use_mem, uint division_limit, size_t use_mem, uint division_limit,
uint age_threshold, uint changed_blocks_hash_size) uint age_threshold, uint changed_blocks_hash_size)
{ {
ulong blocks, hash_links; size_t blocks, hash_links;
size_t length; size_t length;
int error; int error;
DBUG_ENTER("init_simple_key_cache"); DBUG_ENTER("init_simple_key_cache");
@@ -519,8 +519,8 @@ int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
DBUG_PRINT("info", ("key_cache_block_size: %u", DBUG_PRINT("info", ("key_cache_block_size: %u",
key_cache_block_size)); key_cache_block_size));
blocks= (ulong) (use_mem / (sizeof(BLOCK_LINK) + 2 * sizeof(HASH_LINK) + blocks= use_mem / (sizeof(BLOCK_LINK) + 2 * sizeof(HASH_LINK) +
sizeof(HASH_LINK*) * 5/4 + key_cache_block_size)); sizeof(HASH_LINK*) * 5/4 + key_cache_block_size);
/* Changed blocks hash needs to be a power of 2 */ /* Changed blocks hash needs to be a power of 2 */
changed_blocks_hash_size= my_round_up_to_next_power(MY_MAX(changed_blocks_hash_size, changed_blocks_hash_size= my_round_up_to_next_power(MY_MAX(changed_blocks_hash_size,
@@ -532,7 +532,7 @@ int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
for ( ; ; ) for ( ; ; )
{ {
/* Set my_hash_entries to the next bigger 2 power */ /* Set my_hash_entries to the next bigger 2 power */
if ((keycache->hash_entries= next_power(blocks)) < blocks * 5/4) if ((keycache->hash_entries= next_power((uint)blocks)) < blocks * 5/4)
keycache->hash_entries<<= 1; keycache->hash_entries<<= 1;
hash_links= 2 * blocks; hash_links= 2 * blocks;
#if defined(MAX_THREADS) #if defined(MAX_THREADS)
@@ -543,8 +543,8 @@ int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
ALIGN_SIZE(hash_links * sizeof(HASH_LINK)) + ALIGN_SIZE(hash_links * sizeof(HASH_LINK)) +
ALIGN_SIZE(sizeof(HASH_LINK*) * ALIGN_SIZE(sizeof(HASH_LINK*) *
keycache->hash_entries) + keycache->hash_entries) +
sizeof(BLOCK_LINK*)* (changed_blocks_hash_size*2))) + sizeof(BLOCK_LINK*)* ((size_t)changed_blocks_hash_size*2))) +
((size_t) blocks * keycache->key_cache_block_size) > use_mem && blocks > 8) (blocks * keycache->key_cache_block_size) > use_mem && blocks > 8)
blocks--; blocks--;
keycache->allocated_mem_size= blocks * keycache->key_cache_block_size; keycache->allocated_mem_size= blocks * keycache->key_cache_block_size;
if ((keycache->block_mem= my_large_malloc(&keycache->allocated_mem_size, if ((keycache->block_mem= my_large_malloc(&keycache->allocated_mem_size,
@@ -584,7 +584,7 @@ int init_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
} }
keycache->blocks_unused= blocks; keycache->blocks_unused= blocks;
keycache->disk_blocks= (int) blocks; keycache->disk_blocks= (int) blocks;
keycache->hash_links= hash_links; keycache->hash_links= (int)hash_links;
keycache->hash_links_used= 0; keycache->hash_links_used= 0;
keycache->free_hash_list= NULL; keycache->free_hash_list= NULL;
keycache->blocks_used= keycache->blocks_changed= 0; keycache->blocks_used= keycache->blocks_changed= 0;
@@ -4854,7 +4854,7 @@ static int cache_empty(SIMPLE_KEY_CACHE_CB *keycache)
} }
if (errcnt) if (errcnt)
{ {
fprintf(stderr, "blocks: %d used: %lu\n", fprintf(stderr, "blocks: %d used: %zu\n",
keycache->disk_blocks, keycache->blocks_used); keycache->disk_blocks, keycache->blocks_used);
fprintf(stderr, "hash_links: %d used: %d\n", fprintf(stderr, "hash_links: %d used: %d\n",
keycache->hash_links, keycache->hash_links_used); keycache->hash_links, keycache->hash_links_used);

View File

@@ -151,7 +151,9 @@ Table_type dd_frm_type(THD *thd, char *path, LEX_CSTRING *engine_name,
} }
} }
cont: __attribute__((unused)); #ifdef WITH_PARTITION_STORAGE_ENGINE
cont:
#endif
/* read the true engine name */ /* read the true engine name */
{ {
MY_STAT state; MY_STAT state;

View File

@@ -1523,7 +1523,8 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
/* print a line which partition the error belongs to */ /* print a line which partition the error belongs to */
if (error != HA_ADMIN_NOT_IMPLEMENTED && if (error != HA_ADMIN_NOT_IMPLEMENTED &&
error != HA_ADMIN_ALREADY_DONE && error != HA_ADMIN_ALREADY_DONE &&
error != HA_ADMIN_TRY_ALTER) error != HA_ADMIN_TRY_ALTER &&
error != HA_ERR_TABLE_READONLY)
{ {
print_admin_msg(thd, MYSQL_ERRMSG_SIZE, &msg_error, print_admin_msg(thd, MYSQL_ERRMSG_SIZE, &msg_error,
table_share->db.str, table->alias, table_share->db.str, table->alias,

View File

@@ -6201,7 +6201,9 @@ bool ha_table_exists(THD *thd, const LEX_CSTRING *db,
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
retry_from_frm: __attribute__((unused)); #ifdef WITH_PARTITION_STORAGE_ENGINE
retry_from_frm:
#endif
char path[FN_REFLEN + 1]; char path[FN_REFLEN + 1];
size_t path_len = build_table_filename(path, sizeof(path) - 1, size_t path_len = build_table_filename(path, sizeof(path) - 1,
db->str, table_name->str, "", 0); db->str, table_name->str, "", 0);

View File

@@ -2384,10 +2384,6 @@ left_is_superset(const DTCollation *left, const DTCollation *right)
bool DTCollation::aggregate(const DTCollation &dt, uint flags) bool DTCollation::aggregate(const DTCollation &dt, uint flags)
{ {
THD *thd = current_thd;
myf utf8_flag= thd ? thd->get_utf8_flag() :
global_system_variables.old_behavior & OLD_MODE_UTF8_IS_UTF8MB3;
if (!my_charset_same(collation, dt.collation)) if (!my_charset_same(collation, dt.collation))
{ {
/* /*
@@ -2475,6 +2471,9 @@ bool DTCollation::aggregate(const DTCollation &dt, uint flags)
set(dt); set(dt);
return 0; return 0;
} }
THD *thd = current_thd;
myf utf8_flag= thd ? thd->get_utf8_flag()
: global_system_variables.old_behavior & OLD_MODE_UTF8_IS_UTF8MB3;
CHARSET_INFO *bin= get_charset_by_csname(collation->cs_name.str, CHARSET_INFO *bin= get_charset_by_csname(collation->cs_name.str,
MY_CS_BINSORT,MYF(utf8_flag)); MY_CS_BINSORT,MYF(utf8_flag));
set(bin, DERIVATION_NONE); set(bin, DERIVATION_NONE);

View File

@@ -2350,11 +2350,13 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
mysql_prlock_unlock(&lock->m_rwlock); mysql_prlock_unlock(&lock->m_rwlock);
#ifdef HAVE_PSI_INTERFACE
PSI_metadata_locker_state state __attribute__((unused)); PSI_metadata_locker_state state __attribute__((unused));
PSI_metadata_locker *locker= NULL; PSI_metadata_locker *locker= NULL;
if (ticket->m_psi != NULL) if (ticket->m_psi != NULL)
locker= PSI_CALL_start_metadata_wait(&state, ticket->m_psi, __FILE__, __LINE__); locker= PSI_CALL_start_metadata_wait(&state, ticket->m_psi, __FILE__, __LINE__);
#endif
will_wait_for(ticket); will_wait_for(ticket);
@@ -2401,8 +2403,10 @@ MDL_context::acquire_lock(MDL_request *mdl_request, double lock_wait_timeout)
done_waiting_for(); done_waiting_for();
#ifdef HAVE_PSI_INTERFACE
if (locker != NULL) if (locker != NULL)
PSI_CALL_end_metadata_wait(locker, 0); PSI_CALL_end_metadata_wait(locker, 0);
#endif
if (wait_status != MDL_wait::GRANTED) if (wait_status != MDL_wait::GRANTED)
{ {

View File

@@ -1,5 +1,5 @@
/* Copyright (c) 2011, 2012, Oracle and/or its affiliates. /* Copyright (c) 2011, 2012, Oracle and/or its affiliates.
Copyright (c) 2011, 2014, SkySQL Ab. Copyright (c) 2011, 2021, MariaDB Corporation.
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
@@ -174,19 +174,19 @@ extern "C" sig_handler handle_fatal_signal(int sig)
my_safe_printf_stderr("Server version: %s\n", server_version); my_safe_printf_stderr("Server version: %s\n", server_version);
if (dflt_key_cache) if (dflt_key_cache)
my_safe_printf_stderr("key_buffer_size=%lu\n", my_safe_printf_stderr("key_buffer_size=%zu\n",
(ulong) dflt_key_cache->key_cache_mem_size); dflt_key_cache->key_cache_mem_size);
my_safe_printf_stderr("read_buffer_size=%ld\n", my_safe_printf_stderr("read_buffer_size=%lu\n",
(long) global_system_variables.read_buff_size); global_system_variables.read_buff_size);
my_safe_printf_stderr("max_used_connections=%lu\n", my_safe_printf_stderr("max_used_connections=%lu\n",
(ulong) max_used_connections); max_used_connections);
if (thread_scheduler) if (thread_scheduler)
my_safe_printf_stderr("max_threads=%u\n", my_safe_printf_stderr("max_threads=%lu\n",
(uint) thread_scheduler->max_threads + thread_scheduler->max_threads +
(uint) extra_max_connections); extra_max_connections);
my_safe_printf_stderr("thread_count=%u\n", THD_count::value()); my_safe_printf_stderr("thread_count=%u\n", THD_count::value());
@@ -195,11 +195,10 @@ extern "C" sig_handler handle_fatal_signal(int sig)
my_safe_printf_stderr("It is possible that mysqld could use up to \n" my_safe_printf_stderr("It is possible that mysqld could use up to \n"
"key_buffer_size + " "key_buffer_size + "
"(read_buffer_size + sort_buffer_size)*max_threads = " "(read_buffer_size + sort_buffer_size)*max_threads = "
"%lu K bytes of memory\n", "%zu K bytes of memory\n",
(ulong)
(dflt_key_cache->key_cache_mem_size + (dflt_key_cache->key_cache_mem_size +
(global_system_variables.read_buff_size + (global_system_variables.read_buff_size +
global_system_variables.sortbuff_size) * (size_t)global_system_variables.sortbuff_size) *
(thread_scheduler->max_threads + extra_max_connections) + (thread_scheduler->max_threads + extra_max_connections) +
(max_connections + extra_max_connections) * (max_connections + extra_max_connections) *
sizeof(THD)) / 1024); sizeof(THD)) / 1024);

View File

@@ -33,6 +33,7 @@
#include "sql_statistics.h" #include "sql_statistics.h"
#include "wsrep_mysqld.h" #include "wsrep_mysqld.h"
const LEX_CSTRING msg_status= {STRING_WITH_LEN("status")};
const LEX_CSTRING msg_repair= { STRING_WITH_LEN("repair") }; const LEX_CSTRING msg_repair= { STRING_WITH_LEN("repair") };
const LEX_CSTRING msg_assign_to_keycache= const LEX_CSTRING msg_assign_to_keycache=
{ STRING_WITH_LEN("assign_to_keycache") }; { STRING_WITH_LEN("assign_to_keycache") };
@@ -490,6 +491,20 @@ static bool wsrep_toi_replication(THD *thd, TABLE_LIST *tables)
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
static void send_read_only_warning(THD *thd, const LEX_CSTRING *msg_status,
const LEX_CSTRING *table_name)
{
Protocol *protocol= thd->protocol;
char buf[MYSQL_ERRMSG_SIZE];
size_t length;
length= my_snprintf(buf, sizeof(buf),
ER_THD(thd, ER_OPEN_AS_READONLY),
table_name->str);
protocol->store(msg_status, system_charset_info);
protocol->store(buf, length, system_charset_info);
}
/** /**
Collect field names of result set that will be sent to a client Collect field names of result set that will be sent to a client
@@ -774,20 +789,16 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
goto send_result; goto send_result;
} }
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify) if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify &&
operator_func != &handler::ha_analyze)
{ {
/* purecov: begin inspected */ /* purecov: begin inspected */
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];
size_t length;
enum_sql_command save_sql_command= lex->sql_command; enum_sql_command save_sql_command= lex->sql_command;
DBUG_PRINT("admin", ("sending error message")); DBUG_PRINT("admin", ("sending error message"));
protocol->prepare_for_resend(); protocol->prepare_for_resend();
protocol->store(&table_name, system_charset_info); protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info); protocol->store(operator_name, system_charset_info);
protocol->store(&error_clex_str, system_charset_info); send_read_only_warning(thd, &error_clex_str, &table_name);
length= my_snprintf(buff, sizeof(buff), ER_THD(thd, ER_OPEN_AS_READONLY),
table_name.str);
protocol->store(buff, length, system_charset_info);
trans_commit_stmt(thd); trans_commit_stmt(thd);
trans_commit(thd); trans_commit(thd);
close_thread_tables(thd); close_thread_tables(thd);
@@ -923,6 +934,15 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
if (compl_result_code == HA_ADMIN_OK && collect_eis) if (compl_result_code == HA_ADMIN_OK && collect_eis)
{ {
if (result_code == HA_ERR_TABLE_READONLY)
{
protocol->prepare_for_resend();
protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
send_read_only_warning(thd, &msg_status, &table_name);
(void) protocol->write();
result_code= HA_ADMIN_OK;
}
/* /*
Here we close and reopen table in read mode because operation of Here we close and reopen table in read mode because operation of
collecting statistics is long and it will be better do not block collecting statistics is long and it will be better do not block
@@ -1032,7 +1052,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->prepare_for_resend(); protocol->prepare_for_resend();
protocol->store(&table_name, system_charset_info); protocol->store(&table_name, system_charset_info);
protocol->store(operator_name, system_charset_info); protocol->store(operator_name, system_charset_info);
protocol->store(STRING_WITH_LEN("status"), system_charset_info); protocol->store(&msg_status, system_charset_info);
protocol->store(STRING_WITH_LEN("Engine-independent statistics collected"), protocol->store(STRING_WITH_LEN("Engine-independent statistics collected"),
system_charset_info); system_charset_info);
if (protocol->write()) if (protocol->write())
@@ -1102,25 +1122,25 @@ send_result_message:
break; break;
case HA_ADMIN_OK: case HA_ADMIN_OK:
protocol->store(STRING_WITH_LEN("status"), system_charset_info); protocol->store(&msg_status, system_charset_info);
protocol->store(STRING_WITH_LEN("OK"), system_charset_info); protocol->store(STRING_WITH_LEN("OK"), system_charset_info);
break; break;
case HA_ADMIN_FAILED: case HA_ADMIN_FAILED:
protocol->store(STRING_WITH_LEN("status"), system_charset_info); protocol->store(&msg_status, system_charset_info);
protocol->store(STRING_WITH_LEN("Operation failed"), protocol->store(STRING_WITH_LEN("Operation failed"),
system_charset_info); system_charset_info);
break; break;
case HA_ADMIN_REJECT: case HA_ADMIN_REJECT:
protocol->store(STRING_WITH_LEN("status"), system_charset_info); protocol->store(&msg_status, system_charset_info);
protocol->store(STRING_WITH_LEN("Operation need committed state"), protocol->store(STRING_WITH_LEN("Operation need committed state"),
system_charset_info); system_charset_info);
open_for_modify= FALSE; open_for_modify= FALSE;
break; break;
case HA_ADMIN_ALREADY_DONE: case HA_ADMIN_ALREADY_DONE:
protocol->store(STRING_WITH_LEN("status"), system_charset_info); protocol->store(&msg_status, system_charset_info);
protocol->store(STRING_WITH_LEN("Table is already up to date"), protocol->store(STRING_WITH_LEN("Table is already up to date"),
system_charset_info); system_charset_info);
break; break;
@@ -1265,7 +1285,11 @@ send_result_message:
fatal_error=1; fatal_error=1;
break; break;
} }
case HA_ERR_TABLE_READONLY:
{
send_read_only_warning(thd, &msg_status, &table_name);
break;
}
default: // Probably HA_ADMIN_INTERNAL_ERROR default: // Probably HA_ADMIN_INTERNAL_ERROR
{ {
char buf[MYSQL_ERRMSG_SIZE]; char buf[MYSQL_ERRMSG_SIZE];

View File

@@ -4900,11 +4900,13 @@ void destroy_thd(MYSQL_THD thd)
extern "C" pthread_key(struct st_my_thread_var *, THR_KEY_mysys); extern "C" pthread_key(struct st_my_thread_var *, THR_KEY_mysys);
MYSQL_THD create_background_thd() MYSQL_THD create_background_thd()
{ {
DBUG_ASSERT(!current_thd); auto save_thd = current_thd;
set_current_thd(nullptr);
auto save_mysysvar= pthread_getspecific(THR_KEY_mysys); auto save_mysysvar= pthread_getspecific(THR_KEY_mysys);
/* /*
Allocate new mysys_var specifically this THD, Allocate new mysys_var specifically new THD,
so that e.g safemalloc, DBUG etc are happy. so that e.g safemalloc, DBUG etc are happy.
*/ */
pthread_setspecific(THR_KEY_mysys, 0); pthread_setspecific(THR_KEY_mysys, 0);
@@ -4912,7 +4914,8 @@ MYSQL_THD create_background_thd()
auto thd_mysysvar= pthread_getspecific(THR_KEY_mysys); auto thd_mysysvar= pthread_getspecific(THR_KEY_mysys);
auto thd= new THD(0); auto thd= new THD(0);
pthread_setspecific(THR_KEY_mysys, save_mysysvar); pthread_setspecific(THR_KEY_mysys, save_mysysvar);
thd->set_psi(PSI_CALL_get_thread()); thd->set_psi(nullptr);
set_current_thd(save_thd);
/* /*
Workaround the adverse effect of incrementing thread_count Workaround the adverse effect of incrementing thread_count

View File

@@ -643,7 +643,7 @@ public:
Ptr[str_length]=0; Ptr[str_length]=0;
return Ptr; return Ptr;
} }
(void) realloc(str_length+1); /* This will add end \0 */ (void) realloc(str_length); /* This will add end \0 */
return Ptr; return Ptr;
} }
/* /*
@@ -666,7 +666,7 @@ public:
if (Ptr && str_length < Alloced_length) if (Ptr && str_length < Alloced_length)
Ptr[str_length]=0; Ptr[str_length]=0;
else else
(void) realloc(str_length + 1); (void) realloc(str_length);
return Ptr; return Ptr;
} }

View File

@@ -201,7 +201,7 @@ DWORD win_aiosocket::begin_read()
else else
{ {
/* Do async read (named pipe) */ /* Do async read (named pipe) */
if (ReadFile(m_handle, buf.buf, buf.len, 0, &m_overlapped)) if (!ReadFile(m_handle, buf.buf, buf.len, 0, &m_overlapped))
err= GetLastError(); err= GetLastError();
} }

View File

@@ -1247,7 +1247,7 @@ btr_cur_search_to_nth_level_func(
btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is
s- or x-latched, but see also above! */ s- or x-latched, but see also above! */
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
srw_lock* ahi_latch, srw_spin_lock* ahi_latch,
/*!< in: currently held AHI rdlock, or NULL */ /*!< in: currently held AHI rdlock, or NULL */
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
mtr_t* mtr, /*!< in: mtr */ mtr_t* mtr, /*!< in: mtr */
@@ -3344,11 +3344,11 @@ static void btr_cur_prefetch_siblings(const buf_block_t *block,
if (prev == FIL_NULL); if (prev == FIL_NULL);
else if (space->acquire()) else if (space->acquire())
buf_read_page_background(space, page_id_t(space->id, prev), buf_read_page_background(space, page_id_t(space->id, prev),
block->zip_size(), false); block->zip_size());
if (next == FIL_NULL); if (next == FIL_NULL);
else if (space->acquire()) else if (space->acquire())
buf_read_page_background(space, page_id_t(space->id, next), buf_read_page_background(space, page_id_t(space->id, next),
block->zip_size(), false); block->zip_size());
} }
/*************************************************************//** /*************************************************************//**
@@ -3611,7 +3611,7 @@ fail_err:
ut_ad(flags == BTR_NO_LOCKING_FLAG); ut_ad(flags == BTR_NO_LOCKING_FLAG);
} else if (index->table->is_temporary()) { } else if (index->table->is_temporary()) {
} else { } else {
srw_lock* ahi_latch = btr_search_sys.get_latch(*index); srw_spin_lock* ahi_latch = btr_search_sys.get_latch(*index);
if (!reorg && cursor->flag == BTR_CUR_HASH) { if (!reorg && cursor->flag == BTR_CUR_HASH) {
btr_search_update_hash_node_on_insert( btr_search_update_hash_node_on_insert(
cursor, ahi_latch); cursor, ahi_latch);
@@ -4331,7 +4331,7 @@ btr_cur_update_in_place(
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
{ {
srw_lock* ahi_latch = block->index srw_spin_lock* ahi_latch = block->index
? btr_search_sys.get_latch(*index) : NULL; ? btr_search_sys.get_latch(*index) : NULL;
if (ahi_latch) { if (ahi_latch) {
/* TO DO: Can we skip this if none of the fields /* TO DO: Can we skip this if none of the fields

View File

@@ -1015,7 +1015,7 @@ btr_search_guess_on_hash(
ulint mode, ulint mode,
ulint latch_mode, ulint latch_mode,
btr_cur_t* cursor, btr_cur_t* cursor,
srw_lock* ahi_latch, srw_spin_lock* ahi_latch,
mtr_t* mtr) mtr_t* mtr)
{ {
ulint fold; ulint fold;
@@ -1460,7 +1460,7 @@ void
btr_search_build_page_hash_index( btr_search_build_page_hash_index(
dict_index_t* index, dict_index_t* index,
buf_block_t* block, buf_block_t* block,
srw_lock* ahi_latch, srw_spin_lock* ahi_latch,
uint16_t n_fields, uint16_t n_fields,
uint16_t n_bytes, uint16_t n_bytes,
bool left_side) bool left_side)
@@ -1660,7 +1660,7 @@ exit_func:
@param[in,out] cursor cursor which was just positioned */ @param[in,out] cursor cursor which was just positioned */
void btr_search_info_update_slow(btr_search_t *info, btr_cur_t *cursor) void btr_search_info_update_slow(btr_search_t *info, btr_cur_t *cursor)
{ {
srw_lock* ahi_latch = &btr_search_sys.get_part(*cursor->index) srw_spin_lock* ahi_latch = &btr_search_sys.get_part(*cursor->index)
->latch; ->latch;
buf_block_t* block = btr_cur_get_block(cursor); buf_block_t* block = btr_cur_get_block(cursor);
@@ -1727,7 +1727,7 @@ btr_search_move_or_delete_hash_entries(
assert_block_ahi_valid(block); assert_block_ahi_valid(block);
assert_block_ahi_valid(new_block); assert_block_ahi_valid(new_block);
srw_lock* ahi_latch = index srw_spin_lock* ahi_latch = index
? &btr_search_sys.get_part(*index)->latch ? &btr_search_sys.get_part(*index)->latch
: nullptr; : nullptr;
@@ -1852,7 +1852,7 @@ void btr_search_update_hash_on_delete(btr_cur_t *cursor)
inserted next to the cursor. inserted next to the cursor.
@param[in] ahi_latch the adaptive hash index latch */ @param[in] ahi_latch the adaptive hash index latch */
void btr_search_update_hash_node_on_insert(btr_cur_t *cursor, void btr_search_update_hash_node_on_insert(btr_cur_t *cursor,
srw_lock *ahi_latch) srw_spin_lock *ahi_latch)
{ {
buf_block_t* block; buf_block_t* block;
dict_index_t* index; dict_index_t* index;
@@ -1925,7 +1925,7 @@ func_exit:
to the cursor to the cursor
@param[in] ahi_latch the adaptive hash index latch */ @param[in] ahi_latch the adaptive hash index latch */
void btr_search_update_hash_on_insert(btr_cur_t *cursor, void btr_search_update_hash_on_insert(btr_cur_t *cursor,
srw_lock *ahi_latch) srw_spin_lock *ahi_latch)
{ {
buf_block_t* block; buf_block_t* block;
dict_index_t* index; dict_index_t* index;

View File

@@ -282,7 +282,7 @@ void page_hash_latch::read_lock_wait()
/* First, try busy spinning for a while. */ /* First, try busy spinning for a while. */
for (auto spin= srv_n_spin_wait_rounds; spin--; ) for (auto spin= srv_n_spin_wait_rounds; spin--; )
{ {
ut_delay(srv_spin_wait_delay); LF_BACKOFF();
if (read_trylock()) if (read_trylock())
return; return;
} }
@@ -301,7 +301,7 @@ void page_hash_latch::write_lock_wait()
{ {
if (write_lock_poll()) if (write_lock_poll())
return; return;
ut_delay(srv_spin_wait_delay); LF_BACKOFF();
} }
/* Fall back to yielding to other threads. */ /* Fall back to yielding to other threads. */

View File

@@ -683,7 +683,7 @@ buf_load()
} }
space->reacquire(); space->reacquire();
buf_read_page_background(space, dump[i], zip_size, true); buf_read_page_background(space, dump[i], zip_size);
if (buf_load_abort_flag) { if (buf_load_abort_flag) {
if (space) { if (space) {

View File

@@ -495,14 +495,13 @@ an exclusive lock on the buffer frame. The flag is cleared and the x-lock
released by the i/o-handler thread. released by the i/o-handler thread.
@param[in,out] space tablespace @param[in,out] space tablespace
@param[in] page_id page id @param[in] page_id page id
@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 */
@param[in] sync true if synchronous aio is desired */
void buf_read_page_background(fil_space_t *space, const page_id_t page_id, void buf_read_page_background(fil_space_t *space, const page_id_t page_id,
ulint zip_size, bool sync) ulint zip_size)
{ {
dberr_t err; dberr_t err;
if (buf_read_page_low(&err, space, sync, BUF_READ_ANY_PAGE, if (buf_read_page_low(&err, space, false, BUF_READ_ANY_PAGE,
page_id, zip_size, false)) { page_id, zip_size, false)) {
srv_stats.buf_pool_reads.add(1); srv_stats.buf_pool_reads.add(1);
} }

View File

@@ -225,7 +225,8 @@ void dict_table_close(dict_table_t *table)
if (table->release()) if (table->release())
{ {
table->stats_mutex_lock(); table->stats_mutex_lock();
dict_stats_deinit(table); if (table->get_ref_count() == 0)
dict_stats_deinit(table);
table->stats_mutex_unlock(); table->stats_mutex_unlock();
} }
dict_sys.unlock(); dict_sys.unlock();
@@ -258,7 +259,8 @@ dict_table_close(
that FLUSH TABLE can be used to forcibly fetch stats from disk if that FLUSH TABLE can be used to forcibly fetch stats from disk if
they have been manually modified. */ they have been manually modified. */
table->stats_mutex_lock(); table->stats_mutex_lock();
dict_stats_deinit(table); if (table->get_ref_count() == 0)
dict_stats_deinit(table);
table->stats_mutex_unlock(); table->stats_mutex_unlock();
} }

View File

@@ -14527,7 +14527,12 @@ ha_innobase::info_low(
DBUG_ASSERT(ib_table->get_ref_count() > 0); DBUG_ASSERT(ib_table->get_ref_count() > 0);
if (!ib_table->is_readable()) { if (!ib_table->is_readable()) {
ib_table->stats_mutex_lock();
ib_table->stat_initialized = true; ib_table->stat_initialized = true;
ib_table->stat_n_rows = 0;
ib_table->stat_clustered_index_size = 0;
ib_table->stat_sum_of_other_index_sizes = 0;
ib_table->stats_mutex_unlock();
} }
if (flag & HA_STATUS_TIME) { if (flag & HA_STATUS_TIME) {

View File

@@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2019, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2019, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2020, MariaDB Corporation. Copyright (c) 2017, 2021, 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
@@ -201,7 +201,7 @@ btr_cur_search_to_nth_level_func(
btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is btr_cur_t* cursor, /*!< in/out: tree cursor; the cursor page is
s- or x-latched, but see also above! */ s- or x-latched, but see also above! */
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
srw_lock* ahi_latch, srw_spin_lock* ahi_latch,
/*!< in: currently held AHI rdlock, or NULL */ /*!< in: currently held AHI rdlock, or NULL */
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
mtr_t* mtr, /*!< in/out: mini-transaction */ mtr_t* mtr, /*!< in/out: mini-transaction */

View File

@@ -135,7 +135,7 @@ btr_pcur_open_with_no_init_func(
that the ahi_latch protects the record! */ that the ahi_latch protects the record! */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
srw_lock* ahi_latch, srw_spin_lock* ahi_latch,
/*!< in: currently held AHI rdlock, or NULL */ /*!< in: currently held AHI rdlock, or NULL */
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
mtr_t* mtr); /*!< in: mtr */ mtr_t* mtr); /*!< in: mtr */

View File

@@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2020, MariaDB Corporation. Copyright (c) 2015, 2021, 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
@@ -479,7 +479,7 @@ btr_pcur_open_with_no_init_func(
that the ahi_latch protects the record! */ that the ahi_latch protects the record! */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */ btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
#ifdef BTR_CUR_HASH_ADAPT #ifdef BTR_CUR_HASH_ADAPT
srw_lock* ahi_latch, srw_spin_lock* ahi_latch,
/*!< in: currently held AHI rdlock, or NULL */ /*!< in: currently held AHI rdlock, or NULL */
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
mtr_t* mtr) /*!< in: mtr */ mtr_t* mtr) /*!< in: mtr */

View File

@@ -81,7 +81,7 @@ btr_search_guess_on_hash(
ulint mode, ulint mode,
ulint latch_mode, ulint latch_mode,
btr_cur_t* cursor, btr_cur_t* cursor,
srw_lock* ahi_latch, srw_spin_lock* ahi_latch,
mtr_t* mtr); mtr_t* mtr);
/** Move or delete hash entries for moved records, usually in a page split. /** Move or delete hash entries for moved records, usually in a page split.
@@ -114,7 +114,7 @@ void btr_search_drop_page_hash_when_freed(const page_id_t page_id);
inserted next to the cursor. inserted next to the cursor.
@param[in] ahi_latch the adaptive hash index latch */ @param[in] ahi_latch the adaptive hash index latch */
void btr_search_update_hash_node_on_insert(btr_cur_t *cursor, void btr_search_update_hash_node_on_insert(btr_cur_t *cursor,
srw_lock *ahi_latch); srw_spin_lock *ahi_latch);
/** Updates the page hash index when a single record is inserted on a page. /** Updates the page hash index when a single record is inserted on a page.
@param[in,out] cursor cursor which was positioned to the @param[in,out] cursor cursor which was positioned to the
@@ -123,7 +123,7 @@ void btr_search_update_hash_node_on_insert(btr_cur_t *cursor,
to the cursor to the cursor
@param[in] ahi_latch the adaptive hash index latch */ @param[in] ahi_latch the adaptive hash index latch */
void btr_search_update_hash_on_insert(btr_cur_t *cursor, void btr_search_update_hash_on_insert(btr_cur_t *cursor,
srw_lock *ahi_latch); srw_spin_lock *ahi_latch);
/** Updates the page hash index when a single record is deleted from a page. /** Updates the page hash index when a single record is deleted from a page.
@param[in] cursor cursor which was positioned on the record to delete @param[in] cursor cursor which was positioned on the record to delete
@@ -237,16 +237,26 @@ struct btr_search_sys_t
struct partition struct partition
{ {
/** latches protecting hash_table */ /** latches protecting hash_table */
srw_lock latch; srw_spin_lock latch;
/** mapping of dtuple_fold() to rec_t* in buf_block_t::frame */ /** mapping of dtuple_fold() to rec_t* in buf_block_t::frame */
hash_table_t table; hash_table_t table;
/** memory heap for table */ /** memory heap for table */
mem_heap_t *heap; mem_heap_t *heap;
char pad[(CPU_LEVEL1_DCACHE_LINESIZE - sizeof(srw_lock) - #ifdef _MSC_VER
sizeof(hash_table_t) - sizeof(mem_heap_t)) & #pragma warning(push)
// nonstandard extension - zero sized array, if perfschema is not compiled
#pragma warning(disable : 4200)
#endif
char pad[(CPU_LEVEL1_DCACHE_LINESIZE - sizeof latch -
sizeof table - sizeof heap) &
(CPU_LEVEL1_DCACHE_LINESIZE - 1)]; (CPU_LEVEL1_DCACHE_LINESIZE - 1)];
#ifdef _MSC_VER
#pragma warning(pop)
#endif
void init() void init()
{ {
memset((void*) this, 0, sizeof *this); memset((void*) this, 0, sizeof *this);
@@ -296,7 +306,7 @@ struct btr_search_sys_t
} }
/** Get the search latch for the adaptive hash index partition */ /** Get the search latch for the adaptive hash index partition */
srw_lock *get_latch(const dict_index_t &index) const srw_spin_lock *get_latch(const dict_index_t &index) const
{ return &get_part(index)->latch; } { return &get_part(index)->latch; }
/** Create and initialize at startup */ /** Create and initialize at startup */
@@ -341,7 +351,7 @@ inline ulint dict_index_t::n_ahi_pages() const
{ {
if (!btr_search_enabled) if (!btr_search_enabled)
return 0; return 0;
srw_lock *latch= &btr_search_sys.get_part(*this)->latch; srw_spin_lock *latch= &btr_search_sys.get_part(*this)->latch;
latch->rd_lock(SRW_LOCK_CALL); latch->rd_lock(SRW_LOCK_CALL);
ulint ref_count= search_info->ref_count; ulint ref_count= search_info->ref_count;
latch->rd_unlock(); latch->rd_unlock();

View File

@@ -48,10 +48,9 @@ an exclusive lock on the buffer frame. The flag is cleared and the x-lock
released by the i/o-handler thread. released by the i/o-handler thread.
@param[in,out] space tablespace @param[in,out] space tablespace
@param[in] page_id page id @param[in] page_id page id
@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 */
@param[in] sync true if synchronous aio is desired */
void buf_read_page_background(fil_space_t *space, const page_id_t page_id, void buf_read_page_background(fil_space_t *space, const page_id_t page_id,
ulint zip_size, bool sync) ulint zip_size)
MY_ATTRIBUTE((nonnull)); MY_ATTRIBUTE((nonnull));
/** Applies a random read-ahead in buf_pool if there are at least a threshold /** Applies a random read-ahead in buf_pool if there are at least a threshold

View File

@@ -2268,10 +2268,10 @@ public:
lock_t* autoinc_lock; lock_t* autoinc_lock;
/** Mutex protecting autoinc and freed_indexes. */ /** Mutex protecting autoinc and freed_indexes. */
srw_mutex autoinc_mutex; srw_spin_mutex autoinc_mutex;
private: private:
/** Mutex protecting locks on this table. */ /** Mutex protecting locks on this table. */
srw_mutex lock_mutex; srw_spin_mutex lock_mutex;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/** The owner of lock_mutex (0 if none) */ /** The owner of lock_mutex (0 if none) */
Atomic_relaxed<os_thread_id_t> lock_mutex_owner{0}; Atomic_relaxed<os_thread_id_t> lock_mutex_owner{0};

View File

@@ -175,16 +175,13 @@ dict_stats_deinit(
dict_table_t* table) /*!< in/out: table */ dict_table_t* table) /*!< in/out: table */
{ {
ut_ad(table->stats_mutex_is_owner()); ut_ad(table->stats_mutex_is_owner());
ut_ad(table->get_ref_count() == 0);
ut_a(table->get_ref_count() == 0); #ifdef HAVE_valgrind
if (!table->stat_initialized) { if (!table->stat_initialized) {
return; return;
} }
table->stat_initialized = FALSE;
#ifdef HAVE_valgrind
MEM_UNDEFINED(&table->stat_n_rows, sizeof table->stat_n_rows); MEM_UNDEFINED(&table->stat_n_rows, sizeof table->stat_n_rows);
MEM_UNDEFINED(&table->stat_clustered_index_size, MEM_UNDEFINED(&table->stat_clustered_index_size,
sizeof table->stat_clustered_index_size); sizeof table->stat_clustered_index_size);
@@ -218,4 +215,5 @@ dict_stats_deinit(
sizeof(index->stat_n_leaf_pages)); sizeof(index->stat_n_leaf_pages));
} }
#endif /* HAVE_valgrind */ #endif /* HAVE_valgrind */
table->stat_initialized = FALSE;
} }

View File

@@ -584,7 +584,7 @@ class lock_sys_t
#else #else
{ {
private: private:
srw_lock_low lock; srw_spin_lock_low lock;
public: public:
/** Try to acquire a lock */ /** Try to acquire a lock */
bool try_acquire() { return lock.wr_lock_try(); } bool try_acquire() { return lock.wr_lock_try(); }
@@ -666,7 +666,7 @@ private:
bool m_initialised; bool m_initialised;
/** mutex proteting the locks */ /** mutex proteting the locks */
MY_ALIGNED(CPU_LEVEL1_DCACHE_LINESIZE) srw_lock latch; MY_ALIGNED(CPU_LEVEL1_DCACHE_LINESIZE) srw_spin_lock latch;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/** The owner of exclusive latch (0 if none); protected by latch */ /** The owner of exclusive latch (0 if none); protected by latch */
std::atomic<os_thread_id_t> writer{0}; std::atomic<os_thread_id_t> writer{0};

View File

@@ -124,8 +124,8 @@ protected:
} }
DBUG_ASSERT((l & ~WRITER_WAITING) == UPDATER); DBUG_ASSERT((l & ~WRITER_WAITING) == UPDATER);
/* Any thread that had set WRITER_WAITING will eventually be woken /* Any thread that had set WRITER_WAITING will eventually be woken
up by ssux_lock_low::x_unlock() or ssux_lock_low::u_unlock() up by ssux_lock_impl::x_unlock() or ssux_lock_impl::u_unlock()
(not ssux_lock_low::wr_u_downgrade() to keep the code simple). */ (not ssux_lock_impl::wr_u_downgrade() to keep the code simple). */
return true; return true;
} }
/** Downgrade an exclusive lock to an update lock. */ /** Downgrade an exclusive lock to an update lock. */

View File

@@ -32,11 +32,14 @@ public:
void wr_unlock() { pthread_mutex_unlock(&lock); } void wr_unlock() { pthread_mutex_unlock(&lock); }
bool wr_lock_try() { return !pthread_mutex_trylock(&lock); } bool wr_lock_try() { return !pthread_mutex_trylock(&lock); }
}; };
typedef srw_mutex srw_spin_mutex;
#else #else
/** Futex-based mutex */ /** Futex-based mutex */
class srw_mutex final template<bool spinloop>
class srw_mutex_impl final
{ {
/** The lock word, containing HOLDER and a count of waiters */ /** The lock word, containing HOLDER + 1 if the lock is being held,
plus the number of waiters */
std::atomic<uint32_t> lock; std::atomic<uint32_t> lock;
/** Identifies that the lock is being held */ /** Identifies that the lock is being held */
static constexpr uint32_t HOLDER= 1U << 31; static constexpr uint32_t HOLDER= 1U << 31;
@@ -62,7 +65,7 @@ public:
bool wr_lock_try() bool wr_lock_try()
{ {
uint32_t lk= 0; uint32_t lk= 0;
return lock.compare_exchange_strong(lk, HOLDER, return lock.compare_exchange_strong(lk, HOLDER + 1,
std::memory_order_acquire, std::memory_order_acquire,
std::memory_order_relaxed); std::memory_order_relaxed);
} }
@@ -70,18 +73,27 @@ public:
void wr_lock() { if (!wr_lock_try()) wait_and_lock(); } void wr_lock() { if (!wr_lock_try()) wait_and_lock(); }
void wr_unlock() void wr_unlock()
{ {
const uint32_t lk= lock.fetch_and(~HOLDER, std::memory_order_release); const uint32_t lk= lock.fetch_sub(HOLDER + 1, std::memory_order_release);
if (lk != HOLDER) if (lk != HOLDER + 1)
{ {
DBUG_ASSERT(lk & HOLDER); DBUG_ASSERT(lk & HOLDER);
wake(); wake();
} }
} }
}; };
typedef srw_mutex_impl<true> srw_spin_mutex;
typedef srw_mutex_impl<false> srw_mutex;
#endif
# if defined _WIN32 || defined SUX_LOCK_GENERIC
# else
template<bool spinlock> class srw_lock_impl;
#endif #endif
/** Slim shared-update-exclusive lock with no recursion */ /** Slim shared-update-exclusive lock with no recursion */
class ssux_lock_low final template<bool spinloop>
class ssux_lock_impl final
#ifdef SUX_LOCK_GENERIC #ifdef SUX_LOCK_GENERIC
: private rw_lock : private rw_lock
#endif #endif
@@ -91,7 +103,7 @@ class ssux_lock_low final
# ifdef SUX_LOCK_GENERIC # ifdef SUX_LOCK_GENERIC
# elif defined _WIN32 # elif defined _WIN32
# else # else
friend class srw_lock; friend srw_lock_impl<spinloop>;
# endif # endif
#endif #endif
#ifdef SUX_LOCK_GENERIC #ifdef SUX_LOCK_GENERIC
@@ -258,7 +270,7 @@ public:
class srw_lock_low class srw_lock_low
{ {
# ifdef UNIV_PFS_RWLOCK # ifdef UNIV_PFS_RWLOCK
friend class srw_lock; friend class srw_lock_impl;
# endif # endif
SRWLOCK lock; SRWLOCK lock;
public: public:
@@ -271,12 +283,14 @@ public:
bool wr_lock_try() { return TryAcquireSRWLockExclusive(&lock); } bool wr_lock_try() { return TryAcquireSRWLockExclusive(&lock); }
void wr_unlock() { ReleaseSRWLockExclusive(&lock); } void wr_unlock() { ReleaseSRWLockExclusive(&lock); }
}; };
typedef srw_lock_low srw_spin_lock_low;
#elif defined SUX_LOCK_GENERIC #elif defined SUX_LOCK_GENERIC
/** Slim read-write lock */ /** Slim read-write lock */
class srw_lock_low class srw_lock_low
{ {
# ifdef UNIV_PFS_RWLOCK # ifdef UNIV_PFS_RWLOCK
friend class srw_lock; friend class srw_lock_impl;
# endif # endif
rw_lock_t lock; rw_lock_t lock;
public: public:
@@ -289,8 +303,10 @@ public:
bool wr_lock_try() { return !rw_trywrlock(&lock); } bool wr_lock_try() { return !rw_trywrlock(&lock); }
void wr_unlock() { rw_unlock(&lock); } void wr_unlock() { rw_unlock(&lock); }
}; };
typedef srw_lock_low srw_spin_lock_low;
#else #else
typedef ssux_lock_low srw_lock_low; typedef ssux_lock_impl<false> srw_lock_low;
typedef ssux_lock_impl<true> srw_spin_lock_low;
#endif #endif
#ifndef UNIV_PFS_RWLOCK #ifndef UNIV_PFS_RWLOCK
@@ -298,7 +314,7 @@ typedef ssux_lock_low srw_lock_low;
# define SRW_LOCK_ARGS(file, line) /* nothing */ # define SRW_LOCK_ARGS(file, line) /* nothing */
# define SRW_LOCK_CALL /* nothing */ # define SRW_LOCK_CALL /* nothing */
typedef srw_lock_low srw_lock; typedef srw_lock_low srw_lock;
typedef ssux_lock_low ssux_lock; typedef srw_spin_lock_low srw_spin_lock;
#else #else
# define SRW_LOCK_INIT(key) init(key) # define SRW_LOCK_INIT(key) init(key)
# define SRW_LOCK_ARGS(file, line) file, line # define SRW_LOCK_ARGS(file, line) file, line
@@ -308,7 +324,7 @@ typedef ssux_lock_low ssux_lock;
class ssux_lock class ssux_lock
{ {
PSI_rwlock *pfs_psi; PSI_rwlock *pfs_psi;
ssux_lock_low lock; ssux_lock_impl<false> lock;
ATTRIBUTE_NOINLINE void psi_rd_lock(const char *file, unsigned line); ATTRIBUTE_NOINLINE void psi_rd_lock(const char *file, unsigned line);
ATTRIBUTE_NOINLINE void psi_wr_lock(const char *file, unsigned line); ATTRIBUTE_NOINLINE void psi_wr_lock(const char *file, unsigned line);
@@ -382,10 +398,18 @@ public:
}; };
/** Slim reader-writer lock with PERFORMANCE_SCHEMA instrumentation */ /** Slim reader-writer lock with PERFORMANCE_SCHEMA instrumentation */
class srw_lock # if defined _WIN32 || defined SUX_LOCK_GENERIC
# else
template<bool spinlock>
# endif
class srw_lock_impl
{ {
PSI_rwlock *pfs_psi; PSI_rwlock *pfs_psi;
# if defined _WIN32 || defined SUX_LOCK_GENERIC
srw_lock_low lock; srw_lock_low lock;
# else
ssux_lock_impl<spinlock> lock;
# endif
ATTRIBUTE_NOINLINE void psi_rd_lock(const char *file, unsigned line); ATTRIBUTE_NOINLINE void psi_rd_lock(const char *file, unsigned line);
ATTRIBUTE_NOINLINE void psi_wr_lock(const char *file, unsigned line); ATTRIBUTE_NOINLINE void psi_wr_lock(const char *file, unsigned line);
@@ -433,4 +457,13 @@ public:
bool rd_lock_try() { return lock.rd_lock_try(); } bool rd_lock_try() { return lock.rd_lock_try(); }
bool wr_lock_try() { return lock.wr_lock_try(); } bool wr_lock_try() { return lock.wr_lock_try(); }
}; };
# if defined _WIN32 || defined SUX_LOCK_GENERIC
typedef srw_lock_impl srw_lock;
typedef srw_lock_impl srw_spin_lock;
# else
typedef srw_lock_impl<false> srw_lock;
typedef srw_lock_impl<true> srw_spin_lock;
# endif
#endif #endif

View File

@@ -27,12 +27,12 @@ this program; if not, write to the Free Software Foundation, Inc.,
/** A "fat" rw-lock that supports /** A "fat" rw-lock that supports
S (shared), U (update, or shared-exclusive), and X (exclusive) modes S (shared), U (update, or shared-exclusive), and X (exclusive) modes
as well as recursive U and X latch acquisition as well as recursive U and X latch acquisition
@tparam srw ssux_lock_low or ssux_lock */ @tparam ssux ssux_lock_impl or ssux_lock */
template<typename srw> template<typename ssux>
class sux_lock final class sux_lock final
{ {
/** The underlying non-recursive lock */ /** The underlying non-recursive lock */
srw lock; ssux lock;
/** Numbers of U and X locks. Protected by lock. */ /** Numbers of U and X locks. Protected by lock. */
uint32_t recursive; uint32_t recursive;
/** The owner of the U or X lock (0 if none); protected by lock */ /** The owner of the U or X lock (0 if none); protected by lock */
@@ -270,20 +270,14 @@ public:
bool is_waiting() const { return lock.is_waiting(); } bool is_waiting() const { return lock.is_waiting(); }
}; };
/** needed for dict_index_t::clone() */ typedef sux_lock<ssux_lock_impl<true>> block_lock;
template<> inline void sux_lock<ssux_lock>::operator=(const sux_lock&)
{
memset((void*) this, 0, sizeof *this);
}
typedef sux_lock<ssux_lock_low> block_lock;
#ifndef UNIV_PFS_RWLOCK #ifndef UNIV_PFS_RWLOCK
typedef block_lock index_lock; typedef sux_lock<ssux_lock_impl<false>> index_lock;
#else #else
typedef sux_lock<ssux_lock> index_lock; typedef sux_lock<ssux_lock> index_lock;
template<> inline void sux_lock<ssux_lock_low>::init() template<> inline void sux_lock<ssux_lock_impl<true>>::init()
{ {
lock.init(); lock.init();
ut_ad(!writer.load(std::memory_order_relaxed)); ut_ad(!writer.load(std::memory_order_relaxed));
@@ -340,8 +334,13 @@ inline void sux_lock<ssux_lock>::u_x_upgrade(const char *file, unsigned line)
} }
#endif #endif
template<> /** needed for dict_index_t::clone() */
inline void sux_lock<ssux_lock_low>::s_lock() template<> inline void index_lock::operator=(const sux_lock&)
{
memset((void*) this, 0, sizeof *this);
}
template<typename ssux> inline void sux_lock<ssux>::s_lock()
{ {
ut_ad(!have_x()); ut_ad(!have_x());
ut_ad(!have_s()); ut_ad(!have_s());
@@ -349,8 +348,7 @@ inline void sux_lock<ssux_lock_low>::s_lock()
ut_d(s_lock_register()); ut_d(s_lock_register());
} }
template<> template<typename ssux> inline void sux_lock<ssux>::u_lock()
inline void sux_lock<ssux_lock_low>::u_lock()
{ {
os_thread_id_t id= os_thread_get_curr_id(); os_thread_id_t id= os_thread_get_curr_id();
if (writer.load(std::memory_order_relaxed) == id) if (writer.load(std::memory_order_relaxed) == id)
@@ -364,8 +362,7 @@ inline void sux_lock<ssux_lock_low>::u_lock()
} }
} }
template<> template<typename ssux> inline void sux_lock<ssux>::x_lock(bool for_io)
inline void sux_lock<ssux_lock_low>::x_lock(bool for_io)
{ {
os_thread_id_t id= os_thread_get_curr_id(); os_thread_id_t id= os_thread_get_curr_id();
if (writer.load(std::memory_order_relaxed) == id) if (writer.load(std::memory_order_relaxed) == id)
@@ -382,15 +379,14 @@ inline void sux_lock<ssux_lock_low>::x_lock(bool for_io)
} }
} }
template<> template<typename ssux> inline void sux_lock<ssux>::u_x_upgrade()
inline void sux_lock<ssux_lock_low>::u_x_upgrade()
{ {
ut_ad(have_u_not_x()); ut_ad(have_u_not_x());
lock.u_wr_upgrade(); lock.u_wr_upgrade();
recursive/= RECURSIVE_U; recursive/= RECURSIVE_U;
} }
template<> inline bool sux_lock<ssux_lock_low>::x_lock_upgraded() template<typename ssux> inline bool sux_lock<ssux>::x_lock_upgraded()
{ {
os_thread_id_t id= os_thread_get_curr_id(); os_thread_id_t id= os_thread_get_curr_id();
if (writer.load(std::memory_order_relaxed) == id) if (writer.load(std::memory_order_relaxed) == id)
@@ -417,8 +413,7 @@ template<> inline bool sux_lock<ssux_lock_low>::x_lock_upgraded()
} }
} }
template<> template<typename ssux> inline bool sux_lock<ssux>::u_lock_try(bool for_io)
inline bool sux_lock<ssux_lock_low>::u_lock_try(bool for_io)
{ {
os_thread_id_t id= os_thread_get_curr_id(); os_thread_id_t id= os_thread_get_curr_id();
if (writer.load(std::memory_order_relaxed) == id) if (writer.load(std::memory_order_relaxed) == id)
@@ -438,8 +433,7 @@ inline bool sux_lock<ssux_lock_low>::u_lock_try(bool for_io)
return false; return false;
} }
template<> template<typename ssux> inline bool sux_lock<ssux>::x_lock_try()
inline bool sux_lock<ssux_lock_low>::x_lock_try()
{ {
os_thread_id_t id= os_thread_get_curr_id(); os_thread_id_t id= os_thread_get_curr_id();
if (writer.load(std::memory_order_relaxed) == id) if (writer.load(std::memory_order_relaxed) == id)

View File

@@ -125,7 +125,7 @@ class purge_sys_t
{ {
public: public:
/** latch protecting view, m_enabled */ /** latch protecting view, m_enabled */
MY_ALIGNED(CACHE_LINE_SIZE) mutable srw_lock latch; MY_ALIGNED(CACHE_LINE_SIZE) mutable srw_spin_lock latch;
private: private:
/** The purge will not remove undo logs which are >= this view */ /** The purge will not remove undo logs which are >= this view */
ReadViewBase view; ReadViewBase view;

View File

@@ -72,7 +72,7 @@ struct MY_ALIGNED(CPU_LEVEL1_DCACHE_LINESIZE) trx_rseg_t
/** tablespace containing the rollback segment; constant after init() */ /** tablespace containing the rollback segment; constant after init() */
fil_space_t *space; fil_space_t *space;
/** latch protecting everything except page_no, space */ /** latch protecting everything except page_no, space */
srw_lock_low latch; srw_spin_lock_low latch;
/** rollback segment header page number; constant after init() */ /** rollback segment header page number; constant after init() */
uint32_t page_no; uint32_t page_no;
/** length of the TRX_RSEG_HISTORY list (number of transactions) */ /** length of the TRX_RSEG_HISTORY list (number of transactions) */

View File

@@ -565,7 +565,7 @@ public:
private: private:
/** mutex protecting state and some of lock /** mutex protecting state and some of lock
(some are protected by lock_sys.latch) */ (some are protected by lock_sys.latch) */
srw_mutex mutex; srw_spin_mutex mutex;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
/** The owner of mutex (0 if none); protected by mutex */ /** The owner of mutex (0 if none); protected by mutex */
std::atomic<os_thread_id_t> mutex_owner{0}; std::atomic<os_thread_id_t> mutex_owner{0};

View File

@@ -2501,6 +2501,13 @@ extern "C" int thd_is_slave(const MYSQL_THD thd);
# define thd_is_slave(thd) 0 # define thd_is_slave(thd) 0
#endif #endif
#if defined __aarch64__&&defined __GNUC__&&__GNUC__==4&&!defined __clang__
/* Avoid GCC 4.8.5 internal compiler error due to srw_mutex::wr_unlock().
We would only need this for row_ins_clust_index_entry_low(),
but GCC 4.8.5 does not support pop_options. */
# pragma GCC optimize ("no-expensive-optimizations")
#endif
/***************************************************************//** /***************************************************************//**
Tries to insert an entry into a clustered index, ignoring foreign key Tries to insert an entry into a clustered index, ignoring foreign key
constraints. If a record with the same unique key is found, the other constraints. If a record with the same unique key is found, the other

View File

@@ -1038,6 +1038,12 @@ try_again:
goto err_exit; goto err_exit;
} }
/* FIXME: We are acquiring exclusive dict_sys.latch only to
avoid increased wait times in
trx_purge_get_next_rec() and trx_purge_truncate_history(). */
dict_sys.lock(SRW_LOCK_CALL);
dict_sys.unlock();
already_locked: already_locked:
ut_ad(!node->table->is_temporary()); ut_ad(!node->table->is_temporary());

View File

@@ -3930,7 +3930,7 @@ row_sel_try_search_shortcut_for_mysql(
ut_ad(!prebuilt->templ_contains_blob); ut_ad(!prebuilt->templ_contains_blob);
ut_ad(trx->read_view.is_open()); ut_ad(trx->read_view.is_open());
srw_lock* ahi_latch = btr_search_sys.get_latch(*index); srw_spin_lock* ahi_latch = btr_search_sys.get_latch(*index);
ahi_latch->rd_lock(SRW_LOCK_CALL); ahi_latch->rd_lock(SRW_LOCK_CALL);
btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE, btr_pcur_open_with_no_init(index, search_tuple, PAGE_CUR_GE,
BTR_SEARCH_LEAF, pcur, ahi_latch, mtr); BTR_SEARCH_LEAF, pcur, ahi_latch, mtr);

View File

@@ -20,8 +20,24 @@ this program; if not, write to the Free Software Foundation, Inc.,
#include "srv0srv.h" #include "srv0srv.h"
#include "my_cpu.h" #include "my_cpu.h"
/** @return the parameter for srw_pause() */
static inline unsigned srw_pause_delay()
{
return my_cpu_relax_multiplier / 4 * srv_spin_wait_delay;
}
/** Pause the CPU for some time, with no memory accesses. */
static inline void srw_pause(unsigned delay)
{
HMT_low();
while (delay--)
MY_RELAX_CPU();
HMT_medium();
}
#ifdef SUX_LOCK_GENERIC #ifdef SUX_LOCK_GENERIC
void ssux_lock_low::init() template<bool spinloop>
void ssux_lock_impl<spinloop>::init()
{ {
DBUG_ASSERT(!is_locked_or_waiting()); DBUG_ASSERT(!is_locked_or_waiting());
pthread_mutex_init(&mutex, nullptr); pthread_mutex_init(&mutex, nullptr);
@@ -29,7 +45,8 @@ void ssux_lock_low::init()
pthread_cond_init(&cond_exclusive, nullptr); pthread_cond_init(&cond_exclusive, nullptr);
} }
void ssux_lock_low::destroy() template<bool spinloop>
void ssux_lock_impl<spinloop>::destroy()
{ {
DBUG_ASSERT(!is_locked_or_waiting()); DBUG_ASSERT(!is_locked_or_waiting());
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
@@ -37,7 +54,8 @@ void ssux_lock_low::destroy()
pthread_cond_destroy(&cond_exclusive); pthread_cond_destroy(&cond_exclusive);
} }
inline void ssux_lock_low::writer_wait(uint32_t l) template<bool spinloop>
inline void ssux_lock_impl<spinloop>::writer_wait(uint32_t l)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
while (value() == l) while (value() == l)
@@ -45,7 +63,8 @@ inline void ssux_lock_low::writer_wait(uint32_t l)
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
} }
inline void ssux_lock_low::readers_wait(uint32_t l) template<bool spinloop>
inline void ssux_lock_impl<spinloop>::readers_wait(uint32_t l)
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
while (value() == l) while (value() == l)
@@ -53,7 +72,8 @@ inline void ssux_lock_low::readers_wait(uint32_t l)
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
} }
inline void ssux_lock_low::wake() template<bool spinloop>
inline void ssux_lock_impl<spinloop>::wake()
{ {
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
uint32_t l= value(); uint32_t l= value();
@@ -70,7 +90,8 @@ inline void ssux_lock_low::wake()
/** Wait for a read lock. /** Wait for a read lock.
@param lock word value from a failed read_trylock() */ @param lock word value from a failed read_trylock() */
void ssux_lock_low::read_lock(uint32_t l) template<bool spinloop>
void ssux_lock_impl<spinloop>::read_lock(uint32_t l)
{ {
do do
{ {
@@ -90,15 +111,19 @@ void ssux_lock_low::read_lock(uint32_t l)
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
continue; continue;
} }
else else if (spinloop)
{
const unsigned delay= srw_pause_delay();
for (auto spin= srv_n_spin_wait_rounds; spin; spin--) for (auto spin= srv_n_spin_wait_rounds; spin; spin--)
{ {
ut_delay(srv_spin_wait_delay); srw_pause(delay);
if (read_trylock<true>(l)) if (read_trylock<true>(l))
return; return;
else if (l == WRITER_WAITING) else if (l == WRITER_WAITING)
goto wake_writer; goto wake_writer;
} }
}
readers_wait(l); readers_wait(l);
} }
@@ -107,7 +132,8 @@ void ssux_lock_low::read_lock(uint32_t l)
/** Wait for an update lock. /** Wait for an update lock.
@param lock word value from a failed update_trylock() */ @param lock word value from a failed update_trylock() */
void ssux_lock_low::update_lock(uint32_t l) template<bool spinloop>
void ssux_lock_impl<spinloop>::update_lock(uint32_t l)
{ {
do do
{ {
@@ -127,15 +153,19 @@ void ssux_lock_low::update_lock(uint32_t l)
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
continue; continue;
} }
else else if (spinloop)
{
const unsigned delay= srw_pause_delay();
for (auto spin= srv_n_spin_wait_rounds; spin; spin--) for (auto spin= srv_n_spin_wait_rounds; spin; spin--)
{ {
ut_delay(srv_spin_wait_delay); srw_pause(delay);
if (update_trylock(l)) if (update_trylock(l))
return; return;
else if ((l | UPDATER) == (UPDATER | WRITER_WAITING)) else if ((l | UPDATER) == (UPDATER | WRITER_WAITING))
goto wake_writer; goto wake_writer;
} }
}
readers_wait(l); readers_wait(l);
} }
@@ -144,21 +174,12 @@ void ssux_lock_low::update_lock(uint32_t l)
/** Wait for a write lock after a failed write_trylock() or upgrade_trylock() /** Wait for a write lock after a failed write_trylock() or upgrade_trylock()
@param holding_u whether we already hold u_lock() */ @param holding_u whether we already hold u_lock() */
void ssux_lock_low::write_lock(bool holding_u) template<bool spinloop>
void ssux_lock_impl<spinloop>::write_lock(bool holding_u)
{ {
for (;;) for (;;)
{ {
uint32_t l= write_lock_wait_start(); uint32_t l= write_lock_wait_start();
/* We are the first writer to be granted the lock. Spin for a while. */
for (auto spin= srv_n_spin_wait_rounds; spin; spin--)
{
l= holding_u ? WRITER_WAITING | UPDATER : WRITER_WAITING;
if (write_lock_wait_try(l))
return;
if (!(l & WRITER_WAITING))
l= write_lock_wait_start();
ut_delay(srv_spin_wait_delay);
}
const uint32_t e= holding_u ? WRITER_WAITING | UPDATER : WRITER_WAITING; const uint32_t e= holding_u ? WRITER_WAITING | UPDATER : WRITER_WAITING;
l= e; l= e;
@@ -190,21 +211,34 @@ void ssux_lock_low::write_lock(bool holding_u)
} }
} }
void ssux_lock_low::rd_unlock() { if (read_unlock()) wake(); } template<bool spinloop>
void ssux_lock_low::u_unlock() { update_unlock(); wake(); } void ssux_lock_impl<spinloop>::rd_unlock() { if (read_unlock()) wake(); }
void ssux_lock_low::wr_unlock() { write_unlock(); wake(); } template<bool spinloop>
void ssux_lock_impl<spinloop>::u_unlock() { update_unlock(); wake(); }
template<bool spinloop>
void ssux_lock_impl<spinloop>::wr_unlock() { write_unlock(); wake(); }
template void ssux_lock_impl<false>::init();
template void ssux_lock_impl<false>::destroy();
template void ssux_lock_impl<false>::rd_unlock();
template void ssux_lock_impl<false>::u_unlock();
template void ssux_lock_impl<false>::wr_unlock();
#else /* SUX_LOCK_GENERIC */ #else /* SUX_LOCK_GENERIC */
static_assert(4 == sizeof(rw_lock), "ABI"); static_assert(4 == sizeof(rw_lock), "ABI");
# ifdef _WIN32 # ifdef _WIN32
# include <synchapi.h> # include <synchapi.h>
inline void srw_mutex::wait(uint32_t lk) template<bool spinloop>
inline void srw_mutex_impl<spinloop>::wait(uint32_t lk)
{ WaitOnAddress(&lock, &lk, 4, INFINITE); } { WaitOnAddress(&lock, &lk, 4, INFINITE); }
void srw_mutex::wake() { WakeByAddressSingle(&lock); } template<bool spinloop>
void srw_mutex_impl<spinloop>::wake() { WakeByAddressSingle(&lock); }
inline void ssux_lock_low::wait(uint32_t lk) template<bool spinloop>
inline void ssux_lock_impl<spinloop>::wait(uint32_t lk)
{ WaitOnAddress(&readers, &lk, 4, INFINITE); } { WaitOnAddress(&readers, &lk, 4, INFINITE); }
void ssux_lock_low::wake() { WakeByAddressSingle(&readers); } template<bool spinloop>
void ssux_lock_impl<spinloop>::wake() { WakeByAddressSingle(&readers); }
# else # else
# ifdef __linux__ # ifdef __linux__
@@ -221,49 +255,93 @@ void ssux_lock_low::wake() { WakeByAddressSingle(&readers); }
# error "no futex support" # error "no futex support"
# endif # endif
inline void srw_mutex::wait(uint32_t lk) { SRW_FUTEX(&lock, WAIT, lk); } template<bool spinloop>
void srw_mutex::wake() { SRW_FUTEX(&lock, WAKE, 1); } inline void srw_mutex_impl<spinloop>::wait(uint32_t lk)
{ SRW_FUTEX(&lock, WAIT, lk); }
template<bool spinloop>
void srw_mutex_impl<spinloop>::wake() { SRW_FUTEX(&lock, WAKE, 1); }
inline void ssux_lock_low::wait(uint32_t lk) { SRW_FUTEX(&readers, WAIT, lk); } template<bool spinloop>
void ssux_lock_low::wake() { SRW_FUTEX(&readers, WAKE, 1); } inline void ssux_lock_impl<spinloop>::wait(uint32_t lk)
{ SRW_FUTEX(&readers, WAIT, lk); }
template<bool spinloop>
void ssux_lock_impl<spinloop>::wake() { SRW_FUTEX(&readers, WAKE, 1); }
# endif # endif
template void srw_mutex_impl<false>::wake();
template void ssux_lock_impl<false>::wake();
template void srw_mutex_impl<true>::wake();
template void ssux_lock_impl<true>::wake();
void srw_mutex::wait_and_lock() template<>
void srw_mutex_impl<true>::wait_and_lock()
{ {
uint32_t lk= 1 + lock.fetch_add(1, std::memory_order_relaxed); uint32_t lk= 1 + lock.fetch_add(1, std::memory_order_relaxed);
for (auto spin= srv_n_spin_wait_rounds; spin; spin--)
const unsigned delay= srw_pause_delay();
for (auto spin= srv_n_spin_wait_rounds;;)
{ {
lk&= ~HOLDER; DBUG_ASSERT(~HOLDER & lk);
DBUG_ASSERT(lk); if (lk & HOLDER)
while (!lock.compare_exchange_weak(lk, HOLDER | (lk - 1), lk= lock.load(std::memory_order_relaxed);
std::memory_order_acquire, else
std::memory_order_relaxed)) {
if (lk & HOLDER) lk= lock.fetch_or(HOLDER, std::memory_order_relaxed);
goto occupied; if (!(lk & HOLDER))
return; goto acquired;
occupied: }
ut_delay(srv_spin_wait_delay); srw_pause(delay);
if (!--spin)
break;
} }
for (;;) for (;; wait(lk))
{ {
lk= lock.load(std::memory_order_relaxed); if (lk & HOLDER)
while (!(lk & HOLDER))
{ {
lk= lock.load(std::memory_order_relaxed);
if (lk & HOLDER)
continue;
}
lk= lock.fetch_or(HOLDER, std::memory_order_relaxed);
if (!(lk & HOLDER))
{
acquired:
DBUG_ASSERT(lk); DBUG_ASSERT(lk);
if (lock.compare_exchange_weak(lk, HOLDER | (lk - 1), std::atomic_thread_fence(std::memory_order_acquire);
std::memory_order_acquire, return;
std::memory_order_relaxed))
return;
} }
DBUG_ASSERT(lk > HOLDER); DBUG_ASSERT(lk > HOLDER);
wait(lk);
} }
} }
void ssux_lock_low::wr_wait(uint32_t lk) template<>
void srw_mutex_impl<false>::wait_and_lock()
{
uint32_t lk= 1 + lock.fetch_add(1, std::memory_order_relaxed);
for (;; wait(lk))
{
if (lk & HOLDER)
{
lk= lock.load(std::memory_order_relaxed);
if (lk & HOLDER)
continue;
}
lk= lock.fetch_or(HOLDER, std::memory_order_relaxed);
if (!(lk & HOLDER))
{
DBUG_ASSERT(lk);
std::atomic_thread_fence(std::memory_order_acquire);
return;
}
DBUG_ASSERT(lk > HOLDER);
}
}
template<bool spinloop>
void ssux_lock_impl<spinloop>::wr_wait(uint32_t lk)
{ {
DBUG_ASSERT(writer.is_locked()); DBUG_ASSERT(writer.is_locked());
DBUG_ASSERT(lk); DBUG_ASSERT(lk);
@@ -278,7 +356,11 @@ void ssux_lock_low::wr_wait(uint32_t lk)
while (lk != WRITER); while (lk != WRITER);
} }
void ssux_lock_low::rd_wait() template void ssux_lock_impl<true>::wr_wait(uint32_t);
template void ssux_lock_impl<false>::wr_wait(uint32_t);
template<bool spinloop>
void ssux_lock_impl<spinloop>::rd_wait()
{ {
for (;;) for (;;)
{ {
@@ -297,10 +379,22 @@ void ssux_lock_low::rd_wait()
} }
writer.wr_unlock(); writer.wr_unlock();
} }
template void ssux_lock_impl<true>::rd_wait();
template void ssux_lock_impl<false>::rd_wait();
#endif /* SUX_LOCK_GENERIC */ #endif /* SUX_LOCK_GENERIC */
#ifdef UNIV_PFS_RWLOCK #ifdef UNIV_PFS_RWLOCK
void srw_lock::psi_rd_lock(const char *file, unsigned line) # if defined _WIN32 || defined SUX_LOCK_GENERIC
# define void_srw_lock void srw_lock_impl
# else
# define void_srw_lock template<bool spinloop> void srw_lock_impl<spinloop>
template void srw_lock_impl<false>::psi_rd_lock(const char*, unsigned);
template void srw_lock_impl<false>::psi_wr_lock(const char*, unsigned);
template void srw_lock_impl<true>::psi_rd_lock(const char*, unsigned);
template void srw_lock_impl<true>::psi_wr_lock(const char*, unsigned);
# endif
void_srw_lock::psi_rd_lock(const char *file, unsigned line)
{ {
PSI_rwlock_locker_state state; PSI_rwlock_locker_state state;
const bool nowait= lock.rd_lock_try(); const bool nowait= lock.rd_lock_try();
@@ -316,7 +410,7 @@ void srw_lock::psi_rd_lock(const char *file, unsigned line)
lock.rd_lock(); lock.rd_lock();
} }
void srw_lock::psi_wr_lock(const char *file, unsigned line) void_srw_lock::psi_wr_lock(const char *file, unsigned line)
{ {
PSI_rwlock_locker_state state; PSI_rwlock_locker_state state;
const bool nowait= lock.wr_lock_try(); const bool nowait= lock.wr_lock_try();
@@ -396,7 +490,7 @@ void ssux_lock::psi_u_wr_upgrade(const char *file, unsigned line)
DBUG_ASSERT(lock.writer.is_locked()); DBUG_ASSERT(lock.writer.is_locked());
uint32_t lk= 1; uint32_t lk= 1;
const bool nowait= const bool nowait=
lock.readers.compare_exchange_strong(lk, ssux_lock_low::WRITER, lock.readers.compare_exchange_strong(lk, ssux_lock_impl<false>::WRITER,
std::memory_order_acquire, std::memory_order_acquire,
std::memory_order_relaxed); std::memory_order_relaxed);
if (PSI_rwlock_locker *locker= PSI_RWLOCK_CALL(start_rwlock_wrwait) if (PSI_rwlock_locker *locker= PSI_RWLOCK_CALL(start_rwlock_wrwait)
@@ -412,4 +506,14 @@ void ssux_lock::psi_u_wr_upgrade(const char *file, unsigned line)
else if (!nowait) else if (!nowait)
lock.u_wr_upgrade(); lock.u_wr_upgrade();
} }
#else /* UNIV_PFS_RWLOCK */
template void ssux_lock_impl<false>::rd_lock();
# ifdef SUX_LOCK_GENERIC
template void ssux_lock_impl<false>::write_lock(bool);
template void ssux_lock_impl<false>::update_lock(uint32_t);
# else
template void ssux_lock_impl<false>::rd_unlock();
template void ssux_lock_impl<false>::u_unlock();
template void ssux_lock_impl<false>::wr_unlock();
# endif
#endif /* UNIV_PFS_RWLOCK */ #endif /* UNIV_PFS_RWLOCK */

View File

@@ -1275,7 +1275,7 @@ inline void trx_t::commit_in_memory(const mtr_t *mtr)
/* Wait for any implicit-to-explicit lock conversions to cease, /* Wait for any implicit-to-explicit lock conversions to cease,
so that there will be no race condition in lock_release(). */ so that there will be no race condition in lock_release(). */
while (UNIV_UNLIKELY(is_referenced())) while (UNIV_UNLIKELY(is_referenced()))
ut_delay(srv_spin_wait_delay); LF_BACKOFF();
} }
else else
ut_ad(read_only || !rsegs.m_redo.rseg); ut_ad(read_only || !rsegs.m_redo.rseg);

View File

@@ -62,7 +62,7 @@ static void test_srw_lock()
} }
} }
static ssux_lock_low ssux; static ssux_lock_impl<false> ssux;
static void test_ssux_lock() static void test_ssux_lock()
{ {
@@ -95,7 +95,7 @@ static void test_ssux_lock()
} }
} }
static sux_lock<ssux_lock_low> sux; static sux_lock<ssux_lock_impl<true>> sux;
static void test_sux_lock() static void test_sux_lock()
{ {

View File

@@ -40,8 +40,10 @@ static const char *opt_s3_host_name= DEFAULT_AWS_HOST_NAME;
static const char *opt_database; static const char *opt_database;
static const char *opt_s3_bucket="MariaDB"; static const char *opt_s3_bucket="MariaDB";
static my_bool opt_compression, opt_verbose, opt_force, opt_s3_debug; static my_bool opt_compression, opt_verbose, opt_force, opt_s3_debug;
static my_bool opt_s3_use_http;
static ulong opt_operation= OP_IMPOSSIBLE, opt_protocol_version= 1; static ulong opt_operation= OP_IMPOSSIBLE, opt_protocol_version= 1;
static ulong opt_block_size; static ulong opt_block_size;
static ulong opt_s3_port;
static char **default_argv=0; static char **default_argv=0;
static ms3_st *global_s3_client= 0; static ms3_st *global_s3_client= 0;
@@ -65,6 +67,12 @@ static struct my_option my_long_options[] =
{"s3_host_name", 'h', "Host name to S3 provider", {"s3_host_name", 'h', "Host name to S3 provider",
(char**) &opt_s3_host_name, (char**) &opt_s3_host_name, 0, (char**) &opt_s3_host_name, (char**) &opt_s3_host_name, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"s3_port", 'p', "Port number to connect to (0 means use default)",
(char**) &opt_s3_port, (char**) &opt_s3_port, 0, GET_ULONG, REQUIRED_ARG,
0, 0, 65536, 0, 1, 0 },
{"s3_use_http", 'P', "If true, force use of HTTP protocol",
(char**) &opt_s3_use_http, (char**) &opt_s3_use_http,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"compress", 'c', "Use compression", &opt_compression, &opt_compression, {"compress", 'c', "Use compression", &opt_compression, &opt_compression,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"op", 'o', "Operation to execute. One of 'from_s3', 'to_s3' or " {"op", 'o', "Operation to execute. One of 'from_s3', 'to_s3' or "
@@ -196,6 +204,7 @@ int main(int argc, char** argv)
{ {
MY_INIT(argv[0]); MY_INIT(argv[0]);
get_options(&argc,(char***) &argv); get_options(&argc,(char***) &argv);
size_t block_size= opt_block_size;
s3_init_library(); s3_init_library();
if (!(global_s3_client= ms3_init(opt_s3_access_key, if (!(global_s3_client= ms3_init(opt_s3_access_key,
@@ -207,15 +216,22 @@ int main(int argc, char** argv)
my_exit(1); my_exit(1);
} }
{ ms3_set_option(global_s3_client, MS3_OPT_BUFFER_CHUNK_SIZE, &block_size);
size_t block_size= opt_block_size;
uint8_t protocol_version= (uint8_t) opt_protocol_version;
ms3_set_option(global_s3_client, MS3_OPT_BUFFER_CHUNK_SIZE, &block_size);
if (protocol_version) if (opt_protocol_version)
ms3_set_option(global_s3_client, MS3_OPT_FORCE_PROTOCOL_VERSION, {
&protocol_version); uint8_t protocol_version= (uint8_t) opt_protocol_version;
ms3_set_option(global_s3_client, MS3_OPT_FORCE_PROTOCOL_VERSION,
&protocol_version);
} }
if (opt_s3_port)
{
int port= (int) opt_s3_port;
ms3_set_option(global_s3_client, MS3_OPT_PORT_NUMBER, &port);
}
if (opt_s3_use_http)
ms3_set_option(global_s3_client, MS3_OPT_USE_HTTP, NULL);
for (; *argv ; argv++) for (; *argv ; argv++)
{ {

View File

@@ -1278,6 +1278,7 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
if (!file || !param) return HA_ADMIN_INTERNAL_ERROR; if (!file || !param) return HA_ADMIN_INTERNAL_ERROR;
unmap_file(file); unmap_file(file);
register_handler(file);
maria_chk_init(param); maria_chk_init(param);
param->thd= thd; param->thd= thd;
param->op_name= "check"; param->op_name= "check";
@@ -1333,14 +1334,18 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt)
{ {
ulonglong old_testflag= param->testflag; ulonglong old_testflag= param->testflag;
param->testflag |= T_MEDIUM; param->testflag |= T_MEDIUM;
if (!(error= init_io_cache(&param->read_cache, file->dfile.file,
my_default_record_cache_size, READ_CACHE, /* BLOCK_RECORD does not need a cache as it is using the page cache */
share->pack.header_length, 1, MYF(MY_WME)))) if (file->s->data_file_type != BLOCK_RECORD)
{ error= init_io_cache(&param->read_cache, file->dfile.file,
my_default_record_cache_size, READ_CACHE,
share->pack.header_length, 1, MYF(MY_WME));
if (!error)
error= maria_chk_data_link(param, file, error= maria_chk_data_link(param, file,
MY_TEST(param->testflag & T_EXTEND)); MY_TEST(param->testflag & T_EXTEND));
if (file->s->data_file_type != BLOCK_RECORD)
end_io_cache(&param->read_cache); end_io_cache(&param->read_cache);
}
param->testflag= old_testflag; param->testflag= old_testflag;
} }
} }

View File

@@ -44,11 +44,6 @@ public:
DBUG_ENTER("delete_row"); DBUG_ENTER("delete_row");
DBUG_RETURN(HA_ERR_TABLE_READONLY); DBUG_RETURN(HA_ERR_TABLE_READONLY);
} }
int check(THD *, HA_CHECK_OPT *) override
{
DBUG_ENTER("delete_row");
DBUG_RETURN(HA_ERR_TABLE_READONLY);
}
int analyze(THD *, HA_CHECK_OPT *) override int analyze(THD *, HA_CHECK_OPT *) override
{ {
DBUG_ENTER("analyze"); DBUG_ENTER("analyze");

View File

@@ -414,6 +414,12 @@ int maria_chk_size(HA_CHECK *param, register MARIA_HA *info)
char buff[22],buff2[22]; char buff[22],buff2[22];
DBUG_ENTER("maria_chk_size"); DBUG_ENTER("maria_chk_size");
if (info->s3)
{
/* We cannot check file sizes for S3 */
DBUG_RETURN(0);
}
if (!(param->testflag & T_SILENT)) if (!(param->testflag & T_SILENT))
puts("- check file-size"); puts("- check file-size");

View File

@@ -2772,7 +2772,7 @@ retry:
#ifdef WITH_S3_STORAGE_ENGINE #ifdef WITH_S3_STORAGE_ENGINE
static void read_big_block(PAGECACHE *pagecache, static void read_big_block(PAGECACHE *pagecache,
PAGECACHE_BLOCK_LINK *block) PAGECACHE_BLOCK_LINK *block)
{ {
int page_st; int page_st;
size_t big_block_size_in_pages; size_t big_block_size_in_pages;
@@ -2810,6 +2810,11 @@ static void read_big_block(PAGECACHE *pagecache,
if (block_to_read->status & PCBLOCK_ERROR) if (block_to_read->status & PCBLOCK_ERROR)
{ {
/* We get first block with an error so all operation failed */ /* We get first block with an error so all operation failed */
DBUG_PRINT("error", ("Got error when reading first page"));
block->status|= PCBLOCK_ERROR;
block->error= block_to_read->error;
remove_reader(block_to_read);
unreg_request(pagecache, block_to_read, 1);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
if (block_to_read->status & PCBLOCK_BIG_READ) if (block_to_read->status & PCBLOCK_BIG_READ)
@@ -3952,7 +3957,6 @@ void pagecache_set_write_on_delete_by_link(PAGECACHE_BLOCK_LINK *block)
@retval 0 deleted or was not present at all @retval 0 deleted or was not present at all
@retval 1 error @retval 1 error
*/ */
static my_bool pagecache_delete_internal(PAGECACHE *pagecache, static my_bool pagecache_delete_internal(PAGECACHE *pagecache,

View File

@@ -583,8 +583,8 @@ int aria_copy_from_s3(ms3_st *s3_client, const char *aws_bucket,
if (s3_get_object(s3_client, aws_bucket, aws_path, &block, 0, 0)) if (s3_get_object(s3_client, aws_bucket, aws_path, &block, 0, 0))
{ {
my_printf_error(EE_FILENOTFOUND, "Table %s doesn't exist in s3", MYF(0), my_printf_error(EE_FILENOTFOUND, "File %s/%s doesn't exist in s3", MYF(0),
filename); database,filename);
goto err; goto err;
} }
if (block.length < MARIA_STATE_INFO_SIZE) if (block.length < MARIA_STATE_INFO_SIZE)

View File

@@ -73,7 +73,7 @@ IF(ORACLE_INCLUDE_DIR AND ORACLE_OCI_LIBRARY)
ENDIF() ENDIF()
ENDIF() ENDIF()
IF(MSVC) IF(MSVC AND (TARGET spider))
IF (CMAKE_BUILD_TYPE STREQUAL "Debug") IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
ADD_CUSTOM_COMMAND(TARGET spider ADD_CUSTOM_COMMAND(TARGET spider
POST_BUILD POST_BUILD

View File

@@ -0,0 +1,18 @@
for master_1
for child2
child2_1
child2_2
child2_3
for child3
MDEV-25684 Crash in THD::find_temporary_table while calling spider_direct_sql UDF without temporary table created
connection master_1;
SELECT SPIDER_DIRECT_SQL('SELECT * FROM s', 'non_existing_temporary_table', 'srv "s_2_1"');
ERROR HY000: Temporary table 'test.non_existing_temporary_table' is not found
for master_1
for child2
child2_1
child2_2
child2_3
for child3

View File

@@ -0,0 +1,3 @@
!include include/default_mysqld.cnf
!include ../my_1_1.cnf
!include ../my_2_1.cnf

View File

@@ -0,0 +1,19 @@
--disable_query_log
--disable_result_log
--source ../../t/test_init.inc
--enable_result_log
--enable_query_log
--echo
--echo MDEV-25684 Crash in THD::find_temporary_table while calling spider_direct_sql UDF without temporary table created
--echo
--connection master_1
--error 12703
SELECT SPIDER_DIRECT_SQL('SELECT * FROM s', 'non_existing_temporary_table', 'srv "s_2_1"');
--disable_query_log
--disable_result_log
--source ../../t/test_deinit.inc
--enable_result_log
--enable_query_log

View File

@@ -3934,6 +3934,10 @@ TABLE *spider_find_temporary_table(
) { ) {
DBUG_ENTER("spider_find_temporary_table"); DBUG_ENTER("spider_find_temporary_table");
#ifdef SPIDER_open_temporary_table #ifdef SPIDER_open_temporary_table
if (!thd->has_temporary_tables())
{
DBUG_RETURN(NULL);
}
if (thd->open_temporary_table(table_list)) if (thd->open_temporary_table(table_list))
{ {
DBUG_RETURN(NULL); DBUG_RETURN(NULL);

View File

@@ -19203,6 +19203,9 @@ static void test_bug11766854()
struct st_mysql_client_plugin *plugin; struct st_mysql_client_plugin *plugin;
DBUG_ENTER("test_bug11766854"); DBUG_ENTER("test_bug11766854");
if (!getenv("QA_AUTH_CLIENT_SO"))
DBUG_VOID_RETURN;
myheader("test_bug11766854"); myheader("test_bug11766854");
plugin= mysql_load_plugin(mysql, "foo", -1, 0); plugin= mysql_load_plugin(mysql, "foo", -1, 0);

View File

@@ -0,0 +1,14 @@
main.mysql_upgrade : Takes long time on Appveyor
main.mysqlslap : Takes long time
mysql.upgrade_view : Takes long time
main.check : Takes long time on Appveyor
main.mrr_icp_extra : Takes long time on Appveyor
main.derived_opt : Takes long time on Appveyor
main.trigger : Takes long time on Appveyor
main.index_merge_myisam : Takes long time on Appveyor
main.mysqldump : Takes long time on Appveyor
main.derived : Takes long time on Appveyor
main.multi_update : Takes long time on Appveyor
main.index_merge_innodb : Takes long time on Appveyor
main.count_distinct2 : Takes long time on Appveyor
main.mysqltest : Takes long time on Appveyor