Commit c95d142f authored by monty@mashka.mysql.fi's avatar monty@mashka.mysql.fi

Add new user variables for tuning memory usage:

query_alloc_block_size, query_prealloc_size, range_alloc_block_size,transaction_alloc_block_size and transaction_prealloc_size
Add more checks for "out of memory" detection in range optimization
parent 9bba878b
...@@ -1806,7 +1806,7 @@ AC_CHECK_FUNCS(alarm bmove \ ...@@ -1806,7 +1806,7 @@ AC_CHECK_FUNCS(alarm bmove \
cuserid fcntl fconvert poll \ cuserid fcntl fconvert poll \
getrusage getpwuid getcwd getrlimit getwd index stpcpy locking longjmp \ getrusage getpwuid getcwd getrlimit getwd index stpcpy locking longjmp \
perror pread realpath readlink rename \ perror pread realpath readlink rename \
socket strnlen madvise mkstemp \ socket strnlen madvise mallinfo mkstemp \
strtol strtoul strtoll strtoull snprintf tempnam thr_setconcurrency \ strtol strtoul strtoll strtoull snprintf tempnam thr_setconcurrency \
gethostbyaddr_r gethostbyname_r getpwnam \ gethostbyaddr_r gethostbyname_r getpwnam \
bfill bzero bcmp strstr strpbrk strerror \ bfill bzero bcmp strstr strpbrk strerror \
......
...@@ -171,6 +171,38 @@ set @@rand_seed1=10000000,@@rand_seed2=1000000; ...@@ -171,6 +171,38 @@ set @@rand_seed1=10000000,@@rand_seed2=1000000;
select ROUND(RAND(),5); select ROUND(RAND(),5);
ROUND(RAND(),5) ROUND(RAND(),5)
0.02887 0.02887
show variables like '%alloc%';
Variable_name Value
query_alloc_block_size 8192
query_prealloc_size 8192
range_alloc_block_size 2048
transaction_alloc_block_size 8192
transaction_prealloc_size 4096
set @@range_alloc_block_size=1024*16;
set @@query_alloc_block_size=1024*17+2;
set @@query_prealloc_size=1024*18;
set @@transaction_alloc_block_size=1024*20-1;
set @@transaction_prealloc_size=1024*21-1;
select @@query_alloc_block_size;
@@query_alloc_block_size
17408
show variables like '%alloc%';
Variable_name Value
query_alloc_block_size 17408
query_prealloc_size 18432
range_alloc_block_size 16384
transaction_alloc_block_size 19456
transaction_prealloc_size 20480
set @@range_alloc_block_size=default;
set @@query_alloc_block_size=default, @@query_prealloc_size=default;
set transaction_alloc_block_size=default, @@transaction_prealloc_size=default;
show variables like '%alloc%';
Variable_name Value
query_alloc_block_size 8192
query_prealloc_size 8192
range_alloc_block_size 2048
transaction_alloc_block_size 8192
transaction_prealloc_size 4096
set big_tables=OFFF; set big_tables=OFFF;
Variable 'big_tables' can't be set to the value of 'OFFF' Variable 'big_tables' can't be set to the value of 'OFFF'
set big_tables="OFFF"; set big_tables="OFFF";
......
...@@ -99,6 +99,18 @@ select @@timestamp>0; ...@@ -99,6 +99,18 @@ select @@timestamp>0;
set @@rand_seed1=10000000,@@rand_seed2=1000000; set @@rand_seed1=10000000,@@rand_seed2=1000000;
select ROUND(RAND(),5); select ROUND(RAND(),5);
show variables like '%alloc%';
set @@range_alloc_block_size=1024*16;
set @@query_alloc_block_size=1024*17+2;
set @@query_prealloc_size=1024*18;
set @@transaction_alloc_block_size=1024*20-1;
set @@transaction_prealloc_size=1024*21-1;
select @@query_alloc_block_size;
show variables like '%alloc%';
set @@range_alloc_block_size=default;
set @@query_alloc_block_size=default, @@query_prealloc_size=default;
set transaction_alloc_block_size=default, @@transaction_prealloc_size=default;
show variables like '%alloc%';
# The following should give errors # The following should give errors
......
...@@ -240,7 +240,7 @@ int berkeley_show_logs(THD *thd) ...@@ -240,7 +240,7 @@ int berkeley_show_logs(THD *thd)
MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC); MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
DBUG_ENTER("berkeley_show_logs"); DBUG_ENTER("berkeley_show_logs");
init_alloc_root(&show_logs_root, 1024, 1024); init_sql_alloc(&show_logs_root, 1024, 1024);
my_pthread_setspecific_ptr(THR_MALLOC,&show_logs_root); my_pthread_setspecific_ptr(THR_MALLOC,&show_logs_root);
if ((error= log_archive(db_env, &all_logs, DB_ARCH_ABS | DB_ARCH_LOG, if ((error= log_archive(db_env, &all_logs, DB_ARCH_ABS | DB_ARCH_LOG,
......
...@@ -1771,7 +1771,7 @@ void Unknown_log_event::print(FILE* file, bool short_form, char* last_db) ...@@ -1771,7 +1771,7 @@ void Unknown_log_event::print(FILE* file, bool short_form, char* last_db)
int Query_log_event::exec_event(struct st_relay_log_info* rli) int Query_log_event::exec_event(struct st_relay_log_info* rli)
{ {
int expected_error, actual_error= 0; int expected_error, actual_error= 0;
init_sql_alloc(&thd->mem_root, 8192,0); init_sql_alloc(&thd->mem_root, thd->variables.query_alloc_block_size,0);
thd->db= (char*) rewrite_db(db); thd->db= (char*) rewrite_db(db);
/* /*
...@@ -1912,7 +1912,7 @@ Default database: '%s'", ...@@ -1912,7 +1912,7 @@ Default database: '%s'",
int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
bool use_rli_only_for_errors) bool use_rli_only_for_errors)
{ {
init_sql_alloc(&thd->mem_root, 8192,0); init_sql_alloc(&thd->mem_root, thd->variables.query_alloc_block_size, 0);
thd->db= (char*) rewrite_db(db); thd->db= (char*) rewrite_db(db);
DBUG_ASSERT(thd->query == 0); DBUG_ASSERT(thd->query == 0);
thd->query = 0; // Should not be needed thd->query = 0; // Should not be needed
......
...@@ -75,6 +75,16 @@ char* query_table_status(THD *thd,const char *db,const char *table_name); ...@@ -75,6 +75,16 @@ char* query_table_status(THD *thd,const char *db,const char *table_name);
#define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int. #define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int.
#endif #endif
#define TEMP_POOL_SIZE 128 #define TEMP_POOL_SIZE 128
#define QUERY_ALLOC_BLOCK_SIZE 8192
#define QUERY_ALLOC_PREALLOC_SIZE 8192
#define TRANS_ALLOC_BLOCK_SIZE 4096
#define TRANS_ALLOC_PREALLOC_SIZE 4096
#define RANGE_ALLOC_BLOCK_SIZE 2048
#define ACL_ALLOC_BLOCK_SIZE 1024
#define UDF_ALLOC_BLOCK_SIZE 1024
#define TABLE_ALLOC_BLOCK_SIZE 1024
/* /*
The following parameters is to decide when to use an extra cache to The following parameters is to decide when to use an extra cache to
optimise seeks when reading a big table in sorted order optimise seeks when reading a big table in sorted order
......
...@@ -3242,7 +3242,10 @@ enum options { ...@@ -3242,7 +3242,10 @@ enum options {
OPT_BDB_LOG_BUFFER_SIZE, OPT_BDB_LOG_BUFFER_SIZE,
OPT_BDB_MAX_LOCK, OPT_BDB_MAX_LOCK,
OPT_ERROR_LOG_FILE, OPT_ERROR_LOG_FILE,
OPT_DEFAULT_WEEK_FORMAT OPT_DEFAULT_WEEK_FORMAT,
OPT_RANGE_ALLOC_BLOCK_SIZE,
OPT_QUERY_ALLOC_BLOCK_SIZE, OPT_QUERY_PREALLOC_SIZE,
OPT_TRANS_ALLOC_BLOCK_SIZE, OPT_TRANS_PREALLOC_SIZE
}; };
...@@ -3976,6 +3979,11 @@ this value; if zero (the default): when the size exceeds max_binlog_size. \ ...@@ -3976,6 +3979,11 @@ this value; if zero (the default): when the size exceeds max_binlog_size. \
"If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.", "If this is not 0, then mysqld will use this value to reserve file descriptors to use with setrlimit(). If this value is 0 then mysqld will reserve max_connections*5 or max_connections + table_cache*2 (whichever is larger) number of files.",
(gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG, (gptr*) &open_files_limit, (gptr*) &open_files_limit, 0, GET_ULONG,
REQUIRED_ARG, 0, 0, 65535, 0, 1, 0}, REQUIRED_ARG, 0, 0, 65535, 0, 1, 0},
{"query_alloc_block_size", OPT_QUERY_ALLOC_BLOCK_SIZE,
"Allocation block size for query parsing and execution",
(gptr*) &global_system_variables.query_alloc_block_size,
(gptr*) &max_system_variables.query_alloc_block_size, 0, GET_ULONG,
REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0},
#ifdef HAVE_QUERY_CACHE #ifdef HAVE_QUERY_CACHE
{"query_cache_limit", OPT_QUERY_CACHE_LIMIT, {"query_cache_limit", OPT_QUERY_CACHE_LIMIT,
"Don't cache results that are bigger than this.", "Don't cache results that are bigger than this.",
...@@ -3992,6 +4000,11 @@ this value; if zero (the default): when the size exceeds max_binlog_size. \ ...@@ -3992,6 +4000,11 @@ this value; if zero (the default): when the size exceeds max_binlog_size. \
(gptr*) &global_system_variables.query_cache_type, (gptr*) &global_system_variables.query_cache_type,
(gptr*) &max_system_variables.query_cache_type, (gptr*) &max_system_variables.query_cache_type,
0, GET_ULONG, REQUIRED_ARG, 1, 0, 2, 0, 1, 0}, 0, GET_ULONG, REQUIRED_ARG, 1, 0, 2, 0, 1, 0},
{"query_prealloc_size", OPT_QUERY_PREALLOC_SIZE,
"Persistent buffer for query parsing and execution",
(gptr*) &global_system_variables.query_prealloc_size,
(gptr*) &max_system_variables.query_prealloc_size, 0, GET_ULONG,
REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0},
#endif /*HAVE_QUERY_CACHE*/ #endif /*HAVE_QUERY_CACHE*/
{"read_buffer_size", OPT_RECORD_BUFFER, {"read_buffer_size", OPT_RECORD_BUFFER,
"Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.", "Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.",
...@@ -4023,6 +4036,11 @@ this value; if zero (the default): when the size exceeds max_binlog_size. \ ...@@ -4023,6 +4036,11 @@ this value; if zero (the default): when the size exceeds max_binlog_size. \
"Number of seconds to wait for more data from a master/slave connection before aborting the read.", "Number of seconds to wait for more data from a master/slave connection before aborting the read.",
(gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0, (gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0,
GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
{"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE,
"Allocation block size for storing ranges during optimization",
(gptr*) &global_system_variables.range_alloc_block_size,
(gptr*) &max_system_variables.range_alloc_block_size, 0, GET_ULONG,
REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0},
{"read-only", OPT_READONLY, {"read-only", OPT_READONLY,
"Make all tables readonly, with the expections for replications (slave) threads and users with the SUPER privilege", "Make all tables readonly, with the expections for replications (slave) threads and users with the SUPER privilege",
(gptr*) &opt_readonly, (gptr*) &opt_readonly,
...@@ -4059,6 +4077,16 @@ this value; if zero (the default): when the size exceeds max_binlog_size. \ ...@@ -4059,6 +4077,16 @@ this value; if zero (the default): when the size exceeds max_binlog_size. \
"The stack size for each thread.", (gptr*) &thread_stack, "The stack size for each thread.", (gptr*) &thread_stack,
(gptr*) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK, (gptr*) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK,
1024*32, ~0L, 0, 1024, 0}, 1024*32, ~0L, 0, 1024, 0},
{"transaction_alloc_block_size", OPT_TRANS_ALLOC_BLOCK_SIZE,
"Allocation block size for transactions to be stored in binary log",
(gptr*) &global_system_variables.trans_alloc_block_size,
(gptr*) &max_system_variables.trans_alloc_block_size, 0, GET_ULONG,
REQUIRED_ARG, QUERY_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0},
{"transaction_prealloc_size", OPT_TRANS_PREALLOC_SIZE,
"Persistent buffer for transactions to be stored in binary log",
(gptr*) &global_system_variables.trans_prealloc_size,
(gptr*) &max_system_variables.trans_prealloc_size, 0, GET_ULONG,
REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0},
{"wait_timeout", OPT_WAIT_TIMEOUT, {"wait_timeout", OPT_WAIT_TIMEOUT,
"The number of seconds the server waits for activity on a connection before closing it", "The number of seconds the server waits for activity on a connection before closing it",
(gptr*) &global_system_variables.net_wait_timeout, (gptr*) &global_system_variables.net_wait_timeout,
......
...@@ -26,11 +26,11 @@ ...@@ -26,11 +26,11 @@
** Create a FT or QUICK RANGE based on a key ** Create a FT or QUICK RANGE based on a key
****************************************************************************/ ****************************************************************************/
QUICK_SELECT *get_ft_or_quick_select_for_ref(TABLE *table, JOIN_TAB *tab) QUICK_SELECT *get_ft_or_quick_select_for_ref(THD *thd, TABLE *table,
JOIN_TAB *tab)
{ {
if (tab->type == JT_FT) if (tab->type == JT_FT)
return new FT_SELECT(table, &tab->ref); return new FT_SELECT(thd, table, &tab->ref);
else return get_quick_select_for_ref(thd, table, &tab->ref);
return get_quick_select_for_ref(table, &tab->ref);
} }
...@@ -28,13 +28,14 @@ class FT_SELECT: public QUICK_SELECT { ...@@ -28,13 +28,14 @@ class FT_SELECT: public QUICK_SELECT {
public: public:
TABLE_REF *ref; TABLE_REF *ref;
FT_SELECT(TABLE *table, TABLE_REF *tref) : FT_SELECT(THD *thd, TABLE *table, TABLE_REF *tref) :
QUICK_SELECT (table,tref->key,1), ref(tref) { init(); } QUICK_SELECT (thd, table, tref->key, 1), ref(tref) { init(); }
int init() { return error=file->ft_init(); } int init() { return error=file->ft_init(); }
int get_next() { return error=file->ft_read(record); } int get_next() { return error=file->ft_read(record); }
}; };
QUICK_SELECT *get_ft_or_quick_select_for_ref(TABLE *table, JOIN_TAB *tab); QUICK_SELECT *get_ft_or_quick_select_for_ref(THD *thd, TABLE *table,
JOIN_TAB *tab);
#endif #endif
...@@ -280,6 +280,7 @@ public: ...@@ -280,6 +280,7 @@ public:
typedef struct st_qsel_param { typedef struct st_qsel_param {
THD *thd;
TABLE *table; TABLE *table;
KEY_PART *key_parts,*key_parts_end,*key[MAX_KEY]; KEY_PART *key_parts,*key_parts_end,*key[MAX_KEY];
MEM_ROOT *mem_root; MEM_ROOT *mem_root;
...@@ -382,13 +383,14 @@ SQL_SELECT::~SQL_SELECT() ...@@ -382,13 +383,14 @@ SQL_SELECT::~SQL_SELECT()
#undef index // Fix for Unixware 7 #undef index // Fix for Unixware 7
QUICK_SELECT::QUICK_SELECT(TABLE *table,uint key_nr,bool no_alloc) QUICK_SELECT::QUICK_SELECT(THD *thd, TABLE *table, uint key_nr, bool no_alloc)
:dont_free(0),error(0),index(key_nr),max_used_key_length(0),head(table), :dont_free(0),error(0),index(key_nr),max_used_key_length(0),head(table),
it(ranges),range(0) it(ranges),range(0)
{ {
if (!no_alloc) if (!no_alloc)
{ {
init_sql_alloc(&alloc,1024,0); // Allocates everything here // Allocates everything through the internal memroot
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
my_pthread_setspecific_ptr(THR_MALLOC,&alloc); my_pthread_setspecific_ptr(THR_MALLOC,&alloc);
} }
else else
...@@ -460,17 +462,17 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg) ...@@ -460,17 +462,17 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg)
SEL_ARG *tmp; SEL_ARG *tmp;
if (type != KEY_RANGE) if (type != KEY_RANGE)
{ {
if(!(tmp=new SEL_ARG(type))) if (!(tmp= new SEL_ARG(type)))
return 0; // out of memory return 0; // out of memory
tmp->prev= *next_arg; // Link into next/prev chain tmp->prev= *next_arg; // Link into next/prev chain
(*next_arg)->next=tmp; (*next_arg)->next=tmp;
(*next_arg)= tmp; (*next_arg)= tmp;
} }
else else
{ {
if(!(tmp=new SEL_ARG(field,part, min_value,max_value, if (!(tmp= new SEL_ARG(field,part, min_value,max_value,
min_flag, max_flag, maybe_flag))) min_flag, max_flag, maybe_flag)))
return 0; // out of memory return 0; // OOM
tmp->parent=new_parent; tmp->parent=new_parent;
tmp->next_key_part=next_key_part; tmp->next_key_part=next_key_part;
if (left != &null_element) if (left != &null_element)
...@@ -481,7 +483,8 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg) ...@@ -481,7 +483,8 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg)
(*next_arg)= tmp; (*next_arg)= tmp;
if (right != &null_element) if (right != &null_element)
tmp->right=right->clone(tmp,next_arg); if (!(tmp->right= right->clone(tmp,next_arg)))
return 0; // OOM
} }
increment_use_count(1); increment_use_count(1);
return tmp; return tmp;
...@@ -560,10 +563,11 @@ SEL_ARG *SEL_ARG::clone_tree() ...@@ -560,10 +563,11 @@ SEL_ARG *SEL_ARG::clone_tree()
{ {
SEL_ARG tmp_link,*next_arg,*root; SEL_ARG tmp_link,*next_arg,*root;
next_arg= &tmp_link; next_arg= &tmp_link;
root=clone((SEL_ARG *) 0, &next_arg); root= clone((SEL_ARG *) 0, &next_arg);
next_arg->next=0; // Fix last link next_arg->next=0; // Fix last link
tmp_link.next->prev=0; // Fix first link tmp_link.next->prev=0; // Fix first link
root->use_count=0; if (root) // If not OOM
root->use_count= 0;
return root; return root;
} }
...@@ -581,7 +585,8 @@ SEL_ARG *SEL_ARG::clone_tree() ...@@ -581,7 +585,8 @@ SEL_ARG *SEL_ARG::clone_tree()
** quick_rows ; How many rows the key matches ** quick_rows ; How many rows the key matches
*****************************************************************************/ *****************************************************************************/
int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables, int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
table_map prev_tables,
ha_rows limit, bool force_quick_range) ha_rows limit, bool force_quick_range)
{ {
uint basflag; uint basflag;
...@@ -624,6 +629,7 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables, ...@@ -624,6 +629,7 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
PARAM param; PARAM param;
/* set up parameter that is passed to all functions */ /* set up parameter that is passed to all functions */
param.thd= thd;
param.baseflag=basflag; param.baseflag=basflag;
param.prev_tables=prev_tables | const_tables; param.prev_tables=prev_tables | const_tables;
param.read_tables=read_tables; param.read_tables=read_tables;
...@@ -632,13 +638,13 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables, ...@@ -632,13 +638,13 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
param.keys=0; param.keys=0;
param.mem_root= &alloc; param.mem_root= &alloc;
current_thd->no_errors=1; // Don't warn about NULL param.thd->no_errors=1; // Don't warn about NULL
init_sql_alloc(&alloc,2048,0); init_sql_alloc(&alloc, param.thd->variables.range_alloc_block_size, 0);
if (!(param.key_parts = (KEY_PART*) alloc_root(&alloc, if (!(param.key_parts = (KEY_PART*) alloc_root(&alloc,
sizeof(KEY_PART)* sizeof(KEY_PART)*
head->key_parts))) head->key_parts)))
{ {
current_thd->no_errors=0; param.thd->no_errors=0;
free_root(&alloc,MYF(0)); // Return memory & allocator free_root(&alloc,MYF(0)); // Return memory & allocator
DBUG_RETURN(0); // Can't use range DBUG_RETURN(0); // Can't use range
} }
...@@ -737,7 +743,7 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables, ...@@ -737,7 +743,7 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables,
} }
free_root(&alloc,MYF(0)); // Return memory & allocator free_root(&alloc,MYF(0)); // Return memory & allocator
my_pthread_setspecific_ptr(THR_MALLOC,old_root); my_pthread_setspecific_ptr(THR_MALLOC,old_root);
current_thd->no_errors=0; param.thd->no_errors=0;
} }
DBUG_EXECUTE("info",print_quick(quick,needed_reg);); DBUG_EXECUTE("info",print_quick(quick,needed_reg););
/* /*
...@@ -765,7 +771,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) ...@@ -765,7 +771,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
while ((item=li++)) while ((item=li++))
{ {
SEL_TREE *new_tree=get_mm_tree(param,item); SEL_TREE *new_tree=get_mm_tree(param,item);
if(current_thd->fatal_error) if (param->thd->fatal_error)
DBUG_RETURN(0); // out of memory DBUG_RETURN(0); // out of memory
tree=tree_and(param,tree,new_tree); tree=tree_and(param,tree,new_tree);
if (tree && tree->type == SEL_TREE::IMPOSSIBLE) if (tree && tree->type == SEL_TREE::IMPOSSIBLE)
...@@ -906,7 +912,7 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, ...@@ -906,7 +912,7 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
{ {
SEL_ARG *sel_arg=0; SEL_ARG *sel_arg=0;
if (!tree && !(tree=new SEL_TREE())) if (!tree && !(tree=new SEL_TREE()))
DBUG_RETURN(0); // out of memory DBUG_RETURN(0); // OOM
if (!value || !(value->used_tables() & ~param->read_tables)) if (!value || !(value->used_tables() & ~param->read_tables))
{ {
sel_arg=get_mm_leaf(param,key_part->field,key_part,type,value); sel_arg=get_mm_leaf(param,key_part->field,key_part,type,value);
...@@ -918,10 +924,11 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, ...@@ -918,10 +924,11 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type,
DBUG_RETURN(tree); DBUG_RETURN(tree);
} }
} }
else { else
{
// This key may be used later // This key may be used later
if(!(sel_arg=new SEL_ARG(SEL_ARG::MAYBE_KEY))) if (!(sel_arg= new SEL_ARG(SEL_ARG::MAYBE_KEY)))
DBUG_RETURN(0); // out of memory DBUG_RETURN(0); // OOM
} }
sel_arg->part=(uchar) key_part->part; sel_arg->part=(uchar) key_part->part;
tree->keys[key_part->key]=sel_add(tree->keys[key_part->key],sel_arg); tree->keys[key_part->key]=sel_add(tree->keys[key_part->key],sel_arg);
...@@ -1164,8 +1171,8 @@ static bool like_range(const char *ptr,uint ptr_length,char escape, ...@@ -1164,8 +1171,8 @@ static bool like_range(const char *ptr,uint ptr_length,char escape,
******************************************************************************/ ******************************************************************************/
/* /*
** Add a new key test to a key when scanning through all keys Add a new key test to a key when scanning through all keys
** This will never be called for same key parts. This will never be called for same key parts.
*/ */
static SEL_ARG * static SEL_ARG *
...@@ -1349,7 +1356,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag) ...@@ -1349,7 +1356,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
// key1->part < key2->part // key1->part < key2->part
key1->use_count--; key1->use_count--;
if (key1->use_count > 0) if (key1->use_count > 0)
key1=key1->clone_tree(); if (!(key1= key1->clone_tree()))
return 0; // OOM
return and_all_keys(key1,key2,clone_flag); return and_all_keys(key1,key2,clone_flag);
} }
...@@ -1368,7 +1376,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag) ...@@ -1368,7 +1376,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
if (key1->use_count > 1) if (key1->use_count > 1)
{ {
key1->use_count--; key1->use_count--;
key1=key1->clone_tree(); if (!(key1=key1->clone_tree()))
return 0; // OOM
key1->use_count++; key1->use_count++;
} }
if (key1->type == SEL_ARG::MAYBE_KEY) if (key1->type == SEL_ARG::MAYBE_KEY)
...@@ -1412,6 +1421,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag) ...@@ -1412,6 +1421,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag)
if (!next || next->type != SEL_ARG::IMPOSSIBLE) if (!next || next->type != SEL_ARG::IMPOSSIBLE)
{ {
SEL_ARG *new_arg= e1->clone_and(e2); SEL_ARG *new_arg= e1->clone_and(e2);
if (!new_arg)
return &null_element; // End of memory
new_arg->next_key_part=next; new_arg->next_key_part=next;
if (!new_tree) if (!new_tree)
{ {
...@@ -1499,8 +1510,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) ...@@ -1499,8 +1510,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
{ {
swap(SEL_ARG *,key1,key2); swap(SEL_ARG *,key1,key2);
} }
else else if (!(key1=key1->clone_tree()))
key1=key1->clone_tree(); return 0; // OOM
} }
// Add tree at key2 to tree at key1 // Add tree at key2 to tree at key1
...@@ -1526,7 +1537,7 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) ...@@ -1526,7 +1537,7 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
SEL_ARG *key2_next=key2->next; SEL_ARG *key2_next=key2->next;
if (key2_shared) if (key2_shared)
{ {
if(!(key2=new SEL_ARG(*key2))) if (!(key2=new SEL_ARG(*key2)))
return 0; // out of memory return 0; // out of memory
key2->increment_use_count(key1->use_count+1); key2->increment_use_count(key1->use_count+1);
key2->next=key2_next; // New copy of key2 key2->next=key2_next; // New copy of key2
...@@ -1568,7 +1579,10 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) ...@@ -1568,7 +1579,10 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
SEL_ARG *next=key2->next; // Keys are not overlapping SEL_ARG *next=key2->next; // Keys are not overlapping
if (key2_shared) if (key2_shared)
{ {
key1=key1->insert(new SEL_ARG(*key2)); // Must make copy SEL_ARG *tmp= new SEL_ARG(*key2); // Must make copy
if (!tmp)
return 0; // OOM
key1=key1->insert(tmp);
key2->increment_use_count(key1->use_count+1); key2->increment_use_count(key1->use_count+1);
} }
else else
...@@ -1614,6 +1628,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) ...@@ -1614,6 +1628,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
if (cmp >= 0 && tmp->cmp_min_to_min(key2) < 0) if (cmp >= 0 && tmp->cmp_min_to_min(key2) < 0)
{ // tmp.min <= x < key2.min { // tmp.min <= x < key2.min
SEL_ARG *new_arg=tmp->clone_first(key2); SEL_ARG *new_arg=tmp->clone_first(key2);
if (!new_arg)
return 0; // OOM
if ((new_arg->next_key_part= key1->next_key_part)) if ((new_arg->next_key_part= key1->next_key_part))
new_arg->increment_use_count(key1->use_count+1); new_arg->increment_use_count(key1->use_count+1);
tmp->copy_min_to_min(key2); tmp->copy_min_to_min(key2);
...@@ -1627,6 +1643,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) ...@@ -1627,6 +1643,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
if (tmp->cmp_min_to_min(&key) > 0) if (tmp->cmp_min_to_min(&key) > 0)
{ // key.min <= x < tmp.min { // key.min <= x < tmp.min
SEL_ARG *new_arg=key.clone_first(tmp); SEL_ARG *new_arg=key.clone_first(tmp);
if (!new_arg)
return 0; // OOM
if ((new_arg->next_key_part=key.next_key_part)) if ((new_arg->next_key_part=key.next_key_part))
new_arg->increment_use_count(key1->use_count+1); new_arg->increment_use_count(key1->use_count+1);
key1=key1->insert(new_arg); key1=key1->insert(new_arg);
...@@ -1641,19 +1659,27 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) ...@@ -1641,19 +1659,27 @@ key_or(SEL_ARG *key1,SEL_ARG *key2)
key.copy_max_to_min(tmp); key.copy_max_to_min(tmp);
if (!(tmp=tmp->next)) if (!(tmp=tmp->next))
{ {
key1=key1->insert(new SEL_ARG(key)); SEL_ARG *tmp2= new SEL_ARG(key);
if (!tmp2)
return 0; // OOM
key1=key1->insert(tmp2);
key2=key2->next; key2=key2->next;
goto end; goto end;
} }
if (tmp->cmp_min_to_max(&key) > 0) if (tmp->cmp_min_to_max(&key) > 0)
{ {
key1=key1->insert(new SEL_ARG(key)); SEL_ARG *tmp2= new SEL_ARG(key);
if (!tmp2)
return 0; // OOM
key1=key1->insert(tmp2);
break; break;
} }
} }
else else
{ {
SEL_ARG *new_arg=tmp->clone_last(&key); // tmp.min <= x <= key.max SEL_ARG *new_arg=tmp->clone_last(&key); // tmp.min <= x <= key.max
if (!new_arg)
return 0; // OOM
tmp->copy_max_to_min(&key); tmp->copy_max_to_min(&key);
tmp->increment_use_count(key1->use_count+1); tmp->increment_use_count(key1->use_count+1);
new_arg->next_key_part=key_or(tmp->next_key_part,key.next_key_part); new_arg->next_key_part=key_or(tmp->next_key_part,key.next_key_part);
...@@ -1670,8 +1696,11 @@ end: ...@@ -1670,8 +1696,11 @@ end:
SEL_ARG *next=key2->next; SEL_ARG *next=key2->next;
if (key2_shared) if (key2_shared)
{ {
SEL_ARG *tmp=new SEL_ARG(*key2); // Must make copy
if (!tmp)
return 0;
key2->increment_use_count(key1->use_count+1); key2->increment_use_count(key1->use_count+1);
key1=key1->insert(new SEL_ARG(*key2)); // Must make copy key1=key1->insert(tmp);
} }
else else
key1=key1->insert(key2); // Will destroy key2_root key1=key1->insert(key2); // Will destroy key2_root
...@@ -2247,7 +2276,8 @@ get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree) ...@@ -2247,7 +2276,8 @@ get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree)
{ {
QUICK_SELECT *quick; QUICK_SELECT *quick;
DBUG_ENTER("get_quick_select"); DBUG_ENTER("get_quick_select");
if ((quick=new QUICK_SELECT(param->table,param->real_keynr[idx]))) if ((quick=new QUICK_SELECT(param->thd, param->table,
param->real_keynr[idx])))
{ {
if (quick->error || if (quick->error ||
get_quick_keys(param,quick,param->key[idx],key_tree,param->min_key,0, get_quick_keys(param,quick,param->key[idx],key_tree,param->min_key,0,
...@@ -2351,11 +2381,11 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key, ...@@ -2351,11 +2381,11 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key,
} }
/* Get range for retrieving rows in QUICK_SELECT::get_next */ /* Get range for retrieving rows in QUICK_SELECT::get_next */
if(!(range= new QUICK_RANGE(param->min_key, if (!(range= new QUICK_RANGE(param->min_key,
(uint) (tmp_min_key - param->min_key), (uint) (tmp_min_key - param->min_key),
param->max_key, param->max_key,
(uint) (tmp_max_key - param->max_key), (uint) (tmp_max_key - param->max_key),
flag))) flag)))
return 1; // out of memory return 1; // out of memory
set_if_bigger(quick->max_used_key_length,range->min_length); set_if_bigger(quick->max_used_key_length,range->min_length);
...@@ -2411,10 +2441,10 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length) ...@@ -2411,10 +2441,10 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length)
** Create a QUICK RANGE based on a key ** Create a QUICK RANGE based on a key
****************************************************************************/ ****************************************************************************/
QUICK_SELECT *get_quick_select_for_ref(TABLE *table, TABLE_REF *ref) QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table, TABLE_REF *ref)
{ {
table->file->index_end(); // Remove old cursor table->file->index_end(); // Remove old cursor
QUICK_SELECT *quick=new QUICK_SELECT(table, ref->key, 1); QUICK_SELECT *quick=new QUICK_SELECT(thd, table, ref->key, 1);
KEY *key_info = &table->key_info[ref->key]; KEY *key_info = &table->key_info[ref->key];
KEY_PART *key_part; KEY_PART *key_part;
uint part; uint part;
...@@ -2423,7 +2453,7 @@ QUICK_SELECT *get_quick_select_for_ref(TABLE *table, TABLE_REF *ref) ...@@ -2423,7 +2453,7 @@ QUICK_SELECT *get_quick_select_for_ref(TABLE *table, TABLE_REF *ref)
return 0; /* no ranges found */ return 0; /* no ranges found */
if (cp_buffer_from_ref(ref)) if (cp_buffer_from_ref(ref))
{ {
if (current_thd->fatal_error) if (thd->fatal_error)
return 0; // out of memory return 0; // out of memory
return quick; // empty range return quick; // empty range
} }
......
...@@ -80,7 +80,7 @@ public: ...@@ -80,7 +80,7 @@ public:
ha_rows records; ha_rows records;
double read_time; double read_time;
QUICK_SELECT(TABLE *table,uint index_arg,bool no_alloc=0); QUICK_SELECT(THD *thd, TABLE *table,uint index_arg,bool no_alloc=0);
virtual ~QUICK_SELECT(); virtual ~QUICK_SELECT();
void reset(void) { next=0; it.rewind(); } void reset(void) { next=0; it.rewind(); }
int init() { return error=file->index_init(index); } int init() { return error=file->index_init(index); }
...@@ -124,13 +124,15 @@ class SQL_SELECT :public Sql_alloc { ...@@ -124,13 +124,15 @@ class SQL_SELECT :public Sql_alloc {
SQL_SELECT(); SQL_SELECT();
~SQL_SELECT(); ~SQL_SELECT();
bool check_quick(bool force_quick_range=0, ha_rows limit = HA_POS_ERROR) bool check_quick(THD *thd, bool force_quick_range= 0,
{ return test_quick_select(~0L,0,limit, force_quick_range) < 0; } ha_rows limit= HA_POS_ERROR)
{ return test_quick_select(thd, ~0L,0,limit, force_quick_range) < 0; }
inline bool skipp_record() { return cond ? cond->val_int() == 0 : 0; } inline bool skipp_record() { return cond ? cond->val_int() == 0 : 0; }
int test_quick_select(key_map keys,table_map prev_tables,ha_rows limit, int test_quick_select(THD *thd, key_map keys, table_map prev_tables,
bool force_quick_range=0); ha_rows limit, bool force_quick_range=0);
}; };
QUICK_SELECT *get_quick_select_for_ref(TABLE *table, struct st_table_ref *ref); QUICK_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
struct st_table_ref *ref);
#endif #endif
...@@ -201,6 +201,18 @@ sys_var_long_ptr sys_rpl_recovery_rank("rpl_recovery_rank", ...@@ -201,6 +201,18 @@ sys_var_long_ptr sys_rpl_recovery_rank("rpl_recovery_rank",
sys_var_long_ptr sys_query_cache_size("query_cache_size", sys_var_long_ptr sys_query_cache_size("query_cache_size",
&query_cache_size, &query_cache_size,
fix_query_cache_size); fix_query_cache_size);
sys_var_thd_ulong sys_range_alloc_block_size("range_alloc_block_size",
&SV::range_alloc_block_size);
sys_var_thd_ulong sys_query_alloc_block_size("query_alloc_block_size",
&SV::query_alloc_block_size);
sys_var_thd_ulong sys_query_prealloc_size("query_prealloc_size",
&SV::query_prealloc_size);
sys_var_thd_ulong sys_trans_alloc_block_size("transaction_alloc_block_size",
&SV::trans_alloc_block_size);
sys_var_thd_ulong sys_trans_prealloc_size("transaction_prealloc_size",
&SV::trans_prealloc_size);
#ifdef HAVE_QUERY_CACHE #ifdef HAVE_QUERY_CACHE
sys_var_long_ptr sys_query_cache_limit("query_cache_limit", sys_var_long_ptr sys_query_cache_limit("query_cache_limit",
&query_cache.query_cache_limit); &query_cache.query_cache_limit);
...@@ -372,7 +384,9 @@ sys_var *sys_variables[]= ...@@ -372,7 +384,9 @@ sys_var *sys_variables[]=
&sys_net_wait_timeout, &sys_net_wait_timeout,
&sys_net_write_timeout, &sys_net_write_timeout,
&sys_new_mode, &sys_new_mode,
&sys_query_alloc_block_size,
&sys_query_cache_size, &sys_query_cache_size,
&sys_query_prealloc_size,
#ifdef HAVE_QUERY_CACHE #ifdef HAVE_QUERY_CACHE
&sys_query_cache_limit, &sys_query_cache_limit,
&sys_query_cache_type, &sys_query_cache_type,
...@@ -382,6 +396,7 @@ sys_var *sys_variables[]= ...@@ -382,6 +396,7 @@ sys_var *sys_variables[]=
&sys_rand_seed2, &sys_rand_seed2,
&sys_read_buff_size, &sys_read_buff_size,
&sys_read_rnd_buff_size, &sys_read_rnd_buff_size,
&sys_range_alloc_block_size,
&sys_rpl_recovery_rank, &sys_rpl_recovery_rank,
&sys_safe_updates, &sys_safe_updates,
&sys_select_limit, &sys_select_limit,
...@@ -401,6 +416,8 @@ sys_var *sys_variables[]= ...@@ -401,6 +416,8 @@ sys_var *sys_variables[]=
&sys_thread_cache_size, &sys_thread_cache_size,
&sys_timestamp, &sys_timestamp,
&sys_tmp_table_size, &sys_tmp_table_size,
&sys_trans_alloc_block_size,
&sys_trans_prealloc_size,
&sys_tx_isolation, &sys_tx_isolation,
#ifdef HAVE_INNOBASE_DB #ifdef HAVE_INNOBASE_DB
&sys_innodb_max_dirty_pages_pct, &sys_innodb_max_dirty_pages_pct,
...@@ -530,14 +547,19 @@ struct show_var_st init_vars[]= { ...@@ -530,14 +547,19 @@ struct show_var_st init_vars[]= {
{"log_error", (char*) log_error_file, SHOW_CHAR}, {"log_error", (char*) log_error_file, SHOW_CHAR},
{"port", (char*) &mysql_port, SHOW_INT}, {"port", (char*) &mysql_port, SHOW_INT},
{"protocol_version", (char*) &protocol_version, SHOW_INT}, {"protocol_version", (char*) &protocol_version, SHOW_INT},
{sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size,
SHOW_SYS},
#ifdef HAVE_QUERY_CACHE #ifdef HAVE_QUERY_CACHE
{sys_query_cache_limit.name,(char*) &sys_query_cache_limit, SHOW_SYS}, {sys_query_cache_limit.name,(char*) &sys_query_cache_limit, SHOW_SYS},
{sys_query_cache_size.name, (char*) &sys_query_cache_size, SHOW_SYS}, {sys_query_cache_size.name, (char*) &sys_query_cache_size, SHOW_SYS},
{sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS}, {sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS},
#endif /* HAVE_QUERY_CACHE */ #endif /* HAVE_QUERY_CACHE */
{sys_query_prealloc_size.name, (char*) &sys_query_prealloc_size, SHOW_SYS},
{sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS}, {sys_read_buff_size.name, (char*) &sys_read_buff_size, SHOW_SYS},
{sys_readonly.name, (char*) &sys_readonly, SHOW_SYS}, {sys_readonly.name, (char*) &sys_readonly, SHOW_SYS},
{sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS}, {sys_read_rnd_buff_size.name,(char*) &sys_read_rnd_buff_size, SHOW_SYS},
{sys_range_alloc_block_size.name, (char*) &sys_range_alloc_block_size,
SHOW_SYS},
{sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS}, {sys_rpl_recovery_rank.name,(char*) &sys_rpl_recovery_rank, SHOW_SYS},
{sys_server_id.name, (char*) &sys_server_id, SHOW_SYS}, {sys_server_id.name, (char*) &sys_server_id, SHOW_SYS},
{sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS}, {sys_slave_net_timeout.name,(char*) &sys_slave_net_timeout, SHOW_SYS},
...@@ -563,6 +585,9 @@ struct show_var_st init_vars[]= { ...@@ -563,6 +585,9 @@ struct show_var_st init_vars[]= {
#endif #endif
{sys_tmp_table_size.name, (char*) &sys_tmp_table_size, SHOW_SYS}, {sys_tmp_table_size.name, (char*) &sys_tmp_table_size, SHOW_SYS},
{"tmpdir", (char*) &mysql_tmpdir, SHOW_CHAR_PTR}, {"tmpdir", (char*) &mysql_tmpdir, SHOW_CHAR_PTR},
{sys_trans_alloc_block_size.name, (char*) &sys_trans_alloc_block_size,
SHOW_SYS},
{sys_trans_prealloc_size.name, (char*) &sys_trans_prealloc_size, SHOW_SYS},
{"version", server_version, SHOW_CHAR}, {"version", server_version, SHOW_CHAR},
{sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS}, {sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS},
{NullS, NullS, SHOW_LONG} {NullS, NullS, SHOW_LONG}
......
...@@ -183,7 +183,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) ...@@ -183,7 +183,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
thd->net.last_error); thd->net.last_error);
goto end; goto end;
} }
init_sql_alloc(&mem,1024,0); init_sql_alloc(&mem, ACL_ALLOC_BLOCK_SIZE, 0);
init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0); init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0);
VOID(my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50)); VOID(my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50));
while (!(read_record_info.read_record(&read_record_info))) while (!(read_record_info.read_record(&read_record_info)))
...@@ -2417,7 +2417,7 @@ my_bool grant_init(THD *org_thd) ...@@ -2417,7 +2417,7 @@ my_bool grant_init(THD *org_thd)
grant_option = FALSE; grant_option = FALSE;
(void) hash_init(&hash_tables,0,0,0, (hash_get_key) get_grant_table, (void) hash_init(&hash_tables,0,0,0, (hash_get_key) get_grant_table,
(hash_free_key) free_grant_table,0); (hash_free_key) free_grant_table,0);
init_sql_alloc(&memex,1024,0); init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0);
/* Don't do anything if running with --skip-grant */ /* Don't do anything if running with --skip-grant */
if (!initialized) if (!initialized)
......
...@@ -327,6 +327,11 @@ struct system_variables ...@@ -327,6 +327,11 @@ struct system_variables
ulong table_type; ulong table_type;
ulong default_week_format; ulong default_week_format;
ulong max_seeks_for_key; ulong max_seeks_for_key;
ulong range_alloc_block_size;
ulong query_alloc_block_size;
ulong query_prealloc_size;
ulong trans_alloc_block_size;
ulong trans_prealloc_size;
my_bool log_warnings; my_bool log_warnings;
my_bool low_priority_updates; my_bool low_priority_updates;
......
...@@ -76,7 +76,8 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -76,7 +76,8 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
select=make_select(table,0,0,conds,&error); select=make_select(table,0,0,conds,&error);
if (error) if (error)
DBUG_RETURN(-1); DBUG_RETURN(-1);
if ((select && select->check_quick(test(thd->options & OPTION_SAFE_UPDATES), if ((select && select->check_quick(thd,
test(thd->options & OPTION_SAFE_UPDATES),
limit)) || limit)) ||
!limit) !limit)
{ {
......
...@@ -46,11 +46,6 @@ ...@@ -46,11 +46,6 @@
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
#define SCRAMBLE_LENGTH 8 #define SCRAMBLE_LENGTH 8
#define MEM_ROOT_BLOCK_SIZE 8192
#define MEM_ROOT_PREALLOC 8192
#define TRANS_MEM_ROOT_BLOCK_SIZE 4096
#define TRANS_MEM_ROOT_PREALLOC 4096
extern int yyparse(void); extern int yyparse(void);
extern "C" pthread_mutex_t THR_LOCK_keycache; extern "C" pthread_mutex_t THR_LOCK_keycache;
#ifdef SOLARIS #ifdef SOLARIS
...@@ -714,9 +709,12 @@ pthread_handler_decl(handle_one_connection,arg) ...@@ -714,9 +709,12 @@ pthread_handler_decl(handle_one_connection,arg)
thd->command=COM_SLEEP; thd->command=COM_SLEEP;
thd->version=refresh_version; thd->version=refresh_version;
thd->set_time(); thd->set_time();
init_sql_alloc(&thd->mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); init_sql_alloc(&thd->mem_root, thd->variables.query_alloc_block_size,
thd->variables.query_prealloc_size);
init_sql_alloc(&thd->transaction.mem_root, init_sql_alloc(&thd->transaction.mem_root,
TRANS_MEM_ROOT_BLOCK_SIZE, TRANS_MEM_ROOT_PREALLOC); thd->variables.trans_alloc_block_size,
thd->variables.trans_prealloc_size);
while (!net->error && net->vio != 0 && !thd->killed) while (!net->error && net->vio != 0 && !thd->killed)
{ {
if (do_command(thd)) if (do_command(thd))
...@@ -791,9 +789,11 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) ...@@ -791,9 +789,11 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
thd->priv_user=thd->user=(char*) my_strdup("boot", MYF(MY_WME)); thd->priv_user=thd->user=(char*) my_strdup("boot", MYF(MY_WME));
buff= (char*) thd->net.buff; buff= (char*) thd->net.buff;
init_sql_alloc(&thd->mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC); init_sql_alloc(&thd->mem_root, thd->variables.query_alloc_block_size,
thd->variables.query_prealloc_size);
init_sql_alloc(&thd->transaction.mem_root, init_sql_alloc(&thd->transaction.mem_root,
TRANS_MEM_ROOT_BLOCK_SIZE, TRANS_MEM_ROOT_PREALLOC); thd->variables.trans_alloc_block_size,
thd->variables.trans_prealloc_size);
while (fgets(buff, thd->net.max_packet, file)) while (fgets(buff, thd->net.max_packet, file))
{ {
uint length=(uint) strlen(buff); uint length=(uint) strlen(buff);
......
...@@ -1000,7 +1000,8 @@ err: ...@@ -1000,7 +1000,8 @@ err:
Approximate how many records will be used in each table Approximate how many records will be used in each table
*****************************************************************************/ *****************************************************************************/
static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table, static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
TABLE *table,
key_map keys,ha_rows limit) key_map keys,ha_rows limit)
{ {
int error; int error;
...@@ -1009,7 +1010,7 @@ static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table, ...@@ -1009,7 +1010,7 @@ static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table,
{ {
select->head=table; select->head=table;
table->reginfo.impossible_range=0; table->reginfo.impossible_range=0;
if ((error=select->test_quick_select(keys,(table_map) 0,limit)) if ((error=select->test_quick_select(thd, keys,(table_map) 0,limit))
== 1) == 1)
DBUG_RETURN(select->quick->records); DBUG_RETURN(select->quick->records);
if (error == -1) if (error == -1)
...@@ -1290,8 +1291,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, ...@@ -1290,8 +1291,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
found_const_table_map, found_const_table_map,
s->on_expr ? s->on_expr : conds, s->on_expr ? s->on_expr : conds,
&error); &error);
records= get_quick_record_count(select,s->table, s->const_keys, records= get_quick_record_count(join->thd, select, s->table,
join->row_limit); s->const_keys, join->row_limit);
s->quick=select->quick; s->quick=select->quick;
s->needed_reg=select->needed_reg; s->needed_reg=select->needed_reg;
select->quick=0; select->quick=0;
...@@ -2687,7 +2688,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) ...@@ -2687,7 +2688,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
/* Join with outer join condition */ /* Join with outer join condition */
COND *orig_cond=sel->cond; COND *orig_cond=sel->cond;
sel->cond=and_conds(sel->cond,tab->on_expr); sel->cond=and_conds(sel->cond,tab->on_expr);
if (sel->test_quick_select(tab->keys, if (sel->test_quick_select(join->thd, tab->keys,
used_tables & ~ current_map, used_tables & ~ current_map,
(join->select_options & (join->select_options &
OPTION_FOUND_ROWS ? OPTION_FOUND_ROWS ?
...@@ -2697,7 +2698,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) ...@@ -2697,7 +2698,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
we have to check isn't it only "impossible ON" instead */ we have to check isn't it only "impossible ON" instead */
sel->cond=orig_cond; sel->cond=orig_cond;
if (!tab->on_expr || if (!tab->on_expr ||
sel->test_quick_select(tab->keys, sel->test_quick_select(join->thd, tab->keys,
used_tables & ~ current_map, used_tables & ~ current_map,
(join->select_options & (join->select_options &
OPTION_FOUND_ROWS ? OPTION_FOUND_ROWS ?
...@@ -5047,7 +5048,8 @@ test_if_quick_select(JOIN_TAB *tab) ...@@ -5047,7 +5048,8 @@ test_if_quick_select(JOIN_TAB *tab)
{ {
delete tab->select->quick; delete tab->select->quick;
tab->select->quick=0; tab->select->quick=0;
return tab->select->test_quick_select(tab->keys,(table_map) 0,HA_POS_ERROR); return tab->select->test_quick_select(tab->join->thd, tab->keys,
(table_map) 0, HA_POS_ERROR);
} }
...@@ -6014,7 +6016,8 @@ create_sort_index(JOIN_TAB *tab, ORDER *order, ha_rows filesort_limit, ...@@ -6014,7 +6016,8 @@ create_sort_index(JOIN_TAB *tab, ORDER *order, ha_rows filesort_limit,
For impossible ranges (like when doing a lookup on NULL on a NOT NULL For impossible ranges (like when doing a lookup on NULL on a NOT NULL
field, quick will contain an empty record set. field, quick will contain an empty record set.
*/ */
if (!(select->quick=get_ft_or_quick_select_for_ref(table, tab))) if (!(select->quick=get_ft_or_quick_select_for_ref(tab->join->thd,
table, tab)))
goto err; goto err;
} }
} }
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include "sql_select.h" #include "sql_select.h"
#include <hash.h> #include <hash.h>
#include <thr_alarm.h> #include <thr_alarm.h>
#include <malloc.h>
/* Intern key cache variables */ /* Intern key cache variables */
extern "C" pthread_mutex_t THR_LOCK_keycache; extern "C" pthread_mutex_t THR_LOCK_keycache;
...@@ -257,6 +258,32 @@ Next alarm time: %lu\n", ...@@ -257,6 +258,32 @@ Next alarm time: %lu\n",
thd->proc_info="malloc"; thd->proc_info="malloc";
my_checkmalloc(); my_checkmalloc();
TERMINATE(stdout); // Write malloc information TERMINATE(stdout); // Write malloc information
#ifdef HAVE_MALLINFO
struct mallinfo info= mallinfo();
printf("\nMemory status:\n\
Non-mmapped space allocated from system: %d\n\
Number of free chunks: %d\n\
Number of fastbin blocks: %d\n\
Number of mmapped regions: %d\n\
Space in mmapped regions: %d\n\
Maximum total allocated space: %d\n\
Space available in freed fastbin blocks: %d\n\
Total allocated space: %d\n\
Total free space: %d\n\
Top-most, releasable space: %d\n",
(int) info.arena,
(int) info.ordblks,
(int) info.smblks,
(int) info.hblks,
(int) info.hblkhd,
(int) info.usmblks,
(int) info.fsmblks,
(int) info.uordblks,
(int) info.fordblks,
(int) info.keepcost);
#endif
puts("");
if (thd) if (thd)
thd->proc_info=0; thd->proc_info=0;
} }
...@@ -124,7 +124,7 @@ void udf_init() ...@@ -124,7 +124,7 @@ void udf_init()
pthread_mutex_init(&THR_LOCK_udf,MY_MUTEX_INIT_SLOW); pthread_mutex_init(&THR_LOCK_udf,MY_MUTEX_INIT_SLOW);
init_sql_alloc(&mem, 1024,0); init_sql_alloc(&mem, UDF_ALLOC_BLOCK_SIZE, 0);
THD *new_thd = new THD; THD *new_thd = new THD;
if (!new_thd || if (!new_thd ||
hash_init(&udf_hash,32,0,0,get_hash_key, NULL, HASH_CASE_INSENSITIVE)) hash_init(&udf_hash,32,0,0,get_hash_key, NULL, HASH_CASE_INSENSITIVE))
......
...@@ -130,7 +130,7 @@ int mysql_update(THD *thd, ...@@ -130,7 +130,7 @@ int mysql_update(THD *thd,
table->used_keys=0; table->used_keys=0;
select=make_select(table,0,0,conds,&error); select=make_select(table,0,0,conds,&error);
if (error || if (error ||
(select && select->check_quick(safe_update, limit)) || !limit) (select && select->check_quick(thd, safe_update, limit)) || !limit)
{ {
delete select; delete select;
if (error) if (error)
......
...@@ -70,7 +70,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, ...@@ -70,7 +70,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag,
outparam->db_stat = db_stat; outparam->db_stat = db_stat;
error=1; error=1;
init_sql_alloc(&outparam->mem_root,1024,0); init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC); MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
my_pthread_setspecific_ptr(THR_MALLOC,&outparam->mem_root); my_pthread_setspecific_ptr(THR_MALLOC,&outparam->mem_root);
......
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