Commit 4441e34e authored by unknown's avatar unknown

BUG#18160 - Memory-/HEAP Table endless growing indexes

Updating data in HEAP table with BTREE index results in wrong index_length
counter value, which keeps growing after each update.

When inserting new record into tree counter is incremented by:
sizeof(TREE_ELEMENT) + key_size + tree->size_of_element
But when deleting element from tree it doesn't decrement counter by key_size:
sizeof(TREE_ELEMENT) + tree->size_of_element

This fix makes accurate allocated memory counter for tree. That is
decrease counter by key_size when deleting tree element.


heap/hp_delete.c:
  Added size of the key to tree_delete() for accurate allocated memory counter.
include/my_tree.h:
  Added size of the key to tree_delete() for accurate allocated memory counter.
myisam/myisamlog.c:
  Added size of the key to tree_delete() for accurate allocated memory counter.
mysql-test/r/heap_btree.result:
  Testcase for BUG#18160.
mysql-test/t/heap_btree.test:
  Testcase for BUG#18160.
mysys/tree.c:
  Added size of the key to tree_delete() for accurate allocated memory counter.
  Note that this size is optional. If one doesn't need precise counter it is safe
  to pass 0 as key_size.
parent 8077c693
...@@ -79,7 +79,8 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo, ...@@ -79,7 +79,8 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos); custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
custom_arg.search_flag= SEARCH_SAME; custom_arg.search_flag= SEARCH_SAME;
old_allocated= keyinfo->rb_tree.allocated; old_allocated= keyinfo->rb_tree.allocated;
res= tree_delete(&keyinfo->rb_tree, info->recbuf, &custom_arg); res= tree_delete(&keyinfo->rb_tree, info->recbuf, custom_arg.key_length,
&custom_arg);
info->s->index_length-= (old_allocated - keyinfo->rb_tree.allocated); info->s->index_length-= (old_allocated - keyinfo->rb_tree.allocated);
return res; return res;
} }
......
...@@ -84,7 +84,7 @@ TREE_ELEMENT *tree_insert(TREE *tree,void *key, uint key_size, ...@@ -84,7 +84,7 @@ TREE_ELEMENT *tree_insert(TREE *tree,void *key, uint key_size,
void *tree_search(TREE *tree, void *key, void *custom_arg); void *tree_search(TREE *tree, void *key, void *custom_arg);
int tree_walk(TREE *tree,tree_walk_action action, int tree_walk(TREE *tree,tree_walk_action action,
void *argument, TREE_WALK visit); void *argument, TREE_WALK visit);
int tree_delete(TREE *tree, void *key, void *custom_arg); int tree_delete(TREE *tree, void *key, uint key_size, void *custom_arg);
void *tree_search_key(TREE *tree, const void *key, void *tree_search_key(TREE *tree, const void *key,
TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos, TREE_ELEMENT **parents, TREE_ELEMENT ***last_pos,
enum ha_rkey_function flag, void *custom_arg); enum ha_rkey_function flag, void *custom_arg);
......
...@@ -475,7 +475,7 @@ static int examine_log(my_string file_name, char **table_names) ...@@ -475,7 +475,7 @@ static int examine_log(my_string file_name, char **table_names)
{ {
if (!curr_file_info->closed) if (!curr_file_info->closed)
files_open--; files_open--;
VOID(tree_delete(&tree, (gptr) curr_file_info, tree.custom_arg)); VOID(tree_delete(&tree, (gptr) curr_file_info, 0, tree.custom_arg));
} }
break; break;
case MI_LOG_EXTRA: case MI_LOG_EXTRA:
......
...@@ -246,3 +246,13 @@ DELETE from t1 where a < 100; ...@@ -246,3 +246,13 @@ DELETE from t1 where a < 100;
SELECT * from t1; SELECT * from t1;
a a
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1(val INT, KEY USING BTREE(val)) ENGINE=memory;
INSERT INTO t1 VALUES(0);
SELECT INDEX_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='t1';
INDEX_LENGTH
21
UPDATE t1 SET val=1;
SELECT INDEX_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='t1';
INDEX_LENGTH
21
DROP TABLE t1;
...@@ -164,4 +164,14 @@ DELETE from t1 where a < 100; ...@@ -164,4 +164,14 @@ DELETE from t1 where a < 100;
SELECT * from t1; SELECT * from t1;
DROP TABLE t1; DROP TABLE t1;
#
# BUG#18160 - Memory-/HEAP Table endless growing indexes
#
CREATE TABLE t1(val INT, KEY USING BTREE(val)) ENGINE=memory;
INSERT INTO t1 VALUES(0);
SELECT INDEX_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='t1';
UPDATE t1 SET val=1;
SELECT INDEX_LENGTH FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=DATABASE() AND TABLE_NAME='t1';
DROP TABLE t1;
# End of 4.1 tests # End of 4.1 tests
...@@ -271,7 +271,7 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size, ...@@ -271,7 +271,7 @@ TREE_ELEMENT *tree_insert(TREE *tree, void *key, uint key_size,
return element; return element;
} }
int tree_delete(TREE *tree, void *key, void *custom_arg) int tree_delete(TREE *tree, void *key, uint key_size, void *custom_arg)
{ {
int cmp,remove_colour; int cmp,remove_colour;
TREE_ELEMENT *element,***parent, ***org_parent, *nod; TREE_ELEMENT *element,***parent, ***org_parent, *nod;
...@@ -326,8 +326,7 @@ int tree_delete(TREE *tree, void *key, void *custom_arg) ...@@ -326,8 +326,7 @@ int tree_delete(TREE *tree, void *key, void *custom_arg)
rb_delete_fixup(tree,parent); rb_delete_fixup(tree,parent);
if (tree->free) if (tree->free)
(*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg); (*tree->free)(ELEMENT_KEY(tree,element), free_free, tree->custom_arg);
/* This doesn't include key_size, but better than nothing */ tree->allocated-= sizeof(TREE_ELEMENT) + tree->size_of_element + key_size;
tree->allocated-= sizeof(TREE_ELEMENT)+tree->size_of_element;
my_free((gptr) element,MYF(0)); my_free((gptr) element,MYF(0));
tree->elements_in_tree--; tree->elements_in_tree--;
return 0; return 0;
......
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