diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 375d8845a2a..7eee64bd6ef 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -433,6 +433,22 @@ datafiles_iter_free(datafiles_iter_t *it) free(it); } +void mdl_lock_all() +{ + mdl_lock_init(); + datafiles_iter_t *it = datafiles_iter_new(fil_system); + if (!it) + return; + + while (fil_node_t *node = datafiles_iter_next(it)){ + if (fil_is_user_tablespace_id(node->space->id) + && check_if_skip_table(node->space->name)) + continue; + + mdl_lock_table(node->space->id); + } + datafiles_iter_free(it); +} /* ======== Date copying thread context ======== */ typedef struct { @@ -2199,10 +2215,6 @@ xtrabackup_copy_datafile(fil_node_t* node, uint thread_n) return(FALSE); } - if (opt_lock_ddl_per_table) { - mdl_lock_table(node->space->id); - } - if (!changed_page_bitmap) { read_filter = &rf_pass_through; } @@ -3562,9 +3574,7 @@ xtrabackup_backup_func() "or RENAME TABLE during the backup, inconsistent backup will be " "produced.\n"); - if (opt_lock_ddl_per_table) { - mdl_lock_init(); - } + /* initialize components */ if(innodb_init_param()) { @@ -3879,6 +3889,10 @@ reread_log_header: "files transfer\n", xtrabackup_parallel); } + if (opt_lock_ddl_per_table) { + mdl_lock_all(); + } + it = datafiles_iter_new(fil_system); if (it == NULL) { msg("mariabackup: Error: datafiles_iter_new() failed.\n"); diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index 7a098b8b3e3..c92b303f104 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -5195,3 +5195,45 @@ t1 CREATE TABLE `t1` ( `b` bigint(10) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 DROP TABLE t1; +# +# MDEV-14603 signal 11 with short stacktrace +# +SET NAMES utf8; +CREATE TABLE t1(i INT); +CREATE PROCEDURE p1(tn VARCHAR(32)) +EXECUTE IMMEDIATE CONCAT('ANALYZE TABLE ',tn); +CALL p1('t1'); +Table Op Msg_type Msg_text +test.t1 analyze status Table is already up to date +DROP PROCEDURE p1; +DROP TABLE t1; +SET NAMES utf8; +CREATE PROCEDURE p1() +EXECUTE IMMEDIATE CONCAT('SELECT ',CONVERT(RAND() USING latin1)); +CALL p1(); +DROP PROCEDURE p1; +SET NAMES utf8; +CREATE PROCEDURE p1() +BEGIN +PREPARE stmt FROM CONCAT('SELECT ',CONVERT(RAND() USING latin1)); +EXECUTE stmt; +DEALLOCATE PREPARE stmt; +END; +$$ +CALL p1(); +DROP PROCEDURE p1; +SET NAMES utf8; +CREATE PROCEDURE p1(a VARCHAR(10) CHARACTER SET utf8) +EXECUTE IMMEDIATE 'SELECT ?' USING CONCAT(a, CONVERT(RAND() USING latin1)); +CALL p1('x'); +DROP PROCEDURE p1; +SET NAMES utf8; +CREATE PROCEDURE p1(a VARCHAR(10) CHARACTER SET utf8) +BEGIN +PREPARE stmt FROM 'SELECT ?'; +EXECUTE stmt USING CONCAT(a, CONVERT(RAND() USING latin1)); +DEALLOCATE PREPARE stmt; +END; +$$ +CALL p1('x'); +DROP PROCEDURE p1; diff --git a/mysql-test/r/win.result b/mysql-test/r/win.result index ae0bc1fe8b1..dd4d09bb1eb 100644 --- a/mysql-test/r/win.result +++ b/mysql-test/r/win.result @@ -3290,5 +3290,15 @@ FROM door as window; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'window' at line 2 DROP TABLE door; # +# MDEV-13352: Server crashes in st_join_table::remove_duplicates +# +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT DISTINCT ROW_NUMBER() OVER(), i FROM t1 WHERE 0; +ROW_NUMBER() OVER() i +SELECT ROW_NUMBER() OVER(), i FROM t1 WHERE 0; +ROW_NUMBER() OVER() i +DROP TABLE t1; +# # Start of 10.3 tests # diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index fb98ec11779..35de237033b 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -4615,3 +4615,60 @@ DROP TABLE t1; EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 AS SELECT 2147483647 AS a,? AS b' USING 2147483647; SHOW CREATE TABLE t1; DROP TABLE t1; + +--echo # +--echo # MDEV-14603 signal 11 with short stacktrace +--echo # + +SET NAMES utf8; +CREATE TABLE t1(i INT); +CREATE PROCEDURE p1(tn VARCHAR(32)) + EXECUTE IMMEDIATE CONCAT('ANALYZE TABLE ',tn); +CALL p1('t1'); +DROP PROCEDURE p1; +DROP TABLE t1; + +SET NAMES utf8; +CREATE PROCEDURE p1() + EXECUTE IMMEDIATE CONCAT('SELECT ',CONVERT(RAND() USING latin1)); +--disable_result_log +CALL p1(); +--enable_result_log +DROP PROCEDURE p1; + +SET NAMES utf8; +DELIMITER $$; +CREATE PROCEDURE p1() +BEGIN + PREPARE stmt FROM CONCAT('SELECT ',CONVERT(RAND() USING latin1)); + EXECUTE stmt; + DEALLOCATE PREPARE stmt; +END; +$$ +DELIMITER ;$$ +--disable_result_log +CALL p1(); +--enable_result_log +DROP PROCEDURE p1; + +SET NAMES utf8; +CREATE PROCEDURE p1(a VARCHAR(10) CHARACTER SET utf8) + EXECUTE IMMEDIATE 'SELECT ?' USING CONCAT(a, CONVERT(RAND() USING latin1)); +--disable_result_log +CALL p1('x'); +--enable_result_log +DROP PROCEDURE p1; + +SET NAMES utf8; +DELIMITER $$; +CREATE PROCEDURE p1(a VARCHAR(10) CHARACTER SET utf8) +BEGIN + PREPARE stmt FROM 'SELECT ?'; + EXECUTE stmt USING CONCAT(a, CONVERT(RAND() USING latin1)); + DEALLOCATE PREPARE stmt; +END; +$$ +DELIMITER ;$$ +--disable_result_log +CALL p1('x'); +DROP PROCEDURE p1; diff --git a/mysql-test/t/win.test b/mysql-test/t/win.test index d74e94625e5..c46aaecfbbf 100644 --- a/mysql-test/t/win.test +++ b/mysql-test/t/win.test @@ -2058,6 +2058,15 @@ FROM door as window; DROP TABLE door; +--echo # +--echo # MDEV-13352: Server crashes in st_join_table::remove_duplicates +--echo # +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1),(2); +SELECT DISTINCT ROW_NUMBER() OVER(), i FROM t1 WHERE 0; +SELECT ROW_NUMBER() OVER(), i FROM t1 WHERE 0; +DROP TABLE t1; + --echo # --echo # Start of 10.3 tests --echo # diff --git a/sql/sql_class.h b/sql/sql_class.h index a46cc9e5319..a4a631ee9f0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1288,6 +1288,25 @@ public: }; +class Item_change_list_savepoint: public Item_change_list +{ +public: + Item_change_list_savepoint(Item_change_list *list) + { + list->move_elements_to(this); + } + void rollback(Item_change_list *list) + { + list->rollback_item_tree_changes(); + move_elements_to(list); + } + ~Item_change_list_savepoint() + { + DBUG_ASSERT(is_empty()); + } +}; + + /** Type of locked tables mode. See comment for THD::locked_tables_mode for complete description. diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index d5d786e8ec7..33a7ee7f78f 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -2769,6 +2769,25 @@ void mysql_sql_stmt_prepare(THD *thd) DBUG_VOID_RETURN; } + /* + Make sure we call Prepared_statement::prepare() with an empty + THD::change_list. It can be non-empty as LEX::get_dynamic_sql_string() + calls fix_fields() for the Item containing the PS source, + e.g. on character set conversion: + + SET NAMES utf8; + DELIMITER $$ + CREATE PROCEDURE p1() + BEGIN + PREPARE stmt FROM CONCAT('SELECT ',CONVERT(RAND() USING latin1)); + EXECUTE stmt; + END; + $$ + DELIMITER ; + CALL p1(); + */ + Item_change_list_savepoint change_list_savepoint(thd); + if (stmt->prepare(query.str, (uint) query.length)) { /* Statement map deletes the statement on erase */ @@ -2779,6 +2798,7 @@ void mysql_sql_stmt_prepare(THD *thd) SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL); my_ok(thd, 0L, 0L, "Statement prepared"); } + change_list_savepoint.rollback(thd); DBUG_VOID_RETURN; } @@ -2810,7 +2830,28 @@ void mysql_sql_stmt_execute_immediate(THD *thd) // See comments on thd->free_list in mysql_sql_stmt_execute() Item *free_list_backup= thd->free_list; thd->free_list= NULL; + /* + Make sure we call Prepared_statement::execute_immediate() + with an empty THD::change_list. It can be non empty as the above + LEX::prepared_stmt_params_fix_fields() and LEX::get_dynamic_str_string() + call fix_fields() for the PS source and PS parameter Items and + can do Item tree changes, e.g. on character set conversion: + + - Example #1: Item tree changes in get_dynamic_str_string() + SET NAMES utf8; + CREATE PROCEDURE p1() + EXECUTE IMMEDIATE CONCAT('SELECT ',CONVERT(RAND() USING latin1)); + CALL p1(); + + - Example #2: Item tree changes in prepared_stmt_param_fix_fields(): + SET NAMES utf8; + CREATE PROCEDURE p1(a VARCHAR(10) CHARACTER SET utf8) + EXECUTE IMMEDIATE 'SELECT ?' USING CONCAT(a, CONVERT(RAND() USING latin1)); + CALL p1('x'); + */ + Item_change_list_savepoint change_list_savepoint(thd); (void) stmt->execute_immediate(query.str, (uint) query.length); + change_list_savepoint.rollback(thd); thd->free_items(); thd->free_list= free_list_backup; @@ -3208,7 +3249,27 @@ void mysql_sql_stmt_execute(THD *thd) */ Item *free_list_backup= thd->free_list; thd->free_list= NULL; // Hide the external (e.g. "SET STATEMENT") Items + /* + Make sure we call Prepared_statement::execute_loop() with an empty + THD::change_list. It can be non-empty because the above + LEX::prepared_stmt_params_fix_fields() calls fix_fields() for + the PS parameter Items and can do some Item tree changes, + e.g. on character set conversion: + + SET NAMES utf8; + DELIMITER $$ + CREATE PROCEDURE p1(a VARCHAR(10) CHARACTER SET utf8) + BEGIN + PREPARE stmt FROM 'SELECT ?'; + EXECUTE stmt USING CONCAT(a, CONVERT(RAND() USING latin1)); + END; + $$ + DELIMITER ; + CALL p1('x'); + */ + Item_change_list_savepoint change_list_savepoint(thd); (void) stmt->execute_loop(&expanded_query, FALSE, NULL, NULL); + change_list_savepoint.rollback(thd); thd->free_items(); // Free items created by execute_loop() /* Now restore the "external" (e.g. "SET STATEMENT") Item list. diff --git a/sql/sql_select.cc b/sql/sql_select.cc index cada01cb566..22464ec9675 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2733,7 +2733,15 @@ bool JOIN::make_aggr_tables_info() curr_tab->having= having; having->update_used_tables(); } - curr_tab->distinct= true; + /* + We only need DISTINCT operation if the join is not degenerate. + If it is, we must not request DISTINCT processing, because + remove_duplicates() assumes there is a preceding computation step (and + in the degenerate join, there's none) + */ + if (top_join_tab_count) + curr_tab->distinct= true; + having= NULL; select_distinct= false; } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 6f18f5606e1..73d465476cd 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -16742,7 +16742,7 @@ innodb_show_mutex_status( DBUG_ASSERT(hton == innodb_hton_ptr); - mutex_monitor->iterate(collector); + mutex_monitor.iterate(collector); if (!collector.to_string(hton, thd, stat_print)) { DBUG_RETURN(1); @@ -17888,12 +17888,14 @@ innobase_commit_by_xid( } if (trx_t* trx = trx_get_trx_by_xid(xid)) { - TrxInInnoDB trx_in_innodb(trx); - - innobase_commit_low(trx); - ut_ad(trx->mysql_thd == NULL); + ut_ad(trx->in_innodb & TRX_FORCE_ROLLBACK_DISABLE); /* use cases are: disconnected xa, slave xa, recovery */ - trx_deregister_from_2pc(trx); + { + TrxInInnoDB trx_in_innodb(trx); + innobase_commit_low(trx); + ut_ad(trx->mysql_thd == NULL); + trx_deregister_from_2pc(trx); + } ut_ad(!trx->will_lock); /* trx cache requirement */ trx_free_for_background(trx); @@ -17922,12 +17924,14 @@ innobase_rollback_by_xid( } if (trx_t* trx = trx_get_trx_by_xid(xid)) { - TrxInInnoDB trx_in_innodb(trx); - - int ret = innobase_rollback_trx(trx); - - trx_deregister_from_2pc(trx); - ut_ad(!trx->will_lock); + int ret; + ut_ad(trx->in_innodb & TRX_FORCE_ROLLBACK_DISABLE); + { + TrxInInnoDB trx_in_innodb(trx); + ret = innobase_rollback_trx(trx); + trx_deregister_from_2pc(trx); + ut_ad(!trx->will_lock); + } trx_free_for_background(trx); return(ret); @@ -18910,7 +18914,7 @@ innodb_monitor_set_option( if (MONITOR_IS_ON(MONITOR_LATCHES)) { - mutex_monitor->enable(); + mutex_monitor.enable(); } break; @@ -18925,7 +18929,7 @@ innodb_monitor_set_option( if (!MONITOR_IS_ON(MONITOR_LATCHES)) { - mutex_monitor->disable(); + mutex_monitor.disable(); } break; @@ -18934,13 +18938,13 @@ innodb_monitor_set_option( if (monitor_id == (MONITOR_LATCHES)) { - mutex_monitor->reset(); + mutex_monitor.reset(); } break; case MONITOR_RESET_ALL_VALUE: srv_mon_reset_all(monitor_id); - mutex_monitor->reset(); + mutex_monitor.reset(); break; default: diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index d26391a80f4..7041ad53f0d 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2017, MariaDB Corporation. +Copyright (c) 2016, 2018, 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 @@ -4492,7 +4492,7 @@ ibuf_merge_or_delete_for_page( return; } - space = fil_space_acquire(page_id.space()); + space = fil_space_acquire_silent(page_id.space()); if (UNIV_UNLIKELY(!space)) { /* Do not try to read the bitmap page from the diff --git a/storage/innobase/include/sync0policy.h b/storage/innobase/include/sync0policy.h index 1b86d2633bf..de27c87816c 100644 --- a/storage/innobase/include/sync0policy.h +++ b/storage/innobase/include/sync0policy.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, 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 @@ -454,14 +454,7 @@ public: void destroy() UNIV_NOTHROW { - latch_meta_t& meta = sync_latch_get_meta(m_id); - - ut_ad(meta.get_id() == m_id); - - meta.get_counter()->sum_deregister(m_count); - m_count = NULL; - ut_d(MutexDebug::destroy()); } diff --git a/storage/innobase/include/sync0types.h b/storage/innobase/include/sync0types.h index d7583f87f3b..711225041bc 100644 --- a/storage/innobase/include/sync0types.h +++ b/storage/innobase/include/sync0types.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, 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 @@ -640,14 +640,6 @@ public: return(count); } - /** Deregister the count. We don't do anything - @param[in] count The count instance to deregister */ - void sum_deregister(Count* count) - UNIV_NOTHROW - { - /* Do nothing */ - } - /** Register a single instance counter */ void single_register(Count* count) UNIV_NOTHROW diff --git a/storage/innobase/include/ut0mutex.h b/storage/innobase/include/ut0mutex.h index bd3603ad4d0..dc387dadbdc 100644 --- a/storage/innobase/include/ut0mutex.h +++ b/storage/innobase/include/ut0mutex.h @@ -164,7 +164,7 @@ public: }; /** Defined in sync0sync.cc */ -extern MutexMonitor* mutex_monitor; +extern MutexMonitor mutex_monitor; /** Creates, or rather, initializes a mutex object in a specified memory diff --git a/storage/innobase/sync/sync0debug.cc b/storage/innobase/sync/sync0debug.cc index fa7a99ea4c0..793c6a59e33 100644 --- a/storage/innobase/sync/sync0debug.cc +++ b/storage/innobase/sync/sync0debug.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -1705,7 +1705,7 @@ private: }; /** Track latch creation location. For reducing the size of the latches */ -static CreateTracker* create_tracker; +static CreateTracker create_tracker; /** Register a latch, called when it is created @param[in] ptr Latch instance that was created @@ -1717,7 +1717,7 @@ sync_file_created_register( const char* filename, uint16_t line) { - create_tracker->register_latch(ptr, filename, line); + create_tracker.register_latch(ptr, filename, line); } /** Deregister a latch, called when it is destroyed @@ -1725,7 +1725,7 @@ sync_file_created_register( void sync_file_created_deregister(const void* ptr) { - create_tracker->deregister_latch(ptr); + create_tracker.deregister_latch(ptr); } /** Get the string where the file was created. Its format is "name:line" @@ -1734,7 +1734,7 @@ sync_file_created_deregister(const void* ptr) std::string sync_file_created_get(const void* ptr) { - return(create_tracker->get(ptr)); + return(create_tracker.get(ptr)); } /** Initializes the synchronization data structures. */ @@ -1744,12 +1744,6 @@ sync_check_init() ut_ad(!LatchDebug::s_initialized); ut_d(LatchDebug::s_initialized = true); - /** For collecting latch statistic - SHOW ... MUTEX */ - mutex_monitor = UT_NEW_NOKEY(MutexMonitor()); - - /** For trcking mutex creation location */ - create_tracker = UT_NEW_NOKEY(CreateTracker()); - sync_latch_meta_init(); /* Init the rw-lock & mutex list and create the mutex to protect it. */ @@ -1773,14 +1767,6 @@ sync_check_close() sync_array_close(); - UT_DELETE(mutex_monitor); - - mutex_monitor = NULL; - - UT_DELETE(create_tracker); - - create_tracker = NULL; - sync_latch_meta_destroy(); } diff --git a/storage/innobase/sync/sync0sync.cc b/storage/innobase/sync/sync0sync.cc index 4be7162f631..16dd90cd879 100644 --- a/storage/innobase/sync/sync0sync.cc +++ b/storage/innobase/sync/sync0sync.cc @@ -118,7 +118,7 @@ mysql_pfs_key_t trx_purge_latch_key; #endif /* UNIV_PFS_RWLOCK */ /** For monitoring active mutexes */ -MutexMonitor* mutex_monitor; +MutexMonitor mutex_monitor; /** Prints wait info of the sync system. diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index 3a798a504fc..393dff8c026 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, 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 @@ -939,13 +939,9 @@ trx_sys_close(void) || srv_read_only_mode || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO); - for (trx_t* trx = UT_LIST_GET_FIRST(trx_sys->rw_trx_list); - trx != NULL; - trx = UT_LIST_GET_FIRST(trx_sys->rw_trx_list)) { - - trx_free_prepared(trx); - + while (trx_t* trx = UT_LIST_GET_FIRST(trx_sys->rw_trx_list)) { UT_LIST_REMOVE(trx_sys->rw_trx_list, trx); + trx_free_prepared(trx); } /* There can't be any active transactions. */