Merge 10.11 into 11.0

This commit is contained in:
Marko Mäkelä 2023-03-17 15:03:17 +02:00
commit 4c355d4e81
97 changed files with 2859 additions and 1530 deletions

View file

@ -331,6 +331,7 @@ mysql-test-run-asan:
needs:
- "fedora-sanitizer: [-DWITH_ASAN=YES]"
<<: *mysql-test-run-def
allow_failure: true
artifacts:
when: always # Also show results when tests fail
reports:
@ -489,6 +490,8 @@ mini-benchmark:
stage: test
dependencies:
- fedora
needs:
- fedora
script:
- ls -la rpm; rm -vf rpm/*.el?.* # Delete artifacts from Centos builds
# 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
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
- cp -av */sysbench-run-*.log */metrics.txt .. # Move files one level down so they can be saved as artifacts
artifacts:

View file

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

View file

@ -19,6 +19,7 @@ usr/share/mysql/estonian
usr/share/mysql/fill_help_tables.sql
usr/share/mysql/french
usr/share/mysql/german
usr/share/mysql/georgian
usr/share/mysql/greek
usr/share/mysql/hindi
usr/share/mysql/hungarian

108
debian/po/ka.po vendored Normal file
View file

@ -0,0 +1,108 @@
# Translation of ka.po to Georgian
# Copyright (C) 2023, MariaDB authors.
# This file is distributed under the same license as the mariadb package.
# Ekaterine Papava <papava.e@gtu.ge>, 2023.
#
msgid ""
msgstr ""
"Project-Id-Version: mariadb\n"
"Report-Msgid-Bugs-To: mariadb@packages.debian.org\n"
"POT-Creation-Date: 2019-07-23 19:16-0300\n"
"PO-Revision-Date: 2023-03-04 05:18+0100\n"
"Last-Translator: Ekaterine Papava <papava.e@gtu.ge>\n"
"Language-Team: Georgian <(nothing)>\n"
"Language: ka\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.2.2\n"
#. Type: note
#. Description
#: ../mariadb-server.templates:2001
msgid "The old data directory will be saved at new location"
msgstr "ძველი მონაცემების საქაღალდე ახალ მდებარეობაზე იქნება შენახული"
#. Type: note
#. Description
#: ../mariadb-server.templates:2001
msgid ""
"A file named /var/lib/mysql/debian-*.flag exists on this system. The number "
"indicates a database binary format version that cannot automatically be "
"upgraded (or downgraded)."
msgstr ""
"ამ სისტემაში არსებობს ფაილი სახელით /var/lib/mysql/debian-*.flag. რიცხვი "
"მიუთითებს ბაზის ბინარული ფორმატის ვერსიაზე, რომლის განახლება (ან ვერსიის "
"ჩამოწევა) შეუძლებელია."
#. Type: note
#. Description
#: ../mariadb-server.templates:2001
msgid ""
"Therefore the previous data directory will be renamed to /var/lib/mysql-* "
"and a new data directory will be initialized at /var/lib/mysql."
msgstr ""
"ამიტომ წინა მონაცემების საქაღალდეს სახელი /var/lib/mysql-*-ზე გადაერქმევა "
"და /var/lib/mysql მონაცემების საქაღალდე თავიდან შეიქმნება."
#. Type: note
#. Description
#: ../mariadb-server.templates:2001
msgid ""
"Please manually export/import your data (e.g. with mysqldump) if needed."
msgstr ""
"საჭიროების შემთხვევაში თქვენი მონაცემები ხელით გაიტანეთ/შემოიტანეთ (მაგ: "
"mysqldump-ით)."
#. Type: note
#. Description
#: ../mariadb-server.templates:3001
msgid "Important note for NIS/YP users"
msgstr "მნიშვნელოვანი შენიშვნა NIS/YP მომხმარებლებისთვის"
#. Type: note
#. Description
#: ../mariadb-server.templates:3001
msgid ""
"Using MariaDB under NIS/YP requires a mysql user account to be added on the "
"local system with:"
msgstr ""
"MariaDB-ის გამოყენება NIS/YP-ის ქვეშ გასაშვებად მოითხოვს ლოკალურ სისტემაში "
"mysql-ის მომხმარებლის დამატებას შემდეგი პარამეტრებით:"
#. Type: note
#. Description
#: ../mariadb-server.templates:3001
msgid ""
"You should also check the permissions and ownership of the /var/lib/mysql "
"directory:"
msgstr "ასევე შეამოწმეთ /var/lib/mysql საქაღალდის წვდომები და მფლობელი:"
#. Type: boolean
#. Description
#: ../mariadb-server.templates:4001
msgid "Remove all MariaDB databases?"
msgstr "წავშალო MariaDB-ის ყველა ბაზა?"
#. Type: boolean
#. Description
#: ../mariadb-server.templates:4001
msgid ""
"The /var/lib/mysql directory which contains the MariaDB databases is about "
"to be removed."
msgstr ""
"საქაღალდე /var/lib/mysql, რომელიც MariaDB-ის მონაცემთა ბაზებს შეიცავს, "
"წაიშლება."
#. Type: boolean
#. Description
#: ../mariadb-server.templates:4001
msgid ""
"If you're removing the MariaDB package in order to later install a more "
"recent version or if a different mariadb-server package is already using it, "
"the data should be kept."
msgstr ""
"თუ შლით MariaDB-ის პაკეტს იმისთვის, რომ მოგვიანებით უფრო ახალი ვერსია "
"დააყენოთ ან mariadb-server-ის სხვა პაკეტი უკვე იყენებს მას, მონაცემები უნდა "
"შენარჩუნდეს."

View file

@ -37,7 +37,7 @@
#define ERRORS_PER_RANGE 1000
#define MAX_SECTIONS 4
#define HEADER_LENGTH 32 /* Length of header in errmsg.sys */
#define ERRMSG_VERSION 4 /* Version number of errmsg.sys */
#define ERRMSG_VERSION 5 /* Version number of errmsg.sys */
#define DEFAULT_CHARSET_DIR "../sql/share/charsets"
#define ER_PREFIX "ER_"
#define ER_PREFIX2 "MARIA_ER_"
@ -85,7 +85,6 @@ struct languages
{
char *lang_long_name; /* full name of the language */
char *lang_short_name; /* abbreviation of the lang. */
char *charset; /* Character set name */
struct languages *next_lang; /* Pointer to next language */
};
@ -329,7 +328,7 @@ static int create_sys_files(struct languages *lang_head,
uint error_count)
{
FILE *to;
uint csnum= 0, i, row_nr;
uint i, row_nr;
ulong length;
uchar head[HEADER_LENGTH];
char outfile[FN_REFLEN], *outfile_end;
@ -345,16 +344,6 @@ static int create_sys_files(struct languages *lang_head,
*/
for (tmp_lang= lang_head; tmp_lang; tmp_lang= tmp_lang->next_lang)
{
/* setting charset name */
if (!(csnum= get_charset_number(tmp_lang->charset, MY_CS_PRIMARY,
MYF(MY_UTF8_IS_UTF8MB3))))
{
fprintf(stderr, "Unknown charset '%s' in '%s'\n", tmp_lang->charset,
TXTFILE);
DBUG_RETURN(1);
}
outfile_end= strxmov(outfile, DATADIRECTORY,
tmp_lang->lang_long_name, NullS);
if (!my_stat(outfile, &stat_info,MYF(0)))
@ -410,7 +399,6 @@ static int create_sys_files(struct languages *lang_head,
int2store(head + 10, max_error); /* Max error */
int2store(head + 12, row_nr);
int2store(head + 14, section_count);
head[30]= csnum;
my_fseek(to, 0l, MY_SEEK_SET, MYF(0));
if (my_fwrite(to, (uchar*) head, HEADER_LENGTH, MYF(MY_WME | MY_FNABP)) ||
@ -450,7 +438,6 @@ static void clean_up(struct languages *lang_head, struct errors *error_head)
next_language= tmp_lang->next_lang;
my_free(tmp_lang->lang_short_name);
my_free(tmp_lang->lang_long_name);
my_free(tmp_lang->charset);
my_free(tmp_lang);
}
@ -1113,12 +1100,6 @@ static struct languages *parse_charset_string(char *str)
DBUG_RETURN(0); /* OOM: Fatal error */
DBUG_PRINT("info", ("short_name: %s", new_lang->lang_short_name));
/* getting the charset name */
str= skip_delimiters(str);
if (!(new_lang->charset= get_word(&str)))
DBUG_RETURN(0); /* Fatal error */
DBUG_PRINT("info", ("charset: %s", new_lang->charset));
/* skipping space, tab or "," */
str= skip_delimiters(str);
}

View file

@ -2271,8 +2271,14 @@ static bool innodb_init()
/* Check if the data files exist or not. */
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)
err= srv_start(create_new_db);
err= srv_start(false);
if (err != DB_SUCCESS)
{
@ -2283,6 +2289,7 @@ static bool innodb_init()
ut_ad(srv_force_recovery <= SRV_FORCE_IGNORE_CORRUPT);
ut_ad(recv_no_log_write);
buf_flush_sync();
recv_sys.debug_free();
DBUG_ASSERT(!buf_pool.any_io_pending());
log_sys.close_file();
@ -3464,7 +3471,9 @@ static void xb_load_single_table_tablespace(const char *dirname,
if (err == DB_SUCCESS && file->space_id() != SRV_TMP_SPACE_ID) {
space = fil_space_t::create(
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);
fil_node_t* node= space->add(
@ -5184,7 +5193,8 @@ exit:
ut_ad(fil_space_t::physical_size(flags) == info.page_size);
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,
flags, &file);
} else {

View file

@ -51,6 +51,8 @@ static struct my_option my_long_options[] =
#endif
{"mysqld", 0, "Read the same set of groups that the mysqld binary does.",
&opt_mysqld, &opt_mysqld, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"mariadbd", 0, "Read the same set of groups that the mariadbd binary does.",
&opt_mysqld, &opt_mysqld, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"no-defaults", 'n', "Return an empty string (useful for scripts).",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"help", '?', "Display this help message and exit.",

View file

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

45
include/my_alloca.h Normal file
View file

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

View file

@ -330,13 +330,6 @@ C_MODE_END
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#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 */
/* We need the following to go around a problem with openssl on solaris */
@ -493,6 +486,7 @@ typedef unsigned short ushort;
#endif
#include <my_compiler.h>
#include <my_alloca.h>
/*
Wen using the embedded library, users might run into link problems,

View file

@ -28,9 +28,7 @@ C_MODE_START
#include <m_ctype.h> /* for CHARSET_INFO */
#include <stdarg.h>
#include <typelib.h>
#ifdef _WIN32
#include <malloc.h> /*for alloca*/
#endif
#include <my_alloca.h>
#include <mysql/plugin.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;
#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_afree(PTR) ((void)0)
#define MAX_ALLOCA_SZ 4096

View file

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

View file

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

View file

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

View file

@ -306,3 +306,13 @@ date_format('2001-01-06', '%w %a %W', 'de_CH')
select date_format('2001-09-01', '%c %b %M', 'de_CH');
date_format('2001-09-01', '%c %b %M', 'de_CH')
9 Sep September
#
# MDEV-30789 Add Georgian error messages and locale
#
SET lc_messages=ka_GE;
SELECT x;
ERROR 42S22: უცნობი სვეტი 'x' 'field list'-ში
SET lc_messages=DEFAULT;
#
# End of 10.11 tests
#

View file

@ -181,3 +181,18 @@ select date_format('2001-10-01', '%c %b %M', 'rm_CH');
select date_format('2001-12-01', '%c %b %M', 'rm_CH');
select date_format('2001-01-06', '%w %a %W', 'de_CH');
select date_format('2001-09-01', '%c %b %M', 'de_CH');
--echo #
--echo # MDEV-30789 Add Georgian error messages and locale
--echo #
SET lc_messages=ka_GE;
--error ER_BAD_FIELD_ERROR
SELECT x;
SET lc_messages=DEFAULT;
--echo #
--echo # End of 10.11 tests
--echo #

View file

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

View file

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

View file

@ -77,7 +77,7 @@ CREATE OR REPLACE TABLE t1 (a DATE) CHARACTER SET utf8
PARTITION BY LIST COLUMNS (a) (PARTITION p0 VALUES IN (FROM_DAYS(100)));
Warnings:
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';
PARTITION_DESCRIPTION
'0000-00-00'

View file

@ -777,16 +777,16 @@ select @@lc_time_names;
@@lc_time_names
en_US
LC_TIME_NAMES: testing locale with the last ID:
set lc_time_names=110;
select @@lc_time_names;
@@lc_time_names
rm_CH
LC_TIME_NAMES: testing a number beyond the valid ID range:
set lc_time_names=111;
ERROR HY000: Unknown locale: '111'
select @@lc_time_names;
@@lc_time_names
rm_CH
ka_GE
LC_TIME_NAMES: testing a number beyond the valid ID range:
set lc_time_names=112;
ERROR HY000: Unknown locale: '112'
select @@lc_time_names;
@@lc_time_names
ka_GE
LC_TIME_NAMES: testing that 0 is en_US:
set lc_time_names=0;
select @@lc_time_names;

View file

@ -538,12 +538,13 @@ set lc_time_names=NULL;
--error ER_UNKNOWN_LOCALE
set lc_time_names=-1;
select @@lc_time_names;
# note same boundary condition tests in sys_vars.lc_time_names_basic
--echo LC_TIME_NAMES: testing locale with the last ID:
set lc_time_names=110;
set lc_time_names=111;
select @@lc_time_names;
--echo LC_TIME_NAMES: testing a number beyond the valid ID range:
--error ER_UNKNOWN_LOCALE
set lc_time_names=111;
set lc_time_names=112;
select @@lc_time_names;
--echo LC_TIME_NAMES: testing that 0 is en_US:
set lc_time_names=0;

View file

@ -30,8 +30,10 @@ insert into t8 values (1, 'publicmessage');
insert into t9 values (1, 'pugliccompressedaaaaaaaaabbbbbbbbbbbbbbccccccccccccccc');
--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%';
--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%';
--let $MYSQLD_DATADIR=`select @@datadir`

View file

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

View file

@ -77,6 +77,9 @@ test/t_dynamic test/t_dynamic 33 5 Dynamic 0
test/t_redundant test/t_redundant 0 5 Redundant 0
=== information_schema.innodb_sys_tablespaces and innodb_sys_datafiles ===
Space_Name Page_Size Zip_Size Path
innodb_undo001 DEFAULT DEFAULT MYSQLD_DATADIR//undo001
innodb_undo002 DEFAULT DEFAULT MYSQLD_DATADIR//undo002
innodb_undo003 DEFAULT DEFAULT MYSQLD_DATADIR//undo003
test/t_redundant DEFAULT DEFAULT MYSQLD_DATADIR/test/t_redundant.ibd
test/t_compact DEFAULT DEFAULT MYSQLD_DATADIR/test/t_compact.ibd
test/t_compressed DEFAULT 2048 MYSQLD_DATADIR/test/t_compressed.ibd

View file

@ -182,7 +182,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_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
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_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

View file

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

View file

@ -214,6 +214,21 @@ WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test';
TABLE_ROWS AVG_ROW_LENGTH>0
3 1
DROP TABLE t1;
#
# MDEV-29975 InnoDB fails to release savepoint during bulk insert
#
CREATE TABLE t (c INT KEY) ENGINE=InnoDB;
begin;
INSERT INTO t VALUES (0,0);
ERROR 21S01: Column count doesn't match value count at row 1
SAVEPOINT a;
INSERT INTO t VALUES (0),(0);
ERROR HY000: Got error 1 "Operation not permitted" during COMMIT
SAVEPOINT a;
commit;
SELECT * FROM t;
c
DROP TABLE t;
# End of 10.6 tests
#
# MDEV-26947 UNIQUE column checks fail in InnoDB resulting

View file

@ -43,5 +43,25 @@ t1 CREATE TABLE `t1` (
PRIMARY KEY (`f1`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci
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;
SET DEBUG_SYNC=reset;

View file

@ -2,6 +2,11 @@ SET GLOBAL innodb_fast_shutdown=0;
# restart: --innodb_undo_tablespaces=2
SET GLOBAL innodb_undo_log_truncate = 0;
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
=== information_schema.innodb_sys_tablespaces and innodb_sys_datafiles ===
Space_Name Page_Size Zip_Size Path
innodb_undo001 DEFAULT DEFAULT MYSQLD_DATADIR//undo001
innodb_undo002 DEFAULT DEFAULT MYSQLD_DATADIR//undo002
innodb_temporary DEFAULT DEFAULT MYSQLD_DATADIR/ibtmp1
create table t1(keyc int primary key, c char(100)) engine = innodb;
create table t2(keyc int primary key, c char(100)) engine = innodb;
connect con1,localhost,root,,;

View file

@ -235,6 +235,20 @@ SELECT TABLE_ROWS, AVG_ROW_LENGTH>0 FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME='t1' AND TABLE_SCHEMA='test';
DROP TABLE t1;
--echo #
--echo # MDEV-29975 InnoDB fails to release savepoint during bulk insert
--echo #
CREATE TABLE t (c INT KEY) ENGINE=InnoDB;
begin;
--error ER_WRONG_VALUE_COUNT_ON_ROW
INSERT INTO t VALUES (0,0);
SAVEPOINT a;
--error ER_ERROR_DURING_COMMIT
INSERT INTO t VALUES (0),(0);
SAVEPOINT a;
commit;
SELECT * FROM t;
DROP TABLE t;
--echo # End of 10.6 tests
--echo #

View file

@ -59,5 +59,29 @@ connection default;
reap;
SHOW CREATE 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;
SET DEBUG_SYNC=reset;

View file

@ -1,2 +1,3 @@
--innodb-buffer-pool-size=24M
--innodb-immediate-scrub-data-uncompressed=ON
--loose-innodb-sys-tablespaces

View file

@ -19,6 +19,9 @@ let $restart_parameters="--innodb_undo_tablespaces=2";
SET GLOBAL innodb_undo_log_truncate = 0;
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
LET $MYSQLD_DATADIR = `select @@datadir`;
LET $INNODB_PAGE_SIZE = `select @@innodb_page_size`;
--source suite/innodb/include/show_i_s_tablespaces.inc
#-----------------------------------------------------------------------------
#
# Perform DML action using multiple clients and multiple undo tablespace.

View file

@ -7,7 +7,7 @@
# Test 3) Query some information_shema tables that are dependent upon
# the page size.
SELECT t.name table_name, t.n_cols, t.flag table_flags,
@@ -36,13 +36,13 @@
@@ -36,7 +36,7 @@
table_name n_cols table_flags index_name root_page type n_fields merge_threshold
test/t1 5 0 PRIMARY 3 3 1 50
test/t2 5 1 PRIMARY 3 3 1 50
@ -16,6 +16,8 @@
test/t4 5 33 PRIMARY 3 3 1 50
=== information_schema.innodb_sys_tablespaces and innodb_sys_datafiles ===
Space_Name Page_Size Zip_Size Path
@@ -45,7 +45,7 @@
innodb_undo003 DEFAULT DEFAULT MYSQLD_DATADIR//undo003
test/t1 DEFAULT DEFAULT MYSQLD_DATADIR/test/t1.ibd
test/t2 DEFAULT DEFAULT MYSQLD_DATADIR/test/t2.ibd
-test/t3 DEFAULT 8192 MYSQLD_DATADIR/test/t3.ibd
@ -23,7 +25,7 @@
test/t4 DEFAULT DEFAULT MYSQLD_DATADIR/test/t4.ibd
innodb_temporary DEFAULT DEFAULT MYSQLD_DATADIR/ibtmp1
DROP TABLE t1, t2, t3, t4;
@@ -52,141 +52,90 @@
@@ -55,141 +55,90 @@
SET SESSION innodb_strict_mode = ON;
CREATE TABLE t1 (
c01 char(200), c02 char(200), c03 char(200), c04 char(200), c05 char(200),
@ -211,7 +213,7 @@
ALTER TABLE t1 KEY_BLOCK_SIZE=4;
SHOW WARNINGS;
Level Code Message
@@ -218,15 +167,21 @@
@@ -221,15 +170,21 @@
DROP TABLE t1;
SET SESSION innodb_strict_mode = OFF;
CREATE TABLE t1 (i int) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=16;
@ -233,7 +235,7 @@
SELECT table_name, row_format, create_options
FROM information_schema.tables WHERE table_name = 't1';
table_name row_format create_options
@@ -272,6 +227,7 @@
@@ -275,6 +230,7 @@
ERROR HY000: Can't create table `test`.`t4` (errno: 140 "Wrong create options")
SHOW WARNINGS;
Level Code Message
@ -241,7 +243,7 @@
Warning 1478 InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.
Error 1005 Can't create table `test`.`t4` (errno: 140 "Wrong create options")
Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB
@@ -279,107 +235,13 @@
@@ -282,107 +238,13 @@
ERROR HY000: Can't create table `test`.`t5` (errno: 140 "Wrong create options")
SHOW WARNINGS;
Level Code Message
@ -350,7 +352,7 @@
# Test 8) Test creating a table that could lead to undo log overflow.
CREATE TABLE t1(a blob,b blob,c blob,d blob,e blob,f blob,g blob,
h blob,i blob,j blob,k blob,l blob,m blob,n blob,
@@ -394,10 +256,6 @@
@@ -397,10 +259,6 @@
UPDATE t1 SET a=@b,b=@b,c=@b,d=@b,e=@b,f=@b,g=@b,h=@b,i=@b,j=@b,
k=@b,l=@b,m=@b,n=@b,o=@b,p=@b,q=@b,r=@b,s=@b,t=@b,u=@b;
CREATE INDEX t1a ON t1 (a(767));
@ -361,7 +363,7 @@
UPDATE t1 SET a=@c,b=@c,c=@c,d=@c,e=@c,f=@c,g=@c,h=@c,i=@c,j=@c,
k=@c,l=@c,m=@c,n=@c,o=@c,p=@c,q=@c,r=@c,s=@c,t=@c,u=@c;
CREATE INDEX t1f ON t1 (f(767));
@@ -412,37 +270,15 @@
@@ -415,37 +273,15 @@
COMMIT;
CREATE INDEX t1g ON t1 (g(767));
UPDATE t1 SET g=@e;
@ -403,7 +405,7 @@
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -468,28 +304,12 @@
@@ -471,28 +307,12 @@
`t` blob DEFAULT NULL,
`u` blob DEFAULT NULL,
KEY `t1a` (`a`(767)),
@ -434,7 +436,7 @@
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci ROW_FORMAT=DYNAMIC
DROP TABLE t1;
# Bug#12547647 UPDATE LOGGING COULD EXCEED LOG PAGE SIZE
@@ -574,27 +394,25 @@
@@ -577,27 +397,25 @@
DROP TABLE t1;
CREATE TABLE t1(
c text NOT NULL, d text NOT NULL,

View file

@ -7,7 +7,7 @@
# Test 3) Query some information_shema tables that are dependent upon
# the page size.
SELECT t.name table_name, t.n_cols, t.flag table_flags,
@@ -36,13 +36,13 @@
@@ -36,7 +36,7 @@
table_name n_cols table_flags index_name root_page type n_fields merge_threshold
test/t1 5 0 PRIMARY 3 3 1 50
test/t2 5 1 PRIMARY 3 3 1 50
@ -16,6 +16,8 @@
test/t4 5 33 PRIMARY 3 3 1 50
=== information_schema.innodb_sys_tablespaces and innodb_sys_datafiles ===
Space_Name Page_Size Zip_Size Path
@@ -45,7 +45,7 @@
innodb_undo003 DEFAULT DEFAULT MYSQLD_DATADIR//undo003
test/t1 DEFAULT DEFAULT MYSQLD_DATADIR/test/t1.ibd
test/t2 DEFAULT DEFAULT MYSQLD_DATADIR/test/t2.ibd
-test/t3 DEFAULT 8192 MYSQLD_DATADIR/test/t3.ibd
@ -23,7 +25,7 @@
test/t4 DEFAULT DEFAULT MYSQLD_DATADIR/test/t4.ibd
innodb_temporary DEFAULT DEFAULT MYSQLD_DATADIR/ibtmp1
DROP TABLE t1, t2, t3, t4;
@@ -54,133 +54,97 @@
@@ -57,133 +57,97 @@
c01 char(200), c02 char(200), c03 char(200), c04 char(200), c05 char(200),
c06 char(200), c07 char(200), c08 char(200), c09 char(200), c10 char(200),
c11 char(200), c12 char(200), c13 char(200), c14 char(200), c15 char(200),
@ -199,7 +201,7 @@
SHOW WARNINGS;
Level Code Message
SELECT table_name, row_format, create_options
@@ -218,8 +182,11 @@
@@ -221,8 +185,11 @@
DROP TABLE t1;
SET SESSION innodb_strict_mode = OFF;
CREATE TABLE t1 (i int) ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=16;
@ -211,7 +213,7 @@
SELECT table_name, row_format, create_options
FROM information_schema.tables WHERE table_name = 't1';
table_name row_format create_options
@@ -279,107 +246,13 @@
@@ -282,107 +249,13 @@
ERROR HY000: Can't create table `test`.`t5` (errno: 140 "Wrong create options")
SHOW WARNINGS;
Level Code Message
@ -320,7 +322,7 @@
# Test 8) Test creating a table that could lead to undo log overflow.
CREATE TABLE t1(a blob,b blob,c blob,d blob,e blob,f blob,g blob,
h blob,i blob,j blob,k blob,l blob,m blob,n blob,
@@ -394,10 +267,6 @@
@@ -397,10 +270,6 @@
UPDATE t1 SET a=@b,b=@b,c=@b,d=@b,e=@b,f=@b,g=@b,h=@b,i=@b,j=@b,
k=@b,l=@b,m=@b,n=@b,o=@b,p=@b,q=@b,r=@b,s=@b,t=@b,u=@b;
CREATE INDEX t1a ON t1 (a(767));
@ -331,7 +333,7 @@
UPDATE t1 SET a=@c,b=@c,c=@c,d=@c,e=@c,f=@c,g=@c,h=@c,i=@c,j=@c,
k=@c,l=@c,m=@c,n=@c,o=@c,p=@c,q=@c,r=@c,s=@c,t=@c,u=@c;
CREATE INDEX t1f ON t1 (f(767));
@@ -412,30 +281,6 @@
@@ -415,30 +284,6 @@
COMMIT;
CREATE INDEX t1g ON t1 (g(767));
UPDATE t1 SET g=@e;
@ -362,7 +364,7 @@
CREATE INDEX t1t ON t1 (t(767));
BEGIN;
UPDATE t1 SET t=@e;
@@ -468,24 +313,8 @@
@@ -471,24 +316,8 @@
`t` blob DEFAULT NULL,
`u` blob DEFAULT NULL,
KEY `t1a` (`a`(767)),
@ -387,7 +389,7 @@
KEY `t1t` (`t`(767)),
KEY `t1u` (`u`(767)),
KEY `t1ut` (`u`(767),`t`(767)),
@@ -577,14 +406,14 @@
@@ -580,14 +409,14 @@
PRIMARY KEY (c(767),d(767)))
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
Warnings:
@ -404,7 +406,7 @@
DROP TABLE t1;
CREATE TABLE t1(
c text NOT NULL, d text NOT NULL,
@@ -594,7 +423,7 @@
@@ -597,7 +426,7 @@
CREATE TABLE t1(c text, PRIMARY KEY (c(440)))
ENGINE=InnoDB ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=1 CHARSET=ASCII;
Warnings:

View file

@ -40,6 +40,9 @@ test/t3 5 41 PRIMARY 3 3 1 50
test/t4 5 33 PRIMARY 3 3 1 50
=== information_schema.innodb_sys_tablespaces and innodb_sys_datafiles ===
Space_Name Page_Size Zip_Size Path
innodb_undo001 DEFAULT DEFAULT MYSQLD_DATADIR//undo001
innodb_undo002 DEFAULT DEFAULT MYSQLD_DATADIR//undo002
innodb_undo003 DEFAULT DEFAULT MYSQLD_DATADIR//undo003
test/t1 DEFAULT DEFAULT MYSQLD_DATADIR/test/t1.ibd
test/t2 DEFAULT DEFAULT MYSQLD_DATADIR/test/t2.ibd
test/t3 DEFAULT 8192 MYSQLD_DATADIR/test/t3.ibd

View file

@ -210,6 +210,9 @@ test/t7_restart#p#p1#sp#s2 test/t7_restart#p#p1#sp#s2 97 8 Dynamic 0
test/t7_restart#p#p1#sp#s3 test/t7_restart#p#p1#sp#s3 97 8 Dynamic 0
=== information_schema.innodb_sys_tablespaces and innodb_sys_datafiles ===
Space_Name Page_Size Zip_Size Path
innodb_undo001 DEFAULT DEFAULT MYSQLD_DATADIR//undo001
innodb_undo002 DEFAULT DEFAULT MYSQLD_DATADIR//undo002
innodb_undo003 DEFAULT DEFAULT MYSQLD_DATADIR//undo003
test/t1_restart DEFAULT DEFAULT MYSQLD_DATADIR/test/t1_restart.ibd
test/t2_restart DEFAULT DEFAULT MYSQLD_DATADIR/test/t2_restart.ibd
test/t3_restart DEFAULT 2048 MYSQLD_DATADIR/test/t3_restart.ibd
@ -393,6 +396,9 @@ test/t7_restart#p#p1#sp#s2 test/t7_restart#p#p1#sp#s2 97 8 Dynamic 0
test/t7_restart#p#p1#sp#s3 test/t7_restart#p#p1#sp#s3 97 8 Dynamic 0
=== information_schema.innodb_sys_tablespaces and innodb_sys_datafiles ===
Space_Name Page_Size Zip_Size Path
innodb_undo001 DEFAULT DEFAULT MYSQLD_DATADIR//undo001
innodb_undo002 DEFAULT DEFAULT MYSQLD_DATADIR//undo002
innodb_undo003 DEFAULT DEFAULT MYSQLD_DATADIR//undo003
test/t1_restart DEFAULT DEFAULT MYSQLD_DATADIR/test/t1_restart.ibd
test/t2_restart DEFAULT DEFAULT MYSQLD_DATADIR/test/t2_restart.ibd
test/t3_restart DEFAULT 2048 MYSQLD_DATADIR/test/t3_restart.ibd
@ -417,6 +423,9 @@ ALTER TABLE t6_restart TRUNCATE PARTITION p2;
ALTER TABLE t7_restart TRUNCATE PARTITION p1;
=== information_schema.innodb_sys_tablespaces and innodb_sys_datafiles ===
Space_Name Page_Size Zip_Size Path
innodb_undo001 DEFAULT DEFAULT MYSQLD_DATADIR//undo001
innodb_undo002 DEFAULT DEFAULT MYSQLD_DATADIR//undo002
innodb_undo003 DEFAULT DEFAULT MYSQLD_DATADIR//undo003
test/t4_restart DEFAULT DEFAULT MYSQLD_DATADIR/test/t4_restart.ibd
test/t6_restart#p#p0 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t6_restart#p#p0.ibd
test/t6_restart#p#p1 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t6_restart#p#p1.ibd
@ -520,6 +529,9 @@ t7_restart#p#p1#sp#s3.ibd
# restart
=== information_schema.innodb_sys_tablespaces and innodb_sys_datafiles ===
Space_Name Page_Size Zip_Size Path
innodb_undo001 DEFAULT DEFAULT MYSQLD_DATADIR//undo001
innodb_undo002 DEFAULT DEFAULT MYSQLD_DATADIR//undo002
innodb_undo003 DEFAULT DEFAULT MYSQLD_DATADIR//undo003
test/t4_restart DEFAULT DEFAULT MYSQLD_DATADIR/test/t4_restart.ibd
test/t6_restart#p#p0 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t6_restart#p#p0.ibd
test/t6_restart#p#p1 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t6_restart#p#p1.ibd
@ -622,6 +634,9 @@ RENAME TABLE t6_restart TO t66_restart;
RENAME TABLE t7_restart TO t77_restart;
=== information_schema.innodb_sys_tablespaces and innodb_sys_datafiles ===
Space_Name Page_Size Zip_Size Path
innodb_undo001 DEFAULT DEFAULT MYSQLD_DATADIR//undo001
innodb_undo002 DEFAULT DEFAULT MYSQLD_DATADIR//undo002
innodb_undo003 DEFAULT DEFAULT MYSQLD_DATADIR//undo003
test/t4_restart DEFAULT DEFAULT MYSQLD_DATADIR/test/t4_restart.ibd
test/t66_restart#p#p0 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t66_restart#p#p0.ibd
test/t66_restart#p#p1 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t66_restart#p#p1.ibd
@ -718,6 +733,9 @@ t77_restart#p#p1#sp#s3.ibd
# restart
=== information_schema.innodb_sys_tablespaces and innodb_sys_datafiles ===
Space_Name Page_Size Zip_Size Path
innodb_undo001 DEFAULT DEFAULT MYSQLD_DATADIR//undo001
innodb_undo002 DEFAULT DEFAULT MYSQLD_DATADIR//undo002
innodb_undo003 DEFAULT DEFAULT MYSQLD_DATADIR//undo003
test/t4_restart DEFAULT DEFAULT MYSQLD_DATADIR/test/t4_restart.ibd
test/t66_restart#p#p0 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t66_restart#p#p0.ibd
test/t66_restart#p#p1 DEFAULT 2048 MYSQL_TMP_DIR/alt_dir/test/t66_restart#p#p1.ibd
@ -853,6 +871,9 @@ t77_restart#p#p1#sp#s3.ibd
# restart
=== information_schema.innodb_sys_tablespaces and innodb_sys_datafiles ===
Space_Name Page_Size Zip_Size Path
innodb_undo001 DEFAULT DEFAULT MYSQLD_DATADIR//undo001
innodb_undo002 DEFAULT DEFAULT MYSQLD_DATADIR//undo002
innodb_undo003 DEFAULT DEFAULT MYSQLD_DATADIR//undo003
test/t4_restart DEFAULT DEFAULT MYSQL_TMP_DIR/new_dir/test/t4_restart.ibd
test/t66_restart#p#p0 DEFAULT 2048 MYSQL_TMP_DIR/new_dir/test/t66_restart#p#p0.ibd
test/t66_restart#p#p1 DEFAULT 2048 MYSQL_TMP_DIR/new_dir/test/t66_restart#p#p1.ibd
@ -992,6 +1013,9 @@ t77_restart.par
# restart
=== information_schema.innodb_sys_tablespaces and innodb_sys_datafiles ===
Space_Name Page_Size Zip_Size Path
innodb_undo001 DEFAULT DEFAULT MYSQLD_DATADIR//undo001
innodb_undo002 DEFAULT DEFAULT MYSQLD_DATADIR//undo002
innodb_undo003 DEFAULT DEFAULT MYSQLD_DATADIR//undo003
test/t4_restart DEFAULT DEFAULT MYSQLD_DATADIR/test/t4_restart.ibd
test/t66_restart#p#p0 DEFAULT 2048 MYSQLD_DATADIR/test/t66_restart#p#p0.ibd
test/t66_restart#p#p1 DEFAULT 2048 MYSQLD_DATADIR/test/t66_restart#p#p1.ibd

View file

@ -181,16 +181,19 @@ CREATE TABLE `t12` (
(
pt1 PAGE_COMPRESSED=0
);
--sorted_result
SELECT name, flag FROM information_schema.innodb_sys_tablespaces WHERE name like 'test/t12%';
ALTER TABLE `t12` ADD PARTITION (
PARTITION pt2 PAGE_COMPRESSED=1
);
--sorted_result
SELECT name, flag FROM information_schema.innodb_sys_tablespaces WHERE name like 'test/t12%';
ALTER TABLE `t12` ADD PARTITION (
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%';
DROP TABLE `t12`;
@ -203,6 +206,7 @@ CREATE TABLE `t13` (
PARTITION pt3 VALUES LESS THAN MAXVALUE
);
SHOW CREATE TABLE `t13`;
--sorted_result
SELECT name, flag FROM information_schema.innodb_sys_tablespaces WHERE name like 'test/t13%';
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
);
SHOW CREATE TABLE `t13`;
--sorted_result
SELECT name, flag FROM information_schema.innodb_sys_tablespaces WHERE name like 'test/t13%';
DROP TABLE `t13`;

View file

@ -112,6 +112,7 @@ ID NAME DESCRIPTION MAX_MONTH_NAME_LENGTH MAX_DAY_NAME_LENGTH DECIMAL_POINT THOU
108 zh_HK Chinese - Hong Kong SAR 3 3 . , english
109 el_GR Greek - Greece 11 9 , . greek
110 rm_CH Romansh - Switzerland 9 9 , ' english
111 ka_GE Georgian - Georgia 10 9 , georgian
show locales;
Id Name Description Error_Message_Language
0 en_US English - United States english
@ -225,6 +226,7 @@ Id Name Description Error_Message_Language
108 zh_HK Chinese - Hong Kong SAR english
109 el_GR Greek - Greece greek
110 rm_CH Romansh - Switzerland english
111 ka_GE Georgian - Georgia georgian
show locales like '%spanish%';
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'like '%spanish%'' at line 1
show locales where description like '%spanish%';

View file

@ -1024,7 +1024,11 @@ SELECT @@lc_time_names;
@@lc_time_names
rm_CH
SET @@lc_time_names = 111;
ERROR HY000: Unknown locale: '111'
SELECT @@lc_time_names;
@@lc_time_names
ka_GE
SET @@lc_time_names = 112;
ERROR HY000: Unknown locale: '112'
'#--------------------FN_DYNVARS_060_10-------------------------#'
SET @@lc_time_names = en_EN;
ERROR HY000: Unknown locale: 'en_EN'

View file

@ -621,8 +621,10 @@ SET @@lc_time_names = 109;
SELECT @@lc_time_names;
SET @@lc_time_names = 110;
SELECT @@lc_time_names;
--Error ER_UNKNOWN_LOCALE
SET @@lc_time_names = 111;
SELECT @@lc_time_names;
--Error ER_UNKNOWN_LOCALE
SET @@lc_time_names = 112;
--echo '#--------------------FN_DYNVARS_060_10-------------------------#'
#############################################################################

View file

@ -13,7 +13,7 @@
along with this program; if not, write to the Free Software
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 <crack.h>
#include <string.h>

View file

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

View file

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

View file

@ -17,7 +17,7 @@
# This scripts creates the MariaDB Server system tables
#
# All unrecognized arguments to this script are passed to mysqld.
# All unrecognized arguments to this script are passed to mariadbd.
basedir=""
builddir=""
@ -33,6 +33,7 @@ mysqld_opt=""
user=""
group=""
silent_startup="--silent-startup"
log_error=""
force=0
in_rpm=0
@ -328,9 +329,9 @@ then
exit 1
fi
# Now we can get arguments from the groups [mysqld] and [mysql_install_db]
# Now we can get arguments from the groups [mariadbd] and [mysql_install_db]
# in the my.cfg file, then re-run to merge with command line arguments.
parse_arguments `"$print_defaults" $defaults $defaults_group_suffix --mysqld mysql_install_db mariadb-install-db`
parse_arguments `"$print_defaults" $defaults $defaults_group_suffix --mariadbd mysql_install_db mariadb-install-db`
parse_arguments PICK-ARGS-FROM-ARGV "$@"
@ -533,7 +534,7 @@ then
args="$args --user=$user"
fi
#To be enabled if/when we enable --group as an option to mysqld
#To be enabled if/when we enable --group as an option to mariadbd
#if test -n "$group"
#then
# args="$args --group=$group"
@ -556,7 +557,18 @@ else
filter_cmd_line="cat"
fi
# Configure mysqld command line
# Disable log error if the user don't have write access to the directory.
# This is common when a user tries to install a personal mariadbd server
if test -n $log_error
then
if test ! -w $log_error
then
log_error=""
args="$args --skip-log-error"
fi
fi
# Configure mariadbd command line
mysqld_bootstrap="${MYSQLD_BOOTSTRAP-$mysqld}"
mysqld_install_cmd_line()
{
@ -599,7 +611,7 @@ cat_sql()
fi
}
# Create the system and help tables by passing them to "mysqld --bootstrap"
# Create the system and help tables by passing them to "mariadbd --bootstrap"
s_echo "Installing MariaDB/MySQL system tables in '$ldata' ..."
if cat_sql | eval "$filter_cmd_line" | mysqld_install_cmd_line > /dev/null
then

View file

@ -258,7 +258,7 @@ static File open_error_msg_file(const char *file_name, const char *language,
goto err;
error_pos=2;
if (head[0] != (uchar) 254 || head[1] != (uchar) 254 ||
head[2] != 2 || head[3] != 4)
head[2] != 2 || head[3] != 5)
goto err; /* purecov: inspected */
ret->text_length= uint4korr(head+6);

View file

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

View file

@ -2687,18 +2687,27 @@ public:
void register_in(THD *thd);
bool depends_only_on(table_map view_map)
{ return marker & MARKER_FULL_EXTRACTION; }
int get_extraction_flag() const
{ return marker & MARKER_EXTRACTION_MASK; }
{ return get_extraction_flag() & MARKER_FULL_EXTRACTION; }
int get_extraction_flag() const
{
if (basic_const_item())
return MARKER_FULL_EXTRACTION;
else
return marker & MARKER_EXTRACTION_MASK;
}
void set_extraction_flag(int16 flags)
{
marker &= ~MARKER_EXTRACTION_MASK;
marker|= flags;
if (!basic_const_item())
{
marker= marker & ~MARKER_EXTRACTION_MASK;
marker|= flags;
}
}
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);
bool pushable_cond_checker_for_derived(uchar *arg)
{

View file

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

View file

@ -24,6 +24,7 @@ english
estonian
french
german
georgian
greek
hindi
hungarian

File diff suppressed because it is too large Load diff

View file

@ -5284,7 +5284,7 @@ private:
bool use_temporary_table(TABLE *table, TABLE **out_table);
void close_temporary_table(TABLE *table);
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);
bool lock_temporary_tables();
void unlock_temporary_tables();

View file

@ -31,7 +31,7 @@ enum err_msgs_index
{
en_US= 0, cs_CZ, da_DK, nl_NL, et_EE, fr_FR, de_DE, el_GR, hu_HU, it_IT,
ja_JP, ko_KR, no_NO, nn_NO, pl_PL, pt_PT, ro_RO, ru_RU, sr_RS, sk_SK,
es_ES, sv_SE, uk_UA, hi_IN
es_ES, sv_SE, uk_UA, hi_IN, ka_GE
} ERR_MSGS_INDEX;
@ -61,6 +61,7 @@ MY_LOCALE_ERRMSGS global_errmsgs[]=
{"swedish", NULL},
{"ukrainian", NULL},
{"hindi", NULL},
{"georgian", NULL},
{NULL, NULL}
};
@ -3317,6 +3318,51 @@ MY_LOCALE my_locale_rm_CH
/***** LOCALE END rm_CH *****/
/***** LOCALE BEGIN ka_GE: Georgian - Georgia *****/
static const char *my_locale_month_names_ka_GE[13] =
{"იანვარი","თებერვალი","მარტი","აპრილი","მაისი","ივნისი","ივლისი","სექტემბერი","ოქტომბერი","ნოემბერი","დეკემბერი", NullS };
static const char *my_locale_ab_month_names_ka_GE[13] =
{"იან","თებ","მარ","აპრ","მაი","ივნ","ივლ","აგვ","სექტ","ოქტ","ნოე","დეკ", NullS };
static const char *my_locale_day_names_ka_GE[8] =
{"ორშაბათი","სამშაბათი","ოთხშაბათი","ხუთშაბათი","პარასკევი","შაბათი","კვირა", NullS };
static const char *my_locale_ab_day_names_ka_GE[8] =
{"ორშ","სამშ","ოთხშ","ხუთშ","პარ","შაბ","კვ", NullS };
static TYPELIB my_locale_typelib_month_names_ka_GE =
{ array_elements(my_locale_month_names_ka_GE)-1, "", my_locale_month_names_ka_GE, NULL };
static TYPELIB my_locale_typelib_ab_month_names_ka_GE =
{ array_elements(my_locale_ab_month_names_ka_GE)-1, "", my_locale_ab_month_names_ka_GE, NULL };
static TYPELIB my_locale_typelib_day_names_ka_GE =
{ array_elements(my_locale_day_names_ka_GE)-1, "", my_locale_day_names_ka_GE, NULL };
static TYPELIB my_locale_typelib_ab_day_names_ka_GE =
{ array_elements(my_locale_ab_day_names_ka_GE)-1, "", my_locale_ab_day_names_ka_GE, NULL };
MY_LOCALE my_locale_ka_GE
(
111,
"ka_GE",
"Georgian - Georgia",
FALSE,
&my_locale_typelib_month_names_ka_GE,
&my_locale_typelib_ab_month_names_ka_GE,
&my_locale_typelib_day_names_ka_GE,
&my_locale_typelib_ab_day_names_ka_GE,
10,
9,
',', /* decimal point ka_GE */
' ', /* thousands_sep ka_GE */
"\x03", /* grouping ka_GE */
&global_errmsgs[ka_GE]
);
/***** LOCALE END ka_GE *****/
/*
The list of all locales.
Note, locales must be ordered according to their
@ -3436,6 +3482,7 @@ MY_LOCALE *my_locales[]=
&my_locale_zh_HK,
&my_locale_el_GR,
&my_locale_rm_CH,
&my_locale_ka_GE,
NULL
};

View file

@ -2396,17 +2396,16 @@ static void check_duplicate_key(THD *thd, const Key *key, const KEY *key_info,
bool Column_definition::prepare_stage1_typelib(THD *thd,
MEM_ROOT *mem_root,
handler *file,
ulonglong table_flags)
column_definition_type_t deftype)
{
/*
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
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.
- 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
occupied memory at the same time when we free this
sql_field -- at the end of execution.
@ -2414,11 +2413,11 @@ bool Column_definition::prepare_stage1_typelib(THD *thd,
values in "interval" in cases when no character conversion is needed,
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')
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 ((charset != default_value->expr->collation.collation &&
@ -2431,14 +2430,11 @@ bool Column_definition::prepare_stage1_typelib(THD *thd,
bool Column_definition::prepare_stage1_string(THD *thd,
MEM_ROOT *mem_root,
handler *file,
ulonglong table_flags)
MEM_ROOT *mem_root)
{
create_length_to_internal_length_string();
if (prepare_blob_field(thd))
return true;
DBUG_ASSERT(file || !default_value); // SP variables have no default_value
/*
Convert the default value from client character
set into the column character set if necessary.
@ -2458,13 +2454,9 @@ bool Column_definition::prepare_stage1_string(THD *thd,
bool Column_definition::prepare_stage1_bit(THD *thd,
MEM_ROOT *mem_root,
handler *file,
ulonglong table_flags)
MEM_ROOT *mem_root)
{
pack_flag= FIELDFLAG_NUMBER;
if (!(table_flags & HA_CAN_BIT_FIELD))
pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
create_length_to_internal_length_bit();
return false;
}
@ -2472,14 +2464,15 @@ bool Column_definition::prepare_stage1_bit(THD *thd,
bool Column_definition::prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
handler *file,
ulonglong table_flags,
column_definition_type_t deftype,
const Column_derived_attributes
*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,
this, file,
table_flags,
this, deftype,
derived_attr);
}
@ -2703,10 +2696,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
mysql_prepare_create_table()
mysql_prepare_create_table_finalize()
thd Thread object.
create_info Create information (like MAX_ROWS).
alter_info List of columns and indexes to create
@ -2729,11 +2789,12 @@ key_add_part_check_null(const handler *file, KEY *key_info,
*/
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)
mysql_prepare_create_table_finalize(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)
{
const char *key_name;
Create_field *sql_field,*dup_field;
@ -2749,28 +2810,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
bool tmp_table= create_table_mode == C_ALTER_TABLE;
const bool create_simple= thd->lex->create_simple();
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_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;
if (connect_string->length != 0 &&
connect_string->length > CONNECT_STRING_MAXLEN &&
@ -2805,42 +2846,16 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(TRUE);
}
for (field_no=0; (sql_field=it++) ; field_no++)
{
/* 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,
file, file->ha_table_flags(),
&dattr))
DBUG_RETURN(true);
DBUG_ASSERT(sql_field->charset);
if (!(sql_field->flags & NOT_NULL_FLAG))
null_fields++;
if (sql_field->real_field_type() == MYSQL_TYPE_BIT &&
file->ha_table_flags() & HA_CAN_BIT_FIELD)
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 */
for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
{
@ -3829,6 +3844,49 @@ without_overlaps_err:
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
@ -3957,7 +4015,8 @@ bool Column_definition::prepare_blob_field(THD *thd)
bool Column_definition::sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root)
{
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);
}
@ -4052,6 +4111,9 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db,
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();
if (unlikely(!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
@ -4268,9 +4330,10 @@ handler *mysql_create_frm_image(THD *thd, const LEX_CSTRING &db,
}
#endif
if (mysql_prepare_create_table(thd, create_info, alter_info, &db_options,
file, key_info, key_count,
create_table_mode, db, table_name))
if (mysql_prepare_create_table_finalize(thd, create_info,
alter_info, &db_options,
file, key_info, key_count,
create_table_mode, db, table_name))
goto err;
create_info->table_options=db_options;

View file

@ -3008,8 +3008,7 @@ bool Type_handler::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags,
column_definition_type_t type,
const Column_derived_attributes
*derived_attr)
const
@ -3022,8 +3021,7 @@ bool Type_handler_null::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags,
column_definition_type_t type,
const Column_derived_attributes
*derived_attr)
const
@ -3037,8 +3035,7 @@ bool Type_handler_row::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags,
column_definition_type_t type,
const Column_derived_attributes
*derived_attr)
const
@ -3052,8 +3049,7 @@ bool Type_handler_temporal_result::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags,
column_definition_type_t type,
const Column_derived_attributes
*derived_attr)
const
@ -3067,8 +3063,7 @@ bool Type_handler_numeric::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags,
column_definition_type_t type,
const Column_derived_attributes
*derived_attr)
const
@ -3081,8 +3076,7 @@ bool Type_handler_newdecimal::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags,
column_definition_type_t type,
const Column_derived_attributes
*derived_attr)
const
@ -3096,28 +3090,26 @@ bool Type_handler_bit::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags,
column_definition_type_t type,
const Column_derived_attributes
*derived_attr)
const
{
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::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags,
column_definition_type_t type,
const Column_derived_attributes
*derived_attr)
const
{
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,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags,
column_definition_type_t type,
const Column_derived_attributes
*derived_attr)
const
{
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,
ulonglong table_flags) const
{
/*
We have sql_field->pack_flag already set here, see
mysql_prepare_create_table().
*/
if (!(table_flags & HA_CAN_BIT_FIELD))
{
def->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
def->create_length_to_internal_length_bit();
}
return false;
}

View file

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

View file

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

View file

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

View file

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

View file

@ -671,7 +671,7 @@ bool THD::drop_temporary_table(TABLE *table, bool *is_trans, bool delete_table)
temporary_tables->remove(share);
/* 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:
if (locked)
@ -1464,20 +1464,21 @@ bool THD::log_events_and_free_tmp_shares()
@param share [IN] TABLE_SHARE to free
@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");
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);
my_free(share);
DBUG_VOID_RETURN;
DBUG_RETURN(error);
}

View file

@ -251,7 +251,7 @@ Gets the root node of a tree and x- or s-latches it.
buf_block_t*
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
or RW_X_LATCH */
mtr_t* mtr, /*!< in: mtr */
@ -263,18 +263,42 @@ btr_root_block_get(
return nullptr;
}
buf_block_t *block = btr_block_get(*index, index->page, mode, mtr, err);
if (block)
buf_block_t *block;
#ifndef BTR_CUR_ADAPT
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);
ut_ad(!block == (*err != DB_SUCCESS));
if (UNIV_LIKELY(block != nullptr))
{
if (!btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF,
*block, *index->table->space) ||
!btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP,
*block, *index->table->space))
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 (!btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF,
*block, *index->table->space) ||
!btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP,
*block, *index->table->space))
{
*err= DB_CORRUPTION;
block= nullptr;
}
}
else if (*err == DB_DECRYPTION_FAILED)
btr_decryption_failed(*index);
return block;
}
@ -285,7 +309,7 @@ static
page_t*
btr_root_get(
/*=========*/
const dict_index_t* index, /*!< in: index tree */
dict_index_t* index, /*!< in: index tree */
mtr_t* mtr, /*!< in: mtr */
dberr_t* err) /*!< out: error code */
{
@ -497,9 +521,7 @@ btr_block_reget(mtr_t *mtr, const dict_index_t &index,
return block;
}
#if 0 /* MDEV-29385 FIXME: Acquire the page latch upfront. */
ut_ad(mtr->memo_contains_flagged(&index.lock, MTR_MEMO_X_LOCK));
#endif
return btr_block_get(index, id.page_no(), rw_latch, mtr, err);
}
@ -687,9 +709,7 @@ btr_page_get_father_node_ptr_for_validate(
const uint32_t page_no = btr_cur_get_block(cursor)->page.id().page_no();
dict_index_t* index = btr_cur_get_index(cursor);
ut_ad(!dict_index_is_spatial(index));
ut_ad(mtr->memo_contains_flagged(&index->lock, MTR_MEMO_X_LOCK
| MTR_MEMO_SX_LOCK));
ut_ad(mtr->memo_contains(index->lock, MTR_MEMO_X_LOCK));
ut_ad(dict_index_get_page(index) != page_no);
const auto level = btr_page_get_level(btr_cur_get_page(cursor));
@ -707,10 +727,6 @@ btr_page_get_father_node_ptr_for_validate(
}
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,
ULINT_UNDEFINED, &heap);
@ -2288,11 +2304,10 @@ btr_insert_on_non_leaf_level(
}
ut_ad(cursor.flag == BTR_CUR_BINARY);
#if 0 /* MDEV-29835 FIXME */
ut_ad(!btr_cur_get_block(&cursor)->page.lock.not_recursive()
ut_ad(btr_cur_get_block(&cursor)
!= mtr->at_savepoint(mtr->get_savepoint() - 1)
|| index->is_spatial()
|| mtr->memo_contains(index->lock, MTR_MEMO_X_LOCK));
#endif
if (UNIV_LIKELY(err == DB_SUCCESS)) {
err = btr_cur_optimistic_insert(flags,
@ -2400,10 +2415,8 @@ btr_attach_half_pages(
prev_block = mtr->get_already_latched(id, MTR_MEMO_PAGE_X_FIX);
#if 1 /* MDEV-29835 FIXME: acquire page latches upfront */
if (!prev_block) {
# if 0 /* MDEV-29835 FIXME */
ut_ad(mtr->memo_contains(index->lock,
MTR_MEMO_X_LOCK));
# endif
prev_block = btr_block_get(*index, prev_page_no,
RW_X_LATCH, mtr);
}
@ -2414,10 +2427,8 @@ btr_attach_half_pages(
next_block = mtr->get_already_latched(id, MTR_MEMO_PAGE_X_FIX);
#if 1 /* MDEV-29835 FIXME: acquire page latches upfront */
if (!next_block) {
# if 0 /* MDEV-29835 FIXME */
ut_ad(mtr->memo_contains(index->lock,
MTR_MEMO_X_LOCK));
# endif
next_block = btr_block_get(*index, next_page_no,
RW_X_LATCH, mtr);
}
@ -2758,6 +2769,8 @@ btr_page_split_and_insert(
ut_ad(dtuple_check_typed(tuple));
ut_ad(!cursor->index()->is_spatial());
buf_pool.pages_split++;
if (!*heap) {
*heap = mem_heap_create(1024);
}
@ -3131,8 +3144,6 @@ insert_failed:
}
func_exit:
MONITOR_INC(MONITOR_INDEX_SPLIT);
ut_ad(page_validate(buf_block_get_frame(left_block),
page_cursor->index));
ut_ad(page_validate(buf_block_get_frame(right_block),
@ -3167,9 +3178,7 @@ dberr_t btr_level_list_remove(const buf_block_t& block,
#if 1 /* MDEV-29835 FIXME: acquire page latches upfront */
if (!prev)
{
# if 0 /* MDEV-29835 FIXME */
ut_ad(mtr->memo_contains(index.lock, MTR_MEMO_X_LOCK));
# endif
prev= btr_block_get(index, id.page_no(), RW_X_LATCH, mtr, &err);
if (UNIV_UNLIKELY(!prev))
return err;
@ -3184,9 +3193,7 @@ dberr_t btr_level_list_remove(const buf_block_t& block,
#if 1 /* MDEV-29835 FIXME: acquire page latches upfront */
if (!next)
{
# if 0 /* MDEV-29835 FIXME */
ut_ad(mtr->memo_contains(index.lock, MTR_MEMO_X_LOCK));
# endif
next= btr_block_get(index, id.page_no(), RW_X_LATCH, mtr, &err);
if (UNIV_UNLIKELY(!next))
return err;
@ -4016,7 +4023,7 @@ btr_discard_page(
if (UNIV_UNLIKELY(!merge_block)) {
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
+ FIL_PAGE_NEXT,
block->page.frame + FIL_PAGE_OFFSET,
@ -4042,7 +4049,7 @@ btr_discard_page(
if (UNIV_UNLIKELY(!merge_block)) {
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
+ FIL_PAGE_PREV,
block->page.frame + FIL_PAGE_OFFSET,
@ -4613,8 +4620,7 @@ btr_validate_level(
/*===============*/
dict_index_t* index, /*!< in: index tree */
const trx_t* trx, /*!< in: transaction or NULL */
ulint level, /*!< in: level number */
bool lockout)/*!< in: true if X-latch index is intended */
ulint level) /*!< in: level number */
{
buf_block_t* block;
page_t* page;
@ -4633,18 +4639,10 @@ btr_validate_level(
#ifdef UNIV_ZIP_DEBUG
page_zip_des_t* page_zip;
#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();
if (lockout) {
mtr_x_lock_index(index, &mtr);
} else {
mtr_sx_lock_index(index, &mtr);
}
mtr_x_lock_index(index, &mtr);
dberr_t err;
block = btr_root_block_get(index, RW_SX_LATCH, &mtr, &err);
@ -4739,11 +4737,7 @@ func_exit:
mem_heap_empty(heap);
offsets = offsets2 = NULL;
if (lockout) {
mtr_x_lock_index(index, &mtr);
} else {
mtr_sx_lock_index(index, &mtr);
}
mtr_x_lock_index(index, &mtr);
page = block->page.frame;
@ -4787,7 +4781,6 @@ func_exit:
if (right_page_no != FIL_NULL) {
const rec_t* right_rec;
savepoint = mtr.get_savepoint();
right_block = btr_block_get(*index, right_page_no, RW_SX_LATCH,
&mtr, &err);
@ -4890,11 +4883,6 @@ broken_links:
father_page = btr_cur_get_page(&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));
if (rec) {
btr_cur_position(index, rec, block, &node_cur);
@ -4976,35 +4964,6 @@ broken_links:
}
} else if (const rec_t* right_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, &mtr);
}
right_block = btr_block_get(*index,
right_page_no,
RW_SX_LATCH,
&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(
index,
page_get_infimum_rec(right_block->page.frame),
@ -5076,19 +5035,6 @@ node_ptr_fails:
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, &mtr);
}
} else if (parent_page_no != FIL_NULL) {
btr_block_get(*index, parent_page_no,
RW_SX_LATCH, &mtr);
}
}
block = btr_block_get(*index, right_page_no, RW_SX_LATCH,
&mtr, &err);
goto loop;
@ -5106,21 +5052,16 @@ btr_validate_index(
dict_index_t* index, /*!< in: index */
const trx_t* trx) /*!< in: transaction or NULL */
{
const bool lockout= index->is_spatial();
mtr_t mtr;
mtr.start();
if (lockout)
mtr_x_lock_index(index, &mtr);
else
mtr_sx_lock_index(index, &mtr);
mtr_x_lock_index(index, &mtr);
dberr_t err;
if (page_t *root= btr_root_get(index, &mtr, &err))
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;
if (!level)
break;

View file

@ -750,29 +750,34 @@ btr_cur_will_modify_tree(
/** Detects whether the modifying record might need a opposite modification
to the intention.
@param[in] page page
@param[in] lock_intention lock intention for the tree operation
@param[in] rec record (current node_ptr)
@param page page
@param lock_intention lock intention for the tree operation
@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 */
static
bool
btr_cur_need_opposite_intention(
const page_t* page,
btr_intention_t lock_intention,
const rec_t* rec)
static bool btr_cur_need_opposite_intention(const page_t *page,
btr_intention_t lock_intention,
ulint node_ptr_max_size,
ulint compress_limit,
const rec_t *rec)
{
switch (lock_intention) {
case BTR_INTENTION_DELETE:
return (page_has_prev(page) && page_rec_is_first(rec, page)) ||
(page_has_next(page) && page_rec_is_last(rec, page));
case BTR_INTENTION_INSERT:
return page_has_next(page) && page_rec_is_last(rec, page);
case BTR_INTENTION_BOTH:
return(false);
}
MY_ASSERT_UNREACHABLE();
return(false);
if (lock_intention != BTR_INTENTION_INSERT)
{
/* We compensate also for btr_cur_compress_recommendation() */
if (!page_has_siblings(page) ||
page_rec_is_first(rec, page) || page_rec_is_last(rec, page) ||
page_get_data_size(page) < node_ptr_max_size + compress_limit)
return true;
if (lock_intention == BTR_INTENTION_DELETE)
return false;
}
else if (page_has_next(page) && page_rec_is_last(rec, page))
return true;
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;
}
/**
@ -997,7 +1002,7 @@ dberr_t btr_cur_t::search_leaf(const dtuple_t *tuple, page_cur_mode_t mode,
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;
switch (latch_mode) {
@ -1009,13 +1014,19 @@ 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));
break;
}
if (lock_intention == BTR_INTENTION_DELETE && buf_pool.n_pend_reads &&
trx_sys.history_size_approx() > BTR_CUR_FINE_HISTORY_LENGTH)
/* Most delete-intended operations are due to the purge of history.
Prioritize them when the history list is growing huge. */
mtr_x_lock_index(index(), mtr);
else
mtr_sx_lock_index(index(), mtr);
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)
{
/* Most delete-intended operations are due to the purge of history.
Prioritize them when the history list is growing huge. */
mtr_x_lock_index(index(), mtr);
break;
}
}
mtr_sx_lock_index(index(), mtr);
break;
#ifdef UNIV_DEBUG
case BTR_CONT_MODIFY_TREE:
@ -1221,6 +1232,10 @@ release_tree:
!btr_block_get(*index(), btr_page_get_next(block->page.frame),
RW_X_LATCH, mtr, &err))
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:
@ -1274,6 +1289,7 @@ release_tree:
break;
case BTR_MODIFY_TREE:
if (btr_cur_need_opposite_intention(block->page.frame, lock_intention,
node_ptr_max_size, compress_limit,
page_cur.rec))
/* If the rec is the first or last in the page for pessimistic
delete intention, it might cause node_ptr insert for the upper
@ -1417,6 +1433,17 @@ release_tree:
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
dberr_t btr_cur_t::pessimistic_search_leaf(const dtuple_t *tuple,
page_cur_mode_t mode, mtr_t *mtr)
@ -1434,8 +1461,7 @@ dberr_t btr_cur_t::pessimistic_search_leaf(const dtuple_t *tuple,
ut_ad(block->page.id().page_no() == index()->page);
block->page.fix();
mtr->rollback_to_savepoint(1);
ut_ad(mtr->memo_contains_flagged(&index()->lock,
MTR_MEMO_SX_LOCK | MTR_MEMO_X_LOCK));
mtr->index_lock_upgrade();
const page_cur_mode_t page_mode{btr_cur_nonleaf_mode(mode)};
@ -1665,7 +1691,6 @@ search_loop:
dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
btr_latch_mode latch_mode, mtr_t *mtr)
{
btr_intention_t lock_intention;
ulint n_blocks= 0;
mem_heap_t *heap= nullptr;
rec_offs offsets_[REC_OFFS_NORMAL_SIZE];
@ -1677,7 +1702,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;
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
know how to release it when we have latched the leaf node */
@ -1685,7 +1710,7 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
auto savepoint= mtr->get_savepoint();
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)
{
@ -1694,12 +1719,18 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
and read IO bandwidth should be prioritized for them, when the
history list is growing huge. */
savepoint++;
if (lock_intention == BTR_INTENTION_DELETE
&& buf_pool.n_pend_reads
&& trx_sys.history_size_approx() > BTR_CUR_FINE_HISTORY_LENGTH)
mtr_x_lock_index(index, mtr);
else
mtr_sx_lock_index(index, mtr);
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)
{
mtr_x_lock_index(index, mtr);
goto index_locked;
}
}
mtr_sx_lock_index(index, mtr);
}
else
{
@ -1720,6 +1751,7 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
}
}
index_locked:
ut_ad(savepoint == mtr->get_savepoint());
const rw_lock_type_t root_leaf_rw_latch=
@ -1792,15 +1824,28 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
!btr_block_get(*index, btr_page_get_next(block->page.frame),
RW_X_LATCH, mtr, &err))
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
{
if (rw_latch == RW_NO_LATCH)
mtr->upgrade_buffer_fix(leaf_savepoint - 1,
rw_lock_type_t(latch_mode));
/* Release index->lock if needed, and the non-leaf pages. */
mtr->rollback_to_savepoint(savepoint - !latch_by_caller,
leaf_savepoint - 1);
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. */
mtr->rollback_to_savepoint(savepoint - !latch_by_caller,
leaf_savepoint - 1);
}
}
break;
}
@ -1822,22 +1867,25 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
: !page_cur_move_to_prev(&page_cur))
goto corrupted;
const rec_t *node_ptr= page_cur.rec;
offsets= rec_get_offsets(node_ptr, index, offsets, 0, ULINT_UNDEFINED,
offsets= rec_get_offsets(page_cur.rec, index, offsets, 0, ULINT_UNDEFINED,
&heap);
ut_ad(latch_mode != BTR_MODIFY_TREE || upper_rw_latch == RW_X_LATCH);
if (latch_mode != BTR_MODIFY_TREE);
else if (btr_cur_need_opposite_intention(block->page.frame,
lock_intention, node_ptr))
else if (btr_cur_need_opposite_intention(block->page.frame, lock_intention,
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
delete intention, it might cause node_ptr insert for the upper
level. We should change the intention and retry. */
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;
height= ULINT_UNDEFINED;
n_blocks= 0;
@ -1846,7 +1894,7 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
else
{
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))
{
ut_ad(n_blocks);
@ -1876,7 +1924,7 @@ dberr_t btr_cur_t::open_leaf(bool first, dict_index_t *index,
}
/* 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++;
}
@ -2178,8 +2226,7 @@ convert_big_rec:
return(DB_TOO_BIG_RECORD);
}
LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page),
goto fail);
LIMIT_OPTIMISTIC_INSERT_DEBUG(page_get_n_recs(page), goto fail);
if (block->page.zip.data && leaf
&& (page_get_data_size(page) + rec_size
@ -2193,7 +2240,7 @@ fail:
/* prefetch siblings of the leaf for the pessimistic
operation, if the page is leaf. */
if (page_is_leaf(page)) {
if (leaf) {
btr_cur_prefetch_siblings(block, index);
}
fail_err:
@ -2262,7 +2309,7 @@ fail_err:
#ifdef UNIV_DEBUG
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(
entry, dict_col_get_clust_pos(
dict_table_get_sys_col(index->table,

View file

@ -408,7 +408,6 @@ static bool buf_page_decrypt_after_read(buf_page_t *bpage,
if (id.space() == SRV_TMP_SPACE_ID
&& innodb_encrypt_temporary_tables) {
slot = buf_pool.io_buf_reserve();
ut_a(slot);
slot->allocate();
bool ok = buf_tmp_page_decrypt(slot->crypt_buf, dst_frame);
slot->release();
@ -431,7 +430,6 @@ decompress:
}
slot = buf_pool.io_buf_reserve();
ut_a(slot);
slot->allocate();
decompress_with_slot:
@ -455,7 +453,6 @@ decrypt_failed:
}
slot = buf_pool.io_buf_reserve();
ut_a(slot);
slot->allocate();
/* 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 */
}
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
to the specified string. The format and the following parameters are the
same as the ones used for printf(3).
@ -1353,21 +1385,25 @@ inline bool buf_pool_t::withdraw_blocks()
block = next_block;
}
mysql_mutex_unlock(&mutex);
/* reserve free_list length */
if (UT_LIST_GET_LEN(withdraw) < withdraw_target) {
buf_flush_LRU(
std::max<ulint>(withdraw_target
- UT_LIST_GET_LEN(withdraw),
srv_LRU_scan_depth));
buf_flush_wait_batch_end_acquiring_mutex(true);
srv_LRU_scan_depth),
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 */
ulint count2 = 0;
mysql_mutex_lock(&mutex);
buf_pool_mutex_exit_forbid();
for (buf_page_t* bpage = UT_LIST_GET_FIRST(LRU), *next_bpage;
bpage; bpage = next_bpage) {
@ -2095,13 +2131,15 @@ lookup:
return bpage;
must_read_page:
if (dberr_t err= buf_read_page(page_id, zip_size, chain))
{
switch (dberr_t err= buf_read_page(page_id, zip_size, chain)) {
case DB_SUCCESS:
case DB_SUCCESS_LOCKED_REC:
goto lookup;
default:
ib::error() << "Reading compressed page " << page_id
<< " failed with error: " << err;
return nullptr;
}
goto lookup;
}
/********************************************************************//**
@ -2245,15 +2283,14 @@ buf_page_get_low(
#ifdef UNIV_DEBUG
switch (mode) {
case BUF_PEEK_IF_IN_POOL:
default:
ut_ad(mode == BUF_PEEK_IF_IN_POOL);
break;
case BUF_GET_POSSIBLY_FREED:
case BUF_GET_IF_IN_POOL:
/* The caller may pass a dummy page size,
because it does not really matter. */
break;
default:
MY_ASSERT_UNREACHABLE();
case BUF_GET_POSSIBLY_FREED:
break;
case BUF_GET:
ut_ad(!mtr->is_freeing_tree());
fil_space_t* s = fil_space_get(page_id.space());
@ -2319,20 +2356,23 @@ loop:
corrupted, or if an encrypted page with a valid
checksum cannot be decypted. */
if (dberr_t local_err = buf_read_page(page_id, zip_size, chain)) {
if (local_err != DB_CORRUPTION
&& mode != BUF_GET_POSSIBLY_FREED
switch (dberr_t local_err = buf_read_page(page_id, zip_size, chain)) {
case DB_SUCCESS:
case DB_SUCCESS_LOCKED_REC:
buf_read_ahead_random(page_id, zip_size);
break;
default:
if (mode != BUF_GET_POSSIBLY_FREED
&& retries++ < BUF_PAGE_READ_MAX_RETRIES) {
DBUG_EXECUTE_IF("intermittent_read_failure",
retries = BUF_PAGE_READ_MAX_RETRIES;);
} else {
if (err) {
*err = local_err;
}
return nullptr;
}
} else {
buf_read_ahead_random(page_id, zip_size);
/* fall through */
case DB_PAGE_CORRUPTED:
if (err) {
*err = local_err;
}
return nullptr;
}
ut_d(if (!(++buf_dbg_counter % 5771)) buf_pool.validate());
@ -2383,11 +2423,12 @@ ignore_block:
return nullptr;
}
} else if (mode != BUF_PEEK_IF_IN_POOL) {
} else if (!mtr) {
} else if (!mtr) {
ut_ad(!block->page.oldest_modification());
mysql_mutex_lock(&buf_pool.mutex);
block->unfix();
free_unfixed_block:
if (!buf_LRU_free_page(&block->page, true)) {
ut_ad(0);
}
@ -2495,20 +2536,19 @@ wait_for_unfix:
/* Decompress the page while not holding
buf_pool.mutex. */
auto ok = buf_zip_decompress(block, false);
block->page.read_unfix(state);
state = block->page.state();
block->page.lock.x_unlock();
const auto ok = buf_zip_decompress(block, false);
--buf_pool.n_pend_unzip;
if (!ok) {
/* FIXME: Evict the corrupted
ROW_FORMAT=COMPRESSED page! */
if (err) {
*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;
}
}
@ -2606,35 +2646,37 @@ buf_page_get_gen(
mtr_t* mtr,
dberr_t* err)
{
if (buf_block_t *block= recv_sys.recover(page_id))
buf_block_t *block= recv_sys.recover(page_id);
if (UNIV_LIKELY(!block))
return buf_page_get_low(page_id, zip_size, rw_latch,
guess, mode, mtr, err);
else if (UNIV_UNLIKELY(block == reinterpret_cast<buf_block_t*>(-1)))
{
if (UNIV_UNLIKELY(block == reinterpret_cast<buf_block_t*>(-1)))
{
corrupted:
if (err)
*err= DB_CORRUPTION;
return nullptr;
}
/* Recovery is a special case; we fix() before acquiring lock. */
auto s= block->page.fix();
ut_ad(s >= buf_page_t::FREED);
/* The block may be write-fixed at this point because we are not
holding a lock, but it must not be read-fixed. */
ut_ad(s < buf_page_t::READ_FIX || s >= buf_page_t::WRITE_FIX);
if (s < buf_page_t::UNFIXED)
{
ut_ad(mode == BUF_GET_POSSIBLY_FREED || mode == BUF_PEEK_IF_IN_POOL);
block->page.unfix();
goto corrupted;
}
corrupted:
if (err)
*err= DB_SUCCESS;
mtr->page_lock(block, rw_latch);
return block;
*err= DB_CORRUPTION;
return nullptr;
}
if (err)
*err= DB_SUCCESS;
/* Recovery is a special case; we fix() before acquiring lock. */
auto s= block->page.fix();
ut_ad(s >= buf_page_t::FREED);
/* The block may be write-fixed at this point because we are not
holding a lock, but it must not be read-fixed. */
ut_ad(s < buf_page_t::READ_FIX || s >= buf_page_t::WRITE_FIX);
if (s < buf_page_t::UNFIXED)
{
ut_ad(mode == BUF_GET_POSSIBLY_FREED || mode == BUF_PEEK_IF_IN_POOL);
mysql_mutex_lock(&buf_pool.mutex);
block->page.unfix();
buf_LRU_free_page(&block->page, true);
mysql_mutex_unlock(&buf_pool.mutex);
goto corrupted;
}
return buf_page_get_low(page_id, zip_size, rw_latch,
guess, mode, mtr, err);
mtr->page_lock(block, rw_latch);
return block;
}
/********************************************************************//**
@ -2922,12 +2964,12 @@ retry:
buf_unzip_LRU_add_block(reinterpret_cast<buf_block_t*>(bpage), FALSE);
}
buf_pool.stat.n_pages_created++;
mysql_mutex_unlock(&buf_pool.mutex);
mtr->memo_push(reinterpret_cast<buf_block_t*>(bpage), MTR_MEMO_PAGE_X_FIX);
bpage->set_accessed();
buf_pool.stat.n_pages_created++;
static_assert(FIL_PAGE_PREV + 4 == FIL_PAGE_NEXT, "adjacent");
memset_aligned<8>(bpage->frame + FIL_PAGE_PREV, 0xff, 8);
@ -3145,7 +3187,6 @@ dberr_t buf_page_t::read_complete(const fil_node_t &node)
ut_d(auto n=) buf_pool.n_pend_reads--;
ut_ad(n > 0);
buf_pool.stat.n_pages_read++;
const byte *read_frame= zip.data ? zip.data : frame;
ut_ad(read_frame);
@ -3286,9 +3327,6 @@ void buf_pool_invalidate()
{
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
earlier is still not complete. For buffer pool invalidation to
proceed we must ensure there is NO write activity happening. */
@ -3439,8 +3477,8 @@ void buf_pool_t::print()
<< UT_LIST_GET_LEN(flush_list)
<< ", n pending decompressions=" << n_pend_unzip
<< ", n pending reads=" << n_pend_reads
<< ", n pending flush LRU=" << n_flush_LRU_
<< " list=" << n_flush_list_
<< ", n pending flush LRU=" << n_flush()
<< " list=" << buf_dblwr.pending_writes()
<< ", pages made young=" << stat.n_pages_made_young
<< ", not young=" << stat.n_pages_not_made_young
<< ", pages read=" << stat.n_pages_read
@ -3552,13 +3590,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->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_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);
time_elapsed = 0.001 + difftime(current_time,

View file

@ -46,7 +46,17 @@ inline buf_block_t *buf_dblwr_trx_sys_get(mtr_t *mtr)
0, RW_X_LATCH, mtr);
}
/** 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 */
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(!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));
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 */
bool buf_dblwr_t::create()
{
if (is_initialised())
if (is_created())
return true;
mtr_t mtr;
@ -341,7 +349,7 @@ func_exit:
void buf_dblwr_t::recover()
{
ut_ad(log_sys.last_checkpoint_lsn);
if (!is_initialised())
if (!is_created())
return;
uint32_t page_no_dblwr= 0;
@ -450,10 +458,9 @@ next_page:
/** Free the doublewrite buffer. */
void buf_dblwr_t::close()
{
if (!is_initialised())
if (!active_slot)
return;
/* Free the double write data structures. */
ut_ad(!active_slot->reserved);
ut_ad(!active_slot->first_free);
ut_ad(!batch_running);
@ -467,35 +474,41 @@ void buf_dblwr_t::close()
mysql_mutex_destroy(&mutex);
memset((void*) this, 0, sizeof *this);
active_slot= &slots[0];
}
/** 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(srv_use_doublewrite_buf);
ut_ad(is_initialised());
ut_ad(!srv_read_only_mode);
mysql_mutex_lock(&mutex);
ut_ad(batch_running);
slot *flush_slot= active_slot == &slots[0] ? &slots[1] : &slots[0];
ut_ad(flush_slot->reserved);
ut_ad(flush_slot->reserved <= flush_slot->first_free);
ut_ad(writes_pending);
if (!--writes_pending)
pthread_cond_broadcast(&write_cond);
if (!--flush_slot->reserved)
if (with_doublewrite)
{
mysql_mutex_unlock(&mutex);
/* This will finish the batch. Sync data files to the disk. */
fil_flush_file_spaces();
mysql_mutex_lock(&mutex);
ut_ad(is_created());
ut_ad(srv_use_doublewrite_buf);
ut_ad(batch_running);
slot *flush_slot= active_slot == &slots[0] ? &slots[1] : &slots[0];
ut_ad(flush_slot->reserved);
ut_ad(flush_slot->reserved <= flush_slot->first_free);
/* We can now reuse the doublewrite memory buffer: */
flush_slot->first_free= 0;
batch_running= false;
pthread_cond_broadcast(&cond);
if (!--flush_slot->reserved)
{
mysql_mutex_unlock(&mutex);
/* This will finish the batch. Sync data files to the disk. */
fil_flush_file_spaces();
mysql_mutex_lock(&mutex);
/* We can now reuse the doublewrite memory buffer: */
flush_slot->first_free= 0;
batch_running= false;
pthread_cond_broadcast(&cond);
}
}
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(srv_use_doublewrite_buf);
ut_ad(is_initialised());
ut_ad(is_created());
ut_ad(!srv_read_only_mode);
ut_ad(!request.bpage);
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. */
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();
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();
mysql_mutex_lock(&mutex);
writes_pending++;
for (;;)
{

File diff suppressed because it is too large Load diff

View file

@ -136,7 +136,6 @@ static void buf_LRU_block_free_hashed_page(buf_block_t *block)
@param[in] bpage control block */
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);
buf_pool.stat.LRU_bytes += bpage->physical_size();
@ -401,8 +400,10 @@ buf_block_t* buf_LRU_get_free_block(buf_LRU_get get)
DBUG_EXECUTE_IF("recv_ran_out_of_buffer",
if (recv_recovery_is_on()
&& recv_sys.apply_log_recs) {
mysql_mutex_lock(&buf_pool.mutex);
goto flush_lru;
});
get_mutex:
mysql_mutex_lock(&buf_pool.mutex);
got_mutex:
buf_LRU_check_size_of_non_data_objects();
@ -451,20 +452,32 @@ got_block:
if ((block = buf_LRU_get_free_only()) != nullptr) {
goto got_block;
}
if (!buf_pool.n_flush_LRU_) {
break;
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);
}
my_cond_wait(&buf_pool.done_free, &buf_pool.mutex.m_mutex);
}
#ifndef DBUG_OFF
not_found:
#endif
mysql_mutex_unlock(&buf_pool.mutex);
if (n_iterations > 1) {
MONITOR_INC( MONITOR_LRU_GET_FREE_WAITS );
}
if (n_iterations > 20 && !buf_lru_free_blocks_error_printed
if (n_iterations == 21 && !buf_lru_free_blocks_error_printed
&& 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"
" (" << n_iterations << " search iterations)! "
<< flush_failures << " failed attempts to"
@ -476,12 +489,7 @@ not_found:
<< os_n_file_writes << " OS file writes, "
<< os_n_fsyncs
<< " OS fsyncs.";
buf_lru_free_blocks_error_printed = true;
}
if (n_iterations > 1) {
MONITOR_INC( MONITOR_LRU_GET_FREE_WAITS );
mysql_mutex_lock(&buf_pool.mutex);
}
/* No free block was found: try to flush the LRU list.
@ -495,15 +503,16 @@ not_found:
#ifndef DBUG_OFF
flush_lru:
#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);
++flush_failures;
}
n_iterations++;
mysql_mutex_lock(&buf_pool.mutex);
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
@ -812,50 +821,57 @@ bool buf_LRU_free_page(buf_page_t *bpage, bool zip)
/* We cannot use transactional_lock_guard here,
because buf_buddy_relocate() in buf_buddy_free() could get stuck. */
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())) {
/* Do not free buffer fixed and I/O-fixed blocks. */
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);
oldest_modification = bpage->oldest_modification();
if (oldest_modification) {
ut_ad(oldest_modification == 1);
if (const lsn_t om = bpage->oldest_modification()) {
ut_ad(om == 1);
buf_pool.delete_from_flush_list(bpage);
}
mysql_mutex_unlock(&buf_pool.flush_list_mutex);
ut_ad(!bpage->oldest_modification());
oldest_modification = 0;
}
if (zip || !bpage->zip.data) {
/* This would completely free the block. */
/* Do not completely free dirty blocks. */
if (oldest_modification) {
goto func_exit;
/* fall through */
case 0:
if (zip || !bpage->zip.data || !bpage->frame) {
break;
}
} else if (oldest_modification && !bpage->frame) {
func_exit:
hash_lock.unlock();
return(false);
} else if (bpage->frame) {
relocate_compressed:
b = static_cast<buf_page_t*>(ut_zalloc_nokey(sizeof *b));
ut_a(b);
mysql_mutex_lock(&buf_pool.flush_list_mutex);
new (b) buf_page_t(*bpage);
b->frame = nullptr;
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);
DBUG_PRINT("ib_buf", ("free page %u:%u",
id.space(), id.page_no()));
DBUG_PRINT("ib_buf", ("free page %u:%u", id.space(), id.page_no()));
ut_ad(bpage->can_relocate());
@ -1026,7 +1042,8 @@ buf_LRU_block_free_non_file_page(
} else {
UT_LIST_ADD_FIRST(buf_pool.free, &block->page);
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);
}
block->page.set_os_unused();

View file

@ -186,6 +186,7 @@ page_exists:
buf_LRU_add_block(bpage, true/* to old blocks */);
}
buf_pool.stat.n_pages_read++;
mysql_mutex_unlock(&buf_pool.mutex);
buf_pool.n_pend_reads++;
return bpage;
@ -205,35 +206,31 @@ flag is cleared and the x-lock released by an i/o-handler thread.
@param[in] zip_size ROW_FORMAT=COMPRESSED page size, or 0,
bitwise-ORed with 1 in recovery
@param[in,out] chain buf_pool.page_hash cell for page_id
@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] block preallocated buffer block
@param[in] sync true if synchronous aio is desired
@return whether a read request was enqueued */
@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
bool
dberr_t
buf_read_page_low(
const page_id_t page_id,
ulint zip_size,
buf_pool_t::hash_chain& chain,
dberr_t* err,
fil_space_t* space,
buf_block_t*& block,
bool sync = false)
{
buf_page_t* bpage;
*err = DB_SUCCESS;
ut_ad(!buf_dblwr.is_inside(page_id));
bpage = buf_page_init_for_read(page_id, zip_size, chain, block);
if (!bpage) {
space->release();
return false;
return DB_SUCCESS_LOCKED_REC;
}
ut_ad(bpage->in_file());
@ -253,7 +250,6 @@ buf_read_page_low(
? IORequest::READ_SYNC
: IORequest::READ_ASYNC),
page_id.page_no() * len, len, dst, bpage);
*err = fio.err;
if (UNIV_UNLIKELY(fio.err != DB_SUCCESS)) {
ut_d(auto n=) buf_pool.n_pend_reads--;
@ -262,14 +258,14 @@ buf_read_page_low(
} else if (sync) {
thd_wait_end(NULL);
/* The i/o was already completed in space->io() */
*err = bpage->read_complete(*fio.node);
fio.err = bpage->read_complete(*fio.node);
space->release();
if (*err == DB_FAIL) {
*err = DB_PAGE_CORRUPTED;
if (fio.err == DB_FAIL) {
fio.err = DB_PAGE_CORRUPTED;
}
}
return true;
return fio.err;
}
/** Acquire a buffer block. */
@ -353,9 +349,8 @@ read_ahead:
if (space->is_stopping())
break;
buf_pool_t::hash_chain &chain= buf_pool.page_hash.cell_get(i.fold());
dberr_t err;
space->reacquire();
if (buf_read_page_low(i, zip_size, chain, &err, space, block))
if (buf_read_page_low(i, zip_size, chain, space, block) == DB_SUCCESS)
{
count++;
ut_ad(!block);
@ -365,18 +360,20 @@ read_ahead:
}
if (count)
{
DBUG_PRINT("ib_buf", ("random read-ahead %zu pages from %s: %u",
count, space->chain.start->name,
low.page_no()));
mysql_mutex_lock(&buf_pool.mutex);
/* Read ahead is considered one I/O operation for the purpose of
LRU policy decision. */
buf_LRU_stat_inc_io();
buf_pool.stat.n_ra_pages_read_rnd+= count;
mysql_mutex_unlock(&buf_pool.mutex);
}
space->release();
/* Read ahead is considered one I/O operation for the purpose of
LRU policy decision. */
buf_LRU_stat_inc_io();
buf_read_release(block);
buf_pool.stat.n_ra_pages_read_rnd+= count;
srv_stats.buf_pool_reads.add(count);
return count;
}
@ -388,6 +385,7 @@ released by the i/o-handler thread.
@param zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param chain buf_pool.page_hash cell for page_id
@retval DB_SUCCESS if the page was read and is not 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
after decryption normal page checksum does not match.
@ -403,22 +401,19 @@ dberr_t buf_read_page(const page_id_t page_id, ulint zip_size,
return DB_TABLESPACE_DELETED;
}
buf_block_t *block= zip_size
? nullptr
: buf_LRU_get_free_block(have_no_mutex);
/* Our caller should already have ensured that the page does not
exist in buf_pool.page_hash. */
dberr_t err;
if (buf_read_page_low(page_id, zip_size, chain, &err, space, block, true))
buf_block_t *block= nullptr;
if (UNIV_LIKELY(!zip_size))
{
ut_ad(!block);
srv_stats.buf_pool_reads.add(1);
mysql_mutex_lock(&buf_pool.mutex);
buf_LRU_stat_inc_io();
block= buf_LRU_get_free_block(have_mutex);
mysql_mutex_unlock(&buf_pool.mutex);
}
else
buf_read_release(block);
buf_LRU_stat_inc_io();
dberr_t err= buf_read_page_low(page_id, zip_size, chain, space, block, true);
buf_read_release(block);
return err;
}
@ -444,12 +439,9 @@ void buf_read_page_background(fil_space_t *space, const page_id_t page_id,
if (!zip_size && !(block= buf_read_acquire()))
goto skip;
dberr_t err;
if (buf_read_page_low(page_id, zip_size, chain, &err, space, block))
{
if (buf_read_page_low(page_id, zip_size, chain, space, block) ==
DB_SUCCESS)
ut_ad(!block);
srv_stats.buf_pool_reads.add(1);
}
else
buf_read_release(block);
@ -601,9 +593,9 @@ failed:
if (space->is_stopping())
break;
buf_pool_t::hash_chain &chain= buf_pool.page_hash.cell_get(new_low.fold());
dberr_t err;
space->reacquire();
if (buf_read_page_low(new_low, zip_size, chain, &err, space, block))
if (buf_read_page_low(new_low, zip_size, chain, space, block) ==
DB_SUCCESS)
{
count++;
ut_ad(!block);
@ -613,17 +605,20 @@ failed:
}
if (count)
{
DBUG_PRINT("ib_buf", ("random read-ahead %zu pages from %s: %u",
count, space->chain.start->name,
new_low.page_no()));
mysql_mutex_lock(&buf_pool.mutex);
/* Read ahead is considered one I/O operation for the purpose of
LRU policy decision. */
buf_LRU_stat_inc_io();
buf_pool.stat.n_ra_pages_read+= count;
mysql_mutex_unlock(&buf_pool.mutex);
}
space->release();
/* Read ahead is considered one I/O operation for the purpose of
LRU policy decision. */
buf_LRU_stat_inc_io();
buf_read_release(block);
buf_pool.stat.n_ra_pages_read+= count;
return count;
}
@ -679,20 +674,22 @@ void buf_read_recv_pages(uint32_t space_id, st_::span<uint32_t> page_nos)
buf_pool_t::hash_chain& chain =
buf_pool.page_hash.cell_get(cur_page_id.fold());
dberr_t err;
space->reacquire();
if (buf_read_page_low(cur_page_id, zip_size, chain, &err, space,
block)) {
switch (buf_read_page_low(cur_page_id, zip_size, chain, space,
block)) {
case DB_SUCCESS:
ut_ad(!block);
block = buf_LRU_get_free_block(have_no_mutex);
}
if (err != DB_SUCCESS) {
break;
case DB_SUCCESS_LOCKED_REC:
break;
default:
sql_print_error("InnoDB: Recovery failed to read page "
UINT32PF " from %s",
cur_page_id.page_no(),
space->chain.start->name);
}
ut_ad(block);
}
DBUG_PRINT("ib_buf", ("recovery read (%zu pages) for %s",

View file

@ -118,6 +118,9 @@ bool fil_space_t::try_to_close(bool print_info)
}
node->close();
fil_system.move_closed_last_to_space_list(node->space);
return true;
}
@ -392,13 +395,7 @@ static bool fil_node_open_file_low(fil_node_t *node)
ut_ad(node->is_open());
if (UNIV_LIKELY(!fil_system.freeze_space_list))
{
/* 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.move_opened_last_to_space_list(node->space);
fil_system.n_open++;
return true;
@ -797,7 +794,17 @@ pfs_os_file_t fil_system_t::detach(fil_space_t *space, bool detach_handle)
space->is_in_default_encrypt= false;
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)
sys_space= nullptr;
else if (space == temp_space)
@ -916,12 +923,14 @@ bool fil_space_free(uint32_t id, bool x_latched)
@param purpose tablespace purpose
@param crypt_data encryption information
@param mode encryption mode
@param opened true if space files are opened
@return pointer to created tablespace, to be filled in with add()
@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_type_t purpose,
fil_space_crypt_t *crypt_data,
fil_encryption_t mode)
fil_encryption_t mode,
bool opened)
{
fil_space_t* space;
@ -974,7 +983,10 @@ fil_space_t *fil_space_t::create(uint32_t id, uint32_t flags,
HASH_INSERT(fil_space_t, hash, &fil_system.spaces, id, space);
fil_system.space_list.push_back(*space);
if (opened)
fil_system.add_opened_last_to_space_list(space);
else
fil_system.space_list.push_back(*space);
switch (id) {
case 0:
@ -1295,6 +1307,15 @@ void fil_system_t::close()
#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 */
ATTRIBUTE_COLD void fil_system_t::extend_to_recv_size()
{
@ -2028,7 +2049,7 @@ err_exit:
if (fil_space_t* space = fil_space_t::create(space_id, flags,
FIL_TYPE_TABLESPACE,
crypt_data, mode)) {
crypt_data, mode, true)) {
fil_node_t* node = space->add(path, file, size, false, true);
IF_WIN(node->find_metadata(), node->find_metadata(file, true));
mtr.start();

View file

@ -890,6 +890,8 @@ rtr_page_split_and_insert(
int first_rec_group = 1;
IF_DBUG(bool iterated = false,);
buf_pool.pages_split++;
if (!*heap) {
*heap = mem_heap_create(1024);
}
@ -1197,8 +1199,6 @@ after_insert:
ut_ad(!rec || rec_offs_validate(rec, cursor->index(), *offsets));
#endif
MONITOR_INC(MONITOR_INDEX_SPLIT);
return(rec);
}

View file

@ -894,43 +894,37 @@ static SHOW_VAR innodb_status_variables[]= {
(char*) &export_vars.innodb_buffer_pool_resize_status, SHOW_CHAR},
{"buffer_pool_load_incomplete",
&export_vars.innodb_buffer_pool_load_incomplete, SHOW_BOOL},
{"buffer_pool_pages_data",
&export_vars.innodb_buffer_pool_pages_data, SHOW_SIZE_T},
{"buffer_pool_pages_data", &UT_LIST_GET_LEN(buf_pool.LRU), SHOW_SIZE_T},
{"buffer_pool_bytes_data",
&export_vars.innodb_buffer_pool_bytes_data, SHOW_SIZE_T},
{"buffer_pool_pages_dirty",
&export_vars.innodb_buffer_pool_pages_dirty, SHOW_SIZE_T},
{"buffer_pool_bytes_dirty",
&export_vars.innodb_buffer_pool_bytes_dirty, SHOW_SIZE_T},
{"buffer_pool_pages_flushed", &buf_flush_page_count, SHOW_SIZE_T},
{"buffer_pool_pages_free",
&export_vars.innodb_buffer_pool_pages_free, SHOW_SIZE_T},
&UT_LIST_GET_LEN(buf_pool.flush_list), SHOW_SIZE_T},
{"buffer_pool_bytes_dirty", &buf_pool.flush_list_bytes, SHOW_SIZE_T},
{"buffer_pool_pages_flushed", &buf_pool.stat.n_pages_written, SHOW_SIZE_T},
{"buffer_pool_pages_free", &UT_LIST_GET_LEN(buf_pool.free), SHOW_SIZE_T},
#ifdef UNIV_DEBUG
{"buffer_pool_pages_latched",
&export_vars.innodb_buffer_pool_pages_latched, SHOW_SIZE_T},
#endif /* UNIV_DEBUG */
{"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",
&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",
&export_vars.innodb_buffer_pool_pages_misc, SHOW_SIZE_T},
{"buffer_pool_pages_old",
&export_vars.innodb_buffer_pool_pages_old, SHOW_SIZE_T},
{"buffer_pool_pages_old", &buf_pool.LRU_old_len, SHOW_SIZE_T},
{"buffer_pool_pages_total",
&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_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",
&export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_SIZE_T},
{"buffer_pool_read_ahead",
&export_vars.innodb_buffer_pool_read_ahead, SHOW_SIZE_T},
&buf_pool.stat.n_ra_pages_read_rnd, SHOW_SIZE_T},
{"buffer_pool_read_ahead", &buf_pool.stat.n_ra_pages_read, SHOW_SIZE_T},
{"buffer_pool_read_ahead_evicted",
&export_vars.innodb_buffer_pool_read_ahead_evicted, SHOW_SIZE_T},
{"buffer_pool_read_requests",
&export_vars.innodb_buffer_pool_read_requests, SHOW_SIZE_T},
{"buffer_pool_reads",
&export_vars.innodb_buffer_pool_reads, SHOW_SIZE_T},
&buf_pool.stat.n_ra_pages_evicted, SHOW_SIZE_T},
{"buffer_pool_read_requests", &buf_pool.stat.n_page_gets, SHOW_SIZE_T},
{"buffer_pool_reads", &buf_pool.stat.n_pages_read, 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},
{"checkpoint_age", &export_vars.innodb_checkpoint_age, SHOW_SIZE_T},
@ -4431,6 +4425,25 @@ innobase_commit_ordered(
DBUG_VOID_RETURN;
}
/** Mark the end of a statement.
@param trx transaction
@return whether an error occurred */
static bool end_of_statement(trx_t *trx)
{
trx_mark_sql_stat_end(trx);
if (UNIV_LIKELY(trx->error_state == DB_SUCCESS))
return false;
trx_savept_t savept;
savept.least_undo_no= 0;
trx->rollback(&savept);
/* MariaDB will roll back the entire transaction. */
trx->bulk_insert= false;
trx->last_sql_stat_start.least_undo_no= 0;
trx->savepoints_discard();
return true;
}
/*****************************************************************//**
Commits a transaction in an InnoDB database or marks an SQL statement
ended.
@ -4507,10 +4520,7 @@ innobase_commit(
/* Store the current undo_no of the transaction so that we
know where to roll back if we have to roll back the next
SQL statement */
trx_mark_sql_stat_end(trx);
if (UNIV_UNLIKELY(trx->error_state != DB_SUCCESS)) {
trx_rollback_for_mysql(trx);
if (UNIV_UNLIKELY(end_of_statement(trx))) {
DBUG_RETURN(1);
}
}
@ -15148,16 +15158,26 @@ ha_innobase::check(
}
if ((check_opt->flags & T_QUICK) || index->is_corrupted()) {
} else if (btr_validate_index(index, m_prebuilt->trx)
!= DB_SUCCESS) {
is_ok = false;
push_warning_printf(thd,
Sql_condition::WARN_LEVEL_WARN,
ER_NOT_KEYFILE,
"InnoDB: The B-tree of"
" index %s is corrupted.",
index->name());
continue;
} 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) {
is_ok = false;
push_warning_printf(
thd,
Sql_condition::WARN_LEVEL_WARN,
ER_NOT_KEYFILE,
"InnoDB: The B-tree of"
" index %s is corrupted.",
index->name());
continue;
}
}
/* Instead of invoking change_active_index(), set up
@ -15280,6 +15300,7 @@ ha_innobase::check(
}
# endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
#endif /* BTR_CUR_HASH_ADAPT */
func_exit:
m_prebuilt->trx->op_info = "";
DBUG_RETURN(is_ok ? HA_ADMIN_OK : HA_ADMIN_CORRUPT);
@ -16945,10 +16966,7 @@ innobase_xa_prepare(
/* Store the current undo_no of the transaction so that we
know where to roll back if we have to roll back the next
SQL statement */
trx_mark_sql_stat_end(trx);
if (UNIV_UNLIKELY(trx->error_state != DB_SUCCESS)) {
trx_rollback_for_mysql(trx);
if (UNIV_UNLIKELY(end_of_statement(trx))) {
return 1;
}
}

View file

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

View file

@ -6130,8 +6130,13 @@ static int i_s_sys_tablespaces_fill(THD *thd, const fil_space_t &s, TABLE *t)
OK(f->store(name.data(), name.size(), system_charset_info));
f->set_notnull();
}
else
f->set_notnull();
else if (srv_is_undo_tablespace(s.id))
{
char name[15];
snprintf(name, sizeof name, "innodb_undo%03u",
(s.id - srv_undo_space_id_start + 1));
OK(f->store(name, strlen(name), system_charset_info));
} else f->set_notnull();
}
fields[SYS_TABLESPACES_NAME]->set_null();

View file

@ -441,7 +441,7 @@ Gets the root node of a tree and x- or s-latches it.
buf_block_t*
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
or RW_X_LATCH */
mtr_t* mtr, /*!< in: mtr */

View file

@ -87,6 +87,9 @@ enum btr_latch_mode {
dict_index_t::lock is being held in non-exclusive mode. */
BTR_MODIFY_LEAF_ALREADY_LATCHED = BTR_MODIFY_LEAF
| 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
dict_index_t::lock is being held in U mode. */
BTR_MODIFY_ROOT_AND_LEAF_ALREADY_LATCHED = BTR_MODIFY_ROOT_AND_LEAF

View file

@ -691,13 +691,14 @@ public:
ut_ad(s < prev_state + UNFIXED);
}
void read_unfix(uint32_t s)
uint32_t read_unfix(uint32_t s)
{
ut_ad(lock.is_write_locked());
ut_ad(s == UNFIXED + 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 < WRITE_FIX);
return old_state + (s - READ_FIX);
}
void set_freed(uint32_t prev_state, uint32_t count= 0)
@ -748,11 +749,11 @@ public:
it from buf_pool.flush_list */
inline void write_complete(bool temporary);
/** Write a flushable page to a file. buf_pool.mutex must be held.
@param lru true=buf_pool.LRU; false=buf_pool.flush_list
/** Write a flushable page to a file or free a freeable block.
@param evict whether to evict the page on write completion
@param space tablespace
@return whether the page was flushed and buf_pool.mutex was released */
inline bool flush(bool lru, fil_space_t *space);
@return whether a page write was initiated and buf_pool.mutex released */
bool flush(bool evict, fil_space_t *space);
/** Notify that a page in a temporary tablespace has been modified. */
void set_temp_modified()
@ -822,8 +823,6 @@ public:
/** @return whether the block is mapped to a data file */
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.
The block can be dirty, but it must not be I/O-fixed or bufferfixed. */
inline bool can_relocate() const;
@ -996,10 +995,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))
/* @} */
/** A "Hazard Pointer" class used to iterate over page lists
inside the buffer pool. A hazard pointer is a buf_page_t pointer
/** A "Hazard Pointer" class used to iterate over buf_pool.LRU or
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
even after we release the buffer pool mutex. */
even after we release the mutex that protects the list. */
class HazardPointer
{
public:
@ -1114,7 +1113,8 @@ struct buf_buddy_free_t {
/*!< 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{
/** Initialize the counters */
void init() { memset((void*) this, 0, sizeof *this); }
@ -1123,9 +1123,8 @@ struct buf_pool_stat_t{
/*!< number of page gets performed;
also successful searches through
the adaptive hash index are
counted as page gets; this field
is NOT protected by the buffer
pool mutex */
counted as page gets;
NOT protected by buf_pool.mutex */
ulint n_pages_read; /*!< number read operations */
ulint n_pages_written;/*!< number write operations */
ulint n_pages_created;/*!< number of pages created
@ -1143,10 +1142,9 @@ struct buf_pool_stat_t{
young because the first access
was not long enough ago, in
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_bytes; /*!< LRU size in bytes */
ulint flush_list_bytes;/*!< flush_list size in bytes */
};
/** Statistics of buddy blocks of a given size. */
@ -1399,6 +1397,11 @@ public:
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 */
inline bool is_shrinking() const
{
@ -1436,17 +1439,10 @@ public:
/** Buffer pool mutex */
alignas(CPU_LEVEL1_DCACHE_LINESIZE) mysql_mutex_t mutex;
/** Number of pending LRU flush; protected by mutex. */
ulint n_flush_LRU_;
/** broadcast when n_flush_LRU reaches 0; protected by mutex */
pthread_cond_t done_flush_LRU;
/** 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_; }
/** current statistics; protected by mutex */
buf_pool_stat_t stat;
/** old statistics; protected by mutex */
buf_pool_stat_t old_stat;
/** @name General fields */
/* @{ */
@ -1607,11 +1603,12 @@ public:
buf_buddy_stat_t buddy_stat[BUF_BUDDY_SIZES_MAX + 1];
/*!< Statistics of buddy system,
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 */
/* @{ */
@ -1620,7 +1617,10 @@ public:
alignas(CPU_LEVEL1_DCACHE_LINESIZE) mysql_mutex_t flush_list_mutex;
/** "hazard pointer" for flush_list scans; protected by flush_list_mutex */
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;
/** number of blocks ever added to flush_list;
sometimes protected by flush_list_mutex */
@ -1629,28 +1629,70 @@ public:
TPOOL_SUPPRESS_TSAN void add_flush_list_requests(size_t size)
{ ut_ad(size); flush_list_requests+= size; }
private:
/** whether the page cleaner needs wakeup from indefinite sleep */
bool page_cleaner_is_idle;
static constexpr unsigned PAGE_CLEANER_IDLE= 1;
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 */
ulint last_activity_count;
public:
/** signalled to wake up the page_cleaner; protected by flush_list_mutex */
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 */
bool page_cleaner_idle() const noexcept
{
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 */
void page_cleaner_wakeup();
/** Wake up the page cleaner if needed.
@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 */
void page_cleaner_set_idle(bool deep_sleep)
{
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 */
@ -1660,9 +1702,6 @@ public:
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
to count the number of buffer
blocks removed from the end of
@ -1672,16 +1711,10 @@ public:
to read this for heuristic
purposes without holding any
mutex or latch */
bool try_LRU_scan; /*!< Cleared when an LRU
scan for free block fails. This
flag is used to avoid repeated
scans of LRU list when we know
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 */
/** Cleared when buf_LRU_get_free_block() fails.
Set whenever the free list grows, along with a broadcast of done_free.
Protected by buf_pool.mutex. */
Atomic_relaxed<bool> try_LRU_scan;
/* @} */
/** @name LRU replacement algorithm fields */
@ -1690,7 +1723,8 @@ public:
UT_LIST_BASE_NODE_T(buf_page_t) free;
/*!< base node of the free
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;
UT_LIST_BASE_NODE_T(buf_page_t) withdraw;
@ -1747,29 +1781,16 @@ public:
{
if (n_pend_reads)
return true;
mysql_mutex_lock(&mutex);
const bool any_pending{n_flush_LRU_ || n_flush_list_};
mysql_mutex_unlock(&mutex);
mysql_mutex_lock(&flush_list_mutex);
const bool any_pending= page_cleaner_status > PAGE_CLEANER_IDLE ||
buf_dblwr.pending_writes();
mysql_mutex_unlock(&flush_list_mutex);
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.
@param bpage buffer pool page */
void delete_from_flush_list(buf_page_t *bpage) noexcept
{ delete_from_flush_list(bpage, true); }
void delete_from_flush_list(buf_page_t *bpage) noexcept;
/** Prepare to insert a modified blcok into flush_list.
@param lsn start LSN of the mini-transaction
@ -1784,7 +1805,7 @@ public:
lsn_t lsn) noexcept;
/** 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:
/** Temporary memory for page_compressed and encrypted I/O */
@ -1795,34 +1816,12 @@ private:
/** array of slots */
buf_tmp_buffer_t *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 create(ulint n_slots);
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;
}
void close();
/** Reserve a buffer */
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;
}
buf_tmp_buffer_t *reserve();
} io_buf;
/** whether resize() is in the critical path */
@ -1911,7 +1910,10 @@ inline void buf_page_t::set_oldest_modification(lsn_t lsn)
/** Clear oldest_modification after removing from buf_pool.flush_list */
inline void buf_page_t::clear_oldest_modification()
{
mysql_mutex_assert_owner(&buf_pool.flush_list_mutex);
#ifdef SAFE_MUTEX
if (oldest_modification() != 2)
mysql_mutex_assert_owner(&buf_pool.flush_list_mutex);
#endif /* SAFE_MUTEX */
ut_d(const auto s= state());
ut_ad(s >= REMOVE_HASH);
ut_ad(oldest_modification());
@ -1923,17 +1925,6 @@ inline void buf_page_t::clear_oldest_modification()
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.
The block can be dirty, but it must not be I/O-fixed or bufferfixed. */
inline bool buf_page_t::can_relocate() const

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2020, MariaDB Corporation.
Copyright (c) 2017, 2022, 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
@ -54,9 +54,9 @@ class buf_dblwr_t
};
/** 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) */
page_id_t block2= page_id_t(0, 0);
page_id_t block2{0, 0};
/** mutex protecting the data members below */
mysql_mutex_t mutex;
@ -72,11 +72,15 @@ class buf_dblwr_t
ulint writes_completed;
/** number of pages written by flush_buffered_writes_completed() */
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 *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 */
inline void init(const byte *header);
@ -84,6 +88,8 @@ class buf_dblwr_t
bool flush_buffered_writes(const ulint size);
public:
/** Initialise the doublewrite buffer data structures. */
void init();
/** Create or restore the doublewrite buffer in the TRX_SYS page.
@return whether the operation succeeded */
bool create();
@ -118,7 +124,7 @@ public:
void recover();
/** 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.
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!
@ -137,14 +143,14 @@ public:
@param size payload size in bytes */
void add_to_batch(const IORequest &request, size_t size);
/** Determine whether the doublewrite buffer is initialized */
bool is_initialised() const
/** Determine whether the doublewrite buffer has been created */
bool is_created() const
{ return UNIV_LIKELY(block1 != page_id_t(0, 0)); }
/** @return whether a page identifier is part of the doublewrite buffer */
bool is_inside(const page_id_t id) const
{
if (!is_initialised())
if (!is_created())
return false;
ut_ad(block1 < block2);
if (id < block1)
@ -156,13 +162,44 @@ public:
/** Wait for flush_buffered_writes() to be fully completed */
void wait_flush_buffered_writes()
{
if (is_initialised())
{
mysql_mutex_lock(&mutex);
while (batch_running)
my_cond_wait(&cond, &mutex.m_mutex);
mysql_mutex_unlock(&mutex);
}
mysql_mutex_lock(&mutex);
while (batch_running)
my_cond_wait(&cond, &mutex.m_mutex);
mysql_mutex_unlock(&mutex);
}
/** Register an unbuffered page write */
void add_unbuffered()
{
mysql_mutex_lock(&mutex);
writes_pending++;
mysql_mutex_unlock(&mutex);
}
size_t pending_writes()
{
mysql_mutex_lock(&mutex);
const size_t pending{writes_pending};
mysql_mutex_unlock(&mutex);
return pending;
}
/** Wait for writes_pending to reach 0 */
void wait_for_page_writes()
{
mysql_mutex_lock(&mutex);
while (writes_pending)
my_cond_wait(&write_cond, &mutex.m_mutex);
mysql_mutex_unlock(&mutex);
}
/** Wait for writes_pending to reach 0 */
void wait_for_page_writes(const timespec &abstime)
{
mysql_mutex_lock(&mutex);
while (writes_pending)
my_cond_timedwait(&write_cond, &mutex.m_mutex, &abstime);
mysql_mutex_unlock(&mutex);
}
};

View file

@ -30,10 +30,8 @@ Created 11/5/1995 Heikki Tuuri
#include "log0log.h"
#include "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.
Also included in buf_flush_page_count. */
Also included in buf_pool.stat.n_pages_written. */
extern ulint buf_lru_flush_page_count;
/** Number of pages freed without flushing. Protected by buf_pool.mutex. */
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)
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
@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 */
ulint buf_flush_LRU(ulint max_n);
ulint buf_flush_LRU(ulint max_n, bool evict);
/** Wait until a flush batch ends.
@param lru true=buf_pool.LRU; false=buf_pool.flush_list */
void buf_flush_wait_batch_end(bool lru);
/** Wait until a LRU flush batch ends. */
void buf_flush_wait_LRU_batch_end();
/** Wait until all persistent pages are flushed up to a limit.
@param sync_lsn buf_pool.get_oldest_modification(LSN_MAX) to wait for */
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. */
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. */
ATTRIBUTE_COLD void buf_flush_buffer_pool();

View file

@ -36,6 +36,7 @@ released by the i/o-handler thread.
@param zip_size ROW_FORMAT=COMPRESSED page size, or 0
@param chain buf_pool.page_hash cell for page_id
@retval DB_SUCCESS if the page was read and is not 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
after decryption normal page checksum does not match.

View file

@ -871,11 +871,13 @@ public:
@param purpose tablespace purpose
@param crypt_data encryption information
@param mode encryption mode
@param opened true if space files are opened
@return pointer to created tablespace, to be filled in with add()
@retval nullptr on failure (such as when the same tablespace exists) */
static fil_space_t *create(uint32_t id, uint32_t flags,
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))
/** Acquire a tablespace reference.
@ -1080,7 +1082,7 @@ private:
inline bool fil_space_t::use_doublewrite() const
{
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()
@ -1357,6 +1359,11 @@ struct fil_system_t
private:
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__
/** available block devices that reside on non-rotational storage */
std::vector<dev_t> ssd;
@ -1412,7 +1419,8 @@ public:
/** 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() */
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;
/** list of all tablespaces for which a FILE_MODIFY record has been written
since the latest redo log checkpoint.
@ -1427,6 +1435,49 @@ public:
potential space_id reuse */
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.
@param space previous tablespace (nullptr to start from the start)
@param recheck whether the removal condition needs to be rechecked after

View file

@ -333,6 +333,9 @@ public:
/** Upgrade U locks on a block to X */
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
@param space tablespace to search for
@return whether space.latch is being held */

View file

@ -85,11 +85,6 @@ struct srv_stats_t
/** Count the amount of data written in total (in bytes) */
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 */
ulint_ctr_n_t page_compression_saved;
/* Number of pages compressed with page compression */
@ -607,23 +602,11 @@ struct export_var_t{
char innodb_buffer_pool_resize_status[512];/*!< Buf pool resize status */
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_data; /*!< Data pages */
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_free; /*!< Free pages */
#ifdef UNIV_DEBUG
ulint innodb_buffer_pool_pages_latched; /*!< Latched pages */
#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_max_age;
ulint innodb_data_pending_reads; /*!< Pending reads */

View file

@ -926,14 +926,19 @@ public:
/**
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
@return whether any transaction not newer than id might be active
*/
bool find_same_or_older(trx_t *caller_trx, trx_id_t id)
bool find_same_or_older(trx_t *trx, trx_id_t id)
{
return rw_trx_hash.iterate(caller_trx, find_same_or_older_callback, &id);
if (trx->max_inactive_id >= id)
return false;
bool found= rw_trx_hash.iterate(trx, find_same_or_older_callback, &id);
if (!found)
trx->max_inactive_id= id;
return found;
}

View file

@ -642,6 +642,10 @@ public:
Cleared in commit_in_memory() after commit_state(),
trx_sys_t::deregister_rw(), release_locks(). */
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:
/** mutex protecting state and some of lock

View file

@ -1064,13 +1064,16 @@ lock_sec_rec_some_has_impl(
const trx_id_t max_trx_id= page_get_max_trx_id(page_align(rec));
if ((caller_trx->id > max_trx_id &&
!trx_sys.find_same_or_older(caller_trx, max_trx_id)) ||
/* Note: It is possible to have caller_trx->id == 0 in a locking read
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))
return nullptr;
/* In this case it is possible that some transaction has an implicit
x-lock. We have to look in the clustered index. */
/* We checked above that some active (or XA PREPARE) transaction exists
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);
}
@ -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
function has completed. */
static
void
bool
lock_rec_convert_impl_to_expl_for_trx(
/*==================================*/
trx_t* trx, /*!< in/out: active transaction */
const page_id_t id, /*!< in: page identifier */
const rec_t* rec, /*!< in: user record on page */
dict_index_t* index, /*!< in: index of record */
trx_t* trx, /*!< in/out: active transaction */
ulint heap_no)/*!< in: rec heap number to lock */
dict_index_t* index) /*!< in: index of record */
{
if (!trx)
return false;
ut_ad(trx->is_referenced());
ut_ad(page_rec_is_leaf(rec));
ut_ad(!rec_is_metadata(rec, *index));
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};
trx->mutex_lock();
@ -5187,6 +5194,7 @@ lock_rec_convert_impl_to_expl_for_trx(
trx->release_reference();
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 */
/** 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
@ -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
should be created.
@tparam is_primary whether the index is the primary key
@param[in,out] caller_trx current transaction
@param[in] id index tree leaf page identifier
@param[in] rec record on the leaf page
@param[in] index the index of the record
@param[in] offsets rec_get_offsets(rec,index)
@return whether caller_trx already holds an exclusive lock on rec */
template<bool is_primary>
static
bool
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_leaf(rec));
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 = 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));
}
if (trx) {
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;
return lock_rec_convert_impl_to_expl_for_trx(trx, id, rec, index);
}
/*********************************************************************//**
@ -5374,8 +5371,9 @@ lock_clust_rec_modify_check_and_lock(
/* If a transaction has no explicit x-lock set on the record, set one
for it */
if (lock_rec_convert_impl_to_expl(thr_get_trx(thr), block->page.id(),
rec, index, offsets)) {
if (lock_rec_convert_impl_to_expl<true>(thr_get_trx(thr),
block->page.id(),
rec, index, offsets)) {
/* We already hold an implicit exclusive lock. */
return DB_SUCCESS;
}
@ -5532,15 +5530,17 @@ lock_sec_rec_read_check_and_lock(
return(DB_SUCCESS);
}
const page_id_t id{block->page.id()};
ut_ad(!rec_is_metadata(rec, *index));
trx_t *trx = thr_get_trx(thr);
if (lock_table_has(trx, index->table, mode)) {
return DB_SUCCESS;
}
if (!page_rec_is_supremum(rec)
&& !lock_table_has(trx, index->table, LOCK_X)
&& lock_rec_convert_impl_to_expl(thr_get_trx(thr), id, rec,
index, offsets)
&& lock_rec_convert_impl_to_expl<false>(
trx, block->page.id(), rec, index, offsets)
&& gap_mode == LOCK_REC_NOT_GAP) {
/* We already hold an implicit exclusive lock. */
return DB_SUCCESS;
@ -5565,7 +5565,8 @@ lock_sec_rec_read_check_and_lock(
if (trx->wsrep == 3) trx->wsrep = 1;
#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);
}
@ -5622,7 +5623,8 @@ lock_clust_rec_read_check_and_lock(
trx_t *trx = thr_get_trx(thr);
if (!lock_table_has(trx, index->table, LOCK_X)
&& 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) {
/* We already hold an implicit exclusive lock. */
return DB_SUCCESS;

View file

@ -1162,14 +1162,6 @@ wait_suspend_loop:
if (!buf_pool.is_initialised()) {
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 {
buf_flush_buffer_pool();
}

View file

@ -3004,7 +3004,7 @@ set_start_lsn:
/* The following is adapted from
buf_pool_t::insert_into_flush_list() */
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);
UT_LIST_ADD_FIRST(buf_pool.flush_list, &block->page);
buf_pool.page_cleaner_wakeup();

View file

@ -140,9 +140,9 @@ inline void buf_pool_t::insert_into_flush_list(buf_page_t *prev,
UT_LIST_REMOVE(flush_list, &block->page);
}
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)
UT_LIST_INSERT_AFTER(flush_list, prev, &block->page);

View file

@ -217,14 +217,12 @@ rec_get_n_extern_new(
stored in one byte for 0..127. The length
will be encoded in two bytes when it is 128 or
more, or when the field is stored externally. */
if (DATA_BIG_COL(col)) {
if (len & 0x80) {
/* 1exxxxxxx xxxxxxxx */
if (len & 0x40) {
n_extern++;
}
lens--;
if (UNIV_UNLIKELY(len & 0x80) && DATA_BIG_COL(col)) {
/* 1exxxxxxx xxxxxxxx */
if (len & 0x40) {
n_extern++;
}
lens--;
}
}
} while (++i < n);
@ -244,6 +242,10 @@ enum rec_leaf_format {
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
in ROW_FORMAT=COMPACT,DYNAMIC,COMPRESSED.
This is a special case of rec_init_offsets() and rec_get_offsets_func().
@ -361,8 +363,7 @@ start:
do {
if (mblob) {
if (i == index->first_user_field()) {
offs = static_cast<rec_offs>(offs
+ FIELD_REF_SIZE);
offs += FIELD_REF_SIZE;
len = combine(offs, STORED_OFFPAGE);
any |= REC_OFFS_EXTERNAL;
field--;
@ -433,27 +434,23 @@ start:
stored in one byte for 0..127. The length
will be encoded in two bytes when it is 128 or
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 */
len = static_cast<rec_offs>(len << 8
| *lens--);
offs = static_cast<rec_offs>(offs
+ get_value(len));
if (UNIV_UNLIKELY(len & 0x4000)) {
ut_ad(index->is_primary());
any |= REC_OFFS_EXTERNAL;
len = combine(offs, STORED_OFFPAGE);
} else {
len = offs;
}
len <<= 8;
len |= *lens--;
static_assert(STORED_OFFPAGE == 0x4000, "");
static_assert(REC_OFFS_EXTERNAL == 0x4000, "");
const rec_offs ext = len & REC_OFFS_EXTERNAL;
offs += get_value(len);
len = offs | ext;
any |= ext;
ut_ad(!ext || index->is_primary());
continue;
}
len = offs = static_cast<rec_offs>(offs + len);
len = offs += len;
} else {
len = offs = static_cast<rec_offs>(offs
+ field->fixed_len);
len = offs += field->fixed_len;
}
} while (field++, rec_offs_base(offsets)[++i] = len,
i < rec_offs_n_fields(offsets));
@ -679,8 +676,7 @@ rec_init_offsets(
do {
rec_offs len;
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
len = offs = static_cast<rec_offs>(
offs + REC_NODE_PTR_SIZE);
len = offs += REC_NODE_PTR_SIZE;
goto resolved;
}
@ -720,29 +716,25 @@ rec_init_offsets(
encoded in two bytes when it is 128 or
more, or when the field is stored
externally. */
if (DATA_BIG_COL(col)) {
if (len & 0x80) {
/* 1exxxxxxx xxxxxxxx */
len = static_cast<rec_offs>(
len << 8 | *lens--);
if (UNIV_UNLIKELY(len & 0x80)
&& DATA_BIG_COL(col)) {
/* 1exxxxxxx xxxxxxxx */
len <<= 8;
len |= *lens--;
/* B-tree node pointers
must not contain externally
stored columns. Thus
the "e" flag must be 0. */
ut_a(!(len & 0x4000));
offs = static_cast<rec_offs>(
offs + get_value(len));
len = offs;
goto resolved;
}
/* B-tree node pointers
must not contain externally
stored columns. Thus
the "e" flag must be 0. */
ut_a(!(len & 0x4000));
offs += len & 0x3fff;
len = offs;
goto resolved;
}
len = offs = static_cast<rec_offs>(offs + len);
len = offs += len;
} else {
len = offs = static_cast<rec_offs>(
offs + field->fixed_len);
len = offs += field->fixed_len;
}
resolved:
rec_offs_base(offsets)[i + 1] = len;
@ -759,35 +751,30 @@ resolved:
rec_offs any;
if (rec_get_1byte_offs_flag(rec)) {
offs = static_cast<rec_offs>(offs + n_fields);
offs += static_cast<rec_offs>(n_fields);
any = offs;
/* Determine offsets to fields */
do {
offs = rec_1_get_field_end_info(rec, i);
if (offs & REC_1BYTE_SQL_NULL_MASK) {
offs &= static_cast<rec_offs>(
~REC_1BYTE_SQL_NULL_MASK);
set_type(offs, SQL_NULL);
offs ^= REC_1BYTE_SQL_NULL_MASK
| SQL_NULL;
}
rec_offs_base(offsets)[1 + i] = offs;
} while (++i < n);
} else {
offs = static_cast<rec_offs>(offs + 2 * n_fields);
offs += static_cast<rec_offs>(2 * n_fields);
any = offs;
/* Determine offsets to fields */
do {
offs = rec_2_get_field_end_info(rec, i);
if (offs & REC_2BYTE_SQL_NULL_MASK) {
offs &= static_cast<rec_offs>(
~REC_2BYTE_SQL_NULL_MASK);
set_type(offs, SQL_NULL);
}
if (offs & REC_2BYTE_EXTERN_MASK) {
offs &= static_cast<rec_offs>(
~REC_2BYTE_EXTERN_MASK);
set_type(offs, STORED_OFFPAGE);
any |= REC_OFFS_EXTERNAL;
}
static_assert(REC_2BYTE_SQL_NULL_MASK
== SQL_NULL, "");
static_assert(REC_2BYTE_EXTERN_MASK
== STORED_OFFPAGE, "");
static_assert(REC_OFFS_EXTERNAL
== STORED_OFFPAGE, "");
any |= (offs & REC_OFFS_EXTERNAL);
rec_offs_base(offsets)[1 + i] = offs;
} while (++i < n);
}
@ -996,8 +983,7 @@ rec_get_offsets_reverse(
do {
rec_offs len;
if (UNIV_UNLIKELY(i == n_node_ptr_field)) {
len = offs = static_cast<rec_offs>(
offs + REC_NODE_PTR_SIZE);
len = offs += REC_NODE_PTR_SIZE;
goto resolved;
}
@ -1034,30 +1020,23 @@ rec_get_offsets_reverse(
stored in one byte for 0..127. The length
will be encoded in two bytes when it is 128 or
more, or when the field is stored externally. */
if (DATA_BIG_COL(col)) {
if (len & 0x80) {
/* 1exxxxxxx xxxxxxxx */
len = static_cast<rec_offs>(
len << 8 | *lens++);
offs = static_cast<rec_offs>(
offs + get_value(len));
if (UNIV_UNLIKELY(len & 0x4000)) {
any_ext = REC_OFFS_EXTERNAL;
len = combine(offs,
STORED_OFFPAGE);
} else {
len = offs;
}
goto resolved;
}
if (UNIV_UNLIKELY(len & 0x80) && DATA_BIG_COL(col)) {
/* 1exxxxxxx xxxxxxxx */
len &= 0x7f;
len <<= 8;
len |= *lens++;
static_assert(STORED_OFFPAGE == 0x4000, "");
static_assert(REC_OFFS_EXTERNAL == 0x4000, "");
rec_offs ext = len & REC_OFFS_EXTERNAL;
offs += get_value(len);
len = offs | ext;
any_ext |= ext;
goto resolved;
}
len = offs = static_cast<rec_offs>(offs + len);
len = offs += len;
} else {
len = offs = static_cast<rec_offs>(offs
+ field->fixed_len);
len = offs += field->fixed_len;
}
resolved:
rec_offs_base(offsets)[i + 1] = len;
@ -1097,7 +1076,7 @@ rec_get_nth_field_offs_old(
return(os);
}
next_os = next_os & ~REC_1BYTE_SQL_NULL_MASK;
next_os &= ~REC_1BYTE_SQL_NULL_MASK;
} else {
os = rec_2_get_field_start_offs(rec, n);
@ -1109,8 +1088,7 @@ rec_get_nth_field_offs_old(
return(os);
}
next_os = next_os & ~(REC_2BYTE_SQL_NULL_MASK
| REC_2BYTE_EXTERN_MASK);
next_os &= ~(REC_2BYTE_SQL_NULL_MASK | REC_2BYTE_EXTERN_MASK);
}
*len = next_os - os;
@ -1263,7 +1241,8 @@ rec_get_converted_size_comp_prefix_low(
} else if (dfield_is_ext(dfield)) {
ut_ad(DATA_BIG_COL(field->col));
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++;
} else {
/* For variable-length columns, we look up the
@ -1614,14 +1593,7 @@ start:
/* set the null flag if necessary */
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);
#if defined __GNUC__ && !defined __clang__ && __GNUC__ < 6
# pragma GCC diagnostic pop
#endif
null_mask <<= 1;
continue;
}
@ -1730,6 +1702,9 @@ rec_convert_dtuple_to_rec_new(
REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
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
@ -2092,14 +2067,12 @@ rec_copy_prefix_to_buf(
stored in one byte for 0..127. The length
will be encoded in two bytes when it is 128 or
more, or when the column is stored externally. */
if (DATA_BIG_COL(col)) {
if (len & 0x80) {
/* 1exxxxxx */
len &= 0x3f;
len <<= 8;
len |= *lens--;
UNIV_PREFETCH_R(lens);
}
if (UNIV_UNLIKELY(len & 0x80) && DATA_BIG_COL(col)) {
/* 1exxxxxx */
len &= 0x3f;
len <<= 8;
len |= *lens--;
UNIV_PREFETCH_R(lens);
}
prefix_len += len;
}

View file

@ -2252,7 +2252,7 @@ row_ins_duplicate_online(ulint n_uniq, const dtuple_t *entry,
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),
reset_trx_id, DATA_TRX_ID_LEN + DATA_ROLL_PTR_LEN)) {
ut_ad(trx_id_len == DATA_TRX_ID_LEN);

View file

@ -3042,6 +3042,9 @@ row_log_apply_op_low(
mtr_start(&mtr);
index->set_modified(mtr);
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
already hold index->lock exclusively. First, search the
@ -3049,7 +3052,8 @@ row_log_apply_op_low(
depending on when the row in the clustered index was
scanned. */
*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)) {
goto func_exit;
}

View file

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

View file

@ -644,6 +644,7 @@ void srv_boot()
if (transactional_lock_enabled())
sql_print_information("InnoDB: Using transactional memory");
#endif
buf_dblwr.init();
srv_thread_pool_init();
trx_pool_init();
srv_init();
@ -896,56 +897,19 @@ srv_export_innodb_status(void)
export_vars.innodb_data_writes = os_n_file_writes;
ulint dblwr = 0;
if (buf_dblwr.is_initialised()) {
buf_dblwr.lock();
dblwr = buf_dblwr.submitted();
export_vars.innodb_dblwr_pages_written = buf_dblwr.written();
export_vars.innodb_dblwr_writes = buf_dblwr.batches();
buf_dblwr.unlock();
}
buf_dblwr.lock();
ulint dblwr = buf_dblwr.submitted();
export_vars.innodb_dblwr_pages_written = buf_dblwr.written();
export_vars.innodb_dblwr_writes = buf_dblwr.batches();
buf_dblwr.unlock();
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 =
buf_pool.stat.LRU_bytes
+ (UT_LIST_GET_LEN(buf_pool.unzip_LRU)
<< 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
export_vars.innodb_buffer_pool_pages_latched =
buf_get_latched_pages_number();

View file

@ -689,7 +689,8 @@ err_exit:
fil_set_max_space_id_if_bigger(space_id);
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(space);
@ -1034,9 +1035,7 @@ ATTRIBUTE_COLD static lsn_t 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);
recv_sys.recovery_on= true;
ut_ad(recv_sys.recovery_on);
/* Clean the buffer pool. */
buf_flush_sync();
@ -1666,8 +1665,6 @@ dberr_t srv_start(bool create_new_db)
}
}
recv_sys.debug_free();
if (srv_operation != SRV_OPERATION_NORMAL) {
ut_ad(srv_operation == SRV_OPERATION_RESTORE_EXPORT
|| srv_operation == SRV_OPERATION_RESTORE);
@ -1682,6 +1679,8 @@ dberr_t srv_start(bool create_new_db)
if (err != DB_SUCCESS) {
return(srv_init_abort(err));
}
recv_sys.debug_free();
}
ut_ad(err == DB_SUCCESS);
@ -1986,7 +1985,7 @@ void innodb_shutdown()
ut_ad(dict_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_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
ut_ad(lock_sys.is_initialised() || !srv_was_started);

View file

@ -557,9 +557,13 @@ trx_release_savepoint_for_mysql(
if (savep != NULL) {
trx_roll_savepoint_free(trx, savep);
return DB_SUCCESS;
} else if (trx->last_sql_stat_start.least_undo_no == 0) {
/* Bulk insert could have discarded savepoints */
return DB_SUCCESS;
}
return(savep != NULL ? DB_SUCCESS : DB_NO_SAVEPOINT);
return DB_NO_SAVEPOINT;
}
/*******************************************************************//**

View file

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

View file

@ -164,7 +164,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_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
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_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

View file

@ -106,16 +106,29 @@ then
done | sort -u > mariadbd-dependencies.txt
# shellcheck disable=SC2046
debuginfo-install -y mariadb-server $(cat mariadbd-dependencies.txt)
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 --"
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"
PERF="perf record -g --freq=99 --output=perf.data --timestamp-filename --pid=$MARIADB_SERVER_PID --"
fi
elif [ -e /usr/bin/perf ]
then
# If flamegraphs were not requested, log normal perf counters if possible
echo "Using 'perf' to log basic performance counters for benchmark"
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"
PERF="perf stat -p $MARIADB_SERVER_PID --"
fi
fi
PERF="perf stat -p $MARIADB_SERVER_PID --"
# Run sysbench on another CPU if system has more than one available
if [ "$(nproc)" -gt 1 ]
@ -133,10 +146,10 @@ uname -a
echo
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"
taskset -cp 0 "$MARIADB_SERVER_PID"
taskset -cp 0 "$MARIADB_SERVER_PID" || echo "taskset failed. Not setting cpu affinity."
mariadb -e "
CREATE DATABASE IF NOT EXISTS sbtest;