Commit 43a21f6e authored by marko's avatar marko

Merge r328:340 from branches/5.0:

r340: Fix http://bugs.mysql.com/bug.php?id=18283 in ha_innodb.cc and
http://bugs.mysql.com/bug.php?id=18238 in InnoDB

r339: Remove disk space leak on update of BLOB columns (Bug #18252).

btr_cur_pessimistic_update(): Invoke rec_get_offsets() after
rec_set_field_extern_bits().

btr_store_big_rec_extern_fields(): Note that offsets will no longer be
valid after calling this function.

r338: Fix bug 18238 : check in pessimistic insert and update if the buffer
pool is exhausted by locks
parent 04a6b957
...@@ -1915,13 +1915,13 @@ btr_cur_pessimistic_update( ...@@ -1915,13 +1915,13 @@ btr_cur_pessimistic_update(
ut_a(rec || optim_err != DB_UNDERFLOW); ut_a(rec || optim_err != DB_UNDERFLOW);
if (rec) { if (rec) {
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
lock_rec_restore_from_page_infimum(rec, page); lock_rec_restore_from_page_infimum(rec, page);
rec_set_field_extern_bits(rec, index, rec_set_field_extern_bits(rec, index,
ext_vect, n_ext_vect, mtr); ext_vect, n_ext_vect, mtr);
offsets = rec_get_offsets(rec, index, offsets,
ULINT_UNDEFINED, &heap);
if (!rec_get_deleted_flag(rec, rec_offs_comp(offsets))) { if (!rec_get_deleted_flag(rec, rec_offs_comp(offsets))) {
/* The new inserted record owns its possible externally /* The new inserted record owns its possible externally
stored fields */ stored fields */
...@@ -3328,7 +3328,10 @@ btr_store_big_rec_extern_fields( ...@@ -3328,7 +3328,10 @@ btr_store_big_rec_extern_fields(
dict_index_t* index, /* in: index of rec; the index tree dict_index_t* index, /* in: index of rec; the index tree
MUST be X-latched */ MUST be X-latched */
rec_t* rec, /* in: record */ rec_t* rec, /* in: record */
const ulint* offsets, /* in: rec_get_offsets(rec, index) */ const ulint* offsets, /* in: rec_get_offsets(rec, index);
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
big_rec_t* big_rec_vec, /* in: vector containing fields big_rec_t* big_rec_vec, /* in: vector containing fields
to be stored externally */ to be stored externally */
mtr_t* local_mtr __attribute__((unused))) /* in: mtr mtr_t* local_mtr __attribute__((unused))) /* in: mtr
......
...@@ -294,14 +294,14 @@ buf_LRU_try_free_flushed_blocks(void) ...@@ -294,14 +294,14 @@ buf_LRU_try_free_flushed_blocks(void)
} }
/********************************************************************** /**********************************************************************
Returns TRUE if less than 15 % of the buffer pool is available. This can be Returns TRUE if less than 25 % of the buffer pool is available. This can be
used in heuristics to prevent huge transactions eating up the whole buffer used in heuristics to prevent huge transactions eating up the whole buffer
pool for their locks. */ pool for their locks. */
ibool ibool
buf_LRU_buf_pool_running_out(void) buf_LRU_buf_pool_running_out(void)
/*==============================*/ /*==============================*/
/* out: TRUE if less than 15 % of buffer pool /* out: TRUE if less than 25 % of buffer pool
left */ left */
{ {
ibool ret = FALSE; ibool ret = FALSE;
...@@ -309,7 +309,7 @@ buf_LRU_buf_pool_running_out(void) ...@@ -309,7 +309,7 @@ buf_LRU_buf_pool_running_out(void)
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 7) { + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) {
ret = TRUE; ret = TRUE;
} }
...@@ -340,11 +340,11 @@ buf_LRU_get_free_block(void) ...@@ -340,11 +340,11 @@ buf_LRU_get_free_block(void)
mutex_enter(&(buf_pool->mutex)); mutex_enter(&(buf_pool->mutex));
if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free) if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 10) { + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 20) {
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
" InnoDB: ERROR: over 9 / 10 of the buffer pool is occupied by\n" " 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: lock heaps or the adaptive hash index! Check that your\n"
"InnoDB: transactions do not set too many row locks.\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: Your buffer pool size is %lu MB. Maybe you should make\n"
...@@ -356,17 +356,17 @@ buf_LRU_get_free_block(void) ...@@ -356,17 +356,17 @@ buf_LRU_get_free_block(void)
ut_error; ut_error;
} 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 / 3) {
if (!buf_lru_switched_on_innodb_mon) { if (!buf_lru_switched_on_innodb_mon) {
/* Over 80 % of the buffer pool is occupied by lock /* Over 67 % 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
leak! */ leak! */
ut_print_timestamp(stderr); ut_print_timestamp(stderr);
fprintf(stderr, fprintf(stderr,
" InnoDB: WARNING: over 4 / 5 of the buffer pool is occupied by\n" " 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: lock heaps or the adaptive hash index! Check that your\n"
"InnoDB: transactions do not set too many row locks.\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: Your buffer pool size is %lu MB. Maybe you should make\n"
......
...@@ -539,11 +539,18 @@ convert_error_code_to_mysql( ...@@ -539,11 +539,18 @@ convert_error_code_to_mysql(
return(HA_ERR_NO_SAVEPOINT); return(HA_ERR_NO_SAVEPOINT);
} else if (error == (int) DB_LOCK_TABLE_FULL) { } else if (error == (int) DB_LOCK_TABLE_FULL) {
/* Since we rolled back the whole transaction, we must
return(HA_ERR_LOCK_TABLE_FULL); tell it also to MySQL so that MySQL knows to empty the
} else { cached binlog for this transaction */
return(-1); // Unknown error
} if (thd) {
ha_rollback(thd);
}
return(HA_ERR_LOCK_TABLE_FULL);
} else {
return(-1); // Unknown error
}
} }
/***************************************************************** /*****************************************************************
......
...@@ -459,7 +459,10 @@ btr_store_big_rec_extern_fields( ...@@ -459,7 +459,10 @@ btr_store_big_rec_extern_fields(
dict_index_t* index, /* in: index of rec; the index tree dict_index_t* index, /* in: index of rec; the index tree
MUST be X-latched */ MUST be X-latched */
rec_t* rec, /* in: record */ rec_t* rec, /* in: record */
const ulint* offsets, /* in: rec_get_offsets(rec, index) */ const ulint* offsets, /* in: rec_get_offsets(rec, index);
the "external storage" flags in offsets
will not correspond to rec when
this function returns */
big_rec_t* big_rec_vec, /* in: vector containing fields big_rec_t* big_rec_vec, /* in: vector containing fields
to be stored externally */ to be stored externally */
mtr_t* local_mtr); /* in: mtr containing the latch to mtr_t* local_mtr); /* in: mtr containing the latch to
......
...@@ -26,14 +26,14 @@ void ...@@ -26,14 +26,14 @@ 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 Returns TRUE if less than 25 % of the buffer pool is available. This can be
used in heuristics to prevent huge transactions eating up the whole buffer used in heuristics to prevent huge transactions eating up the whole buffer
pool for their locks. */ pool for their locks. */
ibool ibool
buf_LRU_buf_pool_running_out(void); buf_LRU_buf_pool_running_out(void);
/*==============================*/ /*==============================*/
/* out: TRUE if less than 15 % of buffer pool /* out: TRUE if less than 25 % of buffer pool
left */ left */
/*####################################################################### /*#######################################################################
......
...@@ -28,6 +28,7 @@ Created 4/20/1996 Heikki Tuuri ...@@ -28,6 +28,7 @@ Created 4/20/1996 Heikki Tuuri
#include "eval0eval.h" #include "eval0eval.h"
#include "data0data.h" #include "data0data.h"
#include "usr0sess.h" #include "usr0sess.h"
#include "buf0lru.h"
#define ROW_INS_PREV 1 #define ROW_INS_PREV 1
#define ROW_INS_NEXT 2 #define ROW_INS_NEXT 2
...@@ -279,10 +280,17 @@ row_ins_sec_index_entry_by_modify( ...@@ -279,10 +280,17 @@ row_ins_sec_index_entry_by_modify(
} }
} else { } else {
ut_a(mode == BTR_MODIFY_TREE); ut_a(mode == BTR_MODIFY_TREE);
if (buf_LRU_buf_pool_running_out()) {
err = DB_LOCK_TABLE_FULL;
goto func_exit;
}
err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG, cursor, err = btr_cur_pessimistic_update(BTR_KEEP_SYS_FLAG, cursor,
&dummy_big_rec, update, 0, thr, mtr); &dummy_big_rec, update, 0, thr, mtr);
} }
func_exit:
mem_heap_free(heap); mem_heap_free(heap);
return(err); return(err);
...@@ -344,10 +352,16 @@ row_ins_clust_index_entry_by_modify( ...@@ -344,10 +352,16 @@ row_ins_clust_index_entry_by_modify(
} }
} else { } else {
ut_a(mode == BTR_MODIFY_TREE); ut_a(mode == BTR_MODIFY_TREE);
if (buf_LRU_buf_pool_running_out()) {
err = DB_LOCK_TABLE_FULL;
goto func_exit;
}
err = btr_cur_pessimistic_update(0, cursor, big_rec, update, err = btr_cur_pessimistic_update(0, cursor, big_rec, update,
0, thr, mtr); 0, thr, mtr);
} }
func_exit:
mem_heap_free(heap); mem_heap_free(heap);
return(err); return(err);
...@@ -2091,6 +2105,12 @@ row_ins_index_entry_low( ...@@ -2091,6 +2105,12 @@ row_ins_index_entry_low(
&insert_rec, &big_rec, thr, &mtr); &insert_rec, &big_rec, thr, &mtr);
} else { } else {
ut_a(mode == BTR_MODIFY_TREE); ut_a(mode == BTR_MODIFY_TREE);
if (buf_LRU_buf_pool_running_out()) {
err = DB_LOCK_TABLE_FULL;
goto function_exit;
}
err = btr_cur_pessimistic_insert(0, &cursor, entry, err = btr_cur_pessimistic_insert(0, &cursor, entry,
&insert_rec, &big_rec, thr, &mtr); &insert_rec, &big_rec, thr, &mtr);
} }
......
...@@ -28,6 +28,7 @@ Created 12/27/1996 Heikki Tuuri ...@@ -28,6 +28,7 @@ Created 12/27/1996 Heikki Tuuri
#include "log0log.h" #include "log0log.h"
#include "pars0sym.h" #include "pars0sym.h"
#include "eval0eval.h" #include "eval0eval.h"
#include "buf0lru.h"
/* What kind of latch and lock can we assume when the control comes to /* What kind of latch and lock can we assume when the control comes to
...@@ -1541,6 +1542,10 @@ row_upd_clust_rec( ...@@ -1541,6 +1542,10 @@ row_upd_clust_rec(
return(err); return(err);
} }
if (buf_LRU_buf_pool_running_out()) {
return(DB_LOCK_TABLE_FULL);
}
/* We may have to modify the tree structure: do a pessimistic descent /* We may have to modify the tree structure: do a pessimistic descent
down the index tree */ down the index tree */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment