diff --git a/mysql-test/include/kill_and_restart_mysqld.inc b/mysql-test/include/kill_and_restart_mysqld.inc new file mode 100644 index 0000000000000..f2ac9b504d226 --- /dev/null +++ b/mysql-test/include/kill_and_restart_mysqld.inc @@ -0,0 +1,19 @@ +--let $_server_id= `SELECT @@server_id` +--let $_expect_file_name= $MYSQLTEST_VARDIR/tmp/mysqld.$_server_id.expect + +if ($restart_parameters) +{ + --echo # Kill and restart: $restart_parameters + --exec echo "restart: $restart_parameters" > $_expect_file_name +} +if (!$restart_parameters) +{ + --echo # Kill and restart + --exec echo "restart" > $_expect_file_name +} + +--shutdown_server 0 +--source include/wait_until_disconnected.inc +--enable_reconnect +--source include/wait_until_connected_again.inc +--disable_reconnect diff --git a/mysql-test/suite/binlog/r/binlog_max_binlog_stmt_cache_size.result b/mysql-test/suite/binlog/r/binlog_max_binlog_stmt_cache_size.result new file mode 100644 index 0000000000000..cf4d7004195da --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_max_binlog_stmt_cache_size.result @@ -0,0 +1,31 @@ +select @@max_binlog_stmt_cache_size; +@@max_binlog_stmt_cache_size +18446744073709547520 +set global max_binlog_stmt_cache_size= 18446744073709547520; +select @@max_binlog_stmt_cache_size; +@@max_binlog_stmt_cache_size +18446744073709547520 +set global max_binlog_stmt_cache_size= 18446744073709547519; +Warnings: +Warning 1292 Truncated incorrect max_binlog_stmt_cache_size value: '18446744073709547519' +select @@max_binlog_stmt_cache_size; +@@max_binlog_stmt_cache_size +18446744073709543424 +set global max_binlog_stmt_cache_size= 18446744073709551615; +Warnings: +Warning 1292 Truncated incorrect max_binlog_stmt_cache_size value: '18446744073709551615' +select @@max_binlog_stmt_cache_size; +@@max_binlog_stmt_cache_size +18446744073709547520 +set global max_binlog_stmt_cache_size= 18446744073709551614; +Warnings: +Warning 1292 Truncated incorrect max_binlog_stmt_cache_size value: '18446744073709551614' +select @@max_binlog_stmt_cache_size; +@@max_binlog_stmt_cache_size +18446744073709547520 +set global max_binlog_stmt_cache_size= 18446744073709551616; +ERROR 42000: Incorrect argument type to variable 'max_binlog_stmt_cache_size' +select @@max_binlog_stmt_cache_size; +@@max_binlog_stmt_cache_size +18446744073709547520 +set global max_binlog_stmt_cache_size= 18446744073709547520; diff --git a/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.opt b/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.opt new file mode 100644 index 0000000000000..c52ef14d5d082 --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.opt @@ -0,0 +1 @@ +--max_binlog_stmt_cache_size=18446744073709547520 diff --git a/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.test b/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.test new file mode 100644 index 0000000000000..f85eed3cea83e --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_max_binlog_stmt_cache_size.test @@ -0,0 +1,22 @@ +source include/have_log_bin.inc; +select @@max_binlog_stmt_cache_size; + +--let $cache_size=`select @@max_binlog_stmt_cache_size;` + +set global max_binlog_stmt_cache_size= 18446744073709547520; +select @@max_binlog_stmt_cache_size; + +set global max_binlog_stmt_cache_size= 18446744073709547519; +select @@max_binlog_stmt_cache_size; + +set global max_binlog_stmt_cache_size= 18446744073709551615; +select @@max_binlog_stmt_cache_size; + +set global max_binlog_stmt_cache_size= 18446744073709551614; +select @@max_binlog_stmt_cache_size; + +--error ER_WRONG_TYPE_FOR_VAR +set global max_binlog_stmt_cache_size= 18446744073709551616; +select @@max_binlog_stmt_cache_size; + +--eval set global max_binlog_stmt_cache_size= $cache_size diff --git a/mysql-test/suite/innodb/r/log_file_size.result b/mysql-test/suite/innodb/r/log_file_size.result new file mode 100644 index 0000000000000..1519f02a8c8a4 --- /dev/null +++ b/mysql-test/suite/innodb/r/log_file_size.result @@ -0,0 +1,35 @@ +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"); +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"); +CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; +BEGIN; +INSERT INTO t1 VALUES (42); +# Kill and restart: --innodb-log-file-size=6M +SELECT * FROM t1; +a +INSERT INTO t1 VALUES (42); +BEGIN; +DELETE FROM t1; +# Kill and restart: --innodb-log-files-in-group=3 --innodb-log-file-size=5M +SELECT * FROM t1; +a +42 +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; +a +42 +123 +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/t/log_file_size.test b/mysql-test/suite/innodb/t/log_file_size.test new file mode 100644 index 0000000000000..95a7bcc143af3 --- /dev/null +++ b/mysql-test/suite/innodb/t/log_file_size.test @@ -0,0 +1,185 @@ +# Test resizing the InnoDB redo log. + +--source include/have_innodb.inc + +# Embedded server does not support crashing +--source include/not_embedded.inc +# Avoid CrashReporter popup on Mac +--source include/not_crashrep.inc +# innodb-force-recovery-crash needs debug +--source include/have_debug.inc + +if (`SELECT @@innodb_log_file_size = 1048576`) { + --skip Test requires innodb_log_file_size>1M. +} + +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"); +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"); + +CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB; +BEGIN; +INSERT INTO t1 VALUES (42); + +let $restart_parameters = --innodb-log-file-size=6M; +--source include/kill_and_restart_mysqld.inc + +SELECT * FROM t1; + +INSERT INTO t1 VALUES (42); +BEGIN; +DELETE FROM t1; + +let $restart_parameters = --innodb-log-files-in-group=3 --innodb-log-file-size=5M; +--source include/kill_and_restart_mysqld.inc + +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; + +BEGIN; +DELETE FROM t1; + +--source include/kill_mysqld.inc + +--error 2 +--exec $MYSQLD_CMD $args --innodb-log-group-home-dir=foo\;bar +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 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 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 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 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 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 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 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 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 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 SEARCH_PATTERN= InnoDB: Setting log file .*ib_logfile[0-9]+ size to; +--source include/search_pattern_in_file.inc +--remove_file $SEARCH_FILE + +# 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 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; +die unless open(FILE, ">$ENV{MYSQLD_DATADIR}/ib_logfile0"); +print FILE "garbage"; +close(FILE); +EOF +--error 2 +--exec $MYSQLD_CMD $args +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 + +perl; +die unless open(FILE, ">$ENV{MYSQLD_DATADIR}/ib_logfile1"); +print FILE "junkfill" x 131072; +close(FILE); +EOF + +--error 2 +--exec $MYSQLD_CMD $args +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 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 + +SELECT * FROM t1; +DROP TABLE t1; diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 3f75f6553a24b..57b28d1fd8a28 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -949,15 +949,39 @@ my_bool getopt_compare_strings(register const char *s, register const char *t, /* function: eval_num_suffix + Transforms suffix like k/m/g to their real value. +*/ + +static inline long eval_num_suffix(char *suffix, int *error) +{ + long num= 1; + if (*suffix == 'k' || *suffix == 'K') + num*= 1024L; + else if (*suffix == 'm' || *suffix == 'M') + num*= 1024L * 1024L; + else if (*suffix == 'g' || *suffix == 'G') + num*= 1024L * 1024L * 1024L; + else if (*suffix) + { + *error= 1; + return 0; + } + return num; +} + +/* + function: eval_num_suffix_ll + Transforms a number with a suffix to real number. Suffix can be k|K for kilo, m|M for mega or g|G for giga. */ -static longlong eval_num_suffix(char *argument, int *error, char *option_name) +static longlong eval_num_suffix_ll(char *argument, + int *error, char *option_name) { char *endchar; longlong num; - DBUG_ENTER("eval_num_suffix"); + DBUG_ENTER("eval_num_suffix_ll"); *error= 0; @@ -970,23 +994,47 @@ static longlong eval_num_suffix(char *argument, int *error, char *option_name) *error= 1; DBUG_RETURN(0); } - if (*endchar == 'k' || *endchar == 'K') - num*= 1024L; - else if (*endchar == 'm' || *endchar == 'M') - num*= 1024L * 1024L; - else if (*endchar == 'g' || *endchar == 'G') - num*= 1024L * 1024L * 1024L; - else if (*endchar) - { + num*= eval_num_suffix(endchar, error); + if (*error) fprintf(stderr, "Unknown suffix '%c' used for variable '%s' (value '%s')\n", *endchar, option_name, argument); + DBUG_RETURN(num); +} + +/* + function: eval_num_suffix_ull + + Transforms a number with a suffix to positive Integer. Suffix can + be k|K for kilo, m|M for mega or g|G for giga. +*/ + +static ulonglong eval_num_suffix_ull(char *argument, + int *error, char *option_name) +{ + char *endchar; + ulonglong num; + DBUG_ENTER("eval_num_suffix_ull"); + + *error= 0; + errno= 0; + num= strtoull(argument, &endchar, 10); + if (errno == ERANGE) + { + my_getopt_error_reporter(ERROR_LEVEL, + "Incorrect integer value: '%s'", argument); *error= 1; DBUG_RETURN(0); } + num*= eval_num_suffix(endchar, error); + if (*error) + fprintf(stderr, + "Unknown suffix '%c' used for variable '%s' (value '%s')\n", + *endchar, option_name, argument); DBUG_RETURN(num); } + /* function: getopt_ll @@ -1000,7 +1048,7 @@ static longlong eval_num_suffix(char *argument, int *error, char *option_name) static longlong getopt_ll(char *arg, const struct my_option *optp, int *err) { - longlong num=eval_num_suffix(arg, err, (char*) optp->name); + longlong num=eval_num_suffix_ll(arg, err, (char*) optp->name); return getopt_ll_limit_value(num, optp, NULL); } @@ -1077,7 +1125,7 @@ longlong getopt_ll_limit_value(longlong num, const struct my_option *optp, static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err) { - ulonglong num= eval_num_suffix(arg, err, (char*) optp->name); + ulonglong num= eval_num_suffix_ull(arg, err, (char*) optp->name); return getopt_ull_limit_value(num, optp, NULL); } diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc index 361da4e627914..ce833ea13da78 100644 --- a/sql/opt_subselect.cc +++ b/sql/opt_subselect.cc @@ -4059,13 +4059,13 @@ SJ_TMP_TABLE::create_sj_weedout_tmp_table(THD *thd) share->db_plugin= ha_lock_engine(0, TMP_ENGINE_HTON); table->file= get_new_handler(share, &table->mem_root, share->db_type()); - DBUG_ASSERT(uniq_tuple_length_arg <= table->file->max_key_length()); } else { share->db_plugin= ha_lock_engine(0, heap_hton); table->file= get_new_handler(share, &table->mem_root, share->db_type()); + DBUG_ASSERT(uniq_tuple_length_arg <= table->file->max_key_length()); } if (!table->file) goto err; diff --git a/storage/connect/filamzip.cpp b/storage/connect/filamzip.cpp index 22fe95aebad82..6aca4631f32da 100644 --- a/storage/connect/filamzip.cpp +++ b/storage/connect/filamzip.cpp @@ -97,7 +97,7 @@ bool ZIPUTIL::WildMatch(PSZ pat, PSZ str) { if (!*++pat) return TRUE; goto loopStart; default: - if (mapCaseTable[(unsigned)*s] != mapCaseTable[(unsigned)*p]) + if (mapCaseTable[(uchar)*s] != mapCaseTable[(uchar)*p]) goto starCheck; break; } /* endswitch */ diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 82fb9459a4295..c79a7e3af1015 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -2808,11 +2808,10 @@ recv_scan_log_recs( recv_init_crash_recovery(); } else { - - ib_logf(IB_LOG_LEVEL_WARN, - "Recovery skipped, " - "--innodb-read-only set!"); - + ib_logf(IB_LOG_LEVEL_ERROR, + "innodb_read_only prevents" + " crash recovery"); + recv_needed_recovery = TRUE; return(TRUE); } } @@ -3252,6 +3251,11 @@ recv_recovery_from_checkpoint_start_func( } /* Done with startup scan. Clear the flag. */ recv_log_scan_is_startup_type = FALSE; + + if (srv_read_only_mode && recv_needed_recovery) { + return(DB_READ_ONLY); + } + if (TYPE_CHECKPOINT) { /* NOTE: we always do a 'recovery' at startup, but only if there is something wrong we will print a message to the @@ -3406,15 +3410,6 @@ void recv_recovery_from_checkpoint_finish(void) /*======================================*/ { - /* Apply the hashed log records to the respective file pages */ - - if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { - - recv_apply_hashed_log_recs(TRUE); - } - - DBUG_PRINT("ib_log", ("apply completed")); - if (recv_needed_recovery) { trx_sys_print_mysql_master_log_pos(); trx_sys_print_mysql_binlog_offset(); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 2fec8b7bc2f38..286b6ae993ea5 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -3,7 +3,7 @@ Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2008, Google Inc. Copyright (c) 2009, Percona Inc. -Copyright (c) 2013, 2016, MariaDB Corporation +Copyright (c) 2013, 2017, MariaDB Corporation Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -601,7 +601,7 @@ create_log_file( fprintf(stderr, "innodb_force_recovery_crash=%lu\n", \ srv_force_recovery_crash); \ fflush(stderr); \ - abort(); \ + exit(3); \ } \ } while (0) #endif @@ -1573,8 +1573,6 @@ innobase_start_or_create_for_mysql(void) ulint max_arch_log_no; #endif /* UNIV_LOG_ARCHIVE */ ulint sum_of_new_sizes; - ulint sum_of_data_file_sizes; - ulint tablespace_size_in_header; dberr_t err; unsigned i; ulint srv_n_log_files_found = srv_n_log_files; @@ -1587,6 +1585,19 @@ innobase_start_or_create_for_mysql(void) size_t dirnamelen; bool sys_datafiles_created = false; + /* Check that os_fast_mutexes work as expected */ + os_fast_mutex_init(PFS_NOT_INSTRUMENTED, &srv_os_test_mutex); + + ut_a(0 == os_fast_mutex_trylock(&srv_os_test_mutex)); + + os_fast_mutex_unlock(&srv_os_test_mutex); + + os_fast_mutex_lock(&srv_os_test_mutex); + + os_fast_mutex_unlock(&srv_os_test_mutex); + + os_fast_mutex_free(&srv_os_test_mutex); + /* This should be initialized early */ ut_init_timer(); @@ -1632,22 +1643,7 @@ innobase_start_or_create_for_mysql(void) #endif /* PAGE_ATOMIC_REF_COUNT */ ); - - if (sizeof(ulint) != sizeof(void*)) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: size of InnoDB's ulint is %lu, " - "but size of void*\n", (ulong) sizeof(ulint)); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: is %lu. The sizes should be the same " - "so that on a 64-bit\n", - (ulong) sizeof(void*)); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: platforms you can allocate more than 4 GB " - "of memory.\n"); - } + compile_time_assert(sizeof(ulint) == sizeof(void*)); #ifdef UNIV_DEBUG ib_logf(IB_LOG_LEVEL_INFO, @@ -2358,7 +2354,6 @@ innobase_start_or_create_for_mysql(void) trx_sys_create(); if (create_new_db) { - ut_a(!srv_read_only_mode); mtr_start(&mtr); @@ -2472,24 +2467,100 @@ innobase_start_or_create_for_mysql(void) LOG_CHECKPOINT, LSN_MAX, min_flushed_lsn, max_flushed_lsn); + if (err == DB_SUCCESS) { + /* Initialize the change buffer. */ + err = dict_boot(); + } + if (err != DB_SUCCESS) { + return(err); + } - return(DB_ERROR); + /* This must precede recv_apply_hashed_log_recs(TRUE). */ + ib_bh = trx_sys_init_at_db_start(); + + if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { + /* Apply the hashed log records to the + respective file pages, for the last batch of + recv_group_scan_log_recs(). */ + + err = recv_apply_hashed_log_recs(TRUE); + DBUG_PRINT("ib_log", ("apply completed")); + + if (err != DB_SUCCESS) { + return(err); + } } - /* Since the insert buffer init is in dict_boot, and the - insert buffer is needed in any disk i/o, first we call - dict_boot(). Note that trx_sys_init_at_db_start() only needs - to access space 0, and the insert buffer at this stage already - works for space 0. */ + if (!srv_read_only_mode) { + const ulint flags = FSP_FLAGS_PAGE_SSIZE(); + for (ulint id = 0; id <= srv_undo_tablespaces; id++) { + if (fil_space_get(id)) { + fsp_flags_try_adjust(id, flags); + } + } - err = dict_boot(); + if (sum_of_new_sizes > 0) { + /* New data file(s) were added */ + mtr_start(&mtr); + fsp_header_inc_size(0, sum_of_new_sizes, &mtr); + mtr_commit(&mtr); + /* Immediately write the log record about + increased tablespace size to disk, so that it + is durable even if mysqld would crash + quickly */ + log_buffer_flush_to_disk(); + } + } - if (err != DB_SUCCESS) { - return(err); + const ulint tablespace_size_in_header + = fsp_header_get_tablespace_size(); + +#ifdef UNIV_DEBUG + /* buf_debug_prints = TRUE; */ +#endif /* UNIV_DEBUG */ + ulint sum_of_data_file_sizes = 0; + + for (ulint d = 0; d < srv_n_data_files; d++) { + sum_of_data_file_sizes += srv_data_file_sizes[d]; + } + + /* Compare the system tablespace file size to what is + stored in FSP_SIZE. In open_or_create_data_files() + we already checked that the file sizes match the + innodb_data_file_path specification. */ + if (srv_read_only_mode + || sum_of_data_file_sizes == tablespace_size_in_header) { + /* Do not complain about the size. */ + } else if (!srv_auto_extend_last_data_file + || sum_of_data_file_sizes + < tablespace_size_in_header) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Tablespace size stored in header is " ULINTPF + " pages, but the sum of data file sizes is " + ULINTPF " pages", + tablespace_size_in_header, + sum_of_data_file_sizes); + + if (srv_force_recovery == 0 + && sum_of_data_file_sizes + < tablespace_size_in_header) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Cannot start InnoDB. The tail of" + " the system tablespace is" + " missing. Have you edited" + " innodb_data_file_path in my.cnf" + " in an inappropriate way, removing" + " data files from there?" + " You can set innodb_force_recovery=1" + " in my.cnf to force" + " a startup if you are trying to" + " recover a badly corrupt database."); + + return(DB_ERROR); + } } - ib_bh = trx_sys_init_at_db_start(); n_recovered_trx = UT_LIST_GET_LEN(trx_sys->rw_trx_list); /* The purge system needs to create the purge view and @@ -2636,20 +2707,8 @@ innobase_start_or_create_for_mysql(void) trx_sys_file_format_tag_init(); } - if (!create_new_db && sum_of_new_sizes > 0) { - /* New data file(s) were added */ - mtr_start(&mtr); - - fsp_header_inc_size(0, sum_of_new_sizes, &mtr); - - mtr_commit(&mtr); - - /* Immediately write the log record about increased tablespace - size to disk, so that it is durable even if mysqld would crash - quickly */ - - log_buffer_flush_to_disk(); - } + ut_ad(err == DB_SUCCESS); + ut_a(sum_of_new_sizes != ULINT_UNDEFINED); #ifdef UNIV_LOG_ARCHIVE /* Archiving is always off under MySQL */ @@ -2711,13 +2770,6 @@ innobase_start_or_create_for_mysql(void) } if (!srv_read_only_mode) { - const ulint flags = FSP_FLAGS_PAGE_SSIZE(); - for (ulint id = 0; id <= srv_undo_tablespaces; id++) { - if (fil_space_get(id)) { - fsp_flags_try_adjust(id, flags); - } - } - /* Create the thread which watches the timeouts for lock waits */ thread_handles[2 + SRV_MAX_N_IO_THREADS] = os_thread_create( @@ -2816,116 +2868,6 @@ innobase_start_or_create_for_mysql(void) buf_flush_page_cleaner_thread_started = true; } -#ifdef UNIV_DEBUG - /* buf_debug_prints = TRUE; */ -#endif /* UNIV_DEBUG */ - sum_of_data_file_sizes = 0; - - for (i = 0; i < srv_n_data_files; i++) { - sum_of_data_file_sizes += srv_data_file_sizes[i]; - } - - tablespace_size_in_header = fsp_header_get_tablespace_size(); - - if (!srv_read_only_mode - && !srv_auto_extend_last_data_file - && sum_of_data_file_sizes != tablespace_size_in_header) { - - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: tablespace size" - " stored in header is %lu pages, but\n", - (ulong) tablespace_size_in_header); - ut_print_timestamp(stderr); - fprintf(stderr, - "InnoDB: the sum of data file sizes is %lu pages\n", - (ulong) sum_of_data_file_sizes); - - if (srv_force_recovery == 0 - && sum_of_data_file_sizes < tablespace_size_in_header) { - /* This is a fatal error, the tail of a tablespace is - missing */ - - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Cannot start InnoDB." - " The tail of the system tablespace is\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: missing. Have you edited" - " innodb_data_file_path in my.cnf in an\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: inappropriate way, removing" - " ibdata files from there?\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: You can set innodb_force_recovery=1" - " in my.cnf to force\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: a startup if you are trying" - " to recover a badly corrupt database.\n"); - - return(DB_ERROR); - } - } - - if (!srv_read_only_mode - && srv_auto_extend_last_data_file - && sum_of_data_file_sizes < tablespace_size_in_header) { - - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: tablespace size stored in header" - " is %lu pages, but\n", - (ulong) tablespace_size_in_header); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: the sum of data file sizes" - " is only %lu pages\n", - (ulong) sum_of_data_file_sizes); - - if (srv_force_recovery == 0) { - - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Cannot start InnoDB. The tail of" - " the system tablespace is\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: missing. Have you edited" - " innodb_data_file_path in my.cnf in an\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: inappropriate way, removing" - " ibdata files from there?\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: You can set innodb_force_recovery=1" - " in my.cnf to force\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: a startup if you are trying to" - " recover a badly corrupt database.\n"); - - return(DB_ERROR); - } - } - - /* Check that os_fast_mutexes work as expected */ - os_fast_mutex_init(PFS_NOT_INSTRUMENTED, &srv_os_test_mutex); - - ut_a(0 == os_fast_mutex_trylock(&srv_os_test_mutex)); - - os_fast_mutex_unlock(&srv_os_test_mutex); - - os_fast_mutex_lock(&srv_os_test_mutex); - - os_fast_mutex_unlock(&srv_os_test_mutex); - - os_fast_mutex_free(&srv_os_test_mutex); - if (srv_print_verbose_log) { ib_logf(IB_LOG_LEVEL_INFO, "%s started; log sequence number " LSN_PF "", diff --git a/storage/xtradb/log/log0recv.cc b/storage/xtradb/log/log0recv.cc index 1777084e74610..11c643afff10b 100644 --- a/storage/xtradb/log/log0recv.cc +++ b/storage/xtradb/log/log0recv.cc @@ -2,7 +2,7 @@ Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2016, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 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 @@ -2900,11 +2900,10 @@ recv_scan_log_recs( recv_init_crash_recovery(); } else { - - ib_logf(IB_LOG_LEVEL_WARN, - "Recovery skipped, " - "--innodb-read-only set!"); - + ib_logf(IB_LOG_LEVEL_ERROR, + "innodb_read_only prevents" + " crash recovery"); + recv_needed_recovery = TRUE; return(TRUE); } } @@ -3351,6 +3350,11 @@ recv_recovery_from_checkpoint_start_func( } /* Done with startup scan. Clear the flag. */ recv_log_scan_is_startup_type = FALSE; + + if (srv_read_only_mode && recv_needed_recovery) { + return(DB_READ_ONLY); + } + if (TYPE_CHECKPOINT) { /* NOTE: we always do a 'recovery' at startup, but only if there is something wrong we will print a message to the @@ -3505,15 +3509,6 @@ void recv_recovery_from_checkpoint_finish(void) /*======================================*/ { - /* Apply the hashed log records to the respective file pages */ - - if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { - - recv_apply_hashed_log_recs(TRUE); - } - - DBUG_PRINT("ib_log", ("apply completed")); - if (recv_needed_recovery) { trx_sys_print_mysql_master_log_pos(); trx_sys_print_mysql_binlog_offset(); diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc index b933171e68301..14f16870de9b9 100644 --- a/storage/xtradb/srv/srv0start.cc +++ b/storage/xtradb/srv/srv0start.cc @@ -631,7 +631,7 @@ create_log_file( fprintf(stderr, "innodb_force_recovery_crash=%lu\n", \ srv_force_recovery_crash); \ fflush(stderr); \ - abort(); \ + exit(3); \ } \ } while (0) #endif @@ -1631,8 +1631,6 @@ innobase_start_or_create_for_mysql(void) lsn_t max_arch_log_no = LSN_MAX; #endif /* UNIV_LOG_ARCHIVE */ ulint sum_of_new_sizes; - ulint sum_of_data_file_sizes; - ulint tablespace_size_in_header; dberr_t err; unsigned i; ulint srv_n_log_files_found = srv_n_log_files; @@ -1645,6 +1643,19 @@ innobase_start_or_create_for_mysql(void) size_t dirnamelen; bool sys_datafiles_created = false; + /* Check that os_fast_mutexes work as expected */ + os_fast_mutex_init(PFS_NOT_INSTRUMENTED, &srv_os_test_mutex); + + ut_a(0 == os_fast_mutex_trylock(&srv_os_test_mutex)); + + os_fast_mutex_unlock(&srv_os_test_mutex); + + os_fast_mutex_lock(&srv_os_test_mutex); + + os_fast_mutex_unlock(&srv_os_test_mutex); + + os_fast_mutex_free(&srv_os_test_mutex); + /* This should be initialized early */ ut_init_timer(); @@ -1690,22 +1701,7 @@ innobase_start_or_create_for_mysql(void) #endif /* PAGE_ATOMIC_REF_COUNT */ ); - - if (sizeof(ulint) != sizeof(void*)) { - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: size of InnoDB's ulint is %lu, " - "but size of void*\n", (ulong) sizeof(ulint)); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: is %lu. The sizes should be the same " - "so that on a 64-bit\n", - (ulong) sizeof(void*)); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: platforms you can allocate more than 4 GB " - "of memory.\n"); - } + compile_time_assert(sizeof(ulint) == sizeof(void*)); /* If stacktrace is used we set up signal handler for SIGUSR2 signal here. If signal handler set fails we report that and disable @@ -2437,7 +2433,6 @@ innobase_start_or_create_for_mysql(void) trx_sys_create(); if (create_new_db) { - ut_a(!srv_read_only_mode); init_log_online(); @@ -2519,25 +2514,103 @@ innobase_start_or_create_for_mysql(void) min_flushed_lsn, max_flushed_lsn); if (err != DB_SUCCESS) { - - return(DB_ERROR); + return(err); } init_log_online(); - /* Since the insert buffer init is in dict_boot, and the - insert buffer is needed in any disk i/o, first we call - dict_boot(). Note that trx_sys_init_at_db_start() only needs - to access space 0, and the insert buffer at this stage already - works for space 0. */ - + /* Initialize the change buffer. */ err = dict_boot(); if (err != DB_SUCCESS) { return(err); } + /* This must precede recv_apply_hashed_log_recs(TRUE). */ ib_bh = trx_sys_init_at_db_start(); + + if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { + /* Apply the hashed log records to the + respective file pages, for the last batch of + recv_group_scan_log_recs(). */ + + err = recv_apply_hashed_log_recs(TRUE); + DBUG_PRINT("ib_log", ("apply completed")); + + if (err != DB_SUCCESS) { + return(err); + } + } + + if (!srv_read_only_mode) { + const ulint flags = FSP_FLAGS_PAGE_SSIZE(); + for (ulint id = 0; id <= srv_undo_tablespaces; id++) { + if (fil_space_get(id)) { + fsp_flags_try_adjust(id, flags); + } + } + + if (sum_of_new_sizes > 0) { + /* New data file(s) were added */ + mtr_start(&mtr); + fsp_header_inc_size(0, sum_of_new_sizes, &mtr); + mtr_commit(&mtr); + /* Immediately write the log record about + increased tablespace size to disk, so that it + is durable even if mysqld would crash + quickly */ + log_buffer_flush_to_disk(); + } + } + + const ulint tablespace_size_in_header + = fsp_header_get_tablespace_size(); + +#ifdef UNIV_DEBUG + /* buf_debug_prints = TRUE; */ +#endif /* UNIV_DEBUG */ + ulint sum_of_data_file_sizes = 0; + + for (ulint d = 0; d < srv_n_data_files; d++) { + sum_of_data_file_sizes += srv_data_file_sizes[d]; + } + + /* Compare the system tablespace file size to what is + stored in FSP_SIZE. In open_or_create_data_files() + we already checked that the file sizes match the + innodb_data_file_path specification. */ + if (srv_read_only_mode + || sum_of_data_file_sizes == tablespace_size_in_header) { + /* Do not complain about the size. */ + } else if (!srv_auto_extend_last_data_file + || sum_of_data_file_sizes + < tablespace_size_in_header) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Tablespace size stored in header is " ULINTPF + " pages, but the sum of data file sizes is " + ULINTPF " pages", + tablespace_size_in_header, + sum_of_data_file_sizes); + + if (srv_force_recovery == 0 + && sum_of_data_file_sizes + < tablespace_size_in_header) { + ib_logf(IB_LOG_LEVEL_ERROR, + "Cannot start InnoDB. The tail of" + " the system tablespace is" + " missing. Have you edited" + " innodb_data_file_path in my.cnf" + " in an inappropriate way, removing" + " data files from there?" + " You can set innodb_force_recovery=1" + " in my.cnf to force" + " a startup if you are trying to" + " recover a badly corrupt database."); + + return(DB_ERROR); + } + } + n_recovered_trx = UT_LIST_GET_LEN(trx_sys->rw_trx_list); /* The purge system needs to create the purge view and @@ -2690,20 +2763,8 @@ innobase_start_or_create_for_mysql(void) trx_sys_file_format_tag_init(); } - if (!create_new_db && sum_of_new_sizes > 0) { - /* New data file(s) were added */ - mtr_start(&mtr); - - fsp_header_inc_size(0, sum_of_new_sizes, &mtr); - - mtr_commit(&mtr); - - /* Immediately write the log record about increased tablespace - size to disk, so that it is durable even if mysqld would crash - quickly */ - - log_buffer_flush_to_disk(); - } + ut_ad(err == DB_SUCCESS); + ut_a(sum_of_new_sizes != ULINT_UNDEFINED); #ifdef UNIV_LOG_ARCHIVE if (!srv_read_only_mode) { @@ -2768,13 +2829,6 @@ innobase_start_or_create_for_mysql(void) } if (!srv_read_only_mode) { - const ulint flags = FSP_FLAGS_PAGE_SSIZE(); - for (ulint id = 0; id <= srv_undo_tablespaces; id++) { - if (fil_space_get(id)) { - fsp_flags_try_adjust(id, flags); - } - } - /* Create the thread which watches the timeouts for lock waits */ thread_handles[2 + SRV_MAX_N_IO_THREADS] = os_thread_create( @@ -2877,116 +2931,6 @@ innobase_start_or_create_for_mysql(void) buf_flush_lru_manager_thread_handle = os_thread_create(buf_flush_lru_manager_thread, NULL, NULL); buf_flush_lru_manager_thread_started = true; -#ifdef UNIV_DEBUG - /* buf_debug_prints = TRUE; */ -#endif /* UNIV_DEBUG */ - sum_of_data_file_sizes = 0; - - for (i = 0; i < srv_n_data_files; i++) { - sum_of_data_file_sizes += srv_data_file_sizes[i]; - } - - tablespace_size_in_header = fsp_header_get_tablespace_size(); - - if (!srv_read_only_mode - && !srv_auto_extend_last_data_file - && sum_of_data_file_sizes != tablespace_size_in_header) { - - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: tablespace size" - " stored in header is %lu pages, but\n", - (ulong) tablespace_size_in_header); - ut_print_timestamp(stderr); - fprintf(stderr, - "InnoDB: the sum of data file sizes is %lu pages\n", - (ulong) sum_of_data_file_sizes); - - if (srv_force_recovery == 0 - && sum_of_data_file_sizes < tablespace_size_in_header) { - /* This is a fatal error, the tail of a tablespace is - missing */ - - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Cannot start InnoDB." - " The tail of the system tablespace is\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: missing. Have you edited" - " innodb_data_file_path in my.cnf in an\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: inappropriate way, removing" - " ibdata files from there?\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: You can set innodb_force_recovery=1" - " in my.cnf to force\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: a startup if you are trying" - " to recover a badly corrupt database.\n"); - - return(DB_ERROR); - } - } - - if (!srv_read_only_mode - && srv_auto_extend_last_data_file - && sum_of_data_file_sizes < tablespace_size_in_header) { - - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Error: tablespace size stored in header" - " is %lu pages, but\n", - (ulong) tablespace_size_in_header); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: the sum of data file sizes" - " is only %lu pages\n", - (ulong) sum_of_data_file_sizes); - - if (srv_force_recovery == 0) { - - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: Cannot start InnoDB. The tail of" - " the system tablespace is\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: missing. Have you edited" - " innodb_data_file_path in my.cnf in an\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: inappropriate way, removing" - " ibdata files from there?\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: You can set innodb_force_recovery=1" - " in my.cnf to force\n"); - ut_print_timestamp(stderr); - fprintf(stderr, - " InnoDB: a startup if you are trying to" - " recover a badly corrupt database.\n"); - - return(DB_ERROR); - } - } - - /* Check that os_fast_mutexes work as expected */ - os_fast_mutex_init(PFS_NOT_INSTRUMENTED, &srv_os_test_mutex); - - ut_a(0 == os_fast_mutex_trylock(&srv_os_test_mutex)); - - os_fast_mutex_unlock(&srv_os_test_mutex); - - os_fast_mutex_lock(&srv_os_test_mutex); - - os_fast_mutex_unlock(&srv_os_test_mutex); - - os_fast_mutex_free(&srv_os_test_mutex); - if (!srv_file_per_table && srv_pass_corrupt_table) { fprintf(stderr, "InnoDB: Warning:" " The option innodb_file_per_table is disabled,"