diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index 750d3191d..45ee87c66 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -146,7 +146,6 @@ SET(INNOBASE_SOURCES pars/pars0pars.cc pars/pars0sym.cc que/que0que.cc - read/read0read.cc row/row0ext.cc row/row0ftsort.cc row/row0import.cc diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index b335c17ea..6d1fe8e90 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -445,13 +445,7 @@ from innodb_lock_wait_timeout via trx_t::mysql_thd. @return lock wait timeout in seconds */ #define trx_lock_wait_timeout_get(t) thd_lock_wait_timeout((t)->mysql_thd) -/** -Determine if the transaction is a non-locking autocommit select -(implied read-only). -@param t transaction -@return true if non-locking autocommit select transaction. */ -#define trx_is_autocommit_non_locking(t) \ - ((t)->auto_commit && (t)->will_lock == 0) +#include /** Determine if the transaction is a non-locking autocommit select diff --git a/storage/innobase/libs/read/include/innodb/read/ReadView.h b/storage/innobase/libs/read/include/innodb/read/ReadView.h index 410baf45a..72c852d00 100644 --- a/storage/innobase/libs/read/include/innodb/read/ReadView.h +++ b/storage/innobase/libs/read/include/innodb/read/ReadView.h @@ -215,7 +215,7 @@ class ReadView { Opens a read view where exactly the transactions serialized before this point in time are seen in the view. @param id Creator transaction id */ - inline void prepare(trx_id_t id); + void prepare(trx_id_t id); /** Copy state from another view. Must call copy_complete() to finish. diff --git a/storage/innobase/libs/read/src/MVCC.cpp b/storage/innobase/libs/read/src/MVCC.cpp index ffca74abc..3666d6c01 100644 --- a/storage/innobase/libs/read/src/MVCC.cpp +++ b/storage/innobase/libs/read/src/MVCC.cpp @@ -1,9 +1,16 @@ #include #include -#include #include #include +#include +#include +#include +#include +#include +#include +#include +#include /** Constructor @param size Number of views to pre-allocate */ @@ -169,3 +176,119 @@ void MVCC::view_close(ReadView *&view, bool own_mutex) { } } +/** +Allocate and create a view. +@param view view owned by this class created for the + caller. Must be freed by calling view_close() +@param trx transaction instance of caller */ +void MVCC::view_open(ReadView *&view, trx_t *trx) { + ut_ad(!srv_read_only_mode); + + /** If no new RW transaction has been started since the last view + was created then reuse the the existing view. */ + if (view != NULL) { + uintptr_t p = reinterpret_cast(view); + + view = reinterpret_cast(p & ~1); + + ut_ad(view->m_closed); + + /* NOTE: This can be optimised further, for now we only + resuse the view iff there are no active RW transactions. + + There is an inherent race here between purge and this + thread. Purge will skip views that are marked as closed. + Therefore we must set the low limit id after we reset the + closed status after the check. */ + + if (trx_is_autocommit_non_locking(trx) && view->empty()) { + view->m_closed = false; + + if (view->m_low_limit_id == trx_sys_get_max_trx_id()) { + return; + } else { + view->m_closed = true; + } + } + + mutex_enter(&trx_sys->mutex); + + UT_LIST_REMOVE(m_views, view); + + } else { + mutex_enter(&trx_sys->mutex); + + view = get_view(); + } + + if (view != NULL) { + view->prepare(trx->id); + + UT_LIST_ADD_FIRST(m_views, view); + + ut_ad(!view->is_closed()); + + ut_ad(validate()); + } + + trx_sys_mutex_exit(); +} + +/** Clones the oldest view and stores it in view. No need to +call view_close(). The caller owns the view that is passed in. +This function is called by Purge to determine whether it should +purge the delete marked record or not. +@param view Preallocated view, owned by the caller */ + +void MVCC::clone_oldest_view(ReadView *view) { + mutex_enter(&trx_sys->mutex); + + ReadView *oldest_view = get_oldest_view(); + + if (oldest_view == NULL) { + view->prepare(0); + + trx_sys_mutex_exit(); + + } else { + view->copy_prepare(*oldest_view); + + trx_sys_mutex_exit(); + + view->copy_complete(); + } +} + +/** +@return the number of active views */ + +ulint MVCC::size() const { + trx_sys_mutex_enter(); + + ulint size = 0; + + for (const ReadView *view = UT_LIST_GET_FIRST(m_views); view != NULL; + view = UT_LIST_GET_NEXT(m_view_list, view)) { + if (!view->is_closed()) { + ++size; + } + } + + trx_sys_mutex_exit(); + + return (size); +} + + +/** +Set the view creator transaction id. Note: This shouldbe set only +for views created by RW transactions. +@param view Set the creator trx id for this view +@param id Transaction id to set */ + +void MVCC::set_view_creator_trx_id(ReadView *view, trx_id_t id) { + ut_ad(id > 0); + ut_ad(mutex_own(&trx_sys->mutex)); + + view->creator_trx_id(id); +} diff --git a/storage/innobase/libs/read/src/ReadView.cpp b/storage/innobase/libs/read/src/ReadView.cpp index 20ff7632b..5b45a86c9 100644 --- a/storage/innobase/libs/read/src/ReadView.cpp +++ b/storage/innobase/libs/read/src/ReadView.cpp @@ -1,6 +1,8 @@ #include #include +#include +#include /** Minimum number of elements to reserve in ReadView::ids_t */ static const ulint MIN_TRX_IDS = 32; @@ -234,3 +236,35 @@ void ReadView::copy_complete() { m_creator_trx_id = 0; } +/** +Opens a read view where exactly the transactions serialized before this +point in time are seen in the view. +@param id Creator transaction id */ + +void ReadView::prepare(trx_id_t id) { + ut_ad(mutex_own(&trx_sys->mutex)); + + m_creator_trx_id = id; + + m_low_limit_no = m_low_limit_id = m_up_limit_id = trx_sys->max_trx_id; + + if (!trx_sys->rw_trx_ids.empty()) { + copy_trx_ids(trx_sys->rw_trx_ids); + } else { + m_ids.clear(); + } + + ut_ad(m_up_limit_id <= m_low_limit_id); + + if (UT_LIST_GET_LEN(trx_sys->serialisation_list) > 0) { + const trx_t *trx; + + trx = UT_LIST_GET_FIRST(trx_sys->serialisation_list); + + if (trx->no < m_low_limit_no) { + m_low_limit_no = trx->no; + } + } + + m_closed = false; +} diff --git a/storage/innobase/libs/trx_trx/include/innodb/trx_trx/trx_is_autocommit_non_locking.h b/storage/innobase/libs/trx_trx/include/innodb/trx_trx/trx_is_autocommit_non_locking.h new file mode 100644 index 000000000..b28861fbf --- /dev/null +++ b/storage/innobase/libs/trx_trx/include/innodb/trx_trx/trx_is_autocommit_non_locking.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +#include + +/** +Determine if the transaction is a non-locking autocommit select +(implied read-only). +@param t transaction +@return true if non-locking autocommit select transaction. */ +#define trx_is_autocommit_non_locking(t) \ + ((t)->auto_commit && (t)->will_lock == 0) diff --git a/storage/innobase/libs/trx_trx/src/CMakeLists.txt b/storage/innobase/libs/trx_trx/src/CMakeLists.txt index 95cf8d49d..d6f88b8d5 100644 --- a/storage/innobase/libs/trx_trx/src/CMakeLists.txt +++ b/storage/innobase/libs/trx_trx/src/CMakeLists.txt @@ -9,6 +9,7 @@ add_library( ${LIB_NAME} STATIC TrxVersion.cpp hit_list_t.cpp trx_mod_tables_t.cpp + trx_is_autocommit_non_locking.cpp ) target_compile_options( ${LIB_NAME} PRIVATE ) diff --git a/storage/innobase/libs/trx_trx/src/trx_is_autocommit_non_locking.cpp b/storage/innobase/libs/trx_trx/src/trx_is_autocommit_non_locking.cpp new file mode 100644 index 000000000..b36a8cd23 --- /dev/null +++ b/storage/innobase/libs/trx_trx/src/trx_is_autocommit_non_locking.cpp @@ -0,0 +1 @@ +#include diff --git a/storage/innobase/read/read0read.cc b/storage/innobase/read/read0read.cc deleted file mode 100644 index 4c2485053..000000000 --- a/storage/innobase/read/read0read.cc +++ /dev/null @@ -1,217 +0,0 @@ -/***************************************************************************** - -Copyright (c) 1996, 2018, Oracle and/or its affiliates. All Rights Reserved. - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License, version 2.0, as published by the -Free Software Foundation. - -This program is also distributed with certain software (including but not -limited to OpenSSL) that is licensed under separate terms, as designated in a -particular file or component or in included license documentation. The authors -of MySQL hereby grant you an additional permission to link the program and -your derivative works with the separately licensed software that they have -included with MySQL. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, -for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., -51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - -*****************************************************************************/ - -/** @file read/read0read.cc - Cursor read - - Created 2/16/1997 Heikki Tuuri - *******************************************************/ - -#include -#include -#include - - -#include "srv0srv.h" -#include "trx0sys.h" - - - - - - - - - - - - - - - - -/** -Opens a read view where exactly the transactions serialized before this -point in time are seen in the view. -@param id Creator transaction id */ - -void ReadView::prepare(trx_id_t id) { - ut_ad(mutex_own(&trx_sys->mutex)); - - m_creator_trx_id = id; - - m_low_limit_no = m_low_limit_id = m_up_limit_id = trx_sys->max_trx_id; - - if (!trx_sys->rw_trx_ids.empty()) { - copy_trx_ids(trx_sys->rw_trx_ids); - } else { - m_ids.clear(); - } - - ut_ad(m_up_limit_id <= m_low_limit_id); - - if (UT_LIST_GET_LEN(trx_sys->serialisation_list) > 0) { - const trx_t *trx; - - trx = UT_LIST_GET_FIRST(trx_sys->serialisation_list); - - if (trx->no < m_low_limit_no) { - m_low_limit_no = trx->no; - } - } - - m_closed = false; -} - - - - - -/** -Allocate and create a view. -@param view view owned by this class created for the - caller. Must be freed by calling view_close() -@param trx transaction instance of caller */ -void MVCC::view_open(ReadView *&view, trx_t *trx) { - ut_ad(!srv_read_only_mode); - - /** If no new RW transaction has been started since the last view - was created then reuse the the existing view. */ - if (view != NULL) { - uintptr_t p = reinterpret_cast(view); - - view = reinterpret_cast(p & ~1); - - ut_ad(view->m_closed); - - /* NOTE: This can be optimised further, for now we only - resuse the view iff there are no active RW transactions. - - There is an inherent race here between purge and this - thread. Purge will skip views that are marked as closed. - Therefore we must set the low limit id after we reset the - closed status after the check. */ - - if (trx_is_autocommit_non_locking(trx) && view->empty()) { - view->m_closed = false; - - if (view->m_low_limit_id == trx_sys_get_max_trx_id()) { - return; - } else { - view->m_closed = true; - } - } - - mutex_enter(&trx_sys->mutex); - - UT_LIST_REMOVE(m_views, view); - - } else { - mutex_enter(&trx_sys->mutex); - - view = get_view(); - } - - if (view != NULL) { - view->prepare(trx->id); - - UT_LIST_ADD_FIRST(m_views, view); - - ut_ad(!view->is_closed()); - - ut_ad(validate()); - } - - trx_sys_mutex_exit(); -} - - - - - - - - - -/** Clones the oldest view and stores it in view. No need to -call view_close(). The caller owns the view that is passed in. -This function is called by Purge to determine whether it should -purge the delete marked record or not. -@param view Preallocated view, owned by the caller */ - -void MVCC::clone_oldest_view(ReadView *view) { - mutex_enter(&trx_sys->mutex); - - ReadView *oldest_view = get_oldest_view(); - - if (oldest_view == NULL) { - view->prepare(0); - - trx_sys_mutex_exit(); - - } else { - view->copy_prepare(*oldest_view); - - trx_sys_mutex_exit(); - - view->copy_complete(); - } -} - -/** -@return the number of active views */ - -ulint MVCC::size() const { - trx_sys_mutex_enter(); - - ulint size = 0; - - for (const ReadView *view = UT_LIST_GET_FIRST(m_views); view != NULL; - view = UT_LIST_GET_NEXT(m_view_list, view)) { - if (!view->is_closed()) { - ++size; - } - } - - trx_sys_mutex_exit(); - - return (size); -} - - - -/** -Set the view creator transaction id. Note: This shouldbe set only -for views created by RW transactions. -@param view Set the creator trx id for this view -@param id Transaction id to set */ - -void MVCC::set_view_creator_trx_id(ReadView *view, trx_id_t id) { - ut_ad(id > 0); - ut_ad(mutex_own(&trx_sys->mutex)); - - view->creator_trx_id(id); -}