diff options
author | Aleksey Midenkov <midenok@gmail.com> | 2019-08-14 19:16:08 +0300 |
---|---|---|
committer | Aleksey Midenkov <midenok@gmail.com> | 2019-08-14 19:16:08 +0300 |
commit | c23a5e0e5eecad9ec8a8f5ffa1f28a86c5b2b261 (patch) | |
tree | e5440e382c1158494fa80ba798a06c52ee9eb948 | |
parent | a20f6f9853e522ad388f5b968ce11af3c5d1fc10 (diff) | |
parent | 2347ffd843b8e4ee9d8eaafab05368435db59ece (diff) | |
download | mariadb-git-c23a5e0e5eecad9ec8a8f5ffa1f28a86c5b2b261.tar.gz |
Merge 10.2 into 10.3
-rw-r--r-- | mysql-test/suite/innodb/r/innodb_bug14704286.result | 65 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/innodb_bug84958.result | 81 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb_bug14704286.test | 95 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb_bug84958.test | 86 | ||||
-rw-r--r-- | mysql-test/valgrind.supp | 117 | ||||
-rw-r--r-- | storage/innobase/row/row0sel.cc | 55 | ||||
-rw-r--r-- | storage/rocksdb/ha_rocksdb.cc | 4 | ||||
-rw-r--r-- | storage/rocksdb/mysql-test/rocksdb/suite.pm | 4 |
8 files changed, 334 insertions, 173 deletions
diff --git a/mysql-test/suite/innodb/r/innodb_bug14704286.result b/mysql-test/suite/innodb/r/innodb_bug14704286.result deleted file mode 100644 index f84d5206e07..00000000000 --- a/mysql-test/suite/innodb/r/innodb_bug14704286.result +++ /dev/null @@ -1,65 +0,0 @@ -use test; -drop table if exists t1; -create table t1 (id int primary key, value int, value2 int, -value3 int, index(value,value2)) engine=innodb; -insert into t1 values -(10,10,10,10),(11,11,11,11),(12,12,12,12),(13,13,13,13),(14,14,14,14), -(15,15,15,15),(16,16,16,16),(17,17,17,17),(18,18,18,18),(19,19,19,19), -(20,20,20,20); -connect conn1, localhost, root,,; -connect conn2, localhost, root,,; -connect conn3, localhost, root,,; -connection conn1; -use test; -start transaction with consistent snapshot; -connection conn2; -use test; -CREATE PROCEDURE update_t1() -BEGIN -DECLARE i INT DEFAULT 1; -while (i <= 5000) DO -update test.t1 set value2=value2+1, value3=value3+1 where id=12; -SET i = i + 1; -END WHILE; -END| -set autocommit=0; -CALL update_t1(); -select * from t1; -id value value2 value3 -10 10 10 10 -11 11 11 11 -12 12 5012 5012 -13 13 13 13 -14 14 14 14 -15 15 15 15 -16 16 16 16 -17 17 17 17 -18 18 18 18 -19 19 19 19 -20 20 20 20 -set autocommit=1; -select * from t1; -id value value2 value3 -10 10 10 10 -11 11 11 11 -12 12 5012 5012 -13 13 13 13 -14 14 14 14 -15 15 15 15 -16 16 16 16 -17 17 17 17 -18 18 18 18 -19 19 19 19 -20 20 20 20 -connection conn1; -select * from t1 force index(value) where value=12; -connection conn3; -kill query @id; -connection conn1; -ERROR 70100: Query execution was interrupted -connection default; -disconnect conn1; -disconnect conn2; -disconnect conn3; -drop procedure if exists update_t1; -drop table if exists t1; diff --git a/mysql-test/suite/innodb/r/innodb_bug84958.result b/mysql-test/suite/innodb/r/innodb_bug84958.result new file mode 100644 index 00000000000..1a59a10eb2f --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug84958.result @@ -0,0 +1,81 @@ +# +# Bug #84958 InnoDB's MVCC has O(N^2) behaviors +# https://bugs.mysql.com/bug.php?id=84958 +# +# Set up the test with a procedure and a function. +# +CREATE PROCEDURE insert_n(start int, end int) +BEGIN +DECLARE i INT DEFAULT start; +WHILE i <= end do +INSERT INTO t1 VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = i; +SET i = i + 1; +END WHILE; +END~~ +CREATE FUNCTION num_pages_get() +RETURNS INT +BEGIN +DECLARE ret INT; +SELECT variable_value INTO ret +FROM information_schema.global_status +WHERE variable_name = 'innodb_buffer_pool_read_requests'; +RETURN ret; +END~~ +# +# Create a table with one record in it and start an RR transaction +# +CREATE TABLE t1 (a INT, b INT, c INT, PRIMARY KEY(a,b), KEY (b,c)) +ENGINE=InnoDB; +BEGIN; +SELECT * FROM t1; +a b c +# +# Create 100 newer record versions in con2 and con3 +# +connect con2, localhost, root,,; +connection con2; +INSERT INTO t1 VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = NULL; +CALL insert_n(1, 50);; +connect con3, localhost, root,,; +connection con3; +CALL insert_n(51, 100);; +connection con2; +connection con3; +INSERT INTO t1 VALUES (1, 2, 1) ON DUPLICATE KEY UPDATE c = NULL; +connection default; +# +# Connect to default and record how many pages were accessed +# when selecting the record using the secondary key. +# +SET @num_pages_1 = num_pages_get(); +SELECT * FROM t1 force index (b); +a b c +SET @num_pages_2= num_pages_get(); +SELECT @num_pages_2 - @num_pages_1 < 500; +@num_pages_2 - @num_pages_1 < 500 +1 +# +# Commit and show the final record. +# +SELECT * FROM t1; +a b c +SELECT * FROM t1 force index (b); +a b c +COMMIT; +SELECT * FROM t1 force index (b); +a b c +1 2 NULL +SELECT * FROM t1; +a b c +1 2 NULL +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +# +# Cleanup +# +disconnect con2; +disconnect con3; +DROP TABLE t1; +DROP PROCEDURE insert_n; +DROP FUNCTION num_pages_get; diff --git a/mysql-test/suite/innodb/t/innodb_bug14704286.test b/mysql-test/suite/innodb/t/innodb_bug14704286.test deleted file mode 100644 index fb5e6b829a1..00000000000 --- a/mysql-test/suite/innodb/t/innodb_bug14704286.test +++ /dev/null @@ -1,95 +0,0 @@ ---source include/have_innodb.inc - -# -# create test-bed to run test -# -use test; ---disable_warnings -drop table if exists t1; ---enable_warnings -create table t1 (id int primary key, value int, value2 int, -value3 int, index(value,value2)) engine=innodb; - -insert into t1 values -(10,10,10,10),(11,11,11,11),(12,12,12,12),(13,13,13,13),(14,14,14,14), -(15,15,15,15),(16,16,16,16),(17,17,17,17),(18,18,18,18),(19,19,19,19), -(20,20,20,20); -let $ID= `SELECT @id := CONNECTION_ID()`; - -# -# we need multiple connections as we need to keep one connection -# active with trx requesting consistent read. -# -connect (conn1, localhost, root,,); -connect (conn2, localhost, root,,); -connect (conn3, localhost, root,,); - -# -# start trx with consistent read -# -connection conn1; -use test; - -start transaction with consistent snapshot; - -# -# update table such that secondary index is updated. -# -connection conn2; -use test; -delimiter |; -CREATE PROCEDURE update_t1() -BEGIN - DECLARE i INT DEFAULT 1; - while (i <= 5000) DO - update test.t1 set value2=value2+1, value3=value3+1 where id=12; - SET i = i + 1; - END WHILE; -END| - -delimiter ;| -set autocommit=0; -CALL update_t1(); -select * from t1; -set autocommit=1; -select * from t1; - -# -# Now try to fire select query from connection-1 enforcing -# use of secondary index. -# -connection conn1; -let $ID= `SELECT @id := CONNECTION_ID()`; -#--error ER_QUERY_INTERRUPTED ---send -select * from t1 force index(value) where value=12; - -# -# select is going to take good time so let's kill query. -# -connection conn3; -let $wait_condition= - select * from information_schema.processlist where state = 'Sending data' and - info = 'select * from t1 force index(value) where value=12'; ---source include/wait_condition.inc -let $ignore= `SELECT @id := $ID`; -kill query @id; - -# -# reap the value of connection-1 -# -connection conn1; ---error ER_QUERY_INTERRUPTED -reap; - -# -# clean test-bed. -# -connection default; -disconnect conn1; -disconnect conn2; -disconnect conn3; -drop procedure if exists update_t1; -drop table if exists t1; - - diff --git a/mysql-test/suite/innodb/t/innodb_bug84958.test b/mysql-test/suite/innodb/t/innodb_bug84958.test new file mode 100644 index 00000000000..4456df21cb9 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug84958.test @@ -0,0 +1,86 @@ +--echo # +--echo # Bug #84958 InnoDB's MVCC has O(N^2) behaviors +--echo # https://bugs.mysql.com/bug.php?id=84958 +--echo # +--echo # Set up the test with a procedure and a function. +--echo # + +--source include/have_innodb.inc + +DELIMITER ~~; +CREATE PROCEDURE insert_n(start int, end int) +BEGIN + DECLARE i INT DEFAULT start; + WHILE i <= end do + INSERT INTO t1 VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = i; + SET i = i + 1; + END WHILE; +END~~ + +CREATE FUNCTION num_pages_get() +RETURNS INT +BEGIN + DECLARE ret INT; + SELECT variable_value INTO ret + FROM information_schema.global_status + WHERE variable_name = 'innodb_buffer_pool_read_requests'; + RETURN ret; +END~~ +DELIMITER ;~~ + +--echo # +--echo # Create a table with one record in it and start an RR transaction +--echo # +CREATE TABLE t1 (a INT, b INT, c INT, PRIMARY KEY(a,b), KEY (b,c)) +ENGINE=InnoDB; +BEGIN; +SELECT * FROM t1; + +--echo # +--echo # Create 100 newer record versions in con2 and con3 +--echo # +connect (con2, localhost, root,,); +connection con2; +INSERT INTO t1 VALUES (1, 2, 3) ON DUPLICATE KEY UPDATE c = NULL; +--send CALL insert_n(1, 50); + +connect (con3, localhost, root,,); +connection con3; +--send CALL insert_n(51, 100); + +connection con2; +reap; +connection con3; +reap; +INSERT INTO t1 VALUES (1, 2, 1) ON DUPLICATE KEY UPDATE c = NULL; + +connection default; + +--echo # +--echo # Connect to default and record how many pages were accessed +--echo # when selecting the record using the secondary key. +--echo # +SET @num_pages_1 = num_pages_get(); +SELECT * FROM t1 force index (b); +SET @num_pages_2= num_pages_get(); + +SELECT @num_pages_2 - @num_pages_1 < 500; + +--echo # +--echo # Commit and show the final record. +--echo # +SELECT * FROM t1; +SELECT * FROM t1 force index (b); +COMMIT; +SELECT * FROM t1 force index (b); +SELECT * FROM t1; +CHECK TABLE t1; + +--echo # +--echo # Cleanup +--echo # +disconnect con2; +disconnect con3; +DROP TABLE t1; +DROP PROCEDURE insert_n; +DROP FUNCTION num_pages_get; diff --git a/mysql-test/valgrind.supp b/mysql-test/valgrind.supp index 0b0fefd9adf..76409477143 100644 --- a/mysql-test/valgrind.supp +++ b/mysql-test/valgrind.supp @@ -1800,3 +1800,120 @@ obj:/usr/lib64/libcrypto.so* } + + +## +## The following is a copy of facebook/mysql-5.6 suppressions: +## + +# +# RocksDB Storage Engine suppressions start +# + +{ + Still reachable for once-per-process initializations + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:_ZN7rocksdb16ThreadStatusUtil19NewColumnFamilyInfoEPKNS_2DBEPKNS_16ColumnFamilyDataERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPKNS_3EnvE + fun:_ZNK7rocksdb6DBImpl21NewThreadStatusCfInfoEPNS_16ColumnFamilyDataE + fun:_ZN7rocksdb2DB4OpenERKNS_9DBOptionsERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22ColumnFamilyDescriptorESaISD_EEPSC_IPNS_18ColumnFamilyHandleESaISJ_EEPPS0_ + fun:_ZN7rocksdb13TransactionDB4OpenERKNS_9DBOptionsERKNS_20TransactionDBOptionsERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22ColumnFamilyDescriptorESaISG_EEPSF_IPNS_18ColumnFamilyHandleESaISM_EEPPS0_ + fun:_ZN7myrocksL17rocksdb_init_funcEPv +} + + +{ + Still reachable for once-per-process initializations 2 + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:_ZN7rocksdb16ThreadStatusUtil19NewColumnFamilyInfoEPKNS_2DBEPKNS_16ColumnFamilyDataERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPKNS_3EnvE + fun:_ZNK7rocksdb6DBImpl21NewThreadStatusCfInfoEPNS_16ColumnFamilyDataE + fun:_ZN7rocksdb6DBImpl4OpenERKNS_9DBOptionsERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22ColumnFamilyDescriptorESaISD_EEPSC_IPNS_18ColumnFamilyHandleESaISJ_EEPPNS_2DBEbb + fun:_ZN7rocksdb13TransactionDB4OpenERKNS_9DBOptionsERKNS_20TransactionDBOptionsERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKSt6vectorINS_22ColumnFamilyDescriptorESaISG_EEPSF_IPNS_18ColumnFamilyHandleESaISM_EEPPS0_ +# fun:_ZN7myrocksL17rocksdb_init_funcEPv +# ^ commenting the above out because we are hitting the --num-callers=16 +# limitation that MTR sets for valgrind +} + +{ + Still reachable for once-per-process initializations 3 + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:_ZN7rocksdb16ThreadStatusUtil19NewColumnFamilyInfoEPKNS_2DBEPKNS_16ColumnFamilyDataERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPKNS_3EnvE + fun:_ZNK7rocksdb6DBImpl21NewThreadStatusCfInfoEPNS_16ColumnFamilyDataE + fun:_ZN7rocksdb6DBImpl22CreateColumnFamilyImplERKNS_19ColumnFamilyOptionsERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEPPNS_18ColumnFamilyHandleE +} + +{ + Still reachable for once-per-process initializations + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:_ZN7rocksdb19ThreadStatusUpdater14RegisterThreadENS_12ThreadStatus10ThreadTypeEm + fun:_ZN7rocksdb16ThreadStatusUtil14RegisterThreadEPKNS_3EnvENS_12ThreadStatus10ThreadTypeE + fun:_ZN7rocksdb14ThreadPoolImpl4Impl15BGThreadWrapperEPv + ... +} + +{ + Still reachable for once-per-process initializations + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:_ZN7rocksdb14ThreadLocalPtr14InitSingletonsEv + fun:_ZN7rocksdb3Env7DefaultEv + fun:_ZN7rocksdb9DBOptionsC1Ev + ... + fun:_ZN7myrocksL27rdb_init_rocksdb_db_optionsEv +} + +{ + Still reachable for once-per-process initializations + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:_ZN7rocksdb12_GLOBAL__N_18PosixEnv* + fun:_ZN7rocksdb3Env7DefaultEv + fun:_ZN7rocksdb9DBOptionsC1Ev + ... + fun:_ZN7myrocksL27rdb_init_rocksdb_db_optionsEv +} + +{ + Still reachable for thread local storage initialization (SetHandle) + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:_ZNSt13unordered_mapIjPFvPvESt4hashIjESt8equal_toIjESaISt4pairIKjS2_EEEixERS8_ + fun:_ZN7rocksdb14ThreadLocalPtr10StaticMeta10SetHandlerEjPFvPvE + fun:_ZN7rocksdb14ThreadLocalPtrC1EPFvPvE + ... +} + +{ + Still reachable for thread local storage initialization (ReclaimId) + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:_ZN7rocksdb10autovectorIjLm8EE9push_backERKj + fun:_ZN7rocksdb14ThreadLocalPtr10StaticMeta9ReclaimIdEj + fun:_ZN7rocksdb14ThreadLocalPtrD1Ev + ... +} + +{ + Static initialization + Memcheck:Leak + match-leak-kinds: reachable + ... + fun:_Z41__static_initialization_and_destruction_0ii + ... +} + +## +## RocksDB Storage Engine suppressions end +## + diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index c6674352d56..3ce042be92d 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -3240,14 +3240,29 @@ row_sel_build_prev_vers_for_mysql( return(err); } +/** Helper class to cache clust_rec and old_ver */ +class Row_sel_get_clust_rec_for_mysql +{ + const rec_t *cached_clust_rec; + rec_t *cached_old_vers; + +public: + Row_sel_get_clust_rec_for_mysql() : + cached_clust_rec(NULL), cached_old_vers(NULL) {} + + dberr_t operator()(row_prebuilt_t *prebuilt, dict_index_t *sec_index, + const rec_t *rec, que_thr_t *thr, const rec_t **out_rec, + ulint **offsets, mem_heap_t **offset_heap, + dtuple_t **vrow, mtr_t *mtr); +}; + /*********************************************************************//** Retrieves the clustered index record corresponding to a record in a non-clustered index. Does the necessary locking. Used in the MySQL interface. @return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, or error code */ -static MY_ATTRIBUTE((warn_unused_result)) dberr_t -row_sel_get_clust_rec_for_mysql( +Row_sel_get_clust_rec_for_mysql::operator()( /*============================*/ row_prebuilt_t* prebuilt,/*!< in: prebuilt struct in the handle */ dict_index_t* sec_index,/*!< in: secondary index where rec resides */ @@ -3439,15 +3454,36 @@ row_sel_get_clust_rec_for_mysql( clust_rec, clust_index, *offsets, &trx->read_view)) { - /* The following call returns 'offsets' associated with - 'old_vers' */ - err = row_sel_build_prev_vers_for_mysql( - &trx->read_view, clust_index, prebuilt, - clust_rec, offsets, offset_heap, &old_vers, - vrow, mtr); + if (clust_rec != cached_clust_rec) { + /* The following call returns 'offsets' associated with + 'old_vers' */ + err = row_sel_build_prev_vers_for_mysql( + &trx->read_view, clust_index, prebuilt, + clust_rec, offsets, offset_heap, &old_vers, + vrow, mtr); + + if (err != DB_SUCCESS) { + + goto err_exit; + } + cached_clust_rec = clust_rec; + cached_old_vers = old_vers; + } else { + err = DB_SUCCESS; + old_vers = cached_old_vers; + + /* The offsets need not be same for the latest + version of clust_rec and its old version + old_vers. Re-calculate the offsets for old_vers. */ - if (err != DB_SUCCESS || old_vers == NULL) { + if (old_vers != NULL) { + *offsets = rec_get_offsets( + old_vers, clust_index, *offsets, + true, ULINT_UNDEFINED, offset_heap); + } + } + if (old_vers == NULL) { goto err_exit; } @@ -4178,6 +4214,7 @@ row_search_mvcc( dtuple_t* vrow = NULL; const rec_t* result_rec = NULL; const rec_t* clust_rec; + Row_sel_get_clust_rec_for_mysql row_sel_get_clust_rec_for_mysql; dberr_t err = DB_SUCCESS; ibool unique_search = FALSE; ibool mtr_has_extra_clust_latch = FALSE; diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc index 474ff6d7fc1..fb3b7af67fb 100644 --- a/storage/rocksdb/ha_rocksdb.cc +++ b/storage/rocksdb/ha_rocksdb.cc @@ -5836,11 +5836,11 @@ static int rocksdb_done_func(void *const p) { // Disown the cache data since we're shutting down. // This results in memory leaks but it improved the shutdown time. // Don't disown when running under valgrind -#ifndef HAVE_purify +#ifndef HAVE_valgrind if (rocksdb_tbl_options->block_cache) { rocksdb_tbl_options->block_cache->DisownData(); } -#endif /* HAVE_purify */ +#endif /* HAVE_valgrind */ /* MariaDB: don't clear rocksdb_db_options and rocksdb_tbl_options. diff --git a/storage/rocksdb/mysql-test/rocksdb/suite.pm b/storage/rocksdb/mysql-test/rocksdb/suite.pm index 3423d34ded5..e4f074df471 100644 --- a/storage/rocksdb/mysql-test/rocksdb/suite.pm +++ b/storage/rocksdb/mysql-test/rocksdb/suite.pm @@ -20,8 +20,8 @@ my $sst_dump= return "RocksDB is not compiled, no sst_dump" unless $sst_dump; $ENV{MARIAROCKS_SST_DUMP}="$sst_dump"; -# Temporarily disable testing under valgrind, due to MDEV-12439 -return "RocksDB tests disabled under valgrind" if ($::opt_valgrind); +## Temporarily disable testing under valgrind, due to MDEV-12439 +#return "RocksDB tests disabled under valgrind" if ($::opt_valgrind); bless { }; |