diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f3b618e6987..9c16a8ea805 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -5555,7 +5555,6 @@ static my_bool have_committing_connections() if (is_committing_connection(tmp)) { - mysql_mutex_unlock(&LOCK_thread_count); return TRUE; } } diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index f24bb2cff93..4a4ecc74d7c 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1200,6 +1200,7 @@ bool Sql_cmd_optimize_table::execute(THD *thd) if (check_table_access(thd, SELECT_ACL | INSERT_ACL, first_table, FALSE, UINT_MAX, FALSE)) goto error; /* purecov: inspected */ + WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL) thd->enable_slow_log= opt_log_slow_admin_statements; res= (specialflag & SPECIAL_NO_NEW_FUNC) ? mysql_recreate_table(thd, first_table, true) : diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 0d1a3ad6ea7..aab655275b2 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1211,6 +1211,9 @@ static void wsrep_copy_query(THD *thd) { thd->wsrep_retry_command = thd->get_command(); thd->wsrep_retry_query_len = thd->query_length(); + if (thd->wsrep_retry_query) { + my_free(thd->wsrep_retry_query); + } thd->wsrep_retry_query = (char *)my_malloc( thd->wsrep_retry_query_len + 1, MYF(0)); strncpy(thd->wsrep_retry_query, thd->query(), thd->wsrep_retry_query_len); @@ -3793,8 +3796,7 @@ end_with_restore_list: if ((res= insert_precheck(thd, all_tables))) break; #ifdef WITH_WSREP - if (lex->sql_command == SQLCOM_INSERT_SELECT && - thd->wsrep_consistency_check == CONSISTENCY_CHECK_DECLARED) + if (thd->wsrep_consistency_check == CONSISTENCY_CHECK_DECLARED) { thd->wsrep_consistency_check = CONSISTENCY_CHECK_RUNNING; WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL); diff --git a/sql/wsrep_mysqld.cc b/sql/wsrep_mysqld.cc index a9344b0a946..79103ae8e71 100644 --- a/sql/wsrep_mysqld.cc +++ b/sql/wsrep_mysqld.cc @@ -132,7 +132,7 @@ static void wsrep_log_cb(wsrep_log_level_t level, const char *msg) { sql_print_error("WSREP: %s", msg); break; case WSREP_LOG_DEBUG: - sql_print_information ("[Debug] WSREP: %s", msg); + if (wsrep_debug) sql_print_information ("[Debug] WSREP: %s", msg); default: break; } @@ -794,10 +794,10 @@ void wsrep_filter_new_cluster (int* argc, char* argv[]) { /* make a copy of the argument to convert possible underscores to hyphens. * the copy need not to be longer than WSREP_NEW_CLUSTER option */ - char arg[sizeof(WSREP_NEW_CLUSTER) + 2]= { 0, }; + char arg[sizeof(WSREP_NEW_CLUSTER) + 1]= { 0, }; strncpy(arg, argv[i], sizeof(arg) - 1); - char* underscore; - while (NULL != (underscore= strchr(arg, '_'))) *underscore= '-'; + char* underscore(arg); + while (NULL != (underscore= strchr(underscore, '_'))) *underscore= '-'; if (!strcmp(arg, WSREP_NEW_CLUSTER)) { @@ -904,7 +904,7 @@ wsrep_causal_wait (THD* thd) switch (ret) { case WSREP_NOT_IMPLEMENTED: - msg= "consistent reads by wsrep backend. " + msg= "synchronous reads by wsrep backend. " "Please unset wsrep_causal_reads variable."; err= ER_NOT_SUPPORTED_YET; break; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a33d9a1d5bb..53679b83d7a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -5642,7 +5642,7 @@ wsrep_innobase_mysql_sort( case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_VARCHAR: { - uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN]; + uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'}; uint tmp_length = REC_VERSION_56_MAX_INDEX_COL_LEN; /* Use the charset number to pick the right charset struct for @@ -5681,11 +5681,11 @@ wsrep_innobase_mysql_sort( } else { /* strnxfrm will expand the destination string, protocols < 3 truncated the sorted sring - protocols > 3 gets full sorted sring + protocols >= 3 gets full sorted sring */ tmp_length = charset->coll->strnxfrm( charset, str, buf_length, - str_length, tmp_str, tmp_length, 0); + str_length, tmp_str, str_length, 0); DBUG_ASSERT(tmp_length <= buf_length); ret_length = tmp_length; } @@ -6228,6 +6228,7 @@ UNIV_INTERN uint wsrep_store_key_val_for_row( /*===============================*/ + THD* thd, TABLE* table, uint keynr, /*!< in: key number */ char* buff, /*!< in/out: buffer for the key value (in MySQL @@ -6242,25 +6243,33 @@ wsrep_store_key_val_for_row( char* buff_start = buff; enum_field_types mysql_type; Field* field; - + uint buff_space = buff_len; + DBUG_ENTER("wsrep_store_key_val_for_row"); memset(buff, 0, buff_len); *key_is_null = TRUE; for (; key_part != end; key_part++) { + uchar sorted[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'}; ibool part_is_null = FALSE; if (key_part->null_bit) { - if (record[key_part->null_offset] & - key_part->null_bit) { - *buff = 1; - part_is_null = TRUE; + if (buff_space > 0) { + if (record[key_part->null_offset] + & key_part->null_bit) { + *buff = 1; + part_is_null = TRUE; + } else { + *buff = 0; + } + buff++; + buff_space--; } else { - *buff = 0; + fprintf (stderr, "WSREP: key truncated: %s\n", + wsrep_thd_query(thd)); } - buff++; } if (!part_is_null) *key_is_null = FALSE; @@ -6280,8 +6289,15 @@ wsrep_store_key_val_for_row( key_len = key_part->length; if (part_is_null) { - buff += key_len + 2; - + true_len = key_len + 2; + if (true_len > buff_space) { + fprintf (stderr, + "WSREP: key truncated: %s\n", + wsrep_thd_query(thd)); + true_len = buff_space; + } + buff += true_len; + buff_space -= true_len; continue; } cs = field->charset(); @@ -6321,13 +6337,20 @@ wsrep_store_key_val_for_row( REC_VERSION_56_MAX_INDEX_COL_LEN); if (wsrep_protocol_version > 1) { - memcpy(buff, sorted, true_len); - /* Note that we always reserve the maximum possible - length of the true VARCHAR in the key value, though - only len first bytes after the 2 length bytes contain - actual data. The rest of the space was reset to zero - in the bzero() call above. */ - buff += true_len; + /* Note that we always reserve the maximum possible + length of the true VARCHAR in the key value, though + only len first bytes after the 2 length bytes contain + actual data. The rest of the space was reset to zero + in the bzero() call above. */ + if (true_len > buff_space) { + fprintf (stderr, + "WSREP: key truncated: %s\n", + wsrep_thd_query(thd)); + true_len = buff_space; + } + memcpy(buff, sorted, true_len); + buff += true_len; + buff_space -= true_len; } else { buff += key_len; } @@ -6351,7 +6374,15 @@ wsrep_store_key_val_for_row( key_len = key_part->length; if (part_is_null) { - buff += key_len + 2; + true_len = key_len + 2; + if (true_len > buff_space) { + fprintf (stderr, + "WSREP: key truncated: %s\n", + wsrep_thd_query(thd)); + true_len = buff_space; + } + buff += true_len; + buff_space -= true_len; continue; } @@ -6394,15 +6425,22 @@ wsrep_store_key_val_for_row( mysql_type, cs->number, sorted, true_len, REC_VERSION_56_MAX_INDEX_COL_LEN); - memcpy(buff, sorted, true_len); /* Note that we always reserve the maximum possible length of the BLOB prefix in the key value. */ if (wsrep_protocol_version > 1) { - buff += true_len; - } else { - buff += key_len; - } + if (true_len > buff_space) { + fprintf (stderr, + "WSREP: key truncated: %s\n", + wsrep_thd_query(thd)); + true_len = buff_space; + } + buff += true_len; + buff_space -= true_len; + } else { + buff += key_len; + } + memcpy(buff, sorted, true_len); } else { /* Here we handle all other data types except the true VARCHAR, BLOB and TEXT. Note that the column @@ -6419,9 +6457,17 @@ wsrep_store_key_val_for_row( key_len = key_part->length; if (part_is_null) { - buff += key_len; + true_len = key_len; + if (true_len > buff_space) { + fprintf (stderr, + "WSREP: key truncated: %s\n", + wsrep_thd_query(thd)); + true_len = buff_space; + } + buff += true_len; + buff_space -= true_len; - continue; + continue; } src_start = record + key_part->offset; @@ -6459,12 +6505,18 @@ wsrep_store_key_val_for_row( mysql_type, cs->number, sorted, true_len, REC_VERSION_56_MAX_INDEX_COL_LEN); + if (true_len > buff_space) { + fprintf (stderr, + "WSREP: key truncated: %s\n", + wsrep_thd_query(thd)); + true_len = buff_space; + } memcpy(buff, sorted, true_len); } else { memcpy(buff, src_start, true_len); } - buff += true_len; - + buff += true_len; + buff_space -= true_len; } } @@ -9690,7 +9742,8 @@ ha_innobase::wsrep_append_keys( ibool is_null; len = wsrep_store_key_val_for_row( - table, 0, key, key_info->key_length, record0, &is_null); + thd, table, 0, key, WSREP_MAX_SUPPORTED_KEY_LENGTH, + record0, &is_null); if (!is_null) { rcode = wsrep_append_key( @@ -9712,9 +9765,6 @@ ha_innobase::wsrep_append_keys( KEY* key_info = table->key_info + i; if (key_info->flags & HA_NOSAME) { hasPK = true; - if (i != table->s->primary_key) { - wsrep_thd_set_PA_safe(thd, FALSE); - } } } @@ -9745,7 +9795,8 @@ ha_innobase::wsrep_append_keys( (!tab && referenced_by_foreign_key()))) { len = wsrep_store_key_val_for_row( - table, i, key0, key_info->key_length, + thd, table, i, key0, + WSREP_MAX_SUPPORTED_KEY_LENGTH, record0, &is_null); if (!is_null) { rcode = wsrep_append_key( @@ -9755,7 +9806,6 @@ ha_innobase::wsrep_append_keys( if (key_info->flags & HA_NOSAME || shared) key_appended = true; - } else { @@ -9764,7 +9814,8 @@ ha_innobase::wsrep_append_keys( } if (record1) { len = wsrep_store_key_val_for_row( - table, i, key1, key_info->key_length, + thd, table, i, key1, + WSREP_MAX_SUPPORTED_KEY_LENGTH, record1, &is_null); if (!is_null && memcmp(key0, key1, len)) { rcode = wsrep_append_key( diff --git a/storage/innobase/include/hash0hash.h b/storage/innobase/include/hash0hash.h index 6f9a628df5d..9a4077befb1 100644 --- a/storage/innobase/include/hash0hash.h +++ b/storage/innobase/include/hash0hash.h @@ -144,6 +144,33 @@ do {\ }\ } while (0) +#ifdef WITH_WSREP +/*******************************************************************//** +Inserts a struct to the head of hash table. */ + +#define HASH_PREPEND(TYPE, NAME, TABLE, FOLD, DATA) \ +do { \ + hash_cell_t* cell3333; \ + TYPE* struct3333; \ + \ + HASH_ASSERT_OWN(TABLE, FOLD) \ + \ + (DATA)->NAME = NULL; \ + \ + cell3333 = hash_get_nth_cell(TABLE, hash_calc_hash(FOLD, TABLE));\ + \ + if (cell3333->node == NULL) { \ + cell3333->node = DATA; \ + DATA->NAME = NULL; \ + } else { \ + struct3333 = (TYPE*) cell3333->node; \ + \ + DATA->NAME = struct3333; \ + \ + cell3333->node = DATA; \ + } \ +} while (0) +#endif /*WITH_WSREP */ #ifdef UNIV_HASH_DEBUG # define HASH_ASSERT_VALID(DATA) ut_a((void*) (DATA) != (void*) -1) # define HASH_INVALIDATE(DATA, NAME) *(void**) (&DATA->NAME) = (void*) -1 diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 659b2e5b62a..e5c2266ab2f 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1088,7 +1088,8 @@ lock_rec_has_to_wait( wsrep_thd_conflict_state(trx->mysql_thd, FALSE), wsrep_thd_conflict_state(lock2->trx->mysql_thd, FALSE) ); lock_rec_print(stderr, lock2); - abort(); + return FALSE; + //abort(); } else { /* if lock2->index->n_uniq <= lock2->index->n_user_defined_cols @@ -2037,7 +2038,8 @@ lock_rec_create( ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted); #ifdef WITH_WSREP - if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + + if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { lock_t *hash = (lock_t *)c_lock->hash; lock_t *prev = NULL; @@ -2100,6 +2102,9 @@ lock_rec_create( return(lock); } trx_mutex_exit(c_lock->trx); + } else if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + HASH_PREPEND(lock_t, hash, lock_sys->rec_hash, + lock_rec_fold(space, page_no), lock); } else { HASH_INSERT(lock_t, hash, lock_sys->rec_hash, lock_rec_fold(space, page_no), lock); @@ -2115,7 +2120,6 @@ lock_rec_create( ut_ad(trx_mutex_own(trx)); if (type_mode & LOCK_WAIT) { - lock_set_lock_and_trx_wait(lock, trx); } @@ -2127,7 +2131,6 @@ lock_rec_create( MONITOR_INC(MONITOR_RECLOCK_CREATED); MONITOR_INC(MONITOR_NUM_RECLOCK); - return(lock); } @@ -2345,7 +2348,16 @@ lock_rec_add_to_queue( if (lock_get_wait(lock) && lock_rec_get_nth_bit(lock, heap_no)) { - +#ifdef WITH_WSREP + if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + if (wsrep_debug) { + fprintf(stderr, + "BF skipping wait: %lu\n", + trx->id); + lock_rec_print(stderr, lock); + } + } else +#endif goto somebody_waits; } } @@ -2655,7 +2667,13 @@ lock_rec_has_to_wait_in_queue( if (heap_no < lock_rec_get_n_bits(lock) && (p[bit_offset] & bit_mask) && lock_has_to_wait(wait_lock, lock)) { - +#ifdef WITH_WSREP + if (wsrep_thd_is_BF(wait_lock->trx->mysql_thd, FALSE) && + wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE)) { + /* don't wait for another BF lock */ + continue; + } +#endif return(lock); } } diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 7cbd91b65cd..adced7059e4 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -417,12 +417,9 @@ wsrep_row_upd_check_foreign_constraints( } if (foreign->referenced_table) { - mutex_enter(&(dict_sys->mutex)); - - (foreign->referenced_table - ->n_foreign_key_checks_running)++; - - mutex_exit(&(dict_sys->mutex)); + os_inc_counter(dict_sys->mutex, + foreign->referenced_table + ->n_foreign_key_checks_running); } /* NOTE that if the thread ends up waiting for a lock @@ -434,20 +431,14 @@ wsrep_row_upd_check_foreign_constraints( TRUE, foreign, table, entry, thr); if (foreign->referenced_table) { - mutex_enter(&(dict_sys->mutex)); - - ut_a(foreign->referenced_table - ->n_foreign_key_checks_running > 0); - - (foreign->referenced_table - ->n_foreign_key_checks_running)--; + os_dec_counter(dict_sys->mutex, + foreign->referenced_table + ->n_foreign_key_checks_running); if (opened == TRUE) { dict_table_close(foreign->referenced_table, TRUE, FALSE); opened = FALSE; } - - mutex_exit(&(dict_sys->mutex)); } if (err != DB_SUCCESS) { diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 025b9e8cf31..577146f62d8 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -362,7 +362,10 @@ case "$mode" in # Stop the service and regardless of whether it was # running or not, start it again. if $0 stop $other_args; then - $0 start $other_args + if ! $0 start $other_args; then + log_failure_msg "Failed to restart server." + exit 1 + fi else log_failure_msg "Failed to stop running server, so refusing to try to start." exit 1