diff options
author | monty@mashka.mysql.fi <> | 2003-01-08 11:24:39 +0200 |
---|---|---|
committer | monty@mashka.mysql.fi <> | 2003-01-08 11:24:39 +0200 |
commit | 89ef355b9e8844d6da47da788adcf2249ee8fa77 (patch) | |
tree | 3baa30a8807f3489fb00ce29549c8b3360ed650c | |
parent | 602f3664e3b874bf2fa7e94dfde7f45be94fe5d3 (diff) | |
download | mariadb-git-89ef355b9e8844d6da47da788adcf2249ee8fa77.tar.gz |
Fix for bug in LOAD DATA INFILE and replication
Fix for SHOW VARIABLES in embedded server
-rw-r--r-- | Docs/internals.texi | 73 | ||||
-rw-r--r-- | configure.in | 2 | ||||
-rw-r--r-- | sql/log_event.cc | 56 | ||||
-rw-r--r-- | sql/log_event.h | 5 | ||||
-rw-r--r-- | sql/slave.cc | 6 | ||||
-rw-r--r-- | sql/sql_show.cc | 2 |
6 files changed, 129 insertions, 15 deletions
diff --git a/Docs/internals.texi b/Docs/internals.texi index 6719bd4a6fa..a94158f84f8 100644 --- a/Docs/internals.texi +++ b/Docs/internals.texi @@ -96,13 +96,84 @@ cached for each user/database combination. Many use of @code{GROUP BY} or @code{DISTINCT} caches all found rows in a @code{HEAP} table. (This is a very quick in-memory table with hash index.) -@item Join Row Cache +@item Join buffer Cache For every full join in a @code{SELECT} statement (a full join here means there were no keys that one could use to find the next table in a list), the found rows are cached in a join cache. One @code{SELECT} query can use many join caches in the worst case. @end table +@node join_buffer_size, flush tables, caching, Top +@subchapter How MySQL uses the join_buffer cache + +Basic information about @code{join_buffer_size}: + +@itemize @bullet +@item +It's only used in the case when join type is of type @code{ALL} or +@code{index}; In other words: no possible keys can be used. +@item +A join buffer is never allocated for the first not-const table, +even it it would be of type @code{ALL}/@code{index}. +@item +The buffer is allocated when we need to do a each full join between two +tables and freed after the query is done. +@item +Accepted row combinations of tables before the @code{ALL}/@code{index} +able is stored in the cache and is used to compare against each read +row in the @code{ALL} table. +@item +We only store the used fields in the join_buffer cache, not the +whole rows. +@end itemize + +Assume you have the following join: + +@example +Table name Type +t1 range +t2 ref +t3 @code{ALL} +@end example + +The join is then done as follows: + +@example +- While rows in t1 matching range + - Read through all rows in t2 according to reference key + - Store used fields form t1,t2 in cache + - If cache is full + - Read through all rows in t3 + - Compare t3 row against all t1,t2 combination in cache + - If rows satisfying join condition, send it to client + - Empty cache + +- Read through all rows in t3 + - Compare t3 row against all stored t1,t2 combinations in cache + - If rows satisfying join condition, send it to client +@end example + +The above means that table t3 is scanned + +@example +(size-of-stored-row(t1,t2) * accepted-row-cominations(t1,t2))/ +join_buffer_size+1 +@end example +times. + +Some conclusions: + +@itemize @bullet +@item +The larger the join_buff_size, the fewer scans of t3. +If @code{join_buff_size} is already large enough to hold all previous row +combinations then there is no speed to gain by making it bigger. +@item +If there is several tables of @code{ALL}/@code{index} then the we +allocate one @code{join_buffer_size buffer} for each of them and use the +same algorithm described above to handle it. (In other words, we store +the same row combination several times into different buffers) +@end itemize @node flush tables, filesort, caching, Top @chapter How MySQL Handles @code{FLUSH TABLES} diff --git a/configure.in b/configure.in index 0375cc61235..06dc6e03fb6 100644 --- a/configure.in +++ b/configure.in @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! -AM_INIT_AUTOMAKE(mysql, 4.0.8-gamma) +AM_INIT_AUTOMAKE(mysql, 4.0.9-gamma) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 diff --git a/sql/log_event.cc b/sql/log_event.cc index d451a5bc46c..3c2c2fd27b1 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -206,7 +206,19 @@ Log_event::Log_event(const char* buf, bool old_format) int Log_event::exec_event(struct st_relay_log_info* rli) { - if (rli) // QQ When is this not true ? + /* + rli is null when (as far as I (Guilhem) know) + the caller is + Load_log_event::exec_event *and* that one is called from + Execute_load_log_event::exec_event. + In this case, we don't do anything here ; + Execute_load_log_event::exec_event will call Log_event::exec_event + again later with the proper rli. + Strictly speaking, if we were sure that rli is null + only in the case discussed above, 'if (rli)' is useless here. + But as we are not 100% sure, keep it for now. + */ + if (rli) { if (rli->inside_transaction) rli->inc_pending(get_event_len()); @@ -1773,8 +1785,34 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) return Log_event::exec_event(rli); } +/* + Does the data loading job when executing a LOAD DATA on the slave + + SYNOPSIS + Load_log_event::exec_event + net + rli + use_rli_only_for_errors - if set to 1, rli is provided to + Load_log_event::exec_event only for this + function to have RPL_LOG_NAME and + rli->last_slave_error, both being used by + error reports. rli's position advancing + is skipped (done by the caller which is + Execute_load_log_event::exec_event). + - if set to 0, rli is provided for full use, + i.e. for error reports and position + advancing. + + DESCRIPTION + Does the data loading job when executing a LOAD DATA on the slave + + RETURN VALUE + 0 Success + 1 Failure +*/ -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) { init_sql_alloc(&thd->mem_root, 8192,0); thd->db = rewrite_db((char*)db); @@ -1836,8 +1874,12 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli) TL_WRITE)) thd->query_error = 1; if (thd->cuted_fields) + /* + log_pos is the position of the LOAD + event in the master log + */ sql_print_error("Slave: load data infile at position %s in log \ -'%s' produced %d warning(s)", llstr(rli->master_log_pos,llbuff), RPL_LOG_NAME, +'%s' produced %d warning(s)", llstr(log_pos,llbuff), RPL_LOG_NAME, thd->cuted_fields ); if (net) net->pkt_nr= thd->net.pkt_nr; @@ -1877,7 +1919,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli) return 1; } - return Log_event::exec_event(rli); + return ( use_rli_only_for_errors ? 0 : Log_event::exec_event(rli) ); } @@ -2132,7 +2174,11 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli) save_options = thd->options; thd->options &= ~ (ulong) (OPTION_BIN_LOG); lev->thd = thd; - if (lev->exec_event(0,0)) + /* + lev->exec_event should use rli only for errors + i.e. should not advance rli's position + */ + if (lev->exec_event(0,rli,1)) { slave_print_error(rli,my_errno, "Failed executing load from '%s'", fname); thd->options = save_options; diff --git a/sql/log_event.h b/sql/log_event.h index 69a70d535ec..5b9f30b3afd 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -417,9 +417,10 @@ public: const char* get_db() { return db; } int exec_event(struct st_relay_log_info* rli) { - return exec_event(thd->slave_net,rli); + return exec_event(thd->slave_net,rli,0); } - int exec_event(NET* net, struct st_relay_log_info* rli); + int exec_event(NET* net, struct st_relay_log_info* rli, + bool use_rli_only_for_errors); #else void print(FILE* file, bool short_form = 0, char* last_db = 0); #endif diff --git a/sql/slave.cc b/sql/slave.cc index 455b574b355..b8689a28a54 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2343,12 +2343,6 @@ static int process_io_rotate(MASTER_INFO *mi, Rotate_log_event *rev) memcpy(mi->master_log_name, rev->new_log_ident, rev->ident_len+1); mi->master_log_pos= rev->pos; - - pthread_mutex_lock(&mi->rli.data_lock); - memcpy(mi->rli.master_log_name, rev->new_log_ident, rev->ident_len+1); - mi->rli.master_log_pos= rev->pos; - pthread_mutex_unlock(&mi->rli.data_lock); - DBUG_PRINT("info", ("master_log_pos: '%s' %d", mi->master_log_name, (ulong) mi->master_log_pos)); #ifndef DBUG_OFF diff --git a/sql/sql_show.cc b/sql/sql_show.cc index a11abf75506..04d3f13a8d0 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1217,6 +1217,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, case SHOW_RPL_STATUS: net_store_data(&packet2, rpl_status_type[(int)rpl_status]); break; +#ifndef EMBEDDED_LIBRARY case SHOW_SLAVE_RUNNING: { LOCK_ACTIVE_MI; @@ -1226,6 +1227,7 @@ int mysqld_show(THD *thd, const char *wild, show_var_st *variables, UNLOCK_ACTIVE_MI; break; } +#endif case SHOW_OPENTABLES: net_store_data(&packet2,(uint32) cached_tables()); break; |