Merge 10.4 into 10.5
This commit is contained in:
commit
1fe6e5a1a5
@ -1810,5 +1810,61 @@ b a a b
|
|||||||
9 9 10 10
|
9 9 10 10
|
||||||
set optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity;
|
set optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity;
|
||||||
drop table t1,t2,t3;
|
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
|
# End of 10.1 tests
|
||||||
set @@global.histogram_size=@save_histogram_size;
|
set @@global.histogram_size=@save_histogram_size;
|
||||||
|
@ -1235,6 +1235,38 @@ set optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity;
|
|||||||
|
|
||||||
drop table t1,t2,t3;
|
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
|
--echo # End of 10.1 tests
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -1820,6 +1820,62 @@ b a a b
|
|||||||
9 9 10 10
|
9 9 10 10
|
||||||
set optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity;
|
set optimizer_use_condition_selectivity= @@optimizer_use_condition_selectivity;
|
||||||
drop table t1,t2,t3;
|
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
|
# End of 10.1 tests
|
||||||
set @@global.histogram_size=@save_histogram_size;
|
set @@global.histogram_size=@save_histogram_size;
|
||||||
set optimizer_switch=@save_optimizer_switch_for_selectivity_test;
|
set optimizer_switch=@save_optimizer_switch_for_selectivity_test;
|
||||||
|
@ -30,7 +30,7 @@ SET GLOBAL master_verify_checksum=0;
|
|||||||
SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set";
|
SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set";
|
||||||
connection slave;
|
connection slave;
|
||||||
START SLAVE IO_THREAD;
|
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;
|
connection master;
|
||||||
SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set";
|
SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set";
|
||||||
SET GLOBAL debug_dbug= "";
|
SET GLOBAL debug_dbug= "";
|
||||||
@ -39,7 +39,7 @@ SET GLOBAL master_verify_checksum=1;
|
|||||||
connection slave;
|
connection slave;
|
||||||
SET GLOBAL debug_dbug="+d,corrupt_queue_event";
|
SET GLOBAL debug_dbug="+d,corrupt_queue_event";
|
||||||
START SLAVE IO_THREAD;
|
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";
|
SET GLOBAL debug_dbug="-d,corrupt_queue_event";
|
||||||
# 6. Slave. Corruption in relay log
|
# 6. Slave. Corruption in relay log
|
||||||
SET GLOBAL debug_dbug="+d,corrupt_read_log_event_char";
|
SET GLOBAL debug_dbug="+d,corrupt_read_log_event_char";
|
||||||
|
@ -122,11 +122,11 @@ SET GLOBAL master_verify_checksum=0;
|
|||||||
SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set";
|
SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set";
|
||||||
--connection slave
|
--connection slave
|
||||||
START SLAVE IO_THREAD;
|
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
|
# (ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE) in queue_event(), then immediately
|
||||||
# sets error 1595 (ER_SLAVE_RELAY_LOG_WRITE_FAILURE) in handle_slave_io().
|
# 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.
|
# So we usually get 1595, but it is occasionally possible to get 1743.
|
||||||
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
|
--source include/wait_for_slave_io_error.inc
|
||||||
--connection master
|
--connection master
|
||||||
SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set";
|
SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set";
|
||||||
@ -138,7 +138,7 @@ SET GLOBAL master_verify_checksum=1;
|
|||||||
--connection slave
|
--connection slave
|
||||||
SET GLOBAL debug_dbug="+d,corrupt_queue_event";
|
SET GLOBAL debug_dbug="+d,corrupt_queue_event";
|
||||||
START SLAVE IO_THREAD;
|
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
|
--source include/wait_for_slave_io_error.inc
|
||||||
SET GLOBAL debug_dbug="-d,corrupt_queue_event";
|
SET GLOBAL debug_dbug="-d,corrupt_queue_event";
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ SET GLOBAL master_verify_checksum=0;
|
|||||||
SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set";
|
SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set";
|
||||||
connection slave;
|
connection slave;
|
||||||
START SLAVE IO_THREAD;
|
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;
|
connection master;
|
||||||
SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set";
|
SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set";
|
||||||
SET GLOBAL debug_dbug= "";
|
SET GLOBAL debug_dbug= "";
|
||||||
@ -39,7 +39,7 @@ SET GLOBAL master_verify_checksum=1;
|
|||||||
connection slave;
|
connection slave;
|
||||||
SET GLOBAL debug_dbug="+d,corrupt_queue_event";
|
SET GLOBAL debug_dbug="+d,corrupt_queue_event";
|
||||||
START SLAVE IO_THREAD;
|
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";
|
SET GLOBAL debug_dbug="-d,corrupt_queue_event";
|
||||||
# 6. Slave. Corruption in relay log
|
# 6. Slave. Corruption in relay log
|
||||||
SET GLOBAL debug_dbug="+d,corrupt_read_log_event_char";
|
SET GLOBAL debug_dbug="+d,corrupt_read_log_event_char";
|
||||||
|
40
mysql-test/suite/rpl/r/rpl_semi_sync_gtid_reconnect.result
Normal file
40
mysql-test/suite/rpl/r/rpl_semi_sync_gtid_reconnect.result
Normal file
@ -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
|
74
mysql-test/suite/rpl/t/rpl_semi_sync_gtid_reconnect.test
Normal file
74
mysql-test/suite/rpl/t/rpl_semi_sync_gtid_reconnect.test
Normal file
@ -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
|
@ -83,7 +83,14 @@ fi
|
|||||||
pcmd="pv $pvopts"
|
pcmd="pv $pvopts"
|
||||||
declare -a RC
|
declare -a RC
|
||||||
|
|
||||||
|
set +e
|
||||||
INNOBACKUPEX_BIN=$(which mariabackup)
|
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
|
XBSTREAM_BIN=mbstream
|
||||||
XBCRYPT_BIN=xbcrypt # Not available in MariaBackup
|
XBCRYPT_BIN=xbcrypt # Not available in MariaBackup
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "sql_alloc.h"
|
#include "sql_alloc.h"
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Simple intrusive linked list.
|
Simple intrusive linked list.
|
||||||
@ -532,6 +533,51 @@ public:
|
|||||||
List<T> *res= new (mem_root) List<T>;
|
List<T> *res= new (mem_root) List<T>;
|
||||||
return res == NULL || res->push_back(first, mem_root) ? NULL : res;
|
return res == NULL || res->push_back(first, mem_root) ? NULL : res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Iterator;
|
||||||
|
using value_type= T;
|
||||||
|
using iterator= Iterator;
|
||||||
|
using const_iterator= const Iterator;
|
||||||
|
|
||||||
|
Iterator begin() const { return Iterator(first); }
|
||||||
|
Iterator end() const { return Iterator(); }
|
||||||
|
|
||||||
|
class Iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using iterator_category= std::forward_iterator_tag;
|
||||||
|
using value_type= T;
|
||||||
|
using difference_type= std::ptrdiff_t;
|
||||||
|
using pointer= T *;
|
||||||
|
using reference= T &;
|
||||||
|
|
||||||
|
Iterator(list_node *p= &end_of_list) : node{p} {}
|
||||||
|
|
||||||
|
Iterator &operator++()
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(node != &end_of_list);
|
||||||
|
|
||||||
|
node= node->next;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator++(int)
|
||||||
|
{
|
||||||
|
Iterator tmp(*this);
|
||||||
|
operator++();
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
T &operator*() { return *static_cast<T *>(node->info); }
|
||||||
|
|
||||||
|
bool operator!=(const typename List<T>::iterator &rhs)
|
||||||
|
{
|
||||||
|
return node != rhs.node;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
list_node *node{&end_of_list};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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. */
|
/* Check if the dump thread is created by a slave with semisync enabled. */
|
||||||
thd->semi_sync_slave = is_semi_sync_slave();
|
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->errmsg= "Failed to run hook 'transmit_start'";
|
||||||
info->error= ER_UNKNOWN_ERROR;
|
info->error= ER_UNKNOWN_ERROR;
|
||||||
|
@ -9090,7 +9090,6 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
|
|||||||
something went wrong.
|
something went wrong.
|
||||||
*/
|
*/
|
||||||
sel /= (double)table->quick_rows[key] / (double) table->stat_records();
|
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);
|
set_if_smaller(sel, 1.0);
|
||||||
used_range_selectivity= true;
|
used_range_selectivity= true;
|
||||||
}
|
}
|
||||||
@ -9139,7 +9138,6 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
|
|||||||
if (table->field[fldno]->cond_selectivity > 0)
|
if (table->field[fldno]->cond_selectivity > 0)
|
||||||
{
|
{
|
||||||
sel /= table->field[fldno]->cond_selectivity;
|
sel /= table->field[fldno]->cond_selectivity;
|
||||||
// MDEV-20595 FIXME: DBUG_ASSERT(sel > 0 && sel <= 2.0);
|
|
||||||
set_if_smaller(sel, 1.0);
|
set_if_smaller(sel, 1.0);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -9197,7 +9195,6 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
|
|||||||
if (field->cond_selectivity > 0)
|
if (field->cond_selectivity > 0)
|
||||||
{
|
{
|
||||||
sel/= field->cond_selectivity;
|
sel/= field->cond_selectivity;
|
||||||
// MDEV-20595 FIXME: DBUG_ASSERT(sel > 0 && sel <= 2.0);
|
|
||||||
set_if_smaller(sel, 1.0);
|
set_if_smaller(sel, 1.0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -9209,7 +9206,6 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
|
|||||||
sel*= table_multi_eq_cond_selectivity(join, idx, s, rem_tables,
|
sel*= table_multi_eq_cond_selectivity(join, idx, s, rem_tables,
|
||||||
keyparts, ref_keyuse_steps);
|
keyparts, ref_keyuse_steps);
|
||||||
|
|
||||||
DBUG_ASSERT(0.0 < sel && sel <= 1.0);
|
|
||||||
return sel;
|
return sel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
#include "sql_audit.h"
|
#include "sql_audit.h"
|
||||||
#include "sql_sequence.h"
|
#include "sql_sequence.h"
|
||||||
#include "tztime.h"
|
#include "tztime.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
@ -3024,34 +3024,37 @@ CHARSET_INFO* get_sql_field_charset(Column_definition *sql_field,
|
|||||||
|
|
||||||
void promote_first_timestamp_column(List<Create_field> *column_definitions)
|
void promote_first_timestamp_column(List<Create_field> *column_definitions)
|
||||||
{
|
{
|
||||||
List_iterator_fast<Create_field> it(*column_definitions);
|
for (Create_field &column_definition : *column_definitions)
|
||||||
Create_field *column_definition;
|
|
||||||
|
|
||||||
while ((column_definition= it++) != NULL)
|
|
||||||
{
|
{
|
||||||
if (column_definition->is_timestamp_type() || // TIMESTAMP
|
if (column_definition.is_timestamp_type() || // TIMESTAMP
|
||||||
column_definition->unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy
|
column_definition.unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("field-ptr:%p", column_definition->field));
|
DBUG_PRINT("info", ("field-ptr:%p", column_definition.field));
|
||||||
if ((column_definition->flags & NOT_NULL_FLAG) != 0 && // NOT NULL,
|
if ((column_definition.flags & NOT_NULL_FLAG) != 0 && // NOT NULL,
|
||||||
column_definition->default_value == NULL && // no constant default,
|
column_definition.default_value == NULL && // no constant default,
|
||||||
column_definition->unireg_check == Field::NONE && // no function default
|
column_definition.unireg_check == Field::NONE && // no function default
|
||||||
column_definition->vcol_info == NULL &&
|
column_definition.vcol_info == NULL &&
|
||||||
column_definition->period == NULL &&
|
column_definition.period == NULL &&
|
||||||
!(column_definition->flags & VERS_SYSTEM_FIELD)) // column isn't generated
|
!(column_definition.flags & VERS_SYSTEM_FIELD)) // column isn't generated
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("First TIMESTAMP column '%s' was promoted to "
|
DBUG_PRINT("info", ("First TIMESTAMP column '%s' was promoted to "
|
||||||
"DEFAULT CURRENT_TIMESTAMP ON UPDATE "
|
"DEFAULT CURRENT_TIMESTAMP ON UPDATE "
|
||||||
"CURRENT_TIMESTAMP",
|
"CURRENT_TIMESTAMP",
|
||||||
column_definition->field_name.str
|
column_definition.field_name.str
|
||||||
));
|
));
|
||||||
column_definition->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
|
column_definition.unireg_check= Field::TIMESTAMP_DNUN_FIELD;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool key_cmp(const Key_part_spec &a, const Key_part_spec &b)
|
||||||
|
{
|
||||||
|
return a.length == b.length &&
|
||||||
|
!lex_string_cmp(system_charset_info, &a.field_name, &b.field_name);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Check if there is a duplicate key. Report a warning for every duplicate key.
|
Check if there is a duplicate key. Report a warning for every duplicate key.
|
||||||
|
|
||||||
@ -3060,8 +3063,8 @@ void promote_first_timestamp_column(List<Create_field> *column_definitions)
|
|||||||
@param key_info Key meta-data info.
|
@param key_info Key meta-data info.
|
||||||
@param key_list List of existing keys.
|
@param key_list List of existing keys.
|
||||||
*/
|
*/
|
||||||
static void check_duplicate_key(THD *thd, Key *key, KEY *key_info,
|
static void check_duplicate_key(THD *thd, const Key *key, const KEY *key_info,
|
||||||
List<Key> *key_list)
|
const List<Key> *key_list)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We only check for duplicate indexes if it is requested and the
|
We only check for duplicate indexes if it is requested and the
|
||||||
@ -3073,56 +3076,28 @@ static void check_duplicate_key(THD *thd, Key *key, KEY *key_info,
|
|||||||
if (!key->key_create_info.check_for_duplicate_indexes || key->generated)
|
if (!key->key_create_info.check_for_duplicate_indexes || key->generated)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
List_iterator_fast<Key> key_list_iterator(*key_list);
|
for (const Key &k : *key_list)
|
||||||
List_iterator_fast<Key_part_spec> key_column_iterator(key->columns);
|
|
||||||
Key *k;
|
|
||||||
|
|
||||||
while ((k= key_list_iterator++))
|
|
||||||
{
|
{
|
||||||
// Looking for a similar key...
|
// Looking for a similar key...
|
||||||
|
|
||||||
if (k == key)
|
if (&k == key)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (k->generated ||
|
if (k.generated ||
|
||||||
(key->type != k->type) ||
|
(key->type != k.type) ||
|
||||||
(key->key_create_info.algorithm != k->key_create_info.algorithm) ||
|
(key->key_create_info.algorithm != k.key_create_info.algorithm) ||
|
||||||
(key->columns.elements != k->columns.elements))
|
(key->columns.elements != k.columns.elements))
|
||||||
{
|
{
|
||||||
// Keys are different.
|
// Keys are different.
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (std::equal(key->columns.begin(), key->columns.end(), k.columns.begin(),
|
||||||
Keys 'key' and 'k' might be identical.
|
key_cmp))
|
||||||
Check that the keys have identical columns in the same order.
|
|
||||||
*/
|
|
||||||
|
|
||||||
List_iterator_fast<Key_part_spec> k_column_iterator(k->columns);
|
|
||||||
uint i;
|
|
||||||
key_column_iterator.rewind();
|
|
||||||
|
|
||||||
for (i= 0; i < key->columns.elements; ++i)
|
|
||||||
{
|
{
|
||||||
Key_part_spec *c1= key_column_iterator++;
|
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, ER_DUP_INDEX,
|
||||||
Key_part_spec *c2= k_column_iterator++;
|
ER_THD(thd, ER_DUP_INDEX), key_info->name.str);
|
||||||
|
return;
|
||||||
DBUG_ASSERT(c1 && c2);
|
|
||||||
|
|
||||||
if (lex_string_cmp(system_charset_info,
|
|
||||||
&c1->field_name, &c2->field_name) ||
|
|
||||||
(c1->length != c2->length))
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Report a warning if we have two identical keys.
|
|
||||||
|
|
||||||
if (i == key->columns.elements)
|
|
||||||
{
|
|
||||||
push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
|
|
||||||
ER_DUP_INDEX, ER_THD(thd, ER_DUP_INDEX),
|
|
||||||
key_info->name.str);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
sql/table.cc
20
sql/table.cc
@ -5248,6 +5248,8 @@ void TABLE::init(THD *thd, TABLE_LIST *tl)
|
|||||||
update_handler= NULL;
|
update_handler= NULL;
|
||||||
check_unique_buf= NULL;
|
check_unique_buf= NULL;
|
||||||
vers_write= s->versioned;
|
vers_write= s->versioned;
|
||||||
|
quick_condition_rows=0;
|
||||||
|
initialize_quick_structures();
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
/* used in RBR Triggers */
|
/* used in RBR Triggers */
|
||||||
master_had_triggers= 0;
|
master_had_triggers= 0;
|
||||||
@ -9743,3 +9745,21 @@ bool TABLE::export_structure(THD *thd, Row_definition_list *defs)
|
|||||||
}
|
}
|
||||||
return false;
|
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));
|
||||||
|
}
|
||||||
|
@ -1524,6 +1524,7 @@ public:
|
|||||||
bool is_filled_at_execution();
|
bool is_filled_at_execution();
|
||||||
|
|
||||||
bool update_const_key_parts(COND *conds);
|
bool update_const_key_parts(COND *conds);
|
||||||
|
void initialize_quick_structures();
|
||||||
|
|
||||||
my_ptrdiff_t default_values_offset() const
|
my_ptrdiff_t default_values_offset() const
|
||||||
{ return (my_ptrdiff_t) (s->default_values - record[0]); }
|
{ return (my_ptrdiff_t) (s->default_values - record[0]); }
|
||||||
|
@ -130,62 +130,7 @@ struct mtr_memo_slot_t {
|
|||||||
|
|
||||||
/** Mini-transaction handle and buffer */
|
/** Mini-transaction handle and buffer */
|
||||||
struct mtr_t {
|
struct mtr_t {
|
||||||
|
mtr_t() : m_state(MTR_STATE_INIT) {}
|
||||||
/** 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() { }
|
|
||||||
|
|
||||||
/** Start a mini-transaction. */
|
/** Start a mini-transaction. */
|
||||||
void start();
|
void start();
|
||||||
@ -207,14 +152,7 @@ struct mtr_t {
|
|||||||
|
|
||||||
/** Return current size of the buffer.
|
/** Return current size of the buffer.
|
||||||
@return savepoint */
|
@return savepoint */
|
||||||
ulint get_savepoint() const
|
ulint get_savepoint() const {ut_ad(is_active()); return m_memo.size();}
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Release the (index tree) s-latch stored in an mtr memo after a
|
/** Release the (index tree) s-latch stored in an mtr memo after a
|
||||||
savepoint.
|
savepoint.
|
||||||
@ -251,11 +189,11 @@ struct mtr_t {
|
|||||||
the same set of tablespaces as this one */
|
the same set of tablespaces as this one */
|
||||||
void set_spaces(const mtr_t& mtr)
|
void set_spaces(const mtr_t& mtr)
|
||||||
{
|
{
|
||||||
ut_ad(!m_impl.m_user_space_id);
|
ut_ad(!m_user_space_id);
|
||||||
ut_ad(!m_impl.m_user_space);
|
ut_ad(!m_user_space);
|
||||||
|
|
||||||
ut_d(m_impl.m_user_space_id = mtr.m_impl.m_user_space_id);
|
ut_d(m_user_space_id = mtr.m_user_space_id);
|
||||||
m_impl.m_user_space = mtr.m_impl.m_user_space;
|
m_user_space = mtr.m_user_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the tablespace associated with the mini-transaction
|
/** Set the tablespace associated with the mini-transaction
|
||||||
@ -264,16 +202,16 @@ struct mtr_t {
|
|||||||
@return the tablespace */
|
@return the tablespace */
|
||||||
fil_space_t* set_named_space_id(ulint space_id)
|
fil_space_t* set_named_space_id(ulint space_id)
|
||||||
{
|
{
|
||||||
ut_ad(!m_impl.m_user_space_id);
|
ut_ad(!m_user_space_id);
|
||||||
ut_d(m_impl.m_user_space_id = space_id);
|
ut_d(m_user_space_id = space_id);
|
||||||
if (!space_id) {
|
if (!space_id) {
|
||||||
return fil_system.sys_space;
|
return fil_system.sys_space;
|
||||||
} else {
|
} else {
|
||||||
ut_ad(m_impl.m_user_space_id == space_id);
|
ut_ad(m_user_space_id == space_id);
|
||||||
ut_ad(!m_impl.m_user_space);
|
ut_ad(!m_user_space);
|
||||||
m_impl.m_user_space = fil_space_get(space_id);
|
m_user_space = fil_space_get(space_id);
|
||||||
ut_ad(m_impl.m_user_space);
|
ut_ad(m_user_space);
|
||||||
return m_impl.m_user_space;
|
return m_user_space;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,10 +220,10 @@ struct mtr_t {
|
|||||||
@param[in] space user or system tablespace */
|
@param[in] space user or system tablespace */
|
||||||
void set_named_space(fil_space_t* space)
|
void set_named_space(fil_space_t* space)
|
||||||
{
|
{
|
||||||
ut_ad(!m_impl.m_user_space_id);
|
ut_ad(!m_user_space_id);
|
||||||
ut_d(m_impl.m_user_space_id = space->id);
|
ut_d(m_user_space_id = space->id);
|
||||||
if (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);
|
void release_page(const void* ptr, mtr_memo_type_t type);
|
||||||
|
|
||||||
/** Note that the mini-transaction has modified data. */
|
/** Note that the mini-transaction has modified data. */
|
||||||
void set_modified()
|
void set_modified() { m_modifications = true; }
|
||||||
{
|
|
||||||
m_impl.m_modifications = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the state to not-modified. This will not log the
|
/** Set the state to not-modified. This will not log the
|
||||||
changes. This is only used during redo log apply, to avoid
|
changes. This is only used during redo log apply, to avoid
|
||||||
logging the changes. */
|
logging the changes. */
|
||||||
void discard_modifications()
|
void discard_modifications() { m_modifications = false; }
|
||||||
{
|
|
||||||
m_impl.m_modifications = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the LSN of commit().
|
/** Get the LSN of commit().
|
||||||
@return the commit LSN
|
@return the commit LSN
|
||||||
@ -368,45 +300,28 @@ struct mtr_t {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Note that we are inside the change buffer code. */
|
/** Note that we are inside the change buffer code. */
|
||||||
void enter_ibuf()
|
void enter_ibuf() { m_inside_ibuf = true; }
|
||||||
{
|
|
||||||
m_impl.m_inside_ibuf = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Note that we have exited from the change buffer code. */
|
/** Note that we have exited from the change buffer code. */
|
||||||
void exit_ibuf()
|
void exit_ibuf() { m_inside_ibuf = false; }
|
||||||
{
|
|
||||||
m_impl.m_inside_ibuf = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return true if we are inside the change buffer code */
|
/** @return true if we are inside the change buffer code */
|
||||||
bool is_inside_ibuf() const
|
bool is_inside_ibuf() const { return m_inside_ibuf; }
|
||||||
{
|
|
||||||
return(m_impl.m_inside_ibuf);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@return true if the mini-transaction is active */
|
@return true if the mini-transaction is active */
|
||||||
bool is_active() const
|
bool is_active() const { return m_state == MTR_STATE_ACTIVE; }
|
||||||
{
|
|
||||||
return(m_impl.m_state == MTR_STATE_ACTIVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get flush observer
|
/** Get flush observer
|
||||||
@return flush observer */
|
@return flush observer */
|
||||||
FlushObserver* get_flush_observer() const
|
FlushObserver* get_flush_observer() const { return m_flush_observer; }
|
||||||
{
|
|
||||||
return(m_impl.m_flush_observer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set flush observer
|
/** Set flush observer
|
||||||
@param[in] observer flush observer */
|
@param[in] observer flush observer */
|
||||||
void set_flush_observer(FlushObserver* observer)
|
void set_flush_observer(FlushObserver* observer)
|
||||||
{
|
{
|
||||||
ut_ad(observer == NULL
|
ut_ad(observer == NULL || m_log_mode == MTR_LOG_NO_REDO);
|
||||||
|| m_impl.m_log_mode == MTR_LOG_NO_REDO);
|
m_flush_observer = observer;
|
||||||
|
|
||||||
m_impl.m_flush_observer = observer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
@ -446,65 +361,31 @@ struct mtr_t {
|
|||||||
void print() const;
|
void print() const;
|
||||||
|
|
||||||
/** @return true if the mini-transaction has committed */
|
/** @return true if the mini-transaction has committed */
|
||||||
bool has_committed() const
|
bool has_committed() const { return m_state == MTR_STATE_COMMITTED; }
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return true if mini-transaction contains modifications. */
|
/** @return true if mini-transaction contains modifications. */
|
||||||
bool has_modifications() const
|
bool has_modifications() const { return m_modifications; }
|
||||||
{
|
|
||||||
return(m_impl.m_modifications);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return the memo stack */
|
/** @return the memo stack */
|
||||||
const mtr_buf_t* get_memo() const
|
const mtr_buf_t* get_memo() const { return &m_memo; }
|
||||||
{
|
|
||||||
return(&m_impl.m_memo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @return the memo stack */
|
/** @return the memo stack */
|
||||||
mtr_buf_t* get_memo()
|
mtr_buf_t* get_memo() { return &m_memo; }
|
||||||
{
|
|
||||||
return(&m_impl.m_memo);
|
|
||||||
}
|
|
||||||
#endif /* UNIV_DEBUG */
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
||||||
/** @return true if a record was added to the mini-transaction */
|
/** @return true if a record was added to the mini-transaction */
|
||||||
bool is_dirty() const
|
bool is_dirty() const { return m_made_dirty; }
|
||||||
{
|
|
||||||
return(m_impl.m_made_dirty);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Note that a record has been added to the log */
|
/** Note that a record has been added to the log */
|
||||||
void added_rec()
|
void added_rec() { ++m_n_log_recs; }
|
||||||
{
|
|
||||||
++m_impl.m_n_log_recs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the buffered redo log of this mini-transaction.
|
/** Get the buffered redo log of this mini-transaction.
|
||||||
@return redo log */
|
@return redo log */
|
||||||
const mtr_buf_t* get_log() const
|
const mtr_buf_t* get_log() const { return &m_log; }
|
||||||
{
|
|
||||||
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
|
||||||
|
|
||||||
return(&m_impl.m_log);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the buffered redo log of this mini-transaction.
|
/** Get the buffered redo log of this mini-transaction.
|
||||||
@return redo log */
|
@return redo log */
|
||||||
mtr_buf_t* get_log()
|
mtr_buf_t* get_log() { return &m_log; }
|
||||||
{
|
|
||||||
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
|
||||||
|
|
||||||
return(&m_impl.m_log);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Push an object to an mtr memo stack.
|
/** Push an object to an mtr memo stack.
|
||||||
@param object object
|
@param object object
|
||||||
@ -518,15 +399,56 @@ struct mtr_t {
|
|||||||
MY_ATTRIBUTE((warn_unused_result));
|
MY_ATTRIBUTE((warn_unused_result));
|
||||||
|
|
||||||
private:
|
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:
|
/** Release the resources */
|
||||||
Impl m_impl;
|
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 */
|
/** LSN at commit time */
|
||||||
volatile lsn_t m_commit_lsn;
|
lsn_t m_commit_lsn;
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "mtr0mtr.ic"
|
#include "mtr0mtr.ic"
|
||||||
|
@ -49,7 +49,6 @@ mtr_t::memo_push(void* object, mtr_memo_type_t type)
|
|||||||
ut_ad(object != NULL);
|
ut_ad(object != NULL);
|
||||||
ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
|
ut_ad(type >= MTR_MEMO_PAGE_S_FIX);
|
||||||
ut_ad(type <= MTR_MEMO_SX_LOCK);
|
ut_ad(type <= MTR_MEMO_SX_LOCK);
|
||||||
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
|
||||||
ut_ad(ut_is_2pow(type));
|
ut_ad(ut_is_2pow(type));
|
||||||
|
|
||||||
/* If this mtr has x-fixed a clean page then we set
|
/* 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. */
|
can insert the dirtied page to the flush list. */
|
||||||
|
|
||||||
if ((type == MTR_MEMO_PAGE_X_FIX || type == MTR_MEMO_PAGE_SX_FIX)
|
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));
|
reinterpret_cast<const buf_block_t*>(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
mtr_memo_slot_t* slot;
|
mtr_memo_slot_t* slot = m_memo.push<mtr_memo_slot_t*>(sizeof(*slot));
|
||||||
|
|
||||||
slot = m_impl.m_memo.push<mtr_memo_slot_t*>(sizeof(*slot));
|
|
||||||
|
|
||||||
slot->type = type;
|
slot->type = type;
|
||||||
slot->object = object;
|
slot->object = object;
|
||||||
@ -81,11 +78,9 @@ mtr_t::release_s_latch_at_savepoint(
|
|||||||
rw_lock_t* lock)
|
rw_lock_t* lock)
|
||||||
{
|
{
|
||||||
ut_ad(is_active());
|
ut_ad(is_active());
|
||||||
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
ut_ad(m_memo.size() > savepoint);
|
||||||
|
|
||||||
ut_ad(m_impl.m_memo.size() > savepoint);
|
mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
|
||||||
|
|
||||||
mtr_memo_slot_t* slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint);
|
|
||||||
|
|
||||||
ut_ad(slot->object == lock);
|
ut_ad(slot->object == lock);
|
||||||
ut_ad(slot->type == MTR_MEMO_S_LOCK);
|
ut_ad(slot->type == MTR_MEMO_S_LOCK);
|
||||||
@ -104,8 +99,7 @@ mtr_t::sx_latch_at_savepoint(
|
|||||||
buf_block_t* block)
|
buf_block_t* block)
|
||||||
{
|
{
|
||||||
ut_ad(is_active());
|
ut_ad(is_active());
|
||||||
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
ut_ad(m_memo.size() > savepoint);
|
||||||
ut_ad(m_impl.m_memo.size() > savepoint);
|
|
||||||
|
|
||||||
ut_ad(!memo_contains_flagged(
|
ut_ad(!memo_contains_flagged(
|
||||||
block,
|
block,
|
||||||
@ -113,9 +107,7 @@ mtr_t::sx_latch_at_savepoint(
|
|||||||
| MTR_MEMO_PAGE_X_FIX
|
| MTR_MEMO_PAGE_X_FIX
|
||||||
| MTR_MEMO_PAGE_SX_FIX));
|
| MTR_MEMO_PAGE_SX_FIX));
|
||||||
|
|
||||||
mtr_memo_slot_t* slot;
|
mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
|
||||||
|
|
||||||
slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint);
|
|
||||||
|
|
||||||
ut_ad(slot->object == block);
|
ut_ad(slot->object == block);
|
||||||
|
|
||||||
@ -124,8 +116,8 @@ mtr_t::sx_latch_at_savepoint(
|
|||||||
|
|
||||||
rw_lock_sx_lock(&block->lock);
|
rw_lock_sx_lock(&block->lock);
|
||||||
|
|
||||||
if (!m_impl.m_made_dirty) {
|
if (!m_made_dirty) {
|
||||||
m_impl.m_made_dirty = is_block_dirtied(block);
|
m_made_dirty = is_block_dirtied(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
slot->type = MTR_MEMO_PAGE_SX_FIX;
|
slot->type = MTR_MEMO_PAGE_SX_FIX;
|
||||||
@ -140,8 +132,7 @@ mtr_t::x_latch_at_savepoint(
|
|||||||
buf_block_t* block)
|
buf_block_t* block)
|
||||||
{
|
{
|
||||||
ut_ad(is_active());
|
ut_ad(is_active());
|
||||||
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
ut_ad(m_memo.size() > savepoint);
|
||||||
ut_ad(m_impl.m_memo.size() > savepoint);
|
|
||||||
|
|
||||||
ut_ad(!memo_contains_flagged(
|
ut_ad(!memo_contains_flagged(
|
||||||
block,
|
block,
|
||||||
@ -149,9 +140,7 @@ mtr_t::x_latch_at_savepoint(
|
|||||||
| MTR_MEMO_PAGE_X_FIX
|
| MTR_MEMO_PAGE_X_FIX
|
||||||
| MTR_MEMO_PAGE_SX_FIX));
|
| MTR_MEMO_PAGE_SX_FIX));
|
||||||
|
|
||||||
mtr_memo_slot_t* slot;
|
mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
|
||||||
|
|
||||||
slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint);
|
|
||||||
|
|
||||||
ut_ad(slot->object == block);
|
ut_ad(slot->object == block);
|
||||||
|
|
||||||
@ -160,8 +149,8 @@ mtr_t::x_latch_at_savepoint(
|
|||||||
|
|
||||||
rw_lock_x_lock(&block->lock);
|
rw_lock_x_lock(&block->lock);
|
||||||
|
|
||||||
if (!m_impl.m_made_dirty) {
|
if (!m_made_dirty) {
|
||||||
m_impl.m_made_dirty = is_block_dirtied(block);
|
m_made_dirty = is_block_dirtied(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
slot->type = MTR_MEMO_PAGE_X_FIX;
|
slot->type = MTR_MEMO_PAGE_X_FIX;
|
||||||
@ -176,11 +165,8 @@ mtr_t::release_block_at_savepoint(
|
|||||||
buf_block_t* block)
|
buf_block_t* block)
|
||||||
{
|
{
|
||||||
ut_ad(is_active());
|
ut_ad(is_active());
|
||||||
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
|
||||||
|
|
||||||
mtr_memo_slot_t* slot;
|
mtr_memo_slot_t* slot = m_memo.at<mtr_memo_slot_t*>(savepoint);
|
||||||
|
|
||||||
slot = m_impl.m_memo.at<mtr_memo_slot_t*>(savepoint);
|
|
||||||
|
|
||||||
ut_a(slot->object == block);
|
ut_a(slot->object == block);
|
||||||
|
|
||||||
@ -198,10 +184,10 @@ Gets the logging mode of a mini-transaction.
|
|||||||
mtr_log_t
|
mtr_log_t
|
||||||
mtr_t::get_log_mode() const
|
mtr_t::get_log_mode() const
|
||||||
{
|
{
|
||||||
ut_ad(m_impl.m_log_mode >= MTR_LOG_ALL);
|
ut_ad(m_log_mode >= MTR_LOG_ALL);
|
||||||
ut_ad(m_impl.m_log_mode <= MTR_LOG_SHORT_INSERTS);
|
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_ALL);
|
||||||
ut_ad(mode <= MTR_LOG_SHORT_INSERTS);
|
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) {
|
switch (old_mode) {
|
||||||
case MTR_LOG_NO_REDO:
|
case MTR_LOG_NO_REDO:
|
||||||
@ -233,9 +219,8 @@ mtr_t::set_log_mode(mtr_log_t mode)
|
|||||||
case MTR_LOG_ALL:
|
case MTR_LOG_ALL:
|
||||||
/* MTR_LOG_NO_REDO can only be set before generating
|
/* MTR_LOG_NO_REDO can only be set before generating
|
||||||
any redo log records. */
|
any redo log records. */
|
||||||
ut_ad(mode != MTR_LOG_NO_REDO
|
ut_ad(mode != MTR_LOG_NO_REDO || m_n_log_recs == 0);
|
||||||
|| m_impl.m_n_log_recs == 0);
|
m_log_mode = mode;
|
||||||
m_impl.m_log_mode = mode;
|
|
||||||
return(old_mode);
|
return(old_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,18 +36,18 @@ struct mtr_t;
|
|||||||
/** Logging modes for a mini-transaction */
|
/** Logging modes for a mini-transaction */
|
||||||
enum mtr_log_t {
|
enum mtr_log_t {
|
||||||
/** Default mode: log all operations modifying disk-based data */
|
/** 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.
|
/** 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
|
Set when applying log in crash recovery or when a modification of a
|
||||||
ROW_FORMAT=COMPRESSED page is attempted. */
|
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 */
|
/** 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 */
|
/** Inserts are logged in a shorter form */
|
||||||
MTR_LOG_SHORT_INSERTS = 24
|
MTR_LOG_SHORT_INSERTS
|
||||||
};
|
};
|
||||||
|
|
||||||
/** @name Log item types
|
/** @name Log item types
|
||||||
@ -278,15 +278,10 @@ enum mtr_memo_type_t {
|
|||||||
};
|
};
|
||||||
#endif /* !UNIV_CHECKSUM */
|
#endif /* !UNIV_CHECKSUM */
|
||||||
|
|
||||||
#ifdef UNIV_DEBUG
|
|
||||||
# define MTR_MAGIC_N 54551
|
|
||||||
#endif /* UNIV_DEBUG */
|
|
||||||
|
|
||||||
enum mtr_state_t {
|
enum mtr_state_t {
|
||||||
MTR_STATE_INIT = 0,
|
MTR_STATE_INIT = 0,
|
||||||
MTR_STATE_ACTIVE = 12231,
|
MTR_STATE_ACTIVE,
|
||||||
MTR_STATE_COMMITTING = 56456,
|
MTR_STATE_COMMITTED
|
||||||
MTR_STATE_COMMITTED = 34676
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* mtr0types_h */
|
#endif /* mtr0types_h */
|
||||||
|
@ -27,7 +27,6 @@ Created 9/20/1997 Heikki Tuuri
|
|||||||
|
|
||||||
#include "univ.i"
|
#include "univ.i"
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <my_service_manager.h>
|
#include <my_service_manager.h>
|
||||||
@ -3733,32 +3732,25 @@ recv_recovery_from_checkpoint_finish(void)
|
|||||||
@param[in] page_no page number
|
@param[in] page_no page number
|
||||||
@return page frame
|
@return page frame
|
||||||
@retval NULL if no page was found */
|
@retval NULL if no page was found */
|
||||||
|
|
||||||
const byte*
|
const byte*
|
||||||
recv_dblwr_t::find_page(ulint space_id, ulint page_no)
|
recv_dblwr_t::find_page(ulint space_id, ulint page_no)
|
||||||
{
|
{
|
||||||
std::vector<const byte*, ut_allocator<const byte*> > matches;
|
const byte *result= NULL;
|
||||||
const byte* result = 0;
|
lsn_t max_lsn= 0;
|
||||||
|
|
||||||
for (const byte* page : pages) {
|
for (const byte *page : pages)
|
||||||
if (page_get_space_id(page) == space_id
|
{
|
||||||
&& page_get_page_no(page) == page_no) {
|
if (page_get_page_no(page) != page_no ||
|
||||||
matches.push_back(page);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
lsn_t max_lsn = 0;
|
return result;
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
|
@ -343,6 +343,7 @@ struct ReleaseAll {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef UNIV_DEBUG
|
||||||
/** Check that all slots have been handled. */
|
/** Check that all slots have been handled. */
|
||||||
struct DebugCheck {
|
struct DebugCheck {
|
||||||
/** @return true always. */
|
/** @return true always. */
|
||||||
@ -352,6 +353,7 @@ struct DebugCheck {
|
|||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/** Release a resource acquired by the mini-transaction. */
|
/** Release a resource acquired by the mini-transaction. */
|
||||||
struct ReleaseBlocks {
|
struct ReleaseBlocks {
|
||||||
@ -404,59 +406,6 @@ struct ReleaseBlocks {
|
|||||||
FlushObserver* m_flush_observer;
|
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 */
|
/** Write the block contents to the REDO log */
|
||||||
struct mtr_write_log_t {
|
struct mtr_write_log_t {
|
||||||
/** Append a block to the redo log buffer.
|
/** Append a block to the redo log buffer.
|
||||||
@ -490,76 +439,75 @@ mtr_write_log(
|
|||||||
/** Start a mini-transaction. */
|
/** Start a mini-transaction. */
|
||||||
void mtr_t::start()
|
void mtr_t::start()
|
||||||
{
|
{
|
||||||
UNIV_MEM_INVALID(this, sizeof(*this));
|
UNIV_MEM_INVALID(this, sizeof *this);
|
||||||
|
|
||||||
UNIV_MEM_INVALID(&m_impl, sizeof(m_impl));
|
new(&m_memo) mtr_buf_t();
|
||||||
|
new(&m_log) mtr_buf_t();
|
||||||
|
|
||||||
m_commit_lsn = 0;
|
m_made_dirty= false;
|
||||||
|
m_inside_ibuf= false;
|
||||||
new(&m_impl.m_log) mtr_buf_t();
|
m_modifications= false;
|
||||||
new(&m_impl.m_memo) mtr_buf_t();
|
m_n_log_recs= 0;
|
||||||
|
m_log_mode= MTR_LOG_ALL;
|
||||||
m_impl.m_mtr = this;
|
ut_d(m_user_space_id= TRX_SYS_SPACE);
|
||||||
m_impl.m_log_mode = MTR_LOG_ALL;
|
m_user_space= NULL;
|
||||||
m_impl.m_inside_ibuf = false;
|
m_state= MTR_STATE_ACTIVE;
|
||||||
m_impl.m_modifications = false;
|
m_flush_observer= NULL;
|
||||||
m_impl.m_made_dirty = false;
|
m_commit_lsn= 0;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Release the resources */
|
/** Release the resources */
|
||||||
void
|
inline void mtr_t::release_resources()
|
||||||
mtr_t::Command::release_resources()
|
|
||||||
{
|
{
|
||||||
ut_ad(m_impl->m_magic_n == MTR_MAGIC_N);
|
ut_d(m_memo.for_each_block_in_reverse(CIterate<DebugCheck>()));
|
||||||
|
m_log.erase();
|
||||||
/* Currently only used in commit */
|
m_memo.erase();
|
||||||
ut_ad(m_impl->m_state == MTR_STATE_COMMITTING);
|
m_state= MTR_STATE_COMMITTED;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Commit a mini-transaction. */
|
/** Commit a mini-transaction. */
|
||||||
void
|
void
|
||||||
mtr_t::commit()
|
mtr_t::commit()
|
||||||
{
|
{
|
||||||
ut_ad(is_active());
|
ut_ad(is_active());
|
||||||
ut_ad(!is_inside_ibuf());
|
ut_ad(!is_inside_ibuf());
|
||||||
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
|
||||||
m_impl.m_state = MTR_STATE_COMMITTING;
|
|
||||||
|
|
||||||
/* This is a dirty read, for debugging. */
|
/* This is a dirty read, for debugging. */
|
||||||
ut_ad(!m_impl.m_modifications || !recv_no_log_write);
|
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
|
lsn_t start_lsn;
|
||||||
&& (m_impl.m_n_log_recs > 0
|
|
||||||
|| m_impl.m_log_mode == MTR_LOG_NO_REDO)) {
|
|
||||||
|
|
||||||
ut_ad(!srv_read_only_mode
|
if (const ulint len= prepare_write())
|
||||||
|| m_impl.m_log_mode == MTR_LOG_NO_REDO);
|
start_lsn= finish_write(len);
|
||||||
|
else
|
||||||
|
start_lsn= m_commit_lsn;
|
||||||
|
|
||||||
cmd.execute();
|
if (m_made_dirty)
|
||||||
} else {
|
log_flush_order_mutex_enter();
|
||||||
cmd.release_all();
|
|
||||||
cmd.release_resources();
|
/* 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,
|
/** 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(log_mutex_own());
|
||||||
ut_ad(is_active());
|
ut_ad(is_active());
|
||||||
ut_ad(!is_inside_ibuf());
|
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(get_log_mode() == MTR_LOG_ALL);
|
||||||
ut_ad(!m_impl.m_made_dirty);
|
ut_ad(!m_made_dirty);
|
||||||
ut_ad(m_impl.m_memo.size() == 0);
|
ut_ad(m_memo.size() == 0);
|
||||||
ut_ad(!srv_read_only_mode);
|
ut_ad(!srv_read_only_mode);
|
||||||
ut_d(m_impl.m_state = MTR_STATE_COMMITTING);
|
ut_ad(write_mlog_checkpoint || m_n_log_recs > 1);
|
||||||
ut_ad(write_mlog_checkpoint || m_impl.m_n_log_recs > 1);
|
|
||||||
|
|
||||||
switch (m_impl.m_n_log_recs) {
|
switch (m_n_log_recs) {
|
||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
case 1:
|
case 1:
|
||||||
*m_impl.m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG;
|
*m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
mlog_catenate_ulint(
|
mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END, MLOG_1BYTE);
|
||||||
&m_impl.m_log, MLOG_MULTI_REC_END, MLOG_1BYTE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write_mlog_checkpoint) {
|
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);
|
compile_time_assert(SIZE_OF_MLOG_CHECKPOINT == 1 + 8);
|
||||||
*ptr = MLOG_CHECKPOINT;
|
*ptr = MLOG_CHECKPOINT;
|
||||||
mach_write_to_8(ptr + 1, checkpoint_lsn);
|
mach_write_to_8(ptr + 1, checkpoint_lsn);
|
||||||
}
|
}
|
||||||
|
|
||||||
Command cmd(this);
|
finish_write(m_log.size());
|
||||||
cmd.finish_write(m_impl.m_log.size());
|
release_resources();
|
||||||
cmd.release_resources();
|
|
||||||
|
|
||||||
if (write_mlog_checkpoint) {
|
if (write_mlog_checkpoint) {
|
||||||
DBUG_PRINT("ib_log",
|
DBUG_PRINT("ib_log",
|
||||||
@ -623,8 +567,7 @@ mtr_t::commit_checkpoint(
|
|||||||
bool
|
bool
|
||||||
mtr_t::is_named_space(ulint space) const
|
mtr_t::is_named_space(ulint space) const
|
||||||
{
|
{
|
||||||
ut_ad(!m_impl.m_user_space
|
ut_ad(!m_user_space || m_user_space->id != TRX_SYS_SPACE);
|
||||||
|| m_impl.m_user_space->id != TRX_SYS_SPACE);
|
|
||||||
|
|
||||||
switch (get_log_mode()) {
|
switch (get_log_mode()) {
|
||||||
case MTR_LOG_NONE:
|
case MTR_LOG_NONE:
|
||||||
@ -632,7 +575,7 @@ mtr_t::is_named_space(ulint space) const
|
|||||||
return(true);
|
return(true);
|
||||||
case MTR_LOG_ALL:
|
case MTR_LOG_ALL:
|
||||||
case MTR_LOG_SHORT_INSERTS:
|
case MTR_LOG_SHORT_INSERTS:
|
||||||
return(m_impl.m_user_space_id == space
|
return(m_user_space_id == space
|
||||||
|| is_predefined_tablespace(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 */
|
@return whether the mini-transaction is associated with the space */
|
||||||
bool mtr_t::is_named_space(const fil_space_t* space) const
|
bool mtr_t::is_named_space(const fil_space_t* space) const
|
||||||
{
|
{
|
||||||
ut_ad(!m_impl.m_user_space
|
ut_ad(!m_user_space || m_user_space->id != TRX_SYS_SPACE);
|
||||||
|| m_impl.m_user_space->id != TRX_SYS_SPACE);
|
|
||||||
|
|
||||||
switch (get_log_mode()) {
|
switch (get_log_mode()) {
|
||||||
case MTR_LOG_NONE:
|
case MTR_LOG_NONE:
|
||||||
case MTR_LOG_NO_REDO:
|
case MTR_LOG_NO_REDO:
|
||||||
return true;
|
return true;
|
||||||
case MTR_LOG_ALL:
|
case MTR_LOG_ALL:
|
||||||
case MTR_LOG_SHORT_INSERTS:
|
case MTR_LOG_SHORT_INSERTS:
|
||||||
return(m_impl.m_user_space == space
|
return m_user_space == space || is_predefined_tablespace(space->id);
|
||||||
|| is_predefined_tablespace(space->id));
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ut_error;
|
ut_error;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif /* UNIV_DEBUG */
|
#endif /* UNIV_DEBUG */
|
||||||
|
|
||||||
@ -674,12 +615,11 @@ mtr_t::x_lock_space(ulint space_id, const char* file, unsigned line)
|
|||||||
{
|
{
|
||||||
fil_space_t* space;
|
fil_space_t* space;
|
||||||
|
|
||||||
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
|
||||||
ut_ad(is_active());
|
ut_ad(is_active());
|
||||||
|
|
||||||
if (space_id == TRX_SYS_SPACE) {
|
if (space_id == TRX_SYS_SPACE) {
|
||||||
space = fil_system.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 {
|
} else {
|
||||||
space = fil_space_get(space_id);
|
space = fil_space_get(space_id);
|
||||||
ut_ad(get_log_mode() != MTR_LOG_NO_REDO
|
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
|
bool
|
||||||
mtr_t::memo_release(const void* object, ulint type)
|
mtr_t::memo_release(const void* object, ulint type)
|
||||||
{
|
{
|
||||||
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
|
||||||
ut_ad(is_active());
|
ut_ad(is_active());
|
||||||
|
|
||||||
/* We cannot release a page that has been written to in the
|
/* We cannot release a page that has been written to in the
|
||||||
middle of a mini-transaction. */
|
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));
|
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);
|
memo_slot_release(iteration.functor.m_slot);
|
||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
@ -725,16 +664,15 @@ mtr_t::memo_release(const void* object, ulint type)
|
|||||||
void
|
void
|
||||||
mtr_t::release_page(const void* ptr, mtr_memo_type_t type)
|
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());
|
ut_ad(is_active());
|
||||||
|
|
||||||
/* We cannot release a page that has been written to in the
|
/* We cannot release a page that has been written to in the
|
||||||
middle of a mini-transaction. */
|
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));
|
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());
|
memo_slot_release(iteration.functor.get_slot());
|
||||||
return;
|
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.
|
/** Prepare to write the mini-transaction log to the redo log buffer.
|
||||||
@return number of bytes to write in finish_write() */
|
@return number of bytes to write in finish_write() */
|
||||||
ulint
|
inline ulint mtr_t::prepare_write()
|
||||||
mtr_t::Command::prepare_write()
|
|
||||||
{
|
{
|
||||||
ut_ad(!recv_no_log_write);
|
ut_ad(!recv_no_log_write);
|
||||||
|
|
||||||
switch (m_impl->m_log_mode) {
|
if (UNIV_UNLIKELY(m_log_mode != MTR_LOG_ALL)) {
|
||||||
case MTR_LOG_SHORT_INSERTS:
|
ut_ad(m_log_mode == MTR_LOG_NO_REDO);
|
||||||
ut_ad(0);
|
ut_ad(m_log.size() == 0);
|
||||||
/* fall through */
|
|
||||||
case MTR_LOG_NO_REDO:
|
|
||||||
case MTR_LOG_NONE:
|
|
||||||
ut_ad(m_impl->m_log.size() == 0);
|
|
||||||
log_mutex_enter();
|
log_mutex_enter();
|
||||||
m_end_lsn = m_start_lsn = log_sys.lsn;
|
m_commit_lsn = log_sys.lsn;
|
||||||
return(0);
|
return 0;
|
||||||
case MTR_LOG_ALL:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ulint len = m_impl->m_log.size();
|
ulint len = m_log.size();
|
||||||
ulint n_recs = m_impl->m_n_log_recs;
|
ulint n_recs = m_n_log_recs;
|
||||||
ut_ad(len > 0);
|
ut_ad(len > 0);
|
||||||
ut_ad(n_recs > 0);
|
ut_ad(n_recs > 0);
|
||||||
|
|
||||||
@ -773,9 +704,9 @@ mtr_t::Command::prepare_write()
|
|||||||
log_buffer_extend(ulong((len + 1) * 2));
|
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)) {
|
if (space != NULL && is_predefined_tablespace(space->id)) {
|
||||||
/* Omit MLOG_FILE_NAME for predefined tablespaces. */
|
/* Omit MLOG_FILE_NAME for predefined tablespaces. */
|
||||||
@ -784,35 +715,32 @@ mtr_t::Command::prepare_write()
|
|||||||
|
|
||||||
log_mutex_enter();
|
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 mini-transaction was the first one to modify
|
||||||
this tablespace since the latest checkpoint, so
|
this tablespace since the latest checkpoint, so
|
||||||
some MLOG_FILE_NAME records were appended to m_log. */
|
some MLOG_FILE_NAME records were appended to m_log. */
|
||||||
ut_ad(m_impl->m_n_log_recs > n_recs);
|
ut_ad(m_n_log_recs > n_recs);
|
||||||
mlog_catenate_ulint(
|
mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END, MLOG_1BYTE);
|
||||||
&m_impl->m_log, MLOG_MULTI_REC_END, MLOG_1BYTE);
|
len = m_log.size();
|
||||||
len = m_impl->m_log.size();
|
|
||||||
} else {
|
} else {
|
||||||
/* This was not the first time of dirtying a
|
/* This was not the first time of dirtying a
|
||||||
tablespace since the latest checkpoint. */
|
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) {
|
if (n_recs <= 1) {
|
||||||
ut_ad(n_recs == 1);
|
ut_ad(n_recs == 1);
|
||||||
|
|
||||||
/* Flag the single log record as the
|
/* Flag the single log record as the
|
||||||
only record in this mini-transaction. */
|
only record in this mini-transaction. */
|
||||||
*m_impl->m_log.front()->begin()
|
*m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG;
|
||||||
|= MLOG_SINGLE_REC_FLAG;
|
|
||||||
} else {
|
} else {
|
||||||
/* Because this mini-transaction comprises
|
/* Because this mini-transaction comprises
|
||||||
multiple log records, append MLOG_MULTI_REC_END
|
multiple log records, append MLOG_MULTI_REC_END
|
||||||
at the end. */
|
at the end. */
|
||||||
|
|
||||||
mlog_catenate_ulint(
|
mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END,
|
||||||
&m_impl->m_log, MLOG_MULTI_REC_END,
|
MLOG_1BYTE);
|
||||||
MLOG_1BYTE);
|
|
||||||
len++;
|
len++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -824,98 +752,37 @@ mtr_t::Command::prepare_write()
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Append the redo log records to the redo log buffer
|
/** Append the redo log records to the redo log buffer
|
||||||
@param[in] len number of bytes to write */
|
@param[in] len number of bytes to write
|
||||||
void
|
@return start_lsn */
|
||||||
mtr_t::Command::finish_write(
|
inline lsn_t mtr_t::finish_write(ulint len)
|
||||||
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(log_mutex_own());
|
||||||
ut_ad(m_impl->m_log.size() == len);
|
ut_ad(m_log.size() == len);
|
||||||
ut_ad(len > 0);
|
ut_ad(len > 0);
|
||||||
|
|
||||||
if (m_impl->m_log.is_small()) {
|
lsn_t start_lsn;
|
||||||
const mtr_buf_t::block_t* front = m_impl->m_log.front();
|
|
||||||
|
if (m_log.is_small()) {
|
||||||
|
const mtr_buf_t::block_t* front = m_log.front();
|
||||||
ut_ad(len <= front->used());
|
ut_ad(len <= front->used());
|
||||||
|
|
||||||
m_end_lsn = log_reserve_and_write_fast(
|
m_commit_lsn = log_reserve_and_write_fast(front->begin(), len,
|
||||||
front->begin(), len, &m_start_lsn);
|
&start_lsn);
|
||||||
|
|
||||||
if (m_end_lsn > 0) {
|
if (m_commit_lsn) {
|
||||||
return;
|
return start_lsn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open the database log for log_write_low */
|
/* 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;
|
mtr_write_log_t write_log;
|
||||||
m_impl->m_log.for_each_block(write_log);
|
m_log.for_each_block(write_log);
|
||||||
|
|
||||||
m_end_lsn = log_close();
|
m_commit_lsn = log_close();
|
||||||
}
|
return start_lsn;
|
||||||
|
|
||||||
/** 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>());
|
|
||||||
|
|
||||||
/* 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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef UNIV_DEBUG
|
#ifdef UNIV_DEBUG
|
||||||
@ -1014,10 +881,9 @@ struct FlaggedCheck {
|
|||||||
bool
|
bool
|
||||||
mtr_t::memo_contains_flagged(const void* ptr, ulint flags) const
|
mtr_t::memo_contains_flagged(const void* ptr, ulint flags) const
|
||||||
{
|
{
|
||||||
ut_ad(m_impl.m_magic_n == MTR_MAGIC_N);
|
ut_ad(is_active());
|
||||||
ut_ad(is_committing() || 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)));
|
CIterate<FlaggedCheck>(FlaggedCheck(ptr, flags)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1033,7 +899,7 @@ mtr_t::memo_contains_page_flagged(
|
|||||||
ulint flags) const
|
ulint flags) const
|
||||||
{
|
{
|
||||||
Iterate<FindPage> iteration(FindPage(ptr, flags));
|
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();
|
? NULL : iteration.functor.get_block();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1056,7 +922,7 @@ void
|
|||||||
mtr_t::print() const
|
mtr_t::print() const
|
||||||
{
|
{
|
||||||
ib::info() << "Mini-transaction handle: memo size "
|
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";
|
<< get_log()->size() << " bytes";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user