summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Kosov <claprix@yandex.ru>2019-05-14 17:59:47 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2019-05-15 15:25:10 +0300
commit56976e60f5f6dfae026a4aa1c5e7be935c1478b0 (patch)
treedeef30819305f30ac6bbb6f83a83126c02b4eadb
parent409e210e74a6dc7a6e267c71ab32677b2bf12103 (diff)
downloadmariadb-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.h4
-rw-r--r--storage/innobase/log/log0log.cc116
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));