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

Merge 10.9 into 10.10

This commit is contained in:
Marko Mäkelä
2023-03-17 06:59:46 +02:00
70 changed files with 1868 additions and 1524 deletions

View File

@@ -331,6 +331,7 @@ mysql-test-run-asan:
needs: needs:
- "fedora-sanitizer: [-DWITH_ASAN=YES]" - "fedora-sanitizer: [-DWITH_ASAN=YES]"
<<: *mysql-test-run-def <<: *mysql-test-run-def
allow_failure: true
artifacts: artifacts:
when: always # Also show results when tests fail when: always # Also show results when tests fail
reports: reports:
@@ -489,6 +490,8 @@ mini-benchmark:
stage: test stage: test
dependencies: dependencies:
- fedora - fedora
needs:
- fedora
script: script:
- ls -la rpm; rm -vf rpm/*.el?.* # Delete artifacts from Centos builds - ls -la rpm; rm -vf rpm/*.el?.* # Delete artifacts from Centos builds
# Don't use cracklib, otherwise the Sysbench user password will be rejected # Don't use cracklib, otherwise the Sysbench user password will be rejected
@@ -503,7 +506,7 @@ mini-benchmark:
- | - |
mariadb --skip-column-names -e "SELECT @@version, @@version_comment" | tee /tmp/version mariadb --skip-column-names -e "SELECT @@version, @@version_comment" | tee /tmp/version
grep $MARIADB_MAJOR_VERSION /tmp/version || echo "MariaDB didn't install properly" grep $MARIADB_MAJOR_VERSION /tmp/version || echo "MariaDB didn't install properly"
- yum install -y sysbench procps-ng perf || yum install -y https://kojipkgs.fedoraproject.org//packages/luajit/2.0.4/3.el7/x86_64/luajit-2.0.4-3.el7.x86_64.rpm https://kojipkgs.fedoraproject.org//packages/sysbench/1.0.17/2.el7/x86_64/sysbench-1.0.17-2.el7.x86_64.rpm https://kojipkgs.fedoraproject.org//packages/ck/0.5.2/2.el7/x86_64/ck-0.5.2-2.el7.x86_64.rpm - yum install -y sysbench procps-ng perf util-linux || yum install -y https://kojipkgs.fedoraproject.org//packages/luajit/2.0.4/3.el7/x86_64/luajit-2.0.4-3.el7.x86_64.rpm https://kojipkgs.fedoraproject.org//packages/sysbench/1.0.17/2.el7/x86_64/sysbench-1.0.17-2.el7.x86_64.rpm https://kojipkgs.fedoraproject.org//packages/ck/0.5.2/2.el7/x86_64/ck-0.5.2-2.el7.x86_64.rpm
- /usr/share/mysql/mini-benchmark - /usr/share/mysql/mini-benchmark
- cp -av */sysbench-run-*.log */metrics.txt .. # Move files one level down so they can be saved as artifacts - cp -av */sysbench-run-*.log */metrics.txt .. # Move files one level down so they can be saved as artifacts
artifacts: artifacts:

View File

@@ -15,6 +15,7 @@ usr/include/mariadb/mariadb_version.h
usr/include/mariadb/my_config.h usr/include/mariadb/my_config.h
usr/include/mariadb/my_global.h usr/include/mariadb/my_global.h
usr/include/mariadb/my_sys.h usr/include/mariadb/my_sys.h
usr/include/mariadb/my_alloca.h
usr/include/mariadb/mysql.h usr/include/mariadb/mysql.h
usr/include/mariadb/mysql/ usr/include/mariadb/mysql/
usr/include/mariadb/mysql/client_plugin.h usr/include/mariadb/mysql/client_plugin.h

View File

@@ -2280,8 +2280,14 @@ static bool innodb_init()
/* Check if the data files exist or not. */ /* Check if the data files exist or not. */
dberr_t err= srv_sys_space.check_file_spec(&create_new_db, 5U << 20); dberr_t err= srv_sys_space.check_file_spec(&create_new_db, 5U << 20);
if (create_new_db)
{
msg("mariadb-backup: InnoDB files do not exist");
return true;
}
if (err == DB_SUCCESS) if (err == DB_SUCCESS)
err= srv_start(create_new_db); err= srv_start(false);
if (err != DB_SUCCESS) if (err != DB_SUCCESS)
{ {
@@ -2292,6 +2298,7 @@ static bool innodb_init()
ut_ad(srv_force_recovery <= SRV_FORCE_IGNORE_CORRUPT); ut_ad(srv_force_recovery <= SRV_FORCE_IGNORE_CORRUPT);
ut_ad(recv_no_log_write); ut_ad(recv_no_log_write);
buf_flush_sync(); buf_flush_sync();
recv_sys.debug_free();
DBUG_ASSERT(!buf_pool.any_io_pending()); DBUG_ASSERT(!buf_pool.any_io_pending());
log_sys.close_file(); log_sys.close_file();
@@ -3473,7 +3480,9 @@ static void xb_load_single_table_tablespace(const char *dirname,
if (err == DB_SUCCESS && file->space_id() != SRV_TMP_SPACE_ID) { if (err == DB_SUCCESS && file->space_id() != SRV_TMP_SPACE_ID) {
space = fil_space_t::create( space = fil_space_t::create(
file->space_id(), file->flags(), file->space_id(), file->flags(),
FIL_TYPE_TABLESPACE, NULL/* TODO: crypt_data */); FIL_TYPE_TABLESPACE, nullptr/* TODO: crypt_data */,
FIL_ENCRYPTION_DEFAULT,
file->handle() != OS_FILE_CLOSED);
ut_a(space != NULL); ut_a(space != NULL);
fil_node_t* node= space->add( fil_node_t* node= space->add(
@@ -5279,7 +5288,8 @@ exit:
ut_ad(fil_space_t::physical_size(flags) == info.page_size); ut_ad(fil_space_t::physical_size(flags) == info.page_size);
if (fil_space_t::create(info.space_id, flags, if (fil_space_t::create(info.space_id, flags,
FIL_TYPE_TABLESPACE, 0)) { FIL_TYPE_TABLESPACE, 0, FIL_ENCRYPTION_DEFAULT,
true)) {
*success = xb_space_create_file(real_name, info.space_id, *success = xb_space_create_file(real_name, info.space_id,
flags, &file); flags, &file);
} else { } else {

View File

@@ -37,6 +37,7 @@ SET(HEADERS
ma_dyncol.h ma_dyncol.h
my_list.h my_list.h
my_alloc.h my_alloc.h
my_alloca.h
typelib.h typelib.h
my_dbug.h my_dbug.h
m_string.h m_string.h
@@ -111,7 +112,9 @@ ${footer}
ENDMACRO() ENDMACRO()
INSTALL_COMPAT_HEADER(my_global.h "") INSTALL_COMPAT_HEADER(my_global.h "")
INSTALL_COMPAT_HEADER(my_alloca.h "")
INSTALL_COMPAT_HEADER(my_config.h "") INSTALL_COMPAT_HEADER(my_config.h "")
INSTALL_COMPAT_HEADER(my_alloca.h "")
INSTALL_COMPAT_HEADER(my_sys.h "") INSTALL_COMPAT_HEADER(my_sys.h "")
INSTALL_COMPAT_HEADER(mysql_version.h " INSTALL_COMPAT_HEADER(mysql_version.h "
#include <mariadb_version.h> #include <mariadb_version.h>

45
include/my_alloca.h Normal file
View File

@@ -0,0 +1,45 @@
/* Copyright (c) 2023, MariaDB Corporation.
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 Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
#ifndef MY_ALLOCA_INCLUDED
#define MY_ALLOCA_INCLUDED
#ifdef _WIN32
#include <malloc.h> /*for alloca*/
/*
MSVC may define "alloca" when compiling in /Ze mode
(with extensions from Microsoft), but otherwise only
the _alloca function is defined:
*/
#ifndef alloca
#define alloca _alloca
#endif
#else
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#endif
#if defined(HAVE_ALLOCA)
/*
If the GCC/LLVM compiler from the MinGW is used,
alloca may not be defined when using the MSVC CRT:
*/
#if defined(__GNUC__) && !defined(HAVE_ALLOCA_H) && !defined(alloca)
#define alloca __builtin_alloca
#endif /* GNUC */
#endif
#endif /* MY_ALLOCA_INCLUDED */

View File

@@ -330,13 +330,6 @@ C_MODE_END
#ifdef HAVE_UNISTD_H #ifdef HAVE_UNISTD_H
#include <unistd.h> #include <unistd.h>
#endif #endif
#if defined(__cplusplus) && defined(NO_CPLUSPLUS_ALLOCA)
#undef HAVE_ALLOCA
#undef HAVE_ALLOCA_H
#endif
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#include <errno.h> /* Recommended by debian */ #include <errno.h> /* Recommended by debian */
/* We need the following to go around a problem with openssl on solaris */ /* We need the following to go around a problem with openssl on solaris */
@@ -493,6 +486,7 @@ typedef unsigned short ushort;
#endif #endif
#include <my_compiler.h> #include <my_compiler.h>
#include <my_alloca.h>
/* /*
Wen using the embedded library, users might run into link problems, Wen using the embedded library, users might run into link problems,

View File

@@ -28,9 +28,7 @@ C_MODE_START
#include <m_ctype.h> /* for CHARSET_INFO */ #include <m_ctype.h> /* for CHARSET_INFO */
#include <stdarg.h> #include <stdarg.h>
#include <typelib.h> #include <typelib.h>
#ifdef _WIN32 #include <my_alloca.h>
#include <malloc.h> /*for alloca*/
#endif
#include <mysql/plugin.h> #include <mysql/plugin.h>
#include <mysql/service_my_print_error.h> #include <mysql/service_my_print_error.h>
@@ -195,16 +193,6 @@ my_bool my_test_if_thinly_provisioned(File handle);
extern my_bool my_may_have_atomic_write; extern my_bool my_may_have_atomic_write;
#if defined(HAVE_ALLOCA) && !defined(HAVE_valgrind) #if defined(HAVE_ALLOCA) && !defined(HAVE_valgrind)
#if defined(_AIX) && !defined(__GNUC__) && !defined(_AIX43)
#pragma alloca
#endif /* _AIX */
#if defined(__MWERKS__)
#undef alloca
#define alloca _alloca
#endif /* __MWERKS__ */
#if defined(__GNUC__) && !defined(HAVE_ALLOCA_H) && ! defined(alloca)
#define alloca __builtin_alloca
#endif /* GNUC */
#define my_alloca(SZ) alloca((size_t) (SZ)) #define my_alloca(SZ) alloca((size_t) (SZ))
#define my_afree(PTR) ((void)0) #define my_afree(PTR) ((void)0)
#define MAX_ALLOCA_SZ 4096 #define MAX_ALLOCA_SZ 4096

View File

@@ -24,22 +24,19 @@
*provider* (encryption plugin). *provider* (encryption plugin).
*/ */
#ifdef __cplusplus
extern "C" {
#endif
#ifndef MYSQL_ABI_CHECK #ifndef MYSQL_ABI_CHECK
#include <my_alloca.h>
#ifdef _WIN32 #ifdef _WIN32
#include <malloc.h>
#ifndef __cplusplus #ifndef __cplusplus
#define inline __inline #define inline __inline
#endif #endif
#else #else
#include <stdlib.h> #include <stdlib.h>
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif #endif
#endif #endif
#ifdef __cplusplus
extern "C" {
#endif #endif
/* returned from encryption_key_get_latest_version() */ /* returned from encryption_key_get_latest_version() */

View File

@@ -20697,3 +20697,20 @@ id select_type table type possible_keys key key_len ref rows Extra
drop view v1; drop view v1;
drop table t1; drop table t1;
# End of 10.4 tests # End of 10.4 tests
#
# MDEV-28958: condition pushable into view after simplification
# contains constant TRUE/FALSE as subformula
#
create table t1 (c1 int);
insert into t1 values (3), (7), (1), (3), (1), (3);
create table t2 (c2 int);
insert into t2 values (3), (5), (7), (3);
create view v1 as select * from t1 group by c1;
create view v2 as select c1 as a, c2 as b from v1,t2 where c1=c2;
select * from v2 group by a,b having a=b or b > a+10;
a b
3 3
7 7
drop view v1,v2;
drop table t1,t2;
# End of 10.7 tests

View File

@@ -3944,3 +3944,24 @@ drop view v1;
drop table t1; drop table t1;
--echo # End of 10.4 tests --echo # End of 10.4 tests
--echo #
--echo # MDEV-28958: condition pushable into view after simplification
--echo # contains constant TRUE/FALSE as subformula
--echo #
create table t1 (c1 int);
insert into t1 values (3), (7), (1), (3), (1), (3);
create table t2 (c2 int);
insert into t2 values (3), (5), (7), (3);
create view v1 as select * from t1 group by c1;
create view v2 as select c1 as a, c2 as b from v1,t2 where c1=c2;
select * from v2 group by a,b having a=b or b > a+10;
drop view v1,v2;
drop table t1,t2;
--echo # End of 10.7 tests

View File

@@ -20,3 +20,24 @@ create table t1 (a varchar(1), primary key (a))
partition by list (ascii(a)) partition by list (ascii(a))
(partition p1 values in (65)); (partition p1 values in (65));
ERROR HY000: This partition function is not allowed ERROR HY000: This partition function is not allowed
#
# Start of 10.9 tests
#
#
# MDEV-30805 SIGSEGV in my_convert and UBSAN: member access within null pointer of type 'const struct MY_CHARSET_HANDLER' in my_convert
#
CREATE TABLE t1 (a CHAR CHARACTER SET ucs2)
PARTITION BY RANGE COLUMNS (a)
(PARTITION p0 VALUES LESS THAN ('a'));
ALTER TABLE t1 CHANGE COLUMN a a CHAR BINARY;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(1) CHARACTER SET latin1 COLLATE latin1_bin DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
PARTITION BY RANGE COLUMNS(`a`)
(PARTITION `p0` VALUES LESS THAN ('a') ENGINE = MyISAM)
DROP TABLE t1;
#
# End of 10.9 tests
#

View File

@@ -27,3 +27,23 @@ partition by list (ascii(a))
#insert into t1 values ('A'); #insert into t1 values ('A');
#replace into t1 values ('A'); #replace into t1 values ('A');
#drop table t1; #drop table t1;
--echo #
--echo # Start of 10.9 tests
--echo #
--echo #
--echo # MDEV-30805 SIGSEGV in my_convert and UBSAN: member access within null pointer of type 'const struct MY_CHARSET_HANDLER' in my_convert
--echo #
CREATE TABLE t1 (a CHAR CHARACTER SET ucs2)
PARTITION BY RANGE COLUMNS (a)
(PARTITION p0 VALUES LESS THAN ('a'));
ALTER TABLE t1 CHANGE COLUMN a a CHAR BINARY;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # End of 10.9 tests
--echo #

View File

@@ -77,7 +77,7 @@ CREATE OR REPLACE TABLE t1 (a DATE) CHARACTER SET utf8
PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (FROM_DAYS(100))); PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (FROM_DAYS(100)));
Warnings: Warnings:
Note 1003 PARTITION BY LIST COLUMNS(`a`) Note 1003 PARTITION BY LIST COLUMNS(`a`)
(PARTITION `p0` VALUES IN (_utf8mb3 0x303030302d30302d3030) ENGINE = MyISAM) (PARTITION `p0` VALUES IN (_latin1 0x303030302d30302d3030) ENGINE = MyISAM)
SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1'; SELECT PARTITION_DESCRIPTION FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_NAME='t1';
PARTITION_DESCRIPTION PARTITION_DESCRIPTION
'0000-00-00' '0000-00-00'

View File

@@ -31,8 +31,10 @@ insert into t8 values (1, 'publicmessage');
insert into t9 values (1, 'pugliccompressedaaaaaaaaabbbbbbbbbbbbbbccccccccccccccc'); insert into t9 values (1, 'pugliccompressedaaaaaaaaabbbbbbbbbbbbbbccccccccccccccc');
--echo # should list tables t1-t6 --echo # should list tables t1-t6
--sorted_result
SELECT NAME,ENCRYPTION_SCHEME,CURRENT_KEY_ID FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 AND NAME LIKE 'enctests%'; SELECT NAME,ENCRYPTION_SCHEME,CURRENT_KEY_ID FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION <> 0 AND NAME LIKE 'enctests%';
--echo # should list tables t7-t9 --echo # should list tables t7-t9
--sorted_result
SELECT NAME,ENCRYPTION_SCHEME,CURRENT_KEY_ID FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 and NAME LIKE 'enctests%'; SELECT NAME,ENCRYPTION_SCHEME,CURRENT_KEY_ID FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION WHERE MIN_KEY_VERSION = 0 and NAME LIKE 'enctests%';
--let $MYSQLD_DATADIR=`select @@datadir` --let $MYSQLD_DATADIR=`select @@datadir`

View File

@@ -9,6 +9,7 @@ INSERT INTO t2 VALUES ('foobar');
# #
# MDEV-9640: Add used key_id to INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION # MDEV-9640: Add used key_id to INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION
# #
--sorted_result
SELECT NAME, ENCRYPTION_SCHEME, MIN_KEY_VERSION, CURRENT_KEY_VERSION, SELECT NAME, ENCRYPTION_SCHEME, MIN_KEY_VERSION, CURRENT_KEY_VERSION,
CURRENT_KEY_ID CURRENT_KEY_ID
FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION FROM INFORMATION_SCHEMA.INNODB_TABLESPACES_ENCRYPTION

View File

@@ -190,7 +190,7 @@ compress_pages_page_decompressed compression 0 NULL NULL NULL 0 NULL NULL NULL N
compress_pages_page_compression_error compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of page compression errors compress_pages_page_compression_error compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of page compression errors
compress_pages_encrypted compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of pages encrypted compress_pages_encrypted compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of pages encrypted
compress_pages_decrypted compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of pages decrypted compress_pages_decrypted compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of pages decrypted
index_page_splits index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of index page splits index_page_splits index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Number of index page splits
index_page_merge_attempts index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of index page merge attempts index_page_merge_attempts index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of index page merge attempts
index_page_merge_successful index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of successful index page merges index_page_merge_successful index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of successful index page merges
index_page_reorg_attempts index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of index page reorganization attempts index_page_reorg_attempts index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of index page reorganization attempts

View File

@@ -23,6 +23,7 @@ INNODB_BUFFER_POOL_PAGES_OLD
INNODB_BUFFER_POOL_PAGES_TOTAL INNODB_BUFFER_POOL_PAGES_TOTAL
INNODB_BUFFER_POOL_PAGES_LRU_FLUSHED INNODB_BUFFER_POOL_PAGES_LRU_FLUSHED
INNODB_BUFFER_POOL_PAGES_LRU_FREED INNODB_BUFFER_POOL_PAGES_LRU_FREED
INNODB_BUFFER_POOL_PAGES_SPLIT
INNODB_BUFFER_POOL_READ_AHEAD_RND INNODB_BUFFER_POOL_READ_AHEAD_RND
INNODB_BUFFER_POOL_READ_AHEAD INNODB_BUFFER_POOL_READ_AHEAD
INNODB_BUFFER_POOL_READ_AHEAD_EVICTED INNODB_BUFFER_POOL_READ_AHEAD_EVICTED

View File

@@ -43,5 +43,25 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`f1`) PRIMARY KEY (`f1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
DROP TABLE t1; DROP TABLE t1;
#
# MDEV-30183 Assertion `!memcmp(rec_trx_id, old_pk_trx_id->data,
# 6 + 7)' failed in row_log_table_apply_update
#
set @old_sql_mode = @@sql_mode;
set @@sql_mode="";
CREATE TABLE t1(col_int int, col_varchar varchar(500))ENGINE=InnoDB;
INSERT INTO t1(col_int) values(2560);
set debug_sync="row_log_table_apply1_before SIGNAL con1_begin WAIT_FOR con1_commit";
ALTER TABLE t1 ADD PRIMARY KEY ( col_varchar);
connection con1;
SET DEBUG_SYNC="now WAIT_FOR con1_begin";
UPDATE t1 SET col_int = 2178;
INSERT INTO t1(col_int) VALUES(3016);
UPDATE t1 set col_int=2802;
SET DEBUG_SYNC="now SIGNAL con1_commit";
connection default;
ERROR 23000: Duplicate entry '' for key 'PRIMARY'
DROP TABLE t1;
SET @@sql_mode = @old_sql_mode;
disconnect con1; disconnect con1;
SET DEBUG_SYNC=reset; SET DEBUG_SYNC=reset;

View File

@@ -59,5 +59,29 @@ connection default;
reap; reap;
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-30183 Assertion `!memcmp(rec_trx_id, old_pk_trx_id->data,
--echo # 6 + 7)' failed in row_log_table_apply_update
--echo #
set @old_sql_mode = @@sql_mode;
set @@sql_mode="";
CREATE TABLE t1(col_int int, col_varchar varchar(500))ENGINE=InnoDB;
INSERT INTO t1(col_int) values(2560);
set debug_sync="row_log_table_apply1_before SIGNAL con1_begin WAIT_FOR con1_commit";
send ALTER TABLE t1 ADD PRIMARY KEY ( col_varchar);
connection con1;
SET DEBUG_SYNC="now WAIT_FOR con1_begin";
UPDATE t1 SET col_int = 2178;
INSERT INTO t1(col_int) VALUES(3016);
UPDATE t1 set col_int=2802;
SET DEBUG_SYNC="now SIGNAL con1_commit";
connection default;
--error ER_DUP_ENTRY
reap;
DROP TABLE t1;
SET @@sql_mode = @old_sql_mode;
disconnect con1; disconnect con1;
SET DEBUG_SYNC=reset; SET DEBUG_SYNC=reset;

View File

@@ -181,16 +181,19 @@ CREATE TABLE `t12` (
( (
pt1 PAGE_COMPRESSED=0 pt1 PAGE_COMPRESSED=0
); );
--sorted_result
SELECT name, flag FROM information_schema.innodb_sys_tablespaces WHERE name like 'test/t12%'; SELECT name, flag FROM information_schema.innodb_sys_tablespaces WHERE name like 'test/t12%';
ALTER TABLE `t12` ADD PARTITION ( ALTER TABLE `t12` ADD PARTITION (
PARTITION pt2 PAGE_COMPRESSED=1 PARTITION pt2 PAGE_COMPRESSED=1
); );
--sorted_result
SELECT name, flag FROM information_schema.innodb_sys_tablespaces WHERE name like 'test/t12%'; SELECT name, flag FROM information_schema.innodb_sys_tablespaces WHERE name like 'test/t12%';
ALTER TABLE `t12` ADD PARTITION ( ALTER TABLE `t12` ADD PARTITION (
PARTITION pt3 PAGE_COMPRESSED=1 PAGE_COMPRESSION_LEVEL=3 PARTITION pt3 PAGE_COMPRESSED=1 PAGE_COMPRESSION_LEVEL=3
); );
--sorted_result
SELECT name, flag FROM information_schema.innodb_sys_tablespaces WHERE name like 'test/t12%'; SELECT name, flag FROM information_schema.innodb_sys_tablespaces WHERE name like 'test/t12%';
DROP TABLE `t12`; DROP TABLE `t12`;
@@ -203,6 +206,7 @@ CREATE TABLE `t13` (
PARTITION pt3 VALUES LESS THAN MAXVALUE PARTITION pt3 VALUES LESS THAN MAXVALUE
); );
SHOW CREATE TABLE `t13`; SHOW CREATE TABLE `t13`;
--sorted_result
SELECT name, flag FROM information_schema.innodb_sys_tablespaces WHERE name like 'test/t13%'; SELECT name, flag FROM information_schema.innodb_sys_tablespaces WHERE name like 'test/t13%';
ALTER TABLE `t13` PARTITION BY RANGE(id) ( ALTER TABLE `t13` PARTITION BY RANGE(id) (
@@ -211,6 +215,7 @@ ALTER TABLE `t13` PARTITION BY RANGE(id) (
PARTITION pt3 VALUES LESS THAN MAXVALUE PAGE_COMPRESSED=0 PARTITION pt3 VALUES LESS THAN MAXVALUE PAGE_COMPRESSED=0
); );
SHOW CREATE TABLE `t13`; SHOW CREATE TABLE `t13`;
--sorted_result
SELECT name, flag FROM information_schema.innodb_sys_tablespaces WHERE name like 'test/t13%'; SELECT name, flag FROM information_schema.innodb_sys_tablespaces WHERE name like 'test/t13%';
DROP TABLE `t13`; DROP TABLE `t13`;

View File

@@ -13,7 +13,7 @@
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
#include <my_global.h> #include <my_alloca.h>
#include <mysql/plugin_password_validation.h> #include <mysql/plugin_password_validation.h>
#include <crack.h> #include <crack.h>
#include <string.h> #include <string.h>

View File

@@ -6,7 +6,7 @@
* See COPYRIGHT.txt for details. * See COPYRIGHT.txt for details.
*/ */
#include <my_global.h> #include <my_alloca.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <errno.h> #include <errno.h>
#include <poll.h> #include <poll.h>
@@ -17,9 +17,6 @@
#if __linux__ #if __linux__
#include <sys/epoll.h> #include <sys/epoll.h>
#endif #endif
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#include "hstcpsvr_worker.hpp" #include "hstcpsvr_worker.hpp"
#include "string_buffer.hpp" #include "string_buffer.hpp"

View File

@@ -11,6 +11,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <my_alloca.h>
#if 0 #if 0
extern "C" { extern "C" {

View File

@@ -5377,7 +5377,7 @@ public:
bool sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root); bool sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root);
bool prepare_stage1(THD *thd, MEM_ROOT *mem_root, bool prepare_stage1(THD *thd, MEM_ROOT *mem_root,
handler *file, ulonglong table_flags, column_definition_type_t type,
const Column_derived_attributes *derived_attr); const Column_derived_attributes *derived_attr);
void prepare_stage1_simple(CHARSET_INFO *cs) void prepare_stage1_simple(CHARSET_INFO *cs)
{ {
@@ -5385,11 +5385,9 @@ public:
create_length_to_internal_length_simple(); create_length_to_internal_length_simple();
} }
bool prepare_stage1_typelib(THD *thd, MEM_ROOT *mem_root, bool prepare_stage1_typelib(THD *thd, MEM_ROOT *mem_root,
handler *file, ulonglong table_flags); column_definition_type_t deftype);
bool prepare_stage1_string(THD *thd, MEM_ROOT *mem_root, bool prepare_stage1_string(THD *thd, MEM_ROOT *mem_root);
handler *file, ulonglong table_flags); bool prepare_stage1_bit(THD *thd, MEM_ROOT *mem_root);
bool prepare_stage1_bit(THD *thd, MEM_ROOT *mem_root,
handler *file, ulonglong table_flags);
bool bulk_alter(const Column_derived_attributes *derived_attr, bool bulk_alter(const Column_derived_attributes *derived_attr,
const Column_bulk_alter_attributes *bulk_attr) const Column_bulk_alter_attributes *bulk_attr)

View File

@@ -2687,17 +2687,26 @@ public:
void register_in(THD *thd); void register_in(THD *thd);
bool depends_only_on(table_map view_map) bool depends_only_on(table_map view_map)
{ return marker & MARKER_FULL_EXTRACTION; } { return get_extraction_flag() & MARKER_FULL_EXTRACTION; }
int get_extraction_flag() const int get_extraction_flag() const
{ return marker & MARKER_EXTRACTION_MASK; } {
if (basic_const_item())
return MARKER_FULL_EXTRACTION;
else
return marker & MARKER_EXTRACTION_MASK;
}
void set_extraction_flag(int16 flags) void set_extraction_flag(int16 flags)
{ {
marker &= ~MARKER_EXTRACTION_MASK; if (!basic_const_item())
{
marker= marker & ~MARKER_EXTRACTION_MASK;
marker|= flags; marker|= flags;
} }
}
void clear_extraction_flag() void clear_extraction_flag()
{ {
marker &= ~MARKER_EXTRACTION_MASK; if (!basic_const_item())
marker= marker & ~MARKER_EXTRACTION_MASK;
} }
void check_pushable_cond(Pushdown_checker excl_dep_func, uchar *arg); void check_pushable_cond(Pushdown_checker excl_dep_func, uchar *arg);
bool pushable_cond_checker_for_derived(uchar *arg) bool pushable_cond_checker_for_derived(uchar *arg)

View File

@@ -787,8 +787,9 @@ bool Create_json_table::add_json_table_fields(THD *thd, TABLE *table,
*/ */
sql_f->length= sql_f->char_length; sql_f->length= sql_f->char_length;
if (sql_f->prepare_stage1(thd, thd->mem_root, table->file, if (sql_f->prepare_stage1(thd, thd->mem_root,
table->file->ha_table_flags(), &da)) COLUMN_DEFINITION_TABLE_FIELD,
&da))
goto err_exit; goto err_exit;
while ((jc2= it2++) != jc) while ((jc2= it2++) != jc)

View File

@@ -5282,7 +5282,7 @@ private:
bool use_temporary_table(TABLE *table, TABLE **out_table); bool use_temporary_table(TABLE *table, TABLE **out_table);
void close_temporary_table(TABLE *table); void close_temporary_table(TABLE *table);
bool log_events_and_free_tmp_shares(); bool log_events_and_free_tmp_shares();
void free_tmp_table_share(TMP_TABLE_SHARE *share, bool delete_table); bool free_tmp_table_share(TMP_TABLE_SHARE *share, bool delete_table);
void free_temporary_table(TABLE *table); void free_temporary_table(TABLE *table);
bool lock_temporary_tables(); bool lock_temporary_tables();
void unlock_temporary_tables(); void unlock_temporary_tables();

View File

@@ -2395,17 +2395,16 @@ static void check_duplicate_key(THD *thd, const Key *key, const KEY *key_info,
bool Column_definition::prepare_stage1_typelib(THD *thd, bool Column_definition::prepare_stage1_typelib(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
handler *file, column_definition_type_t deftype)
ulonglong table_flags)
{ {
/* /*
Pass the last parameter to prepare_interval_field() as follows: Pass the last parameter to prepare_interval_field() as follows:
- If we are preparing for an SP variable (file is NULL), we pass "false", - If we are preparing for an SP variable, we pass "false",
to force allocation and full copying of TYPELIB values on the given to force allocation and full copying of TYPELIB values on the given
mem_root, even if no character set conversion is needed. This is needed mem_root, even if no character set conversion is needed. This is needed
because a life cycle of an SP variable is longer than the current query. because a life cycle of an SP variable is longer than the current query.
- If we are preparing for a CREATE TABLE, (file != NULL), we pass "true". - If we are preparing for a CREATE TABLE, we pass "true".
This will create the typelib in runtime memory - we will free the This will create the typelib in runtime memory - we will free the
occupied memory at the same time when we free this occupied memory at the same time when we free this
sql_field -- at the end of execution. sql_field -- at the end of execution.
@@ -2413,11 +2412,11 @@ bool Column_definition::prepare_stage1_typelib(THD *thd,
values in "interval" in cases when no character conversion is needed, values in "interval" in cases when no character conversion is needed,
to avoid extra copying. to avoid extra copying.
*/ */
if (prepare_interval_field(mem_root, file != NULL)) if (prepare_interval_field(mem_root,
deftype == COLUMN_DEFINITION_TABLE_FIELD))
return true; // E.g. wrong values with commas: SET('a,b') return true; // E.g. wrong values with commas: SET('a,b')
create_length_to_internal_length_typelib(); create_length_to_internal_length_typelib();
DBUG_ASSERT(file || !default_value); // SP variables have no default_value
if (default_value && default_value->expr->basic_const_item()) if (default_value && default_value->expr->basic_const_item())
{ {
if ((charset != default_value->expr->collation.collation && if ((charset != default_value->expr->collation.collation &&
@@ -2430,14 +2429,11 @@ bool Column_definition::prepare_stage1_typelib(THD *thd,
bool Column_definition::prepare_stage1_string(THD *thd, bool Column_definition::prepare_stage1_string(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root)
handler *file,
ulonglong table_flags)
{ {
create_length_to_internal_length_string(); create_length_to_internal_length_string();
if (prepare_blob_field(thd)) if (prepare_blob_field(thd))
return true; return true;
DBUG_ASSERT(file || !default_value); // SP variables have no default_value
/* /*
Convert the default value from client character Convert the default value from client character
set into the column character set if necessary. set into the column character set if necessary.
@@ -2457,13 +2453,9 @@ bool Column_definition::prepare_stage1_string(THD *thd,
bool Column_definition::prepare_stage1_bit(THD *thd, bool Column_definition::prepare_stage1_bit(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root)
handler *file,
ulonglong table_flags)
{ {
pack_flag= FIELDFLAG_NUMBER; pack_flag= FIELDFLAG_NUMBER;
if (!(table_flags & HA_CAN_BIT_FIELD))
pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
create_length_to_internal_length_bit(); create_length_to_internal_length_bit();
return false; return false;
} }
@@ -2471,14 +2463,15 @@ bool Column_definition::prepare_stage1_bit(THD *thd,
bool Column_definition::prepare_stage1(THD *thd, bool Column_definition::prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
handler *file, column_definition_type_t deftype,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
{ {
// SP variables have no default_value
DBUG_ASSERT(deftype == COLUMN_DEFINITION_TABLE_FIELD || !default_value);
return type_handler()->Column_definition_prepare_stage1(thd, mem_root, return type_handler()->Column_definition_prepare_stage1(thd, mem_root,
this, file, this, deftype,
table_flags,
derived_attr); derived_attr);
} }
@@ -2702,10 +2695,77 @@ key_add_part_check_null(const handler *file, KEY *key_info,
/* /*
Preparation for table creation Prepare for a table creation.
Stage 1: prepare the field list.
*/
static bool mysql_prepare_create_table_stage1(THD *thd,
HA_CREATE_INFO *create_info,
Alter_info *alter_info)
{
DBUG_ENTER("mysql_prepare_create_table_stage1");
const Column_derived_attributes dattr(create_info->default_table_charset);
const Column_bulk_alter_attributes
battr(create_info->alter_table_convert_to_charset);
Create_field *sql_field;
List_iterator_fast<Create_field> it(alter_info->create_list);
DBUG_EXECUTE_IF("test_pseudo_invisible",{
mysql_add_invisible_field(thd, &alter_info->create_list,
"invisible", &type_handler_slong, INVISIBLE_SYSTEM,
new (thd->mem_root)Item_int(thd, 9));
});
DBUG_EXECUTE_IF("test_completely_invisible",{
mysql_add_invisible_field(thd, &alter_info->create_list,
"invisible", &type_handler_slong, INVISIBLE_FULL,
new (thd->mem_root)Item_int(thd, 9));
});
DBUG_EXECUTE_IF("test_invisible_index",{
LEX_CSTRING temp;
temp.str= "invisible";
temp.length= strlen("invisible");
mysql_add_invisible_index(thd, &alter_info->key_list
, &temp, Key::MULTIPLE);
});
for ( ; (sql_field=it++) ; )
{
/* Virtual fields are always NULL */
if (sql_field->vcol_info)
sql_field->flags&= ~NOT_NULL_FLAG;
/*
Initialize length from its original value (number of characters),
which was set in the parser. This is necessary if we're
executing a prepared statement for the second time.
*/
sql_field->length= sql_field->char_length;
if (sql_field->bulk_alter(&dattr, &battr))
DBUG_RETURN(true);
if (sql_field->prepare_stage1(thd, thd->mem_root,
COLUMN_DEFINITION_TABLE_FIELD,
&dattr))
DBUG_RETURN(true);
DBUG_ASSERT(sql_field->charset);
if (check_column_name(sql_field->field_name.str))
{
my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name.str);
DBUG_RETURN(TRUE);
}
}
DBUG_RETURN(false);
}
/*
Preparation for table creation, final stage.
SYNOPSIS SYNOPSIS
mysql_prepare_create_table() mysql_prepare_create_table_finalize()
thd Thread object. thd Thread object.
create_info Create information (like MAX_ROWS). create_info Create information (like MAX_ROWS).
alter_info List of columns and indexes to create alter_info List of columns and indexes to create
@@ -2728,11 +2788,12 @@ key_add_part_check_null(const handler *file, KEY *key_info,
*/ */
static int static int
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info, mysql_prepare_create_table_finalize(THD *thd, HA_CREATE_INFO *create_info,
Alter_info *alter_info, uint *db_options, Alter_info *alter_info, uint *db_options,
handler *file, KEY **key_info_buffer, handler *file, KEY **key_info_buffer,
uint *key_count, int create_table_mode, uint *key_count, int create_table_mode,
const LEX_CSTRING db, const LEX_CSTRING table_name) const LEX_CSTRING db,
const LEX_CSTRING table_name)
{ {
const char *key_name; const char *key_name;
Create_field *sql_field,*dup_field; Create_field *sql_field,*dup_field;
@@ -2748,28 +2809,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
bool tmp_table= create_table_mode == C_ALTER_TABLE; bool tmp_table= create_table_mode == C_ALTER_TABLE;
const bool create_simple= thd->lex->create_simple(); const bool create_simple= thd->lex->create_simple();
bool is_hash_field_needed= false; bool is_hash_field_needed= false;
const Column_derived_attributes dattr(create_info->default_table_charset);
const Column_bulk_alter_attributes
battr(create_info->alter_table_convert_to_charset);
DBUG_ENTER("mysql_prepare_create_table"); DBUG_ENTER("mysql_prepare_create_table");
DBUG_EXECUTE_IF("test_pseudo_invisible",{
mysql_add_invisible_field(thd, &alter_info->create_list,
"invisible", &type_handler_slong, INVISIBLE_SYSTEM,
new (thd->mem_root)Item_int(thd, 9));
});
DBUG_EXECUTE_IF("test_completely_invisible",{
mysql_add_invisible_field(thd, &alter_info->create_list,
"invisible", &type_handler_slong, INVISIBLE_FULL,
new (thd->mem_root)Item_int(thd, 9));
});
DBUG_EXECUTE_IF("test_invisible_index",{
LEX_CSTRING temp;
temp.str= "invisible";
temp.length= strlen("invisible");
mysql_add_invisible_index(thd, &alter_info->key_list
, &temp, Key::MULTIPLE);
});
LEX_CSTRING* connect_string = &create_info->connect_string; LEX_CSTRING* connect_string = &create_info->connect_string;
if (connect_string->length != 0 && if (connect_string->length != 0 &&
connect_string->length > CONNECT_STRING_MAXLEN && connect_string->length > CONNECT_STRING_MAXLEN &&
@@ -2804,42 +2845,16 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
for (field_no=0; (sql_field=it++) ; field_no++) for (field_no=0; (sql_field=it++) ; field_no++)
{ {
/* Virtual fields are always NULL */ if (!(sql_field->flags & NOT_NULL_FLAG))
if (sql_field->vcol_info) null_fields++;
sql_field->flags&= ~NOT_NULL_FLAG;
/*
Initialize length from its original value (number of characters),
which was set in the parser. This is necessary if we're
executing a prepared statement for the second time.
*/
sql_field->length= sql_field->char_length;
if (sql_field->bulk_alter(&dattr, &battr))
DBUG_RETURN(true);
if (sql_field->prepare_stage1(thd, thd->mem_root,
file, file->ha_table_flags(),
&dattr))
DBUG_RETURN(true);
DBUG_ASSERT(sql_field->charset);
if (sql_field->real_field_type() == MYSQL_TYPE_BIT && if (sql_field->real_field_type() == MYSQL_TYPE_BIT &&
file->ha_table_flags() & HA_CAN_BIT_FIELD) file->ha_table_flags() & HA_CAN_BIT_FIELD)
total_uneven_bit_length+= sql_field->length & 7; total_uneven_bit_length+= sql_field->length & 7;
if (!(sql_field->flags & NOT_NULL_FLAG))
null_fields++;
if (check_column_name(sql_field->field_name.str))
{
my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name.str);
DBUG_RETURN(TRUE);
}
/* Check if we have used the same field name before */ /* Check if we have used the same field name before */
for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++) for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
{ {
@@ -3827,6 +3842,49 @@ without_overlaps_err:
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
/*
Preparation for table creation
SYNOPSIS
mysql_prepare_create_table()
thd Thread object.
create_info Create information (like MAX_ROWS).
alter_info List of columns and indexes to create
db_options INOUT Table options (like HA_OPTION_PACK_RECORD).
file The handler for the new table.
key_info_buffer OUT An array of KEY structs for the indexes.
key_count OUT The number of elements in the array.
create_table_mode C_ORDINARY_CREATE, C_ALTER_TABLE,
C_CREATE_SELECT, C_ASSISTED_DISCOVERY
DESCRIPTION
Prepares the table and key structures for table creation.
NOTES
sets create_info->varchar if the table has a varchar
RETURN VALUES
FALSE OK
TRUE error
*/
static int
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
Alter_info *alter_info, uint *db_options,
handler *file, KEY **key_info_buffer,
uint *key_count, int create_table_mode,
const LEX_CSTRING db,
const LEX_CSTRING table_name)
{
return mysql_prepare_create_table_stage1(thd, create_info, alter_info) ||
mysql_prepare_create_table_finalize(thd, create_info, alter_info,
db_options, file, key_info_buffer,
key_count, create_table_mode,
db, table_name);
}
/** /**
check comment length of table, column, index and partition check comment length of table, column, index and partition
@@ -3955,7 +4013,8 @@ bool Column_definition::prepare_blob_field(THD *thd)
bool Column_definition::sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root) bool Column_definition::sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root)
{ {
const Column_derived_attributes dattr(thd->variables.collation_database); const Column_derived_attributes dattr(thd->variables.collation_database);
return prepare_stage1(thd, mem_root, NULL, HA_CAN_GEOMETRY, &dattr) || return prepare_stage1(thd, mem_root,
COLUMN_DEFINITION_ROUTINE_LOCAL, &dattr) ||
prepare_stage2(NULL, HA_CAN_GEOMETRY); prepare_stage2(NULL, HA_CAN_GEOMETRY);
} }
@@ -4050,6 +4109,9 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db,
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
} }
if (mysql_prepare_create_table_stage1(thd, create_info, alter_info))
DBUG_RETURN(NULL);
db_options= create_info->table_options_with_row_type(); db_options= create_info->table_options_with_row_type();
if (unlikely(!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root, if (unlikely(!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
@@ -4266,7 +4328,8 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db,
} }
#endif #endif
if (mysql_prepare_create_table(thd, create_info, alter_info, &db_options, if (mysql_prepare_create_table_finalize(thd, create_info,
alter_info, &db_options,
file, key_info, key_count, file, key_info, key_count,
create_table_mode, db, table_name)) create_table_mode, db, table_name))
goto err; goto err;

View File

@@ -3008,8 +3008,7 @@ bool Type_handler::
Column_definition_prepare_stage1(THD *thd, Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *def, Column_definition *def,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const const
@@ -3022,8 +3021,7 @@ bool Type_handler_null::
Column_definition_prepare_stage1(THD *thd, Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *def, Column_definition *def,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const const
@@ -3037,8 +3035,7 @@ bool Type_handler_row::
Column_definition_prepare_stage1(THD *thd, Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *def, Column_definition *def,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const const
@@ -3052,8 +3049,7 @@ bool Type_handler_temporal_result::
Column_definition_prepare_stage1(THD *thd, Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *def, Column_definition *def,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const const
@@ -3067,8 +3063,7 @@ bool Type_handler_numeric::
Column_definition_prepare_stage1(THD *thd, Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *def, Column_definition *def,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const const
@@ -3081,8 +3076,7 @@ bool Type_handler_newdecimal::
Column_definition_prepare_stage1(THD *thd, Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *def, Column_definition *def,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const const
@@ -3096,28 +3090,26 @@ bool Type_handler_bit::
Column_definition_prepare_stage1(THD *thd, Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *def, Column_definition *def,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const const
{ {
def->charset= &my_charset_numeric; def->charset= &my_charset_numeric;
return def->prepare_stage1_bit(thd, mem_root, file, table_flags); return def->prepare_stage1_bit(thd, mem_root);
} }
bool Type_handler_typelib:: bool Type_handler_typelib::
Column_definition_prepare_stage1(THD *thd, Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *def, Column_definition *def,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const const
{ {
return def->prepare_charset_for_string(derived_attr) || return def->prepare_charset_for_string(derived_attr) ||
def->prepare_stage1_typelib(thd, mem_root, file, table_flags); def->prepare_stage1_typelib(thd, mem_root, type);
} }
@@ -3125,14 +3117,13 @@ bool Type_handler_string_result::
Column_definition_prepare_stage1(THD *thd, Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *def, Column_definition *def,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const const
{ {
return def->prepare_charset_for_string(derived_attr) || return def->prepare_charset_for_string(derived_attr) ||
def->prepare_stage1_string(thd, mem_root, file, table_flags); def->prepare_stage1_string(thd, mem_root);
} }
@@ -3343,10 +3334,11 @@ bool Type_handler_bit::
handler *file, handler *file,
ulonglong table_flags) const ulonglong table_flags) const
{ {
/* if (!(table_flags & HA_CAN_BIT_FIELD))
We have sql_field->pack_flag already set here, see {
mysql_prepare_create_table(). def->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
*/ def->create_length_to_internal_length_bit();
}
return false; return false;
} }

View File

@@ -3962,8 +3962,7 @@ public:
virtual bool Column_definition_prepare_stage1(THD *thd, virtual bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *c, Column_definition *c,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const; const;
@@ -4441,8 +4440,7 @@ public:
bool Column_definition_prepare_stage1(THD *thd, bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *c, Column_definition *c,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const override; const override;
@@ -4756,8 +4754,7 @@ public:
bool Column_definition_prepare_stage1(THD *thd, bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *c, Column_definition *c,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const override; const override;
@@ -5310,8 +5307,7 @@ public:
bool Column_definition_prepare_stage1(THD *thd, bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *c, Column_definition *c,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const override; const override;
@@ -5414,8 +5410,7 @@ public:
bool Column_definition_prepare_stage1(THD *thd, bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *c, Column_definition *c,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const override; const override;
@@ -5947,8 +5942,7 @@ public:
bool Column_definition_prepare_stage1(THD *thd, bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *c, Column_definition *c,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const override; const override;
@@ -6791,8 +6785,7 @@ public:
bool Column_definition_prepare_stage1(THD *thd, bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *c, Column_definition *c,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const override; const override;
@@ -6849,8 +6842,7 @@ public:
bool Column_definition_prepare_stage1(THD *thd, bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *c, Column_definition *c,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const override; const override;
@@ -7286,8 +7278,7 @@ public:
bool Column_definition_prepare_stage1(THD *thd, bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *c, Column_definition *c,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const override; const override;

View File

@@ -382,8 +382,8 @@ public:
} }
bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root, bool Column_definition_prepare_stage1(THD *thd, MEM_ROOT *mem_root,
Column_definition *def, handler *file, Column_definition *def,
ulonglong table_flags, column_definition_type_t type,
const Column_derived_attributes *derived_attr) const Column_derived_attributes *derived_attr)
const override const override
{ {

View File

@@ -280,8 +280,7 @@ bool Type_handler_geometry::
Column_definition_prepare_stage1(THD *thd, Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *def, Column_definition *def,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) const *derived_attr) const
{ {

View File

@@ -108,8 +108,7 @@ public:
bool Column_definition_prepare_stage1(THD *thd, bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root, MEM_ROOT *mem_root,
Column_definition *c, Column_definition *c,
handler *file, column_definition_type_t type,
ulonglong table_flags,
const Column_derived_attributes const Column_derived_attributes
*derived_attr) *derived_attr)
const override; const override;

View File

@@ -671,7 +671,7 @@ bool THD::drop_temporary_table(TABLE *table, bool *is_trans, bool delete_table)
temporary_tables->remove(share); temporary_tables->remove(share);
/* Free the TABLE_SHARE and/or delete the files. */ /* Free the TABLE_SHARE and/or delete the files. */
free_tmp_table_share(share, delete_table); result= free_tmp_table_share(share, delete_table);
end: end:
if (locked) if (locked)
@@ -1464,20 +1464,21 @@ bool THD::log_events_and_free_tmp_shares()
@param share [IN] TABLE_SHARE to free @param share [IN] TABLE_SHARE to free
@param delete_table [IN] Whether to delete the table files? @param delete_table [IN] Whether to delete the table files?
@return void @return false Success
true Error
*/ */
void THD::free_tmp_table_share(TMP_TABLE_SHARE *share, bool delete_table) bool THD::free_tmp_table_share(TMP_TABLE_SHARE *share, bool delete_table)
{ {
bool error= false;
DBUG_ENTER("THD::free_tmp_table_share"); DBUG_ENTER("THD::free_tmp_table_share");
if (delete_table) if (delete_table)
{ {
rm_temporary_table(share->db_type(), share->path.str); error= rm_temporary_table(share->db_type(), share->path.str);
} }
free_table_share(share); free_table_share(share);
my_free(share); my_free(share);
DBUG_RETURN(error);
DBUG_VOID_RETURN;
} }

View File

@@ -254,7 +254,7 @@ Gets the root node of a tree and x- or s-latches it.
buf_block_t* buf_block_t*
btr_root_block_get( btr_root_block_get(
/*===============*/ /*===============*/
const dict_index_t* index, /*!< in: index tree */ dict_index_t* index, /*!< in: index tree */
rw_lock_type_t mode, /*!< in: either RW_S_LATCH rw_lock_type_t mode, /*!< in: either RW_S_LATCH
or RW_X_LATCH */ or RW_X_LATCH */
mtr_t* mtr, /*!< in: mtr */ mtr_t* mtr, /*!< in: mtr */
@@ -266,11 +266,31 @@ btr_root_block_get(
return nullptr; return nullptr;
} }
buf_block_t *block = btr_block_get(*index, index->page, mode, false, mtr, buf_block_t *block;
err); #ifndef BTR_CUR_ADAPT
if (block) static constexpr buf_block_t *guess= nullptr;
#else
buf_block_t *&guess= btr_search_get_info(index)->root_guess;
guess=
#endif
block=
buf_page_get_gen(page_id_t{index->table->space->id, index->page},
index->table->space->zip_size(), mode, guess, BUF_GET,
mtr, err, false);
ut_ad(!block == (*err != DB_SUCCESS));
if (UNIV_LIKELY(block != nullptr))
{ {
if (index->is_ibuf()); if (!!page_is_comp(block->page.frame) != index->table->not_redundant() ||
btr_page_get_index_id(block->page.frame) != index->id ||
!fil_page_index_page_check(block->page.frame) ||
index->is_spatial() !=
(fil_page_get_type(block->page.frame) == FIL_PAGE_RTREE))
{
*err= DB_PAGE_CORRUPTED;
block= nullptr;
}
else if (index->is_ibuf());
else if (!btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF, else if (!btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF,
*block, *index->table->space) || *block, *index->table->space) ||
!btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP, !btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP,
@@ -280,6 +300,9 @@ btr_root_block_get(
block= nullptr; block= nullptr;
} }
} }
else if (*err == DB_DECRYPTION_FAILED)
btr_decryption_failed(*index);
return block; return block;
} }
@@ -290,7 +313,7 @@ static
page_t* page_t*
btr_root_get( btr_root_get(
/*=========*/ /*=========*/
const dict_index_t* index, /*!< in: index tree */ dict_index_t* index, /*!< in: index tree */
mtr_t* mtr, /*!< in: mtr */ mtr_t* mtr, /*!< in: mtr */
dberr_t* err) /*!< out: error code */ dberr_t* err) /*!< out: error code */
{ {
@@ -502,9 +525,7 @@ btr_block_reget(mtr_t *mtr, const dict_index_t &index,
return block; return block;
} }
#if 0 /* MDEV-29385 FIXME: Acquire the page latch upfront. */
ut_ad(mtr->memo_contains_flagged(&index.lock, MTR_MEMO_X_LOCK)); ut_ad(mtr->memo_contains_flagged(&index.lock, MTR_MEMO_X_LOCK));
#endif
return btr_block_get(index, id.page_no(), rw_latch, true, mtr, err); return btr_block_get(index, id.page_no(), rw_latch, true, mtr, err);
} }
@@ -773,9 +794,7 @@ btr_page_get_father_node_ptr_for_validate(
const uint32_t page_no = btr_cur_get_block(cursor)->page.id().page_no(); const uint32_t page_no = btr_cur_get_block(cursor)->page.id().page_no();
dict_index_t* index = btr_cur_get_index(cursor); dict_index_t* index = btr_cur_get_index(cursor);
ut_ad(!dict_index_is_spatial(index)); ut_ad(!dict_index_is_spatial(index));
ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_X_LOCK));
ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK));
ut_ad(dict_index_get_page(index) != page_no); ut_ad(dict_index_get_page(index) != page_no);
const auto level = btr_page_get_level(btr_cur_get_page(cursor)); const auto level = btr_page_get_level(btr_cur_get_page(cursor));
@@ -793,10 +812,6 @@ btr_page_get_father_node_ptr_for_validate(
} }
const rec_t* node_ptr = btr_cur_get_rec(cursor); const rec_t* node_ptr = btr_cur_get_rec(cursor);
#if 0 /* MDEV-29835 FIXME */
ut_ad(!btr_cur_get_block(cursor)->page.lock.not_recursive()
|| mtr->memo_contains(index->lock, MTR_MEMO_X_LOCK));
#endif
offsets = rec_get_offsets(node_ptr, index, offsets, 0, offsets = rec_get_offsets(node_ptr, index, offsets, 0,
ULINT_UNDEFINED, &heap); ULINT_UNDEFINED, &heap);
@@ -2457,11 +2472,10 @@ btr_insert_on_non_leaf_level(
} }
ut_ad(cursor.flag == BTR_CUR_BINARY); ut_ad(cursor.flag == BTR_CUR_BINARY);
#if 0 /* MDEV-29835 FIXME */ ut_ad(btr_cur_get_block(&cursor)
ut_ad(!btr_cur_get_block(&cursor)->page.lock.not_recursive() != mtr->at_savepoint(mtr->get_savepoint() - 1)
|| index->is_spatial() || index->is_spatial()
|| mtr->memo_contains(index->lock, MTR_MEMO_X_LOCK)); || mtr->memo_contains(index->lock, MTR_MEMO_X_LOCK));
#endif
if (UNIV_LIKELY(err == DB_SUCCESS)) { if (UNIV_LIKELY(err == DB_SUCCESS)) {
err = btr_cur_optimistic_insert(flags, err = btr_cur_optimistic_insert(flags,
@@ -2569,10 +2583,8 @@ btr_attach_half_pages(
prev_block = mtr->get_already_latched(id, MTR_MEMO_PAGE_X_FIX); prev_block = mtr->get_already_latched(id, MTR_MEMO_PAGE_X_FIX);
#if 1 /* MDEV-29835 FIXME: acquire page latches upfront */ #if 1 /* MDEV-29835 FIXME: acquire page latches upfront */
if (!prev_block) { if (!prev_block) {
# if 0 /* MDEV-29835 FIXME */
ut_ad(mtr->memo_contains(index->lock, ut_ad(mtr->memo_contains(index->lock,
MTR_MEMO_X_LOCK)); MTR_MEMO_X_LOCK));
# endif
prev_block = btr_block_get(*index, prev_page_no, prev_block = btr_block_get(*index, prev_page_no,
RW_X_LATCH, !level, mtr); RW_X_LATCH, !level, mtr);
} }
@@ -2583,10 +2595,8 @@ btr_attach_half_pages(
next_block = mtr->get_already_latched(id, MTR_MEMO_PAGE_X_FIX); next_block = mtr->get_already_latched(id, MTR_MEMO_PAGE_X_FIX);
#if 1 /* MDEV-29835 FIXME: acquire page latches upfront */ #if 1 /* MDEV-29835 FIXME: acquire page latches upfront */
if (!next_block) { if (!next_block) {
# if 0 /* MDEV-29835 FIXME */
ut_ad(mtr->memo_contains(index->lock, ut_ad(mtr->memo_contains(index->lock,
MTR_MEMO_X_LOCK)); MTR_MEMO_X_LOCK));
# endif
next_block = btr_block_get(*index, next_page_no, next_block = btr_block_get(*index, next_page_no,
RW_X_LATCH, !level, mtr); RW_X_LATCH, !level, mtr);
} }
@@ -2966,6 +2976,8 @@ btr_page_split_and_insert(
ut_ad(*err == DB_SUCCESS); ut_ad(*err == DB_SUCCESS);
ut_ad(dtuple_check_typed(tuple)); ut_ad(dtuple_check_typed(tuple));
buf_pool.pages_split++;
if (cursor->index()->is_spatial()) { if (cursor->index()->is_spatial()) {
/* Split rtree page and update parent */ /* Split rtree page and update parent */
return rtr_page_split_and_insert(flags, cursor, offsets, heap, return rtr_page_split_and_insert(flags, cursor, offsets, heap,
@@ -3363,8 +3375,6 @@ func_exit:
left_block, right_block, mtr); left_block, right_block, mtr);
} }
MONITOR_INC(MONITOR_INDEX_SPLIT);
ut_ad(page_validate(buf_block_get_frame(left_block), ut_ad(page_validate(buf_block_get_frame(left_block),
page_cursor->index)); page_cursor->index));
ut_ad(page_validate(buf_block_get_frame(right_block), ut_ad(page_validate(buf_block_get_frame(right_block),
@@ -3399,9 +3409,7 @@ dberr_t btr_level_list_remove(const buf_block_t& block,
#if 1 /* MDEV-29835 FIXME: acquire page latches upfront */ #if 1 /* MDEV-29835 FIXME: acquire page latches upfront */
if (!prev) if (!prev)
{ {
# if 0 /* MDEV-29835 FIXME */
ut_ad(mtr->memo_contains(index.lock, MTR_MEMO_X_LOCK)); ut_ad(mtr->memo_contains(index.lock, MTR_MEMO_X_LOCK));
# endif
prev= btr_block_get(index, id.page_no(), RW_X_LATCH, prev= btr_block_get(index, id.page_no(), RW_X_LATCH,
page_is_leaf(block.page.frame), mtr, &err); page_is_leaf(block.page.frame), mtr, &err);
if (UNIV_UNLIKELY(!prev)) if (UNIV_UNLIKELY(!prev))
@@ -3417,9 +3425,7 @@ dberr_t btr_level_list_remove(const buf_block_t& block,
#if 1 /* MDEV-29835 FIXME: acquire page latches upfront */ #if 1 /* MDEV-29835 FIXME: acquire page latches upfront */
if (!next) if (!next)
{ {
# if 0 /* MDEV-29835 FIXME */
ut_ad(mtr->memo_contains(index.lock, MTR_MEMO_X_LOCK)); ut_ad(mtr->memo_contains(index.lock, MTR_MEMO_X_LOCK));
# endif
next= btr_block_get(index, id.page_no(), RW_X_LATCH, next= btr_block_get(index, id.page_no(), RW_X_LATCH,
page_is_leaf(block.page.frame), mtr, &err); page_is_leaf(block.page.frame), mtr, &err);
if (UNIV_UNLIKELY(!next)) if (UNIV_UNLIKELY(!next))
@@ -4293,7 +4299,7 @@ btr_discard_page(
if (UNIV_UNLIKELY(!merge_block)) { if (UNIV_UNLIKELY(!merge_block)) {
return err; return err;
} }
#if 0 /* MDEV-29385 FIXME: Acquire the page latch upfront. */ #if 1 /* MDEV-29835 FIXME: Acquire the page latch upfront. */
ut_ad(!memcmp_aligned<4>(merge_block->page.frame ut_ad(!memcmp_aligned<4>(merge_block->page.frame
+ FIL_PAGE_NEXT, + FIL_PAGE_NEXT,
block->page.frame + FIL_PAGE_OFFSET, block->page.frame + FIL_PAGE_OFFSET,
@@ -4319,7 +4325,7 @@ btr_discard_page(
if (UNIV_UNLIKELY(!merge_block)) { if (UNIV_UNLIKELY(!merge_block)) {
return err; return err;
} }
#if 0 /* MDEV-29385 FIXME: Acquire the page latch upfront. */ #if 1 /* MDEV-29835 FIXME: Acquire the page latch upfront. */
ut_ad(!memcmp_aligned<4>(merge_block->page.frame ut_ad(!memcmp_aligned<4>(merge_block->page.frame
+ FIL_PAGE_PREV, + FIL_PAGE_PREV,
block->page.frame + FIL_PAGE_OFFSET, block->page.frame + FIL_PAGE_OFFSET,
@@ -4901,8 +4907,7 @@ btr_validate_level(
/*===============*/ /*===============*/
dict_index_t* index, /*!< in: index tree */ dict_index_t* index, /*!< in: index tree */
const trx_t* trx, /*!< in: transaction or NULL */ const trx_t* trx, /*!< in: transaction or NULL */
ulint level, /*!< in: level number */ ulint level) /*!< in: level number */
bool lockout)/*!< in: true if X-latch index is intended */
{ {
buf_block_t* block; buf_block_t* block;
page_t* page; page_t* page;
@@ -4921,18 +4926,10 @@ btr_validate_level(
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
page_zip_des_t* page_zip; page_zip_des_t* page_zip;
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
ulint savepoint = 0;
uint32_t parent_page_no = FIL_NULL;
uint32_t parent_right_page_no = FIL_NULL;
bool rightmost_child = false;
mtr.start(); mtr.start();
if (lockout) {
mtr_x_lock_index(index, &mtr); mtr_x_lock_index(index, &mtr);
} else {
mtr_sx_lock_index(index, &mtr);
}
dberr_t err; dberr_t err;
block = btr_root_block_get(index, RW_SX_LATCH, &mtr, &err); block = btr_root_block_get(index, RW_SX_LATCH, &mtr, &err);
@@ -5028,11 +5025,7 @@ func_exit:
mem_heap_empty(heap); mem_heap_empty(heap);
offsets = offsets2 = NULL; offsets = offsets2 = NULL;
if (lockout) {
mtr_x_lock_index(index, &mtr); mtr_x_lock_index(index, &mtr);
} else {
mtr_sx_lock_index(index, &mtr);
}
page = block->page.frame; page = block->page.frame;
@@ -5076,7 +5069,6 @@ func_exit:
if (right_page_no != FIL_NULL) { if (right_page_no != FIL_NULL) {
const rec_t* right_rec; const rec_t* right_rec;
savepoint = mtr.get_savepoint();
right_block = btr_block_get(*index, right_page_no, RW_SX_LATCH, right_block = btr_block_get(*index, right_page_no, RW_SX_LATCH,
!level, &mtr, &err); !level, &mtr, &err);
@@ -5179,11 +5171,6 @@ broken_links:
father_page = btr_cur_get_page(&node_cur); father_page = btr_cur_get_page(&node_cur);
node_ptr = btr_cur_get_rec(&node_cur); node_ptr = btr_cur_get_rec(&node_cur);
parent_page_no = page_get_page_no(father_page);
parent_right_page_no = btr_page_get_next(father_page);
rightmost_child = page_rec_is_supremum(
page_rec_get_next(node_ptr));
rec = page_rec_get_prev(page_get_supremum_rec(page)); rec = page_rec_get_prev(page_get_supremum_rec(page));
if (rec) { if (rec) {
btr_cur_position(index, rec, block, &node_cur); btr_cur_position(index, rec, block, &node_cur);
@@ -5265,37 +5252,6 @@ broken_links:
} }
} else if (const rec_t* right_node_ptr } else if (const rec_t* right_node_ptr
= page_rec_get_next(node_ptr)) { = page_rec_get_next(node_ptr)) {
if (!lockout && rightmost_child) {
/* To obey latch order of tree blocks,
we should release the right_block once to
obtain lock of the uncle block. */
ut_ad(right_block
== mtr.at_savepoint(savepoint));
mtr.rollback_to_savepoint(savepoint,
savepoint + 1);
if (parent_right_page_no != FIL_NULL) {
btr_block_get(*index,
parent_right_page_no,
RW_SX_LATCH, false,
&mtr);
}
right_block = btr_block_get(*index,
right_page_no,
RW_SX_LATCH,
!level, &mtr,
&err);
if (!right_block) {
btr_validate_report1(index, level,
block);
fputs("InnoDB: broken FIL_PAGE_NEXT"
" link\n", stderr);
goto invalid_page;
}
}
btr_cur_position( btr_cur_position(
index, index,
page_get_infimum_rec(right_block->page.frame), page_get_infimum_rec(right_block->page.frame),
@@ -5367,20 +5323,6 @@ node_ptr_fails:
mtr.start(); mtr.start();
if (!lockout) {
if (rightmost_child) {
if (parent_right_page_no != FIL_NULL) {
btr_block_get(*index,
parent_right_page_no,
RW_SX_LATCH, false,
&mtr);
}
} else if (parent_page_no != FIL_NULL) {
btr_block_get(*index, parent_page_no,
RW_SX_LATCH, false, &mtr);
}
}
block = btr_block_get(*index, right_page_no, RW_SX_LATCH, block = btr_block_get(*index, right_page_no, RW_SX_LATCH,
!level, &mtr, &err); !level, &mtr, &err);
goto loop; goto loop;
@@ -5398,21 +5340,16 @@ btr_validate_index(
dict_index_t* index, /*!< in: index */ dict_index_t* index, /*!< in: index */
const trx_t* trx) /*!< in: transaction or NULL */ const trx_t* trx) /*!< in: transaction or NULL */
{ {
const bool lockout= index->is_spatial();
mtr_t mtr; mtr_t mtr;
mtr.start(); mtr.start();
if (lockout)
mtr_x_lock_index(index, &mtr); mtr_x_lock_index(index, &mtr);
else
mtr_sx_lock_index(index, &mtr);
dberr_t err; dberr_t err;
if (page_t *root= btr_root_get(index, &mtr, &err)) if (page_t *root= btr_root_get(index, &mtr, &err))
for (auto level= btr_page_get_level(root);; level--) for (auto level= btr_page_get_level(root);; level--)
{ {
if (dberr_t err_level= btr_validate_level(index, trx, level, lockout)) if (dberr_t err_level= btr_validate_level(index, trx, level))
err= err_level; err= err_level;
if (!level) if (!level)
break; break;

View File

@@ -748,29 +748,34 @@ btr_cur_will_modify_tree(
/** Detects whether the modifying record might need a opposite modification /** Detects whether the modifying record might need a opposite modification
to the intention. to the intention.
@param[in] page page @param page page
@param[in] lock_intention lock intention for the tree operation @param lock_intention lock intention for the tree operation
@param[in] rec record (current node_ptr) @param node_ptr_max_size the maximum size of a node pointer
@param compress_limit BTR_CUR_PAGE_COMPRESS_LIMIT(index)
@param rec record (current node_ptr)
@return true if tree modification is needed */ @return true if tree modification is needed */
static static bool btr_cur_need_opposite_intention(const page_t *page,
bool
btr_cur_need_opposite_intention(
const page_t* page,
btr_intention_t lock_intention, btr_intention_t lock_intention,
ulint node_ptr_max_size,
ulint compress_limit,
const rec_t *rec) const rec_t *rec)
{ {
switch (lock_intention) { if (lock_intention != BTR_INTENTION_INSERT)
case BTR_INTENTION_DELETE: {
return (page_has_prev(page) && page_rec_is_first(rec, page)) || /* We compensate also for btr_cur_compress_recommendation() */
(page_has_next(page) && page_rec_is_last(rec, page)); if (!page_has_siblings(page) ||
case BTR_INTENTION_INSERT: page_rec_is_first(rec, page) || page_rec_is_last(rec, page) ||
return page_has_next(page) && page_rec_is_last(rec, page); page_get_data_size(page) < node_ptr_max_size + compress_limit)
case BTR_INTENTION_BOTH: return true;
return(false); if (lock_intention == BTR_INTENTION_DELETE)
return false;
} }
else if (page_has_next(page) && page_rec_is_last(rec, page))
MY_ASSERT_UNREACHABLE(); return true;
return(false); LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page), return true);
const ulint max_size= page_get_max_insert_size_after_reorganize(page, 2);
return max_size < BTR_CUR_PAGE_REORGANIZE_LIMIT + node_ptr_max_size ||
max_size < node_ptr_max_size * 2;
} }
/** /**
@@ -1039,7 +1044,7 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode,
const ulint savepoint= mtr->get_savepoint(); const ulint savepoint= mtr->get_savepoint();
ulint node_ptr_max_size= 0; ulint node_ptr_max_size= 0, compress_limit= 0;
rw_lock_type_t rw_latch= RW_S_LATCH; rw_lock_type_t rw_latch= RW_S_LATCH;
switch (latch_mode) { switch (latch_mode) {
@@ -1051,12 +1056,18 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode,
ut_ad(mtr->memo_contains_flagged(&index()->lock, MTR_MEMO_X_LOCK)); ut_ad(mtr->memo_contains_flagged(&index()->lock, MTR_MEMO_X_LOCK));
break; break;
} }
if (lock_intention == BTR_INTENTION_DELETE && buf_pool.n_pend_reads && if (lock_intention == BTR_INTENTION_DELETE)
{
compress_limit= BTR_CUR_PAGE_COMPRESS_LIMIT(index());
if (buf_pool.n_pend_reads &&
trx_sys.history_size_approx() > BTR_CUR_FINE_HISTORY_LENGTH) trx_sys.history_size_approx() > BTR_CUR_FINE_HISTORY_LENGTH)
{
/* Most delete-intended operations are due to the purge of history. /* Most delete-intended operations are due to the purge of history.
Prioritize them when the history list is growing huge. */ Prioritize them when the history list is growing huge. */
mtr_x_lock_index(index(), mtr); mtr_x_lock_index(index(), mtr);
else break;
}
}
mtr_sx_lock_index(index(), mtr); mtr_sx_lock_index(index(), mtr);
break; break;
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
@@ -1332,6 +1343,10 @@ release_tree:
!btr_block_get(*index(), btr_page_get_next(block->page.frame), !btr_block_get(*index(), btr_page_get_next(block->page.frame),
RW_X_LATCH, false, mtr, &err)) RW_X_LATCH, false, mtr, &err))
goto func_exit; goto func_exit;
if (btr_cur_need_opposite_intention(block->page.frame, lock_intention,
node_ptr_max_size, compress_limit,
page_cur.rec))
goto need_opposite_intention;
} }
reached_latched_leaf: reached_latched_leaf:
@@ -1385,6 +1400,7 @@ release_tree:
break; break;
case BTR_MODIFY_TREE: case BTR_MODIFY_TREE:
if (btr_cur_need_opposite_intention(block->page.frame, lock_intention, if (btr_cur_need_opposite_intention(block->page.frame, lock_intention,
node_ptr_max_size, compress_limit,
page_cur.rec)) page_cur.rec))
/* If the rec is the first or last in the page for pessimistic /* If the rec is the first or last in the page for pessimistic
delete intention, it might cause node_ptr insert for the upper delete intention, it might cause node_ptr insert for the upper
@@ -1537,6 +1553,17 @@ release_tree:
goto search_loop; goto search_loop;
} }
ATTRIBUTE_COLD void mtr_t::index_lock_upgrade()
{
auto &slot= m_memo[get_savepoint() - 1];
if (slot.type == MTR_MEMO_X_LOCK)
return;
ut_ad(slot.type == MTR_MEMO_SX_LOCK);
index_lock *lock= static_cast<index_lock*>(slot.object);
lock->u_x_upgrade(SRW_LOCK_CALL);
slot.type= MTR_MEMO_X_LOCK;
}
ATTRIBUTE_COLD ATTRIBUTE_COLD
dberr_t btr_cur_t::pessimistic_search_leaf(const dtuple_t *tuple, dberr_t btr_cur_t::pessimistic_search_leaf(const dtuple_t *tuple,
page_cur_mode_t mode, mtr_t *mtr) page_cur_mode_t mode, mtr_t *mtr)
@@ -1555,8 +1582,7 @@ dberr_t btr_cur_t::pessimistic_search_leaf(const dtuple_t *tuple,
ut_ad(block->page.id().page_no() == index()->page); ut_ad(block->page.id().page_no() == index()->page);
block->page.fix(); block->page.fix();
mtr->rollback_to_savepoint(1); mtr->rollback_to_savepoint(1);
ut_ad(mtr->memo_contains_flagged(&index()->lock, mtr->index_lock_upgrade();
MTR_MEMO_SX_LOCK | MTR_MEMO_X_LOCK));
const page_cur_mode_t page_mode{btr_cur_nonleaf_mode(mode)}; const page_cur_mode_t page_mode{btr_cur_nonleaf_mode(mode)};
@@ -1786,7 +1812,6 @@ search_loop:
dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index, dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
btr_latch_mode latch_mode, mtr_t *mtr) btr_latch_mode latch_mode, mtr_t *mtr)
{ {
btr_intention_t lock_intention;
ulint n_blocks= 0; ulint n_blocks= 0;
mem_heap_t *heap= nullptr; mem_heap_t *heap= nullptr;
rec_offs offsets_[REC_OFFS_NORMAL_SIZE]; rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
@@ -1798,7 +1823,7 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
const bool latch_by_caller= latch_mode & BTR_ALREADY_S_LATCHED; const bool latch_by_caller= latch_mode & BTR_ALREADY_S_LATCHED;
latch_mode= btr_latch_mode(latch_mode & ~BTR_ALREADY_S_LATCHED); latch_mode= btr_latch_mode(latch_mode & ~BTR_ALREADY_S_LATCHED);
lock_intention= btr_cur_get_and_clear_intention(&latch_mode); btr_intention_t lock_intention= btr_cur_get_and_clear_intention(&latch_mode);
/* Store the position of the tree latch we push to mtr so that we /* Store the position of the tree latch we push to mtr so that we
know how to release it when we have latched the leaf node */ know how to release it when we have latched the leaf node */
@@ -1806,7 +1831,7 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
auto savepoint= mtr->get_savepoint(); auto savepoint= mtr->get_savepoint();
rw_lock_type_t upper_rw_latch= RW_X_LATCH; rw_lock_type_t upper_rw_latch= RW_X_LATCH;
ulint node_ptr_max_size= 0; ulint node_ptr_max_size= 0, compress_limit= 0;
if (latch_mode == BTR_MODIFY_TREE) if (latch_mode == BTR_MODIFY_TREE)
{ {
@@ -1815,11 +1840,17 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
and read IO bandwidth should be prioritized for them, when the and read IO bandwidth should be prioritized for them, when the
history list is growing huge. */ history list is growing huge. */
savepoint++; savepoint++;
if (lock_intention == BTR_INTENTION_DELETE if (lock_intention == BTR_INTENTION_DELETE)
&& buf_pool.n_pend_reads {
&& trx_sys.history_size_approx() > BTR_CUR_FINE_HISTORY_LENGTH) compress_limit= BTR_CUR_PAGE_COMPRESS_LIMIT(index);
if (buf_pool.n_pend_reads &&
trx_sys.history_size_approx() > BTR_CUR_FINE_HISTORY_LENGTH)
{
mtr_x_lock_index(index, mtr); mtr_x_lock_index(index, mtr);
else goto index_locked;
}
}
mtr_sx_lock_index(index, mtr); mtr_sx_lock_index(index, mtr);
} }
else else
@@ -1841,9 +1872,11 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
} }
} }
index_locked:
ut_ad(savepoint == mtr->get_savepoint()); ut_ad(savepoint == mtr->get_savepoint());
const rw_lock_type_t root_leaf_rw_latch= rw_lock_type_t(latch_mode & ~12); const rw_lock_type_t root_leaf_rw_latch=
rw_lock_type_t(latch_mode & (RW_S_LATCH | RW_X_LATCH));
page_cur.index = index; page_cur.index = index;
@@ -1914,16 +1947,29 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
!btr_block_get(*index, btr_page_get_next(block->page.frame), !btr_block_get(*index, btr_page_get_next(block->page.frame),
RW_X_LATCH, false, mtr, &err)) RW_X_LATCH, false, mtr, &err))
break; break;
if (!index->lock.have_x() &&
btr_cur_need_opposite_intention(block->page.frame,
lock_intention,
node_ptr_max_size,
compress_limit, page_cur.rec))
goto need_opposite_intention;
} }
else else
{ {
if (rw_latch == RW_NO_LATCH) if (rw_latch == RW_NO_LATCH)
mtr->upgrade_buffer_fix(leaf_savepoint - 1, mtr->upgrade_buffer_fix(leaf_savepoint - 1,
rw_lock_type_t(latch_mode)); rw_lock_type_t(latch_mode &
(RW_X_LATCH | RW_S_LATCH)));
if (latch_mode != BTR_CONT_MODIFY_TREE)
{
ut_ad(latch_mode == BTR_MODIFY_LEAF ||
latch_mode == BTR_SEARCH_LEAF);
/* Release index->lock if needed, and the non-leaf pages. */ /* Release index->lock if needed, and the non-leaf pages. */
mtr->rollback_to_savepoint(savepoint - !latch_by_caller, mtr->rollback_to_savepoint(savepoint - !latch_by_caller,
leaf_savepoint - 1); leaf_savepoint - 1);
} }
}
break; break;
} }
} }
@@ -1944,22 +1990,25 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
: !page_cur_move_to_prev(&page_cur)) : !page_cur_move_to_prev(&page_cur))
goto corrupted; goto corrupted;
const rec_t *node_ptr= page_cur.rec; offsets= rec_get_offsets(page_cur.rec, index, offsets, 0, ULINT_UNDEFINED,
offsets= rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED,
&heap); &heap);
ut_ad(latch_mode != BTR_MODIFY_TREE || upper_rw_latch == RW_X_LATCH); ut_ad(latch_mode != BTR_MODIFY_TREE || upper_rw_latch == RW_X_LATCH);
if (latch_mode != BTR_MODIFY_TREE); if (latch_mode != BTR_MODIFY_TREE);
else if (btr_cur_need_opposite_intention(block->page.frame, else if (btr_cur_need_opposite_intention(block->page.frame, lock_intention,
lock_intention, node_ptr)) node_ptr_max_size, compress_limit,
page_cur.rec))
{ {
need_opposite_intention:
/* If the rec is the first or last in the page for pessimistic /* If the rec is the first or last in the page for pessimistic
delete intention, it might cause node_ptr insert for the upper delete intention, it might cause node_ptr insert for the upper
level. We should change the intention and retry. */ level. We should change the intention and retry. */
mtr->rollback_to_savepoint(savepoint); mtr->rollback_to_savepoint(savepoint);
lock_intention= BTR_INTENTION_BOTH; mtr->index_lock_upgrade();
/* X-latch all pages from now on */
latch_mode= BTR_CONT_MODIFY_TREE;
page= index->page; page= index->page;
height= ULINT_UNDEFINED; height= ULINT_UNDEFINED;
n_blocks= 0; n_blocks= 0;
@@ -1968,7 +2017,7 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
else else
{ {
if (!btr_cur_will_modify_tree(index, block->page.frame, if (!btr_cur_will_modify_tree(index, block->page.frame,
lock_intention, node_ptr, lock_intention, page_cur.rec,
node_ptr_max_size, zip_size, mtr)) node_ptr_max_size, zip_size, mtr))
{ {
ut_ad(n_blocks); ut_ad(n_blocks);
@@ -1998,7 +2047,7 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
} }
/* Go to the child node */ /* Go to the child node */
page= btr_node_ptr_get_child_page_no(node_ptr, offsets); page= btr_node_ptr_get_child_page_no(page_cur.rec, offsets);
n_blocks++; n_blocks++;
} }
@@ -2308,8 +2357,7 @@ convert_big_rec:
return(DB_TOO_BIG_RECORD); return(DB_TOO_BIG_RECORD);
} }
LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page), LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page), goto fail);
goto fail);
if (block->page.zip.data && leaf if (block->page.zip.data && leaf
&& (page_get_data_size(page) + rec_size && (page_get_data_size(page) + rec_size
@@ -2323,7 +2371,7 @@ fail:
/* prefetch siblings of the leaf for the pessimistic /* prefetch siblings of the leaf for the pessimistic
operation, if the page is leaf. */ operation, if the page is leaf. */
if (page_is_leaf(page)) { if (leaf) {
btr_cur_prefetch_siblings(block, index); btr_cur_prefetch_siblings(block, index);
} }
fail_err: fail_err:
@@ -2392,7 +2440,7 @@ fail_err:
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
if (!(flags & BTR_CREATE_FLAG) if (!(flags & BTR_CREATE_FLAG)
&& index->is_primary() && page_is_leaf(page)) { && leaf && index->is_primary()) {
const dfield_t* trx_id = dtuple_get_nth_field( const dfield_t* trx_id = dtuple_get_nth_field(
entry, dict_col_get_clust_pos( entry, dict_col_get_clust_pos(
dict_table_get_sys_col(index->table, dict_table_get_sys_col(index->table,

View File

@@ -409,7 +409,6 @@ static bool buf_page_decrypt_after_read(buf_page_t *bpage,
if (id.space() == SRV_TMP_SPACE_ID if (id.space() == SRV_TMP_SPACE_ID
&& innodb_encrypt_temporary_tables) { && innodb_encrypt_temporary_tables) {
slot = buf_pool.io_buf_reserve(); slot = buf_pool.io_buf_reserve();
ut_a(slot);
slot->allocate(); slot->allocate();
bool ok = buf_tmp_page_decrypt(slot->crypt_buf, dst_frame); bool ok = buf_tmp_page_decrypt(slot->crypt_buf, dst_frame);
slot->release(); slot->release();
@@ -432,7 +431,6 @@ decompress:
} }
slot = buf_pool.io_buf_reserve(); slot = buf_pool.io_buf_reserve();
ut_a(slot);
slot->allocate(); slot->allocate();
decompress_with_slot: decompress_with_slot:
@@ -456,7 +454,6 @@ decrypt_failed:
} }
slot = buf_pool.io_buf_reserve(); slot = buf_pool.io_buf_reserve();
ut_a(slot);
slot->allocate(); slot->allocate();
/* decrypt using crypt_buf to dst_frame */ /* decrypt using crypt_buf to dst_frame */
@@ -1287,6 +1284,41 @@ inline bool buf_pool_t::realloc(buf_block_t *block)
return(true); /* free_list was enough */ return(true); /* free_list was enough */
} }
void buf_pool_t::io_buf_t::create(ulint n_slots)
{
this->n_slots= n_slots;
slots= static_cast<buf_tmp_buffer_t*>
(ut_malloc_nokey(n_slots * sizeof *slots));
memset((void*) slots, 0, n_slots * sizeof *slots);
}
void buf_pool_t::io_buf_t::close()
{
for (buf_tmp_buffer_t *s= slots, *e= slots + n_slots; s != e; s++)
{
aligned_free(s->crypt_buf);
aligned_free(s->comp_buf);
}
ut_free(slots);
slots= nullptr;
n_slots= 0;
}
buf_tmp_buffer_t *buf_pool_t::io_buf_t::reserve()
{
for (;;)
{
for (buf_tmp_buffer_t *s= slots, *e= slots + n_slots; s != e; s++)
if (s->acquire())
return s;
os_aio_wait_until_no_pending_writes();
for (buf_tmp_buffer_t *s= slots, *e= slots + n_slots; s != e; s++)
if (s->acquire())
return s;
os_aio_wait_until_no_pending_reads();
}
}
/** Sets the global variable that feeds MySQL's innodb_buffer_pool_resize_status /** Sets the global variable that feeds MySQL's innodb_buffer_pool_resize_status
to the specified string. The format and the following parameters are the to the specified string. The format and the following parameters are the
same as the ones used for printf(3). same as the ones used for printf(3).
@@ -1353,21 +1385,25 @@ inline bool buf_pool_t::withdraw_blocks()
block = next_block; block = next_block;
} }
mysql_mutex_unlock(&mutex);
/* reserve free_list length */ /* reserve free_list length */
if (UT_LIST_GET_LEN(withdraw) < withdraw_target) { if (UT_LIST_GET_LEN(withdraw) < withdraw_target) {
buf_flush_LRU( buf_flush_LRU(
std::max<ulint>(withdraw_target std::max<ulint>(withdraw_target
- UT_LIST_GET_LEN(withdraw), - UT_LIST_GET_LEN(withdraw),
srv_LRU_scan_depth)); srv_LRU_scan_depth),
buf_flush_wait_batch_end_acquiring_mutex(true); true);
mysql_mutex_unlock(&buf_pool.mutex);
buf_dblwr.flush_buffered_writes();
mysql_mutex_lock(&buf_pool.flush_list_mutex);
buf_flush_wait_LRU_batch_end();
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
mysql_mutex_lock(&buf_pool.mutex);
} }
/* relocate blocks/buddies in withdrawn area */ /* relocate blocks/buddies in withdrawn area */
ulint count2 = 0; ulint count2 = 0;
mysql_mutex_lock(&mutex);
buf_pool_mutex_exit_forbid(); buf_pool_mutex_exit_forbid();
for (buf_page_t* bpage = UT_LIST_GET_FIRST(LRU), *next_bpage; for (buf_page_t* bpage = UT_LIST_GET_FIRST(LRU), *next_bpage;
bpage; bpage = next_bpage) { bpage; bpage = next_bpage) {
@@ -2220,13 +2256,15 @@ lookup:
return bpage; return bpage;
must_read_page: must_read_page:
if (dberr_t err= buf_read_page(page_id, zip_size)) switch (dberr_t err= buf_read_page(page_id, zip_size)) {
{ case DB_SUCCESS:
case DB_SUCCESS_LOCKED_REC:
goto lookup;
default:
ib::error() << "Reading compressed page " << page_id ib::error() << "Reading compressed page " << page_id
<< " failed with error: " << err; << " failed with error: " << err;
return nullptr; return nullptr;
} }
goto lookup;
} }
/********************************************************************//** /********************************************************************//**
@@ -2369,11 +2407,6 @@ buf_page_get_low(
|| (rw_latch == RW_X_LATCH) || (rw_latch == RW_X_LATCH)
|| (rw_latch == RW_SX_LATCH) || (rw_latch == RW_SX_LATCH)
|| (rw_latch == RW_NO_LATCH)); || (rw_latch == RW_NO_LATCH));
ut_ad(!allow_ibuf_merge
|| mode == BUF_GET
|| mode == BUF_GET_POSSIBLY_FREED
|| mode == BUF_GET_IF_IN_POOL
|| mode == BUF_GET_IF_IN_POOL_OR_WATCH);
if (err) { if (err) {
*err = DB_SUCCESS; *err = DB_SUCCESS;
@@ -2381,15 +2414,15 @@ buf_page_get_low(
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
switch (mode) { switch (mode) {
case BUF_PEEK_IF_IN_POOL: default:
ut_ad(!allow_ibuf_merge);
ut_ad(mode == BUF_PEEK_IF_IN_POOL);
break;
case BUF_GET_POSSIBLY_FREED:
case BUF_GET_IF_IN_POOL: case BUF_GET_IF_IN_POOL:
/* The caller may pass a dummy page size, /* The caller may pass a dummy page size,
because it does not really matter. */ because it does not really matter. */
break; break;
default:
MY_ASSERT_UNREACHABLE();
case BUF_GET_POSSIBLY_FREED:
break;
case BUF_GET: case BUF_GET:
case BUF_GET_IF_IN_POOL_OR_WATCH: case BUF_GET_IF_IN_POOL_OR_WATCH:
ut_ad(!mtr->is_freeing_tree()); ut_ad(!mtr->is_freeing_tree());
@@ -2471,21 +2504,24 @@ loop:
corrupted, or if an encrypted page with a valid corrupted, or if an encrypted page with a valid
checksum cannot be decypted. */ checksum cannot be decypted. */
if (dberr_t local_err = buf_read_page(page_id, zip_size)) { switch (dberr_t local_err = buf_read_page(page_id, zip_size)) {
if (local_err != DB_CORRUPTION case DB_SUCCESS:
&& mode != BUF_GET_POSSIBLY_FREED case DB_SUCCESS_LOCKED_REC:
buf_read_ahead_random(page_id, zip_size, ibuf_inside(mtr));
break;
default:
if (mode != BUF_GET_POSSIBLY_FREED
&& retries++ < BUF_PAGE_READ_MAX_RETRIES) { && retries++ < BUF_PAGE_READ_MAX_RETRIES) {
DBUG_EXECUTE_IF("intermittent_read_failure", DBUG_EXECUTE_IF("intermittent_read_failure",
retries = BUF_PAGE_READ_MAX_RETRIES;); retries = BUF_PAGE_READ_MAX_RETRIES;);
} else { }
/* fall through */
case DB_PAGE_CORRUPTED:
if (err) { if (err) {
*err = local_err; *err = local_err;
} }
return nullptr; return nullptr;
} }
} else {
buf_read_ahead_random(page_id, zip_size, ibuf_inside(mtr));
}
ut_d(if (!(++buf_dbg_counter % 5771)) buf_pool.validate()); ut_d(if (!(++buf_dbg_counter % 5771)) buf_pool.validate());
goto loop; goto loop;
@@ -2541,6 +2577,7 @@ ignore_block:
mysql_mutex_lock(&buf_pool.mutex); mysql_mutex_lock(&buf_pool.mutex);
block->unfix(); block->unfix();
free_unfixed_block:
if (!buf_LRU_free_page(&block->page, true)) { if (!buf_LRU_free_page(&block->page, true)) {
ut_ad(0); ut_ad(0);
} }
@@ -2656,20 +2693,19 @@ wait_for_unfix:
/* Decompress the page while not holding /* Decompress the page while not holding
buf_pool.mutex. */ buf_pool.mutex. */
auto ok = buf_zip_decompress(block, false); const auto ok = buf_zip_decompress(block, false);
block->page.read_unfix(state);
state = block->page.state();
block->page.lock.x_unlock();
--buf_pool.n_pend_unzip; --buf_pool.n_pend_unzip;
if (!ok) { if (!ok) {
/* FIXME: Evict the corrupted
ROW_FORMAT=COMPRESSED page! */
if (err) { if (err) {
*err = DB_PAGE_CORRUPTED; *err = DB_PAGE_CORRUPTED;
} }
return nullptr; mysql_mutex_lock(&buf_pool.mutex);
}
state = block->page.read_unfix(state);
block->page.lock.x_unlock();
if (!ok) {
goto free_unfixed_block;
} }
} }
@@ -2875,9 +2911,11 @@ buf_page_get_gen(
dberr_t* err, dberr_t* err,
bool allow_ibuf_merge) bool allow_ibuf_merge)
{ {
if (buf_block_t *block= recv_sys.recover(page_id)) buf_block_t *block= recv_sys.recover(page_id);
{ if (UNIV_LIKELY(!block))
if (UNIV_UNLIKELY(block == reinterpret_cast<buf_block_t*>(-1))) return buf_page_get_low(page_id, zip_size, rw_latch,
guess, mode, mtr, err, allow_ibuf_merge);
else if (UNIV_UNLIKELY(block == reinterpret_cast<buf_block_t*>(-1)))
{ {
corrupted: corrupted:
if (err) if (err)
@@ -2898,7 +2936,10 @@ buf_page_get_gen(
{ {
got_freed_page: got_freed_page:
ut_ad(mode == BUF_GET_POSSIBLY_FREED || mode == BUF_PEEK_IF_IN_POOL); ut_ad(mode == BUF_GET_POSSIBLY_FREED || mode == BUF_PEEK_IF_IN_POOL);
mysql_mutex_lock(&buf_pool.mutex);
block->page.unfix(); block->page.unfix();
buf_LRU_free_page(&block->page, true);
mysql_mutex_unlock(&buf_pool.mutex);
goto corrupted; goto corrupted;
} }
else if (must_merge && else if (must_merge &&
@@ -2939,10 +2980,6 @@ buf_page_get_gen(
return block; return block;
} }
return buf_page_get_low(page_id, zip_size, rw_latch,
guess, mode, mtr, err, allow_ibuf_merge);
}
/********************************************************************//** /********************************************************************//**
This is the general function used to get optimistic access to a database This is the general function used to get optimistic access to a database
page. page.
@@ -3238,12 +3275,12 @@ retry:
buf_unzip_LRU_add_block(reinterpret_cast<buf_block_t*>(bpage), FALSE); buf_unzip_LRU_add_block(reinterpret_cast<buf_block_t*>(bpage), FALSE);
} }
buf_pool.stat.n_pages_created++;
mysql_mutex_unlock(&buf_pool.mutex); mysql_mutex_unlock(&buf_pool.mutex);
mtr->memo_push(reinterpret_cast<buf_block_t*>(bpage), MTR_MEMO_PAGE_X_FIX); mtr->memo_push(reinterpret_cast<buf_block_t*>(bpage), MTR_MEMO_PAGE_X_FIX);
bpage->set_accessed(); bpage->set_accessed();
buf_pool.stat.n_pages_created++;
/* Delete possible entries for the page from the insert buffer: /* Delete possible entries for the page from the insert buffer:
such can exist if the page belonged to an index which was dropped */ such can exist if the page belonged to an index which was dropped */
@@ -3493,7 +3530,6 @@ dberr_t buf_page_t::read_complete(const fil_node_t &node)
ut_d(auto n=) buf_pool.n_pend_reads--; ut_d(auto n=) buf_pool.n_pend_reads--;
ut_ad(n > 0); ut_ad(n > 0);
buf_pool.stat.n_pages_read++;
const byte *read_frame= zip.data ? zip.data : frame; const byte *read_frame= zip.data ? zip.data : frame;
ut_ad(read_frame); ut_ad(read_frame);
@@ -3645,9 +3681,6 @@ void buf_pool_invalidate()
{ {
mysql_mutex_lock(&buf_pool.mutex); mysql_mutex_lock(&buf_pool.mutex);
buf_flush_wait_batch_end(true);
buf_flush_wait_batch_end(false);
/* It is possible that a write batch that has been posted /* It is possible that a write batch that has been posted
earlier is still not complete. For buffer pool invalidation to earlier is still not complete. For buffer pool invalidation to
proceed we must ensure there is NO write activity happening. */ proceed we must ensure there is NO write activity happening. */
@@ -3798,8 +3831,8 @@ void buf_pool_t::print()
<< UT_LIST_GET_LEN(flush_list) << UT_LIST_GET_LEN(flush_list)
<< ", n pending decompressions=" << n_pend_unzip << ", n pending decompressions=" << n_pend_unzip
<< ", n pending reads=" << n_pend_reads << ", n pending reads=" << n_pend_reads
<< ", n pending flush LRU=" << n_flush_LRU_ << ", n pending flush LRU=" << n_flush()
<< " list=" << n_flush_list_ << " list=" << buf_dblwr.pending_writes()
<< ", pages made young=" << stat.n_pages_made_young << ", pages made young=" << stat.n_pages_made_young
<< ", not young=" << stat.n_pages_not_made_young << ", not young=" << stat.n_pages_not_made_young
<< ", pages read=" << stat.n_pages_read << ", pages read=" << stat.n_pages_read
@@ -3911,13 +3944,13 @@ void buf_stats_get_pool_info(buf_pool_info_t *pool_info)
pool_info->flush_list_len = UT_LIST_GET_LEN(buf_pool.flush_list); pool_info->flush_list_len = UT_LIST_GET_LEN(buf_pool.flush_list);
pool_info->n_pend_unzip = UT_LIST_GET_LEN(buf_pool.unzip_LRU); pool_info->n_pend_unzip = UT_LIST_GET_LEN(buf_pool.unzip_LRU);
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
pool_info->n_pend_reads = buf_pool.n_pend_reads; pool_info->n_pend_reads = buf_pool.n_pend_reads;
pool_info->n_pending_flush_lru = buf_pool.n_flush_LRU_; pool_info->n_pending_flush_lru = buf_pool.n_flush();
pool_info->n_pending_flush_list = buf_pool.n_flush_list_; pool_info->n_pending_flush_list = buf_dblwr.pending_writes();
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
current_time = time(NULL); current_time = time(NULL);
time_elapsed = 0.001 + difftime(current_time, time_elapsed = 0.001 + difftime(current_time,

View File

@@ -46,7 +46,17 @@ inline buf_block_t *buf_dblwr_trx_sys_get(mtr_t *mtr)
0, RW_X_LATCH, mtr); 0, RW_X_LATCH, mtr);
} }
/** Initialize the doublewrite buffer data structure. void buf_dblwr_t::init()
{
if (!active_slot)
{
active_slot= &slots[0];
mysql_mutex_init(buf_dblwr_mutex_key, &mutex, nullptr);
pthread_cond_init(&cond, nullptr);
}
}
/** Initialise the persistent storage of the doublewrite buffer.
@param header doublewrite page header in the TRX_SYS page */ @param header doublewrite page header in the TRX_SYS page */
inline void buf_dblwr_t::init(const byte *header) inline void buf_dblwr_t::init(const byte *header)
{ {
@@ -54,8 +64,6 @@ inline void buf_dblwr_t::init(const byte *header)
ut_ad(!active_slot->reserved); ut_ad(!active_slot->reserved);
ut_ad(!batch_running); ut_ad(!batch_running);
mysql_mutex_init(buf_dblwr_mutex_key, &mutex, nullptr);
pthread_cond_init(&cond, nullptr);
block1= page_id_t(0, mach_read_from_4(header + TRX_SYS_DOUBLEWRITE_BLOCK1)); block1= page_id_t(0, mach_read_from_4(header + TRX_SYS_DOUBLEWRITE_BLOCK1));
block2= page_id_t(0, mach_read_from_4(header + TRX_SYS_DOUBLEWRITE_BLOCK2)); block2= page_id_t(0, mach_read_from_4(header + TRX_SYS_DOUBLEWRITE_BLOCK2));
@@ -74,7 +82,7 @@ inline void buf_dblwr_t::init(const byte *header)
@return whether the operation succeeded */ @return whether the operation succeeded */
bool buf_dblwr_t::create() bool buf_dblwr_t::create()
{ {
if (is_initialised()) if (is_created())
return true; return true;
mtr_t mtr; mtr_t mtr;
@@ -341,7 +349,7 @@ func_exit:
void buf_dblwr_t::recover() void buf_dblwr_t::recover()
{ {
ut_ad(log_sys.last_checkpoint_lsn); ut_ad(log_sys.last_checkpoint_lsn);
if (!is_initialised()) if (!is_created())
return; return;
uint32_t page_no_dblwr= 0; uint32_t page_no_dblwr= 0;
@@ -450,10 +458,9 @@ next_page:
/** Free the doublewrite buffer. */ /** Free the doublewrite buffer. */
void buf_dblwr_t::close() void buf_dblwr_t::close()
{ {
if (!is_initialised()) if (!active_slot)
return; return;
/* Free the double write data structures. */
ut_ad(!active_slot->reserved); ut_ad(!active_slot->reserved);
ut_ad(!active_slot->first_free); ut_ad(!active_slot->first_free);
ut_ad(!batch_running); ut_ad(!batch_running);
@@ -467,19 +474,24 @@ void buf_dblwr_t::close()
mysql_mutex_destroy(&mutex); mysql_mutex_destroy(&mutex);
memset((void*) this, 0, sizeof *this); memset((void*) this, 0, sizeof *this);
active_slot= &slots[0];
} }
/** Update the doublewrite buffer on write completion. */ /** Update the doublewrite buffer on write completion. */
void buf_dblwr_t::write_completed() void buf_dblwr_t::write_completed(bool with_doublewrite)
{ {
ut_ad(this == &buf_dblwr); ut_ad(this == &buf_dblwr);
ut_ad(srv_use_doublewrite_buf);
ut_ad(is_initialised());
ut_ad(!srv_read_only_mode); ut_ad(!srv_read_only_mode);
mysql_mutex_lock(&mutex); mysql_mutex_lock(&mutex);
ut_ad(writes_pending);
if (!--writes_pending)
pthread_cond_broadcast(&write_cond);
if (with_doublewrite)
{
ut_ad(is_created());
ut_ad(srv_use_doublewrite_buf);
ut_ad(batch_running); ut_ad(batch_running);
slot *flush_slot= active_slot == &slots[0] ? &slots[1] : &slots[0]; slot *flush_slot= active_slot == &slots[0] ? &slots[1] : &slots[0];
ut_ad(flush_slot->reserved); ut_ad(flush_slot->reserved);
@@ -497,6 +509,7 @@ void buf_dblwr_t::write_completed()
batch_running= false; batch_running= false;
pthread_cond_broadcast(&cond); pthread_cond_broadcast(&cond);
} }
}
mysql_mutex_unlock(&mutex); mysql_mutex_unlock(&mutex);
} }
@@ -640,7 +653,7 @@ void buf_dblwr_t::flush_buffered_writes_completed(const IORequest &request)
{ {
ut_ad(this == &buf_dblwr); ut_ad(this == &buf_dblwr);
ut_ad(srv_use_doublewrite_buf); ut_ad(srv_use_doublewrite_buf);
ut_ad(is_initialised()); ut_ad(is_created());
ut_ad(!srv_read_only_mode); ut_ad(!srv_read_only_mode);
ut_ad(!request.bpage); ut_ad(!request.bpage);
ut_ad(request.node == fil_system.sys_space->chain.start); ut_ad(request.node == fil_system.sys_space->chain.start);
@@ -706,7 +719,7 @@ posted, and also when we may have to wait for a page latch!
Otherwise a deadlock of threads can occur. */ Otherwise a deadlock of threads can occur. */
void buf_dblwr_t::flush_buffered_writes() void buf_dblwr_t::flush_buffered_writes()
{ {
if (!is_initialised() || !srv_use_doublewrite_buf) if (!is_created() || !srv_use_doublewrite_buf)
{ {
fil_flush_file_spaces(); fil_flush_file_spaces();
return; return;
@@ -739,6 +752,7 @@ void buf_dblwr_t::add_to_batch(const IORequest &request, size_t size)
const ulint buf_size= 2 * block_size(); const ulint buf_size= 2 * block_size();
mysql_mutex_lock(&mutex); mysql_mutex_lock(&mutex);
writes_pending++;
for (;;) for (;;)
{ {

File diff suppressed because it is too large Load Diff

View File

@@ -136,7 +136,6 @@ static void buf_LRU_block_free_hashed_page(buf_block_t *block)
@param[in] bpage control block */ @param[in] bpage control block */
static inline void incr_LRU_size_in_bytes(const buf_page_t* bpage) static inline void incr_LRU_size_in_bytes(const buf_page_t* bpage)
{ {
/* FIXME: use atomics, not mutex */
mysql_mutex_assert_owner(&buf_pool.mutex); mysql_mutex_assert_owner(&buf_pool.mutex);
buf_pool.stat.LRU_bytes += bpage->physical_size(); buf_pool.stat.LRU_bytes += bpage->physical_size();
@@ -400,8 +399,10 @@ buf_block_t *buf_LRU_get_free_block(bool have_mutex)
DBUG_EXECUTE_IF("recv_ran_out_of_buffer", DBUG_EXECUTE_IF("recv_ran_out_of_buffer",
if (recv_recovery_is_on() if (recv_recovery_is_on()
&& recv_sys.apply_log_recs) { && recv_sys.apply_log_recs) {
mysql_mutex_lock(&buf_pool.mutex);
goto flush_lru; goto flush_lru;
}); });
get_mutex:
mysql_mutex_lock(&buf_pool.mutex); mysql_mutex_lock(&buf_pool.mutex);
got_mutex: got_mutex:
buf_LRU_check_size_of_non_data_objects(); buf_LRU_check_size_of_non_data_objects();
@@ -444,20 +445,32 @@ got_block:
if ((block = buf_LRU_get_free_only()) != nullptr) { if ((block = buf_LRU_get_free_only()) != nullptr) {
goto got_block; goto got_block;
} }
if (!buf_pool.n_flush_LRU_) {
break;
}
my_cond_wait(&buf_pool.done_free, &buf_pool.mutex.m_mutex);
}
#ifndef DBUG_OFF
not_found:
#endif
mysql_mutex_unlock(&buf_pool.mutex); mysql_mutex_unlock(&buf_pool.mutex);
mysql_mutex_lock(&buf_pool.flush_list_mutex);
const auto n_flush = buf_pool.n_flush();
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
mysql_mutex_lock(&buf_pool.mutex);
if (!n_flush) {
goto not_found;
}
if (!buf_pool.try_LRU_scan) {
mysql_mutex_lock(&buf_pool.flush_list_mutex);
buf_pool.page_cleaner_wakeup(true);
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
my_cond_wait(&buf_pool.done_free,
&buf_pool.mutex.m_mutex);
}
}
if (n_iterations > 20 && !buf_lru_free_blocks_error_printed not_found:
if (n_iterations > 1) {
MONITOR_INC( MONITOR_LRU_GET_FREE_WAITS );
}
if (n_iterations == 21 && !buf_lru_free_blocks_error_printed
&& srv_buf_pool_old_size == srv_buf_pool_size) { && srv_buf_pool_old_size == srv_buf_pool_size) {
buf_lru_free_blocks_error_printed = true;
mysql_mutex_unlock(&buf_pool.mutex);
ib::warn() << "Difficult to find free blocks in the buffer pool" ib::warn() << "Difficult to find free blocks in the buffer pool"
" (" << n_iterations << " search iterations)! " " (" << n_iterations << " search iterations)! "
<< flush_failures << " failed attempts to" << flush_failures << " failed attempts to"
@@ -469,12 +482,7 @@ not_found:
<< os_n_file_writes << " OS file writes, " << os_n_file_writes << " OS file writes, "
<< os_n_fsyncs << os_n_fsyncs
<< " OS fsyncs."; << " OS fsyncs.";
mysql_mutex_lock(&buf_pool.mutex);
buf_lru_free_blocks_error_printed = true;
}
if (n_iterations > 1) {
MONITOR_INC( MONITOR_LRU_GET_FREE_WAITS );
} }
/* No free block was found: try to flush the LRU list. /* No free block was found: try to flush the LRU list.
@@ -488,15 +496,16 @@ not_found:
#ifndef DBUG_OFF #ifndef DBUG_OFF
flush_lru: flush_lru:
#endif #endif
if (!buf_flush_LRU(innodb_lru_flush_size)) { if (!buf_flush_LRU(innodb_lru_flush_size, true)) {
MONITOR_INC(MONITOR_LRU_SINGLE_FLUSH_FAILURE_COUNT); MONITOR_INC(MONITOR_LRU_SINGLE_FLUSH_FAILURE_COUNT);
++flush_failures; ++flush_failures;
} }
n_iterations++; n_iterations++;
mysql_mutex_lock(&buf_pool.mutex);
buf_pool.stat.LRU_waits++; buf_pool.stat.LRU_waits++;
goto got_mutex; mysql_mutex_unlock(&buf_pool.mutex);
buf_dblwr.flush_buffered_writes();
goto get_mutex;
} }
/** Move the LRU_old pointer so that the length of the old blocks list /** Move the LRU_old pointer so that the length of the old blocks list
@@ -805,50 +814,57 @@ bool buf_LRU_free_page(buf_page_t *bpage, bool zip)
/* We cannot use transactional_lock_guard here, /* We cannot use transactional_lock_guard here,
because buf_buddy_relocate() in buf_buddy_free() could get stuck. */ because buf_buddy_relocate() in buf_buddy_free() could get stuck. */
hash_lock.lock(); hash_lock.lock();
lsn_t oldest_modification = bpage->oldest_modification_acquire(); const lsn_t oldest_modification = bpage->oldest_modification_acquire();
if (UNIV_UNLIKELY(!bpage->can_relocate())) { if (UNIV_UNLIKELY(!bpage->can_relocate())) {
/* Do not free buffer fixed and I/O-fixed blocks. */ /* Do not free buffer fixed and I/O-fixed blocks. */
goto func_exit; goto func_exit;
} }
if (oldest_modification == 1) { switch (oldest_modification) {
case 2:
ut_ad(id.space() == SRV_TMP_SPACE_ID);
ut_ad(!bpage->zip.data);
if (!bpage->is_freed()) {
goto func_exit;
}
bpage->clear_oldest_modification();
break;
case 1:
mysql_mutex_lock(&buf_pool.flush_list_mutex); mysql_mutex_lock(&buf_pool.flush_list_mutex);
oldest_modification = bpage->oldest_modification(); if (const lsn_t om = bpage->oldest_modification()) {
if (oldest_modification) { ut_ad(om == 1);
ut_ad(oldest_modification == 1);
buf_pool.delete_from_flush_list(bpage); buf_pool.delete_from_flush_list(bpage);
} }
mysql_mutex_unlock(&buf_pool.flush_list_mutex); mysql_mutex_unlock(&buf_pool.flush_list_mutex);
ut_ad(!bpage->oldest_modification()); ut_ad(!bpage->oldest_modification());
oldest_modification = 0; /* fall through */
case 0:
if (zip || !bpage->zip.data || !bpage->frame) {
break;
} }
relocate_compressed:
if (zip || !bpage->zip.data) {
/* This would completely free the block. */
/* Do not completely free dirty blocks. */
if (oldest_modification) {
goto func_exit;
}
} else if (oldest_modification && !bpage->frame) {
func_exit:
hash_lock.unlock();
return(false);
} else if (bpage->frame) {
b = static_cast<buf_page_t*>(ut_zalloc_nokey(sizeof *b)); b = static_cast<buf_page_t*>(ut_zalloc_nokey(sizeof *b));
ut_a(b); ut_a(b);
mysql_mutex_lock(&buf_pool.flush_list_mutex); mysql_mutex_lock(&buf_pool.flush_list_mutex);
new (b) buf_page_t(*bpage); new (b) buf_page_t(*bpage);
b->frame = nullptr; b->frame = nullptr;
b->set_state(buf_page_t::UNFIXED + 1); b->set_state(buf_page_t::UNFIXED + 1);
break;
default:
if (zip || !bpage->zip.data || !bpage->frame) {
/* This would completely free the block. */
/* Do not completely free dirty blocks. */
func_exit:
hash_lock.unlock();
return(false);
}
goto relocate_compressed;
} }
mysql_mutex_assert_owner(&buf_pool.mutex); mysql_mutex_assert_owner(&buf_pool.mutex);
DBUG_PRINT("ib_buf", ("free page %u:%u", DBUG_PRINT("ib_buf", ("free page %u:%u", id.space(), id.page_no()));
id.space(), id.page_no()));
ut_ad(bpage->can_relocate()); ut_ad(bpage->can_relocate());
@@ -1026,7 +1042,8 @@ buf_LRU_block_free_non_file_page(
} else { } else {
UT_LIST_ADD_FIRST(buf_pool.free, &block->page); UT_LIST_ADD_FIRST(buf_pool.free, &block->page);
ut_d(block->page.in_free_list = true); ut_d(block->page.in_free_list = true);
pthread_cond_signal(&buf_pool.done_free); buf_pool.try_LRU_scan= true;
pthread_cond_broadcast(&buf_pool.done_free);
} }
MEM_NOACCESS(block->page.frame, srv_page_size); MEM_NOACCESS(block->page.frame, srv_page_size);

View File

@@ -226,6 +226,7 @@ static buf_page_t* buf_page_init_for_read(ulint mode, const page_id_t page_id,
buf_LRU_add_block(bpage, true/* to old blocks */); buf_LRU_add_block(bpage, true/* to old blocks */);
} }
buf_pool.stat.n_pages_read++;
mysql_mutex_unlock(&buf_pool.mutex); mysql_mutex_unlock(&buf_pool.mutex);
buf_pool.n_pend_reads++; buf_pool.n_pend_reads++;
goto func_exit_no_mutex; goto func_exit_no_mutex;
@@ -245,20 +246,18 @@ buffer buf_pool if it is not already there, in which case does nothing.
Sets the io_fix flag and sets an exclusive lock on the buffer frame. The Sets the io_fix flag and sets an exclusive lock on the buffer frame. The
flag is cleared and the x-lock released by an i/o-handler thread. flag is cleared and the x-lock released by an i/o-handler thread.
@param[out] err DB_SUCCESS or DB_TABLESPACE_DELETED
if we are trying
to read from a non-existent tablespace
@param[in,out] space tablespace @param[in,out] space tablespace
@param[in] sync true if synchronous aio is desired @param[in] sync true if synchronous aio is desired
@param[in] mode BUF_READ_IBUF_PAGES_ONLY, ..., @param[in] mode BUF_READ_IBUF_PAGES_ONLY, ...,
@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] unzip true=request uncompressed page @param[in] unzip true=request uncompressed page
@return whether a read request was queued */ @return error code
@retval DB_SUCCESS if the page was read
@retval DB_SUCCESS_LOCKED_REC if the page exists in the buffer pool already */
static static
bool dberr_t
buf_read_page_low( buf_read_page_low(
dberr_t* err,
fil_space_t* space, fil_space_t* space,
bool sync, bool sync,
ulint mode, ulint mode,
@@ -268,15 +267,12 @@ buf_read_page_low(
{ {
buf_page_t* bpage; buf_page_t* bpage;
*err = DB_SUCCESS;
if (buf_dblwr.is_inside(page_id)) { if (buf_dblwr.is_inside(page_id)) {
ib::error() << "Trying to read doublewrite buffer page " ib::error() << "Trying to read doublewrite buffer page "
<< page_id; << page_id;
ut_ad(0); ut_ad(0);
nothing_read:
space->release(); space->release();
return false; return DB_PAGE_CORRUPTED;
} }
if (sync) { if (sync) {
@@ -299,8 +295,9 @@ nothing_read:
completed */ completed */
bpage = buf_page_init_for_read(mode, page_id, zip_size, unzip); bpage = buf_page_init_for_read(mode, page_id, zip_size, unzip);
if (bpage == NULL) { if (!bpage) {
goto nothing_read; space->release();
return DB_SUCCESS_LOCKED_REC;
} }
ut_ad(bpage->in_file()); ut_ad(bpage->in_file());
@@ -320,7 +317,6 @@ nothing_read:
? IORequest::READ_SYNC ? IORequest::READ_SYNC
: IORequest::READ_ASYNC), : IORequest::READ_ASYNC),
page_id.page_no() * len, len, dst, bpage); page_id.page_no() * len, len, dst, bpage);
*err = fio.err;
if (UNIV_UNLIKELY(fio.err != DB_SUCCESS)) { if (UNIV_UNLIKELY(fio.err != DB_SUCCESS)) {
ut_d(auto n=) buf_pool.n_pend_reads--; ut_d(auto n=) buf_pool.n_pend_reads--;
@@ -329,14 +325,14 @@ nothing_read:
} else if (sync) { } else if (sync) {
thd_wait_end(NULL); thd_wait_end(NULL);
/* The i/o was already completed in space->io() */ /* The i/o was already completed in space->io() */
*err = bpage->read_complete(*fio.node); fio.err = bpage->read_complete(*fio.node);
space->release(); space->release();
if (*err == DB_FAIL) { if (fio.err == DB_FAIL) {
*err = DB_PAGE_CORRUPTED; fio.err = DB_PAGE_CORRUPTED;
} }
} }
return true; return fio.err;
} }
/** 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
@@ -414,24 +410,26 @@ read_ahead:
continue; continue;
if (space->is_stopping()) if (space->is_stopping())
break; break;
dberr_t err;
space->reacquire(); space->reacquire();
if (buf_read_page_low(&err, space, false, ibuf_mode, i, zip_size, false)) if (buf_read_page_low(space, false, ibuf_mode, i, zip_size, false) ==
DB_SUCCESS)
count++; count++;
} }
if (count) if (count)
{
DBUG_PRINT("ib_buf", ("random read-ahead %zu pages from %s: %u", DBUG_PRINT("ib_buf", ("random read-ahead %zu pages from %s: %u",
count, space->chain.start->name, count, space->chain.start->name,
low.page_no())); low.page_no()));
space->release(); mysql_mutex_lock(&buf_pool.mutex);
/* Read ahead is considered one I/O operation for the purpose of /* Read ahead is considered one I/O operation for the purpose of
LRU policy decision. */ LRU policy decision. */
buf_LRU_stat_inc_io(); buf_LRU_stat_inc_io();
buf_pool.stat.n_ra_pages_read_rnd+= count; buf_pool.stat.n_ra_pages_read_rnd+= count;
srv_stats.buf_pool_reads.add(count); mysql_mutex_unlock(&buf_pool.mutex);
}
space->release();
return count; return count;
} }
@@ -441,8 +439,9 @@ 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] 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
@retval DB_SUCCESS if the page was read and is not corrupted, @retval DB_SUCCESS if the page was read and is not corrupted
@retval DB_PAGE_CORRUPTED if page based on checksum check is corrupted, @retval DB_SUCCESS_LOCKED_REC if the page was not read
@retval DB_PAGE_CORRUPTED if page based on checksum check is corrupted
@retval DB_DECRYPTION_FAILED if page post encryption checksum matches but @retval DB_DECRYPTION_FAILED if page post encryption checksum matches but
after decryption normal page checksum does not match. after decryption normal page checksum does not match.
@retval DB_TABLESPACE_DELETED if tablespace .ibd file is missing */ @retval DB_TABLESPACE_DELETED if tablespace .ibd file is missing */
@@ -456,13 +455,9 @@ dberr_t buf_read_page(const page_id_t page_id, ulint zip_size)
return DB_TABLESPACE_DELETED; return DB_TABLESPACE_DELETED;
} }
dberr_t err; buf_LRU_stat_inc_io(); /* NOT protected by buf_pool.mutex */
if (buf_read_page_low(&err, space, true, BUF_READ_ANY_PAGE, return buf_read_page_low(space, true, BUF_READ_ANY_PAGE,
page_id, zip_size, false)) page_id, zip_size, false);
srv_stats.buf_pool_reads.add(1);
buf_LRU_stat_inc_io();
return err;
} }
/** High-level function which reads a page asynchronously from a file to the /** High-level function which reads a page asynchronously from a file to the
@@ -475,12 +470,8 @@ released by the i/o-handler thread.
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) ulint zip_size)
{ {
dberr_t err; buf_read_page_low(space, false, BUF_READ_ANY_PAGE,
page_id, zip_size, false);
if (buf_read_page_low(&err, space, false, BUF_READ_ANY_PAGE,
page_id, zip_size, false)) {
srv_stats.buf_pool_reads.add(1);
}
/* We do not increment number of I/O operations used for LRU policy /* We do not increment number of I/O operations used for LRU policy
here (buf_LRU_stat_inc_io()). We use this in heuristics to decide here (buf_LRU_stat_inc_io()). We use this in heuristics to decide
@@ -638,23 +629,26 @@ failed:
continue; continue;
if (space->is_stopping()) if (space->is_stopping())
break; break;
dberr_t err;
space->reacquire(); space->reacquire();
count+= buf_read_page_low(&err, space, false, ibuf_mode, new_low, zip_size, if (buf_read_page_low(space, false, ibuf_mode, new_low, zip_size, false) ==
false); DB_SUCCESS)
count++;
} }
if (count) if (count)
{
DBUG_PRINT("ib_buf", ("random read-ahead %zu pages from %s: %u", DBUG_PRINT("ib_buf", ("random read-ahead %zu pages from %s: %u",
count, space->chain.start->name, count, space->chain.start->name,
new_low.page_no())); new_low.page_no()));
space->release(); mysql_mutex_lock(&buf_pool.mutex);
/* Read ahead is considered one I/O operation for the purpose of /* Read ahead is considered one I/O operation for the purpose of
LRU policy decision. */ LRU policy decision. */
buf_LRU_stat_inc_io(); buf_LRU_stat_inc_io();
buf_pool.stat.n_ra_pages_read+= count; buf_pool.stat.n_ra_pages_read+= count;
mysql_mutex_unlock(&buf_pool.mutex);
}
space->release();
return count; return count;
} }
@@ -707,13 +701,12 @@ void buf_read_recv_pages(uint32_t space_id, st_::span<uint32_t> page_nos)
} }
} }
dberr_t err;
space->reacquire(); space->reacquire();
buf_read_page_low(&err, space, false, switch (buf_read_page_low(space, false, BUF_READ_ANY_PAGE,
BUF_READ_ANY_PAGE, cur_page_id, zip_size, cur_page_id, zip_size, true)) {
true); case DB_SUCCESS: case DB_SUCCESS_LOCKED_REC:
break;
if (err != DB_SUCCESS) { default:
sql_print_error("InnoDB: Recovery failed to read page " sql_print_error("InnoDB: Recovery failed to read page "
UINT32PF " from %s", UINT32PF " from %s",
cur_page_id.page_no(), cur_page_id.page_no(),

View File

@@ -119,6 +119,9 @@ bool fil_space_t::try_to_close(bool print_info)
} }
node->close(); node->close();
fil_system.move_closed_last_to_space_list(node->space);
return true; return true;
} }
@@ -393,13 +396,7 @@ static bool fil_node_open_file_low(fil_node_t *node)
ut_ad(node->is_open()); ut_ad(node->is_open());
if (UNIV_LIKELY(!fil_system.freeze_space_list)) fil_system.move_opened_last_to_space_list(node->space);
{
/* Move the file last in fil_system.space_list, so that
fil_space_t::try_to_close() should close it as a last resort. */
fil_system.space_list.erase(space_list_t::iterator(node->space));
fil_system.space_list.push_back(*node->space);
}
fil_system.n_open++; fil_system.n_open++;
return true; return true;
@@ -796,7 +793,17 @@ pfs_os_file_t fil_system_t::detach(fil_space_t *space, bool detach_handle)
space->is_in_default_encrypt= false; space->is_in_default_encrypt= false;
default_encrypt_tables.remove(*space); default_encrypt_tables.remove(*space);
} }
space_list.erase(space_list_t::iterator(space));
{
space_list_t::iterator s= space_list_t::iterator(space);
if (space_list_last_opened == space)
{
space_list_t::iterator prev= s;
space_list_last_opened= &*--prev;
}
space_list.erase(s);
}
if (space == sys_space) if (space == sys_space)
sys_space= nullptr; sys_space= nullptr;
else if (space == temp_space) else if (space == temp_space)
@@ -915,12 +922,14 @@ bool fil_space_free(uint32_t id, bool x_latched)
@param purpose tablespace purpose @param purpose tablespace purpose
@param crypt_data encryption information @param crypt_data encryption information
@param mode encryption mode @param mode encryption mode
@param opened true if space files are opened
@return pointer to created tablespace, to be filled in with add() @return pointer to created tablespace, to be filled in with add()
@retval nullptr on failure (such as when the same tablespace exists) */ @retval nullptr on failure (such as when the same tablespace exists) */
fil_space_t *fil_space_t::create(uint32_t id, uint32_t flags, fil_space_t *fil_space_t::create(uint32_t id, uint32_t flags,
fil_type_t purpose, fil_type_t purpose,
fil_space_crypt_t *crypt_data, fil_space_crypt_t *crypt_data,
fil_encryption_t mode) fil_encryption_t mode,
bool opened)
{ {
fil_space_t* space; fil_space_t* space;
@@ -973,6 +982,9 @@ fil_space_t *fil_space_t::create(uint32_t id, uint32_t flags,
HASH_INSERT(fil_space_t, hash, &fil_system.spaces, id, space); HASH_INSERT(fil_space_t, hash, &fil_system.spaces, id, space);
if (opened)
fil_system.add_opened_last_to_space_list(space);
else
fil_system.space_list.push_back(*space); fil_system.space_list.push_back(*space);
switch (id) { switch (id) {
@@ -1294,6 +1306,15 @@ void fil_system_t::close()
#endif /* __linux__ */ #endif /* __linux__ */
} }
void fil_system_t::add_opened_last_to_space_list(fil_space_t *space)
{
if (UNIV_LIKELY(space_list_last_opened != nullptr))
space_list.insert(space_list_t::iterator(space_list_last_opened), *space);
else
space_list.push_back(*space);
space_list_last_opened= space;
}
/** Extend all open data files to the recovered size */ /** Extend all open data files to the recovered size */
ATTRIBUTE_COLD void fil_system_t::extend_to_recv_size() ATTRIBUTE_COLD void fil_system_t::extend_to_recv_size()
{ {
@@ -1917,7 +1938,7 @@ err_exit:
if (fil_space_t* space = fil_space_t::create(space_id, flags, if (fil_space_t* space = fil_space_t::create(space_id, flags,
FIL_TYPE_TABLESPACE, FIL_TYPE_TABLESPACE,
crypt_data, mode)) { crypt_data, mode, true)) {
fil_node_t* node = space->add(path, file, size, false, true); fil_node_t* node = space->add(path, file, size, false, true);
IF_WIN(node->find_metadata(), node->find_metadata(file, true)); IF_WIN(node->find_metadata(), node->find_metadata(file, true));
mtr.start(); mtr.start();

View File

@@ -1209,8 +1209,6 @@ after_insert:
ut_ad(!rec || rec_offs_validate(rec, cursor->index(), *offsets)); ut_ad(!rec || rec_offs_validate(rec, cursor->index(), *offsets));
#endif #endif
MONITOR_INC(MONITOR_INDEX_SPLIT);
return(rec); return(rec);
} }

View File

@@ -914,43 +914,37 @@ static SHOW_VAR innodb_status_variables[]= {
(char*) &export_vars.innodb_buffer_pool_resize_status, SHOW_CHAR}, (char*) &export_vars.innodb_buffer_pool_resize_status, SHOW_CHAR},
{"buffer_pool_load_incomplete", {"buffer_pool_load_incomplete",
&export_vars.innodb_buffer_pool_load_incomplete, SHOW_BOOL}, &export_vars.innodb_buffer_pool_load_incomplete, SHOW_BOOL},
{"buffer_pool_pages_data", {"buffer_pool_pages_data", &UT_LIST_GET_LEN(buf_pool.LRU), SHOW_SIZE_T},
&export_vars.innodb_buffer_pool_pages_data, SHOW_SIZE_T},
{"buffer_pool_bytes_data", {"buffer_pool_bytes_data",
&export_vars.innodb_buffer_pool_bytes_data, SHOW_SIZE_T}, &export_vars.innodb_buffer_pool_bytes_data, SHOW_SIZE_T},
{"buffer_pool_pages_dirty", {"buffer_pool_pages_dirty",
&export_vars.innodb_buffer_pool_pages_dirty, SHOW_SIZE_T}, &UT_LIST_GET_LEN(buf_pool.flush_list), SHOW_SIZE_T},
{"buffer_pool_bytes_dirty", {"buffer_pool_bytes_dirty", &buf_pool.flush_list_bytes, SHOW_SIZE_T},
&export_vars.innodb_buffer_pool_bytes_dirty, SHOW_SIZE_T}, {"buffer_pool_pages_flushed", &buf_pool.stat.n_pages_written, SHOW_SIZE_T},
{"buffer_pool_pages_flushed", &buf_flush_page_count, SHOW_SIZE_T}, {"buffer_pool_pages_free", &UT_LIST_GET_LEN(buf_pool.free), SHOW_SIZE_T},
{"buffer_pool_pages_free",
&export_vars.innodb_buffer_pool_pages_free, SHOW_SIZE_T},
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
{"buffer_pool_pages_latched", {"buffer_pool_pages_latched",
&export_vars.innodb_buffer_pool_pages_latched, SHOW_SIZE_T}, &export_vars.innodb_buffer_pool_pages_latched, SHOW_SIZE_T},
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
{"buffer_pool_pages_made_not_young", {"buffer_pool_pages_made_not_young",
&export_vars.innodb_buffer_pool_pages_made_not_young, SHOW_SIZE_T}, &buf_pool.stat.n_pages_not_made_young, SHOW_SIZE_T},
{"buffer_pool_pages_made_young", {"buffer_pool_pages_made_young",
&export_vars.innodb_buffer_pool_pages_made_young, SHOW_SIZE_T}, &buf_pool.stat.n_pages_made_young, SHOW_SIZE_T},
{"buffer_pool_pages_misc", {"buffer_pool_pages_misc",
&export_vars.innodb_buffer_pool_pages_misc, SHOW_SIZE_T}, &export_vars.innodb_buffer_pool_pages_misc, SHOW_SIZE_T},
{"buffer_pool_pages_old", {"buffer_pool_pages_old", &buf_pool.LRU_old_len, SHOW_SIZE_T},
&export_vars.innodb_buffer_pool_pages_old, SHOW_SIZE_T},
{"buffer_pool_pages_total", {"buffer_pool_pages_total",
&export_vars.innodb_buffer_pool_pages_total, SHOW_SIZE_T}, &export_vars.innodb_buffer_pool_pages_total, SHOW_SIZE_T},
{"buffer_pool_pages_LRU_flushed", &buf_lru_flush_page_count, SHOW_SIZE_T}, {"buffer_pool_pages_LRU_flushed", &buf_lru_flush_page_count, SHOW_SIZE_T},
{"buffer_pool_pages_LRU_freed", &buf_lru_freed_page_count, SHOW_SIZE_T}, {"buffer_pool_pages_LRU_freed", &buf_lru_freed_page_count, SHOW_SIZE_T},
{"buffer_pool_pages_split", &buf_pool.pages_split, SHOW_SIZE_T},
{"buffer_pool_read_ahead_rnd", {"buffer_pool_read_ahead_rnd",
&export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_SIZE_T}, &buf_pool.stat.n_ra_pages_read_rnd, SHOW_SIZE_T},
{"buffer_pool_read_ahead", {"buffer_pool_read_ahead", &buf_pool.stat.n_ra_pages_read, SHOW_SIZE_T},
&export_vars.innodb_buffer_pool_read_ahead, SHOW_SIZE_T},
{"buffer_pool_read_ahead_evicted", {"buffer_pool_read_ahead_evicted",
&export_vars.innodb_buffer_pool_read_ahead_evicted, SHOW_SIZE_T}, &buf_pool.stat.n_ra_pages_evicted, SHOW_SIZE_T},
{"buffer_pool_read_requests", {"buffer_pool_read_requests", &buf_pool.stat.n_page_gets, SHOW_SIZE_T},
&export_vars.innodb_buffer_pool_read_requests, SHOW_SIZE_T}, {"buffer_pool_reads", &buf_pool.stat.n_pages_read, SHOW_SIZE_T},
{"buffer_pool_reads",
&export_vars.innodb_buffer_pool_reads, SHOW_SIZE_T},
{"buffer_pool_wait_free", &buf_pool.stat.LRU_waits, SHOW_SIZE_T}, {"buffer_pool_wait_free", &buf_pool.stat.LRU_waits, SHOW_SIZE_T},
{"buffer_pool_write_requests", &buf_pool.flush_list_requests, SHOW_SIZE_T}, {"buffer_pool_write_requests", &buf_pool.flush_list_requests, SHOW_SIZE_T},
{"checkpoint_age", &export_vars.innodb_checkpoint_age, SHOW_SIZE_T}, {"checkpoint_age", &export_vars.innodb_checkpoint_age, SHOW_SIZE_T},
@@ -15152,10 +15146,19 @@ ha_innobase::check(
} }
if ((check_opt->flags & T_QUICK) || index->is_corrupted()) { if ((check_opt->flags & T_QUICK) || index->is_corrupted()) {
} else if (btr_validate_index(index, m_prebuilt->trx) } else if (trx_id_t bulk_trx_id =
m_prebuilt->table->bulk_trx_id) {
if (!m_prebuilt->trx->read_view.changes_visible(
bulk_trx_id)) {
is_ok = true;
goto func_exit;
}
if (btr_validate_index(index, m_prebuilt->trx)
!= DB_SUCCESS) { != DB_SUCCESS) {
is_ok = false; is_ok = false;
push_warning_printf(thd, push_warning_printf(
thd,
Sql_condition::WARN_LEVEL_WARN, Sql_condition::WARN_LEVEL_WARN,
ER_NOT_KEYFILE, ER_NOT_KEYFILE,
"InnoDB: The B-tree of" "InnoDB: The B-tree of"
@@ -15163,6 +15166,7 @@ ha_innobase::check(
index->name()); index->name());
continue; continue;
} }
}
/* Instead of invoking change_active_index(), set up /* Instead of invoking change_active_index(), set up
a dummy template for non-locking reads, disabling a dummy template for non-locking reads, disabling
@@ -15284,6 +15288,7 @@ ha_innobase::check(
} }
# endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */ # endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */ #endif /* BTR_CUR_HASH_ADAPT */
func_exit:
m_prebuilt->trx->op_info = ""; m_prebuilt->trx->op_info = "";
DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT); DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);
@@ -19426,10 +19431,22 @@ static MYSQL_SYSVAR_BOOL(numa_interleave, srv_numa_interleave,
NULL, NULL, FALSE); NULL, NULL, FALSE);
#endif /* HAVE_LIBNUMA */ #endif /* HAVE_LIBNUMA */
static void innodb_change_buffering_update(THD *thd, struct st_mysql_sys_var*,
void*, const void *save)
{
ulong i= *static_cast<const ulong*>(save);
if (i != IBUF_USE_NONE && !ibuf.index)
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_NOT_KEYFILE,
"InnoDB: The change buffer is corrupted.");
else
innodb_change_buffering= i;
}
static MYSQL_SYSVAR_ENUM(change_buffering, innodb_change_buffering, static MYSQL_SYSVAR_ENUM(change_buffering, innodb_change_buffering,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_DEPRECATED, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_DEPRECATED,
"Buffer changes to secondary indexes.", "Buffer changes to secondary indexes.",
nullptr, nullptr, IBUF_USE_NONE, &innodb_change_buffering_typelib); nullptr, innodb_change_buffering_update,
IBUF_USE_NONE, &innodb_change_buffering_typelib);
static MYSQL_SYSVAR_UINT(change_buffer_max_size, static MYSQL_SYSVAR_UINT(change_buffer_max_size,
srv_change_buffer_max_size, srv_change_buffer_max_size,

View File

@@ -6120,6 +6120,7 @@ func_exit:
id, MTR_MEMO_PAGE_SX_FIX); id, MTR_MEMO_PAGE_SX_FIX);
if (UNIV_UNLIKELY(!root)) { if (UNIV_UNLIKELY(!root)) {
err = DB_CORRUPTION;
goto func_exit; goto func_exit;
} }

View File

@@ -403,8 +403,13 @@ ibuf_init_at_db_start(void)
if (!header_page) { if (!header_page) {
err_exit: err_exit:
sql_print_error("InnoDB: The change buffer is corrupted"); sql_print_error("InnoDB: The change buffer is corrupted"
" or has been removed on upgrade"
" to MariaDB 11.0 or later");
mtr.commit(); mtr.commit();
if (innodb_change_buffering == IBUF_USE_NONE) {
err = DB_SUCCESS;
}
return err; return err;
} }
@@ -1980,6 +1985,7 @@ void
ibuf_free_excess_pages(void) ibuf_free_excess_pages(void)
/*========================*/ /*========================*/
{ {
if (UNIV_UNLIKELY(!ibuf.index)) return;
/* Free at most a few pages at a time, so that we do not delay the /* Free at most a few pages at a time, so that we do not delay the
requested service too much */ requested service too much */
@@ -2421,6 +2427,7 @@ will be merged from ibuf trees to the pages read
@retval 0 if ibuf.empty */ @retval 0 if ibuf.empty */
ulint ibuf_contract() ulint ibuf_contract()
{ {
if (UNIV_UNLIKELY(!ibuf.index)) return 0;
mtr_t mtr; mtr_t mtr;
btr_cur_t cur; btr_cur_t cur;
ulint sum_sizes; ulint sum_sizes;
@@ -2470,6 +2477,7 @@ ibuf_merge_space(
/*=============*/ /*=============*/
ulint space) /*!< in: tablespace id to merge */ ulint space) /*!< in: tablespace id to merge */
{ {
if (UNIV_UNLIKELY(!ibuf.index)) return 0;
mtr_t mtr; mtr_t mtr;
btr_pcur_t pcur; btr_pcur_t pcur;
@@ -2935,13 +2943,14 @@ void
ibuf_update_max_tablespace_id(void) ibuf_update_max_tablespace_id(void)
/*===============================*/ /*===============================*/
{ {
if (UNIV_UNLIKELY(!ibuf.index)) return;
const rec_t* rec; const rec_t* rec;
const byte* field; const byte* field;
ulint len; ulint len;
btr_pcur_t pcur; btr_pcur_t pcur;
mtr_t mtr; mtr_t mtr;
ut_a(!dict_table_is_comp(ibuf.index->table)); ut_ad(!ibuf.index->table->not_redundant());
ibuf_mtr_start(&mtr); ibuf_mtr_start(&mtr);
@@ -4420,6 +4429,8 @@ in DISCARD TABLESPACE, IMPORT TABLESPACE, or read-ahead.
@param[in] space missing or to-be-discarded tablespace */ @param[in] space missing or to-be-discarded tablespace */
void ibuf_delete_for_discarded_space(uint32_t space) void ibuf_delete_for_discarded_space(uint32_t space)
{ {
if (UNIV_UNLIKELY(!ibuf.index)) return;
btr_pcur_t pcur; btr_pcur_t pcur;
const rec_t* ibuf_rec; const rec_t* ibuf_rec;
mtr_t mtr; mtr_t mtr;
@@ -4533,6 +4544,7 @@ ibuf_print(
/*=======*/ /*=======*/
FILE* file) /*!< in: file where to print */ FILE* file) /*!< in: file where to print */
{ {
if (UNIV_UNLIKELY(!ibuf.index)) return;
mysql_mutex_lock(&ibuf_mutex); mysql_mutex_lock(&ibuf_mutex);
if (ibuf.empty) if (ibuf.empty)
@@ -4577,8 +4589,6 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
mtr_t mtr; mtr_t mtr;
mysql_mutex_lock(&ibuf_mutex);
/* The two bitmap pages (allocation bitmap and ibuf bitmap) repeat /* The two bitmap pages (allocation bitmap and ibuf bitmap) repeat
every page_size pages. For example if page_size is 16 KiB, then the every page_size pages. For example if page_size is 16 KiB, then the
two bitmap pages repeat every 16 KiB * 16384 = 256 MiB. In the loop two bitmap pages repeat every 16 KiB * 16384 = 256 MiB. In the loop
@@ -4587,18 +4597,14 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
for (uint32_t page_no = 0; page_no < size; page_no += physical_size) { for (uint32_t page_no = 0; page_no < size; page_no += physical_size) {
if (trx_is_interrupted(trx)) { if (trx_is_interrupted(trx)) {
mysql_mutex_unlock(&ibuf_mutex);
return(DB_INTERRUPTED); return(DB_INTERRUPTED);
} }
mtr_start(&mtr); mtr_start(&mtr);
ibuf_enter(&mtr);
buf_block_t* bitmap_page = ibuf_bitmap_get_map_page( buf_block_t* bitmap_page = ibuf_bitmap_get_map_page(
page_id_t(space->id, page_no), zip_size, &mtr); page_id_t(space->id, page_no), zip_size, &mtr);
if (!bitmap_page) { if (!bitmap_page) {
mysql_mutex_unlock(&ibuf_mutex);
ibuf_exit(&mtr);
mtr.commit(); mtr.commit();
return DB_CORRUPTION; return DB_CORRUPTION;
} }
@@ -4621,7 +4627,6 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
physical_size))); physical_size)));
} }
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
ibuf_exit(&mtr);
mtr_commit(&mtr); mtr_commit(&mtr);
continue; continue;
} }
@@ -4636,8 +4641,6 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
cur_page_id, zip_size, cur_page_id, zip_size,
IBUF_BITMAP_IBUF, &mtr)) { IBUF_BITMAP_IBUF, &mtr)) {
mysql_mutex_unlock(&ibuf_mutex);
ibuf_exit(&mtr);
mtr_commit(&mtr); mtr_commit(&mtr);
ib_errf(trx->mysql_thd, ib_errf(trx->mysql_thd,
@@ -4671,11 +4674,9 @@ dberr_t ibuf_check_bitmap_on_import(const trx_t* trx, fil_space_t* space)
} }
} }
ibuf_exit(&mtr);
mtr_commit(&mtr); mtr_commit(&mtr);
} }
mysql_mutex_unlock(&ibuf_mutex);
return(DB_SUCCESS); return(DB_SUCCESS);
} }

View File

@@ -445,7 +445,7 @@ Gets the root node of a tree and x- or s-latches it.
buf_block_t* buf_block_t*
btr_root_block_get( btr_root_block_get(
/*===============*/ /*===============*/
const dict_index_t* index, /*!< in: index tree */ dict_index_t* index, /*!< in: index tree */
rw_lock_type_t mode, /*!< in: either RW_S_LATCH rw_lock_type_t mode, /*!< in: either RW_S_LATCH
or RW_X_LATCH */ or RW_X_LATCH */
mtr_t* mtr, /*!< in: mtr */ mtr_t* mtr, /*!< in: mtr */

View File

@@ -103,6 +103,9 @@ enum btr_latch_mode {
dict_index_t::lock is being held in non-exclusive mode. */ dict_index_t::lock is being held in non-exclusive mode. */
BTR_MODIFY_LEAF_ALREADY_LATCHED = BTR_MODIFY_LEAF BTR_MODIFY_LEAF_ALREADY_LATCHED = BTR_MODIFY_LEAF
| BTR_ALREADY_S_LATCHED, | BTR_ALREADY_S_LATCHED,
/** Attempt to modify records in an x-latched tree. */
BTR_MODIFY_TREE_ALREADY_LATCHED = BTR_MODIFY_TREE
| BTR_ALREADY_S_LATCHED,
/** U-latch root and X-latch a leaf page, assuming that /** U-latch root and X-latch a leaf page, assuming that
dict_index_t::lock is being held in U mode. */ dict_index_t::lock is being held in U mode. */
BTR_MODIFY_ROOT_AND_LEAF_ALREADY_LATCHED = BTR_MODIFY_ROOT_AND_LEAF BTR_MODIFY_ROOT_AND_LEAF_ALREADY_LATCHED = BTR_MODIFY_ROOT_AND_LEAF

View File

@@ -720,13 +720,14 @@ public:
ut_ad(s < REINIT); ut_ad(s < REINIT);
} }
void read_unfix(uint32_t s) uint32_t read_unfix(uint32_t s)
{ {
ut_ad(lock.is_write_locked()); ut_ad(lock.is_write_locked());
ut_ad(s == UNFIXED + 1 || s == IBUF_EXIST + 1 || s == REINIT + 1); ut_ad(s == UNFIXED + 1 || s == IBUF_EXIST + 1 || s == REINIT + 1);
ut_d(auto old_state=) zip.fix.fetch_add(s - READ_FIX); uint32_t old_state= zip.fix.fetch_add(s - READ_FIX);
ut_ad(old_state >= READ_FIX); ut_ad(old_state >= READ_FIX);
ut_ad(old_state < WRITE_FIX); ut_ad(old_state < WRITE_FIX);
return old_state + (s - READ_FIX);
} }
void set_freed(uint32_t prev_state, uint32_t count= 0) void set_freed(uint32_t prev_state, uint32_t count= 0)
@@ -777,11 +778,11 @@ public:
it from buf_pool.flush_list */ it from buf_pool.flush_list */
inline void write_complete(bool temporary); inline void write_complete(bool temporary);
/** Write a flushable page to a file. buf_pool.mutex must be held. /** Write a flushable page to a file or free a freeable block.
@param lru true=buf_pool.LRU; false=buf_pool.flush_list @param evict whether to evict the page on write completion
@param space tablespace @param space tablespace
@return whether the page was flushed and buf_pool.mutex was released */ @return whether a page write was initiated and buf_pool.mutex released */
inline bool flush(bool lru, fil_space_t *space); bool flush(bool evict, fil_space_t *space);
/** Notify that a page in a temporary tablespace has been modified. */ /** Notify that a page in a temporary tablespace has been modified. */
void set_temp_modified() void set_temp_modified()
@@ -851,8 +852,6 @@ public:
/** @return whether the block is mapped to a data file */ /** @return whether the block is mapped to a data file */
bool in_file() const { return state() >= FREED; } bool in_file() const { return state() >= FREED; }
/** @return whether the block is modified and ready for flushing */
inline bool ready_for_flush() const;
/** @return whether the block can be relocated in memory. /** @return whether the block can be relocated in memory.
The block can be dirty, but it must not be I/O-fixed or bufferfixed. */ The block can be dirty, but it must not be I/O-fixed or bufferfixed. */
inline bool can_relocate() const; inline bool can_relocate() const;
@@ -1025,10 +1024,10 @@ Compute the hash fold value for blocks in buf_pool.zip_hash. */
#define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b)) #define BUF_POOL_ZIP_FOLD_BPAGE(b) BUF_POOL_ZIP_FOLD((buf_block_t*) (b))
/* @} */ /* @} */
/** A "Hazard Pointer" class used to iterate over page lists /** A "Hazard Pointer" class used to iterate over buf_pool.LRU or
inside the buffer pool. A hazard pointer is a buf_page_t pointer buf_pool.flush_list. A hazard pointer is a buf_page_t pointer
which we intend to iterate over next and we want it remain valid which we intend to iterate over next and we want it remain valid
even after we release the buffer pool mutex. */ even after we release the mutex that protects the list. */
class HazardPointer class HazardPointer
{ {
public: public:
@@ -1143,7 +1142,8 @@ struct buf_buddy_free_t {
/*!< Node of zip_free list */ /*!< Node of zip_free list */
}; };
/** @brief The buffer pool statistics structure. */ /** @brief The buffer pool statistics structure;
protected by buf_pool.mutex unless otherwise noted. */
struct buf_pool_stat_t{ struct buf_pool_stat_t{
/** Initialize the counters */ /** Initialize the counters */
void init() { memset((void*) this, 0, sizeof *this); } void init() { memset((void*) this, 0, sizeof *this); }
@@ -1152,9 +1152,8 @@ struct buf_pool_stat_t{
/*!< number of page gets performed; /*!< number of page gets performed;
also successful searches through also successful searches through
the adaptive hash index are the adaptive hash index are
counted as page gets; this field counted as page gets;
is NOT protected by the buffer NOT protected by buf_pool.mutex */
pool mutex */
ulint n_pages_read; /*!< number read operations */ ulint n_pages_read; /*!< number read operations */
ulint n_pages_written;/*!< number write operations */ ulint n_pages_written;/*!< number write operations */
ulint n_pages_created;/*!< number of pages created ulint n_pages_created;/*!< number of pages created
@@ -1172,10 +1171,9 @@ struct buf_pool_stat_t{
young because the first access young because the first access
was not long enough ago, in was not long enough ago, in
buf_page_peek_if_too_old() */ buf_page_peek_if_too_old() */
/** number of waits for eviction; writes protected by buf_pool.mutex */ /** number of waits for eviction */
ulint LRU_waits; ulint LRU_waits;
ulint LRU_bytes; /*!< LRU size in bytes */ ulint LRU_bytes; /*!< LRU size in bytes */
ulint flush_list_bytes;/*!< flush_list size in bytes */
}; };
/** Statistics of buddy blocks of a given size. */ /** Statistics of buddy blocks of a given size. */
@@ -1496,6 +1494,11 @@ public:
n_chunks_new / 4 * chunks->size; n_chunks_new / 4 * chunks->size;
} }
/** @return whether the buffer pool has run out */
TPOOL_SUPPRESS_TSAN
bool ran_out() const
{ return UNIV_UNLIKELY(!try_LRU_scan || !UT_LIST_GET_LEN(free)); }
/** @return whether the buffer pool is shrinking */ /** @return whether the buffer pool is shrinking */
inline bool is_shrinking() const inline bool is_shrinking() const
{ {
@@ -1533,17 +1536,10 @@ public:
/** Buffer pool mutex */ /** Buffer pool mutex */
alignas(CPU_LEVEL1_DCACHE_LINESIZE) mysql_mutex_t mutex; alignas(CPU_LEVEL1_DCACHE_LINESIZE) mysql_mutex_t mutex;
/** Number of pending LRU flush; protected by mutex. */ /** current statistics; protected by mutex */
ulint n_flush_LRU_; buf_pool_stat_t stat;
/** broadcast when n_flush_LRU reaches 0; protected by mutex */ /** old statistics; protected by mutex */
pthread_cond_t done_flush_LRU; buf_pool_stat_t old_stat;
/** Number of pending flush_list flush; protected by mutex */
ulint n_flush_list_;
/** broadcast when n_flush_list reaches 0; protected by mutex */
pthread_cond_t done_flush_list;
TPOOL_SUPPRESS_TSAN ulint n_flush_LRU() const { return n_flush_LRU_; }
TPOOL_SUPPRESS_TSAN ulint n_flush_list() const { return n_flush_list_; }
/** @name General fields */ /** @name General fields */
/* @{ */ /* @{ */
@@ -1704,11 +1700,12 @@ public:
buf_buddy_stat_t buddy_stat[BUF_BUDDY_SIZES_MAX + 1]; buf_buddy_stat_t buddy_stat[BUF_BUDDY_SIZES_MAX + 1];
/*!< Statistics of buddy system, /*!< Statistics of buddy system,
indexed by block size */ indexed by block size */
buf_pool_stat_t stat; /*!< current statistics */
buf_pool_stat_t old_stat; /*!< old statistics */
/* @} */ /* @} */
/** number of index page splits */
Atomic_counter<ulint> pages_split;
/** @name Page flushing algorithm fields */ /** @name Page flushing algorithm fields */
/* @{ */ /* @{ */
@@ -1717,7 +1714,10 @@ public:
alignas(CPU_LEVEL1_DCACHE_LINESIZE) mysql_mutex_t flush_list_mutex; alignas(CPU_LEVEL1_DCACHE_LINESIZE) mysql_mutex_t flush_list_mutex;
/** "hazard pointer" for flush_list scans; protected by flush_list_mutex */ /** "hazard pointer" for flush_list scans; protected by flush_list_mutex */
FlushHp flush_hp; FlushHp flush_hp;
/** modified blocks (a subset of LRU) */ /** flush_list size in bytes; protected by flush_list_mutex */
ulint flush_list_bytes;
/** possibly modified persistent pages (a subset of LRU);
buf_dblwr.pending_writes() is approximately COUNT(is_write_fixed()) */
UT_LIST_BASE_NODE_T(buf_page_t) flush_list; UT_LIST_BASE_NODE_T(buf_page_t) flush_list;
/** number of blocks ever added to flush_list; /** number of blocks ever added to flush_list;
sometimes protected by flush_list_mutex */ sometimes protected by flush_list_mutex */
@@ -1726,28 +1726,70 @@ public:
TPOOL_SUPPRESS_TSAN void add_flush_list_requests(size_t size) TPOOL_SUPPRESS_TSAN void add_flush_list_requests(size_t size)
{ ut_ad(size); flush_list_requests+= size; } { ut_ad(size); flush_list_requests+= size; }
private: private:
/** whether the page cleaner needs wakeup from indefinite sleep */ static constexpr unsigned PAGE_CLEANER_IDLE= 1;
bool page_cleaner_is_idle; static constexpr unsigned FLUSH_LIST_ACTIVE= 2;
static constexpr unsigned LRU_FLUSH= 4;
/** Number of pending LRU flush * LRU_FLUSH +
PAGE_CLEANER_IDLE + FLUSH_LIST_ACTIVE flags */
unsigned page_cleaner_status;
/** track server activity count for signaling idle flushing */ /** track server activity count for signaling idle flushing */
ulint last_activity_count; ulint last_activity_count;
public: public:
/** signalled to wake up the page_cleaner; protected by flush_list_mutex */ /** signalled to wake up the page_cleaner; protected by flush_list_mutex */
pthread_cond_t do_flush_list; pthread_cond_t do_flush_list;
/** broadcast when !n_flush(); protected by flush_list_mutex */
pthread_cond_t done_flush_LRU;
/** broadcast when a batch completes; protected by flush_list_mutex */
pthread_cond_t done_flush_list;
/** @return number of pending LRU flush */
unsigned n_flush() const
{
mysql_mutex_assert_owner(&flush_list_mutex);
return page_cleaner_status / LRU_FLUSH;
}
/** Increment the number of pending LRU flush */
inline void n_flush_inc();
/** Decrement the number of pending LRU flush */
inline void n_flush_dec();
/** @return whether flush_list flushing is active */
bool flush_list_active() const
{
mysql_mutex_assert_owner(&flush_list_mutex);
return page_cleaner_status & FLUSH_LIST_ACTIVE;
}
void flush_list_set_active()
{
ut_ad(!flush_list_active());
page_cleaner_status+= FLUSH_LIST_ACTIVE;
}
void flush_list_set_inactive()
{
ut_ad(flush_list_active());
page_cleaner_status-= FLUSH_LIST_ACTIVE;
}
/** @return whether the page cleaner must sleep due to being idle */ /** @return whether the page cleaner must sleep due to being idle */
bool page_cleaner_idle() const noexcept bool page_cleaner_idle() const noexcept
{ {
mysql_mutex_assert_owner(&flush_list_mutex); mysql_mutex_assert_owner(&flush_list_mutex);
return page_cleaner_is_idle; return page_cleaner_status & PAGE_CLEANER_IDLE;
} }
/** Wake up the page cleaner if needed */ /** Wake up the page cleaner if needed.
void page_cleaner_wakeup(); @param for_LRU whether to wake up for LRU eviction */
void page_cleaner_wakeup(bool for_LRU= false);
/** Register whether an explicit wakeup of the page cleaner is needed */ /** Register whether an explicit wakeup of the page cleaner is needed */
void page_cleaner_set_idle(bool deep_sleep) void page_cleaner_set_idle(bool deep_sleep)
{ {
mysql_mutex_assert_owner(&flush_list_mutex); mysql_mutex_assert_owner(&flush_list_mutex);
page_cleaner_is_idle= deep_sleep; page_cleaner_status= (page_cleaner_status & ~PAGE_CLEANER_IDLE) |
(PAGE_CLEANER_IDLE * deep_sleep);
} }
/** Update server last activity count */ /** Update server last activity count */
@@ -1757,9 +1799,6 @@ public:
last_activity_count= activity_count; last_activity_count= activity_count;
} }
// n_flush_LRU() + n_flush_list()
// is approximately COUNT(is_write_fixed()) in flush_list
unsigned freed_page_clock;/*!< a sequence number used unsigned freed_page_clock;/*!< a sequence number used
to count the number of buffer to count the number of buffer
blocks removed from the end of blocks removed from the end of
@@ -1769,16 +1808,10 @@ public:
to read this for heuristic to read this for heuristic
purposes without holding any purposes without holding any
mutex or latch */ mutex or latch */
bool try_LRU_scan; /*!< Cleared when an LRU /** Cleared when buf_LRU_get_free_block() fails.
scan for free block fails. This Set whenever the free list grows, along with a broadcast of done_free.
flag is used to avoid repeated Protected by buf_pool.mutex. */
scans of LRU list when we know Atomic_relaxed<bool> try_LRU_scan;
that there is no free block
available in the scan depth for
eviction. Set whenever
we flush a batch from the
buffer pool. Protected by the
buf_pool.mutex */
/* @} */ /* @} */
/** @name LRU replacement algorithm fields */ /** @name LRU replacement algorithm fields */
@@ -1787,7 +1820,8 @@ public:
UT_LIST_BASE_NODE_T(buf_page_t) free; UT_LIST_BASE_NODE_T(buf_page_t) free;
/*!< base node of the free /*!< base node of the free
block list */ block list */
/** signaled each time when the free list grows; protected by mutex */ /** broadcast each time when the free list grows or try_LRU_scan is set;
protected by mutex */
pthread_cond_t done_free; pthread_cond_t done_free;
UT_LIST_BASE_NODE_T(buf_page_t) withdraw; UT_LIST_BASE_NODE_T(buf_page_t) withdraw;
@@ -1847,29 +1881,16 @@ public:
{ {
if (n_pend_reads) if (n_pend_reads)
return true; return true;
mysql_mutex_lock(&mutex); mysql_mutex_lock(&flush_list_mutex);
const bool any_pending{n_flush_LRU_ || n_flush_list_}; const bool any_pending= page_cleaner_status > PAGE_CLEANER_IDLE ||
mysql_mutex_unlock(&mutex); buf_dblwr.pending_writes();
mysql_mutex_unlock(&flush_list_mutex);
return any_pending; return any_pending;
} }
/** @return total amount of pending I/O */
ulint io_pending() const
{
return n_pend_reads + n_flush_LRU() + n_flush_list();
}
private:
/** Remove a block from the flush list. */
inline void delete_from_flush_list_low(buf_page_t *bpage) noexcept;
/** Remove a block from flush_list.
@param bpage buffer pool page
@param clear whether to invoke buf_page_t::clear_oldest_modification() */
void delete_from_flush_list(buf_page_t *bpage, bool clear) noexcept;
public:
/** Remove a block from flush_list. /** Remove a block from flush_list.
@param bpage buffer pool page */ @param bpage buffer pool page */
void delete_from_flush_list(buf_page_t *bpage) noexcept void delete_from_flush_list(buf_page_t *bpage) noexcept;
{ delete_from_flush_list(bpage, true); }
/** Prepare to insert a modified blcok into flush_list. /** Prepare to insert a modified blcok into flush_list.
@param lsn start LSN of the mini-transaction @param lsn start LSN of the mini-transaction
@@ -1884,7 +1905,7 @@ public:
lsn_t lsn) noexcept; lsn_t lsn) noexcept;
/** Free a page whose underlying file page has been freed. */ /** Free a page whose underlying file page has been freed. */
inline void release_freed_page(buf_page_t *bpage) noexcept; ATTRIBUTE_COLD void release_freed_page(buf_page_t *bpage) noexcept;
private: private:
/** Temporary memory for page_compressed and encrypted I/O */ /** Temporary memory for page_compressed and encrypted I/O */
@@ -1895,34 +1916,12 @@ private:
/** array of slots */ /** array of slots */
buf_tmp_buffer_t *slots; buf_tmp_buffer_t *slots;
void create(ulint n_slots) void create(ulint n_slots);
{
this->n_slots= n_slots;
slots= static_cast<buf_tmp_buffer_t*>
(ut_malloc_nokey(n_slots * sizeof *slots));
memset((void*) slots, 0, n_slots * sizeof *slots);
}
void close() void close();
{
for (buf_tmp_buffer_t *s= slots, *e= slots + n_slots; s != e; s++)
{
aligned_free(s->crypt_buf);
aligned_free(s->comp_buf);
}
ut_free(slots);
slots= nullptr;
n_slots= 0;
}
/** Reserve a buffer */ /** Reserve a buffer */
buf_tmp_buffer_t *reserve() buf_tmp_buffer_t *reserve();
{
for (buf_tmp_buffer_t *s= slots, *e= slots + n_slots; s != e; s++)
if (s->acquire())
return s;
return nullptr;
}
} io_buf; } io_buf;
/** whether resize() is in the critical path */ /** whether resize() is in the critical path */
@@ -2011,7 +2010,10 @@ inline void buf_page_t::set_oldest_modification(lsn_t lsn)
/** Clear oldest_modification after removing from buf_pool.flush_list */ /** Clear oldest_modification after removing from buf_pool.flush_list */
inline void buf_page_t::clear_oldest_modification() inline void buf_page_t::clear_oldest_modification()
{ {
#ifdef SAFE_MUTEX
if (oldest_modification() != 2)
mysql_mutex_assert_owner(&buf_pool.flush_list_mutex); mysql_mutex_assert_owner(&buf_pool.flush_list_mutex);
#endif /* SAFE_MUTEX */
ut_d(const auto s= state()); ut_d(const auto s= state());
ut_ad(s >= REMOVE_HASH); ut_ad(s >= REMOVE_HASH);
ut_ad(oldest_modification()); ut_ad(oldest_modification());
@@ -2023,17 +2025,6 @@ inline void buf_page_t::clear_oldest_modification()
oldest_modification_.store(0, std::memory_order_release); oldest_modification_.store(0, std::memory_order_release);
} }
/** @return whether the block is modified and ready for flushing */
inline bool buf_page_t::ready_for_flush() const
{
mysql_mutex_assert_owner(&buf_pool.mutex);
ut_ad(in_LRU_list);
const auto s= state();
ut_a(s >= FREED);
ut_ad(!fsp_is_system_temporary(id().space()) || oldest_modification() == 2);
return s < READ_FIX;
}
/** @return whether the block can be relocated in memory. /** @return whether the block can be relocated in memory.
The block can be dirty, but it must not be I/O-fixed or bufferfixed. */ The block can be dirty, but it must not be I/O-fixed or bufferfixed. */
inline bool buf_page_t::can_relocate() const inline bool buf_page_t::can_relocate() const

View File

@@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2020, MariaDB Corporation. Copyright (c) 2017, 2022, 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
@@ -54,9 +54,9 @@ class buf_dblwr_t
}; };
/** the page number of the first doublewrite block (block_size() pages) */ /** the page number of the first doublewrite block (block_size() pages) */
page_id_t block1= page_id_t(0, 0); page_id_t block1{0, 0};
/** the page number of the second doublewrite block (block_size() pages) */ /** the page number of the second doublewrite block (block_size() pages) */
page_id_t block2= page_id_t(0, 0); page_id_t block2{0, 0};
/** mutex protecting the data members below */ /** mutex protecting the data members below */
mysql_mutex_t mutex; mysql_mutex_t mutex;
@@ -72,11 +72,15 @@ class buf_dblwr_t
ulint writes_completed; ulint writes_completed;
/** number of pages written by flush_buffered_writes_completed() */ /** number of pages written by flush_buffered_writes_completed() */
ulint pages_written; ulint pages_written;
/** condition variable for !writes_pending */
pthread_cond_t write_cond;
/** number of pending page writes */
size_t writes_pending;
slot slots[2]; slot slots[2];
slot *active_slot= &slots[0]; slot *active_slot;
/** Initialize the doublewrite buffer data structure. /** Initialise the persistent storage of the doublewrite buffer.
@param header doublewrite page header in the TRX_SYS page */ @param header doublewrite page header in the TRX_SYS page */
inline void init(const byte *header); inline void init(const byte *header);
@@ -84,6 +88,8 @@ class buf_dblwr_t
bool flush_buffered_writes(const ulint size); bool flush_buffered_writes(const ulint size);
public: public:
/** Initialise the doublewrite buffer data structures. */
void init();
/** Create or restore the doublewrite buffer in the TRX_SYS page. /** Create or restore the doublewrite buffer in the TRX_SYS page.
@return whether the operation succeeded */ @return whether the operation succeeded */
bool create(); bool create();
@@ -118,7 +124,7 @@ public:
void recover(); void recover();
/** Update the doublewrite buffer on data page write completion. */ /** Update the doublewrite buffer on data page write completion. */
void write_completed(); void write_completed(bool with_doublewrite);
/** Flush possible buffered writes to persistent storage. /** Flush possible buffered writes to persistent storage.
It is very important to call this function after a batch of writes has been It is very important to call this function after a batch of writes has been
posted, and also when we may have to wait for a page latch! posted, and also when we may have to wait for a page latch!
@@ -137,14 +143,14 @@ public:
@param size payload size in bytes */ @param size payload size in bytes */
void add_to_batch(const IORequest &request, size_t size); void add_to_batch(const IORequest &request, size_t size);
/** Determine whether the doublewrite buffer is initialized */ /** Determine whether the doublewrite buffer has been created */
bool is_initialised() const bool is_created() const
{ return UNIV_LIKELY(block1 != page_id_t(0, 0)); } { return UNIV_LIKELY(block1 != page_id_t(0, 0)); }
/** @return whether a page identifier is part of the doublewrite buffer */ /** @return whether a page identifier is part of the doublewrite buffer */
bool is_inside(const page_id_t id) const bool is_inside(const page_id_t id) const
{ {
if (!is_initialised()) if (!is_created())
return false; return false;
ut_ad(block1 < block2); ut_ad(block1 < block2);
if (id < block1) if (id < block1)
@@ -155,14 +161,45 @@ public:
/** Wait for flush_buffered_writes() to be fully completed */ /** Wait for flush_buffered_writes() to be fully completed */
void wait_flush_buffered_writes() void wait_flush_buffered_writes()
{
if (is_initialised())
{ {
mysql_mutex_lock(&mutex); mysql_mutex_lock(&mutex);
while (batch_running) while (batch_running)
my_cond_wait(&cond, &mutex.m_mutex); my_cond_wait(&cond, &mutex.m_mutex);
mysql_mutex_unlock(&mutex); mysql_mutex_unlock(&mutex);
} }
/** Register an unbuffered page write */
void add_unbuffered()
{
mysql_mutex_lock(&mutex);
writes_pending++;
mysql_mutex_unlock(&mutex);
}
size_t pending_writes()
{
mysql_mutex_lock(&mutex);
const size_t pending{writes_pending};
mysql_mutex_unlock(&mutex);
return pending;
}
/** Wait for writes_pending to reach 0 */
void wait_for_page_writes()
{
mysql_mutex_lock(&mutex);
while (writes_pending)
my_cond_wait(&write_cond, &mutex.m_mutex);
mysql_mutex_unlock(&mutex);
}
/** Wait for writes_pending to reach 0 */
void wait_for_page_writes(const timespec &abstime)
{
mysql_mutex_lock(&mutex);
while (writes_pending)
my_cond_timedwait(&write_cond, &mutex.m_mutex, &abstime);
mysql_mutex_unlock(&mutex);
} }
}; };

View File

@@ -30,10 +30,8 @@ Created 11/5/1995 Heikki Tuuri
#include "log0log.h" #include "log0log.h"
#include "buf0buf.h" #include "buf0buf.h"
/** Number of pages flushed. Protected by buf_pool.mutex. */
extern ulint buf_flush_page_count;
/** Number of pages flushed via LRU. Protected by buf_pool.mutex. /** Number of pages flushed via LRU. Protected by buf_pool.mutex.
Also included in buf_flush_page_count. */ Also included in buf_pool.stat.n_pages_written. */
extern ulint buf_lru_flush_page_count; extern ulint buf_lru_flush_page_count;
/** Number of pages freed without flushing. Protected by buf_pool.mutex. */ /** Number of pages freed without flushing. Protected by buf_pool.mutex. */
extern ulint buf_lru_freed_page_count; extern ulint buf_lru_freed_page_count;
@@ -86,15 +84,18 @@ buf_flush_init_for_writing(
bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed= nullptr) bool buf_flush_list_space(fil_space_t *space, ulint *n_flushed= nullptr)
MY_ATTRIBUTE((warn_unused_result)); MY_ATTRIBUTE((warn_unused_result));
/** Write out dirty blocks from buf_pool.LRU. /** Write out dirty blocks from buf_pool.LRU,
and move clean blocks to buf_pool.free.
The caller must invoke buf_dblwr.flush_buffered_writes()
after releasing buf_pool.mutex.
@param max_n wished maximum mumber of blocks flushed @param max_n wished maximum mumber of blocks flushed
@return the number of processed pages @param evict whether to evict pages after flushing
@return evict ? number of processed pages : number of pages written
@retval 0 if a buf_pool.LRU batch is already running */ @retval 0 if a buf_pool.LRU batch is already running */
ulint buf_flush_LRU(ulint max_n); ulint buf_flush_LRU(ulint max_n, bool evict);
/** Wait until a flush batch ends. /** Wait until a LRU flush batch ends. */
@param lru true=buf_pool.LRU; false=buf_pool.flush_list */ void buf_flush_wait_LRU_batch_end();
void buf_flush_wait_batch_end(bool lru);
/** Wait until all persistent pages are flushed up to a limit. /** Wait until all persistent pages are flushed up to a limit.
@param sync_lsn buf_pool.get_oldest_modification(LSN_MAX) to wait for */ @param sync_lsn buf_pool.get_oldest_modification(LSN_MAX) to wait for */
ATTRIBUTE_COLD void buf_flush_wait_flushed(lsn_t sync_lsn); ATTRIBUTE_COLD void buf_flush_wait_flushed(lsn_t sync_lsn);
@@ -106,9 +107,6 @@ ATTRIBUTE_COLD void buf_flush_ahead(lsn_t lsn, bool furious);
/** Initialize page_cleaner. */ /** Initialize page_cleaner. */
ATTRIBUTE_COLD void buf_flush_page_cleaner_init(); ATTRIBUTE_COLD void buf_flush_page_cleaner_init();
/** Wait for pending flushes to complete. */
void buf_flush_wait_batch_end_acquiring_mutex(bool lru);
/** Flush the buffer pool on shutdown. */ /** Flush the buffer pool on shutdown. */
ATTRIBUTE_COLD void buf_flush_buffer_pool(); ATTRIBUTE_COLD void buf_flush_buffer_pool();

View File

@@ -33,10 +33,11 @@ Created 11/5/1995 Heikki Tuuri
buffer buf_pool if it is not already there. Sets the io_fix flag and sets buffer buf_pool if it is not already there. Sets the io_fix flag and sets
an exclusive lock on the buffer frame. The flag is cleared and the x-lock 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] page_id page id @param page_id page id
@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0 @param zip_size ROW_FORMAT=COMPRESSED page size, or 0
@retval DB_SUCCESS if the page was read and is not corrupted, @retval DB_SUCCESS if the page was read and is not corrupted
@retval DB_PAGE_CORRUPTED if page based on checksum check is corrupted, @retval DB_SUCCESS_LOCKED_REC if the page was not read
@retval DB_PAGE_CORRUPTED if page based on checksum check is corrupted
@retval DB_DECRYPTION_FAILED if page post encryption checksum matches but @retval DB_DECRYPTION_FAILED if page post encryption checksum matches but
after decryption normal page checksum does not match. after decryption normal page checksum does not match.
@retval DB_TABLESPACE_DELETED if tablespace .ibd file is missing */ @retval DB_TABLESPACE_DELETED if tablespace .ibd file is missing */

View File

@@ -898,11 +898,13 @@ public:
@param purpose tablespace purpose @param purpose tablespace purpose
@param crypt_data encryption information @param crypt_data encryption information
@param mode encryption mode @param mode encryption mode
@param opened true if space files are opened
@return pointer to created tablespace, to be filled in with add() @return pointer to created tablespace, to be filled in with add()
@retval nullptr on failure (such as when the same tablespace exists) */ @retval nullptr on failure (such as when the same tablespace exists) */
static fil_space_t *create(uint32_t id, uint32_t flags, static fil_space_t *create(uint32_t id, uint32_t flags,
fil_type_t purpose, fil_space_crypt_t *crypt_data, fil_type_t purpose, fil_space_crypt_t *crypt_data,
fil_encryption_t mode= FIL_ENCRYPTION_DEFAULT); fil_encryption_t mode= FIL_ENCRYPTION_DEFAULT,
bool opened= false);
MY_ATTRIBUTE((warn_unused_result)) MY_ATTRIBUTE((warn_unused_result))
/** Acquire a tablespace reference. /** Acquire a tablespace reference.
@@ -1107,7 +1109,7 @@ private:
inline bool fil_space_t::use_doublewrite() const inline bool fil_space_t::use_doublewrite() const
{ {
return !UT_LIST_GET_FIRST(chain)->atomic_write && srv_use_doublewrite_buf && return !UT_LIST_GET_FIRST(chain)->atomic_write && srv_use_doublewrite_buf &&
buf_dblwr.is_initialised(); buf_dblwr.is_created();
} }
inline void fil_space_t::set_imported() inline void fil_space_t::set_imported()
@@ -1384,6 +1386,11 @@ struct fil_system_t
private: private:
bool m_initialised; bool m_initialised;
/** Points to the last opened space in space_list. Protected with
fil_system.mutex. */
fil_space_t *space_list_last_opened= nullptr;
#ifdef __linux__ #ifdef __linux__
/** available block devices that reside on non-rotational storage */ /** available block devices that reside on non-rotational storage */
std::vector<dev_t> ssd; std::vector<dev_t> ssd;
@@ -1425,7 +1432,8 @@ public:
/** nonzero if fil_node_open_file_low() should avoid moving the tablespace /** nonzero if fil_node_open_file_low() should avoid moving the tablespace
to the end of space_list, for FIFO policy of try_to_close() */ to the end of space_list, for FIFO policy of try_to_close() */
ulint freeze_space_list; ulint freeze_space_list;
/** list of all tablespaces */ /** List of all file spaces, opened spaces should be at the top of the list
to optimize try_to_close() execution. Protected with fil_system.mutex. */
ilist<fil_space_t, space_list_tag_t> space_list; ilist<fil_space_t, space_list_tag_t> space_list;
/** list of all tablespaces for which a FILE_MODIFY record has been written /** list of all tablespaces for which a FILE_MODIFY record has been written
since the latest redo log checkpoint. since the latest redo log checkpoint.
@@ -1440,6 +1448,49 @@ public:
potential space_id reuse */ potential space_id reuse */
bool space_id_reuse_warned; bool space_id_reuse_warned;
/** Add the file to the end of opened spaces list in
fil_system.space_list, so that fil_space_t::try_to_close() should close
it as a last resort.
@param space space to add */
void add_opened_last_to_space_list(fil_space_t *space);
/** Move the file to the end of opened spaces list in
fil_system.space_list, so that fil_space_t::try_to_close() should close
it as a last resort.
@param space space to move */
inline void move_opened_last_to_space_list(fil_space_t *space)
{
/* In the case when several files of the same space are added in a
row, there is no need to remove and add a space to the same position
in space_list. It can be for system or temporary tablespaces. */
if (freeze_space_list || space_list_last_opened == space)
return;
space_list.erase(space_list_t::iterator(space));
add_opened_last_to_space_list(space);
}
/** Move closed file last in fil_system.space_list, so that
fil_space_t::try_to_close() iterates opened files first in FIFO order,
i.e. first opened, first closed.
@param space space to move */
void move_closed_last_to_space_list(fil_space_t *space)
{
if (UNIV_UNLIKELY(freeze_space_list))
return;
space_list_t::iterator s= space_list_t::iterator(space);
if (space_list_last_opened == space)
{
space_list_t::iterator prev= s;
space_list_last_opened= &*--prev;
}
space_list.erase(s);
space_list.push_back(*space);
}
/** Return the next tablespace from default_encrypt_tables list. /** Return the next tablespace from default_encrypt_tables list.
@param space previous tablespace (nullptr to start from the start) @param space previous tablespace (nullptr to start from the start)
@param recheck whether the removal condition needs to be rechecked after @param recheck whether the removal condition needs to be rechecked after

View File

@@ -342,6 +342,9 @@ public:
/** Upgrade U locks on a block to X */ /** Upgrade U locks on a block to X */
void page_lock_upgrade(const buf_block_t &block); void page_lock_upgrade(const buf_block_t &block);
/** Upgrade index U lock to X */
ATTRIBUTE_COLD void index_lock_upgrade();
/** Check if we are holding tablespace latch /** Check if we are holding tablespace latch
@param space tablespace to search for @param space tablespace to search for
@return whether space.latch is being held */ @return whether space.latch is being held */

View File

@@ -85,11 +85,6 @@ struct srv_stats_t
/** Count the amount of data written in total (in bytes) */ /** Count the amount of data written in total (in bytes) */
ulint_ctr_1_t data_written; ulint_ctr_1_t data_written;
/** Number of buffer pool reads that led to the reading of
a disk page */
ulint_ctr_1_t buf_pool_reads;
/** Number of bytes saved by page compression */ /** Number of bytes saved by page compression */
ulint_ctr_n_t page_compression_saved; ulint_ctr_n_t page_compression_saved;
/* Number of pages compressed with page compression */ /* Number of pages compressed with page compression */
@@ -614,23 +609,11 @@ struct export_var_t{
char innodb_buffer_pool_resize_status[512];/*!< Buf pool resize status */ char innodb_buffer_pool_resize_status[512];/*!< Buf pool resize status */
my_bool innodb_buffer_pool_load_incomplete;/*!< Buf pool load incomplete */ my_bool innodb_buffer_pool_load_incomplete;/*!< Buf pool load incomplete */
ulint innodb_buffer_pool_pages_total; /*!< Buffer pool size */ ulint innodb_buffer_pool_pages_total; /*!< Buffer pool size */
ulint innodb_buffer_pool_pages_data; /*!< Data pages */
ulint innodb_buffer_pool_bytes_data; /*!< File bytes used */ ulint innodb_buffer_pool_bytes_data; /*!< File bytes used */
ulint innodb_buffer_pool_pages_dirty; /*!< Dirty data pages */
ulint innodb_buffer_pool_bytes_dirty; /*!< File bytes modified */
ulint innodb_buffer_pool_pages_misc; /*!< Miscellanous pages */ ulint innodb_buffer_pool_pages_misc; /*!< Miscellanous pages */
ulint innodb_buffer_pool_pages_free; /*!< Free pages */
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
ulint innodb_buffer_pool_pages_latched; /*!< Latched pages */ ulint innodb_buffer_pool_pages_latched; /*!< Latched pages */
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
ulint innodb_buffer_pool_pages_made_not_young;
ulint innodb_buffer_pool_pages_made_young;
ulint innodb_buffer_pool_pages_old;
ulint innodb_buffer_pool_read_requests; /*!< buf_pool.stat.n_page_gets */
ulint innodb_buffer_pool_reads; /*!< srv_buf_pool_reads */
ulint innodb_buffer_pool_read_ahead_rnd;/*!< srv_read_ahead_rnd */
ulint innodb_buffer_pool_read_ahead; /*!< srv_read_ahead */
ulint innodb_buffer_pool_read_ahead_evicted;/*!< srv_read_ahead evicted*/
ulint innodb_checkpoint_age; ulint innodb_checkpoint_age;
ulint innodb_checkpoint_max_age; ulint innodb_checkpoint_max_age;
ulint innodb_data_pending_reads; /*!< Pending reads */ ulint innodb_data_pending_reads; /*!< Pending reads */

View File

@@ -924,14 +924,19 @@ public:
/** /**
Determine if the specified transaction or any older one might be active. Determine if the specified transaction or any older one might be active.
@param caller_trx used to get/set pins @param trx current transaction
@param id transaction identifier @param id transaction identifier
@return whether any transaction not newer than id might be active @return whether any transaction not newer than id might be active
*/ */
bool find_same_or_older(trx_t *caller_trx, trx_id_t id) bool find_same_or_older(trx_t *trx, trx_id_t id)
{ {
return rw_trx_hash.iterate(caller_trx, find_same_or_older_callback, &id); if (trx->max_inactive_id >= id)
return false;
bool found= rw_trx_hash.iterate(trx, find_same_or_older_callback, &id);
if (!found)
trx->max_inactive_id= id;
return found;
} }

View File

@@ -642,6 +642,10 @@ public:
Cleared in commit_in_memory() after commit_state(), Cleared in commit_in_memory() after commit_state(),
trx_sys_t::deregister_rw(), release_locks(). */ trx_sys_t::deregister_rw(), release_locks(). */
trx_id_t id; trx_id_t id;
/** The largest encountered transaction identifier for which no
transaction was observed to be active. This is a cache to speed up
trx_sys_t::find_same_or_older(). */
trx_id_t max_inactive_id;
private: private:
/** mutex protecting state and some of lock /** mutex protecting state and some of lock

View File

@@ -1064,13 +1064,16 @@ lock_sec_rec_some_has_impl(
const trx_id_t max_trx_id= page_get_max_trx_id(page_align(rec)); const trx_id_t max_trx_id= page_get_max_trx_id(page_align(rec));
if ((caller_trx->id > max_trx_id && /* Note: It is possible to have caller_trx->id == 0 in a locking read
!trx_sys.find_same_or_older(caller_trx, max_trx_id)) || if caller_trx has not modified any persistent tables. */
if (!trx_sys.find_same_or_older(caller_trx, max_trx_id) ||
!lock_check_trx_id_sanity(max_trx_id, rec, index, offsets)) !lock_check_trx_id_sanity(max_trx_id, rec, index, offsets))
return nullptr; return nullptr;
/* In this case it is possible that some transaction has an implicit /* We checked above that some active (or XA PREPARE) transaction exists
x-lock. We have to look in the clustered index. */ that is older than PAGE_MAX_TRX_ID. That is, some transaction may be
holding an implicit lock on the record. We have to look up the
clustered index record to find if it is (or was) the case. */
return row_vers_impl_x_locked(caller_trx, rec, index, offsets); return row_vers_impl_x_locked(caller_trx, rec, index, offsets);
} }
@@ -5157,20 +5160,24 @@ has an implicit lock on the record. The transaction instance must have a
reference count > 0 so that it can't be committed and freed before this reference count > 0 so that it can't be committed and freed before this
function has completed. */ function has completed. */
static static
void bool
lock_rec_convert_impl_to_expl_for_trx( lock_rec_convert_impl_to_expl_for_trx(
/*==================================*/ /*==================================*/
trx_t* trx, /*!< in/out: active transaction */
const page_id_t id, /*!< in: page identifier */ const page_id_t id, /*!< in: page identifier */
const rec_t* rec, /*!< in: user record on page */ const rec_t* rec, /*!< in: user record on page */
dict_index_t* index, /*!< in: index of record */ dict_index_t* index) /*!< in: index of record */
trx_t* trx, /*!< in/out: active transaction */
ulint heap_no)/*!< in: rec heap number to lock */
{ {
if (!trx)
return false;
ut_ad(trx->is_referenced()); ut_ad(trx->is_referenced());
ut_ad(page_rec_is_leaf(rec)); ut_ad(page_rec_is_leaf(rec));
ut_ad(!rec_is_metadata(rec, *index)); ut_ad(!rec_is_metadata(rec, *index));
DEBUG_SYNC_C("before_lock_rec_convert_impl_to_expl_for_trx"); DEBUG_SYNC_C("before_lock_rec_convert_impl_to_expl_for_trx");
ulint heap_no= page_rec_get_heap_no(rec);
{ {
LockGuard g{lock_sys.rec_hash, id}; LockGuard g{lock_sys.rec_hash, id};
trx->mutex_lock(); trx->mutex_lock();
@@ -5187,6 +5194,7 @@ lock_rec_convert_impl_to_expl_for_trx(
trx->release_reference(); trx->release_reference();
DEBUG_SYNC_C("after_lock_rec_convert_impl_to_expl_for_trx"); DEBUG_SYNC_C("after_lock_rec_convert_impl_to_expl_for_trx");
return false;
} }
@@ -5260,7 +5268,6 @@ static void lock_rec_other_trx_holds_expl(trx_t *caller_trx, trx_t *trx,
} }
#endif /* UNIV_DEBUG */ #endif /* UNIV_DEBUG */
/** If an implicit x-lock exists on a record, convert it to an explicit one. /** If an implicit x-lock exists on a record, convert it to an explicit one.
Often, this is called by a transaction that is about to enter a lock wait Often, this is called by a transaction that is about to enter a lock wait
@@ -5272,12 +5279,14 @@ This may also be called by the same transaction that is already holding
an implicit exclusive lock on the record. In this case, no explicit lock an implicit exclusive lock on the record. In this case, no explicit lock
should be created. should be created.
@tparam is_primary whether the index is the primary key
@param[in,out] caller_trx current transaction @param[in,out] caller_trx current transaction
@param[in] id index tree leaf page identifier @param[in] id index tree leaf page identifier
@param[in] rec record on the leaf page @param[in] rec record on the leaf page
@param[in] index the index of the record @param[in] index the index of the record
@param[in] offsets rec_get_offsets(rec,index) @param[in] offsets rec_get_offsets(rec,index)
@return whether caller_trx already holds an exclusive lock on rec */ @return whether caller_trx already holds an exclusive lock on rec */
template<bool is_primary>
static static
bool bool
lock_rec_convert_impl_to_expl( lock_rec_convert_impl_to_expl(
@@ -5295,8 +5304,9 @@ lock_rec_convert_impl_to_expl(
ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets)); ut_ad(!page_rec_is_comp(rec) == !rec_offs_comp(offsets));
ut_ad(page_rec_is_leaf(rec)); ut_ad(page_rec_is_leaf(rec));
ut_ad(!rec_is_metadata(rec, *index)); ut_ad(!rec_is_metadata(rec, *index));
ut_ad(index->is_primary() == is_primary);
if (dict_index_is_clust(index)) { if (is_primary) {
trx_id_t trx_id; trx_id_t trx_id;
trx_id = lock_clust_rec_some_has_impl(rec, index, offsets); trx_id = lock_clust_rec_some_has_impl(rec, index, offsets);
@@ -5322,20 +5332,7 @@ lock_rec_convert_impl_to_expl(
ut_d(lock_rec_other_trx_holds_expl(caller_trx, trx, rec, id)); ut_d(lock_rec_other_trx_holds_expl(caller_trx, trx, rec, id));
} }
if (trx) { return lock_rec_convert_impl_to_expl_for_trx(trx, id, rec, index);
ulint heap_no = page_rec_get_heap_no(rec);
ut_ad(trx->is_referenced());
/* If the transaction is still active and has no
explicit x-lock set on the record, set one for it.
trx cannot be committed until the ref count is zero. */
lock_rec_convert_impl_to_expl_for_trx(
id, rec, index, trx, heap_no);
}
return false;
} }
/*********************************************************************//** /*********************************************************************//**
@@ -5374,7 +5371,8 @@ lock_clust_rec_modify_check_and_lock(
/* If a transaction has no explicit x-lock set on the record, set one /* If a transaction has no explicit x-lock set on the record, set one
for it */ for it */
if (lock_rec_convert_impl_to_expl(thr_get_trx(thr), block->page.id(), if (lock_rec_convert_impl_to_expl<true>(thr_get_trx(thr),
block->page.id(),
rec, index, offsets)) { rec, index, offsets)) {
/* We already hold an implicit exclusive lock. */ /* We already hold an implicit exclusive lock. */
return DB_SUCCESS; return DB_SUCCESS;
@@ -5532,15 +5530,17 @@ lock_sec_rec_read_check_and_lock(
return(DB_SUCCESS); return(DB_SUCCESS);
} }
const page_id_t id{block->page.id()};
ut_ad(!rec_is_metadata(rec, *index)); ut_ad(!rec_is_metadata(rec, *index));
trx_t *trx = thr_get_trx(thr); trx_t *trx = thr_get_trx(thr);
if (lock_table_has(trx, index->table, mode)) {
return DB_SUCCESS;
}
if (!page_rec_is_supremum(rec) if (!page_rec_is_supremum(rec)
&& !lock_table_has(trx, index->table, LOCK_X) && lock_rec_convert_impl_to_expl<false>(
&& lock_rec_convert_impl_to_expl(thr_get_trx(thr), id, rec, trx, block->page.id(), rec, index, offsets)
index, offsets)
&& gap_mode == LOCK_REC_NOT_GAP) { && gap_mode == LOCK_REC_NOT_GAP) {
/* We already hold an implicit exclusive lock. */ /* We already hold an implicit exclusive lock. */
return DB_SUCCESS; return DB_SUCCESS;
@@ -5565,7 +5565,8 @@ lock_sec_rec_read_check_and_lock(
if (trx->wsrep == 3) trx->wsrep = 1; if (trx->wsrep == 3) trx->wsrep = 1;
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
ut_ad(lock_rec_queue_validate(false, id, rec, index, offsets)); ut_ad(lock_rec_queue_validate(false, block->page.id(),
rec, index, offsets));
return(err); return(err);
} }
@@ -5622,7 +5623,8 @@ lock_clust_rec_read_check_and_lock(
trx_t *trx = thr_get_trx(thr); trx_t *trx = thr_get_trx(thr);
if (!lock_table_has(trx, index->table, LOCK_X) if (!lock_table_has(trx, index->table, LOCK_X)
&& heap_no != PAGE_HEAP_NO_SUPREMUM && heap_no != PAGE_HEAP_NO_SUPREMUM
&& lock_rec_convert_impl_to_expl(trx, id, rec, index, offsets) && lock_rec_convert_impl_to_expl<true>(trx, id,
rec, index, offsets)
&& gap_mode == LOCK_REC_NOT_GAP) { && gap_mode == LOCK_REC_NOT_GAP) {
/* We already hold an implicit exclusive lock. */ /* We already hold an implicit exclusive lock. */
return DB_SUCCESS; return DB_SUCCESS;

View File

@@ -1152,14 +1152,6 @@ wait_suspend_loop:
if (!buf_pool.is_initialised()) { if (!buf_pool.is_initialised()) {
ut_ad(!srv_was_started); ut_ad(!srv_was_started);
} else if (ulint pending_io = buf_pool.io_pending()) {
if (srv_print_verbose_log && count > 600) {
ib::info() << "Waiting for " << pending_io << " buffer"
" page I/Os to complete";
count = 0;
}
goto loop;
} else { } else {
buf_flush_buffer_pool(); buf_flush_buffer_pool();
} }

View File

@@ -3093,7 +3093,7 @@ set_start_lsn:
/* The following is adapted from /* The following is adapted from
buf_pool_t::insert_into_flush_list() */ buf_pool_t::insert_into_flush_list() */
mysql_mutex_lock(&buf_pool.flush_list_mutex); mysql_mutex_lock(&buf_pool.flush_list_mutex);
buf_pool.stat.flush_list_bytes+= block->physical_size(); buf_pool.flush_list_bytes+= block->physical_size();
block->page.set_oldest_modification(start_lsn); block->page.set_oldest_modification(start_lsn);
UT_LIST_ADD_FIRST(buf_pool.flush_list, &block->page); UT_LIST_ADD_FIRST(buf_pool.flush_list, &block->page);
buf_pool.page_cleaner_wakeup(); buf_pool.page_cleaner_wakeup();

View File

@@ -140,9 +140,9 @@ inline void buf_pool_t::insert_into_flush_list(buf_page_t *prev,
UT_LIST_REMOVE(flush_list, &block->page); UT_LIST_REMOVE(flush_list, &block->page);
} }
else else
stat.flush_list_bytes+= block->physical_size(); flush_list_bytes+= block->physical_size();
ut_ad(stat.flush_list_bytes <= curr_pool_size); ut_ad(flush_list_bytes <= curr_pool_size);
if (prev) if (prev)
UT_LIST_INSERT_AFTER(flush_list, prev, &block->page); UT_LIST_INSERT_AFTER(flush_list, prev, &block->page);

View File

@@ -217,8 +217,7 @@ rec_get_n_extern_new(
stored in one byte for 0..127. The length stored in one byte for 0..127. The length
will be encoded in two bytes when it is 128 or will be encoded in two bytes when it is 128 or
more, or when the field is stored externally. */ more, or when the field is stored externally. */
if (DATA_BIG_COL(col)) { if (UNIV_UNLIKELY(len & 0x80) && DATA_BIG_COL(col)) {
if (len & 0x80) {
/* 1exxxxxxx xxxxxxxx */ /* 1exxxxxxx xxxxxxxx */
if (len & 0x40) { if (len & 0x40) {
n_extern++; n_extern++;
@@ -226,7 +225,6 @@ rec_get_n_extern_new(
lens--; lens--;
} }
} }
}
} while (++i < n); } while (++i < n);
return(n_extern); return(n_extern);
@@ -244,6 +242,10 @@ enum rec_leaf_format {
REC_LEAF_INSTANT REC_LEAF_INSTANT
}; };
#if defined __GNUC__ && !defined __clang__ && __GNUC__ < 11
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wconversion" /* GCC 5 to 10 need this */
#endif
/** Determine the offset to each field in a leaf-page record /** Determine the offset to each field in a leaf-page record
in ROW_FORMAT=COMPACT,DYNAMIC,COMPRESSED. in ROW_FORMAT=COMPACT,DYNAMIC,COMPRESSED.
This is a special case of rec_init_offsets() and rec_get_offsets_func(). This is a special case of rec_init_offsets() and rec_get_offsets_func().
@@ -361,8 +363,7 @@ start:
do { do {
if (mblob) { if (mblob) {
if (i == index->first_user_field()) { if (i == index->first_user_field()) {
offs = static_cast<rec_offs>(offs offs += FIELD_REF_SIZE;
+ FIELD_REF_SIZE);
len = combine(offs, STORED_OFFPAGE); len = combine(offs, STORED_OFFPAGE);
any |= REC_OFFS_EXTERNAL; any |= REC_OFFS_EXTERNAL;
field--; field--;
@@ -433,27 +434,23 @@ start:
stored in one byte for 0..127. The length stored in one byte for 0..127. The length
will be encoded in two bytes when it is 128 or will be encoded in two bytes when it is 128 or
more, or when the field is stored externally. */ more, or when the field is stored externally. */
if ((len & 0x80) && DATA_BIG_COL(col)) { if (UNIV_UNLIKELY(len & 0x80) && DATA_BIG_COL(col)) {
/* 1exxxxxxx xxxxxxxx */ /* 1exxxxxxx xxxxxxxx */
len = static_cast<rec_offs>(len << 8 len <<= 8;
| *lens--); len |= *lens--;
offs = static_cast<rec_offs>(offs static_assert(STORED_OFFPAGE == 0x4000, "");
+ get_value(len)); static_assert(REC_OFFS_EXTERNAL == 0x4000, "");
if (UNIV_UNLIKELY(len & 0x4000)) { const rec_offs ext = len & REC_OFFS_EXTERNAL;
ut_ad(index->is_primary()); offs += get_value(len);
any |= REC_OFFS_EXTERNAL; len = offs | ext;
len = combine(offs, STORED_OFFPAGE); any |= ext;
} else { ut_ad(!ext || index->is_primary());
len = offs;
}
continue; continue;
} }
len = offs = static_cast<rec_offs>(offs + len); len = offs += len;
} else { } else {
len = offs = static_cast<rec_offs>(offs len = offs += field->fixed_len;
+ field->fixed_len);
} }
} while (field++, rec_offs_base(offsets)[++i] = len, } while (field++, rec_offs_base(offsets)[++i] = len,
i < rec_offs_n_fields(offsets)); i < rec_offs_n_fields(offsets));
@@ -679,8 +676,7 @@ rec_init_offsets(
do { do {
rec_offs len; rec_offs len;
if (UNIV_UNLIKELY(i == n_node_ptr_field)) { if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
len = offs = static_cast<rec_offs>( len = offs += REC_NODE_PTR_SIZE;
offs + REC_NODE_PTR_SIZE);
goto resolved; goto resolved;
} }
@@ -720,29 +716,25 @@ rec_init_offsets(
encoded in two bytes when it is 128 or encoded in two bytes when it is 128 or
more, or when the field is stored more, or when the field is stored
externally. */ externally. */
if (DATA_BIG_COL(col)) { if (UNIV_UNLIKELY(len & 0x80)
if (len & 0x80) { && DATA_BIG_COL(col)) {
/* 1exxxxxxx xxxxxxxx */ /* 1exxxxxxx xxxxxxxx */
len = static_cast<rec_offs>( len <<= 8;
len << 8 | *lens--); len |= *lens--;
/* B-tree node pointers /* B-tree node pointers
must not contain externally must not contain externally
stored columns. Thus stored columns. Thus
the "e" flag must be 0. */ the "e" flag must be 0. */
ut_a(!(len & 0x4000)); ut_a(!(len & 0x4000));
offs = static_cast<rec_offs>( offs += len & 0x3fff;
offs + get_value(len));
len = offs; len = offs;
goto resolved; goto resolved;
} }
}
len = offs = static_cast<rec_offs>(offs + len); len = offs += len;
} else { } else {
len = offs = static_cast<rec_offs>( len = offs += field->fixed_len;
offs + field->fixed_len);
} }
resolved: resolved:
rec_offs_base(offsets)[i + 1] = len; rec_offs_base(offsets)[i + 1] = len;
@@ -759,35 +751,30 @@ resolved:
rec_offs any; rec_offs any;
if (rec_get_1byte_offs_flag(rec)) { if (rec_get_1byte_offs_flag(rec)) {
offs = static_cast<rec_offs>(offs + n_fields); offs += static_cast<rec_offs>(n_fields);
any = offs; any = offs;
/* Determine offsets to fields */ /* Determine offsets to fields */
do { do {
offs = rec_1_get_field_end_info(rec, i); offs = rec_1_get_field_end_info(rec, i);
if (offs & REC_1BYTE_SQL_NULL_MASK) { if (offs & REC_1BYTE_SQL_NULL_MASK) {
offs &= static_cast<rec_offs>( offs ^= REC_1BYTE_SQL_NULL_MASK
~REC_1BYTE_SQL_NULL_MASK); | SQL_NULL;
set_type(offs, SQL_NULL);
} }
rec_offs_base(offsets)[1 + i] = offs; rec_offs_base(offsets)[1 + i] = offs;
} while (++i < n); } while (++i < n);
} else { } else {
offs = static_cast<rec_offs>(offs + 2 * n_fields); offs += static_cast<rec_offs>(2 * n_fields);
any = offs; any = offs;
/* Determine offsets to fields */ /* Determine offsets to fields */
do { do {
offs = rec_2_get_field_end_info(rec, i); offs = rec_2_get_field_end_info(rec, i);
if (offs & REC_2BYTE_SQL_NULL_MASK) { static_assert(REC_2BYTE_SQL_NULL_MASK
offs &= static_cast<rec_offs>( == SQL_NULL, "");
~REC_2BYTE_SQL_NULL_MASK); static_assert(REC_2BYTE_EXTERN_MASK
set_type(offs, SQL_NULL); == STORED_OFFPAGE, "");
} static_assert(REC_OFFS_EXTERNAL
if (offs & REC_2BYTE_EXTERN_MASK) { == STORED_OFFPAGE, "");
offs &= static_cast<rec_offs>( any |= (offs & REC_OFFS_EXTERNAL);
~REC_2BYTE_EXTERN_MASK);
set_type(offs, STORED_OFFPAGE);
any |= REC_OFFS_EXTERNAL;
}
rec_offs_base(offsets)[1 + i] = offs; rec_offs_base(offsets)[1 + i] = offs;
} while (++i < n); } while (++i < n);
} }
@@ -999,8 +986,7 @@ rec_get_offsets_reverse(
do { do {
rec_offs len; rec_offs len;
if (UNIV_UNLIKELY(i == n_node_ptr_field)) { if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
len = offs = static_cast<rec_offs>( len = offs += REC_NODE_PTR_SIZE;
offs + REC_NODE_PTR_SIZE);
goto resolved; goto resolved;
} }
@@ -1037,30 +1023,23 @@ rec_get_offsets_reverse(
stored in one byte for 0..127. The length stored in one byte for 0..127. The length
will be encoded in two bytes when it is 128 or will be encoded in two bytes when it is 128 or
more, or when the field is stored externally. */ more, or when the field is stored externally. */
if (DATA_BIG_COL(col)) { if (UNIV_UNLIKELY(len & 0x80) && DATA_BIG_COL(col)) {
if (len & 0x80) {
/* 1exxxxxxx xxxxxxxx */ /* 1exxxxxxx xxxxxxxx */
len = static_cast<rec_offs>( len &= 0x7f;
len << 8 | *lens++); len <<= 8;
len |= *lens++;
offs = static_cast<rec_offs>( static_assert(STORED_OFFPAGE == 0x4000, "");
offs + get_value(len)); static_assert(REC_OFFS_EXTERNAL == 0x4000, "");
if (UNIV_UNLIKELY(len & 0x4000)) { rec_offs ext = len & REC_OFFS_EXTERNAL;
any_ext = REC_OFFS_EXTERNAL; offs += get_value(len);
len = combine(offs, len = offs | ext;
STORED_OFFPAGE); any_ext |= ext;
} else {
len = offs;
}
goto resolved; goto resolved;
} }
}
len = offs = static_cast<rec_offs>(offs + len); len = offs += len;
} else { } else {
len = offs = static_cast<rec_offs>(offs len = offs += field->fixed_len;
+ field->fixed_len);
} }
resolved: resolved:
rec_offs_base(offsets)[i + 1] = len; rec_offs_base(offsets)[i + 1] = len;
@@ -1100,7 +1079,7 @@ rec_get_nth_field_offs_old(
return(os); return(os);
} }
next_os = next_os & ~REC_1BYTE_SQL_NULL_MASK; next_os &= ~REC_1BYTE_SQL_NULL_MASK;
} else { } else {
os = rec_2_get_field_start_offs(rec, n); os = rec_2_get_field_start_offs(rec, n);
@@ -1112,8 +1091,7 @@ rec_get_nth_field_offs_old(
return(os); return(os);
} }
next_os = next_os & ~(REC_2BYTE_SQL_NULL_MASK next_os &= ~(REC_2BYTE_SQL_NULL_MASK | REC_2BYTE_EXTERN_MASK);
| REC_2BYTE_EXTERN_MASK);
} }
*len = next_os - os; *len = next_os - os;
@@ -1266,7 +1244,8 @@ rec_get_converted_size_comp_prefix_low(
} else if (dfield_is_ext(dfield)) { } else if (dfield_is_ext(dfield)) {
ut_ad(DATA_BIG_COL(field->col)); ut_ad(DATA_BIG_COL(field->col));
extra_size += 2; extra_size += 2;
} else if (len < 128 || !DATA_BIG_COL(field->col)) { } else if (UNIV_LIKELY(len < 128)
|| !DATA_BIG_COL(field->col)) {
extra_size++; extra_size++;
} else { } else {
/* For variable-length columns, we look up the /* For variable-length columns, we look up the
@@ -1617,14 +1596,7 @@ start:
/* set the null flag if necessary */ /* set the null flag if necessary */
if (dfield_is_null(field)) { if (dfield_is_null(field)) {
#if defined __GNUC__ && !defined __clang__ && __GNUC__ < 6
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wconversion" /* GCC 5 may need this here */
#endif
*nulls |= static_cast<byte>(null_mask); *nulls |= static_cast<byte>(null_mask);
#if defined __GNUC__ && !defined __clang__ && __GNUC__ < 6
# pragma GCC diagnostic pop
#endif
null_mask <<= 1; null_mask <<= 1;
continue; continue;
} }
@@ -1733,6 +1705,9 @@ rec_convert_dtuple_to_rec_new(
REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT); REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
return buf; return buf;
} }
#if defined __GNUC__ && !defined __clang__ && __GNUC__ < 11
# pragma GCC diagnostic pop /* ignored "-Wconversion" */
#endif
/*********************************************************//** /*********************************************************//**
Builds a physical record out of a data tuple and Builds a physical record out of a data tuple and
@@ -2095,15 +2070,13 @@ rec_copy_prefix_to_buf(
stored in one byte for 0..127. The length stored in one byte for 0..127. The length
will be encoded in two bytes when it is 128 or will be encoded in two bytes when it is 128 or
more, or when the column is stored externally. */ more, or when the column is stored externally. */
if (DATA_BIG_COL(col)) { if (UNIV_UNLIKELY(len & 0x80) && DATA_BIG_COL(col)) {
if (len & 0x80) {
/* 1exxxxxx */ /* 1exxxxxx */
len &= 0x3f; len &= 0x3f;
len <<= 8; len <<= 8;
len |= *lens--; len |= *lens--;
UNIV_PREFETCH_R(lens); UNIV_PREFETCH_R(lens);
} }
}
prefix_len += len; prefix_len += len;
} }
} }

View File

@@ -2253,7 +2253,7 @@ row_ins_duplicate_online(ulint n_uniq, const dtuple_t *entry,
ulint trx_id_len; ulint trx_id_len;
if (fields == n_uniq if (fields == n_uniq + 2
&& memcmp(rec_get_nth_field(rec, offsets, n_uniq, &trx_id_len), && memcmp(rec_get_nth_field(rec, offsets, n_uniq, &trx_id_len),
reset_trx_id, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN)) { reset_trx_id, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN)) {
ut_ad(trx_id_len == DATA_TRX_ID_LEN); ut_ad(trx_id_len == DATA_TRX_ID_LEN);

View File

@@ -3078,6 +3078,9 @@ row_log_apply_op_low(
mtr_start(&mtr); mtr_start(&mtr);
index->set_modified(mtr); index->set_modified(mtr);
cursor.page_cur.index = index; cursor.page_cur.index = index;
if (has_index_lock) {
mtr_x_lock_index(index, &mtr);
}
/* We perform the pessimistic variant of the operations if we /* We perform the pessimistic variant of the operations if we
already hold index->lock exclusively. First, search the already hold index->lock exclusively. First, search the
@@ -3085,7 +3088,8 @@ row_log_apply_op_low(
depending on when the row in the clustered index was depending on when the row in the clustered index was
scanned. */ scanned. */
*error = cursor.search_leaf(entry, PAGE_CUR_LE, has_index_lock *error = cursor.search_leaf(entry, PAGE_CUR_LE, has_index_lock
? BTR_MODIFY_TREE : BTR_MODIFY_LEAF, &mtr); ? BTR_MODIFY_TREE_ALREADY_LATCHED
: BTR_MODIFY_LEAF, &mtr);
if (UNIV_UNLIKELY(*error != DB_SUCCESS)) { if (UNIV_UNLIKELY(*error != DB_SUCCESS)) {
goto func_exit; goto func_exit;
} }

View File

@@ -859,7 +859,7 @@ static monitor_info_t innodb_counter_info[] =
MONITOR_DEFAULT_START, MONITOR_MODULE_INDEX}, MONITOR_DEFAULT_START, MONITOR_MODULE_INDEX},
{"index_page_splits", "index", "Number of index page splits", {"index_page_splits", "index", "Number of index page splits",
MONITOR_NONE, MONITOR_EXISTING,
MONITOR_DEFAULT_START, MONITOR_INDEX_SPLIT}, MONITOR_DEFAULT_START, MONITOR_INDEX_SPLIT},
{"index_page_merge_attempts", "index", {"index_page_merge_attempts", "index",
@@ -1318,10 +1318,12 @@ srv_mon_process_existing_counter(
/* Get the value from corresponding global variable */ /* Get the value from corresponding global variable */
switch (monitor_id) { switch (monitor_id) {
/* export_vars.innodb_buffer_pool_reads. Num Reads from case MONITOR_INDEX_SPLIT:
disk (page not in buffer) */ value = buf_pool.pages_split;
break;
case MONITOR_OVLD_BUF_POOL_READS: case MONITOR_OVLD_BUF_POOL_READS:
value = srv_stats.buf_pool_reads; value = buf_pool.stat.n_pages_read;
break; break;
/* innodb_buffer_pool_read_requests, the number of logical /* innodb_buffer_pool_read_requests, the number of logical
@@ -1382,7 +1384,7 @@ srv_mon_process_existing_counter(
/* innodb_buffer_pool_bytes_dirty */ /* innodb_buffer_pool_bytes_dirty */
case MONITOR_OVLD_BUF_POOL_BYTES_DIRTY: case MONITOR_OVLD_BUF_POOL_BYTES_DIRTY:
value = buf_pool.stat.flush_list_bytes; value = buf_pool.flush_list_bytes;
break; break;
/* innodb_buffer_pool_pages_free */ /* innodb_buffer_pool_pages_free */

View File

@@ -655,6 +655,7 @@ void srv_boot()
if (transactional_lock_enabled()) if (transactional_lock_enabled())
sql_print_information("InnoDB: Using transactional memory"); sql_print_information("InnoDB: Using transactional memory");
#endif #endif
buf_dblwr.init();
srv_thread_pool_init(); srv_thread_pool_init();
trx_pool_init(); trx_pool_init();
srv_init(); srv_init();
@@ -909,56 +910,19 @@ srv_export_innodb_status(void)
export_vars.innodb_data_writes = os_n_file_writes; export_vars.innodb_data_writes = os_n_file_writes;
ulint dblwr = 0;
if (buf_dblwr.is_initialised()) {
buf_dblwr.lock(); buf_dblwr.lock();
dblwr = buf_dblwr.submitted(); ulint dblwr = buf_dblwr.submitted();
export_vars.innodb_dblwr_pages_written = buf_dblwr.written(); export_vars.innodb_dblwr_pages_written = buf_dblwr.written();
export_vars.innodb_dblwr_writes = buf_dblwr.batches(); export_vars.innodb_dblwr_writes = buf_dblwr.batches();
buf_dblwr.unlock(); buf_dblwr.unlock();
}
export_vars.innodb_data_written = srv_stats.data_written + dblwr; export_vars.innodb_data_written = srv_stats.data_written + dblwr;
export_vars.innodb_buffer_pool_read_requests
= buf_pool.stat.n_page_gets;
export_vars.innodb_buffer_pool_reads = srv_stats.buf_pool_reads;
export_vars.innodb_buffer_pool_read_ahead_rnd =
buf_pool.stat.n_ra_pages_read_rnd;
export_vars.innodb_buffer_pool_read_ahead =
buf_pool.stat.n_ra_pages_read;
export_vars.innodb_buffer_pool_read_ahead_evicted =
buf_pool.stat.n_ra_pages_evicted;
export_vars.innodb_buffer_pool_pages_data =
UT_LIST_GET_LEN(buf_pool.LRU);
export_vars.innodb_buffer_pool_bytes_data = export_vars.innodb_buffer_pool_bytes_data =
buf_pool.stat.LRU_bytes buf_pool.stat.LRU_bytes
+ (UT_LIST_GET_LEN(buf_pool.unzip_LRU) + (UT_LIST_GET_LEN(buf_pool.unzip_LRU)
<< srv_page_size_shift); << srv_page_size_shift);
export_vars.innodb_buffer_pool_pages_dirty =
UT_LIST_GET_LEN(buf_pool.flush_list);
export_vars.innodb_buffer_pool_pages_made_young
= buf_pool.stat.n_pages_made_young;
export_vars.innodb_buffer_pool_pages_made_not_young
= buf_pool.stat.n_pages_not_made_young;
export_vars.innodb_buffer_pool_pages_old = buf_pool.LRU_old_len;
export_vars.innodb_buffer_pool_bytes_dirty =
buf_pool.stat.flush_list_bytes;
export_vars.innodb_buffer_pool_pages_free =
UT_LIST_GET_LEN(buf_pool.free);
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
export_vars.innodb_buffer_pool_pages_latched = export_vars.innodb_buffer_pool_pages_latched =
buf_get_latched_pages_number(); buf_get_latched_pages_number();

View File

@@ -452,7 +452,8 @@ err_exit:
fil_set_max_space_id_if_bigger(space_id); fil_set_max_space_id_if_bigger(space_id);
fil_space_t *space= fil_space_t::create(space_id, fsp_flags, fil_space_t *space= fil_space_t::create(space_id, fsp_flags,
FIL_TYPE_TABLESPACE, NULL); FIL_TYPE_TABLESPACE, nullptr,
FIL_ENCRYPTION_DEFAULT, true);
ut_a(fil_validate()); ut_a(fil_validate());
ut_a(space); ut_a(space);
@@ -798,9 +799,7 @@ static lsn_t srv_prepare_to_delete_redo_log_file()
{ {
DBUG_ENTER("srv_prepare_to_delete_redo_log_file"); DBUG_ENTER("srv_prepare_to_delete_redo_log_file");
/* Disable checkpoints in the page cleaner. */ ut_ad(recv_sys.recovery_on);
ut_ad(!recv_sys.recovery_on);
recv_sys.recovery_on= true;
/* Clean the buffer pool. */ /* Clean the buffer pool. */
buf_flush_sync(); buf_flush_sync();
@@ -1343,8 +1342,6 @@ dberr_t srv_start(bool create_new_db)
} }
} }
recv_sys.debug_free();
if (srv_operation != SRV_OPERATION_NORMAL) { if (srv_operation != SRV_OPERATION_NORMAL) {
ut_ad(srv_operation == SRV_OPERATION_RESTORE_EXPORT ut_ad(srv_operation == SRV_OPERATION_RESTORE_EXPORT
|| srv_operation == SRV_OPERATION_RESTORE); || srv_operation == SRV_OPERATION_RESTORE);
@@ -1396,6 +1393,8 @@ dberr_t srv_start(bool create_new_db)
return(srv_init_abort(err)); return(srv_init_abort(err));
} }
} }
recv_sys.debug_free();
} }
ut_ad(err == DB_SUCCESS); ut_ad(err == DB_SUCCESS);
@@ -1716,12 +1715,12 @@ void innodb_shutdown()
ut_ad(dict_sys.is_initialised() || !srv_was_started); ut_ad(dict_sys.is_initialised() || !srv_was_started);
ut_ad(trx_sys.is_initialised() || !srv_was_started); ut_ad(trx_sys.is_initialised() || !srv_was_started);
ut_ad(buf_dblwr.is_initialised() || !srv_was_started ut_ad(buf_dblwr.is_created() || !srv_was_started
|| srv_read_only_mode || srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO); || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
ut_ad(lock_sys.is_initialised() || !srv_was_started); ut_ad(lock_sys.is_initialised() || !srv_was_started);
ut_ad(log_sys.is_initialised() || !srv_was_started); ut_ad(log_sys.is_initialised() || !srv_was_started);
ut_ad(ibuf.index || !srv_was_started ut_ad(ibuf.index || !innodb_change_buffering || !srv_was_started
|| srv_force_recovery >= SRV_FORCE_NO_DDL_UNDO); || srv_force_recovery >= SRV_FORCE_NO_DDL_UNDO);
dict_stats_deinit(); dict_stats_deinit();

View File

@@ -404,6 +404,7 @@ void trx_t::free()
sizeof skip_lock_inheritance_and_n_ref); sizeof skip_lock_inheritance_and_n_ref);
/* do not poison mutex */ /* do not poison mutex */
MEM_NOACCESS(&id, sizeof id); MEM_NOACCESS(&id, sizeof id);
MEM_NOACCESS(&max_inactive_id, sizeof id);
MEM_NOACCESS(&state, sizeof state); MEM_NOACCESS(&state, sizeof state);
MEM_NOACCESS(&is_recovered, sizeof is_recovered); MEM_NOACCESS(&is_recovered, sizeof is_recovered);
#ifdef WITH_WSREP #ifdef WITH_WSREP

View File

@@ -172,7 +172,7 @@ compress_pages_page_decompressed compression 0 NULL NULL NULL 0 NULL NULL NULL N
compress_pages_page_compression_error compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of page compression errors compress_pages_page_compression_error compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of page compression errors
compress_pages_encrypted compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of pages encrypted compress_pages_encrypted compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of pages encrypted
compress_pages_decrypted compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of pages decrypted compress_pages_decrypted compression 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of pages decrypted
index_page_splits index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of index page splits index_page_splits index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 status_counter Number of index page splits
index_page_merge_attempts index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of index page merge attempts index_page_merge_attempts index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of index page merge attempts
index_page_merge_successful index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of successful index page merges index_page_merge_successful index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of successful index page merges
index_page_reorg_attempts index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of index page reorganization attempts index_page_reorg_attempts index 0 NULL NULL NULL 0 NULL NULL NULL NULL NULL NULL NULL 0 counter Number of index page reorganization attempts

View File

@@ -107,15 +107,28 @@ then
# shellcheck disable=SC2046 # shellcheck disable=SC2046
debuginfo-install -y mariadb-server $(cat mariadbd-dependencies.txt) debuginfo-install -y mariadb-server $(cat mariadbd-dependencies.txt)
if [ ! $(perf record echo "testing perf" > /dev/null 2>&1) ]
then
echo "perf does not have permission to run on this system. Skipping."
PERF=""
else
echo "Using 'perf' to record performance counters in perf.data files" echo "Using 'perf' to record performance counters in perf.data files"
PERF="perf record -g --freq=99 --output=perf.data --timestamp-filename --pid=$MARIADB_SERVER_PID --" PERF="perf record -g --freq=99 --output=perf.data --timestamp-filename --pid=$MARIADB_SERVER_PID --"
fi
elif [ -e /usr/bin/perf ] elif [ -e /usr/bin/perf ]
then then
# If flamegraphs were not requested, log normal perf counters if possible # If flamegraphs were not requested, log normal perf counters if possible
if [ ! $(perf stat echo "testing perf" > /dev/null 2>&1) ]
then
echo "perf does not have permission to run on this system. Skipping."
PERF=""
else
echo "Using 'perf' to log basic performance counters for benchmark" echo "Using 'perf' to log basic performance counters for benchmark"
fi
PERF="perf stat -p $MARIADB_SERVER_PID --" PERF="perf stat -p $MARIADB_SERVER_PID --"
fi
fi
# Run sysbench on another CPU if system has more than one available # Run sysbench on another CPU if system has more than one available
if [ "$(nproc)" -gt 1 ] if [ "$(nproc)" -gt 1 ]
@@ -133,10 +146,10 @@ uname -a
echo echo
echo "Set highest priority for MariaDB Server process ID $MARIADB_SERVER_PID" echo "Set highest priority for MariaDB Server process ID $MARIADB_SERVER_PID"
renice --priority -20 --pid "$MARIADB_SERVER_PID" renice --priority -20 --pid "$MARIADB_SERVER_PID" || echo "renice failed. Not setting priority."
echo "Set CPU affinity 0 for MariaDB Server process ID $MARIADB_SERVER_PID" echo "Set CPU affinity 0 for MariaDB Server process ID $MARIADB_SERVER_PID"
taskset -cp 0 "$MARIADB_SERVER_PID" taskset -cp 0 "$MARIADB_SERVER_PID" || echo "taskset failed. Not setting cpu affinity."
mariadb -e " mariadb -e "
CREATE DATABASE IF NOT EXISTS sbtest; CREATE DATABASE IF NOT EXISTS sbtest;