diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2017-12-08 10:02:28 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2017-12-08 10:02:28 +0200 |
commit | 0a02c1a6678f8ee278224ebd8ddfe74ee852cfb7 (patch) | |
tree | c834a9d3262d1389e0e76e27e154ca6a63eb2db3 | |
parent | a61fbf87ed9f6bb68332b81bc1024d1ded944d3d (diff) | |
parent | dfafe15abbd552ed487b2b0f7188db9303b1fa1f (diff) | |
download | mariadb-git-0a02c1a6678f8ee278224ebd8ddfe74ee852cfb7.tar.gz |
Merge 10.2 into bb-10.2-ext
-rw-r--r-- | client/mysqladmin.cc | 8 | ||||
-rw-r--r-- | mysql-test/suite/galera/disabled.def | 8 | ||||
-rw-r--r-- | mysql-test/suite/galera/r/MW-388.result | 12 | ||||
-rw-r--r-- | mysql-test/suite/galera/r/galera_bf_lock_wait.result | 23 | ||||
-rw-r--r-- | mysql-test/suite/galera/t/galera_bf_lock_wait.test | 52 | ||||
-rw-r--r-- | mysql-test/suite/storage_engine/type_bit_indexes.result | 4 | ||||
-rw-r--r-- | sql/sql_parse.cc | 33 | ||||
-rw-r--r-- | sql/sys_vars.cc | 3 | ||||
-rw-r--r-- | sql/wsrep_var.cc | 16 | ||||
-rw-r--r-- | sql/wsrep_var.h | 3 | ||||
-rw-r--r-- | storage/innobase/fsp/fsp0fsp.cc | 2 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 14 | ||||
-rw-r--r-- | storage/innobase/include/lock0priv.h | 19 | ||||
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 140 | ||||
-rw-r--r-- | storage/innobase/lock/lock0prdt.cc | 10 | ||||
-rw-r--r-- | storage/innobase/lock/lock0wait.cc | 34 |
16 files changed, 271 insertions, 110 deletions
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index 45b332a6cd6..7e824cadf40 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -34,9 +34,9 @@ char *host= NULL, *user= 0, *opt_password= 0, *default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME; -char truncated_var_names[MAX_MYSQL_VAR][MAX_TRUNC_LENGTH]; -char ex_var_names[MAX_MYSQL_VAR][FN_REFLEN]; -ulonglong last_values[MAX_MYSQL_VAR]; +char truncated_var_names[MAX_MYSQL_VAR+100][MAX_TRUNC_LENGTH]; +char ex_var_names[MAX_MYSQL_VAR+100][FN_REFLEN]; +ulonglong last_values[MAX_MYSQL_VAR+100]; static int interval=0; static my_bool option_force=0,interrupted=0,new_line=0, opt_compress= 0, opt_local= 0, opt_relative= 0, opt_verbose= 0, @@ -885,7 +885,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv) return -1; } - DBUG_ASSERT(mysql_num_rows(res) < MAX_MYSQL_VAR); + DBUG_ASSERT(mysql_num_rows(res) < MAX_MYSQL_VAR+100); if (!opt_vertical) print_header(res); diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 193b9f87d56..793d389c5d3 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -57,6 +57,8 @@ galera_as_slave : MDEV-13549 Galera test failures 10.1 galera_var_innodb_disallow_writes : MDEV-10949 galera_kill_applier : race condition at the start of the test GAL-480 : "Lost connection to MySQL" -MW-328A : "Found wrong usage of mutex" -MW-328B : "Found wrong usage of mutex" -MW-328C : "Found wrong usage of mutex" +MW-328C: MDEV-13549 Galera test failures 10.1 +MW-328A: MDEV-13549 Galera test failures 10.1 +MW-328B: MDEV-13549 Galera test failures 10.1 +MW-328: MDEV-13549 Galera test failures 10.1 +galera_suspend_slave: MDEV-13549 Galera test failures 10.1 diff --git a/mysql-test/suite/galera/r/MW-388.result b/mysql-test/suite/galera/r/MW-388.result index 17d347a11fb..7a8c2adafc1 100644 --- a/mysql-test/suite/galera/r/MW-388.result +++ b/mysql-test/suite/galera/r/MW-388.result @@ -1,3 +1,4 @@ +connection node_1; CREATE TABLE t1 (f1 INTEGER PRIMARY KEY, f2 CHAR(255)) Engine=InnoDB; CREATE PROCEDURE insert_proc () BEGIN @@ -12,28 +13,37 @@ SET GLOBAL wsrep_slave_threads = 2; SET GLOBAL DEBUG = "d,sync.wsrep_apply_cb"; Warnings: Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +connection node_2; INSERT INTO t1 VALUES (1, 'node 2');; +connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1; +connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR sync.wsrep_apply_cb_reached"; +connection node_1; SET SESSION wsrep_sync_wait = 0; SET SESSION DEBUG_SYNC = 'wsrep_after_replication SIGNAL wsrep_after_replication_reached WAIT_FOR wsrep_after_replication_continue'; CALL insert_proc ();; +connection node_1a; SET SESSION DEBUG_SYNC = "now WAIT_FOR wsrep_after_replication_reached"; SET GLOBAL DEBUG = ""; Warnings: Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead SET DEBUG_SYNC = "now SIGNAL wsrep_after_replication_continue"; SET DEBUG_SYNC = "now SIGNAL signal.wsrep_apply_cb"; +connection node_2; +connection node_1; SELECT @errno = 1213; @errno = 1213 -1 +0 SELECT * FROM t1; f1 f2 1 node 2 3 node 1 +connection node_2; SELECT * FROM t1; f1 f2 1 node 2 3 node 1 +connection node_1; SET GLOBAL wsrep_slave_threads = DEFAULT; DROP TABLE t1; DROP PROCEDURE insert_proc; diff --git a/mysql-test/suite/galera/r/galera_bf_lock_wait.result b/mysql-test/suite/galera/r/galera_bf_lock_wait.result new file mode 100644 index 00000000000..7ec524da888 --- /dev/null +++ b/mysql-test/suite/galera/r/galera_bf_lock_wait.result @@ -0,0 +1,23 @@ +CREATE TABLE t1 ENGINE=InnoDB select 1 as a, 1 as b union select 2, 2; +ALTER TABLE t1 add primary key(a); +CREATE PROCEDURE p1() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION rollback; +WHILE 1 DO +start transaction; +update t1 set b=connection_id() where a=1; +commit; +END WHILE; +END| +connect node_1_p1, 127.0.0.1, root, , test, $NODE_MYPORT_1; +call p1; +connect node_1_p2, 127.0.0.1, root, , test, $NODE_MYPORT_1; +call p1; +connect node_2_p1, 127.0.0.1, root, , test, $NODE_MYPORT_2; +call p1; +connect node_2_p2, 127.0.0.1, root, , test, $NODE_MYPORT_2; +call p1; +connection default; +checking error log for 'BF lock wait long' message for 10 times every 10 seconds ... +drop table t1; +drop procedure p1; diff --git a/mysql-test/suite/galera/t/galera_bf_lock_wait.test b/mysql-test/suite/galera/t/galera_bf_lock_wait.test new file mode 100644 index 00000000000..e3a9077a888 --- /dev/null +++ b/mysql-test/suite/galera/t/galera_bf_lock_wait.test @@ -0,0 +1,52 @@ +--source include/galera_cluster.inc +--source include/big_test.inc + +CREATE TABLE t1 ENGINE=InnoDB select 1 as a, 1 as b union select 2, 2; +ALTER TABLE t1 add primary key(a); + +DELIMITER |; + +CREATE PROCEDURE p1() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION rollback; + WHILE 1 DO + start transaction; + update t1 set b=connection_id() where a=1; + commit; + END WHILE; +END| + + +DELIMITER ;| + +--connect node_1_p1, 127.0.0.1, root, , test, $NODE_MYPORT_1 +send call p1; +--connect node_1_p2, 127.0.0.1, root, , test, $NODE_MYPORT_1 +send call p1; +--connect node_2_p1, 127.0.0.1, root, , test, $NODE_MYPORT_2 +send call p1; +--connect node_2_p2, 127.0.0.1, root, , test, $NODE_MYPORT_2 +send call p1; + +connection default; +let $counter=10; +let $sleep_period=10; + +echo checking error log for 'BF lock wait long' message for $counter times every $sleep_period seconds ...; +while($counter > 0) +{ +--disable_query_log +--disable_result_log + eval do sleep($sleep_period); +--enable_query_log +--enable_result_log + +# use error 0,1 instead if want test to continue + --error 1 + exec grep 'BF lock wait long' $MYSQLTEST_VARDIR/log/mysqld.*.err; + dec $counter; +} + +drop table t1; +drop procedure p1; + diff --git a/mysql-test/suite/storage_engine/type_bit_indexes.result b/mysql-test/suite/storage_engine/type_bit_indexes.result index af8ddf7d6c9..e7c0cf656c5 100644 --- a/mysql-test/suite/storage_engine/type_bit_indexes.result +++ b/mysql-test/suite/storage_engine/type_bit_indexes.result @@ -69,7 +69,7 @@ INSERT INTO t1 (a,b,c,d) VALUES (1,0xFFFF,0xFFFFFFFF,0xFFFFFFFFFFFFFFFF); EXPLAIN SELECT HEX(b+c) FROM t1 WHERE c > 1 OR HEX(b) < 0xFFFFFF; id select_type table type possible_keys key key_len ref rows Extra -# # # # # b_c # # # # +# # # # # NULL # # # # SELECT HEX(b+c) FROM t1 WHERE c > 1 OR HEX(b) < 0xFFFFFF; HEX(b+c) 10 @@ -98,7 +98,7 @@ INSERT INTO t1 (a,b,c,d) VALUES (1,0xFFFF,0xFFFFFFFF,0xFFFFFFFFFFFFFFFF); EXPLAIN SELECT DISTINCT a+0 FROM t1 ORDER BY a; id select_type table type possible_keys key key_len ref rows Extra -# # # # # a # # # # +# # # # # NULL # # # # SELECT DISTINCT a+0 FROM t1 ORDER BY a; a+0 0 diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 8b1b20f5857..4246c9cdae9 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5751,14 +5751,19 @@ end_with_restore_list: thd->print_aborted_warning(3, "RELEASE"); } #ifdef WITH_WSREP - if (WSREP(thd) && (thd->wsrep_conflict_state != NO_CONFLICT && - thd->wsrep_conflict_state != REPLAYING)) - { - DBUG_ASSERT(thd->is_error()); // the error is already issued + if (WSREP(thd)) { + + if (thd->wsrep_conflict_state == NO_CONFLICT || + thd->wsrep_conflict_state == REPLAYING) + { + my_ok(thd); + } + } else { +#endif /* WITH_WSREP */ + my_ok(thd); +#ifdef WITH_WSREP } - else #endif /* WITH_WSREP */ - my_ok(thd); break; } case SQLCOM_ROLLBACK: @@ -5795,13 +5800,16 @@ end_with_restore_list: if (tx_release) thd->set_killed(KILL_CONNECTION); #ifdef WITH_WSREP - if (WSREP(thd) && thd->wsrep_conflict_state != NO_CONFLICT) - { - DBUG_ASSERT(thd->is_error()); // the error is already issued + if (WSREP(thd)) { + if (thd->wsrep_conflict_state == NO_CONFLICT) { + my_ok(thd); + } + } else { +#endif /* WITH_WSREP */ + my_ok(thd); +#ifdef WITH_WSREP } - else #endif /* WITH_WSREP */ - my_ok(thd); break; } case SQLCOM_RELEASE_SAVEPOINT: @@ -6258,8 +6266,9 @@ finish: trans_rollback_stmt(thd); } #ifdef WITH_WSREP - else if (thd->spcont && + if (thd->spcont && (thd->wsrep_conflict_state == MUST_ABORT || + thd->wsrep_conflict_state == ABORTED || thd->wsrep_conflict_state == CERT_FAILURE)) { /* diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index d8bf044f53b..78242e0a088 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -5014,7 +5014,8 @@ static Sys_var_mybool Sys_wsrep_on ( "wsrep_on", "To enable wsrep replication ", SESSION_VAR(wsrep_on), CMD_LINE(OPT_ARG), DEFAULT(FALSE), - NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_on_check), ON_UPDATE(wsrep_on_update)); static Sys_var_charptr Sys_wsrep_start_position ( diff --git a/sql/wsrep_var.cc b/sql/wsrep_var.cc index 188fa3e292b..34c5865548c 100644 --- a/sql/wsrep_var.cc +++ b/sql/wsrep_var.cc @@ -42,12 +42,28 @@ int wsrep_init_vars() return 0; } +extern ulong innodb_lock_schedule_algorithm; + bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type) { if (var_type == OPT_GLOBAL) { // FIXME: this variable probably should be changed only per session thd->variables.wsrep_on = global_system_variables.wsrep_on; } + + return false; +} + +bool wsrep_on_check(sys_var *self, THD* thd, set_var* var) +{ + bool new_wsrep_on= (bool)var->save_result.ulonglong_value; + + if (new_wsrep_on && innodb_lock_schedule_algorithm != 0) { + my_message(ER_WRONG_ARGUMENTS, " WSREP (galera) can't be enabled " + "if innodb_lock_schedule_algorithm=VATS. Please configure" + " innodb_lock_schedule_algorithm=FCFS and restart.", MYF(0)); + return true; + } return false; } diff --git a/sql/wsrep_var.h b/sql/wsrep_var.h index dde59d1503f..b9051b29843 100644 --- a/sql/wsrep_var.h +++ b/sql/wsrep_var.h @@ -41,7 +41,8 @@ int wsrep_init_vars(); #define DEFAULT_ARGS (THD* thd, enum_var_type var_type) #define INIT_ARGS (const char* opt) -extern bool wsrep_causal_reads_update UPDATE_ARGS; +extern bool wsrep_causal_reads_update UPDATE_ARGS; +extern bool wsrep_on_check CHECK_ARGS; extern bool wsrep_on_update UPDATE_ARGS; extern bool wsrep_sync_wait_update UPDATE_ARGS; extern bool wsrep_start_position_check CHECK_ARGS; diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc index 80303314d9f..2531a9fb5aa 100644 --- a/storage/innobase/fsp/fsp0fsp.cc +++ b/storage/innobase/fsp/fsp0fsp.cc @@ -2446,8 +2446,6 @@ fseg_alloc_free_page_low( ut_ad(mach_read_from_4(seg_inode + FSEG_MAGIC_N) == FSEG_MAGIC_N_VALUE); ut_ad(!((page_offset(seg_inode) - FSEG_ARR_OFFSET) % FSEG_INODE_SIZE)); - ut_ad(space->purpose == FIL_TYPE_TEMPORARY - || space->purpose == FIL_TYPE_TABLESPACE); seg_id = mach_read_from_8(seg_inode + FSEG_ID); ut_ad(seg_id); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a0da106a57a..1fade781612 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -3864,6 +3864,16 @@ innobase_init( goto error; } +#ifdef WITH_WSREP + /* Currently, Galera does not support VATS lock schedule algorithm. */ + if (innodb_lock_schedule_algorithm == INNODB_LOCK_SCHEDULE_ALGORITHM_VATS + && global_system_variables.wsrep_on) { + ib::info() << "In Galera environment Variance-Aware-Transaction-Sheduling Algorithm" + " is not supported. Falling back to First-Come-First-Served order. "; + innodb_lock_schedule_algorithm = INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS; + } +#endif /* WITH_WSREP */ + #ifndef HAVE_LZ4 if (innodb_compression_algorithm == PAGE_LZ4_ALGORITHM) { sql_print_error("InnoDB: innodb_compression_algorithm = %lu unsupported.\n" @@ -5353,7 +5363,7 @@ innobase_kill_query( wsrep_thd_is_BF(current_thd, FALSE)); } - if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE) && trx->abort_type != TRX_WSREP_ABORT) { lock_mutex_enter(); lock_mutex_taken = true; } @@ -20879,7 +20889,7 @@ static MYSQL_SYSVAR_ULONG(doublewrite_batch_size, srv_doublewrite_batch_size, #endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */ static MYSQL_SYSVAR_ENUM(lock_schedule_algorithm, innodb_lock_schedule_algorithm, - PLUGIN_VAR_RQCMDARG, + PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, "The algorithm Innodb uses for deciding which locks to grant next when" " a lock is released. Possible values are" " FCFS" diff --git a/storage/innobase/include/lock0priv.h b/storage/innobase/include/lock0priv.h index 6bb75817ad6..185779e476f 100644 --- a/storage/innobase/include/lock0priv.h +++ b/storage/innobase/include/lock0priv.h @@ -721,7 +721,7 @@ public: as a victim, and we got the lock immediately: no need to wait then */ dberr_t add_to_waitq( - const lock_t* wait_for, + lock_t* wait_for, const lock_prdt_t* prdt = NULL); @@ -731,21 +731,22 @@ public: @param[in] owns_trx_mutex true if caller owns the trx_t::mutex @param[in] add_to_hash add the lock to hash table @param[in] prdt Predicate lock (optional) + @param[in,out] c_lock Conflicting lock request or NULL + in Galera conflicting lock is selected + as deadlock victim if requester + is BF transaction. @return new lock instance */ lock_t* create( trx_t* trx, bool owns_trx_mutex, bool add_to_hash, const lock_prdt_t* - prdt = NULL); + prdt = NULL +#ifdef WITH_WSREP + ,lock_t* c_lock = NULL +#endif /* WITH_WSREP */ + ); - lock_t* create( - lock_t* const c_lock, - trx_t* trx, - bool owns_trx_mutex, - bool add_to_hash, - const lock_prdt_t* - prdt = NULL); /** Check of the lock is on m_rec_id. @param[in] lock Lock to compare with diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index d9ac953d2e8..7a1afec820c 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -811,13 +811,18 @@ lock_reset_lock_and_trx_wait( } ib::error() << - "Trx id " << lock->trx->id - << " is waiting a lock in statement " - << (stmt ? stmt : "NULL") - << " for this trx id " << trx_id - << " and statement " - << (stmt2 ? stmt2 : "NULL") - << "wait_lock " << lock->trx->lock.wait_lock; + "Trx id " << ib::hex(lock->trx->id) + << " is waiting a lock " + << " for this trx id " << ib::hex(trx_id) + << " wait_lock " << lock->trx->lock.wait_lock; + if (stmt) { + ib::info() << " SQL1: " << stmt; + } + + if (stmt2) { + ib::info() << " SQL2: " << stmt2; + } + ut_ad(0); } @@ -1316,7 +1321,7 @@ lock_rec_has_expl( Checks if some other transaction has a lock request in the queue. @return lock or NULL */ static -const lock_t* +lock_t* lock_rec_other_has_expl_req( /*========================*/ lock_mode mode, /*!< in: LOCK_S or LOCK_X */ @@ -1339,10 +1344,10 @@ lock_rec_other_has_expl_req( return(NULL); } - for (const lock_t* lock = lock_rec_get_first(lock_sys->rec_hash, + for (lock_t* lock = lock_rec_get_first(lock_sys->rec_hash, block, heap_no); lock != NULL; - lock = lock_rec_get_next_const(heap_no, lock)) { + lock = lock_rec_get_next(heap_no, lock)) { if (lock->trx != trx && !lock_rec_get_gap(lock) @@ -1431,7 +1436,7 @@ Checks if some other transaction has a conflicting explicit lock request in the queue, so that we have to wait. @return lock or NULL */ static -const lock_t* +lock_t* lock_rec_other_has_conflicting( /*===========================*/ ulint mode, /*!< in: LOCK_S or LOCK_X, @@ -1443,7 +1448,7 @@ lock_rec_other_has_conflicting( ulint heap_no,/*!< in: heap number of the record */ const trx_t* trx) /*!< in: our transaction */ { - const lock_t* lock; + lock_t* lock; ut_ad(lock_mutex_own()); @@ -1451,13 +1456,16 @@ lock_rec_other_has_conflicting( for (lock = lock_rec_get_first(lock_sys->rec_hash, block, heap_no); lock != NULL; - lock = lock_rec_get_next_const(heap_no, lock)) { + lock = lock_rec_get_next(heap_no, lock)) { if (lock_rec_has_to_wait(true, trx, mode, lock, is_supremum)) { #ifdef WITH_WSREP if (wsrep_on_trx(trx)) { trx_mutex_enter(lock->trx); - wsrep_kill_victim((trx_t *)trx, (lock_t *)lock); + /* Below function will roll back either trx + or lock->trx depending on priority of the + transaction. */ + wsrep_kill_victim(const_cast<trx_t*>(trx), lock); trx_mutex_exit(lock->trx); } #endif /* WITH_WSREP */ @@ -1947,19 +1955,21 @@ Create a new lock. @param[in] owns_trx_mutex true if caller owns the trx_t::mutex @param[in] add_to_hash add the lock to hash table @param[in] prdt Predicate lock (optional) +@param[in,out] c_lock Conflicting lock request or NULL + in Galera conflicting lock is selected + as deadlock victim if requester + is BF transaction. @return a new lock instance */ lock_t* -RecLock::create(trx_t* trx, bool owns_trx_mutex, bool add_to_hash, const lock_prdt_t* prdt) -{ - return create(NULL, trx, owns_trx_mutex, add_to_hash, prdt); -} -lock_t* RecLock::create( - lock_t* const c_lock, trx_t* trx, bool owns_trx_mutex, bool add_to_hash, - const lock_prdt_t* prdt) + const lock_prdt_t* prdt +#ifdef WITH_WSREP + ,lock_t* c_lock +#endif /* WITH_WSREP */ +) { ut_ad(lock_mutex_own()); ut_ad(owns_trx_mutex == trx_mutex_own(trx)); @@ -2045,7 +2055,7 @@ RecLock::create( trx_mutex_exit(c_lock->trx); if (wsrep_debug) { - ib::info() << "WSREP: c_lock canceled " << c_lock->trx->id; + ib::info() << "WSREP: c_lock canceled " << ib::hex(c_lock->trx->id); ib::info() << " SQL1: " << wsrep_thd_query(c_lock->trx->mysql_thd); ib::info() << " SQL2: " @@ -2182,8 +2192,8 @@ RecLock::mark_trx_for_rollback(trx_t* trx) if (thd != NULL) { char buffer[1024]; - ib::info() << "Blocking transaction: ID: " << trx->id << " - " - << " Blocked transaction ID: "<< m_trx->id << " - " + ib::info() << "Blocking transaction: ID: " << ib::hex(trx->id) << " - " + << " Blocked transaction ID: "<< ib::hex(m_trx->id) << " - " << thd_get_error_context_description(thd, buffer, sizeof(buffer), 512); } @@ -2224,7 +2234,7 @@ queue is itself waiting roll it back, also do a deadlock check and resolve. as a victim, and we got the lock immediately: no need to wait then */ dberr_t -RecLock::add_to_waitq(const lock_t* wait_for, const lock_prdt_t* prdt) +RecLock::add_to_waitq(lock_t* wait_for, const lock_prdt_t* prdt) { ut_ad(lock_mutex_own()); ut_ad(m_trx == thr_get_trx(m_thr)); @@ -2259,7 +2269,12 @@ RecLock::add_to_waitq(const lock_t* wait_for, const lock_prdt_t* prdt) bool high_priority = trx_is_high_priority(m_trx); /* Don't queue the lock to hash table, if high priority transaction. */ - lock_t* lock = create(m_trx, true, !high_priority, prdt); + lock_t* lock = create( + m_trx, true, !high_priority, prdt +#ifdef WITH_WSREP + ,wait_for +#endif /* WITH_WSREP */ + ); /* Attempt to jump over the low priority waiting locks. */ if (high_priority && jump_queue(lock, wait_for)) { @@ -2268,10 +2283,18 @@ RecLock::add_to_waitq(const lock_t* wait_for, const lock_prdt_t* prdt) return(DB_SUCCESS); } +#ifdef WITH_WSREP + if (!lock_get_wait(lock) && wsrep_thd_is_BF(m_trx->mysql_thd, FALSE)) { + if (wsrep_debug) { + ib::info() << "WSREP: BF thread got lock granted early, ID " << ib::hex(lock->trx->id) + << " query: " << wsrep_thd_query(m_trx->mysql_thd); + } + return(DB_SUCCESS); + } +#endif /* WITH_WSREP */ ut_ad(lock_get_wait(lock)); - dberr_t err = deadlock_check(lock); - + dberr_t err = deadlock_check(lock); ut_ad(trx_mutex_own(m_trx)); // Move it only when it does not cause a deadlock. @@ -2553,8 +2576,7 @@ lock_rec_lock_slow( err = DB_SUCCESS; } else { - - const lock_t* wait_for = lock_rec_other_has_conflicting( + lock_t* wait_for = lock_rec_other_has_conflicting( mode, block, heap_no, trx); if (wait_for != NULL) { @@ -2684,6 +2706,14 @@ lock_rec_has_to_wait_in_queue( #ifdef WITH_WSREP if (wsrep_thd_is_BF(wait_lock->trx->mysql_thd, FALSE) && wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE)) { + if (wsrep_debug) { + ib::info() << "WSREP: waiting BF trx: " << ib::hex(wait_lock->trx->id) + << " query: " << wsrep_thd_query(wait_lock->trx->mysql_thd); + lock_rec_print(stderr, wait_lock); + ib::info() << "WSREP: do not wait another BF trx: " << ib::hex(lock->trx->id) + << " query: " << wsrep_thd_query(lock->trx->mysql_thd); + lock_rec_print(stderr, lock); + } /* don't wait for another BF lock */ continue; } @@ -2786,8 +2816,8 @@ RecLock::jump_queue( DBUG_LOG("trx", "Granting High Priority Transaction " - << lock->trx->id << " a lock jumping over" - << " waiting Transaction " << conflict_lock->trx->id); + << ib::hex(lock->trx->id) << " a lock jumping over" + << " waiting Transaction " << ib::hex(conflict_lock->trx->id)); lock_reset_lock_and_trx_wait(lock); return(true); @@ -2958,9 +2988,9 @@ RecLock::make_trx_hit_list( ut_ad(trx->lock.wait_lock != next); DBUG_LOG("trx", "High Priority Transaction " - << lock->trx->id + << ib::hex(lock->trx->id) << " waking up blocking transaction " - << trx->id); + << ib::hex(trx->id)); trx->lock.was_chosen_as_deadlock_victim = true; lock_cancel_waiting_and_release(trx->lock.wait_lock); @@ -3050,22 +3080,21 @@ lock_grant_and_move_on_page( && lock_get_wait(lock) && !lock_rec_has_to_wait_in_queue(lock)) { - bool exit_trx_mutex = false; - + if (lock->trx->abort_type != TRX_SERVER_ABORT) { ut_ad(trx_mutex_own(lock->trx)); trx_mutex_exit(lock->trx); exit_trx_mutex = true; } - + lock_grant(lock, false); - + if (exit_trx_mutex) { ut_ad(!trx_mutex_own(lock->trx)); trx_mutex_enter(lock->trx); } - + if (previous != NULL) { /* Move the lock to the head of the list. */ HASH_GET_NEXT(hash, previous) = HASH_GET_NEXT(hash, lock); @@ -3161,9 +3190,9 @@ lock_rec_dequeue_from_page( } } } - } else { - lock_grant_and_move_on_page(lock_hash, space, page_no); - } + } else { + lock_grant_and_move_on_page(lock_hash, space, page_no); + } } /*************************************************************//** @@ -4389,7 +4418,7 @@ lock_table_create( ut_list_insert(table->locks, c_lock, lock, TableLockGetNode()); if (wsrep_debug) { ib::info() << "table lock BF conflict for " << - c_lock->trx->id; + ib::hex(c_lock->trx->id); ib::info() << " SQL: " << wsrep_thd_query(c_lock->trx->mysql_thd); } @@ -4425,7 +4454,7 @@ lock_table_create( } if (wsrep_debug) { - ib::info() << "WSREP: c_lock canceled " << c_lock->trx->id; + ib::info() << "WSREP: c_lock canceled " << ib::hex(c_lock->trx->id); ib::info() << " SQL: " << wsrep_thd_query(c_lock->trx->mysql_thd); } @@ -4697,7 +4726,7 @@ Checks if other transactions have an incompatible mode lock request in the lock queue. @return lock or NULL */ UNIV_INLINE -const lock_t* +lock_t* lock_table_other_has_incompatible( /*==============================*/ const trx_t* trx, /*!< in: transaction, or NULL if all @@ -4708,7 +4737,7 @@ lock_table_other_has_incompatible( const dict_table_t* table, /*!< in: table */ lock_mode mode) /*!< in: lock mode */ { - const lock_t* lock; + lock_t* lock; ut_ad(lock_mutex_own()); @@ -4757,7 +4786,7 @@ lock_table( { trx_t* trx; dberr_t err; - const lock_t* wait_for; + lock_t* wait_for; ut_ad(table && thr); @@ -4813,9 +4842,9 @@ lock_table( mode: this trx may have to wait */ if (wait_for != NULL) { - err = lock_table_enqueue_waiting((lock_t*)wait_for, mode | flags, table, thr); + err = lock_table_enqueue_waiting(wait_for, mode | flags, table, thr); } else { - lock_table_create(table, mode | flags, trx); + lock_table_create(wait_for, table, mode | flags, trx); ut_a(!flags || mode == LOCK_S || mode == LOCK_X); @@ -6744,7 +6773,7 @@ lock_rec_insert_check_and_lock( const ulint type_mode = LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION; - const lock_t* wait_for = lock_rec_other_has_conflicting( + lock_t* wait_for = lock_rec_other_has_conflicting( type_mode, block, heap_no, trx); if (wait_for != NULL) { @@ -8486,16 +8515,7 @@ DeadlockChecker::check_and_resolve(const lock_t* lock, trx_t* trx) ut_ad(trx == checker.m_start); ut_ad(trx == victim_trx); -#ifdef WITH_WSREP - if (!wsrep_thd_is_BF(victim_trx->mysql_thd, TRUE)) - { -#endif /* WITH_WSREP */ - rollback_print(victim_trx, lock); -#ifdef WITH_WSREP - } else { - /* BF processor */; - } -#endif /* WITH_WSREP */ + rollback_print(victim_trx, lock); MONITOR_INC(MONITOR_DEADLOCK); diff --git a/storage/innobase/lock/lock0prdt.cc b/storage/innobase/lock/lock0prdt.cc index 88573b8a71a..dc2c6e2d15e 100644 --- a/storage/innobase/lock/lock0prdt.cc +++ b/storage/innobase/lock/lock0prdt.cc @@ -290,7 +290,7 @@ Checks if some other transaction has a conflicting predicate lock request in the queue, so that we have to wait. @return lock or NULL */ static -const lock_t* +lock_t* lock_prdt_other_has_conflicting( /*============================*/ ulint mode, /*!< in: LOCK_S or LOCK_X, @@ -305,10 +305,10 @@ lock_prdt_other_has_conflicting( { ut_ad(lock_mutex_own()); - for (const lock_t* lock = lock_rec_get_first( + for (lock_t* lock = lock_rec_get_first( lock_hash_get(mode), block, PRDT_HEAPNO); lock != NULL; - lock = lock_rec_get_next_const(PRDT_HEAPNO, lock)) { + lock = lock_rec_get_next(PRDT_HEAPNO, lock)) { if (lock->trx == trx) { continue; @@ -565,7 +565,7 @@ lock_prdt_insert_check_and_lock( const ulint mode = LOCK_X | LOCK_PREDICATE | LOCK_INSERT_INTENTION; - const lock_t* wait_for = lock_prdt_other_has_conflicting( + lock_t* wait_for = lock_prdt_other_has_conflicting( mode, block, prdt, trx); if (wait_for != NULL) { @@ -854,7 +854,7 @@ lock_prdt_lock( if (lock == NULL) { - const lock_t* wait_for; + lock_t* wait_for; wait_for = lock_prdt_other_has_conflicting( prdt_mode, block, prdt, trx); diff --git a/storage/innobase/lock/lock0wait.cc b/storage/innobase/lock/lock0wait.cc index 0ed55558dc4..c41821412af 100644 --- a/storage/innobase/lock/lock0wait.cc +++ b/storage/innobase/lock/lock0wait.cc @@ -183,20 +183,38 @@ lock_wait_table_reserve_slot( /*********************************************************************//** check if lock timeout was for priority thread, as a side effect trigger lock monitor +@param[in] trx transaction owning the lock +@param[in] locked true if trx and lock_sys_mutex is ownd @return false for regular lock timeout */ -static ibool +static +bool wsrep_is_BF_lock_timeout( -/*====================*/ - trx_t* trx) /* in: trx to check for lock priority */ + const trx_t* trx, + bool locked = true) { - if (wsrep_on_trx(trx) && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { - fprintf(stderr, "WSREP: BF lock wait long\n"); + if (wsrep_on_trx(trx) + && wsrep_thd_is_BF(trx->mysql_thd, FALSE) + && trx->error_state != DB_DEADLOCK) { + ib::info() << "WSREP: BF lock wait long for trx:" << ib::hex(trx->id) + << " query: " << wsrep_thd_query(trx->mysql_thd); + if (!locked) { + lock_mutex_enter(); + } + + ut_ad(lock_mutex_own()); + + wsrep_trx_print_locking(stderr, trx, 3000); + + if (!locked) { + lock_mutex_exit(); + } + srv_print_innodb_monitor = TRUE; srv_print_innodb_lock_monitor = TRUE; os_event_set(srv_monitor_event); - return TRUE; + return true; } - return FALSE; + return false; } #endif /* WITH_WSREP */ @@ -399,7 +417,7 @@ lock_wait_suspend_thread( && wait_time > (double) lock_wait_timeout #ifdef WITH_WSREP && (!wsrep_on_trx(trx) || - (!wsrep_is_BF_lock_timeout(trx) && trx->error_state != DB_DEADLOCK)) + (!wsrep_is_BF_lock_timeout(trx, false) && trx->error_state != DB_DEADLOCK)) #endif /* WITH_WSREP */ && !trx_is_high_priority(trx)) { |