From 40e65e878eac4d88ec124610e5ede5132b3c4cf2 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Mon, 11 Nov 2019 21:12:14 +0200 Subject: [PATCH 1/4] rpl_semi_sync_gtid_reconnect results merge --- .../suite/rpl/r/rpl_semi_sync_gtid_reconnect.result | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_gtid_reconnect.result b/mysql-test/suite/rpl/r/rpl_semi_sync_gtid_reconnect.result index 3c720b94fde..4285228f162 100644 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_gtid_reconnect.result +++ b/mysql-test/suite/rpl/r/rpl_semi_sync_gtid_reconnect.result @@ -1,27 +1,39 @@ include/master-slave.inc [connection master] +connection master; RESET MASTER; SET @@GLOBAL.rpl_semi_sync_master_enabled = 1; +connection slave; include/stop_slave.inc SET @@GLOBAL. rpl_semi_sync_slave_enabled = 1; include/start_slave.inc +connection master; CREATE TABLE t1 (a INT); INSERT INTO t1 SET a = 1; include/save_master_gtid.inc FLUSH LOGS; INSERT INTO t1 SET a = 2; +connection slave; +connection slave; include/stop_slave_sql.inc +connection master; INSERT INTO t1 SET a = 3; include/sync_slave_io_with_master.inc +connection slave; include/stop_slave_io.inc +connection master; RESET MASTER; SET @@global.gtid_binlog_state = '0-1-2'; +connection slave; CHANGE MASTER TO MASTER_USE_GTID = slave_pos; SET @@global.gtid_slave_pos = '0-1-2'; include/start_slave.inc +connection master; INSERT INTO t1 SET a = 4; +connection master; DROP TABLE t1; SET @@GLOBAL. rpl_semi_sync_master_enabled = 0; +connection slave; include/stop_slave.inc SET @@GLOBAL. rpl_semi_sync_slave_enabled = 0; include/start_slave.inc From 7df07c766651c37cda4daf8a6aa1fb1c38efc62c Mon Sep 17 00:00:00 2001 From: Sujatha Date: Tue, 5 Nov 2019 15:01:29 +0530 Subject: [PATCH 2/4] MDEV-20953: binlog_encryption.rpl_corruption failed in buildbot due to wrong error code Problem: ======== CURRENT_TEST: binlog_encryption.rpl_corruption mysqltest: In included file "./include/wait_for_slave_io_error.inc": ... At line 72: Slave stopped with wrong error code **** Slave stopped with wrong error code: 1743 (expected 1595,1913) **** Analysis: ======== The test emulates the corruption at the various stages of replication for example in binlog file, in network and in relay log etc. It verifies that all corruption cases are handled through appropriate error messages. The test cases which emulate network failure expect following errors. --ER_SLAVE_RELAY_LOG_WRITE_FAILURE (1595) --ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE (1743) Ideally test should expect error codes as 1595 and 1743. But the test actually waits on incorrect error code 1595,1913 Fix: === Added appropriate error code for 'ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE'. Replaced 1913 with 1743. --- mysql-test/extra/rpl_tests/rpl_corruption.inc | 8 ++++---- mysql-test/suite/binlog_encryption/rpl_corruption.result | 4 ++-- mysql-test/suite/rpl/r/rpl_corruption.result | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mysql-test/extra/rpl_tests/rpl_corruption.inc b/mysql-test/extra/rpl_tests/rpl_corruption.inc index 048a9d74249..1726ee4ba2f 100644 --- a/mysql-test/extra/rpl_tests/rpl_corruption.inc +++ b/mysql-test/extra/rpl_tests/rpl_corruption.inc @@ -122,11 +122,11 @@ SET GLOBAL master_verify_checksum=0; SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set"; --connection slave START SLAVE IO_THREAD; -# When the checksum error is detected, the slave sets error code 1913 +# When the checksum error is detected, the slave sets error code 1743 # (ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE) in queue_event(), then immediately # sets error 1595 (ER_SLAVE_RELAY_LOG_WRITE_FAILURE) in handle_slave_io(). -# So we usually get 1595, but it is occasionally possible to get 1913. -let $slave_io_errno= 1595,1913; +# So we usually get 1595, but it is occasionally possible to get 1743. +let $slave_io_errno= 1595,1743; # ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE --source include/wait_for_slave_io_error.inc --connection master SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set"; @@ -138,7 +138,7 @@ SET GLOBAL master_verify_checksum=1; --connection slave SET GLOBAL debug_dbug="+d,corrupt_queue_event"; START SLAVE IO_THREAD; -let $slave_io_errno= 1595,1913; +let $slave_io_errno= 1595,1743; # ER_SLAVE_RELAY_LOG_WRITE_FAILURE, ER_NETWORK_READ_EVENT_CHECKSUM_FAILURE --source include/wait_for_slave_io_error.inc SET GLOBAL debug_dbug="-d,corrupt_queue_event"; diff --git a/mysql-test/suite/binlog_encryption/rpl_corruption.result b/mysql-test/suite/binlog_encryption/rpl_corruption.result index 51c2c6261b8..05db91bf058 100644 --- a/mysql-test/suite/binlog_encryption/rpl_corruption.result +++ b/mysql-test/suite/binlog_encryption/rpl_corruption.result @@ -25,14 +25,14 @@ SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set"; SET GLOBAL master_verify_checksum=0; SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set"; START SLAVE IO_THREAD; -include/wait_for_slave_io_error.inc [errno=1595,1913] +include/wait_for_slave_io_error.inc [errno=1595,1743] SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set"; SET GLOBAL debug_dbug= ""; SET GLOBAL master_verify_checksum=1; # 5. Slave. Corruption in network SET GLOBAL debug_dbug="+d,corrupt_queue_event"; START SLAVE IO_THREAD; -include/wait_for_slave_io_error.inc [errno=1595,1913] +include/wait_for_slave_io_error.inc [errno=1595,1743] SET GLOBAL debug_dbug="-d,corrupt_queue_event"; # 6. Slave. Corruption in relay log SET GLOBAL debug_dbug="+d,corrupt_read_log_event_char"; diff --git a/mysql-test/suite/rpl/r/rpl_corruption.result b/mysql-test/suite/rpl/r/rpl_corruption.result index 51c2c6261b8..05db91bf058 100644 --- a/mysql-test/suite/rpl/r/rpl_corruption.result +++ b/mysql-test/suite/rpl/r/rpl_corruption.result @@ -25,14 +25,14 @@ SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set"; SET GLOBAL master_verify_checksum=0; SET GLOBAL debug_dbug="+d,corrupt_read_log_event2_set"; START SLAVE IO_THREAD; -include/wait_for_slave_io_error.inc [errno=1595,1913] +include/wait_for_slave_io_error.inc [errno=1595,1743] SET GLOBAL debug_dbug="-d,corrupt_read_log_event2_set"; SET GLOBAL debug_dbug= ""; SET GLOBAL master_verify_checksum=1; # 5. Slave. Corruption in network SET GLOBAL debug_dbug="+d,corrupt_queue_event"; START SLAVE IO_THREAD; -include/wait_for_slave_io_error.inc [errno=1595,1913] +include/wait_for_slave_io_error.inc [errno=1595,1743] SET GLOBAL debug_dbug="-d,corrupt_queue_event"; # 6. Slave. Corruption in relay log SET GLOBAL debug_dbug="+d,corrupt_read_log_event_char"; From dc8380b65da2071735129c829a3ea7bca006bf5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 12 Nov 2019 14:41:24 +0200 Subject: [PATCH 3/4] MDEV-14602: Cleanup recv_dblwr_t::find_page() Avoid creating std::vector, and use single instead of double traversal. --- storage/innobase/log/log0recv.cc | 49 ++++++++++---------------------- 1 file changed, 15 insertions(+), 34 deletions(-) diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc index 3068a510b4e..9a20c7f7d22 100644 --- a/storage/innobase/log/log0recv.cc +++ b/storage/innobase/log/log0recv.cc @@ -27,7 +27,6 @@ Created 9/20/1997 Heikki Tuuri #include "univ.i" -#include #include #include #include @@ -4044,44 +4043,26 @@ recv_recovery_rollback_active(void) @param[in] page_no page number @return page frame @retval NULL if no page was found */ - const byte* recv_dblwr_t::find_page(ulint space_id, ulint page_no) { - typedef std::vector > - matches_t; + const byte *result= NULL; + lsn_t max_lsn= 0; - matches_t matches; - const byte* result = 0; + for (list::const_iterator i = pages.begin(); i != pages.end(); ++i) + { + const byte *page= *i; + if (page_get_page_no(page) != page_no || + page_get_space_id(page) != space_id) + continue; + const lsn_t lsn= mach_read_from_8(page + FIL_PAGE_LSN); + if (lsn <= max_lsn) + continue; + max_lsn= lsn; + result= page; + } - for (list::iterator i = pages.begin(); i != pages.end(); ++i) { - if (page_get_space_id(*i) == space_id - && page_get_page_no(*i) == page_no) { - matches.push_back(*i); - } - } - - if (matches.size() == 1) { - result = matches[0]; - } else if (matches.size() > 1) { - - lsn_t max_lsn = 0; - lsn_t page_lsn = 0; - - for (matches_t::iterator i = matches.begin(); - i != matches.end(); - ++i) { - - page_lsn = mach_read_from_8(*i + FIL_PAGE_LSN); - - if (page_lsn > max_lsn) { - max_lsn = page_lsn; - result = *i; - } - } - } - - return(result); + return result; } #ifndef DBUG_OFF From 2570cb8b91711b38e4a448cc92b95e49abb218b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Tue, 12 Nov 2019 15:46:57 +0200 Subject: [PATCH 4/4] MDEV-12353 preparation: Clean up mtr_t mtr_t::Impl, mtr_t::Command: Merge to mtr_t. MTR_MAGIC_N: Remove. MTR_STATE_COMMITTING: Remove. This state was only being set internally during mtr_t::commit(). mtr_t::Command::m_locks_released: Remove (set-and-never-read member). mtr_t::Command::m_start_lsn: Replaced with the return value of finish_write() and a parameter to release_blocks(). mtr_t::Command::m_end_lsn: Removed as a duplicate of mtr_t::m_commit_lsn. mtr_t::Command::prepare_write(): Replace a switch () with a comparison against 0. Only 2 m_log_mode are allowed. --- storage/innobase/include/mtr0mtr.h | 246 ++++++---------- storage/innobase/include/mtr0mtr.ic | 55 ++-- storage/innobase/include/mtr0types.h | 19 +- storage/innobase/mtr/mtr0mtr.cc | 423 +++++++++------------------ 4 files changed, 251 insertions(+), 492 deletions(-) diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 4f518071bfb..30d2e937f1f 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -2,7 +2,7 @@ Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 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 @@ -146,68 +146,7 @@ struct mtr_memo_slot_t { /** Mini-transaction handle and buffer */ struct mtr_t { - - /** State variables of the mtr */ - struct Impl { - - /** memo stack for locks etc. */ - mtr_buf_t m_memo; - - /** mini-transaction log */ - mtr_buf_t m_log; - - /** true if mtr has made at least one buffer pool page dirty */ - bool m_made_dirty; - - /** true if inside ibuf changes */ - bool m_inside_ibuf; - - /** true if the mini-transaction modified buffer pool pages */ - bool m_modifications; - - /** Count of how many page initial log records have been - written to the mtr log */ - ib_uint32_t m_n_log_recs; - - /** specifies which operations should be logged; default - value MTR_LOG_ALL */ - mtr_log_t m_log_mode; -#ifdef UNIV_DEBUG - /** Persistent user tablespace associated with the - mini-transaction, or 0 (TRX_SYS_SPACE) if none yet */ - ulint m_user_space_id; -#endif /* UNIV_DEBUG */ - /** User tablespace that is being modified by the - mini-transaction */ - fil_space_t* m_user_space; - /** Undo tablespace that is being modified by the - mini-transaction */ - fil_space_t* m_undo_space; - /** System tablespace if it is being modified by the - mini-transaction */ - fil_space_t* m_sys_space; - - /** State of the transaction */ - mtr_state_t m_state; - - /** Flush Observer */ - FlushObserver* m_flush_observer; - -#ifdef UNIV_DEBUG - /** For checking corruption. */ - ulint m_magic_n; -#endif /* UNIV_DEBUG */ - - /** Owning mini-transaction */ - mtr_t* m_mtr; - }; - - mtr_t() - { - m_impl.m_state = MTR_STATE_INIT; - } - - ~mtr_t() { } + mtr_t() : m_state(MTR_STATE_INIT) {} /** Release the free extents that was reserved using fsp_reserve_free_extents(). This is equivalent to calling @@ -236,14 +175,7 @@ struct mtr_t { /** Return current size of the buffer. @return savepoint */ - ulint get_savepoint() const - MY_ATTRIBUTE((warn_unused_result)) - { - ut_ad(is_active()); - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); - - return(m_impl.m_memo.size()); - } + ulint get_savepoint() const {ut_ad(is_active()); return m_memo.size();} /** Release the (index tree) s-latch stored in an mtr memo after a savepoint. @@ -279,10 +211,10 @@ struct mtr_t { @return the system tablespace */ fil_space_t* set_sys_modified() { - if (!m_impl.m_sys_space) { + if (!m_sys_space) { lookup_sys_space(); } - return(m_impl.m_sys_space); + return m_sys_space; } /** Copy the tablespaces associated with the mini-transaction @@ -291,15 +223,15 @@ struct mtr_t { the same set of tablespaces as this one */ void set_spaces(const mtr_t& mtr) { - ut_ad(!m_impl.m_user_space_id); - ut_ad(!m_impl.m_user_space); - ut_ad(!m_impl.m_undo_space); - ut_ad(!m_impl.m_sys_space); + ut_ad(!m_user_space_id); + ut_ad(!m_user_space); + ut_ad(!m_undo_space); + ut_ad(!m_sys_space); - ut_d(m_impl.m_user_space_id = mtr.m_impl.m_user_space_id); - m_impl.m_user_space = mtr.m_impl.m_user_space; - m_impl.m_undo_space = mtr.m_impl.m_undo_space; - m_impl.m_sys_space = mtr.m_impl.m_sys_space; + ut_d(m_user_space_id = mtr.m_user_space_id); + m_user_space = mtr.m_user_space; + m_undo_space = mtr.m_undo_space; + m_sys_space = mtr.m_sys_space; } /** Set the tablespace associated with the mini-transaction @@ -308,13 +240,13 @@ struct mtr_t { @return the tablespace */ fil_space_t* set_named_space(ulint space_id) { - ut_ad(!m_impl.m_user_space_id); - ut_d(m_impl.m_user_space_id = space_id); + ut_ad(!m_user_space_id); + ut_d(m_user_space_id = space_id); if (!space_id) { return(set_sys_modified()); } else { lookup_user_space(space_id); - return(m_impl.m_user_space); + return m_user_space; } } @@ -381,18 +313,12 @@ struct mtr_t { void release_page(const void* ptr, mtr_memo_type_t type); /** Note that the mini-transaction has modified data. */ - void set_modified() - { - m_impl.m_modifications = true; - } + void set_modified() { m_modifications = true; } /** Set the state to not-modified. This will not log the changes. This is only used during redo log apply, to avoid logging the changes. */ - void discard_modifications() - { - m_impl.m_modifications = false; - } + void discard_modifications() { m_modifications = false; } /** Get the LSN of commit(). @return the commit LSN @@ -404,45 +330,28 @@ struct mtr_t { } /** Note that we are inside the change buffer code. */ - void enter_ibuf() - { - m_impl.m_inside_ibuf = true; - } + void enter_ibuf() { m_inside_ibuf = true; } /** Note that we have exited from the change buffer code. */ - void exit_ibuf() - { - m_impl.m_inside_ibuf = false; - } + void exit_ibuf() { m_inside_ibuf = false; } /** @return true if we are inside the change buffer code */ - bool is_inside_ibuf() const - { - return(m_impl.m_inside_ibuf); - } + bool is_inside_ibuf() const { return m_inside_ibuf; } /* @return true if the mini-transaction is active */ - bool is_active() const - { - return(m_impl.m_state == MTR_STATE_ACTIVE); - } + bool is_active() const { return m_state == MTR_STATE_ACTIVE; } /** Get flush observer @return flush observer */ - FlushObserver* get_flush_observer() const - { - return(m_impl.m_flush_observer); - } + FlushObserver* get_flush_observer() const { return m_flush_observer; } /** Set flush observer @param[in] observer flush observer */ void set_flush_observer(FlushObserver* observer) { - ut_ad(observer == NULL - || m_impl.m_log_mode == MTR_LOG_NO_REDO); - - m_impl.m_flush_observer = observer; + ut_ad(observer == NULL || m_log_mode == MTR_LOG_NO_REDO); + m_flush_observer = observer; } #ifdef UNIV_DEBUG @@ -482,65 +391,31 @@ struct mtr_t { void print() const; /** @return true if the mini-transaction has committed */ - bool has_committed() const - { - return(m_impl.m_state == MTR_STATE_COMMITTED); - } - - /** @return true if the mini-transaction is committing */ - bool is_committing() const - { - return(m_impl.m_state == MTR_STATE_COMMITTING); - } + bool has_committed() const { return m_state == MTR_STATE_COMMITTED; } /** @return true if mini-transaction contains modifications. */ - bool has_modifications() const - { - return(m_impl.m_modifications); - } + bool has_modifications() const { return m_modifications; } /** @return the memo stack */ - const mtr_buf_t* get_memo() const - { - return(&m_impl.m_memo); - } + const mtr_buf_t* get_memo() const { return &m_memo; } /** @return the memo stack */ - mtr_buf_t* get_memo() - { - return(&m_impl.m_memo); - } + mtr_buf_t* get_memo() { return &m_memo; } #endif /* UNIV_DEBUG */ /** @return true if a record was added to the mini-transaction */ - bool is_dirty() const - { - return(m_impl.m_made_dirty); - } + bool is_dirty() const { return m_made_dirty; } /** Note that a record has been added to the log */ - void added_rec() - { - ++m_impl.m_n_log_recs; - } + void added_rec() { ++m_n_log_recs; } /** Get the buffered redo log of this mini-transaction. @return redo log */ - const mtr_buf_t* get_log() const - { - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); - - return(&m_impl.m_log); - } + const mtr_buf_t* get_log() const { return &m_log; } /** Get the buffered redo log of this mini-transaction. @return redo log */ - mtr_buf_t* get_log() - { - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); - - return(&m_impl.m_log); - } + mtr_buf_t* get_log() { return &m_log; } /** Push an object to an mtr memo stack. @param object object @@ -560,15 +435,60 @@ private: @param[in] space_id tablespace ID */ void lookup_user_space(ulint space_id); - class Command; + /** Prepare to write the mini-transaction log to the redo log buffer. + @return number of bytes to write in finish_write() */ + inline ulint prepare_write(); - friend class Command; + /** Append the redo log records to the redo log buffer. + @param[in] len number of bytes to write + @return start_lsn */ + inline lsn_t finish_write(ulint len); -private: - Impl m_impl; + /** Release the resources */ + inline void release_resources(); + + /** memo stack for locks etc. */ + mtr_buf_t m_memo; + + /** mini-transaction log */ + mtr_buf_t m_log; + + /** true if mtr has made at least one buffer pool page dirty */ + bool m_made_dirty; + + /** true if inside ibuf changes */ + bool m_inside_ibuf; + + /** true if the mini-transaction modified buffer pool pages */ + bool m_modifications; + + /** Count of how many page initial log records have been + written to the mtr log */ + ib_uint32_t m_n_log_recs; + + /** specifies which operations should be logged; default + value MTR_LOG_ALL */ + mtr_log_t m_log_mode; +#ifdef UNIV_DEBUG + /** Persistent user tablespace associated with the + mini-transaction, or 0 (TRX_SYS_SPACE) if none yet */ + ulint m_user_space_id; +#endif /* UNIV_DEBUG */ + /** User tablespace that is being modified by the mini-transaction */ + fil_space_t* m_user_space; + /** Undo tablespace that is being modified by the mini-transaction */ + fil_space_t* m_undo_space; + /** System tablespace if being modified by the mini-transaction */ + fil_space_t* m_sys_space; + + /** State of the transaction */ + mtr_state_t m_state; + + /** Flush Observer */ + FlushObserver* m_flush_observer; /** LSN at commit time */ - volatile lsn_t m_commit_lsn; + lsn_t m_commit_lsn; }; #include "mtr0mtr.ic" diff --git a/storage/innobase/include/mtr0mtr.ic b/storage/innobase/include/mtr0mtr.ic index 574d0de24a5..7175ede0d6a 100644 --- a/storage/innobase/include/mtr0mtr.ic +++ b/storage/innobase/include/mtr0mtr.ic @@ -49,7 +49,6 @@ mtr_t::memo_push(void* object, mtr_memo_type_t type) ut_ad(object != NULL); ut_ad(type >= MTR_MEMO_PAGE_S_FIX); ut_ad(type <= MTR_MEMO_SX_LOCK); - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); ut_ad(ut_is_2pow(type)); /* If this mtr has x-fixed a clean page then we set @@ -58,15 +57,13 @@ mtr_t::memo_push(void* object, mtr_memo_type_t type) can insert the dirtied page to the flush list. */ if ((type == MTR_MEMO_PAGE_X_FIX || type == MTR_MEMO_PAGE_SX_FIX) - && !m_impl.m_made_dirty) { + && !m_made_dirty) { - m_impl.m_made_dirty = is_block_dirtied( + m_made_dirty = is_block_dirtied( reinterpret_cast(object)); } - mtr_memo_slot_t* slot; - - slot = m_impl.m_memo.push(sizeof(*slot)); + mtr_memo_slot_t* slot = m_memo.push(sizeof(*slot)); slot->type = type; slot->object = object; @@ -81,11 +78,9 @@ mtr_t::release_s_latch_at_savepoint( rw_lock_t* lock) { ut_ad(is_active()); - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); + ut_ad(m_memo.size() > savepoint); - ut_ad(m_impl.m_memo.size() > savepoint); - - mtr_memo_slot_t* slot = m_impl.m_memo.at(savepoint); + mtr_memo_slot_t* slot = m_memo.at(savepoint); ut_ad(slot->object == lock); ut_ad(slot->type == MTR_MEMO_S_LOCK); @@ -104,8 +99,7 @@ mtr_t::sx_latch_at_savepoint( buf_block_t* block) { ut_ad(is_active()); - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); - ut_ad(m_impl.m_memo.size() > savepoint); + ut_ad(m_memo.size() > savepoint); ut_ad(!memo_contains_flagged( block, @@ -113,9 +107,7 @@ mtr_t::sx_latch_at_savepoint( | MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)); - mtr_memo_slot_t* slot; - - slot = m_impl.m_memo.at(savepoint); + mtr_memo_slot_t* slot = m_memo.at(savepoint); ut_ad(slot->object == block); @@ -124,8 +116,8 @@ mtr_t::sx_latch_at_savepoint( rw_lock_sx_lock(&block->lock); - if (!m_impl.m_made_dirty) { - m_impl.m_made_dirty = is_block_dirtied(block); + if (!m_made_dirty) { + m_made_dirty = is_block_dirtied(block); } slot->type = MTR_MEMO_PAGE_SX_FIX; @@ -140,8 +132,7 @@ mtr_t::x_latch_at_savepoint( buf_block_t* block) { ut_ad(is_active()); - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); - ut_ad(m_impl.m_memo.size() > savepoint); + ut_ad(m_memo.size() > savepoint); ut_ad(!memo_contains_flagged( block, @@ -149,9 +140,7 @@ mtr_t::x_latch_at_savepoint( | MTR_MEMO_PAGE_X_FIX | MTR_MEMO_PAGE_SX_FIX)); - mtr_memo_slot_t* slot; - - slot = m_impl.m_memo.at(savepoint); + mtr_memo_slot_t* slot = m_memo.at(savepoint); ut_ad(slot->object == block); @@ -160,8 +149,8 @@ mtr_t::x_latch_at_savepoint( rw_lock_x_lock(&block->lock); - if (!m_impl.m_made_dirty) { - m_impl.m_made_dirty = is_block_dirtied(block); + if (!m_made_dirty) { + m_made_dirty = is_block_dirtied(block); } slot->type = MTR_MEMO_PAGE_X_FIX; @@ -176,11 +165,8 @@ mtr_t::release_block_at_savepoint( buf_block_t* block) { ut_ad(is_active()); - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); - mtr_memo_slot_t* slot; - - slot = m_impl.m_memo.at(savepoint); + mtr_memo_slot_t* slot = m_memo.at(savepoint); ut_a(slot->object == block); @@ -198,10 +184,10 @@ Gets the logging mode of a mini-transaction. mtr_log_t mtr_t::get_log_mode() const { - ut_ad(m_impl.m_log_mode >= MTR_LOG_ALL); - ut_ad(m_impl.m_log_mode <= MTR_LOG_SHORT_INSERTS); + ut_ad(m_log_mode >= MTR_LOG_ALL); + ut_ad(m_log_mode <= MTR_LOG_SHORT_INSERTS); - return(m_impl.m_log_mode); + return m_log_mode; } /** @@ -214,7 +200,7 @@ mtr_t::set_log_mode(mtr_log_t mode) ut_ad(mode >= MTR_LOG_ALL); ut_ad(mode <= MTR_LOG_SHORT_INSERTS); - const mtr_log_t old_mode = m_impl.m_log_mode; + const mtr_log_t old_mode = m_log_mode; switch (old_mode) { case MTR_LOG_NO_REDO: @@ -233,9 +219,8 @@ mtr_t::set_log_mode(mtr_log_t mode) case MTR_LOG_ALL: /* MTR_LOG_NO_REDO can only be set before generating any redo log records. */ - ut_ad(mode != MTR_LOG_NO_REDO - || m_impl.m_n_log_recs == 0); - m_impl.m_log_mode = mode; + ut_ad(mode != MTR_LOG_NO_REDO || m_n_log_recs == 0); + m_log_mode = mode; return(old_mode); } diff --git a/storage/innobase/include/mtr0types.h b/storage/innobase/include/mtr0types.h index 1179da6d926..985ad7b81ea 100644 --- a/storage/innobase/include/mtr0types.h +++ b/storage/innobase/include/mtr0types.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2015, 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 @@ -36,18 +36,18 @@ struct mtr_t; /** Logging modes for a mini-transaction */ enum mtr_log_t { /** Default mode: log all operations modifying disk-based data */ - MTR_LOG_ALL = 21, + MTR_LOG_ALL = 0, /** Log no operations and dirty pages are not added to the flush list. Set when applying log in crash recovery or when a modification of a ROW_FORMAT=COMPRESSED page is attempted. */ - MTR_LOG_NONE = 22, + MTR_LOG_NONE, /** Don't generate REDO log but add dirty pages to flush list */ - MTR_LOG_NO_REDO = 23, + MTR_LOG_NO_REDO, /** Inserts are logged in a shorter form */ - MTR_LOG_SHORT_INSERTS = 24 + MTR_LOG_SHORT_INSERTS }; /** @name Log item types @@ -267,15 +267,10 @@ enum mtr_memo_type_t { }; #endif /* !UNIV_CHECKSUM */ -#ifdef UNIV_DEBUG -# define MTR_MAGIC_N 54551 -#endif /* UNIV_DEBUG */ - enum mtr_state_t { MTR_STATE_INIT = 0, - MTR_STATE_ACTIVE = 12231, - MTR_STATE_COMMITTING = 56456, - MTR_STATE_COMMITTED = 34676 + MTR_STATE_ACTIVE, + MTR_STATE_COMMITTED }; #endif /* mtr0types_h */ diff --git a/storage/innobase/mtr/mtr0mtr.cc b/storage/innobase/mtr/mtr0mtr.cc index fc6f3321164..533b10b861e 100644 --- a/storage/innobase/mtr/mtr0mtr.cc +++ b/storage/innobase/mtr/mtr0mtr.cc @@ -343,6 +343,7 @@ struct ReleaseAll { } }; +#ifdef UNIV_DEBUG /** Check that all slots have been handled. */ struct DebugCheck { /** @return true always. */ @@ -352,6 +353,7 @@ struct DebugCheck { return(true); } }; +#endif /** Release a resource acquired by the mini-transaction. */ struct ReleaseBlocks { @@ -404,59 +406,6 @@ struct ReleaseBlocks { FlushObserver* m_flush_observer; }; -class mtr_t::Command { -public: - /** Constructor. - Takes ownership of the mtr->m_impl, is responsible for deleting it. - @param[in,out] mtr mini-transaction */ - explicit Command(mtr_t* mtr) : m_impl(&mtr->m_impl), m_locks_released() - {} - - /** Destructor */ - ~Command() - { - ut_ad(m_impl == 0); - } - - /** Write the redo log record, add dirty pages to the flush list and - release the resources. */ - void execute(); - - /** Release the blocks used in this mini-transaction. */ - void release_blocks(); - - /** Release the latches acquired by the mini-transaction. */ - void release_latches(); - - /** Release both the latches and blocks used in the mini-transaction. */ - void release_all(); - - /** Release the resources */ - void release_resources(); - - /** Append the redo log records to the redo log buffer. - @param[in] len number of bytes to write */ - void finish_write(ulint len); - -private: - /** Prepare to write the mini-transaction log to the redo log buffer. - @return number of bytes to write in finish_write() */ - ulint prepare_write(); - - /** The mini-transaction state. */ - mtr_t::Impl* m_impl; - - /** Set to 1 after the user thread releases the latches. The log - writer thread must wait for this to be set to 1. */ - volatile ulint m_locks_released; - - /** Start lsn of the possible log entry for this mtr */ - lsn_t m_start_lsn; - - /** End lsn of the possible log entry for this mtr */ - lsn_t m_end_lsn; -}; - /** Write the block contents to the REDO log */ struct mtr_write_log_t { /** Append a block to the redo log buffer. @@ -490,78 +439,77 @@ mtr_write_log( /** Start a mini-transaction. */ void mtr_t::start() { - UNIV_MEM_INVALID(this, sizeof(*this)); + UNIV_MEM_INVALID(this, sizeof *this); - UNIV_MEM_INVALID(&m_impl, sizeof(m_impl)); + new(&m_memo) mtr_buf_t(); + new(&m_log) mtr_buf_t(); - m_commit_lsn = 0; - - new(&m_impl.m_log) mtr_buf_t(); - new(&m_impl.m_memo) mtr_buf_t(); - - m_impl.m_mtr = this; - m_impl.m_log_mode = MTR_LOG_ALL; - m_impl.m_inside_ibuf = false; - m_impl.m_modifications = false; - m_impl.m_made_dirty = false; - m_impl.m_n_log_recs = 0; - m_impl.m_state = MTR_STATE_ACTIVE; - ut_d(m_impl.m_user_space_id = TRX_SYS_SPACE); - m_impl.m_user_space = NULL; - m_impl.m_undo_space = NULL; - m_impl.m_sys_space = NULL; - m_impl.m_flush_observer = NULL; - - ut_d(m_impl.m_magic_n = MTR_MAGIC_N); + m_made_dirty= false; + m_inside_ibuf= false; + m_modifications= false; + m_n_log_recs= 0; + m_log_mode= MTR_LOG_ALL; + ut_d(m_user_space_id= TRX_SYS_SPACE); + m_user_space= NULL; + m_undo_space= NULL; + m_sys_space= NULL; + m_state= MTR_STATE_ACTIVE; + m_flush_observer= NULL; + m_commit_lsn= 0; } /** Release the resources */ -void -mtr_t::Command::release_resources() +inline void mtr_t::release_resources() { - ut_ad(m_impl->m_magic_n == MTR_MAGIC_N); - - /* Currently only used in commit */ - ut_ad(m_impl->m_state == MTR_STATE_COMMITTING); - - ut_d(m_impl->m_memo.for_each_block_in_reverse(CIterate())); - - /* Reset the mtr buffers */ - m_impl->m_log.erase(); - - m_impl->m_memo.erase(); - - m_impl->m_state = MTR_STATE_COMMITTED; - - m_impl = 0; + ut_d(m_memo.for_each_block_in_reverse(CIterate())); + m_log.erase(); + m_memo.erase(); + m_state= MTR_STATE_COMMITTED; } /** Commit a mini-transaction. */ void mtr_t::commit() { - ut_ad(is_active()); - ut_ad(!is_inside_ibuf()); - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); - m_impl.m_state = MTR_STATE_COMMITTING; + ut_ad(is_active()); + ut_ad(!is_inside_ibuf()); - /* This is a dirty read, for debugging. */ - ut_ad(!m_impl.m_modifications || !recv_no_log_write); + /* This is a dirty read, for debugging. */ + ut_ad(!m_modifications || !recv_no_log_write); + ut_ad(!m_modifications || m_log_mode != MTR_LOG_NONE); - Command cmd(this); + if (m_modifications + && (m_n_log_recs || m_log_mode == MTR_LOG_NO_REDO)) + { + ut_ad(!srv_read_only_mode || m_log_mode == MTR_LOG_NO_REDO); - if (m_impl.m_modifications - && (m_impl.m_n_log_recs > 0 - || m_impl.m_log_mode == MTR_LOG_NO_REDO)) { + lsn_t start_lsn; - ut_ad(!srv_read_only_mode - || m_impl.m_log_mode == MTR_LOG_NO_REDO); + if (const ulint len= prepare_write()) + start_lsn= finish_write(len); + else + start_lsn= m_commit_lsn; - cmd.execute(); - } else { - cmd.release_all(); - cmd.release_resources(); - } + if (m_made_dirty) + log_flush_order_mutex_enter(); + + /* It is now safe to release the log mutex because the + flush_order mutex will ensure that we are the first one + to insert into the flush list. */ + log_mutex_exit(); + + m_memo.for_each_block_in_reverse(CIterate + (ReleaseBlocks(start_lsn, m_commit_lsn, + m_flush_observer))); + if (m_made_dirty) + log_flush_order_mutex_exit(); + + m_memo.for_each_block_in_reverse(CIterate()); + } + else + m_memo.for_each_block_in_reverse(CIterate()); + + release_resources(); } /** Commit a mini-transaction that did not modify any pages, @@ -580,37 +528,31 @@ mtr_t::commit_checkpoint( ut_ad(log_mutex_own()); ut_ad(is_active()); ut_ad(!is_inside_ibuf()); - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); ut_ad(get_log_mode() == MTR_LOG_ALL); - ut_ad(!m_impl.m_made_dirty); - ut_ad(m_impl.m_memo.size() == 0); + ut_ad(!m_made_dirty); + ut_ad(m_memo.size() == 0); ut_ad(!srv_read_only_mode); - ut_d(m_impl.m_state = MTR_STATE_COMMITTING); - ut_ad(write_mlog_checkpoint || m_impl.m_n_log_recs > 1); + ut_ad(write_mlog_checkpoint || m_n_log_recs > 1); - switch (m_impl.m_n_log_recs) { + switch (m_n_log_recs) { case 0: break; case 1: - *m_impl.m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG; + *m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG; break; default: - mlog_catenate_ulint( - &m_impl.m_log, MLOG_MULTI_REC_END, MLOG_1BYTE); + mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END, MLOG_1BYTE); } if (write_mlog_checkpoint) { - byte* ptr = m_impl.m_log.push(SIZE_OF_MLOG_CHECKPOINT); -#if SIZE_OF_MLOG_CHECKPOINT != 9 -# error SIZE_OF_MLOG_CHECKPOINT != 9 -#endif + byte* ptr = m_log.push(SIZE_OF_MLOG_CHECKPOINT); + compile_time_assert(SIZE_OF_MLOG_CHECKPOINT == 1 + 8); *ptr = MLOG_CHECKPOINT; mach_write_to_8(ptr + 1, checkpoint_lsn); } - Command cmd(this); - cmd.finish_write(m_impl.m_log.size()); - cmd.release_resources(); + finish_write(m_log.size()); + release_resources(); if (write_mlog_checkpoint) { DBUG_PRINT("ib_log", @@ -627,18 +569,12 @@ mtr_t::commit_checkpoint( bool mtr_t::is_named_space(ulint space) const { - ut_ad(!m_impl.m_sys_space - || m_impl.m_sys_space->id == TRX_SYS_SPACE); - ut_ad(!m_impl.m_undo_space - || m_impl.m_undo_space->id != TRX_SYS_SPACE); - ut_ad(!m_impl.m_user_space - || m_impl.m_user_space->id != TRX_SYS_SPACE); - ut_ad(!m_impl.m_sys_space - || m_impl.m_sys_space != m_impl.m_user_space); - ut_ad(!m_impl.m_sys_space - || m_impl.m_sys_space != m_impl.m_undo_space); - ut_ad(!m_impl.m_user_space - || m_impl.m_user_space != m_impl.m_undo_space); + ut_ad(!m_sys_space || m_sys_space->id == TRX_SYS_SPACE); + ut_ad(!m_undo_space || m_undo_space->id != TRX_SYS_SPACE); + ut_ad(!m_user_space || m_user_space->id != TRX_SYS_SPACE); + ut_ad(!m_sys_space || m_sys_space != m_user_space); + ut_ad(!m_sys_space || m_sys_space != m_undo_space); + ut_ad(!m_user_space || m_user_space != m_undo_space); switch (get_log_mode()) { case MTR_LOG_NONE: @@ -646,7 +582,7 @@ mtr_t::is_named_space(ulint space) const return(true); case MTR_LOG_ALL: case MTR_LOG_SHORT_INSERTS: - return(m_impl.m_user_space_id == space + return(m_user_space_id == space || is_predefined_tablespace(space)); } @@ -666,17 +602,16 @@ mtr_t::x_lock_space(ulint space_id, const char* file, unsigned line) { fil_space_t* space; - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); ut_ad(is_active()); if (space_id == TRX_SYS_SPACE) { - space = m_impl.m_sys_space; + space = m_sys_space; if (!space) { - space = m_impl.m_sys_space = fil_space_get(space_id); + space = m_sys_space = fil_space_get(space_id); } - } else if ((space = m_impl.m_user_space) && space_id == space->id) { - } else if ((space = m_impl.m_undo_space) && space_id == space->id) { + } else if ((space = m_user_space) && space_id == space->id) { + } else if ((space = m_undo_space) && space_id == space->id) { } else if (get_log_mode() == MTR_LOG_NO_REDO) { space = fil_space_get(space_id); ut_ad(space->purpose == FIL_TYPE_TEMPORARY @@ -685,7 +620,7 @@ mtr_t::x_lock_space(ulint space_id, const char* file, unsigned line) || srv_is_tablespace_truncated(space->id)); } else { /* called from trx_rseg_create() */ - space = m_impl.m_undo_space = fil_space_get(space_id); + space = m_undo_space = fil_space_get(space_id); } ut_ad(space); @@ -701,9 +636,9 @@ mtr_t::x_lock_space(ulint space_id, const char* file, unsigned line) void mtr_t::lookup_sys_space() { - ut_ad(!m_impl.m_sys_space); - m_impl.m_sys_space = fil_space_get(TRX_SYS_SPACE); - ut_ad(m_impl.m_sys_space); + ut_ad(!m_sys_space); + m_sys_space = fil_space_get(TRX_SYS_SPACE); + ut_ad(m_sys_space); } /** Look up the user tablespace. @@ -712,10 +647,10 @@ void mtr_t::lookup_user_space(ulint space_id) { ut_ad(space_id != TRX_SYS_SPACE); - ut_ad(m_impl.m_user_space_id == space_id); - ut_ad(!m_impl.m_user_space); - m_impl.m_user_space = fil_space_get(space_id); - ut_ad(m_impl.m_user_space); + ut_ad(m_user_space_id == space_id); + ut_ad(!m_user_space); + m_user_space = fil_space_get(space_id); + ut_ad(m_user_space); } /** Set the tablespace associated with the mini-transaction @@ -724,14 +659,13 @@ mtr_t::lookup_user_space(ulint space_id) void mtr_t::set_named_space(fil_space_t* space) { - ut_ad(m_impl.m_user_space_id == TRX_SYS_SPACE); - ut_d(m_impl.m_user_space_id = space->id); + ut_ad(m_user_space_id == TRX_SYS_SPACE); + ut_d(m_user_space_id = space->id); if (space->id == TRX_SYS_SPACE) { - ut_ad(m_impl.m_sys_space == NULL - || m_impl.m_sys_space == space); - m_impl.m_sys_space = space; + ut_ad(!m_sys_space || m_sys_space == space); + m_sys_space = space; } else { - m_impl.m_user_space = space; + m_user_space = space; } } @@ -740,16 +674,15 @@ mtr_t::set_named_space(fil_space_t* space) bool mtr_t::memo_release(const void* object, ulint type) { - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); ut_ad(is_active()); /* We cannot release a page that has been written to in the middle of a mini-transaction. */ - ut_ad(!m_impl.m_modifications || type != MTR_MEMO_PAGE_X_FIX); + ut_ad(!m_modifications || type != MTR_MEMO_PAGE_X_FIX); Iterate iteration(Find(object, type)); - if (!m_impl.m_memo.for_each_block_in_reverse(iteration)) { + if (!m_memo.for_each_block_in_reverse(iteration)) { memo_slot_release(iteration.functor.m_slot); return(true); } @@ -763,16 +696,15 @@ mtr_t::memo_release(const void* object, ulint type) void mtr_t::release_page(const void* ptr, mtr_memo_type_t type) { - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); ut_ad(is_active()); /* We cannot release a page that has been written to in the middle of a mini-transaction. */ - ut_ad(!m_impl.m_modifications || type != MTR_MEMO_PAGE_X_FIX); + ut_ad(!m_modifications || type != MTR_MEMO_PAGE_X_FIX); Iterate iteration(FindPage(ptr, type)); - if (!m_impl.m_memo.for_each_block_in_reverse(iteration)) { + if (!m_memo.for_each_block_in_reverse(iteration)) { memo_slot_release(iteration.functor.get_slot()); return; } @@ -783,27 +715,20 @@ mtr_t::release_page(const void* ptr, mtr_memo_type_t type) /** Prepare to write the mini-transaction log to the redo log buffer. @return number of bytes to write in finish_write() */ -ulint -mtr_t::Command::prepare_write() +inline ulint mtr_t::prepare_write() { ut_ad(!recv_no_log_write); - switch (m_impl->m_log_mode) { - case MTR_LOG_SHORT_INSERTS: - ut_ad(0); - /* fall through (write no redo log) */ - case MTR_LOG_NO_REDO: - case MTR_LOG_NONE: - ut_ad(m_impl->m_log.size() == 0); + if (UNIV_UNLIKELY(m_log_mode != MTR_LOG_ALL)) { + ut_ad(m_log_mode == MTR_LOG_NO_REDO); + ut_ad(m_log.size() == 0); log_mutex_enter(); - m_end_lsn = m_start_lsn = log_sys->lsn; - return(0); - case MTR_LOG_ALL: - break; + m_commit_lsn = log_sys->lsn; + return 0; } - ulint len = m_impl->m_log.size(); - ulint n_recs = m_impl->m_n_log_recs; + ulint len = m_log.size(); + ulint n_recs = m_n_log_recs; ut_ad(len > 0); ut_ad(n_recs > 0); @@ -811,9 +736,9 @@ mtr_t::Command::prepare_write() log_buffer_extend((len + 1) * 2); } - ut_ad(m_impl->m_n_log_recs == n_recs); + ut_ad(m_n_log_recs == n_recs); - fil_space_t* space = m_impl->m_user_space; + fil_space_t* space = m_user_space; if (space != NULL && is_predefined_tablespace(space->id)) { /* Omit MLOG_FILE_NAME for predefined tablespaces. */ @@ -822,35 +747,32 @@ mtr_t::Command::prepare_write() log_mutex_enter(); - if (fil_names_write_if_was_clean(space, m_impl->m_mtr)) { + if (fil_names_write_if_was_clean(space, this)) { /* This mini-transaction was the first one to modify this tablespace since the latest checkpoint, so some MLOG_FILE_NAME records were appended to m_log. */ - ut_ad(m_impl->m_n_log_recs > n_recs); - mlog_catenate_ulint( - &m_impl->m_log, MLOG_MULTI_REC_END, MLOG_1BYTE); - len = m_impl->m_log.size(); + ut_ad(m_n_log_recs > n_recs); + mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END, MLOG_1BYTE); + len = m_log.size(); } else { /* This was not the first time of dirtying a tablespace since the latest checkpoint. */ - ut_ad(n_recs == m_impl->m_n_log_recs); + ut_ad(n_recs == m_n_log_recs); if (n_recs <= 1) { ut_ad(n_recs == 1); /* Flag the single log record as the only record in this mini-transaction. */ - *m_impl->m_log.front()->begin() - |= MLOG_SINGLE_REC_FLAG; + *m_log.front()->begin() |= MLOG_SINGLE_REC_FLAG; } else { /* Because this mini-transaction comprises multiple log records, append MLOG_MULTI_REC_END at the end. */ - mlog_catenate_ulint( - &m_impl->m_log, MLOG_MULTI_REC_END, - MLOG_1BYTE); + mlog_catenate_ulint(&m_log, MLOG_MULTI_REC_END, + MLOG_1BYTE); len++; } } @@ -862,98 +784,37 @@ mtr_t::Command::prepare_write() } /** Append the redo log records to the redo log buffer -@param[in] len number of bytes to write */ -void -mtr_t::Command::finish_write( - ulint len) +@param[in] len number of bytes to write +@return start_lsn */ +inline lsn_t mtr_t::finish_write(ulint len) { - ut_ad(m_impl->m_log_mode == MTR_LOG_ALL); + ut_ad(m_log_mode == MTR_LOG_ALL); ut_ad(log_mutex_own()); - ut_ad(m_impl->m_log.size() == len); + ut_ad(m_log.size() == len); ut_ad(len > 0); - if (m_impl->m_log.is_small()) { - const mtr_buf_t::block_t* front = m_impl->m_log.front(); + lsn_t start_lsn; + + if (m_log.is_small()) { + const mtr_buf_t::block_t* front = m_log.front(); ut_ad(len <= front->used()); - m_end_lsn = log_reserve_and_write_fast( - front->begin(), len, &m_start_lsn); + m_commit_lsn = log_reserve_and_write_fast(front->begin(), len, + &start_lsn); - if (m_end_lsn > 0) { - return; + if (m_commit_lsn) { + return start_lsn; } } /* Open the database log for log_write_low */ - m_start_lsn = log_reserve_and_open(len); + start_lsn = log_reserve_and_open(len); mtr_write_log_t write_log; - m_impl->m_log.for_each_block(write_log); + m_log.for_each_block(write_log); - m_end_lsn = log_close(); -} - -/** Release the latches and blocks acquired by this mini-transaction */ -void -mtr_t::Command::release_all() -{ - m_impl->m_memo.for_each_block_in_reverse(CIterate()); - - /* Note that we have released the latches. */ - m_locks_released = 1; -} - -/** Release the latches acquired by this mini-transaction */ -void -mtr_t::Command::release_latches() -{ - m_impl->m_memo.for_each_block_in_reverse(CIterate()); - - /* Note that we have released the latches. */ - m_locks_released = 1; -} - -/** Release the blocks used in this mini-transaction */ -void -mtr_t::Command::release_blocks() -{ - m_impl->m_memo.for_each_block_in_reverse( - CIterate( - ReleaseBlocks(m_start_lsn, m_end_lsn, - m_impl->m_flush_observer))); -} - -/** Write the redo log record, add dirty pages to the flush list and release -the resources. */ -void -mtr_t::Command::execute() -{ - ut_ad(m_impl->m_log_mode != MTR_LOG_NONE); - - if (const ulint len = prepare_write()) { - finish_write(len); - } - - if (m_impl->m_made_dirty) { - log_flush_order_mutex_enter(); - } - - /* It is now safe to release the log mutex because the - flush_order mutex will ensure that we are the first one - to insert into the flush list. */ - log_mutex_exit(); - - m_impl->m_mtr->m_commit_lsn = m_end_lsn; - - release_blocks(); - - if (m_impl->m_made_dirty) { - log_flush_order_mutex_exit(); - } - - release_latches(); - - release_resources(); + m_commit_lsn = log_close(); + return start_lsn; } /** Release the free extents that was reserved using @@ -966,23 +827,22 @@ mtr_t::release_free_extents(ulint n_reserved) { fil_space_t* space; - ut_ad(m_impl.m_undo_space == NULL); + ut_ad(!m_undo_space); - if (m_impl.m_user_space != NULL) { + if (m_user_space) { - ut_ad(m_impl.m_user_space->id - == m_impl.m_user_space_id); - ut_ad(memo_contains(get_memo(), &m_impl.m_user_space->latch, + ut_ad(m_user_space->id == m_user_space_id); + ut_ad(memo_contains(get_memo(), &m_user_space->latch, MTR_MEMO_X_LOCK)); - space = m_impl.m_user_space; + space = m_user_space; } else { - ut_ad(m_impl.m_sys_space->id == TRX_SYS_SPACE); - ut_ad(memo_contains(get_memo(), &m_impl.m_sys_space->latch, + ut_ad(m_sys_space->id == TRX_SYS_SPACE); + ut_ad(memo_contains(get_memo(), &m_sys_space->latch, MTR_MEMO_X_LOCK)); - space = m_impl.m_sys_space; + space = m_sys_space; } space->release_free_extents(n_reserved); @@ -1084,10 +944,9 @@ struct FlaggedCheck { bool mtr_t::memo_contains_flagged(const void* ptr, ulint flags) const { - ut_ad(m_impl.m_magic_n == MTR_MAGIC_N); - ut_ad(is_committing() || is_active()); + ut_ad(is_active()); - return !m_impl.m_memo.for_each_block_in_reverse( + return !m_memo.for_each_block_in_reverse( CIterate(FlaggedCheck(ptr, flags))); } @@ -1103,7 +962,7 @@ mtr_t::memo_contains_page_flagged( ulint flags) const { Iterate iteration(FindPage(ptr, flags)); - return m_impl.m_memo.for_each_block_in_reverse(iteration) + return m_memo.for_each_block_in_reverse(iteration) ? NULL : iteration.functor.get_block(); } @@ -1126,7 +985,7 @@ void mtr_t::print() const { ib::info() << "Mini-transaction handle: memo size " - << m_impl.m_memo.size() << " bytes log size " + << m_memo.size() << " bytes log size " << get_log()->size() << " bytes"; }