diff options
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | mysql-test/r/variables.result | 32 | ||||
-rw-r--r-- | mysql-test/t/variables.test | 12 | ||||
-rw-r--r-- | scripts/Makefile.am | 4 | ||||
-rw-r--r-- | scripts/make_sharedlib_distribution.sh | 117 | ||||
-rw-r--r-- | sql/ha_berkeley.cc | 2 | ||||
-rw-r--r-- | sql/mysql_priv.h | 10 | ||||
-rw-r--r-- | sql/mysqld.cc | 29 | ||||
-rw-r--r-- | sql/opt_ft.cc | 8 | ||||
-rw-r--r-- | sql/opt_ft.h | 7 | ||||
-rw-r--r-- | sql/opt_range.cc | 103 | ||||
-rw-r--r-- | sql/opt_range.h | 14 | ||||
-rw-r--r-- | sql/set_var.cc | 25 | ||||
-rw-r--r-- | sql/sql_acl.cc | 4 | ||||
-rw-r--r-- | sql/sql_class.h | 7 | ||||
-rw-r--r-- | sql/sql_delete.cc | 2 | ||||
-rw-r--r-- | sql/sql_select.cc | 19 | ||||
-rw-r--r-- | sql/sql_test.cc | 27 | ||||
-rw-r--r-- | sql/sql_udf.cc | 2 | ||||
-rw-r--r-- | sql/sql_update.cc | 2 | ||||
-rw-r--r-- | sql/table.cc | 2 |
21 files changed, 362 insertions, 68 deletions
diff --git a/configure.in b/configure.in index f098a3d39a8..207404a89c5 100644 --- a/configure.in +++ b/configure.in @@ -1821,7 +1821,7 @@ AC_CHECK_FUNCS(alarm bmove \ cuserid fcntl fconvert poll \ getrusage getpwuid getcwd getrlimit getwd index stpcpy locking longjmp \ perror pread realpath readlink rename \ - socket strnlen madvise mkstemp \ + socket strnlen madvise mallinfo mkstemp \ strtol strtoul strtoll strtoull snprintf tempnam thr_setconcurrency \ gethostbyaddr_r gethostbyname_r getpwnam \ bfill bzero bcmp strstr strpbrk strerror \ diff --git a/mysql-test/r/variables.result b/mysql-test/r/variables.result index ead09cc6ed7..30eb18dc7ed 100644 --- a/mysql-test/r/variables.result +++ b/mysql-test/r/variables.result @@ -163,6 +163,38 @@ set @@rand_seed1=10000000,@@rand_seed2=1000000; select ROUND(RAND(),5); ROUND(RAND(),5) 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; ERROR 42000: Variable 'big_tables' can't be set to the value of 'OFFF' set big_tables="OFFF"; diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test index 22f8406cba5..7b5456e1895 100644 --- a/mysql-test/t/variables.test +++ b/mysql-test/t/variables.test @@ -98,6 +98,18 @@ select @@timestamp>0; set @@rand_seed1=10000000,@@rand_seed2=1000000; 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 diff --git a/scripts/Makefile.am b/scripts/Makefile.am index 4782c763447..48592d2ff00 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -37,6 +37,7 @@ bin_SCRIPTS = @server_scripts@ \ mysql_create_system_tables EXTRA_SCRIPTS = make_binary_distribution.sh \ + make_sharedlib_distribution.sh \ make_win_src_distribution.sh \ msql2mysql.sh \ mysql_config.sh \ @@ -69,6 +70,7 @@ dist_pkgdata_DATA = fill_help_tables.sql mysql_fix_privilege_tables.sql # failures with it. CLEANFILES = @server_scripts@ \ make_binary_distribution \ + make_sharedlib_distribution \ msql2mysql \ mysql_config \ mysql_fix_privilege_tables \ @@ -141,7 +143,7 @@ SUFFIXES = .sh # Don't update the files from bitkeeper %::SCCS/s.% -all: fill_help_tables.sql make_win_src_distribution make_binary_distribution +all: fill_help_tables.sql make_win_src_distribution make_binary_distribution make_sharedlib_distribution fill_help_tables.sql: fill_help_tables ../Docs/manual.texi ./fill_help_tables < ../Docs/manual.texi > fill_help_tables.sql diff --git a/scripts/make_sharedlib_distribution.sh b/scripts/make_sharedlib_distribution.sh new file mode 100644 index 00000000000..4104a315296 --- /dev/null +++ b/scripts/make_sharedlib_distribution.sh @@ -0,0 +1,117 @@ +#!/bin/sh +# The default path should be /usr/local + +# Get some info from configure +# chmod +x ./scripts/setsomevars + +machine=@MACHINE_TYPE@ +system=@SYSTEM_TYPE@ +version=@VERSION@ +export machine system version +SOURCE=`pwd` +CP="cp -p" +MV="mv" + +STRIP=1 +DEBUG=0 +SILENT=0 +TMP=/tmp +SUFFIX="" + +parse_arguments() { + for arg do + case "$arg" in + --debug) DEBUG=1;; + --tmp=*) TMP=`echo "$arg" | sed -e "s;--tmp=;;"` ;; + --suffix=*) SUFFIX=`echo "$arg" | sed -e "s;--suffix=;;"` ;; + --no-strip) STRIP=0 ;; + --silent) SILENT=1 ;; + *) + echo "Unknown argument '$arg'" + exit 1 + ;; + esac + done +} + +parse_arguments "$@" + +BASE=$TMP/my_dist$SUFFIX + +if [ -d $BASE ] ; then + rm -r -f $BASE +fi + +mkdir -p $BASE/lib + +for i in \ + libmysql/.libs/libmysqlclient.so* \ + libmysql_r/.libs/libmysqlclient_r.so* +do + if [ -f $i ] + then + $CP $i $BASE/lib + fi +done + +# Change the distribution to a long descriptive name +NEW_NAME=mysql-shared-$version-$system-$machine$SUFFIX +BASE2=$TMP/$NEW_NAME +rm -r -f $BASE2 +mv $BASE $BASE2 +BASE=$BASE2 + +#if we are debugging, do not do tar/gz +if [ x$DEBUG = x1 ] ; then + exit +fi + +# This is needed to prefer GNU tar instead of tar because tar can't +# always handle long filenames + +PATH_DIRS=`echo $PATH | sed -e 's/^:/. /' -e 's/:$/ ./' -e 's/::/ . /g' -e 's/:/ /g' ` +which_1 () +{ + for cmd + do + for d in $PATH_DIRS + do + for file in $d/$cmd + do + if test -x $file -a ! -d $file + then + echo $file + exit 0 + fi + done + done + done + exit 1 +} + +# +# Create the result tar file +# + +tar=`which_1 gnutar gtar` +if test "$?" = "1" -o "$tar" = "" +then + tar=tar +fi + +echo "Using $tar to create archive" +cd $TMP + +OPT=cvf +if [ x$SILENT = x1 ] ; then + OPT=cf +fi + +$tar $OPT $SOURCE/$NEW_NAME.tar $NEW_NAME +cd $SOURCE +echo "Compressing archive" +gzip -9 $NEW_NAME.tar +echo "Removing temporary directory" +rm -r -f $BASE + +echo "$NEW_NAME.tar.gz created" diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 1b99efeaa43..0795c9d6a96 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -238,7 +238,7 @@ int berkeley_show_logs(Protocol *protocol) MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC); 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); if ((error= db_env->log_archive(db_env, &all_logs, diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index afbda2b4ad1..d1fe1abb2bd 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -85,6 +85,16 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; #define MYSQLD_NET_RETRY_COUNT 10 // Abort read after this many int. #endif #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 optimise seeks when reading a big table in sorted order diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 1c26d4a8b7c..0664175d2a2 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3567,6 +3567,10 @@ enum options OPT_BDB_LOG_BUFFER_SIZE, OPT_BDB_MAX_LOCK, OPT_ERROR_LOG_FILE, + 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, OPT_ENABLE_SHARED_MEMORY, OPT_SHARED_MEMORY_BASE_NAME, OPT_OLD_PASSWORDS, @@ -4392,6 +4396,11 @@ The minimum value for this variable is 4096.", (gptr*) &global_system_variables.preload_buff_size, (gptr*) &max_system_variables.preload_buff_size, 0, GET_ULONG, REQUIRED_ARG, 32*1024L, 1024, 1024*1024*1024L, 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 {"query_cache_limit", OPT_QUERY_CACHE_LIMIT, "Don't cache results that are bigger than this.", @@ -4413,6 +4422,11 @@ The minimum value for this variable is 4096.", (gptr*) &global_system_variables.query_cache_type, (gptr*) &max_system_variables.query_cache_type, 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*/ {"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.", @@ -4451,6 +4465,11 @@ The minimum value for this variable is 4096.", (gptr*) &slave_net_timeout, (gptr*) &slave_net_timeout, 0, GET_ULONG, REQUIRED_ARG, SLAVE_NET_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, #endif /* HAVE_REPLICATION */ + {"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, "Make all tables readonly, with the expections for replications (slave) threads and users with the SUPER privilege.", (gptr*) &opt_readonly, @@ -4487,6 +4506,16 @@ The minimum value for this variable is 4096.", "The stack size for each thread.", (gptr*) &thread_stack, (gptr*) &thread_stack, 0, GET_ULONG, REQUIRED_ARG,DEFAULT_THREAD_STACK, 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, "The number of seconds the server waits for activity on a connection before closing it.", (gptr*) &global_system_variables.net_wait_timeout, diff --git a/sql/opt_ft.cc b/sql/opt_ft.cc index b35b3230a39..74349819937 100644 --- a/sql/opt_ft.cc +++ b/sql/opt_ft.cc @@ -26,11 +26,11 @@ ** 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) - return new FT_SELECT(table, &tab->ref); - else - return get_quick_select_for_ref(table, &tab->ref); + return new FT_SELECT(thd, table, &tab->ref); + return get_quick_select_for_ref(thd, table, &tab->ref); } diff --git a/sql/opt_ft.h b/sql/opt_ft.h index b055edc107c..69b6b72f3fc 100644 --- a/sql/opt_ft.h +++ b/sql/opt_ft.h @@ -28,13 +28,14 @@ class FT_SELECT: public QUICK_SELECT { public: TABLE_REF *ref; - FT_SELECT(TABLE *table, TABLE_REF *tref) : - QUICK_SELECT (table,tref->key,1), ref(tref) { init(); } + FT_SELECT(THD *thd, TABLE *table, TABLE_REF *tref) : + QUICK_SELECT (thd, table, tref->key, 1), ref(tref) { init(); } int init() { return error=file->ft_init(); } 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 diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 24768537e3d..b356bda6112 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -279,6 +279,7 @@ public: typedef struct st_qsel_param { + THD *thd; TABLE *table; KEY_PART *key_parts,*key_parts_end,*key[MAX_KEY]; MEM_ROOT *mem_root; @@ -378,13 +379,14 @@ SQL_SELECT::~SQL_SELECT() #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), used_key_parts(0), head(table), it(ranges),range(0) { 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); } else @@ -456,17 +458,17 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg) SEL_ARG *tmp; if (type != KEY_RANGE) { - if (!(tmp=new SEL_ARG(type))) - return 0; // out of memory + if (!(tmp= new SEL_ARG(type))) + return 0; // out of memory tmp->prev= *next_arg; // Link into next/prev chain (*next_arg)->next=tmp; (*next_arg)= tmp; } else { - if (!(tmp=new SEL_ARG(field,part, min_value,max_value, - min_flag, max_flag, maybe_flag))) - return 0; // out of memory + if (!(tmp= new SEL_ARG(field,part, min_value,max_value, + min_flag, max_flag, maybe_flag))) + return 0; // OOM tmp->parent=new_parent; tmp->next_key_part=next_key_part; if (left != &null_element) @@ -477,7 +479,8 @@ SEL_ARG *SEL_ARG::clone(SEL_ARG *new_parent,SEL_ARG **next_arg) (*next_arg)= tmp; 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); return tmp; @@ -556,10 +559,11 @@ SEL_ARG *SEL_ARG::clone_tree() { SEL_ARG tmp_link,*next_arg,*root; 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 tmp_link.next->prev=0; // Fix first link - root->use_count=0; + if (root) // If not OOM + root->use_count= 0; return root; } @@ -577,7 +581,8 @@ SEL_ARG *SEL_ARG::clone_tree() ** 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) { uint basflag; @@ -618,9 +623,9 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables, SEL_TREE *tree; KEY_PART *key_parts; PARAM param; - THD *thd= current_thd; - + /* set up parameter that is passed to all functions */ + param.thd= thd; param.baseflag=basflag; param.prev_tables=prev_tables | const_tables; param.read_tables=read_tables; @@ -630,7 +635,7 @@ int SQL_SELECT::test_quick_select(key_map keys_to_use, table_map prev_tables, param.mem_root= &alloc; thd->no_errors=1; // Don't warn about NULL - init_sql_alloc(&alloc,2048,0); + init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0); if (!(param.key_parts = (KEY_PART*) alloc_root(&alloc, sizeof(KEY_PART)* head->key_parts))) @@ -765,7 +770,7 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) while ((item=li++)) { SEL_TREE *new_tree=get_mm_tree(param,item); - if (current_thd->is_fatal_error) + if (param->thd->is_fatal_error) DBUG_RETURN(0); // out of memory tree=tree_and(param,tree,new_tree); if (tree && tree->type == SEL_TREE::IMPOSSIBLE) @@ -906,7 +911,7 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, { SEL_ARG *sel_arg=0; if (!tree && !(tree=new SEL_TREE())) - DBUG_RETURN(0); // out of memory + DBUG_RETURN(0); // OOM if (!value || !(value->used_tables() & ~param->read_tables)) { sel_arg=get_mm_leaf(param,key_part->field,key_part,type,value); @@ -918,10 +923,11 @@ get_mm_parts(PARAM *param, Field *field, Item_func::Functype type, DBUG_RETURN(tree); } } - else { + else + { // This key may be used later - if (!(sel_arg=new SEL_ARG(SEL_ARG::MAYBE_KEY))) - DBUG_RETURN(0); // out of memory + if (!(sel_arg= new SEL_ARG(SEL_ARG::MAYBE_KEY))) + DBUG_RETURN(0); // OOM } sel_arg->part=(uchar) key_part->part; tree->keys[key_part->key]=sel_add(tree->keys[key_part->key],sel_arg); @@ -1126,8 +1132,8 @@ get_mm_leaf(PARAM *param, Field *field, KEY_PART *key_part, ******************************************************************************/ /* -** Add a new key test to a key when scanning through all keys -** This will never be called for same key parts. + Add a new key test to a key when scanning through all keys + This will never be called for same key parts. */ static SEL_ARG * @@ -1311,7 +1317,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag) // key1->part < key2->part key1->use_count--; 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); } @@ -1330,7 +1337,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag) if (key1->use_count > 1) { key1->use_count--; - key1=key1->clone_tree(); + if (!(key1=key1->clone_tree())) + return 0; // OOM key1->use_count++; } if (key1->type == SEL_ARG::MAYBE_KEY) @@ -1374,6 +1382,8 @@ key_and(SEL_ARG *key1,SEL_ARG *key2,uint clone_flag) if (!next || next->type != SEL_ARG::IMPOSSIBLE) { SEL_ARG *new_arg= e1->clone_and(e2); + if (!new_arg) + return &null_element; // End of memory new_arg->next_key_part=next; if (!new_tree) { @@ -1461,8 +1471,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) { swap(SEL_ARG *,key1,key2); } - else - key1=key1->clone_tree(); + else if (!(key1=key1->clone_tree())) + return 0; // OOM } // Add tree at key2 to tree at key1 @@ -1530,7 +1540,10 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) SEL_ARG *next=key2->next; // Keys are not overlapping 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); } else @@ -1576,6 +1589,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) if (cmp >= 0 && tmp->cmp_min_to_min(key2) < 0) { // tmp.min <= x < key2.min SEL_ARG *new_arg=tmp->clone_first(key2); + if (!new_arg) + return 0; // OOM if ((new_arg->next_key_part= key1->next_key_part)) new_arg->increment_use_count(key1->use_count+1); tmp->copy_min_to_min(key2); @@ -1589,6 +1604,8 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) if (tmp->cmp_min_to_min(&key) > 0) { // key.min <= x < tmp.min SEL_ARG *new_arg=key.clone_first(tmp); + if (!new_arg) + return 0; // OOM if ((new_arg->next_key_part=key.next_key_part)) new_arg->increment_use_count(key1->use_count+1); key1=key1->insert(new_arg); @@ -1603,19 +1620,27 @@ key_or(SEL_ARG *key1,SEL_ARG *key2) key.copy_max_to_min(tmp); 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; goto end; } 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; } } else { 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->increment_use_count(key1->use_count+1); new_arg->next_key_part=key_or(tmp->next_key_part,key.next_key_part); @@ -1632,8 +1657,11 @@ end: SEL_ARG *next=key2->next; 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); - key1=key1->insert(new SEL_ARG(*key2)); // Must make copy + key1=key1->insert(tmp); } else key1=key1->insert(key2); // Will destroy key2_root @@ -2222,7 +2250,8 @@ get_quick_select(PARAM *param,uint idx,SEL_ARG *key_tree) { QUICK_SELECT *quick; 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 || get_quick_keys(param,quick,param->key[idx],key_tree,param->min_key,0, @@ -2334,10 +2363,10 @@ get_quick_keys(PARAM *param,QUICK_SELECT *quick,KEY_PART *key, /* Get range for retrieving rows in QUICK_SELECT::get_next */ if (!(range= new QUICK_RANGE(param->min_key, - (uint) (tmp_min_key - param->min_key), - param->max_key, - (uint) (tmp_max_key - param->max_key), - flag))) + (uint) (tmp_min_key - param->min_key), + param->max_key, + (uint) (tmp_max_key - param->max_key), + flag))) return 1; // out of memory set_if_bigger(quick->max_used_key_length,range->min_length); @@ -2394,10 +2423,10 @@ static bool null_part_in_key(KEY_PART *key_part, const char *key, uint length) ** 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 - 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_PART *key_part; uint part; @@ -2406,7 +2435,7 @@ QUICK_SELECT *get_quick_select_for_ref(TABLE *table, TABLE_REF *ref) return 0; /* no ranges found */ if (cp_buffer_from_ref(ref)) { - if (current_thd->is_fatal_error) + if (thd->is_fatal_error) return 0; // out of memory return quick; // empty range } diff --git a/sql/opt_range.h b/sql/opt_range.h index 00736bfc22f..4c1aba7b829 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -83,7 +83,7 @@ public: ha_rows records; 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(); void reset(void) { next=0; it.rewind(); } int init() { return error=file->index_init(index); } @@ -127,13 +127,15 @@ class SQL_SELECT :public Sql_alloc { SQL_SELECT(); ~SQL_SELECT(); - bool check_quick(bool force_quick_range=0, ha_rows limit = HA_POS_ERROR) - { return test_quick_select(~0L,0,limit, force_quick_range) < 0; } + bool check_quick(THD *thd, bool 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; } - int test_quick_select(key_map keys,table_map prev_tables,ha_rows limit, - bool force_quick_range=0); + int test_quick_select(THD *thd, key_map keys, table_map prev_tables, + 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 diff --git a/sql/set_var.cc b/sql/set_var.cc index eb456b0745f..8f1193263ee 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -235,6 +235,18 @@ sys_var_long_ptr sys_rpl_recovery_rank("rpl_recovery_rank", sys_var_long_ptr sys_query_cache_size("query_cache_size", &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 sys_var_long_ptr sys_query_cache_limit("query_cache_limit", &query_cache.query_cache_limit); @@ -441,7 +453,9 @@ sys_var *sys_variables[]= &sys_old_passwords, &sys_preload_buff_size, &sys_pseudo_thread_id, + &sys_query_alloc_block_size, &sys_query_cache_size, + &sys_query_prealloc_size, #ifdef HAVE_QUERY_CACHE &sys_query_cache_limit, &sys_query_cache_min_res_unit, @@ -452,6 +466,7 @@ sys_var *sys_variables[]= &sys_rand_seed2, &sys_read_buff_size, &sys_read_rnd_buff_size, + &sys_range_alloc_block_size, #ifdef HAVE_REPLICATION &sys_relay_log_purge, #endif @@ -478,6 +493,8 @@ sys_var *sys_variables[]= &sys_thread_cache_size, &sys_timestamp, &sys_tmp_table_size, + &sys_trans_alloc_block_size, + &sys_trans_prealloc_size, &sys_tx_isolation, #ifdef HAVE_INNOBASE_DB &sys_innodb_max_dirty_pages_pct, @@ -629,6 +646,8 @@ struct show_var_st init_vars[]= { {"protocol_version", (char*) &protocol_version, SHOW_INT}, {sys_preload_buff_size.name, (char*) &sys_preload_buff_size, SHOW_SYS}, {sys_pseudo_thread_id.name, (char*) &sys_pseudo_thread_id, SHOW_SYS}, + {sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size, + SHOW_SYS}, #ifdef HAVE_QUERY_CACHE {sys_query_cache_limit.name,(char*) &sys_query_cache_limit, SHOW_SYS}, {sys_query_cache_min_res_unit.name, (char*) &sys_query_cache_min_res_unit, @@ -637,9 +656,12 @@ struct show_var_st init_vars[]= { {sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS}, {"secure_auth", (char*) &sys_secure_auth, SHOW_SYS}, #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_readonly.name, (char*) &sys_readonly, 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}, #ifdef HAVE_REPLICATION {sys_relay_log_purge.name, (char*) &sys_relay_log_purge, SHOW_SYS}, #endif @@ -675,6 +697,9 @@ struct show_var_st init_vars[]= { #endif {sys_tmp_table_size.name, (char*) &sys_tmp_table_size, SHOW_SYS}, {"tmpdir", (char*) &opt_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}, {sys_net_wait_timeout.name, (char*) &sys_net_wait_timeout, SHOW_SYS}, {NullS, NullS, SHOW_LONG} diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 179da6096de..a27dd3999fe 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -186,7 +186,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables) thd->net.last_error); 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); VOID(my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50)); while (!(read_record_info.read_record(&read_record_info))) @@ -2450,7 +2450,7 @@ my_bool grant_init(THD *org_thd) (void) hash_init(&column_priv_hash,&my_charset_latin1, 0,0,0, (hash_get_key) get_grant_table, (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 */ if (!initialized) diff --git a/sql/sql_class.h b/sql/sql_class.h index 5c84f39c91b..9d70f136ffa 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -392,10 +392,15 @@ struct system_variables ulong table_type; ulong tmp_table_size; ulong tx_isolation; - /* Determines if which non-standard SQL behaviour should be enabled */ + /* Determines which non-standard SQL behaviour should be enabled */ ulong sql_mode; ulong default_week_format; 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; ulong group_concat_max_len; /* In slave thread we need to know in behalf of which diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index 48ef5b4b74c..070d4cbbce9 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -89,7 +89,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, select=make_select(table,0,0,conds,&error); if (error) DBUG_RETURN(-1); - if ((select && select->check_quick(safe_update, limit)) || !limit) + if ((select && select->check_quick(thd, safe_update, limit)) || !limit) { delete select; free_underlaid_joins(thd, &thd->lex.select_lex); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 96b80f89bda..89aae95c951 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1574,7 +1574,8 @@ err: 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) { int error; @@ -1583,7 +1584,7 @@ static ha_rows get_quick_record_count(SQL_SELECT *select,TABLE *table, { select->head=table; 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) DBUG_RETURN(select->quick->records); if (error == -1) @@ -1866,8 +1867,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, found_const_table_map, s->on_expr ? s->on_expr : conds, &error); - records= get_quick_record_count(select,s->table, s->const_keys, - join->row_limit); + records= get_quick_record_count(join->thd, select, s->table, + s->const_keys, join->row_limit); s->quick=select->quick; s->needed_reg=select->needed_reg; select->quick=0; @@ -3377,7 +3378,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) /* Join with outer join condition */ COND *orig_cond=sel->cond; 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, (join->select_options & OPTION_FOUND_ROWS ? @@ -3390,7 +3391,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) */ sel->cond=orig_cond; if (!tab->on_expr || - sel->test_quick_select(tab->keys, + sel->test_quick_select(join->thd, tab->keys, used_tables & ~ current_map, (join->select_options & OPTION_FOUND_ROWS ? @@ -5828,7 +5829,8 @@ test_if_quick_select(JOIN_TAB *tab) { delete tab->select->quick; 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); } @@ -6921,7 +6923,8 @@ create_sort_index(THD *thd, JOIN *join, ORDER *order, For impossible ranges (like when doing a lookup on NULL on a NOT NULL 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; } } diff --git a/sql/sql_test.cc b/sql/sql_test.cc index f991a09398b..5a2b8ec86e5 100644 --- a/sql/sql_test.cc +++ b/sql/sql_test.cc @@ -22,6 +22,7 @@ #include "sql_select.h" #include <hash.h> #include <thr_alarm.h> +#include <malloc.h> /* Intern key cache variables */ extern "C" pthread_mutex_t THR_LOCK_keycache; @@ -365,6 +366,32 @@ Next alarm time: %lu\n", thd->proc_info="malloc"; my_checkmalloc(); 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) thd->proc_info=0; } diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc index c237b023e7b..337f2540a39 100644 --- a/sql/sql_udf.cc +++ b/sql/sql_udf.cc @@ -128,7 +128,7 @@ void udf_init() my_rwlock_init(&THR_LOCK_udf,NULL); - init_sql_alloc(&mem, 1024,0); + init_sql_alloc(&mem, UDF_ALLOC_BLOCK_SIZE, 0); THD *new_thd = new THD; if (!new_thd || hash_init(&udf_hash,system_charset_info,32,0,0,get_hash_key, NULL, 0)) diff --git a/sql/sql_update.cc b/sql/sql_update.cc index f2185d265e1..e14e20b62d6 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -152,7 +152,7 @@ int mysql_update(THD *thd, table->used_keys=0; select=make_select(table,0,0,conds,&error); if (error || - (select && select->check_quick(safe_update, limit)) || !limit) + (select && select->check_quick(thd, safe_update, limit)) || !limit) { delete select; free_underlaid_joins(thd, &thd->lex.select_lex); diff --git a/sql/table.cc b/sql/table.cc index c31b68fc2dc..be5b7edfd93 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -90,7 +90,7 @@ int openfrm(const char *name, const char *alias, uint db_stat, uint prgflag, outparam->db_stat = db_stat; 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); my_pthread_setspecific_ptr(THR_MALLOC,&outparam->mem_root); |