From 969939e89c29bb3f3d91f8b4ab539601b5daa4d8 Mon Sep 17 00:00:00 2001 From: Sachin Date: Wed, 25 Jul 2018 12:54:37 +0530 Subject: [PATCH 1/9] MDEV-16821 Set password for user makes rpl test to fail Actually if we use "set password for " command this changes the checksum of mysql.user table -localhost root Y Y Y Y Y Y Y Y YY Y Y Y Y Y Y Y Y Y Y Y $ Y Y Y Y Y Y Y 0 00 0 N N 0.000000 +localhost root Y Y Y Y Y Y Y Y YY Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y 0 00 0 mysql_native_password N N 0.000000 In short we replace '' with mysql_native_password which make checksum to be different, and hence check test case fails. So we use UPDATE mysql.user command. --- mysql-test/extra/rpl_tests/rpl_row_001.test | 4 ++-- mysql-test/suite/rpl/r/rpl_row_001.result | 4 ++-- mysql-test/suite/rpl/r/rpl_stm_000001.result | 4 ++-- mysql-test/suite/rpl/t/rpl_stm_000001.test | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_row_001.test b/mysql-test/extra/rpl_tests/rpl_row_001.test index 8eb684e0dff..2706336bdea 100644 --- a/mysql-test/extra/rpl_tests/rpl_row_001.test +++ b/mysql-test/extra/rpl_tests/rpl_row_001.test @@ -14,7 +14,7 @@ connection slave; sync_with_master; STOP SLAVE; connection master; -SET PASSWORD FOR root@"localhost" = PASSWORD('foo'); +UPDATE mysql.user SET password=password('foo') WHERE host='localhost' AND user='root'; connection slave; START SLAVE; connection master; @@ -22,7 +22,7 @@ connection master; # Give slave time to do at last one failed connect retry # This one must be short so that the slave will not stop retrying real_sleep 2; -SET PASSWORD FOR root@"localhost" = PASSWORD(''); +UPDATE mysql.user SET password=password('') WHERE host='localhost' AND user='root'; # Give slave time to connect (will retry every second) sleep 2; diff --git a/mysql-test/suite/rpl/r/rpl_row_001.result b/mysql-test/suite/rpl/r/rpl_row_001.result index 94985548f59..3ca694a8e76 100644 --- a/mysql-test/suite/rpl/r/rpl_row_001.result +++ b/mysql-test/suite/rpl/r/rpl_row_001.result @@ -18,11 +18,11 @@ Ababa connection slave; STOP SLAVE; connection master; -SET PASSWORD FOR root@"localhost" = PASSWORD('foo'); +UPDATE mysql.user SET password=password('foo') WHERE host='localhost' AND user='root'; connection slave; START SLAVE; connection master; -SET PASSWORD FOR root@"localhost" = PASSWORD(''); +UPDATE mysql.user SET password=password('') WHERE host='localhost' AND user='root'; CREATE TABLE t3(n INT); INSERT INTO t3 VALUES(1),(2); connection slave; diff --git a/mysql-test/suite/rpl/r/rpl_stm_000001.result b/mysql-test/suite/rpl/r/rpl_stm_000001.result index 5680d22f233..0b9ed6fc09c 100644 --- a/mysql-test/suite/rpl/r/rpl_stm_000001.result +++ b/mysql-test/suite/rpl/r/rpl_stm_000001.result @@ -19,11 +19,11 @@ abandons connection slave; stop slave; connection master; -set password for root@"localhost" = password('foo'); +UPDATE mysql.user SET password=password('foo') WHERE host='localhost' AND user='root'; connection slave; start slave; connection master; -set password for root@"localhost" = password(''); +UPDATE mysql.user SET password=password('') WHERE host='localhost' AND user='root'; create table t3(n int); insert into t3 values(1),(2); connection slave; diff --git a/mysql-test/suite/rpl/t/rpl_stm_000001.test b/mysql-test/suite/rpl/t/rpl_stm_000001.test index 7e8f669ff34..119fd6168e0 100644 --- a/mysql-test/suite/rpl/t/rpl_stm_000001.test +++ b/mysql-test/suite/rpl/t/rpl_stm_000001.test @@ -19,7 +19,7 @@ select * from t1 limit 10; sync_slave_with_master; stop slave; connection master; -set password for root@"localhost" = password('foo'); +UPDATE mysql.user SET password=password('foo') WHERE host='localhost' AND user='root'; connection slave; start slave; connection master; @@ -27,7 +27,7 @@ connection master; # Give slave time to do at last one failed connect retry # This one must be short so that the slave will not stop retrying real_sleep 2; -set password for root@"localhost" = password(''); +UPDATE mysql.user SET password=password('') WHERE host='localhost' AND user='root'; # Give slave time to connect (will retry every second) sleep 2; From de85355436e483902e0fff432348bc16f9ec1557 Mon Sep 17 00:00:00 2001 From: Thirunarayanan Balathandayuthapani Date: Wed, 25 Jul 2018 13:56:39 +0530 Subject: [PATCH 2/9] MDEV-16713 Hangs server with repeating log entry At most one transaction can be active at a time for temporary tables. There is no need to check previous version of record for the temporary tables. --- .../suite/innodb/r/temporary_table.result | 13 +++++++++++++ mysql-test/suite/innodb/t/temporary_table.test | 17 +++++++++++++++++ storage/innobase/row/row0sel.cc | 7 +++++++ storage/innobase/row/row0vers.cc | 2 ++ 4 files changed, 39 insertions(+) diff --git a/mysql-test/suite/innodb/r/temporary_table.result b/mysql-test/suite/innodb/r/temporary_table.result index 64eb3270934..628bb648ead 100644 --- a/mysql-test/suite/innodb/r/temporary_table.result +++ b/mysql-test/suite/innodb/r/temporary_table.result @@ -650,3 +650,16 @@ SELECT * FROM t1; f1 0 DROP TABLE t1; +create procedure t1_proc() +begin +DECLARE var INT UNSIGNED; +CREATE TEMPORARY TABLE t1(f1 INT UNSIGNED, f2 INT UNSIGNED, KEY( f1, f2 ) )engine=innodb; +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +START TRANSACTION; +INSERT INTO t1 SET f1 = 1, f2 = 1; +UPDATE t1 SET f2 = 2; +SET var = ( SELECT 1 FROM t1 ); +DROP TABLE t1; +END// +call t1_proc; +drop procedure t1_proc; diff --git a/mysql-test/suite/innodb/t/temporary_table.test b/mysql-test/suite/innodb/t/temporary_table.test index db87367dbb9..6856ca86323 100644 --- a/mysql-test/suite/innodb/t/temporary_table.test +++ b/mysql-test/suite/innodb/t/temporary_table.test @@ -476,3 +476,20 @@ UPDATE t1 SET f1 = 0; ROLLBACK; SELECT * FROM t1; DROP TABLE t1; + +delimiter //; +create procedure t1_proc() +begin +DECLARE var INT UNSIGNED; +CREATE TEMPORARY TABLE t1(f1 INT UNSIGNED, f2 INT UNSIGNED, KEY( f1, f2 ) )engine=innodb; +SET TRANSACTION ISOLATION LEVEL READ COMMITTED; +START TRANSACTION; +INSERT INTO t1 SET f1 = 1, f2 = 1; +UPDATE t1 SET f2 = 2; +SET var = ( SELECT 1 FROM t1 ); +DROP TABLE t1; +END// +delimiter ;// + +call t1_proc; +drop procedure t1_proc; diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index d21fd4a10ed..5d142c24490 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -5023,6 +5023,13 @@ wrong_offs: if (!rec_get_deleted_flag(rec, comp)) { goto no_gap_lock; } + + /* At most one transaction can be active + for temporary table. */ + if (dict_table_is_temporary(clust_index->table)) { + goto no_gap_lock; + } + if (index == clust_index) { trx_id_t trx_id = row_get_rec_trx_id( rec, index, offsets); diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index f58f0a47bd5..24acd04c84b 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -114,6 +114,8 @@ row_vers_impl_x_locked_low( trx_id = row_get_rec_trx_id(clust_rec, clust_index, clust_offsets); corrupt = FALSE; + ut_ad(!dict_table_is_temporary(clust_index->table)); + trx_t* trx = trx_rw_is_active(trx_id, &corrupt, true); if (trx == 0) { From aad70e9b4cdd719c3f7a559764e37ba7eea7bc3e Mon Sep 17 00:00:00 2001 From: Igor Babaev Date: Wed, 25 Jul 2018 11:57:57 -0700 Subject: [PATCH 3/9] MDEV-16820 Lost 'Impossible where' from query with inexpensive subquery This patch fixes another problem introduced by the patch for mdev-4817. The latter changed Item_cond::fix_fields() in such a way that it could call the virtual method is_expensive(). With the first its call the method saves the result in Item::is_expensive_cache. For all next calls the method returns the result from this cache. So if the item once was determined as expensive the method always returns true. For subqueries it's not good, because non-optimized subqueries always is considered as expensive. It means that the cache should be invalidated after the call of optimize_constant_subqueries(). --- mysql-test/r/subselect.result | 16 ++++++++++++++++ mysql-test/r/subselect_no_exists_to_in.result | 16 ++++++++++++++++ mysql-test/r/subselect_no_mat.result | 16 ++++++++++++++++ mysql-test/r/subselect_no_opts.result | 16 ++++++++++++++++ mysql-test/r/subselect_no_scache.result | 16 ++++++++++++++++ mysql-test/r/subselect_no_semijoin.result | 16 ++++++++++++++++ mysql-test/t/subselect.test | 15 +++++++++++++++ sql/item.h | 5 +++++ sql/sql_select.cc | 7 +++++++ 9 files changed, 123 insertions(+) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index e2ed43158f1..1c75aa66287 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -7240,6 +7240,22 @@ a 5 SET @@optimizer_switch= @optimiser_switch_save; DROP TABLE t1, t2, t3; +# +# MDEV-16820: impossible where with inexpensive subquery +# +create table t1 (a int) engine=myisam; +insert into t1 values (3), (1), (7); +create table t2 (b int, index idx(b)); +insert into t2 values (2), (5), (3), (2); +explain select * from t1 where (select max(b) from t2) = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +drop table t1,t2; End of 5.5 tests # End of 10.0 tests # diff --git a/mysql-test/r/subselect_no_exists_to_in.result b/mysql-test/r/subselect_no_exists_to_in.result index 6306cfff89d..0bd14a535e0 100644 --- a/mysql-test/r/subselect_no_exists_to_in.result +++ b/mysql-test/r/subselect_no_exists_to_in.result @@ -7240,6 +7240,22 @@ a 5 SET @@optimizer_switch= @optimiser_switch_save; DROP TABLE t1, t2, t3; +# +# MDEV-16820: impossible where with inexpensive subquery +# +create table t1 (a int) engine=myisam; +insert into t1 values (3), (1), (7); +create table t2 (b int, index idx(b)); +insert into t2 values (2), (5), (3), (2); +explain select * from t1 where (select max(b) from t2) = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +drop table t1,t2; End of 5.5 tests # End of 10.0 tests # diff --git a/mysql-test/r/subselect_no_mat.result b/mysql-test/r/subselect_no_mat.result index 0db1b031133..a3b7871bb7e 100644 --- a/mysql-test/r/subselect_no_mat.result +++ b/mysql-test/r/subselect_no_mat.result @@ -7233,6 +7233,22 @@ a 5 SET @@optimizer_switch= @optimiser_switch_save; DROP TABLE t1, t2, t3; +# +# MDEV-16820: impossible where with inexpensive subquery +# +create table t1 (a int) engine=myisam; +insert into t1 values (3), (1), (7); +create table t2 (b int, index idx(b)); +insert into t2 values (2), (5), (3), (2); +explain select * from t1 where (select max(b) from t2) = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +drop table t1,t2; End of 5.5 tests # End of 10.0 tests # diff --git a/mysql-test/r/subselect_no_opts.result b/mysql-test/r/subselect_no_opts.result index 1fa6f385b2b..9dcc690448f 100644 --- a/mysql-test/r/subselect_no_opts.result +++ b/mysql-test/r/subselect_no_opts.result @@ -7231,6 +7231,22 @@ a 5 SET @@optimizer_switch= @optimiser_switch_save; DROP TABLE t1, t2, t3; +# +# MDEV-16820: impossible where with inexpensive subquery +# +create table t1 (a int) engine=myisam; +insert into t1 values (3), (1), (7); +create table t2 (b int, index idx(b)); +insert into t2 values (2), (5), (3), (2); +explain select * from t1 where (select max(b) from t2) = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +drop table t1,t2; End of 5.5 tests # End of 10.0 tests # diff --git a/mysql-test/r/subselect_no_scache.result b/mysql-test/r/subselect_no_scache.result index 986542bd0bf..7b3c001f6b3 100644 --- a/mysql-test/r/subselect_no_scache.result +++ b/mysql-test/r/subselect_no_scache.result @@ -7246,6 +7246,22 @@ a 5 SET @@optimizer_switch= @optimiser_switch_save; DROP TABLE t1, t2, t3; +# +# MDEV-16820: impossible where with inexpensive subquery +# +create table t1 (a int) engine=myisam; +insert into t1 values (3), (1), (7); +create table t2 (b int, index idx(b)); +insert into t2 values (2), (5), (3), (2); +explain select * from t1 where (select max(b) from t2) = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +drop table t1,t2; End of 5.5 tests # End of 10.0 tests # diff --git a/mysql-test/r/subselect_no_semijoin.result b/mysql-test/r/subselect_no_semijoin.result index d5fcc17f08c..a0625246e2b 100644 --- a/mysql-test/r/subselect_no_semijoin.result +++ b/mysql-test/r/subselect_no_semijoin.result @@ -7231,6 +7231,22 @@ a 5 SET @@optimizer_switch= @optimiser_switch_save; DROP TABLE t1, t2, t3; +# +# MDEV-16820: impossible where with inexpensive subquery +# +create table t1 (a int) engine=myisam; +insert into t1 values (3), (1), (7); +create table t2 (b int, index idx(b)); +insert into t2 values (2), (5), (3), (2); +explain select * from t1 where (select max(b) from t2) = 10; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY NULL NULL NULL NULL NULL NULL NULL Impossible WHERE +2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away +drop table t1,t2; End of 5.5 tests # End of 10.0 tests # diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 7e9e5a731bc..1048e5a5a27 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -6102,6 +6102,21 @@ and t1.a in (select `test`.`t3`.`c` from `test`.`t3`); SET @@optimizer_switch= @optimiser_switch_save; DROP TABLE t1, t2, t3; +--echo # +--echo # MDEV-16820: impossible where with inexpensive subquery +--echo # + +create table t1 (a int) engine=myisam; +insert into t1 values (3), (1), (7); + +create table t2 (b int, index idx(b)); +insert into t2 values (2), (5), (3), (2); + +explain select * from t1 where (select max(b) from t2) = 10; +explain select * from t1 where (select max(b) from t2) = 10 and t1.a > 3; + +drop table t1,t2; + --echo End of 5.5 tests --echo # End of 10.0 tests diff --git a/sql/item.h b/sql/item.h index ce07f993dc4..8fad8dadf22 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1614,6 +1614,11 @@ public: virtual bool limit_index_condition_pushdown_processor(void *arg) { return 0; } virtual bool exists2in_processor(void *arg) { return 0; } virtual bool find_selective_predicates_list_processor(void *arg) { return 0; } + bool cleanup_is_expensive_cache_processor(void *arg) + { + is_expensive_cache= (int8)(-1); + return 0; + } /* TRUE if the expression depends only on the table indicated by tab_map diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 1fa21437266..4cabf5c1b40 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1335,6 +1335,13 @@ JOIN::optimize_inner() if (optimize_constant_subqueries()) DBUG_RETURN(1); + if (conds && conds->has_subquery()) + (void) conds->walk(&Item::cleanup_is_expensive_cache_processor, + 0, (void *) 0); + if (having && having->has_subquery()) + (void) having->walk(&Item::cleanup_is_expensive_cache_processor, + 0, (void *) 0); + if (setup_jtbm_semi_joins(this, join_list, &conds)) DBUG_RETURN(1); From 7f548943298f520d2cba635c4aa9af5262f4a0c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 24 Jul 2018 09:35:47 +0300 Subject: [PATCH 4/9] Remove mtr_set_flush_observer() --- storage/innobase/btr/btr0bulk.cc | 22 +++++++++------------- storage/innobase/include/mtr0mtr.h | 7 ------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index 5fae57fe2d4..39423fe318d 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.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. 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 @@ -50,10 +50,10 @@ PageBulk::init() mtr = static_cast( mem_heap_alloc(m_heap, sizeof(mtr_t))); - mtr_start(mtr); + mtr->start(); mtr_x_lock(dict_index_get_lock(m_index), mtr); - mtr_set_log_mode(mtr, MTR_LOG_NO_REDO); - mtr_set_flush_observer(mtr, m_flush_observer); + mtr->set_log_mode(MTR_LOG_NO_REDO); + mtr->set_flush_observer(m_flush_observer); if (m_page_no == FIL_NULL) { mtr_t alloc_mtr; @@ -597,18 +597,14 @@ PageBulk::release() dberr_t PageBulk::latch() { - ibool ret; - - mtr_start(m_mtr); + m_mtr->start(); mtr_x_lock(dict_index_get_lock(m_index), m_mtr); - mtr_set_log_mode(m_mtr, MTR_LOG_NO_REDO); - mtr_set_flush_observer(m_mtr, m_flush_observer); + m_mtr->set_log_mode(MTR_LOG_NO_REDO); + m_mtr->set_flush_observer(m_flush_observer); - /* TODO: need a simple and wait version of buf_page_optimistic_get. */ - ret = buf_page_optimistic_get(RW_X_LATCH, m_block, m_modify_clock, - __FILE__, __LINE__, m_mtr); /* In case the block is S-latched by page_cleaner. */ - if (!ret) { + if (!buf_page_optimistic_get(RW_X_LATCH, m_block, m_modify_clock, + __FILE__, __LINE__, m_mtr)) { page_id_t page_id(dict_index_get_space(m_index), m_page_no); page_size_t page_size(dict_table_page_size(m_index->table)); diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 6639a3448ea..bdd3a6a67b9 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -63,13 +63,6 @@ savepoint. */ @return old mode */ #define mtr_set_log_mode(m, d) (m)->set_log_mode((d)) -/** Get the flush observer of a mini-transaction. -@return flush observer object */ -#define mtr_get_flush_observer(m) (m)->get_flush_observer() - -/** Set the flush observer of a mini-transaction. */ -#define mtr_set_flush_observer(m, d) (m)->set_flush_observer((d)) - /** Read 1 - 4 bytes from a file page buffered in the buffer pool. @return value read */ #define mtr_read_ulint(p, t, m) (m)->read_ulint((p), (t)) From 172199b88cc9bc3f0765aef02a3a18ced8539d91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 24 Jul 2018 10:23:17 +0300 Subject: [PATCH 5/9] PageBulk: Remove dead code Native ALTER TABLE is never invoked on temporary tables. --- storage/innobase/btr/btr0bulk.cc | 8 ++------ storage/innobase/include/btr0bulk.h | 1 + 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index 39423fe318d..86b233a8884 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -122,9 +122,7 @@ PageBulk::init() btr_page_set_level(new_page, NULL, m_level, mtr); } - if (dict_index_is_sec_or_ibuf(m_index) - && !dict_table_is_temporary(m_index->table) - && page_is_leaf(new_page)) { + if (!m_level && dict_index_is_sec_or_ibuf(m_index)) { page_update_max_trx_id(new_block, NULL, m_trx_id, mtr); } @@ -310,9 +308,7 @@ PageBulk::commit( ut_ad(page_validate(m_page, m_index)); /* Set no free space left and no buffered changes in ibuf. */ - if (!dict_index_is_clust(m_index) - && !dict_table_is_temporary(m_index->table) - && page_is_leaf(m_page)) { + if (!dict_index_is_clust(m_index) && page_is_leaf(m_page)) { ibuf_set_bitmap_for_bulk_load( m_block, innobase_fill_factor == 100); } diff --git a/storage/innobase/include/btr0bulk.h b/storage/innobase/include/btr0bulk.h index a1887c3df2b..8c82b3c9708 100644 --- a/storage/innobase/include/btr0bulk.h +++ b/storage/innobase/include/btr0bulk.h @@ -84,6 +84,7 @@ public: m_err(DB_SUCCESS) { ut_ad(!dict_index_is_spatial(m_index)); + ut_ad(!dict_table_is_temporary(m_index->table)); } /** Deconstructor */ From a3b22147ca7ed31625e500a1e0731769724e7ed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 24 Jul 2018 10:46:30 +0300 Subject: [PATCH 6/9] Remove pointer indirection for PageBulk::m_mtr --- storage/innobase/btr/btr0bulk.cc | 62 ++++++++++++++--------------- storage/innobase/include/btr0bulk.h | 6 +-- 2 files changed, 32 insertions(+), 36 deletions(-) diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index 86b233a8884..e528156be92 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -39,7 +39,6 @@ Note: we commit all mtrs on failure. dberr_t PageBulk::init() { - mtr_t* mtr; buf_block_t* new_block; page_t* new_page; page_zip_des_t* new_page_zip; @@ -48,12 +47,10 @@ PageBulk::init() ut_ad(m_heap == NULL); m_heap = mem_heap_create(1000); - mtr = static_cast( - mem_heap_alloc(m_heap, sizeof(mtr_t))); - mtr->start(); - mtr_x_lock(dict_index_get_lock(m_index), mtr); - mtr->set_log_mode(MTR_LOG_NO_REDO); - mtr->set_flush_observer(m_flush_observer); + m_mtr.start(); + mtr_x_lock(&m_index->lock, &m_mtr); + m_mtr.set_log_mode(MTR_LOG_NO_REDO); + m_mtr.set_flush_observer(m_flush_observer); if (m_page_no == FIL_NULL) { mtr_t alloc_mtr; @@ -70,21 +67,21 @@ PageBulk::init() success = fsp_reserve_free_extents(&n_reserved, m_index->space, 1, FSP_NORMAL, &alloc_mtr); if (!success) { - mtr_commit(&alloc_mtr); - mtr_commit(mtr); + alloc_mtr.commit(); + m_mtr.commit(); return(DB_OUT_OF_FILE_SPACE); } /* Allocate a new page. */ new_block = btr_page_alloc(m_index, 0, FSP_UP, m_level, - &alloc_mtr, mtr); + &alloc_mtr, &m_mtr); if (n_reserved > 0) { fil_space_release_free_extents(m_index->space, n_reserved); } - mtr_commit(&alloc_mtr); + alloc_mtr.commit(); new_page = buf_block_get_frame(new_block); new_page_zip = buf_block_get_page_zip(new_block); @@ -92,25 +89,25 @@ PageBulk::init() if (new_page_zip) { page_create_zip(new_block, m_index, m_level, 0, - NULL, mtr); + NULL, &m_mtr); } else { ut_ad(!dict_index_is_spatial(m_index)); - page_create(new_block, mtr, + page_create(new_block, &m_mtr, dict_table_is_comp(m_index->table), false); - btr_page_set_level(new_page, NULL, m_level, mtr); + btr_page_set_level(new_page, NULL, m_level, &m_mtr); } - btr_page_set_next(new_page, NULL, FIL_NULL, mtr); - btr_page_set_prev(new_page, NULL, FIL_NULL, mtr); + btr_page_set_next(new_page, NULL, FIL_NULL, &m_mtr); + btr_page_set_prev(new_page, NULL, FIL_NULL, &m_mtr); - btr_page_set_index_id(new_page, NULL, m_index->id, mtr); + btr_page_set_index_id(new_page, NULL, m_index->id, &m_mtr); } else { page_id_t page_id(dict_index_get_space(m_index), m_page_no); page_size_t page_size(dict_table_page_size(m_index->table)); new_block = btr_block_get(page_id, page_size, - RW_X_LATCH, m_index, mtr); + RW_X_LATCH, m_index, &m_mtr); new_page = buf_block_get_frame(new_block); new_page_zip = buf_block_get_page_zip(new_block); @@ -119,14 +116,13 @@ PageBulk::init() ut_ad(page_dir_get_n_heap(new_page) == PAGE_HEAP_NO_USER_LOW); - btr_page_set_level(new_page, NULL, m_level, mtr); + btr_page_set_level(new_page, NULL, m_level, &m_mtr); } if (!m_level && dict_index_is_sec_or_ibuf(m_index)) { - page_update_max_trx_id(new_block, NULL, m_trx_id, mtr); + page_update_max_trx_id(new_block, NULL, m_trx_id, &m_mtr); } - m_mtr = mtr; m_block = new_block; m_block->skip_flush_check = true; m_page = new_page; @@ -314,7 +310,7 @@ PageBulk::commit( } } - mtr_commit(m_mtr); + m_mtr.commit(); } /** Compress a page of compressed table @@ -326,7 +322,7 @@ PageBulk::compress() ut_ad(m_page_zip != NULL); return(page_zip_compress(m_page_zip, m_page, m_index, - page_zip_level, NULL, m_mtr)); + page_zip_level, NULL, &m_mtr)); } /** Get node pointer @@ -478,7 +474,7 @@ void PageBulk::setNext( ulint next_page_no) { - btr_page_set_next(m_page, NULL, next_page_no, m_mtr); + btr_page_set_next(m_page, NULL, next_page_no, &m_mtr); } /** Set previous page @@ -487,7 +483,7 @@ void PageBulk::setPrev( ulint prev_page_no) { - btr_page_set_prev(m_page, NULL, prev_page_no, m_mtr); + btr_page_set_prev(m_page, NULL, prev_page_no, &m_mtr); } /** Check if required space is available in the page for the rec to be inserted. @@ -560,7 +556,7 @@ PageBulk::storeExt( page_cur->block = m_block; dberr_t err = btr_store_big_rec_extern_fields( - &btr_pcur, offsets, big_rec, m_mtr, BTR_STORE_INSERT_BULK); + &btr_pcur, offsets, big_rec, &m_mtr, BTR_STORE_INSERT_BULK); ut_ad(page_offset(m_cur_rec) == page_offset(page_cur->rec)); @@ -586,27 +582,27 @@ PageBulk::release() /* No other threads can modify this block. */ m_modify_clock = buf_block_get_modify_clock(m_block); - mtr_commit(m_mtr); + m_mtr.commit(); } /** Start mtr and latch the block */ dberr_t PageBulk::latch() { - m_mtr->start(); - mtr_x_lock(dict_index_get_lock(m_index), m_mtr); - m_mtr->set_log_mode(MTR_LOG_NO_REDO); - m_mtr->set_flush_observer(m_flush_observer); + m_mtr.start(); + mtr_x_lock(&m_index->lock, &m_mtr); + m_mtr.set_log_mode(MTR_LOG_NO_REDO); + m_mtr.set_flush_observer(m_flush_observer); /* In case the block is S-latched by page_cleaner. */ if (!buf_page_optimistic_get(RW_X_LATCH, m_block, m_modify_clock, - __FILE__, __LINE__, m_mtr)) { + __FILE__, __LINE__, &m_mtr)) { page_id_t page_id(dict_index_get_space(m_index), m_page_no); page_size_t page_size(dict_table_page_size(m_index->table)); m_block = buf_page_get_gen(page_id, page_size, RW_X_LATCH, m_block, BUF_GET_IF_IN_POOL, - __FILE__, __LINE__, m_mtr, &m_err); + __FILE__, __LINE__, &m_mtr, &m_err); if (m_err != DB_SUCCESS) { return (m_err); diff --git a/storage/innobase/include/btr0bulk.h b/storage/innobase/include/btr0bulk.h index 8c82b3c9708..e6ef2fa4a03 100644 --- a/storage/innobase/include/btr0bulk.h +++ b/storage/innobase/include/btr0bulk.h @@ -63,7 +63,7 @@ public: : m_heap(NULL), m_index(index), - m_mtr(NULL), + m_mtr(), m_trx_id(trx_id), m_block(NULL), m_page(NULL), @@ -206,8 +206,8 @@ private: /** The index B-tree */ dict_index_t* m_index; - /** The min-transaction */ - mtr_t* m_mtr; + /** The mini-transaction */ + mtr_t m_mtr; /** The transaction id */ trx_id_t m_trx_id; From 4a456eac2a27817731697d00057a9714f0e20caa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 24 Jul 2018 10:48:31 +0300 Subject: [PATCH 7/9] Remove unused BtrBulk::m_heap --- storage/innobase/btr/btr0bulk.cc | 2 -- storage/innobase/include/btr0bulk.h | 8 -------- 2 files changed, 10 deletions(-) diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index e528156be92..ec2fea64cc3 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -763,8 +763,6 @@ BtrBulk::insert( bool is_left_most = false; dberr_t err = DB_SUCCESS; - ut_ad(m_heap != NULL); - /* Check if we need to create a PageBulk for the level. */ if (level + 1 > m_page_bulks->size()) { PageBulk* new_page_bulk diff --git a/storage/innobase/include/btr0bulk.h b/storage/innobase/include/btr0bulk.h index e6ef2fa4a03..9048833c7a9 100644 --- a/storage/innobase/include/btr0bulk.h +++ b/storage/innobase/include/btr0bulk.h @@ -279,7 +279,6 @@ public: trx_id_t trx_id, FlushObserver* observer) : - m_heap(NULL), m_index(index), m_trx_id(trx_id), m_flush_observer(observer) @@ -293,7 +292,6 @@ public: /** Destructor */ ~BtrBulk() { - mem_heap_free(m_heap); UT_DELETE(m_page_bulks); #ifdef UNIV_DEBUG @@ -305,9 +303,6 @@ public: Note: must be called right after constructor. */ void init() { - ut_ad(m_heap == NULL); - m_heap = mem_heap_create(1000); - m_page_bulks = UT_NEW_NOKEY(page_bulk_vector()); } @@ -371,9 +366,6 @@ private: void logFreeCheck(); private: - /** Memory heap for allocation */ - mem_heap_t* m_heap; - /** B-tree index */ dict_index_t* m_index; From 32eb5823e42d488c2c8eb85fdf822733e0a482a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 24 Jul 2018 10:54:15 +0300 Subject: [PATCH 8/9] Remove pointer indirection for BtrBulk::m_page_bulks --- storage/innobase/btr/btr0bulk.cc | 32 ++++++++++++++--------------- storage/innobase/include/btr0bulk.h | 11 +--------- storage/innobase/row/row0ftsort.cc | 1 - storage/innobase/row/row0merge.cc | 4 ---- 4 files changed, 17 insertions(+), 31 deletions(-) diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index ec2fea64cc3..692ce90d8b8 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -730,10 +730,10 @@ BtrBulk::logFreeCheck() void BtrBulk::release() { - ut_ad(m_root_level + 1 == m_page_bulks->size()); + ut_ad(m_root_level + 1 == m_page_bulks.size()); for (ulint level = 0; level <= m_root_level; level++) { - PageBulk* page_bulk = m_page_bulks->at(level); + PageBulk* page_bulk = m_page_bulks.at(level); page_bulk->release(); } @@ -743,10 +743,10 @@ BtrBulk::release() void BtrBulk::latch() { - ut_ad(m_root_level + 1 == m_page_bulks->size()); + ut_ad(m_root_level + 1 == m_page_bulks.size()); for (ulint level = 0; level <= m_root_level; level++) { - PageBulk* page_bulk = m_page_bulks->at(level); + PageBulk* page_bulk = m_page_bulks.at(level); page_bulk->latch(); } } @@ -764,7 +764,7 @@ BtrBulk::insert( dberr_t err = DB_SUCCESS; /* Check if we need to create a PageBulk for the level. */ - if (level + 1 > m_page_bulks->size()) { + if (level + 1 > m_page_bulks.size()) { PageBulk* new_page_bulk = UT_NEW_NOKEY(PageBulk(m_index, m_trx_id, FIL_NULL, level, m_flush_observer)); @@ -773,16 +773,16 @@ BtrBulk::insert( return(err); } - m_page_bulks->push_back(new_page_bulk); - ut_ad(level + 1 == m_page_bulks->size()); + m_page_bulks.push_back(new_page_bulk); + ut_ad(level + 1 == m_page_bulks.size()); m_root_level = level; is_left_most = true; } - ut_ad(m_page_bulks->size() > level); + ut_ad(m_page_bulks.size() > level); - PageBulk* page_bulk = m_page_bulks->at(level); + PageBulk* page_bulk = m_page_bulks.at(level); if (is_left_most && level > 0 && page_bulk->getRecNo() == 0) { /* The node pointer must be marked as the predefined minimum @@ -838,7 +838,7 @@ BtrBulk::insert( /* Set new page bulk to page_bulks. */ ut_ad(sibling_page_bulk->getLevel() <= m_root_level); - m_page_bulks->at(level) = sibling_page_bulk; + m_page_bulks.at(level) = sibling_page_bulk; UT_DELETE(page_bulk); page_bulk = sibling_page_bulk; @@ -871,11 +871,11 @@ BtrBulk::insert( if (big_rec != NULL) { ut_ad(dict_index_is_clust(m_index)); ut_ad(page_bulk->getLevel() == 0); - ut_ad(page_bulk == m_page_bulks->at(0)); + ut_ad(page_bulk == m_page_bulks.at(0)); /* Release all latched but leaf node. */ for (ulint level = 1; level <= m_root_level; level++) { - PageBulk* page_bulk = m_page_bulks->at(level); + PageBulk* page_bulk = m_page_bulks.at(level); page_bulk->release(); } @@ -884,7 +884,7 @@ BtrBulk::insert( /* Latch */ for (ulint level = 1; level <= m_root_level; level++) { - PageBulk* page_bulk = m_page_bulks->at(level); + PageBulk* page_bulk = m_page_bulks.at(level); page_bulk->latch(); } } @@ -909,17 +909,17 @@ BtrBulk::finish(dberr_t err) ut_ad(!dict_table_is_temporary(m_index->table)); - if (m_page_bulks->size() == 0) { + if (m_page_bulks.size() == 0) { /* The table is empty. The root page of the index tree is already in a consistent state. No need to flush. */ return(err); } - ut_ad(m_root_level + 1 == m_page_bulks->size()); + ut_ad(m_root_level + 1 == m_page_bulks.size()); /* Finish all page bulks */ for (ulint level = 0; level <= m_root_level; level++) { - PageBulk* page_bulk = m_page_bulks->at(level); + PageBulk* page_bulk = m_page_bulks.at(level); last_page_no = page_bulk->getPageNo(); diff --git a/storage/innobase/include/btr0bulk.h b/storage/innobase/include/btr0bulk.h index 9048833c7a9..a3af0ea7c93 100644 --- a/storage/innobase/include/btr0bulk.h +++ b/storage/innobase/include/btr0bulk.h @@ -292,20 +292,11 @@ public: /** Destructor */ ~BtrBulk() { - UT_DELETE(m_page_bulks); - #ifdef UNIV_DEBUG fil_space_dec_redo_skipped_count(m_index->space); #endif /* UNIV_DEBUG */ } - /** Initialization - Note: must be called right after constructor. */ - void init() - { - m_page_bulks = UT_NEW_NOKEY(page_bulk_vector()); - } - /** Insert a tuple @param[in] tuple tuple to insert. @return error code */ @@ -379,7 +370,7 @@ private: FlushObserver* m_flush_observer; /** Page cursor vector for all level */ - page_bulk_vector* m_page_bulks; + page_bulk_vector m_page_bulks; }; #endif diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index 0a937847c33..c59d3a95e3e 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -1689,7 +1689,6 @@ row_fts_merge_insert( /* Create bulk load instance */ ins_ctx.btr_bulk = UT_NEW_NOKEY(BtrBulk(aux_index, trx->id, observer)); - ins_ctx.btr_bulk->init(); /* Create tuple for insert */ ins_ctx.tuple = dtuple_create(heap, dict_index_get_n_fields(aux_index)); diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 66f3b3936af..8edea4959f1 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -2404,8 +2404,6 @@ write_buffers: BtrBulk(index[i], trx->id, observer)); - - clust_btr_bulk->init(); } else { clust_btr_bulk->latch(); } @@ -2519,7 +2517,6 @@ write_buffers: BtrBulk btr_bulk(index[i], trx->id, observer); - btr_bulk.init(); err = row_merge_insert_index_tuples( trx->id, index[i], old_table, @@ -4888,7 +4885,6 @@ wait_again: if (error == DB_SUCCESS) { BtrBulk btr_bulk(sort_idx, trx->id, flush_observer); - btr_bulk.init(); pct_cost = (COST_BUILD_INDEX_STATIC + (total_dynamic_cost * merge_files[i].offset / From 0f90728bc0f8bc946a61500801b23f8a316e73d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Wed, 25 Jul 2018 17:05:47 +0300 Subject: [PATCH 9/9] MDEV-16809 Allow full redo logging for ALTER TABLE Introduce the configuration option innodb_log_optimize_ddl for controlling whether native index creation or table-rebuild in InnoDB should keep optimizing the redo log (and writing MLOG_INDEX_LOAD records to ensure that concurrent backup would fail). By default, we have innodb_log_optimize_ddl=ON, that is, the default behaviour that was introduced in MariaDB 10.2.2 (with the merge of InnoDB from MySQL 5.7) will be unchanged. BtrBulk::m_trx: Replaces m_trx_id. We must be able to check for KILL QUERY even if !m_flush_observer (innodb_log_optimize_ddl=OFF). page_cur_insert_rec_write_log(): Declare globally, so that this can be called from PageBulk::insert(). row_merge_insert_index_tuples(): Remove the unused parameter trx_id. row_merge_build_indexes(): Enable or disable redo logging based on the innodb_log_optimize_ddl parameter. PageBulk::init(), PageBulk::insert(), PageBulk::finish(): Write redo log records if needed. For ROW_FORMAT=COMPRESSED, redo log will be written in PageBulk::compress() unless we called m_mtr.set_log_mode(MTR_LOG_NO_REDO). --- .../innodb_log_optimize_ddl.result | 37 ++++ .../mariabackup/innodb_log_optimize_ddl.test | 47 ++++++ .../suite/sys_vars/r/sysvars_innodb.result | 14 ++ storage/innobase/btr/btr0bulk.cc | 159 +++++++++++++----- storage/innobase/buf/buf0flu.cc | 10 +- storage/innobase/handler/ha_innodb.cc | 8 + storage/innobase/include/btr0bulk.h | 29 ++-- storage/innobase/include/buf0flu.h | 7 +- storage/innobase/include/page0cur.h | 15 ++ storage/innobase/page/page0cur.cc | 22 +-- storage/innobase/row/row0ftsort.cc | 7 +- storage/innobase/row/row0merge.cc | 39 ++--- 12 files changed, 291 insertions(+), 103 deletions(-) create mode 100644 mysql-test/suite/mariabackup/innodb_log_optimize_ddl.result create mode 100644 mysql-test/suite/mariabackup/innodb_log_optimize_ddl.test diff --git a/mysql-test/suite/mariabackup/innodb_log_optimize_ddl.result b/mysql-test/suite/mariabackup/innodb_log_optimize_ddl.result new file mode 100644 index 00000000000..47b74e0f709 --- /dev/null +++ b/mysql-test/suite/mariabackup/innodb_log_optimize_ddl.result @@ -0,0 +1,37 @@ +SET GLOBAL innodb_log_optimize_ddl=OFF; +CREATE TABLE tz(id BIGINT PRIMARY KEY, i INT) +ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +INSERT INTO tz(id) select * from seq_1_to_10000; +CREATE TABLE tr(id BIGINT PRIMARY KEY, i INT) +ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO tr(id) select * from seq_1_to_10000; +CREATE TABLE td(id BIGINT PRIMARY KEY, i INT) +ENGINE=InnoDB; +INSERT INTO td(id) select * from seq_1_to_10000; +CREATE PROCEDURE a() +BEGIN +ALTER TABLE tz ADD INDEX(i); +ALTER TABLE tr ADD INDEX(i); +ALTER TABLE td ADD INDEX(i); +END // +call a(); +# shutdown server +# remove datadir +# xtrabackup move back +# restart server +DROP PROCEDURE a; +CHECK TABLE tz,tr,td; +Table Op Msg_type Msg_text +test.tz check status OK +test.tr check status OK +test.td check status OK +SELECT COUNT(*) FROM tz; +COUNT(*) +10000 +SELECT COUNT(*) FROM tr; +COUNT(*) +10000 +SELECT COUNT(*) FROM td; +COUNT(*) +10000 +DROP TABLE tz,tr,td; diff --git a/mysql-test/suite/mariabackup/innodb_log_optimize_ddl.test b/mysql-test/suite/mariabackup/innodb_log_optimize_ddl.test new file mode 100644 index 00000000000..d6680bec077 --- /dev/null +++ b/mysql-test/suite/mariabackup/innodb_log_optimize_ddl.test @@ -0,0 +1,47 @@ +# see unsupported_redo.test for the opposite (default) case +--source include/have_innodb.inc +--source include/have_sequence.inc + +SET GLOBAL innodb_log_optimize_ddl=OFF; + +CREATE TABLE tz(id BIGINT PRIMARY KEY, i INT) +ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +INSERT INTO tz(id) select * from seq_1_to_10000; +CREATE TABLE tr(id BIGINT PRIMARY KEY, i INT) +ENGINE=InnoDB ROW_FORMAT=REDUNDANT; +INSERT INTO tr(id) select * from seq_1_to_10000; +CREATE TABLE td(id BIGINT PRIMARY KEY, i INT) +ENGINE=InnoDB; +INSERT INTO td(id) select * from seq_1_to_10000; + +DELIMITER //; +CREATE PROCEDURE a() +BEGIN + ALTER TABLE tz ADD INDEX(i); + ALTER TABLE tr ADD INDEX(i); + ALTER TABLE td ADD INDEX(i); +END // +DELIMITER ;// + +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; + +send call a(); + +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log +exec $XTRABACKUP --prepare --target-dir=$targetdir; + +reap; + +-- source include/restart_and_restore.inc +--rmdir $targetdir + +DROP PROCEDURE a; + +CHECK TABLE tz,tr,td; +SELECT COUNT(*) FROM tz; +SELECT COUNT(*) FROM tr; +SELECT COUNT(*) FROM td; + +DROP TABLE tz,tr,td; diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index 894f9a95ccb..9d02435d815 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -1798,6 +1798,20 @@ NUMERIC_BLOCK_SIZE NULL ENUM_VALUE_LIST NULL READ_ONLY YES COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME INNODB_LOG_OPTIMIZE_DDL +SESSION_VALUE NULL +GLOBAL_VALUE ON +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE ON +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Reduce redo logging when natively creating indexes or rebuilding tables. Setting this OFF avoids delay due to page flushing and allows concurrent backup. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_LOG_WRITE_AHEAD_SIZE SESSION_VALUE NULL GLOBAL_VALUE 8192 diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc index 692ce90d8b8..bf33745f091 100644 --- a/storage/innobase/btr/btr0bulk.cc +++ b/storage/innobase/btr/btr0bulk.cc @@ -29,9 +29,12 @@ Created 03/11/2014 Shaohua Wang #include "btr0cur.h" #include "btr0pcur.h" #include "ibuf0ibuf.h" +#include "trx0trx.h" /** Innodb B-tree index fill factor for bulk load. */ long innobase_fill_factor; +/** whether to reduce redo logging during ALTER TABLE */ +my_bool innodb_log_optimize_ddl; /** Initialize members, allocate page if needed and start mtr. Note: we commit all mtrs on failure. @@ -49,8 +52,12 @@ PageBulk::init() m_mtr.start(); mtr_x_lock(&m_index->lock, &m_mtr); - m_mtr.set_log_mode(MTR_LOG_NO_REDO); - m_mtr.set_flush_observer(m_flush_observer); + if (m_flush_observer) { + m_mtr.set_log_mode(MTR_LOG_NO_REDO); + m_mtr.set_flush_observer(m_flush_observer); + } else { + m_mtr.set_named_space(m_index->space); + } if (m_page_no == FIL_NULL) { mtr_t alloc_mtr; @@ -59,8 +66,8 @@ PageBulk::init() because we don't guarantee pages are committed following the allocation order, and we will always generate redo log for page allocation, even when creating a new tablespace. */ - mtr_start(&alloc_mtr); - alloc_mtr.set_named_space(dict_index_get_space(m_index)); + alloc_mtr.start(); + alloc_mtr.set_named_space(m_index->space); ulint n_reserved; bool success; @@ -90,18 +97,29 @@ PageBulk::init() if (new_page_zip) { page_create_zip(new_block, m_index, m_level, 0, NULL, &m_mtr); + memset(FIL_PAGE_PREV + new_page, 0xff, 8); + page_zip_write_header(new_page_zip, + FIL_PAGE_PREV + new_page, + 8, &m_mtr); + mach_write_to_8(PAGE_HEADER + PAGE_INDEX_ID + new_page, + m_index->id); + page_zip_write_header(new_page_zip, + PAGE_HEADER + PAGE_INDEX_ID + + new_page, 8, &m_mtr); } else { ut_ad(!dict_index_is_spatial(m_index)); page_create(new_block, &m_mtr, dict_table_is_comp(m_index->table), false); - btr_page_set_level(new_page, NULL, m_level, &m_mtr); + mlog_write_ulint(FIL_PAGE_PREV + new_page, FIL_NULL, + MLOG_4BYTES, &m_mtr); + mlog_write_ulint(FIL_PAGE_NEXT + new_page, FIL_NULL, + MLOG_4BYTES, &m_mtr); + mlog_write_ulint(PAGE_HEADER + PAGE_LEVEL + new_page, + m_level, MLOG_2BYTES, &m_mtr); + mlog_write_ull(PAGE_HEADER + PAGE_INDEX_ID + new_page, + m_index->id, &m_mtr); } - - btr_page_set_next(new_page, NULL, FIL_NULL, &m_mtr); - btr_page_set_prev(new_page, NULL, FIL_NULL, &m_mtr); - - btr_page_set_index_id(new_page, NULL, m_index->id, &m_mtr); } else { page_id_t page_id(dict_index_get_space(m_index), m_page_no); page_size_t page_size(dict_table_page_size(m_index->table)); @@ -116,11 +134,12 @@ PageBulk::init() ut_ad(page_dir_get_n_heap(new_page) == PAGE_HEAP_NO_USER_LOW); - btr_page_set_level(new_page, NULL, m_level, &m_mtr); + btr_page_set_level(new_page, new_page_zip, m_level, &m_mtr); } if (!m_level && dict_index_is_sec_or_ibuf(m_index)) { - page_update_max_trx_id(new_block, NULL, m_trx_id, &m_mtr); + page_update_max_trx_id(new_block, new_page_zip, m_trx_id, + &m_mtr); } m_block = new_block; @@ -146,7 +165,9 @@ PageBulk::init() m_rec_no = page_header_get_field(new_page, PAGE_N_RECS); ut_d(m_total_data = 0); - page_header_set_field(m_page, NULL, PAGE_HEAP_TOP, UNIV_PAGE_SIZE - 1); + /* See page_copy_rec_list_end_to_created_page() */ + ut_d(page_header_set_field(m_page, NULL, PAGE_HEAP_TOP, + srv_page_size - 1)); return(DB_SUCCESS); } @@ -213,6 +234,14 @@ PageBulk::insert( m_free_space -= rec_size + slot_size; m_heap_top += rec_size; m_rec_no += 1; + + if (!m_flush_observer && !m_page_zip) { + /* For ROW_FORMAT=COMPRESSED, redo log may be written + in PageBulk::compress(). */ + page_cur_insert_rec_write_log(insert_rec, rec_size, + m_cur_rec, m_index, &m_mtr); + } + m_cur_rec = insert_rec; } @@ -223,15 +252,10 @@ void PageBulk::finish() { ut_ad(m_rec_no > 0); - -#ifdef UNIV_DEBUG ut_ad(m_total_data + page_dir_calc_reserved_space(m_rec_no) <= page_get_free_space_of_empty(m_is_comp)); - - /* To pass the debug tests we have to set these dummy values - in the debug version */ - page_dir_set_n_slots(m_page, NULL, UNIV_PAGE_SIZE / 2); -#endif + /* See page_copy_rec_list_end_to_created_page() */ + ut_d(page_dir_set_n_slots(m_page, NULL, srv_page_size / 2)); ulint count = 0; ulint n_recs = 0; @@ -282,14 +306,43 @@ PageBulk::finish() page_dir_slot_set_n_owned(slot, NULL, count + 1); ut_ad(!dict_index_is_spatial(m_index)); - page_dir_set_n_slots(m_page, NULL, 2 + slot_index); - page_header_set_ptr(m_page, NULL, PAGE_HEAP_TOP, m_heap_top); - page_dir_set_n_heap(m_page, NULL, PAGE_HEAP_NO_USER_LOW + m_rec_no); - page_header_set_field(m_page, NULL, PAGE_N_RECS, m_rec_no); - page_header_set_ptr(m_page, NULL, PAGE_LAST_INSERT, m_cur_rec); - page_header_set_field(m_page, NULL, PAGE_DIRECTION, PAGE_RIGHT); - page_header_set_field(m_page, NULL, PAGE_N_DIRECTION, 0); + if (!m_flush_observer && !m_page_zip) { + mlog_write_ulint(PAGE_HEADER + PAGE_N_DIR_SLOTS + m_page, + 2 + slot_index, MLOG_2BYTES, &m_mtr); + mlog_write_ulint(PAGE_HEADER + PAGE_HEAP_TOP + m_page, + ulint(m_heap_top - m_page), + MLOG_2BYTES, &m_mtr); + mlog_write_ulint(PAGE_HEADER + PAGE_N_HEAP + m_page, + (PAGE_HEAP_NO_USER_LOW + m_rec_no) + | ulint(m_is_comp) << 15, + MLOG_2BYTES, &m_mtr); + mlog_write_ulint(PAGE_HEADER + PAGE_N_RECS + m_page, m_rec_no, + MLOG_2BYTES, &m_mtr); + mlog_write_ulint(PAGE_HEADER + PAGE_LAST_INSERT + m_page, + ulint(m_cur_rec - m_page), + MLOG_2BYTES, &m_mtr); + mlog_write_ulint(PAGE_HEADER + PAGE_DIRECTION + m_page, + PAGE_RIGHT, MLOG_2BYTES, &m_mtr); + mlog_write_ulint(PAGE_HEADER + PAGE_N_DIRECTION + m_page, 0, + MLOG_2BYTES, &m_mtr); + } else { + /* For ROW_FORMAT=COMPRESSED, redo log may be written + in PageBulk::compress(). */ + mach_write_to_2(PAGE_HEADER + PAGE_N_DIR_SLOTS + m_page, + 2 + slot_index); + mach_write_to_2(PAGE_HEADER + PAGE_HEAP_TOP + m_page, + ulint(m_heap_top - m_page)); + mach_write_to_2(PAGE_HEADER + PAGE_N_HEAP + m_page, + (PAGE_HEAP_NO_USER_LOW + m_rec_no) + | ulint(m_is_comp) << 15); + mach_write_to_2(PAGE_HEADER + PAGE_N_RECS + m_page, m_rec_no); + mach_write_to_2(PAGE_HEADER + PAGE_LAST_INSERT + m_page, + ulint(m_cur_rec - m_page)); + mach_write_to_2(PAGE_HEADER + PAGE_DIRECTION + m_page, + PAGE_RIGHT); + mach_write_to_2(PAGE_HEADER + PAGE_N_DIRECTION + m_page, 0); + } m_block->skip_flush_check = false; } @@ -470,20 +523,30 @@ PageBulk::copyOut( /** Set next page @param[in] next_page_no next page no */ -void -PageBulk::setNext( - ulint next_page_no) +inline void PageBulk::setNext(ulint next_page_no) { - btr_page_set_next(m_page, NULL, next_page_no, &m_mtr); + if (UNIV_LIKELY_NULL(m_page_zip)) { + /* For ROW_FORMAT=COMPRESSED, redo log may be written + in PageBulk::compress(). */ + mach_write_to_4(m_page + FIL_PAGE_NEXT, next_page_no); + } else { + mlog_write_ulint(m_page + FIL_PAGE_NEXT, next_page_no, + MLOG_4BYTES, &m_mtr); + } } /** Set previous page @param[in] prev_page_no previous page no */ -void -PageBulk::setPrev( - ulint prev_page_no) +inline void PageBulk::setPrev(ulint prev_page_no) { - btr_page_set_prev(m_page, NULL, prev_page_no, &m_mtr); + if (UNIV_LIKELY_NULL(m_page_zip)) { + /* For ROW_FORMAT=COMPRESSED, redo log may be written + in PageBulk::compress(). */ + mach_write_to_4(m_page + FIL_PAGE_PREV, prev_page_no); + } else { + mlog_write_ulint(m_page + FIL_PAGE_PREV, prev_page_no, + MLOG_4BYTES, &m_mtr); + } } /** Check if required space is available in the page for the rec to be inserted. @@ -591,8 +654,12 @@ PageBulk::latch() { m_mtr.start(); mtr_x_lock(&m_index->lock, &m_mtr); - m_mtr.set_log_mode(MTR_LOG_NO_REDO); - m_mtr.set_flush_observer(m_flush_observer); + if (m_flush_observer) { + m_mtr.set_log_mode(MTR_LOG_NO_REDO); + m_mtr.set_flush_observer(m_flush_observer); + } else { + m_mtr.set_named_space(m_index->space); + } /* In case the block is S-latched by page_cleaner. */ if (!buf_page_optimistic_get(RW_X_LATCH, m_block, m_modify_clock, @@ -635,7 +702,7 @@ BtrBulk::pageSplit( } /* 2. create a new page. */ - PageBulk new_page_bulk(m_index, m_trx_id, FIL_NULL, + PageBulk new_page_bulk(m_index, m_trx->id, FIL_NULL, page_bulk->getLevel(), m_flush_observer); dberr_t err = new_page_bulk.init(); if (err != DB_SUCCESS) { @@ -714,8 +781,7 @@ BtrBulk::pageCommit( } /** Log free check */ -void -BtrBulk::logFreeCheck() +inline void BtrBulk::logFreeCheck() { if (log_sys->check_flush_or_checkpoint) { release(); @@ -766,7 +832,7 @@ BtrBulk::insert( /* Check if we need to create a PageBulk for the level. */ if (level + 1 > m_page_bulks.size()) { PageBulk* new_page_bulk - = UT_NEW_NOKEY(PageBulk(m_index, m_trx_id, FIL_NULL, + = UT_NEW_NOKEY(PageBulk(m_index, m_trx->id, FIL_NULL, level, m_flush_observer)); err = new_page_bulk->init(); if (err != DB_SUCCESS) { @@ -819,7 +885,7 @@ BtrBulk::insert( if (!page_bulk->isSpaceAvailable(rec_size)) { /* Create a sibling page_bulk. */ PageBulk* sibling_page_bulk; - sibling_page_bulk = UT_NEW_NOKEY(PageBulk(m_index, m_trx_id, + sibling_page_bulk = UT_NEW_NOKEY(PageBulk(m_index, m_trx->id, FIL_NULL, level, m_flush_observer)); err = sibling_page_bulk->init(); @@ -845,8 +911,11 @@ BtrBulk::insert( /* Important: log_free_check whether we need a checkpoint. */ if (page_is_leaf(sibling_page_bulk->getPage())) { - /* Check whether trx is interrupted */ - if (m_flush_observer->check_interrupted()) { + if (trx_is_interrupted(m_trx)) { + if (m_flush_observer) { + m_flush_observer->interrupted(); + } + err = DB_INTERRUPTED; goto func_exit; } @@ -944,7 +1013,7 @@ BtrBulk::finish(dberr_t err) last_page_no); page_size_t page_size(dict_table_page_size(m_index->table)); ulint root_page_no = dict_index_get_page(m_index); - PageBulk root_page_bulk(m_index, m_trx_id, + PageBulk root_page_bulk(m_index, m_trx->id, root_page_no, m_root_level, m_flush_observer); diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index cf53a10fa21..75a0498dde5 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -3735,18 +3735,12 @@ FlushObserver::~FlushObserver() DBUG_LOG("flush", "~FlushObserver(): trx->id=" << m_trx->id); } -/** Check whether trx is interrupted -@return true if trx is interrupted */ -bool -FlushObserver::check_interrupted() +/** Check whether the operation has been interrupted */ +void FlushObserver::check_interrupted() { if (trx_is_interrupted(m_trx)) { interrupted(); - - return(true); } - - return(false); } /** Notify observer of a flush diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 7000865a7cd..a8594fd37b3 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -20359,6 +20359,13 @@ static MYSQL_SYSVAR_BOOL(log_compressed_pages, page_zip_log_pages, " compression algorithm doesn't change.", NULL, NULL, TRUE); +static MYSQL_SYSVAR_BOOL(log_optimize_ddl, innodb_log_optimize_ddl, + PLUGIN_VAR_OPCMDARG, + "Reduce redo logging when natively creating indexes or rebuilding tables." + " Setting this OFF avoids delay due to page flushing and" + " allows concurrent backup.", + NULL, NULL, TRUE); + static MYSQL_SYSVAR_ULONG(autoextend_increment, sys_tablespace_auto_extend_increment, PLUGIN_VAR_RQCMDARG, @@ -21278,6 +21285,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(log_write_ahead_size), MYSQL_SYSVAR(log_group_home_dir), MYSQL_SYSVAR(log_compressed_pages), + MYSQL_SYSVAR(log_optimize_ddl), MYSQL_SYSVAR(max_dirty_pages_pct), MYSQL_SYSVAR(max_dirty_pages_pct_lwm), MYSQL_SYSVAR(adaptive_flushing_lwm), diff --git a/storage/innobase/include/btr0bulk.h b/storage/innobase/include/btr0bulk.h index a3af0ea7c93..edf34bd5ae4 100644 --- a/storage/innobase/include/btr0bulk.h +++ b/storage/innobase/include/btr0bulk.h @@ -34,6 +34,8 @@ Created 03/11/2014 Shaohua Wang /** Innodb B-tree index fill factor for bulk load. */ extern long innobase_fill_factor; +/** whether to reduce redo logging during ALTER TABLE */ +extern my_bool innodb_log_optimize_ddl; /* The proper function call sequence of PageBulk is as below: @@ -146,11 +148,11 @@ public: /** Set next page @param[in] next_page_no next page no */ - void setNext(ulint next_page_no); + inline void setNext(ulint next_page_no); /** Set previous page @param[in] prev_page_no previous page no */ - void setPrev(ulint prev_page_no); + inline void setPrev(ulint prev_page_no); /** Release block by commiting mtr */ inline void release(); @@ -257,7 +259,7 @@ private: when the block is re-pinned */ ib_uint64_t m_modify_clock; - /** Flush observer */ + /** Flush observer, or NULL if redo logging is enabled */ FlushObserver* m_flush_observer; /** Operation result DB_SUCCESS or error code */ @@ -272,19 +274,19 @@ class BtrBulk public: /** Constructor @param[in] index B-tree index - @param[in] trx_id transaction id + @param[in] trx transaction @param[in] observer flush observer */ BtrBulk( dict_index_t* index, - trx_id_t trx_id, + const trx_t* trx, FlushObserver* observer) : m_index(index), - m_trx_id(trx_id), + m_trx(trx), m_flush_observer(observer) { - ut_ad(m_flush_observer != NULL); #ifdef UNIV_DEBUG + if (m_flush_observer) fil_space_inc_redo_skipped_count(m_index->space); #endif /* UNIV_DEBUG */ } @@ -293,6 +295,7 @@ public: ~BtrBulk() { #ifdef UNIV_DEBUG + if (m_flush_observer) fil_space_dec_redo_skipped_count(m_index->space); #endif /* UNIV_DEBUG */ } @@ -354,20 +357,20 @@ private: } /** Log free check */ - void logFreeCheck(); + inline void logFreeCheck(); private: /** B-tree index */ - dict_index_t* m_index; + dict_index_t*const m_index; - /** Transaction id */ - trx_id_t m_trx_id; + /** Transaction */ + const trx_t*const m_trx; /** Root page level */ ulint m_root_level; - /** Flush observer */ - FlushObserver* m_flush_observer; + /** Flush observer, or NULL if redo logging is enabled */ + FlushObserver*const m_flush_observer; /** Page cursor vector for all level */ page_bulk_vector m_page_bulks; diff --git a/storage/innobase/include/buf0flu.h b/storage/innobase/include/buf0flu.h index c3b518c4295..5c1dddd9a3b 100644 --- a/storage/innobase/include/buf0flu.h +++ b/storage/innobase/include/buf0flu.h @@ -371,9 +371,8 @@ public: m_interrupted = true; } - /** Check whether trx is interrupted - @return true if trx is interrupted */ - bool check_interrupted(); + /** Check whether the operation has been interrupted */ + void check_interrupted(); /** Flush dirty pages. */ void flush(); @@ -395,7 +394,7 @@ private: const ulint m_space_id; /** Trx instance */ - trx_t* const m_trx; + const trx_t* const m_trx; /** Performance schema accounting object, used by ALTER TABLE. If not NULL, then stage->begin_phase_flush() will be called initially, diff --git a/storage/innobase/include/page0cur.h b/storage/innobase/include/page0cur.h index f3890c43b73..a038f68731c 100644 --- a/storage/innobase/include/page0cur.h +++ b/storage/innobase/include/page0cur.h @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 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 @@ -330,6 +331,20 @@ page_cur_open_on_rnd_user_rec( /*==========================*/ buf_block_t* block, /*!< in: page */ page_cur_t* cursor);/*!< out: page cursor */ +/** Write a redo log record of inserting a record into an index page. +@param[in] insert_rec inserted record +@param[in] rec_size rec_get_size(insert_rec) +@param[in] cursor_rec predecessor of insert_rec +@param[in,out] index index tree +@param[in,out] mtr mini-transaction */ +void +page_cur_insert_rec_write_log( + const rec_t* insert_rec, + ulint rec_size, + const rec_t* cursor_rec, + dict_index_t* index, + mtr_t* mtr) + MY_ATTRIBUTE((nonnull)); /***********************************************************//** Parses a log record of a record insert on a page. @return end of log record or NULL */ diff --git a/storage/innobase/page/page0cur.cc b/storage/innobase/page/page0cur.cc index 113c31e44ae..b611d484306 100644 --- a/storage/innobase/page/page0cur.cc +++ b/storage/innobase/page/page0cur.cc @@ -2,6 +2,7 @@ Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. +Copyright (c) 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 @@ -834,18 +835,19 @@ page_cur_open_on_rnd_user_rec( } while (rnd--); } -/***********************************************************//** -Writes the log record of a record insert on a page. */ -static +/** Write a redo log record of inserting a record into an index page. +@param[in] insert_rec inserted record +@param[in] rec_size rec_get_size(insert_rec) +@param[in] cursor_rec predecessor of insert_rec +@param[in,out] index index tree +@param[in,out] mtr mini-transaction */ void page_cur_insert_rec_write_log( -/*==========================*/ - rec_t* insert_rec, /*!< in: inserted physical record */ - ulint rec_size, /*!< in: insert_rec size */ - rec_t* cursor_rec, /*!< in: record the - cursor is pointing to */ - dict_index_t* index, /*!< in: record descriptor */ - mtr_t* mtr) /*!< in: mini-transaction handle */ + const rec_t* insert_rec, + ulint rec_size, + const rec_t* cursor_rec, + dict_index_t* index, + mtr_t* mtr) { ulint cur_rec_size; ulint extra_size; diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index c59d3a95e3e..6abc84ddee7 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -1684,11 +1684,10 @@ row_fts_merge_insert( dict_table_close(aux_table, FALSE, FALSE); aux_index = dict_table_get_first_index(aux_table); - FlushObserver* observer; - observer = psort_info[0].psort_common->trx->flush_observer; - /* Create bulk load instance */ - ins_ctx.btr_bulk = UT_NEW_NOKEY(BtrBulk(aux_index, trx->id, observer)); + ins_ctx.btr_bulk = UT_NEW_NOKEY( + BtrBulk(aux_index, trx, psort_info[0].psort_common->trx + ->flush_observer)); /* Create tuple for insert */ ins_ctx.tuple = dtuple_create(heap, dict_index_get_n_fields(aux_index)); diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 8edea4959f1..951c16394a7 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -274,7 +274,6 @@ private: #define FTS_PENDING_DOC_MEMORY_LIMIT 1000000 /** Insert sorted data tuples to the index. -@param[in] trx_id transaction identifier @param[in] index index to be inserted @param[in] old_table old table @param[in] fd file descriptor @@ -289,7 +288,6 @@ and then stage->inc() will be called for each record that is processed. static MY_ATTRIBUTE((warn_unused_result)) dberr_t row_merge_insert_index_tuples( - trx_id_t trx_id, dict_index_t* index, const dict_table_t* old_table, int fd, @@ -2402,14 +2400,14 @@ write_buffers: if (clust_btr_bulk == NULL) { clust_btr_bulk = UT_NEW_NOKEY( BtrBulk(index[i], - trx->id, - observer)); + trx, + observer/**/)); } else { clust_btr_bulk->latch(); } err = row_merge_insert_index_tuples( - trx->id, index[i], old_table, + index[i], old_table, -1, NULL, buf, clust_btr_bulk, table_total_rows, curr_progress, @@ -2515,11 +2513,11 @@ write_buffers: trx->error_key_num = i; goto all_done;); - BtrBulk btr_bulk(index[i], trx->id, + BtrBulk btr_bulk(index[i], trx, observer); err = row_merge_insert_index_tuples( - trx->id, index[i], old_table, + index[i], old_table, -1, NULL, buf, &btr_bulk, table_total_rows, curr_progress, @@ -3375,7 +3373,6 @@ row_merge_mtuple_to_dtuple( } /** Insert sorted data tuples to the index. -@param[in] trx_id transaction identifier @param[in] index index to be inserted @param[in] old_table old table @param[in] fd file descriptor @@ -3390,7 +3387,6 @@ and then stage->inc() will be called for each record that is processed. static MY_ATTRIBUTE((warn_unused_result)) dberr_t row_merge_insert_index_tuples( - trx_id_t trx_id, dict_index_t* index, const dict_table_t* old_table, int fd, @@ -3428,7 +3424,6 @@ row_merge_insert_index_tuples( ut_ad(!srv_read_only_mode); ut_ad(!(index->type & DICT_FTS)); ut_ad(!dict_index_is_spatial(index)); - ut_ad(trx_id); if (stage != NULL) { stage->begin_phase_insert(); @@ -4632,11 +4627,15 @@ row_merge_build_indexes( we use bulk load to create all types of indexes except spatial index, for which redo logging is enabled. If we create only spatial indexes, we don't need to flush dirty pages at all. */ - bool need_flush_observer = (old_table != new_table); + bool need_flush_observer = bool(innodb_log_optimize_ddl); - for (i = 0; i < n_indexes; i++) { - if (!dict_index_is_spatial(indexes[i])) { - need_flush_observer = true; + if (need_flush_observer) { + need_flush_observer = old_table != new_table; + + for (i = 0; i < n_indexes; i++) { + if (!dict_index_is_spatial(indexes[i])) { + need_flush_observer = true; + } } } @@ -4883,7 +4882,7 @@ wait_again: os_thread_sleep(20000000);); /* 20 sec */ if (error == DB_SUCCESS) { - BtrBulk btr_bulk(sort_idx, trx->id, + BtrBulk btr_bulk(sort_idx, trx, flush_observer); pct_cost = (COST_BUILD_INDEX_STATIC + @@ -4903,7 +4902,7 @@ wait_again: } error = row_merge_insert_index_tuples( - trx->id, sort_idx, old_table, + sort_idx, old_table, merge_files[i].fd, block, NULL, &btr_bulk, merge_files[i].n_rec, pct_progress, pct_cost, @@ -4936,14 +4935,16 @@ wait_again: ut_ad(sort_idx->online_status == ONLINE_INDEX_COMPLETE); } else { - ut_ad(need_flush_observer); + if (flush_observer) { + flush_observer->flush(); + row_merge_write_redo(indexes[i]); + } + if (global_system_variables.log_warnings > 2) { sql_print_information( "InnoDB: Online DDL : Applying" " log to index"); } - flush_observer->flush(); - row_merge_write_redo(indexes[i]); DEBUG_SYNC_C("row_log_apply_before"); error = row_log_apply(trx, sort_idx, table, stage);