summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormonty@mashka.mysql.fi <>2003-01-08 11:24:39 +0200
committermonty@mashka.mysql.fi <>2003-01-08 11:24:39 +0200
commit89ef355b9e8844d6da47da788adcf2249ee8fa77 (patch)
tree3baa30a8807f3489fb00ce29549c8b3360ed650c
parent602f3664e3b874bf2fa7e94dfde7f45be94fe5d3 (diff)
downloadmariadb-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.texi73
-rw-r--r--configure.in2
-rw-r--r--sql/log_event.cc56
-rw-r--r--sql/log_event.h5
-rw-r--r--sql/slave.cc6
-rw-r--r--sql/sql_show.cc2
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;