diff options
author | Brave Galera Crew <devel@codership.com> | 2019-01-23 15:30:00 +0400 |
---|---|---|
committer | Sergey Vojtovich <svoj@mariadb.org> | 2019-01-23 15:30:00 +0400 |
commit | 36a2a185fe18d31a644da46cfabd9757a379280c (patch) | |
tree | 00ca186ce2cfdc3ab7e4979336a384e2b51c5aa9 /storage | |
parent | 382115b99297ceaa4c3067f79efb5c2515013be5 (diff) | |
download | mariadb-git-36a2a185fe18d31a644da46cfabd9757a379280c.tar.gz |
Galera4
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/buf/buf0dump.cc | 4 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 490 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.h | 33 | ||||
-rw-r--r-- | storage/innobase/include/trx0trx.h | 5 | ||||
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 55 | ||||
-rw-r--r-- | storage/innobase/row/row0ins.cc | 30 | ||||
-rw-r--r-- | storage/innobase/row/row0sel.cc | 10 | ||||
-rw-r--r-- | storage/innobase/row/row0upd.cc | 6 | ||||
-rw-r--r-- | storage/innobase/srv/srv0conc.cc | 8 | ||||
-rw-r--r-- | storage/innobase/srv/srv0srv.cc | 4 | ||||
-rw-r--r-- | storage/innobase/srv/srv0start.cc | 2 | ||||
-rw-r--r-- | storage/innobase/trx/trx0roll.cc | 11 | ||||
-rw-r--r-- | storage/innobase/trx/trx0rseg.cc | 69 | ||||
-rw-r--r-- | storage/innobase/trx/trx0trx.cc | 7 |
14 files changed, 341 insertions, 393 deletions
diff --git a/storage/innobase/buf/buf0dump.cc b/storage/innobase/buf/buf0dump.cc index c8e7236dc93..2747a6fa338 100644 --- a/storage/innobase/buf/buf0dump.cc +++ b/storage/innobase/buf/buf0dump.cc @@ -822,7 +822,7 @@ DECLARE_THREAD(buf_dump_thread)(void*) if (srv_buffer_pool_load_at_startup) { #ifdef WITH_WSREP - if (!wsrep_recovery) { + if (!get_wsrep_recovery()) { #endif /* WITH_WSREP */ buf_load(); #ifdef WITH_WSREP @@ -856,7 +856,7 @@ DECLARE_THREAD(buf_dump_thread)(void*) "Dumping of buffer pool not started" " as load was incomplete"); #ifdef WITH_WSREP - } else if (wsrep_recovery) { + } else if (get_wsrep_recovery()) { #endif /* WITH_WSREP */ } else { buf_dump(FALSE/* do complete dump at shutdown */); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 2690ff9f736..186c3ee3154 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -131,6 +131,9 @@ void close_thread_tables(THD* thd); #define tdc_size 400 #endif +#include <mysql/plugin.h> +#include <mysql/service_wsrep.h> + #include "ha_innodb.h" #include "i_s.h" #include "sync0sync.h" @@ -138,9 +141,6 @@ void close_thread_tables(THD* thd); #include <string> #include <sstream> -#include <mysql/plugin.h> -#include <mysql/service_wsrep.h> - #ifdef WITH_WSREP #include "dict0priv.h" #include <mysql/service_md5.h> @@ -148,21 +148,6 @@ void close_thread_tables(THD* thd); extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log; -static inline wsrep_ws_handle_t* -wsrep_ws_handle(THD* thd, const trx_t* trx) { - return wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), - (wsrep_trx_id_t)trx->id); -} - -extern TC_LOG* tc_log; -extern void wsrep_cleanup_transaction(THD *thd); -static int -wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, - my_bool signal); -static void -wsrep_fake_trx_id(handlerton* hton, THD *thd); -static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid); -static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid); #endif /* WITH_WSREP */ /** to force correct commit order in binlog */ @@ -1843,8 +1828,13 @@ thd_to_trx_id( { return(thd_to_trx(thd)->id); } -#endif /* WITH_WSREP */ +static int +wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, + my_bool signal); +static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid); +static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid); +#endif /* WITH_WSREP */ /********************************************************************//** Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth time calls srv_active_wake_master_thread. This function should be used @@ -4161,13 +4151,12 @@ static int innodb_init(void* p) innobase_hton->show_status = innobase_show_status; innobase_hton->flags = HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS - | HTON_NATIVE_SYS_VERSIONING; + | HTON_NATIVE_SYS_VERSIONING | HTON_WSREP_REPLICATION; #ifdef WITH_WSREP innobase_hton->abort_transaction=wsrep_abort_transaction; innobase_hton->set_checkpoint=innobase_wsrep_set_checkpoint; innobase_hton->get_checkpoint=innobase_wsrep_get_checkpoint; - innobase_hton->fake_trx_id=wsrep_fake_trx_id; #endif /* WITH_WSREP */ innobase_hton->tablefile_extensions = ha_innobase_exts; @@ -4502,6 +4491,14 @@ innobase_commit_ordered_2( trx->flush_log_later = true; } +#ifdef WITH_WSREP + /* If the transaction is not run in 2pc, we must assign wsrep + XID here in order to get it written in rollback segment. */ + if (wsrep_on(thd)) { + thd_get_xid(thd, (MYSQL_XID*)trx->xid); + } +#endif /* WITH_WSREP */ + innobase_commit_low(trx); if (!read_only) { @@ -4704,6 +4701,15 @@ innobase_rollback( dberr_t error; +#ifdef WITH_WSREP + /* If trx was assigned wsrep XID in prepare phase and the + trx is being rolled back due to BF abort, clear XID in order + to avoid writing it to rollback segment out of order. The XID + will be reassigned when the transaction is replayed. */ + if (wsrep_is_wsrep_xid(trx->xid)) { + trx->xid->null(); + } +#endif /* WITH_WSREP */ if (rollback_trx || !thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) { @@ -5109,7 +5115,7 @@ static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels) { DBUG_ENTER("innobase_kill_query"); #ifdef WITH_WSREP - if (wsrep_thd_get_conflict_state(thd) != NO_CONFLICT) { + if (wsrep_on(thd) && wsrep_thd_is_aborting(thd)) { /* if victim has been signaled by BF thread and/or aborting is already progressing, following query aborting is not necessary any more. @@ -8107,9 +8113,9 @@ ha_innobase::write_row( wsrep_thd_query(m_user_thd) : (char *)"void"); error= DB_SUCCESS; - wsrep_thd_set_conflict_state( - m_user_thd, MUST_ABORT); - innobase_srv_conc_exit_innodb(m_prebuilt); + wsrep_thd_self_abort(m_user_thd); + innobase_srv_conc_exit_innodb( + m_prebuilt); /* jump straight to func exit over * later wsrep hooks */ goto func_exit; @@ -8179,10 +8185,14 @@ report_error: #ifdef WITH_WSREP if (!error_result && wsrep_on(m_user_thd) - && wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE + && wsrep_thd_is_local(m_user_thd) && !wsrep_consistency_check(m_user_thd) - && !wsrep_thd_ignore_table(m_user_thd)) { - if (wsrep_append_keys(m_user_thd, false, record, NULL)) { + && (thd_sql_command(m_user_thd) != SQLCOM_CREATE_TABLE) + && (thd_sql_command(m_user_thd) != SQLCOM_LOAD || + thd_binlog_format(m_user_thd) == BINLOG_FORMAT_ROW)) { + if (wsrep_append_keys(m_user_thd, WSREP_SERVICE_KEY_EXCLUSIVE, + record, + NULL)) { DBUG_PRINT("wsrep", ("row key failed")); error_result = HA_ERR_INTERNAL_ERROR; goto wsrep_error; @@ -8868,13 +8878,17 @@ func_exit: innobase_active_small(); #ifdef WITH_WSREP - if (error == DB_SUCCESS && - wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE && - wsrep_on(m_user_thd) && - !wsrep_thd_ignore_table(m_user_thd)) { + if (error == DB_SUCCESS + && wsrep_on(m_user_thd) + && wsrep_thd_is_local(m_user_thd)) { + DBUG_PRINT("wsrep", ("update row key")); - if (wsrep_append_keys(m_user_thd, false, old_row, new_row)) { + if (wsrep_append_keys(m_user_thd, + wsrep_protocol_version >= 4 + ? WSREP_SERVICE_KEY_UPDATE + : WSREP_SERVICE_KEY_EXCLUSIVE, + old_row, new_row)){ WSREP_DEBUG("WSREP: UPDATE_ROW_KEY FAILED"); DBUG_PRINT("wsrep", ("row key failed")); err = HA_ERR_INTERNAL_ERROR; @@ -8934,11 +8948,14 @@ ha_innobase::delete_row( innobase_active_small(); #ifdef WITH_WSREP - if (error == DB_SUCCESS && - wsrep_thd_exec_mode(m_user_thd) == LOCAL_STATE && - wsrep_on(m_user_thd) && - !wsrep_thd_ignore_table(m_user_thd)) { - if (wsrep_append_keys(m_user_thd, false, record, NULL)) { + if (error == DB_SUCCESS + && wsrep_on(m_user_thd) + && wsrep_thd_is_local(m_user_thd) + && !wsrep_thd_ignore_table(m_user_thd)) { + + if (wsrep_append_keys(m_user_thd, WSREP_SERVICE_KEY_EXCLUSIVE, + record, + NULL)) { DBUG_PRINT("wsrep", ("delete fail")); error = (dberr_t) HA_ERR_INTERNAL_ERROR; goto wsrep_error; @@ -10121,6 +10138,22 @@ wsrep_dict_foreign_find_index( ibool check_charsets, ulint check_null); +inline +const char* +wsrep_key_type_to_str(Wsrep_service_key_type type) +{ + switch (type) { + case WSREP_SERVICE_KEY_SHARED: + return "shared"; + case WSREP_SERVICE_KEY_REFERENCE: + return "reference"; + case WSREP_SERVICE_KEY_UPDATE: + return "update"; + case WSREP_SERVICE_KEY_EXCLUSIVE: + return "exclusive"; + }; + return "unknown"; +} extern dberr_t wsrep_append_foreign_key( @@ -10130,17 +10163,17 @@ wsrep_append_foreign_key( const rec_t* rec, /*!<in: clustered index record */ dict_index_t* index, /*!<in: clustered index */ ibool referenced, /*!<in: is check for referenced table */ - ibool shared) /*!<in: is shared access */ + Wsrep_service_key_type key_type) /*!< in: access type of this key + (shared, exclusive, reference...) */ { ut_a(trx); THD* thd = (THD*)trx->mysql_thd; ulint rcode = DB_SUCCESS; char cache_key[513] = {'\0'}; int cache_key_len=0; - bool const copy = true; if (!wsrep_on(trx->mysql_thd) || - wsrep_thd_exec_mode(thd) != LOCAL_STATE) { + wsrep_thd_is_local(trx->mysql_thd) == false) { return DB_SUCCESS; } @@ -10230,8 +10263,8 @@ wsrep_append_foreign_key( if (rcode != DB_SUCCESS) { WSREP_ERROR( "FK key set failed: " ULINTPF - " (" ULINTPF " " ULINTPF "), index: %s %s, %s", - rcode, referenced, shared, + " (" ULINTPF "%s), index: %s %s, %s", + rcode, referenced, wsrep_key_type_to_str(key_type), (index) ? index->name() : "void index", (index && index->table) ? index->table->name.m_name : "void table", @@ -10250,7 +10283,7 @@ wsrep_append_foreign_key( #ifdef WSREP_DEBUG_PRINT ulint j; fprintf(stderr, "FK parent key, table: %s %s len: %lu ", - cache_key, (shared) ? "shared" : "exclusive", len+1); + cache_key, wsrep_key_type_to_str(key_type), len+1); for (j=0; j<len+1; j++) { fprintf(stderr, " %hhX, ", key[j]); } @@ -10269,7 +10302,8 @@ wsrep_append_foreign_key( wsrep_buf_t wkey_part[3]; wsrep_key_t wkey = {wkey_part, 3}; - if (!wsrep_prepare_key( + if (!wsrep_prepare_key_for_innodb( + thd, (const uchar*)cache_key, cache_key_len + 1, (const uchar*)key, len+1, @@ -10280,17 +10314,7 @@ wsrep_append_foreign_key( wsrep_thd_query(thd) : "void"); return DB_ERROR; } - - wsrep_t *wsrep= get_wsrep(); - - rcode = (int)wsrep->append_key( - wsrep, - wsrep_ws_handle(thd, trx), - &wkey, - 1, - shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE, - copy); - + rcode = wsrep_thd_append_key(thd, &wkey, 1, key_type); if (rcode) { DBUG_PRINT("wsrep", ("row key failed: " ULINTPF, rcode)); WSREP_ERROR("Appending cascaded fk row key failed: %s, " @@ -10311,16 +10335,19 @@ wsrep_append_key( TABLE_SHARE *table_share, const char* key, uint16_t key_len, - bool shared + Wsrep_service_key_type key_type /*!< in: access type of this key + (shared, exclusive, semi...) */ ) { DBUG_ENTER("wsrep_append_key"); - bool const copy = true; + DBUG_PRINT("enter", + ("thd: %lu trx: %lld", thd_get_thread_id(thd), + (long long)trx->id)); #ifdef WSREP_DEBUG_PRINT - fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s\n Query: %s ", - (shared) ? "Shared" : "Exclusive", - thd_get_thread_id(thd), (long long)trx->id, key_len, - table_share->table_name.str, wsrep_thd_query(thd)); + fprintf(stderr, "%s conn %lu, trx " TRX_ID_FMT ", keylen %d, key %s.%s\n", + wsrep_key_type_to_str(key_type), + thd_get_thread_id(thd), trx->id, key_len, + table_share->table_name.str, key); for (int i=0; i<key_len; i++) { fprintf(stderr, "%hhX, ", key[i]); } @@ -10329,7 +10356,8 @@ wsrep_append_key( wsrep_buf_t wkey_part[3]; wsrep_key_t wkey = {wkey_part, 3}; - if (!wsrep_prepare_key( + if (!wsrep_prepare_key_for_innodb( + thd, (const uchar*)table_share->table_cache_key.str, table_share->table_cache_key.length, (const uchar*)key, key_len, @@ -10341,15 +10369,7 @@ wsrep_append_key( DBUG_RETURN(HA_ERR_INTERNAL_ERROR); } - wsrep_t *wsrep= get_wsrep(); - - int rcode = (int)wsrep->append_key( - wsrep, - wsrep_ws_handle(thd, trx), - &wkey, - 1, - shared ? WSREP_KEY_SHARED : WSREP_KEY_EXCLUSIVE, - copy); + int rcode = wsrep_thd_append_key(thd, &wkey, 1, key_type); if (rcode) { DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); WSREP_WARN("Appending row key failed: %s, %d", @@ -10390,16 +10410,30 @@ int ha_innobase::wsrep_append_keys( /*===========================*/ THD *thd, - bool shared, + Wsrep_service_key_type key_type, /*!< in: access type of this row + operation: + (shared, exclusive, reference...) */ const uchar* record0, /* in: row in MySQL format */ const uchar* record1) /* in: row in MySQL format */ { + /* Sanity check: newly inserted records should always be passed with + EXCLUSIVE key type, all the rest are expected to carry a pre-image + */ + ut_a(record1 != NULL || key_type == WSREP_SERVICE_KEY_EXCLUSIVE); + int rcode; DBUG_ENTER("wsrep_append_keys"); bool key_appended = false; trx_t *trx = thd_to_trx(thd); +#ifdef WSREP_DEBUG_PRINT + fprintf(stderr, "%s conn %lu, trx " TRX_ID_FMT ", table %s\nSQL: %s\n", + wsrep_key_type_to_str(key_type), + thd_get_thread_id(thd), trx->id, + table_share->table_name.str, wsrep_thd_query(thd)); +#endif + if (table_share && table_share->tmp_table != NO_TMP_TABLE) { WSREP_DEBUG("skipping tmp table DML: THD: %lu tmp: %d SQL: %s", thd_get_thread_id(thd), @@ -10422,7 +10456,7 @@ ha_innobase::wsrep_append_keys( if (!is_null) { rcode = wsrep_append_key( thd, trx, table_share, keyval, - len, shared); + len, key_type); if (rcode) { DBUG_RETURN(rcode); @@ -10440,68 +10474,91 @@ ha_innobase::wsrep_append_keys( KEY* key_info = table->key_info + i; if (key_info->flags & HA_NOSAME) { hasPK = true; + break; } } for (i=0; i<table->s->keys; ++i) { - uint len; - char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; - char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; - char* key0 = &keyval0[1]; - char* key1 = &keyval1[1]; KEY* key_info = table->key_info + i; - ibool is_null; dict_index_t* idx = innobase_get_index(i); dict_table_t* tab = (idx) ? idx->table : NULL; + /* keyval[] shall contain an ordinal number at byte 0 + and the actual key data shall be written at byte 1. + Hence the total data length is the key length + 1 */ + char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; + char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; keyval0[0] = (char)i; keyval1[0] = (char)i; + char* key0 = &keyval0[1]; + char* key1 = &keyval1[1]; if (!tab) { WSREP_WARN("MariaDB-InnoDB key mismatch %s %s", table->s->table_name.str, key_info->name.str); } - /* !hasPK == table with no PK, must append all non-unique keys */ + /* !hasPK == table with no PK, + must append all non-unique keys */ if (!hasPK || key_info->flags & HA_NOSAME || ((tab && referenced_by_foreign_key2(tab, idx)) || (!tab && referenced_by_foreign_key()))) { - len = wsrep_store_key_val_for_row( + ibool is_null0; + uint len0 = wsrep_store_key_val_for_row( thd, table, i, key0, WSREP_MAX_SUPPORTED_KEY_LENGTH, - record0, &is_null); - if (!is_null) { - rcode = wsrep_append_key( - thd, trx, table_share, - keyval0, len+1, shared); - - if (rcode) { - DBUG_RETURN(rcode); - } - - if (key_info->flags & HA_NOSAME || shared) - key_appended = true; - } else { - WSREP_DEBUG("NULL key skipped: %s", - wsrep_thd_query(thd)); - } + record0, &is_null0); if (record1) { - len = wsrep_store_key_val_for_row( + ibool is_null1; + uint len1 = wsrep_store_key_val_for_row( thd, table, i, key1, WSREP_MAX_SUPPORTED_KEY_LENGTH, - record1, &is_null); + record1, &is_null1); + + if (is_null0 != is_null1 || + len0 != len1 || + memcmp(key0, key1, len0)) { + /* This key has chaged. If it + is unique, this is an exclusive + operation -> upgrade key type */ + if (key_info->flags & HA_NOSAME) { + key_type = WSREP_SERVICE_KEY_EXCLUSIVE; + } - if (!is_null && memcmp(key0, key1, len)) { - rcode = wsrep_append_key( + if (!is_null1) { + rcode = wsrep_append_key( thd, trx, table_share, - keyval1, len+1, shared); - if (rcode) DBUG_RETURN(rcode); + keyval1, + /* for len1+1 see keyval1 + initialization comment */ + len1+1, key_type); + if (rcode) + DBUG_RETURN(rcode); + } } } + + if (!is_null0) { + rcode = wsrep_append_key( + thd, trx, table_share, + /* for len0+1 see keyval0 + initialization comment */ + keyval0, len0+1, key_type); + if (rcode) + DBUG_RETURN(rcode); + + if (key_info->flags & HA_NOSAME || + key_type == WSREP_SERVICE_KEY_SHARED|| + key_type == WSREP_SERVICE_KEY_REFERENCE) + key_appended = true; + } else { + WSREP_DEBUG("NULL key skipped: %s", + wsrep_thd_query(thd)); + } } } } @@ -10515,7 +10572,7 @@ ha_innobase::wsrep_append_keys( if ((rcode = wsrep_append_key(thd, trx, table_share, (const char*) digest, 16, - shared))) { + key_type))) { DBUG_RETURN(rcode); } @@ -10524,7 +10581,7 @@ ha_innobase::wsrep_append_keys( digest, record1, table, m_prebuilt); if ((rcode = wsrep_append_key(thd, trx, table_share, (const char*) digest, - 16, shared))) { + 16, key_type))) { DBUG_RETURN(rcode); } } @@ -15405,8 +15462,7 @@ ha_innobase::external_lock( if (!skip) { #ifdef WITH_WSREP - if (!wsrep_on(thd) || wsrep_thd_exec_mode(thd) == LOCAL_STATE) - { + if (!wsrep_on(thd) || wsrep_thd_is_local(m_user_thd)) { #endif /* WITH_WSREP */ my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0), " InnoDB is limited to row-logging when" @@ -16920,6 +16976,14 @@ innobase_rollback_by_xid( } if (trx_t* trx = trx_get_trx_by_xid(xid)) { +#ifdef WITH_WSREP + /* If a wsrep transaction is being rolled back during + the recovery, we must clear the xid in order to avoid + writing serialisation history for rolled back transaction. */ + if (wsrep_is_wsrep_xid(trx->xid)) { + trx->xid->null(); + } +#endif /* WITH_WSREP */ int ret = innobase_rollback_trx(trx); trx_deregister_from_2pc(trx); ut_ad(!trx->will_lock); @@ -18520,123 +18584,32 @@ wsrep_innobase_kill_one_trx( bf_trx ? bf_trx->id : 0); DBUG_RETURN(1); } - WSREP_LOG_CONFLICT(bf_thd, thd, TRUE); - + wsrep_thd_LOCK(thd); WSREP_DEBUG("BF kill (" ULINTPF ", seqno: " INT64PF "), victim: (%lu) trx: " TRX_ID_FMT, signal, bf_seqno, thd_get_thread_id(thd), victim_trx->id); - WSREP_DEBUG("Aborting query: %s conf %d trx: %" PRId64, + WSREP_DEBUG("Aborting query: %s conf %s trx: %lld", (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void", - wsrep_thd_conflict_state(thd, FALSE), - wsrep_thd_ws_handle(thd)->trx_id); - - wsrep_thd_LOCK(thd); - DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock", - { - const char act[]= - "now " - "wait_for signal.wsrep_after_BF_victim_lock"; - DBUG_ASSERT(!debug_sync_set_action(bf_thd, - STRING_WITH_LEN(act))); - };); - - - if (wsrep_thd_query_state(thd) == QUERY_EXITING) { - WSREP_DEBUG("kill trx EXITING for " TRX_ID_FMT, - victim_trx->id); - wsrep_thd_UNLOCK(thd); - DBUG_RETURN(0); - } - - if (wsrep_thd_exec_mode(thd) != LOCAL_STATE) { - WSREP_DEBUG("withdraw for BF trx: " TRX_ID_FMT ", state: %d", - victim_trx->id, - wsrep_thd_get_conflict_state(thd)); - } - - switch (wsrep_thd_get_conflict_state(thd)) { - case NO_CONFLICT: - wsrep_thd_set_conflict_state(thd, MUST_ABORT); - break; - case MUST_ABORT: - WSREP_DEBUG("victim " TRX_ID_FMT " in MUST ABORT state", - victim_trx->id); - wsrep_thd_UNLOCK(thd); - wsrep_thd_awake(thd, signal); - DBUG_RETURN(0); - break; - case ABORTED: - case ABORTING: // fall through - default: - WSREP_DEBUG("victim " TRX_ID_FMT " in state %d", - victim_trx->id, wsrep_thd_get_conflict_state(thd)); - wsrep_thd_UNLOCK(thd); - DBUG_RETURN(0); - break; - } - - switch (wsrep_thd_query_state(thd)) { - case QUERY_COMMITTING: - enum wsrep_status rcode; - - WSREP_DEBUG("kill query for: %ld", - thd_get_thread_id(thd)); - WSREP_DEBUG("kill trx QUERY_COMMITTING for " TRX_ID_FMT, - victim_trx->id); - - if (wsrep_thd_exec_mode(thd) == REPL_RECV) { - wsrep_abort_slave_trx(bf_seqno, - wsrep_thd_trx_seqno(thd)); - } else { - wsrep_t *wsrep= get_wsrep(); - rcode = wsrep->abort_pre_commit( - wsrep, bf_seqno, - (wsrep_trx_id_t)wsrep_thd_ws_handle(thd)->trx_id - ); - - switch (rcode) { - case WSREP_WARNING: - WSREP_DEBUG("cancel commit warning: " - TRX_ID_FMT, - victim_trx->id); - wsrep_thd_UNLOCK(thd); - wsrep_thd_awake(thd, signal); - DBUG_RETURN(1); - break; - case WSREP_OK: - break; - default: - WSREP_ERROR( - "cancel commit bad exit: %d " - TRX_ID_FMT, - rcode, victim_trx->id); - /* unable to interrupt, must abort */ - /* note: kill_mysql() will block, if we cannot. - * kill the lock holder first. - */ - abort(); - break; - } - } - wsrep_thd_UNLOCK(thd); - wsrep_thd_awake(thd, signal); - break; - case QUERY_EXEC: - /* it is possible that victim trx is itself waiting for some - * other lock. We need to cancel this waiting - */ - WSREP_DEBUG("kill trx QUERY_EXEC for " TRX_ID_FMT, - victim_trx->id); - - victim_trx->lock.was_chosen_as_deadlock_victim= TRUE; - + wsrep_thd_transaction_state_str(thd), + wsrep_thd_transaction_id(thd)); + + /* + * we mark with was_chosen_as_deadlock_victim transaction, + * which is already marked as BF victim + * lock_sys is held until this vicitm has aborted + */ + victim_trx->lock.was_chosen_as_wsrep_victim = TRUE; + + wsrep_thd_UNLOCK(thd); + if (wsrep_thd_bf_abort(bf_thd, thd, signal)) + { if (victim_trx->lock.wait_lock) { - WSREP_DEBUG("victim has wait flag: %ld", - thd_get_thread_id(thd)); + WSREP_DEBUG("victim has wait flag: %lu", + thd_get_thread_id(thd)); lock_t* wait_lock = victim_trx->lock.wait_lock; if (wait_lock) { @@ -18644,67 +18617,7 @@ wsrep_innobase_kill_one_trx( victim_trx->lock.was_chosen_as_deadlock_victim= TRUE; lock_cancel_waiting_and_release(wait_lock); } - - wsrep_thd_UNLOCK(thd); - wsrep_thd_awake(thd, signal); - } else { - /* abort currently executing query */ - DBUG_PRINT("wsrep",("sending KILL_QUERY to: %lu", - thd_get_thread_id(thd))); - WSREP_DEBUG("kill query for: %ld", - thd_get_thread_id(thd)); - /* Note that innobase_kill_query will take lock_mutex - and trx_mutex */ - wsrep_thd_UNLOCK(thd); - wsrep_thd_awake(thd, signal); - - /* for BF thd, we need to prevent him from committing */ - if (wsrep_thd_exec_mode(thd) == REPL_RECV) { - wsrep_abort_slave_trx(bf_seqno, - wsrep_thd_trx_seqno(thd)); - } - } - break; - case QUERY_IDLE: - { - WSREP_DEBUG("kill IDLE for " TRX_ID_FMT, victim_trx->id); - - if (wsrep_thd_exec_mode(thd) == REPL_RECV) { - WSREP_DEBUG("kill BF IDLE, seqno: %lld", - (long long)wsrep_thd_trx_seqno(thd)); - wsrep_thd_UNLOCK(thd); - wsrep_abort_slave_trx(bf_seqno, - wsrep_thd_trx_seqno(thd)); - DBUG_RETURN(0); } - /* This will lock thd from proceeding after net_read() */ - wsrep_thd_set_conflict_state(thd, ABORTING); - - wsrep_lock_rollback(); - - if (wsrep_aborting_thd_contains(thd)) { - WSREP_WARN("duplicate thd aborter %lu", - (ulong) thd_get_thread_id(thd)); - } else { - wsrep_aborting_thd_enqueue(thd); - DBUG_PRINT("wsrep",("enqueuing trx abort for %lu", - thd_get_thread_id(thd))); - WSREP_DEBUG("enqueuing trx abort for (%lu)", - thd_get_thread_id(thd)); - } - - DBUG_PRINT("wsrep",("signalling wsrep rollbacker")); - WSREP_DEBUG("signaling aborter"); - wsrep_unlock_rollback(); - wsrep_thd_UNLOCK(thd); - - break; - } - default: - WSREP_WARN("bad wsrep query state: %d", - wsrep_thd_query_state(thd)); - wsrep_thd_UNLOCK(thd); - break; } DBUG_RETURN(0); @@ -18724,26 +18637,22 @@ wsrep_abort_transaction( trx_t* victim_trx = thd_to_trx(victim_thd); trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL; - WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %d", + WSREP_DEBUG("abort transaction: BF: %s victim: %s victim conf: %s", wsrep_thd_query(bf_thd), wsrep_thd_query(victim_thd), - wsrep_thd_conflict_state(victim_thd, FALSE)); + wsrep_thd_transaction_state_str(victim_thd)); if (victim_trx) { lock_mutex_enter(); trx_mutex_enter(victim_trx); - int rcode = wsrep_innobase_kill_one_trx(bf_thd, bf_trx, - victim_trx, signal); - lock_mutex_exit(); + int rcode= wsrep_innobase_kill_one_trx(bf_thd, bf_trx, + victim_trx, signal); trx_mutex_exit(victim_trx); + lock_mutex_exit(); wsrep_srv_conc_cancel_wait(victim_trx); DBUG_RETURN(rcode); } else { - WSREP_DEBUG("victim does not have transaction"); - wsrep_thd_LOCK(victim_thd); - wsrep_thd_set_conflict_state(victim_thd, MUST_ABORT); - wsrep_thd_UNLOCK(victim_thd); - wsrep_thd_awake(victim_thd, signal); + wsrep_thd_bf_abort(bf_thd, victim_thd, signal); } DBUG_RETURN(-1); @@ -18779,15 +18688,6 @@ innobase_wsrep_get_checkpoint( trx_rseg_read_wsrep_checkpoint(*xid); return 0; } - -static void wsrep_fake_trx_id(handlerton *, THD *thd) -{ - trx_id_t trx_id = trx_sys.get_new_trx_id(); - WSREP_DEBUG("innodb fake trx id: " TRX_ID_FMT " thd: %s", - trx_id, wsrep_thd_query(thd)); - wsrep_ws_handle_for_trx(wsrep_thd_ws_handle(thd), trx_id); -} - #endif /* WITH_WSREP */ /* plugin options */ diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index 6f0c5b535fb..71212785df4 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -16,6 +16,10 @@ this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ +#ifdef WITH_WSREP +#include "wsrep_api.h" +#include <mysql/service_wsrep.h> +#endif /* WITH_WSREP */ /* The InnoDB handler: the interface between MySQL and InnoDB. */ @@ -444,8 +448,11 @@ protected: dict_index_t* innobase_get_index(uint keynr); #ifdef WITH_WSREP - int wsrep_append_keys(THD *thd, bool shared, - const uchar* record0, const uchar* record1); + int wsrep_append_keys( + THD *thd, + Wsrep_service_key_type key_type, + const uchar* record0, + const uchar* record1); #endif /** Builds a 'template' to the prebuilt struct. @@ -571,23 +578,7 @@ thd_get_work_part_info( struct trx_t; #ifdef WITH_WSREP #include <mysql/service_wsrep.h> -//extern "C" int wsrep_trx_order_before(void *thd1, void *thd2); - -extern "C" bool wsrep_thd_is_wsrep_on(THD *thd); - - -extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode); -extern "C" void wsrep_thd_set_query_state( - THD *thd, enum wsrep_query_state state); - -extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id); - -extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd); -extern "C" time_t wsrep_thd_query_start(THD *thd); -extern "C" query_id_t wsrep_thd_query_id(THD *thd); -extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); -extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); -#endif +#endif /* WITH_WSREP */ extern const struct _ft_vft ft_vft_result; @@ -621,10 +612,6 @@ innobase_index_name_is_reserved( be created. */ MY_ATTRIBUTE((nonnull(1), warn_unused_result)); -#ifdef WITH_WSREP -//extern "C" int wsrep_trx_is_aborting(void *thd_ptr); -#endif - /** Parse hint for table and its indexes, and update the information in dictionary. @param[in] thd Connection thread diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 34d61100a9b..8bf64c28441 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -577,6 +577,11 @@ struct trx_lock_t { lock_sys.mutex. Otherwise, this may only be modified by the thread that is serving the running transaction. */ +#ifdef WITH_WSREP + bool was_chosen_as_wsrep_victim; + /*!< high priority wsrep thread has + marked this trx to abort */ +#endif /* WITH_WSREP */ /** Pre-allocated record locks */ struct { diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 7fc986bdbca..493f73cc148 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -762,9 +762,7 @@ lock_rec_has_to_wait( << wsrep_thd_query(lock2->trx->mysql_thd); } - if (wsrep_trx_order_before(trx->mysql_thd, - lock2->trx->mysql_thd) - && (type_mode & LOCK_MODE_MASK) == LOCK_X + if ((type_mode & LOCK_MODE_MASK) == LOCK_X && (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) { if (for_locking || wsrep_debug) { /* exclusive lock conflicts are not @@ -774,12 +772,11 @@ lock_rec_has_to_wait( << type_mode << " supremum: " << lock_is_on_supremum << "conflicts states: my " - << wsrep_thd_conflict_state( - trx->mysql_thd, FALSE) + << wsrep_thd_transaction_state_str( + trx->mysql_thd) << " locked " - << wsrep_thd_conflict_state( - lock2->trx->mysql_thd, - FALSE); + << wsrep_thd_transaction_state_str( + lock2->trx->mysql_thd); lock_rec_print(stderr, lock2); ib::info() << " SQL1: " << wsrep_thd_query(trx->mysql_thd) @@ -1098,11 +1095,14 @@ wsrep_kill_victim( return; } - my_bool bf_this = wsrep_thd_is_BF(trx->mysql_thd, FALSE); + if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + return; + } + my_bool bf_other = wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE); - if ((bf_this && !bf_other) || - (bf_this && bf_other && wsrep_trx_order_before( + if ((!bf_other) || + (wsrep_thd_order_before( trx->mysql_thd, lock->trx->mysql_thd))) { if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { @@ -1113,11 +1113,7 @@ wsrep_kill_victim( is in the queue*/ } else if (lock->trx != trx) { if (wsrep_log_conflicts) { - if (bf_this) { - ib::info() << "*** Priority TRANSACTION:"; - } else { - ib::info() << "*** Victim TRANSACTION:"; - } + ib::info() << "*** Priority TRANSACTION:"; trx_print_latched(stderr, trx, 3000); @@ -1426,7 +1422,7 @@ lock_rec_create_low( lock_t *prev = NULL; while (hash && wsrep_thd_is_BF(hash->trx->mysql_thd, TRUE) - && wsrep_trx_order_before(hash->trx->mysql_thd, + && wsrep_thd_order_before(hash->trx->mysql_thd, trx->mysql_thd)) { prev = hash; hash = (lock_t *)hash->hash; @@ -1840,15 +1836,15 @@ lock_rec_add_to_queue( ib::info() << "WSREP BF lock conflict for my lock:\n BF:" << ((wsrep_thd_is_BF(trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_exec_mode(trx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(trx->mysql_thd, false) << " seqno: " << + wsrep_thd_client_state_str(trx->mysql_thd) << " conflict: " << + wsrep_thd_transaction_state_str(trx->mysql_thd) << " seqno: " << wsrep_thd_trx_seqno(trx->mysql_thd) << " SQL: " << wsrep_thd_query(trx->mysql_thd); trx_t* otrx = other_lock->trx; ib::info() << "WSREP other lock:\n BF:" << ((wsrep_thd_is_BF(otrx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_exec_mode(otrx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(otrx->mysql_thd, false) << " seqno: " << + wsrep_thd_client_state_str(otrx->mysql_thd) << " conflict: " << + wsrep_thd_transaction_state_str(otrx->mysql_thd) << " seqno: " << wsrep_thd_trx_seqno(otrx->mysql_thd) << " SQL: " << wsrep_thd_query(otrx->mysql_thd); } @@ -4949,8 +4945,8 @@ lock_rec_queue_validate( if (!lock_get_wait(other_lock) ) { ib::info() << "WSREP impl BF lock conflict for my impl lock:\n BF:" << ((wsrep_thd_is_BF(impl_trx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_exec_mode(impl_trx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(impl_trx->mysql_thd, false) << " seqno: " << + wsrep_thd_client_state_str(impl_trx->mysql_thd) << " conflict: " << + wsrep_thd_transaction_state_str(impl_trx->mysql_thd) << " seqno: " << wsrep_thd_trx_seqno(impl_trx->mysql_thd) << " SQL: " << wsrep_thd_query(impl_trx->mysql_thd); @@ -4958,8 +4954,8 @@ lock_rec_queue_validate( ib::info() << "WSREP other lock:\n BF:" << ((wsrep_thd_is_BF(otrx->mysql_thd, FALSE)) ? "BF" : "normal") << " exec: " << - wsrep_thd_exec_mode(otrx->mysql_thd) << " conflict: " << - wsrep_thd_conflict_state(otrx->mysql_thd, false) << " seqno: " << + wsrep_thd_client_state_str(otrx->mysql_thd) << " conflict: " << + wsrep_thd_transaction_state_str(otrx->mysql_thd) << " seqno: " << wsrep_thd_trx_seqno(otrx->mysql_thd) << " SQL: " << wsrep_thd_query(otrx->mysql_thd); } @@ -6395,6 +6391,12 @@ lock_trx_handle_wait( /*=================*/ trx_t* trx) /*!< in/out: trx lock state */ { +#ifdef WITH_WSREP + /* We already own mutexes */ + if (trx->lock.was_chosen_as_wsrep_victim) { + return lock_trx_handle_wait_low(trx); + } +#endif /* WITH_WSREP */ lock_mutex_enter(); trx_mutex_enter(trx); dberr_t err = lock_trx_handle_wait_low(trx); @@ -6992,6 +6994,9 @@ DeadlockChecker::trx_rollback() trx_t* trx = m_wait_lock->trx; print("*** WE ROLL BACK TRANSACTION (1)\n"); +#ifdef WITH_WSREP + wsrep_handle_SR_rollback(m_start->mysql_thd, trx->mysql_thd); +#endif trx_mutex_enter(trx); diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index e2ac60c1103..ed72f6d482b 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -44,6 +44,9 @@ Created 4/20/1996 Heikki Tuuri #include "buf0lru.h" #include "fts0fts.h" #include "fts0types.h" +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /* WITH_WSREP */ /************************************************************************* IMPORTANT NOTE: Any operation that generates redo MUST check that there @@ -1043,7 +1046,7 @@ dberr_t wsrep_append_foreign_key(trx_t *trx, const rec_t* clust_rec, dict_index_t* clust_index, ibool referenced, - ibool shared); + Wsrep_service_key_type key_type); #endif /* WITH_WSREP */ /*********************************************************************//** @@ -1430,7 +1433,7 @@ row_ins_foreign_check_on_constraint( #ifdef WITH_WSREP err = wsrep_append_foreign_key(trx, foreign, clust_rec, clust_index, - FALSE, FALSE); + FALSE, WSREP_SERVICE_KEY_EXCLUSIVE); if (err != DB_SUCCESS) { fprintf(stderr, "WSREP: foreign key append failed: %d\n", err); @@ -1811,7 +1814,10 @@ row_ins_check_foreign_constraint( rec, check_index, check_ref, - (upd_node) ? TRUE : FALSE); + (upd_node != NULL + && wsrep_protocol_version < 4) + ? WSREP_SERVICE_KEY_SHARED + : WSREP_SERVICE_KEY_REFERENCE); #endif /* WITH_WSREP */ goto end_scan; } else if (foreign->type != 0) { @@ -3228,9 +3234,27 @@ row_ins_clust_index_entry( n_uniq = dict_index_is_unique(index) ? index->n_uniq : 0; +#ifdef WITH_WSREP + const bool skip_locking + = wsrep_thd_skip_locking(thr_get_trx(thr)->mysql_thd); + ulint flags = index->table->no_rollback() ? BTR_NO_ROLLBACK + : (index->table->is_temporary() || skip_locking) + ? BTR_NO_LOCKING_FLAG : 0; +#ifdef UNIV_DEBUG + if (skip_locking && strcmp(wsrep_get_sr_table_name(), + index->table->name.m_name)) { + WSREP_ERROR("Record locking is disabled in this thread, " + "but the table being modified is not " + "`%s`: `%s`.", wsrep_get_sr_table_name(), + index->table->name.m_name); + ut_error; + } +#endif /* UNIV_DEBUG */ +#else ulint flags = index->table->no_rollback() ? BTR_NO_ROLLBACK : index->table->is_temporary() ? BTR_NO_LOCKING_FLAG : 0; +#endif /* WITH_WSREP */ const ulint orig_n_fields = entry->n_fields; /* Try first optimistic descent to the B-tree */ diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 658785a5c03..8d7824bfc56 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -54,6 +54,9 @@ Created 12/19/1997 Heikki Tuuri #include "buf0lru.h" #include "srv0srv.h" #include "srv0mon.h" +#ifdef WITH_WSREP +#include "mysql/service_wsrep.h" /* For wsrep_thd_skip_locking */ +#endif /* Maximum number of rows to prefetch; MySQL interface has another parameter */ #define SEL_MAX_N_PREFETCH 16 @@ -4442,6 +4445,13 @@ row_search_mvcc( set_also_gap_locks = FALSE; } +#ifdef WITH_WSREP + else if (wsrep_thd_skip_locking(trx->mysql_thd)) { + ut_ad(!strcmp(wsrep_get_sr_table_name(), + prebuilt->table->name.m_name)); + set_also_gap_locks = FALSE; + } +#endif /* WITH_WSREP */ /* Note that if the search mode was GE or G, then the cursor naturally moves upward (in fetch next) in alphabetical order, diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 591ae238c43..a60210c77c8 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -2458,7 +2458,7 @@ row_upd_sec_index_entry( err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) { + if (wsrep_get_debug()) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name; @@ -2773,7 +2773,7 @@ check_fk: err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) { + if (wsrep_get_debug()) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name; @@ -3002,7 +3002,7 @@ row_upd_del_mark_clust_rec( err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) { + if (wsrep_get_debug()) { ib::warn() << "WSREP: sec index FK check fail for deadlock" << " index " << index->name << " table " << index->table->name; diff --git a/storage/innobase/srv/srv0conc.cc b/storage/innobase/srv/srv0conc.cc index 6beeee58fae..b2b464e31fa 100644 --- a/storage/innobase/srv/srv0conc.cc +++ b/storage/innobase/srv/srv0conc.cc @@ -119,8 +119,8 @@ srv_conc_enter_innodb_with_atomics( ulint sleep_in_us; #ifdef WITH_WSREP if (wsrep_on(trx->mysql_thd) && - wsrep_trx_is_aborting(trx->mysql_thd)) { - if (wsrep_debug) { + wsrep_thd_is_aborting(trx->mysql_thd)) { + if (wsrep_get_debug()) { ib::info() << "srv_conc_enter due to MUST_ABORT"; } @@ -308,14 +308,14 @@ wsrep_srv_conc_cancel_wait( srv_conc_enter_innodb_with_atomics(). No need to cancel here, thr will wake up after os_sleep and let to enter innodb */ - if (wsrep_debug) { + if (wsrep_get_debug()) { ib::info() << "WSREP: conc slot cancel, no atomics"; } #else // JAN: TODO: MySQL 5.7 //os_fast_mutex_lock(&srv_conc_mutex); if (trx->wsrep_event) { - if (wsrep_debug) { + if (wsrep_get_debug()) { ib::info() << "WSREP: conc slot cancel"; } os_event_set(trx->wsrep_event); diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 890bd969670..3b5461aae25 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -76,10 +76,6 @@ Created 10/8/1995 Heikki Tuuri #include <my_service_manager.h> -#ifdef WITH_WSREP -extern int wsrep_debug; -extern int wsrep_trx_is_aborting(void *thd_ptr); -#endif /* The following is the maximum allowed duration of a lock wait. */ UNIV_INTERN ulong srv_fatal_semaphore_wait_threshold = DEFAULT_SRV_FATAL_SEMAPHORE_TIMEOUT; diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 54b0e75fd80..e15afcf9cd7 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2328,7 +2328,7 @@ files_checked: Create the dump/load thread only when not running with --wsrep-recover. */ - if (!wsrep_recovery) { + if (!get_wsrep_recovery()) { #endif /* WITH_WSREP */ /* Create the buffer pool dump/load thread */ diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index 4b0684d1735..22b72a14304 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -178,6 +178,11 @@ trx_rollback_to_savepoint( partial rollback requested, or NULL for complete rollback */ { +#ifdef WITH_WSREP + if (savept == NULL && wsrep_on(trx->mysql_thd)) { + wsrep_handle_SR_rollback(NULL, trx->mysql_thd); + } +#endif /* WITH_WSREP */ ut_ad(!trx_mutex_own(trx)); trx_start_if_not_started_xa(trx, true); @@ -446,12 +451,8 @@ trx_rollback_to_savepoint_for_mysql_low( trx_mark_sql_stat_end(trx); trx->op_info = ""; - #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - trx->lock.was_chosen_as_deadlock_victim) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } + trx->lock.was_chosen_as_wsrep_victim = FALSE; #endif return(err); } diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc index f0793140277..239df440c2b 100644 --- a/storage/innobase/trx/trx0rseg.cc +++ b/storage/innobase/trx/trx0rseg.cc @@ -43,6 +43,33 @@ static long long wsrep_seqno = -1; /** The latest known WSREP XID UUID */ static unsigned char wsrep_uuid[16]; +/** Write the WSREP XID information into rollback segment header. +@param[in,out] rseg_header rollback segment header +@param[in] xid WSREP XID +@param[in,out] mtr mini transaction */ +static void +trx_rseg_write_wsrep_checkpoint( + trx_rsegf_t* rseg_header, + const XID* xid, + mtr_t* mtr) +{ + mlog_write_ulint(TRX_RSEG_WSREP_XID_FORMAT + rseg_header, + uint32_t(xid->formatID), + MLOG_4BYTES, mtr); + + mlog_write_ulint(TRX_RSEG_WSREP_XID_GTRID_LEN + rseg_header, + uint32_t(xid->gtrid_length), + MLOG_4BYTES, mtr); + + mlog_write_ulint(TRX_RSEG_WSREP_XID_BQUAL_LEN + rseg_header, + uint32_t(xid->bqual_length), + MLOG_4BYTES, mtr); + + mlog_write_string(TRX_RSEG_WSREP_XID_DATA + rseg_header, + reinterpret_cast<const byte*>(xid->data), + XIDDATASIZE, mtr); +} + /** Update the WSREP XID information in rollback segment header. @param[in,out] rseg_header rollback segment header @param[in] xid WSREP XID @@ -60,29 +87,15 @@ trx_rseg_update_wsrep_checkpoint( long long xid_seqno = wsrep_xid_seqno(xid); const byte* xid_uuid = wsrep_xid_uuid(xid); - if (!memcmp(xid_uuid, wsrep_uuid, sizeof wsrep_uuid)) { + if (xid_seqno != -1 + && !memcmp(xid_uuid, wsrep_uuid, sizeof wsrep_uuid)) { ut_ad(xid_seqno > wsrep_seqno); } else { memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid); } wsrep_seqno = xid_seqno; #endif /* UNIV_DEBUG */ - - mlog_write_ulint(TRX_RSEG_WSREP_XID_FORMAT + rseg_header, - uint32_t(xid->formatID), - MLOG_4BYTES, mtr); - - mlog_write_ulint(TRX_RSEG_WSREP_XID_GTRID_LEN + rseg_header, - uint32_t(xid->gtrid_length), - MLOG_4BYTES, mtr); - - mlog_write_ulint(TRX_RSEG_WSREP_XID_BQUAL_LEN + rseg_header, - uint32_t(xid->bqual_length), - MLOG_4BYTES, mtr); - - mlog_write_string(TRX_RSEG_WSREP_XID_DATA + rseg_header, - reinterpret_cast<const byte*>(xid->data), - XIDDATASIZE, mtr); + trx_rseg_write_wsrep_checkpoint(rseg_header, xid, mtr); } /** Update WSREP checkpoint XID in first rollback segment header @@ -97,6 +110,13 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) mtr_t mtr; mtr.start(); + const byte* xid_uuid = wsrep_xid_uuid(xid); + /* We must make check against wsrep_uuid here, the + trx_rseg_update_wsrep_checkpoint() writes over wsrep_uuid with + xid contents in debug mode and the memcmp() will never give nonzero + result. */ + const bool must_clear_rsegs = memcmp(wsrep_uuid, xid_uuid, + sizeof wsrep_uuid); const trx_rseg_t* rseg = trx_sys.rseg_array[0]; trx_rsegf_t* rseg_header = trx_rsegf_get(rseg->space, rseg->page_no, @@ -107,10 +127,11 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) trx_rseg_update_wsrep_checkpoint(rseg_header, xid, &mtr); - const byte* xid_uuid = wsrep_xid_uuid(xid); - if (memcmp(wsrep_uuid, xid_uuid, sizeof wsrep_uuid)) { + if (must_clear_rsegs) { + XID null_xid; + memset(&null_xid, 0, sizeof null_xid); + null_xid.null(); memcpy(wsrep_uuid, xid_uuid, sizeof wsrep_uuid); - /* Because the UUID part of the WSREP XID differed from current_xid_uuid, the WSREP group UUID was changed, and we must reset the XID in all rollback @@ -118,10 +139,12 @@ void trx_rseg_update_wsrep_checkpoint(const XID* xid) for (ulint rseg_id = 1; rseg_id < TRX_SYS_N_RSEGS; ++rseg_id) { if (const trx_rseg_t* rseg = trx_sys.rseg_array[rseg_id]) { - trx_rseg_update_wsrep_checkpoint( + trx_rseg_write_wsrep_checkpoint( trx_rsegf_get(rseg->space, - rseg->page_no, &mtr), - xid, &mtr); + rseg->page_no, + &mtr), + &null_xid, + &mtr); } } } diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 333c7fe90eb..7be760c6221 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1441,11 +1441,8 @@ trx_commit_in_memory( trx_mutex_enter(trx); trx->dict_operation = TRX_DICT_OP_NONE; - #ifdef WITH_WSREP - if (trx->mysql_thd && wsrep_on(trx->mysql_thd)) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } + trx->lock.was_chosen_as_wsrep_victim = FALSE; #endif DBUG_LOG("trx", "Commit in memory: " << trx); @@ -2155,7 +2152,7 @@ static my_bool trx_get_trx_by_xid_callback(rw_trx_hash_element_t *element, transaction needs a valid trx->xid for invoking trx_sys_update_wsrep_checkpoint(). */ if (!wsrep_is_wsrep_xid(trx->xid)) -#endif +#endif /* WITH_WSREP */ /* Invalidate the XID, so that subsequent calls will not find it. */ trx->xid->null(); arg->trx= trx; |