mirror of
https://github.com/MariaDB/server.git
synced 2026-04-22 08:15:31 +02:00
merge
This commit is contained in:
commit
bf5df8ccbf
162 changed files with 4381 additions and 1696 deletions
|
|
@ -131,6 +131,10 @@ IF (NOT CPACK_GENERATOR)
|
|||
ENDIF(WIN32)
|
||||
ENDIF(NOT CPACK_GENERATOR)
|
||||
|
||||
IF(DEB)
|
||||
SET(INSTALL_LAYOUT "DEB")
|
||||
ENDIF(DEB)
|
||||
|
||||
INCLUDE(mysql_version)
|
||||
INCLUDE(cpack_rpm)
|
||||
INCLUDE(cpack_source_ignore_files)
|
||||
|
|
|
|||
2
VERSION
2
VERSION
|
|
@ -1,4 +1,4 @@
|
|||
MYSQL_VERSION_MAJOR=5
|
||||
MYSQL_VERSION_MINOR=5
|
||||
MYSQL_VERSION_PATCH=24
|
||||
MYSQL_VERSION_PATCH=25
|
||||
MYSQL_VERSION_EXTRA=
|
||||
|
|
|
|||
|
|
@ -86,6 +86,15 @@
|
|||
/* Chars needed to store LONGLONG, excluding trailing '\0'. */
|
||||
#define LONGLONG_LEN 20
|
||||
|
||||
/* general_log or slow_log tables under mysql database */
|
||||
static inline my_bool general_log_or_slow_log_tables(const char *db,
|
||||
const char *table)
|
||||
{
|
||||
return (strcmp(db, "mysql") == 0) &&
|
||||
((strcmp(table, "general_log") == 0) ||
|
||||
(strcmp(table, "slow_log") == 0));
|
||||
}
|
||||
|
||||
static void add_load_option(DYNAMIC_STRING *str, const char *option,
|
||||
const char *option_value);
|
||||
static ulong find_set(TYPELIB *lib, const char *x, uint length,
|
||||
|
|
@ -2503,6 +2512,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
|
|||
"TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s'";
|
||||
FILE *sql_file= md_result_file;
|
||||
int len;
|
||||
my_bool is_log_table;
|
||||
MYSQL_RES *result;
|
||||
MYSQL_ROW row;
|
||||
DBUG_ENTER("get_table_structure");
|
||||
|
|
@ -2587,9 +2597,12 @@ static uint get_table_structure(char *table, char *db, char *table_type,
|
|||
/*
|
||||
Even if the "table" is a view, we do a DROP TABLE here. The
|
||||
view-specific code below fills in the DROP VIEW.
|
||||
We will skip the DROP TABLE for general_log and slow_log, since
|
||||
those stmts will fail, in case we apply dump by enabling logging.
|
||||
*/
|
||||
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",
|
||||
opt_quoted_table);
|
||||
if (!general_log_or_slow_log_tables(db, table))
|
||||
fprintf(sql_file, "DROP TABLE IF EXISTS %s;\n",
|
||||
opt_quoted_table);
|
||||
check_io(sql_file);
|
||||
}
|
||||
|
||||
|
|
@ -2701,12 +2714,25 @@ static uint get_table_structure(char *table, char *db, char *table_type,
|
|||
|
||||
row= mysql_fetch_row(result);
|
||||
|
||||
fprintf(sql_file, (opt_compatible_mode & 3) ? "%s;\n" :
|
||||
"/*!40101 SET @saved_cs_client = @@character_set_client */;\n"
|
||||
"/*!40101 SET character_set_client = utf8 */;\n"
|
||||
"%s;\n"
|
||||
"/*!40101 SET character_set_client = @saved_cs_client */;\n",
|
||||
row[1]);
|
||||
is_log_table= general_log_or_slow_log_tables(db, table);
|
||||
if (is_log_table)
|
||||
row[1]+= 13; /* strlen("CREATE TABLE ")= 13 */
|
||||
if (opt_compatible_mode & 3)
|
||||
{
|
||||
fprintf(sql_file,
|
||||
is_log_table ? "CREATE TABLE IF NOT EXISTS %s;\n" : "%s;\n",
|
||||
row[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(sql_file,
|
||||
"/*!40101 SET @saved_cs_client = @@character_set_client */;\n"
|
||||
"/*!40101 SET character_set_client = utf8 */;\n"
|
||||
"%s%s;\n"
|
||||
"/*!40101 SET character_set_client = @saved_cs_client */;\n",
|
||||
is_log_table ? "CREATE TABLE IF NOT EXISTS " : "",
|
||||
row[1]);
|
||||
}
|
||||
|
||||
check_io(sql_file);
|
||||
mysql_free_result(result);
|
||||
|
|
@ -4315,6 +4341,22 @@ static int dump_all_tables_in_db(char *database)
|
|||
if (opt_xml)
|
||||
print_xml_tag(md_result_file, "", "\n", "database", "name=", database, NullS);
|
||||
|
||||
if (strcmp(database, "mysql") == 0)
|
||||
{
|
||||
char table_type[NAME_LEN];
|
||||
char ignore_flag;
|
||||
uint num_fields;
|
||||
num_fields= get_table_structure((char *) "general_log",
|
||||
database, table_type, &ignore_flag);
|
||||
if (num_fields == 0)
|
||||
verbose_msg("-- Warning: get_table_structure() failed with some internal "
|
||||
"error for 'general_log' table\n");
|
||||
num_fields= get_table_structure((char *) "slow_log",
|
||||
database, table_type, &ignore_flag);
|
||||
if (num_fields == 0)
|
||||
verbose_msg("-- Warning: get_table_structure() failed with some internal "
|
||||
"error for 'slow_log' table\n");
|
||||
}
|
||||
if (lock_tables)
|
||||
{
|
||||
DYNAMIC_STRING query;
|
||||
|
|
|
|||
|
|
@ -94,8 +94,19 @@ IF(FEATURE_SET)
|
|||
ENDIF()
|
||||
|
||||
OPTION(ENABLED_LOCAL_INFILE "" ON)
|
||||
SET(WITH_SSL bundled CACHE STRING "")
|
||||
SET(WITH_ZLIB bundled CACHE STRING "")
|
||||
IF(RPM)
|
||||
SET(WITH_SSL system CACHE STRING "")
|
||||
SET(WITH_ZLIB system CACHE STRING "")
|
||||
ELSEIF(DEB)
|
||||
SET(WITH_SSL system CACHE STRING "")
|
||||
SET(WITH_ZLIB system CACHE STRING "")
|
||||
SET(WITH_LIBWRAP ON)
|
||||
SET(WITH_MAX ON)
|
||||
SET(HAVE_EMBEDDED_PRIVILEGE_CONTROL ON)
|
||||
ELSE()
|
||||
SET(WITH_SSL bundled CACHE STRING "")
|
||||
SET(WITH_ZLIB bundled CACHE STRING "")
|
||||
ENDIF()
|
||||
|
||||
IF(NOT COMPILATION_COMMENT)
|
||||
SET(COMPILATION_COMMENT "MariaDB Server")
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ IF(UNIX)
|
|||
|
||||
IF(CMAKE_REQUIRED_LIBRARIES)
|
||||
LIST(REMOVE_DUPLICATES CMAKE_REQUIRED_LIBRARIES)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
LINK_LIBRARIES(${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
OPTION(WITH_LIBWRAP "Compile with tcp wrappers support" OFF)
|
||||
|
|
|
|||
2
debian/additions/mariadb.cnf
vendored
2
debian/additions/mariadb.cnf
vendored
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
[client]
|
||||
# Default is Latin1, if you need UTF-8 set this (also in server section)
|
||||
#character-set-server = utf8
|
||||
#default-character-set = utf8
|
||||
|
||||
[mysqld]
|
||||
#
|
||||
|
|
|
|||
23
debian/dist/Debian/rules
vendored
23
debian/dist/Debian/rules
vendored
|
|
@ -70,30 +70,11 @@ endif
|
|||
CXX=$${MYSQL_BUILD_CXX:-g++} \
|
||||
CXXFLAGS=$${MYSQL_BUILD_CXXFLAGS:-"-O2 -fno-omit-frame-pointer -g -pipe -Wall -Wno-uninitialized"} \
|
||||
cmake .. \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DINSTALL_SBINDIR=sbin \
|
||||
-DMYSQL_DATADIR=/var/lib/mysql \
|
||||
-DINSTALL_INCLUDEDIR=include/mysql \
|
||||
-DINSTALL_INFODIR=share/info \
|
||||
-DINSTALL_MANDIR=share/man \
|
||||
\
|
||||
-DMYSQL_SERVER_SUFFIX="-$(DEBVERSION)" \
|
||||
-DBUILD_CONFIG=mysql_release \
|
||||
-DCOMPILATION_COMMENT="mariadb.org binary distribution" \
|
||||
-DSYSTEM_TYPE="debian-linux-gnu" \
|
||||
-DINSTALL_LAYOUT=DEB \
|
||||
\
|
||||
-DENABLED_LOCAL_INFILE=1 \
|
||||
-DWITH_FAST_MUTEXES=1 \
|
||||
\
|
||||
-DMYSQL_UNIX_ADDR=/var/run/mysqld/mysqld.sock \
|
||||
\
|
||||
-DEXTRA_CHARSETS=all \
|
||||
-DWITH_LIBWRAP=1 \
|
||||
-DWITH_SSL=system \
|
||||
-DWITH_ZLIB=system \
|
||||
-DWITH_EMBEDDED_SERVER=1 \
|
||||
-DHAVE_EMBEDDED_PRIVILEGE_CONTROL=ON \
|
||||
-DWITH_MAX=1'
|
||||
-DDEB=debian'
|
||||
|
||||
touch $@
|
||||
|
||||
|
|
|
|||
23
debian/dist/Ubuntu/rules
vendored
23
debian/dist/Ubuntu/rules
vendored
|
|
@ -70,30 +70,11 @@ endif
|
|||
CXX=$${MYSQL_BUILD_CXX:-g++} \
|
||||
CXXFLAGS=$${MYSQL_BUILD_CXXFLAGS:-"-O2 -fno-omit-frame-pointer -g -pipe -Wall -Wno-uninitialized"} \
|
||||
cmake .. \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DINSTALL_SBINDIR=sbin \
|
||||
-DMYSQL_DATADIR=/var/lib/mysql \
|
||||
-DINSTALL_INCLUDEDIR=include/mysql \
|
||||
-DINSTALL_INFODIR=share/info \
|
||||
-DINSTALL_MANDIR=share/man \
|
||||
\
|
||||
-DMYSQL_SERVER_SUFFIX="-$(DEBVERSION)" \
|
||||
-DBUILD_CONFIG=mysql_release \
|
||||
-DCOMPILATION_COMMENT="mariadb.org binary distribution" \
|
||||
-DSYSTEM_TYPE="debian-linux-gnu" \
|
||||
-DINSTALL_LAYOUT=DEB \
|
||||
\
|
||||
-DENABLED_LOCAL_INFILE=1 \
|
||||
-DWITH_FAST_MUTEXES=1 \
|
||||
\
|
||||
-DMYSQL_UNIX_ADDR=/var/run/mysqld/mysqld.sock \
|
||||
\
|
||||
-DEXTRA_CHARSETS=all \
|
||||
-DWITH_LIBWRAP=1 \
|
||||
-DWITH_SSL=system \
|
||||
-DWITH_ZLIB=system \
|
||||
-DWITH_EMBEDDED_SERVER=1 \
|
||||
-DHAVE_EMBEDDED_PRIVILEGE_CONTROL=ON \
|
||||
-DWITH_MAX=1'
|
||||
-DDEB=ubuntu'
|
||||
|
||||
touch $@
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
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
|
||||
|
|
@ -10,8 +10,8 @@
|
|||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||
along with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
|
||||
|
||||
/*
|
||||
* Vio Lite.
|
||||
|
|
|
|||
|
|
@ -1518,7 +1518,7 @@ sub command_line_setup {
|
|||
|
||||
# We make the path absolute, as the server will do a chdir() before usage
|
||||
unless ( $opt_vardir =~ m,^/, or
|
||||
(IS_WINDOWS and $opt_vardir =~ m,^[a-z]:/,i) )
|
||||
(IS_WINDOWS and $opt_vardir =~ m,^[a-z]:[/\\],i) )
|
||||
{
|
||||
# Make absolute path, relative test dir
|
||||
$opt_vardir= "$glob_mysql_test_dir/$opt_vardir";
|
||||
|
|
@ -2717,6 +2717,7 @@ sub setup_vardir() {
|
|||
# hm, what paths work for debs and for rpms ?
|
||||
for (<$bindir/lib64/mysql/plugin/*.so>,
|
||||
<$bindir/lib/mysql/plugin/*.so>,
|
||||
<$bindir/lib/plugin/*.so>, # bintar
|
||||
<$bindir/lib/plugin/*.dll>)
|
||||
{
|
||||
my $pname=basename($_);
|
||||
|
|
@ -3463,12 +3464,6 @@ sub mysql_install_db {
|
|||
mtr_add_arg($args, "--lc-messages-dir=%s", $install_lang);
|
||||
mtr_add_arg($args, "--character-sets-dir=%s", $install_chsdir);
|
||||
|
||||
# On some old linux kernels, aio on tmpfs is not supported
|
||||
# Remove this if/when Bug #58421 fixes this in the server
|
||||
if ($^O eq "linux" && $opt_mem) {
|
||||
mtr_add_arg($args, "--loose-skip-innodb-use-native-aio");
|
||||
}
|
||||
|
||||
# InnoDB arguments that affect file location and sizes may
|
||||
# need to be given to the bootstrap process as well as the
|
||||
# server process.
|
||||
|
|
@ -4742,6 +4737,7 @@ sub extract_warning_lines ($$) {
|
|||
qr|Access denied for user|,
|
||||
qr|Aborted connection|,
|
||||
qr|table.*is full|,
|
||||
qr|Linux Native AIO|, # warning that aio does not work on /dev/shm
|
||||
);
|
||||
|
||||
my $matched_lines= [];
|
||||
|
|
@ -5245,13 +5241,6 @@ sub mysqld_arguments ($$$) {
|
|||
mtr_add_arg($args, "--user=root");
|
||||
}
|
||||
|
||||
# On some old linux kernels, aio on tmpfs is not supported
|
||||
# Remove this if/when Bug #58421 fixes this in the server
|
||||
if ($^O eq "linux" && $opt_mem)
|
||||
{
|
||||
mtr_add_arg($args, "--loose-skip-innodb-use-native-aio");
|
||||
}
|
||||
|
||||
if (!using_extern() and !$opt_user_args)
|
||||
{
|
||||
# Turn on logging to file
|
||||
|
|
@ -5292,6 +5281,7 @@ sub mysqld_arguments ($$$) {
|
|||
}
|
||||
elsif ($plugin = mtr_match_prefix($arg, "--plugin-load="))
|
||||
{
|
||||
next if $plugin =~ /=$/;
|
||||
push @plugins, $plugin unless $seen{$plugin};
|
||||
$seen{$plugin} = 1;
|
||||
}
|
||||
|
|
|
|||
56
mysql-test/r/bug12427262.result
Normal file
56
mysql-test/r/bug12427262.result
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#
|
||||
# Bug#12427262 : 60961: SHOW TABLES VERY SLOW WHEN NOT IN SYSTEM DISK CACHE.
|
||||
#
|
||||
create database show_table_lw_db;
|
||||
use show_table_lw_db;
|
||||
create table t1 (c1 int);
|
||||
create table t2 (c1 int);
|
||||
create table t3 (c1 int);
|
||||
create table t4 (c1 int);
|
||||
create table t5 (c1 int);
|
||||
create table t6 (c1 int);
|
||||
create table t7 (c1 int);
|
||||
create table t8 (c1 int);
|
||||
create table t9 (c1 int);
|
||||
create table t10 (c1 int);
|
||||
select Sum(ALL(COUNT_READ)) from performance_schema.file_summary_by_instance where FILE_NAME
|
||||
like "%show_table_lw_db%" AND FILE_NAME like "%.frm%" AND EVENT_NAME='wait/io/file/sql/FRM'
|
||||
into @count_read_before;
|
||||
show tables;
|
||||
Tables_in_show_table_lw_db
|
||||
t1
|
||||
t10
|
||||
t2
|
||||
t3
|
||||
t4
|
||||
t5
|
||||
t6
|
||||
t7
|
||||
t8
|
||||
t9
|
||||
select Sum(ALL(COUNT_READ)) from performance_schema.file_summary_by_instance where FILE_NAME
|
||||
like "%show_table_lw_db%" AND FILE_NAME like "%.frm%" AND EVENT_NAME='wait/io/file/sql/FRM'
|
||||
into @count_read_after;
|
||||
select @count_read_after-@count_read_before;
|
||||
@count_read_after-@count_read_before
|
||||
0.000000000000000000000000000000
|
||||
show full tables;
|
||||
Tables_in_show_table_lw_db Table_type
|
||||
t1 BASE TABLE
|
||||
t10 BASE TABLE
|
||||
t2 BASE TABLE
|
||||
t3 BASE TABLE
|
||||
t4 BASE TABLE
|
||||
t5 BASE TABLE
|
||||
t6 BASE TABLE
|
||||
t7 BASE TABLE
|
||||
t8 BASE TABLE
|
||||
t9 BASE TABLE
|
||||
select Sum(ALL(COUNT_READ)) from performance_schema.file_summary_by_instance where FILE_NAME
|
||||
like "%show_table_lw_db%" AND FILE_NAME like "%.frm%" AND EVENT_NAME='wait/io/file/sql/FRM'
|
||||
into @count_read_after;
|
||||
select @count_read_after-@count_read_before;
|
||||
@count_read_after-@count_read_before
|
||||
10.000000000000000000000000000000
|
||||
drop table t1;
|
||||
drop database show_table_lw_db;
|
||||
|
|
@ -204,4 +204,30 @@ SELECT BIT_XOR(t1.b) FROM t1 JOIN t2 ON t1.c=t2.c WHERE t1.pk=1;
|
|||
BIT_XOR(t1.b)
|
||||
0
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# Bug#12713907: STRANGE OPTIMIZE & WRONG RESULT UNDER ORDER BY
|
||||
# COUNT(*) LIMIT.
|
||||
#
|
||||
CREATE TABLE t1 (
|
||||
id BIGINT(20) ,
|
||||
member_id_to INT(11) ,
|
||||
r_date DATE ,
|
||||
PRIMARY KEY (id,r_date),
|
||||
KEY r_date_idx (r_date),
|
||||
KEY t1_idx01 (member_id_to)
|
||||
) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES
|
||||
(107924526,518491,'2011-05-01'),
|
||||
(107924527,518491,'2011-05-01'),
|
||||
(107924534,518491,'2011-06-21'),
|
||||
(107924535,518491,'2011-06-21'),
|
||||
(107924542,1601319,'2011-06-21'),
|
||||
(107924543,1601319,'2011-06-21'),
|
||||
(107924544,1601319,'2011-06-21'),
|
||||
(107924545,1601319,'2011-06-21');
|
||||
SELECT member_id_to, COUNT(*) FROM t1 WHERE r_date =
|
||||
'2011-06-21' GROUP BY member_id_to ORDER BY 2 LIMIT 1;
|
||||
member_id_to COUNT(*)
|
||||
518491 2
|
||||
DROP TABLE t1;
|
||||
End of 5.5 tests
|
||||
|
|
|
|||
7
mysql-test/r/mdev316.result
Normal file
7
mysql-test/r/mdev316.result
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
set names swe7;
|
||||
select '' in ('',convert(0,time));
|
||||
'' in ('',convert(0,time))
|
||||
1
|
||||
select case '' when '' then 1 when convert(0,time) then 2 end;
|
||||
case '' when '' then 1 when convert(0,time) then 2 end
|
||||
1
|
||||
|
|
@ -5222,3 +5222,48 @@ DROP DATABASE b12809202_db;
|
|||
# Delete all existing binary logs.
|
||||
#
|
||||
RESET MASTER;
|
||||
#
|
||||
# Bug#45740 MYSQLDUMP DOESN'T DUMP GENERAL_LOG AND SLOW_QUERY CAUSES RESTORE PROBLEM
|
||||
#
|
||||
SET @old_log_output_state= @@global.log_output;
|
||||
SET @old_general_log_state= @@global.general_log;
|
||||
SET @old_slow_query_log_state= @@global.slow_query_log;
|
||||
call mtr.add_suppression("Failed to write to mysql.general_log");
|
||||
SET @@global.log_output="TABLE";
|
||||
SET @@global.general_log='OFF';
|
||||
SET @@global.slow_query_log='OFF';
|
||||
DROP DATABASE mysql;
|
||||
Warnings:
|
||||
Error 1146 Table 'mysql.proc' doesn't exist
|
||||
Error 1146 Table 'mysql.event' doesn't exist
|
||||
SHOW CREATE TABLE mysql.general_log;
|
||||
Table Create Table
|
||||
general_log CREATE TABLE `general_log` (
|
||||
`event_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`user_host` mediumtext NOT NULL,
|
||||
`thread_id` int(11) NOT NULL,
|
||||
`server_id` int(10) unsigned NOT NULL,
|
||||
`command_type` varchar(64) NOT NULL,
|
||||
`argument` mediumtext NOT NULL
|
||||
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='General log'
|
||||
SHOW CREATE TABLE mysql.slow_log;
|
||||
Table Create Table
|
||||
slow_log CREATE TABLE `slow_log` (
|
||||
`start_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
`user_host` mediumtext NOT NULL,
|
||||
`query_time` time(6) NOT NULL,
|
||||
`lock_time` time(6) NOT NULL,
|
||||
`rows_sent` int(11) NOT NULL,
|
||||
`rows_examined` int(11) NOT NULL,
|
||||
`db` varchar(512) NOT NULL,
|
||||
`last_insert_id` int(11) NOT NULL,
|
||||
`insert_id` int(11) NOT NULL,
|
||||
`server_id` int(10) unsigned NOT NULL,
|
||||
`sql_text` mediumtext NOT NULL
|
||||
) ENGINE=CSV DEFAULT CHARSET=utf8 COMMENT='Slow log'
|
||||
SET @@global.log_output= @old_log_output_state;
|
||||
SET @@global.slow_query_log= @old_slow_query_log_state;
|
||||
SET @@global.general_log= @old_general_log_state;
|
||||
#
|
||||
# End of 5.1 tests
|
||||
#
|
||||
|
|
|
|||
|
|
@ -22,3 +22,7 @@ ERROR 42000: Access denied; you need (at least one of) the SUPER privilege(s) fo
|
|||
**** Clean up ****
|
||||
set global binlog_format = @saved_binlog_format;
|
||||
drop user mysqltest_1@localhost;
|
||||
GRANT REPLICATION CLIENT ON *.* TO 'mysqltest_1'@'localhost';
|
||||
SHOW MASTER LOGS;
|
||||
SHOW BINARY LOGS;
|
||||
DROP USER 'mysqltest_1'@'localhost';
|
||||
|
|
|
|||
|
|
@ -54,3 +54,22 @@ disconnect root;
|
|||
connection default;
|
||||
set global binlog_format = @saved_binlog_format;
|
||||
drop user mysqltest_1@localhost;
|
||||
|
||||
|
||||
# Testing if REPLICATION CLIENT privilege is enough to execute
|
||||
# SHOW MASTER LOGS and SHOW BINARY.
|
||||
GRANT REPLICATION CLIENT ON *.* TO 'mysqltest_1'@'localhost';
|
||||
--connect(rpl,localhost,mysqltest_1,,)
|
||||
|
||||
--connection rpl
|
||||
# We are only interested if the following commands succeed and not on
|
||||
# their output.
|
||||
--disable_result_log
|
||||
SHOW MASTER LOGS;
|
||||
SHOW BINARY LOGS;
|
||||
--enable_result_log
|
||||
|
||||
# clean up
|
||||
--disconnect rpl
|
||||
connection default;
|
||||
DROP USER 'mysqltest_1'@'localhost';
|
||||
|
|
|
|||
6
mysql-test/suite/innodb/r/innodb_bug12902967.result
Normal file
6
mysql-test/suite/innodb/r/innodb_bug12902967.result
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
create table t1 (f1 integer primary key) engine innodb;
|
||||
alter table t1 add constraint c1 foreign key (f1) references t1(f1);
|
||||
ERROR HY000: Error on rename of '#sql-temporary' to './test/t1' (errno: 150)
|
||||
InnoDB: which are not compatible with the new table definition.
|
||||
InnoDB: has or is referenced in foreign key constraints
|
||||
drop table t1;
|
||||
56
mysql-test/suite/innodb/r/innodb_bug14007649.result
Normal file
56
mysql-test/suite/innodb/r/innodb_bug14007649.result
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
create table t1 (
|
||||
rowid int,
|
||||
f1 int,
|
||||
f2 int,
|
||||
key i1 (f1, f2),
|
||||
key i2 (f2)) engine=innodb;
|
||||
show create table t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`rowid` int(11) DEFAULT NULL,
|
||||
`f1` int(11) DEFAULT NULL,
|
||||
`f2` int(11) DEFAULT NULL,
|
||||
KEY `i1` (`f1`,`f2`),
|
||||
KEY `i2` (`f2`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
insert into `t1` (rowid, f1, f2) values (1, 1, 10), (2, 1, NULL);
|
||||
start transaction with consistent snapshot;
|
||||
start transaction;
|
||||
update t1 set f2 = 4 where f1 = 1 and f2 is null;
|
||||
(b) Number of rows updated:
|
||||
select row_count();
|
||||
row_count()
|
||||
1
|
||||
insert into t1 values (3, 1, null);
|
||||
(b) After update and insert query.
|
||||
select rowid, f1, f2 from t1;
|
||||
rowid f1 f2
|
||||
1 1 10
|
||||
2 1 4
|
||||
3 1 NULL
|
||||
commit;
|
||||
(a) Before the update statement is executed.
|
||||
select rowid, f1, f2 from t1;
|
||||
rowid f1 f2
|
||||
1 1 10
|
||||
2 1 NULL
|
||||
SET SESSION debug_dbug="+d,bug14007649";
|
||||
update t1 set f2 = 6 where f1 = 1 and f2 is null;
|
||||
(a) Number of rows updated:
|
||||
select row_count();
|
||||
row_count()
|
||||
1
|
||||
(a) After the update statement is executed.
|
||||
select rowid, f1, f2 from t1;
|
||||
rowid f1 f2
|
||||
1 1 10
|
||||
2 1 NULL
|
||||
3 1 6
|
||||
commit;
|
||||
"The trx with consistent snapshot ended."
|
||||
select rowid, f1, f2 from t1;
|
||||
rowid f1 f2
|
||||
1 1 10
|
||||
2 1 4
|
||||
3 1 6
|
||||
drop table t1;
|
||||
|
|
@ -4,11 +4,6 @@
|
|||
|
||||
--source include/have_innodb.inc
|
||||
|
||||
if (`select plugin_auth_version <= "1.1.8-24.1" from information_schema.plugins where plugin_name='innodb'`)
|
||||
{
|
||||
--skip Not fixed in XtraDB 1.1.8-24.1 or earlier
|
||||
}
|
||||
|
||||
# DEBUG_SYNC must be compiled in.
|
||||
--source include/have_debug_sync.inc
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,5 @@
|
|||
-- source include/have_innodb.inc
|
||||
|
||||
if (`select plugin_auth_version <= "1.0.17-13.0" from information_schema.plugins where plugin_name='innodb'`)
|
||||
{
|
||||
--skip Not fixed in XtraDB 1.0.17-13.0 or earlier
|
||||
}
|
||||
|
||||
let $MYSQLD_DATADIR= `select @@datadir`;
|
||||
|
||||
let $per_table=`select @@innodb_file_per_table`;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,5 @@
|
|||
--source include/have_innodb.inc
|
||||
|
||||
if (`select plugin_auth_version <= "1.0.17-13.0" from information_schema.plugins where plugin_name='innodb'`)
|
||||
{
|
||||
--skip Not fixed in XtraDB 1.0.17-13.0 or earlier
|
||||
}
|
||||
|
||||
#
|
||||
# Check and select innodb lock type
|
||||
#
|
||||
|
|
|
|||
42
mysql-test/suite/innodb/t/innodb_bug12902967.test
Normal file
42
mysql-test/suite/innodb/t/innodb_bug12902967.test
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Bug 12902967: Creating self referencing fk on same index unhandled,
|
||||
# confusing error
|
||||
#
|
||||
# Creating a self referencing foreign key on the same
|
||||
# column/index is an unhandled exception, it should throw a sensible
|
||||
# error but instead implies that your data dictionary may now be out
|
||||
# of sync:
|
||||
|
||||
--source include/have_innodb.inc
|
||||
--source include/not_embedded.inc
|
||||
|
||||
let error_log= $MYSQLTEST_VARDIR/log/mysqld.1.err;
|
||||
--source include/restart_mysqld.inc
|
||||
|
||||
create table t1 (f1 integer primary key) engine innodb;
|
||||
|
||||
# The below statement should produce error message in error log.
|
||||
# This error message should mention problem with foreign keys
|
||||
# rather than with data dictionary.
|
||||
--replace_regex /'\.\/test\/#sql-[0-9a-f_]*'/'#sql-temporary'/
|
||||
--error ER_ERROR_ON_RENAME
|
||||
alter table t1 add constraint c1 foreign key (f1) references t1(f1);
|
||||
--source include/restart_mysqld.inc
|
||||
perl;
|
||||
|
||||
$file = "$ENV{'error_log'}";
|
||||
open ( FILE, $file) || die "can't open file! ($file)\n";
|
||||
@lines = <FILE>;
|
||||
close (FILE);
|
||||
$count = 0;
|
||||
foreach $line (reverse @lines) {
|
||||
if ($line =~ "^InnoDB:") {
|
||||
++$count;
|
||||
print "$line";
|
||||
if ($count == 2) {
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
|
||||
drop table t1;
|
||||
|
|
@ -2,11 +2,6 @@
|
|||
--source include/have_debug_sync.inc
|
||||
--source include/not_embedded.inc
|
||||
|
||||
if (`select plugin_auth_version <= "1.1.8-24.1" from information_schema.plugins where plugin_name='innodb'`)
|
||||
{
|
||||
--skip Not fixed in XtraDB 1.1.8-24.1 or earlier
|
||||
}
|
||||
|
||||
SET DEBUG_SYNC='reset';
|
||||
|
||||
# Save the initial number of concurrent sessions
|
||||
|
|
|
|||
63
mysql-test/suite/innodb/t/innodb_bug14007649.test
Normal file
63
mysql-test/suite/innodb/t/innodb_bug14007649.test
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
--source include/have_innodb.inc
|
||||
--source include/have_debug.inc
|
||||
|
||||
if (`select plugin_auth_version <= "1.1.8-26.0" from information_schema.plugins where plugin_name='innodb'`)
|
||||
{
|
||||
--skip Not fixed in XtraDB 1.1.8-26.0 or earlier
|
||||
}
|
||||
|
||||
create table t1 (
|
||||
rowid int,
|
||||
f1 int,
|
||||
f2 int,
|
||||
key i1 (f1, f2),
|
||||
key i2 (f2)) engine=innodb;
|
||||
|
||||
show create table t1;
|
||||
insert into `t1` (rowid, f1, f2) values (1, 1, 10), (2, 1, NULL);
|
||||
|
||||
connect (a,localhost,root,,);
|
||||
connect (b,localhost,root,,);
|
||||
|
||||
connection a;
|
||||
start transaction with consistent snapshot;
|
||||
|
||||
connection b;
|
||||
start transaction;
|
||||
update t1 set f2 = 4 where f1 = 1 and f2 is null;
|
||||
|
||||
-- echo (b) Number of rows updated:
|
||||
select row_count();
|
||||
|
||||
insert into t1 values (3, 1, null);
|
||||
|
||||
-- echo (b) After update and insert query.
|
||||
select rowid, f1, f2 from t1;
|
||||
|
||||
commit;
|
||||
|
||||
connection a;
|
||||
|
||||
-- echo (a) Before the update statement is executed.
|
||||
select rowid, f1, f2 from t1;
|
||||
|
||||
SET SESSION debug_dbug="+d,bug14007649";
|
||||
update t1 set f2 = 6 where f1 = 1 and f2 is null;
|
||||
|
||||
-- echo (a) Number of rows updated:
|
||||
select row_count();
|
||||
|
||||
-- echo (a) After the update statement is executed.
|
||||
select rowid, f1, f2 from t1;
|
||||
|
||||
commit;
|
||||
|
||||
--echo "The trx with consistent snapshot ended."
|
||||
|
||||
select rowid, f1, f2 from t1;
|
||||
|
||||
connection default;
|
||||
disconnect a;
|
||||
disconnect b;
|
||||
|
||||
drop table t1;
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
percona_sync_flush: removed from XtraDB-26.0
|
||||
|
||||
percona_suppress_log_warning_1592: Feature not merged into MariaDB
|
||||
percona_log_slow_slave_statements: Feature not merged into MariaDB
|
||||
percona_log_slow_slave_statements-and-use_global_long_query_time: Feature not merged into MariaDB
|
||||
|
|
|
|||
41
mysql-test/suite/rpl/r/rpl_auto_increment_bug45679.result
Normal file
41
mysql-test/suite/rpl/r/rpl_auto_increment_bug45679.result
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
include/master-slave.inc
|
||||
[connection master]
|
||||
call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.');
|
||||
create table tm (b int auto_increment, a int, primary key (a,b)) engine= myisam;
|
||||
create table ti (b int auto_increment, a int, primary key (a,b)) engine= innodb;
|
||||
ERROR 42000: Incorrect table definition; there can be only one auto column and it must be defined as a key
|
||||
create table ti (b int auto_increment, a int, primary key (b,a)) engine= innodb;
|
||||
set @@binlog_format=statement;
|
||||
*** autoincrement field is not the first in PK warning must be there: ***
|
||||
insert into tm set b=null, a=1;
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT into autoincrement field which is not the first part in the composed primary key is unsafe.
|
||||
show warnings;
|
||||
Level Code Message
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT into autoincrement field which is not the first part in the composed primary key is unsafe.
|
||||
*** no warning when autoincrement is the first in PK
|
||||
insert into ti set b=null, a=1;
|
||||
show warnings;
|
||||
Level Code Message
|
||||
create function multi_part_pk_with_autoinc (arg int)
|
||||
returns int
|
||||
begin
|
||||
insert into tm set b=null, a=arg;
|
||||
return arg;
|
||||
end//
|
||||
select multi_part_pk_with_autoinc (3);
|
||||
multi_part_pk_with_autoinc (3)
|
||||
3
|
||||
Warnings:
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it invokes a trigger or a stored function that inserts into an AUTO_INCREMENT column. Inserted values cannot be logged correctly.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT into autoincrement field which is not the first part in the composed primary key is unsafe.
|
||||
*** autoincrement field is not the first in PK warning must be there: ***
|
||||
show warnings;
|
||||
Level Code Message
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. Statement is unsafe because it invokes a trigger or a stored function that inserts into an AUTO_INCREMENT column. Inserted values cannot be logged correctly.
|
||||
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT into autoincrement field which is not the first part in the composed primary key is unsafe.
|
||||
set @@binlog_format=mixed;
|
||||
insert into tm set b=null, a=2;
|
||||
drop table tm, ti;
|
||||
drop function multi_part_pk_with_autoinc;
|
||||
include/rpl_end.inc
|
||||
|
|
@ -114,4 +114,23 @@ id c
|
|||
3 3
|
||||
[on master]
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
CREATE TABLE test.t5 (a INT AUTO_INCREMENT PRIMARY KEY, b INT, c INT);
|
||||
CREATE TABLE test.t1 (a INT);
|
||||
INSERT INTO test.t1 VALUES(1);
|
||||
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
|
||||
CREATE TABLE test.t_slave (a INT AUTO_INCREMENT PRIMARY KEY, b INT, c INT);
|
||||
CREATE TRIGGER t1_update AFTER UPDATE ON test.t1 FOR EACH ROW
|
||||
INSERT INTO test.t_slave VALUES(NULL, ROUND(RAND() * 1000), @c);
|
||||
SET INSERT_ID=2;
|
||||
SET @c=2;
|
||||
SET @@rand_seed1=10000000, @@rand_seed2=1000000;
|
||||
INSERT INTO t5 VALUES (NULL, ROUND(RAND() * 1000), @c);
|
||||
SELECT b into @b FROM test.t5;
|
||||
UPDATE test.t1 SET a=2;
|
||||
SELECT a AS 'ONE' into @a FROM test.t_slave;
|
||||
SELECT c AS 'NULL' into @c FROM test.t_slave;
|
||||
SELECT b into @b FROM test.t_slave;
|
||||
drop table test.t5;
|
||||
drop table test.t1;
|
||||
drop table test.t_slave;
|
||||
include/rpl_end.inc
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
include/master-slave.inc
|
||||
[connection master]
|
||||
[connection slave]
|
||||
SET DEBUG_SYNC= 'after_show_binlog_events SIGNAL on_show_binlog_events WAIT_FOR end';
|
||||
SHOW BINLOG EVENTS;
|
||||
[connection slave1]
|
||||
SET DEBUG_SYNC= 'now WAIT_FOR on_show_binlog_events';
|
||||
FLUSH LOGS;
|
||||
SET DEBUG_SYNC= 'now SIGNAL end';
|
||||
SET DEBUG_SYNC= 'RESET';
|
||||
[connection slave]
|
||||
SET DEBUG_SYNC= 'RESET';
|
||||
include/rpl_end.inc
|
||||
|
|
@ -3,8 +3,8 @@ include/master-slave.inc
|
|||
include/rpl_restart_server.inc [server_number=2 parameters: --report-port=9000]
|
||||
include/start_slave.inc
|
||||
[Slave restarted with the report-port set to some value]
|
||||
include/assert.inc [The value shown for the slave's port number is 9000 which is the value set for report-port.]
|
||||
include/rpl_restart_server.inc [server_number=2 parameters: --report-port=]
|
||||
include/assert.inc [The value shown for the slave's port number is user specified port number which is the value set for report-port.]
|
||||
include/rpl_restart_server.inc [server_number=2]
|
||||
include/start_slave.inc
|
||||
[Slave restarted with the report-port set to the value of slave's port number]
|
||||
include/assert.inc [The default value shown for the slave's port number is the actual port number of the slave.]
|
||||
|
|
|
|||
62
mysql-test/suite/rpl/t/rpl_auto_increment_bug45679.test
Normal file
62
mysql-test/suite/rpl/t/rpl_auto_increment_bug45679.test
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# Test of auto-increment.
|
||||
#
|
||||
# BUG#11754117-45670
|
||||
# Multipart primary key with the autoincrement part not first in it
|
||||
# is replication unsafe.
|
||||
#
|
||||
|
||||
source include/master-slave.inc;
|
||||
source include/have_binlog_format_mixed.inc;
|
||||
source include/have_innodb.inc;
|
||||
|
||||
call mtr.add_suppression('Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.');
|
||||
|
||||
--connection master
|
||||
create table tm (b int auto_increment, a int, primary key (a,b)) engine= myisam;
|
||||
--error ER_WRONG_AUTO_KEY
|
||||
create table ti (b int auto_increment, a int, primary key (a,b)) engine= innodb;
|
||||
create table ti (b int auto_increment, a int, primary key (b,a)) engine= innodb;
|
||||
|
||||
set @@binlog_format=statement;
|
||||
--echo *** autoincrement field is not the first in PK warning must be there: ***
|
||||
insert into tm set b=null, a=1;
|
||||
show warnings;
|
||||
--echo *** no warning when autoincrement is the first in PK
|
||||
insert into ti set b=null, a=1;
|
||||
show warnings;
|
||||
|
||||
delimiter //;
|
||||
create function multi_part_pk_with_autoinc (arg int)
|
||||
returns int
|
||||
begin
|
||||
insert into tm set b=null, a=arg;
|
||||
return arg;
|
||||
end//
|
||||
delimiter ;//
|
||||
|
||||
select multi_part_pk_with_autoinc (3);
|
||||
--echo *** autoincrement field is not the first in PK warning must be there: ***
|
||||
show warnings;
|
||||
|
||||
set @@binlog_format=mixed;
|
||||
insert into tm set b=null, a=2;
|
||||
|
||||
sync_slave_with_master;
|
||||
|
||||
if (`select count(*) <> 3 from tm`)
|
||||
{
|
||||
--echo Wrong result from SELECT on the slave side.
|
||||
select * from tm;
|
||||
--die
|
||||
}
|
||||
|
||||
# cleanup
|
||||
|
||||
--connection master
|
||||
|
||||
drop table tm, ti;
|
||||
drop function multi_part_pk_with_autoinc;
|
||||
|
||||
sync_slave_with_master;
|
||||
|
||||
--source include/rpl_end.inc
|
||||
|
|
@ -206,4 +206,64 @@ SELECT * FROM t3;
|
|||
connection master;
|
||||
echo [on master];
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
|
||||
--sync_slave_with_master
|
||||
|
||||
#
|
||||
# BUG#11754117 - 45670: INTVAR_EVENTS FOR FILTERED-OUT QUERY_LOG_EVENTS ARE EXECUTED
|
||||
# Int-, Rand- and User- var events accompaning a filtered out Query-log-event should
|
||||
# be filtered as well.
|
||||
#
|
||||
connection master;
|
||||
CREATE TABLE test.t5 (a INT AUTO_INCREMENT PRIMARY KEY, b INT, c INT); # ignored on slave
|
||||
CREATE TABLE test.t1 (a INT); # accepted on slave
|
||||
INSERT INTO test.t1 VALUES(1);
|
||||
|
||||
--sync_slave_with_master
|
||||
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
|
||||
CREATE TABLE test.t_slave (a INT AUTO_INCREMENT PRIMARY KEY, b INT, c INT);
|
||||
CREATE TRIGGER t1_update AFTER UPDATE ON test.t1 FOR EACH ROW
|
||||
INSERT INTO test.t_slave VALUES(NULL, ROUND(RAND() * 1000), @c);
|
||||
|
||||
connection master;
|
||||
SET INSERT_ID=2;
|
||||
SET @c=2;
|
||||
SET @@rand_seed1=10000000, @@rand_seed2=1000000;
|
||||
INSERT INTO t5 VALUES (NULL, ROUND(RAND() * 1000), @c); # to be ignored
|
||||
SELECT b into @b FROM test.t5;
|
||||
--let $b_master=`select @b`
|
||||
UPDATE test.t1 SET a=2; # to run trigger on slave
|
||||
|
||||
--sync_slave_with_master
|
||||
|
||||
# The proof:
|
||||
SELECT a AS 'ONE' into @a FROM test.t_slave;
|
||||
SELECT c AS 'NULL' into @c FROM test.t_slave;
|
||||
|
||||
let $count= 1;
|
||||
let $table= test.t_slave;
|
||||
source include/wait_until_rows_count.inc;
|
||||
|
||||
if (`SELECT @a != 2 and @c != NULL`)
|
||||
{
|
||||
SELECT * FROM test.t_slave;
|
||||
--die Intvar or user var from replication events unexpetedly escaped out to screw a following query applying context.
|
||||
}
|
||||
|
||||
SELECT b into @b FROM test.t_slave;
|
||||
--let $b_slave=`select @b`
|
||||
|
||||
if (`SELECT $b_slave = $b_master`)
|
||||
{
|
||||
--echo Might be pure coincidence of two randoms from master and slave table. Don not panic yet.
|
||||
}
|
||||
|
||||
# cleanup BUG#11754117
|
||||
connection master;
|
||||
drop table test.t5;
|
||||
drop table test.t1;
|
||||
|
||||
--sync_slave_with_master
|
||||
drop table test.t_slave;
|
||||
|
||||
--source include/rpl_end.inc
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
# BUG#13979418: SHOW BINLOG EVENTS MAY CRASH THE SERVER
|
||||
#
|
||||
# The function mysql_show_binlog_events has a local stack variable
|
||||
# 'LOG_INFO linfo;', which is assigned to thd->current_linfo, however
|
||||
# this variable goes out of scope and is destroyed before clean
|
||||
# thd->current_linfo.
|
||||
#
|
||||
# This test case runs SHOW BINLOG EVENTS and FLUSH LOGS to make sure
|
||||
# that with the fix local variable linfo is valid along all
|
||||
# mysql_show_binlog_events function scope.
|
||||
#
|
||||
--source include/have_debug_sync.inc
|
||||
--source include/master-slave.inc
|
||||
|
||||
--echo [connection slave]
|
||||
--connection slave
|
||||
SET DEBUG_SYNC= 'after_show_binlog_events SIGNAL on_show_binlog_events WAIT_FOR end';
|
||||
--send SHOW BINLOG EVENTS
|
||||
|
||||
--connection slave1
|
||||
--echo [connection slave1]
|
||||
SET DEBUG_SYNC= 'now WAIT_FOR on_show_binlog_events';
|
||||
FLUSH LOGS;
|
||||
SET DEBUG_SYNC= 'now SIGNAL end';
|
||||
SET DEBUG_SYNC= 'RESET';
|
||||
|
||||
--echo [connection slave]
|
||||
--connection slave
|
||||
--disable_result_log
|
||||
--reap
|
||||
--enable_result_log
|
||||
SET DEBUG_SYNC= 'RESET';
|
||||
|
||||
--connection master
|
||||
--source include/rpl_end.inc
|
||||
|
|
@ -38,21 +38,23 @@ connection master;
|
|||
|
||||
# 9000 is the value of the port we should get.
|
||||
--let $report_port= query_get_value(SHOW SLAVE HOSTS, Port, 1)
|
||||
--let assert_text= The value shown for the slave's port number is 9000 which is the value set for report-port.
|
||||
--let assert_text= The value shown for the slave's port number is user specified port number which is the value set for report-port.
|
||||
--let assert_cond= $report_port = "9000"
|
||||
--source include/assert.inc
|
||||
|
||||
|
||||
# Start the server with the report-port being passed with no value. So on SHOW SLAVE HOSTS
|
||||
# on the master the value of slave's port should be the actual value of the slave port.
|
||||
connection master;
|
||||
|
||||
--let $rpl_server_number= 2
|
||||
--let $rpl_server_parameters= --report-port=
|
||||
--let $rpl_server_parameters=
|
||||
--source include/rpl_restart_server.inc
|
||||
|
||||
connection slave;
|
||||
--source include/start_slave.inc
|
||||
|
||||
connection master;
|
||||
sync_slave_with_master;
|
||||
--echo [Slave restarted with the report-port set to the value of slave's port number]
|
||||
|
||||
connection master;
|
||||
|
|
|
|||
|
|
@ -11,4 +11,5 @@
|
|||
##############################################################################
|
||||
|
||||
innodb_trx_rseg_n_slots_debug_basic: variable innodb_trx_rseg_n_slots_debug is removed in MariaDB
|
||||
innodb_flush_checkpoint_debug_basic: removed from XtraDB-26.0
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
--source include/have_innodb.inc
|
||||
--source include/have_debug.inc
|
||||
|
||||
if (`select plugin_auth_version <= "1.1.8-24.1" from information_schema.plugins where plugin_name='innodb'`)
|
||||
{
|
||||
--skip Not supported by XtraDB 1.1.8-24.1 or earlier
|
||||
}
|
||||
|
||||
SET @start_global_value = @@global.innodb_trx_rseg_n_slots_debug;
|
||||
SELECT @start_global_value;
|
||||
|
||||
|
|
|
|||
51
mysql-test/t/bug12427262.test
Normal file
51
mysql-test/t/bug12427262.test
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
--echo #
|
||||
--echo # Bug#12427262 : 60961: SHOW TABLES VERY SLOW WHEN NOT IN SYSTEM DISK CACHE.
|
||||
--echo #
|
||||
|
||||
--source include/not_embedded.inc
|
||||
--source include/have_perfschema.inc
|
||||
|
||||
--disable_warnings
|
||||
create database show_table_lw_db;
|
||||
use show_table_lw_db;
|
||||
create table t1 (c1 int);
|
||||
create table t2 (c1 int);
|
||||
create table t3 (c1 int);
|
||||
create table t4 (c1 int);
|
||||
create table t5 (c1 int);
|
||||
create table t6 (c1 int);
|
||||
create table t7 (c1 int);
|
||||
create table t8 (c1 int);
|
||||
create table t9 (c1 int);
|
||||
create table t10 (c1 int);
|
||||
--enable_warnings
|
||||
|
||||
# Query PS to know initial read count for frm file.
|
||||
select Sum(ALL(COUNT_READ)) from performance_schema.file_summary_by_instance where FILE_NAME
|
||||
like "%show_table_lw_db%" AND FILE_NAME like "%.frm%" AND EVENT_NAME='wait/io/file/sql/FRM'
|
||||
into @count_read_before;
|
||||
|
||||
show tables;
|
||||
|
||||
# Query PS to know read count for frm file after above query. It should
|
||||
# not be changed as FRM file will not be opened for above query.
|
||||
select Sum(ALL(COUNT_READ)) from performance_schema.file_summary_by_instance where FILE_NAME
|
||||
like "%show_table_lw_db%" AND FILE_NAME like "%.frm%" AND EVENT_NAME='wait/io/file/sql/FRM'
|
||||
into @count_read_after;
|
||||
|
||||
select @count_read_after-@count_read_before;
|
||||
|
||||
show full tables;
|
||||
|
||||
# Query PS to know read count for frm file after above query. COUNT_READ
|
||||
# will be incremented by 1 as FRM file will be opened for above query.
|
||||
select Sum(ALL(COUNT_READ)) from performance_schema.file_summary_by_instance where FILE_NAME
|
||||
like "%show_table_lw_db%" AND FILE_NAME like "%.frm%" AND EVENT_NAME='wait/io/file/sql/FRM'
|
||||
into @count_read_after;
|
||||
|
||||
select @count_read_after-@count_read_before;
|
||||
|
||||
--disable_warnings
|
||||
drop table t1;
|
||||
drop database show_table_lw_db;
|
||||
--enable_warnings
|
||||
|
|
@ -144,5 +144,33 @@ SELECT BIT_XOR(t1.b) FROM t1 JOIN t2 ON t1.c=t2.c WHERE t1.pk=1;
|
|||
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
--echo #
|
||||
--echo # Bug#12713907: STRANGE OPTIMIZE & WRONG RESULT UNDER ORDER BY
|
||||
--echo # COUNT(*) LIMIT.
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (
|
||||
id BIGINT(20) ,
|
||||
member_id_to INT(11) ,
|
||||
r_date DATE ,
|
||||
PRIMARY KEY (id,r_date),
|
||||
KEY r_date_idx (r_date),
|
||||
KEY t1_idx01 (member_id_to)
|
||||
) ENGINE=InnoDB;
|
||||
|
||||
INSERT INTO t1 VALUES
|
||||
(107924526,518491,'2011-05-01'),
|
||||
(107924527,518491,'2011-05-01'),
|
||||
(107924534,518491,'2011-06-21'),
|
||||
(107924535,518491,'2011-06-21'),
|
||||
(107924542,1601319,'2011-06-21'),
|
||||
(107924543,1601319,'2011-06-21'),
|
||||
(107924544,1601319,'2011-06-21'),
|
||||
(107924545,1601319,'2011-06-21');
|
||||
|
||||
SELECT member_id_to, COUNT(*) FROM t1 WHERE r_date =
|
||||
'2011-06-21' GROUP BY member_id_to ORDER BY 2 LIMIT 1;
|
||||
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo End of 5.5 tests
|
||||
|
|
|
|||
6
mysql-test/t/mdev316.test
Normal file
6
mysql-test/t/mdev316.test
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#
|
||||
# MDEV-316 lp:1009085 Assertion failed: warn_item, file item_cmpfunc.cc, line 3613
|
||||
#
|
||||
set names swe7;
|
||||
select '' in ('',convert(0,time));
|
||||
select case '' when '' then 1 when convert(0,time) then 2 end;
|
||||
|
|
@ -2413,3 +2413,30 @@ RESET MASTER;
|
|||
|
||||
# Wait till we reached the initial number of concurrent sessions
|
||||
--source include/wait_until_count_sessions.inc
|
||||
|
||||
--echo #
|
||||
--echo # Bug#45740 MYSQLDUMP DOESN'T DUMP GENERAL_LOG AND SLOW_QUERY CAUSES RESTORE PROBLEM
|
||||
--echo #
|
||||
SET @old_log_output_state= @@global.log_output;
|
||||
SET @old_general_log_state= @@global.general_log;
|
||||
SET @old_slow_query_log_state= @@global.slow_query_log;
|
||||
|
||||
call mtr.add_suppression("Failed to write to mysql.general_log");
|
||||
--exec $MYSQL_DUMP -uroot --all-databases > $MYSQLTEST_VARDIR/tmp/bug45740.sql
|
||||
# Make log_output as table and disabling general_log and slow_log
|
||||
SET @@global.log_output="TABLE";
|
||||
SET @@global.general_log='OFF';
|
||||
SET @@global.slow_query_log='OFF';
|
||||
DROP DATABASE mysql;
|
||||
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug45740.sql
|
||||
SHOW CREATE TABLE mysql.general_log;
|
||||
SHOW CREATE TABLE mysql.slow_log;
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/bug45740.sql
|
||||
|
||||
SET @@global.log_output= @old_log_output_state;
|
||||
SET @@global.slow_query_log= @old_slow_query_log_state;
|
||||
SET @@global.general_log= @old_general_log_state;
|
||||
|
||||
--echo #
|
||||
--echo # End of 5.1 tests
|
||||
--echo #
|
||||
|
|
|
|||
|
|
@ -4461,3 +4461,4 @@ SELECT * FROM t1, t2 WHERE a=3 AND a=b;
|
|||
drop table t1,t2;
|
||||
|
||||
--echo End of 5.3 tests
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (c) 2000, 2011, Oracle and/or its affiliates.
|
||||
Copyright (c) 2008-2011 Monty Program Ab
|
||||
Copyright (c) 2000, 2012, Oracle and/or its affiliates.
|
||||
Copyright (c) 2008, 2011, Monty Program Ab
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef FIELD_INCLUDED
|
||||
#define FIELD_INCLUDED
|
||||
/* Copyright (c) 2000, 2011 Oracle and/or its affiliates.
|
||||
Copyright (c) 2008-2011 Monty Program Ab
|
||||
/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
|
||||
Copyright (c) 2008, 2011, Monty Program Ab
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
/*
|
||||
Copyright (c) 2000, 2011, Oracle and/or its affiliates.
|
||||
Copyright (c) 2000, 2012, Oracle and/or its affiliates.
|
||||
Copyright (c) 2010, 2012, Monty Program Ab
|
||||
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -3032,6 +3032,11 @@ void Item_func_case::fix_length_and_dec()
|
|||
nagg++;
|
||||
if (!(found_types= collect_cmp_types(agg, nagg)))
|
||||
return;
|
||||
|
||||
Item *date_arg= 0;
|
||||
if (found_types & (1 << TIME_RESULT))
|
||||
date_arg= find_date_time_item(args, arg_count, 0);
|
||||
|
||||
if (found_types & (1 << STRING_RESULT))
|
||||
{
|
||||
/*
|
||||
|
|
@ -3071,16 +3076,12 @@ void Item_func_case::fix_length_and_dec()
|
|||
change_item_tree_if_needed(thd, &args[nagg * 2], agg[nagg + 1]);
|
||||
}
|
||||
|
||||
Item *date_arg= 0;
|
||||
for (i= 0; i <= (uint)TIME_RESULT; i++)
|
||||
{
|
||||
if (found_types & (1 << i) && !cmp_items[i])
|
||||
{
|
||||
DBUG_ASSERT((Item_result)i != ROW_RESULT);
|
||||
|
||||
if ((Item_result)i == TIME_RESULT)
|
||||
date_arg= find_date_time_item(args, arg_count, 0);
|
||||
|
||||
if (!(cmp_items[i]=
|
||||
cmp_item::get_comparator((Item_result)i, date_arg,
|
||||
cmp_collation.collation)))
|
||||
|
|
@ -4051,15 +4052,15 @@ void Item_func_in::fix_length_and_dec()
|
|||
}
|
||||
else
|
||||
{
|
||||
if (found_types & (1 << TIME_RESULT))
|
||||
date_arg= find_date_time_item(args, arg_count, 0);
|
||||
if (found_types & (1 << STRING_RESULT) &&
|
||||
agg_arg_charsets_for_comparison(cmp_collation, args, arg_count))
|
||||
return;
|
||||
for (i= 0; i <= (uint) TIME_RESULT; i++)
|
||||
{
|
||||
if (found_types & (1 << i) && !cmp_items[i])
|
||||
{
|
||||
if ((Item_result)i == STRING_RESULT &&
|
||||
agg_arg_charsets_for_comparison(cmp_collation, args, arg_count))
|
||||
return;
|
||||
if ((Item_result)i == TIME_RESULT)
|
||||
date_arg= find_date_time_item(args, arg_count, 0);
|
||||
if (!cmp_items[i] && !(cmp_items[i]=
|
||||
cmp_item::get_comparator((Item_result)i, date_arg,
|
||||
cmp_collation.collation)))
|
||||
|
|
|
|||
|
|
@ -854,6 +854,14 @@ public:
|
|||
}
|
||||
}
|
||||
String *val_str(String *);
|
||||
longlong val_int()
|
||||
{ return args[0]->val_int(); }
|
||||
double val_real()
|
||||
{ return args[0]->val_real(); }
|
||||
my_decimal *val_decimal(my_decimal *d)
|
||||
{ return args[0]->val_decimal(d); }
|
||||
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
|
||||
{ return args[0]->get_date(ltime, fuzzydate); }
|
||||
void fix_length_and_dec();
|
||||
const char *func_name() const { return "convert"; }
|
||||
virtual void print(String *str, enum_query_type query_type);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2002, 2011, Oracle and/or its affiliates.
|
||||
Copyright (c) 2010, 2011, Monty Program Ab
|
||||
/* Copyright (c) 2002, 2012, Oracle and/or its affiliates.
|
||||
Copyright (c) 2010, 2012, Monty Program Ab
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -222,6 +222,11 @@ class Relay_log_info;
|
|||
extern PSI_mutex_key key_LOG_INFO_lock;
|
||||
#endif
|
||||
|
||||
/*
|
||||
Note that we destroy the lock mutex in the desctructor here.
|
||||
This means that object instances cannot be destroyed/go out of scope,
|
||||
until we have reset thd->current_linfo to NULL;
|
||||
*/
|
||||
typedef struct st_log_info
|
||||
{
|
||||
char log_file_name[FN_REFLEN];
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright (c) 2000, 2011, Oracle and/or its affiliates.
|
||||
Copyright (c) 2000, 2012, Oracle and/or its affiliates.
|
||||
Copyright (c) 2010, 2012, Monty Program Ab
|
||||
|
||||
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
|
||||
|
|
@ -5838,11 +5839,12 @@ void Intvar_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
|
|||
#endif
|
||||
|
||||
|
||||
#if defined(HAVE_REPLICATION)&& !defined(MYSQL_CLIENT)
|
||||
|
||||
/*
|
||||
Intvar_log_event::do_apply_event()
|
||||
*/
|
||||
|
||||
#if defined(HAVE_REPLICATION)&& !defined(MYSQL_CLIENT)
|
||||
int Intvar_log_event::do_apply_event(Relay_log_info const *rli)
|
||||
{
|
||||
/*
|
||||
|
|
@ -5851,6 +5853,9 @@ int Intvar_log_event::do_apply_event(Relay_log_info const *rli)
|
|||
*/
|
||||
const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
|
||||
|
||||
if (rli->deferred_events_collecting)
|
||||
return rli->deferred_events->add(this);
|
||||
|
||||
switch (type) {
|
||||
case LAST_INSERT_ID_EVENT:
|
||||
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 1;
|
||||
|
|
@ -5957,6 +5962,9 @@ int Rand_log_event::do_apply_event(Relay_log_info const *rli)
|
|||
*/
|
||||
const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
|
||||
|
||||
if (rli->deferred_events_collecting)
|
||||
return rli->deferred_events->add(this);
|
||||
|
||||
thd->rand.seed1= (ulong) seed1;
|
||||
thd->rand.seed2= (ulong) seed2;
|
||||
return 0;
|
||||
|
|
@ -5983,6 +5991,29 @@ Rand_log_event::do_shall_skip(Relay_log_info *rli)
|
|||
return continue_group(rli);
|
||||
}
|
||||
|
||||
/**
|
||||
Exec deferred Int-, Rand- and User- var events prefixing
|
||||
a Query-log-event event.
|
||||
|
||||
@param thd THD handle
|
||||
|
||||
@return false on success, true if a failure in an event applying occurred.
|
||||
*/
|
||||
bool slave_execute_deferred_events(THD *thd)
|
||||
{
|
||||
bool res= false;
|
||||
Relay_log_info *rli= thd->rli_slave;
|
||||
|
||||
DBUG_ASSERT(rli && (!rli->deferred_events_collecting || rli->deferred_events));
|
||||
|
||||
if (!rli->deferred_events_collecting || rli->deferred_events->is_empty())
|
||||
return res;
|
||||
|
||||
res= rli->deferred_events->execute(rli);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* !MYSQL_CLIENT */
|
||||
|
||||
|
||||
|
|
@ -6421,6 +6452,10 @@ int User_var_log_event::do_apply_event(Relay_log_info const *rli)
|
|||
{
|
||||
Item *it= 0;
|
||||
CHARSET_INFO *charset;
|
||||
|
||||
if (rli->deferred_events_collecting)
|
||||
return rli->deferred_events->add(this);
|
||||
|
||||
if (!(charset= get_charset(charset_number, MYF(MY_WME))))
|
||||
return 1;
|
||||
LEX_STRING user_var_name;
|
||||
|
|
|
|||
|
|
@ -4258,6 +4258,14 @@ private:
|
|||
const char* log_ident;
|
||||
uint ident_len;
|
||||
};
|
||||
|
||||
/**
|
||||
The function is called by slave applier in case there are
|
||||
active table filtering rules to force gathering events associated
|
||||
with Query-log-event into an array to execute
|
||||
them once the fate of the Query is determined for execution.
|
||||
*/
|
||||
bool slave_execute_deferred_events(THD *thd);
|
||||
#endif
|
||||
|
||||
int append_query_string(THD *thd, CHARSET_INFO *csinfo,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2007, 2010, Oracle and/or its affiliates.
|
||||
/* Copyright (c) 2007, 2012, Oracle and/or its affiliates.
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright (c) 2000, 2011, Oracle and/or its affiliates.
|
||||
Copyright (c) 2012, Monty Program Ab
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ Relay_log_info::Relay_log_info(bool is_slave_recovery)
|
|||
inited(0), abort_slave(0), slave_running(0), until_condition(UNTIL_NONE),
|
||||
until_log_pos(0), retried_trans(0),
|
||||
tables_to_lock(0), tables_to_lock_count(0),
|
||||
last_event_start_time(0), m_flags(0), row_stmt_start_timestamp(0),
|
||||
long_find_row_note_printed(false),
|
||||
last_event_start_time(0), deferred_events(NULL),m_flags(0),
|
||||
row_stmt_start_timestamp(0), long_find_row_note_printed(false),
|
||||
m_annotate_event(0)
|
||||
{
|
||||
DBUG_ENTER("Relay_log_info::Relay_log_info");
|
||||
|
|
|
|||
|
|
@ -389,6 +389,41 @@ public:
|
|||
*/
|
||||
time_t last_event_start_time;
|
||||
|
||||
/*
|
||||
A container to hold on Intvar-, Rand-, Uservar- log-events in case
|
||||
the slave is configured with table filtering rules.
|
||||
The withhold events are executed when their parent Query destiny is
|
||||
determined for execution as well.
|
||||
*/
|
||||
Deferred_log_events *deferred_events;
|
||||
|
||||
/*
|
||||
State of the container: true stands for IRU events gathering,
|
||||
false does for execution, either deferred or direct.
|
||||
*/
|
||||
bool deferred_events_collecting;
|
||||
|
||||
/*
|
||||
Returns true if the argument event resides in the containter;
|
||||
more specifically, the checking is done against the last added event.
|
||||
*/
|
||||
bool is_deferred_event(Log_event * ev)
|
||||
{
|
||||
return deferred_events_collecting ? deferred_events->is_last(ev) : false;
|
||||
};
|
||||
/* The general cleanup that slave applier may need at the end of query. */
|
||||
inline void cleanup_after_query()
|
||||
{
|
||||
if (deferred_events)
|
||||
deferred_events->rewind();
|
||||
};
|
||||
/* The general cleanup that slave applier may need at the end of session. */
|
||||
void cleanup_after_session()
|
||||
{
|
||||
if (deferred_events)
|
||||
delete deferred_events;
|
||||
};
|
||||
|
||||
/**
|
||||
Helper function to do after statement completion.
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#ifndef MYSQL_CLIENT
|
||||
#include "unireg.h" // REQUIRED by later includes
|
||||
#include "rpl_rli.h"
|
||||
#include "log_event.h"
|
||||
#include "sql_select.h"
|
||||
|
||||
/**
|
||||
|
|
@ -1057,6 +1058,7 @@ table_def::~table_def()
|
|||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@param even_buf point to the buffer containing serialized event
|
||||
@param event_len length of the event accounting possible checksum alg
|
||||
|
|
@ -1112,3 +1114,67 @@ bool event_checksum_test(uchar *event_buf, ulong event_len, uint8 alg)
|
|||
}
|
||||
return DBUG_EVALUATE_IF("simulate_checksum_test_failure", TRUE, res);
|
||||
}
|
||||
|
||||
|
||||
#if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
|
||||
|
||||
Deferred_log_events::Deferred_log_events(Relay_log_info *rli) : last_added(NULL)
|
||||
{
|
||||
my_init_dynamic_array(&array, sizeof(Log_event *), 32, 16);
|
||||
}
|
||||
|
||||
Deferred_log_events::~Deferred_log_events()
|
||||
{
|
||||
delete_dynamic(&array);
|
||||
}
|
||||
|
||||
int Deferred_log_events::add(Log_event *ev)
|
||||
{
|
||||
last_added= ev;
|
||||
insert_dynamic(&array, (uchar*) &ev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Deferred_log_events::is_empty()
|
||||
{
|
||||
return array.elements == 0;
|
||||
}
|
||||
|
||||
bool Deferred_log_events::execute(Relay_log_info *rli)
|
||||
{
|
||||
bool res= false;
|
||||
|
||||
DBUG_ASSERT(rli->deferred_events_collecting);
|
||||
|
||||
rli->deferred_events_collecting= false;
|
||||
for (uint i= 0; !res && i < array.elements; i++)
|
||||
{
|
||||
Log_event *ev= (* (Log_event **)
|
||||
dynamic_array_ptr(&array, i));
|
||||
res= ev->apply_event(rli);
|
||||
}
|
||||
rli->deferred_events_collecting= true;
|
||||
return res;
|
||||
}
|
||||
|
||||
void Deferred_log_events::rewind()
|
||||
{
|
||||
/*
|
||||
Reset preceeding Query log event events which execution was
|
||||
deferred because of slave side filtering.
|
||||
*/
|
||||
if (!is_empty())
|
||||
{
|
||||
for (uint i= 0; i < array.elements; i++)
|
||||
{
|
||||
Log_event *ev= *(Log_event **) dynamic_array_ptr(&array, i);
|
||||
delete ev;
|
||||
}
|
||||
if (array.elements > array.max_element)
|
||||
freeze_size(&array);
|
||||
reset_dynamic(&array);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include "mysql_com.h"
|
||||
|
||||
class Relay_log_info;
|
||||
|
||||
class Log_event;
|
||||
|
||||
/**
|
||||
A table definition from the master.
|
||||
|
|
@ -262,6 +262,24 @@ CPP_UNNAMED_NS_START
|
|||
};
|
||||
|
||||
CPP_UNNAMED_NS_END
|
||||
|
||||
class Deferred_log_events
|
||||
{
|
||||
private:
|
||||
DYNAMIC_ARRAY array;
|
||||
Log_event *last_added;
|
||||
|
||||
public:
|
||||
Deferred_log_events(Relay_log_info *rli);
|
||||
~Deferred_log_events();
|
||||
/* queue for exection at Query-log-event time prior the Query */;
|
||||
int add(Log_event *ev);
|
||||
bool is_empty();
|
||||
bool execute(Relay_log_info *rli);
|
||||
void rewind();
|
||||
bool is_last(Log_event *ev) { return ev == last_added; };
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
// NB. number of printed bit values is limited to sizeof(buf) - 1
|
||||
|
|
|
|||
|
|
@ -6501,6 +6501,9 @@ ER_TABLE_IN_FK_CHECK
|
|||
ER_UNUSED_1
|
||||
eng "You should never see it"
|
||||
|
||||
ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST
|
||||
eng "INSERT into autoincrement field which is not the first part in the composed primary key is unsafe."
|
||||
|
||||
#
|
||||
# End of 5.5 error messages.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -2794,7 +2794,8 @@ static int exec_relay_log_event(THD* thd, Relay_log_info* rli)
|
|||
/* fall through */
|
||||
default:
|
||||
DBUG_PRINT("info", ("Deleting the event after it has been executed"));
|
||||
delete ev;
|
||||
if (!rli->is_deferred_event(ev))
|
||||
delete ev;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -3458,6 +3459,12 @@ pthread_handler_t handle_slave_sql(void *arg)
|
|||
goto err_during_init;
|
||||
}
|
||||
thd->init_for_queries();
|
||||
thd->rli_slave= rli;
|
||||
if ((rli->deferred_events_collecting= rpl_filter->is_on()))
|
||||
{
|
||||
rli->deferred_events= new Deferred_log_events(rli);
|
||||
}
|
||||
|
||||
thd->temporary_tables = rli->save_temporary_tables; // restore temp tables
|
||||
set_thd_in_use_temporary_tables(rli); // (re)set sql_thd in use for saved temp tables
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (c) 2002, 2011, Oracle and/or its affiliates.
|
||||
Copyright (c) 2011, Monty Program Ab
|
||||
Copyright (c) 2002, 2012, Oracle and/or its affiliates.
|
||||
Copyright (c) 2011, 2012, Monty Program Ab
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -219,6 +219,7 @@ static bool
|
|||
has_write_table_with_auto_increment(TABLE_LIST *tables);
|
||||
static bool
|
||||
has_write_table_with_auto_increment_and_select(TABLE_LIST *tables);
|
||||
static bool has_write_table_auto_increment_not_first_in_pk(TABLE_LIST *tables);
|
||||
|
||||
uint cached_open_tables(void)
|
||||
{
|
||||
|
|
@ -5745,6 +5746,12 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count,
|
|||
if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables &&
|
||||
has_write_table_with_auto_increment_and_select(tables))
|
||||
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_WRITE_AUTOINC_SELECT);
|
||||
/* Todo: merge all has_write_table_auto_inc with decide_logging_format */
|
||||
if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables)
|
||||
{
|
||||
if (has_write_table_auto_increment_not_first_in_pk(tables))
|
||||
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST);
|
||||
}
|
||||
|
||||
/*
|
||||
INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys
|
||||
|
|
@ -9506,6 +9513,32 @@ has_write_table_with_auto_increment_and_select(TABLE_LIST *tables)
|
|||
return(has_select && has_auto_increment_tables);
|
||||
}
|
||||
|
||||
/*
|
||||
Tells if there is a table whose auto_increment column is a part
|
||||
of a compound primary key while is not the first column in
|
||||
the table definition.
|
||||
|
||||
@param tables Table list
|
||||
|
||||
@return true if the table exists, fais if does not.
|
||||
*/
|
||||
|
||||
static bool
|
||||
has_write_table_auto_increment_not_first_in_pk(TABLE_LIST *tables)
|
||||
{
|
||||
for (TABLE_LIST *table= tables; table; table= table->next_global)
|
||||
{
|
||||
/* we must do preliminary checks as table->table may be NULL */
|
||||
if (!table->placeholder() &&
|
||||
table->table->found_next_number_field &&
|
||||
(table->lock_type >= TL_WRITE_ALLOW_WRITE)
|
||||
&& table->table->s->next_number_keypart != 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (c) 2000, 2011, Oracle and/or its affiliates.
|
||||
Copyright (c) 2008-2012 Monty Program Ab
|
||||
Copyright (c) 2000, 2012, Oracle and/or its affiliates.
|
||||
Copyright (c) 2008, 2012, Monty Program Ab
|
||||
|
||||
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
|
||||
|
|
@ -726,7 +726,7 @@ bool Drop_table_error_handler::handle_condition(THD *thd,
|
|||
THD::THD()
|
||||
:Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION,
|
||||
/* statement id */ 0),
|
||||
rli_fake(0),
|
||||
rli_fake(0), rli_slave(NULL),
|
||||
in_sub_stmt(0), log_all_errors(0),
|
||||
binlog_unsafe_warning_flags(0),
|
||||
binlog_table_maps(0),
|
||||
|
|
@ -1412,6 +1412,8 @@ THD::~THD()
|
|||
}
|
||||
|
||||
mysql_audit_free_thd(this);
|
||||
if (rli_slave)
|
||||
rli_slave->cleanup_after_session();
|
||||
#endif
|
||||
|
||||
free_root(&main_mem_root, MYF(0));
|
||||
|
|
@ -1791,6 +1793,11 @@ void THD::cleanup_after_query()
|
|||
table_map_for_update= 0;
|
||||
m_binlog_invoker= FALSE;
|
||||
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
if (rli_slave)
|
||||
rli_slave->cleanup_after_query();
|
||||
#endif
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Copyright (c) 2000, 2011, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009-2012, Monty Program Ab
|
||||
Copyright (c) 2000, 2012, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2012, Monty Program Ab
|
||||
|
||||
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
|
||||
|
|
@ -1547,6 +1547,8 @@ public:
|
|||
|
||||
/* Used to execute base64 coded binlog events in MySQL server */
|
||||
Relay_log_info* rli_fake;
|
||||
/* Slave applier execution context */
|
||||
Relay_log_info* rli_slave;
|
||||
|
||||
void reset_for_next_command(bool calculate_userstat);
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -68,7 +68,8 @@ Query_tables_list::binlog_stmt_unsafe_errcode[BINLOG_STMT_UNSAFE_COUNT] =
|
|||
ER_BINLOG_UNSAFE_CREATE_REPLACE_SELECT,
|
||||
ER_BINLOG_UNSAFE_CREATE_SELECT_AUTOINC,
|
||||
ER_BINLOG_UNSAFE_UPDATE_IGNORE,
|
||||
ER_BINLOG_UNSAFE_INSERT_TWO_KEYS
|
||||
ER_BINLOG_UNSAFE_INSERT_TWO_KEYS,
|
||||
ER_BINLOG_UNSAFE_AUTOINC_NOT_FIRST
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1433,6 +1433,12 @@ public:
|
|||
*/
|
||||
BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS,
|
||||
|
||||
/**
|
||||
INSERT into auto-inc field which is not the first part of composed
|
||||
primary key.
|
||||
*/
|
||||
BINLOG_STMT_UNSAFE_AUTOINC_NOT_FIRST,
|
||||
|
||||
/* The last element of this enumeration type. */
|
||||
BINLOG_STMT_UNSAFE_COUNT
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2074,6 +2074,11 @@ mysql_execute_command(THD *thd)
|
|||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
/*
|
||||
Execute deferred events first
|
||||
*/
|
||||
if (slave_execute_deferred_events(thd))
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -2685,7 +2690,7 @@ end_with_restore_list:
|
|||
goto error;
|
||||
#else
|
||||
{
|
||||
if (check_global_access(thd, SUPER_ACL))
|
||||
if (check_global_access(thd, SUPER_ACL | REPL_CLIENT_ACL))
|
||||
goto error;
|
||||
res = show_binlogs(thd);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1883,6 +1883,8 @@ bool mysql_show_binlog_events(THD* thd)
|
|||
File file = -1;
|
||||
MYSQL_BIN_LOG *binary_log= NULL;
|
||||
int old_max_allowed_packet= thd->variables.max_allowed_packet;
|
||||
LOG_INFO linfo;
|
||||
|
||||
DBUG_ENTER("mysql_show_binlog_events");
|
||||
|
||||
Log_event::init_show_field_list(&field_list);
|
||||
|
|
@ -1925,7 +1927,6 @@ bool mysql_show_binlog_events(THD* thd)
|
|||
char search_file_name[FN_REFLEN], *name;
|
||||
const char *log_file_name = lex_mi->log_file_name;
|
||||
mysql_mutex_t *log_lock = binary_log->get_log_lock();
|
||||
LOG_INFO linfo;
|
||||
Log_event* ev;
|
||||
|
||||
unit->set_limit(thd->lex->current_select);
|
||||
|
|
@ -2022,6 +2023,8 @@ bool mysql_show_binlog_events(THD* thd)
|
|||
|
||||
mysql_mutex_unlock(log_lock);
|
||||
}
|
||||
// Check that linfo is still on the function scope.
|
||||
DEBUG_SYNC(thd, "after_show_binlog_events");
|
||||
|
||||
ret= FALSE;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2000, 2010 Oracle and/or its affiliates.
|
||||
2009-2011 Monty Program Ab
|
||||
/* Copyright (c) 2000, 2012 Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2012, Monty Program Ab
|
||||
|
||||
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
|
||||
|
|
@ -18594,8 +18594,6 @@ check_reverse_order:
|
|||
join_read_first:join_read_last;
|
||||
tab->type=JT_NEXT; // Read with index_first(), index_next()
|
||||
|
||||
if (table->covering_keys.is_set(best_key) && ! table->key_read)
|
||||
table->enable_keyread();
|
||||
if (tab->pre_idx_push_select_cond)
|
||||
{
|
||||
tab->set_cond(tab->pre_idx_push_select_cond);
|
||||
|
|
@ -18606,6 +18604,7 @@ check_reverse_order:
|
|||
orig_cond= 0;
|
||||
orig_cond_saved= false;
|
||||
}
|
||||
|
||||
table->file->ha_index_or_rnd_end();
|
||||
if (tab->join->select_options & SELECT_DESCRIBE)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
|
||||
Copyright (c) 2009, 2011, Monty Program Ab
|
||||
Copyright (c) 2009, 2012, Monty Program Ab
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -238,10 +238,17 @@ uint explain_filename(THD* thd,
|
|||
{
|
||||
part_name_len= tmp_p - part_name - 1;
|
||||
subpart_name= tmp_p + 3;
|
||||
tmp_p+= 3;
|
||||
}
|
||||
else if ((tmp_p[1] == 'Q' || tmp_p[1] == 'q') &&
|
||||
(tmp_p[2] == 'L' || tmp_p[2] == 'l') &&
|
||||
tmp_p[3] == '-')
|
||||
{
|
||||
name_type= TEMP;
|
||||
tmp_p+= 4; /* sql- prefix found */
|
||||
}
|
||||
else
|
||||
res= 2;
|
||||
tmp_p+= 3;
|
||||
break;
|
||||
case 'T':
|
||||
case 't':
|
||||
|
|
@ -6926,21 +6933,47 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||
(void) quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
|
||||
}
|
||||
else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
|
||||
new_alias, FN_FROM_IS_TMP) ||
|
||||
((new_name != table_name || new_db != db) && // we also do rename
|
||||
(need_copy_table != ALTER_TABLE_METADATA_ONLY ||
|
||||
mysql_rename_table(save_old_db_type, db, table_name, new_db,
|
||||
new_alias, NO_FRM_RENAME)) &&
|
||||
Table_triggers_list::change_table_name(thd, db, alias, table_name,
|
||||
new_db, new_alias)))
|
||||
new_alias, FN_FROM_IS_TMP))
|
||||
{
|
||||
/* Try to get everything back. */
|
||||
error=1;
|
||||
(void) quick_rm_table(new_db_type,new_db,new_alias, 0);
|
||||
error= 1;
|
||||
(void) quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
|
||||
(void) mysql_rename_table(old_db_type, db, old_name, db, alias,
|
||||
FN_FROM_IS_TMP);
|
||||
}
|
||||
else if (new_name != table_name || new_db != db)
|
||||
{
|
||||
if (need_copy_table == ALTER_TABLE_METADATA_ONLY &&
|
||||
mysql_rename_table(save_old_db_type, db, table_name, new_db,
|
||||
new_alias, NO_FRM_RENAME))
|
||||
{
|
||||
/* Try to get everything back. */
|
||||
error= 1;
|
||||
(void) quick_rm_table(new_db_type, new_db, new_alias, 0);
|
||||
(void) mysql_rename_table(old_db_type, db, old_name, db, alias,
|
||||
FN_FROM_IS_TMP);
|
||||
}
|
||||
else if (Table_triggers_list::change_table_name(thd, db, alias,
|
||||
table_name, new_db,
|
||||
new_alias))
|
||||
{
|
||||
/* Try to get everything back. */
|
||||
error= 1;
|
||||
(void) quick_rm_table(new_db_type, new_db, new_alias, 0);
|
||||
(void) mysql_rename_table(old_db_type, db, old_name, db,
|
||||
alias, FN_FROM_IS_TMP);
|
||||
/*
|
||||
If we were performing "fast"/in-place ALTER TABLE we also need
|
||||
to restore old name of table in storage engine as a separate
|
||||
step, as the above rename affects .FRM only.
|
||||
*/
|
||||
if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
|
||||
{
|
||||
(void) mysql_rename_table(save_old_db_type, new_db, new_alias,
|
||||
db, table_name, NO_FRM_RENAME);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! error)
|
||||
(void) quick_rm_table(old_db_type, db, old_name, FN_IS_TMP);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
/* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -3463,6 +3463,8 @@ btr_estimate_n_rows_in_range(
|
|||
n_rows = n_rows * 2;
|
||||
}
|
||||
|
||||
DBUG_EXECUTE_IF("bug14007649", return(n_rows););
|
||||
|
||||
/* Do not estimate the number of rows in the range
|
||||
to over 1 / 2 of the estimated rows in the whole
|
||||
table */
|
||||
|
|
|
|||
|
|
@ -1750,8 +1750,6 @@ buf_flush_batch(
|
|||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
srv_buf_pool_flushed += count;
|
||||
|
||||
return(count);
|
||||
}
|
||||
|
||||
|
|
@ -1778,13 +1776,6 @@ buf_flush_common(
|
|||
#endif /* UNIV_DEBUG */
|
||||
|
||||
srv_buf_pool_flushed += page_count;
|
||||
|
||||
if (flush_type == BUF_FLUSH_LRU) {
|
||||
/* We keep track of all flushes happening as part of LRU
|
||||
flush. When estimating the desired rate at which flush_list
|
||||
should be flushed we factor in this value. */
|
||||
buf_lru_flush_page_count += page_count;
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ dict_print(void)
|
|||
monitor printout */
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
|
||||
srv_fatal_semaphore_wait_threshold += SRV_SEMAPHORE_WAIT_EXTENSION;
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
heap = mem_heap_create(1000);
|
||||
|
|
@ -214,7 +214,7 @@ dict_print(void)
|
|||
|
||||
/* Restore the fatal semaphore wait timeout */
|
||||
mutex_enter(&kernel_mutex);
|
||||
srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
|
||||
srv_fatal_semaphore_wait_threshold -= SRV_SEMAPHORE_WAIT_EXTENSION;
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1908,7 +1908,7 @@ fil_inc_pending_ops(
|
|||
|
||||
if (space == NULL) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to do ibuf merge to a"
|
||||
"InnoDB: Error: trying to do an operation on a"
|
||||
" dropped tablespace %lu\n",
|
||||
(ulong) id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4197,6 +4197,31 @@ table_opened:
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
UNIV_INTERN
|
||||
handler*
|
||||
ha_innobase::clone(
|
||||
/*===============*/
|
||||
const char* name, /*!< in: table name */
|
||||
MEM_ROOT* mem_root) /*!< in: memory context */
|
||||
{
|
||||
ha_innobase* new_handler;
|
||||
|
||||
DBUG_ENTER("ha_innobase::clone");
|
||||
|
||||
new_handler = static_cast<ha_innobase*>(handler::clone(name,
|
||||
mem_root));
|
||||
if (new_handler) {
|
||||
DBUG_ASSERT(new_handler->prebuilt != NULL);
|
||||
DBUG_ASSERT(new_handler->user_thd == user_thd);
|
||||
DBUG_ASSERT(new_handler->prebuilt->trx == prebuilt->trx);
|
||||
|
||||
new_handler->prebuilt->select_lock_type
|
||||
= prebuilt->select_lock_type;
|
||||
}
|
||||
|
||||
DBUG_RETURN(new_handler);
|
||||
}
|
||||
|
||||
UNIV_INTERN
|
||||
uint
|
||||
ha_innobase::max_supported_key_part_length() const
|
||||
|
|
@ -8546,7 +8571,7 @@ ha_innobase::check(
|
|||
|
||||
/* Enlarge the fatal lock wait timeout during CHECK TABLE. */
|
||||
mutex_enter(&kernel_mutex);
|
||||
srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
|
||||
srv_fatal_semaphore_wait_threshold += SRV_SEMAPHORE_WAIT_EXTENSION;
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
for (index = dict_table_get_first_index(prebuilt->table);
|
||||
|
|
@ -8687,7 +8712,7 @@ ha_innobase::check(
|
|||
|
||||
/* Restore the fatal lock wait timeout after CHECK TABLE. */
|
||||
mutex_enter(&kernel_mutex);
|
||||
srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
|
||||
srv_fatal_semaphore_wait_threshold -= SRV_SEMAPHORE_WAIT_EXTENSION;
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
prebuilt->trx->op_info = "";
|
||||
|
|
|
|||
|
|
@ -133,6 +133,7 @@ class ha_innobase: public handler
|
|||
const key_map* keys_to_use_for_scanning();
|
||||
|
||||
int open(const char *name, int mode, uint test_if_locked);
|
||||
handler* clone(const char *name, MEM_ROOT *mem_root);
|
||||
int close(void);
|
||||
double scan_time();
|
||||
double read_time(uint index, uint ranges, ha_rows rows);
|
||||
|
|
|
|||
|
|
@ -262,6 +262,7 @@ extern ibool srv_print_latch_waits;
|
|||
|
||||
extern ulint srv_activity_count;
|
||||
extern ulint srv_fatal_semaphore_wait_threshold;
|
||||
#define SRV_SEMAPHORE_WAIT_EXTENSION 7200
|
||||
extern ulint srv_dml_needed_delay;
|
||||
|
||||
extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
|
||||
|
|
|
|||
|
|
@ -1364,10 +1364,18 @@ innobase_start_or_create_for_mysql(void)
|
|||
}
|
||||
# endif /* __WIN__ */
|
||||
|
||||
os_aio_init(io_limit,
|
||||
srv_n_read_io_threads,
|
||||
srv_n_write_io_threads,
|
||||
SRV_MAX_N_PENDING_SYNC_IOS);
|
||||
if (!os_aio_init(io_limit,
|
||||
srv_n_read_io_threads,
|
||||
srv_n_write_io_threads,
|
||||
SRV_MAX_N_PENDING_SYNC_IOS)) {
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Fatal error: cannot initialize AIO"
|
||||
" sub-system\n");
|
||||
|
||||
return(DB_ERROR);
|
||||
}
|
||||
|
||||
fil_init(srv_file_per_table ? 50000 : 5000,
|
||||
srv_max_n_open_files);
|
||||
|
|
|
|||
|
|
@ -928,6 +928,11 @@ sync_array_print_long_waits(
|
|||
ibool fatal = FALSE;
|
||||
double longest_diff = 0;
|
||||
|
||||
/* For huge tables, skip the check during CHECK TABLE etc... */
|
||||
if (fatal_timeout > SRV_SEMAPHORE_WAIT_EXTENSION) {
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG_VALGRIND
|
||||
/* Increase the timeouts if running under valgrind because it executes
|
||||
extremely slowly. UNIV_DEBUG_VALGRIND does not necessary mean that
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
|
@ -11,8 +11,8 @@ 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., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
|
|
@ -42,6 +42,28 @@ Created 6/2/1994 Heikki Tuuri
|
|||
#include "ibuf0ibuf.h"
|
||||
#include "trx0trx.h"
|
||||
|
||||
/**************************************************************//**
|
||||
Report that an index page is corrupted. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_corruption_report(
|
||||
/*==================*/
|
||||
const buf_block_t* block, /*!< in: corrupted block */
|
||||
const dict_index_t* index) /*!< in: index tree */
|
||||
{
|
||||
fprintf(stderr, "InnoDB: flag mismatch in space %u page %u"
|
||||
" index %s of table %s\n",
|
||||
(unsigned) buf_block_get_space(block),
|
||||
(unsigned) buf_block_get_page_no(block),
|
||||
index->name, index->table_name);
|
||||
if (block->page.zip.data) {
|
||||
buf_page_print(block->page.zip.data,
|
||||
buf_block_get_zip_size(block),
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
}
|
||||
buf_page_print(buf_block_get_frame(block), 0, 0);
|
||||
}
|
||||
|
||||
#ifdef UNIV_BLOB_DEBUG
|
||||
# include "srv0srv.h"
|
||||
# include "ut0rbt.h"
|
||||
|
|
@ -664,6 +686,12 @@ btr_root_fseg_validate(
|
|||
{
|
||||
ulint offset = mach_read_from_2(seg_header + FSEG_HDR_OFFSET);
|
||||
|
||||
if (UNIV_UNLIKELY(srv_pass_corrupt_table)) {
|
||||
return (mach_read_from_4(seg_header + FSEG_HDR_SPACE) == space)
|
||||
&& (offset >= FIL_PAGE_DATA)
|
||||
&& (offset <= UNIV_PAGE_SIZE - FIL_PAGE_DATA_END);
|
||||
}
|
||||
|
||||
ut_a(mach_read_from_4(seg_header + FSEG_HDR_SPACE) == space);
|
||||
ut_a(offset >= FIL_PAGE_DATA);
|
||||
ut_a(offset <= UNIV_PAGE_SIZE - FIL_PAGE_DATA_END);
|
||||
|
|
@ -698,12 +726,22 @@ btr_root_block_get(
|
|||
}
|
||||
ut_a(block);
|
||||
|
||||
ut_a((ibool)!!page_is_comp(buf_block_get_frame(block))
|
||||
== dict_table_is_comp(index->table));
|
||||
btr_assert_not_corrupted(block, index);
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
if (!dict_index_is_ibuf(index)) {
|
||||
const page_t* root = buf_block_get_frame(block);
|
||||
|
||||
if (UNIV_UNLIKELY(srv_pass_corrupt_table)) {
|
||||
if (!btr_root_fseg_validate(FIL_PAGE_DATA
|
||||
+ PAGE_BTR_SEG_LEAF
|
||||
+ root, space))
|
||||
return(NULL);
|
||||
if (!btr_root_fseg_validate(FIL_PAGE_DATA
|
||||
+ PAGE_BTR_SEG_TOP
|
||||
+ root, space))
|
||||
return(NULL);
|
||||
return(block);
|
||||
}
|
||||
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_LEAF
|
||||
+ root, space));
|
||||
ut_a(btr_root_fseg_validate(FIL_PAGE_DATA + PAGE_BTR_SEG_TOP
|
||||
|
|
@ -912,28 +950,31 @@ btr_page_alloc_for_ibuf(
|
|||
/**************************************************************//**
|
||||
Allocates a new file page to be used in an index tree. NOTE: we assume
|
||||
that the caller has made the reservation for free extents!
|
||||
@return new allocated block, x-latched; NULL if out of space */
|
||||
UNIV_INTERN
|
||||
@retval NULL if no page could be allocated
|
||||
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||
@retval block (not allocated or initialized) otherwise */
|
||||
static __attribute__((nonnull, warn_unused_result))
|
||||
buf_block_t*
|
||||
btr_page_alloc(
|
||||
/*===========*/
|
||||
btr_page_alloc_low(
|
||||
/*===============*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint hint_page_no, /*!< in: hint of a good page */
|
||||
byte file_direction, /*!< in: direction where a possible
|
||||
page split is made */
|
||||
ulint level, /*!< in: level where the page is placed
|
||||
in the tree */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
mtr_t* mtr, /*!< in/out: mini-transaction
|
||||
for the allocation */
|
||||
mtr_t* init_mtr) /*!< in/out: mtr or another
|
||||
mini-transaction in which the
|
||||
page should be initialized.
|
||||
If init_mtr!=mtr, but the page
|
||||
is already X-latched in mtr, do
|
||||
not initialize the page. */
|
||||
{
|
||||
fseg_header_t* seg_header;
|
||||
page_t* root;
|
||||
buf_block_t* new_block;
|
||||
ulint new_page_no;
|
||||
|
||||
if (dict_index_is_ibuf(index)) {
|
||||
|
||||
return(btr_page_alloc_for_ibuf(index, mtr));
|
||||
}
|
||||
|
||||
root = btr_root_get(index, mtr);
|
||||
|
||||
|
|
@ -947,45 +988,81 @@ btr_page_alloc(
|
|||
reservation for free extents, and thus we know that a page can
|
||||
be allocated: */
|
||||
|
||||
new_page_no = fseg_alloc_free_page_general(seg_header, hint_page_no,
|
||||
file_direction, TRUE, mtr);
|
||||
if (new_page_no == FIL_NULL) {
|
||||
return(fseg_alloc_free_page_general(
|
||||
seg_header, hint_page_no, file_direction,
|
||||
TRUE, mtr, init_mtr));
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
/**************************************************************//**
|
||||
Allocates a new file page to be used in an index tree. NOTE: we assume
|
||||
that the caller has made the reservation for free extents!
|
||||
@retval NULL if no page could be allocated
|
||||
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||
@retval block (not allocated or initialized) otherwise */
|
||||
UNIV_INTERN
|
||||
buf_block_t*
|
||||
btr_page_alloc(
|
||||
/*===========*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint hint_page_no, /*!< in: hint of a good page */
|
||||
byte file_direction, /*!< in: direction where a possible
|
||||
page split is made */
|
||||
ulint level, /*!< in: level where the page is placed
|
||||
in the tree */
|
||||
mtr_t* mtr, /*!< in/out: mini-transaction
|
||||
for the allocation */
|
||||
mtr_t* init_mtr) /*!< in/out: mini-transaction
|
||||
for x-latching and initializing
|
||||
the page */
|
||||
{
|
||||
buf_block_t* new_block;
|
||||
|
||||
if (dict_index_is_ibuf(index)) {
|
||||
|
||||
return(btr_page_alloc_for_ibuf(index, mtr));
|
||||
}
|
||||
|
||||
new_block = buf_page_get(dict_index_get_space(index),
|
||||
dict_table_zip_size(index->table),
|
||||
new_page_no, RW_X_LATCH, mtr);
|
||||
buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
|
||||
new_block = btr_page_alloc_low(
|
||||
index, hint_page_no, file_direction, level, mtr, init_mtr);
|
||||
|
||||
if (new_block) {
|
||||
buf_block_dbg_add_level(new_block, SYNC_TREE_NODE_NEW);
|
||||
}
|
||||
|
||||
return(new_block);
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Gets the number of pages in a B-tree.
|
||||
@return number of pages */
|
||||
@return number of pages, or ULINT_UNDEFINED if the index is unavailable */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_get_size(
|
||||
/*=========*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint flag) /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
|
||||
ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction where index
|
||||
is s-latched */
|
||||
{
|
||||
fseg_header_t* seg_header;
|
||||
page_t* root;
|
||||
ulint n;
|
||||
ulint dummy;
|
||||
mtr_t mtr;
|
||||
|
||||
mtr_start(&mtr);
|
||||
ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
|
||||
MTR_MEMO_S_LOCK));
|
||||
|
||||
mtr_s_lock(dict_index_get_lock(index), &mtr);
|
||||
if (index->page == FIL_NULL
|
||||
|| index->to_be_dropped
|
||||
|| *index->name == TEMP_INDEX_PREFIX) {
|
||||
return(ULINT_UNDEFINED);
|
||||
}
|
||||
|
||||
root = btr_root_get(index, &mtr);
|
||||
root = btr_root_get(index, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !root) {
|
||||
mtr_commit(&mtr);
|
||||
mtr_commit(mtr);
|
||||
return(0);
|
||||
}
|
||||
ut_a(root);
|
||||
|
|
@ -993,22 +1070,20 @@ btr_get_size(
|
|||
if (flag == BTR_N_LEAF_PAGES) {
|
||||
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
|
||||
|
||||
fseg_n_reserved_pages(seg_header, &n, &mtr);
|
||||
fseg_n_reserved_pages(seg_header, &n, mtr);
|
||||
|
||||
} else if (flag == BTR_TOTAL_SIZE) {
|
||||
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_TOP;
|
||||
|
||||
n = fseg_n_reserved_pages(seg_header, &dummy, &mtr);
|
||||
n = fseg_n_reserved_pages(seg_header, &dummy, mtr);
|
||||
|
||||
seg_header = root + PAGE_HEADER + PAGE_BTR_SEG_LEAF;
|
||||
|
||||
n += fseg_n_reserved_pages(seg_header, &dummy, &mtr);
|
||||
n += fseg_n_reserved_pages(seg_header, &dummy, mtr);
|
||||
} else {
|
||||
ut_error;
|
||||
}
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
return(n);
|
||||
}
|
||||
|
||||
|
|
@ -1090,10 +1165,10 @@ btr_page_free(
|
|||
buf_block_t* block, /*!< in: block to be freed, x-latched */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
ulint level;
|
||||
|
||||
level = btr_page_get_level(buf_block_get_frame(block), mtr);
|
||||
const page_t* page = buf_block_get_frame(block);
|
||||
ulint level = btr_page_get_level(page, mtr);
|
||||
|
||||
ut_ad(fil_page_get_type(block->frame) == FIL_PAGE_INDEX);
|
||||
btr_page_free_low(index, block, level, mtr);
|
||||
}
|
||||
|
||||
|
|
@ -1207,9 +1282,11 @@ btr_page_get_father_node_ptr_func(
|
|||
!= page_no)) {
|
||||
rec_t* print_rec;
|
||||
fputs("InnoDB: Dump of the child page:\n", stderr);
|
||||
buf_page_print(page_align(user_rec), 0);
|
||||
buf_page_print(page_align(user_rec), 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
fputs("InnoDB: Dump of the parent page:\n", stderr);
|
||||
buf_page_print(page_align(node_ptr), 0);
|
||||
buf_page_print(page_align(node_ptr), 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
|
||||
fputs("InnoDB: Corruption of an index tree: table ", stderr);
|
||||
ut_print_name(stderr, NULL, TRUE, index->table_name);
|
||||
|
|
@ -1333,16 +1410,12 @@ btr_create(
|
|||
/* Allocate then the next page to the segment: it will be the
|
||||
tree root page */
|
||||
|
||||
page_no = fseg_alloc_free_page(buf_block_get_frame(
|
||||
ibuf_hdr_block)
|
||||
+ IBUF_HEADER
|
||||
+ IBUF_TREE_SEG_HEADER,
|
||||
IBUF_TREE_ROOT_PAGE_NO,
|
||||
FSP_UP, mtr);
|
||||
ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
|
||||
|
||||
block = buf_page_get(space, zip_size, page_no,
|
||||
RW_X_LATCH, mtr);
|
||||
block = fseg_alloc_free_page(
|
||||
buf_block_get_frame(ibuf_hdr_block)
|
||||
+ IBUF_HEADER + IBUF_TREE_SEG_HEADER,
|
||||
IBUF_TREE_ROOT_PAGE_NO,
|
||||
FSP_UP, mtr);
|
||||
ut_ad(buf_block_get_page_no(block) == IBUF_TREE_ROOT_PAGE_NO);
|
||||
} else {
|
||||
#ifdef UNIV_BLOB_DEBUG
|
||||
if ((type & DICT_CLUSTERED) && !index->blobs) {
|
||||
|
|
@ -1562,7 +1635,7 @@ btr_page_reorganize_low(
|
|||
ibool success = FALSE;
|
||||
|
||||
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(!!page_is_comp(page) == dict_table_is_comp(index->table));
|
||||
btr_assert_not_corrupted(block, index);
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
ut_a(!page_zip || page_zip_validate(page_zip, page));
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
|
|
@ -1664,8 +1737,8 @@ btr_page_reorganize_low(
|
|||
|
||||
if (UNIV_UNLIKELY(data_size1 != data_size2)
|
||||
|| UNIV_UNLIKELY(max_ins_size1 != max_ins_size2)) {
|
||||
buf_page_print(page, 0);
|
||||
buf_page_print(temp_page, 0);
|
||||
buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(temp_page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: page old data size %lu"
|
||||
" new data size %lu\n"
|
||||
|
|
@ -1676,6 +1749,7 @@ btr_page_reorganize_low(
|
|||
(unsigned long) data_size1, (unsigned long) data_size2,
|
||||
(unsigned long) max_ins_size1,
|
||||
(unsigned long) max_ins_size2);
|
||||
ut_ad(0);
|
||||
} else {
|
||||
success = TRUE;
|
||||
}
|
||||
|
|
@ -1839,7 +1913,7 @@ btr_root_raise_and_insert(
|
|||
|
||||
level = btr_page_get_level(root, mtr);
|
||||
|
||||
new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr);
|
||||
new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr);
|
||||
new_page = buf_block_get_frame(new_block);
|
||||
new_page_zip = buf_block_get_page_zip(new_block);
|
||||
ut_a(!new_page_zip == !root_page_zip);
|
||||
|
|
@ -2575,7 +2649,7 @@ func_start:
|
|||
|
||||
/* 2. Allocate a new page to the index */
|
||||
new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
|
||||
btr_page_get_level(page, mtr), mtr);
|
||||
btr_page_get_level(page, mtr), mtr, mtr);
|
||||
new_page = buf_block_get_frame(new_block);
|
||||
new_page_zip = buf_block_get_page_zip(new_block);
|
||||
btr_page_create(new_block, new_page_zip, cursor->index,
|
||||
|
|
@ -3025,15 +3099,16 @@ btr_node_ptr_delete(
|
|||
ut_a(err == DB_SUCCESS);
|
||||
|
||||
if (!compressed) {
|
||||
btr_cur_compress_if_useful(&cursor, mtr);
|
||||
btr_cur_compress_if_useful(&cursor, FALSE, mtr);
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
If page is the only on its level, this function moves its records to the
|
||||
father page, thus reducing the tree height. */
|
||||
father page, thus reducing the tree height.
|
||||
@return father block */
|
||||
static
|
||||
void
|
||||
buf_block_t*
|
||||
btr_lift_page_up(
|
||||
/*=============*/
|
||||
dict_index_t* index, /*!< in: index tree */
|
||||
|
|
@ -3150,6 +3225,8 @@ btr_lift_page_up(
|
|||
}
|
||||
ut_ad(page_validate(father_page, index));
|
||||
ut_ad(btr_check_node_ptr(index, father_block, mtr));
|
||||
|
||||
return(father_block);
|
||||
}
|
||||
|
||||
/*************************************************************//**
|
||||
|
|
@ -3166,11 +3243,13 @@ UNIV_INTERN
|
|||
ibool
|
||||
btr_compress(
|
||||
/*=========*/
|
||||
btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift;
|
||||
the page must not be empty: in record delete
|
||||
use btr_discard_page if the page would become
|
||||
empty */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
btr_cur_t* cursor, /*!< in/out: cursor on the page to merge
|
||||
or lift; the page must not be empty:
|
||||
when deleting records, use btr_discard_page()
|
||||
if the page would become empty */
|
||||
ibool adjust, /*!< in: TRUE if should adjust the
|
||||
cursor position even if compression occurs */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
dict_index_t* index;
|
||||
ulint space;
|
||||
|
|
@ -3188,13 +3267,15 @@ btr_compress(
|
|||
ulint* offsets;
|
||||
ulint data_size;
|
||||
ulint n_recs;
|
||||
ulint nth_rec = 0; /* remove bogus warning */
|
||||
ulint max_ins_size;
|
||||
ulint max_ins_size_reorg;
|
||||
|
||||
block = btr_cur_get_block(cursor);
|
||||
page = btr_cur_get_page(cursor);
|
||||
index = btr_cur_get_index(cursor);
|
||||
ut_a((ibool) !!page_is_comp(page) == dict_table_is_comp(index->table));
|
||||
|
||||
btr_assert_not_corrupted(block, index);
|
||||
|
||||
ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(index),
|
||||
MTR_MEMO_X_LOCK));
|
||||
|
|
@ -3214,6 +3295,10 @@ btr_compress(
|
|||
offsets = btr_page_get_father_block(NULL, heap, index, block, mtr,
|
||||
&father_cursor);
|
||||
|
||||
if (adjust) {
|
||||
nth_rec = page_rec_get_n_recs_before(btr_cur_get_rec(cursor));
|
||||
}
|
||||
|
||||
/* Decide the page to which we try to merge and which will inherit
|
||||
the locks */
|
||||
|
||||
|
|
@ -3240,9 +3325,9 @@ btr_compress(
|
|||
} else {
|
||||
/* The page is the only one on the level, lift the records
|
||||
to the father */
|
||||
btr_lift_page_up(index, block, mtr);
|
||||
mem_heap_free(heap);
|
||||
return(TRUE);
|
||||
|
||||
merge_block = btr_lift_page_up(index, block, mtr);
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
n_recs = page_get_n_recs(page);
|
||||
|
|
@ -3324,6 +3409,10 @@ err_exit:
|
|||
|
||||
btr_node_ptr_delete(index, block, mtr);
|
||||
lock_update_merge_left(merge_block, orig_pred, block);
|
||||
|
||||
if (adjust) {
|
||||
nth_rec += page_rec_get_n_recs_before(orig_pred);
|
||||
}
|
||||
} else {
|
||||
rec_t* orig_succ;
|
||||
#ifdef UNIV_BTR_DEBUG
|
||||
|
|
@ -3388,7 +3477,6 @@ err_exit:
|
|||
}
|
||||
|
||||
btr_blob_dbg_remove(page, index, "btr_compress");
|
||||
mem_heap_free(heap);
|
||||
|
||||
if (!dict_index_is_clust(index) && page_is_leaf(merge_page)) {
|
||||
/* Update the free bits of the B-tree page in the
|
||||
|
|
@ -3440,6 +3528,16 @@ err_exit:
|
|||
btr_page_free(index, block, mtr);
|
||||
|
||||
ut_ad(btr_check_node_ptr(index, merge_block, mtr));
|
||||
func_exit:
|
||||
mem_heap_free(heap);
|
||||
|
||||
if (adjust) {
|
||||
btr_cur_position(
|
||||
index,
|
||||
page_rec_get_nth(merge_block->frame, nth_rec),
|
||||
merge_block, cursor);
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
|
@ -3876,7 +3974,7 @@ btr_index_rec_validate(
|
|||
(ulong) rec_get_n_fields_old(rec), (ulong) n);
|
||||
|
||||
if (dump_on_error) {
|
||||
buf_page_print(page, 0);
|
||||
buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
|
||||
fputs("InnoDB: corrupt record ", stderr);
|
||||
rec_print_old(stderr, rec);
|
||||
|
|
@ -3914,7 +4012,8 @@ btr_index_rec_validate(
|
|||
(ulong) i, (ulong) len, (ulong) fixed_size);
|
||||
|
||||
if (dump_on_error) {
|
||||
buf_page_print(page, 0);
|
||||
buf_page_print(page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
|
||||
fputs("InnoDB: corrupt record ", stderr);
|
||||
rec_print_new(stderr, rec, offsets);
|
||||
|
|
@ -4124,8 +4223,8 @@ loop:
|
|||
btr_validate_report2(index, level, block, right_block);
|
||||
fputs("InnoDB: broken FIL_PAGE_NEXT"
|
||||
" or FIL_PAGE_PREV links\n", stderr);
|
||||
buf_page_print(page, 0);
|
||||
buf_page_print(right_page, 0);
|
||||
buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(right_page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
|
||||
ret = FALSE;
|
||||
}
|
||||
|
|
@ -4134,8 +4233,8 @@ loop:
|
|||
!= page_is_comp(page))) {
|
||||
btr_validate_report2(index, level, block, right_block);
|
||||
fputs("InnoDB: 'compact' flag mismatch\n", stderr);
|
||||
buf_page_print(page, 0);
|
||||
buf_page_print(right_page, 0);
|
||||
buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(right_page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
|
||||
ret = FALSE;
|
||||
|
||||
|
|
@ -4158,8 +4257,8 @@ loop:
|
|||
fputs("InnoDB: records in wrong order"
|
||||
" on adjacent pages\n", stderr);
|
||||
|
||||
buf_page_print(page, 0);
|
||||
buf_page_print(right_page, 0);
|
||||
buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(right_page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
|
||||
fputs("InnoDB: record ", stderr);
|
||||
rec = page_rec_get_prev(page_get_supremum_rec(page));
|
||||
|
|
@ -4208,8 +4307,8 @@ loop:
|
|||
fputs("InnoDB: node pointer to the page is wrong\n",
|
||||
stderr);
|
||||
|
||||
buf_page_print(father_page, 0);
|
||||
buf_page_print(page, 0);
|
||||
buf_page_print(father_page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
|
||||
fputs("InnoDB: node ptr ", stderr);
|
||||
rec_print(stderr, node_ptr, index);
|
||||
|
|
@ -4241,8 +4340,10 @@ loop:
|
|||
|
||||
btr_validate_report1(index, level, block);
|
||||
|
||||
buf_page_print(father_page, 0);
|
||||
buf_page_print(page, 0);
|
||||
buf_page_print(father_page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
|
||||
fputs("InnoDB: Error: node ptrs differ"
|
||||
" on levels > 0\n"
|
||||
|
|
@ -4287,9 +4388,15 @@ loop:
|
|||
btr_validate_report1(index, level,
|
||||
block);
|
||||
|
||||
buf_page_print(father_page, 0);
|
||||
buf_page_print(page, 0);
|
||||
buf_page_print(right_page, 0);
|
||||
buf_page_print(
|
||||
father_page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(
|
||||
page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(
|
||||
right_page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
}
|
||||
} else {
|
||||
page_t* right_father_page
|
||||
|
|
@ -4307,10 +4414,18 @@ loop:
|
|||
btr_validate_report1(index, level,
|
||||
block);
|
||||
|
||||
buf_page_print(father_page, 0);
|
||||
buf_page_print(right_father_page, 0);
|
||||
buf_page_print(page, 0);
|
||||
buf_page_print(right_page, 0);
|
||||
buf_page_print(
|
||||
father_page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(
|
||||
right_father_page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(
|
||||
page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(
|
||||
right_page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
}
|
||||
|
||||
if (page_get_page_no(right_father_page)
|
||||
|
|
@ -4324,10 +4439,18 @@ loop:
|
|||
btr_validate_report1(index, level,
|
||||
block);
|
||||
|
||||
buf_page_print(father_page, 0);
|
||||
buf_page_print(right_father_page, 0);
|
||||
buf_page_print(page, 0);
|
||||
buf_page_print(right_page, 0);
|
||||
buf_page_print(
|
||||
father_page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(
|
||||
right_father_page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(
|
||||
page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
buf_page_print(
|
||||
right_page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4372,6 +4495,12 @@ btr_validate_index(
|
|||
mtr_x_lock(dict_index_get_lock(index), &mtr);
|
||||
|
||||
root = btr_root_get(index, &mtr);
|
||||
|
||||
if (UNIV_UNLIKELY(srv_pass_corrupt_table && !root)) {
|
||||
mtr_commit(&mtr);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
n = btr_page_get_level(root, &mtr);
|
||||
|
||||
for (i = 0; i <= n && !trx_is_interrupted(trx); i++) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, Google Inc.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
|
|
@ -18,8 +18,8 @@ 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., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
|
|
@ -438,7 +438,12 @@ btr_cur_search_to_nth_level(
|
|||
ut_ad(dict_index_check_search_tuple(index, tuple));
|
||||
ut_ad(!dict_index_is_ibuf(index) || ibuf_inside(mtr));
|
||||
ut_ad(dtuple_check_typed(tuple));
|
||||
ut_ad(index->page != FIL_NULL);
|
||||
|
||||
UNIV_MEM_INVALID(&cursor->up_match, sizeof cursor->up_match);
|
||||
UNIV_MEM_INVALID(&cursor->up_bytes, sizeof cursor->up_bytes);
|
||||
UNIV_MEM_INVALID(&cursor->low_match, sizeof cursor->low_match);
|
||||
UNIV_MEM_INVALID(&cursor->low_bytes, sizeof cursor->low_bytes);
|
||||
#ifdef UNIV_DEBUG
|
||||
cursor->up_match = ULINT_UNDEFINED;
|
||||
cursor->low_match = ULINT_UNDEFINED;
|
||||
|
|
@ -810,11 +815,11 @@ retry_page_get:
|
|||
|
||||
if (level != 0) {
|
||||
/* x-latch the page */
|
||||
page = btr_page_get(
|
||||
buf_block_t* child_block = btr_block_get(
|
||||
space, zip_size, page_no, RW_X_LATCH, index, mtr);
|
||||
|
||||
ut_a((ibool)!!page_is_comp(page)
|
||||
== dict_table_is_comp(index->table));
|
||||
page = buf_block_get_frame(child_block);
|
||||
btr_assert_not_corrupted(child_block, index);
|
||||
} else {
|
||||
cursor->low_match = low_match;
|
||||
cursor->low_bytes = low_bytes;
|
||||
|
|
@ -1959,7 +1964,7 @@ btr_cur_update_in_place(
|
|||
page_zip = buf_block_get_page_zip(block);
|
||||
|
||||
/* Check that enough space is available on the compressed page. */
|
||||
if (UNIV_LIKELY_NULL(page_zip)
|
||||
if (page_zip
|
||||
&& !btr_cur_update_alloc_zip(page_zip, block, index,
|
||||
rec_offs_size(offsets), FALSE, mtr)) {
|
||||
return(DB_ZIP_OVERFLOW);
|
||||
|
|
@ -2158,7 +2163,7 @@ any_extern:
|
|||
ut_a(!page_zip || page_zip_validate(page_zip, page));
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)
|
||||
if (page_zip
|
||||
&& !btr_cur_update_alloc_zip(page_zip, block, index,
|
||||
new_rec_size, TRUE, mtr)) {
|
||||
err = DB_ZIP_OVERFLOW;
|
||||
|
|
@ -2321,7 +2326,9 @@ btr_cur_pessimistic_update(
|
|||
/*=======================*/
|
||||
ulint flags, /*!< in: undo logging, locking, and rollback
|
||||
flags */
|
||||
btr_cur_t* cursor, /*!< in: cursor on the record to update */
|
||||
btr_cur_t* cursor, /*!< in/out: cursor on the record to update;
|
||||
cursor may become invalid if *big_rec == NULL
|
||||
|| !(flags & BTR_KEEP_POS_FLAG) */
|
||||
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
|
||||
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
|
||||
be stored externally by the caller, or NULL */
|
||||
|
|
@ -2463,10 +2470,10 @@ btr_cur_pessimistic_update(
|
|||
record to be inserted: we have to remember which fields were such */
|
||||
|
||||
ut_ad(!page_is_comp(page) || !rec_get_node_ptr_flag(rec));
|
||||
offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, heap);
|
||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||
n_ext += btr_push_update_extern_fields(new_entry, update, *heap);
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
if (page_zip) {
|
||||
ut_ad(page_is_comp(page));
|
||||
if (page_zip_rec_needs_ext(
|
||||
rec_get_converted_size(index, new_entry, n_ext),
|
||||
|
|
@ -2486,6 +2493,10 @@ make_external:
|
|||
err = DB_TOO_BIG_RECORD;
|
||||
goto return_after_reservations;
|
||||
}
|
||||
|
||||
ut_ad(page_is_leaf(page));
|
||||
ut_ad(dict_index_is_clust(index));
|
||||
ut_ad(flags & BTR_KEEP_POS_FLAG);
|
||||
}
|
||||
|
||||
if (trx->fake_changes) {
|
||||
|
|
@ -2519,6 +2530,8 @@ make_external:
|
|||
rec = btr_cur_insert_if_possible(cursor, new_entry, n_ext, mtr);
|
||||
|
||||
if (rec) {
|
||||
page_cursor->rec = rec;
|
||||
|
||||
lock_rec_restore_from_page_infimum(btr_cur_get_block(cursor),
|
||||
rec, block);
|
||||
|
||||
|
|
@ -2532,7 +2545,10 @@ make_external:
|
|||
rec, index, offsets, mtr);
|
||||
}
|
||||
|
||||
btr_cur_compress_if_useful(cursor, mtr);
|
||||
btr_cur_compress_if_useful(
|
||||
cursor,
|
||||
big_rec_vec != NULL && (flags & BTR_KEEP_POS_FLAG),
|
||||
mtr);
|
||||
|
||||
if (page_zip && !dict_index_is_clust(index)
|
||||
&& page_is_leaf(page)) {
|
||||
|
|
@ -2552,6 +2568,21 @@ make_external:
|
|||
}
|
||||
}
|
||||
|
||||
if (big_rec_vec) {
|
||||
ut_ad(page_is_leaf(page));
|
||||
ut_ad(dict_index_is_clust(index));
|
||||
ut_ad(flags & BTR_KEEP_POS_FLAG);
|
||||
|
||||
/* btr_page_split_and_insert() in
|
||||
btr_cur_pessimistic_insert() invokes
|
||||
mtr_memo_release(mtr, index->lock, MTR_MEMO_X_LOCK).
|
||||
We must keep the index->lock when we created a
|
||||
big_rec, so that row_upd_clust_rec() can store the
|
||||
big_rec in the same mini-transaction. */
|
||||
|
||||
mtr_x_lock(dict_index_get_lock(index), mtr);
|
||||
}
|
||||
|
||||
/* Was the record to be updated positioned as the first user
|
||||
record on its page? */
|
||||
was_first = page_cur_is_before_first(page_cursor);
|
||||
|
|
@ -2567,6 +2598,7 @@ make_external:
|
|||
ut_a(rec);
|
||||
ut_a(err == DB_SUCCESS);
|
||||
ut_a(dummy_big_rec == NULL);
|
||||
page_cursor->rec = rec;
|
||||
|
||||
if (dict_index_is_sec_or_ibuf(index)) {
|
||||
/* Update PAGE_MAX_TRX_ID in the index page header.
|
||||
|
|
@ -3011,10 +3043,12 @@ UNIV_INTERN
|
|||
ibool
|
||||
btr_cur_compress_if_useful(
|
||||
/*=======================*/
|
||||
btr_cur_t* cursor, /*!< in: cursor on the page to compress;
|
||||
cursor does not stay valid if compression
|
||||
occurs */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
btr_cur_t* cursor, /*!< in/out: cursor on the page to compress;
|
||||
cursor does not stay valid if !adjust and
|
||||
compression occurs */
|
||||
ibool adjust, /*!< in: TRUE if should adjust the
|
||||
cursor position even if compression occurs */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
ut_ad(mtr_memo_contains(mtr,
|
||||
dict_index_get_lock(btr_cur_get_index(cursor)),
|
||||
|
|
@ -3023,7 +3057,7 @@ btr_cur_compress_if_useful(
|
|||
MTR_MEMO_PAGE_X_FIX));
|
||||
|
||||
return(btr_cur_compress_recommendation(cursor, mtr)
|
||||
&& btr_compress(cursor, mtr));
|
||||
&& btr_compress(cursor, adjust, mtr));
|
||||
}
|
||||
|
||||
/*******************************************************//**
|
||||
|
|
@ -3270,7 +3304,7 @@ return_after_reservations:
|
|||
mem_heap_free(heap);
|
||||
|
||||
if (ret == FALSE) {
|
||||
ret = btr_cur_compress_if_useful(cursor, mtr);
|
||||
ret = btr_cur_compress_if_useful(cursor, FALSE, mtr);
|
||||
}
|
||||
|
||||
if (n_extents > 0) {
|
||||
|
|
@ -4011,10 +4045,10 @@ btr_cur_set_ownership_of_extern_field(
|
|||
byte_val = byte_val | BTR_EXTERN_OWNER_FLAG;
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
if (page_zip) {
|
||||
mach_write_to_1(data + local_len + BTR_EXTERN_LEN, byte_val);
|
||||
page_zip_write_blob_ptr(page_zip, rec, index, offsets, i, mtr);
|
||||
} else if (UNIV_LIKELY(mtr != NULL)) {
|
||||
} else if (mtr != NULL) {
|
||||
|
||||
mlog_write_ulint(data + local_len + BTR_EXTERN_LEN, byte_val,
|
||||
MLOG_1BYTE, mtr);
|
||||
|
|
@ -4253,9 +4287,9 @@ The fields are stored on pages allocated from leaf node
|
|||
file segment of the index tree.
|
||||
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_store_big_rec_extern_fields_func(
|
||||
/*=================================*/
|
||||
enum db_err
|
||||
btr_store_big_rec_extern_fields(
|
||||
/*============================*/
|
||||
dict_index_t* index, /*!< in: index of rec; the index tree
|
||||
MUST be X-latched */
|
||||
buf_block_t* rec_block, /*!< in/out: block containing rec */
|
||||
|
|
@ -4264,38 +4298,37 @@ btr_store_big_rec_extern_fields_func(
|
|||
the "external storage" flags in offsets
|
||||
will not correspond to rec when
|
||||
this function returns */
|
||||
#ifdef UNIV_DEBUG
|
||||
mtr_t* local_mtr, /*!< in: mtr containing the
|
||||
latch to rec and to the tree */
|
||||
#endif /* UNIV_DEBUG */
|
||||
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
|
||||
ibool update_in_place,/*! in: TRUE if the record is updated
|
||||
in place (not delete+insert) */
|
||||
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
|
||||
const big_rec_t*big_rec_vec) /*!< in: vector containing fields
|
||||
const big_rec_t*big_rec_vec, /*!< in: vector containing fields
|
||||
to be stored externally */
|
||||
|
||||
mtr_t* btr_mtr, /*!< in: mtr containing the
|
||||
latches to the clustered index */
|
||||
enum blob_op op) /*! in: operation code */
|
||||
{
|
||||
ulint rec_page_no;
|
||||
byte* field_ref;
|
||||
ulint extern_len;
|
||||
ulint store_len;
|
||||
ulint page_no;
|
||||
ulint space_id;
|
||||
ulint zip_size;
|
||||
ulint prev_page_no;
|
||||
ulint hint_page_no;
|
||||
ulint i;
|
||||
mtr_t mtr;
|
||||
mem_heap_t* heap = NULL;
|
||||
ulint rec_page_no;
|
||||
byte* field_ref;
|
||||
ulint extern_len;
|
||||
ulint store_len;
|
||||
ulint page_no;
|
||||
ulint space_id;
|
||||
ulint zip_size;
|
||||
ulint prev_page_no;
|
||||
ulint hint_page_no;
|
||||
ulint i;
|
||||
mtr_t mtr;
|
||||
mtr_t* alloc_mtr;
|
||||
mem_heap_t* heap = NULL;
|
||||
page_zip_des_t* page_zip;
|
||||
z_stream c_stream;
|
||||
z_stream c_stream;
|
||||
buf_block_t** freed_pages = NULL;
|
||||
ulint n_freed_pages = 0;
|
||||
enum db_err error = DB_SUCCESS;
|
||||
|
||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||
ut_ad(rec_offs_any_extern(offsets));
|
||||
ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
|
||||
ut_ad(btr_mtr);
|
||||
ut_ad(mtr_memo_contains(btr_mtr, dict_index_get_lock(index),
|
||||
MTR_MEMO_X_LOCK));
|
||||
ut_ad(mtr_memo_contains(local_mtr, rec_block, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(mtr_memo_contains(btr_mtr, rec_block, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(buf_block_get_frame(rec_block) == page_align(rec));
|
||||
ut_a(dict_index_is_clust(index));
|
||||
|
||||
|
|
@ -4308,7 +4341,7 @@ btr_store_big_rec_extern_fields_func(
|
|||
rec_page_no = buf_block_get_page_no(rec_block);
|
||||
ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
if (page_zip) {
|
||||
int err;
|
||||
|
||||
/* Zlib deflate needs 128 kilobytes for the default
|
||||
|
|
@ -4324,6 +4357,42 @@ btr_store_big_rec_extern_fields_func(
|
|||
ut_a(err == Z_OK);
|
||||
}
|
||||
|
||||
if (btr_blob_op_is_update(op)) {
|
||||
/* Avoid reusing pages that have been previously freed
|
||||
in btr_mtr. */
|
||||
if (btr_mtr->n_freed_pages) {
|
||||
if (heap == NULL) {
|
||||
heap = mem_heap_create(
|
||||
btr_mtr->n_freed_pages
|
||||
* sizeof *freed_pages);
|
||||
}
|
||||
|
||||
freed_pages = mem_heap_alloc(
|
||||
heap,
|
||||
btr_mtr->n_freed_pages
|
||||
* sizeof *freed_pages);
|
||||
n_freed_pages = 0;
|
||||
}
|
||||
|
||||
/* Because btr_mtr will be committed after mtr, it is
|
||||
possible that the tablespace has been extended when
|
||||
the B-tree record was updated or inserted, or it will
|
||||
be extended while allocating pages for big_rec.
|
||||
|
||||
TODO: In mtr (not btr_mtr), write a redo log record
|
||||
about extending the tablespace to its current size,
|
||||
and remember the current size. Whenever the tablespace
|
||||
grows as pages are allocated, write further redo log
|
||||
records to mtr. (Currently tablespace extension is not
|
||||
covered by the redo log. If it were, the record would
|
||||
only be written to btr_mtr, which is committed after
|
||||
mtr.) */
|
||||
alloc_mtr = btr_mtr;
|
||||
} else {
|
||||
/* Use the local mtr for allocations. */
|
||||
alloc_mtr = &mtr;
|
||||
}
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
|
||||
/* All pointers to externally stored columns in the record
|
||||
must either be zero or they must be pointers to inherited
|
||||
|
|
@ -4338,7 +4407,7 @@ btr_store_big_rec_extern_fields_func(
|
|||
/* Either this must be an update in place,
|
||||
or the BLOB must be inherited, or the BLOB pointer
|
||||
must be zero (will be written in this function). */
|
||||
ut_a(update_in_place
|
||||
ut_a(op == BTR_STORE_UPDATE
|
||||
|| (field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG)
|
||||
|| !memcmp(field_ref, field_ref_zero,
|
||||
BTR_EXTERN_FIELD_REF_SIZE));
|
||||
|
|
@ -4363,7 +4432,7 @@ btr_store_big_rec_extern_fields_func(
|
|||
|
||||
prev_page_no = FIL_NULL;
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
if (page_zip) {
|
||||
int err = deflateReset(&c_stream);
|
||||
ut_a(err == Z_OK);
|
||||
|
||||
|
|
@ -4383,18 +4452,24 @@ btr_store_big_rec_extern_fields_func(
|
|||
hint_page_no = prev_page_no + 1;
|
||||
}
|
||||
|
||||
alloc_another:
|
||||
block = btr_page_alloc(index, hint_page_no,
|
||||
FSP_NO_DIR, 0, &mtr);
|
||||
FSP_NO_DIR, 0, alloc_mtr, &mtr);
|
||||
if (UNIV_UNLIKELY(block == NULL)) {
|
||||
|
||||
mtr_commit(&mtr);
|
||||
error = DB_OUT_OF_FILE_SPACE;
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
deflateEnd(&c_stream);
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
return(DB_OUT_OF_FILE_SPACE);
|
||||
if (rw_lock_get_x_lock_count(&block->lock) > 1) {
|
||||
/* This page must have been freed in
|
||||
btr_mtr previously. Put it aside, and
|
||||
allocate another page for the BLOB data. */
|
||||
ut_ad(alloc_mtr == btr_mtr);
|
||||
ut_ad(btr_blob_op_is_update(op));
|
||||
ut_ad(n_freed_pages < btr_mtr->n_freed_pages);
|
||||
freed_pages[n_freed_pages++] = block;
|
||||
goto alloc_another;
|
||||
}
|
||||
|
||||
page_no = buf_block_get_page_no(block);
|
||||
|
|
@ -4411,7 +4486,7 @@ btr_store_big_rec_extern_fields_func(
|
|||
SYNC_EXTERN_STORAGE);
|
||||
prev_page = buf_block_get_frame(prev_block);
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
if (page_zip) {
|
||||
mlog_write_ulint(
|
||||
prev_page + FIL_PAGE_NEXT,
|
||||
page_no, MLOG_4BYTES, &mtr);
|
||||
|
|
@ -4428,7 +4503,7 @@ btr_store_big_rec_extern_fields_func(
|
|||
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
if (page_zip) {
|
||||
int err;
|
||||
page_zip_des_t* blob_page_zip;
|
||||
|
||||
|
|
@ -4511,11 +4586,15 @@ btr_store_big_rec_extern_fields_func(
|
|||
goto next_zip_page;
|
||||
}
|
||||
|
||||
rec_block = buf_page_get(space_id, zip_size,
|
||||
rec_page_no,
|
||||
RW_X_LATCH, &mtr);
|
||||
buf_block_dbg_add_level(rec_block,
|
||||
SYNC_NO_ORDER_CHECK);
|
||||
if (alloc_mtr == &mtr) {
|
||||
rec_block = buf_page_get(
|
||||
space_id, zip_size,
|
||||
rec_page_no,
|
||||
RW_X_LATCH, &mtr);
|
||||
buf_block_dbg_add_level(
|
||||
rec_block,
|
||||
SYNC_NO_ORDER_CHECK);
|
||||
}
|
||||
|
||||
if (err == Z_STREAM_END) {
|
||||
mach_write_to_4(field_ref
|
||||
|
|
@ -4549,7 +4628,8 @@ btr_store_big_rec_extern_fields_func(
|
|||
|
||||
page_zip_write_blob_ptr(
|
||||
page_zip, rec, index, offsets,
|
||||
big_rec_vec->fields[i].field_no, &mtr);
|
||||
big_rec_vec->fields[i].field_no,
|
||||
alloc_mtr);
|
||||
|
||||
next_zip_page:
|
||||
prev_page_no = page_no;
|
||||
|
|
@ -4594,19 +4674,23 @@ next_zip_page:
|
|||
|
||||
extern_len -= store_len;
|
||||
|
||||
rec_block = buf_page_get(space_id, zip_size,
|
||||
rec_page_no,
|
||||
RW_X_LATCH, &mtr);
|
||||
buf_block_dbg_add_level(rec_block,
|
||||
SYNC_NO_ORDER_CHECK);
|
||||
if (alloc_mtr == &mtr) {
|
||||
rec_block = buf_page_get(
|
||||
space_id, zip_size,
|
||||
rec_page_no,
|
||||
RW_X_LATCH, &mtr);
|
||||
buf_block_dbg_add_level(
|
||||
rec_block,
|
||||
SYNC_NO_ORDER_CHECK);
|
||||
}
|
||||
|
||||
mlog_write_ulint(field_ref + BTR_EXTERN_LEN, 0,
|
||||
MLOG_4BYTES, &mtr);
|
||||
MLOG_4BYTES, alloc_mtr);
|
||||
mlog_write_ulint(field_ref
|
||||
+ BTR_EXTERN_LEN + 4,
|
||||
big_rec_vec->fields[i].len
|
||||
- extern_len,
|
||||
MLOG_4BYTES, &mtr);
|
||||
MLOG_4BYTES, alloc_mtr);
|
||||
|
||||
if (prev_page_no == FIL_NULL) {
|
||||
btr_blob_dbg_add_blob(
|
||||
|
|
@ -4616,18 +4700,19 @@ next_zip_page:
|
|||
|
||||
mlog_write_ulint(field_ref
|
||||
+ BTR_EXTERN_SPACE_ID,
|
||||
space_id,
|
||||
MLOG_4BYTES, &mtr);
|
||||
space_id, MLOG_4BYTES,
|
||||
alloc_mtr);
|
||||
|
||||
mlog_write_ulint(field_ref
|
||||
+ BTR_EXTERN_PAGE_NO,
|
||||
page_no,
|
||||
MLOG_4BYTES, &mtr);
|
||||
page_no, MLOG_4BYTES,
|
||||
alloc_mtr);
|
||||
|
||||
mlog_write_ulint(field_ref
|
||||
+ BTR_EXTERN_OFFSET,
|
||||
FIL_PAGE_DATA,
|
||||
MLOG_4BYTES, &mtr);
|
||||
MLOG_4BYTES,
|
||||
alloc_mtr);
|
||||
}
|
||||
|
||||
prev_page_no = page_no;
|
||||
|
|
@ -4641,8 +4726,23 @@ next_zip_page:
|
|||
}
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY_NULL(page_zip)) {
|
||||
func_exit:
|
||||
if (page_zip) {
|
||||
deflateEnd(&c_stream);
|
||||
}
|
||||
|
||||
if (n_freed_pages) {
|
||||
ulint i;
|
||||
|
||||
ut_ad(alloc_mtr == btr_mtr);
|
||||
ut_ad(btr_blob_op_is_update(op));
|
||||
|
||||
for (i = 0; i < n_freed_pages; i++) {
|
||||
btr_page_free_low(index, freed_pages[i], 0, alloc_mtr);
|
||||
}
|
||||
}
|
||||
|
||||
if (heap != NULL) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
|
|
@ -4663,7 +4763,7 @@ next_zip_page:
|
|||
ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
|
||||
}
|
||||
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
|
||||
return(DB_SUCCESS);
|
||||
return(error);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
|
|
@ -4866,7 +4966,7 @@ btr_free_externally_stored_field(
|
|||
|
||||
btr_page_free_low(index, ext_block, 0, &mtr);
|
||||
|
||||
if (UNIV_LIKELY(page_zip != NULL)) {
|
||||
if (page_zip) {
|
||||
mach_write_to_4(field_ref + BTR_EXTERN_PAGE_NO,
|
||||
next_page_no);
|
||||
mach_write_to_4(field_ref + BTR_EXTERN_LEN + 4,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
|
@ -52,12 +52,13 @@ btr_pcur_create_for_mysql(void)
|
|||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Frees the memory for a persistent cursor object. */
|
||||
Resets a persistent cursor object, freeing ::old_rec_buf if it is
|
||||
allocated and resetting the other members to their initial values. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_free_for_mysql(
|
||||
/*====================*/
|
||||
btr_pcur_t* cursor) /*!< in, own: persistent cursor */
|
||||
btr_pcur_reset(
|
||||
/*===========*/
|
||||
btr_pcur_t* cursor) /*!< in, out: persistent cursor */
|
||||
{
|
||||
if (cursor->old_rec_buf != NULL) {
|
||||
|
||||
|
|
@ -66,6 +67,7 @@ btr_pcur_free_for_mysql(
|
|||
cursor->old_rec_buf = NULL;
|
||||
}
|
||||
|
||||
cursor->btr_cur.index = NULL;
|
||||
cursor->btr_cur.page_cur.rec = NULL;
|
||||
cursor->old_rec = NULL;
|
||||
cursor->old_n_fields = 0;
|
||||
|
|
@ -73,7 +75,17 @@ btr_pcur_free_for_mysql(
|
|||
|
||||
cursor->latch_mode = BTR_NO_LATCHES;
|
||||
cursor->pos_state = BTR_PCUR_NOT_POSITIONED;
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
Frees the memory for a persistent cursor object. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_free_for_mysql(
|
||||
/*====================*/
|
||||
btr_pcur_t* cursor) /*!< in, own: persistent cursor */
|
||||
{
|
||||
btr_pcur_reset(cursor);
|
||||
mem_free(cursor);
|
||||
}
|
||||
|
||||
|
|
@ -127,6 +139,8 @@ btr_pcur_store_position(
|
|||
|
||||
ut_a(btr_page_get_next(page, mtr) == FIL_NULL);
|
||||
ut_a(btr_page_get_prev(page, mtr) == FIL_NULL);
|
||||
ut_ad(page_is_leaf(page));
|
||||
ut_ad(page_get_page_no(page) == index->page);
|
||||
|
||||
cursor->old_stored = BTR_PCUR_OLD_STORED;
|
||||
|
||||
|
|
@ -319,13 +333,19 @@ btr_pcur_restore_position_func(
|
|||
/* Save the old search mode of the cursor */
|
||||
old_mode = cursor->search_mode;
|
||||
|
||||
if (UNIV_LIKELY(cursor->rel_pos == BTR_PCUR_ON)) {
|
||||
switch (cursor->rel_pos) {
|
||||
case BTR_PCUR_ON:
|
||||
mode = PAGE_CUR_LE;
|
||||
} else if (cursor->rel_pos == BTR_PCUR_AFTER) {
|
||||
break;
|
||||
case BTR_PCUR_AFTER:
|
||||
mode = PAGE_CUR_G;
|
||||
} else {
|
||||
ut_ad(cursor->rel_pos == BTR_PCUR_BEFORE);
|
||||
break;
|
||||
case BTR_PCUR_BEFORE:
|
||||
mode = PAGE_CUR_L;
|
||||
break;
|
||||
default:
|
||||
ut_error;
|
||||
mode = 0;
|
||||
}
|
||||
|
||||
btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode,
|
||||
|
|
@ -334,25 +354,44 @@ btr_pcur_restore_position_func(
|
|||
/* Restore the old search mode */
|
||||
cursor->search_mode = old_mode;
|
||||
|
||||
if (cursor->rel_pos == BTR_PCUR_ON
|
||||
&& btr_pcur_is_on_user_rec(cursor)
|
||||
&& 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor),
|
||||
rec_get_offsets(
|
||||
btr_pcur_get_rec(cursor), index,
|
||||
NULL, ULINT_UNDEFINED, &heap))) {
|
||||
if (btr_pcur_is_on_user_rec(cursor)) {
|
||||
switch (cursor->rel_pos) {
|
||||
case BTR_PCUR_ON:
|
||||
if (!cmp_dtuple_rec(
|
||||
tuple, btr_pcur_get_rec(cursor),
|
||||
rec_get_offsets(btr_pcur_get_rec(cursor),
|
||||
index, NULL,
|
||||
ULINT_UNDEFINED, &heap))) {
|
||||
|
||||
/* We have to store the NEW value for the modify clock, since
|
||||
the cursor can now be on a different page! But we can retain
|
||||
the value of old_rec */
|
||||
/* We have to store the NEW value for
|
||||
the modify clock, since the cursor can
|
||||
now be on a different page! But we can
|
||||
retain the value of old_rec */
|
||||
|
||||
cursor->block_when_stored = btr_pcur_get_block(cursor);
|
||||
cursor->modify_clock = buf_block_get_modify_clock(
|
||||
cursor->block_when_stored);
|
||||
cursor->old_stored = BTR_PCUR_OLD_STORED;
|
||||
cursor->block_when_stored =
|
||||
btr_pcur_get_block(cursor);
|
||||
cursor->modify_clock =
|
||||
buf_block_get_modify_clock(
|
||||
cursor->block_when_stored);
|
||||
cursor->old_stored = BTR_PCUR_OLD_STORED;
|
||||
|
||||
mem_heap_free(heap);
|
||||
mem_heap_free(heap);
|
||||
|
||||
return(TRUE);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
break;
|
||||
case BTR_PCUR_BEFORE:
|
||||
page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
|
||||
break;
|
||||
case BTR_PCUR_AFTER:
|
||||
page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
|
||||
break;
|
||||
#ifdef UNIV_DEBUG
|
||||
default:
|
||||
ut_error;
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
||||
}
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, Google Inc.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
|
|
@ -1240,7 +1240,7 @@ cleanup:
|
|||
index->name, (ulong) block->n_pointers);
|
||||
rw_lock_x_unlock(btr_search_get_latch(index->id));
|
||||
|
||||
btr_search_validate();
|
||||
ut_ad(btr_search_validate());
|
||||
} else {
|
||||
rw_lock_x_unlock(btr_search_get_latch(index->id));
|
||||
}
|
||||
|
|
@ -2143,7 +2143,9 @@ btr_search_validate(void)
|
|||
(ulong) block->curr_left_side);
|
||||
|
||||
if (n_page_dumps < 20) {
|
||||
buf_page_print(page, 0);
|
||||
buf_page_print(
|
||||
page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
n_page_dumps++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, Google Inc.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
|
|
@ -57,7 +57,9 @@ Created 11/5/1995 Heikki Tuuri
|
|||
/* prototypes for new functions added to ha_innodb.cc */
|
||||
trx_t* innobase_get_trx();
|
||||
|
||||
static inline void _increment_page_get_statistics(buf_block_t* block, trx_t* trx)
|
||||
static inline
|
||||
void
|
||||
_increment_page_get_statistics(buf_block_t* block, trx_t* trx)
|
||||
{
|
||||
ulint block_hash;
|
||||
ulint block_hash_byte;
|
||||
|
|
@ -680,8 +682,12 @@ void
|
|||
buf_page_print(
|
||||
/*===========*/
|
||||
const byte* read_buf, /*!< in: a database page */
|
||||
ulint zip_size) /*!< in: compressed page size, or
|
||||
0 for uncompressed pages */
|
||||
ulint zip_size, /*!< in: compressed page size, or
|
||||
0 for uncompressed pages */
|
||||
ulint flags) /*!< in: 0 or
|
||||
BUF_PAGE_PRINT_NO_CRASH or
|
||||
BUF_PAGE_PRINT_NO_FULL */
|
||||
|
||||
{
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
dict_index_t* index;
|
||||
|
|
@ -695,11 +701,14 @@ buf_page_print(
|
|||
size = UNIV_PAGE_SIZE;
|
||||
}
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr, " InnoDB: Page dump in ascii and hex (%lu bytes):\n",
|
||||
(ulong) size);
|
||||
ut_print_buf(stderr, read_buf, size);
|
||||
fputs("\nInnoDB: End of page dump\n", stderr);
|
||||
if (!(flags & BUF_PAGE_PRINT_NO_FULL)) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Page dump in ascii and hex (%lu bytes):\n",
|
||||
(ulong) size);
|
||||
ut_print_buf(stderr, read_buf, size);
|
||||
fputs("\nInnoDB: End of page dump\n", stderr);
|
||||
}
|
||||
|
||||
if (zip_size) {
|
||||
/* Print compressed page. */
|
||||
|
|
@ -873,6 +882,8 @@ buf_page_print(
|
|||
stderr);
|
||||
break;
|
||||
}
|
||||
|
||||
ut_ad(flags & BUF_PAGE_PRINT_NO_CRASH);
|
||||
}
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
|
|
@ -1078,11 +1089,8 @@ buf_chunk_init(
|
|||
for (i = chunk->size; i--; ) {
|
||||
|
||||
buf_block_init(buf_pool, block, frame);
|
||||
UNIV_MEM_INVALID(block->frame, UNIV_PAGE_SIZE);
|
||||
|
||||
#ifdef HAVE_valgrind
|
||||
/* Wipe contents of frame to eliminate a Purify warning */
|
||||
memset(block->frame, '\0', UNIV_PAGE_SIZE);
|
||||
#endif
|
||||
/* Add the block to the free list */
|
||||
mutex_enter(&buf_pool->free_list_mutex);
|
||||
UT_LIST_ADD_LAST(free, buf_pool->free, (&block->page));
|
||||
|
|
@ -2768,7 +2776,7 @@ wait_until_unfixed:
|
|||
|
||||
block->page.buf_fix_count = 1;
|
||||
buf_block_set_io_fix(block, BUF_IO_READ);
|
||||
rw_lock_x_lock_func(&block->lock, 0, file, line);
|
||||
rw_lock_x_lock_inline(&block->lock, 0, file, line);
|
||||
|
||||
UNIV_MEM_INVALID(bpage, sizeof *bpage);
|
||||
|
||||
|
|
@ -2931,14 +2939,14 @@ wait_until_unfixed:
|
|||
break;
|
||||
|
||||
case RW_S_LATCH:
|
||||
rw_lock_s_lock_func(&(block->lock), 0, file, line);
|
||||
rw_lock_s_lock_inline(&(block->lock), 0, file, line);
|
||||
|
||||
fix_type = MTR_MEMO_PAGE_S_FIX;
|
||||
break;
|
||||
|
||||
default:
|
||||
ut_ad(rw_latch == RW_X_LATCH);
|
||||
rw_lock_x_lock_func(&(block->lock), 0, file, line);
|
||||
rw_lock_x_lock_inline(&(block->lock), 0, file, line);
|
||||
|
||||
fix_type = MTR_MEMO_PAGE_X_FIX;
|
||||
break;
|
||||
|
|
@ -3023,8 +3031,8 @@ buf_page_optimistic_get(
|
|||
file, line);
|
||||
fix_type = MTR_MEMO_PAGE_S_FIX;
|
||||
} else {
|
||||
success = rw_lock_x_lock_func_nowait(&(block->lock),
|
||||
file, line);
|
||||
success = rw_lock_x_lock_func_nowait_inline(&(block->lock),
|
||||
file, line);
|
||||
fix_type = MTR_MEMO_PAGE_X_FIX;
|
||||
}
|
||||
|
||||
|
|
@ -3165,8 +3173,8 @@ buf_page_get_known_nowait(
|
|||
file, line);
|
||||
fix_type = MTR_MEMO_PAGE_S_FIX;
|
||||
} else {
|
||||
success = rw_lock_x_lock_func_nowait(&(block->lock),
|
||||
file, line);
|
||||
success = rw_lock_x_lock_func_nowait_inline(&(block->lock),
|
||||
file, line);
|
||||
fix_type = MTR_MEMO_PAGE_X_FIX;
|
||||
}
|
||||
|
||||
|
|
@ -3186,7 +3194,7 @@ buf_page_get_known_nowait(
|
|||
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
|
||||
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
ut_a(block->page.file_page_was_freed == FALSE);
|
||||
ut_a(mode == BUF_KEEP_OLD || !block->page.file_page_was_freed);
|
||||
#endif
|
||||
|
||||
#ifdef UNIV_IBUF_COUNT_DEBUG
|
||||
|
|
@ -3261,8 +3269,8 @@ buf_page_try_get_func(
|
|||
S-latch. */
|
||||
|
||||
fix_type = MTR_MEMO_PAGE_X_FIX;
|
||||
success = rw_lock_x_lock_func_nowait(&block->lock,
|
||||
file, line);
|
||||
success = rw_lock_x_lock_func_nowait_inline(&block->lock,
|
||||
file, line);
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
|
|
@ -3997,7 +4005,8 @@ corrupt:
|
|||
"InnoDB: You may have to recover"
|
||||
" from a backup.\n",
|
||||
(ulong) bpage->offset);
|
||||
buf_page_print(frame, buf_page_get_zip_size(bpage));
|
||||
buf_page_print(frame, buf_page_get_zip_size(bpage),
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Database page corruption on disk"
|
||||
" or a failed\n"
|
||||
|
|
@ -5285,34 +5294,32 @@ buf_all_freed(void)
|
|||
/*********************************************************************//**
|
||||
Checks that there currently are no pending i/o-operations for the buffer
|
||||
pool.
|
||||
@return TRUE if there is no pending i/o */
|
||||
@return number of pending i/o */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_pool_check_no_pending_io(void)
|
||||
/*==============================*/
|
||||
ulint
|
||||
buf_pool_check_num_pending_io(void)
|
||||
/*===============================*/
|
||||
{
|
||||
ulint i;
|
||||
ibool ret = TRUE;
|
||||
ulint pending_io = 0;
|
||||
|
||||
buf_pool_mutex_enter_all();
|
||||
|
||||
for (i = 0; i < srv_buf_pool_instances && ret; i++) {
|
||||
for (i = 0; i < srv_buf_pool_instances; i++) {
|
||||
const buf_pool_t* buf_pool;
|
||||
|
||||
buf_pool = buf_pool_from_array(i);
|
||||
|
||||
if (buf_pool->n_pend_reads
|
||||
+ buf_pool->n_flush[BUF_FLUSH_LRU]
|
||||
+ buf_pool->n_flush[BUF_FLUSH_LIST]
|
||||
+ buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]) {
|
||||
pending_io += buf_pool->n_pend_reads
|
||||
+ buf_pool->n_flush[BUF_FLUSH_LRU]
|
||||
+ buf_pool->n_flush[BUF_FLUSH_LIST]
|
||||
+ buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE];
|
||||
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
buf_pool_mutex_exit_all();
|
||||
|
||||
return(ret);
|
||||
return(pending_io);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
|||
|
|
@ -767,7 +767,8 @@ buf_flush_buffered_writes(void)
|
|||
if (UNIV_UNLIKELY
|
||||
(!page_simple_validate_new(block->frame))) {
|
||||
corrupted_page:
|
||||
buf_page_print(block->frame, 0);
|
||||
buf_page_print(block->frame, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
|
|
@ -2036,22 +2037,6 @@ buf_flush_list(
|
|||
|
||||
buf_pool = buf_pool_from_array(i);
|
||||
|
||||
if (lsn_limit != IB_ULONGLONG_MAX) {
|
||||
buf_page_t* bpage;
|
||||
|
||||
buf_flush_list_mutex_enter(buf_pool);
|
||||
bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
|
||||
if (!bpage
|
||||
|| bpage->oldest_modification >= lsn_limit) {
|
||||
|
||||
buf_flush_list_mutex_exit(buf_pool);
|
||||
continue;
|
||||
} else {
|
||||
|
||||
buf_flush_list_mutex_exit(buf_pool);
|
||||
}
|
||||
}
|
||||
|
||||
if (!buf_flush_start(buf_pool, BUF_FLUSH_LIST)) {
|
||||
/* We have two choices here. If lsn_limit was
|
||||
specified then skipping an instance of buffer
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ Created 11/5/1995 Heikki Tuuri
|
|||
#include "page0zip.h"
|
||||
#include "log0recv.h"
|
||||
#include "srv0srv.h"
|
||||
#include "srv0start.h"
|
||||
|
||||
/** The number of blocks from the LRU_old pointer onward, including
|
||||
the block pointed to, must be buf_pool->LRU_old_ratio/BUF_LRU_OLD_RATIO_DIV
|
||||
|
|
@ -371,42 +372,278 @@ next_page:
|
|||
ut_free(page_arr);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
While flushing (or removing dirty) pages from a tablespace we don't
|
||||
want to hog the CPU and resources. Release the buffer pool and block
|
||||
mutex and try to force a context switch. Then reacquire the same mutexes.
|
||||
The current page is "fixed" before the release of the mutexes and then
|
||||
"unfixed" again once we have reacquired the mutexes. */
|
||||
static
|
||||
void
|
||||
buf_flush_yield(
|
||||
/*============*/
|
||||
buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */
|
||||
buf_page_t* bpage) /*!< in/out: current page */
|
||||
{
|
||||
mutex_t* block_mutex;
|
||||
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(buf_page_in_file(bpage));
|
||||
|
||||
block_mutex = buf_page_get_mutex(bpage);
|
||||
|
||||
mutex_enter(block_mutex);
|
||||
/* "Fix" the block so that the position cannot be
|
||||
changed after we release the buffer pool and
|
||||
block mutexes. */
|
||||
buf_page_set_sticky(bpage);
|
||||
|
||||
/* Now it is safe to release the buf_pool->mutex. */
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
|
||||
mutex_exit(block_mutex);
|
||||
/* Try and force a context switch. */
|
||||
os_thread_yield();
|
||||
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
|
||||
mutex_enter(block_mutex);
|
||||
/* "Unfix" the block now that we have both the
|
||||
buffer pool and block mutex again. */
|
||||
buf_page_unset_sticky(bpage);
|
||||
mutex_exit(block_mutex);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
If we have hogged the resources for too long then release the buffer
|
||||
pool and flush list mutex and do a thread yield. Set the current page
|
||||
to "sticky" so that it is not relocated during the yield.
|
||||
@return TRUE if yielded */
|
||||
static
|
||||
ibool
|
||||
buf_flush_try_yield(
|
||||
/*================*/
|
||||
buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */
|
||||
buf_page_t* bpage, /*!< in/out: bpage to remove */
|
||||
ulint processed) /*!< in: number of pages processed */
|
||||
{
|
||||
/* Every BUF_LRU_DROP_SEARCH_SIZE iterations in the
|
||||
loop we release buf_pool->mutex to let other threads
|
||||
do their job but only if the block is not IO fixed. This
|
||||
ensures that the block stays in its position in the
|
||||
flush_list. */
|
||||
|
||||
if (bpage != NULL
|
||||
&& processed >= BUF_LRU_DROP_SEARCH_SIZE
|
||||
&& buf_page_get_io_fix(bpage) == BUF_IO_NONE) {
|
||||
|
||||
buf_flush_list_mutex_exit(buf_pool);
|
||||
|
||||
/* Release the buffer pool and block mutex
|
||||
to give the other threads a go. */
|
||||
|
||||
buf_flush_yield(buf_pool, bpage);
|
||||
|
||||
buf_flush_list_mutex_enter(buf_pool);
|
||||
|
||||
/* Should not have been removed from the flush
|
||||
list during the yield. However, this check is
|
||||
not sufficient to catch a remove -> add. */
|
||||
|
||||
ut_ad(bpage->in_flush_list);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Removes a single page from a given tablespace inside a specific
|
||||
buffer pool instance.
|
||||
@return TRUE if page was removed. */
|
||||
static
|
||||
ibool
|
||||
buf_flush_or_remove_page(
|
||||
/*=====================*/
|
||||
buf_pool_t* buf_pool, /*!< in/out: buffer pool instance */
|
||||
buf_page_t* bpage) /*!< in/out: bpage to remove */
|
||||
{
|
||||
mutex_t* block_mutex;
|
||||
ibool processed = FALSE;
|
||||
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(buf_flush_list_mutex_own(buf_pool));
|
||||
|
||||
block_mutex = buf_page_get_mutex(bpage);
|
||||
|
||||
/* bpage->space and bpage->io_fix are protected by
|
||||
buf_pool->mutex and block_mutex. It is safe to check
|
||||
them while holding buf_pool->mutex only. */
|
||||
|
||||
if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
|
||||
|
||||
/* We cannot remove this page during this scan
|
||||
yet; maybe the system is currently reading it
|
||||
in, or flushing the modifications to the file */
|
||||
|
||||
} else {
|
||||
|
||||
/* We have to release the flush_list_mutex to obey the
|
||||
latching order. We are however guaranteed that the page
|
||||
will stay in the flush_list because buf_flush_remove()
|
||||
needs buf_pool->mutex as well (for the non-flush case). */
|
||||
|
||||
buf_flush_list_mutex_exit(buf_pool);
|
||||
|
||||
mutex_enter(block_mutex);
|
||||
|
||||
ut_ad(bpage->oldest_modification != 0);
|
||||
|
||||
if (bpage->buf_fix_count == 0) {
|
||||
|
||||
buf_flush_remove(bpage);
|
||||
|
||||
processed = TRUE;
|
||||
}
|
||||
|
||||
mutex_exit(block_mutex);
|
||||
|
||||
buf_flush_list_mutex_enter(buf_pool);
|
||||
}
|
||||
|
||||
ut_ad(!mutex_own(block_mutex));
|
||||
|
||||
return(processed);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Remove all dirty pages belonging to a given tablespace inside a specific
|
||||
buffer pool instance when we are deleting the data file(s) of that
|
||||
tablespace. The pages still remain a part of LRU and are evicted from
|
||||
the list as they age towards the tail of the LRU. */
|
||||
the list as they age towards the tail of the LRU.
|
||||
@return TRUE if all freed. */
|
||||
static
|
||||
ibool
|
||||
buf_flush_or_remove_pages(
|
||||
/*======================*/
|
||||
buf_pool_t* buf_pool, /*!< buffer pool instance */
|
||||
ulint id) /*!< in: target space id for which
|
||||
to remove or flush pages */
|
||||
{
|
||||
buf_page_t* prev;
|
||||
buf_page_t* bpage;
|
||||
ulint processed = 0;
|
||||
ibool all_freed = TRUE;
|
||||
|
||||
buf_flush_list_mutex_enter(buf_pool);
|
||||
|
||||
for (bpage = UT_LIST_GET_LAST(buf_pool->flush_list);
|
||||
bpage != NULL;
|
||||
bpage = prev) {
|
||||
|
||||
ut_a(buf_page_in_file(bpage));
|
||||
ut_ad(bpage->in_flush_list);
|
||||
|
||||
/* Save the previous link because once we free the
|
||||
page we can't rely on the links. */
|
||||
|
||||
prev = UT_LIST_GET_PREV(flush_list, bpage);
|
||||
|
||||
if (buf_page_get_space(bpage) != id) {
|
||||
|
||||
/* Skip this block, as it does not belong to
|
||||
the target space. */
|
||||
|
||||
} else if (!buf_flush_or_remove_page(buf_pool, bpage)) {
|
||||
|
||||
/* Remove was unsuccessful, we have to try again
|
||||
by scanning the entire list from the end. */
|
||||
|
||||
all_freed = FALSE;
|
||||
}
|
||||
|
||||
++processed;
|
||||
|
||||
/* Yield if we have hogged the CPU and mutexes for too long. */
|
||||
if (buf_flush_try_yield(buf_pool, prev, processed)) {
|
||||
|
||||
/* Reset the batch size counter if we had to yield. */
|
||||
|
||||
processed = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
buf_flush_list_mutex_exit(buf_pool);
|
||||
|
||||
return(all_freed);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Remove or flush all the dirty pages that belong to a given tablespace
|
||||
inside a specific buffer pool instance. The pages will remain in the LRU
|
||||
list and will be evicted from the LRU list as they age and move towards
|
||||
the tail of the LRU list. */
|
||||
static
|
||||
void
|
||||
buf_LRU_remove_dirty_pages_for_tablespace(
|
||||
/*======================================*/
|
||||
buf_flush_dirty_pages(
|
||||
/*==================*/
|
||||
buf_pool_t* buf_pool, /*!< buffer pool instance */
|
||||
ulint id) /*!< in: space id */
|
||||
{
|
||||
ibool all_freed;
|
||||
|
||||
do {
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
|
||||
all_freed = buf_flush_or_remove_pages(buf_pool, id);
|
||||
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
|
||||
ut_ad(buf_flush_validate(buf_pool));
|
||||
|
||||
if (!all_freed) {
|
||||
os_thread_sleep(20000);
|
||||
}
|
||||
|
||||
} while (!all_freed);
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Remove all pages that belong to a given tablespace inside a specific
|
||||
buffer pool instance when we are DISCARDing the tablespace. */
|
||||
static
|
||||
void
|
||||
buf_LRU_remove_all_pages(
|
||||
/*=====================*/
|
||||
buf_pool_t* buf_pool, /*!< buffer pool instance */
|
||||
ulint id) /*!< in: space id */
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
ibool all_freed;
|
||||
ulint i;
|
||||
|
||||
scan_again:
|
||||
//buf_pool_mutex_enter(buf_pool);
|
||||
mutex_enter(&buf_pool->LRU_list_mutex);
|
||||
rw_lock_x_lock(&buf_pool->page_hash_latch);
|
||||
buf_flush_list_mutex_enter(buf_pool);
|
||||
|
||||
all_freed = TRUE;
|
||||
|
||||
for (bpage = UT_LIST_GET_LAST(buf_pool->flush_list), i = 0;
|
||||
bpage != NULL; ++i) {
|
||||
for (bpage = UT_LIST_GET_LAST(buf_pool->LRU);
|
||||
bpage != NULL;
|
||||
/* No op */) {
|
||||
|
||||
buf_page_t* prev_bpage;
|
||||
mutex_t* block_mutex = NULL;
|
||||
|
||||
ut_a(buf_page_in_file(bpage));
|
||||
ut_ad(bpage->in_LRU_list);
|
||||
|
||||
prev_bpage = UT_LIST_GET_PREV(flush_list, bpage);
|
||||
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
|
||||
|
||||
/* bpage->space and bpage->io_fix are protected by
|
||||
buf_pool->mutex and block_mutex. It is safe to check
|
||||
buf_pool->mutex and the block_mutex. It is safe to check
|
||||
them while holding buf_pool->mutex only. */
|
||||
|
||||
if (buf_page_get_space(bpage) != id) {
|
||||
|
|
@ -420,97 +657,89 @@ scan_again:
|
|||
|
||||
all_freed = FALSE;
|
||||
goto next_page;
|
||||
} else {
|
||||
|
||||
block_mutex = buf_page_get_mutex(bpage);
|
||||
mutex_enter(block_mutex);
|
||||
|
||||
if (bpage->buf_fix_count > 0) {
|
||||
|
||||
mutex_exit(block_mutex);
|
||||
|
||||
/* We cannot remove this page during
|
||||
this scan yet; maybe the system is
|
||||
currently reading it in, or flushing
|
||||
the modifications to the file */
|
||||
|
||||
all_freed = FALSE;
|
||||
|
||||
goto next_page;
|
||||
}
|
||||
}
|
||||
|
||||
/* We have to release the flush_list_mutex to obey the
|
||||
latching order. We are however guaranteed that the page
|
||||
will stay in the flush_list because buf_flush_remove()
|
||||
needs buf_pool->mutex as well. */
|
||||
buf_flush_list_mutex_exit(buf_pool);
|
||||
block_mutex = buf_page_get_mutex_enter(bpage);
|
||||
ut_ad(mutex_own(block_mutex));
|
||||
|
||||
if (!block_mutex) {
|
||||
/* It may be impossible case...
|
||||
Something wrong, so will be scan_again */
|
||||
all_freed = FALSE;
|
||||
goto next_page;
|
||||
#ifdef UNIV_DEBUG
|
||||
if (buf_debug_prints) {
|
||||
fprintf(stderr,
|
||||
"Dropping space %lu page %lu\n",
|
||||
(ulong) buf_page_get_space(bpage),
|
||||
(ulong) buf_page_get_page_no(bpage));
|
||||
}
|
||||
#endif
|
||||
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
|
||||
/* Do nothing, because the adaptive hash index
|
||||
covers uncompressed pages only. */
|
||||
} else if (((buf_block_t*) bpage)->index) {
|
||||
ulint page_no;
|
||||
ulint zip_size;
|
||||
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
|
||||
zip_size = buf_page_get_zip_size(bpage);
|
||||
page_no = buf_page_get_page_no(bpage);
|
||||
|
||||
if (bpage->buf_fix_count > 0) {
|
||||
mutex_exit(block_mutex);
|
||||
buf_flush_list_mutex_enter(buf_pool);
|
||||
|
||||
/* We cannot remove this page during
|
||||
this scan yet; maybe the system is
|
||||
currently reading it in, or flushing
|
||||
the modifications to the file */
|
||||
/* Note that the following call will acquire
|
||||
and release block->lock X-latch. */
|
||||
|
||||
all_freed = FALSE;
|
||||
goto next_page;
|
||||
btr_search_drop_page_hash_when_freed(
|
||||
id, zip_size, page_no);
|
||||
|
||||
goto scan_again;
|
||||
}
|
||||
|
||||
ut_ad(bpage->oldest_modification != 0);
|
||||
if (bpage->oldest_modification != 0) {
|
||||
buf_flush_remove(bpage);
|
||||
}
|
||||
|
||||
buf_flush_remove(bpage);
|
||||
ut_ad(!bpage->in_flush_list);
|
||||
|
||||
/* Remove from the LRU list. */
|
||||
|
||||
if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
|
||||
!= BUF_BLOCK_ZIP_FREE) {
|
||||
|
||||
buf_LRU_block_free_hashed_page((buf_block_t*) bpage, TRUE);
|
||||
mutex_exit(block_mutex);
|
||||
|
||||
} else {
|
||||
/* The block_mutex should have been released
|
||||
by buf_LRU_block_remove_hashed_page() when it
|
||||
returns BUF_BLOCK_ZIP_FREE. */
|
||||
ut_ad(block_mutex == &buf_pool->zip_mutex);
|
||||
}
|
||||
|
||||
ut_ad(!mutex_own(block_mutex));
|
||||
|
||||
mutex_exit(block_mutex);
|
||||
buf_flush_list_mutex_enter(buf_pool);
|
||||
next_page:
|
||||
bpage = prev_bpage;
|
||||
|
||||
if (!bpage) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Every BUF_LRU_DROP_SEARCH_SIZE iterations in the
|
||||
loop we release buf_pool->mutex to let other threads
|
||||
do their job. */
|
||||
if (i < BUF_LRU_DROP_SEARCH_SIZE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We IO-fix the block to make sure that the block
|
||||
stays in its position in the flush_list. */
|
||||
if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
|
||||
/* Block is already IO-fixed. We don't
|
||||
want to change the value. Lets leave
|
||||
this block alone. */
|
||||
continue;
|
||||
}
|
||||
|
||||
buf_flush_list_mutex_exit(buf_pool);
|
||||
block_mutex = buf_page_get_mutex(bpage);
|
||||
mutex_enter(block_mutex);
|
||||
buf_page_set_sticky(bpage);
|
||||
mutex_exit(block_mutex);
|
||||
|
||||
/* Now it is safe to release the buf_pool->mutex. */
|
||||
//buf_pool_mutex_exit(buf_pool);
|
||||
mutex_exit(&buf_pool->LRU_list_mutex);
|
||||
rw_lock_x_unlock(&buf_pool->page_hash_latch);
|
||||
|
||||
os_thread_yield();
|
||||
//buf_pool_mutex_enter(buf_pool);
|
||||
mutex_enter(&buf_pool->LRU_list_mutex);
|
||||
rw_lock_x_lock(&buf_pool->page_hash_latch);
|
||||
|
||||
|
||||
mutex_enter(block_mutex);
|
||||
buf_page_unset_sticky(bpage);
|
||||
mutex_exit(block_mutex);
|
||||
|
||||
buf_flush_list_mutex_enter(buf_pool);
|
||||
ut_ad(bpage->in_flush_list);
|
||||
|
||||
i = 0;
|
||||
}
|
||||
|
||||
// buf_pool_mutex_exit(buf_pool);
|
||||
mutex_exit(&buf_pool->LRU_list_mutex);
|
||||
rw_lock_x_unlock(&buf_pool->page_hash_latch);
|
||||
buf_flush_list_mutex_exit(buf_pool);
|
||||
|
||||
ut_ad(buf_flush_validate(buf_pool));
|
||||
|
||||
if (!all_freed) {
|
||||
os_thread_sleep(20000);
|
||||
|
|
@ -520,28 +749,46 @@ next_page:
|
|||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Invalidates all pages belonging to a given tablespace when we are deleting
|
||||
the data file(s) of that tablespace. */
|
||||
Removes all pages belonging to a given tablespace. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_invalidate_tablespace(
|
||||
buf_LRU_flush_or_remove_pages(
|
||||
/*==========================*/
|
||||
ulint id) /*!< in: space id */
|
||||
ulint id, /*!< in: space id */
|
||||
enum buf_remove_t buf_remove)/*!< in: remove or flush
|
||||
strategy */
|
||||
{
|
||||
ulint i;
|
||||
ulint i;
|
||||
|
||||
/* Before we attempt to drop pages one by one we first
|
||||
attempt to drop page hash index entries in batches to make
|
||||
it more efficient. The batching attempt is a best effort
|
||||
attempt and does not guarantee that all pages hash entries
|
||||
will be dropped. We get rid of remaining page hash entries
|
||||
one by one below. */
|
||||
for (i = 0; i < srv_buf_pool_instances; i++) {
|
||||
buf_pool_t* buf_pool;
|
||||
|
||||
buf_pool = buf_pool_from_array(i);
|
||||
buf_LRU_drop_page_hash_for_tablespace(buf_pool, id);
|
||||
buf_LRU_remove_dirty_pages_for_tablespace(buf_pool, id);
|
||||
|
||||
switch (buf_remove) {
|
||||
case BUF_REMOVE_ALL_NO_WRITE:
|
||||
/* A DISCARD tablespace case. Remove AHI entries
|
||||
and evict all pages from LRU. */
|
||||
|
||||
/* Before we attempt to drop pages hash entries
|
||||
one by one we first attempt to drop page hash
|
||||
index entries in batches to make it more
|
||||
efficient. The batching attempt is a best effort
|
||||
attempt and does not guarantee that all pages
|
||||
hash entries will be dropped. We get rid of
|
||||
remaining page hash entries one by one below. */
|
||||
buf_LRU_drop_page_hash_for_tablespace(buf_pool, id);
|
||||
buf_LRU_remove_all_pages(buf_pool, id);
|
||||
break;
|
||||
|
||||
case BUF_REMOVE_FLUSH_NO_WRITE:
|
||||
/* A DROP table case. AHI entries are already
|
||||
removed. No need to evict all pages from LRU
|
||||
list. Just evict pages from flush list without
|
||||
writing. */
|
||||
buf_flush_dirty_pages(buf_pool, id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2260,6 +2507,7 @@ func_exit:
|
|||
/********************************************************************//**
|
||||
Dump the LRU page list to the specific file. */
|
||||
#define LRU_DUMP_FILE "ib_lru_dump"
|
||||
#define LRU_DUMP_TEMP_FILE "ib_lru_dump.tmp"
|
||||
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
|
|
@ -2294,8 +2542,10 @@ buf_LRU_file_dump(void)
|
|||
goto end;
|
||||
}
|
||||
|
||||
dump_file = os_file_create(innodb_file_temp_key, LRU_DUMP_FILE, OS_FILE_OVERWRITE,
|
||||
OS_FILE_NORMAL, OS_DATA_FILE, &success);
|
||||
dump_file = os_file_create(innodb_file_temp_key, LRU_DUMP_TEMP_FILE,
|
||||
OS_FILE_OVERWRITE, OS_FILE_NORMAL, OS_DATA_FILE,
|
||||
&success);
|
||||
|
||||
if (!success) {
|
||||
os_file_get_last_error(TRUE);
|
||||
fprintf(stderr,
|
||||
|
|
@ -2324,6 +2574,13 @@ buf_LRU_file_dump(void)
|
|||
offset++;
|
||||
|
||||
if (offset == UNIV_PAGE_SIZE/4) {
|
||||
if (srv_shutdown_state != SRV_SHUTDOWN_NONE) {
|
||||
success = 0;
|
||||
fprintf(stderr,
|
||||
" InnoDB: stopped dumping lru"
|
||||
" pages because of server"
|
||||
" shutdown.\n");
|
||||
}
|
||||
success = os_file_write(LRU_DUMP_FILE, dump_file, buffer,
|
||||
(buffers << UNIV_PAGE_SIZE_SHIFT) & 0xFFFFFFFFUL,
|
||||
(buffers >> (32 - UNIV_PAGE_SIZE_SHIFT)),
|
||||
|
|
@ -2363,8 +2620,16 @@ buf_LRU_file_dump(void)
|
|||
|
||||
ret = TRUE;
|
||||
end:
|
||||
if (dump_file != (os_file_t) -1)
|
||||
if (dump_file != (os_file_t) -1) {
|
||||
if (success) {
|
||||
success = os_file_flush(dump_file, TRUE);
|
||||
}
|
||||
os_file_close(dump_file);
|
||||
}
|
||||
if (success) {
|
||||
success = os_file_rename(innodb_file_temp_key,
|
||||
LRU_DUMP_TEMP_FILE, LRU_DUMP_FILE);
|
||||
}
|
||||
if (buffer_base)
|
||||
ut_free(buffer_base);
|
||||
|
||||
|
|
@ -2410,6 +2675,7 @@ buf_LRU_file_restore(void)
|
|||
dump_record_t* records = NULL;
|
||||
ulint size;
|
||||
ulint size_high;
|
||||
ulint recsize = sizeof(dump_record_t);
|
||||
ulint length;
|
||||
|
||||
dump_file = os_file_create_simple_no_error_handling(innodb_file_temp_key,
|
||||
|
|
@ -2417,7 +2683,14 @@ buf_LRU_file_restore(void)
|
|||
if (!success || !os_file_get_size(dump_file, &size, &size_high)) {
|
||||
os_file_get_last_error(TRUE);
|
||||
fprintf(stderr,
|
||||
" InnoDB: cannot open %s\n", LRU_DUMP_FILE);
|
||||
" InnoDB: cannot open %s, "
|
||||
" buffer pool preload not done.\n", LRU_DUMP_FILE);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (size == 0 || size_high > 0 || size % recsize) {
|
||||
fprintf(stderr, " InnoDB: broken LRU dump file,"
|
||||
" buffer pool preload not done\n");
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
|
@ -2501,6 +2774,14 @@ buf_LRU_file_restore(void)
|
|||
if (offset % 16 == 15) {
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
buf_flush_free_margins(FALSE);
|
||||
/* skip loading of the rest of the file if we are
|
||||
terminating anyway */
|
||||
if(srv_shutdown_state != SRV_SHUTDOWN_NONE) {
|
||||
fprintf(stderr,
|
||||
" InnoDB: stopped loading lru pages"
|
||||
" because of server shutdown\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
zip_size = fil_space_get_zip_size(space_id);
|
||||
|
|
|
|||
|
|
@ -239,6 +239,166 @@ dict_hdr_create(
|
|||
return(TRUE);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Verifies the SYS_STATS table by scanning its clustered index. This
|
||||
function may only be called at InnoDB startup time.
|
||||
|
||||
@return TRUE if SYS_STATS was verified successfully */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dict_verify_xtradb_sys_stats(void)
|
||||
/*==============================*/
|
||||
{
|
||||
dict_index_t* sys_stats_index;
|
||||
ulint saved_srv_pass_corrupt_table = srv_pass_corrupt_table;
|
||||
ibool result;
|
||||
|
||||
sys_stats_index = dict_table_get_first_index(dict_sys->sys_stats);
|
||||
|
||||
/* Since this may be called only during server startup, avoid hitting
|
||||
various asserts by using XtraDB pass_corrupt_table option. */
|
||||
srv_pass_corrupt_table = 1;
|
||||
result = btr_validate_index(sys_stats_index, NULL);
|
||||
srv_pass_corrupt_table = saved_srv_pass_corrupt_table;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Creates the B-tree for the SYS_STATS clustered index, adds the XtraDB
|
||||
mark and the id of the index to the dictionary header page. Rewrites
|
||||
both passed args. */
|
||||
static
|
||||
void
|
||||
dict_create_xtradb_sys_stats(
|
||||
/*=========================*/
|
||||
dict_hdr_t** dict_hdr, /*!< in/out: dictionary header */
|
||||
mtr_t* mtr) /*!< in/out: mtr */
|
||||
{
|
||||
ulint root_page_no;
|
||||
|
||||
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
|
||||
DICT_HDR_SPACE, 0, DICT_STATS_ID,
|
||||
dict_ind_redundant, mtr);
|
||||
if (root_page_no == FIL_NULL) {
|
||||
fprintf(stderr, "InnoDB: Warning: failed to create SYS_STATS btr.\n");
|
||||
srv_use_sys_stats_table = FALSE;
|
||||
} else {
|
||||
mlog_write_ulint(*dict_hdr + DICT_HDR_STATS, root_page_no,
|
||||
MLOG_4BYTES, mtr);
|
||||
mlog_write_ull(*dict_hdr + DICT_HDR_XTRADB_MARK,
|
||||
DICT_HDR_XTRADB_FLAG, mtr);
|
||||
}
|
||||
mtr_commit(mtr);
|
||||
/* restart mtr */
|
||||
mtr_start(mtr);
|
||||
*dict_hdr = dict_hdr_get(mtr);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Create the table and index structure of SYS_STATS for the dictionary
|
||||
cache and add it there. If called for the first time, also support
|
||||
wrong root page id injection for testing purposes. */
|
||||
static
|
||||
void
|
||||
dict_add_to_cache_xtradb_sys_stats(
|
||||
/*===============================*/
|
||||
ibool first_time __attribute__((unused)),
|
||||
/*!< in: first invocation flag. If
|
||||
TRUE, optionally inject wrong root page
|
||||
id */
|
||||
mem_heap_t* heap, /*!< in: memory heap for table/index
|
||||
allocation */
|
||||
dict_hdr_t* dict_hdr, /*!< in: dictionary header */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
dict_table_t* table;
|
||||
dict_index_t* index;
|
||||
ulint root_page_id;
|
||||
ulint error;
|
||||
|
||||
table = dict_mem_table_create("SYS_STATS", DICT_HDR_SPACE, 4, 0);
|
||||
table->n_mysql_handles_opened = 1; /* for pin */
|
||||
|
||||
dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "KEY_COLS", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "DIFF_VALS", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "NON_NULL_VALS", DATA_BINARY, 0, 0);
|
||||
|
||||
/* The '+ 2' below comes from the fields DB_TRX_ID, DB_ROLL_PTR */
|
||||
#if DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2
|
||||
#error "DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2"
|
||||
#endif
|
||||
#if DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2
|
||||
#error "DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2"
|
||||
#endif
|
||||
|
||||
table->id = DICT_STATS_ID;
|
||||
dict_table_add_to_cache(table, heap);
|
||||
dict_sys->sys_stats = table;
|
||||
mem_heap_empty(heap);
|
||||
|
||||
index = dict_mem_index_create("SYS_STATS", "CLUST_IND",
|
||||
DICT_HDR_SPACE,
|
||||
DICT_UNIQUE | DICT_CLUSTERED, 2);
|
||||
|
||||
dict_mem_index_add_field(index, "INDEX_ID", 0);
|
||||
dict_mem_index_add_field(index, "KEY_COLS", 0);
|
||||
|
||||
index->id = DICT_STATS_ID;
|
||||
|
||||
root_page_id = mtr_read_ulint(dict_hdr + DICT_HDR_STATS, MLOG_4BYTES,
|
||||
mtr);
|
||||
#ifdef UNIV_DEBUG
|
||||
if ((srv_sys_stats_root_page != 0) && first_time)
|
||||
root_page_id = srv_sys_stats_root_page;
|
||||
#endif
|
||||
error = dict_index_add_to_cache(table, index, root_page_id, FALSE);
|
||||
ut_a(error == DB_SUCCESS);
|
||||
|
||||
mem_heap_empty(heap);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Discard the existing dictionary cache SYS_STATS information, create and
|
||||
add it there anew. Does not touch the old SYS_STATS tablespace page
|
||||
under the assumption that they are corrupted or overwritten for other
|
||||
purposes. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
dict_recreate_xtradb_sys_stats(void)
|
||||
/*================================*/
|
||||
{
|
||||
mtr_t mtr;
|
||||
dict_hdr_t* dict_hdr;
|
||||
dict_index_t* sys_stats_clust_idx;
|
||||
mem_heap_t* heap;
|
||||
|
||||
heap = mem_heap_create(450);
|
||||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
|
||||
sys_stats_clust_idx = dict_table_get_first_index(dict_sys->sys_stats);
|
||||
dict_index_remove_from_cache(dict_sys->sys_stats, sys_stats_clust_idx);
|
||||
|
||||
dict_table_remove_from_cache(dict_sys->sys_stats);
|
||||
|
||||
dict_sys->sys_stats = NULL;
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
dict_hdr = dict_hdr_get(&mtr);
|
||||
|
||||
dict_create_xtradb_sys_stats(&dict_hdr, &mtr);
|
||||
dict_add_to_cache_xtradb_sys_stats(FALSE, heap, dict_hdr, &mtr);
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Initializes the data dictionary memory structures when the database is
|
||||
started. This function is also called when the data dictionary is created. */
|
||||
|
|
@ -254,13 +414,13 @@ dict_boot(void)
|
|||
mtr_t mtr;
|
||||
ulint error;
|
||||
|
||||
heap = mem_heap_create(450);
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
/* Create the hash tables etc. */
|
||||
dict_init();
|
||||
|
||||
heap = mem_heap_create(450);
|
||||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
|
||||
/* Get the dictionary header */
|
||||
|
|
@ -268,25 +428,9 @@ dict_boot(void)
|
|||
|
||||
if (mach_read_from_8(dict_hdr + DICT_HDR_XTRADB_MARK)
|
||||
!= DICT_HDR_XTRADB_FLAG) {
|
||||
/* not extended yet by XtraDB, need to be extended */
|
||||
ulint root_page_no;
|
||||
|
||||
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
|
||||
DICT_HDR_SPACE, 0, DICT_STATS_ID,
|
||||
dict_ind_redundant, &mtr);
|
||||
if (root_page_no == FIL_NULL) {
|
||||
fprintf(stderr, "InnoDB: Warning: failed to create SYS_STATS btr.\n");
|
||||
srv_use_sys_stats_table = FALSE;
|
||||
} else {
|
||||
mlog_write_ulint(dict_hdr + DICT_HDR_STATS, root_page_no,
|
||||
MLOG_4BYTES, &mtr);
|
||||
mlog_write_ull(dict_hdr + DICT_HDR_XTRADB_MARK,
|
||||
DICT_HDR_XTRADB_FLAG, &mtr);
|
||||
}
|
||||
mtr_commit(&mtr);
|
||||
/* restart mtr */
|
||||
mtr_start(&mtr);
|
||||
dict_hdr = dict_hdr_get(&mtr);
|
||||
/* not extended yet by XtraDB, need to be extended */
|
||||
dict_create_xtradb_sys_stats(&dict_hdr, &mtr);
|
||||
}
|
||||
|
||||
/* Because we only write new row ids to disk-based data structure
|
||||
|
|
@ -465,42 +609,7 @@ dict_boot(void)
|
|||
FALSE);
|
||||
ut_a(error == DB_SUCCESS);
|
||||
|
||||
/*-------------------------*/
|
||||
table = dict_mem_table_create("SYS_STATS", DICT_HDR_SPACE, 4, 0);
|
||||
table->n_mysql_handles_opened = 1; /* for pin */
|
||||
|
||||
dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "KEY_COLS", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "DIFF_VALS", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "NON_NULL_VALS", DATA_BINARY, 0, 0);
|
||||
|
||||
/* The '+ 2' below comes from the fields DB_TRX_ID, DB_ROLL_PTR */
|
||||
#if DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2
|
||||
#error "DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2"
|
||||
#endif
|
||||
#if DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2
|
||||
#error "DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2"
|
||||
#endif
|
||||
|
||||
table->id = DICT_STATS_ID;
|
||||
dict_table_add_to_cache(table, heap);
|
||||
dict_sys->sys_stats = table;
|
||||
mem_heap_empty(heap);
|
||||
|
||||
index = dict_mem_index_create("SYS_STATS", "CLUST_IND",
|
||||
DICT_HDR_SPACE,
|
||||
DICT_UNIQUE | DICT_CLUSTERED, 2);
|
||||
|
||||
dict_mem_index_add_field(index, "INDEX_ID", 0);
|
||||
dict_mem_index_add_field(index, "KEY_COLS", 0);
|
||||
|
||||
index->id = DICT_STATS_ID;
|
||||
error = dict_index_add_to_cache(table, index,
|
||||
mtr_read_ulint(dict_hdr
|
||||
+ DICT_HDR_STATS,
|
||||
MLOG_4BYTES, &mtr),
|
||||
FALSE);
|
||||
ut_a(error == DB_SUCCESS);
|
||||
dict_add_to_cache_xtradb_sys_stats(TRUE, heap, dict_hdr, &mtr);
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
|
@ -11,8 +11,8 @@ 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., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
|
|
@ -56,6 +56,8 @@ UNIV_INTERN dict_index_t* dict_ind_compact;
|
|||
#include "ha_prototypes.h" /* innobase_strcasecmp(), innobase_casedn_str()*/
|
||||
#include "row0upd.h"
|
||||
#include "srv0start.h" /* SRV_LOG_SPACE_FIRST_ID */
|
||||
#include "m_string.h"
|
||||
#include "my_sys.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
|
|
@ -2400,6 +2402,8 @@ dict_foreign_free(
|
|||
/*==============*/
|
||||
dict_foreign_t* foreign) /*!< in, own: foreign key struct */
|
||||
{
|
||||
ut_a(foreign->foreign_table->n_foreign_key_checks_running == 0);
|
||||
|
||||
mem_heap_free(foreign->heap);
|
||||
}
|
||||
|
||||
|
|
@ -4381,25 +4385,32 @@ dict_reload_statistics(
|
|||
heap = mem_heap_create(1000);
|
||||
|
||||
while (index) {
|
||||
mtr_t mtr;
|
||||
|
||||
if (table->is_corrupt) {
|
||||
ut_a(srv_pass_corrupt_table);
|
||||
mem_heap_free(heap);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
size = btr_get_size(index, BTR_TOTAL_SIZE);
|
||||
mtr_start(&mtr);
|
||||
mtr_s_lock(dict_index_get_lock(index), &mtr);
|
||||
|
||||
size = btr_get_size(index, BTR_TOTAL_SIZE, &mtr);
|
||||
|
||||
index->stat_index_size = size;
|
||||
|
||||
*sum_of_index_sizes += size;
|
||||
|
||||
size = btr_get_size(index, BTR_N_LEAF_PAGES);
|
||||
size = btr_get_size(index, BTR_N_LEAF_PAGES, &mtr);
|
||||
|
||||
if (size == 0) {
|
||||
/* The root node of the tree is a leaf */
|
||||
size = 1;
|
||||
}
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
index->stat_n_leaf_pages = size;
|
||||
|
||||
/*===========================================*/
|
||||
|
|
@ -4731,6 +4742,7 @@ dict_update_statistics(
|
|||
(srv_force_recovery < SRV_FORCE_NO_IBUF_MERGE
|
||||
|| (srv_force_recovery < SRV_FORCE_NO_LOG_REDO
|
||||
&& dict_index_is_clust(index)))) {
|
||||
mtr_t mtr;
|
||||
ulint size;
|
||||
|
||||
if (table->is_corrupt) {
|
||||
|
|
@ -4739,15 +4751,24 @@ dict_update_statistics(
|
|||
return;
|
||||
}
|
||||
|
||||
size = btr_get_size(index, BTR_TOTAL_SIZE);
|
||||
mtr_start(&mtr);
|
||||
mtr_s_lock(dict_index_get_lock(index), &mtr);
|
||||
|
||||
index->stat_index_size = size;
|
||||
size = btr_get_size(index, BTR_TOTAL_SIZE, &mtr);
|
||||
|
||||
sum_of_index_sizes += size;
|
||||
if (size != ULINT_UNDEFINED) {
|
||||
sum_of_index_sizes += size;
|
||||
index->stat_index_size = size;
|
||||
size = btr_get_size(
|
||||
index, BTR_N_LEAF_PAGES, &mtr);
|
||||
}
|
||||
|
||||
size = btr_get_size(index, BTR_N_LEAF_PAGES);
|
||||
mtr_commit(&mtr);
|
||||
|
||||
if (size == 0) {
|
||||
switch (size) {
|
||||
case ULINT_UNDEFINED:
|
||||
goto fake_statistics;
|
||||
case 0:
|
||||
/* The root node of the tree is a leaf */
|
||||
size = 1;
|
||||
}
|
||||
|
|
@ -4764,6 +4785,7 @@ dict_update_statistics(
|
|||
various means, also via secondary indexes. */
|
||||
ulint i;
|
||||
|
||||
fake_statistics:
|
||||
sum_of_index_sizes++;
|
||||
index->stat_index_size = index->stat_n_leaf_pages = 1;
|
||||
|
||||
|
|
|
|||
|
|
@ -2137,8 +2137,9 @@ static
|
|||
void
|
||||
dict_load_foreign_cols(
|
||||
/*===================*/
|
||||
const char* id, /*!< in: foreign constraint id as a
|
||||
null-terminated string */
|
||||
const char* id, /*!< in: foreign constraint id, not
|
||||
necessary '\0'-terminated */
|
||||
ulint id_len, /*!< in: id length */
|
||||
dict_foreign_t* foreign)/*!< in: foreign constraint object */
|
||||
{
|
||||
dict_table_t* sys_foreign_cols;
|
||||
|
|
@ -2168,7 +2169,7 @@ dict_load_foreign_cols(
|
|||
tuple = dtuple_create(foreign->heap, 1);
|
||||
dfield = dtuple_get_nth_field(tuple, 0);
|
||||
|
||||
dfield_set_data(dfield, id, ut_strlen(id));
|
||||
dfield_set_data(dfield, id, id_len);
|
||||
dict_index_copy_types(tuple, sys_index, 1);
|
||||
|
||||
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
|
||||
|
|
@ -2181,7 +2182,7 @@ dict_load_foreign_cols(
|
|||
ut_a(!rec_get_deleted_flag(rec, 0));
|
||||
|
||||
field = rec_get_nth_field_old(rec, 0, &len);
|
||||
ut_a(len == ut_strlen(id));
|
||||
ut_a(len == id_len);
|
||||
ut_a(ut_memcmp(id, field, len) == 0);
|
||||
|
||||
field = rec_get_nth_field_old(rec, 1, &len);
|
||||
|
|
@ -2210,8 +2211,9 @@ static
|
|||
ulint
|
||||
dict_load_foreign(
|
||||
/*==============*/
|
||||
const char* id, /*!< in: foreign constraint id as a
|
||||
null-terminated string */
|
||||
const char* id, /*!< in: foreign constraint id, not
|
||||
necessary '\0'-terminated */
|
||||
ulint id_len, /*!< in: id length */
|
||||
ibool check_charsets,
|
||||
/*!< in: TRUE=check charset compatibility */
|
||||
ibool check_recursive)
|
||||
|
|
@ -2247,7 +2249,7 @@ dict_load_foreign(
|
|||
tuple = dtuple_create(heap2, 1);
|
||||
dfield = dtuple_get_nth_field(tuple, 0);
|
||||
|
||||
dfield_set_data(dfield, id, ut_strlen(id));
|
||||
dfield_set_data(dfield, id, id_len);
|
||||
dict_index_copy_types(tuple, sys_index, 1);
|
||||
|
||||
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
|
||||
|
|
@ -2259,8 +2261,8 @@ dict_load_foreign(
|
|||
/* Not found */
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error A: cannot load foreign constraint %s\n",
|
||||
id);
|
||||
"InnoDB: Error A: cannot load foreign constraint "
|
||||
"%.*s\n", (int) id_len, id);
|
||||
|
||||
btr_pcur_close(&pcur);
|
||||
mtr_commit(&mtr);
|
||||
|
|
@ -2272,11 +2274,11 @@ dict_load_foreign(
|
|||
field = rec_get_nth_field_old(rec, 0, &len);
|
||||
|
||||
/* Check if the id in record is the searched one */
|
||||
if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
|
||||
if (len != id_len || ut_memcmp(id, field, len) != 0) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error B: cannot load foreign constraint %s\n",
|
||||
id);
|
||||
"InnoDB: Error B: cannot load foreign constraint "
|
||||
"%.*s\n", (int) id_len, id);
|
||||
|
||||
btr_pcur_close(&pcur);
|
||||
mtr_commit(&mtr);
|
||||
|
|
@ -2302,7 +2304,7 @@ dict_load_foreign(
|
|||
foreign->type = (unsigned int) (n_fields_and_type >> 24);
|
||||
foreign->n_fields = (unsigned int) (n_fields_and_type & 0x3FFUL);
|
||||
|
||||
foreign->id = mem_heap_strdup(foreign->heap, id);
|
||||
foreign->id = mem_heap_strdupl(foreign->heap, id, id_len);
|
||||
|
||||
field = rec_get_nth_field_old(rec, 3, &len);
|
||||
|
||||
|
|
@ -2318,7 +2320,7 @@ dict_load_foreign(
|
|||
btr_pcur_close(&pcur);
|
||||
mtr_commit(&mtr);
|
||||
|
||||
dict_load_foreign_cols(id, foreign);
|
||||
dict_load_foreign_cols(id, id_len, foreign);
|
||||
|
||||
ref_table = dict_table_check_if_in_cache_low(
|
||||
foreign->referenced_table_name_lookup);
|
||||
|
|
@ -2397,8 +2399,8 @@ dict_load_foreigns(
|
|||
ibool check_charsets) /*!< in: TRUE=check charset
|
||||
compatibility */
|
||||
{
|
||||
char tuple_buf[DTUPLE_EST_ALLOC(1)];
|
||||
btr_pcur_t pcur;
|
||||
mem_heap_t* heap;
|
||||
dtuple_t* tuple;
|
||||
dfield_t* dfield;
|
||||
dict_index_t* sec_index;
|
||||
|
|
@ -2406,7 +2408,6 @@ dict_load_foreigns(
|
|||
const rec_t* rec;
|
||||
const byte* field;
|
||||
ulint len;
|
||||
char* id ;
|
||||
ulint err;
|
||||
mtr_t mtr;
|
||||
|
||||
|
|
@ -2433,9 +2434,8 @@ dict_load_foreigns(
|
|||
sec_index = dict_table_get_next_index(
|
||||
dict_table_get_first_index(sys_foreign));
|
||||
start_load:
|
||||
heap = mem_heap_create(256);
|
||||
|
||||
tuple = dtuple_create(heap, 1);
|
||||
tuple = dtuple_create_from_mem(tuple_buf, sizeof(tuple_buf), 1);
|
||||
dfield = dtuple_get_nth_field(tuple, 0);
|
||||
|
||||
dfield_set_data(dfield, table_name, ut_strlen(table_name));
|
||||
|
|
@ -2489,7 +2489,6 @@ loop:
|
|||
|
||||
/* Now we get a foreign key constraint id */
|
||||
field = rec_get_nth_field_old(rec, 1, &len);
|
||||
id = mem_heap_strdupl(heap, (char*) field, len);
|
||||
|
||||
btr_pcur_store_position(&pcur, &mtr);
|
||||
|
||||
|
|
@ -2497,11 +2496,11 @@ loop:
|
|||
|
||||
/* Load the foreign constraint definition to the dictionary cache */
|
||||
|
||||
err = dict_load_foreign(id, check_charsets, check_recursive);
|
||||
err = dict_load_foreign((char*) field, len, check_charsets,
|
||||
check_recursive);
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
btr_pcur_close(&pcur);
|
||||
mem_heap_free(heap);
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
|
@ -2517,7 +2516,6 @@ next_rec:
|
|||
load_next_index:
|
||||
btr_pcur_close(&pcur);
|
||||
mtr_commit(&mtr);
|
||||
mem_heap_free(heap);
|
||||
|
||||
sec_index = dict_table_get_next_index(sec_index);
|
||||
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ struct fil_space_struct {
|
|||
.ibd file of tablespace and want to
|
||||
stop temporarily posting of new i/o
|
||||
requests on the file */
|
||||
ibool stop_ibuf_merges;
|
||||
ibool stop_new_ops;
|
||||
/*!< we set this TRUE when we start
|
||||
deleting a single-table tablespace */
|
||||
ibool is_being_deleted;
|
||||
|
|
@ -218,12 +218,13 @@ struct fil_space_struct {
|
|||
ulint n_pending_flushes; /*!< this is positive when flushing
|
||||
the tablespace to disk; dropping of the
|
||||
tablespace is forbidden if this is positive */
|
||||
ulint n_pending_ibuf_merges;/*!< this is positive
|
||||
when merging insert buffer entries to
|
||||
a page so that we may need to access
|
||||
the ibuf bitmap page in the
|
||||
tablespade: dropping of the tablespace
|
||||
is forbidden if this is positive */
|
||||
ulint n_pending_ops;/*!< this is positive when we
|
||||
have pending operations against this
|
||||
tablespace. The pending operations can
|
||||
be ibuf merges or lock validation code
|
||||
trying to read a block.
|
||||
Dropping of the tablespace is forbidden
|
||||
if this is positive */
|
||||
hash_node_t hash; /*!< hash chain node */
|
||||
hash_node_t name_hash;/*!< hash chain the name_hash table */
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
|
|
@ -974,11 +975,6 @@ retry:
|
|||
return;
|
||||
}
|
||||
|
||||
if (fil_system->n_open < fil_system->max_n_open) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
space = fil_space_get_by_id(space_id);
|
||||
|
||||
if (space != NULL && space->stop_ios) {
|
||||
|
|
@ -995,6 +991,25 @@ retry:
|
|||
|
||||
mutex_exit(&fil_system->mutex);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
|
||||
/* Wake the i/o-handler threads to make sure pending
|
||||
i/o's are performed */
|
||||
os_aio_simulated_wake_handler_threads();
|
||||
|
||||
/* The sleep here is just to give IO helper threads a
|
||||
bit of time to do some work. It is not required that
|
||||
all IO related to the tablespace being renamed must
|
||||
be flushed here as we do fil_flush() in
|
||||
fil_rename_tablespace() as well. */
|
||||
os_thread_sleep(20000);
|
||||
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
|
||||
/* Flush tablespaces so that we can close modified
|
||||
files in the LRU list */
|
||||
fil_flush_file_spaces(FIL_TABLESPACE);
|
||||
|
||||
os_thread_sleep(20000);
|
||||
|
||||
count2++;
|
||||
|
|
@ -1002,6 +1017,11 @@ retry:
|
|||
goto retry;
|
||||
}
|
||||
|
||||
if (fil_system->n_open < fil_system->max_n_open) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the file is already open, no need to do anything; if the space
|
||||
does not exist, we handle the situation in the function which called
|
||||
this function */
|
||||
|
|
@ -1274,7 +1294,7 @@ try_again:
|
|||
}
|
||||
|
||||
space->stop_ios = FALSE;
|
||||
space->stop_ibuf_merges = FALSE;
|
||||
space->stop_new_ops = FALSE;
|
||||
space->is_being_deleted = FALSE;
|
||||
space->purpose = purpose;
|
||||
space->size = 0;
|
||||
|
|
@ -1283,7 +1303,7 @@ try_again:
|
|||
space->n_reserved_extents = 0;
|
||||
|
||||
space->n_pending_flushes = 0;
|
||||
space->n_pending_ibuf_merges = 0;
|
||||
space->n_pending_ops = 0;
|
||||
|
||||
UT_LIST_INIT(space->chain);
|
||||
space->magic_n = FIL_SPACE_MAGIC_N;
|
||||
|
|
@ -1896,13 +1916,12 @@ fil_read_first_page(
|
|||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/*******************************************************************//**
|
||||
Increments the count of pending insert buffer page merges, if space is not
|
||||
being deleted.
|
||||
@return TRUE if being deleted, and ibuf merges should be skipped */
|
||||
Increments the count of pending operation, if space is not being deleted.
|
||||
@return TRUE if being deleted, and operation should be skipped */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
fil_inc_pending_ibuf_merges(
|
||||
/*========================*/
|
||||
fil_inc_pending_ops(
|
||||
/*================*/
|
||||
ulint id) /*!< in: space id */
|
||||
{
|
||||
fil_space_t* space;
|
||||
|
|
@ -1918,13 +1937,13 @@ fil_inc_pending_ibuf_merges(
|
|||
(ulong) id);
|
||||
}
|
||||
|
||||
if (space == NULL || space->stop_ibuf_merges) {
|
||||
if (space == NULL || space->stop_new_ops) {
|
||||
mutex_exit(&fil_system->mutex);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
space->n_pending_ibuf_merges++;
|
||||
space->n_pending_ops++;
|
||||
|
||||
mutex_exit(&fil_system->mutex);
|
||||
|
||||
|
|
@ -1932,11 +1951,11 @@ fil_inc_pending_ibuf_merges(
|
|||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Decrements the count of pending insert buffer page merges. */
|
||||
Decrements the count of pending operations. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
fil_decr_pending_ibuf_merges(
|
||||
/*=========================*/
|
||||
fil_decr_pending_ops(
|
||||
/*=================*/
|
||||
ulint id) /*!< in: space id */
|
||||
{
|
||||
fil_space_t* space;
|
||||
|
|
@ -1947,13 +1966,13 @@ fil_decr_pending_ibuf_merges(
|
|||
|
||||
if (space == NULL) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: decrementing ibuf merge of a"
|
||||
" dropped tablespace %lu\n",
|
||||
"InnoDB: Error: decrementing pending operation"
|
||||
" of a dropped tablespace %lu\n",
|
||||
(ulong) id);
|
||||
}
|
||||
|
||||
if (space != NULL) {
|
||||
space->n_pending_ibuf_merges--;
|
||||
space->n_pending_ops--;
|
||||
}
|
||||
|
||||
mutex_exit(&fil_system->mutex);
|
||||
|
|
@ -2164,7 +2183,7 @@ fil_op_log_parse_or_replay(
|
|||
switch (type) {
|
||||
case MLOG_FILE_DELETE:
|
||||
if (fil_tablespace_exists_in_mem(space_id)) {
|
||||
ut_a(fil_delete_tablespace(space_id));
|
||||
ut_a(fil_delete_tablespace(space_id, TRUE));
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
@ -2234,7 +2253,9 @@ UNIV_INTERN
|
|||
ibool
|
||||
fil_delete_tablespace(
|
||||
/*==================*/
|
||||
ulint id) /*!< in: space id */
|
||||
ulint id, /*!< in: space id */
|
||||
ibool evict_all) /*!< in: TRUE if we want all pages
|
||||
evicted from LRU. */
|
||||
{
|
||||
ibool success;
|
||||
fil_space_t* space;
|
||||
|
|
@ -2243,15 +2264,15 @@ fil_delete_tablespace(
|
|||
char* path;
|
||||
|
||||
ut_a(id != 0);
|
||||
stop_ibuf_merges:
|
||||
stop_new_ops:
|
||||
mutex_enter(&fil_system->mutex);
|
||||
|
||||
space = fil_space_get_by_id(id);
|
||||
|
||||
if (space != NULL) {
|
||||
space->stop_ibuf_merges = TRUE;
|
||||
space->stop_new_ops = TRUE;
|
||||
|
||||
if (space->n_pending_ibuf_merges == 0) {
|
||||
if (space->n_pending_ops == 0) {
|
||||
mutex_exit(&fil_system->mutex);
|
||||
|
||||
count = 0;
|
||||
|
|
@ -2265,9 +2286,10 @@ stop_ibuf_merges:
|
|||
ut_print_filename(stderr, space->name);
|
||||
fprintf(stderr, ",\n"
|
||||
"InnoDB: but there are %lu pending"
|
||||
" ibuf merges on it.\n"
|
||||
" operations (most likely ibuf merges)"
|
||||
" on it.\n"
|
||||
"InnoDB: Loop %lu.\n",
|
||||
(ulong) space->n_pending_ibuf_merges,
|
||||
(ulong) space->n_pending_ops,
|
||||
(ulong) count);
|
||||
}
|
||||
|
||||
|
|
@ -2276,7 +2298,7 @@ stop_ibuf_merges:
|
|||
os_thread_sleep(20000);
|
||||
count++;
|
||||
|
||||
goto stop_ibuf_merges;
|
||||
goto stop_new_ops;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2302,7 +2324,7 @@ try_again:
|
|||
}
|
||||
|
||||
ut_a(space);
|
||||
ut_a(space->n_pending_ibuf_merges == 0);
|
||||
ut_a(space->n_pending_ops == 0);
|
||||
|
||||
space->is_being_deleted = TRUE;
|
||||
|
||||
|
|
@ -2358,7 +2380,11 @@ try_again:
|
|||
if (srv_lazy_drop_table) {
|
||||
buf_LRU_mark_space_was_deleted(id);
|
||||
} else {
|
||||
buf_LRU_invalidate_tablespace(id);
|
||||
buf_LRU_flush_or_remove_pages(
|
||||
id, evict_all
|
||||
? BUF_REMOVE_ALL_NO_WRITE
|
||||
: BUF_REMOVE_FLUSH_NO_WRITE);
|
||||
|
||||
}
|
||||
#endif
|
||||
/* printf("Deleting tablespace %s id %lu\n", space->name, id); */
|
||||
|
|
@ -2447,7 +2473,7 @@ fil_discard_tablespace(
|
|||
{
|
||||
ibool success;
|
||||
|
||||
success = fil_delete_tablespace(id);
|
||||
success = fil_delete_tablespace(id, TRUE);
|
||||
|
||||
if (!success) {
|
||||
fprintf(stderr,
|
||||
|
|
@ -2579,7 +2605,7 @@ fil_rename_tablespace(
|
|||
retry:
|
||||
count++;
|
||||
|
||||
if (count > 1000) {
|
||||
if (!(count % 1000)) {
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: Warning: problems renaming ", stderr);
|
||||
ut_print_filename(stderr, old_name);
|
||||
|
|
@ -3905,7 +3931,7 @@ convert_err_exit:
|
|||
|
||||
level = btr_page_get_level(page, &mtr);
|
||||
|
||||
new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, &mtr);
|
||||
new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, &mtr, &mtr);
|
||||
new_page = buf_block_get_frame(new_block);
|
||||
new_page_zip = buf_block_get_page_zip(new_block);
|
||||
btr_page_create(new_block, new_page_zip, index, level, &mtr);
|
||||
|
|
@ -3953,7 +3979,7 @@ convert_err_exit:
|
|||
split_rec = page_get_middle_rec(page);
|
||||
|
||||
new_block = btr_page_alloc(index, page_no + 1, FSP_UP,
|
||||
btr_page_get_level(page, &mtr), &mtr);
|
||||
btr_page_get_level(page, &mtr), &mtr, &mtr);
|
||||
new_page = buf_block_get_frame(new_block);
|
||||
new_page_zip = buf_block_get_page_zip(new_block);
|
||||
btr_page_create(new_block, new_page_zip, index,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
|
@ -248,28 +248,38 @@ fsp_fill_free_list(
|
|||
descriptor page and ibuf bitmap page;
|
||||
then we do not allocate more extents */
|
||||
ulint space, /*!< in: space */
|
||||
fsp_header_t* header, /*!< in: space header */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
fsp_header_t* header, /*!< in/out: space header */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
/**********************************************************************//**
|
||||
Allocates a single free page from a segment. This function implements
|
||||
the intelligent allocation strategy which tries to minimize file space
|
||||
fragmentation.
|
||||
@return the allocated page number, FIL_NULL if no page could be allocated */
|
||||
@retval NULL if no page could be allocated
|
||||
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||
@retval block (not allocated or initialized) otherwise */
|
||||
static
|
||||
ulint
|
||||
buf_block_t*
|
||||
fseg_alloc_free_page_low(
|
||||
/*=====================*/
|
||||
ulint space, /*!< in: space */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
fseg_inode_t* seg_inode, /*!< in: segment inode */
|
||||
ulint hint, /*!< in: hint of which page would be desirable */
|
||||
fseg_inode_t* seg_inode, /*!< in/out: segment inode */
|
||||
ulint hint, /*!< in: hint of which page would be
|
||||
desirable */
|
||||
byte direction, /*!< in: if the new page is needed because
|
||||
of an index page split, and records are
|
||||
inserted there in order, into which
|
||||
direction they go alphabetically: FSP_DOWN,
|
||||
FSP_UP, FSP_NO_DIR */
|
||||
mtr_t* mtr); /*!< in: mtr handle */
|
||||
mtr_t* mtr, /*!< in/out: mini-transaction */
|
||||
mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
|
||||
in which the page should be initialized.
|
||||
If init_mtr!=mtr, but the page is already
|
||||
latched in mtr, do not initialize the page. */
|
||||
__attribute__((warn_unused_result, nonnull));
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
@ -639,23 +649,22 @@ xdes_calc_descriptor_index(
|
|||
|
||||
/********************************************************************//**
|
||||
Gets pointer to a the extent descriptor of a page. The page where the extent
|
||||
descriptor resides is x-locked. If the page offset is equal to the free limit
|
||||
of the space, adds new extents from above the free limit to the space free
|
||||
list, if not free limit == space size. This adding is necessary to make the
|
||||
descriptor defined, as they are uninitialized above the free limit.
|
||||
descriptor resides is x-locked. This function no longer extends the data
|
||||
file.
|
||||
@return pointer to the extent descriptor, NULL if the page does not
|
||||
exist in the space or if the offset exceeds the free limit */
|
||||
UNIV_INLINE
|
||||
exist in the space or if the offset is >= the free limit */
|
||||
UNIV_INLINE __attribute__((nonnull, warn_unused_result))
|
||||
xdes_t*
|
||||
xdes_get_descriptor_with_space_hdr(
|
||||
/*===============================*/
|
||||
fsp_header_t* sp_header,/*!< in/out: space header, x-latched */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset, /*!< in: page offset;
|
||||
if equal to the free limit,
|
||||
we try to add new extents to
|
||||
the space free list */
|
||||
mtr_t* mtr) /*!< in: mtr handle */
|
||||
fsp_header_t* sp_header, /*!< in/out: space header, x-latched
|
||||
in mtr */
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset, /*!< in: page offset; if equal
|
||||
to the free limit, we try to
|
||||
add new extents to the space
|
||||
free list */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
ulint limit;
|
||||
ulint size;
|
||||
|
|
@ -663,11 +672,9 @@ xdes_get_descriptor_with_space_hdr(
|
|||
ulint descr_page_no;
|
||||
page_t* descr_page;
|
||||
|
||||
ut_ad(mtr);
|
||||
ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
|
||||
MTR_MEMO_X_LOCK));
|
||||
ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_S_FIX)
|
||||
|| mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(mtr_memo_contains_page(mtr, sp_header, MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(page_offset(sp_header) == FSP_HEADER_OFFSET);
|
||||
/* Read free limit and space size */
|
||||
limit = mach_read_from_4(sp_header + FSP_FREE_LIMIT);
|
||||
|
|
@ -704,8 +711,8 @@ Gets pointer to a the extent descriptor of a page. The page where the extent
|
|||
descriptor resides is x-locked. This function no longer extends the data
|
||||
file.
|
||||
@return pointer to the extent descriptor, NULL if the page does not
|
||||
exist in the space or if the offset is >= the free limit */
|
||||
static
|
||||
exist in the space or if the offset exceeds the free limit */
|
||||
static __attribute__((nonnull, warn_unused_result))
|
||||
xdes_t*
|
||||
xdes_get_descriptor(
|
||||
/*================*/
|
||||
|
|
@ -714,7 +721,7 @@ xdes_get_descriptor(
|
|||
or 0 for uncompressed pages */
|
||||
ulint offset, /*!< in: page offset; if equal to the free limit,
|
||||
we try to add new extents to the space free list */
|
||||
mtr_t* mtr) /*!< in: mtr handle */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
buf_block_t* block;
|
||||
fsp_header_t* sp_header;
|
||||
|
|
@ -1098,14 +1105,14 @@ fsp_header_get_tablespace_size(void)
|
|||
Tries to extend a single-table tablespace so that a page would fit in the
|
||||
data file.
|
||||
@return TRUE if success */
|
||||
static
|
||||
static __attribute__((nonnull, warn_unused_result))
|
||||
ibool
|
||||
fsp_try_extend_data_file_with_pages(
|
||||
/*================================*/
|
||||
ulint space, /*!< in: space */
|
||||
ulint page_no, /*!< in: page number */
|
||||
fsp_header_t* header, /*!< in: space header */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
fsp_header_t* header, /*!< in/out: space header */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
ibool success;
|
||||
ulint actual_size;
|
||||
|
|
@ -1130,7 +1137,7 @@ fsp_try_extend_data_file_with_pages(
|
|||
/***********************************************************************//**
|
||||
Tries to extend the last data file of a tablespace if it is auto-extending.
|
||||
@return FALSE if not auto-extending */
|
||||
static
|
||||
static __attribute__((nonnull))
|
||||
ibool
|
||||
fsp_try_extend_data_file(
|
||||
/*=====================*/
|
||||
|
|
@ -1140,8 +1147,8 @@ fsp_try_extend_data_file(
|
|||
the actual file size rounded down to
|
||||
megabyte */
|
||||
ulint space, /*!< in: space */
|
||||
fsp_header_t* header, /*!< in: space header */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
fsp_header_t* header, /*!< in/out: space header */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
ulint size;
|
||||
ulint zip_size;
|
||||
|
|
@ -1277,7 +1284,7 @@ fsp_fill_free_list(
|
|||
then we do not allocate more extents */
|
||||
ulint space, /*!< in: space */
|
||||
fsp_header_t* header, /*!< in/out: space header */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
ulint limit;
|
||||
ulint size;
|
||||
|
|
@ -1476,29 +1483,120 @@ fsp_alloc_free_extent(
|
|||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Allocates a single free page from a space. The page is marked as used.
|
||||
@return the page offset, FIL_NULL if no page could be allocated */
|
||||
Allocates a single free page from a space. */
|
||||
static __attribute__((nonnull))
|
||||
void
|
||||
fsp_alloc_from_free_frag(
|
||||
/*=====================*/
|
||||
fsp_header_t* header, /*!< in/out: tablespace header */
|
||||
xdes_t* descr, /*!< in/out: extent descriptor */
|
||||
ulint bit, /*!< in: slot to allocate in the extent */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
{
|
||||
ulint frag_n_used;
|
||||
|
||||
ut_ad(xdes_get_state(descr, mtr) == XDES_FREE_FRAG);
|
||||
ut_a(xdes_get_bit(descr, XDES_FREE_BIT, bit, mtr));
|
||||
xdes_set_bit(descr, XDES_FREE_BIT, bit, FALSE, mtr);
|
||||
|
||||
/* Update the FRAG_N_USED field */
|
||||
frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
|
||||
mtr);
|
||||
frag_n_used++;
|
||||
mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
|
||||
mtr);
|
||||
if (xdes_is_full(descr, mtr)) {
|
||||
/* The fragment is full: move it to another list */
|
||||
flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
|
||||
mtr);
|
||||
xdes_set_state(descr, XDES_FULL_FRAG, mtr);
|
||||
|
||||
flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
|
||||
mtr);
|
||||
mlog_write_ulint(header + FSP_FRAG_N_USED,
|
||||
frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
|
||||
mtr);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Gets a buffer block for an allocated page.
|
||||
|
||||
NOTE: If init_mtr != mtr, the block will only be initialized if it was
|
||||
not previously x-latched. It is assumed that the block has been
|
||||
x-latched only by mtr, and freed in mtr in that case.
|
||||
|
||||
@return block, initialized if init_mtr==mtr
|
||||
or rw_lock_x_lock_count(&block->lock) == 1 */
|
||||
static
|
||||
ulint
|
||||
buf_block_t*
|
||||
fsp_page_create(
|
||||
/*============*/
|
||||
ulint space, /*!< in: space id of the allocated page */
|
||||
ulint zip_size, /*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
ulint page_no, /*!< in: page number of the allocated page */
|
||||
mtr_t* mtr, /*!< in: mini-transaction of the allocation */
|
||||
mtr_t* init_mtr) /*!< in: mini-transaction for initializing
|
||||
the page */
|
||||
{
|
||||
buf_block_t* block
|
||||
= buf_page_create(space, page_no, zip_size, init_mtr);
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX)
|
||||
== rw_lock_own(&block->lock, RW_LOCK_EX));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
/* Mimic buf_page_get(), but avoid the buf_pool->page_hash lookup. */
|
||||
rw_lock_x_lock(&block->lock);
|
||||
mutex_enter(&block->mutex);
|
||||
buf_block_buf_fix_inc(block, __FILE__, __LINE__);
|
||||
mutex_exit(&block->mutex);
|
||||
mtr_memo_push(init_mtr, block, MTR_MEMO_PAGE_X_FIX);
|
||||
|
||||
if (init_mtr == mtr
|
||||
|| rw_lock_get_x_lock_count(&block->lock) == 1) {
|
||||
|
||||
/* Initialize the page, unless it was already
|
||||
X-latched in mtr. (In this case, we would want to
|
||||
allocate another page that has not been freed in mtr.) */
|
||||
ut_ad(init_mtr == mtr
|
||||
|| !mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
|
||||
|
||||
fsp_init_file_page(block, init_mtr);
|
||||
}
|
||||
|
||||
return(block);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Allocates a single free page from a space. The page is marked as used.
|
||||
@retval NULL if no page could be allocated
|
||||
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||
@retval block (not allocated or initialized) otherwise */
|
||||
static __attribute__((nonnull, warn_unused_result))
|
||||
buf_block_t*
|
||||
fsp_alloc_free_page(
|
||||
/*================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
ulint hint, /*!< in: hint of which page would be desirable */
|
||||
mtr_t* mtr) /*!< in: mtr handle */
|
||||
mtr_t* mtr, /*!< in/out: mini-transaction */
|
||||
mtr_t* init_mtr)/*!< in/out: mini-transaction in which the
|
||||
page should be initialized
|
||||
(may be the same as mtr) */
|
||||
{
|
||||
fsp_header_t* header;
|
||||
fil_addr_t first;
|
||||
xdes_t* descr;
|
||||
buf_block_t* block;
|
||||
ulint free;
|
||||
ulint frag_n_used;
|
||||
ulint page_no;
|
||||
ulint space_size;
|
||||
ibool success;
|
||||
|
||||
ut_ad(mtr);
|
||||
ut_ad(init_mtr);
|
||||
|
||||
header = fsp_get_space_header(space, zip_size, mtr);
|
||||
|
||||
|
|
@ -1525,7 +1623,7 @@ fsp_alloc_free_page(
|
|||
if (descr == NULL) {
|
||||
/* No free space left */
|
||||
|
||||
return(FIL_NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
xdes_set_state(descr, XDES_FREE_FRAG, mtr);
|
||||
|
|
@ -1570,50 +1668,18 @@ fsp_alloc_free_page(
|
|||
" space size %lu. Page no %lu.\n",
|
||||
(ulong) space, (ulong) space_size,
|
||||
(ulong) page_no);
|
||||
return(FIL_NULL);
|
||||
return(NULL);
|
||||
}
|
||||
success = fsp_try_extend_data_file_with_pages(space, page_no,
|
||||
header, mtr);
|
||||
if (!success) {
|
||||
if (!fsp_try_extend_data_file_with_pages(space, page_no,
|
||||
header, mtr)) {
|
||||
/* No disk space left */
|
||||
return(FIL_NULL);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
xdes_set_bit(descr, XDES_FREE_BIT, free, FALSE, mtr);
|
||||
fsp_alloc_from_free_frag(header, descr, free, mtr);
|
||||
|
||||
/* Update the FRAG_N_USED field */
|
||||
frag_n_used = mtr_read_ulint(header + FSP_FRAG_N_USED, MLOG_4BYTES,
|
||||
mtr);
|
||||
frag_n_used++;
|
||||
mlog_write_ulint(header + FSP_FRAG_N_USED, frag_n_used, MLOG_4BYTES,
|
||||
mtr);
|
||||
if (xdes_is_full(descr, mtr)) {
|
||||
/* The fragment is full: move it to another list */
|
||||
flst_remove(header + FSP_FREE_FRAG, descr + XDES_FLST_NODE,
|
||||
mtr);
|
||||
xdes_set_state(descr, XDES_FULL_FRAG, mtr);
|
||||
|
||||
flst_add_last(header + FSP_FULL_FRAG, descr + XDES_FLST_NODE,
|
||||
mtr);
|
||||
mlog_write_ulint(header + FSP_FRAG_N_USED,
|
||||
frag_n_used - FSP_EXTENT_SIZE, MLOG_4BYTES,
|
||||
mtr);
|
||||
}
|
||||
|
||||
/* Initialize the allocated page to the buffer pool, so that it can
|
||||
be obtained immediately with buf_page_get without need for a disk
|
||||
read. */
|
||||
|
||||
buf_page_create(space, page_no, zip_size, mtr);
|
||||
|
||||
block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
|
||||
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
|
||||
|
||||
/* Prior contents of the page should be ignored */
|
||||
fsp_init_file_page(block, mtr);
|
||||
|
||||
return(page_no);
|
||||
return(fsp_page_create(space, zip_size, page_no, mtr, init_mtr));
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
@ -1652,6 +1718,9 @@ fsp_free_page(
|
|||
fputs("InnoDB: Dump of descriptor: ", stderr);
|
||||
ut_print_buf(stderr, ((byte*)descr) - 50, 200);
|
||||
putc('\n', stderr);
|
||||
/* Crash in debug version, so that we get a core dump
|
||||
of this corruption. */
|
||||
ut_ad(0);
|
||||
|
||||
if (state == XDES_FREE) {
|
||||
/* We put here some fault tolerance: if the page
|
||||
|
|
@ -1670,6 +1739,9 @@ fsp_free_page(
|
|||
"InnoDB: Dump of descriptor: ", (ulong) page);
|
||||
ut_print_buf(stderr, ((byte*)descr) - 50, 200);
|
||||
putc('\n', stderr);
|
||||
/* Crash in debug version, so that we get a core dump
|
||||
of this corruption. */
|
||||
ut_ad(0);
|
||||
|
||||
/* We put here some fault tolerance: if the page
|
||||
is already free, return without doing anything! */
|
||||
|
|
@ -1704,6 +1776,8 @@ fsp_free_page(
|
|||
mtr);
|
||||
fsp_free_extent(space, zip_size, page, mtr);
|
||||
}
|
||||
|
||||
mtr->n_freed_pages++;
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
@ -1841,7 +1915,6 @@ fsp_alloc_seg_inode_page(
|
|||
fseg_inode_t* inode;
|
||||
buf_block_t* block;
|
||||
page_t* page;
|
||||
ulint page_no;
|
||||
ulint space;
|
||||
ulint zip_size;
|
||||
ulint i;
|
||||
|
|
@ -1852,15 +1925,15 @@ fsp_alloc_seg_inode_page(
|
|||
zip_size = dict_table_flags_to_zip_size(
|
||||
mach_read_from_4(FSP_SPACE_FLAGS + space_header));
|
||||
|
||||
page_no = fsp_alloc_free_page(space, zip_size, 0, mtr);
|
||||
block = fsp_alloc_free_page(space, zip_size, 0, mtr, mtr);
|
||||
|
||||
if (page_no == FIL_NULL) {
|
||||
if (block == NULL) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
block = buf_page_get(space, zip_size, page_no, RW_X_LATCH, mtr);
|
||||
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
|
||||
ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
|
||||
|
||||
block->check_index_page_at_flush = FALSE;
|
||||
|
||||
|
|
@ -2273,19 +2346,20 @@ fseg_create_general(
|
|||
}
|
||||
|
||||
if (page == 0) {
|
||||
page = fseg_alloc_free_page_low(space, zip_size,
|
||||
inode, 0, FSP_UP, mtr);
|
||||
block = fseg_alloc_free_page_low(space, zip_size,
|
||||
inode, 0, FSP_UP, mtr, mtr);
|
||||
|
||||
if (page == FIL_NULL) {
|
||||
if (block == NULL) {
|
||||
|
||||
fsp_free_seg_inode(space, zip_size, inode, mtr);
|
||||
|
||||
goto funct_exit;
|
||||
}
|
||||
|
||||
block = buf_page_get(space, zip_size, page, RW_X_LATCH, mtr);
|
||||
ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
|
||||
|
||||
header = byte_offset + buf_block_get_frame(block);
|
||||
mlog_write_ulint(header - byte_offset + FIL_PAGE_TYPE,
|
||||
mlog_write_ulint(buf_block_get_frame(block) + FIL_PAGE_TYPE,
|
||||
FIL_PAGE_TYPE_SYS, MLOG_2BYTES, mtr);
|
||||
}
|
||||
|
||||
|
|
@ -2462,8 +2536,10 @@ fseg_fill_free_list(
|
|||
Allocates a free extent for the segment: looks first in the free list of the
|
||||
segment, then tries to allocate from the space free list. NOTE that the extent
|
||||
returned still resides in the segment free list, it is not yet taken off it!
|
||||
@return allocated extent, still placed in the segment free list, NULL
|
||||
if could not be allocated */
|
||||
@retval NULL if no page could be allocated
|
||||
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||
@retval block (not allocated or initialized) otherwise */
|
||||
static
|
||||
xdes_t*
|
||||
fseg_alloc_free_extent(
|
||||
|
|
@ -2515,22 +2591,30 @@ fseg_alloc_free_extent(
|
|||
Allocates a single free page from a segment. This function implements
|
||||
the intelligent allocation strategy which tries to minimize file space
|
||||
fragmentation.
|
||||
@return the allocated page number, FIL_NULL if no page could be allocated */
|
||||
@retval NULL if no page could be allocated
|
||||
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||
@retval block (not allocated or initialized) otherwise */
|
||||
static
|
||||
ulint
|
||||
buf_block_t*
|
||||
fseg_alloc_free_page_low(
|
||||
/*=====================*/
|
||||
ulint space, /*!< in: space */
|
||||
ulint zip_size,/*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
fseg_inode_t* seg_inode, /*!< in: segment inode */
|
||||
ulint hint, /*!< in: hint of which page would be desirable */
|
||||
fseg_inode_t* seg_inode, /*!< in/out: segment inode */
|
||||
ulint hint, /*!< in: hint of which page would be
|
||||
desirable */
|
||||
byte direction, /*!< in: if the new page is needed because
|
||||
of an index page split, and records are
|
||||
inserted there in order, into which
|
||||
direction they go alphabetically: FSP_DOWN,
|
||||
FSP_UP, FSP_NO_DIR */
|
||||
mtr_t* mtr) /*!< in: mtr handle */
|
||||
mtr_t* mtr, /*!< in/out: mini-transaction */
|
||||
mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
|
||||
in which the page should be initialized.
|
||||
If init_mtr!=mtr, but the page is already
|
||||
latched in mtr, do not initialize the page. */
|
||||
{
|
||||
fsp_header_t* space_header;
|
||||
ulint space_size;
|
||||
|
|
@ -2541,7 +2625,6 @@ fseg_alloc_free_page_low(
|
|||
ulint ret_page; /*!< the allocated page offset, FIL_NULL
|
||||
if could not be allocated */
|
||||
xdes_t* ret_descr; /*!< the extent of the allocated page */
|
||||
ibool frag_page_allocated = FALSE;
|
||||
ibool success;
|
||||
ulint n;
|
||||
|
||||
|
|
@ -2563,6 +2646,7 @@ fseg_alloc_free_page_low(
|
|||
if (descr == NULL) {
|
||||
/* Hint outside space or too high above free limit: reset
|
||||
hint */
|
||||
/* The file space header page is always allocated. */
|
||||
hint = 0;
|
||||
descr = xdes_get_descriptor(space, zip_size, hint, mtr);
|
||||
}
|
||||
|
|
@ -2573,15 +2657,19 @@ fseg_alloc_free_page_low(
|
|||
&& mach_read_from_8(descr + XDES_ID) == seg_id
|
||||
&& (xdes_get_bit(descr, XDES_FREE_BIT,
|
||||
hint % FSP_EXTENT_SIZE, mtr) == TRUE)) {
|
||||
|
||||
take_hinted_page:
|
||||
/* 1. We can take the hinted page
|
||||
=================================*/
|
||||
ret_descr = descr;
|
||||
ret_page = hint;
|
||||
/* Skip the check for extending the tablespace. If the
|
||||
page hint were not within the size of the tablespace,
|
||||
we would have got (descr == NULL) above and reset the hint. */
|
||||
goto got_hinted_page;
|
||||
/*-----------------------------------------------------------*/
|
||||
} else if ((xdes_get_state(descr, mtr) == XDES_FREE)
|
||||
&& ((reserved - used) < reserved / FSEG_FILLFACTOR)
|
||||
&& (used >= FSEG_FRAG_LIMIT)) {
|
||||
} else if (xdes_get_state(descr, mtr) == XDES_FREE
|
||||
&& reserved - used < reserved / FSEG_FILLFACTOR
|
||||
&& used >= FSEG_FRAG_LIMIT) {
|
||||
|
||||
/* 2. We allocate the free extent from space and can take
|
||||
=========================================================
|
||||
|
|
@ -2599,7 +2687,7 @@ fseg_alloc_free_page_low(
|
|||
/* Try to fill the segment free list */
|
||||
fseg_fill_free_list(seg_inode, space, zip_size,
|
||||
hint + FSP_EXTENT_SIZE, mtr);
|
||||
ret_page = hint;
|
||||
goto take_hinted_page;
|
||||
/*-----------------------------------------------------------*/
|
||||
} else if ((direction != FSP_NO_DIR)
|
||||
&& ((reserved - used) < reserved / FSEG_FILLFACTOR)
|
||||
|
|
@ -2647,7 +2735,7 @@ fseg_alloc_free_page_low(
|
|||
first = flst_get_first(seg_inode + FSEG_FREE, mtr);
|
||||
} else {
|
||||
ut_error;
|
||||
return(FIL_NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ret_descr = xdes_lst_get_descriptor(space, zip_size,
|
||||
|
|
@ -2659,20 +2747,23 @@ fseg_alloc_free_page_low(
|
|||
} else if (used < FSEG_FRAG_LIMIT) {
|
||||
/* 6. We allocate an individual page from the space
|
||||
===================================================*/
|
||||
ret_page = fsp_alloc_free_page(space, zip_size, hint, mtr);
|
||||
ret_descr = NULL;
|
||||
buf_block_t* block = fsp_alloc_free_page(
|
||||
space, zip_size, hint, mtr, init_mtr);
|
||||
|
||||
frag_page_allocated = TRUE;
|
||||
|
||||
if (ret_page != FIL_NULL) {
|
||||
if (block != NULL) {
|
||||
/* Put the page in the fragment page array of the
|
||||
segment */
|
||||
n = fseg_find_free_frag_page_slot(seg_inode, mtr);
|
||||
ut_a(n != FIL_NULL);
|
||||
ut_a(n != ULINT_UNDEFINED);
|
||||
|
||||
fseg_set_nth_frag_page_no(seg_inode, n, ret_page,
|
||||
mtr);
|
||||
fseg_set_nth_frag_page_no(
|
||||
seg_inode, n, buf_block_get_page_no(block),
|
||||
mtr);
|
||||
}
|
||||
|
||||
/* fsp_alloc_free_page() invoked fsp_init_file_page()
|
||||
already. */
|
||||
return(block);
|
||||
/*-----------------------------------------------------------*/
|
||||
} else {
|
||||
/* 7. We allocate a new extent and take its first page
|
||||
|
|
@ -2690,7 +2781,7 @@ fseg_alloc_free_page_low(
|
|||
if (ret_page == FIL_NULL) {
|
||||
/* Page could not be allocated */
|
||||
|
||||
return(FIL_NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (space != 0) {
|
||||
|
|
@ -2708,38 +2799,22 @@ fseg_alloc_free_page_low(
|
|||
" the space size %lu. Page no %lu.\n",
|
||||
(ulong) space, (ulong) space_size,
|
||||
(ulong) ret_page);
|
||||
return(FIL_NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
success = fsp_try_extend_data_file_with_pages(
|
||||
space, ret_page, space_header, mtr);
|
||||
if (!success) {
|
||||
/* No disk space left */
|
||||
return(FIL_NULL);
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!frag_page_allocated) {
|
||||
/* Initialize the allocated page to buffer pool, so that it
|
||||
can be obtained immediately with buf_page_get without need
|
||||
for a disk read */
|
||||
buf_block_t* block;
|
||||
ulint zip_size = dict_table_flags_to_zip_size(
|
||||
mach_read_from_4(FSP_SPACE_FLAGS + space_header));
|
||||
|
||||
block = buf_page_create(space, ret_page, zip_size, mtr);
|
||||
buf_block_dbg_add_level(block, SYNC_FSP_PAGE);
|
||||
|
||||
if (UNIV_UNLIKELY(block != buf_page_get(space, zip_size,
|
||||
ret_page, RW_X_LATCH,
|
||||
mtr))) {
|
||||
ut_error;
|
||||
}
|
||||
|
||||
/* The prior contents of the page should be ignored */
|
||||
fsp_init_file_page(block, mtr);
|
||||
|
||||
got_hinted_page:
|
||||
/* ret_descr == NULL if the block was allocated from free_frag
|
||||
(XDES_FREE_FRAG) */
|
||||
if (ret_descr != NULL) {
|
||||
/* At this point we know the extent and the page offset.
|
||||
The extent is still in the appropriate list (FSEG_NOT_FULL
|
||||
or FSEG_FREE), and the page is not yet marked as used. */
|
||||
|
|
@ -2752,22 +2827,28 @@ fseg_alloc_free_page_low(
|
|||
fseg_mark_page_used(seg_inode, ret_page, ret_descr, mtr);
|
||||
}
|
||||
|
||||
buf_reset_check_index_page_at_flush(space, ret_page);
|
||||
|
||||
return(ret_page);
|
||||
return(fsp_page_create(
|
||||
space, dict_table_flags_to_zip_size(
|
||||
mach_read_from_4(FSP_SPACE_FLAGS
|
||||
+ space_header)),
|
||||
ret_page, mtr, init_mtr));
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Allocates a single free page from a segment. This function implements
|
||||
the intelligent allocation strategy which tries to minimize file space
|
||||
fragmentation.
|
||||
@return allocated page offset, FIL_NULL if no page could be allocated */
|
||||
@retval NULL if no page could be allocated
|
||||
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||
@retval block (not allocated or initialized) otherwise */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
buf_block_t*
|
||||
fseg_alloc_free_page_general(
|
||||
/*=========================*/
|
||||
fseg_header_t* seg_header,/*!< in: segment header */
|
||||
ulint hint, /*!< in: hint of which page would be desirable */
|
||||
fseg_header_t* seg_header,/*!< in/out: segment header */
|
||||
ulint hint, /*!< in: hint of which page would be
|
||||
desirable */
|
||||
byte direction,/*!< in: if the new page is needed because
|
||||
of an index page split, and records are
|
||||
inserted there in order, into which
|
||||
|
|
@ -2778,15 +2859,18 @@ fseg_alloc_free_page_general(
|
|||
with fsp_reserve_free_extents, then there
|
||||
is no need to do the check for this individual
|
||||
page */
|
||||
mtr_t* mtr) /*!< in: mtr handle */
|
||||
mtr_t* mtr, /*!< in/out: mini-transaction handle */
|
||||
mtr_t* init_mtr)/*!< in/out: mtr or another mini-transaction
|
||||
in which the page should be initialized.
|
||||
If init_mtr!=mtr, but the page is already
|
||||
latched in mtr, do not initialize the page. */
|
||||
{
|
||||
fseg_inode_t* inode;
|
||||
ulint space;
|
||||
ulint flags;
|
||||
ulint zip_size;
|
||||
rw_lock_t* latch;
|
||||
ibool success;
|
||||
ulint page_no;
|
||||
buf_block_t* block;
|
||||
ulint n_reserved;
|
||||
|
||||
space = page_get_space_id(page_align(seg_header));
|
||||
|
|
@ -2811,43 +2895,20 @@ fseg_alloc_free_page_general(
|
|||
|
||||
inode = fseg_inode_get(seg_header, space, zip_size, mtr);
|
||||
|
||||
if (!has_done_reservation) {
|
||||
success = fsp_reserve_free_extents(&n_reserved, space, 2,
|
||||
FSP_NORMAL, mtr);
|
||||
if (!success) {
|
||||
return(FIL_NULL);
|
||||
}
|
||||
if (!has_done_reservation
|
||||
&& !fsp_reserve_free_extents(&n_reserved, space, 2,
|
||||
FSP_NORMAL, mtr)) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
page_no = fseg_alloc_free_page_low(space, zip_size,
|
||||
inode, hint, direction, mtr);
|
||||
block = fseg_alloc_free_page_low(space, zip_size,
|
||||
inode, hint, direction,
|
||||
mtr, init_mtr);
|
||||
if (!has_done_reservation) {
|
||||
fil_space_release_free_extents(space, n_reserved);
|
||||
}
|
||||
|
||||
return(page_no);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Allocates a single free page from a segment. This function implements
|
||||
the intelligent allocation strategy which tries to minimize file space
|
||||
fragmentation.
|
||||
@return allocated page offset, FIL_NULL if no page could be allocated */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
fseg_alloc_free_page(
|
||||
/*=================*/
|
||||
fseg_header_t* seg_header,/*!< in: segment header */
|
||||
ulint hint, /*!< in: hint of which page would be desirable */
|
||||
byte direction,/*!< in: if the new page is needed because
|
||||
of an index page split, and records are
|
||||
inserted there in order, into which
|
||||
direction they go alphabetically: FSP_DOWN,
|
||||
FSP_UP, FSP_NO_DIR */
|
||||
mtr_t* mtr) /*!< in: mtr handle */
|
||||
{
|
||||
return(fseg_alloc_free_page_general(seg_header, hint, direction,
|
||||
FALSE, mtr));
|
||||
return(block);
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
@ -3358,6 +3419,8 @@ crash:
|
|||
descr + XDES_FLST_NODE, mtr);
|
||||
fsp_free_extent(space, zip_size, page, mtr);
|
||||
}
|
||||
|
||||
mtr->n_freed_pages++;
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2000, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2000, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, 2009 Google Inc.
|
||||
Copyright (c) 2009, Percona Inc.
|
||||
|
||||
|
|
@ -26,8 +26,8 @@ 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., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
|
|
@ -194,6 +194,9 @@ static my_bool innobase_create_status_file = FALSE;
|
|||
static my_bool innobase_stats_on_metadata = TRUE;
|
||||
static my_bool innobase_large_prefix = FALSE;
|
||||
static my_bool innobase_use_sys_stats_table = FALSE;
|
||||
#ifdef UNIV_DEBUG
|
||||
static ulong innobase_sys_stats_root_page = 0;
|
||||
#endif
|
||||
static my_bool innobase_buffer_pool_shm_checksum = TRUE;
|
||||
static uint innobase_buffer_pool_shm_key = 0;
|
||||
|
||||
|
|
@ -1169,6 +1172,9 @@ convert_error_code_to_mysql(
|
|||
case DB_OUT_OF_FILE_SPACE:
|
||||
return(HA_ERR_RECORD_FILE_FULL);
|
||||
|
||||
case DB_TABLE_IN_FK_CHECK:
|
||||
return(HA_ERR_TABLE_IN_FK_CHECK);
|
||||
|
||||
case DB_TABLE_IS_BEING_USED:
|
||||
return(HA_ERR_WRONG_COMMAND);
|
||||
|
||||
|
|
@ -2718,6 +2724,10 @@ mem_free_and_error:
|
|||
|
||||
srv_use_sys_stats_table = (ibool) innobase_use_sys_stats_table;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
srv_sys_stats_root_page = innobase_sys_stats_root_page;
|
||||
#endif
|
||||
|
||||
/* -------------- Log files ---------------------------*/
|
||||
|
||||
/* The default dir for log files is the datadir of MySQL */
|
||||
|
|
@ -3815,52 +3825,140 @@ ha_innobase::primary_key_is_clustered()
|
|||
return(true);
|
||||
}
|
||||
|
||||
/** Always normalize table name to lower case on Windows */
|
||||
#ifdef __WIN__
|
||||
#define normalize_table_name(norm_name, name) \
|
||||
normalize_table_name_low(norm_name, name, TRUE)
|
||||
#else
|
||||
#define normalize_table_name(norm_name, name) \
|
||||
normalize_table_name_low(norm_name, name, FALSE)
|
||||
#endif /* __WIN__ */
|
||||
|
||||
/*****************************************************************//**
|
||||
Normalizes a table name string. A normalized name consists of the
|
||||
database name catenated to '/' and table name. An example:
|
||||
test/mytable. On Windows normalization puts both the database name and the
|
||||
table name always to lower case. */
|
||||
table name always to lower case if "set_lower_case" is set to TRUE. */
|
||||
static
|
||||
void
|
||||
normalize_table_name(
|
||||
/*=================*/
|
||||
normalize_table_name_low(
|
||||
/*=====================*/
|
||||
char* norm_name, /*!< out: normalized name as a
|
||||
null-terminated string */
|
||||
const char* name) /*!< in: table name string */
|
||||
const char* name, /*!< in: table name string */
|
||||
ibool set_lower_case) /*!< in: TRUE if we want to set
|
||||
name to lower case */
|
||||
{
|
||||
char* name_ptr;
|
||||
char* db_ptr;
|
||||
ulint db_len;
|
||||
char* ptr;
|
||||
|
||||
/* Scan name from the end */
|
||||
|
||||
ptr = strend(name)-1;
|
||||
ptr = strend(name) - 1;
|
||||
|
||||
/* seek to the last path separator */
|
||||
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
|
||||
ptr--;
|
||||
}
|
||||
|
||||
name_ptr = ptr + 1;
|
||||
|
||||
DBUG_ASSERT(ptr > name);
|
||||
/* skip any number of path separators */
|
||||
while (ptr >= name && (*ptr == '\\' || *ptr == '/')) {
|
||||
ptr--;
|
||||
}
|
||||
|
||||
ptr--;
|
||||
DBUG_ASSERT(ptr >= name);
|
||||
|
||||
/* seek to the last but one path separator or one char before
|
||||
the beginning of name */
|
||||
db_len = 0;
|
||||
while (ptr >= name && *ptr != '\\' && *ptr != '/') {
|
||||
ptr--;
|
||||
db_len++;
|
||||
}
|
||||
|
||||
db_ptr = ptr + 1;
|
||||
|
||||
memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
|
||||
memcpy(norm_name, db_ptr, db_len);
|
||||
|
||||
norm_name[name_ptr - db_ptr - 1] = '/';
|
||||
norm_name[db_len] = '/';
|
||||
|
||||
#ifdef __WIN__
|
||||
innobase_casedn_str(norm_name);
|
||||
#endif
|
||||
memcpy(norm_name + db_len + 1, name_ptr, strlen(name_ptr) + 1);
|
||||
|
||||
if (set_lower_case) {
|
||||
innobase_casedn_str(norm_name);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(DBUG_OFF)
|
||||
/*********************************************************************
|
||||
Test normalize_table_name_low(). */
|
||||
static
|
||||
void
|
||||
test_normalize_table_name_low()
|
||||
/*===========================*/
|
||||
{
|
||||
char norm_name[128];
|
||||
const char* test_data[][2] = {
|
||||
/* input, expected result */
|
||||
{"./mysqltest/t1", "mysqltest/t1"},
|
||||
{"./test/#sql-842b_2", "test/#sql-842b_2"},
|
||||
{"./test/#sql-85a3_10", "test/#sql-85a3_10"},
|
||||
{"./test/#sql2-842b-2", "test/#sql2-842b-2"},
|
||||
{"./test/bug29807", "test/bug29807"},
|
||||
{"./test/foo", "test/foo"},
|
||||
{"./test/innodb_bug52663", "test/innodb_bug52663"},
|
||||
{"./test/t", "test/t"},
|
||||
{"./test/t1", "test/t1"},
|
||||
{"./test/t10", "test/t10"},
|
||||
{"/a/b/db/table", "db/table"},
|
||||
{"/a/b/db///////table", "db/table"},
|
||||
{"/a/b////db///////table", "db/table"},
|
||||
{"/var/tmp/mysqld.1/#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
|
||||
{"db/table", "db/table"},
|
||||
{"ddd/t", "ddd/t"},
|
||||
{"d/ttt", "d/ttt"},
|
||||
{"d/t", "d/t"},
|
||||
{".\\mysqltest\\t1", "mysqltest/t1"},
|
||||
{".\\test\\#sql-842b_2", "test/#sql-842b_2"},
|
||||
{".\\test\\#sql-85a3_10", "test/#sql-85a3_10"},
|
||||
{".\\test\\#sql2-842b-2", "test/#sql2-842b-2"},
|
||||
{".\\test\\bug29807", "test/bug29807"},
|
||||
{".\\test\\foo", "test/foo"},
|
||||
{".\\test\\innodb_bug52663", "test/innodb_bug52663"},
|
||||
{".\\test\\t", "test/t"},
|
||||
{".\\test\\t1", "test/t1"},
|
||||
{".\\test\\t10", "test/t10"},
|
||||
{"C:\\a\\b\\db\\table", "db/table"},
|
||||
{"C:\\a\\b\\db\\\\\\\\\\\\\\table", "db/table"},
|
||||
{"C:\\a\\b\\\\\\\\db\\\\\\\\\\\\\\table", "db/table"},
|
||||
{"C:\\var\\tmp\\mysqld.1\\#sql842b_2_10", "mysqld.1/#sql842b_2_10"},
|
||||
{"db\\table", "db/table"},
|
||||
{"ddd\\t", "ddd/t"},
|
||||
{"d\\ttt", "d/ttt"},
|
||||
{"d\\t", "d/t"},
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < UT_ARR_SIZE(test_data); i++) {
|
||||
printf("test_normalize_table_name_low(): "
|
||||
"testing \"%s\", expected \"%s\"... ",
|
||||
test_data[i][0], test_data[i][1]);
|
||||
|
||||
normalize_table_name_low(norm_name, test_data[i][0], FALSE);
|
||||
|
||||
if (strcmp(norm_name, test_data[i][1]) == 0) {
|
||||
printf("ok\n");
|
||||
} else {
|
||||
printf("got \"%s\"\n", norm_name);
|
||||
ut_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !DBUG_OFF */
|
||||
|
||||
/********************************************************************//**
|
||||
Get the upper limit of the MySQL integral and floating-point type.
|
||||
@return maximum allowed value for the field */
|
||||
|
|
@ -4262,6 +4360,8 @@ ha_innobase::open(
|
|||
THD* thd;
|
||||
ulint retries = 0;
|
||||
char* is_part = NULL;
|
||||
ibool par_case_name_set = FALSE;
|
||||
char par_case_name[MAX_FULL_NAME_LEN + 1];
|
||||
|
||||
DBUG_ENTER("ha_innobase::open");
|
||||
|
||||
|
|
@ -4292,51 +4392,107 @@ ha_innobase::open(
|
|||
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
|
||||
}
|
||||
|
||||
/* Create buffers for packing the fields of a record. Why
|
||||
table->stored_rec_length did not work here? Obviously, because char
|
||||
fields when packed actually became 1 byte longer, when we also
|
||||
stored the string length as the first byte. */
|
||||
|
||||
upd_and_key_val_buff_len =
|
||||
table->s->stored_rec_length + table->s->max_key_length
|
||||
+ MAX_REF_PARTS * 3;
|
||||
if (!(uchar*) my_multi_malloc(MYF(MY_WME),
|
||||
&upd_buff, upd_and_key_val_buff_len,
|
||||
&key_val_buff, upd_and_key_val_buff_len,
|
||||
NullS)) {
|
||||
free_share(share);
|
||||
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
/* Will be allocated if it is needed in ::update_row() */
|
||||
upd_buf = NULL;
|
||||
upd_buf_size = 0;
|
||||
|
||||
/* We look for pattern #P# to see if the table is partitioned
|
||||
MySQL table. The retry logic for partitioned tables is a
|
||||
workaround for http://bugs.mysql.com/bug.php?id=33349. Look
|
||||
at support issue https://support.mysql.com/view.php?id=21080
|
||||
for more details. */
|
||||
#ifdef __WIN__
|
||||
is_part = strstr(norm_name, "#p#");
|
||||
#else
|
||||
is_part = strstr(norm_name, "#P#");
|
||||
#endif /* __WIN__ */
|
||||
|
||||
retry:
|
||||
/* Get pointer to a table object in InnoDB dictionary cache */
|
||||
ib_table = dict_table_get(norm_name, TRUE);
|
||||
|
||||
|
||||
if (srv_pass_corrupt_table <= 1 && ib_table && ib_table->is_corrupt) {
|
||||
free_share(share);
|
||||
my_free(upd_buff);
|
||||
my_free(upd_buf);
|
||||
upd_buf = NULL;
|
||||
upd_buf_size = 0;
|
||||
|
||||
DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
|
||||
}
|
||||
|
||||
share->ib_table = ib_table;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (NULL == ib_table) {
|
||||
if (is_part && retries < 10) {
|
||||
++retries;
|
||||
os_thread_sleep(100000);
|
||||
goto retry;
|
||||
/* MySQL partition engine hard codes the file name
|
||||
separator as "#P#". The text case is fixed even if
|
||||
lower_case_table_names is set to 1 or 2. This is true
|
||||
for sub-partition names as well. InnoDB always
|
||||
normalises file names to lower case on Windows, this
|
||||
can potentially cause problems when copying/moving
|
||||
tables between platforms.
|
||||
|
||||
1) If boot against an installation from Windows
|
||||
platform, then its partition table name could
|
||||
be all be in lower case in system tables. So we
|
||||
will need to check lower case name when load table.
|
||||
|
||||
2) If we boot an installation from other case
|
||||
sensitive platform in Windows, we might need to
|
||||
check the existence of table name without lowering
|
||||
case them in the system table. */
|
||||
if (innobase_get_lower_case_table_names() == 1) {
|
||||
|
||||
if (!par_case_name_set) {
|
||||
#ifndef __WIN__
|
||||
/* Check for the table using lower
|
||||
case name, including the partition
|
||||
separator "P" */
|
||||
memcpy(par_case_name, norm_name,
|
||||
strlen(norm_name));
|
||||
par_case_name[strlen(norm_name)] = 0;
|
||||
innobase_casedn_str(par_case_name);
|
||||
#else
|
||||
/* On Windows platfrom, check
|
||||
whether there exists table name in
|
||||
system table whose name is
|
||||
not being normalized to lower case */
|
||||
normalize_table_name_low(
|
||||
par_case_name, name, FALSE);
|
||||
#endif
|
||||
par_case_name_set = TRUE;
|
||||
}
|
||||
|
||||
ib_table = dict_table_get(
|
||||
par_case_name, FALSE);
|
||||
}
|
||||
if (!ib_table) {
|
||||
++retries;
|
||||
os_thread_sleep(100000);
|
||||
goto retry;
|
||||
} else {
|
||||
#ifndef __WIN__
|
||||
sql_print_warning("Partition table %s opened "
|
||||
"after converting to lower "
|
||||
"case. The table may have "
|
||||
"been moved from a case "
|
||||
"in-sensitive file system. "
|
||||
"Please recreate table in "
|
||||
"the current file system\n",
|
||||
norm_name);
|
||||
#else
|
||||
sql_print_warning("Partition table %s opened "
|
||||
"after skipping the step to "
|
||||
"lower case the table name. "
|
||||
"The table may have been "
|
||||
"moved from a case sensitive "
|
||||
"file system. Please "
|
||||
"recreate table in the "
|
||||
"current file system\n",
|
||||
norm_name);
|
||||
#endif
|
||||
goto table_opened;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_part) {
|
||||
|
|
@ -4361,12 +4517,13 @@ retry:
|
|||
"how you can resolve the problem.\n",
|
||||
norm_name);
|
||||
free_share(share);
|
||||
my_free(upd_buff);
|
||||
my_errno = ENOENT;
|
||||
|
||||
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
|
||||
}
|
||||
|
||||
table_opened:
|
||||
|
||||
if (ib_table->ibd_file_missing && !thd_tablespace_op(thd)) {
|
||||
sql_print_error("MySQL is trying to open a table handle but "
|
||||
"the .ibd file for\ntable %s does not exist.\n"
|
||||
|
|
@ -4377,16 +4534,14 @@ retry:
|
|||
"how you can resolve the problem.\n",
|
||||
norm_name);
|
||||
free_share(share);
|
||||
my_free(upd_buff);
|
||||
my_errno = ENOENT;
|
||||
|
||||
dict_table_decrement_handle_count(ib_table, FALSE);
|
||||
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
|
||||
}
|
||||
|
||||
prebuilt = row_create_prebuilt(ib_table);
|
||||
prebuilt = row_create_prebuilt(ib_table, table->s->stored_rec_length);
|
||||
|
||||
prebuilt->mysql_row_len = table->s->stored_rec_length;;
|
||||
prebuilt->default_rec = table->s->default_values;
|
||||
ut_ad(prebuilt->default_rec);
|
||||
|
||||
|
|
@ -4575,7 +4730,13 @@ ha_innobase::close(void)
|
|||
|
||||
row_prebuilt_free(prebuilt, FALSE);
|
||||
|
||||
my_free(upd_buff);
|
||||
if (upd_buf != NULL) {
|
||||
ut_ad(upd_buf_size != 0);
|
||||
my_free(upd_buf);
|
||||
upd_buf = NULL;
|
||||
upd_buf_size = 0;
|
||||
}
|
||||
|
||||
free_share(share);
|
||||
|
||||
/* Tell InnoDB server that there might be work for
|
||||
|
|
@ -6101,6 +6262,23 @@ ha_innobase::update_row(
|
|||
|
||||
ut_a(prebuilt->trx == trx);
|
||||
|
||||
if (upd_buf == NULL) {
|
||||
ut_ad(upd_buf_size == 0);
|
||||
|
||||
/* Create a buffer for packing the fields of a record. Why
|
||||
table->stored_rec_length did not work here? Obviously, because char
|
||||
fields when packed actually became 1 byte longer, when we also
|
||||
stored the string length as the first byte. */
|
||||
|
||||
upd_buf_size = table->s->stored_rec_length + table->s->max_key_length
|
||||
+ MAX_REF_PARTS * 3;
|
||||
upd_buf = (uchar*) my_malloc(upd_buf_size, MYF(MY_WME));
|
||||
if (upd_buf == NULL) {
|
||||
upd_buf_size = 0;
|
||||
DBUG_RETURN(HA_ERR_OUT_OF_MEM);
|
||||
}
|
||||
}
|
||||
|
||||
ha_statistic_increment(&SSV::ha_update_count);
|
||||
|
||||
if (share->ib_table->is_corrupt) {
|
||||
|
|
@ -6117,11 +6295,10 @@ ha_innobase::update_row(
|
|||
}
|
||||
|
||||
/* Build an update vector from the modified fields in the rows
|
||||
(uses upd_buff of the handle) */
|
||||
(uses upd_buf of the handle) */
|
||||
|
||||
calc_row_difference(uvect, (uchar*) old_row, new_row, table,
|
||||
upd_buff, (ulint)upd_and_key_val_buff_len,
|
||||
prebuilt, user_thd);
|
||||
upd_buf, upd_buf_size, prebuilt, user_thd);
|
||||
|
||||
/* This is not a delete */
|
||||
prebuilt->upd_node->is_delete = FALSE;
|
||||
|
|
@ -6492,6 +6669,7 @@ ha_innobase::index_read(
|
|||
DBUG_ENTER("index_read");
|
||||
|
||||
ut_a(prebuilt->trx == thd_to_trx(user_thd));
|
||||
ut_ad(key_len != 0 || find_flag != HA_READ_KEY_EXACT);
|
||||
|
||||
ha_statistic_increment(&SSV::ha_read_key_count);
|
||||
|
||||
|
|
@ -6524,8 +6702,7 @@ ha_innobase::index_read(
|
|||
|
||||
row_sel_convert_mysql_key_to_innobase(
|
||||
prebuilt->search_tuple,
|
||||
(byte*) key_val_buff,
|
||||
(ulint)upd_and_key_val_buff_len,
|
||||
srch_key_val1, sizeof(srch_key_val1),
|
||||
index,
|
||||
(byte*) key_ptr,
|
||||
(ulint) key_len,
|
||||
|
|
@ -7695,6 +7872,8 @@ ha_innobase::create(
|
|||
DBUG_RETURN(HA_ERR_TO_BIG_ROW);
|
||||
}
|
||||
|
||||
ut_a(strlen(name) < sizeof(name2));
|
||||
|
||||
strcpy(name2, name);
|
||||
|
||||
normalize_table_name(norm_name, name2);
|
||||
|
|
@ -8138,6 +8317,11 @@ ha_innobase::delete_table(
|
|||
|
||||
DBUG_ENTER("ha_innobase::delete_table");
|
||||
|
||||
DBUG_EXECUTE_IF(
|
||||
"test_normalize_table_name_low",
|
||||
test_normalize_table_name_low();
|
||||
);
|
||||
|
||||
/* Strangely, MySQL passes the table name without the '.frm'
|
||||
extension, in contrast to ::create */
|
||||
normalize_table_name(norm_name, name);
|
||||
|
|
@ -8299,6 +8483,8 @@ innobase_rename_table(
|
|||
normalize_table_name(norm_to, to);
|
||||
normalize_table_name(norm_from, from);
|
||||
|
||||
DEBUG_SYNC_C("innodb_rename_table_ready");
|
||||
|
||||
/* Serialize data dictionary operations with dictionary mutex:
|
||||
no deadlocks can occur then in these operations */
|
||||
|
||||
|
|
@ -8417,12 +8603,6 @@ ha_innobase::records_in_range(
|
|||
{
|
||||
KEY* key;
|
||||
dict_index_t* index;
|
||||
uchar* key_val_buff2 = (uchar*) my_malloc(
|
||||
table->s->stored_rec_length
|
||||
+ table->s->max_key_length + 100,
|
||||
MYF(MY_FAE));
|
||||
ulint buff2_len = table->s->stored_rec_length
|
||||
+ table->s->max_key_length + 100;
|
||||
dtuple_t* range_start;
|
||||
dtuple_t* range_end;
|
||||
ib_int64_t n_rows;
|
||||
|
|
@ -8479,8 +8659,8 @@ ha_innobase::records_in_range(
|
|||
dict_index_copy_types(range_end, index, key_parts);
|
||||
|
||||
row_sel_convert_mysql_key_to_innobase(
|
||||
range_start, (byte*) key_val_buff,
|
||||
(ulint)upd_and_key_val_buff_len,
|
||||
range_start,
|
||||
srch_key_val1, sizeof(srch_key_val1),
|
||||
index,
|
||||
(byte*) (min_key ? min_key->key :
|
||||
(const uchar*) 0),
|
||||
|
|
@ -8491,8 +8671,9 @@ ha_innobase::records_in_range(
|
|||
: range_start->n_fields == 0);
|
||||
|
||||
row_sel_convert_mysql_key_to_innobase(
|
||||
range_end, (byte*) key_val_buff2,
|
||||
buff2_len, index,
|
||||
range_end,
|
||||
srch_key_val2, sizeof(srch_key_val2),
|
||||
index,
|
||||
(byte*) (max_key ? max_key->key :
|
||||
(const uchar*) 0),
|
||||
(ulint) (max_key ? max_key->length : 0),
|
||||
|
|
@ -8519,7 +8700,6 @@ ha_innobase::records_in_range(
|
|||
mem_heap_free(heap);
|
||||
|
||||
func_exit:
|
||||
my_free(key_val_buff2);
|
||||
|
||||
prebuilt->trx->op_info = (char*)"";
|
||||
|
||||
|
|
@ -12382,6 +12562,13 @@ static MYSQL_SYSVAR_BOOL(use_sys_stats_table, innobase_use_sys_stats_table,
|
|||
"So you should use ANALYZE TABLE command intentionally.",
|
||||
NULL, NULL, FALSE);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
static MYSQL_SYSVAR_ULONG(sys_stats_root_page, innobase_sys_stats_root_page,
|
||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||
"Override the SYS_STATS root page id, 0 = no override (for testing only)",
|
||||
NULL, NULL, 0, 0, ULONG_MAX, 0);
|
||||
#endif
|
||||
|
||||
static MYSQL_SYSVAR_BOOL(adaptive_hash_index, btr_search_enabled,
|
||||
PLUGIN_VAR_OPCMDARG,
|
||||
"Enable InnoDB adaptive hash index (enabled by default). "
|
||||
|
|
@ -12598,6 +12785,13 @@ static MYSQL_SYSVAR_ULONG(read_ahead_threshold, srv_read_ahead_threshold,
|
|||
"trigger a readahead.",
|
||||
NULL, NULL, 56, 0, 64, 0);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
static MYSQL_SYSVAR_UINT(trx_rseg_n_slots_debug, trx_rseg_n_slots_debug,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"Debug flags for InnoDB to limit TRX_RSEG_N_SLOTS for trx_rsegf_undo_find_free()",
|
||||
NULL, NULL, 0, 0, 1024, 0);
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
static MYSQL_SYSVAR_LONGLONG(ibuf_max_size, srv_ibuf_max_size,
|
||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||
"The maximum size of the insert buffer. (in bytes)",
|
||||
|
|
@ -12719,14 +12913,6 @@ static MYSQL_SYSVAR_ENUM(adaptive_flushing_method, srv_adaptive_flushing_method,
|
|||
"Choose method of innodb_adaptive_flushing. (native, [estimate], keep_average)",
|
||||
NULL, innodb_adaptive_flushing_method_update, 1, &adaptive_flushing_method_typelib);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
static MYSQL_SYSVAR_ULONG(flush_checkpoint_debug, srv_flush_checkpoint_debug,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"Debug flags for InnoDB flushing and checkpointing (0=none,"
|
||||
"1=stop preflush and checkpointing)",
|
||||
NULL, NULL, 0, 0, 1, 0);
|
||||
#endif
|
||||
|
||||
static MYSQL_SYSVAR_ULONG(import_table_from_xtrabackup, srv_expand_import,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"Enable/Disable converting automatically *.ibd files when import tablespace.",
|
||||
|
|
@ -12832,6 +13018,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
|||
MYSQL_SYSVAR(stats_auto_update),
|
||||
MYSQL_SYSVAR(stats_update_need_lock),
|
||||
MYSQL_SYSVAR(use_sys_stats_table),
|
||||
#ifdef UNIV_DEBUG_never /* disable this flag. --innodb-sys-stats becomes ambiguous */
|
||||
MYSQL_SYSVAR(sys_stats_root_page),
|
||||
#endif
|
||||
MYSQL_SYSVAR(stats_sample_pages),
|
||||
MYSQL_SYSVAR(adaptive_hash_index),
|
||||
MYSQL_SYSVAR(adaptive_hash_index_partitions),
|
||||
|
|
@ -12873,9 +13062,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
|||
MYSQL_SYSVAR(purge_threads),
|
||||
MYSQL_SYSVAR(purge_batch_size),
|
||||
MYSQL_SYSVAR(rollback_segments),
|
||||
#ifdef UNIV_DEBUG
|
||||
MYSQL_SYSVAR(flush_checkpoint_debug),
|
||||
#endif
|
||||
#ifdef UNIV_DEBUG_never /* disable this flag. --innodb-trx becomes ambiguous */
|
||||
MYSQL_SYSVAR(trx_rseg_n_slots_debug),
|
||||
#endif /* UNIV_DEBUG */
|
||||
MYSQL_SYSVAR(corrupt_table_action),
|
||||
MYSQL_SYSVAR(lazy_drop_table),
|
||||
MYSQL_SYSVAR(fake_changes),
|
||||
|
|
|
|||
|
|
@ -79,13 +79,14 @@ class ha_innobase: public handler
|
|||
INNOBASE_SHARE* share; /*!< information for MySQL
|
||||
table locking */
|
||||
|
||||
uchar* upd_buff; /*!< buffer used in updates */
|
||||
uchar* key_val_buff; /*!< buffer used in converting
|
||||
uchar* upd_buf; /*!< buffer used in updates */
|
||||
ulint upd_buf_size; /*!< the size of upd_buf in bytes */
|
||||
uchar srch_key_val1[REC_VERSION_56_MAX_INDEX_COL_LEN + 2];
|
||||
uchar srch_key_val2[REC_VERSION_56_MAX_INDEX_COL_LEN + 2];
|
||||
/*!< buffers used in converting
|
||||
search key values from MySQL format
|
||||
to Innodb format */
|
||||
ulong upd_and_key_val_buff_len;
|
||||
/* the length of each of the previous
|
||||
two buffers */
|
||||
to InnoDB format. "+ 2" for the two
|
||||
bytes where the length is stored */
|
||||
Table_flags int_table_flags;
|
||||
uint primary_key;
|
||||
ulong start_of_scan; /*!< this is set to 1 when we are
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 2005, 2010, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 2005, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
|
@ -11,8 +11,8 @@ 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., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
|
|
@ -878,6 +878,8 @@ ha_innobase::add_index(
|
|||
prebuilt->table, indexed_table,
|
||||
index, num_of_idx, table);
|
||||
|
||||
DBUG_EXECUTE_IF("crash_innodb_add_index_after", DBUG_SUICIDE(););
|
||||
|
||||
error_handling:
|
||||
/* After an error, remove all those index definitions from the
|
||||
dictionary which were defined. */
|
||||
|
|
@ -1020,7 +1022,12 @@ ha_innobase::final_add_index(
|
|||
row_prebuilt_free(prebuilt, TRUE);
|
||||
error = row_merge_drop_table(trx, old_table);
|
||||
add->indexed_table->n_mysql_handles_opened++;
|
||||
prebuilt = row_create_prebuilt(add->indexed_table);
|
||||
prebuilt = row_create_prebuilt(add->indexed_table,
|
||||
0 /* XXX Do we know the mysql_row_len here?
|
||||
Before the addition of this parameter to
|
||||
row_create_prebuilt() the mysql_row_len
|
||||
member was left 0 (from zalloc) in the
|
||||
prebuilt object. */);
|
||||
}
|
||||
|
||||
err = convert_error_code_to_mysql(
|
||||
|
|
@ -1154,7 +1161,9 @@ ha_innobase::prepare_drop_index(
|
|||
goto func_exit;
|
||||
}
|
||||
|
||||
rw_lock_x_lock(dict_index_get_lock(index));
|
||||
index->to_be_dropped = TRUE;
|
||||
rw_lock_x_unlock(dict_index_get_lock(index));
|
||||
}
|
||||
|
||||
/* If FOREIGN_KEY_CHECKS = 1 you may not drop an index defined
|
||||
|
|
@ -1273,7 +1282,9 @@ func_exit:
|
|||
= dict_table_get_first_index(prebuilt->table);
|
||||
|
||||
do {
|
||||
rw_lock_x_lock(dict_index_get_lock(index));
|
||||
index->to_be_dropped = FALSE;
|
||||
rw_lock_x_unlock(dict_index_get_lock(index));
|
||||
index = dict_table_get_next_index(index);
|
||||
} while (index);
|
||||
}
|
||||
|
|
@ -1339,7 +1350,9 @@ ha_innobase::final_drop_index(
|
|||
for (index = dict_table_get_first_index(prebuilt->table);
|
||||
index; index = dict_table_get_next_index(index)) {
|
||||
|
||||
rw_lock_x_lock(dict_index_get_lock(index));
|
||||
index->to_be_dropped = FALSE;
|
||||
rw_lock_x_unlock(dict_index_get_lock(index));
|
||||
}
|
||||
|
||||
goto func_exit;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1997, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 1997, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
|
@ -11,8 +11,8 @@ 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., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
|
|
@ -1523,7 +1523,7 @@ ibuf_add_ops(
|
|||
|
||||
for (i = 0; i < IBUF_OP_COUNT; i++) {
|
||||
#ifdef HAVE_ATOMIC_BUILTINS
|
||||
os_atomic_increment_ulint(&arr[i], ops[i]);
|
||||
(void) os_atomic_increment_ulint(&arr[i], ops[i]);
|
||||
#else /* HAVE_ATOMIC_BUILTINS */
|
||||
arr[i] += ops[i];
|
||||
#endif /* HAVE_ATOMIC_BUILTINS */
|
||||
|
|
@ -2222,14 +2222,14 @@ ibool
|
|||
ibuf_add_free_page(void)
|
||||
/*====================*/
|
||||
{
|
||||
mtr_t mtr;
|
||||
page_t* header_page;
|
||||
ulint flags;
|
||||
ulint zip_size;
|
||||
ulint page_no;
|
||||
page_t* page;
|
||||
page_t* root;
|
||||
page_t* bitmap_page;
|
||||
mtr_t mtr;
|
||||
page_t* header_page;
|
||||
ulint flags;
|
||||
ulint zip_size;
|
||||
buf_block_t* block;
|
||||
page_t* page;
|
||||
page_t* root;
|
||||
page_t* bitmap_page;
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
|
|
@ -2250,29 +2250,24 @@ ibuf_add_free_page(void)
|
|||
of a deadlock. This is the reason why we created a special ibuf
|
||||
header page apart from the ibuf tree. */
|
||||
|
||||
page_no = fseg_alloc_free_page(
|
||||
block = fseg_alloc_free_page(
|
||||
header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 0, FSP_UP,
|
||||
&mtr);
|
||||
|
||||
if (UNIV_UNLIKELY(page_no == FIL_NULL)) {
|
||||
if (block == NULL) {
|
||||
mtr_commit(&mtr);
|
||||
|
||||
return(FALSE);
|
||||
} else {
|
||||
buf_block_t* block = buf_page_get(
|
||||
IBUF_SPACE_ID, 0, page_no, RW_X_LATCH, &mtr);
|
||||
|
||||
ibuf_enter(&mtr);
|
||||
|
||||
mutex_enter(&ibuf_mutex);
|
||||
|
||||
root = ibuf_tree_root_get(&mtr);
|
||||
|
||||
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
|
||||
|
||||
page = buf_block_get_frame(block);
|
||||
}
|
||||
|
||||
ut_ad(rw_lock_get_x_lock_count(&block->lock) == 1);
|
||||
ibuf_enter(&mtr);
|
||||
mutex_enter(&ibuf_mutex);
|
||||
root = ibuf_tree_root_get(&mtr);
|
||||
|
||||
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
|
||||
page = buf_block_get_frame(block);
|
||||
|
||||
/* Add the page to the free list and update the ibuf size data */
|
||||
|
||||
flst_add_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
|
||||
|
|
@ -2288,12 +2283,13 @@ ibuf_add_free_page(void)
|
|||
(level 2 page) */
|
||||
|
||||
bitmap_page = ibuf_bitmap_get_map_page(
|
||||
IBUF_SPACE_ID, page_no, zip_size, &mtr);
|
||||
IBUF_SPACE_ID, buf_block_get_page_no(block), zip_size, &mtr);
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
ibuf_bitmap_page_set_bits(
|
||||
bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr);
|
||||
bitmap_page, buf_block_get_page_no(block), zip_size,
|
||||
IBUF_BITMAP_IBUF, TRUE, &mtr);
|
||||
|
||||
ibuf_mtr_commit(&mtr);
|
||||
|
||||
|
|
@ -2588,7 +2584,15 @@ ibuf_get_merge_page_nos_func(
|
|||
} else {
|
||||
rec_page_no = ibuf_rec_get_page_no(mtr, rec);
|
||||
rec_space_id = ibuf_rec_get_space(mtr, rec);
|
||||
ut_ad(rec_page_no > IBUF_TREE_ROOT_PAGE_NO);
|
||||
/* In the system tablespace, the smallest
|
||||
possible secondary index leaf page number is
|
||||
bigger than IBUF_TREE_ROOT_PAGE_NO (4). In
|
||||
other tablespaces, the clustered index tree is
|
||||
created at page 3, which makes page 4 the
|
||||
smallest possible secondary index leaf page
|
||||
(and that only after DROP INDEX). */
|
||||
ut_ad(rec_page_no
|
||||
> IBUF_TREE_ROOT_PAGE_NO - (rec_space_id != 0));
|
||||
}
|
||||
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
|
|
@ -3920,6 +3924,7 @@ ibuf_insert_to_index_page_low(
|
|||
|
||||
fputs("InnoDB: Submit a detailed bug report"
|
||||
" to http://bugs.mysql.com\n", stderr);
|
||||
ut_ad(0);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
|
|
@ -3970,9 +3975,10 @@ ibuf_insert_to_index_page(
|
|||
"InnoDB: but the number of fields does not match!\n",
|
||||
stderr);
|
||||
dump:
|
||||
buf_page_print(page, 0);
|
||||
buf_page_print(page, 0, BUF_PAGE_PRINT_NO_CRASH);
|
||||
|
||||
dtuple_print(stderr, entry);
|
||||
ut_ad(0);
|
||||
|
||||
fputs("InnoDB: The table where where"
|
||||
" this index record belongs\n"
|
||||
|
|
@ -4113,6 +4119,11 @@ ibuf_set_del_mark(
|
|||
TRUE, mtr);
|
||||
}
|
||||
} else {
|
||||
const page_t* page
|
||||
= page_cur_get_page(&page_cur);
|
||||
const buf_block_t* block
|
||||
= page_cur_get_block(&page_cur);
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: unable to find a record to delete-mark\n",
|
||||
stderr);
|
||||
|
|
@ -4121,10 +4132,14 @@ ibuf_set_del_mark(
|
|||
fputs("\n"
|
||||
"InnoDB: record ", stderr);
|
||||
rec_print(stderr, page_cur_get_rec(&page_cur), index);
|
||||
putc('\n', stderr);
|
||||
fputs("\n"
|
||||
"InnoDB: Submit a detailed bug report"
|
||||
" to http://bugs.mysql.com\n", stderr);
|
||||
fprintf(stderr, "\nspace %u offset %u"
|
||||
" (%u records, index id %llu)\n"
|
||||
"InnoDB: Submit a detailed bug report"
|
||||
" to http://bugs.mysql.com\n",
|
||||
(unsigned) buf_block_get_space(block),
|
||||
(unsigned) buf_block_get_page_no(block),
|
||||
(unsigned) page_get_n_recs(page),
|
||||
(ulonglong) btr_page_get_index_id(page));
|
||||
ut_ad(0);
|
||||
}
|
||||
}
|
||||
|
|
@ -4168,12 +4183,31 @@ ibuf_delete(
|
|||
offsets = rec_get_offsets(
|
||||
rec, index, offsets, ULINT_UNDEFINED, &heap);
|
||||
|
||||
/* Refuse to delete the last record. */
|
||||
ut_a(page_get_n_recs(page) > 1);
|
||||
if (page_get_n_recs(page) <= 1
|
||||
|| !(REC_INFO_DELETED_FLAG
|
||||
& rec_get_info_bits(rec, page_is_comp(page)))) {
|
||||
/* Refuse to purge the last record or a
|
||||
record that has not been marked for deletion. */
|
||||
ut_print_timestamp(stderr);
|
||||
fputs(" InnoDB: unable to purge a record\n",
|
||||
stderr);
|
||||
fputs("InnoDB: tuple ", stderr);
|
||||
dtuple_print(stderr, entry);
|
||||
fputs("\n"
|
||||
"InnoDB: record ", stderr);
|
||||
rec_print_new(stderr, rec, offsets);
|
||||
fprintf(stderr, "\nspace %u offset %u"
|
||||
" (%u records, index id %llu)\n"
|
||||
"InnoDB: Submit a detailed bug report"
|
||||
" to http://bugs.mysql.com\n",
|
||||
(unsigned) buf_block_get_space(block),
|
||||
(unsigned) buf_block_get_page_no(block),
|
||||
(unsigned) page_get_n_recs(page),
|
||||
(ulonglong) btr_page_get_index_id(page));
|
||||
|
||||
/* The record should have been marked for deletion. */
|
||||
ut_ad(REC_INFO_DELETED_FLAG
|
||||
& rec_get_info_bits(rec, page_is_comp(page)));
|
||||
ut_ad(0);
|
||||
return;
|
||||
}
|
||||
|
||||
lock_update_delete(block, rec);
|
||||
|
||||
|
|
@ -4259,6 +4293,7 @@ ibuf_restore_pos(
|
|||
|
||||
fprintf(stderr, "InnoDB: ibuf tree ok\n");
|
||||
fflush(stderr);
|
||||
ut_ad(0);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
|
|
@ -4441,7 +4476,7 @@ ibuf_merge_or_delete_for_page(
|
|||
function. When the counter is > 0, that prevents tablespace
|
||||
from being dropped. */
|
||||
|
||||
tablespace_being_deleted = fil_inc_pending_ibuf_merges(space);
|
||||
tablespace_being_deleted = fil_inc_pending_ops(space);
|
||||
|
||||
if (UNIV_UNLIKELY(tablespace_being_deleted)) {
|
||||
/* Do not try to read the bitmap page from space;
|
||||
|
|
@ -4467,7 +4502,7 @@ ibuf_merge_or_delete_for_page(
|
|||
/* No inserts buffered for this page */
|
||||
|
||||
if (!tablespace_being_deleted) {
|
||||
fil_decr_pending_ibuf_merges(space);
|
||||
fil_decr_pending_ops(space);
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
@ -4516,12 +4551,14 @@ ibuf_merge_or_delete_for_page(
|
|||
|
||||
bitmap_page = ibuf_bitmap_get_map_page(space, page_no,
|
||||
zip_size, &mtr);
|
||||
buf_page_print(bitmap_page, 0);
|
||||
buf_page_print(bitmap_page, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
ibuf_mtr_commit(&mtr);
|
||||
|
||||
fputs("\nInnoDB: Dump of the page:\n", stderr);
|
||||
|
||||
buf_page_print(block->frame, 0);
|
||||
buf_page_print(block->frame, 0,
|
||||
BUF_PAGE_PRINT_NO_CRASH);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: corruption in the tablespace."
|
||||
|
|
@ -4541,6 +4578,7 @@ ibuf_merge_or_delete_for_page(
|
|||
(ulong) page_no,
|
||||
(ulong)
|
||||
fil_page_get_type(block->frame));
|
||||
ut_ad(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4747,7 +4785,7 @@ reset_bit:
|
|||
mem_heap_free(heap);
|
||||
|
||||
#ifdef HAVE_ATOMIC_BUILTINS
|
||||
os_atomic_increment_ulint(&ibuf->n_merges, 1);
|
||||
(void) os_atomic_increment_ulint(&ibuf->n_merges, 1);
|
||||
ibuf_add_ops(ibuf->n_merged_ops, mops);
|
||||
ibuf_add_ops(ibuf->n_discarded_ops, dops);
|
||||
#else /* HAVE_ATOMIC_BUILTINS */
|
||||
|
|
@ -4763,7 +4801,7 @@ reset_bit:
|
|||
|
||||
if (update_ibuf_bitmap && !tablespace_being_deleted) {
|
||||
|
||||
fil_decr_pending_ibuf_merges(space);
|
||||
fil_decr_pending_ops(space);
|
||||
}
|
||||
|
||||
#ifdef UNIV_IBUF_COUNT_DEBUG
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
|
@ -11,8 +11,8 @@ 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., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
|
|
@ -92,6 +92,26 @@ insert/delete buffer when the record is not in the buffer pool. */
|
|||
buffer when the record is not in the buffer pool. */
|
||||
#define BTR_DELETE 8192
|
||||
|
||||
/**************************************************************//**
|
||||
Report that an index page is corrupted. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_corruption_report(
|
||||
/*==================*/
|
||||
const buf_block_t* block, /*!< in: corrupted block */
|
||||
const dict_index_t* index) /*!< in: index tree */
|
||||
UNIV_COLD __attribute__((nonnull));
|
||||
|
||||
/** Assert that a B-tree page is not corrupted.
|
||||
@param block buffer block containing a B-tree page
|
||||
@param index the B-tree index */
|
||||
#define btr_assert_not_corrupted(block, index) \
|
||||
if ((ibool) !!page_is_comp(buf_block_get_frame(block)) \
|
||||
!= dict_table_is_comp((index)->table)) { \
|
||||
btr_corruption_report(block, index); \
|
||||
ut_error; \
|
||||
}
|
||||
|
||||
#ifdef UNIV_BLOB_DEBUG
|
||||
# include "ut0rbt.h"
|
||||
/** An index->blobs entry for keeping track of off-page column references */
|
||||
|
|
@ -569,11 +589,14 @@ UNIV_INTERN
|
|||
ibool
|
||||
btr_compress(
|
||||
/*=========*/
|
||||
btr_cur_t* cursor, /*!< in: cursor on the page to merge or lift;
|
||||
the page must not be empty: in record delete
|
||||
use btr_discard_page if the page would become
|
||||
empty */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
btr_cur_t* cursor, /*!< in/out: cursor on the page to merge
|
||||
or lift; the page must not be empty:
|
||||
when deleting records, use btr_discard_page()
|
||||
if the page would become empty */
|
||||
ibool adjust, /*!< in: TRUE if should adjust the
|
||||
cursor position even if compression occurs */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
/*************************************************************//**
|
||||
Discards a page from a B-tree. This is used to remove the last record from
|
||||
a B-tree page: the whole page must be removed at the same time. This cannot
|
||||
|
|
@ -614,17 +637,23 @@ btr_parse_page_reorganize(
|
|||
#ifndef UNIV_HOTBACKUP
|
||||
/**************************************************************//**
|
||||
Gets the number of pages in a B-tree.
|
||||
@return number of pages */
|
||||
@return number of pages, or ULINT_UNDEFINED if the index is unavailable */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_get_size(
|
||||
/*=========*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint flag); /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
|
||||
ulint flag, /*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction where index
|
||||
is s-latched */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/**************************************************************//**
|
||||
Allocates a new file page to be used in an index tree. NOTE: we assume
|
||||
that the caller has made the reservation for free extents!
|
||||
@return new allocated block, x-latched; NULL if out of space */
|
||||
@retval NULL if no page could be allocated
|
||||
@retval block, rw_lock_x_lock_count(&block->lock) == 1 if allocation succeeded
|
||||
(init_mtr == mtr, or the page was not previously freed in mtr)
|
||||
@retval block (not allocated or initialized) otherwise */
|
||||
UNIV_INTERN
|
||||
buf_block_t*
|
||||
btr_page_alloc(
|
||||
|
|
@ -635,7 +664,12 @@ btr_page_alloc(
|
|||
page split is made */
|
||||
ulint level, /*!< in: level where the page is placed
|
||||
in the tree */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
mtr_t* mtr, /*!< in/out: mini-transaction
|
||||
for the allocation */
|
||||
mtr_t* init_mtr) /*!< in/out: mini-transaction
|
||||
for x-latching and initializing
|
||||
the page */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
/**************************************************************//**
|
||||
Frees a file page used in an index tree. NOTE: cannot free field external
|
||||
storage pages because the page must contain info on its level. */
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ btr_node_ptr_get_child_page_no(
|
|||
"InnoDB: a nonsensical page number 0"
|
||||
" in a node ptr record at offset %lu\n",
|
||||
(ulong) page_offset(rec));
|
||||
buf_page_print(page_align(rec), 0);
|
||||
buf_page_print(page_align(rec), 0, 0);
|
||||
}
|
||||
|
||||
return(page_no);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
|
@ -11,8 +11,8 @@ 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., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
|
|
@ -36,6 +36,9 @@ Created 10/16/1994 Heikki Tuuri
|
|||
#define BTR_NO_LOCKING_FLAG 2 /* do no record lock checking */
|
||||
#define BTR_KEEP_SYS_FLAG 4 /* sys fields will be found from the
|
||||
update vector or inserted entry */
|
||||
#define BTR_KEEP_POS_FLAG 8 /* btr_cur_pessimistic_update()
|
||||
must keep cursor position when
|
||||
moving columns to big_rec */
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
#include "que0types.h"
|
||||
|
|
@ -310,7 +313,9 @@ btr_cur_pessimistic_update(
|
|||
/*=======================*/
|
||||
ulint flags, /*!< in: undo logging, locking, and rollback
|
||||
flags */
|
||||
btr_cur_t* cursor, /*!< in: cursor on the record to update */
|
||||
btr_cur_t* cursor, /*!< in/out: cursor on the record to update;
|
||||
cursor may become invalid if *big_rec == NULL
|
||||
|| !(flags & BTR_KEEP_POS_FLAG) */
|
||||
mem_heap_t** heap, /*!< in/out: pointer to memory heap, or NULL */
|
||||
big_rec_t** big_rec,/*!< out: big rec vector whose fields have to
|
||||
be stored externally by the caller, or NULL */
|
||||
|
|
@ -364,10 +369,13 @@ UNIV_INTERN
|
|||
ibool
|
||||
btr_cur_compress_if_useful(
|
||||
/*=======================*/
|
||||
btr_cur_t* cursor, /*!< in: cursor on the page to compress;
|
||||
btr_cur_t* cursor, /*!< in/out: cursor on the page to compress;
|
||||
cursor does not stay valid if compression
|
||||
occurs */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
ibool adjust, /*!< in: TRUE if should adjust the
|
||||
cursor position even if compression occurs */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull));
|
||||
/*******************************************************//**
|
||||
Removes the record on which the tree cursor is positioned. It is assumed
|
||||
that the mtr has an x-latch on the page where the cursor is positioned,
|
||||
|
|
@ -492,6 +500,27 @@ btr_cur_disown_inherited_fields(
|
|||
const upd_t* update, /*!< in: update vector */
|
||||
mtr_t* mtr) /*!< in/out: mini-transaction */
|
||||
__attribute__((nonnull(2,3,4,5,6)));
|
||||
|
||||
/** Operation code for btr_store_big_rec_extern_fields(). */
|
||||
enum blob_op {
|
||||
/** Store off-page columns for a freshly inserted record */
|
||||
BTR_STORE_INSERT = 0,
|
||||
/** Store off-page columns for an insert by update */
|
||||
BTR_STORE_INSERT_UPDATE,
|
||||
/** Store off-page columns for an update */
|
||||
BTR_STORE_UPDATE
|
||||
};
|
||||
|
||||
/*******************************************************************//**
|
||||
Determine if an operation on off-page columns is an update.
|
||||
@return TRUE if op != BTR_STORE_INSERT */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_blob_op_is_update(
|
||||
/*==================*/
|
||||
enum blob_op op) /*!< in: operation */
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
/*******************************************************************//**
|
||||
Stores the fields in big_rec_vec to the tablespace and puts pointers to
|
||||
them in rec. The extern flags in rec will have to be set beforehand.
|
||||
|
|
@ -499,52 +528,23 @@ The fields are stored on pages allocated from leaf node
|
|||
file segment of the index tree.
|
||||
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_store_big_rec_extern_fields_func(
|
||||
/*=================================*/
|
||||
enum db_err
|
||||
btr_store_big_rec_extern_fields(
|
||||
/*============================*/
|
||||
dict_index_t* index, /*!< in: index of rec; the index tree
|
||||
MUST be X-latched */
|
||||
buf_block_t* rec_block, /*!< in/out: block containing rec */
|
||||
rec_t* rec, /*!< in: record */
|
||||
rec_t* rec, /*!< in/out: record */
|
||||
const ulint* offsets, /*!< in: rec_get_offsets(rec, index);
|
||||
the "external storage" flags in offsets
|
||||
will not correspond to rec when
|
||||
this function returns */
|
||||
#ifdef UNIV_DEBUG
|
||||
mtr_t* local_mtr, /*!< in: mtr containing the
|
||||
latch to rec and to the tree */
|
||||
#endif /* UNIV_DEBUG */
|
||||
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
|
||||
ibool update_in_place,/*! in: TRUE if the record is updated
|
||||
in place (not delete+insert) */
|
||||
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
|
||||
const big_rec_t*big_rec_vec) /*!< in: vector containing fields
|
||||
const big_rec_t*big_rec_vec, /*!< in: vector containing fields
|
||||
to be stored externally */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/** Stores the fields in big_rec_vec to the tablespace and puts pointers to
|
||||
them in rec. The extern flags in rec will have to be set beforehand.
|
||||
The fields are stored on pages allocated from leaf node
|
||||
file segment of the index tree.
|
||||
@param index in: clustered index; MUST be X-latched by mtr
|
||||
@param b in/out: block containing rec; MUST be X-latched by mtr
|
||||
@param rec in/out: clustered index record
|
||||
@param offsets in: rec_get_offsets(rec, index);
|
||||
the "external storage" flags in offsets will not be adjusted
|
||||
@param mtr in: mini-transaction that holds x-latch on index and b
|
||||
@param upd in: TRUE if the record is updated in place (not delete+insert)
|
||||
@param big in: vector containing fields to be stored externally
|
||||
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
|
||||
#ifdef UNIV_DEBUG
|
||||
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
|
||||
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,mtr,upd,big)
|
||||
#elif defined UNIV_BLOB_LIGHT_DEBUG
|
||||
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
|
||||
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,upd,big)
|
||||
#else
|
||||
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
|
||||
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,big)
|
||||
#endif
|
||||
mtr_t* btr_mtr, /*!< in: mtr containing the
|
||||
latches to the clustered index */
|
||||
enum blob_op op) /*! in: operation code */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
|
||||
/*******************************************************************//**
|
||||
Frees the space in an externally stored field to the file space
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
|
@ -11,8 +11,8 @@ 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., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ btr_cur_compress_recommendation(
|
|||
btr_cur_t* cursor, /*!< in: btr cursor */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
page_t* page;
|
||||
const page_t* page;
|
||||
|
||||
ut_ad(mtr_memo_contains(mtr, btr_cur_get_block(cursor),
|
||||
MTR_MEMO_PAGE_X_FIX));
|
||||
|
|
@ -197,4 +197,25 @@ btr_cur_can_delete_without_compress(
|
|||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Determine if an operation on off-page columns is an update.
|
||||
@return TRUE if op != BTR_STORE_INSERT */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
btr_blob_op_is_update(
|
||||
/*==================*/
|
||||
enum blob_op op) /*!< in: operation */
|
||||
{
|
||||
switch (op) {
|
||||
case BTR_STORE_INSERT:
|
||||
return(FALSE);
|
||||
case BTR_STORE_INSERT_UPDATE:
|
||||
case BTR_STORE_UPDATE:
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
ut_ad(0);
|
||||
return(FALSE);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
|
|
|||
|
|
@ -53,6 +53,16 @@ UNIV_INTERN
|
|||
btr_pcur_t*
|
||||
btr_pcur_create_for_mysql(void);
|
||||
/*============================*/
|
||||
|
||||
/**************************************************************//**
|
||||
Resets a persistent cursor object, freeing ::old_rec_buf if it is
|
||||
allocated and resetting the other members to their initial values. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_pcur_reset(
|
||||
/*===========*/
|
||||
btr_pcur_t* cursor);/*!< in, out: persistent cursor */
|
||||
|
||||
/**************************************************************//**
|
||||
Frees the memory for a persistent cursor object. */
|
||||
UNIV_INTERN
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1995, 2012, Oracle and/or its affiliates. All Rights Reserved.
|
||||
|
||||
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
|
||||
|
|
@ -11,8 +11,8 @@ 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., 59 Temple
|
||||
Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
|
||||
|
||||
*****************************************************************************/
|
||||
|
||||
|
|
@ -611,6 +611,31 @@ buf_block_get_modify_clock(
|
|||
#else /* !UNIV_HOTBACKUP */
|
||||
# define buf_block_modify_clock_inc(block) ((void) 0)
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/*******************************************************************//**
|
||||
Increments the bufferfix count. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
buf_block_buf_fix_inc_func(
|
||||
/*=======================*/
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
const char* file, /*!< in: file name */
|
||||
ulint line, /*!< in: line */
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
buf_block_t* block) /*!< in/out: block to bufferfix */
|
||||
__attribute__((nonnull));
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
/** Increments the bufferfix count.
|
||||
@param b in/out: block to bufferfix
|
||||
@param f in: file name where requested
|
||||
@param l in: line number where requested */
|
||||
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(f,l,b)
|
||||
#else /* UNIV_SYNC_DEBUG */
|
||||
/** Increments the bufferfix count.
|
||||
@param b in/out: block to bufferfix
|
||||
@param f in: file name where requested
|
||||
@param l in: line number where requested */
|
||||
# define buf_block_buf_fix_inc(b,f,l) buf_block_buf_fix_inc_func(b)
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
/********************************************************************//**
|
||||
Calculates a page checksum which is stored to the page when it is written
|
||||
to a file. Note that we must be careful to calculate the same value
|
||||
|
|
@ -700,6 +725,13 @@ buf_print(void);
|
|||
/*============*/
|
||||
#endif /* UNIV_DEBUG_PRINT || UNIV_DEBUG || UNIV_BUF_DEBUG */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
enum buf_page_print_flags {
|
||||
/** Do not crash at the end of buf_page_print(). */
|
||||
BUF_PAGE_PRINT_NO_CRASH = 1,
|
||||
/** Do not print the full page dump. */
|
||||
BUF_PAGE_PRINT_NO_FULL = 2
|
||||
};
|
||||
|
||||
/********************************************************************//**
|
||||
Prints a page to stderr. */
|
||||
UNIV_INTERN
|
||||
|
|
@ -707,8 +739,12 @@ void
|
|||
buf_page_print(
|
||||
/*===========*/
|
||||
const byte* read_buf, /*!< in: a database page */
|
||||
ulint zip_size); /*!< in: compressed page size, or
|
||||
ulint zip_size, /*!< in: compressed page size, or
|
||||
0 for uncompressed pages */
|
||||
ulint flags) /*!< in: 0 or
|
||||
BUF_PAGE_PRINT_NO_CRASH or
|
||||
BUF_PAGE_PRINT_NO_FULL */
|
||||
__attribute__((nonnull));
|
||||
/********************************************************************//**
|
||||
Decompress a block.
|
||||
@return TRUE if successful */
|
||||
|
|
@ -773,11 +809,11 @@ buf_all_freed(void);
|
|||
/*********************************************************************//**
|
||||
Checks that there currently are no pending i/o-operations for the buffer
|
||||
pool.
|
||||
@return TRUE if there is no pending i/o */
|
||||
@return number of pending i/o operations */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
buf_pool_check_no_pending_io(void);
|
||||
/*==============================*/
|
||||
ulint
|
||||
buf_pool_check_num_pending_io(void);
|
||||
/*===============================*/
|
||||
/*********************************************************************//**
|
||||
Invalidates the file pages in the buffer pool when an archive recovery is
|
||||
completed. All the file pages buffered must be in a replaceable state when
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue