mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 03:52:35 +01:00
Merge 10.0 into 10.1
This commit is contained in:
commit
2e67e66c3a
29 changed files with 624 additions and 549 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
*/||
|
||||
|
||||
|
|
|
@ -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` =~
|
||||
|
|
|
@ -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` (
|
||||
|
|
|
@ -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
|
||||
|
|
29
mysql-test/suite/innodb/r/read_only_recovery.result
Normal file
29
mysql-test/suite/innodb/r/read_only_recovery.result
Normal 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;
|
|
@ -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
|
||||
|
||||
#
|
||||
|
|
|
@ -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;
|
||||
|
|
36
mysql-test/suite/innodb/t/read_only_recovery.test
Normal file
36
mysql-test/suite/innodb/t/read_only_recovery.test
Normal 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;
|
|
@ -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";
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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';
|
|
@ -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),
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue