mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Many files:
Fix bug #6817 and bug #6827 : do not crash the server if the buffer pool becomes filled by the locks of ONE huge transaction, return error 1206 instead; do not crash the server, but return error if we cannot allocate memory for the buffer pool at a mysqld startup innobase/buf/buf0buf.c: Fix bug #6817 and bug #6827 : do not crash the server if the buffer pool becomes filled by the locks of ONE huge transaction, return error 1206 instead; do not crash the server, but return error if we cannot allocate memory for the buffer pool at a mysqld startup innobase/buf/buf0lru.c: Fix bug #6817 and bug #6827 : do not crash the server if the buffer pool becomes filled by the locks of ONE huge transaction, return error 1206 instead; do not crash the server, but return error if we cannot allocate memory for the buffer pool at a mysqld startup innobase/include/buf0lru.h: Fix bug #6817 and bug #6827 : do not crash the server if the buffer pool becomes filled by the locks of ONE huge transaction, return error 1206 instead; do not crash the server, but return error if we cannot allocate memory for the buffer pool at a mysqld startup innobase/include/db0err.h: Fix bug #6817 and bug #6827 : do not crash the server if the buffer pool becomes filled by the locks of ONE huge transaction, return error 1206 instead; do not crash the server, but return error if we cannot allocate memory for the buffer pool at a mysqld startup innobase/include/row0sel.h: Fix bug #6817 and bug #6827 : do not crash the server if the buffer pool becomes filled by the locks of ONE huge transaction, return error 1206 instead; do not crash the server, but return error if we cannot allocate memory for the buffer pool at a mysqld startup innobase/include/ut0mem.h: Fix bug #6817 and bug #6827 : do not crash the server if the buffer pool becomes filled by the locks of ONE huge transaction, return error 1206 instead; do not crash the server, but return error if we cannot allocate memory for the buffer pool at a mysqld startup innobase/mem/mem0pool.c: Fix bug #6817 and bug #6827 : do not crash the server if the buffer pool becomes filled by the locks of ONE huge transaction, return error 1206 instead; do not crash the server, but return error if we cannot allocate memory for the buffer pool at a mysqld startup innobase/row/row0mysql.c: Fix bug #6817 and bug #6827 : do not crash the server if the buffer pool becomes filled by the locks of ONE huge transaction, return error 1206 instead; do not crash the server, but return error if we cannot allocate memory for the buffer pool at a mysqld startup innobase/row/row0sel.c: Fix bug #6817 and bug #6827 : do not crash the server if the buffer pool becomes filled by the locks of ONE huge transaction, return error 1206 instead; do not crash the server, but return error if we cannot allocate memory for the buffer pool at a mysqld startup innobase/srv/srv0start.c: Fix bug #6817 and bug #6827 : do not crash the server if the buffer pool becomes filled by the locks of ONE huge transaction, return error 1206 instead; do not crash the server, but return error if we cannot allocate memory for the buffer pool at a mysqld startup innobase/ut/ut0mem.c: Fix bug #6817 and bug #6827 : do not crash the server if the buffer pool becomes filled by the locks of ONE huge transaction, return error 1206 instead; do not crash the server, but return error if we cannot allocate memory for the buffer pool at a mysqld startup
This commit is contained in:
@ -547,8 +547,9 @@ buf_pool_init(
|
|||||||
}
|
}
|
||||||
/*----------------------------------------*/
|
/*----------------------------------------*/
|
||||||
} else {
|
} else {
|
||||||
buf_pool->frame_mem = ut_malloc(
|
buf_pool->frame_mem = ut_malloc_low(
|
||||||
UNIV_PAGE_SIZE * (n_frames + 1));
|
UNIV_PAGE_SIZE * (n_frames + 1),
|
||||||
|
TRUE, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buf_pool->frame_mem == NULL) {
|
if (buf_pool->frame_mem == NULL) {
|
||||||
|
@ -42,6 +42,10 @@ initial segment in buf_LRU_get_recent_limit */
|
|||||||
|
|
||||||
#define BUF_LRU_INITIAL_RATIO 8
|
#define BUF_LRU_INITIAL_RATIO 8
|
||||||
|
|
||||||
|
/* If we switch on the InnoDB monitor because there are too few available
|
||||||
|
frames in the buffer pool, we set this to TRUE */
|
||||||
|
ibool buf_lru_switched_on_innodb_mon = FALSE;
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
Takes a block out of the LRU list and page hash table and sets the block
|
Takes a block out of the LRU list and page hash table and sets the block
|
||||||
state to BUF_BLOCK_REMOVE_HASH. */
|
state to BUF_BLOCK_REMOVE_HASH. */
|
||||||
@ -287,6 +291,32 @@ buf_LRU_try_free_flushed_blocks(void)
|
|||||||
mutex_exit(&(buf_pool->mutex));
|
mutex_exit(&(buf_pool->mutex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
Returns TRUE if less than 15 % of the buffer pool is available. This can be
|
||||||
|
used in heuristics to prevent huge transactions eating up the whole buffer
|
||||||
|
pool for their locks. */
|
||||||
|
|
||||||
|
ibool
|
||||||
|
buf_LRU_buf_pool_running_out(void)
|
||||||
|
/*==============================*/
|
||||||
|
/* out: TRUE if less than 15 % of buffer pool
|
||||||
|
left */
|
||||||
|
{
|
||||||
|
ibool ret = FALSE;
|
||||||
|
|
||||||
|
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 / 7) {
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_exit(&(buf_pool->mutex));
|
||||||
|
|
||||||
|
return(ret);
|
||||||
|
}
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
Returns a free block from buf_pool. The block is taken off the free list.
|
Returns a free block from buf_pool. The block is taken off the free list.
|
||||||
If it is empty, blocks are moved from the end of the LRU list to the free
|
If it is empty, blocks are moved from the end of the LRU list to the free
|
||||||
@ -325,7 +355,8 @@ loop:
|
|||||||
|
|
||||||
} else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
|
} else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
|
||||||
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 5) {
|
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 5) {
|
||||||
if (!srv_print_innodb_monitor) {
|
|
||||||
|
if (!buf_lru_switched_on_innodb_mon) {
|
||||||
|
|
||||||
/* Over 80 % of the buffer pool is occupied by lock
|
/* Over 80 % of the buffer pool is occupied by lock
|
||||||
heaps or the adaptive hash index. This may be a memory
|
heaps or the adaptive hash index. This may be a memory
|
||||||
@ -342,16 +373,18 @@ loop:
|
|||||||
"InnoDB: lock heap and hash index sizes.\n",
|
"InnoDB: lock heap and hash index sizes.\n",
|
||||||
(ulong) (buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE)));
|
(ulong) (buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE)));
|
||||||
|
|
||||||
|
buf_lru_switched_on_innodb_mon = TRUE;
|
||||||
srv_print_innodb_monitor = TRUE;
|
srv_print_innodb_monitor = TRUE;
|
||||||
os_event_set(srv_lock_timeout_thread_event);
|
os_event_set(srv_lock_timeout_thread_event);
|
||||||
}
|
}
|
||||||
} else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
|
} else if (buf_lru_switched_on_innodb_mon) {
|
||||||
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) {
|
|
||||||
|
|
||||||
/* Switch off the InnoDB Monitor; this is a simple way
|
/* Switch off the InnoDB Monitor; this is a simple way
|
||||||
to stop the monitor if the situation becomes less urgent,
|
to stop the monitor if the situation becomes less urgent,
|
||||||
but may also surprise users! */
|
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;
|
srv_print_innodb_monitor = FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,16 @@ wasted. */
|
|||||||
void
|
void
|
||||||
buf_LRU_try_free_flushed_blocks(void);
|
buf_LRU_try_free_flushed_blocks(void);
|
||||||
/*==================================*/
|
/*==================================*/
|
||||||
|
/**********************************************************************
|
||||||
|
Returns TRUE if less than 15 % of the buffer pool is available. This can be
|
||||||
|
used in heuristics to prevent huge transactions eating up the whole buffer
|
||||||
|
pool for their locks. */
|
||||||
|
|
||||||
|
ibool
|
||||||
|
buf_LRU_buf_pool_running_out(void);
|
||||||
|
/*==============================*/
|
||||||
|
/* out: TRUE if less than 15 % of buffer pool
|
||||||
|
left */
|
||||||
|
|
||||||
/*#######################################################################
|
/*#######################################################################
|
||||||
These are low-level functions
|
These are low-level functions
|
||||||
|
@ -53,7 +53,11 @@ Created 5/24/1996 Heikki Tuuri
|
|||||||
name already exists */
|
name already exists */
|
||||||
#define DB_TABLESPACE_DELETED 44 /* tablespace does not exist or is
|
#define DB_TABLESPACE_DELETED 44 /* tablespace does not exist or is
|
||||||
being dropped right now */
|
being dropped right now */
|
||||||
|
#define DB_LOCK_TABLE_FULL 45 /* lock structs have exhausted the
|
||||||
|
buffer pool (for big transactions,
|
||||||
|
InnoDB stores the lock structs in the
|
||||||
|
buffer pool) */
|
||||||
|
|
||||||
/* The following are partial failure codes */
|
/* The following are partial failure codes */
|
||||||
#define DB_FAIL 1000
|
#define DB_FAIL 1000
|
||||||
#define DB_OVERFLOW 1001
|
#define DB_OVERFLOW 1001
|
||||||
|
@ -120,6 +120,7 @@ row_search_for_mysql(
|
|||||||
/* out: DB_SUCCESS,
|
/* out: DB_SUCCESS,
|
||||||
DB_RECORD_NOT_FOUND,
|
DB_RECORD_NOT_FOUND,
|
||||||
DB_END_OF_INDEX, DB_DEADLOCK,
|
DB_END_OF_INDEX, DB_DEADLOCK,
|
||||||
|
DB_LOCK_TABLE_FULL,
|
||||||
or DB_TOO_BIG_RECORD */
|
or DB_TOO_BIG_RECORD */
|
||||||
byte* buf, /* in/out: buffer for the fetched
|
byte* buf, /* in/out: buffer for the fetched
|
||||||
row in the MySQL format */
|
row in the MySQL format */
|
||||||
|
@ -38,8 +38,10 @@ ut_malloc_low(
|
|||||||
/*==========*/
|
/*==========*/
|
||||||
/* out, own: allocated memory */
|
/* out, own: allocated memory */
|
||||||
ulint n, /* in: number of bytes to allocate */
|
ulint n, /* in: number of bytes to allocate */
|
||||||
ibool set_to_zero); /* in: TRUE if allocated memory should be set
|
ibool set_to_zero, /* in: TRUE if allocated memory should be set
|
||||||
to zero if UNIV_SET_MEM_TO_ZERO is defined */
|
to zero if UNIV_SET_MEM_TO_ZERO is defined */
|
||||||
|
ibool assert_on_error); /* in: if TRUE, we crash mysqld if the memory
|
||||||
|
cannot be allocated */
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
|
Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
|
||||||
defined. */
|
defined. */
|
||||||
|
@ -199,7 +199,7 @@ mem_pool_create(
|
|||||||
but only when allocated at a higher level in mem0mem.c.
|
but only when allocated at a higher level in mem0mem.c.
|
||||||
This is to avoid masking useful Purify warnings. */
|
This is to avoid masking useful Purify warnings. */
|
||||||
|
|
||||||
pool->buf = ut_malloc_low(size, FALSE);
|
pool->buf = ut_malloc_low(size, FALSE, TRUE);
|
||||||
pool->size = size;
|
pool->size = size;
|
||||||
|
|
||||||
mutex_create(&(pool->mutex));
|
mutex_create(&(pool->mutex));
|
||||||
|
@ -308,7 +308,8 @@ handle_new_error:
|
|||||||
|
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
|
|
||||||
} else if (err == DB_DEADLOCK || err == DB_LOCK_WAIT_TIMEOUT) {
|
} else if (err == DB_DEADLOCK || err == DB_LOCK_WAIT_TIMEOUT
|
||||||
|
|| err == DB_LOCK_TABLE_FULL) {
|
||||||
/* Roll back the whole transaction; this resolution was added
|
/* Roll back the whole transaction; this resolution was added
|
||||||
to version 3.23.43 */
|
to version 3.23.43 */
|
||||||
|
|
||||||
|
@ -730,8 +730,18 @@ sel_set_rec_lock(
|
|||||||
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or LOC_REC_NOT_GAP */
|
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or LOC_REC_NOT_GAP */
|
||||||
que_thr_t* thr) /* in: query thread */
|
que_thr_t* thr) /* in: query thread */
|
||||||
{
|
{
|
||||||
|
trx_t* trx;
|
||||||
ulint err;
|
ulint err;
|
||||||
|
|
||||||
|
trx = thr_get_trx(thr);
|
||||||
|
|
||||||
|
if (UT_LIST_GET_LEN(trx->trx_locks) > 10000) {
|
||||||
|
if (buf_LRU_buf_pool_running_out()) {
|
||||||
|
|
||||||
|
return(DB_LOCK_TABLE_FULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (index->type & DICT_CLUSTERED) {
|
if (index->type & DICT_CLUSTERED) {
|
||||||
err = lock_clust_rec_read_check_and_lock(0, rec, index, mode,
|
err = lock_clust_rec_read_check_and_lock(0, rec, index, mode,
|
||||||
type, thr);
|
type, thr);
|
||||||
@ -2765,6 +2775,7 @@ row_search_for_mysql(
|
|||||||
/* out: DB_SUCCESS,
|
/* out: DB_SUCCESS,
|
||||||
DB_RECORD_NOT_FOUND,
|
DB_RECORD_NOT_FOUND,
|
||||||
DB_END_OF_INDEX, DB_DEADLOCK,
|
DB_END_OF_INDEX, DB_DEADLOCK,
|
||||||
|
DB_LOCK_TABLE_FULL,
|
||||||
or DB_TOO_BIG_RECORD */
|
or DB_TOO_BIG_RECORD */
|
||||||
byte* buf, /* in/out: buffer for the fetched
|
byte* buf, /* in/out: buffer for the fetched
|
||||||
row in the MySQL format */
|
row in the MySQL format */
|
||||||
|
@ -1172,6 +1172,9 @@ NetWare. */
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: Fatal error: cannot allocate the memory for the buffer pool\n");
|
||||||
|
|
||||||
return(DB_ERROR);
|
return(DB_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,8 +61,10 @@ ut_malloc_low(
|
|||||||
/*==========*/
|
/*==========*/
|
||||||
/* out, own: allocated memory */
|
/* out, own: allocated memory */
|
||||||
ulint n, /* in: number of bytes to allocate */
|
ulint n, /* in: number of bytes to allocate */
|
||||||
ibool set_to_zero) /* in: TRUE if allocated memory should be set
|
ibool set_to_zero, /* in: TRUE if allocated memory should be set
|
||||||
to zero if UNIV_SET_MEM_TO_ZERO is defined */
|
to zero if UNIV_SET_MEM_TO_ZERO is defined */
|
||||||
|
ibool assert_on_error) /* in: if TRUE, we crash mysqld if the memory
|
||||||
|
cannot be allocated */
|
||||||
{
|
{
|
||||||
void* ret;
|
void* ret;
|
||||||
|
|
||||||
@ -86,9 +88,7 @@ ut_malloc_low(
|
|||||||
"InnoDB: Check if you should increase the swap file or\n"
|
"InnoDB: Check if you should increase the swap file or\n"
|
||||||
"InnoDB: ulimits of your operating system.\n"
|
"InnoDB: ulimits of your operating system.\n"
|
||||||
"InnoDB: On FreeBSD check you have compiled the OS with\n"
|
"InnoDB: On FreeBSD check you have compiled the OS with\n"
|
||||||
"InnoDB: a big enough maximum process size.\n"
|
"InnoDB: a big enough maximum process size.\n",
|
||||||
"InnoDB: We now intentionally generate a seg fault so that\n"
|
|
||||||
"InnoDB: on Linux we get a stack trace.\n",
|
|
||||||
(ulong) n, (ulong) ut_total_allocated_memory,
|
(ulong) n, (ulong) ut_total_allocated_memory,
|
||||||
#ifdef __WIN__
|
#ifdef __WIN__
|
||||||
(ulong) GetLastError()
|
(ulong) GetLastError()
|
||||||
@ -110,7 +110,15 @@ ut_malloc_low(
|
|||||||
/* Intentional segfault on NetWare causes an abend. Avoid this
|
/* Intentional segfault on NetWare causes an abend. Avoid this
|
||||||
by graceful exit handling in ut_a(). */
|
by graceful exit handling in ut_a(). */
|
||||||
#if (!defined __NETWARE__)
|
#if (!defined __NETWARE__)
|
||||||
if (*ut_mem_null_ptr) ut_mem_null_ptr = 0;
|
if (assert_on_error) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
ut_a(0);
|
ut_a(0);
|
||||||
#endif
|
#endif
|
||||||
@ -144,7 +152,7 @@ ut_malloc(
|
|||||||
/* out, own: allocated memory */
|
/* out, own: allocated memory */
|
||||||
ulint n) /* in: number of bytes to allocate */
|
ulint n) /* in: number of bytes to allocate */
|
||||||
{
|
{
|
||||||
return(ut_malloc_low(n, TRUE));
|
return(ut_malloc_low(n, TRUE, TRUE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
|
Reference in New Issue
Block a user