Merge 10.0 into 10.1

This commit is contained in:
Marko Mäkelä 2017-02-08 08:53:34 +02:00
commit 2e67e66c3a
29 changed files with 624 additions and 549 deletions

View file

@ -3339,6 +3339,8 @@ void do_exec(struct st_command *command)
DBUG_ENTER("do_exec");
DBUG_PRINT("enter", ("cmd: '%s'", cmd));
var_set_int("$sys_errno",0);
/* Skip leading space */
while (*cmd && my_isspace(charset_info, *cmd))
cmd++;
@ -3455,6 +3457,7 @@ void do_exec(struct st_command *command)
report_or_die("command \"%s\" failed with wrong error: %d",
command->first_argument, status);
}
var_set_int("$sys_errno",status);
}
else if (command->expected_errors.err[0].type == ERR_ERRNO &&
command->expected_errors.err[0].code.errnum != 0)

View file

@ -292,6 +292,7 @@ CREATE DEFINER=root@localhost
PROCEDURE add_suppression(pattern VARCHAR(255))
BEGIN
INSERT INTO test_suppressions (pattern) VALUES (pattern);
FLUSH NO_WRITE_TO_BINLOG TABLE test_suppressions;
END
*/||

View file

@ -53,9 +53,19 @@ sub _verify_binpath {
sub _gdb {
my ($core_name)= @_;
print "\nTrying 'gdb' to get a backtrace\n";
# Check that gdb exists
`gdb --version`;
if ($?) {
print "gdb not found, cannot get the stack trace\n";
return;
}
return unless -f $core_name;
if (-f $core_name) {
print "\nTrying 'gdb' to get a backtrace from coredump $core_name\n";
} else {
print "\nCoredump $core_name does not exist, cannot run 'gdb'\n";
return;
}
# Find out name of binary that generated core
`gdb -c '$core_name' --batch 2>&1` =~

View file

@ -26,7 +26,8 @@ KEY `fk_crewRoleAssigned_roleCode` (`role_code`),
CONSTRAINT `fk_crewRoleAssigned_crewId` FOREIGN KEY (`crew_id`) REFERENCES `repro`.`crew` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_crewRoleAssigned_pilotId` FOREIGN KEY (`crew_id`) REFERENCES `repro`.`pilot` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB COMMENT="This is a comment about tables";
# Restart mysqld --innodb_read_only=1
ALTER TABLE `repro`.`crew_role_assigned` COMMENT = 'innodb_read_only';
ERROR HY000: Table 'crew_role_assigned' is read only
SHOW CREATE TABLE `repro`.`crew_role_assigned`;
Table Create Table
crew_role_assigned CREATE TABLE `crew_role_assigned` (
@ -52,7 +53,6 @@ crew_role_assigned CREATE TABLE `crew_role_assigned` (
CONSTRAINT `fk_crewRoleAssigned_crewId` FOREIGN KEY (`crew_id`) REFERENCES `crew` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `fk_crewRoleAssigned_pilotId` FOREIGN KEY (`crew_id`) REFERENCES `pilot` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='This is a new comment about tables'
# Restart mysqld --innodb_read_only=1
SHOW CREATE TABLE `repro`.`crew_role_assigned`;
Table Create Table
crew_role_assigned CREATE TABLE `crew_role_assigned` (

View file

@ -15,15 +15,57 @@ INSERT INTO t1 VALUES (123);
BEGIN;
DELETE FROM t1;
# Kill the server
--innodb-force-recovery-crash=1
--innodb-force-recovery-crash=3
--innodb-force-recovery-crash=4
--innodb-force-recovery-crash=5
--innodb-force-recovery-crash=6
--innodb-force-recovery-crash=7
--innodb-force-recovery-crash=8
--innodb-force-recovery-crash=9
--innodb-force-recovery-crash=10
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /syntax error in innodb_log_group_home_dir/ in mysqld.1.err
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /InnoDB: Starting an apply batch of log records/ in mysqld.1.err
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /InnoDB: Starting an apply batch of log records/ in mysqld.1.err
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /InnoDB: innodb_read_only prevents crash recovery/ in mysqld.1.err
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /InnoDB: Starting an apply batch of log records/ in mysqld.1.err
FOUND /InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages/ in mysqld.1.err
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /InnoDB: Starting an apply batch of log records/ in mysqld.1.err
FOUND /InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages/ in mysqld.1.err
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /InnoDB: innodb_read_only prevents crash recovery/ in mysqld.1.err
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /InnoDB: Starting an apply batch of log records/ in mysqld.1.err
FOUND /InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages/ in mysqld.1.err
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /InnoDB: Cannot create log files in read-only mode/ in mysqld.1.err
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /InnoDB: Setting log file .*ib_logfile[0-9]+ size to/ in mysqld.1.err
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /InnoDB: Setting log file .*ib_logfile[0-9]+ size to/ in mysqld.1.err
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /InnoDB: Only one log file found/ in mysqld.1.err
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /InnoDB: Log file .*ib_logfile0 size 7 is not a multiple of innodb_page_size/ in mysqld.1.err
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /InnoDB: Log file .*ib_logfile1 is of different size 1048576 bytes than other log files/ in mysqld.1.err
SELECT * FROM t1;
ERROR 42000: Unknown storage engine 'InnoDB'
FOUND /InnoDB: Setting log file .*ib_logfile[0-9]+ size to/ in mysqld.1.err
FOUND /InnoDB: Renaming log file .*ib_logfile101 to .*ib_logfile0/ in mysqld.1.err
SELECT * FROM t1;
a
42

View file

@ -0,0 +1,29 @@
CREATE TABLE t(a INT PRIMARY KEY) ENGINE=InnoDB;
BEGIN;
INSERT INTO t VALUES(1),(2);
DELETE FROM t WHERE a=2;
# Normal MariaDB shutdown would roll back the above transaction.
# We want the transaction to remain open, so we will kill the server
# after ensuring that any non-transactional files are clean.
FLUSH TABLES;
# Ensure that the above incomplete transaction becomes durable.
SET GLOBAL innodb_flush_log_at_trx_commit=1;
BEGIN;
INSERT INTO t VALUES(0);
ROLLBACK;
# Kill and restart: --innodb-force-recovery=3
SELECT * FROM t;
a
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM t;
a
1
SELECT * FROM t;
a
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM t;
a
1
SELECT * FROM t;
a
DROP TABLE t;

View file

@ -33,10 +33,11 @@ CONSTRAINT `fk_crewRoleAssigned_crewId` FOREIGN KEY (`crew_id`) REFERENCES `repr
CONSTRAINT `fk_crewRoleAssigned_pilotId` FOREIGN KEY (`crew_id`) REFERENCES `repro`.`pilot` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB COMMENT="This is a comment about tables";
--echo # Restart mysqld --innodb_read_only=1
-- let $restart_parameters=--innodb-read-only=1
-- let $restart_parameters=--innodb-read-only
-- source include/restart_mysqld.inc
--error ER_OPEN_AS_READONLY
ALTER TABLE `repro`.`crew_role_assigned` COMMENT = 'innodb_read_only';
SHOW CREATE TABLE `repro`.`crew_role_assigned`;
-- let $restart_parameters=
@ -45,8 +46,7 @@ SHOW CREATE TABLE `repro`.`crew_role_assigned`;
ALTER TABLE `repro`.`crew_role_assigned` COMMENT = "This is a new comment about tables";
SHOW CREATE TABLE `repro`.`crew_role_assigned`;
--echo # Restart mysqld --innodb_read_only=1
-- let $restart_parameters=--innodb-read-only=1
-- let $restart_parameters=--innodb-read-only
-- source include/restart_mysqld.inc
#

View file

@ -6,7 +6,7 @@
--source include/not_embedded.inc
# Avoid CrashReporter popup on Mac
--source include/not_crashrep.inc
# innodb-force-recovery-crash needs debug
# DBUG_EXECUTE_IF is needed
--source include/have_debug.inc
if (`SELECT @@innodb_log_file_size = 1048576`) {
@ -17,7 +17,22 @@ if (`SELECT @@innodb_log_file_size = 1048576`) {
call mtr.add_suppression("InnoDB: Resizing redo log");
call mtr.add_suppression("InnoDB: Starting to delete and rewrite log files");
call mtr.add_suppression("InnoDB: New log files created");
# This message is output by 10.0 and 10.1, not by 10.2
call mtr.add_suppression("InnoDB: The log sequence number in the ibdata files is higher than the log sequence number in the ib_logfiles");
call mtr.add_suppression("InnoDB: The log sequence numbers [0-9]+ and [0-9]+ in ibdata files do not match the log sequence number [0-9]+ in the ib_logfiles");
call mtr.add_suppression("syntax error in innodb_log_group_home_dir");
call mtr.add_suppression("Plugin 'InnoDB' init function returned error");
call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE failed");
call mtr.add_suppression("InnoDB: Plugin initialization aborted");
call mtr.add_suppression("InnoDB: innodb_read_only prevents crash recovery");
call mtr.add_suppression("InnoDB: Are you sure you are using the right ib_logfiles");
call mtr.add_suppression("InnoDB: Cannot create log files in read-only mode");
call mtr.add_suppression("InnoDB: Only one log file found");
call mtr.add_suppression("InnoDB: Log file .*ib_logfile[01].* size");
call mtr.add_suppression("InnoDB: Unable to open .*ib_logfile0. to check native AIO read support");
# InnoDB shutdown after refused startup is not clean in 10.0 or 10.1!
call mtr.add_suppression("mysqld got signal 11");
call mtr.add_suppression("Attempting backtrace");
FLUSH TABLES;
--enable_query_log
@ -42,106 +57,122 @@ SELECT * FROM t1;
INSERT INTO t1 VALUES (123);
let MYSQLD_DATADIR= `select @@datadir`;
let SEARCH_ABORT = NOT FOUND;
let SEARCH_FILE= $MYSQLTEST_VARDIR/log/my_restart.err;
let $args=--innodb --unknown-option --loose-console --core-file > $SEARCH_FILE 2>&1;
let $crash=--innodb --unknown-option --loose-console > $SEARCH_FILE 2>&1 --innodb-force-recovery-crash;
let SEARCH_RANGE= -50000;
let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err;
BEGIN;
DELETE FROM t1;
--source include/kill_mysqld.inc
--error 2
--exec $MYSQLD_CMD $args --innodb-log-group-home-dir=foo\;bar
--let $restart_parameters= --innodb-log-group-home-dir=foo\;bar
--source include/start_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= syntax error in innodb_log_group_home_dir;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--echo --innodb-force-recovery-crash=1
--error 3
--exec $MYSQLD_CMD $crash=1
--let $restart_parameters= --debug=d,innodb_log_abort_1
--source include/restart_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--echo --innodb-force-recovery-crash=3
--error 3
--exec $MYSQLD_CMD $crash=3
--let $restart_parameters= --debug=d,innodb_log_abort_3
--source include/restart_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--error 2
--exec $MYSQLD_CMD $args --innodb-read-only
--let $restart_parameters= --innodb-read-only
--source include/restart_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= InnoDB: innodb_read_only prevents crash recovery;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--echo --innodb-force-recovery-crash=4
--error 3
--exec $MYSQLD_CMD $crash=4
--let $restart_parameters= --debug=d,innodb_log_abort_4
--source include/restart_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records;
--source include/search_pattern_in_file.inc
let SEARCH_PATTERN= InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--echo --innodb-force-recovery-crash=5
--error 3
--exec $MYSQLD_CMD $crash=5
--let $restart_parameters= --debug=d,innodb_log_abort_5
--source include/restart_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records;
--source include/search_pattern_in_file.inc
let SEARCH_PATTERN= InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--error 2
--exec $MYSQLD_CMD $args --innodb-read-only
--let $restart_parameters= --innodb-read-only
--source include/restart_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= InnoDB: innodb_read_only prevents crash recovery;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--echo --innodb-force-recovery-crash=6
--error 3
--exec $MYSQLD_CMD $crash=6
--let $restart_parameters= --debug=d,innodb_log_abort_6
--source include/restart_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records;
--source include/search_pattern_in_file.inc
let SEARCH_PATTERN= InnoDB: Resizing redo log from 3\*[0-9]+ to 2\*[0-9]+ pages;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--echo --innodb-force-recovery-crash=7
--error 3
--exec $MYSQLD_CMD $crash=7
# this crashes right after deleting all log files
--remove_file $SEARCH_FILE
--error 2
--exec $MYSQLD_CMD $args --innodb-read-only
--let $restart_parameters= --debug=d,innodb_log_abort_7
--source include/restart_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
# this aborts right after deleting all log files
--let $restart_parameters= --innodb-read-only
--source include/restart_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= InnoDB: Cannot create log files in read-only mode;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--echo --innodb-force-recovery-crash=8
--error 3
--exec $MYSQLD_CMD $crash=8
--let $restart_parameters= --debug=d,innodb_log_abort_8
--source include/restart_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= InnoDB: Setting log file .*ib_logfile[0-9]+ size to;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--echo --innodb-force-recovery-crash=9
--error 3
--exec $MYSQLD_CMD $crash=9
--let $restart_parameters= --debug=d,innodb_log_abort_9
--source include/restart_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= InnoDB: Setting log file .*ib_logfile[0-9]+ size to;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--source include/shutdown_mysqld.inc
# We should have perfectly synced files here.
# Rename the log files, and trigger an error in recovery.
--move_file $MYSQLD_DATADIR/ib_logfile101 $MYSQLD_DATADIR/ib_logfile0
--move_file $MYSQLD_DATADIR/ib_logfile1 $MYSQLD_DATADIR/ib_logfile1_hidden
--error 2
--exec $MYSQLD_CMD $args
--let $restart_parameters=
--source include/start_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= InnoDB: Only one log file found;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--move_file $MYSQLD_DATADIR/ib_logfile0 $MYSQLD_DATADIR/ib_logfile101
perl;
@ -149,11 +180,12 @@ die unless open(FILE, ">$ENV{MYSQLD_DATADIR}/ib_logfile0");
print FILE "garbage";
close(FILE);
EOF
--error 2
--exec $MYSQLD_CMD $args
--source include/restart_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= InnoDB: Log file .*ib_logfile0 size 7 is not a multiple of innodb_page_size;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--remove_file $MYSQLD_DATADIR/ib_logfile0
--move_file $MYSQLD_DATADIR/ib_logfile101 $MYSQLD_DATADIR/ib_logfile0
@ -163,26 +195,28 @@ print FILE "junkfill" x 131072;
close(FILE);
EOF
--error 2
--exec $MYSQLD_CMD $args
--source include/restart_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= InnoDB: Log file .*ib_logfile1 is of different size 1048576 bytes than other log files;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--remove_file $MYSQLD_DATADIR/ib_logfile1
--move_file $MYSQLD_DATADIR/ib_logfile0 $MYSQLD_DATADIR/ib_logfile101
--move_file $MYSQLD_DATADIR/ib_logfile1_hidden $MYSQLD_DATADIR/ib_logfile1
--echo --innodb-force-recovery-crash=10
--error 3
--exec $MYSQLD_CMD $crash=10
--let $restart_parameters= --debug=d,innodb_log_abort_10
--source include/restart_mysqld.inc
--error ER_UNKNOWN_STORAGE_ENGINE
SELECT * FROM t1;
let SEARCH_PATTERN= InnoDB: Setting log file .*ib_logfile[0-9]+ size to;
--source include/search_pattern_in_file.inc
let SEARCH_PATTERN= InnoDB: Renaming log file .*ib_logfile101 to .*ib_logfile0;
--source include/search_pattern_in_file.inc
--remove_file $SEARCH_FILE
--let $restart_parameters=
--source include/start_mysqld.inc
--source include/restart_mysqld.inc
SELECT * FROM t1;
DROP TABLE t1;

View file

@ -0,0 +1,36 @@
--source include/have_innodb.inc
# need to restart server
--source include/not_embedded.inc
--connect(con1, localhost, root)
CREATE TABLE t(a INT PRIMARY KEY) ENGINE=InnoDB;
BEGIN;
# Generate insert_undo log.
INSERT INTO t VALUES(1),(2);
# Generate update_undo log.
DELETE FROM t WHERE a=2;
--connection default
--echo # Normal MariaDB shutdown would roll back the above transaction.
--echo # We want the transaction to remain open, so we will kill the server
--echo # after ensuring that any non-transactional files are clean.
FLUSH TABLES;
--echo # Ensure that the above incomplete transaction becomes durable.
SET GLOBAL innodb_flush_log_at_trx_commit=1;
BEGIN;
INSERT INTO t VALUES(0);
ROLLBACK;
--let $restart_parameters= --innodb-force-recovery=3
--source include/kill_and_restart_mysqld.inc
--disconnect con1
SELECT * FROM t;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM t;
--let $restart_parameters= --innodb-read-only
--source include/restart_mysqld.inc
SELECT * FROM t;
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM t;
--let $restart_parameters=
--source include/restart_mysqld.inc
SELECT * FROM t;
DROP TABLE t;

View file

@ -31,6 +31,7 @@ INSERT INTO `sql_1` VALUES(1,'one');
--echo
--echo # Verify that the tables are treated as normal tables .
--echo
--sorted_result
SELECT object_type, object_schema, object_name
FROM performance_schema.objects_summary_global_by_type
WHERE object_schema="test";

View file

@ -1,33 +0,0 @@
select @@global.innodb_force_recovery_crash in (0, 1);
@@global.innodb_force_recovery_crash in (0, 1)
1
select @@global.innodb_force_recovery_crash;
@@global.innodb_force_recovery_crash
0
select @@session.innodb_force_recovery_crash;
ERROR HY000: Variable 'innodb_force_recovery_crash' is a GLOBAL variable
show global variables like 'innodb_force_recovery_crash';
Variable_name Value
innodb_force_recovery_crash 0
show session variables like 'innodb_force_recovery_crash';
Variable_name Value
innodb_force_recovery_crash 0
select * from information_schema.global_variables where variable_name='innodb_force_recovery_crash';
VARIABLE_NAME VARIABLE_VALUE
INNODB_FORCE_RECOVERY_CRASH 0
select * from information_schema.session_variables where variable_name='innodb_force_recovery_crash';
VARIABLE_NAME VARIABLE_VALUE
INNODB_FORCE_RECOVERY_CRASH 0
set global innodb_force_recovery_crash=1;
ERROR HY000: Variable 'innodb_force_recovery_crash' is a read only variable
set global innodb_force_recovery_crash=0;
ERROR HY000: Variable 'innodb_force_recovery_crash' is a read only variable
select @@global.innodb_force_recovery_crash;
@@global.innodb_force_recovery_crash
0
set session innodb_force_recovery_crash='some';
ERROR HY000: Variable 'innodb_force_recovery_crash' is a read only variable
set @@session.innodb_force_recovery_crash='some';
ERROR HY000: Variable 'innodb_force_recovery_crash' is a read only variable
set global innodb_force_recovery_crash='some';
ERROR HY000: Variable 'innodb_force_recovery_crash' is a read only variable

View file

@ -1055,20 +1055,6 @@ NUMERIC_BLOCK_SIZE 0
ENUM_VALUE_LIST NULL
READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME INNODB_FORCE_RECOVERY_CRASH
SESSION_VALUE NULL
GLOBAL_VALUE 0
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 0
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Kills the server during crash recovery.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 10
NUMERIC_BLOCK_SIZE 0
ENUM_VALUE_LIST NULL
READ_ONLY YES
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME INNODB_FT_AUX_TABLE
SESSION_VALUE NULL
GLOBAL_VALUE

View file

@ -1,28 +0,0 @@
--source include/have_innodb.inc
--source include/have_debug.inc
#
# exists as global only
#
select @@global.innodb_force_recovery_crash in (0, 1);
select @@global.innodb_force_recovery_crash;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
select @@session.innodb_force_recovery_crash;
show global variables like 'innodb_force_recovery_crash';
show session variables like 'innodb_force_recovery_crash';
select * from information_schema.global_variables where variable_name='innodb_force_recovery_crash';
select * from information_schema.session_variables where variable_name='innodb_force_recovery_crash';
# show that it's read-only
#
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
set global innodb_force_recovery_crash=1;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
set global innodb_force_recovery_crash=0;
select @@global.innodb_force_recovery_crash;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
set session innodb_force_recovery_crash='some';
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
set @@session.innodb_force_recovery_crash='some';
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
set global innodb_force_recovery_crash='some';

View file

@ -19360,13 +19360,6 @@ static MYSQL_SYSVAR_ULONG(force_recovery, srv_force_recovery,
"Helps to save your data in case the disk image of the database becomes corrupt.",
NULL, NULL, 0, 0, 6, 0);
#ifndef DBUG_OFF
static MYSQL_SYSVAR_ULONG(force_recovery_crash, srv_force_recovery_crash,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Kills the server during crash recovery.",
NULL, NULL, 0, 0, 10, 0);
#endif /* !DBUG_OFF */
static MYSQL_SYSVAR_ULONG(page_size, srv_page_size,
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
"Page size to use for all InnoDB tablespaces.",
@ -19957,9 +19950,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(flush_log_at_trx_commit),
MYSQL_SYSVAR(flush_method),
MYSQL_SYSVAR(force_recovery),
#ifndef DBUG_OFF
MYSQL_SYSVAR(force_recovery_crash),
#endif /* !DBUG_OFF */
MYSQL_SYSVAR(ft_cache_size),
MYSQL_SYSVAR(ft_total_cache_size),
MYSQL_SYSVAR(ft_result_cache_limit),

View file

@ -3,7 +3,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, 2009, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation
Copyright (c) 2013, 2017, MariaDB Corporation Ab. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@ -439,9 +439,6 @@ extern double srv_adaptive_flushing_lwm;
extern ulong srv_flushing_avg_loops;
extern ulong srv_force_recovery;
#ifndef DBUG_OFF
extern ulong srv_force_recovery_crash;
#endif /* !DBUG_OFF */
extern ulint srv_fast_shutdown; /*!< If this is 1, do not do a
purge and index buffer merge.
@ -889,24 +886,17 @@ ulint
srv_get_task_queue_length(void);
/*===========================*/
/*********************************************************************//**
Releases threads of the type given from suspension in the thread table.
NOTE! The server mutex has to be reserved by the caller!
@return number of threads released: this may be less than n if not
enough threads were suspended at the moment */
UNIV_INTERN
ulint
srv_release_threads(
/*================*/
enum srv_thread_type type, /*!< in: thread type */
ulint n); /*!< in: number of threads to release */
/** Ensure that a given number of threads of the type given are running
(or are already terminated).
@param[in] type thread type
@param[in] n number of threads that have to run */
void
srv_release_threads(enum srv_thread_type type, ulint n);
/**********************************************************************//**
Wakeup the purge threads. */
/** Wake up the purge threads. */
UNIV_INTERN
void
srv_purge_wakeup(void);
/*==================*/
srv_purge_wakeup();
/** Status variables to be passed to MySQL */
struct export_var_t{

View file

@ -3246,7 +3246,6 @@ logs_empty_and_mark_files_at_shutdown(void)
lsn_t lsn;
ulint arch_log_no;
ulint count = 0;
ulint total_trx;
ulint pending_io;
ibool server_busy;
@ -3279,10 +3278,9 @@ loop:
shutdown, because the InnoDB layer may have committed or
prepared transactions and we don't want to lose them. */
total_trx = trx_sys_any_active_transactions();
if (total_trx > 0) {
if (ulint total_trx = srv_was_started && !srv_read_only_mode
&& srv_force_recovery < SRV_FORCE_NO_TRX_UNDO
? trx_sys_any_active_transactions() : 0) {
if (srv_print_verbose_log && count > 600) {
ib_logf(IB_LOG_LEVEL_INFO,
"Waiting for %lu active transactions to finish",

View file

@ -3,7 +3,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
Copyright (c) 2013, 2017, MariaDB Corporation Ab. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@ -344,11 +344,6 @@ starting from SRV_FORCE_IGNORE_CORRUPT, so that data can be recovered
by SELECT or mysqldump. When this is nonzero, we do not allow any user
modifications to the data. */
UNIV_INTERN ulong srv_force_recovery;
#ifndef DBUG_OFF
/** Inject a crash at different steps of the recovery process.
This is for testing and debugging only. */
UNIV_INTERN ulong srv_force_recovery_crash;
#endif /* !DBUG_OFF */
/** Print all user-level transactions deadlocks to mysqld stderr */
@ -840,7 +835,6 @@ srv_suspend_thread_low(
/*===================*/
srv_slot_t* slot) /*!< in/out: thread slot */
{
ut_ad(!srv_read_only_mode);
ut_ad(srv_sys_mutex_own());
@ -898,34 +892,71 @@ srv_suspend_thread(
return(sig_count);
}
/*********************************************************************//**
Releases threads of the type given from suspension in the thread table.
NOTE! The server mutex has to be reserved by the caller!
@return number of threads released: this may be less than n if not
enough threads were suspended at the moment. */
UNIV_INTERN
ulint
srv_release_threads(
/*================*/
srv_thread_type type, /*!< in: thread type */
ulint n) /*!< in: number of threads to release */
/** Resume the calling thread.
@param[in,out] slot thread slot
@param[in] sig_count signal count (if wait)
@param[in] wait whether to wait for the event
@param[in] timeout_usec timeout in microseconds (0=infinite)
@return whether the wait timed out */
static
bool
srv_resume_thread(srv_slot_t* slot, int64_t sig_count = 0, bool wait = true,
ulint timeout_usec = 0)
{
ulint i;
ulint count = 0;
bool timeout;
ut_ad(!srv_read_only_mode);
ut_ad(slot->in_use);
ut_ad(slot->suspended);
if (!wait) {
timeout = false;
} else if (timeout_usec) {
timeout = OS_SYNC_TIME_EXCEEDED == os_event_wait_time_low(
slot->event, timeout_usec, sig_count);
} else {
timeout = false;
os_event_wait_low(slot->event, sig_count);
}
srv_sys_mutex_enter();
ut_ad(slot->in_use);
ut_ad(slot->suspended);
slot->suspended = FALSE;
++srv_sys->n_threads_active[slot->type];
srv_sys_mutex_exit();
return(timeout);
}
/** Ensure that a given number of threads of the type given are running
(or are already terminated).
@param[in] type thread type
@param[in] n number of threads that have to run */
void
srv_release_threads(enum srv_thread_type type, ulint n)
{
ulint running;
ut_ad(srv_thread_type_validate(type));
ut_ad(n > 0);
srv_sys_mutex_enter();
do {
running = 0;
for (i = 0; i < srv_sys->n_sys_threads; i++) {
srv_slot_t* slot;
srv_sys_mutex_enter();
slot = &srv_sys->sys_threads[i];
for (ulint i = 0; i < srv_sys->n_sys_threads; i++) {
srv_slot_t* slot = &srv_sys->sys_threads[i];
if (slot->in_use
&& srv_slot_get_type(slot) == type
&& slot->suspended) {
if (!slot->in_use || srv_slot_get_type(slot) != type) {
continue;
} else if (!slot->suspended) {
if (++running >= n) {
break;
}
continue;
}
switch (type) {
case SRV_NONE:
@ -955,21 +986,11 @@ srv_release_threads(
break;
}
slot->suspended = FALSE;
++srv_sys->n_threads_active[type];
os_event_set(slot->event);
if (++count == n) {
break;
}
}
}
srv_sys_mutex_exit();
return(count);
srv_sys_mutex_exit();
} while (running && running < n);
}
/*********************************************************************//**
@ -982,11 +1003,8 @@ srv_free_slot(
{
srv_sys_mutex_enter();
if (!slot->suspended) {
/* Mark the thread as inactive. */
srv_suspend_thread_low(slot);
}
/* Mark the thread as inactive. */
srv_suspend_thread_low(slot);
/* Free the slot for reuse. */
ut_ad(slot->in_use);
slot->in_use = FALSE;
@ -2057,15 +2075,7 @@ srv_active_wake_master_thread(void)
if (slot->in_use) {
ut_a(srv_slot_get_type(slot) == SRV_MASTER);
if (slot->suspended) {
slot->suspended = FALSE;
++srv_sys->n_threads_active[SRV_MASTER];
os_event_set(slot->event);
}
os_event_set(slot->event);
}
srv_sys_mutex_exit();
@ -2537,7 +2547,7 @@ suspend_thread:
manual also mentions this string in several places. */
srv_main_thread_op_info = "waiting for server activity";
os_event_wait(slot->event);
srv_resume_thread(slot);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL);
@ -2649,8 +2659,7 @@ DECLARE_THREAD(srv_worker_thread)(
do {
srv_suspend_thread(slot);
os_event_wait(slot->event);
srv_resume_thread(slot);
if (srv_task_execute()) {
@ -2786,8 +2795,6 @@ srv_purge_coordinator_suspend(
ib_int64_t sig_count = srv_suspend_thread(slot);
do {
ulint ret;
rw_lock_x_lock(&purge_sys->latch);
purge_sys->running = false;
@ -2796,32 +2803,11 @@ srv_purge_coordinator_suspend(
/* We don't wait right away on the the non-timed wait because
we want to signal the thread that wants to suspend purge. */
if (stop) {
os_event_wait_low(slot->event, sig_count);
ret = 0;
} else if (rseg_history_len <= trx_sys->rseg_history_len) {
ret = os_event_wait_time_low(
slot->event, SRV_PURGE_MAX_TIMEOUT, sig_count);
} else {
/* We don't want to waste time waiting, if the
history list increased by the time we got here,
unless purge has been stopped. */
ret = 0;
}
srv_sys_mutex_enter();
/* The thread can be in state !suspended after the timeout
but before this check if another thread sent a wakeup signal. */
if (slot->suspended) {
slot->suspended = FALSE;
++srv_sys->n_threads_active[slot->type];
ut_a(srv_sys->n_threads_active[slot->type] == 1);
}
srv_sys_mutex_exit();
const bool wait = stop
|| rseg_history_len <= trx_sys->rseg_history_len;
const bool timeout = srv_resume_thread(
slot, sig_count, wait,
stop ? 0 : SRV_PURGE_MAX_TIMEOUT);
sig_count = srv_suspend_thread(slot);
@ -2833,6 +2819,19 @@ srv_purge_coordinator_suspend(
if (!stop) {
ut_a(purge_sys->n_stop == 0);
purge_sys->running = true;
if (timeout
&& rseg_history_len == trx_sys->rseg_history_len
&& trx_sys->rseg_history_len < 5000) {
/* No new records were added since the
wait started. Simply wait for new
records. The magic number 5000 is an
approximation for the case where we
have cached UNDO log records which
prevent truncate of the UNDO
segments. */
stop = true;
}
} else {
ut_a(purge_sys->n_stop > 0);
@ -2841,33 +2840,9 @@ srv_purge_coordinator_suspend(
}
rw_lock_x_unlock(&purge_sys->latch);
if (ret == OS_SYNC_TIME_EXCEEDED) {
/* No new records added since wait started then simply
wait for new records. The magic number 5000 is an
approximation for the case where we have cached UNDO
log records which prevent truncate of the UNDO
segments. */
if (rseg_history_len == trx_sys->rseg_history_len
&& trx_sys->rseg_history_len < 5000) {
stop = true;
}
}
} while (stop);
srv_sys_mutex_enter();
if (slot->suspended) {
slot->suspended = FALSE;
++srv_sys->n_threads_active[slot->type];
ut_a(srv_sys->n_threads_active[slot->type] == 1);
}
srv_sys_mutex_exit();
srv_resume_thread(slot, 0, false);
}
/*********************************************************************//**
@ -2920,8 +2895,9 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
srv_purge_coordinator_suspend(slot, rseg_history_len);
}
ut_ad(!slot->suspended);
if (srv_purge_should_exit(n_total_purged)) {
ut_a(!slot->suspended);
break;
}
@ -3032,12 +3008,10 @@ srv_get_task_queue_length(void)
return(n_tasks);
}
/**********************************************************************//**
Wakeup the purge threads. */
/** Wake up the purge threads. */
UNIV_INTERN
void
srv_purge_wakeup(void)
/*==================*/
srv_purge_wakeup()
{
ut_ad(!srv_read_only_mode);
@ -3052,4 +3026,3 @@ srv_purge_wakeup(void)
}
}
}

View file

@ -593,19 +593,6 @@ create_log_file(
/** Initial number of the first redo log file */
#define INIT_LOG_FILE0 (SRV_N_LOG_FILES_MAX + 1)
#ifdef DBUG_OFF
# define RECOVERY_CRASH(x) do {} while(0)
#else
# define RECOVERY_CRASH(x) do { \
if (srv_force_recovery_crash == x) { \
fprintf(stderr, "innodb_force_recovery_crash=%lu\n", \
srv_force_recovery_crash); \
fflush(stderr); \
exit(3); \
} \
} while (0)
#endif
/*********************************************************************//**
Creates all log files.
@return DB_SUCCESS or error code */
@ -646,13 +633,14 @@ create_log_files(
file should be recoverable. The buffer
pool was clean, and we can simply create
all log files from the scratch. */
RECOVERY_CRASH(6);
DBUG_EXECUTE_IF("innodb_log_abort_6",
return(DB_ERROR););
}
}
ut_ad(!buf_pool_check_no_pending_io());
RECOVERY_CRASH(7);
DBUG_EXECUTE_IF("innodb_log_abort_7", return(DB_ERROR););
for (unsigned i = 0; i < srv_n_log_files; i++) {
sprintf(logfilename + dirnamelen,
@ -665,7 +653,7 @@ create_log_files(
}
}
RECOVERY_CRASH(8);
DBUG_EXECUTE_IF("innodb_log_abort_8", return(DB_ERROR););
/* We did not create the first log file initially as
ib_logfile0, so that crash recovery cannot find it until it
@ -711,10 +699,16 @@ create_log_files(
return(DB_SUCCESS);
}
/*********************************************************************//**
Renames the first log file. */
/** Rename the first redo log file.
@param[in,out] logfilename buffer for the log file name
@param[in] dirnamelen length of the directory path
@param[in] lsn FIL_PAGE_FILE_FLUSH_LSN value
@param[in,out] logfile0 name of the first log file
@return error code
@retval DB_SUCCESS on successful operation */
MY_ATTRIBUTE((warn_unused_result, nonnull))
static
void
dberr_t
create_log_files_rename(
/*====================*/
char* logfilename, /*!< in/out: buffer for log file name */
@ -725,6 +719,9 @@ create_log_files_rename(
/* If innodb_flush_method=O_DSYNC,
we need to explicitly flush the log buffers. */
fil_flush(SRV_LOG_SPACE_FIRST_ID);
DBUG_EXECUTE_IF("innodb_log_abort_9", return(DB_ERROR););
/* Close the log files, so that we can rename
the first one. */
fil_close_log_files(false);
@ -733,26 +730,28 @@ create_log_files_rename(
checkpoint has been created. */
sprintf(logfilename + dirnamelen, "ib_logfile%u", 0);
RECOVERY_CRASH(9);
ib_logf(IB_LOG_LEVEL_INFO,
"Renaming log file %s to %s", logfile0, logfilename);
mutex_enter(&log_sys->mutex);
ut_ad(strlen(logfile0) == 2 + strlen(logfilename));
ibool success = os_file_rename(
innodb_file_log_key, logfile0, logfilename);
ut_a(success);
RECOVERY_CRASH(10);
dberr_t err = os_file_rename(
innodb_file_log_key, logfile0, logfilename)
? DB_SUCCESS : DB_ERROR;
/* Replace the first file with ib_logfile0. */
strcpy(logfile0, logfilename);
mutex_exit(&log_sys->mutex);
fil_open_log_and_system_tablespace_files();
DBUG_EXECUTE_IF("innodb_log_abort_10", err = DB_ERROR;);
ib_logf(IB_LOG_LEVEL_WARN, "New log files created, LSN=" LSN_PF, lsn);
if (err == DB_SUCCESS) {
fil_open_log_and_system_tablespace_files();
ib_logf(IB_LOG_LEVEL_WARN,
"New log files created, LSN=" LSN_PF, lsn);
}
return(err);
}
/*********************************************************************//**
@ -2221,14 +2220,18 @@ innobase_start_or_create_for_mysql(void)
dirnamelen, max_flushed_lsn,
logfile0);
if (err == DB_SUCCESS) {
err = create_log_files_rename(
logfilename,
dirnamelen,
max_flushed_lsn,
logfile0);
}
if (err != DB_SUCCESS) {
return(err);
}
create_log_files_rename(
logfilename, dirnamelen,
max_flushed_lsn, logfile0);
/* Suppress the message about
crash recovery. */
max_flushed_lsn = min_flushed_lsn
@ -2396,8 +2399,12 @@ files_checked:
fil_flush_file_spaces(FIL_TABLESPACE);
create_log_files_rename(logfilename, dirnamelen,
max_flushed_lsn, logfile0);
err = create_log_files_rename(logfilename, dirnamelen,
max_flushed_lsn, logfile0);
if (err != DB_SUCCESS) {
return(err);
}
#ifdef UNIV_LOG_ARCHIVE
} else if (srv_archive_recovery) {
@ -2629,7 +2636,8 @@ files_checked:
ULINT_MAX, LSN_MAX, NULL);
ut_a(success);
RECOVERY_CRASH(1);
DBUG_EXECUTE_IF("innodb_log_abort_1",
return(DB_ERROR););
min_flushed_lsn = max_flushed_lsn = log_get_lsn();
@ -2644,8 +2652,6 @@ files_checked:
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
RECOVERY_CRASH(2);
/* Flush the old log files. */
log_buffer_flush_to_disk();
/* If innodb_flush_method=O_DSYNC,
@ -2660,21 +2666,27 @@ files_checked:
ut_d(recv_no_log_write = TRUE);
ut_ad(!buf_pool_check_no_pending_io());
RECOVERY_CRASH(3);
DBUG_EXECUTE_IF("innodb_log_abort_3",
return(DB_ERROR););
/* Stamp the LSN to the data files. */
fil_write_flushed_lsn_to_data_files(
max_flushed_lsn, 0);
fil_flush_file_spaces(FIL_TABLESPACE);
DBUG_EXECUTE_IF("innodb_log_abort_4", err = DB_ERROR;);
RECOVERY_CRASH(4);
if (err != DB_SUCCESS) {
return(err);
}
fil_flush_file_spaces(FIL_TABLESPACE);
/* Close and free the redo log files, so that
we can replace them. */
fil_close_log_files(true);
RECOVERY_CRASH(5);
DBUG_EXECUTE_IF("innodb_log_abort_5",
return(DB_ERROR););
/* Free the old log file space. */
log_group_close_all();
@ -2688,12 +2700,15 @@ files_checked:
dirnamelen, max_flushed_lsn,
logfile0);
if (err == DB_SUCCESS) {
err = create_log_files_rename(
logfilename, dirnamelen,
max_flushed_lsn, logfile0);
}
if (err != DB_SUCCESS) {
return(err);
}
create_log_files_rename(logfilename, dirnamelen,
max_flushed_lsn, logfile0);
}
srv_startup_is_before_trx_rollback_phase = FALSE;

View file

@ -1322,7 +1322,9 @@ trx_sys_close(void)
ut_a(UT_LIST_GET_LEN(trx_sys->ro_trx_list) == 0);
/* Only prepared transactions may be left in the system. Free them. */
ut_a(UT_LIST_GET_LEN(trx_sys->rw_trx_list) == trx_sys->n_prepared_trx);
ut_a(UT_LIST_GET_LEN(trx_sys->rw_trx_list) == trx_sys->n_prepared_trx
|| srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
while ((trx = UT_LIST_GET_FIRST(trx_sys->rw_trx_list)) != NULL) {
trx_free_prepared(trx);

View file

@ -312,7 +312,11 @@ trx_free_prepared(
/*==============*/
trx_t* trx) /*!< in, own: trx object */
{
ut_a(trx_state_eq(trx, TRX_STATE_PREPARED));
ut_a(trx_state_eq(trx, TRX_STATE_PREPARED)
|| (trx_state_eq(trx, TRX_STATE_ACTIVE)
&& trx->is_recovered
&& (srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO)));
ut_a(trx->magic_n == TRX_MAGIC_N);
lock_trx_release_locks(trx);

View file

@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2014, 2017, MariaDB Corporation. 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
@ -2011,13 +2012,37 @@ trx_undo_free_prepared(
ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS);
if (trx->update_undo) {
ut_a(trx->update_undo->state == TRX_UNDO_PREPARED);
switch (trx->update_undo->state) {
case TRX_UNDO_PREPARED:
break;
case TRX_UNDO_ACTIVE:
/* lock_trx_release_locks() assigns
trx->is_recovered=false */
ut_a(srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
break;
default:
ut_error;
}
UT_LIST_REMOVE(undo_list, trx->rseg->update_undo_list,
trx->update_undo);
trx_undo_mem_free(trx->update_undo);
}
if (trx->insert_undo) {
ut_a(trx->insert_undo->state == TRX_UNDO_PREPARED);
switch (trx->insert_undo->state) {
case TRX_UNDO_PREPARED:
break;
case TRX_UNDO_ACTIVE:
/* lock_trx_release_locks() assigns
trx->is_recovered=false */
ut_a(srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
break;
default:
ut_error;
}
UT_LIST_REMOVE(undo_list, trx->rseg->insert_undo_list,
trx->insert_undo);
trx_undo_mem_free(trx->insert_undo);

View file

@ -20777,13 +20777,6 @@ static MYSQL_SYSVAR_ULONG(force_recovery, srv_force_recovery,
"Helps to save your data in case the disk image of the database becomes corrupt.",
NULL, NULL, 0, 0, 6, 0);
#ifndef DBUG_OFF
static MYSQL_SYSVAR_ULONG(force_recovery_crash, srv_force_recovery_crash,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Kills the server during crash recovery.",
NULL, NULL, 0, 0, 10, 0);
#endif /* !DBUG_OFF */
static MYSQL_SYSVAR_ULONG(page_size, srv_page_size,
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
"Page size to use for all InnoDB tablespaces.",
@ -21443,9 +21436,6 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(use_global_flush_log_at_trx_commit),
MYSQL_SYSVAR(flush_method),
MYSQL_SYSVAR(force_recovery),
#ifndef DBUG_OFF
MYSQL_SYSVAR(force_recovery_crash),
#endif /* !DBUG_OFF */
MYSQL_SYSVAR(ft_cache_size),
MYSQL_SYSVAR(ft_total_cache_size),
MYSQL_SYSVAR(ft_result_cache_limit),

View file

@ -3,7 +3,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2008, 2009, Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation
Copyright (c) 2013, 2017, MariaDB Corporation Ab. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@ -509,9 +509,6 @@ extern double srv_adaptive_flushing_lwm;
extern ulong srv_flushing_avg_loops;
extern ulong srv_force_recovery;
#ifndef DBUG_OFF
extern ulong srv_force_recovery_crash;
#endif /* !DBUG_OFF */
extern ulint srv_fast_shutdown; /*!< If this is 1, do not do a
purge and index buffer merge.
@ -1073,24 +1070,17 @@ ulint
srv_get_task_queue_length(void);
/*===========================*/
/*********************************************************************//**
Releases threads of the type given from suspension in the thread table.
NOTE! The server mutex has to be reserved by the caller!
@return number of threads released: this may be less than n if not
enough threads were suspended at the moment */
UNIV_INTERN
ulint
srv_release_threads(
/*================*/
enum srv_thread_type type, /*!< in: thread type */
ulint n); /*!< in: number of threads to release */
/** Ensure that a given number of threads of the type given are running
(or are already terminated).
@param[in] type thread type
@param[in] n number of threads that have to run */
void
srv_release_threads(enum srv_thread_type type, ulint n);
/**********************************************************************//**
Wakeup the purge threads. */
/** Wake up the purge threads. */
UNIV_INTERN
void
srv_purge_wakeup(void);
/*==================*/
srv_purge_wakeup();
/** Status variables to be passed to MySQL */
struct export_var_t{

View file

@ -3560,7 +3560,6 @@ logs_empty_and_mark_files_at_shutdown(void)
lsn_t lsn;
lsn_t tracked_lsn;
ulint count = 0;
ulint total_trx;
ulint pending_io;
ibool server_busy;
@ -3597,10 +3596,9 @@ loop:
shutdown, because the InnoDB layer may have committed or
prepared transactions and we don't want to lose them. */
total_trx = trx_sys_any_active_transactions();
if (total_trx > 0) {
if (ulint total_trx = srv_was_started && !srv_read_only_mode
&& srv_force_recovery < SRV_FORCE_NO_TRX_UNDO
? trx_sys_any_active_transactions() : 0) {
if (srv_print_verbose_log && count > 600) {
ib_logf(IB_LOG_LEVEL_INFO,
"Waiting for %lu active transactions to finish",

View file

@ -3,7 +3,7 @@
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2008, 2009 Google Inc.
Copyright (c) 2009, Percona Inc.
Copyright (c) 2013, 2017, MariaDB Corporation.
Copyright (c) 2013, 2017, MariaDB Corporation Ab. All Rights Reserved.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@ -474,11 +474,6 @@ starting from SRV_FORCE_IGNORE_CORRUPT, so that data can be recovered
by SELECT or mysqldump. When this is nonzero, we do not allow any user
modifications to the data. */
UNIV_INTERN ulong srv_force_recovery;
#ifndef DBUG_OFF
/** Inject a crash at different steps of the recovery process.
This is for testing and debugging only. */
UNIV_INTERN ulong srv_force_recovery_crash;
#endif /* !DBUG_OFF */
/** Print all user-level transactions deadlocks to mysqld stderr */
@ -998,7 +993,6 @@ srv_suspend_thread_low(
/*===================*/
srv_slot_t* slot) /*!< in/out: thread slot */
{
ut_ad(!srv_read_only_mode);
ut_ad(srv_sys_mutex_own());
@ -1056,34 +1050,71 @@ srv_suspend_thread(
return(sig_count);
}
/*********************************************************************//**
Releases threads of the type given from suspension in the thread table.
NOTE! The server mutex has to be reserved by the caller!
@return number of threads released: this may be less than n if not
enough threads were suspended at the moment. */
UNIV_INTERN
ulint
srv_release_threads(
/*================*/
srv_thread_type type, /*!< in: thread type */
ulint n) /*!< in: number of threads to release */
/** Resume the calling thread.
@param[in,out] slot thread slot
@param[in] sig_count signal count (if wait)
@param[in] wait whether to wait for the event
@param[in] timeout_usec timeout in microseconds (0=infinite)
@return whether the wait timed out */
static
bool
srv_resume_thread(srv_slot_t* slot, int64_t sig_count = 0, bool wait = true,
ulint timeout_usec = 0)
{
ulint i;
ulint count = 0;
bool timeout;
ut_ad(!srv_read_only_mode);
ut_ad(slot->in_use);
ut_ad(slot->suspended);
if (!wait) {
timeout = false;
} else if (timeout_usec) {
timeout = OS_SYNC_TIME_EXCEEDED == os_event_wait_time_low(
slot->event, timeout_usec, sig_count);
} else {
timeout = false;
os_event_wait_low(slot->event, sig_count);
}
srv_sys_mutex_enter();
ut_ad(slot->in_use);
ut_ad(slot->suspended);
slot->suspended = FALSE;
++srv_sys->n_threads_active[slot->type];
srv_sys_mutex_exit();
return(timeout);
}
/** Ensure that a given number of threads of the type given are running
(or are already terminated).
@param[in] type thread type
@param[in] n number of threads that have to run */
void
srv_release_threads(enum srv_thread_type type, ulint n)
{
ulint running;
ut_ad(srv_thread_type_validate(type));
ut_ad(n > 0);
srv_sys_mutex_enter();
do {
running = 0;
for (i = 0; i < srv_sys->n_sys_threads; i++) {
srv_slot_t* slot;
srv_sys_mutex_enter();
slot = &srv_sys->sys_threads[i];
for (ulint i = 0; i < srv_sys->n_sys_threads; i++) {
srv_slot_t* slot = &srv_sys->sys_threads[i];
if (slot->in_use
&& srv_slot_get_type(slot) == type
&& slot->suspended) {
if (!slot->in_use || srv_slot_get_type(slot) != type) {
continue;
} else if (!slot->suspended) {
if (++running >= n) {
break;
}
continue;
}
switch (type) {
case SRV_NONE:
@ -1113,21 +1144,11 @@ srv_release_threads(
break;
}
slot->suspended = FALSE;
++srv_sys->n_threads_active[type];
os_event_set(slot->event);
if (++count == n) {
break;
}
}
}
srv_sys_mutex_exit();
return(count);
srv_sys_mutex_exit();
} while (running && running < n);
}
/*********************************************************************//**
@ -1140,11 +1161,8 @@ srv_free_slot(
{
srv_sys_mutex_enter();
if (!slot->suspended) {
/* Mark the thread as inactive. */
srv_suspend_thread_low(slot);
}
/* Mark the thread as inactive. */
srv_suspend_thread_low(slot);
/* Free the slot for reuse. */
ut_ad(slot->in_use);
slot->in_use = FALSE;
@ -2686,15 +2704,7 @@ srv_active_wake_master_thread(void)
if (slot->in_use) {
ut_a(srv_slot_get_type(slot) == SRV_MASTER);
if (slot->suspended) {
slot->suspended = FALSE;
++srv_sys->n_threads_active[SRV_MASTER];
os_event_set(slot->event);
}
os_event_set(slot->event);
}
srv_sys_mutex_exit();
@ -3221,7 +3231,7 @@ suspend_thread:
manual also mentions this string in several places. */
srv_main_thread_op_info = "waiting for server activity";
os_event_wait(slot->event);
srv_resume_thread(slot);
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
os_thread_exit(NULL);
@ -3343,8 +3353,7 @@ DECLARE_THREAD(srv_worker_thread)(
do {
srv_suspend_thread(slot);
os_event_wait(slot->event);
srv_resume_thread(slot);
srv_current_thread_priority = srv_purge_thread_priority;
@ -3484,8 +3493,6 @@ srv_purge_coordinator_suspend(
ib_int64_t sig_count = srv_suspend_thread(slot);
do {
ulint ret;
rw_lock_x_lock(&purge_sys->latch);
purge_sys->running = false;
@ -3494,32 +3501,11 @@ srv_purge_coordinator_suspend(
/* We don't wait right away on the the non-timed wait because
we want to signal the thread that wants to suspend purge. */
if (stop) {
os_event_wait_low(slot->event, sig_count);
ret = 0;
} else if (rseg_history_len <= trx_sys->rseg_history_len) {
ret = os_event_wait_time_low(
slot->event, SRV_PURGE_MAX_TIMEOUT, sig_count);
} else {
/* We don't want to waste time waiting, if the
history list increased by the time we got here,
unless purge has been stopped. */
ret = 0;
}
srv_sys_mutex_enter();
/* The thread can be in state !suspended after the timeout
but before this check if another thread sent a wakeup signal. */
if (slot->suspended) {
slot->suspended = FALSE;
++srv_sys->n_threads_active[slot->type];
ut_a(srv_sys->n_threads_active[slot->type] == 1);
}
srv_sys_mutex_exit();
const bool wait = stop
|| rseg_history_len <= trx_sys->rseg_history_len;
const bool timeout = srv_resume_thread(
slot, sig_count, wait,
stop ? 0 : SRV_PURGE_MAX_TIMEOUT);
sig_count = srv_suspend_thread(slot);
@ -3531,6 +3517,19 @@ srv_purge_coordinator_suspend(
if (!stop) {
ut_a(purge_sys->n_stop == 0);
purge_sys->running = true;
if (timeout
&& rseg_history_len == trx_sys->rseg_history_len
&& trx_sys->rseg_history_len < 5000) {
/* No new records were added since the
wait started. Simply wait for new
records. The magic number 5000 is an
approximation for the case where we
have cached UNDO log records which
prevent truncate of the UNDO
segments. */
stop = true;
}
} else {
ut_a(purge_sys->n_stop > 0);
@ -3539,33 +3538,9 @@ srv_purge_coordinator_suspend(
}
rw_lock_x_unlock(&purge_sys->latch);
if (ret == OS_SYNC_TIME_EXCEEDED) {
/* No new records added since wait started then simply
wait for new records. The magic number 5000 is an
approximation for the case where we have cached UNDO
log records which prevent truncate of the UNDO
segments. */
if (rseg_history_len == trx_sys->rseg_history_len
&& trx_sys->rseg_history_len < 5000) {
stop = true;
}
}
} while (stop);
srv_sys_mutex_enter();
if (slot->suspended) {
slot->suspended = FALSE;
++srv_sys->n_threads_active[slot->type];
ut_a(srv_sys->n_threads_active[slot->type] == 1);
}
srv_sys_mutex_exit();
srv_resume_thread(slot, 0, false);
}
/*********************************************************************//**
@ -3621,8 +3596,9 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
srv_purge_coordinator_suspend(slot, rseg_history_len);
}
ut_ad(!slot->suspended);
if (srv_purge_should_exit(n_total_purged)) {
ut_a(!slot->suspended);
break;
}
@ -3737,12 +3713,10 @@ srv_get_task_queue_length(void)
return(n_tasks);
}
/**********************************************************************//**
Wakeup the purge threads. */
/** Wake up the purge threads. */
UNIV_INTERN
void
srv_purge_wakeup(void)
/*==================*/
srv_purge_wakeup()
{
ut_ad(!srv_read_only_mode);
@ -3757,4 +3731,3 @@ srv_purge_wakeup(void)
}
}
}

View file

@ -623,19 +623,6 @@ create_log_file(
/** Initial number of the first redo log file */
#define INIT_LOG_FILE0 (SRV_N_LOG_FILES_MAX + 1)
#ifdef DBUG_OFF
# define RECOVERY_CRASH(x) do {} while(0)
#else
# define RECOVERY_CRASH(x) do { \
if (srv_force_recovery_crash == x) { \
fprintf(stderr, "innodb_force_recovery_crash=%lu\n", \
srv_force_recovery_crash); \
fflush(stderr); \
exit(3); \
} \
} while (0)
#endif
/*********************************************************************//**
Creates all log files.
@return DB_SUCCESS or error code */
@ -676,13 +663,14 @@ create_log_files(
file should be recoverable. The buffer
pool was clean, and we can simply create
all log files from the scratch. */
RECOVERY_CRASH(6);
DBUG_EXECUTE_IF("innodb_log_abort_6",
return(DB_ERROR););
}
}
ut_ad(!buf_pool_check_no_pending_io());
RECOVERY_CRASH(7);
DBUG_EXECUTE_IF("innodb_log_abort_7", return(DB_ERROR););
for (unsigned i = 0; i < srv_n_log_files; i++) {
sprintf(logfilename + dirnamelen,
@ -695,7 +683,7 @@ create_log_files(
}
}
RECOVERY_CRASH(8);
DBUG_EXECUTE_IF("innodb_log_abort_8", return(DB_ERROR););
/* We did not create the first log file initially as
ib_logfile0, so that crash recovery cannot find it until it
@ -751,10 +739,16 @@ create_log_files(
return(DB_SUCCESS);
}
/*********************************************************************//**
Renames the first log file. */
/** Rename the first redo log file.
@param[in,out] logfilename buffer for the log file name
@param[in] dirnamelen length of the directory path
@param[in] lsn FIL_PAGE_FILE_FLUSH_LSN value
@param[in,out] logfile0 name of the first log file
@return error code
@retval DB_SUCCESS on successful operation */
MY_ATTRIBUTE((warn_unused_result, nonnull))
static
void
dberr_t
create_log_files_rename(
/*====================*/
char* logfilename, /*!< in/out: buffer for log file name */
@ -765,6 +759,9 @@ create_log_files_rename(
/* If innodb_flush_method=O_DSYNC,
we need to explicitly flush the log buffers. */
fil_flush(SRV_LOG_SPACE_FIRST_ID);
DBUG_EXECUTE_IF("innodb_log_abort_9", return(DB_ERROR););
/* Close the log files, so that we can rename
the first one. */
fil_close_log_files(false);
@ -773,26 +770,28 @@ create_log_files_rename(
checkpoint has been created. */
sprintf(logfilename + dirnamelen, "ib_logfile%u", 0);
RECOVERY_CRASH(9);
ib_logf(IB_LOG_LEVEL_INFO,
"Renaming log file %s to %s", logfile0, logfilename);
mutex_enter(&log_sys->mutex);
ut_ad(strlen(logfile0) == 2 + strlen(logfilename));
ibool success = os_file_rename(
innodb_file_log_key, logfile0, logfilename);
ut_a(success);
RECOVERY_CRASH(10);
dberr_t err = os_file_rename(
innodb_file_log_key, logfile0, logfilename)
? DB_SUCCESS : DB_ERROR;
/* Replace the first file with ib_logfile0. */
strcpy(logfile0, logfilename);
mutex_exit(&log_sys->mutex);
fil_open_log_and_system_tablespace_files();
DBUG_EXECUTE_IF("innodb_log_abort_10", err = DB_ERROR;);
ib_logf(IB_LOG_LEVEL_WARN, "New log files created, LSN=" LSN_PF, lsn);
if (err == DB_SUCCESS) {
fil_open_log_and_system_tablespace_files();
ib_logf(IB_LOG_LEVEL_WARN,
"New log files created, LSN=" LSN_PF, lsn);
}
return(err);
}
/*********************************************************************//**
@ -2299,14 +2298,18 @@ innobase_start_or_create_for_mysql(void)
dirnamelen, max_flushed_lsn,
logfile0);
if (err == DB_SUCCESS) {
err = create_log_files_rename(
logfilename,
dirnamelen,
max_flushed_lsn,
logfile0);
}
if (err != DB_SUCCESS) {
return(err);
}
create_log_files_rename(
logfilename, dirnamelen,
max_flushed_lsn, logfile0);
/* Suppress the message about
crash recovery. */
max_flushed_lsn = min_flushed_lsn
@ -2476,8 +2479,12 @@ files_checked:
fil_flush_file_spaces(FIL_TABLESPACE);
create_log_files_rename(logfilename, dirnamelen,
max_flushed_lsn, logfile0);
err = create_log_files_rename(logfilename, dirnamelen,
max_flushed_lsn, logfile0);
if (err != DB_SUCCESS) {
return(err);
}
} else {
/* Check if we support the max format that is stamped
@ -2679,7 +2686,8 @@ files_checked:
ULINT_MAX, LSN_MAX, NULL);
ut_a(success);
RECOVERY_CRASH(1);
DBUG_EXECUTE_IF("innodb_log_abort_1",
return(DB_ERROR););
min_flushed_lsn = max_flushed_lsn = log_get_lsn();
@ -2694,8 +2702,6 @@ files_checked:
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
RECOVERY_CRASH(2);
/* Flush the old log files. */
log_buffer_flush_to_disk();
/* If innodb_flush_method=O_DSYNC,
@ -2710,21 +2716,27 @@ files_checked:
ut_d(recv_no_log_write = TRUE);
ut_ad(!buf_pool_check_no_pending_io());
RECOVERY_CRASH(3);
DBUG_EXECUTE_IF("innodb_log_abort_3",
return(DB_ERROR););
/* Stamp the LSN to the data files. */
fil_write_flushed_lsn_to_data_files(
max_flushed_lsn, 0);
fil_flush_file_spaces(FIL_TABLESPACE);
DBUG_EXECUTE_IF("innodb_log_abort_4", err = DB_ERROR;);
RECOVERY_CRASH(4);
if (err != DB_SUCCESS) {
return(err);
}
fil_flush_file_spaces(FIL_TABLESPACE);
/* Close and free the redo log files, so that
we can replace them. */
fil_close_log_files(true);
RECOVERY_CRASH(5);
DBUG_EXECUTE_IF("innodb_log_abort_5",
return(DB_ERROR););
/* Free the old log file space. */
log_group_close_all();
@ -2748,8 +2760,11 @@ files_checked:
fil_write_flushed_lsn_to_data_files(min_flushed_lsn, 0);
fil_flush_file_spaces(FIL_TABLESPACE);
create_log_files_rename(logfilename, dirnamelen,
log_get_lsn(), logfile0);
err = create_log_files_rename(logfilename, dirnamelen,
log_get_lsn(), logfile0);
if (err != DB_SUCCESS) {
return(err);
}
}
srv_startup_is_before_trx_rollback_phase = FALSE;

View file

@ -1335,7 +1335,9 @@ trx_sys_close(void)
ut_a(UT_LIST_GET_LEN(trx_sys->ro_trx_list) == 0);
/* Only prepared transactions may be left in the system. Free them. */
ut_a(UT_LIST_GET_LEN(trx_sys->rw_trx_list) == trx_sys->n_prepared_trx);
ut_a(UT_LIST_GET_LEN(trx_sys->rw_trx_list) == trx_sys->n_prepared_trx
|| srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
while ((trx = UT_LIST_GET_FIRST(trx_sys->rw_trx_list)) != NULL) {
trx_free_prepared(trx);

View file

@ -478,7 +478,11 @@ trx_free_prepared(
/*==============*/
trx_t* trx) /*!< in, own: trx object */
{
ut_a(trx_state_eq(trx, TRX_STATE_PREPARED));
ut_a(trx_state_eq(trx, TRX_STATE_PREPARED)
|| (trx_state_eq(trx, TRX_STATE_ACTIVE)
&& trx->is_recovered
&& (srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO)));
ut_a(trx->magic_n == TRX_MAGIC_N);
lock_trx_release_locks(trx);

View file

@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2014, 2017, MariaDB Corporation. 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
@ -2011,13 +2012,37 @@ trx_undo_free_prepared(
ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS);
if (trx->update_undo) {
ut_a(trx->update_undo->state == TRX_UNDO_PREPARED);
switch (trx->update_undo->state) {
case TRX_UNDO_PREPARED:
break;
case TRX_UNDO_ACTIVE:
/* lock_trx_release_locks() assigns
trx->is_recovered=false */
ut_a(srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
break;
default:
ut_error;
}
UT_LIST_REMOVE(undo_list, trx->rseg->update_undo_list,
trx->update_undo);
trx_undo_mem_free(trx->update_undo);
}
if (trx->insert_undo) {
ut_a(trx->insert_undo->state == TRX_UNDO_PREPARED);
switch (trx->insert_undo->state) {
case TRX_UNDO_PREPARED:
break;
case TRX_UNDO_ACTIVE:
/* lock_trx_release_locks() assigns
trx->is_recovered=false */
ut_a(srv_read_only_mode
|| srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
break;
default:
ut_error;
}
UT_LIST_REMOVE(undo_list, trx->rseg->insert_undo_list,
trx->insert_undo);
trx_undo_mem_free(trx->insert_undo);