mirror of
https://github.com/MariaDB/server.git
synced 2025-12-13 20:03:16 +03:00
branches/zip: Implement resizeable buffer pool.
mysql.patch: Patch to change or add variables to MySQL innodb.patch: Patch to make the master thread poll requests to resize the buffer pool. Replace srv_pool_size and innobase_buffer_pool_size with srv_buf_pool_size, srv_buf_pool_old_size, and srv_buf_pool_curr_size. Add buf_chunk_t, a collection of buf_block_t.
This commit is contained in:
466
buf/buf0buf.c
466
buf/buf0buf.c
@@ -215,6 +215,15 @@ ibool buf_debug_prints = FALSE; /* If this is set TRUE,
|
||||
read-ahead or flush occurs */
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/* A chunk of buffers. The buffer pool is allocated in chunks. */
|
||||
struct buf_chunk_struct{
|
||||
ulint mem_size; /* allocated size of the chunk */
|
||||
ulint size; /* size of frames[] and blocks[] */
|
||||
void* mem; /* pointer to the memory area which
|
||||
was allocated for the frames */
|
||||
buf_block_t* blocks; /* array of buffer control blocks */
|
||||
};
|
||||
|
||||
/************************************************************************
|
||||
Calculates a page checksum which is stored to the page when it is written
|
||||
to a file. Note that we must be careful to calculate the same value on
|
||||
@@ -626,19 +635,195 @@ buf_block_init(
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Allocates a chunk of buffer frames. */
|
||||
static
|
||||
buf_chunk_t*
|
||||
buf_chunk_init(
|
||||
/*===========*/
|
||||
/* out: chunk, or NULL on failure */
|
||||
buf_chunk_t* chunk, /* out: chunk of buffers */
|
||||
ulint mem_size) /* in: requested size in bytes */
|
||||
{
|
||||
buf_block_t* block;
|
||||
byte* frame;
|
||||
ulint i;
|
||||
|
||||
/* Round down to a multiple of page size,
|
||||
although it already should be. */
|
||||
mem_size = ut_2pow_round(mem_size, UNIV_PAGE_SIZE);
|
||||
/* Reserve space for the block descriptors. */
|
||||
mem_size += ut_2pow_round((mem_size / UNIV_PAGE_SIZE) * (sizeof *block)
|
||||
+ (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
|
||||
|
||||
chunk->mem_size = mem_size;
|
||||
chunk->mem = os_mem_alloc_large(&chunk->mem_size);
|
||||
|
||||
if (UNIV_UNLIKELY(chunk->mem == NULL)) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Allocate the block descriptors from
|
||||
the start of the memory block. */
|
||||
chunk->blocks = chunk->mem;
|
||||
|
||||
/* Align pointer to the first frame */
|
||||
|
||||
frame = ut_align(chunk->mem, UNIV_PAGE_SIZE);
|
||||
chunk->size = chunk->mem_size / UNIV_PAGE_SIZE
|
||||
- (frame != chunk->mem);
|
||||
|
||||
/* Subtract the space needed for block descriptors. */
|
||||
{
|
||||
ulint size = chunk->size;
|
||||
|
||||
while (frame < (byte*) (chunk->blocks + size)) {
|
||||
frame += UNIV_PAGE_SIZE;
|
||||
size--;
|
||||
}
|
||||
|
||||
chunk->size = size;
|
||||
}
|
||||
|
||||
/* Init block structs and assign frames for them. Then we
|
||||
assign the frames to the first blocks (we already mapped the
|
||||
memory above). */
|
||||
|
||||
block = chunk->blocks;
|
||||
|
||||
for (i = chunk->size; i--; ) {
|
||||
|
||||
buf_block_init(block, frame);
|
||||
|
||||
#ifdef HAVE_purify
|
||||
/* Wipe contents of frame to eliminate a Purify warning */
|
||||
memset(block->frame, '\0', UNIV_PAGE_SIZE);
|
||||
#endif
|
||||
/* Add the block to the free list */
|
||||
UT_LIST_ADD_LAST(free, buf_pool->free, block);
|
||||
block->in_free_list = TRUE;
|
||||
|
||||
block++;
|
||||
frame += UNIV_PAGE_SIZE;
|
||||
}
|
||||
|
||||
return(chunk);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Checks that all file pages in the buffer chunk are in a replaceable state. */
|
||||
static
|
||||
const buf_block_t*
|
||||
buf_chunk_not_freed(
|
||||
/*================*/
|
||||
/* out: address of a non-free block,
|
||||
or NULL if all freed */
|
||||
buf_chunk_t* chunk) /* in: chunk being checked */
|
||||
{
|
||||
buf_block_t* block;
|
||||
ulint i;
|
||||
|
||||
ut_ad(buf_pool);
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
block = chunk->blocks;
|
||||
|
||||
for (i = chunk->size; i--; block++) {
|
||||
mutex_enter(&block->mutex);
|
||||
|
||||
if (block->state == BUF_BLOCK_FILE_PAGE
|
||||
&& !buf_flush_ready_for_replace(block)) {
|
||||
|
||||
mutex_exit(&block->mutex);
|
||||
return(block);
|
||||
}
|
||||
|
||||
mutex_exit(&block->mutex);
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Checks that all blocks in the buffer chunk are in BUF_BLOCK_NOT_USED state. */
|
||||
static
|
||||
ibool
|
||||
buf_chunk_all_free(
|
||||
/*===============*/
|
||||
/* out: TRUE if all freed */
|
||||
const buf_chunk_t* chunk) /* in: chunk being checked */
|
||||
{
|
||||
const buf_block_t* block;
|
||||
ulint i;
|
||||
|
||||
ut_ad(buf_pool);
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
block = chunk->blocks;
|
||||
|
||||
for (i = chunk->size; i--; block++) {
|
||||
|
||||
if (block->state != BUF_BLOCK_NOT_USED) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Frees a chunk of buffer frames. */
|
||||
static
|
||||
void
|
||||
buf_chunk_free(
|
||||
/*===========*/
|
||||
buf_chunk_t* chunk) /* out: chunk of buffers */
|
||||
{
|
||||
buf_block_t* block;
|
||||
const buf_block_t* block_end;
|
||||
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
ut_ad(mutex_own(&(buf_pool->mutex)));
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
block_end = chunk->blocks + chunk->size;
|
||||
|
||||
for (block = chunk->blocks; block < block_end; block++) {
|
||||
ut_a(block->state == BUF_BLOCK_NOT_USED);
|
||||
ut_a(!block->page_zip.data);
|
||||
|
||||
/* Remove the block from the free list. */
|
||||
ut_a(block->in_free_list);
|
||||
UT_LIST_REMOVE(free, buf_pool->free, block);
|
||||
|
||||
/* Free the latches. */
|
||||
mutex_free(&block->mutex);
|
||||
rw_lock_free(&block->lock);
|
||||
#ifdef UNIV_SYNC_DEBUG
|
||||
rw_lock_free(&block->debug_latch);
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
}
|
||||
|
||||
os_mem_free_large(chunk->mem, chunk->mem_size);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Creates the buffer pool. */
|
||||
|
||||
buf_pool_t*
|
||||
buf_pool_init(
|
||||
/*==========*/
|
||||
buf_pool_init(void)
|
||||
/*===============*/
|
||||
/* out, own: buf_pool object, NULL if not
|
||||
enough memory or error */
|
||||
ulint curr_size) /* in: current size to use */
|
||||
{
|
||||
byte* frame;
|
||||
buf_chunk_t* chunk;
|
||||
ulint i;
|
||||
buf_block_t* block;
|
||||
|
||||
buf_pool = mem_alloc(sizeof(buf_pool_t));
|
||||
|
||||
@@ -648,49 +833,23 @@ buf_pool_init(
|
||||
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
buf_pool->frame_mem_size = (curr_size + 1) * UNIV_PAGE_SIZE;
|
||||
buf_pool->n_chunks = 1;
|
||||
buf_pool->chunks = chunk = mem_alloc(sizeof *chunk);
|
||||
|
||||
buf_pool->frame_mem = os_mem_alloc_large(&buf_pool->frame_mem_size);
|
||||
|
||||
if (UNIV_UNLIKELY(buf_pool->frame_mem == NULL)) {
|
||||
UT_LIST_INIT(buf_pool->free);
|
||||
|
||||
if (!buf_chunk_init(chunk, srv_buf_pool_size)) {
|
||||
mem_free(chunk);
|
||||
mem_free(buf_pool);
|
||||
buf_pool = NULL;
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* Align pointer to the first frame */
|
||||
srv_buf_pool_old_size = srv_buf_pool_size;
|
||||
buf_pool->curr_size = chunk->size;
|
||||
srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
|
||||
|
||||
frame = ut_align(buf_pool->frame_mem, UNIV_PAGE_SIZE);
|
||||
|
||||
curr_size = buf_pool->frame_mem_size / UNIV_PAGE_SIZE
|
||||
- (frame != buf_pool->frame_mem);
|
||||
|
||||
buf_pool->blocks = ut_malloc(sizeof(buf_block_t) * curr_size);
|
||||
|
||||
if (UNIV_UNLIKELY(buf_pool->blocks == NULL)) {
|
||||
|
||||
os_mem_free_large(buf_pool->frame_mem,
|
||||
buf_pool->frame_mem_size);
|
||||
buf_pool->frame_mem = NULL;
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
buf_pool->curr_size = curr_size;
|
||||
|
||||
/* Init block structs and assign frames for them. Then we
|
||||
assign the frames to the first blocks (we already mapped the
|
||||
memory above). */
|
||||
|
||||
for (i = 0; i < curr_size; i++) {
|
||||
|
||||
block = buf_pool_get_nth_block(buf_pool, i);
|
||||
|
||||
buf_block_init(block, frame);
|
||||
|
||||
frame += UNIV_PAGE_SIZE;
|
||||
}
|
||||
|
||||
buf_pool->page_hash = hash_create(2 * curr_size);
|
||||
buf_pool->page_hash = hash_create(2 * buf_pool->curr_size);
|
||||
|
||||
buf_pool->n_pend_reads = 0;
|
||||
|
||||
@@ -727,33 +886,130 @@ buf_pool_init(
|
||||
|
||||
buf_pool->LRU_old = NULL;
|
||||
|
||||
/* Add control blocks to the free list */
|
||||
UT_LIST_INIT(buf_pool->free);
|
||||
|
||||
for (i = 0; i < curr_size; i++) {
|
||||
|
||||
block = buf_pool_get_nth_block(buf_pool, i);
|
||||
|
||||
if (block->frame) {
|
||||
/* Wipe contents of frame to eliminate a Purify
|
||||
warning */
|
||||
|
||||
#ifdef HAVE_purify
|
||||
memset(block->frame, '\0', UNIV_PAGE_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
UT_LIST_ADD_LAST(free, buf_pool->free, block);
|
||||
block->in_free_list = TRUE;
|
||||
}
|
||||
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
|
||||
btr_search_sys_create(curr_size * UNIV_PAGE_SIZE / sizeof(void*) / 64);
|
||||
btr_search_sys_create(buf_pool->curr_size
|
||||
* UNIV_PAGE_SIZE / sizeof(void*) / 64);
|
||||
|
||||
return(buf_pool);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Resizes the buffer pool. */
|
||||
|
||||
void
|
||||
buf_pool_resize(void)
|
||||
/*=================*/
|
||||
{
|
||||
buf_chunk_t* chunks;
|
||||
buf_chunk_t* chunk;
|
||||
|
||||
mutex_enter(&buf_pool->mutex);
|
||||
|
||||
if (srv_buf_pool_old_size == srv_buf_pool_size) {
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
if (srv_buf_pool_curr_size + 1048576 > srv_buf_pool_size) {
|
||||
|
||||
/* Shrink the buffer pool by at least one megabyte */
|
||||
|
||||
ulint chunk_size
|
||||
= (srv_buf_pool_curr_size - srv_buf_pool_size)
|
||||
/ UNIV_PAGE_SIZE;
|
||||
ulint max_size;
|
||||
buf_chunk_t* max_chunk;
|
||||
|
||||
shrink_again:
|
||||
if (buf_pool->n_chunks <= 1) {
|
||||
|
||||
/* Cannot shrink if there is only one chunk */
|
||||
goto func_done;
|
||||
}
|
||||
|
||||
/* Search for the largest free chunk
|
||||
not larger than the size difference */
|
||||
chunks = buf_pool->chunks;
|
||||
chunk = chunks + buf_pool->n_chunks;
|
||||
max_size = 0;
|
||||
max_chunk = NULL;
|
||||
|
||||
while (--chunk >= chunks) {
|
||||
if (chunk->size <= chunk_size
|
||||
&& chunk->size > max_size
|
||||
&& buf_chunk_all_free(chunk)) {
|
||||
max_size = chunk->size;
|
||||
max_chunk = chunk;
|
||||
}
|
||||
}
|
||||
|
||||
if (!max_size) {
|
||||
|
||||
/* Cannot shrink: try again later
|
||||
(do not assign srv_buf_pool_old_size) */
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
srv_buf_pool_old_size = srv_buf_pool_size;
|
||||
|
||||
/* Rewrite buf_pool->chunks. Copy everything but max_chunk. */
|
||||
chunks = mem_alloc((buf_pool->n_chunks - 1) * sizeof *chunks);
|
||||
memcpy(chunks, buf_pool->chunks,
|
||||
(max_chunk - buf_pool->chunks) * sizeof *chunks);
|
||||
memcpy(chunks + (max_chunk - buf_pool->chunks),
|
||||
max_chunk + 1,
|
||||
buf_pool->chunks + buf_pool->n_chunks
|
||||
- (max_chunk + 1));
|
||||
ut_a(buf_pool->curr_size > max_chunk->size);
|
||||
buf_pool->curr_size -= max_chunk->size;
|
||||
srv_buf_pool_curr_size = buf_pool->curr_size * UNIV_PAGE_SIZE;
|
||||
chunk_size -= max_chunk->size;
|
||||
buf_chunk_free(max_chunk);
|
||||
mem_free(buf_pool->chunks);
|
||||
buf_pool->chunks = chunks;
|
||||
buf_pool->n_chunks--;
|
||||
|
||||
/* Allow a slack of one megabyte. */
|
||||
if (chunk_size > 1048576 / UNIV_PAGE_SIZE) {
|
||||
|
||||
goto shrink_again;
|
||||
}
|
||||
} else if (srv_buf_pool_curr_size + 1048576 < srv_buf_pool_size) {
|
||||
|
||||
/* Enlarge the buffer pool by at least one megabyte */
|
||||
|
||||
ulint mem_size
|
||||
= srv_buf_pool_size - srv_buf_pool_curr_size;
|
||||
|
||||
chunks = mem_alloc((buf_pool->n_chunks + 1) * sizeof *chunks);
|
||||
|
||||
memcpy(chunks, buf_pool->chunks, buf_pool->n_chunks
|
||||
* sizeof *chunks);
|
||||
|
||||
chunk = &chunks[buf_pool->n_chunks];
|
||||
|
||||
if (!buf_chunk_init(chunk, mem_size)) {
|
||||
mem_free(chunks);
|
||||
} else {
|
||||
buf_pool->curr_size += chunk->size;
|
||||
srv_buf_pool_curr_size = buf_pool->curr_size
|
||||
* UNIV_PAGE_SIZE;
|
||||
mem_free(buf_pool->chunks);
|
||||
buf_pool->chunks = chunks;
|
||||
buf_pool->n_chunks++;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: reinitialize buf_pool->page_hash */
|
||||
|
||||
func_done:
|
||||
srv_buf_pool_old_size = srv_buf_pool_size;
|
||||
|
||||
func_exit:
|
||||
mutex_exit(&buf_pool->mutex);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Moves to the block to the start of the LRU list if there is a danger
|
||||
that the block would drift out of the buffer pool. */
|
||||
@@ -1979,7 +2235,7 @@ ibool
|
||||
buf_validate(void)
|
||||
/*==============*/
|
||||
{
|
||||
buf_block_t* block;
|
||||
buf_chunk_t* chunk;
|
||||
ulint i;
|
||||
ulint n_single_flush = 0;
|
||||
ulint n_lru_flush = 0;
|
||||
@@ -1993,43 +2249,51 @@ buf_validate(void)
|
||||
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
for (i = 0; i < buf_pool->curr_size; i++) {
|
||||
chunk = buf_pool->chunks;
|
||||
|
||||
block = buf_pool_get_nth_block(buf_pool, i);
|
||||
for (i = buf_pool->n_chunks; i--; chunk++) {
|
||||
|
||||
ulint j;
|
||||
buf_block_t* block = chunk->blocks;
|
||||
|
||||
for (j = chunk->size; j--; block++) {
|
||||
|
||||
mutex_enter(&block->mutex);
|
||||
|
||||
if (block->state == BUF_BLOCK_FILE_PAGE) {
|
||||
|
||||
ut_a(buf_page_hash_get(block->space,
|
||||
block->offset) == block);
|
||||
block->offset)
|
||||
== block);
|
||||
n_page++;
|
||||
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
ut_a((block->io_fix == BUF_IO_READ)
|
||||
|| ibuf_count_get(block->space, block->offset)
|
||||
== 0);
|
||||
|| !ibuf_count_get(block->space,
|
||||
block->offset));
|
||||
#endif
|
||||
if (block->io_fix == BUF_IO_WRITE) {
|
||||
|
||||
if (block->flush_type == BUF_FLUSH_LRU) {
|
||||
switch (block->flush_type) {
|
||||
case BUF_FLUSH_LRU:
|
||||
n_lru_flush++;
|
||||
ut_a(rw_lock_is_locked(
|
||||
&block->lock,
|
||||
RW_LOCK_SHARED));
|
||||
} else if (block->flush_type
|
||||
== BUF_FLUSH_LIST) {
|
||||
break;
|
||||
case BUF_FLUSH_LIST:
|
||||
n_list_flush++;
|
||||
} else if (block->flush_type
|
||||
== BUF_FLUSH_SINGLE_PAGE) {
|
||||
break;
|
||||
case BUF_FLUSH_SINGLE_PAGE:
|
||||
n_single_flush++;
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
} else if (block->io_fix == BUF_IO_READ) {
|
||||
|
||||
ut_a(rw_lock_is_locked(&(block->lock),
|
||||
ut_a(rw_lock_is_locked(&block->lock,
|
||||
RW_LOCK_EX));
|
||||
}
|
||||
|
||||
@@ -2046,6 +2310,7 @@ buf_validate(void)
|
||||
|
||||
mutex_exit(&block->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
if (n_lru + n_free > buf_pool->curr_size) {
|
||||
fprintf(stderr, "n LRU %lu, n free %lu\n",
|
||||
@@ -2090,7 +2355,7 @@ buf_print(void)
|
||||
ulint j;
|
||||
dulint id;
|
||||
ulint n_found;
|
||||
buf_frame_t* frame;
|
||||
buf_chunk_t* chunk;
|
||||
dict_index_t* index;
|
||||
|
||||
ut_ad(buf_pool);
|
||||
@@ -2125,8 +2390,14 @@ buf_print(void)
|
||||
|
||||
n_found = 0;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
frame = buf_pool_get_nth_block(buf_pool, i)->frame;
|
||||
chunk = buf_pool->chunks;
|
||||
|
||||
for (i = buf_pool->n_chunks; i--; chunk++) {
|
||||
buf_block_t* block = chunk->blocks;
|
||||
ulint n_blocks = chunk->size;
|
||||
|
||||
for (; n_blocks--; block++) {
|
||||
const buf_frame_t* frame = block->frame;
|
||||
|
||||
if (fil_page_get_type(frame) == FIL_PAGE_INDEX) {
|
||||
|
||||
@@ -2137,7 +2408,8 @@ buf_print(void)
|
||||
|
||||
while (j < n_found) {
|
||||
|
||||
if (ut_dulint_cmp(index_ids[j], id) == 0) {
|
||||
if (ut_dulint_cmp(index_ids[j],
|
||||
id) == 0) {
|
||||
counts[j]++;
|
||||
|
||||
break;
|
||||
@@ -2152,6 +2424,7 @@ buf_print(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
|
||||
@@ -2184,17 +2457,26 @@ Returns the number of latched pages in the buffer pool. */
|
||||
ulint
|
||||
buf_get_latched_pages_number(void)
|
||||
{
|
||||
buf_block_t* block;
|
||||
buf_chunk_t* chunk;
|
||||
ulint i;
|
||||
ulint fixed_pages_number = 0;
|
||||
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
for (i = 0; i < buf_pool->curr_size; i++) {
|
||||
chunk = buf_pool->chunks;
|
||||
|
||||
block = buf_pool_get_nth_block(buf_pool, i);
|
||||
for (i = buf_pool->n_chunks; i--; chunk++) {
|
||||
buf_block_t* block;
|
||||
ulint j;
|
||||
|
||||
block = chunk->blocks;
|
||||
|
||||
for (j = chunk->size; j--; block++) {
|
||||
if (block->magic_n != BUF_BLOCK_MAGIC_N) {
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (block->magic_n == BUF_BLOCK_MAGIC_N) {
|
||||
mutex_enter(&block->mutex);
|
||||
|
||||
if (block->buf_fix_count != 0 || block->io_fix != 0) {
|
||||
@@ -2340,23 +2622,20 @@ ibool
|
||||
buf_all_freed(void)
|
||||
/*===============*/
|
||||
{
|
||||
buf_block_t* block;
|
||||
buf_chunk_t* chunk;
|
||||
ulint i;
|
||||
|
||||
ut_ad(buf_pool);
|
||||
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
for (i = 0; i < buf_pool->curr_size; i++) {
|
||||
chunk = buf_pool->chunks;
|
||||
|
||||
block = buf_pool_get_nth_block(buf_pool, i);
|
||||
for (i = buf_pool->n_chunks; i--; chunk++) {
|
||||
|
||||
mutex_enter(&block->mutex);
|
||||
|
||||
if (block->state == BUF_BLOCK_FILE_PAGE) {
|
||||
|
||||
if (!buf_flush_ready_for_replace(block)) {
|
||||
const buf_block_t* block = buf_chunk_not_freed(chunk);
|
||||
|
||||
if (UNIV_LIKELY_NULL(block)) {
|
||||
fprintf(stderr,
|
||||
"Page %lu %lu still fixed or dirty\n",
|
||||
(ulong) block->space,
|
||||
@@ -2365,9 +2644,6 @@ buf_all_freed(void)
|
||||
}
|
||||
}
|
||||
|
||||
mutex_exit(&block->mutex);
|
||||
}
|
||||
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
|
||||
return(TRUE);
|
||||
|
||||
@@ -157,7 +157,7 @@ long innobase_mirrored_log_groups, innobase_log_files_in_group,
|
||||
innobase_lock_wait_timeout, innobase_force_recovery,
|
||||
innobase_open_files;
|
||||
|
||||
longlong innobase_buffer_pool_size, innobase_log_file_size;
|
||||
longlong innobase_log_file_size;
|
||||
|
||||
/* The default values for the following char* start-up parameters
|
||||
are determined in innobase_init below: */
|
||||
@@ -1404,7 +1404,7 @@ innobase_init(void *p)
|
||||
|
||||
/* Check that values don't overflow on 32-bit systems. */
|
||||
if (sizeof(ulint) == 4) {
|
||||
if (innobase_buffer_pool_size > UINT_MAX32) {
|
||||
if (srv_buf_pool_size > UINT_MAX32) {
|
||||
sql_print_error(
|
||||
"innobase_buffer_pool_size can't be over 4GB"
|
||||
" on 32-bit systems");
|
||||
@@ -1533,14 +1533,6 @@ innobase_init(void *p)
|
||||
#endif /* UNIV_LOG_ARCHIVE */
|
||||
srv_log_buffer_size = (ulint) innobase_log_buffer_size;
|
||||
|
||||
/* We set srv_pool_size here in units of 1 kB. InnoDB internally
|
||||
changes the value so that it becomes the number of database pages. */
|
||||
|
||||
/* Careful here: we first convert the signed long int to ulint
|
||||
and only after that divide */
|
||||
|
||||
srv_pool_size = ((ulint) innobase_buffer_pool_size) / 1024;
|
||||
|
||||
srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
|
||||
|
||||
srv_n_file_io_threads = (ulint) innobase_file_io_threads;
|
||||
|
||||
@@ -207,7 +207,7 @@ extern SHOW_VAR innodb_status_variables[];
|
||||
extern ulong innobase_fast_shutdown;
|
||||
extern ulong innobase_large_page_size;
|
||||
extern long innobase_mirrored_log_groups, innobase_log_files_in_group;
|
||||
extern longlong innobase_buffer_pool_size, innobase_log_file_size;
|
||||
extern longlong innobase_log_file_size;
|
||||
extern long innobase_log_buffer_size;
|
||||
extern long innobase_additional_mem_pool_size;
|
||||
extern long innobase_file_io_threads, innobase_lock_wait_timeout;
|
||||
@@ -225,6 +225,8 @@ extern my_bool innobase_log_archive,
|
||||
innobase_file_per_table, innobase_locks_unsafe_for_binlog,
|
||||
innobase_create_status_file;
|
||||
extern "C" {
|
||||
extern ulong srv_buf_pool_curr_size;
|
||||
extern ulong srv_buf_pool_size;
|
||||
extern ulong srv_max_buf_pool_modified_pct;
|
||||
extern ulong srv_max_purge_lag;
|
||||
extern ulong srv_auto_extend_increment;
|
||||
|
||||
@@ -69,11 +69,16 @@ extern ulint srv_buf_pool_write_requests; /* variable to count write request
|
||||
Creates the buffer pool. */
|
||||
|
||||
buf_pool_t*
|
||||
buf_pool_init(
|
||||
/*==========*/
|
||||
buf_pool_init(void);
|
||||
/*===============*/
|
||||
/* out, own: buf_pool object, NULL if not
|
||||
enough memory or error */
|
||||
ulint curr_size); /* in: current size to use */
|
||||
/************************************************************************
|
||||
Resizes the buffer pool. */
|
||||
|
||||
void
|
||||
buf_pool_resize(void);
|
||||
/*=================*/
|
||||
/*************************************************************************
|
||||
Gets the current size of buffer buf_pool in bytes. */
|
||||
UNIV_INLINE
|
||||
@@ -833,11 +838,8 @@ struct buf_pool_struct{
|
||||
mutex_t mutex; /* mutex protecting the buffer pool
|
||||
struct and control blocks, except the
|
||||
read-write lock in them */
|
||||
byte* frame_mem; /* pointer to the memory area which
|
||||
was allocated for the frames */
|
||||
ulint frame_mem_size; /* allocated length of frame_mem
|
||||
in bytes */
|
||||
buf_block_t* blocks; /* array of buffer control blocks */
|
||||
ulint n_chunks; /* number of buffer pool chunks */
|
||||
buf_chunk_t* chunks; /* buffer pool chunks */
|
||||
ulint curr_size; /* current pool size in pages */
|
||||
hash_table_t* page_hash; /* hash table of the file pages */
|
||||
|
||||
|
||||
@@ -42,22 +42,6 @@ buf_pool_get_curr_size(void)
|
||||
return(buf_pool->curr_size * UNIV_PAGE_SIZE);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Accessor function for block array. */
|
||||
UNIV_INLINE
|
||||
buf_block_t*
|
||||
buf_pool_get_nth_block(
|
||||
/*===================*/
|
||||
/* out: pointer to block */
|
||||
buf_pool_t* buf_pool,/* in: buf_pool */
|
||||
ulint i) /* in: index of the block */
|
||||
{
|
||||
ut_ad(buf_pool);
|
||||
ut_ad(i < buf_pool->curr_size);
|
||||
|
||||
return(i + buf_pool->blocks);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Gets the smallest oldest_modification lsn for any page in the pool. Returns
|
||||
ut_dulint_zero if all modified pages have been flushed to disk. */
|
||||
@@ -114,8 +98,6 @@ buf_block_get_frame(
|
||||
buf_block_t* block) /* in: pointer to the control block */
|
||||
{
|
||||
ut_ad(block);
|
||||
ut_ad(block >= buf_pool->blocks);
|
||||
ut_ad(block < buf_pool->blocks + buf_pool->curr_size);
|
||||
ut_ad(block->state != BUF_BLOCK_NOT_USED);
|
||||
ut_ad((block->state != BUF_BLOCK_FILE_PAGE)
|
||||
|| (block->buf_fix_count > 0));
|
||||
@@ -133,8 +115,6 @@ buf_block_get_space(
|
||||
const buf_block_t* block) /* in: pointer to the control block */
|
||||
{
|
||||
ut_ad(block);
|
||||
ut_ad(block >= buf_pool->blocks);
|
||||
ut_ad(block < buf_pool->blocks + buf_pool->curr_size);
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(block->buf_fix_count > 0);
|
||||
|
||||
@@ -151,8 +131,6 @@ buf_block_get_page_no(
|
||||
const buf_block_t* block) /* in: pointer to the control block */
|
||||
{
|
||||
ut_ad(block);
|
||||
ut_ad(block >= buf_pool->blocks);
|
||||
ut_ad(block < buf_pool->blocks + buf_pool->curr_size);
|
||||
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
|
||||
ut_ad(block->buf_fix_count > 0);
|
||||
|
||||
|
||||
@@ -94,8 +94,9 @@ ibool
|
||||
buf_flush_ready_for_replace(
|
||||
/*========================*/
|
||||
/* out: TRUE if can replace immediately */
|
||||
buf_block_t* block); /* in: buffer control block, must be in state
|
||||
BUF_BLOCK_FILE_PAGE and in the LRU list */
|
||||
buf_block_t* block); /* in: buffer control block, must
|
||||
be in state BUF_BLOCK_FILE_PAGE
|
||||
and in the LRU list */
|
||||
/**********************************************************************
|
||||
Validates the flush list. */
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ Created 11/17/1995 Heikki Tuuri
|
||||
#define buf0types_h
|
||||
|
||||
typedef struct buf_block_struct buf_block_t;
|
||||
typedef struct buf_chunk_struct buf_chunk_t;
|
||||
typedef struct buf_pool_struct buf_pool_t;
|
||||
|
||||
/* The 'type' used of a buffer frame */
|
||||
|
||||
@@ -84,7 +84,9 @@ extern ulong srv_flush_log_at_trx_commit;
|
||||
|
||||
extern byte srv_latin1_ordering[256];/* The sort order table of the latin1
|
||||
character set */
|
||||
extern ulint srv_pool_size;
|
||||
extern ulong srv_buf_pool_size; /* requested size in kilobytes */
|
||||
extern ulong srv_buf_pool_old_size; /* previously requested size */
|
||||
extern ulong srv_buf_pool_curr_size; /* current size in kilobytes */
|
||||
extern ulint srv_mem_pool_size;
|
||||
extern ulint srv_lock_table_size;
|
||||
|
||||
@@ -153,7 +155,6 @@ extern ulong srv_thread_sleep_delay;
|
||||
extern ulint srv_spin_wait_delay;
|
||||
extern ibool srv_priority_boost;
|
||||
|
||||
extern ulint srv_pool_size;
|
||||
extern ulint srv_mem_pool_size;
|
||||
extern ulint srv_lock_table_size;
|
||||
|
||||
|
||||
52
innodb.patch
Normal file
52
innodb.patch
Normal file
@@ -0,0 +1,52 @@
|
||||
Index: srv/srv0srv.c
|
||||
===================================================================
|
||||
--- srv/srv0srv.c (revision 1010)
|
||||
+++ srv/srv0srv.c (working copy)
|
||||
@@ -2183,6 +2182,12 @@ loop:
|
||||
/* ---- When there is database activity by users, we cycle in this
|
||||
loop */
|
||||
|
||||
+ if (UNIV_UNLIKELY(srv_buf_pool_size != srv_buf_pool_old_size)) {
|
||||
+ srv_main_thread_op_info = "resizing buffer pool";
|
||||
+
|
||||
+ buf_pool_resize();
|
||||
+ }
|
||||
+
|
||||
srv_main_thread_op_info = "reserving kernel mutex";
|
||||
|
||||
n_ios_very_old = log_sys->n_log_ios + buf_pool->n_pages_read
|
||||
@@ -2543,6 +2548,12 @@ flush_loop:
|
||||
master thread to wait for more server activity */
|
||||
|
||||
suspend_thread:
|
||||
+ if (UNIV_UNLIKELY(srv_buf_pool_size != srv_buf_pool_old_size)) {
|
||||
+ srv_main_thread_op_info = "resizing buffer pool";
|
||||
+
|
||||
+ buf_pool_resize();
|
||||
+ }
|
||||
+
|
||||
srv_main_thread_op_info = "suspending";
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
@@ -2553,7 +2564,9 @@ suspend_thread:
|
||||
goto loop;
|
||||
}
|
||||
|
||||
+#if 0
|
||||
event = srv_suspend_thread();
|
||||
+#endif
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
@@ -2563,7 +2576,11 @@ suspend_thread:
|
||||
manual also mentions this string in several places. */
|
||||
srv_main_thread_op_info = "waiting for server activity";
|
||||
|
||||
+#if 0
|
||||
os_event_wait(event);
|
||||
+#else
|
||||
+ os_thread_sleep(1000000);
|
||||
+#endif
|
||||
|
||||
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
|
||||
/* This is only extra safety, the thread should exit
|
||||
72
mysql.patch
Normal file
72
mysql.patch
Normal file
@@ -0,0 +1,72 @@
|
||||
diff -pu mysql-5.1-bk/sql/mysqld.cc mysql-5.1-zip/sql/mysqld.cc
|
||||
--- mysql-5.1-bk/sql/mysqld.cc 2006-11-09 16:01:19.000000000 +0200
|
||||
+++ mysql-5.1-zip/sql/mysqld.cc 2006-11-13 12:54:04.000000000 +0200
|
||||
@@ -370,7 +370,6 @@ extern long innobase_lock_scan_time;
|
||||
extern long innobase_mirrored_log_groups, innobase_log_files_in_group;
|
||||
extern longlong innobase_log_file_size;
|
||||
extern long innobase_log_buffer_size;
|
||||
-extern longlong innobase_buffer_pool_size;
|
||||
extern long innobase_additional_mem_pool_size;
|
||||
extern long innobase_file_io_threads, innobase_lock_wait_timeout;
|
||||
extern long innobase_force_recovery;
|
||||
@@ -390,6 +389,8 @@ extern "C" {
|
||||
extern ulong srv_max_buf_pool_modified_pct;
|
||||
extern ulong srv_max_purge_lag;
|
||||
extern ulong srv_auto_extend_increment;
|
||||
+extern ulong srv_buf_pool_curr_size;
|
||||
+extern ulong srv_buf_pool_size;
|
||||
extern ulong srv_n_spin_wait_rounds;
|
||||
extern ulong srv_n_free_tickets_to_enter;
|
||||
extern ulong srv_thread_sleep_delay;
|
||||
@@ -5801,9 +5802,9 @@ log and this option does nothing anymore
|
||||
(gptr*) &srv_auto_extend_increment,
|
||||
0, GET_LONG, REQUIRED_ARG, 8L, 1L, 1000L, 0, 1L, 0},
|
||||
{"innodb_buffer_pool_size", OPT_INNODB_BUFFER_POOL_SIZE,
|
||||
- "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
|
||||
- (gptr*) &innobase_buffer_pool_size, (gptr*) &innobase_buffer_pool_size, 0,
|
||||
- GET_LL, REQUIRED_ARG, 8*1024*1024L, 1024*1024L, LONGLONG_MAX, 0,
|
||||
+ "The requested size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
|
||||
+ (gptr*) &srv_buf_pool_size, (gptr*) &srv_buf_pool_size, 0,
|
||||
+ GET_LL, REQUIRED_ARG, 8*1024*1024L, 5*1024*1024L, LONGLONG_MAX, 0,
|
||||
1024*1024L, 0},
|
||||
{"innodb_commit_concurrency", OPT_INNODB_COMMIT_CONCURRENCY,
|
||||
"Helps in performance tuning in heavily concurrent environments.",
|
||||
diff -pu mysql-5.1-bk/sql/set_var.cc mysql-5.1-zip/sql/set_var.cc
|
||||
--- mysql-5.1-bk/sql/set_var.cc 2006-11-09 16:01:19.000000000 +0200
|
||||
+++ mysql-5.1-zip/sql/set_var.cc 2006-11-13 12:54:05.000000000 +0200
|
||||
@@ -65,7 +65,6 @@ extern ulong innobase_fast_shutdown;
|
||||
extern long innobase_mirrored_log_groups, innobase_log_files_in_group;
|
||||
extern longlong innobase_log_file_size;
|
||||
extern long innobase_log_buffer_size;
|
||||
-extern longlong innobase_buffer_pool_size;
|
||||
extern long innobase_additional_mem_pool_size;
|
||||
extern long innobase_file_io_threads, innobase_lock_wait_timeout;
|
||||
extern long innobase_force_recovery;
|
||||
@@ -81,6 +80,8 @@ extern my_bool innobase_log_archive,
|
||||
innobase_locks_unsafe_for_binlog;
|
||||
|
||||
extern "C" {
|
||||
+extern ulong srv_buf_pool_curr_size;
|
||||
+extern ulong srv_buf_pool_size;
|
||||
extern ulong srv_max_buf_pool_modified_pct;
|
||||
extern ulong srv_max_purge_lag;
|
||||
extern ulong srv_auto_extend_increment;
|
||||
@@ -499,6 +500,8 @@ sys_var_thd_bool sys_innodb_support_xa("
|
||||
&SV::innodb_support_xa);
|
||||
sys_var_long_ptr sys_innodb_autoextend_increment("innodb_autoextend_increment",
|
||||
&srv_auto_extend_increment);
|
||||
+sys_var_long_ptr sys_innodb_buffer_pool_size("innodb_buffer_pool_size",
|
||||
+ &srv_buf_pool_size);
|
||||
sys_var_long_ptr sys_innodb_sync_spin_loops("innodb_sync_spin_loops",
|
||||
&srv_n_spin_wait_rounds);
|
||||
sys_var_long_ptr sys_innodb_concurrency_tickets("innodb_concurrency_tickets",
|
||||
@@ -818,7 +821,8 @@ SHOW_VAR init_vars[]= {
|
||||
#ifdef WITH_INNOBASE_STORAGE_ENGINE
|
||||
{"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG },
|
||||
{sys_innodb_autoextend_increment.name, (char*) &sys_innodb_autoextend_increment, SHOW_SYS},
|
||||
- {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONGLONG },
|
||||
+ {sys_innodb_buffer_pool_size.name, (char*) &sys_innodb_buffer_pool_size, SHOW_SYS },
|
||||
+ {"innodb_buffer_pool_curr_size", (char*) &srv_buf_pool_curr_size, SHOW_LONGLONG },
|
||||
{"innodb_checksums", (char*) &innobase_use_checksums, SHOW_MY_BOOL},
|
||||
{sys_innodb_commit_concurrency.name, (char*) &sys_innodb_commit_concurrency, SHOW_SYS},
|
||||
{sys_innodb_concurrency_tickets.name, (char*) &sys_innodb_concurrency_tickets, SHOW_SYS},
|
||||
@@ -159,10 +159,11 @@ byte srv_latin1_ordering[256] /* The sort order table of the latin1
|
||||
, 0xD8, 0x55, 0x55, 0x55, 0x59, 0x59, 0xDE, 0xFF
|
||||
};
|
||||
|
||||
ulint srv_pool_size = ULINT_MAX; /* size in pages; MySQL inits
|
||||
this to size in kilobytes but
|
||||
we normalize this to pages in
|
||||
srv_boot() */
|
||||
ulong srv_buf_pool_size = ULINT_MAX; /* requested size
|
||||
in kilobytes */
|
||||
ulong srv_buf_pool_old_size; /* previously requested size */
|
||||
ulong srv_buf_pool_curr_size = 0; /* current size
|
||||
in kilobytes */
|
||||
ulint srv_mem_pool_size = ULINT_MAX; /* size in bytes */
|
||||
ulint srv_lock_table_size = ULINT_MAX;
|
||||
|
||||
@@ -1233,9 +1234,7 @@ srv_normalize_init_values(void)
|
||||
|
||||
srv_log_buffer_size = srv_log_buffer_size / UNIV_PAGE_SIZE;
|
||||
|
||||
srv_pool_size = srv_pool_size / (UNIV_PAGE_SIZE / 1024);
|
||||
|
||||
srv_lock_table_size = 5 * srv_pool_size;
|
||||
srv_lock_table_size = 5 * (srv_buf_pool_size / UNIV_PAGE_SIZE);
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
@@ -1132,7 +1132,7 @@ innobase_start_or_create_for_mysql(void)
|
||||
}
|
||||
|
||||
/* Note that the call srv_boot() also changes the values of
|
||||
srv_pool_size etc. to the units used by InnoDB internally */
|
||||
some variables to the units used by InnoDB internally */
|
||||
|
||||
/* Set the maximum number of threads which can wait for a semaphore
|
||||
inside InnoDB: this is the 'sync wait array' size, as well as the
|
||||
@@ -1147,15 +1147,12 @@ innobase_start_or_create_for_mysql(void)
|
||||
NetWare. */
|
||||
srv_max_n_threads = 1000;
|
||||
#else
|
||||
if (srv_pool_size >= 1000 * 1024) {
|
||||
/* Here we still have srv_pool_size counted
|
||||
in kilobytes (in 4.0 this was in bytes)
|
||||
srv_boot() converts the value to
|
||||
pages; if buffer pool is less than 1000 MB,
|
||||
if (srv_buf_pool_size >= 1000 * 1024 * 1024) {
|
||||
/* If buffer pool is less than 1000 MB,
|
||||
assume fewer threads. */
|
||||
srv_max_n_threads = 50000;
|
||||
|
||||
} else if (srv_pool_size >= 8 * 1024) {
|
||||
} else if (srv_buf_pool_size >= 8 * 1024 * 1024) {
|
||||
|
||||
srv_max_n_threads = 10000;
|
||||
} else {
|
||||
@@ -1164,7 +1161,7 @@ innobase_start_or_create_for_mysql(void)
|
||||
computers */
|
||||
}
|
||||
#endif
|
||||
err = srv_boot(); /* This changes srv_pool_size to units of a page */
|
||||
err = srv_boot();
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
|
||||
@@ -1230,7 +1227,7 @@ innobase_start_or_create_for_mysql(void)
|
||||
|
||||
fil_init(srv_max_n_open_files);
|
||||
|
||||
ret = buf_pool_init(srv_pool_size);
|
||||
ret = buf_pool_init();
|
||||
|
||||
if (ret == NULL) {
|
||||
fprintf(stderr,
|
||||
|
||||
Reference in New Issue
Block a user