diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-04-25 09:05:52 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-04-25 09:05:52 +0300 |
commit | acf6f92aa936fbfe7524617ae57d011ab8f1f96d (patch) | |
tree | e7fc2258c06a0fdab1cce115de4d71a091d82d28 /storage | |
parent | 765ae6e82165d1bc4cf6cc9f0d556d66a5e172d1 (diff) | |
parent | bc145193c164b895a52b943e73fff53952d48a60 (diff) | |
download | mariadb-git-acf6f92aa936fbfe7524617ae57d011ab8f1f96d.tar.gz |
Merge 10.2 into 10.3
Diffstat (limited to 'storage')
24 files changed, 154 insertions, 261 deletions
diff --git a/storage/archive/ha_archive.cc b/storage/archive/ha_archive.cc index 487c0038239..9d7f7e66b28 100644 --- a/storage/archive/ha_archive.cc +++ b/storage/archive/ha_archive.cc @@ -1671,7 +1671,6 @@ void ha_archive::update_create_info(HA_CREATE_INFO *create_info) DBUG_VOID_RETURN; } - /* Hints for optimizer, see ha_tina for more information */ @@ -1679,22 +1678,7 @@ int ha_archive::info(uint flag) { DBUG_ENTER("ha_archive::info"); - mysql_mutex_lock(&share->mutex); - if (share->dirty) - { - DBUG_PRINT("ha_archive", ("archive flushing out rows for scan")); - DBUG_ASSERT(share->archive_write_open); - azflush(&(share->archive_write), Z_SYNC_FLUSH); - share->dirty= FALSE; - } - - /* - This should be an accurate number now, though bulk and delayed inserts can - cause the number to be inaccurate. - */ - stats.records= share->rows_recorded; - mysql_mutex_unlock(&share->mutex); - + flush_and_clear_pending_writes(); stats.deleted= 0; DBUG_PRINT("ha_archive", ("Stats rows is %d\n", (int)stats.records)); @@ -1737,6 +1721,38 @@ int ha_archive::info(uint flag) } +int ha_archive::external_lock(THD *thd, int lock_type) +{ + if (lock_type == F_RDLCK) + { + // We are going to read from the table. Flush any pending writes that we + // may have + flush_and_clear_pending_writes(); + } + return 0; +} + + +void ha_archive::flush_and_clear_pending_writes() +{ + mysql_mutex_lock(&share->mutex); + if (share->dirty) + { + DBUG_PRINT("ha_archive", ("archive flushing out rows for scan")); + DBUG_ASSERT(share->archive_write_open); + azflush(&(share->archive_write), Z_SYNC_FLUSH); + share->dirty= FALSE; + } + + /* + This should be an accurate number now, though bulk and delayed inserts can + cause the number to be inaccurate. + */ + stats.records= share->rows_recorded; + mysql_mutex_unlock(&share->mutex); +} + + /* This method tells us that a bulk insert operation is about to occur. We set a flag which will keep write_row from saying that its data is dirty. This in diff --git a/storage/archive/ha_archive.h b/storage/archive/ha_archive.h index 56ff566db8c..a74374a340f 100644 --- a/storage/archive/ha_archive.h +++ b/storage/archive/ha_archive.h @@ -169,5 +169,8 @@ public: int unpack_row(azio_stream *file_to_read, uchar *record); unsigned int pack_row(uchar *record, azio_stream *writer); bool check_if_incompatible_data(HA_CREATE_INFO *info, uint table_changes); + int external_lock(THD *thd, int lock_type); +private: + void flush_and_clear_pending_writes(); }; diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index d5d1dcea152..579eb62d82c 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -3897,10 +3897,6 @@ got_block: } } -#ifdef UNIV_IBUF_COUNT_DEBUG - ut_a(ibuf_count_get(page_id) == 0); -#endif /* UNIV_IBUF_COUNT_DEBUG */ - return(bpage); } @@ -4682,15 +4678,9 @@ evict_from_pool: } } - if (!recv_no_ibuf_operations) { - if (access_time) { -#ifdef UNIV_IBUF_COUNT_DEBUG - ut_a(ibuf_count_get(page_id) == 0); -#endif /* UNIV_IBUF_COUNT_DEBUG */ - } else { - ibuf_merge_or_delete_for_page( - block, page_id, &page_size, TRUE); - } + if (!access_time && !recv_no_ibuf_operations) { + ibuf_merge_or_delete_for_page( + block, page_id, &page_size, TRUE); } buf_pool_mutex_enter(buf_pool); @@ -4892,10 +4882,6 @@ evict_from_pool: buf_read_ahead_linear(page_id, page_size, ibuf_inside(mtr)); } -#ifdef UNIV_IBUF_COUNT_DEBUG - ut_a(ibuf_count_get(fix_block->page.id) == 0); -#endif - ut_ad(!rw_lock_own_flagged(hash_lock, RW_LOCK_FLAG_X | RW_LOCK_FLAG_S)); @@ -5003,10 +4989,6 @@ buf_page_optimistic_get( ibuf_inside(mtr)); } -#ifdef UNIV_IBUF_COUNT_DEBUG - ut_a(ibuf_count_get(block->page.id) == 0); -#endif /* UNIV_IBUF_COUNT_DEBUG */ - buf_pool = buf_pool_from_block(block); buf_pool->stat.n_page_gets++; @@ -5110,9 +5092,6 @@ buf_page_get_known_nowait( } #endif /* UNIV_DEBUG */ -#ifdef UNIV_IBUF_COUNT_DEBUG - ut_a((mode == BUF_KEEP_OLD) || ibuf_count_get(block->page.id) == 0); -#endif buf_pool->stat.n_page_gets++; return(TRUE); @@ -5197,10 +5176,6 @@ buf_page_try_get_func( buf_pool->stat.n_page_gets++; -#ifdef UNIV_IBUF_COUNT_DEBUG - ut_a(ibuf_count_get(block->page.id) == 0); -#endif /* UNIV_IBUF_COUNT_DEBUG */ - return(block); } @@ -5599,11 +5574,6 @@ buf_page_create( if (block && buf_page_in_file(&block->page) && !buf_pool_watch_is_sentinel(buf_pool, &block->page)) { - -#ifdef UNIV_IBUF_COUNT_DEBUG - ut_a(ibuf_count_get(page_id) == 0); -#endif /* UNIV_IBUF_COUNT_DEBUG */ - ut_d(block->page.file_page_was_freed = FALSE); /* Page can be found in buf_pool */ @@ -5708,9 +5678,6 @@ buf_page_create( #if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG ut_a(++buf_dbg_counter % 5771 || buf_validate()); #endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */ -#ifdef UNIV_IBUF_COUNT_DEBUG - ut_a(ibuf_count_get(block->page.id) == 0); -#endif return(block); } @@ -6158,14 +6125,6 @@ database_corrupted: buf_pool_mutex_enter(buf_pool); mutex_enter(block_mutex); -#ifdef UNIV_IBUF_COUNT_DEBUG - if (io_type == BUF_IO_WRITE || uncompressed) { - /* For BUF_IO_READ of compressed-only blocks, the - buffered operations will be merged by buf_page_get_gen() - after the block has been uncompressed. */ - ut_a(ibuf_count_get(bpage->id) == 0); - } -#endif /* Because this thread which does the unlocking is not the same that did the locking, we use a pass value != 0 in unlock, which simply removes the newest lock debug record, without checking the thread @@ -6394,11 +6353,6 @@ buf_pool_validate_instance( buf_pool, block->page.id) == &block->page); -#ifdef UNIV_IBUF_COUNT_DEBUG - ut_a(buf_page_get_io_fix(&block->page) - == BUF_IO_READ - || !ibuf_count_get(block->page.id)); -#endif switch (buf_page_get_io_fix(&block->page)) { case BUF_IO_NONE: break; diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc index b1c84e1d74a..fd9d4713a9c 100644 --- a/storage/innobase/buf/buf0flu.cc +++ b/storage/innobase/buf/buf0flu.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. Copyright (c) 2013, 2014, Fusion-io This program is free software; you can redistribute it and/or modify it under @@ -1043,11 +1043,6 @@ buf_flush_write_block_low( ut_ad(!buf_page_get_mutex(bpage)->is_owned()); ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_WRITE); ut_ad(bpage->oldest_modification != 0); - -#ifdef UNIV_IBUF_COUNT_DEBUG - ut_a(ibuf_count_get(bpage->id) == 0); -#endif /* UNIV_IBUF_COUNT_DEBUG */ - ut_ad(bpage->newest_modification != 0); /* Force the log to the disk before writing the modified block */ diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 859d5ece06a..9b4a0809f25 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1595,10 +1595,6 @@ buf_LRU_free_page( goto func_exit; } -#ifdef UNIV_IBUF_COUNT_DEBUG - ut_a(ibuf_count_get(bpage->id) == 0); -#endif /* UNIV_IBUF_COUNT_DEBUG */ - if (zip || !bpage->zip.data) { /* This would completely free the block. */ /* Do not completely free dirty blocks. */ diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 2bf22778f70..e67f860f3e2 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -4355,11 +4355,19 @@ dict_create_foreign_constraints_low( } orig = ptr; - ptr = dict_accept(cs, ptr, "TABLE", &success); - - if (!success) { - - goto loop; + for (;;) { + ptr = dict_accept(cs, ptr, "TABLE", &success); + if (success) { + break; + } + ptr = dict_accept(cs, ptr, "ONLINE", &success); + if (success) { + continue; + } + ptr = dict_accept(cs, ptr, "IGNORE", &success); + if (!success) { + goto loop; + } } /* We are doing an ALTER TABLE: scan the table name we are altering */ diff --git a/storage/innobase/ibuf/ibuf0ibuf.cc b/storage/innobase/ibuf/ibuf0ibuf.cc index e8d089ee41b..86deae0c015 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.cc +++ b/storage/innobase/ibuf/ibuf0ibuf.cc @@ -192,35 +192,6 @@ uint ibuf_debug; /** The insert buffer control structure */ ibuf_t* ibuf = NULL; -#ifdef UNIV_IBUF_COUNT_DEBUG -/** Number of tablespaces in the ibuf_counts array */ -#define IBUF_COUNT_N_SPACES 4 -/** Number of pages within each tablespace in the ibuf_counts array */ -#define IBUF_COUNT_N_PAGES 130000 - -/** Buffered entry counts for file pages, used in debugging */ -static ulint ibuf_counts[IBUF_COUNT_N_SPACES][IBUF_COUNT_N_PAGES]; - -/** Checks that the indexes to ibuf_counts[][] are within limits. -@param[in] page_id page id */ -UNIV_INLINE -void -ibuf_count_check( - const page_id_t page_id) -{ - if (page_id.space() < IBUF_COUNT_N_SPACES - && page_id.page_no() < IBUF_COUNT_N_PAGES) { - return; - } - - ib::fatal() << "UNIV_IBUF_COUNT_DEBUG limits space_id and page_no" - " and breaks crash recovery. space_id=" << page_id.space() - << ", should be 0<=space_id<" << IBUF_COUNT_N_SPACES - << ". page_no=" << page_id.page_no() - << ", should be 0<=page_no<" << IBUF_COUNT_N_PAGES; -} -#endif - /** @name Offsets to the per-page bits in the insert buffer bitmap */ /* @{ */ #define IBUF_BITMAP_FREE 0 /*!< Bits indicating the @@ -408,35 +379,6 @@ ibuf_tree_root_get( return(root); } -#ifdef UNIV_IBUF_COUNT_DEBUG - -/** Gets the ibuf count for a given page. -@param[in] page_id page id -@return number of entries in the insert buffer currently buffered for -this page */ -ulint ibuf_count_get(const page_id_t page_id) -{ - ibuf_count_check(page_id); - - return(ibuf_counts[page_id.space()][page_id.page_no()]); -} - -/** Sets the ibuf count for a given page. -@param[in] page_id page id -@param[in] val value to set */ -static -void -ibuf_count_set( - const page_id_t page_id, - ulint val) -{ - ibuf_count_check(page_id); - ut_a(val < srv_page_size); - - ibuf_counts[page_id.space()][page_id.page_no()] = val; -} -#endif - /******************************************************************//** Closes insert buffer and frees the data structures. */ void @@ -733,10 +675,6 @@ ibuf_bitmap_page_set_bits( compile_time_assert(!(IBUF_BITS_PER_PAGE % 2)); ut_ad(mtr_memo_contains_page(mtr, page, MTR_MEMO_PAGE_X_FIX)); ut_ad(mtr->is_named_space(page_id.space())); -#ifdef UNIV_IBUF_COUNT_DEBUG - ut_a((bit != IBUF_BITMAP_BUFFERED) || (val != FALSE) - || (0 == ibuf_count_get(page_id))); -#endif bit_offset = (page_id.page_no() % page_size.physical()) * IBUF_BITS_PER_PAGE + bit; @@ -3492,9 +3430,6 @@ fail_exit: which it cannot do until we have buffered the IBUF_OP_DELETE and done mtr_commit(&mtr) to release the latch. */ -#ifdef UNIV_IBUF_COUNT_DEBUG - ut_a((buffered == 0) || ibuf_count_get(page_id)); -#endif ibuf_mtr_start(&bitmap_mtr); index->set_modified(bitmap_mtr); @@ -3637,17 +3572,6 @@ fail_exit: } func_exit: -#ifdef UNIV_IBUF_COUNT_DEBUG - if (err == DB_SUCCESS) { - - ib::info() << "Incrementing ibuf count of page " << page_id - << " from " << ibuf_count_get(space, page_no) - << " by 1"; - - ibuf_count_set(page_id, ibuf_count_get(page_id) + 1); - } -#endif - ibuf_mtr_commit(&mtr); btr_pcur_close(&pcur); @@ -4339,14 +4263,6 @@ ibuf_delete_rec( ibuf->empty = true; } -#ifdef UNIV_IBUF_COUNT_DEBUG - ib::info() << "Decrementing ibuf count of space " << space - << " page " << page_no << " from " - << ibuf_count_get(page_id) << " by 1"; - - ibuf_count_set(page_id, ibuf_count_get(page_id) - 1); -#endif /* UNIV_IBUF_COUNT_DEBUG */ - return(FALSE); } @@ -4382,10 +4298,6 @@ ibuf_delete_rec( false, mtr); ut_a(err == DB_SUCCESS); -#ifdef UNIV_IBUF_COUNT_DEBUG - ibuf_count_set(page_id, ibuf_count_get(page_id) - 1); -#endif /* UNIV_IBUF_COUNT_DEBUG */ - ibuf_size_update(root); mutex_exit(&ibuf_mutex); @@ -4768,10 +4680,6 @@ reset_bit: my_atomic_addlint(&ibuf->n_merges, 1); ibuf_add_ops(ibuf->n_merged_ops, mops); ibuf_add_ops(ibuf->n_discarded_ops, dops); - -#ifdef UNIV_IBUF_COUNT_DEBUG - ut_a(ibuf_count_get(page_id) == 0); -#endif } /*********************************************************************//** @@ -4889,11 +4797,6 @@ ibuf_print( /*=======*/ FILE* file) /*!< in: file where to print */ { -#ifdef UNIV_IBUF_COUNT_DEBUG - ulint i; - ulint j; -#endif - mutex_enter(&ibuf_mutex); fprintf(file, @@ -4910,22 +4813,6 @@ ibuf_print( fputs("discarded operations:\n ", file); ibuf_print_ops(ibuf->n_discarded_ops, file); -#ifdef UNIV_IBUF_COUNT_DEBUG - for (i = 0; i < IBUF_COUNT_N_SPACES; i++) { - for (j = 0; j < IBUF_COUNT_N_PAGES; j++) { - ulint count = ibuf_count_get(page_id_t(i, j, 0)); - - if (count > 0) { - fprintf(stderr, - "Ibuf count for page " - ULINTPF ":" ULINTPF "" - " is " ULINTPF "\n", - i, j, count); - } - } - } -#endif /* UNIV_IBUF_COUNT_DEBUG */ - mutex_exit(&ibuf_mutex); } diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h index 72b9e291fca..1f5e8bfe4b2 100644 --- a/storage/innobase/include/ibuf0ibuf.h +++ b/storage/innobase/include/ibuf0ibuf.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2018, MariaDB Corporation. +Copyright (c) 2016, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -381,13 +381,6 @@ ibuf_parse_bitmap_init( buf_block_t* block, /*!< in: block or NULL */ mtr_t* mtr); /*!< in: mtr or NULL */ -#ifdef UNIV_IBUF_COUNT_DEBUG -/** Gets the ibuf count for a given page. -@param[in] page_id page id -@return number of entries in the insert buffer currently buffered for -this page */ -ulint ibuf_count_get(const page_id_t page_id); -#endif /******************************************************************//** Looks if the insert buffer is empty. @return true if empty */ diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index 8c5be47fb85..043429b7f56 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -431,6 +431,7 @@ class rw_trx_hash_t if (trx_t *trx= element->trx) { ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED) || + trx_state_eq(trx, TRX_STATE_PREPARED_RECOVERED) || (trx_state_eq(trx, TRX_STATE_ACTIVE) && (!srv_was_started || srv_read_only_mode || @@ -515,6 +516,7 @@ class rw_trx_hash_t ut_ad(!trx_is_autocommit_non_locking(trx)); mutex_enter(&trx->mutex); ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) || + trx_state_eq(trx, TRX_STATE_PREPARED_RECOVERED) || trx_state_eq(trx, TRX_STATE_PREPARED)); mutex_exit(&trx->mutex); } diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 653f9ad0d8f..b2594b46895 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -447,7 +447,7 @@ Check transaction state */ ut_ad(!trx_is_autocommit_non_locking((t))); \ switch ((t)->state) { \ case TRX_STATE_PREPARED: \ - /* fall through */ \ + case TRX_STATE_PREPARED_RECOVERED: \ case TRX_STATE_ACTIVE: \ case TRX_STATE_COMMITTED_IN_MEMORY: \ continue; \ @@ -785,6 +785,7 @@ public: TRX_STATE_NOT_STARTED TRX_STATE_ACTIVE TRX_STATE_PREPARED + TRX_STATE_PREPARED_RECOVERED (special case of TRX_STATE_PREPARED) TRX_STATE_COMMITTED_IN_MEMORY (alias below COMMITTED) Valid state transitions are: diff --git a/storage/innobase/include/trx0trx.ic b/storage/innobase/include/trx0trx.ic index 6589aca4e77..6cf4e51fa20 100644 --- a/storage/innobase/include/trx0trx.ic +++ b/storage/innobase/include/trx0trx.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2018, MariaDB Corporation. +Copyright (c) 2016, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -47,7 +47,7 @@ trx_state_eq( #ifdef UNIV_DEBUG switch (trx->state) { case TRX_STATE_PREPARED: - + case TRX_STATE_PREPARED_RECOVERED: ut_ad(!trx_is_autocommit_non_locking(trx)); return(trx->state == state); diff --git a/storage/innobase/include/trx0types.h b/storage/innobase/include/trx0types.h index 252d93796ee..e6b1851f330 100644 --- a/storage/innobase/include/trx0types.h +++ b/storage/innobase/include/trx0types.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, 2018, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -62,10 +62,11 @@ enum trx_state_t { TRX_STATE_NOT_STARTED, TRX_STATE_ACTIVE, - - /** Support for 2PC/XA */ + /** XA PREPARE has been executed; only XA COMMIT or XA ROLLBACK + are possible */ TRX_STATE_PREPARED, - + /** XA PREPARE transaction that was returned to ha_recover() */ + TRX_STATE_PREPARED_RECOVERED, TRX_STATE_COMMITTED_IN_MEMORY }; diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index 549394c80de..b66c4a96c9b 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -205,9 +205,6 @@ using the call command. */ this will break redo log file compatibility, but it may be useful when debugging redo log application problems. */ #define UNIV_IBUF_DEBUG /* debug the insert buffer */ -#define UNIV_IBUF_COUNT_DEBUG /* debug the insert buffer; -this limits the database to IBUF_COUNT_N_SPACES and IBUF_COUNT_N_PAGES, -and the insert buffer must be empty when the database is started */ #define UNIV_PERF_DEBUG /* debug flag that enables light weight performance related stuff. */ diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 8414ed82e34..7ef468fae39 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -6307,6 +6307,7 @@ lock_trx_release_locks( { check_trx_state(trx); ut_ad(trx_state_eq(trx, TRX_STATE_PREPARED) + || trx_state_eq(trx, TRX_STATE_PREPARED_RECOVERED) || trx_state_eq(trx, TRX_STATE_ACTIVE)); bool release_lock = UT_LIST_GET_LEN(trx->lock.trx_locks) > 0; diff --git a/storage/innobase/row/row0undo.cc b/storage/innobase/row/row0undo.cc index 9b88f950917..7fe59807521 100644 --- a/storage/innobase/row/row0undo.cc +++ b/storage/innobase/row/row0undo.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -130,6 +130,7 @@ row_undo_node_create( undo_node_t* undo; ut_ad(trx_state_eq(trx, TRX_STATE_ACTIVE) + || trx_state_eq(trx, TRX_STATE_PREPARED_RECOVERED) || trx_state_eq(trx, TRX_STATE_PREPARED)); ut_ad(parent); diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index a60170de48e..830255e89f0 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1400,10 +1400,6 @@ dberr_t srv_start(bool create_new_db) #ifdef UNIV_IBUF_DEBUG ib::info() << "!!!!!!!! UNIV_IBUF_DEBUG switched on !!!!!!!!!"; -# ifdef UNIV_IBUF_COUNT_DEBUG - ib::info() << "!!!!!!!! UNIV_IBUF_COUNT_DEBUG switched on !!!!!!!!!"; - ib::error() << "Crash recovery will fail with UNIV_IBUF_COUNT_DEBUG"; -# endif #endif #ifdef UNIV_LOG_LSN_DEBUG diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index 9e992d2f145..2bff7495c1b 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2018, MariaDB Corporation. +Copyright (c) 2016, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -236,6 +236,7 @@ dberr_t trx_rollback_for_mysql(trx_t* trx) return(trx_rollback_for_mysql_low(trx)); case TRX_STATE_PREPARED: + case TRX_STATE_PREPARED_RECOVERED: ut_ad(!trx_is_autocommit_non_locking(trx)); if (trx->rsegs.m_redo.undo || trx->rsegs.m_redo.old_insert) { /* Change the undo log state back from @@ -335,6 +336,7 @@ trx_rollback_last_sql_stat_for_mysql( return(err); case TRX_STATE_PREPARED: + case TRX_STATE_PREPARED_RECOVERED: case TRX_STATE_COMMITTED_IN_MEMORY: /* The statement rollback is only allowed on an ACTIVE transaction, not a PREPARED or COMMITTED one. */ @@ -508,6 +510,7 @@ trx_rollback_to_savepoint_for_mysql( trx, savep, mysql_binlog_cache_pos)); case TRX_STATE_PREPARED: + case TRX_STATE_PREPARED_RECOVERED: case TRX_STATE_COMMITTED_IN_MEMORY: /* The savepoint rollback is only allowed on an ACTIVE transaction, not a PREPARED or COMMITTED one. */ diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index cdb5d4a1ee3..0d75b72a149 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -466,6 +466,7 @@ trx_free_at_shutdown(trx_t *trx) { ut_ad(trx->is_recovered); ut_a(trx_state_eq(trx, TRX_STATE_PREPARED) + || trx_state_eq(trx, TRX_STATE_PREPARED_RECOVERED) || (trx_state_eq(trx, TRX_STATE_ACTIVE) && (!srv_was_started || srv_operation == SRV_OPERATION_RESTORE @@ -1551,7 +1552,7 @@ trx_commit_or_rollback_prepare( case TRX_STATE_ACTIVE: case TRX_STATE_PREPARED: - + case TRX_STATE_PREPARED_RECOVERED: /* If the trx is in a lock wait state, moves the waiting query thread to the suspended state */ @@ -1662,7 +1663,7 @@ trx_commit_for_mysql( /* fall through */ case TRX_STATE_ACTIVE: case TRX_STATE_PREPARED: - + case TRX_STATE_PREPARED_RECOVERED: trx->op_info = "committing"; trx_commit(trx); @@ -1708,6 +1709,7 @@ trx_mark_sql_stat_end( switch (trx->state) { case TRX_STATE_PREPARED: + case TRX_STATE_PREPARED_RECOVERED: case TRX_STATE_COMMITTED_IN_MEMORY: break; case TRX_STATE_NOT_STARTED: @@ -1762,6 +1764,7 @@ trx_print_low( (ulong) difftime(time(NULL), trx->start_time)); goto state_ok; case TRX_STATE_PREPARED: + case TRX_STATE_PREPARED_RECOVERED: fprintf(f, ", ACTIVE (PREPARED) %lu sec", (ulong) difftime(time(NULL), trx->start_time)); goto state_ok; @@ -2041,6 +2044,7 @@ struct trx_recover_for_mysql_callback_arg static my_bool trx_recover_for_mysql_callback(rw_trx_hash_element_t *element, trx_recover_for_mysql_callback_arg *arg) { + DBUG_ASSERT(arg->len > 0); mutex_enter(&element->mutex); if (trx_t *trx= element->trx) { @@ -2052,17 +2056,38 @@ static my_bool trx_recover_for_mysql_callback(rw_trx_hash_element_t *element, if (trx_state_eq(trx, TRX_STATE_PREPARED)) { ut_ad(trx->is_recovered); + ut_ad(trx->id); if (arg->count == 0) ib::info() << "Starting recovery for XA transactions..."; - ib::info() << "Transaction " << trx_get_id_for_print(trx) - << " in prepared state after recovery"; - ib::info() << "Transaction contains changes to " << trx->undo_no - << " rows"; - arg->xid_list[arg->count++]= *trx->xid; + XID& xid= arg->xid_list[arg->count]; + if (arg->count++ < arg->len) + { + trx->state= TRX_STATE_PREPARED_RECOVERED; + ib::info() << "Transaction " << trx->id + << " in prepared state after recovery"; + ib::info() << "Transaction contains changes to " << trx->undo_no + << " rows"; + xid= *trx->xid; + } } } mutex_exit(&element->mutex); - return arg->count == arg->len; + /* Do not terminate upon reaching arg->len; count all transactions */ + return false; +} + + +static my_bool trx_recover_reset_callback(rw_trx_hash_element_t *element, + void*) +{ + mutex_enter(&element->mutex); + if (trx_t *trx= element->trx) + { + if (trx_state_eq(trx, TRX_STATE_PREPARED_RECOVERED)) + trx->state= TRX_STATE_PREPARED; + } + mutex_exit(&element->mutex); + return false; } @@ -2086,9 +2111,18 @@ int trx_recover_for_mysql(XID *xid_list, uint len) trx_sys.rw_trx_hash.iterate_no_dups(reinterpret_cast<my_hash_walk_action> (trx_recover_for_mysql_callback), &arg); if (arg.count) + { ib::info() << arg.count - << " transactions in prepared state after recovery"; - return int(arg.count); + << " transactions in prepared state after recovery"; + /* After returning the full list, reset the state, because + init_server_components() wants to recover the collection of + transactions twice, by first calling tc_log->open() and then + ha_recover() directly. */ + if (arg.count <= len) + trx_sys.rw_trx_hash.iterate(reinterpret_cast<my_hash_walk_action> + (trx_recover_reset_callback), NULL); + } + return int(std::min(arg.count, len)); } @@ -2106,7 +2140,9 @@ static my_bool trx_get_trx_by_xid_callback(rw_trx_hash_element_t *element, mutex_enter(&element->mutex); if (trx_t *trx= element->trx) { - if (trx->is_recovered && trx_state_eq(trx, TRX_STATE_PREPARED) && + if (trx->is_recovered && + (trx_state_eq(trx, TRX_STATE_PREPARED) || + trx_state_eq(trx, TRX_STATE_PREPARED_RECOVERED)) && arg->xid->eq(reinterpret_cast<XID*>(trx->xid))) { #ifdef WITH_WSREP @@ -2172,6 +2208,7 @@ trx_start_if_not_started_xa_low( } return; case TRX_STATE_PREPARED: + case TRX_STATE_PREPARED_RECOVERED: case TRX_STATE_COMMITTED_IN_MEMORY: break; } @@ -2199,6 +2236,7 @@ trx_start_if_not_started_low( return; case TRX_STATE_PREPARED: + case TRX_STATE_PREPARED_RECOVERED: case TRX_STATE_COMMITTED_IN_MEMORY: break; } @@ -2265,6 +2303,7 @@ trx_start_for_ddl_low( case TRX_STATE_ACTIVE: case TRX_STATE_PREPARED: + case TRX_STATE_PREPARED_RECOVERED: case TRX_STATE_COMMITTED_IN_MEMORY: break; } diff --git a/storage/maria/ma_test3.c b/storage/maria/ma_test3.c index f81d5363c6b..604c2b676a4 100644 --- a/storage/maria/ma_test3.c +++ b/storage/maria/ma_test3.c @@ -362,7 +362,7 @@ int test_write(MARIA_HA *file,int id,int lock_type) maria_extra(file,HA_EXTRA_WRITE_CACHE,0); } - sprintf((char*) record.id,"%7ld", (long) getpid()); + my_snprintf((char*) record.id, sizeof(record.id), "%7ld", (long) getpid()); strnmov((char*) record.text,"Testing...", sizeof(record.text)); tries=(uint) rnd(100)+10; diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c index ae3b95db6ec..43798fe8c07 100644 --- a/storage/maria/maria_chk.c +++ b/storage/maria/maria_chk.c @@ -1731,8 +1731,8 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name) null_bit[0]=null_pos[0]=0; if (keyseg->null_bit) { - sprintf(null_bit,"%d",keyseg->null_bit); - sprintf(null_pos,"%ld",(long) keyseg->null_pos+1); + my_snprintf(null_bit, sizeof(null_bit), "%d", keyseg->null_bit); + my_snprintf(null_pos, sizeof(null_pos), "%ld", (long) keyseg->null_pos+1); } printf("%-7ld%-5d%-9s%-10s%-30s\n", (long) keyseg->start+1,keyseg->length, diff --git a/storage/myisam/mi_test3.c b/storage/myisam/mi_test3.c index 6922655450b..52df065eae5 100644 --- a/storage/myisam/mi_test3.c +++ b/storage/myisam/mi_test3.c @@ -365,7 +365,7 @@ int test_write(MI_INFO *file,int id,int lock_type) mi_extra(file,HA_EXTRA_WRITE_CACHE,0); } - sprintf((char*) record.id,"%7ld",(long) getpid()); + my_snprintf((char*) record.id, sizeof(record.id), "%7ld", (long) getpid()); strnmov((char*) record.text,"Testing...", sizeof(record.text)); tries=(uint) rnd(100)+10; diff --git a/storage/myisam/myisamchk.c b/storage/myisam/myisamchk.c index ad8de98280c..abb5a99d423 100644 --- a/storage/myisam/myisamchk.c +++ b/storage/myisam/myisamchk.c @@ -1405,8 +1405,8 @@ static void descript(HA_CHECK *param, register MI_INFO *info, char * name) null_bit[0]=null_pos[0]=0; if (keyseg->null_bit) { - sprintf(null_bit,"%d",keyseg->null_bit); - sprintf(null_pos,"%ld",(long) keyseg->null_pos+1); + my_snprintf(null_bit, sizeof(null_bit), "%d", keyseg->null_bit); + my_snprintf(null_pos, sizeof(null_pos), "%ld", (long) keyseg->null_pos+1); } printf("%-7ld%-5d%-9s%-10s%-30s\n", (long) keyseg->start+1,keyseg->length, diff --git a/storage/perfschema/pfs_events.h b/storage/perfschema/pfs_events.h index 97fb7e08d63..905d6f8590f 100644 --- a/storage/perfschema/pfs_events.h +++ b/storage/perfschema/pfs_events.h @@ -34,14 +34,8 @@ struct PFS_events ulonglong m_event_id; /** END_EVENT_ID. */ ulonglong m_end_event_id; - /** (EVENT_TYPE) */ - enum_event_type m_event_type; /** NESTING_EVENT_ID. */ ulonglong m_nesting_event_id; - /** NESTING_EVENT_TYPE */ - enum_event_type m_nesting_event_type; - /** Instrument metadata. */ - PFS_instr_class *m_class; /** Timer start. This member is populated only if m_class->m_timed is true. @@ -52,8 +46,14 @@ struct PFS_events This member is populated only if m_class->m_timed is true. */ ulonglong m_timer_end; + /** Instrument metadata. */ + PFS_instr_class *m_class; /** Location of the instrumentation in the source code (file name). */ const char *m_source_file; + /** (EVENT_TYPE) */ + enum_event_type m_event_type; + /** NESTING_EVENT_TYPE */ + enum_event_type m_nesting_event_type; /** Location of the instrumentation in the source code (line number). */ uint m_source_line; }; diff --git a/storage/perfschema/pfs_events_waits.h b/storage/perfschema/pfs_events_waits.h index 6a50134ad44..0d4e4c37cae 100644 --- a/storage/perfschema/pfs_events_waits.h +++ b/storage/perfschema/pfs_events_waits.h @@ -55,6 +55,23 @@ enum events_waits_class /** A wait event record. */ struct PFS_events_waits : public PFS_events { + /** Executing thread. */ + PFS_thread *m_thread; + /** Table share, for table operations only. */ + PFS_table_share *m_weak_table_share; + /** File, for file operations only. */ + PFS_file *m_weak_file; + /** Address in memory of the object instance waited on. */ + const void *m_object_instance_addr; + /** Socket, for socket operations only. */ + PFS_socket *m_weak_socket; + /** + Number of bytes read/written. + This member is populated for file READ/WRITE operations only. + */ + size_t m_number_of_bytes; + /** Flags */ + ulong m_flags; /** The type of wait. Readers: @@ -67,34 +84,17 @@ struct PFS_events_waits : public PFS_events - TRUNCATE EVENTS_WAITS_HISTORY_LONG */ events_waits_class m_wait_class; - /** Executing thread. */ - PFS_thread *m_thread; /** Object type */ enum_object_type m_object_type; - /** Table share, for table operations only. */ - PFS_table_share *m_weak_table_share; - /** File, for file operations only. */ - PFS_file *m_weak_file; - /** Socket, for socket operations only. */ - PFS_socket *m_weak_socket; /** For weak pointers, target object version. */ uint32 m_weak_version; - /** Address in memory of the object instance waited on. */ - const void *m_object_instance_addr; /** Operation performed. */ enum_operation_type m_operation; /** - Number of bytes read/written. - This member is populated for file READ/WRITE operations only. - */ - size_t m_number_of_bytes; - /** Index used. This member is populated for TABLE IO operations only. */ uint m_index; - /** Flags */ - ulong m_flags; }; /** TIMED bit in the state flags bitfield. */ |