diff options
-rw-r--r-- | mysql-test/r/subselect4.result | 34 | ||||
-rw-r--r-- | mysql-test/r/subselect_innodb.result | 15 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/log_file_size.result | 12 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/log_file_size.test | 16 | ||||
-rw-r--r-- | mysql-test/t/subselect4.test | 19 | ||||
-rw-r--r-- | mysql-test/t/subselect_innodb.test | 59 | ||||
-rw-r--r-- | plugin/server_audit/server_audit.c | 2 | ||||
-rw-r--r-- | sql/item_subselect.cc | 7 | ||||
-rw-r--r-- | sql/item_subselect.h | 9 | ||||
-rw-r--r-- | sql/log_slow.h | 33 | ||||
-rw-r--r-- | sql/sql_select.cc | 2 | ||||
-rw-r--r-- | storage/innobase/include/log0recv.h | 33 | ||||
-rw-r--r-- | storage/innobase/log/log0log.cc | 11 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 171 | ||||
-rw-r--r-- | storage/innobase/srv/srv0start.cc | 6 | ||||
-rw-r--r-- | storage/maria/ha_maria.cc | 230 | ||||
-rw-r--r-- | storage/myisam/ha_myisam.cc | 204 | ||||
-rw-r--r-- | storage/xtradb/include/log0recv.h | 33 | ||||
-rw-r--r-- | storage/xtradb/log/log0log.cc | 11 | ||||
-rw-r--r-- | storage/xtradb/log/log0recv.cc | 169 | ||||
-rw-r--r-- | storage/xtradb/srv/srv0start.cc | 4 |
21 files changed, 501 insertions, 579 deletions
diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result index 6e4e8abfeb5..9188f3bfd28 100644 --- a/mysql-test/r/subselect4.result +++ b/mysql-test/r/subselect4.result @@ -2436,5 +2436,39 @@ EXECUTE stmt; i 6 drop table t1, t2, t3; +# +# MDEV-11078: NULL NOT IN (non-empty subquery) should never return results +# +create table t1(a int,b int); +create table t2(a int,b int); +insert into t1 value (1,2); +select (NULL) in (select 1 from t1); +(NULL) in (select 1 from t1) +NULL +select (null) in (select 1 from t2); +(null) in (select 1 from t2) +0 +select 1 in (select 1 from t1); +1 in (select 1 from t1) +1 +select 1 in (select 1 from t2); +1 in (select 1 from t2) +0 +select 1 from dual where null in (select 1 from t1); +1 +select 1 from dual where null in (select 1 from t2); +1 +select (null,null) in (select * from t1); +(null,null) in (select * from t1) +NULL +select (null,null) in (select * from t2); +(null,null) in (select * from t2) +0 +select 1 from dual where null not in (select 1 from t1); +1 +select 1 from dual where null not in (select 1 from t2); +1 +1 +drop table t1,t2; SET optimizer_switch= @@global.optimizer_switch; set @@tmp_table_size= @@global.tmp_table_size; diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result index 07d00e96549..fe69dac17a0 100644 --- a/mysql-test/r/subselect_innodb.result +++ b/mysql-test/r/subselect_innodb.result @@ -496,6 +496,21 @@ HAVING SQ2_alias1 . col_int_key >= 7 drop table t1; set optimizer_switch=@subselect_innodb_tmp; # +# MDEV-9635:Server crashes in part_of_refkey or assertion +# `!created && key_to_save < (int)s->keys' failed in +# TABLE::use_index(int) or with join_cache_level>2 +# +SET join_cache_level=3; +CREATE TABLE t1 (f1 VARCHAR(1024)) ENGINE=InnoDB; +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 (f2 VARCHAR(4)) ENGINE=InnoDB; +INSERT INTO t2 VALUES ('foo'),('bar'); +SELECT * FROM v1, t2 WHERE ( f1, f2 ) IN ( SELECT f1, f1 FROM t1 ); +f1 f2 +set join_cache_level = default; +drop view v1; +drop table t1,t2; +# # MDEV-6041: ORDER BY+subqueries: subquery_table.key=outer_table.col is not recongized as binding # create table t1(a int) engine=innodb; diff --git a/mysql-test/suite/innodb/r/log_file_size.result b/mysql-test/suite/innodb/r/log_file_size.result index d0b389379e7..67794f293aa 100644 --- a/mysql-test/suite/innodb/r/log_file_size.result +++ b/mysql-test/suite/innodb/r/log_file_size.result @@ -20,28 +20,24 @@ 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 +FOUND /InnoDB: Starting crash recovery from checkpoint LSN=/ 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 +FOUND /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 +FOUND /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 +FOUND /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; diff --git a/mysql-test/suite/innodb/t/log_file_size.test b/mysql-test/suite/innodb/t/log_file_size.test index ae63ee6e133..bf307123734 100644 --- a/mysql-test/suite/innodb/t/log_file_size.test +++ b/mysql-test/suite/innodb/t/log_file_size.test @@ -76,15 +76,13 @@ let SEARCH_PATTERN= syntax error in innodb_log_group_home_dir; --source include/restart_mysqld.inc --error ER_UNKNOWN_STORAGE_ENGINE SELECT * FROM t1; -let SEARCH_PATTERN= InnoDB: Starting an apply batch of log records; +let SEARCH_PATTERN= InnoDB: Starting crash recovery from checkpoint LSN=; --source include/search_pattern_in_file.inc --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 --let $restart_parameters= --innodb-read-only --source include/restart_mysqld.inc @@ -98,18 +96,14 @@ let SEARCH_PATTERN= InnoDB: innodb_read_only prevents crash recovery; --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; +let SEARCH_PATTERN= redo log from 3\*[0-9]+ to 2\*[0-9]+ pages; --source include/search_pattern_in_file.inc --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; +let SEARCH_PATTERN= redo log from 3\*[0-9]+ to 2\*[0-9]+ pages; --source include/search_pattern_in_file.inc --let $restart_parameters= --innodb-read-only @@ -124,9 +118,7 @@ let SEARCH_PATTERN= InnoDB: innodb_read_only prevents crash recovery; --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; +let SEARCH_PATTERN= redo log from 3\*[0-9]+ to 2\*[0-9]+ pages; --source include/search_pattern_in_file.inc --let $restart_parameters= --debug=d,innodb_log_abort_7 diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test index cb102f8319e..76b4df47a6a 100644 --- a/mysql-test/t/subselect4.test +++ b/mysql-test/t/subselect4.test @@ -1997,5 +1997,24 @@ EXECUTE stmt; drop table t1, t2, t3; +--echo # +--echo # MDEV-11078: NULL NOT IN (non-empty subquery) should never return results +--echo # + +create table t1(a int,b int); +create table t2(a int,b int); +insert into t1 value (1,2); +select (NULL) in (select 1 from t1); +select (null) in (select 1 from t2); +select 1 in (select 1 from t1); +select 1 in (select 1 from t2); +select 1 from dual where null in (select 1 from t1); +select 1 from dual where null in (select 1 from t2); +select (null,null) in (select * from t1); +select (null,null) in (select * from t2); +select 1 from dual where null not in (select 1 from t1); +select 1 from dual where null not in (select 1 from t2); +drop table t1,t2; + SET optimizer_switch= @@global.optimizer_switch; set @@tmp_table_size= @@global.tmp_table_size; diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test index af6ec90ba74..384464a9b7a 100644 --- a/mysql-test/t/subselect_innodb.test +++ b/mysql-test/t/subselect_innodb.test @@ -483,56 +483,21 @@ drop table t1; set optimizer_switch=@subselect_innodb_tmp; --echo # ---echo # MDEV-6041: ORDER BY+subqueries: subquery_table.key=outer_table.col is not recongized as binding +--echo # MDEV-9635:Server crashes in part_of_refkey or assertion +--echo # `!created && key_to_save < (int)s->keys' failed in +--echo # TABLE::use_index(int) or with join_cache_level>2 --echo # -create table t1(a int) engine=innodb; -insert into t1 values (0),(1),(2),(3),(4),(5),(6),(7),(8),(9); - -create table t2( - id int primary key, - key1 int, - col1 int, - key(key1) -) engine=innodb; -insert into t2 - select - A.a + B.a*10 + C.a*100 + D.a* 1000, - A.a + 10*B.a, - 123456 -from t1 A, t1 B, t1 C, t1 D; - ---echo # Table tsubq: ---echo # - must use 'ref' (not 'index'), and must not use 'Using filesort' ---echo # - shows a bad estimate for 'rows' (but I'm not sure if one can do better w/o histograms) -explain select - (SELECT - concat(id, '-', key1, '-', col1) - FROM t2 - WHERE t2.key1 = t1.a - ORDER BY t2.id ASC LIMIT 1) -from - t1; +SET join_cache_level=3; ---echo # ---echo # MDEV-6081: ORDER BY+ref(const): selectivity is very incorrect (MySQL Bug#14338686) ---echo # +CREATE TABLE t1 (f1 VARCHAR(1024)) ENGINE=InnoDB; +CREATE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; -alter table t2 add key2 int; -update t2 set key2=key1; -alter table t2 add key(key2); -analyze table t2; -flush tables; ---echo # Table tsubq must use 'ref' + Using filesort (not 'index' w/o filesort) ---replace_column 9 # -explain select - (SELECT - concat(id, '-', key1, '-', col1) - FROM t2 - WHERE t2.key1 = t1.a - ORDER BY t2.key2 ASC LIMIT 1) -from - t1; +CREATE TABLE t2 (f2 VARCHAR(4)) ENGINE=InnoDB; +INSERT INTO t2 VALUES ('foo'),('bar'); -drop table t1,t2; +SELECT * FROM v1, t2 WHERE ( f1, f2 ) IN ( SELECT f1, f1 FROM t1 ); +set join_cache_level = default; +drop view v1; +drop table t1,t2; diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index 3b93d3277a6..de0b7bfae8e 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -15,7 +15,7 @@ #define PLUGIN_VERSION 0x104 -#define PLUGIN_STR_VERSION "1.4.0" +#define PLUGIN_STR_VERSION "1.4.1" #define _my_thread_var loc_thread_var diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 8cff6a1e6c8..e87db62bd98 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -2048,6 +2048,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, We can encounter "NULL IN (SELECT ...)". Wrap the added condition within a trig_cond. */ + disable_cond_guard_for_const_null_left_expr(0); item= new Item_func_trig_cond(item, get_cond_guard(0)); } @@ -2072,6 +2073,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, having= new Item_is_not_null_test(this, having); if (left_expr->maybe_null) { + disable_cond_guard_for_const_null_left_expr(0); if (!(having= new Item_func_trig_cond(having, get_cond_guard(0)))) DBUG_RETURN(true); @@ -2090,6 +2092,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, */ if (!abort_on_null && left_expr->maybe_null) { + disable_cond_guard_for_const_null_left_expr(0); if (!(item= new Item_func_trig_cond(item, get_cond_guard(0)))) DBUG_RETURN(true); } @@ -2116,6 +2119,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, (char *)"<result>")); if (!abort_on_null && left_expr->maybe_null) { + disable_cond_guard_for_const_null_left_expr(0); if (!(new_having= new Item_func_trig_cond(new_having, get_cond_guard(0)))) DBUG_RETURN(true); @@ -2311,6 +2315,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, Item *col_item= new Item_cond_or(item_eq, item_isnull); if (!abort_on_null && left_expr->element_index(i)->maybe_null) { + disable_cond_guard_for_const_null_left_expr(i); if (!(col_item= new Item_func_trig_cond(col_item, get_cond_guard(i)))) DBUG_RETURN(true); } @@ -2325,6 +2330,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, (char *)"<list ref>")); if (!abort_on_null && left_expr->element_index(i)->maybe_null) { + disable_cond_guard_for_const_null_left_expr(i); if (!(item_nnull_test= new Item_func_trig_cond(item_nnull_test, get_cond_guard(i)))) DBUG_RETURN(true); @@ -2381,6 +2387,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, item= new Item_cond_or(item, item_isnull); if (left_expr->element_index(i)->maybe_null) { + disable_cond_guard_for_const_null_left_expr(i); if (!(item= new Item_func_trig_cond(item, get_cond_guard(i)))) DBUG_RETURN(true); if (!(having_col_item= diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 0c62c3f8d02..f457eb92e3e 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -619,6 +619,15 @@ public: bool expr_cache_is_needed(THD *thd); inline bool left_expr_has_null(); + void disable_cond_guard_for_const_null_left_expr(int i) + { + if (left_expr->const_item() && !left_expr->is_expensive()) + { + if (left_expr->element_index(i)->is_null()) + set_cond_guard_var(i,FALSE); + } + } + int optimize(double *out_rows, double *cost); /* Return the identifier that we could use to identify the subquery for the diff --git a/sql/log_slow.h b/sql/log_slow.h index 3ae2060cc27..aea5b149263 100644 --- a/sql/log_slow.h +++ b/sql/log_slow.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Monty Program Ab +/* Copyright (C) 2009, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -16,23 +16,22 @@ /* Defining what to log to slow log */ #define LOG_SLOW_VERBOSITY_INIT 0 -#define LOG_SLOW_VERBOSITY_INNODB (1 << 0) -#define LOG_SLOW_VERBOSITY_QUERY_PLAN (1 << 1) -#define LOG_SLOW_VERBOSITY_EXPLAIN (1 << 2) +#define LOG_SLOW_VERBOSITY_INNODB (1U << 0) +#define LOG_SLOW_VERBOSITY_QUERY_PLAN (1U << 1) +#define LOG_SLOW_VERBOSITY_EXPLAIN (1U << 2) #define QPLAN_INIT QPLAN_QC_NO -#define QPLAN_ADMIN (1 << 0) -#define QPLAN_FILESORT (1 << 1) -#define QPLAN_FILESORT_DISK (1 << 2) -#define QPLAN_FULL_JOIN (1 << 3) -#define QPLAN_FULL_SCAN (1 << 4) -#define QPLAN_QC (1 << 5) -#define QPLAN_QC_NO (1 << 6) -#define QPLAN_TMP_DISK (1 << 7) -#define QPLAN_TMP_TABLE (1 << 8) -#define QPLAN_FILESORT_PRIORITY_QUEUE (1 << 9) - +#define QPLAN_ADMIN (1U << 0) +#define QPLAN_FILESORT (1U << 1) +#define QPLAN_FILESORT_DISK (1U << 2) +#define QPLAN_FULL_JOIN (1U << 3) +#define QPLAN_FULL_SCAN (1U << 4) +#define QPLAN_QC (1U << 5) +#define QPLAN_QC_NO (1U << 6) +#define QPLAN_TMP_DISK (1U << 7) +#define QPLAN_TMP_TABLE (1U << 8) +#define QPLAN_FILESORT_PRIORITY_QUEUE (1U << 9) + /* ... */ -#define QPLAN_MAX (((ulong) 1) << 31) /* reserved as placeholder */ - +#define QPLAN_MAX (1U << 31) /* reserved as placeholder */ diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d459d0b88bf..c9ad3f48d9d 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -10149,7 +10149,7 @@ void JOIN::drop_unused_derived_keys() continue; if (!table->pos_in_table_list->is_materialized_derived()) continue; - if (table->max_keys > 1) + if (table->max_keys > 1 && !tab->is_ref_for_hash_join()) table->use_index(tab->ref.key); if (table->s->keys) { diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h index f4c7b4ed882..bf34b6a3e29 100644 --- a/storage/innobase/include/log0recv.h +++ b/storage/innobase/include/log0recv.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -271,20 +272,12 @@ void recv_sys_var_init(void); /*===================*/ #endif /* !UNIV_HOTBACKUP */ -/*******************************************************************//** -Empties the hash table of stored log records, applying them to appropriate -pages. */ +/** Apply the hash table of stored log records to persistent data pages. +@param[in] last_batch whether the change buffer merge will be + performed as part of the operation */ UNIV_INTERN void -recv_apply_hashed_log_recs( -/*=======================*/ - ibool allow_ibuf); /*!< in: if TRUE, also ibuf operations are - allowed during the application; if FALSE, - no ibuf operations are allowed, and after - the application all file pages are flushed to - disk and invalidated in buffer pool: this - alternative means that no new log records - can be generated during the application */ +recv_apply_hashed_log_recs(bool last_batch); #ifdef UNIV_HOTBACKUP /*******************************************************************//** Applies log records in the hash table to a backup. */ @@ -434,6 +427,8 @@ struct recv_sys_t{ scan find a corrupt log block, or a corrupt log record, or there is a log parsing buffer overflow */ + /** the time when progress was last reported */ + ib_time_t progress_time; #ifdef UNIV_LOG_ARCHIVE log_group_t* archive_group; /*!< in archive recovery: the log group whose @@ -446,6 +441,20 @@ struct recv_sys_t{ addresses in the hash table */ recv_dblwr_t dblwr; + + /** Determine whether redo log recovery progress should be reported. + @param[in] time the current time + @return whether progress should be reported + (the last report was at least 15 seconds ago) */ + bool report(ib_time_t time) + { + if (time - progress_time < 15) { + return false; + } + + progress_time = time; + return true; + } }; /** The recovery system */ diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index 57516d7c8f4..b94a6d30c7d 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. -Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1746,7 +1746,7 @@ log_preflush_pool_modified_pages( and we could not make a new checkpoint on the basis of the info on the buffer pool only. */ - recv_apply_hashed_log_recs(TRUE); + recv_apply_hashed_log_recs(true); } success = buf_flush_list(ULINT_MAX, new_oldest, &n_pages); @@ -2085,7 +2085,7 @@ log_checkpoint( ut_ad(!srv_read_only_mode); if (recv_recovery_is_on()) { - recv_apply_hashed_log_recs(TRUE); + recv_apply_hashed_log_recs(true); } if (srv_unix_file_flush_method != SRV_UNIX_NOSYNC) { @@ -2336,6 +2336,11 @@ loop: start_lsn += len; buf += len; + if (recv_sys->report(ut_time())) { + ib_logf(IB_LOG_LEVEL_INFO, "Read redo log up to LSN=" LSN_PF, + start_lsn); + } + if (start_lsn != end_lsn) { goto loop; diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 6137c84b21d..a90041aaa90 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/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) 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -73,7 +73,7 @@ this must be less than UNIV_PAGE_SIZE as it is stored in the buffer pool */ #define RECV_READ_AHEAD_AREA 32 /** The recovery system */ -UNIV_INTERN recv_sys_t* recv_sys = NULL; +UNIV_INTERN recv_sys_t* recv_sys; /** TRUE when applying redo log records during crash recovery; FALSE otherwise. Note that this is FALSE while a background thread is rolling back incomplete transactions. */ @@ -129,9 +129,6 @@ UNIV_INTERN ibool recv_is_making_a_backup = FALSE; UNIV_INTERN ibool recv_is_from_backup = FALSE; # define buf_pool_get_curr_size() (5 * 1024 * 1024) #endif /* !UNIV_HOTBACKUP */ -/** The following counter is used to decide when to print info on -log scan */ -static ulint recv_scan_print_counter; /** The type of the previous parsed redo log record */ static ulint recv_previous_parsed_rec_type; @@ -306,8 +303,6 @@ recv_sys_var_init(void) recv_no_ibuf_operations = FALSE; - recv_scan_print_counter = 0; - recv_previous_parsed_rec_type = 999999; recv_previous_parsed_rec_offset = 0; @@ -418,6 +413,7 @@ recv_sys_init( recv_sys->last_block_buf_start, OS_FILE_LOG_BLOCK_SIZE)); recv_sys->found_corrupt_log = FALSE; + recv_sys->progress_time = ut_time(); recv_max_page_lsn = 0; @@ -1587,6 +1583,7 @@ recv_recover_page_func( ibool success; #endif /* !UNIV_HOTBACKUP */ mtr_t mtr; + ib_time_t time; mutex_enter(&(recv_sys->mutex)); @@ -1762,6 +1759,8 @@ recv_recover_page_func( mtr_commit(&mtr); + time = ut_time(); + mutex_enter(&(recv_sys->mutex)); if (recv_max_page_lsn < page_lsn) { @@ -1770,11 +1769,16 @@ recv_recover_page_func( recv_addr->state = RECV_PROCESSED; - ut_a(recv_sys->n_addrs); - recv_sys->n_addrs--; - - mutex_exit(&(recv_sys->mutex)); + ut_a(recv_sys->n_addrs > 0); + if (--recv_sys->n_addrs && recv_sys->progress_time - time >= 15) { + recv_sys->progress_time = time; + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: To recover: " ULINTPF " pages from log\n", + recv_sys->n_addrs); + } + mutex_exit(&recv_sys->mutex); } #ifndef UNIV_HOTBACKUP @@ -1820,59 +1824,48 @@ recv_read_in_area( } buf_read_recv_pages(FALSE, space, zip_size, page_nos, n); - /* - fprintf(stderr, "Recv pages at %lu n %lu\n", page_nos[0], n); - */ return(n); } -/*******************************************************************//** -Empties the hash table of stored log records, applying them to appropriate -pages. */ +/** Apply the hash table of stored log records to persistent data pages. +@param[in] last_batch whether the change buffer merge will be + performed as part of the operation */ UNIV_INTERN void -recv_apply_hashed_log_recs( -/*=======================*/ - ibool allow_ibuf) /*!< in: if TRUE, also ibuf operations are - allowed during the application; if FALSE, - no ibuf operations are allowed, and after - the application all file pages are flushed to - disk and invalidated in buffer pool: this - alternative means that no new log records - can be generated during the application; - the caller must in this case own the log - mutex */ +recv_apply_hashed_log_recs(bool last_batch) { - recv_addr_t* recv_addr; - ulint i; - ibool has_printed = FALSE; - mtr_t mtr; -loop: - mutex_enter(&(recv_sys->mutex)); - - if (recv_sys->apply_batch_on) { + for (;;) { + mutex_enter(&recv_sys->mutex); - mutex_exit(&(recv_sys->mutex)); + if (!recv_sys->apply_batch_on) { + break; + } + mutex_exit(&recv_sys->mutex); os_thread_sleep(500000); - - goto loop; } - ut_ad((!allow_ibuf) == mutex_own(&log_sys->mutex)); + ut_ad(!last_batch == mutex_own(&log_sys->mutex)); - if (!allow_ibuf) { + if (!last_batch) { recv_no_ibuf_operations = TRUE; } + if (ulint n = recv_sys->n_addrs) { + const char* msg = last_batch + ? "Starting final batch to recover " + : "Starting a batch to recover "; + ib_logf(IB_LOG_LEVEL_INFO, + "%s" ULINTPF " pages from redo log", msg, n); + } + recv_sys->apply_log_recs = TRUE; recv_sys->apply_batch_on = TRUE; - for (i = 0; i < hash_get_n_cells(recv_sys->addr_hash); i++) { - - for (recv_addr = static_cast<recv_addr_t*>( - HASH_GET_FIRST(recv_sys->addr_hash, i)); - recv_addr != 0; + for (ulint i = 0; i < hash_get_n_cells(recv_sys->addr_hash); i++) { + for (recv_addr_t* recv_addr = static_cast<recv_addr_t*>( + HASH_GET_FIRST(recv_sys->addr_hash, i)); + recv_addr; recv_addr = static_cast<recv_addr_t*>( HASH_GET_NEXT(addr_hash, recv_addr))) { @@ -1881,24 +1874,12 @@ loop: ulint page_no = recv_addr->page_no; if (recv_addr->state == RECV_NOT_PROCESSED) { - if (!has_printed) { - ib_logf(IB_LOG_LEVEL_INFO, - "Starting an apply batch" - " of log records" - " to the database..."); - fputs("InnoDB: Progress in percent: ", - stderr); - has_printed = TRUE; - } - - mutex_exit(&(recv_sys->mutex)); + mutex_exit(&recv_sys->mutex); if (buf_page_peek(space, page_no)) { - buf_block_t* block; - + mtr_t mtr; mtr_start(&mtr); - - block = buf_page_get( + buf_block_t* block = buf_page_get( space, zip_size, page_no, RW_X_LATCH, &mtr); buf_block_dbg_add_level( @@ -1911,19 +1892,9 @@ loop: page_no); } - mutex_enter(&(recv_sys->mutex)); + mutex_enter(&recv_sys->mutex); } } - - if (has_printed - && (i * 100) / hash_get_n_cells(recv_sys->addr_hash) - != ((i + 1) * 100) - / hash_get_n_cells(recv_sys->addr_hash)) { - - fprintf(stderr, "%lu ", (ulong) - ((i * 100) - / hash_get_n_cells(recv_sys->addr_hash))); - } } /* Wait until all the pages have been processed */ @@ -1937,12 +1908,7 @@ loop: mutex_enter(&(recv_sys->mutex)); } - if (has_printed) { - - fprintf(stderr, "\n"); - } - - if (!allow_ibuf) { + if (!last_batch) { bool success; /* Flush all the file pages to disk and invalidate them in @@ -1982,11 +1948,7 @@ loop: recv_sys_empty_hash(); - if (has_printed) { - fprintf(stderr, "InnoDB: Apply batch completed\n"); - } - - mutex_exit(&(recv_sys->mutex)); + mutex_exit(&recv_sys->mutex); } #else /* !UNIV_HOTBACKUP */ /*******************************************************************//** @@ -2009,11 +1971,6 @@ recv_apply_log_recs_for_backup(void) block = back_block1; - ib_logf(IB_LOG_LEVEL_INFO, - "Starting an apply batch of log records to the database..."); - - fputs("InnoDB: Progress in percent: ", stderr); - n_hash_cells = hash_get_n_cells(recv_sys->addr_hash); for (i = 0; i < n_hash_cells; i++) { @@ -2125,13 +2082,6 @@ recv_apply_log_recs_for_backup(void) skip_this_recv_addr: recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); } - - if ((100 * i) / n_hash_cells - != (100 * (i + 1)) / n_hash_cells) { - fprintf(stderr, "%lu ", - (ulong) ((100 * i) / n_hash_cells)); - fflush(stderr); - } } recv_sys_empty_hash(); @@ -2795,11 +2745,10 @@ recv_scan_log_recs( #ifndef UNIV_HOTBACKUP if (recv_log_scan_is_startup_type && !recv_needed_recovery) { - if (!srv_read_only_mode) { ib_logf(IB_LOG_LEVEL_INFO, - "Log scan progressed past the " - "checkpoint lsn " LSN_PF "", + "Starting crash recovery from " + "checkpoint LSN=" LSN_PF, recv_sys->scanned_lsn); recv_init_crash_recovery(); @@ -2858,19 +2807,6 @@ recv_scan_log_recs( *group_scanned_lsn = scanned_lsn; - if (recv_needed_recovery - || (recv_is_from_backup && !recv_is_making_a_backup)) { - recv_scan_print_counter++; - - if (finished || (recv_scan_print_counter % 80 == 0)) { - - fprintf(stderr, - "InnoDB: Doing recovery: scanned up to" - " log sequence number " LSN_PF "\n", - *group_scanned_lsn); - } - } - if (more_data && !recv_sys->found_corrupt_log) { /* Try to parse more log records */ @@ -2886,7 +2822,7 @@ recv_scan_log_recs( log yet: they would be produced by ibuf operations */ - recv_apply_hashed_log_recs(FALSE); + recv_apply_hashed_log_recs(false); } #endif /* !UNIV_HOTBACKUP */ @@ -2962,11 +2898,6 @@ recv_init_crash_recovery(void) recv_needed_recovery = TRUE; - ib_logf(IB_LOG_LEVEL_INFO, "Database was not shutdown normally!"); - ib_logf(IB_LOG_LEVEL_INFO, "Starting crash recovery."); - ib_logf(IB_LOG_LEVEL_INFO, - "Reading tablespace information from the .ibd files..."); - fil_load_single_table_tablespaces(); /* If we are using the doublewrite method, we will @@ -2977,9 +2908,7 @@ recv_init_crash_recovery(void) if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { ib_logf(IB_LOG_LEVEL_INFO, - "Restoring possible half-written data pages "); - - ib_logf(IB_LOG_LEVEL_INFO, + "Restoring possible half-written data pages " "from the doublewrite buffer..."); buf_dblwr_process(); @@ -3950,7 +3879,7 @@ recv_recovery_from_archive_start( if (limit_lsn != LSN_MAX) { - recv_apply_hashed_log_recs(FALSE); + recv_apply_hashed_log_recs(false); recv_reset_logs(0, FALSE, recv_sys->recovered_lsn); } diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 5fd3adb3191..127ccb34f52 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, 2017, 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 @@ -2520,7 +2520,7 @@ files_checked: } } - /* This must precede recv_apply_hashed_log_recs(TRUE). */ + /* 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) { @@ -2528,7 +2528,7 @@ files_checked: respective file pages, for the last batch of recv_group_scan_log_recs(). */ - recv_apply_hashed_log_recs(TRUE); + recv_apply_hashed_log_recs(true); DBUG_PRINT("ib_log", ("apply completed")); } diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 3e0872b9a89..01197ddae6d 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -1,6 +1,6 @@ /* Copyright (C) 2004-2008 MySQL AB & MySQL Finland AB & TCX DataKonsult AB Copyright (C) 2008-2009 Sun Microsystems, Inc. - Copyright (c) 2009, 2014, SkySQL Ab. + Copyright (c) 2009, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1284,75 +1284,75 @@ int ha_maria::write_row(uchar * buf) int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt) { int error; - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); MARIA_SHARE *share= file->s; const char *old_proc_info; TRN *old_trn= file->trn; - if (!file || !¶m) return HA_ADMIN_INTERNAL_ERROR; + if (!file || !param) return HA_ADMIN_INTERNAL_ERROR; - maria_chk_init(¶m); - param.thd= thd; - param.op_name= "check"; - param.db_name= table->s->db.str; - param.table_name= table->alias.c_ptr(); - param.testflag= check_opt->flags | T_CHECK | T_SILENT; - param.stats_method= (enum_handler_stats_method)THDVAR(thd,stats_method); + maria_chk_init(param); + param->thd= thd; + param->op_name= "check"; + param->db_name= table->s->db.str; + param->table_name= table->alias.c_ptr(); + param->testflag= check_opt->flags | T_CHECK | T_SILENT; + param->stats_method= (enum_handler_stats_method)THDVAR(thd,stats_method); if (!(table->db_stat & HA_READ_ONLY)) - param.testflag |= T_STATISTICS; - param.using_global_keycache= 1; + param->testflag |= T_STATISTICS; + param->using_global_keycache= 1; if (!maria_is_crashed(file) && - (((param.testflag & T_CHECK_ONLY_CHANGED) && + (((param->testflag & T_CHECK_ONLY_CHANGED) && !(share->state.changed & (STATE_CHANGED | STATE_CRASHED_FLAGS | STATE_IN_REPAIR)) && share->state.open_count == 0) || - ((param.testflag & T_FAST) && (share->state.open_count == + ((param->testflag & T_FAST) && (share->state.open_count == (uint) (share->global_changed ? 1 : 0))))) return HA_ADMIN_ALREADY_DONE; - maria_chk_init_for_check(¶m, file); + maria_chk_init_for_check(param, file); if ((file->s->state.changed & (STATE_CRASHED_FLAGS | STATE_MOVED)) == STATE_MOVED) { - _ma_check_print_error(¶m, "%s", zerofill_error_msg); + _ma_check_print_error(param, "%s", zerofill_error_msg); return HA_ADMIN_CORRUPT; } old_proc_info= thd_proc_info(thd, "Checking status"); thd_progress_init(thd, 3); - error= maria_chk_status(¶m, file); // Not fatal - if (maria_chk_size(¶m, file)) + error= maria_chk_status(param, file); // Not fatal + if (maria_chk_size(param, file)) error= 1; if (!error) - error|= maria_chk_del(¶m, file, param.testflag); + error|= maria_chk_del(param, file, param->testflag); thd_proc_info(thd, "Checking keys"); thd_progress_next_stage(thd); if (!error) - error= maria_chk_key(¶m, file); + error= maria_chk_key(param, file); thd_proc_info(thd, "Checking data"); thd_progress_next_stage(thd); if (!error) { - if ((!(param.testflag & T_QUICK) && + if ((!(param->testflag & T_QUICK) && ((share->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) || - (param.testflag & (T_EXTEND | T_MEDIUM)))) || maria_is_crashed(file)) + (param->testflag & (T_EXTEND | T_MEDIUM)))) || maria_is_crashed(file)) { - ulonglong old_testflag= param.testflag; - param.testflag |= T_MEDIUM; - if (!(error= init_io_cache(¶m.read_cache, file->dfile.file, + ulonglong old_testflag= param->testflag; + param->testflag |= T_MEDIUM; + if (!(error= init_io_cache(¶m->read_cache, file->dfile.file, my_default_record_cache_size, READ_CACHE, share->pack.header_length, 1, MYF(MY_WME)))) { - error= maria_chk_data_link(¶m, file, - MY_TEST(param.testflag & T_EXTEND)); - end_io_cache(&(param.read_cache)); + error= maria_chk_data_link(param, file, + MY_TEST(param->testflag & T_EXTEND)); + end_io_cache(¶m->read_cache); } - param.testflag= old_testflag; + param->testflag= old_testflag; } } if (!error) @@ -1360,7 +1360,7 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt) if ((share->state.changed & (STATE_CHANGED | STATE_CRASHED_FLAGS | STATE_IN_REPAIR | STATE_NOT_ANALYZED)) || - (param.testflag & T_STATISTICS) || maria_is_crashed(file)) + (param->testflag & T_STATISTICS) || maria_is_crashed(file)) { file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; mysql_mutex_lock(&share->intern_lock); @@ -1368,7 +1368,7 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt) share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED_FLAGS | STATE_IN_REPAIR); if (!(table->db_stat & HA_READ_ONLY)) - error= maria_update_state_info(¶m, file, + error= maria_update_state_info(param, file, UPDATE_TIME | UPDATE_OPEN_COUNT | UPDATE_STAT); mysql_mutex_unlock(&share->intern_lock); @@ -1399,33 +1399,33 @@ int ha_maria::check(THD * thd, HA_CHECK_OPT * check_opt) int ha_maria::analyze(THD *thd, HA_CHECK_OPT * check_opt) { int error= 0; - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); MARIA_SHARE *share= file->s; const char *old_proc_info; - if (!¶m) + if (!param) return HA_ADMIN_INTERNAL_ERROR; - maria_chk_init(¶m); - param.thd= thd; - param.op_name= "analyze"; - param.db_name= table->s->db.str; - param.table_name= table->alias.c_ptr(); - param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS | + maria_chk_init(param); + param->thd= thd; + param->op_name= "analyze"; + param->db_name= table->s->db.str; + param->table_name= table->alias.c_ptr(); + param->testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS | T_DONT_CHECK_CHECKSUM); - param.using_global_keycache= 1; - param.stats_method= (enum_handler_stats_method)THDVAR(thd,stats_method); + param->using_global_keycache= 1; + param->stats_method= (enum_handler_stats_method)THDVAR(thd,stats_method); if (!(share->state.changed & STATE_NOT_ANALYZED)) return HA_ADMIN_ALREADY_DONE; old_proc_info= thd_proc_info(thd, "Scanning"); thd_progress_init(thd, 1); - error= maria_chk_key(¶m, file); + error= maria_chk_key(param, file); if (!error) { mysql_mutex_lock(&share->intern_lock); - error= maria_update_state_info(¶m, file, UPDATE_STAT); + error= maria_update_state_info(param, file, UPDATE_STAT); mysql_mutex_unlock(&share->intern_lock); } else if (!maria_is_crashed(file) && !thd->killed) @@ -1438,46 +1438,46 @@ int ha_maria::analyze(THD *thd, HA_CHECK_OPT * check_opt) int ha_maria::repair(THD * thd, HA_CHECK_OPT *check_opt) { int error; - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); ha_rows start_records; const char *old_proc_info; - if (!file || !¶m) + if (!file || !param) return HA_ADMIN_INTERNAL_ERROR; - maria_chk_init(¶m); - param.thd= thd; - param.op_name= "repair"; - param.testflag= ((check_opt->flags & ~(T_EXTEND)) | + maria_chk_init(param); + param->thd= thd; + param->op_name= "repair"; + param->testflag= ((check_opt->flags & ~(T_EXTEND)) | T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM | (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT)); - param.sort_buffer_length= THDVAR(thd, sort_buffer_size); - param.backup_time= check_opt->start_time; + param->sort_buffer_length= THDVAR(thd, sort_buffer_size); + param->backup_time= check_opt->start_time; start_records= file->state->records; old_proc_info= thd_proc_info(thd, "Checking table"); thd_progress_init(thd, 1); - while ((error= repair(thd, ¶m, 0)) && param.retry_repair) + while ((error= repair(thd, param, 0)) && param->retry_repair) { - param.retry_repair= 0; - if (test_all_bits(param.testflag, + param->retry_repair= 0; + if (test_all_bits(param->testflag, (uint) (T_RETRY_WITHOUT_QUICK | T_QUICK))) { - param.testflag&= ~(T_RETRY_WITHOUT_QUICK | T_QUICK); + param->testflag&= ~(T_RETRY_WITHOUT_QUICK | T_QUICK); /* Ensure we don't loose any rows when retrying without quick */ - param.testflag|= T_SAFE_REPAIR; + param->testflag|= T_SAFE_REPAIR; if (thd->vio_ok()) - _ma_check_print_info(¶m, "Retrying repair without quick"); + _ma_check_print_info(param, "Retrying repair without quick"); else sql_print_information("Retrying repair of: '%s' without quick", table->s->path.str); continue; } - param.testflag &= ~T_QUICK; - if ((param.testflag & T_REP_BY_SORT)) + param->testflag &= ~T_QUICK; + if (param->testflag & T_REP_BY_SORT) { - param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP; + param->testflag= (param->testflag & ~T_REP_BY_SORT) | T_REP; if (thd->vio_ok()) - _ma_check_print_info(¶m, "Retrying repair with keycache"); + _ma_check_print_info(param, "Retrying repair with keycache"); sql_print_information("Retrying repair of: '%s' with keycache", table->s->path.str); continue; @@ -1501,20 +1501,20 @@ int ha_maria::repair(THD * thd, HA_CHECK_OPT *check_opt) int ha_maria::zerofill(THD * thd, HA_CHECK_OPT *check_opt) { int error; - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); TRN *old_trn; MARIA_SHARE *share= file->s; - if (!file || !¶m) + if (!file || !param) return HA_ADMIN_INTERNAL_ERROR; old_trn= file->trn; - maria_chk_init(¶m); - param.thd= thd; - param.op_name= "zerofill"; - param.testflag= check_opt->flags | T_SILENT | T_ZEROFILL; - param.sort_buffer_length= THDVAR(thd, sort_buffer_size); - error=maria_zerofill(¶m, file, share->open_file_name.str); + maria_chk_init(param); + param->thd= thd; + param->op_name= "zerofill"; + param->testflag= check_opt->flags | T_SILENT | T_ZEROFILL; + param->sort_buffer_length= THDVAR(thd, sort_buffer_size); + error=maria_zerofill(param, file, share->open_file_name.str); /* Reset trn, that may have been set by repair */ _ma_set_trn_for_table(file, old_trn); @@ -1524,7 +1524,7 @@ int ha_maria::zerofill(THD * thd, HA_CHECK_OPT *check_opt) TrID create_trid= trnman_get_min_safe_trid(); mysql_mutex_lock(&share->intern_lock); share->state.changed|= STATE_NOT_MOVABLE; - maria_update_state_info(¶m, file, UPDATE_TIME | UPDATE_OPEN_COUNT); + maria_update_state_info(param, file, UPDATE_TIME | UPDATE_OPEN_COUNT); _ma_update_state_lsns_sub(share, LSN_IMPOSSIBLE, create_trid, TRUE, TRUE); mysql_mutex_unlock(&share->intern_lock); @@ -1535,24 +1535,24 @@ int ha_maria::zerofill(THD * thd, HA_CHECK_OPT *check_opt) int ha_maria::optimize(THD * thd, HA_CHECK_OPT *check_opt) { int error; - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); - if (!file || !¶m) + if (!file || !param) return HA_ADMIN_INTERNAL_ERROR; - maria_chk_init(¶m); - param.thd= thd; - param.op_name= "optimize"; - param.testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE | + maria_chk_init(param); + param->thd= thd; + param->op_name= "optimize"; + param->testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE | T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX); - param.sort_buffer_length= THDVAR(thd, sort_buffer_size); + param->sort_buffer_length= THDVAR(thd, sort_buffer_size); thd_progress_init(thd, 1); - if ((error= repair(thd, ¶m, 1)) && param.retry_repair) + if ((error= repair(thd, param, 1)) && param->retry_repair) { sql_print_warning("Warning: Optimize table got errno %d on %s.%s, retrying", - my_errno, param.db_name, param.table_name); - param.testflag &= ~T_REP_BY_SORT; - error= repair(thd, ¶m, 0); + my_errno, param->db_name, param->table_name); + param->testflag &= ~T_REP_BY_SORT; + error= repair(thd, param, 0); } thd_progress_end(thd); return error; @@ -1802,17 +1802,17 @@ int ha_maria::assign_to_keycache(THD * thd, HA_CHECK_OPT *check_opt) if (error != HA_ADMIN_OK) { /* Send error to user */ - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); - if (!¶m) + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); + if (!param) return HA_ADMIN_INTERNAL_ERROR; - maria_chk_init(¶m); - param.thd= thd; - param.op_name= "assign_to_keycache"; - param.db_name= table->s->db.str; - param.table_name= table->s->table_name.str; - param.testflag= 0; - _ma_check_print_error(¶m, errmsg); + maria_chk_init(param); + param->thd= thd; + param->op_name= "assign_to_keycache"; + param->db_name= table->s->db.str; + param->table_name= table->s->table_name.str; + param->testflag= 0; + _ma_check_print_error(param, errmsg); } DBUG_RETURN(error); #else @@ -1866,17 +1866,17 @@ int ha_maria::preload_keys(THD * thd, HA_CHECK_OPT *check_opt) errmsg= buf; } - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); - if (!¶m) + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); + if (!param) return HA_ADMIN_INTERNAL_ERROR; - maria_chk_init(¶m); - param.thd= thd; - param.op_name= "preload_keys"; - param.db_name= table->s->db.str; - param.table_name= table->s->table_name.str; - param.testflag= 0; - _ma_check_print_error(¶m, "%s", errmsg); + maria_chk_init(param); + param->thd= thd; + param->op_name= "preload_keys"; + param->db_name= table->s->db.str; + param->table_name= table->s->table_name.str; + param->testflag= 0; + _ma_check_print_error(param, "%s", errmsg); DBUG_RETURN(HA_ADMIN_FAILED); } DBUG_RETURN(HA_ADMIN_OK); @@ -1977,25 +1977,25 @@ int ha_maria::enable_indexes(uint mode) else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE) { THD *thd= table->in_use; - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); - if (!¶m) + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); + if (!param) return HA_ADMIN_INTERNAL_ERROR; const char *save_proc_info= thd_proc_info(thd, "Creating index"); - maria_chk_init(¶m); - param.op_name= "recreating_index"; - param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK | + maria_chk_init(param); + param->op_name= "recreating_index"; + param->testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK | T_CREATE_MISSING_KEYS | T_SAFE_REPAIR); /* Don't lock and unlock table if it's locked. Normally table should be locked. This test is mostly for safety. */ if (likely(file->lock_type != F_UNLCK)) - param.testflag|= T_NO_LOCKS; + param->testflag|= T_NO_LOCKS; if (file->create_unique_index_by_sort) - param.testflag|= T_CREATE_UNIQUE_BY_SORT; + param->testflag|= T_CREATE_UNIQUE_BY_SORT; if (bulk_insert_single_undo == BULK_INSERT_SINGLE_UNDO_AND_NO_REPAIR) { @@ -2004,23 +2004,23 @@ int ha_maria::enable_indexes(uint mode) Don't bump create_rename_lsn, because UNDO_BULK_INSERT should not be skipped in case of crash during repair. */ - param.testflag|= T_NO_CREATE_RENAME_LSN; + param->testflag|= T_NO_CREATE_RENAME_LSN; } - param.myf_rw &= ~MY_WAIT_IF_FULL; - param.sort_buffer_length= THDVAR(thd,sort_buffer_size); - param.stats_method= (enum_handler_stats_method)THDVAR(thd,stats_method); - param.tmpdir= &mysql_tmpdir_list; - if ((error= (repair(thd, ¶m, 0) != HA_ADMIN_OK)) && param.retry_repair) + param->myf_rw &= ~MY_WAIT_IF_FULL; + param->sort_buffer_length= THDVAR(thd,sort_buffer_size); + param->stats_method= (enum_handler_stats_method)THDVAR(thd,stats_method); + param->tmpdir= &mysql_tmpdir_list; + if ((error= (repair(thd, param, 0) != HA_ADMIN_OK)) && param->retry_repair) { sql_print_warning("Warning: Enabling keys got errno %d on %s.%s, " "retrying", - my_errno, param.db_name, param.table_name); + my_errno, param->db_name, param->table_name); /* This should never fail normally */ DBUG_ASSERT(thd->killed != 0); /* Repairing by sort failed. Now try standard repair method. */ - param.testflag &= ~T_REP_BY_SORT; - error= (repair(thd, ¶m, 0) != HA_ADMIN_OK); + param->testflag &= ~T_REP_BY_SORT; + error= (repair(thd, param, 0) != HA_ADMIN_OK); /* If the standard repair succeeded, clear all error messages which might have been set by the first repair. They can still be seen diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index 2b70518c8fd..2cfaa5ebdcc 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. - Copyright (c) 2009, 2014, SkySQL Ab. + Copyright (c) 2009, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -872,59 +872,59 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) { if (!file) return HA_ADMIN_INTERNAL_ERROR; int error; - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); MYISAM_SHARE* share = file->s; const char *old_proc_info=thd->proc_info; - if (!¶m) + if (!param) return HA_ADMIN_INTERNAL_ERROR; thd_proc_info(thd, "Checking table"); - myisamchk_init(¶m); - param.thd = thd; - param.op_name = "check"; - param.db_name= table->s->db.str; - param.table_name= table->alias.c_ptr(); - param.testflag = check_opt->flags | T_CHECK | T_SILENT; - param.stats_method= (enum_handler_stats_method)THDVAR(thd, stats_method); + myisamchk_init(param); + param->thd = thd; + param->op_name = "check"; + param->db_name= table->s->db.str; + param->table_name= table->alias.c_ptr(); + param->testflag = check_opt->flags | T_CHECK | T_SILENT; + param->stats_method= (enum_handler_stats_method)THDVAR(thd, stats_method); if (!(table->db_stat & HA_READ_ONLY)) - param.testflag|= T_STATISTICS; - param.using_global_keycache = 1; + param->testflag|= T_STATISTICS; + param->using_global_keycache = 1; if (!mi_is_crashed(file) && - (((param.testflag & T_CHECK_ONLY_CHANGED) && + (((param->testflag & T_CHECK_ONLY_CHANGED) && !(share->state.changed & (STATE_CHANGED | STATE_CRASHED | STATE_CRASHED_ON_REPAIR)) && share->state.open_count == 0) || - ((param.testflag & T_FAST) && (share->state.open_count == + ((param->testflag & T_FAST) && (share->state.open_count == (uint) (share->global_changed ? 1 : 0))))) return HA_ADMIN_ALREADY_DONE; - error = chk_status(¶m, file); // Not fatal - error = chk_size(¶m, file); + error = chk_status(param, file); // Not fatal + error = chk_size(param, file); if (!error) - error |= chk_del(¶m, file, param.testflag); + error |= chk_del(param, file, param->testflag); if (!error) - error = chk_key(¶m, file); + error = chk_key(param, file); if (!error) { - if ((!(param.testflag & T_QUICK) && + if ((!(param->testflag & T_QUICK) && ((share->options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) || - (param.testflag & (T_EXTEND | T_MEDIUM)))) || + (param->testflag & (T_EXTEND | T_MEDIUM)))) || mi_is_crashed(file)) { - ulonglong old_testflag= param.testflag; - param.testflag|=T_MEDIUM; - if (!(error= init_io_cache(¶m.read_cache, file->dfile, + ulonglong old_testflag= param->testflag; + param->testflag|=T_MEDIUM; + if (!(error= init_io_cache(¶m->read_cache, file->dfile, my_default_record_cache_size, READ_CACHE, share->pack.header_length, 1, MYF(MY_WME)))) { - error= chk_data_link(¶m, file, MY_TEST(param.testflag & T_EXTEND)); - end_io_cache(&(param.read_cache)); + error= chk_data_link(param, file, MY_TEST(param->testflag & T_EXTEND)); + end_io_cache(¶m->read_cache); } - param.testflag= old_testflag; + param->testflag= old_testflag; } } if (!error) @@ -932,7 +932,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) if ((share->state.changed & (STATE_CHANGED | STATE_CRASHED_ON_REPAIR | STATE_CRASHED | STATE_NOT_ANALYZED)) || - (param.testflag & T_STATISTICS) || + (param->testflag & T_STATISTICS) || mi_is_crashed(file)) { file->update|=HA_STATE_CHANGED | HA_STATE_ROW_CHANGED; @@ -940,7 +940,7 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) share->state.changed&= ~(STATE_CHANGED | STATE_CRASHED | STATE_CRASHED_ON_REPAIR); if (!(table->db_stat & HA_READ_ONLY)) - error=update_state_info(¶m,file,UPDATE_TIME | UPDATE_OPEN_COUNT | + error=update_state_info(param,file,UPDATE_TIME | UPDATE_OPEN_COUNT | UPDATE_STAT); mysql_mutex_unlock(&share->intern_lock); info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE | @@ -967,30 +967,30 @@ int ha_myisam::check(THD* thd, HA_CHECK_OPT* check_opt) int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt) { int error=0; - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); MYISAM_SHARE* share = file->s; - if (!¶m) + if (!param) return HA_ADMIN_INTERNAL_ERROR; - myisamchk_init(¶m); - param.thd = thd; - param.op_name= "analyze"; - param.db_name= table->s->db.str; - param.table_name= table->alias.c_ptr(); - param.testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS | + myisamchk_init(param); + param->thd = thd; + param->op_name= "analyze"; + param->db_name= table->s->db.str; + param->table_name= table->alias.c_ptr(); + param->testflag= (T_FAST | T_CHECK | T_SILENT | T_STATISTICS | T_DONT_CHECK_CHECKSUM); - param.using_global_keycache = 1; - param.stats_method= (enum_handler_stats_method)THDVAR(thd, stats_method); + param->using_global_keycache = 1; + param->stats_method= (enum_handler_stats_method)THDVAR(thd, stats_method); if (!(share->state.changed & STATE_NOT_ANALYZED)) return HA_ADMIN_ALREADY_DONE; - error = chk_key(¶m, file); + error = chk_key(param, file); if (!error) { mysql_mutex_lock(&share->intern_lock); - error=update_state_info(¶m,file,UPDATE_STAT); + error=update_state_info(param,file,UPDATE_STAT); mysql_mutex_unlock(&share->intern_lock); } else if (!mi_is_crashed(file) && !thd->killed) @@ -1002,37 +1002,37 @@ int ha_myisam::analyze(THD *thd, HA_CHECK_OPT* check_opt) int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) { int error; - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); ha_rows start_records; - if (!file || !¶m) return HA_ADMIN_INTERNAL_ERROR; + if (!file || !param) return HA_ADMIN_INTERNAL_ERROR; - myisamchk_init(¶m); - param.thd = thd; - param.op_name= "repair"; - param.testflag= ((check_opt->flags & ~(T_EXTEND)) | + myisamchk_init(param); + param->thd = thd; + param->op_name= "repair"; + param->testflag= ((check_opt->flags & ~(T_EXTEND)) | T_SILENT | T_FORCE_CREATE | T_CALC_CHECKSUM | (check_opt->flags & T_EXTEND ? T_REP : T_REP_BY_SORT)); - param.sort_buffer_length= THDVAR(thd, sort_buffer_size); - param.backup_time= check_opt->start_time; + param->sort_buffer_length= THDVAR(thd, sort_buffer_size); + param->backup_time= check_opt->start_time; start_records=file->state->records; - while ((error=repair(thd,param,0)) && param.retry_repair) + while ((error=repair(thd,*param,0)) && param->retry_repair) { - param.retry_repair=0; - if (test_all_bits(param.testflag, + param->retry_repair=0; + if (test_all_bits(param->testflag, (uint) (T_RETRY_WITHOUT_QUICK | T_QUICK))) { - param.testflag&= ~(T_RETRY_WITHOUT_QUICK | T_QUICK); + param->testflag&= ~(T_RETRY_WITHOUT_QUICK | T_QUICK); /* Ensure we don't loose any rows when retrying without quick */ - param.testflag|= T_SAFE_REPAIR; + param->testflag|= T_SAFE_REPAIR; sql_print_information("Retrying repair of: '%s' including modifying data file", table->s->path.str); continue; } - param.testflag&= ~T_QUICK; - if ((param.testflag & T_REP_BY_SORT)) + param->testflag&= ~T_QUICK; + if ((param->testflag & T_REP_BY_SORT)) { - param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP; + param->testflag= (param->testflag & ~T_REP_BY_SORT) | T_REP; sql_print_information("Retrying repair of: '%s' with keycache", table->s->path.str); continue; @@ -1054,22 +1054,22 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt) int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt) { int error; - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); - if (!file || !¶m) return HA_ADMIN_INTERNAL_ERROR; + if (!file || !param) return HA_ADMIN_INTERNAL_ERROR; - myisamchk_init(¶m); - param.thd = thd; - param.op_name= "optimize"; - param.testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE | + myisamchk_init(param); + param->thd = thd; + param->op_name= "optimize"; + param->testflag= (check_opt->flags | T_SILENT | T_FORCE_CREATE | T_REP_BY_SORT | T_STATISTICS | T_SORT_INDEX); - param.sort_buffer_length= THDVAR(thd, sort_buffer_size); - if ((error= repair(thd,param,1)) && param.retry_repair) + param->sort_buffer_length= THDVAR(thd, sort_buffer_size); + if ((error= repair(thd,*param,1)) && param->retry_repair) { sql_print_warning("Warning: Optimize table got errno %d on %s.%s, retrying", - my_errno, param.db_name, param.table_name); - param.testflag&= ~T_REP_BY_SORT; - error= repair(thd,param,1); + my_errno, param->db_name, param->table_name); + param->testflag&= ~T_REP_BY_SORT; + error= repair(thd,*param,1); } return error; } @@ -1274,17 +1274,17 @@ int ha_myisam::assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt) if (error != HA_ADMIN_OK) { /* Send error to user */ - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); - if (!¶m) + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); + if (!param) return HA_ADMIN_INTERNAL_ERROR; - myisamchk_init(¶m); - param.thd= thd; - param.op_name= "assign_to_keycache"; - param.db_name= table->s->db.str; - param.table_name= table->s->table_name.str; - param.testflag= 0; - mi_check_print_error(¶m, errmsg); + myisamchk_init(param); + param->thd= thd; + param->op_name= "assign_to_keycache"; + param->db_name= table->s->db.str; + param->table_name= table->s->table_name.str; + param->testflag= 0; + mi_check_print_error(param, errmsg); } DBUG_RETURN(error); } @@ -1341,16 +1341,16 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt) err: { - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); - if (!¶m) + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); + if (!param) return HA_ADMIN_INTERNAL_ERROR; - myisamchk_init(¶m); - param.thd= thd; - param.op_name= "preload_keys"; - param.db_name= table->s->db.str; - param.table_name= table->s->table_name.str; - param.testflag= 0; - mi_check_print_error(¶m, errmsg); + myisamchk_init(param); + param->thd= thd; + param->op_name= "preload_keys"; + param->db_name= table->s->db.str; + param->table_name= table->s->table_name.str; + param->testflag= 0; + mi_check_print_error(param, errmsg); DBUG_RETURN(error); } } @@ -1455,45 +1455,45 @@ int ha_myisam::enable_indexes(uint mode) { THD *thd= table->in_use; int was_error= thd->is_error(); - HA_CHECK ¶m= *(HA_CHECK*) thd->alloc(sizeof(param)); + HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param); const char *save_proc_info=thd->proc_info; - if (!¶m) + if (!param) DBUG_RETURN(HA_ADMIN_INTERNAL_ERROR); thd_proc_info(thd, "Creating index"); - myisamchk_init(¶m); - param.op_name= "recreating_index"; - param.testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK | + myisamchk_init(param); + param->op_name= "recreating_index"; + param->testflag= (T_SILENT | T_REP_BY_SORT | T_QUICK | T_CREATE_MISSING_KEYS); /* Don't lock and unlock table if it's locked. Normally table should be locked. This test is mostly for safety. */ if (likely(file->lock_type != F_UNLCK)) - param.testflag|= T_NO_LOCKS; - + param->testflag|= T_NO_LOCKS; + if (file->create_unique_index_by_sort) - param.testflag|= T_CREATE_UNIQUE_BY_SORT; + param->testflag|= T_CREATE_UNIQUE_BY_SORT; - param.myf_rw&= ~MY_WAIT_IF_FULL; - param.sort_buffer_length= THDVAR(thd, sort_buffer_size); - param.stats_method= (enum_handler_stats_method)THDVAR(thd, stats_method); - param.tmpdir=&mysql_tmpdir_list; - if ((error= (repair(thd,param,0) != HA_ADMIN_OK)) && param.retry_repair) + param->myf_rw&= ~MY_WAIT_IF_FULL; + param->sort_buffer_length= THDVAR(thd, sort_buffer_size); + param->stats_method= (enum_handler_stats_method)THDVAR(thd, stats_method); + param->tmpdir=&mysql_tmpdir_list; + if ((error= (repair(thd,*param,0) != HA_ADMIN_OK)) && param->retry_repair) { sql_print_warning("Warning: Enabling keys got errno %d on %s.%s, retrying", - my_errno, param.db_name, param.table_name); + my_errno, param->db_name, param->table_name); /* Repairing by sort failed. Now try standard repair method. Still we want to fix only index file. If data file corruption was detected (T_RETRY_WITHOUT_QUICK), we shouldn't do much here. Let implicit repair do this job. */ - if (!(param.testflag & T_RETRY_WITHOUT_QUICK)) + if (!(param->testflag & T_RETRY_WITHOUT_QUICK)) { - param.testflag&= ~T_REP_BY_SORT; - error= (repair(thd,param,0) != HA_ADMIN_OK); + param->testflag&= ~T_REP_BY_SORT; + error= (repair(thd,*param,0) != HA_ADMIN_OK); } /* If the standard repair succeeded, clear all error messages which diff --git a/storage/xtradb/include/log0recv.h b/storage/xtradb/include/log0recv.h index 6955491bac8..9e6001caf71 100644 --- a/storage/xtradb/include/log0recv.h +++ b/storage/xtradb/include/log0recv.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -299,20 +300,12 @@ void recv_sys_var_init(void); /*===================*/ #endif /* !UNIV_HOTBACKUP */ -/*******************************************************************//** -Empties the hash table of stored log records, applying them to appropriate -pages. */ +/** Apply the hash table of stored log records to persistent data pages. +@param[in] last_batch whether the change buffer merge will be + performed as part of the operation */ UNIV_INTERN void -recv_apply_hashed_log_recs( -/*=======================*/ - ibool allow_ibuf); /*!< in: if TRUE, also ibuf operations are - allowed during the application; if FALSE, - no ibuf operations are allowed, and after - the application all file pages are flushed to - disk and invalidated in buffer pool: this - alternative means that no new log records - can be generated during the application */ +recv_apply_hashed_log_recs(bool last_batch); #ifdef UNIV_HOTBACKUP /*******************************************************************//** Applies log records in the hash table to a backup. */ @@ -438,6 +431,8 @@ struct recv_sys_t{ scan find a corrupt log block, or a corrupt log record, or there is a log parsing buffer overflow */ + /** the time when progress was last reported */ + ib_time_t progress_time; #ifdef UNIV_LOG_ARCHIVE log_group_t* archive_group; /*!< in archive recovery: the log group whose @@ -450,6 +445,20 @@ struct recv_sys_t{ addresses in the hash table */ recv_dblwr_t dblwr; + + /** Determine whether redo log recovery progress should be reported. + @param[in] time the current time + @return whether progress should be reported + (the last report was at least 15 seconds ago) */ + bool report(ib_time_t time) + { + if (time - progress_time < 15) { + return false; + } + + progress_time = time; + return true; + } }; /** The recovery system */ diff --git a/storage/xtradb/log/log0log.cc b/storage/xtradb/log/log0log.cc index b39a8ed1829..3627d85da63 100644 --- a/storage/xtradb/log/log0log.cc +++ b/storage/xtradb/log/log0log.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2009, Google Inc. -Copyright (c) 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1858,7 +1858,7 @@ log_preflush_pool_modified_pages( and we could not make a new checkpoint on the basis of the info on the buffer pool only. */ - recv_apply_hashed_log_recs(TRUE); + recv_apply_hashed_log_recs(true); } if (!buf_page_cleaner_is_active @@ -2229,7 +2229,7 @@ log_checkpoint( ut_ad(!srv_read_only_mode); if (recv_recovery_is_on()) { - recv_apply_hashed_log_recs(TRUE); + recv_apply_hashed_log_recs(true); } if (srv_unix_file_flush_method != SRV_UNIX_NOSYNC && @@ -2568,6 +2568,11 @@ loop: start_lsn += len; buf += len; + if (recv_sys->report(ut_time())) { + ib_logf(IB_LOG_LEVEL_INFO, "Read redo log up to LSN=" LSN_PF, + start_lsn); + } + if (start_lsn != end_lsn) { if (release_mutex) { diff --git a/storage/xtradb/log/log0recv.cc b/storage/xtradb/log/log0recv.cc index 01975712d99..afb8b7f00b8 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) 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -80,7 +80,7 @@ this must be less than UNIV_PAGE_SIZE as it is stored in the buffer pool */ #define RECV_READ_AHEAD_AREA 32 /** The recovery system */ -UNIV_INTERN recv_sys_t* recv_sys = NULL; +UNIV_INTERN recv_sys_t* recv_sys; /** TRUE when applying redo log records during crash recovery; FALSE otherwise. Note that this is FALSE while a background thread is rolling back incomplete transactions. */ @@ -132,9 +132,6 @@ UNIV_INTERN ibool recv_is_making_a_backup = FALSE; UNIV_INTERN ibool recv_is_from_backup = FALSE; # define buf_pool_get_curr_size() (5 * 1024 * 1024) #endif /* !UNIV_HOTBACKUP */ -/** The following counter is used to decide when to print info on -log scan */ -static ulint recv_scan_print_counter; /** The type of the previous parsed redo log record */ static ulint recv_previous_parsed_rec_type; @@ -305,8 +302,6 @@ recv_sys_var_init(void) recv_no_ibuf_operations = FALSE; - recv_scan_print_counter = 0; - recv_previous_parsed_rec_type = 999999; recv_previous_parsed_rec_offset = 0; @@ -417,6 +412,7 @@ recv_sys_init( recv_sys->last_block_buf_start, OS_FILE_LOG_BLOCK_SIZE)); recv_sys->found_corrupt_log = FALSE; + recv_sys->progress_time = ut_time(); recv_max_page_lsn = 0; @@ -1675,6 +1671,7 @@ recv_recover_page_func( ibool success; #endif /* !UNIV_HOTBACKUP */ mtr_t mtr; + ib_time_t time; mutex_enter(&(recv_sys->mutex)); @@ -1852,6 +1849,8 @@ recv_recover_page_func( mtr_commit(&mtr); + time = ut_time(); + mutex_enter(&(recv_sys->mutex)); if (recv_max_page_lsn < page_lsn) { @@ -1860,11 +1859,16 @@ recv_recover_page_func( recv_addr->state = RECV_PROCESSED; - ut_a(recv_sys->n_addrs); - recv_sys->n_addrs--; - - mutex_exit(&(recv_sys->mutex)); + ut_a(recv_sys->n_addrs > 0); + if (--recv_sys->n_addrs && recv_sys->progress_time - time >= 15) { + recv_sys->progress_time = time; + ut_print_timestamp(stderr); + fprintf(stderr, + " InnoDB: To recover: " ULINTPF " pages from log\n", + recv_sys->n_addrs); + } + mutex_exit(&recv_sys->mutex); } #ifndef UNIV_HOTBACKUP @@ -1910,59 +1914,48 @@ recv_read_in_area( } buf_read_recv_pages(FALSE, space, zip_size, page_nos, n); - /* - fprintf(stderr, "Recv pages at %lu n %lu\n", page_nos[0], n); - */ return(n); } -/*******************************************************************//** -Empties the hash table of stored log records, applying them to appropriate -pages. */ +/** Apply the hash table of stored log records to persistent data pages. +@param[in] last_batch whether the change buffer merge will be + performed as part of the operation */ UNIV_INTERN void -recv_apply_hashed_log_recs( -/*=======================*/ - ibool allow_ibuf) /*!< in: if TRUE, also ibuf operations are - allowed during the application; if FALSE, - no ibuf operations are allowed, and after - the application all file pages are flushed to - disk and invalidated in buffer pool: this - alternative means that no new log records - can be generated during the application; - the caller must in this case own the log - mutex */ +recv_apply_hashed_log_recs(bool last_batch) { - recv_addr_t* recv_addr; - ulint i; - ibool has_printed = FALSE; - mtr_t mtr; -loop: - mutex_enter(&(recv_sys->mutex)); - - if (recv_sys->apply_batch_on) { + for (;;) { + mutex_enter(&recv_sys->mutex); - mutex_exit(&(recv_sys->mutex)); + if (!recv_sys->apply_batch_on) { + break; + } + mutex_exit(&recv_sys->mutex); os_thread_sleep(500000); - - goto loop; } - ut_ad((allow_ibuf == 0) == (mutex_own(&log_sys->mutex) != 0)); + ut_ad(!last_batch == mutex_own(&log_sys->mutex)); - if (!allow_ibuf) { + if (!last_batch) { recv_no_ibuf_operations = TRUE; } + if (ulint n = recv_sys->n_addrs) { + const char* msg = last_batch + ? "Starting final batch to recover " + : "Starting a batch to recover "; + ib_logf(IB_LOG_LEVEL_INFO, + "%s" ULINTPF " pages from redo log", msg, n); + } + recv_sys->apply_log_recs = TRUE; recv_sys->apply_batch_on = TRUE; - for (i = 0; i < hash_get_n_cells(recv_sys->addr_hash); i++) { - - for (recv_addr = static_cast<recv_addr_t*>( - HASH_GET_FIRST(recv_sys->addr_hash, i)); - recv_addr != 0; + for (ulint i = 0; i < hash_get_n_cells(recv_sys->addr_hash); i++) { + for (recv_addr_t* recv_addr = static_cast<recv_addr_t*>( + HASH_GET_FIRST(recv_sys->addr_hash, i)); + recv_addr; recv_addr = static_cast<recv_addr_t*>( HASH_GET_NEXT(addr_hash, recv_addr))) { @@ -1971,24 +1964,12 @@ loop: ulint page_no = recv_addr->page_no; if (recv_addr->state == RECV_NOT_PROCESSED) { - if (!has_printed) { - ib_logf(IB_LOG_LEVEL_INFO, - "Starting an apply batch" - " of log records" - " to the database..."); - fputs("InnoDB: Progress in percent: ", - stderr); - has_printed = TRUE; - } - - mutex_exit(&(recv_sys->mutex)); + mutex_exit(&recv_sys->mutex); if (buf_page_peek(space, page_no)) { - buf_block_t* block; - + mtr_t mtr; mtr_start(&mtr); - - block = buf_page_get( + buf_block_t* block = buf_page_get( space, zip_size, page_no, RW_X_LATCH, &mtr); buf_block_dbg_add_level( @@ -2001,19 +1982,9 @@ loop: page_no); } - mutex_enter(&(recv_sys->mutex)); + mutex_enter(&recv_sys->mutex); } } - - if (has_printed - && (i * 100) / hash_get_n_cells(recv_sys->addr_hash) - != ((i + 1) * 100) - / hash_get_n_cells(recv_sys->addr_hash)) { - - fprintf(stderr, "%lu ", (ulong) - ((i * 100) - / hash_get_n_cells(recv_sys->addr_hash))); - } } /* Wait until all the pages have been processed */ @@ -2027,12 +1998,7 @@ loop: mutex_enter(&(recv_sys->mutex)); } - if (has_printed) { - - fprintf(stderr, "\n"); - } - - if (!allow_ibuf) { + if (!last_batch) { bool success; /* Flush all the file pages to disk and invalidate them in @@ -2072,11 +2038,7 @@ loop: recv_sys_empty_hash(); - if (has_printed) { - fprintf(stderr, "InnoDB: Apply batch completed\n"); - } - - mutex_exit(&(recv_sys->mutex)); + mutex_exit(&recv_sys->mutex); } #else /* !UNIV_HOTBACKUP */ /*******************************************************************//** @@ -2099,11 +2061,6 @@ recv_apply_log_recs_for_backup(void) block = back_block1; - ib_logf(IB_LOG_LEVEL_INFO, - "Starting an apply batch of log records to the database..."); - - fputs("InnoDB: Progress in percent: ", stderr); - n_hash_cells = hash_get_n_cells(recv_sys->addr_hash); for (i = 0; i < n_hash_cells; i++) { @@ -2215,13 +2172,6 @@ recv_apply_log_recs_for_backup(void) skip_this_recv_addr: recv_addr = HASH_GET_NEXT(addr_hash, recv_addr); } - - if ((100 * i) / n_hash_cells - != (100 * (i + 1)) / n_hash_cells) { - fprintf(stderr, "%lu ", - (ulong) ((100 * i) / n_hash_cells)); - fflush(stderr); - } } recv_sys_empty_hash(); @@ -2885,11 +2835,10 @@ recv_scan_log_recs( #ifndef UNIV_HOTBACKUP if (recv_log_scan_is_startup_type && !recv_needed_recovery) { - if (!srv_read_only_mode) { ib_logf(IB_LOG_LEVEL_INFO, - "Log scan progressed past the " - "checkpoint lsn " LSN_PF "", + "Starting crash recovery from " + "checkpoint LSN=" LSN_PF, recv_sys->scanned_lsn); recv_init_crash_recovery(); @@ -2948,19 +2897,6 @@ recv_scan_log_recs( *group_scanned_lsn = scanned_lsn; - if (recv_needed_recovery - || (recv_is_from_backup && !recv_is_making_a_backup)) { - recv_scan_print_counter++; - - if (finished || (recv_scan_print_counter % 80 == 0)) { - - fprintf(stderr, - "InnoDB: Doing recovery: scanned up to" - " log sequence number " LSN_PF "\n", - *group_scanned_lsn); - } - } - if (more_data && !recv_sys->found_corrupt_log) { /* Try to parse more log records */ @@ -2976,7 +2912,7 @@ recv_scan_log_recs( log yet: they would be produced by ibuf operations */ - recv_apply_hashed_log_recs(FALSE); + recv_apply_hashed_log_recs(false); } #endif /* !UNIV_HOTBACKUP */ @@ -3052,11 +2988,6 @@ recv_init_crash_recovery(void) recv_needed_recovery = TRUE; - ib_logf(IB_LOG_LEVEL_INFO, "Database was not shutdown normally!"); - ib_logf(IB_LOG_LEVEL_INFO, "Starting crash recovery."); - ib_logf(IB_LOG_LEVEL_INFO, - "Reading tablespace information from the .ibd files..."); - fil_load_single_table_tablespaces(); /* If we are using the doublewrite method, we will @@ -3067,9 +2998,7 @@ recv_init_crash_recovery(void) if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) { ib_logf(IB_LOG_LEVEL_INFO, - "Restoring possible half-written data pages "); - - ib_logf(IB_LOG_LEVEL_INFO, + "Restoring possible half-written data pages " "from the doublewrite buffer..."); buf_dblwr_process(); diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc index 258d2546634..5bd2b861ea0 100644 --- a/storage/xtradb/srv/srv0start.cc +++ b/storage/xtradb/srv/srv0start.cc @@ -2588,7 +2588,7 @@ files_checked: } } - /* This must precede recv_apply_hashed_log_recs(TRUE). */ + /* 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) { @@ -2596,7 +2596,7 @@ files_checked: respective file pages, for the last batch of recv_group_scan_log_recs(). */ - recv_apply_hashed_log_recs(TRUE); + recv_apply_hashed_log_recs(true); DBUG_PRINT("ib_log", ("apply completed")); } |