diff --git a/ChangeLog b/ChangeLog index 63b42f9d6fb..2f90be6f759 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2009-01-29 The InnoDB Team + + * handler/ha_innodb.cc, include/ibuf0ibuf.h, include/ibuf0ibuf.ic, + ibuf/ibuf0ibuf.c: + Implement the settable global variable innodb_change_buffering, + with the allowed values 'none' and 'inserts'. The default value + 'inserts' enables the buffering of inserts to non-unique secondary + index trees when the B-tree leaf page is not in the buffer pool. + 2009-01-27 The InnoDB Team * buf/buf0lru.c: diff --git a/handler/ha_innodb.cc b/handler/ha_innodb.cc index 20d488d741e..ec4b57a77eb 100644 --- a/handler/ha_innodb.cc +++ b/handler/ha_innodb.cc @@ -61,6 +61,7 @@ extern "C" { #include "../storage/innobase/include/dict0boot.h" #include "../storage/innobase/include/ha_prototypes.h" #include "../storage/innobase/include/ut0mem.h" +#include "../storage/innobase/include/ibuf0ibuf.h" } #include "ha_innodb.h" @@ -141,6 +142,7 @@ static char* innobase_data_home_dir = NULL; static char* innobase_data_file_path = NULL; static char* innobase_log_group_home_dir = NULL; static char* innobase_file_format_name = NULL; +static char* innobase_change_buffering = NULL; /* Note: This variable can be set to on/off and any of the supported file formats in the configuration file, but can only be set to any @@ -185,6 +187,12 @@ static hash_table_t* innobase_open_tables; bool nw_panic = FALSE; #endif +/** Allowed values of innodb_change_buffering */ +static const char* innobase_change_buffering_values[IBUF_USE_INSERT + 1] = { + "none", /* IBUF_USE_NONE */ + "inserts" /* IBUF_USE_INSERT */ +}; + static INNOBASE_SHARE *get_share(const char *table_name); static void free_share(INNOBASE_SHARE *share); static int innobase_close_connection(handlerton *hton, THD* thd); @@ -2069,6 +2077,10 @@ innobase_init( } } + ut_a((ulint) ibuf_use < UT_ARR_SIZE(innobase_change_buffering_values)); + innobase_change_buffering = (char*) + innobase_change_buffering_values[ibuf_use]; + /* --------------------------------------------------*/ srv_file_flush_method_str = innobase_unix_file_flush_method; @@ -9350,6 +9362,72 @@ innodb_file_format_check_update( } } +/***************************************************************** +Check if it is a valid value of innodb_change_buffering. This function is +registered as a callback with MySQL. */ +static +int +innodb_change_buffering_validate( +/*=============================*/ + /* out: 0 for valid + innodb_change_buffering */ + THD* thd, /* in: thread handle */ + struct st_mysql_sys_var* var, /* in: pointer to system + variable */ + void* save, /* out: immediate result + for update function */ + struct st_mysql_value* value) /* in: incoming string */ +{ + const char* change_buffering_input; + char buff[STRING_BUFFER_USUAL_SIZE]; + int len = sizeof(buff); + + ut_a(save != NULL); + ut_a(value != NULL); + + change_buffering_input = value->val_str(value, buff, &len); + + if (change_buffering_input != NULL) { + ulint use; + + for (use = 0; use < UT_ARR_SIZE(innobase_change_buffering_values); + use++) { + if (!innobase_strcasecmp( + change_buffering_input, + innobase_change_buffering_values[use])) { + *(ibuf_use_t*) save = (ibuf_use_t) use; + return(0); + } + } + } + + return(1); +} + +/******************************************************************** +Update the system variable innodb_change_buffering using the "saved" +value. This function is registered as a callback with MySQL. */ +static +void +innodb_change_buffering_update( +/*===========================*/ + THD* thd, /* in: thread handle */ + struct st_mysql_sys_var* var, /* in: pointer to + system variable */ + void* var_ptr, /* out: where the + formal string goes */ + const void* save) /* in: immediate result + from check function */ +{ + ut_a(var_ptr != NULL); + ut_a(save != NULL); + ut_a((*(ibuf_use_t*) save) <= IBUF_USE_INSERT); + + ibuf_use = *(const ibuf_use_t*) save; + + *(const char**) var_ptr = innobase_change_buffering_values[ibuf_use]; +} + static int show_innodb_vars(THD *thd, SHOW_VAR *var, char *buff) { innodb_export_status(); @@ -9587,6 +9665,13 @@ static MYSQL_SYSVAR_BOOL(use_sys_malloc, srv_use_sys_malloc, "Use OS memory allocator instead of InnoDB's internal memory allocator", NULL, NULL, FALSE); +static MYSQL_SYSVAR_STR(change_buffering, innobase_change_buffering, + PLUGIN_VAR_RQCMDARG, + "Buffer changes to reduce random access: " + "OFF, ON, inserting, deleting, changing, or purging.", + innodb_change_buffering_validate, + innodb_change_buffering_update, NULL); + static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(additional_mem_pool_size), MYSQL_SYSVAR(autoextend_increment), @@ -9634,6 +9719,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(autoinc_lock_mode), MYSQL_SYSVAR(version), MYSQL_SYSVAR(use_sys_malloc), + MYSQL_SYSVAR(change_buffering), NULL }; diff --git a/ibuf/ibuf0ibuf.c b/ibuf/ibuf0ibuf.c index 22f29af84de..a22fe2ac604 100644 --- a/ibuf/ibuf0ibuf.c +++ b/ibuf/ibuf0ibuf.c @@ -140,7 +140,10 @@ access order rules. */ /* Table name for the insert buffer. */ #define IBUF_TABLE_NAME "SYS_IBUF_TABLE" -/* The insert buffer control structure */ +/** Operations that can currently be buffered. */ +UNIV_INTERN ibuf_use_t ibuf_use = IBUF_USE_INSERT; + +/** The insert buffer control structure */ UNIV_INTERN ibuf_t* ibuf = NULL; UNIV_INTERN ulint ibuf_flush_count = 0; @@ -2107,6 +2110,7 @@ ibuf_contract_ext( mutex_enter(&ibuf_mutex); if (ibuf->empty) { +ibuf_is_empty: mutex_exit(&ibuf_mutex); return(0); @@ -2135,9 +2139,7 @@ ibuf_contract_ext( mtr_commit(&mtr); btr_pcur_close(&pcur); - mutex_exit(&ibuf_mutex); - - return(0); + goto ibuf_is_empty; } mutex_exit(&ibuf_mutex); @@ -2766,6 +2768,13 @@ ibuf_insert( ut_a(!dict_index_is_clust(index)); + switch (ibuf_use) { + case IBUF_USE_NONE: + return(FALSE); + case IBUF_USE_INSERT: + break; + } + entry_size = rec_get_converted_size(index, entry, 0); if (entry_size diff --git a/include/ibuf0ibuf.h b/include/ibuf0ibuf.h index 2ed6ae7da01..bc53910cca8 100644 --- a/include/ibuf0ibuf.h +++ b/include/ibuf0ibuf.h @@ -17,7 +17,17 @@ Created 7/19/1997 Heikki Tuuri #include "ibuf0types.h" #include "fsp0fsp.h" -extern ibuf_t* ibuf; +/** Combinations of operations that can be buffered. */ +typedef enum { + IBUF_USE_NONE = 0, + IBUF_USE_INSERT /* insert */ +} ibuf_use_t; + +/** Operations that can currently be buffered. */ +extern ibuf_use_t ibuf_use; + +/** The insert buffer control structure */ +extern ibuf_t* ibuf; /* The purpose of the insert buffer is to reduce random disk access. When we wish to insert a record into a non-unique secondary index and diff --git a/include/ibuf0ibuf.ic b/include/ibuf0ibuf.ic index b6f1efb185e..93763e0165f 100644 --- a/include/ibuf0ibuf.ic +++ b/include/ibuf0ibuf.ic @@ -79,7 +79,8 @@ ibuf_should_try( a secondary index when we decide */ { - if (!dict_index_is_clust(index) + if (ibuf_use != IBUF_USE_NONE + && !dict_index_is_clust(index) && (ignore_sec_unique || !dict_index_is_unique(index))) { ibuf_flush_count++;