diff options
author | Eugene Kosov <claprix@yandex.ru> | 2019-05-14 17:59:47 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-05-15 15:25:10 +0300 |
commit | 56976e60f5f6dfae026a4aa1c5e7be935c1478b0 (patch) | |
tree | deef30819305f30ac6bbb6f83a83126c02b4eadb | |
parent | 409e210e74a6dc7a6e267c71ab32677b2bf12103 (diff) | |
download | mariadb-git-56976e60f5f6dfae026a4aa1c5e7be935c1478b0.tar.gz |
MDEV-13080 [ERROR] InnoDB: Missing MLOG_CHECKPOINT between the checkpoint x and the end y
log_buffer_extend(): Do not write to disk. Just allocate new bigger
buffer and copy contents of old one to it. Do not acquire write_mutex.
log_t::is_extending: Removed as unneeded now.
LOG_BUFFER_SIZE: Removed to make the dependence on srv_log_buffer_size
visible.
-rw-r--r-- | storage/innobase/include/log0log.h | 4 | ||||
-rw-r--r-- | storage/innobase/log/log0log.cc | 116 |
2 files changed, 32 insertions, 88 deletions
diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h index d71a34c98d8..4864041ef51 100644 --- a/storage/innobase/include/log0log.h +++ b/storage/innobase/include/log0log.h @@ -411,8 +411,6 @@ extern my_bool innodb_log_checksums; /* The counting of lsn's starts from this value: this must be non-zero */ #define LOG_START_LSN ((lsn_t) (16 * OS_FILE_LOG_BLOCK_SIZE)) -#define LOG_BUFFER_SIZE (srv_log_buffer_size * UNIV_PAGE_SIZE) - /* Offsets of a log block header */ #define LOG_BLOCK_HDR_NO 0 /* block number which must be > 0 and is allowed to wrap around at 2G; the @@ -644,8 +642,6 @@ struct log_t{ later; this is advanced when a flush operation is completed to all the log groups */ - volatile bool is_extending; /*!< this is set to true during extend - the log buffer size */ lsn_t write_lsn; /*!< last written lsn */ lsn_t current_flush_lsn;/*!< end lsn for the current running write + flush operation */ diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc index b912a15791e..1d98f92bff0 100644 --- a/storage/innobase/log/log0log.cc +++ b/storage/innobase/log/log0log.cc @@ -169,89 +169,52 @@ void log_buffer_extend( ulint len) { - ulint move_start; - ulint move_end; - byte tmp_buf[OS_FILE_LOG_BLOCK_SIZE]; + const ulint new_log_buffer_size = (len >> srv_page_size_shift) + 1; + const ulint new_buf_size = (new_log_buffer_size + << (srv_page_size_shift + 1)) + + OS_FILE_LOG_BLOCK_SIZE; + byte* new_buf_ptr = static_cast<byte*>(ut_malloc_nokey(new_buf_size)); - log_mutex_enter_all(); - - while (log_sys->is_extending) { - /* Another thread is trying to extend already. - Needs to wait for. */ - log_mutex_exit_all(); - - log_buffer_flush_to_disk(); - - log_mutex_enter_all(); - - if (srv_log_buffer_size > len / UNIV_PAGE_SIZE) { - /* Already extended enough by the others */ - log_mutex_exit_all(); - return; - } - } + log_mutex_enter(); - if (len >= log_sys->buf_size / 2) { - DBUG_EXECUTE_IF("ib_log_buffer_is_short_crash", - DBUG_SUICIDE();); + const ulint size = srv_log_buffer_size << srv_page_size_shift; - /* log_buffer is too small. try to extend instead of crash. */ - ib::warn() << "The transaction log size is too large" - " for innodb_log_buffer_size (" << len << " >= " - << LOG_BUFFER_SIZE << " / 2). Trying to extend it."; + if (len <= size) { + /* Already extended enough by the others */ + log_mutex_exit(); + ut_free(new_buf_ptr); + return; } - log_sys->is_extending = true; + ib::warn() << "The transaction log size is too large" + " for innodb_log_buffer_size (" << len + << " >= " << size << " / 2). Trying to extend it."; - while ((log_sys->buf_free ^ log_sys->buf_next_to_write) - & (OS_FILE_LOG_BLOCK_SIZE - 1)) { - /* Buffer might have >1 blocks to write still. */ - log_mutex_exit_all(); + byte* old_buf_ptr = log_sys->buf_ptr; + const byte* begin = log_sys->buf; + const byte* end = begin + log_sys->buf_free; - log_buffer_flush_to_disk(); + log_sys->buf_ptr = new_buf_ptr; + srv_log_buffer_size = new_log_buffer_size; + log_sys->buf_size = size; + log_sys->buf + = static_cast<byte*>(ut_align(new_buf_ptr, OS_FILE_LOG_BLOCK_SIZE)); - log_mutex_enter_all(); + if (!log_sys->first_in_use) { + log_sys->buf += size; } - move_start = ut_2pow_round(log_sys->buf_free, - ulint(OS_FILE_LOG_BLOCK_SIZE)); - move_end = log_sys->buf_free; - - /* store the last log block in buffer */ - ut_memcpy(tmp_buf, log_sys->buf + move_start, - move_end - move_start); - - log_sys->buf_free -= move_start; - log_sys->buf_next_to_write -= move_start; + memcpy(log_sys->buf, begin, end - begin); - /* reallocate log buffer */ - srv_log_buffer_size = len / UNIV_PAGE_SIZE + 1; - ut_free(log_sys->buf_ptr); - - log_sys->buf_size = LOG_BUFFER_SIZE; - - log_sys->buf_ptr = static_cast<byte*>( - ut_zalloc_nokey(log_sys->buf_size * 2 + OS_FILE_LOG_BLOCK_SIZE)); - TRASH_ALLOC(log_sys->buf_ptr, - log_sys->buf_size * 2 + OS_FILE_LOG_BLOCK_SIZE); - log_sys->buf = static_cast<byte*>( - ut_align(log_sys->buf_ptr, OS_FILE_LOG_BLOCK_SIZE)); - - log_sys->first_in_use = true; - - log_sys->max_buf_free = log_sys->buf_size / LOG_BUF_FLUSH_RATIO + log_sys->max_buf_free = size / LOG_BUF_FLUSH_RATIO - LOG_BUF_FLUSH_MARGIN; - /* restore the last log block */ - ut_memcpy(log_sys->buf, tmp_buf, move_end - move_start); - - ut_ad(log_sys->is_extending); - log_sys->is_extending = false; + log_mutex_exit(); - log_mutex_exit_all(); + ut_free(old_buf_ptr); ib::info() << "innodb_log_buffer_size was extended to " - << LOG_BUFFER_SIZE << "."; + << size << "."; } /** Calculate actual length in redo buffer and file including @@ -360,20 +323,6 @@ log_reserve_and_open( loop: ut_ad(log_mutex_own()); - if (log_sys->is_extending) { - log_mutex_exit(); - - /* Log buffer size is extending. Writing up to the next block - should wait for the extending finished. */ - - os_thread_sleep(100000); - - ut_ad(++count < 50); - - log_mutex_enter(); - goto loop; - } - /* Calculate an upper limit for the space the string may take in the log buffer */ @@ -718,10 +667,9 @@ log_sys_init() log_sys->lsn = LOG_START_LSN; - ut_a(LOG_BUFFER_SIZE >= 16 * OS_FILE_LOG_BLOCK_SIZE); - ut_a(LOG_BUFFER_SIZE >= 4 * UNIV_PAGE_SIZE); + ut_ad(srv_log_buffer_size >= 4); - log_sys->buf_size = LOG_BUFFER_SIZE; + log_sys->buf_size = srv_log_buffer_size << srv_page_size_shift; log_sys->buf_ptr = static_cast<byte*>( ut_zalloc_nokey(log_sys->buf_size * 2 + OS_FILE_LOG_BLOCK_SIZE)); |