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:
@@ -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:
|
||||||
|
1
debian/libmariadb-dev.install
vendored
1
debian/libmariadb-dev.install
vendored
@@ -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
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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
45
include/my_alloca.h
Normal 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 */
|
@@ -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,
|
||||||
|
@@ -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
|
||||||
|
@@ -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() */
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
#
|
||||||
|
@@ -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 #
|
||||||
|
|
||||||
|
@@ -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'
|
||||||
|
@@ -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`
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
@@ -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`;
|
||||||
|
@@ -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>
|
||||||
|
@@ -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"
|
||||||
|
@@ -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" {
|
||||||
|
10
sql/field.h
10
sql/field.h
@@ -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)
|
||||||
|
17
sql/item.h
17
sql/item.h
@@ -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)
|
||||||
|
@@ -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)
|
||||||
|
@@ -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();
|
||||||
|
211
sql/sql_table.cc
211
sql/sql_table.cc
@@ -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;
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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
|
||||||
{
|
{
|
||||||
|
@@ -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
|
||||||
{
|
{
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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,
|
||||||
|
@@ -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,
|
||||||
|
@@ -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
@@ -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);
|
||||||
|
@@ -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(),
|
||||||
|
@@ -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();
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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,
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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();
|
||||||
|
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
@@ -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();
|
||||||
}
|
}
|
||||||
|
@@ -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();
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
@@ -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 */
|
||||||
|
@@ -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();
|
||||||
|
@@ -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();
|
||||||
|
@@ -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
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user