summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2020-08-20 09:12:16 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2020-08-20 09:12:16 +0300
commitde0e7cd72a6e071aba686178a8ff461dd5a757f5 (patch)
tree9beb054fb01d917e1359b60debce629056c6ef4b
parent90c8d773ed0ea7de5e735e836e1e33a190711f17 (diff)
parenta79c25789474f32097e083d3b4953927c04909bc (diff)
downloadmariadb-git-de0e7cd72a6e071aba686178a8ff461dd5a757f5.tar.gz
Merge 10.2 into 10.3
-rw-r--r--client/mysqltest.cc4
-rw-r--r--extra/mariabackup/xtrabackup.cc10
-rw-r--r--include/my_stacktrace.h3
-rw-r--r--mysql-test/main/mysql_tzinfo_to_sql_symlink.result6
-rw-r--r--mysql-test/suite/encryption/r/innodb_encrypt_log.result2
-rw-r--r--mysql-test/suite/innodb/r/foreign_key.result27
-rw-r--r--mysql-test/suite/innodb/r/innodb.result2
-rw-r--r--mysql-test/suite/innodb/t/foreign_key.test23
-rw-r--r--mysql-test/suite/innodb/t/innodb.test2
-rw-r--r--mysql-test/suite/sys_vars/r/innodb_log_checksums_basic.result4
-rw-r--r--mysql-test/suite/sys_vars/r/sysvars_innodb.result2
-rw-r--r--mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result4
-rw-r--r--mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result4
-rw-r--r--mysys/stacktrace.c133
-rw-r--r--scripts/mysqld_safe.sh20
-rw-r--r--sql/mysqld.cc1
-rw-r--r--sql/tztime.cc3
-rw-r--r--storage/innobase/btr/btr0cur.cc5
-rw-r--r--storage/innobase/buf/buf0buf.cc24
-rw-r--r--storage/innobase/buf/buf0flu.cc4
-rw-r--r--storage/innobase/handler/ha_innodb.cc74
-rw-r--r--storage/innobase/handler/handler0alter.cc9
-rw-r--r--storage/innobase/include/dict0mem.h3
-rw-r--r--storage/innobase/include/log0log.h24
-rw-r--r--storage/innobase/include/log0log.ic23
-rw-r--r--storage/innobase/include/srv0srv.h25
-rw-r--r--storage/innobase/log/log0log.cc9
-rw-r--r--storage/innobase/log/log0recv.cc5
-rw-r--r--storage/innobase/row/row0mysql.cc12
-rw-r--r--storage/innobase/row/row0uins.cc7
-rw-r--r--storage/innobase/row/row0umod.cc57
-rw-r--r--storage/innobase/row/row0undo.cc22
-rw-r--r--storage/innobase/srv/srv0srv.cc100
-rw-r--r--storage/innobase/srv/srv0start.cc4
-rw-r--r--storage/innobase/trx/trx0roll.cc3
-rw-r--r--storage/innobase/trx/trx0trx.cc6
-rw-r--r--unittest/mysys/CMakeLists.txt2
-rw-r--r--unittest/mysys/stacktrace-t.c67
38 files changed, 417 insertions, 318 deletions
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 316e52d95b4..425c5f98095 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -9091,10 +9091,6 @@ static void init_signal_handling(void)
struct sigaction sa;
DBUG_ENTER("init_signal_handling");
-#ifdef HAVE_STACKTRACE
- my_init_stacktrace();
-#endif
-
sa.sa_flags = SA_RESETHAND | SA_NODEFER;
sigemptyset(&sa.sa_mask);
sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL);
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index 277e8b67cf0..0529cb18f23 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -249,6 +249,12 @@ my_bool innobase_locks_unsafe_for_binlog;
my_bool innobase_rollback_on_timeout;
my_bool innobase_create_status_file;
+/* The following counter is used to convey information to InnoDB
+about server activity: in selects it is not sensible to call
+srv_active_wake_master_thread after each fetch or search, we only do
+it every INNOBASE_WAKE_INTERVAL'th step. */
+
+#define INNOBASE_WAKE_INTERVAL 32
ulong innobase_active_counter = 0;
#ifndef _WIN32
@@ -2006,10 +2012,6 @@ static bool innodb_init_param()
srv_undo_dir = (char*) ".";
}
- log_checksum_algorithm_ptr = innodb_log_checksums || srv_encrypt_log
- ? log_block_calc_checksum_crc32
- : log_block_calc_checksum_none;
-
#ifdef _WIN32
srv_use_native_aio = TRUE;
#endif
diff --git a/include/my_stacktrace.h b/include/my_stacktrace.h
index 922a59c196a..015fa062752 100644
--- a/include/my_stacktrace.h
+++ b/include/my_stacktrace.h
@@ -41,7 +41,6 @@
C_MODE_START
#if defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE)
-void my_init_stacktrace();
void my_print_stacktrace(uchar* stack_bottom, ulong thread_stack,
my_bool silent);
int my_safe_print_str(const char* val, size_t max_len);
@@ -52,8 +51,6 @@ char *my_demangle(const char *mangled_name, int *status);
#ifdef __WIN__
void my_set_exception_pointers(EXCEPTION_POINTERS *ep);
#endif /* __WIN__ */
-#else
-#define my_init_stacktrace() do { } while(0)
#endif /* ! (defined(HAVE_STACKTRACE) || defined(HAVE_BACKTRACE)) */
#ifndef _WIN32
diff --git a/mysql-test/main/mysql_tzinfo_to_sql_symlink.result b/mysql-test/main/mysql_tzinfo_to_sql_symlink.result
index 06e21beace1..f56a2df2012 100644
--- a/mysql-test/main/mysql_tzinfo_to_sql_symlink.result
+++ b/mysql-test/main/mysql_tzinfo_to_sql_symlink.result
@@ -15,6 +15,7 @@ TRUNCATE TABLE time_zone;
TRUNCATE TABLE time_zone_name;
TRUNCATE TABLE time_zone_transition;
TRUNCATE TABLE time_zone_transition_type;
+START TRANSACTION;
INSERT INTO time_zone (Use_leap_seconds) VALUES ('N');
SET @time_zone_id= LAST_INSERT_ID();
INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id);
@@ -32,6 +33,7 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset,
Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it.
Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/ignored.tab' as time zone. Skipping it.
Warning: Skipping directory 'MYSQLTEST_VARDIR/zoneinfo/posix/posix': to avoid infinite symlink recursion.
+COMMIT;
ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time;
ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id;
\d |
@@ -57,6 +59,7 @@ TRUNCATE TABLE time_zone;
TRUNCATE TABLE time_zone_name;
TRUNCATE TABLE time_zone_transition;
TRUNCATE TABLE time_zone_transition_type;
+START TRANSACTION;
INSERT INTO time_zone (Use_leap_seconds) VALUES ('N');
SET @time_zone_id= LAST_INSERT_ID();
INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id);
@@ -71,6 +74,7 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset,
(@time_zone_id, 0, 0, 0, 'GMT')
;
Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it.
+COMMIT;
ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time;
ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id;
\d |
@@ -160,6 +164,8 @@ TRUNCATE TABLE time_zone;
TRUNCATE TABLE time_zone_name;
TRUNCATE TABLE time_zone_transition;
TRUNCATE TABLE time_zone_transition_type;
+START TRANSACTION;
+COMMIT;
ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time;
ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id;
\d |
diff --git a/mysql-test/suite/encryption/r/innodb_encrypt_log.result b/mysql-test/suite/encryption/r/innodb_encrypt_log.result
index b999e8cb34a..cd37330f2b0 100644
--- a/mysql-test/suite/encryption/r/innodb_encrypt_log.result
+++ b/mysql-test/suite/encryption/r/innodb_encrypt_log.result
@@ -7,7 +7,7 @@
#
SET GLOBAL innodb_log_checksums=0;
Warnings:
-Warning 138 innodb_encrypt_log implies innodb_log_checksums
+Warning 138 innodb_log_checksums is deprecated and has no effect outside recovery
SELECT @@global.innodb_log_checksums;
@@global.innodb_log_checksums
1
diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result
index dffb718feb6..49206c7c723 100644
--- a/mysql-test/suite/innodb/r/foreign_key.result
+++ b/mysql-test/suite/innodb/r/foreign_key.result
@@ -658,6 +658,7 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;
# MDEV-17187 table doesn't exist in engine after ALTER other tables
# with CONSTRAINTs
#
+call mtr.add_suppression("\\[Warning\\] InnoDB: In ALTER TABLE `test`\\.`t2` has or is referenced in foreign key constraints which are not compatible with the new table definition.");
set foreign_key_checks=on;
create table t1 (id int not null primary key) engine=innodb;
create table t2 (id int not null primary key, fid int not null,
@@ -713,4 +714,30 @@ drop table t1,t2;
ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
drop table t1,t2;
ERROR 42S02: Unknown table 'test.t2'
+#
+# MDEV-22934 Table disappear after two alter table command
+#
+CREATE TABLE t1(f1 INT NOT NULL AUTO_INCREMENT,
+f2 INT NOT NULL,
+PRIMARY KEY (f1), INDEX (f2))ENGINE=InnoDB;
+CREATE TABLE t2(f1 INT NOT NULL,
+f2 INT NOT NULL, f3 INT NOT NULL,
+PRIMARY KEY(f1, f2), UNIQUE KEY(f2),
+CONSTRAINT `t2_ibfk_1` FOREIGN KEY (f2) REFERENCES t1(f2) ON DELETE CASCADE,
+CONSTRAINT `t2_ibfk_2` FOREIGN KEY (f1) REFERENCES t1(f1) ON DELETE CASCADE
+) ENGINE=InnoDB;
+SET FOREIGN_KEY_CHECKS=0;
+ALTER TABLE t2 DROP PRIMARY KEY, ADD PRIMARY KEY(f3), ALGORITHM=INPLACE;
+ALTER TABLE t2 DROP INDEX `f2`, ALGORITHM=COPY;
+SHOW CREATE TABLE t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `f1` int(11) NOT NULL,
+ `f2` int(11) NOT NULL,
+ `f3` int(11) NOT NULL,
+ PRIMARY KEY (`f3`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+CREATE TABLE t2 (f1 INT NOT NULL)ENGINE=InnoDB;
+ERROR 42S01: Table 't2' already exists
+DROP TABLE t2, t1;
# End of 10.2 tests
diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result
index 86f90c2bd79..233023e63c2 100644
--- a/mysql-test/suite/innodb/r/innodb.result
+++ b/mysql-test/suite/innodb/r/innodb.result
@@ -2543,7 +2543,6 @@ set foreign_key_checks=0;
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb;
create table t1(a varchar(10) primary key) engine = innodb;
alter table t1 modify column a int;
-Got one of the listed errors
set foreign_key_checks=1;
drop table t2,t1;
set foreign_key_checks=0;
@@ -2552,6 +2551,7 @@ create table t1(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=latin
alter table t1 convert to character set utf8;
set foreign_key_checks=1;
drop table t2,t1;
+call mtr.add_suppression("\\[Warning\\] InnoDB: In ALTER TABLE `test`.`t1` has or is referenced in foreign key constraints which are not compatible with the new table definition.");
set foreign_key_checks=0;
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8;
diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test
index 27fa63f144e..40bc3a32a4f 100644
--- a/mysql-test/suite/innodb/t/foreign_key.test
+++ b/mysql-test/suite/innodb/t/foreign_key.test
@@ -657,6 +657,8 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;
--echo # with CONSTRAINTs
--echo #
+call mtr.add_suppression("\\[Warning\\] InnoDB: In ALTER TABLE `test`\\.`t2` has or is referenced in foreign key constraints which are not compatible with the new table definition.");
+
set foreign_key_checks=on;
create table t1 (id int not null primary key) engine=innodb;
create table t2 (id int not null primary key, fid int not null,
@@ -698,6 +700,27 @@ drop table t1,t2;
--error ER_BAD_TABLE_ERROR
drop table t1,t2;
+--echo #
+--echo # MDEV-22934 Table disappear after two alter table command
+--echo #
+CREATE TABLE t1(f1 INT NOT NULL AUTO_INCREMENT,
+ f2 INT NOT NULL,
+ PRIMARY KEY (f1), INDEX (f2))ENGINE=InnoDB;
+CREATE TABLE t2(f1 INT NOT NULL,
+ f2 INT NOT NULL, f3 INT NOT NULL,
+ PRIMARY KEY(f1, f2), UNIQUE KEY(f2),
+CONSTRAINT `t2_ibfk_1` FOREIGN KEY (f2) REFERENCES t1(f2) ON DELETE CASCADE,
+CONSTRAINT `t2_ibfk_2` FOREIGN KEY (f1) REFERENCES t1(f1) ON DELETE CASCADE
+) ENGINE=InnoDB;
+
+SET FOREIGN_KEY_CHECKS=0;
+ALTER TABLE t2 DROP PRIMARY KEY, ADD PRIMARY KEY(f3), ALGORITHM=INPLACE;
+ALTER TABLE t2 DROP INDEX `f2`, ALGORITHM=COPY;
+SHOW CREATE TABLE t2;
+--error ER_TABLE_EXISTS_ERROR
+CREATE TABLE t2 (f1 INT NOT NULL)ENGINE=InnoDB;
+DROP TABLE t2, t1;
+
--echo # End of 10.2 tests
--source include/wait_until_count_sessions.inc
diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test
index 2ea6d05d9eb..37708a4536d 100644
--- a/mysql-test/suite/innodb/t/innodb.test
+++ b/mysql-test/suite/innodb/t/innodb.test
@@ -1627,7 +1627,6 @@ drop table t1;
set foreign_key_checks=0;
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb;
create table t1(a varchar(10) primary key) engine = innodb;
--- error 1025,1025
alter table t1 modify column a int;
set foreign_key_checks=1;
drop table t2,t1;
@@ -1643,6 +1642,7 @@ drop table t2,t1;
# test that RENAME does not allow invalid charsets when f_k_c is 0
+call mtr.add_suppression("\\[Warning\\] InnoDB: In ALTER TABLE `test`.`t1` has or is referenced in foreign key constraints which are not compatible with the new table definition.");
set foreign_key_checks=0;
create table t2 (a varchar(10), foreign key (a) references t1(a)) engine = innodb DEFAULT CHARSET=latin1;
create table t3(a varchar(10) primary key) engine = innodb DEFAULT CHARSET=utf8;
diff --git a/mysql-test/suite/sys_vars/r/innodb_log_checksums_basic.result b/mysql-test/suite/sys_vars/r/innodb_log_checksums_basic.result
index 6679ca87249..7724ef9c2ee 100644
--- a/mysql-test/suite/sys_vars/r/innodb_log_checksums_basic.result
+++ b/mysql-test/suite/sys_vars/r/innodb_log_checksums_basic.result
@@ -28,9 +28,11 @@ SELECT @@global.innodb_log_checksums;
@@global.innodb_log_checksums
1
SET GLOBAL innodb_log_checksums = OFF;
+Warnings:
+Warning 138 innodb_log_checksums is deprecated and has no effect outside recovery
SELECT @@global.innodb_log_checksums;
@@global.innodb_log_checksums
-0
+1
SET GLOBAL innodb_log_checksums = default;
SET GLOBAL innodb_log_checksums = ON;
SELECT @@global.innodb_log_checksums;
diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
index c34c4748493..2bd2920ff9d 100644
--- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result
+++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result
@@ -1250,7 +1250,7 @@ SESSION_VALUE NULL
DEFAULT_VALUE ON
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
-VARIABLE_COMMENT Whether to compute and require checksums for InnoDB redo log blocks
+VARIABLE_COMMENT DEPRECATED. Whether to require checksums for InnoDB redo log blocks.
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
diff --git a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result
index 51c2e204b78..bcd96b86516 100644
--- a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result
+++ b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink.result
@@ -15,6 +15,7 @@ TRUNCATE TABLE time_zone;
TRUNCATE TABLE time_zone_name;
TRUNCATE TABLE time_zone_transition;
TRUNCATE TABLE time_zone_transition_type;
+START TRANSACTION;
INSERT INTO time_zone (Use_leap_seconds) VALUES ('N');
SET @time_zone_id= LAST_INSERT_ID();
INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id);
@@ -32,6 +33,7 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset,
Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it.
Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/ignored.tab' as time zone. Skipping it.
Warning: Skipping directory 'MYSQLTEST_VARDIR/zoneinfo/posix/posix': to avoid infinite symlink recursion.
+COMMIT;
ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time;
ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id;
\d |
@@ -57,6 +59,7 @@ TRUNCATE TABLE time_zone;
TRUNCATE TABLE time_zone_name;
TRUNCATE TABLE time_zone_transition;
TRUNCATE TABLE time_zone_transition_type;
+START TRANSACTION;
INSERT INTO time_zone (Use_leap_seconds) VALUES ('N');
SET @time_zone_id= LAST_INSERT_ID();
INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id);
@@ -71,6 +74,7 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset,
(@time_zone_id, 0, 0, 0, 'GMT')
;
Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it.
+COMMIT;
ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time;
ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id;
\d |
diff --git a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result
index 85c4d858be2..aff02cb413e 100644
--- a/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result
+++ b/mysql-test/suite/wsrep/r/mysql_tzinfo_to_sql_symlink_skip.result
@@ -9,6 +9,7 @@ TRUNCATE TABLE time_zone;
TRUNCATE TABLE time_zone_name;
TRUNCATE TABLE time_zone_transition;
TRUNCATE TABLE time_zone_transition_type;
+START TRANSACTION;
INSERT INTO time_zone (Use_leap_seconds) VALUES ('N');
SET @time_zone_id= LAST_INSERT_ID();
INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id);
@@ -26,6 +27,7 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset,
Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it.
Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/ignored.tab' as time zone. Skipping it.
Warning: Skipping directory 'MYSQLTEST_VARDIR/zoneinfo/posix/posix': to avoid infinite symlink recursion.
+COMMIT;
ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time;
ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id;
# Silent run
@@ -36,6 +38,7 @@ TRUNCATE TABLE time_zone;
TRUNCATE TABLE time_zone_name;
TRUNCATE TABLE time_zone_transition;
TRUNCATE TABLE time_zone_transition_type;
+START TRANSACTION;
INSERT INTO time_zone (Use_leap_seconds) VALUES ('N');
SET @time_zone_id= LAST_INSERT_ID();
INSERT INTO time_zone_name (Name, Time_zone_id) VALUES ('GMT', @time_zone_id);
@@ -50,6 +53,7 @@ INSERT INTO time_zone_transition_type (Time_zone_id, Transition_type_id, Offset,
(@time_zone_id, 0, 0, 0, 'GMT')
;
Warning: Unable to load 'MYSQLTEST_VARDIR/zoneinfo/posix/garbage' as time zone. Skipping it.
+COMMIT;
ALTER TABLE time_zone_transition ORDER BY Time_zone_id, Transition_time;
ALTER TABLE time_zone_transition_type ORDER BY Time_zone_id, Transition_type_id;
#
diff --git a/mysys/stacktrace.c b/mysys/stacktrace.c
index a512f5879d6..f5e6352a72e 100644
--- a/mysys/stacktrace.c
+++ b/mysys/stacktrace.c
@@ -34,108 +34,11 @@
#include <execinfo.h>
#endif
-#ifdef __linux__
-#define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end)
-static char *heap_start;
-char *__bss_start;
-#else
-#define PTR_SANE(p) (p)
-#endif /* __linux */
-
-
-void my_init_stacktrace()
-{
-#ifdef __linux__
- heap_start = (char*) &__bss_start;
-#endif /* __linux */
-}
-
-#ifdef __linux__
-
-static void print_buffer(char *buffer, size_t count)
-{
- const char s[]= " ";
- for (; count && *buffer; --count)
- {
- my_write_stderr(isprint(*buffer) ? buffer : s, 1);
- ++buffer;
- }
-}
-
-/**
- Access the pages of this process through /proc/self/task/<tid>/mem
- in order to safely print the contents of a memory address range.
-
- @param addr The address at the start of the memory region.
- @param max_len The length of the memory region.
-
- @return Zero on success.
-*/
-static int safe_print_str(const char *addr, size_t max_len)
-{
- int fd;
- pid_t tid;
- off_t offset;
- ssize_t nbytes= 0;
- size_t total, count;
- char buf[256];
-
- tid= (pid_t) syscall(SYS_gettid);
-
- sprintf(buf, "/proc/self/task/%d/mem", tid);
-
- if ((fd= open(buf, O_RDONLY)) < 0)
- return -1;
-
- /* Ensure that off_t can hold a pointer. */
- compile_time_assert(sizeof(off_t) >= sizeof(intptr));
-
- total= max_len;
- offset= (intptr) addr;
-
- /* Read up to the maximum number of bytes. */
- while (total)
- {
- count= MY_MIN(sizeof(buf), total);
-
- if ((nbytes= pread(fd, buf, count, offset)) < 0)
- {
- /* Just in case... */
- if (errno == EINTR)
- continue;
- else
- break;
- }
-
- /* Advance offset into memory. */
- total-= nbytes;
- offset+= nbytes;
- addr+= nbytes;
-
- /* Output the printable characters. */
- print_buffer(buf, nbytes);
-
- /* Break if less than requested... */
- if ((count - nbytes))
- break;
- }
-
- if (nbytes == -1)
- my_safe_printf_stderr("Can't read from address %p", addr);
-
- close(fd);
-
- return 0;
-}
-
-#endif
-
/*
Attempt to print a char * pointer as a string.
SYNOPSIS
- Prints either until the end of string ('\0'), or max_len characters have
- been printed.
+ Prints until max_len characters have been printed.
RETURN VALUE
0 Pointer was within the heap address space.
@@ -150,24 +53,25 @@ static int safe_print_str(const char *addr, size_t max_len)
int my_safe_print_str(const char* val, size_t max_len)
{
-#ifdef __linux__
- char *heap_end;
-
- // Try and make use of /proc filesystem to safely print memory contents.
- if (!safe_print_str(val, max_len))
- return 0;
-
- heap_end= (char*) sbrk(0);
-#endif
-
- if (!PTR_SANE(val))
+ const char *orig_val= val;
+ if (!val)
{
- my_safe_printf_stderr("%s", "is an invalid pointer");
+ my_safe_printf_stderr("%s", "(null)");
return 1;
}
- for (; max_len && PTR_SANE(val) && *val; --max_len)
- my_write_stderr((val++), 1);
+ for (; max_len; --max_len)
+ {
+ if (my_write_stderr((val++), 1) != 1)
+ {
+ if ((errno == EFAULT) &&(val == orig_val + 1))
+ {
+ // We can not read the address from very beginning
+ my_safe_printf_stderr("Can't access address %p", orig_val);
+ }
+ break;
+ }
+ }
my_safe_printf_stderr("%s", "\n");
return 0;
@@ -511,11 +415,6 @@ static EXCEPTION_POINTERS *exception_ptrs;
#define MODULE64_SIZE_WINXP 576
#define STACKWALK_MAX_FRAMES 64
-void my_init_stacktrace()
-{
-}
-
-
void my_set_exception_pointers(EXCEPTION_POINTERS *ep)
{
exception_ptrs = ep;
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index f40a68a3b1e..22d5a5531c6 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -23,6 +23,7 @@ numa_interleave=0
wsrep_on=0
dry_run=0
defaults_group_suffix=
+ignore_unknown=1
# Initial logging status: error log is not open, and not using syslog
logging=init
@@ -361,11 +362,22 @@ parse_arguments() {
--help) usage ;;
+ --ignore-unknown) ignore_unknown=1 ;;
+ --no-ignore-unknown|--not-ignore-unknown) ignore_unknown=0 ;;
+
*)
- case "$unrecognized_handling" in
- collect) append_arg_to_args "$arg" ;;
- complain) log_error "unknown option '$arg'" ;;
- esac
+ if test $ignore_unknown -eq 0
+ then
+ case "$unrecognized_handling" in
+ collect) append_arg_to_args "$arg" ;;
+ complain) log_error "unknown option '$arg'"
+ esac
+ else
+ case "$arg" in
+ "--loose-"*) append_arg_to_args "$arg" ;;
+ *) append_arg_to_args "--loose-$arg"
+ esac
+ fi
esac
done
}
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 3a509fb8beb..377d549a045 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -3389,7 +3389,6 @@ void init_signals(void)
sigemptyset(&sa.sa_mask);
sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
- my_init_stacktrace();
#if defined(__amiga__)
sa.sa_handler=(void(*)())handle_fatal_signal;
#else
diff --git a/sql/tztime.cc b/sql/tztime.cc
index ca4c10975ca..4ef20d79d5d 100644
--- a/sql/tztime.cc
+++ b/sql/tztime.cc
@@ -2739,9 +2739,11 @@ main(int argc, char **argv)
printf("TRUNCATE TABLE time_zone_name;\n");
printf("TRUNCATE TABLE time_zone_transition;\n");
printf("TRUNCATE TABLE time_zone_transition_type;\n");
+ printf("START TRANSACTION;\n");
if (scan_tz_dir(root_name_end, 0, opt_verbose))
{
+ printf("ROLLBACK;\n");
fflush(stdout);
fprintf(stderr,
"There were fatal errors during processing "
@@ -2749,6 +2751,7 @@ main(int argc, char **argv)
return 1;
}
+ printf("COMMIT;\n");
printf("ALTER TABLE time_zone_transition "
"ORDER BY Time_zone_id, Transition_time;\n");
printf("ALTER TABLE time_zone_transition_type "
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index fffa36475e6..a68bc6550d7 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -3360,7 +3360,7 @@ fail:
/* prefetch siblings of the leaf for the pessimistic
operation, if the page is leaf. */
- if (page_is_leaf(page)) {
+ if (page_is_leaf(page) && !index->is_ibuf()) {
btr_cur_prefetch_siblings(block);
}
fail_err:
@@ -4330,6 +4330,7 @@ btr_cur_optimistic_update(
if (rec_offs_any_extern(*offsets)) {
any_extern:
+ ut_ad(!index->is_ibuf());
/* Externally stored fields are treated in pessimistic
update */
@@ -4525,7 +4526,7 @@ func_exit:
}
}
- if (err != DB_SUCCESS) {
+ if (err != DB_SUCCESS && !index->is_ibuf()) {
/* prefetch siblings of the leaf for the pessimistic
operation. */
btr_cur_prefetch_siblings(block);
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 076b9c33c00..ea1916e192d 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -5653,7 +5653,23 @@ buf_page_create(
if (drop_hash_entry) {
mutex_enter(&block->mutex);
- buf_page_set_sticky(&block->page);
+ /* Avoid a hang if I/O is going on. Release
+ the buffer pool mutex and page hash lock
+ and wait for I/O to complete */
+ while (buf_block_get_io_fix(block) != BUF_IO_NONE) {
+ buf_block_fix(block);
+ mutex_exit(&block->mutex);
+ buf_pool_mutex_exit(buf_pool);
+ rw_lock_x_unlock(hash_lock);
+
+ os_thread_yield();
+
+ buf_pool_mutex_enter(buf_pool);
+ rw_lock_x_lock(hash_lock);
+ mutex_enter(&block->mutex);
+ buf_block_unfix(block);
+ }
+ rw_lock_x_lock(&block->lock);
mutex_exit(&block->mutex);
}
#endif
@@ -5665,11 +5681,7 @@ buf_page_create(
#ifdef BTR_CUR_HASH_ADAPT
if (drop_hash_entry) {
btr_search_drop_page_hash_index(block);
- buf_pool_mutex_enter(buf_pool);
- mutex_enter(&block->mutex);
- buf_page_unset_sticky(&block->page);
- mutex_exit(&block->mutex);
- buf_pool_mutex_exit(buf_pool);
+ rw_lock_x_unlock(&block->lock);
}
#endif /* BTR_CUR_HASH_ADAPT */
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index e1acc7b9095..6f56a09eda2 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -3116,7 +3116,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*)
/* The page_cleaner skips sleep if the server is
idle and there are no pending IOs in the buffer pool
and there is work to do. */
- if (srv_check_activity(&last_activity)
+ if (srv_check_activity(last_activity)
|| buf_get_n_pending_read_ios()
|| n_flushed == 0) {
@@ -3208,7 +3208,7 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*)
n_flushed = n_flushed_lru + n_flushed_list;
- } else if (srv_check_activity(&last_activity)) {
+ } else if (srv_check_activity(last_activity)) {
ulint n_to_flush;
lsn_t lsn_limit = 0;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index c87e396b0de..21b68dd0fb3 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -447,6 +447,14 @@ TYPELIB innodb_flush_method_typelib = {
NULL
};
+/* The following counter is used to convey information to InnoDB
+about server activity: in case of normal DML ops it is not
+sensible to call srv_active_wake_master_thread after each
+operation, we only do it every INNOBASE_WAKE_INTERVAL'th step. */
+
+#define INNOBASE_WAKE_INTERVAL 32
+static ulong innobase_active_counter = 0;
+
/** Allowed values of innodb_change_buffering */
static const char* innodb_change_buffering_names[] = {
"none", /* IBUF_USE_NONE */
@@ -1844,6 +1852,23 @@ thd_to_trx_id(
#endif /* WITH_WSREP */
/********************************************************************//**
+Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
+time calls srv_active_wake_master_thread. This function should be used
+when a single database operation may introduce a small need for
+server utility activity, like checkpointing. */
+inline
+void
+innobase_active_small(void)
+/*=======================*/
+{
+ innobase_active_counter++;
+
+ if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
+ srv_active_wake_master_thread();
+ }
+}
+
+/********************************************************************//**
Converts an InnoDB error code to a MySQL error code and also tells to MySQL
about a possible transaction rollback inside InnoDB caused by a lock wait
timeout or a deadlock.
@@ -3488,8 +3513,7 @@ static int innodb_init_abort()
DBUG_RETURN(1);
}
-/** Update log_checksum_algorithm_ptr with a pointer to the function
-corresponding to whether checksums are enabled.
+/** If applicable, emit a message that log checksums cannot be disabled.
@param[in,out] thd client session, or NULL if at startup
@param[in] check whether redo log block checksums are enabled
@return whether redo log block checksums are enabled */
@@ -3497,34 +3521,21 @@ static inline
bool
innodb_log_checksums_func_update(THD* thd, bool check)
{
- static const char msg[] = "innodb_encrypt_log implies"
- " innodb_log_checksums";
+ static const char msg[] = "innodb_log_checksums is deprecated"
+ " and has no effect outside recovery";
ut_ad(!thd == !srv_was_started);
if (!check) {
- check = srv_encrypt_log;
- if (!check) {
- } else if (thd) {
+ if (thd) {
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
HA_ERR_UNSUPPORTED, msg);
+ check = true;
} else {
sql_print_warning(msg);
}
}
- if (thd) {
- log_mutex_enter();
- log_checksum_algorithm_ptr = check
- ? log_block_calc_checksum_crc32
- : log_block_calc_checksum_none;
- log_mutex_exit();
- } else {
- log_checksum_algorithm_ptr = check
- ? log_block_calc_checksum_crc32
- : log_block_calc_checksum_none;
- }
-
return(check);
}
@@ -6456,6 +6467,11 @@ ha_innobase::close()
MONITOR_INC(MONITOR_TABLE_CLOSE);
+ /* Tell InnoDB server that there might be work for
+ utility threads: */
+
+ srv_active_wake_master_thread();
+
DBUG_RETURN(0);
}
@@ -8166,6 +8182,8 @@ report_error:
}
func_exit:
+ innobase_active_small();
+
DBUG_RETURN(error_result);
}
@@ -8852,6 +8870,11 @@ func_exit:
error, m_prebuilt->table->flags, m_user_thd);
}
+ /* Tell InnoDB server that there might be work for
+ utility threads: */
+
+ innobase_active_small();
+
#ifdef WITH_WSREP
if (error == DB_SUCCESS && trx->is_wsrep() &&
wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE &&
@@ -8910,6 +8933,11 @@ ha_innobase::delete_row(
innobase_srv_conc_exit_innodb(m_prebuilt);
+ /* Tell the InnoDB server that there might be work for
+ utility threads: */
+
+ innobase_active_small();
+
#ifdef WITH_WSREP
if (error == DB_SUCCESS && trx->is_wsrep()
&& wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE
@@ -12697,6 +12725,7 @@ create_table_info_t::create_table_update_dict()
if (m_flags2 & DICT_TF2_FTS) {
if (!innobase_fts_load_stopword(innobase_table, NULL, m_thd)) {
dict_table_close(innobase_table, FALSE, FALSE);
+ srv_active_wake_master_thread();
trx_free(m_trx);
DBUG_RETURN(-1);
}
@@ -12846,6 +12875,11 @@ ha_innobase::create(
error = info.create_table_update_dict();
+ /* Tell the InnoDB server that there might be work for
+ utility threads: */
+
+ srv_active_wake_master_thread();
+
DBUG_RETURN(error);
}
@@ -19068,7 +19102,7 @@ static MYSQL_SYSVAR_ENUM(checksum_algorithm, srv_checksum_algorithm,
static MYSQL_SYSVAR_BOOL(log_checksums, innodb_log_checksums,
PLUGIN_VAR_RQCMDARG,
- "Whether to compute and require checksums for InnoDB redo log blocks",
+ "DEPRECATED. Whether to require checksums for InnoDB redo log blocks.",
NULL, innodb_log_checksums_update, TRUE);
static MYSQL_SYSVAR_BOOL(checksums, innobase_use_checksums,
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 98d68250029..896052f34ac 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -9415,11 +9415,11 @@ ha_innobase::commit_inplace_alter_table(
/* Exclusively lock the table, to ensure that no other
transaction is holding locks on the table while we
- change the table definition. The MySQL meta-data lock
+ change the table definition. The meta-data lock (MDL)
should normally guarantee that no conflicting locks
exist. However, FOREIGN KEY constraints checks and any
transactions collected during crash recovery could be
- holding InnoDB locks only, not MySQL locks. */
+ holding InnoDB locks only, not MDL. */
dberr_t error = row_merge_lock_table(
m_prebuilt->trx, ctx->old_table, LOCK_X);
@@ -9795,6 +9795,11 @@ foreign_fail:
log_append_on_checkpoint(NULL);
+ /* Tell the InnoDB server that there might be work for
+ utility threads: */
+
+ srv_active_wake_master_thread();
+
if (fail) {
for (inplace_alter_handler_ctx** pctx = ctx_array;
*pctx; pctx++) {
diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h
index 2504b2ef61d..59723a3c178 100644
--- a/storage/innobase/include/dict0mem.h
+++ b/storage/innobase/include/dict0mem.h
@@ -1041,6 +1041,9 @@ struct dict_index_t{
/** @return whether this is a spatial index */
bool is_spatial() const { return UNIV_UNLIKELY(type & DICT_SPATIAL); }
+ /** @return whether this is the change buffer */
+ bool is_ibuf() const { return UNIV_UNLIKELY(type & DICT_IBUF); }
+
/** @return whether the index includes virtual columns */
bool has_virtual() const { return type & DICT_VIRTUAL; }
diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h
index 133b1692d31..b201de06d17 100644
--- a/storage/innobase/include/log0log.h
+++ b/storage/innobase/include/log0log.h
@@ -2,7 +2,7 @@
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2009, Google Inc.
-Copyright (c) 2017, 2019, MariaDB Corporation.
+Copyright (c) 2017, 2020, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -56,12 +56,6 @@ step which modifies the database, is started */
#define LOG_CHECKPOINT_FREE_PER_THREAD (4U << srv_page_size_shift)
#define LOG_CHECKPOINT_EXTRA_FREE (8U << srv_page_size_shift)
-typedef ulint (*log_checksum_func_t)(const byte* log_block);
-
-/** Pointer to the log checksum calculation function. Protected with
-log_sys.mutex. */
-extern log_checksum_func_t log_checksum_algorithm_ptr;
-
/** Append a string to the log.
@param[in] str string
@param[in] len string length
@@ -266,14 +260,6 @@ log_block_set_data_len(
/*===================*/
byte* log_block, /*!< in/out: log block */
ulint len); /*!< in: data length */
-/************************************************************//**
-Calculates the checksum for a log block.
-@return checksum */
-UNIV_INLINE
-ulint
-log_block_calc_checksum(
-/*====================*/
- const byte* block); /*!< in: log block */
/** Calculates the checksum for a log block using the CRC32 algorithm.
@param[in] block log block
@@ -283,12 +269,6 @@ ulint
log_block_calc_checksum_crc32(
const byte* block);
-/** Calculates the checksum for a log block using the "no-op" algorithm.
-@return the calculated checksum value */
-UNIV_INLINE
-ulint
-log_block_calc_checksum_none(const byte*);
-
/************************************************************//**
Gets a log block checksum field value.
@return checksum */
@@ -365,7 +345,7 @@ void
log_refresh_stats(void);
/*===================*/
-/** Whether to generate and require checksums on the redo log pages */
+/** Whether to require checksums on the redo log pages */
extern my_bool innodb_log_checksums;
/* Values used as flags */
diff --git a/storage/innobase/include/log0log.ic b/storage/innobase/include/log0log.ic
index 722e658a24b..be28fee7b8e 100644
--- a/storage/innobase/include/log0log.ic
+++ b/storage/innobase/include/log0log.ic
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2018, MariaDB Corporation.
+Copyright (c) 2017, 2020, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -190,18 +190,6 @@ log_block_convert_lsn_to_no(
0xFUL, 0x3FFFFFFFUL)) + 1);
}
-/************************************************************//**
-Calculates the checksum for a log block.
-@return checksum */
-UNIV_INLINE
-ulint
-log_block_calc_checksum(
-/*====================*/
- const byte* block) /*!< in: log block */
-{
- return(log_checksum_algorithm_ptr(block));
-}
-
/** Calculate the checksum for a log block using the pre-5.7.9 algorithm.
@param[in] block log block
@return checksum */
@@ -242,15 +230,6 @@ log_block_calc_checksum_crc32(
return(ut_crc32(block, OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE));
}
-/** Calculates the checksum for a log block using the "no-op" algorithm.
-@return checksum */
-UNIV_INLINE
-ulint
-log_block_calc_checksum_none(const byte*)
-{
- return(LOG_NO_CHECKSUM_MAGIC);
-}
-
/************************************************************//**
Gets a log block checksum field value.
@return checksum */
diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h
index 93755ad7520..6c575733710 100644
--- a/storage/innobase/include/srv0srv.h
+++ b/storage/innobase/include/srv0srv.h
@@ -788,6 +788,19 @@ srv_reset_io_thread_op_info();
/** Wake up the purge threads if there is work to do. */
void
srv_wake_purge_thread_if_not_active();
+/** Wake up the InnoDB master thread if it was suspended (not sleeping). */
+void
+srv_active_wake_master_thread_low();
+
+#define srv_active_wake_master_thread() \
+ do { \
+ if (!srv_read_only_mode) { \
+ srv_active_wake_master_thread_low(); \
+ } \
+ } while (0)
+/** Wake up the master thread if it is suspended or being suspended. */
+void
+srv_wake_master_thread();
/******************************************************************//**
Outputs to a file the output of the InnoDB Monitor.
@@ -816,13 +829,13 @@ reading this value as it is only used in heuristics.
ulint
srv_get_activity_count(void);
/*========================*/
-
-/** Check if there has been any activity.
-@param[in,out] activity_count recent activity count to be returned
-if there is a change
+/*******************************************************************//**
+Check if there has been any activity.
@return FALSE if no change in activity counter. */
-bool srv_check_activity(ulint *activity_count);
-
+ibool
+srv_check_activity(
+/*===============*/
+ ulint old_activity_count); /*!< old activity count */
/******************************************************************//**
Increment the server activity counter. */
void
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index e8f39e03b50..997430497bc 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -2,7 +2,7 @@
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Google Inc.
-Copyright (c) 2014, 2019, MariaDB Corporation.
+Copyright (c) 2014, 2020, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -83,12 +83,9 @@ reduce the size of the log.
/** Redo log system */
log_t log_sys;
-/** Whether to generate and require checksums on the redo log pages */
+/** Whether to require checksums on the redo log pages */
my_bool innodb_log_checksums;
-/** Pointer to the log checksum calculation function */
-log_checksum_func_t log_checksum_algorithm_ptr;
-
/* Next log block number to do dummy record filling if no log records written
for a while */
static ulint next_lbn_to_pad = 0;
@@ -679,7 +676,7 @@ log_block_store_checksum(
/*=====================*/
byte* block) /*!< in/out: pointer to a log block */
{
- log_block_set_checksum(block, log_block_calc_checksum(block));
+ log_block_set_checksum(block, log_block_calc_checksum_crc32(block));
}
/******************************************************//**
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index a9b5b1e25d0..b6f6bc26165 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -1199,7 +1199,10 @@ static dberr_t recv_log_recover_10_4()
% univ_page_size.physical()),
OS_FILE_LOG_BLOCK_SIZE, buf, NULL);
- if (log_block_calc_checksum(buf) != log_block_get_checksum(buf)) {
+ const ulint cksum = log_block_get_checksum(buf);
+
+ if (cksum != LOG_NO_CHECKSUM_MAGIC
+ && cksum != log_block_calc_checksum_crc32(buf)) {
return DB_CORRUPTION;
}
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 0c5f96e20a5..5dcd596fc98 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -3817,7 +3817,7 @@ funct_exit_all_freed:
trx->op_info = "";
- srv_inc_activity_count();
+ srv_wake_master_thread();
DBUG_RETURN(err);
}
@@ -4528,12 +4528,20 @@ end:
if (err != DB_SUCCESS) {
if (old_is_tmp) {
- ib::error() << "In ALTER TABLE "
+ /* In case of copy alter, ignore the
+ loading of foreign key constraint
+ when foreign_key_check is disabled */
+ ib::error_or_warn(trx->check_foreigns)
+ << "In ALTER TABLE "
<< ut_get_name(trx, new_name)
<< " has or is referenced in foreign"
" key constraints which are not"
" compatible with the new table"
" definition.";
+ if (!trx->check_foreigns) {
+ err = DB_SUCCESS;
+ goto funct_exit;
+ }
} else {
ib::error() << "In RENAME TABLE table "
<< ut_get_name(trx, new_name)
diff --git a/storage/innobase/row/row0uins.cc b/storage/innobase/row/row0uins.cc
index 1e560dad7b3..be0f6373e21 100644
--- a/storage/innobase/row/row0uins.cc
+++ b/storage/innobase/row/row0uins.cc
@@ -82,6 +82,7 @@ row_undo_ins_remove_clust_rec(
mtr.set_log_mode(MTR_LOG_NO_REDO);
} else {
index->set_modified(mtr);
+ ut_ad(lock_table_has_locks(index->table));
}
/* This is similar to row_undo_mod_clust(). The DDL thread may
@@ -92,8 +93,7 @@ row_undo_ins_remove_clust_rec(
online = dict_index_is_online_ddl(index);
if (online) {
- ut_ad(node->trx->dict_operation_lock_mode
- != RW_X_LATCH);
+ ut_ad(!node->trx->dict_operation_lock_mode);
ut_ad(node->table->id != DICT_INDEXES_ID);
mtr_s_lock_index(index, &mtr);
}
@@ -568,6 +568,9 @@ row_undo_ins(
return(DB_SUCCESS);
}
+ ut_ad(node->table->is_temporary()
+ || lock_table_has_locks(node->table));
+
/* Iterate over all the indexes and undo the insert.*/
node->index = dict_table_get_first_index(node->table);
diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc
index 2ac54c4025e..3e46c2f6123 100644
--- a/storage/innobase/row/row0umod.cc
+++ b/storage/innobase/row/row0umod.cc
@@ -219,10 +219,7 @@ row_undo_mod_clust(
bool online;
ut_ad(thr_get_trx(thr) == node->trx);
- ut_ad(node->trx->dict_operation_lock_mode);
ut_ad(node->trx->in_rollback);
- ut_ad(rw_lock_own_flagged(&dict_operation_lock,
- RW_LOCK_FLAG_X | RW_LOCK_FLAG_S));
log_free_check();
pcur = &node->pcur;
@@ -234,11 +231,12 @@ row_undo_mod_clust(
mtr.set_log_mode(MTR_LOG_NO_REDO);
} else {
index->set_modified(mtr);
+ ut_ad(lock_table_has_locks(index->table));
}
online = dict_index_is_online_ddl(index);
if (online) {
- ut_ad(node->trx->dict_operation_lock_mode != RW_X_LATCH);
+ ut_ad(!node->trx->dict_operation_lock_mode);
mtr_s_lock_index(index, &mtr);
}
@@ -277,17 +275,7 @@ row_undo_mod_clust(
ut_ad(err == DB_SUCCESS || err == DB_OUT_OF_FILE_SPACE);
}
- /* Online rebuild cannot be initiated while we are holding
- dict_operation_lock and index->lock. (It can be aborted.) */
- ut_ad(online || !dict_index_is_online_ddl(index));
-
- if (err == DB_SUCCESS && online) {
-
- ut_ad(rw_lock_own_flagged(
- &index->lock,
- RW_LOCK_FLAG_S | RW_LOCK_FLAG_X
- | RW_LOCK_FLAG_SX));
-
+ if (err == DB_SUCCESS && online && dict_index_is_online_ddl(index)) {
switch (node->rec_type) {
case TRX_UNDO_DEL_MARK_REC:
row_log_table_insert(
@@ -836,37 +824,6 @@ func_exit_no_pcur:
}
/***********************************************************//**
-Flags a secondary index corrupted. */
-static MY_ATTRIBUTE((nonnull))
-void
-row_undo_mod_sec_flag_corrupted(
-/*============================*/
- trx_t* trx, /*!< in/out: transaction */
- dict_index_t* index) /*!< in: secondary index */
-{
- ut_ad(!dict_index_is_clust(index));
-
- switch (trx->dict_operation_lock_mode) {
- case RW_S_LATCH:
- /* Because row_undo() is holding an S-latch
- on the data dictionary during normal rollback,
- we can only mark the index corrupted in the
- data dictionary cache. TODO: fix this somehow.*/
- mutex_enter(&dict_sys->mutex);
- dict_set_corrupted_index_cache_only(index);
- mutex_exit(&dict_sys->mutex);
- break;
- default:
- ut_ad(0);
- /* fall through */
- case RW_X_LATCH:
- /* This should be the rollback of a data dictionary
- transaction. */
- dict_set_corrupted(index, trx, "rollback");
- }
-}
-
-/***********************************************************//**
Undoes a modify in secondary indexes when undo record type is UPD_DEL.
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
static MY_ATTRIBUTE((nonnull, warn_unused_result))
@@ -979,8 +936,7 @@ row_undo_mod_del_mark_sec(
}
if (err == DB_DUPLICATE_KEY) {
- row_undo_mod_sec_flag_corrupted(
- thr_get_trx(thr), index);
+ index->type |= DICT_CORRUPT;
err = DB_SUCCESS;
/* Do not return any error to the caller. The
duplicate will be reported by ALTER TABLE or
@@ -1125,8 +1081,7 @@ row_undo_mod_upd_exist_sec(
}
if (err == DB_DUPLICATE_KEY) {
- row_undo_mod_sec_flag_corrupted(
- thr_get_trx(thr), index);
+ index->type |= DICT_CORRUPT;
err = DB_SUCCESS;
} else if (err != DB_SUCCESS) {
break;
@@ -1292,6 +1247,8 @@ row_undo_mod(
return(DB_SUCCESS);
}
+ ut_ad(node->table->is_temporary()
+ || lock_table_has_locks(node->table));
node->index = dict_table_get_first_index(node->table);
ut_ad(dict_index_is_clust(node->index));
diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc
index 762228503be..68b8123cbb6 100644
--- a/storage/innobase/row/row0undo.cc
+++ b/storage/innobase/row/row0undo.cc
@@ -283,15 +283,16 @@ row_undo(
? UNDO_NODE_INSERT : UNDO_NODE_MODIFY;
}
- /* Prevent DROP TABLE etc. while we are rolling back this row.
- If we are doing a TABLE CREATE or some other dictionary operation,
- then we already have dict_operation_lock locked in x-mode. Do not
- try to lock again, because that would cause a hang. */
-
- const bool locked_data_dict = (trx->dict_operation_lock_mode == 0);
-
- if (locked_data_dict) {
-
+ /* Prevent prepare_inplace_alter_table_dict() from adding
+ dict_table_t::indexes while we are processing the record.
+ Recovered transactions are not protected by MDL, and the
+ secondary index creation is not protected by table locks
+ for online operation. (A table lock would only be acquired
+ when committing the ALTER TABLE operation.) */
+ const bool locked_data_dict = UNIV_UNLIKELY(trx->is_recovered)
+ && !trx->dict_operation_lock_mode;
+
+ if (UNIV_UNLIKELY(locked_data_dict)) {
row_mysql_freeze_data_dictionary(trx);
}
@@ -307,8 +308,7 @@ row_undo(
err = row_undo_mod(node, thr);
}
- if (locked_data_dict) {
-
+ if (UNIV_UNLIKELY(locked_data_dict)) {
row_mysql_unfreeze_data_dictionary(trx);
}
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 6af3b89f15c..c5b08cd5eb8 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -1923,6 +1923,33 @@ srv_get_active_thread_type(void)
return(ret);
}
+/** Wake up the InnoDB master thread if it was suspended (not sleeping). */
+void
+srv_active_wake_master_thread_low()
+{
+ ut_ad(!srv_read_only_mode);
+ ut_ad(!srv_sys_mutex_own());
+
+ srv_inc_activity_count();
+
+ if (my_atomic_loadlint(&srv_sys.n_threads_active[SRV_MASTER]) == 0) {
+ srv_slot_t* slot;
+
+ srv_sys_mutex_enter();
+
+ slot = &srv_sys.sys_threads[SRV_MASTER_SLOT];
+
+ /* Only if the master thread has been started. */
+
+ if (slot->in_use) {
+ ut_a(srv_slot_get_type(slot) == SRV_MASTER);
+ os_event_set(slot->event);
+ }
+
+ srv_sys_mutex_exit();
+ }
+}
+
/** Wake up the purge threads if there is work to do. */
void
srv_wake_purge_thread_if_not_active()
@@ -1937,6 +1964,14 @@ srv_wake_purge_thread_if_not_active()
}
}
+/** Wake up the master thread if it is suspended or being suspended. */
+void
+srv_wake_master_thread()
+{
+ srv_inc_activity_count();
+ srv_release_threads(SRV_MASTER, 1);
+}
+
/*******************************************************************//**
Get current server activity count. We don't hold srv_sys::mutex while
reading this value as it is only used in heuristics.
@@ -1948,20 +1983,15 @@ srv_get_activity_count(void)
return(srv_sys.activity_count);
}
-/** Check if there has been any activity.
-@param[in,out] activity_count recent activity count to be returned
-if there is a change
+/*******************************************************************//**
+Check if there has been any activity.
@return FALSE if no change in activity counter. */
-bool srv_check_activity(ulint *activity_count)
+ibool
+srv_check_activity(
+/*===============*/
+ ulint old_activity_count) /*!< in: old activity count */
{
- ulint new_activity_count= srv_sys.activity_count;
- if (new_activity_count != *activity_count)
- {
- *activity_count= new_activity_count;
- return true;
- }
-
- return false;
+ return(srv_sys.activity_count != old_activity_count);
}
/********************************************************************//**
@@ -2362,30 +2392,52 @@ DECLARE_THREAD(srv_master_thread)(
slot = srv_reserve_slot(SRV_MASTER);
ut_a(slot == srv_sys.sys_threads);
+loop:
while (srv_shutdown_state <= SRV_SHUTDOWN_INITIATED) {
srv_master_sleep();
MONITOR_INC(MONITOR_MASTER_THREAD_SLEEP);
- if (srv_check_activity(&old_activity_count)) {
+ if (srv_check_activity(old_activity_count)) {
+ old_activity_count = srv_get_activity_count();
srv_master_do_active_tasks();
} else {
srv_master_do_idle_tasks();
}
}
- ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS
- || srv_shutdown_state == SRV_SHUTDOWN_CLEANUP);
-
- if (srv_shutdown_state == SRV_SHUTDOWN_CLEANUP
- && srv_fast_shutdown < 2) {
- srv_shutdown(srv_fast_shutdown == 0);
+ switch (srv_shutdown_state) {
+ case SRV_SHUTDOWN_NONE:
+ case SRV_SHUTDOWN_INITIATED:
+ break;
+ case SRV_SHUTDOWN_FLUSH_PHASE:
+ case SRV_SHUTDOWN_LAST_PHASE:
+ ut_ad(0);
+ /* fall through */
+ case SRV_SHUTDOWN_EXIT_THREADS:
+ /* srv_init_abort() must have been invoked */
+ case SRV_SHUTDOWN_CLEANUP:
+ if (srv_shutdown_state == SRV_SHUTDOWN_CLEANUP
+ && srv_fast_shutdown < 2) {
+ srv_shutdown(srv_fast_shutdown == 0);
+ }
+ srv_suspend_thread(slot);
+ my_thread_end();
+ os_thread_exit();
}
+ srv_main_thread_op_info = "suspending";
+
srv_suspend_thread(slot);
- my_thread_end();
- os_thread_exit();
- OS_THREAD_DUMMY_RETURN;
+
+ /* DO NOT CHANGE THIS STRING. innobase_start_or_create_for_mysql()
+ waits for database activity to die down when converting < 4.1.x
+ databases, and relies on this string being exactly as it is. InnoDB
+ manual also mentions this string in several places. */
+ srv_main_thread_op_info = "waiting for server activity";
+
+ srv_resume_thread(slot);
+ goto loop;
}
/** @return whether purge should exit due to shutdown */
@@ -2553,13 +2605,15 @@ static ulint srv_do_purge(ulint* n_total_purged
++n_use_threads;
}
- } else if (srv_check_activity(&old_activity_count)
+ } else if (srv_check_activity(old_activity_count)
&& n_use_threads > 1) {
/* History length same or smaller since last snapshot,
use fewer threads. */
--n_use_threads;
+
+ old_activity_count = srv_get_activity_count();
}
/* Ensure that the purge threads are less than what
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 859e5a3eec2..318ab49cc9c 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -1178,7 +1178,7 @@ srv_shutdown_all_bg_threads()
if (srv_start_state_is_set(SRV_START_STATE_MASTER)) {
/* c. We wake the master thread so that
it exits */
- srv_inc_activity_count();
+ srv_wake_master_thread();
}
if (srv_start_state_is_set(SRV_START_STATE_PURGE)) {
@@ -2526,7 +2526,7 @@ void srv_shutdown_bg_undo_sources()
fts_optimize_shutdown();
dict_stats_shutdown();
while (row_get_background_drop_list_len_low()) {
- srv_inc_activity_count();
+ srv_wake_master_thread();
os_thread_yield();
}
srv_undo_sources = false;
diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc
index c61a67ec05e..1be444adf07 100644
--- a/storage/innobase/trx/trx0roll.cc
+++ b/storage/innobase/trx/trx0roll.cc
@@ -164,6 +164,9 @@ trx_rollback_to_savepoint_low(
mem_heap_free(heap);
+ /* There might be work for utility threads.*/
+ srv_active_wake_master_thread();
+
MONITOR_DEC(MONITOR_TRX_ACTIVE);
}
diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc
index e1efc7c895f..1d4202b3033 100644
--- a/storage/innobase/trx/trx0trx.cc
+++ b/storage/innobase/trx/trx0trx.cc
@@ -1470,6 +1470,12 @@ trx_commit_in_memory(
}
trx->commit_lsn = lsn;
+
+ /* Tell server some activity has happened, since the trx
+ does changes something. Background utility threads like
+ master thread, purge thread or page_cleaner thread might
+ have some work to do. */
+ srv_active_wake_master_thread();
}
ut_ad(!trx->rsegs.m_noredo.undo);
diff --git a/unittest/mysys/CMakeLists.txt b/unittest/mysys/CMakeLists.txt
index ec4e0b91626..984b033e7aa 100644
--- a/unittest/mysys/CMakeLists.txt
+++ b/unittest/mysys/CMakeLists.txt
@@ -15,7 +15,7 @@
MY_ADD_TESTS(bitmap base64 my_atomic my_rdtsc lf my_malloc my_getopt dynstring
byte_order
- queues LINK_LIBRARIES mysys)
+ queues stacktrace LINK_LIBRARIES mysys)
MY_ADD_TESTS(my_vsnprintf LINK_LIBRARIES strings mysys)
MY_ADD_TESTS(aes LINK_LIBRARIES mysys mysys_ssl)
ADD_DEFINITIONS(${SSL_DEFINES})
diff --git a/unittest/mysys/stacktrace-t.c b/unittest/mysys/stacktrace-t.c
new file mode 100644
index 00000000000..8fa0db15b36
--- /dev/null
+++ b/unittest/mysys/stacktrace-t.c
@@ -0,0 +1,67 @@
+
+/* Copyright (c) 2020, MariaDB Corporation.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA */
+
+#include <my_global.h>
+#include <my_sys.h>
+#include <stdio.h>
+#include <my_stacktrace.h>
+#include <tap.h>
+
+char b_bss[10];
+
+void test_my_safe_print_str()
+{
+ char b_stack[10];
+ char *b_heap= strdup("LEGAL");
+ memcpy(b_stack, "LEGAL", 6);
+ memcpy(b_bss, "LEGAL", 6);
+
+#ifndef __SANITIZE_ADDRESS__
+ fprintf(stderr, "\n===== stack =====\n");
+ my_safe_print_str(b_stack, 65535);
+ fprintf(stderr, "\n===== heap =====\n");
+ my_safe_print_str(b_heap, 65535);
+ fprintf(stderr, "\n===== BSS =====\n");
+ my_safe_print_str(b_bss, 65535);
+ fprintf(stderr, "\n===== data =====\n");
+ my_safe_print_str("LEGAL", 65535);
+ fprintf(stderr, "\n===== Above is a junk, but it is expected. =====\n");
+#endif /*__SANITIZE_ADDRESS__*/
+ fprintf(stderr, "\n===== Nornal length test =====\n");
+ my_safe_print_str("LEGAL", 5);
+ fprintf(stderr, "\n===== NULL =====\n");
+ my_safe_print_str(0, 5);
+#ifndef __SANITIZE_ADDRESS__
+ fprintf(stderr, "\n===== (const char*) 1 =====\n");
+ my_safe_print_str((const char*)1, 5);
+#endif /*__SANITIZE_ADDRESS__*/
+
+ free(b_heap);
+
+ ok(1, "test_my_safe_print_str");
+}
+
+
+int main(int argc __attribute__((unused)), char **argv)
+{
+ MY_INIT(argv[0]);
+ plan(1);
+
+ test_my_safe_print_str();
+
+ my_end(0);
+ return exit_status();
+}