void buf_LRU_block_free_non_file_page( /*=============================*/ buf_block_t* block) /* in: block, must not contain a file page */ { ut_ad(mutex_own(&(buf_pool->mutex))); ut_ad(mutex_own(&block->mutex)); ut_ad(block); ut_a((block->state == BUF_BLOCK_MEMORY) || (block->state == BUF_BLOCK_READY_FOR_USE)); ut_a(block->n_pointers == 0); ut_a(!block->in_free_list); block->state = BUF_BLOCK_NOT_USED; UNIV_MEM_ALLOC(block->frame, UNIV_PAGE_SIZE); #ifdef UNIV_DEBUG /* Wipe contents of page to reveal possible stale pointers to it */ memset(block->frame, '\0', UNIV_PAGE_SIZE); #endif UT_LIST_ADD_FIRST(free, buf_pool->free, block); block->in_free_list = TRUE; UNIV_MEM_ASSERT_AND_FREE(block->frame, UNIV_PAGE_SIZE); if (srv_use_awe && block->frame) { /* Add to the list of mapped pages */ UT_LIST_ADD_FIRST(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, block); } }
/********************************************************************//** Creates a cache of column prefixes of externally stored columns. @return own: column prefix cache */ UNIV_INTERN row_ext_t* row_ext_create( /*===========*/ ulint n_ext, /*!< in: number of externally stored columns */ const ulint* ext, /*!< in: col_no's of externally stored columns in the InnoDB table object, as reported by dict_col_get_no(); NOT relative to the records in the clustered index */ ulint flags, /*!< in: table->flags */ const dtuple_t* tuple, /*!< in: data tuple containing the field references of the externally stored columns; must be indexed by col_no; the clustered index record must be covered by a lock or a page latch to prevent deletion (rollback or purge). */ mem_heap_t* heap) /*!< in: heap where created */ { ulint i; ulint zip_size = dict_table_flags_to_zip_size(flags); row_ext_t* ret = mem_heap_alloc(heap, (sizeof *ret) + (n_ext - 1) * sizeof ret->len); ut_ad(ut_is_2pow(zip_size)); ut_ad(zip_size <= UNIV_PAGE_SIZE); ret->n_ext = n_ext; ret->ext = ext; ret->max_len = DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags); ret->buf = mem_heap_alloc(heap, n_ext * ret->max_len); #ifdef UNIV_DEBUG memset(ret->buf, 0xaa, n_ext * ret->max_len); UNIV_MEM_ALLOC(ret->buf, n_ext * ret->max_len); #endif /* Fetch the BLOB prefixes */ for (i = 0; i < n_ext; i++) { const dfield_t* dfield; dfield = dtuple_get_nth_field(tuple, ext[i]); row_ext_cache_fill(ret, i, zip_size, dfield); } return(ret); }
/**********************************************************************//** Try to allocate a block from buf_pool->zip_free[]. @return allocated block, or NULL if buf_pool->zip_free[] was empty */ static void* buf_buddy_alloc_zip( /*================*/ buf_pool_t* buf_pool, /*!< in: buffer pool instance */ ulint i) /*!< in: index of buf_pool->zip_free[] */ { buf_page_t* bpage; ut_ad(buf_pool_mutex_own(buf_pool)); ut_a(i < BUF_BUDDY_SIZES); ut_a(i >= buf_buddy_get_slot(PAGE_ZIP_MIN_SIZE)); ut_d(BUF_BUDDY_LIST_VALIDATE(buf_pool, i)); bpage = UT_LIST_GET_FIRST(buf_pool->zip_free[i]); if (bpage) { ut_a(buf_page_get_state(bpage) == BUF_BLOCK_ZIP_FREE); buf_buddy_remove_from_free(buf_pool, bpage, i); } else if (i + 1 < BUF_BUDDY_SIZES) { /* Attempt to split. */ bpage = buf_buddy_alloc_zip(buf_pool, i + 1); if (bpage) { buf_page_t* buddy = (buf_page_t*) (((char*) bpage) + (BUF_BUDDY_LOW << i)); ut_ad(!buf_pool_contains_zip(buf_pool, buddy)); ut_d(memset(buddy, i, BUF_BUDDY_LOW << i)); buddy->state = BUF_BLOCK_ZIP_FREE; buf_buddy_add_to_free(buf_pool, buddy, i); } } if (bpage) { ut_d(memset(bpage, ~i, BUF_BUDDY_LOW << i)); UNIV_MEM_ALLOC(bpage, BUF_BUDDY_SIZES << i); } return(bpage); }
/**********************************************************************//** Allocates memory. @return own: allocated memory */ UNIV_INTERN void* ut_malloc_low( /*==========*/ ulint n, /*!< in: number of bytes to allocate */ ibool assert_on_error)/*!< in: if TRUE, we crash mysqld if the memory cannot be allocated */ { #ifndef UNIV_HOTBACKUP ulint retry_count; void* ret; if (UNIV_LIKELY(srv_use_sys_malloc)) { ret = malloc(n); ut_a(ret || !assert_on_error); return(ret); } ut_ad((sizeof(ut_mem_block_t) % 8) == 0); /* check alignment ok */ ut_a(ut_mem_block_list_inited); retry_count = 0; retry: os_fast_mutex_lock(&ut_list_mutex); ret = malloc(n + sizeof(ut_mem_block_t)); if (ret == NULL && retry_count < 60) { if (retry_count == 0) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error: cannot allocate" " %lu bytes of\n" "InnoDB: memory with malloc!" " Total allocated memory\n" "InnoDB: by InnoDB %lu bytes." " Operating system errno: %lu\n" "InnoDB: Check if you should" " increase the swap file or\n" "InnoDB: ulimits of your operating system.\n" "InnoDB: On FreeBSD check you" " have compiled the OS with\n" "InnoDB: a big enough maximum process size.\n" "InnoDB: Note that in most 32-bit" " computers the process\n" "InnoDB: memory space is limited" " to 2 GB or 4 GB.\n" "InnoDB: We keep retrying" " the allocation for 60 seconds...\n", (ulong) n, (ulong) ut_total_allocated_memory, #ifdef __WIN__ (ulong) GetLastError() #else (ulong) errno #endif ); } os_fast_mutex_unlock(&ut_list_mutex); /* Sleep for a second and retry the allocation; maybe this is just a temporary shortage of memory */ os_thread_sleep(1000000); retry_count++; goto retry; } if (ret == NULL) { /* Flush stderr to make more probable that the error message gets in the error file before we generate a seg fault */ fflush(stderr); os_fast_mutex_unlock(&ut_list_mutex); /* Make an intentional seg fault so that we get a stack trace */ if (assert_on_error) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: We now intentionally" " generate a seg fault so that\n" "InnoDB: on Linux we get a stack trace.\n"); if (*ut_mem_null_ptr) ut_mem_null_ptr = 0; } else { return(NULL); } } UNIV_MEM_ALLOC(ret, n + sizeof(ut_mem_block_t)); ((ut_mem_block_t*)ret)->size = n + sizeof(ut_mem_block_t); ((ut_mem_block_t*)ret)->magic_n = UT_MEM_MAGIC_N; ut_total_allocated_memory += n + sizeof(ut_mem_block_t); UT_LIST_ADD_FIRST(mem_block_list, ut_mem_block_list, ((ut_mem_block_t*)ret)); os_fast_mutex_unlock(&ut_list_mutex); return((void*)((byte*)ret + sizeof(ut_mem_block_t))); #else /* !UNIV_HOTBACKUP */ void* ret = malloc(n); ut_a(ret || !assert_on_error); return(ret); #endif /* !UNIV_HOTBACKUP */ }
/********************************************************************//** Allocates memory from a pool. NOTE: This low-level function should only be used in mem0mem.*! @return own: allocated memory buffer */ UNIV_INTERN void* mem_area_alloc( /*===========*/ ulint* psize, /*!< in: requested size in bytes; for optimum space usage, the size should be a power of 2 minus MEM_AREA_EXTRA_SIZE; out: allocated size in bytes (greater than or equal to the requested size) */ mem_pool_t* pool) /*!< in: memory pool */ { mem_area_t* area; ulint size; ulint n; ibool ret; /* If we are using os allocator just make a simple call to malloc */ if (UNIV_LIKELY(srv_use_sys_malloc)) { return(malloc(*psize)); } size = *psize; n = ut_2_log(ut_max(size + MEM_AREA_EXTRA_SIZE, MEM_AREA_MIN_SIZE)); mutex_enter(&(pool->mutex)); mem_n_threads_inside++; ut_a(mem_n_threads_inside == 1); area = UT_LIST_GET_FIRST(pool->free_list[n]); if (area == NULL) { ret = mem_pool_fill_free_list(n, pool); if (ret == FALSE) { /* Out of memory in memory pool: we try to allocate from the operating system with the regular malloc: */ mem_n_threads_inside--; mutex_exit(&(pool->mutex)); return(ut_malloc(size)); } area = UT_LIST_GET_FIRST(pool->free_list[n]); } if (!mem_area_get_free(area)) { fprintf(stderr, "InnoDB: Error: Removing element from mem pool" " free list %lu though the\n" "InnoDB: element is not marked free!\n", (ulong) n); mem_analyze_corruption(area); /* Try to analyze a strange assertion failure reported at [email protected] where the free bit IS 1 in the hex dump above */ if (mem_area_get_free(area)) { fprintf(stderr, "InnoDB: Probably a race condition" " because now the area is marked free!\n"); } ut_error; } if (UT_LIST_GET_LEN(pool->free_list[n]) == 0) { fprintf(stderr, "InnoDB: Error: Removing element from mem pool" " free list %lu\n" "InnoDB: though the list length is 0!\n", (ulong) n); mem_analyze_corruption(area); ut_error; } ut_ad(mem_area_get_size(area) == ut_2_exp(n)); mem_area_set_free(area, FALSE); UT_LIST_REMOVE(free_list, pool->free_list[n], area); pool->reserved += mem_area_get_size(area); mem_n_threads_inside--; mutex_exit(&(pool->mutex)); ut_ad(mem_pool_validate(pool)); *psize = ut_2_exp(n) - MEM_AREA_EXTRA_SIZE; UNIV_MEM_ALLOC(MEM_AREA_EXTRA_SIZE + (byte*)area, *psize); return((void*)(MEM_AREA_EXTRA_SIZE + ((byte*)area))); }
/********************************************************************//** Fills the specified free list. @return TRUE if we were able to insert a block to the free list */ static ibool mem_pool_fill_free_list( /*====================*/ ulint i, /*!< in: free list index */ mem_pool_t* pool) /*!< in: memory pool */ { mem_area_t* area; mem_area_t* area2; ibool ret; ut_ad(mutex_own(&(pool->mutex))); if (UNIV_UNLIKELY(i >= 63)) { /* We come here when we have run out of space in the memory pool: */ return(FALSE); } area = UT_LIST_GET_FIRST(pool->free_list[i + 1]); if (area == NULL) { if (UT_LIST_GET_LEN(pool->free_list[i + 1]) > 0) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error: mem pool free list %lu" " length is %lu\n" "InnoDB: though the list is empty!\n", (ulong) i + 1, (ulong) UT_LIST_GET_LEN(pool->free_list[i + 1])); } ret = mem_pool_fill_free_list(i + 1, pool); if (ret == FALSE) { return(FALSE); } area = UT_LIST_GET_FIRST(pool->free_list[i + 1]); } if (UNIV_UNLIKELY(UT_LIST_GET_LEN(pool->free_list[i + 1]) == 0)) { mem_analyze_corruption(area); ut_error; } UT_LIST_REMOVE(free_list, pool->free_list[i + 1], area); area2 = (mem_area_t*)(((byte*)area) + ut_2_exp(i)); UNIV_MEM_ALLOC(area2, MEM_AREA_EXTRA_SIZE); mem_area_set_size(area2, ut_2_exp(i)); mem_area_set_free(area2, TRUE); UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area2); mem_area_set_size(area, ut_2_exp(i)); UT_LIST_ADD_FIRST(free_list, pool->free_list[i], area); return(TRUE); }
/**************************************************************//** Moves parts of long fields in entry to the big record vector so that the size of tuple drops below the maximum record size allowed in the database. Moves data only from those fields which are not necessary to determine uniquely the insertion place of the tuple in the index. @return own: created big record vector, NULL if we are not able to shorten the entry enough, i.e., if there are too many fixed-length or short fields in entry or the index is clustered */ UNIV_INTERN big_rec_t* dtuple_convert_big_rec( /*===================*/ dict_index_t* index, /*!< in: index */ dtuple_t* entry, /*!< in/out: index entry */ ulint* n_ext) /*!< in/out: number of externally stored columns */ { mem_heap_t* heap; big_rec_t* vector; dfield_t* dfield; dict_field_t* ifield; ulint size; ulint n_fields; ulint local_len; ulint local_prefix_len; if (UNIV_UNLIKELY(!dict_index_is_clust(index))) { return(NULL); } if (dict_table_get_format(index->table) < DICT_TF_FORMAT_ZIP) { /* up to MySQL 5.1: store a 768-byte prefix locally */ local_len = BTR_EXTERN_FIELD_REF_SIZE + DICT_MAX_INDEX_COL_LEN; } else { /* new-format table: do not store any BLOB prefix locally */ local_len = BTR_EXTERN_FIELD_REF_SIZE; } ut_a(dtuple_check_typed_no_assert(entry)); size = rec_get_converted_size(index, entry, *n_ext); if (UNIV_UNLIKELY(size > 1000000000)) { fprintf(stderr, "InnoDB: Warning: tuple size very big: %lu\n", (ulong) size); fputs("InnoDB: Tuple contents: ", stderr); dtuple_print(stderr, entry); putc('\n', stderr); } heap = mem_heap_create(size + dtuple_get_n_fields(entry) * sizeof(big_rec_field_t) + 1000); vector = mem_heap_alloc(heap, sizeof(big_rec_t)); vector->heap = heap; vector->fields = mem_heap_alloc(heap, dtuple_get_n_fields(entry) * sizeof(big_rec_field_t)); /* Decide which fields to shorten: the algorithm is to look for a variable-length field that yields the biggest savings when stored externally */ n_fields = 0; while (page_zip_rec_needs_ext(rec_get_converted_size(index, entry, *n_ext), dict_table_is_comp(index->table), dict_index_get_n_fields(index), dict_table_zip_size(index->table))) { ulint i; ulint longest = 0; ulint longest_i = ULINT_MAX; byte* data; big_rec_field_t* b; for (i = dict_index_get_n_unique_in_tree(index); i < dtuple_get_n_fields(entry); i++) { ulint savings; dfield = dtuple_get_nth_field(entry, i); ifield = dict_index_get_nth_field(index, i); /* Skip fixed-length, NULL, externally stored, or short columns */ if (ifield->fixed_len || dfield_is_null(dfield) || dfield_is_ext(dfield) || dfield_get_len(dfield) <= local_len || dfield_get_len(dfield) <= BTR_EXTERN_FIELD_REF_SIZE * 2) { goto skip_field; } savings = dfield_get_len(dfield) - local_len; /* Check that there would be savings */ if (longest >= savings) { goto skip_field; } longest_i = i; longest = savings; skip_field: continue; } if (!longest) { /* Cannot shorten more */ mem_heap_free(heap); return(NULL); } /* Move data from field longest_i to big rec vector. We store the first bytes locally to the record. Then we can calculate all ordering fields in all indexes from locally stored data. */ dfield = dtuple_get_nth_field(entry, longest_i); ifield = dict_index_get_nth_field(index, longest_i); local_prefix_len = local_len - BTR_EXTERN_FIELD_REF_SIZE; b = &vector->fields[n_fields]; b->field_no = longest_i; b->len = dfield_get_len(dfield) - local_prefix_len; b->data = (char*) dfield_get_data(dfield) + local_prefix_len; /* Allocate the locally stored part of the column. */ data = mem_heap_alloc(heap, local_len); /* Copy the local prefix. */ memcpy(data, dfield_get_data(dfield), local_prefix_len); /* Clear the extern field reference (BLOB pointer). */ memset(data + local_prefix_len, 0, BTR_EXTERN_FIELD_REF_SIZE); #if 0 /* The following would fail the Valgrind checks in page_cur_insert_rec_low() and page_cur_insert_rec_zip(). The BLOB pointers in the record will be initialized after the record and the BLOBs have been written. */ UNIV_MEM_ALLOC(data + local_prefix_len, BTR_EXTERN_FIELD_REF_SIZE); #endif dfield_set_data(dfield, data, local_len); dfield_set_ext(dfield); n_fields++; (*n_ext)++; ut_ad(n_fields < dtuple_get_n_fields(entry)); } vector->n_fields = n_fields; return(vector); }
/****************************************************************//** Allocates large pages memory. @return allocated memory */ UNIV_INTERN void* os_mem_alloc_large( /*===============*/ ulint* n) /*!< in/out: number of bytes */ { void* ptr; ulint size; #if defined HAVE_LARGE_PAGES && defined UNIV_LINUX int shmid; struct shmid_ds buf; if (!os_use_large_pages || !os_large_page_size) { goto skip; } /* Align block size to os_large_page_size */ ut_ad(ut_is_2pow(os_large_page_size)); size = ut_2pow_round(*n + (os_large_page_size - 1), os_large_page_size); shmid = shmget(IPC_PRIVATE, (size_t)size, SHM_HUGETLB | SHM_R | SHM_W); if (shmid < 0) { fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to allocate" " %lu bytes. errno %d\n", size, errno); ptr = NULL; } else { ptr = shmat(shmid, NULL, 0); if (ptr == (void *)-1) { fprintf(stderr, "InnoDB: HugeTLB: Warning: Failed to" " attach shared memory segment, errno %d\n", errno); ptr = NULL; } /* Remove the shared memory segment so that it will be automatically freed after memory is detached or process exits */ shmctl(shmid, IPC_RMID, &buf); } if (ptr) { *n = size; os_fast_mutex_lock(&ut_list_mutex); ut_total_allocated_memory += size; os_fast_mutex_unlock(&ut_list_mutex); UNIV_MEM_ALLOC(ptr, size); return(ptr); } fprintf(stderr, "InnoDB HugeTLB: Warning: Using conventional" " memory pool\n"); skip: #endif /* HAVE_LARGE_PAGES && UNIV_LINUX */ #ifdef __WIN__ SYSTEM_INFO system_info; GetSystemInfo(&system_info); /* Align block size to system page size */ ut_ad(ut_is_2pow(system_info.dwPageSize)); /* system_info.dwPageSize is only 32-bit. Casting to ulint is required on 64-bit Windows. */ size = *n = ut_2pow_round(*n + (system_info.dwPageSize - 1), (ulint) system_info.dwPageSize); ptr = VirtualAlloc(NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (!ptr) { fprintf(stderr, "InnoDB: VirtualAlloc(%lu bytes) failed;" " Windows error %lu\n", (ulong) size, (ulong) GetLastError()); } else { os_fast_mutex_lock(&ut_list_mutex); ut_total_allocated_memory += size; os_fast_mutex_unlock(&ut_list_mutex); UNIV_MEM_ALLOC(ptr, size); } #elif !defined OS_MAP_ANON size = *n; ptr = ut_malloc_low(size, TRUE, FALSE); #else # ifdef HAVE_GETPAGESIZE size = getpagesize(); # else size = UNIV_PAGE_SIZE; # endif /* Align block size to system page size */ ut_ad(ut_is_2pow(size)); size = *n = ut_2pow_round(*n + (size - 1), size); ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | OS_MAP_ANON, -1, 0); if (UNIV_UNLIKELY(ptr == (void*) -1)) { fprintf(stderr, "InnoDB: mmap(%lu bytes) failed;" " errno %lu\n", (ulong) size, (ulong) errno); ptr = NULL; } else { os_fast_mutex_lock(&ut_list_mutex); ut_total_allocated_memory += size; os_fast_mutex_unlock(&ut_list_mutex); UNIV_MEM_ALLOC(ptr, size); } #endif return(ptr); }
buf_block_t* buf_LRU_get_free_block(void) /*========================*/ /* out: the free control block; also if AWE is used, it is guaranteed that the block has its page mapped to a frame when we return */ { buf_block_t* block = NULL; ibool freed; ulint n_iterations = 1; ibool mon_value_was = FALSE; ibool started_monitor = FALSE; loop: mutex_enter(&(buf_pool->mutex)); if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 20) { ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: ERROR: over 95 percent of the buffer pool" " is occupied by\n" "InnoDB: lock heaps or the adaptive hash index!" " Check that your\n" "InnoDB: transactions do not set too many row locks.\n" "InnoDB: Your buffer pool size is %lu MB." " Maybe you should make\n" "InnoDB: the buffer pool bigger?\n" "InnoDB: We intentionally generate a seg fault" " to print a stack trace\n" "InnoDB: on Linux!\n", (ulong) (buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE))); ut_error; } else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 3) { if (!buf_lru_switched_on_innodb_mon) { /* Over 67 % of the buffer pool is occupied by lock heaps or the adaptive hash index. This may be a memory leak! */ ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: WARNING: over 67 percent of" " the buffer pool is occupied by\n" "InnoDB: lock heaps or the adaptive" " hash index! Check that your\n" "InnoDB: transactions do not set too many" " row locks.\n" "InnoDB: Your buffer pool size is %lu MB." " Maybe you should make\n" "InnoDB: the buffer pool bigger?\n" "InnoDB: Starting the InnoDB Monitor to print" " diagnostics, including\n" "InnoDB: lock heap and hash index sizes.\n", (ulong) (buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE))); buf_lru_switched_on_innodb_mon = TRUE; srv_print_innodb_monitor = TRUE; os_event_set(srv_lock_timeout_thread_event); } } else if (buf_lru_switched_on_innodb_mon) { /* Switch off the InnoDB Monitor; this is a simple way to stop the monitor if the situation becomes less urgent, but may also surprise users if the user also switched on the monitor! */ buf_lru_switched_on_innodb_mon = FALSE; srv_print_innodb_monitor = FALSE; } /* If there is a block in the free list, take it */ if (UT_LIST_GET_LEN(buf_pool->free) > 0) { block = UT_LIST_GET_FIRST(buf_pool->free); ut_a(block->in_free_list); UT_LIST_REMOVE(free, buf_pool->free, block); block->in_free_list = FALSE; ut_a(block->state != BUF_BLOCK_FILE_PAGE); ut_a(!block->in_LRU_list); if (srv_use_awe) { if (block->frame) { /* Remove from the list of mapped pages */ UT_LIST_REMOVE(awe_LRU_free_mapped, buf_pool->awe_LRU_free_mapped, block); } else { /* We map the page to a frame; second param FALSE below because we do not want it to be added to the awe_LRU_free_mapped list */ buf_awe_map_page_to_frame(block, FALSE); } } mutex_enter(&block->mutex); block->state = BUF_BLOCK_READY_FOR_USE; UNIV_MEM_ALLOC(block->frame, UNIV_PAGE_SIZE); mutex_exit(&block->mutex); mutex_exit(&(buf_pool->mutex)); if (started_monitor) { srv_print_innodb_monitor = mon_value_was; } return(block); } /* If no block was in the free list, search from the end of the LRU list and try to free a block there */ mutex_exit(&(buf_pool->mutex)); freed = buf_LRU_search_and_free_block(n_iterations); if (freed > 0) { goto loop; } if (n_iterations > 30) { ut_print_timestamp(stderr); fprintf(stderr, "InnoDB: Warning: difficult to find free blocks from\n" "InnoDB: the buffer pool (%lu search iterations)!" " Consider\n" "InnoDB: increasing the buffer pool size.\n" "InnoDB: It is also possible that" " in your Unix version\n" "InnoDB: fsync is very slow, or" " completely frozen inside\n" "InnoDB: the OS kernel. Then upgrading to" " a newer version\n" "InnoDB: of your operating system may help." " Look at the\n" "InnoDB: number of fsyncs in diagnostic info below.\n" "InnoDB: Pending flushes (fsync) log: %lu;" " buffer pool: %lu\n" "InnoDB: %lu OS file reads, %lu OS file writes," " %lu OS fsyncs\n" "InnoDB: Starting InnoDB Monitor to print further\n" "InnoDB: diagnostics to the standard output.\n", (ulong) n_iterations, (ulong) fil_n_pending_log_flushes, (ulong) fil_n_pending_tablespace_flushes, (ulong) os_n_file_reads, (ulong) os_n_file_writes, (ulong) os_n_fsyncs); mon_value_was = srv_print_innodb_monitor; started_monitor = TRUE; srv_print_innodb_monitor = TRUE; os_event_set(srv_lock_timeout_thread_event); } /* No free block was found: try to flush the LRU list */ buf_flush_free_margin(); ++srv_buf_pool_wait_free; os_aio_simulated_wake_handler_threads(); mutex_enter(&(buf_pool->mutex)); if (buf_pool->LRU_flush_ended > 0) { /* We have written pages in an LRU flush. To make the insert buffer more efficient, we try to move these pages to the free list. */ mutex_exit(&(buf_pool->mutex)); buf_LRU_try_free_flushed_blocks(); } else { mutex_exit(&(buf_pool->mutex)); } if (n_iterations > 10) { os_thread_sleep(500000); } n_iterations++; goto loop; }