summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-11-12 16:55:44 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2019-11-12 16:55:44 +0200
commit33cb10d4e9793d1b6800be22e8eb9ceffdd8af4a (patch)
tree19de2029cc51b44d05e2253681ec6e8cf8d229c6
parente5f99a0c0ccbb6cbf4a816fed552af9c20cc32e9 (diff)
parent5098d708a07f90484c9e13fe3ab58113a8a10191 (diff)
downloadmariadb-git-33cb10d4e9793d1b6800be22e8eb9ceffdd8af4a.tar.gz
Merge 10.3 into 10.4
-rw-r--r--mysql-test/main/selectivity.result56
-rw-r--r--mysql-test/main/selectivity.test32
-rw-r--r--mysql-test/main/selectivity_innodb.result56
-rw-r--r--mysql-test/suite/binlog_encryption/rpl_corruption.result4
-rw-r--r--mysql-test/suite/rpl/include/rpl_corruption.inc8
-rw-r--r--mysql-test/suite/rpl/r/rpl_corruption.result4
-rw-r--r--mysql-test/suite/rpl/r/rpl_semi_sync_gtid_reconnect.result40
-rw-r--r--mysql-test/suite/rpl/t/rpl_semi_sync_gtid_reconnect.test74
-rw-r--r--scripts/wsrep_sst_mariabackup.sh7
-rw-r--r--sql/sql_repl.cc5
-rw-r--r--sql/sql_select.cc4
-rw-r--r--sql/table.cc20
-rw-r--r--sql/table.h1
-rw-r--r--storage/innobase/include/mtr0mtr.h236
-rw-r--r--storage/innobase/include/mtr0mtr.ic55
-rw-r--r--storage/innobase/include/mtr0types.h17
-rw-r--r--storage/innobase/log/log0recv.cc40
-rw-r--r--storage/innobase/mtr/mtr0mtr.cc382
18 files changed, 543 insertions, 498 deletions
diff --git a/mysql-test/main/selectivity.result b/mysql-test/main/selectivity.result
index c548748b242..4366ef6a564 100644
--- a/mysql-test/main/selectivity.result
+++ b/mysql-test/main/selectivity.result
@@ -1810,5 +1810,61 @@ b a a b
9 9 10 10
set optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity;
drop table t1,t2,t3;
+#
+# MDEV-20519: Query plan regression with optimizer_use_condition_selectivity=4
+#
+create table t1 (id int, a int, PRIMARY KEY(id), key(a));
+insert into t1 select seq,seq from seq_1_to_100;
+create table t2 (id int, a int, b int, PRIMARY KEY(id), key(a), key(b));
+insert into t2 select seq,seq,seq from seq_1_to_100;
+set optimizer_switch='exists_to_in=off';
+set optimizer_use_condition_selectivity=2;
+SELECT * FROM t1
+WHERE
+EXISTS (SELECT * FROM t1 A INNER JOIN t2 ON t2.a = A.id
+WHERE A.a=t1.a AND t2.b < 20);
+id a
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+10 10
+11 11
+12 12
+13 13
+14 14
+15 15
+16 16
+17 17
+18 18
+19 19
+explain SELECT * FROM t1
+WHERE
+EXISTS (SELECT * FROM t1 A INNER JOIN t2 ON t2.a = A.id
+WHERE A.a=t1.a AND t2.b < 20);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 100 Using where
+2 DEPENDENT SUBQUERY A ref PRIMARY,a a 5 test.t1.a 1
+2 DEPENDENT SUBQUERY t2 ref a,b a 5 test.A.id 1 Using where
+EXPLAIN SELECT * FROM t1 A, t1 B WHERE A.a = B.a and A.id = 65;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE A const PRIMARY,a PRIMARY 4 const 1
+1 SIMPLE B ref a a 5 const 1
+explain SELECT * FROM t1
+WHERE
+EXISTS (SELECT * FROM t1 A INNER JOIN t2 ON t2.a = A.id
+WHERE A.a=t1.a AND t2.b < 20);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 ALL NULL NULL NULL NULL 100 Using where
+2 DEPENDENT SUBQUERY A ref PRIMARY,a a 5 test.t1.a 1
+2 DEPENDENT SUBQUERY t2 ref a,b a 5 test.A.id 1 Using where
+set optimizer_switch= @save_optimizer_switch;
+set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity;
+drop table t1,t2;
# End of 10.1 tests
set @@global.histogram_size=@save_histogram_size;
diff --git a/mysql-test/main/selectivity.test b/mysql-test/main/selectivity.test
index 3cf4f320994..d0158fb717e 100644
--- a/mysql-test/main/selectivity.test
+++ b/mysql-test/main/selectivity.test
@@ -1235,6 +1235,38 @@ set optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity;
drop table t1,t2,t3;
+
+--echo #
+--echo # MDEV-20519: Query plan regression with optimizer_use_condition_selectivity=4
+--echo #
+
+
+
+create table t1 (id int, a int, PRIMARY KEY(id), key(a));
+insert into t1 select seq,seq from seq_1_to_100;
+
+create table t2 (id int, a int, b int, PRIMARY KEY(id), key(a), key(b));
+insert into t2 select seq,seq,seq from seq_1_to_100;
+
+set optimizer_switch='exists_to_in=off';
+set optimizer_use_condition_selectivity=2;
+
+let $query= SELECT * FROM t1
+ WHERE
+ EXISTS (SELECT * FROM t1 A INNER JOIN t2 ON t2.a = A.id
+ WHERE A.a=t1.a AND t2.b < 20);
+
+eval $query;
+eval explain $query;
+
+EXPLAIN SELECT * FROM t1 A, t1 B WHERE A.a = B.a and A.id = 65;
+
+eval explain $query;
+
+set optimizer_switch= @save_optimizer_switch;
+set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity;
+drop table t1,t2;
+
--echo # End of 10.1 tests
#
diff --git a/mysql-test/main/selectivity_innodb.result b/mysql-test/main/selectivity_innodb.result
index b293f6adb5f..062b2da7b4f 100644
--- a/mysql-test/main/selectivity_innodb.result
+++ b/mysql-test/main/selectivity_innodb.result
@@ -1820,6 +1820,62 @@ b a a b
9 9 10 10
set optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity;
drop table t1,t2,t3;
+#
+# MDEV-20519: Query plan regression with optimizer_use_condition_selectivity=4
+#
+create table t1 (id int, a int, PRIMARY KEY(id), key(a));
+insert into t1 select seq,seq from seq_1_to_100;
+create table t2 (id int, a int, b int, PRIMARY KEY(id), key(a), key(b));
+insert into t2 select seq,seq,seq from seq_1_to_100;
+set optimizer_switch='exists_to_in=off';
+set optimizer_use_condition_selectivity=2;
+SELECT * FROM t1
+WHERE
+EXISTS (SELECT * FROM t1 A INNER JOIN t2 ON t2.a = A.id
+WHERE A.a=t1.a AND t2.b < 20);
+id a
+1 1
+2 2
+3 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+10 10
+11 11
+12 12
+13 13
+14 14
+15 15
+16 16
+17 17
+18 18
+19 19
+explain SELECT * FROM t1
+WHERE
+EXISTS (SELECT * FROM t1 A INNER JOIN t2 ON t2.a = A.id
+WHERE A.a=t1.a AND t2.b < 20);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 index NULL a 5 NULL 100 Using where; Using index
+2 DEPENDENT SUBQUERY A ref PRIMARY,a a 5 test.t1.a 1 Using index
+2 DEPENDENT SUBQUERY t2 ref a,b a 5 test.A.id 1 Using where
+EXPLAIN SELECT * FROM t1 A, t1 B WHERE A.a = B.a and A.id = 65;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE A const PRIMARY,a PRIMARY 4 const 1
+1 SIMPLE B ref a a 5 const 1 Using index
+explain SELECT * FROM t1
+WHERE
+EXISTS (SELECT * FROM t1 A INNER JOIN t2 ON t2.a = A.id
+WHERE A.a=t1.a AND t2.b < 20);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t1 index NULL a 5 NULL 100 Using where; Using index
+2 DEPENDENT SUBQUERY A ref PRIMARY,a a 5 test.t1.a 1 Using index
+2 DEPENDENT SUBQUERY t2 ref a,b a 5 test.A.id 1 Using where
+set optimizer_switch= @save_optimizer_switch;
+set optimizer_use_condition_selectivity= @save_optimizer_use_condition_selectivity;
+drop table t1,t2;
# End of 10.1 tests
set @@global.histogram_size=@save_histogram_size;
set optimizer_switch=@save_optimizer_switch_for_selectivity_test;
diff --git a/mysql-test/suite/binlog_encryption/rpl_corruption.result b/mysql-test/suite/binlog_encryption/rpl_corruption.result
index 14a67b3a3a5..25a82fd60cd 100644
--- a/mysql-test/suite/binlog_encryption/rpl_corruption.result
+++ b/mysql-test/suite/binlog_encryption/rpl_corruption.result
@@ -30,7 +30,7 @@ SET GLOBAL master_verify_checksum=0;
SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set";
connection slave;
START SLAVE IO_THREAD;
-include/wait_for_slave_io_error.inc [errno=1595,1913]
+include/wait_for_slave_io_error.inc [errno=1595,1743]
connection master;
SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set";
SET GLOBAL debug_dbug= "";
@@ -39,7 +39,7 @@ SET GLOBAL master_verify_checksum=1;
connection slave;
SET GLOBAL debug_dbug="+d,corrupt_queue_event";
START SLAVE IO_THREAD;
-include/wait_for_slave_io_error.inc [errno=1595,1913]
+include/wait_for_slave_io_error.inc [errno=1595,1743]
SET GLOBAL debug_dbug="-d,corrupt_queue_event";
# 6. Slave. Corruption in relay log
SET GLOBAL debug_dbug="+d,corrupt_read_log_event_char";
diff --git a/mysql-test/suite/rpl/include/rpl_corruption.inc b/mysql-test/suite/rpl/include/rpl_corruption.inc
index 048a9d74249..1726ee4ba2f 100644
--- a/mysql-test/suite/rpl/include/rpl_corruption.inc
+++ b/mysql-test/suite/rpl/include/rpl_corruption.inc
@@ -122,11 +122,11 @@ SET GLOBAL master_verify_checksum=0;
SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set";
--connection slave
START SLAVE IO_THREAD;
-# When the checksum error is detected, the slave sets error code 1913
+# When the checksum error is detected, the slave sets error code 1743
# (ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE) in queue_event(), then immediately
# sets error 1595 (ER_SLAVE_RELAY_LOG_WRITE_FAILURE) in handle_slave_io().
-# So we usually get 1595, but it is occasionally possible to get 1913.
-let $slave_io_errno= 1595,1913;
+# So we usually get 1595, but it is occasionally possible to get 1743.
+let $slave_io_errno= 1595,1743; # ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE
--source include/wait_for_slave_io_error.inc
--connection master
SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set";
@@ -138,7 +138,7 @@ SET GLOBAL master_verify_checksum=1;
--connection slave
SET GLOBAL debug_dbug="+d,corrupt_queue_event";
START SLAVE IO_THREAD;
-let $slave_io_errno= 1595,1913;
+let $slave_io_errno= 1595,1743; # ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE
--source include/wait_for_slave_io_error.inc
SET GLOBAL debug_dbug="-d,corrupt_queue_event";
diff --git a/mysql-test/suite/rpl/r/rpl_corruption.result b/mysql-test/suite/rpl/r/rpl_corruption.result
index 14a67b3a3a5..25a82fd60cd 100644
--- a/mysql-test/suite/rpl/r/rpl_corruption.result
+++ b/mysql-test/suite/rpl/r/rpl_corruption.result
@@ -30,7 +30,7 @@ SET GLOBAL master_verify_checksum=0;
SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set";
connection slave;
START SLAVE IO_THREAD;
-include/wait_for_slave_io_error.inc [errno=1595,1913]
+include/wait_for_slave_io_error.inc [errno=1595,1743]
connection master;
SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set";
SET GLOBAL debug_dbug= "";
@@ -39,7 +39,7 @@ SET GLOBAL master_verify_checksum=1;
connection slave;
SET GLOBAL debug_dbug="+d,corrupt_queue_event";
START SLAVE IO_THREAD;
-include/wait_for_slave_io_error.inc [errno=1595,1913]
+include/wait_for_slave_io_error.inc [errno=1595,1743]
SET GLOBAL debug_dbug="-d,corrupt_queue_event";
# 6. Slave. Corruption in relay log
SET GLOBAL debug_dbug="+d,corrupt_read_log_event_char";
diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_gtid_reconnect.result b/mysql-test/suite/rpl/r/rpl_semi_sync_gtid_reconnect.result
new file mode 100644
index 00000000000..4285228f162
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_semi_sync_gtid_reconnect.result
@@ -0,0 +1,40 @@
+include/master-slave.inc
+[connection master]
+connection master;
+RESET MASTER;
+SET @@GLOBAL.rpl_semi_sync_master_enabled = 1;
+connection slave;
+include/stop_slave.inc
+SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1;
+include/start_slave.inc
+connection master;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 SET a = 1;
+include/save_master_gtid.inc
+FLUSH LOGS;
+INSERT INTO t1 SET a = 2;
+connection slave;
+connection slave;
+include/stop_slave_sql.inc
+connection master;
+INSERT INTO t1 SET a = 3;
+include/sync_slave_io_with_master.inc
+connection slave;
+include/stop_slave_io.inc
+connection master;
+RESET MASTER;
+SET @@global.gtid_binlog_state = '0-1-2';
+connection slave;
+CHANGE MASTER TO MASTER_USE_GTID = slave_pos;
+SET @@global.gtid_slave_pos = '0-1-2';
+include/start_slave.inc
+connection master;
+INSERT INTO t1 SET a = 4;
+connection master;
+DROP TABLE t1;
+SET @@GLOBAL. rpl_semi_sync_master_enabled = 0;
+connection slave;
+include/stop_slave.inc
+SET @@GLOBAL. rpl_semi_sync_slave_enabled = 0;
+include/start_slave.inc
+include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_gtid_reconnect.test b/mysql-test/suite/rpl/t/rpl_semi_sync_gtid_reconnect.test
new file mode 100644
index 00000000000..96f7e805fc5
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_semi_sync_gtid_reconnect.test
@@ -0,0 +1,74 @@
+source include/not_embedded.inc;
+source include/have_binlog_format_mixed.inc;
+source include/master-slave.inc;
+
+#
+# Semisync initialization
+#
+--connection master
+RESET MASTER;
+--let $sav_enabled_master=`SELECT @@GLOBAL.rpl_semi_sync_master_enabled`
+SET @@GLOBAL.rpl_semi_sync_master_enabled = 1;
+
+--connection slave
+source include/stop_slave.inc;
+--let $sav_enabled_slave=`SELECT @@GLOBAL.rpl_semi_sync_slave_enabled`
+SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1;
+source include/start_slave.inc;
+
+# Prove fixes to
+# MDEV-19376 Assert (!m_active_tranxs->is_tranx_end_pos(trx_wait_binlog_name...)
+#
+#
+# Run few queries to replicate/execute on slave.
+# Stop the slave applier.
+# Replicate/not-executed few more.
+# Restart the slave.
+#
+--connection master
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 SET a = 1;
+--source include/save_master_gtid.inc
+--let $resume_gtid = $master_pos
+FLUSH LOGS;
+INSERT INTO t1 SET a = 2;
+
+--sync_slave_with_master
+--connection slave
+--source include/stop_slave_sql.inc
+
+--connection master
+INSERT INTO t1 SET a = 3;
+
+# the sync connection is 'slave' by default
+--source include/sync_slave_io_with_master.inc
+--connection slave
+--source include/stop_slave_io.inc
+
+--connection master
+RESET MASTER;
+--eval SET @@global.gtid_binlog_state = '$resume_gtid'
+
+# The resume gtid is set up to point to the very first binlog file
+--connection slave
+CHANGE MASTER TO MASTER_USE_GTID = slave_pos;
+--eval SET @@global.gtid_slave_pos = '$resume_gtid'
+# Yet the slave io first submits the last received binlog file name:pos.
+--source include/start_slave.inc
+
+# Here goes the cracker.
+--connection master
+INSERT INTO t1 SET a = 4;
+
+#
+# Clean up
+#
+--connection master
+DROP TABLE t1;
+--eval SET @@GLOBAL. rpl_semi_sync_master_enabled = $sav_enabled_master
+
+--sync_slave_with_master
+source include/stop_slave.inc;
+--eval SET @@GLOBAL. rpl_semi_sync_slave_enabled = $sav_enabled_slave
+source include/start_slave.inc;
+--source include/rpl_end.inc
diff --git a/scripts/wsrep_sst_mariabackup.sh b/scripts/wsrep_sst_mariabackup.sh
index 36deeff779d..8d1a36561d3 100644
--- a/scripts/wsrep_sst_mariabackup.sh
+++ b/scripts/wsrep_sst_mariabackup.sh
@@ -83,7 +83,14 @@ fi
pcmd="pv $pvopts"
declare -a RC
+set +e
INNOBACKUPEX_BIN=$(which mariabackup)
+if test -z $INNOBACKUPEX_BIN
+then
+ wsrep_log_error 'mariabackup binary not found in $PATH'
+ exit 42
+fi
+set -e
XBSTREAM_BIN=mbstream
XBCRYPT_BIN=xbcrypt # Not available in MariaBackup
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index a0f952955d5..9f7413241b6 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -2824,7 +2824,10 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos,
/* Check if the dump thread is created by a slave with semisync enabled. */
thd->semi_sync_slave = is_semi_sync_slave();
- if (repl_semisync_master.dump_start(thd, log_ident, pos))
+
+ DBUG_ASSERT(pos == linfo.pos);
+
+ if (repl_semisync_master.dump_start(thd, linfo.log_file_name, linfo.pos))
{
info->errmsg= "Failed to run hook 'transmit_start'";
info->error= ER_UNKNOWN_ERROR;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 896135db7be..a05c2f81b10 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -9087,7 +9087,6 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
something went wrong.
*/
sel /= (double)table->quick_rows[key] / (double) table->stat_records();
- // MDEV-20595 FIXME: DBUG_ASSERT(sel > 0 && sel <= 2.0);
set_if_smaller(sel, 1.0);
used_range_selectivity= true;
}
@@ -9136,7 +9135,6 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
if (table->field[fldno]->cond_selectivity > 0)
{
sel /= table->field[fldno]->cond_selectivity;
- // MDEV-20595 FIXME: DBUG_ASSERT(sel > 0 && sel <= 2.0);
set_if_smaller(sel, 1.0);
}
/*
@@ -9194,7 +9192,6 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
if (field->cond_selectivity > 0)
{
sel/= field->cond_selectivity;
- // MDEV-20595 FIXME: DBUG_ASSERT(sel > 0 && sel <= 2.0);
set_if_smaller(sel, 1.0);
}
break;
@@ -9206,7 +9203,6 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
sel*= table_multi_eq_cond_selectivity(join, idx, s, rem_tables,
keyparts, ref_keyuse_steps);
- DBUG_ASSERT(0.0 < sel && sel <= 1.0);
return sel;
}
diff --git a/sql/table.cc b/sql/table.cc
index 9b027a8b31b..0a7d2c9547a 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -5109,6 +5109,8 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
update_handler= NULL;
check_unique_buf= NULL;
vers_write= s->versioned;
+ quick_condition_rows=0;
+ initialize_quick_structures();
#ifdef HAVE_REPLICATION
/* used in RBR Triggers */
master_had_triggers= 0;
@@ -9608,3 +9610,21 @@ bool TABLE::export_structure(THD *thd, Row_definition_list *defs)
}
return false;
}
+
+/*
+ @brief
+ Initialize all the quick structures that are used to stored the
+ estimates when the range optimizer is run.
+ @details
+ This is specifically needed when we read the TABLE structure from the
+ table cache. There can be some garbage data from previous queries
+ that need to be reset here.
+*/
+
+void TABLE::initialize_quick_structures()
+{
+ bzero(quick_rows, sizeof(quick_rows));
+ bzero(quick_key_parts, sizeof(quick_key_parts));
+ bzero(quick_costs, sizeof(quick_costs));
+ bzero(quick_n_ranges, sizeof(quick_n_ranges));
+}
diff --git a/sql/table.h b/sql/table.h
index 8297774c4d2..700c5f036fd 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1518,6 +1518,7 @@ public:
bool is_filled_at_execution();
bool update_const_key_parts(COND *conds);
+ void initialize_quick_structures();
my_ptrdiff_t default_values_offset() const
{ return (my_ptrdiff_t) (s->default_values - record[0]); }
diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h
index 63878773e05..0dbfc14c68f 100644
--- a/storage/innobase/include/mtr0mtr.h
+++ b/storage/innobase/include/mtr0mtr.h
@@ -130,62 +130,7 @@ struct mtr_memo_slot_t {
/** Mini-transaction handle and buffer */
struct mtr_t {
-
- /** State variables of the mtr */
- struct Impl {
-
- /** memo stack for locks etc. */
- mtr_buf_t m_memo;
-
- /** mini-transaction log */
- mtr_buf_t m_log;
-
- /** true if mtr has made at least one buffer pool page dirty */
- bool m_made_dirty;
-
- /** true if inside ibuf changes */
- bool m_inside_ibuf;
-
- /** true if the mini-transaction modified buffer pool pages */
- bool m_modifications;
-
- /** Count of how many page initial log records have been
- written to the mtr log */
- ib_uint32_t m_n_log_recs;
-
- /** specifies which operations should be logged; default
- value MTR_LOG_ALL */
- mtr_log_t m_log_mode;
-#ifdef UNIV_DEBUG
- /** Persistent user tablespace associated with the
- mini-transaction, or 0 (TRX_SYS_SPACE) if none yet */
- ulint m_user_space_id;
-#endif /* UNIV_DEBUG */
- /** User tablespace that is being modified by the
- mini-transaction */
- fil_space_t* m_user_space;
-
- /** State of the transaction */
- mtr_state_t m_state;
-
- /** Flush Observer */
- FlushObserver* m_flush_observer;
-
-#ifdef UNIV_DEBUG
- /** For checking corruption. */
- ulint m_magic_n;
-#endif /* UNIV_DEBUG */
-
- /** Owning mini-transaction */
- mtr_t* m_mtr;
- };
-
- mtr_t()
- {
- m_impl.m_state = MTR_STATE_INIT;
- }
-
- ~mtr_t() { }
+ mtr_t() : m_state(MTR_STATE_INIT) {}
/** Start a mini-transaction. */
void start();
@@ -207,14 +152,7 @@ struct mtr_t {
/** Return current size of the buffer.
@return savepoint */
- ulint get_savepoint() const
- MY_ATTRIBUTE((warn_unused_result))
- {
- ut_ad(is_active());
- ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
-
- return(m_impl.m_memo.size());
- }
+ ulint get_savepoint() const {ut_ad(is_active()); return m_memo.size();}
/** Release the (index tree) s-latch stored in an mtr memo after a
savepoint.
@@ -251,11 +189,11 @@ struct mtr_t {
the same set of tablespaces as this one */
void set_spaces(const mtr_t& mtr)
{
- ut_ad(!m_impl.m_user_space_id);
- ut_ad(!m_impl.m_user_space);
+ ut_ad(!m_user_space_id);
+ ut_ad(!m_user_space);
- ut_d(m_impl.m_user_space_id = mtr.m_impl.m_user_space_id);
- m_impl.m_user_space = mtr.m_impl.m_user_space;
+ ut_d(m_user_space_id = mtr.m_user_space_id);
+ m_user_space = mtr.m_user_space;
}
/** Set the tablespace associated with the mini-transaction
@@ -264,16 +202,16 @@ struct mtr_t {
@return the tablespace */
fil_space_t* set_named_space_id(ulint space_id)
{
- ut_ad(!m_impl.m_user_space_id);
- ut_d(m_impl.m_user_space_id = space_id);
+ ut_ad(!m_user_space_id);
+ ut_d(m_user_space_id = space_id);
if (!space_id) {
return fil_system.sys_space;
} else {
- ut_ad(m_impl.m_user_space_id == space_id);
- ut_ad(!m_impl.m_user_space);
- m_impl.m_user_space = fil_space_get(space_id);
- ut_ad(m_impl.m_user_space);
- return m_impl.m_user_space;
+ ut_ad(m_user_space_id == space_id);
+ ut_ad(!m_user_space);
+ m_user_space = fil_space_get(space_id);
+ ut_ad(m_user_space);
+ return m_user_space;
}
}
@@ -282,10 +220,10 @@ struct mtr_t {
@param[in] space user or system tablespace */
void set_named_space(fil_space_t* space)
{
- ut_ad(!m_impl.m_user_space_id);
- ut_d(m_impl.m_user_space_id = space->id);
+ ut_ad(!m_user_space_id);
+ ut_d(m_user_space_id = space->id);
if (space->id) {
- m_impl.m_user_space = space;
+ m_user_space = space;
}
}
@@ -345,18 +283,12 @@ struct mtr_t {
void release_page(const void* ptr, mtr_memo_type_t type);
/** Note that the mini-transaction has modified data. */
- void set_modified()
- {
- m_impl.m_modifications = true;
- }
+ void set_modified() { m_modifications = true; }
/** Set the state to not-modified. This will not log the
changes. This is only used during redo log apply, to avoid
logging the changes. */
- void discard_modifications()
- {
- m_impl.m_modifications = false;
- }
+ void discard_modifications() { m_modifications = false; }
/** Get the LSN of commit().
@return the commit LSN
@@ -368,45 +300,28 @@ struct mtr_t {
}
/** Note that we are inside the change buffer code. */
- void enter_ibuf()
- {
- m_impl.m_inside_ibuf = true;
- }
+ void enter_ibuf() { m_inside_ibuf = true; }
/** Note that we have exited from the change buffer code. */
- void exit_ibuf()
- {
- m_impl.m_inside_ibuf = false;
- }
+ void exit_ibuf() { m_inside_ibuf = false; }
/** @return true if we are inside the change buffer code */
- bool is_inside_ibuf() const
- {
- return(m_impl.m_inside_ibuf);
- }
+ bool is_inside_ibuf() const { return m_inside_ibuf; }
/*
@return true if the mini-transaction is active */
- bool is_active() const
- {
- return(m_impl.m_state == MTR_STATE_ACTIVE);
- }
+ bool is_active() const { return m_state == MTR_STATE_ACTIVE; }
/** Get flush observer
@return flush observer */
- FlushObserver* get_flush_observer() const
- {
- return(m_impl.m_flush_observer);
- }
+ FlushObserver* get_flush_observer() const { return m_flush_observer; }
/** Set flush observer
@param[in] observer flush observer */
void set_flush_observer(FlushObserver* observer)
{
- ut_ad(observer == NULL
- || m_impl.m_log_mode == MTR_LOG_NO_REDO);
-
- m_impl.m_flush_observer = observer;
+ ut_ad(observer == NULL || m_log_mode == MTR_LOG_NO_REDO);
+ m_flush_observer = observer;
}
#ifdef UNIV_DEBUG
@@ -446,65 +361,31 @@ struct mtr_t {
void print() const;
/** @return true if the mini-transaction has committed */
- bool has_committed() const
- {
- return(m_impl.m_state == MTR_STATE_COMMITTED);
- }
-
- /** @return true if the mini-transaction is committing */
- bool is_committing() const
- {
- return(m_impl.m_state == MTR_STATE_COMMITTING);
- }
+ bool has_committed() const { return m_state == MTR_STATE_COMMITTED; }
/** @return true if mini-transaction contains modifications. */
- bool has_modifications() const
- {
- return(m_impl.m_modifications);
- }
+ bool has_modifications() const { return m_modifications; }
/** @return the memo stack */
- const mtr_buf_t* get_memo() const
- {
- return(&m_impl.m_memo);
- }
+ const mtr_buf_t* get_memo() const { return &m_memo; }
/** @return the memo stack */
- mtr_buf_t* get_memo()
- {
- return(&m_impl.m_memo);
- }
+ mtr_buf_t* get_memo() { return &m_memo; }
#endif /* UNIV_DEBUG */
/** @return true if a record was added to the mini-transaction */
- bool is_dirty() const
- {
- return(m_impl.m_made_dirty);
- }
+ bool is_dirty() const { return m_made_dirty; }
/** Note that a record has been added to the log */
- void added_rec()
- {
- ++m_impl.m_n_log_recs;
- }
+ void added_rec() { ++m_n_log_recs; }
/** Get the buffered redo log of this mini-transaction.
@return redo log */
- const mtr_buf_t* get_log() const
- {
- ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
-
- return(&m_impl.m_log);
- }
+ const mtr_buf_t* get_log() const { return &m_log; }
/** Get the buffered redo log of this mini-transaction.
@return redo log */
- mtr_buf_t* get_log()
- {
- ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
-
- return(&m_impl.m_log);
- }
+ mtr_buf_t* get_log() { return &m_log; }
/** Push an object to an mtr memo stack.
@param object object
@@ -518,15 +399,56 @@ struct mtr_t {
MY_ATTRIBUTE((warn_unused_result));
private:
- class Command;
+ /** Prepare to write the mini-transaction log to the redo log buffer.
+ @return number of bytes to write in finish_write() */
+ inline ulint prepare_write();
- friend class Command;
+ /** Append the redo log records to the redo log buffer.
+ @param[in] len number of bytes to write
+ @return start_lsn */
+ inline lsn_t finish_write(ulint len);
-private:
- Impl m_impl;
+ /** Release the resources */
+ inline void release_resources();
+
+ /** memo stack for locks etc. */
+ mtr_buf_t m_memo;
+
+ /** mini-transaction log */
+ mtr_buf_t m_log;
+
+ /** true if mtr has made at least one buffer pool page dirty */
+ bool m_made_dirty;
+
+ /** true if inside ibuf changes */
+ bool m_inside_ibuf;
+
+ /** true if the mini-transaction modified buffer pool pages */
+ bool m_modifications;
+
+ /** Count of how many page initial log records have been
+ written to the mtr log */
+ ib_uint32_t m_n_log_recs;
+
+ /** specifies which operations should be logged; default
+ value MTR_LOG_ALL */
+ mtr_log_t m_log_mode;
+#ifdef UNIV_DEBUG
+ /** Persistent user tablespace associated with the
+ mini-transaction, or 0 (TRX_SYS_SPACE) if none yet */
+ ulint m_user_space_id;
+#endif /* UNIV_DEBUG */
+ /** User tablespace that is being modified by the mini-transaction */
+ fil_space_t* m_user_space;
+
+ /** State of the transaction */
+ mtr_state_t m_state;
+
+ /** Flush Observer */
+ FlushObserver* m_flush_observer;
/** LSN at commit time */
- volatile lsn_t m_commit_lsn;
+ lsn_t m_commit_lsn;
};
#include "mtr0mtr.ic"
diff --git a/storage/innobase/include/mtr0mtr.ic b/storage/innobase/include/mtr0mtr.ic
index 99057303c90..7f991269d46 100644
--- a/storage/innobase/include/mtr0mtr.ic
+++ b/storage/innobase/include/mtr0mtr.ic
@@ -49,7 +49,6 @@ mtr_t::memo_push(void* object, mtr_memo_type_t type)
ut_ad(object != NULL);
ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
ut_ad(type <= MTR_MEMO_SX_LOCK);
- ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
ut_ad(ut_is_2pow(type));
/* If this mtr has x-fixed a clean page then we set
@@ -58,15 +57,13 @@ mtr_t::memo_push(void* object, mtr_memo_type_t type)
can insert the dirtied page to the flush list. */
if ((type == MTR_MEMO_PAGE_X_FIX || type == MTR_MEMO_PAGE_SX_FIX)
- && !m_impl.m_made_dirty) {
+ && !m_made_dirty) {
- m_impl.m_made_dirty = is_block_dirtied(
+ m_made_dirty = is_block_dirtied(
reinterpret_cast<const buf_block_t*>(object));
}
- mtr_memo_slot_t* slot;
-
- slot = m_impl.m_memo.push<mtr_memo_slot_t*>(sizeof(*slot));
+ mtr_memo_slot_t* slot = m_memo.push<mtr_memo_slot_t*>(sizeof(*slot));
slot->type = type;
slot->object = object;
@@ -81,11 +78,9 @@ mtr_t::release_s_latch_at_savepoint(
rw_lock_t* lock)
{
ut_ad(is_active());
- ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
-
- ut_ad(m_impl.m_memo.size() > savepoint);
+ ut_ad(m_memo.size() > savepoint);
- mtr_memo_slot_t* slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint);
+ mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
ut_ad(slot->object == lock);
ut_ad(slot->type == MTR_MEMO_S_LOCK);
@@ -104,8 +99,7 @@ mtr_t::sx_latch_at_savepoint(
buf_block_t* block)
{
ut_ad(is_active());
- ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
- ut_ad(m_impl.m_memo.size() > savepoint);
+ ut_ad(m_memo.size() > savepoint);
ut_ad(!memo_contains_flagged(
block,
@@ -113,9 +107,7 @@ mtr_t::sx_latch_at_savepoint(
| MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_SX_FIX));
- mtr_memo_slot_t* slot;
-
- slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint);
+ mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
ut_ad(slot->object == block);
@@ -124,8 +116,8 @@ mtr_t::sx_latch_at_savepoint(
rw_lock_sx_lock(&block->lock);
- if (!m_impl.m_made_dirty) {
- m_impl.m_made_dirty = is_block_dirtied(block);
+ if (!m_made_dirty) {
+ m_made_dirty = is_block_dirtied(block);
}
slot->type = MTR_MEMO_PAGE_SX_FIX;
@@ -140,8 +132,7 @@ mtr_t::x_latch_at_savepoint(
buf_block_t* block)
{
ut_ad(is_active());
- ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
- ut_ad(m_impl.m_memo.size() > savepoint);
+ ut_ad(m_memo.size() > savepoint);
ut_ad(!memo_contains_flagged(
block,
@@ -149,9 +140,7 @@ mtr_t::x_latch_at_savepoint(
| MTR_MEMO_PAGE_X_FIX
| MTR_MEMO_PAGE_SX_FIX));
- mtr_memo_slot_t* slot;
-
- slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint);
+ mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
ut_ad(slot->object == block);
@@ -160,8 +149,8 @@ mtr_t::x_latch_at_savepoint(
rw_lock_x_lock(&block->lock);
- if (!m_impl.m_made_dirty) {
- m_impl.m_made_dirty = is_block_dirtied(block);
+ if (!m_made_dirty) {
+ m_made_dirty = is_block_dirtied(block);
}
slot->type = MTR_MEMO_PAGE_X_FIX;
@@ -176,11 +165,8 @@ mtr_t::release_block_at_savepoint(
buf_block_t* block)
{
ut_ad(is_active());
- ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
-
- mtr_memo_slot_t* slot;
- slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint);
+ mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
ut_a(slot->object == block);
@@ -198,10 +184,10 @@ Gets the logging mode of a mini-transaction.
mtr_log_t
mtr_t::get_log_mode() const
{
- ut_ad(m_impl.m_log_mode >= MTR_LOG_ALL);
- ut_ad(m_impl.m_log_mode <= MTR_LOG_SHORT_INSERTS);
+ ut_ad(m_log_mode >= MTR_LOG_ALL);
+ ut_ad(m_log_mode <= MTR_LOG_SHORT_INSERTS);
- return(m_impl.m_log_mode);
+ return m_log_mode;
}
/**
@@ -214,7 +200,7 @@ mtr_t::set_log_mode(mtr_log_t mode)
ut_ad(mode >= MTR_LOG_ALL);
ut_ad(mode <= MTR_LOG_SHORT_INSERTS);
- const mtr_log_t old_mode = m_impl.m_log_mode;
+ const mtr_log_t old_mode = m_log_mode;
switch (old_mode) {
case MTR_LOG_NO_REDO:
@@ -233,9 +219,8 @@ mtr_t::set_log_mode(mtr_log_t mode)
case MTR_LOG_ALL:
/* MTR_LOG_NO_REDO can only be set before generating
any redo log records. */
- ut_ad(mode != MTR_LOG_NO_REDO
- || m_impl.m_n_log_recs == 0);
- m_impl.m_log_mode = mode;
+ ut_ad(mode != MTR_LOG_NO_REDO || m_n_log_recs == 0);
+ m_log_mode = mode;
return(old_mode);
}
diff --git a/storage/innobase/include/mtr0types.h b/storage/innobase/include/mtr0types.h
index 1a4fd590f6e..bf7484b2337 100644
--- a/storage/innobase/include/mtr0types.h
+++ b/storage/innobase/include/mtr0types.h
@@ -36,18 +36,18 @@ struct mtr_t;
/** Logging modes for a mini-transaction */
enum mtr_log_t {
/** Default mode: log all operations modifying disk-based data */
- MTR_LOG_ALL = 21,
+ MTR_LOG_ALL = 0,
/** Log no operations and dirty pages are not added to the flush list.
Set when applying log in crash recovery or when a modification of a
ROW_FORMAT=COMPRESSED page is attempted. */
- MTR_LOG_NONE = 22,
+ MTR_LOG_NONE,
/** Don't generate REDO log but add dirty pages to flush list */
- MTR_LOG_NO_REDO = 23,
+ MTR_LOG_NO_REDO,
/** Inserts are logged in a shorter form */
- MTR_LOG_SHORT_INSERTS = 24
+ MTR_LOG_SHORT_INSERTS
};
/** @name Log item types
@@ -278,15 +278,10 @@ enum mtr_memo_type_t {
};
#endif /* !UNIV_CHECKSUM */
-#ifdef UNIV_DEBUG
-# define MTR_MAGIC_N 54551
-#endif /* UNIV_DEBUG */
-
enum mtr_state_t {
MTR_STATE_INIT = 0,
- MTR_STATE_ACTIVE = 12231,
- MTR_STATE_COMMITTING = 56456,
- MTR_STATE_COMMITTED = 34676
+ MTR_STATE_ACTIVE,
+ MTR_STATE_COMMITTED
};
#endif /* mtr0types_h */
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 422434734fa..9aecee0c217 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -27,7 +27,6 @@ Created 9/20/1997 Heikki Tuuri
#include "univ.i"
-#include <vector>
#include <map>
#include <string>
#include <my_service_manager.h>
@@ -3894,32 +3893,25 @@ recv_recovery_rollback_active(void)
@param[in] page_no page number
@return page frame
@retval NULL if no page was found */
-
const byte*
recv_dblwr_t::find_page(ulint space_id, ulint page_no)
{
- std::vector<const byte*, ut_allocator<const byte*> > matches;
- const byte* result = 0;
-
- for (const byte* page : pages) {
- if (page_get_space_id(page) == space_id
- && page_get_page_no(page) == page_no) {
- matches.push_back(page);
- }
- }
-
- lsn_t max_lsn = 0;
-
- for (const byte* page : matches) {
- lsn_t page_lsn = mach_read_from_8(page + FIL_PAGE_LSN);
-
- if (page_lsn > max_lsn) {
- max_lsn = page_lsn;
- result = page;
- }
- }
-
- return(result);
+ const byte *result= NULL;
+ lsn_t max_lsn= 0;
+
+ for (const byte *page : pages)
+ {
+ if (page_get_page_no(page) != page_no ||
+ page_get_space_id(page) != space_id)
+ continue;
+ const lsn_t lsn= mach_read_from_8(page + FIL_PAGE_LSN);
+ if (lsn <= max_lsn)
+ continue;
+ max_lsn= lsn;
+ result= page;
+ }
+
+ return result;
}
#ifndef DBUG_OFF
diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc
index 2c255478969..dbaae5e72bd 100644
--- a/storage/innobase/mtr/mtr0mtr.cc
+++ b/storage/innobase/mtr/mtr0mtr.cc
@@ -343,6 +343,7 @@ struct ReleaseAll {
}
};
+#ifdef UNIV_DEBUG
/** Check that all slots have been handled. */
struct DebugCheck {
/** @return true always. */
@@ -352,6 +353,7 @@ struct DebugCheck {
return(true);
}
};
+#endif
/** Release a resource acquired by the mini-transaction. */
struct ReleaseBlocks {
@@ -404,59 +406,6 @@ struct ReleaseBlocks {
FlushObserver* m_flush_observer;
};
-class mtr_t::Command {
-public:
- /** Constructor.
- Takes ownership of the mtr->m_impl, is responsible for deleting it.
- @param[in,out] mtr mini-transaction */
- explicit Command(mtr_t* mtr) : m_impl(&mtr->m_impl), m_locks_released()
- {}
-
- /** Destructor */
- ~Command()
- {
- ut_ad(m_impl == 0);
- }
-
- /** Write the redo log record, add dirty pages to the flush list and
- release the resources. */
- void execute();
-
- /** Release the blocks used in this mini-transaction. */
- void release_blocks();
-
- /** Release the latches acquired by the mini-transaction. */
- void release_latches();
-
- /** Release both the latches and blocks used in the mini-transaction. */
- void release_all();
-
- /** Release the resources */
- void release_resources();
-
- /** Append the redo log records to the redo log buffer.
- @param[in] len number of bytes to write */
- void finish_write(ulint len);
-
-private:
- /** Prepare to write the mini-transaction log to the redo log buffer.
- @return number of bytes to write in finish_write() */
- ulint prepare_write();
-
- /** The mini-transaction state. */
- mtr_t::Impl* m_impl;
-
- /** Set to 1 after the user thread releases the latches. The log
- writer thread must wait for this to be set to 1. */
- volatile ulint m_locks_released;
-
- /** Start lsn of the possible log entry for this mtr */
- lsn_t m_start_lsn;
-
- /** End lsn of the possible log entry for this mtr */
- lsn_t m_end_lsn;
-};
-
/** Write the block contents to the REDO log */
struct mtr_write_log_t {
/** Append a block to the redo log buffer.
@@ -490,76 +439,75 @@ mtr_write_log(
/** Start a mini-transaction. */
void mtr_t::start()
{
- UNIV_MEM_INVALID(this, sizeof(*this));
-
- UNIV_MEM_INVALID(&m_impl, sizeof(m_impl));
-
- m_commit_lsn = 0;
-
- new(&m_impl.m_log) mtr_buf_t();
- new(&m_impl.m_memo) mtr_buf_t();
-
- m_impl.m_mtr = this;
- m_impl.m_log_mode = MTR_LOG_ALL;
- m_impl.m_inside_ibuf = false;
- m_impl.m_modifications = false;
- m_impl.m_made_dirty = false;
- m_impl.m_n_log_recs = 0;
- m_impl.m_state = MTR_STATE_ACTIVE;
- ut_d(m_impl.m_user_space_id = TRX_SYS_SPACE);
- m_impl.m_user_space = NULL;
- m_impl.m_flush_observer = NULL;
-
- ut_d(m_impl.m_magic_n = MTR_MAGIC_N);
+ UNIV_MEM_INVALID(this, sizeof *this);
+
+ new(&m_memo) mtr_buf_t();
+ new(&m_log) mtr_buf_t();
+
+ m_made_dirty= false;
+ m_inside_ibuf= false;
+ m_modifications= false;
+ m_n_log_recs= 0;
+ m_log_mode= MTR_LOG_ALL;
+ ut_d(m_user_space_id= TRX_SYS_SPACE);
+ m_user_space= NULL;
+ m_state= MTR_STATE_ACTIVE;
+ m_flush_observer= NULL;
+ m_commit_lsn= 0;
}
/** Release the resources */
-void
-mtr_t::Command::release_resources()
+inline void mtr_t::release_resources()
{
- ut_ad(m_impl->m_magic_n == MTR_MAGIC_N);
-
- /* Currently only used in commit */
- ut_ad(m_impl->m_state == MTR_STATE_COMMITTING);
-
- ut_d(m_impl->m_memo.for_each_block_in_reverse(CIterate<DebugCheck>()));
-
- /* Reset the mtr buffers */
- m_impl->m_log.erase();
-
- m_impl->m_memo.erase();
-
- m_impl->m_state = MTR_STATE_COMMITTED;
-
- m_impl = 0;
+ ut_d(m_memo.for_each_block_in_reverse(CIterate<DebugCheck>()));
+ m_log.erase();
+ m_memo.erase();
+ m_state= MTR_STATE_COMMITTED;
}
/** Commit a mini-transaction. */
void
mtr_t::commit()
{
- ut_ad(is_active());
- ut_ad(!is_inside_ibuf());
- ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
- m_impl.m_state = MTR_STATE_COMMITTING;
+ ut_ad(is_active());
+ ut_ad(!is_inside_ibuf());
- /* This is a dirty read, for debugging. */
- ut_ad(!m_impl.m_modifications || !recv_no_log_write);
+ /* This is a dirty read, for debugging. */
+ ut_ad(!m_modifications || !recv_no_log_write);
+ ut_ad(!m_modifications || m_log_mode != MTR_LOG_NONE);
- Command cmd(this);
+ if (m_modifications
+ && (m_n_log_recs || m_log_mode == MTR_LOG_NO_REDO))
+ {
+ ut_ad(!srv_read_only_mode || m_log_mode == MTR_LOG_NO_REDO);
- if (m_impl.m_modifications
- && (m_impl.m_n_log_recs > 0
- || m_impl.m_log_mode == MTR_LOG_NO_REDO)) {
+ lsn_t start_lsn;
- ut_ad(!srv_read_only_mode
- || m_impl.m_log_mode == MTR_LOG_NO_REDO);
+ if (const ulint len= prepare_write())
+ start_lsn= finish_write(len);
+ else
+ start_lsn= m_commit_lsn;
- cmd.execute();
- } else {
- cmd.release_all();
- cmd.release_resources();
- }
+ if (m_made_dirty)
+ log_flush_order_mutex_enter();
+
+ /* It is now safe to release the log mutex because the
+ flush_order mutex will ensure that we are the first one
+ to insert into the flush list. */
+ log_mutex_exit();
+
+ m_memo.for_each_block_in_reverse(CIterate<const ReleaseBlocks>
+ (ReleaseBlocks(start_lsn, m_commit_lsn,
+ m_flush_observer)));
+ if (m_made_dirty)
+ log_flush_order_mutex_exit();
+
+ m_memo.for_each_block_in_reverse(CIterate<ReleaseLatches>());
+ }
+ else
+ m_memo.for_each_block_in_reverse(CIterate<ReleaseAll>());
+
+ release_resources();
}
/** Commit a mini-transaction that did not modify any pages,
@@ -578,35 +526,31 @@ mtr_t::commit_checkpoint(
ut_ad(log_mutex_own());
ut_ad(is_active());
ut_ad(!is_inside_ibuf());
- ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
ut_ad(get_log_mode() == MTR_LOG_ALL);
- ut_ad(!m_impl.m_made_dirty);
- ut_ad(m_impl.m_memo.size() == 0);
+ ut_ad(!m_made_dirty);
+ ut_ad(m_memo.size() == 0);
ut_ad(!srv_read_only_mode);
- ut_d(m_impl.m_state = MTR_STATE_COMMITTING);
- ut_ad(write_mlog_checkpoint || m_impl.m_n_log_recs > 1);
+ ut_ad(write_mlog_checkpoint || m_n_log_recs > 1);
- switch (m_impl.m_n_log_recs) {
+ switch (m_n_log_recs) {
case 0:
break;
case 1:
- *m_impl.m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG;
+ *m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG;
break;
default:
- mlog_catenate_ulint(
- &m_impl.m_log, MLOG_MULTI_REC_END, MLOG_1BYTE);
+ mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END, MLOG_1BYTE);
}
if (write_mlog_checkpoint) {
- byte* ptr = m_impl.m_log.push<byte*>(SIZE_OF_MLOG_CHECKPOINT);
+ byte* ptr = m_log.push<byte*>(SIZE_OF_MLOG_CHECKPOINT);
compile_time_assert(SIZE_OF_MLOG_CHECKPOINT == 1 + 8);
*ptr = MLOG_CHECKPOINT;
mach_write_to_8(ptr + 1, checkpoint_lsn);
}
- Command cmd(this);
- cmd.finish_write(m_impl.m_log.size());
- cmd.release_resources();
+ finish_write(m_log.size());
+ release_resources();
if (write_mlog_checkpoint) {
DBUG_PRINT("ib_log",
@@ -623,8 +567,7 @@ mtr_t::commit_checkpoint(
bool
mtr_t::is_named_space(ulint space) const
{
- ut_ad(!m_impl.m_user_space
- || m_impl.m_user_space->id != TRX_SYS_SPACE);
+ ut_ad(!m_user_space || m_user_space->id != TRX_SYS_SPACE);
switch (get_log_mode()) {
case MTR_LOG_NONE:
@@ -632,7 +575,7 @@ mtr_t::is_named_space(ulint space) const
return(true);
case MTR_LOG_ALL:
case MTR_LOG_SHORT_INSERTS:
- return(m_impl.m_user_space_id == space
+ return(m_user_space_id == space
|| is_predefined_tablespace(space));
}
@@ -645,21 +588,19 @@ mtr_t::is_named_space(ulint space) const
@return whether the mini-transaction is associated with the space */
bool mtr_t::is_named_space(const fil_space_t* space) const
{
- ut_ad(!m_impl.m_user_space
- || m_impl.m_user_space->id != TRX_SYS_SPACE);
-
- switch (get_log_mode()) {
- case MTR_LOG_NONE:
- case MTR_LOG_NO_REDO:
- return true;
- case MTR_LOG_ALL:
- case MTR_LOG_SHORT_INSERTS:
- return(m_impl.m_user_space == space
- || is_predefined_tablespace(space->id));
- }
-
- ut_error;
- return false;
+ ut_ad(!m_user_space || m_user_space->id != TRX_SYS_SPACE);
+
+ switch (get_log_mode()) {
+ case MTR_LOG_NONE:
+ case MTR_LOG_NO_REDO:
+ return true;
+ case MTR_LOG_ALL:
+ case MTR_LOG_SHORT_INSERTS:
+ return m_user_space == space || is_predefined_tablespace(space->id);
+ }
+
+ ut_error;
+ return false;
}
#endif /* UNIV_DEBUG */
@@ -674,12 +615,11 @@ mtr_t::x_lock_space(ulint space_id, const char* file, unsigned line)
{
fil_space_t* space;
- ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
ut_ad(is_active());
if (space_id == TRX_SYS_SPACE) {
space = fil_system.sys_space;
- } else if ((space = m_impl.m_user_space) && space_id == space->id) {
+ } else if ((space = m_user_space) && space_id == space->id) {
} else {
space = fil_space_get(space_id);
ut_ad(get_log_mode() != MTR_LOG_NO_REDO
@@ -702,16 +642,15 @@ mtr_t::x_lock_space(ulint space_id, const char* file, unsigned line)
bool
mtr_t::memo_release(const void* object, ulint type)
{
- ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
ut_ad(is_active());
/* We cannot release a page that has been written to in the
middle of a mini-transaction. */
- ut_ad(!m_impl.m_modifications || type != MTR_MEMO_PAGE_X_FIX);
+ ut_ad(!m_modifications || type != MTR_MEMO_PAGE_X_FIX);
Iterate<Find> iteration(Find(object, type));
- if (!m_impl.m_memo.for_each_block_in_reverse(iteration)) {
+ if (!m_memo.for_each_block_in_reverse(iteration)) {
memo_slot_release(iteration.functor.m_slot);
return(true);
}
@@ -725,16 +664,15 @@ mtr_t::memo_release(const void* object, ulint type)
void
mtr_t::release_page(const void* ptr, mtr_memo_type_t type)
{
- ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
ut_ad(is_active());
/* We cannot release a page that has been written to in the
middle of a mini-transaction. */
- ut_ad(!m_impl.m_modifications || type != MTR_MEMO_PAGE_X_FIX);
+ ut_ad(!m_modifications || type != MTR_MEMO_PAGE_X_FIX);
Iterate<FindPage> iteration(FindPage(ptr, type));
- if (!m_impl.m_memo.for_each_block_in_reverse(iteration)) {
+ if (!m_memo.for_each_block_in_reverse(iteration)) {
memo_slot_release(iteration.functor.get_slot());
return;
}
@@ -745,27 +683,20 @@ mtr_t::release_page(const void* ptr, mtr_memo_type_t type)
/** Prepare to write the mini-transaction log to the redo log buffer.
@return number of bytes to write in finish_write() */
-ulint
-mtr_t::Command::prepare_write()
+inline ulint mtr_t::prepare_write()
{
ut_ad(!recv_no_log_write);
- switch (m_impl->m_log_mode) {
- case MTR_LOG_SHORT_INSERTS:
- ut_ad(0);
- /* fall through */
- case MTR_LOG_NO_REDO:
- case MTR_LOG_NONE:
- ut_ad(m_impl->m_log.size() == 0);
+ if (UNIV_UNLIKELY(m_log_mode != MTR_LOG_ALL)) {
+ ut_ad(m_log_mode == MTR_LOG_NO_REDO);
+ ut_ad(m_log.size() == 0);
log_mutex_enter();
- m_end_lsn = m_start_lsn = log_sys.lsn;
- return(0);
- case MTR_LOG_ALL:
- break;
+ m_commit_lsn = log_sys.lsn;
+ return 0;
}
- ulint len = m_impl->m_log.size();
- ulint n_recs = m_impl->m_n_log_recs;
+ ulint len = m_log.size();
+ ulint n_recs = m_n_log_recs;
ut_ad(len > 0);
ut_ad(n_recs > 0);
@@ -773,9 +704,9 @@ mtr_t::Command::prepare_write()
log_buffer_extend(ulong((len + 1) * 2));
}
- ut_ad(m_impl->m_n_log_recs == n_recs);
+ ut_ad(m_n_log_recs == n_recs);
- fil_space_t* space = m_impl->m_user_space;
+ fil_space_t* space = m_user_space;
if (space != NULL && is_predefined_tablespace(space->id)) {
/* Omit MLOG_FILE_NAME for predefined tablespaces. */
@@ -784,35 +715,32 @@ mtr_t::Command::prepare_write()
log_mutex_enter();
- if (fil_names_write_if_was_clean(space, m_impl->m_mtr)) {
+ if (fil_names_write_if_was_clean(space, this)) {
/* This mini-transaction was the first one to modify
this tablespace since the latest checkpoint, so
some MLOG_FILE_NAME records were appended to m_log. */
- ut_ad(m_impl->m_n_log_recs > n_recs);
- mlog_catenate_ulint(
- &m_impl->m_log, MLOG_MULTI_REC_END, MLOG_1BYTE);
- len = m_impl->m_log.size();
+ ut_ad(m_n_log_recs > n_recs);
+ mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END, MLOG_1BYTE);
+ len = m_log.size();
} else {
/* This was not the first time of dirtying a
tablespace since the latest checkpoint. */
- ut_ad(n_recs == m_impl->m_n_log_recs);
+ ut_ad(n_recs == m_n_log_recs);
if (n_recs <= 1) {
ut_ad(n_recs == 1);
/* Flag the single log record as the
only record in this mini-transaction. */
- *m_impl->m_log.front()->begin()
- |= MLOG_SINGLE_REC_FLAG;
+ *m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG;
} else {
/* Because this mini-transaction comprises
multiple log records, append MLOG_MULTI_REC_END
at the end. */
- mlog_catenate_ulint(
- &m_impl->m_log, MLOG_MULTI_REC_END,
- MLOG_1BYTE);
+ mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END,
+ MLOG_1BYTE);
len++;
}
}
@@ -824,98 +752,37 @@ mtr_t::Command::prepare_write()
}
/** Append the redo log records to the redo log buffer
-@param[in] len number of bytes to write */
-void
-mtr_t::Command::finish_write(
- ulint len)
+@param[in] len number of bytes to write
+@return start_lsn */
+inline lsn_t mtr_t::finish_write(ulint len)
{
- ut_ad(m_impl->m_log_mode == MTR_LOG_ALL);
+ ut_ad(m_log_mode == MTR_LOG_ALL);
ut_ad(log_mutex_own());
- ut_ad(m_impl->m_log.size() == len);
+ ut_ad(m_log.size() == len);
ut_ad(len > 0);
- if (m_impl->m_log.is_small()) {
- const mtr_buf_t::block_t* front = m_impl->m_log.front();
+ lsn_t start_lsn;
+
+ if (m_log.is_small()) {
+ const mtr_buf_t::block_t* front = m_log.front();
ut_ad(len <= front->used());
- m_end_lsn = log_reserve_and_write_fast(
- front->begin(), len, &m_start_lsn);
+ m_commit_lsn = log_reserve_and_write_fast(front->begin(), len,
+ &start_lsn);
- if (m_end_lsn > 0) {
- return;
+ if (m_commit_lsn) {
+ return start_lsn;
}
}
/* Open the database log for log_write_low */
- m_start_lsn = log_reserve_and_open(len);
+ start_lsn = log_reserve_and_open(len);
mtr_write_log_t write_log;
- m_impl->m_log.for_each_block(write_log);
-
- m_end_lsn = log_close();
-}
-
-/** Release the latches and blocks acquired by this mini-transaction */
-void
-mtr_t::Command::release_all()
-{
- m_impl->m_memo.for_each_block_in_reverse(CIterate<ReleaseAll>());
-
- /* Note that we have released the latches. */
- m_locks_released = 1;
-}
-
-/** Release the latches acquired by this mini-transaction */
-void
-mtr_t::Command::release_latches()
-{
- m_impl->m_memo.for_each_block_in_reverse(CIterate<ReleaseLatches>());
+ m_log.for_each_block(write_log);
- /* Note that we have released the latches. */
- m_locks_released = 1;
-}
-
-/** Release the blocks used in this mini-transaction */
-void
-mtr_t::Command::release_blocks()
-{
- m_impl->m_memo.for_each_block_in_reverse(
- CIterate<const ReleaseBlocks>(
- ReleaseBlocks(m_start_lsn, m_end_lsn,
- m_impl->m_flush_observer)));
-}
-
-/** Write the redo log record, add dirty pages to the flush list and release
-the resources. */
-void
-mtr_t::Command::execute()
-{
- ut_ad(m_impl->m_log_mode != MTR_LOG_NONE);
-
- if (const ulint len = prepare_write()) {
- finish_write(len);
- }
-
- if (m_impl->m_made_dirty) {
- log_flush_order_mutex_enter();
- }
-
- /* It is now safe to release the log mutex because the
- flush_order mutex will ensure that we are the first one
- to insert into the flush list. */
- log_mutex_exit();
-
- m_impl->m_mtr->m_commit_lsn = m_end_lsn;
-
- release_blocks();
-
- if (m_impl->m_made_dirty) {
- log_flush_order_mutex_exit();
- }
-
- release_latches();
-
- release_resources();
+ m_commit_lsn = log_close();
+ return start_lsn;
}
#ifdef UNIV_DEBUG
@@ -1014,10 +881,9 @@ struct FlaggedCheck {
bool
mtr_t::memo_contains_flagged(const void* ptr, ulint flags) const
{
- ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
- ut_ad(is_committing() || is_active());
+ ut_ad(is_active());
- return !m_impl.m_memo.for_each_block_in_reverse(
+ return !m_memo.for_each_block_in_reverse(
CIterate<FlaggedCheck>(FlaggedCheck(ptr, flags)));
}
@@ -1033,7 +899,7 @@ mtr_t::memo_contains_page_flagged(
ulint flags) const
{
Iterate<FindPage> iteration(FindPage(ptr, flags));
- return m_impl.m_memo.for_each_block_in_reverse(iteration)
+ return m_memo.for_each_block_in_reverse(iteration)
? NULL : iteration.functor.get_block();
}
@@ -1056,7 +922,7 @@ void
mtr_t::print() const
{
ib::info() << "Mini-transaction handle: memo size "
- << m_impl.m_memo.size() << " bytes log size "
+ << m_memo.size() << " bytes log size "
<< get_log()->size() << " bytes";
}