Commit a701afe2 authored by unknown's avatar unknown

Merge rkalimullin@bk-internal.mysql.com:/home/bk/mysql-4.0

into gw.mysql.r18.ru:/usr/home/ram/work/4.0

parents 3487cba7 30025f3f
...@@ -1632,12 +1632,12 @@ if test "$with_debug" = "yes" ...@@ -1632,12 +1632,12 @@ if test "$with_debug" = "yes"
then then
# Medium debug. # Medium debug.
CFLAGS="$DEBUG_CFLAGS $DEBUG_OPTIMIZE_CC -DDBUG_ON -DSAFE_MUTEX $CFLAGS" CFLAGS="$DEBUG_CFLAGS $DEBUG_OPTIMIZE_CC -DDBUG_ON -DSAFE_MUTEX $CFLAGS"
CXXFLAGS="$DEBUG_CXXFLAGS $DEBUG_OPTIMIZE_CXX -DSAFE_MUTEX $CXXFLAGS" CXXFLAGS="$DEBUG_CXXFLAGS $DEBUG_OPTIMIZE_CXX -DDBUG_ON -DSAFE_MUTEX $CXXFLAGS"
elif test "$with_debug" = "full" elif test "$with_debug" = "full"
then then
# Full debug. Very slow in some cases # Full debug. Very slow in some cases
CFLAGS="$DEBUG_CFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CFLAGS" CFLAGS="$DEBUG_CFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CFLAGS"
CXXFLAGS="$DEBUG_CXXFLAGS -DSAFE_MUTEX -DSAFEMALLOC $CXXFLAGS" CXXFLAGS="$DEBUG_CXXFLAGS -DDBUG_ON -DSAFE_MUTEX -DSAFEMALLOC $CXXFLAGS"
else else
# Optimized version. No debug # Optimized version. No debug
CFLAGS="$OPTIMIZE_CFLAGS -DDBUG_OFF $CFLAGS" CFLAGS="$OPTIMIZE_CFLAGS -DDBUG_OFF $CFLAGS"
......
...@@ -27,7 +27,8 @@ extern os_event_t srv_lock_timeout_thread_event; ...@@ -27,7 +27,8 @@ extern os_event_t srv_lock_timeout_thread_event;
/* If the last data file is auto-extended, we add this many pages to it /* If the last data file is auto-extended, we add this many pages to it
at a time */ at a time */
#define SRV_AUTO_EXTEND_INCREMENT (8 * ((1024 * 1024) / UNIV_PAGE_SIZE)) #define SRV_AUTO_EXTEND_INCREMENT \
(srv_auto_extend_increment * ((1024 * 1024) / UNIV_PAGE_SIZE))
/* This is set to TRUE if the MySQL user has set it in MySQL */ /* This is set to TRUE if the MySQL user has set it in MySQL */
extern ibool srv_lower_case_table_names; extern ibool srv_lower_case_table_names;
...@@ -49,6 +50,7 @@ extern ulint* srv_data_file_is_raw_partition; ...@@ -49,6 +50,7 @@ extern ulint* srv_data_file_is_raw_partition;
extern ibool srv_auto_extend_last_data_file; extern ibool srv_auto_extend_last_data_file;
extern ulint srv_last_file_size_max; extern ulint srv_last_file_size_max;
extern ulint srv_auto_extend_increment;
extern ibool srv_created_new_raw; extern ibool srv_created_new_raw;
......
...@@ -86,6 +86,9 @@ ulint srv_last_file_size_max = 0; /* if != 0, this tells ...@@ -86,6 +86,9 @@ ulint srv_last_file_size_max = 0; /* if != 0, this tells
the max size auto-extending the max size auto-extending
may increase the last data may increase the last data
file size */ file size */
ulint srv_auto_extend_increment = 8; /* If the last data file is
auto-extended, we add this
many pages to it at a time */
ulint* srv_data_file_is_raw_partition = NULL; ulint* srv_data_file_is_raw_partition = NULL;
/* If the following is TRUE we do not allow inserts etc. This protects /* If the following is TRUE we do not allow inserts etc. This protects
......
slave stop;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
slave start;
CREATE TABLE t1 (
a int unsigned not null auto_increment primary key,
b int unsigned
) TYPE=MyISAM;
CREATE TABLE t2 (
a int unsigned not null auto_increment primary key,
b int unsigned
) TYPE=MyISAM;
INSERT INTO t1 VALUES (NULL, 0);
INSERT INTO t1 SELECT NULL, 0 FROM t1;
INSERT INTO t2 VALUES (NULL, 0), (NULL,1);
SELECT * FROM t1 ORDER BY a;
a b
1 0
2 0
SELECT * FROM t2 ORDER BY a;
a b
1 0
2 1
UPDATE t1, t2 SET t1.b = (t2.b+4) WHERE t1.a = t2.a;
SELECT * FROM t1 ORDER BY a;
a b
1 4
2 5
SELECT * FROM t2 ORDER BY a;
a b
1 0
2 1
SELECT * FROM t1 ORDER BY a;
a b
1 4
2 5
SELECT * FROM t2 ORDER BY a;
a b
1 0
2 1
--replicate-ignore-table=nothing.sensible
# Let's verify that multi-update is not always skipped by slave if
# some replicate-* rules exist.
# (BUG#7011)
source include/master-slave.inc;
CREATE TABLE t1 (
a int unsigned not null auto_increment primary key,
b int unsigned
) TYPE=MyISAM;
CREATE TABLE t2 (
a int unsigned not null auto_increment primary key,
b int unsigned
) TYPE=MyISAM;
INSERT INTO t1 VALUES (NULL, 0);
INSERT INTO t1 SELECT NULL, 0 FROM t1;
INSERT INTO t2 VALUES (NULL, 0), (NULL,1);
SELECT * FROM t1 ORDER BY a;
SELECT * FROM t2 ORDER BY a;
UPDATE t1, t2 SET t1.b = (t2.b+4) WHERE t1.a = t2.a;
SELECT * FROM t1 ORDER BY a;
SELECT * FROM t2 ORDER BY a;
save_master_pos;
connection slave;
sync_with_master;
SELECT * FROM t1 ORDER BY a;
SELECT * FROM t2 ORDER BY a;
...@@ -4346,12 +4346,12 @@ ha_innobase::update_table_comment( ...@@ -4346,12 +4346,12 @@ ha_innobase::update_table_comment(
(ulong) innobase_get_free_space()); (ulong) innobase_get_free_space());
dict_print_info_on_foreign_keys(FALSE, file, prebuilt->table); dict_print_info_on_foreign_keys(FALSE, file, prebuilt->table);
flen = ftell(file); flen = ftell(file);
if(length + flen + 3 > 64000) { if (flen < 0) {
flen = 0;
} else if (length + flen + 3 > 64000) {
flen = 64000 - 3 - length; flen = 64000 - 3 - length;
} }
ut_ad(flen > 0);
/* allocate buffer for the full string, and /* allocate buffer for the full string, and
read the contents of the temporary file */ read the contents of the temporary file */
...@@ -4414,12 +4414,12 @@ ha_innobase::get_foreign_key_create_info(void) ...@@ -4414,12 +4414,12 @@ ha_innobase::get_foreign_key_create_info(void)
prebuilt->trx->op_info = (char*)""; prebuilt->trx->op_info = (char*)"";
flen = ftell(file); flen = ftell(file);
if(flen > 64000 - 1) { if (flen < 0) {
flen = 0;
} else if(flen > 64000 - 1) {
flen = 64000 - 1; flen = 64000 - 1;
} }
ut_ad(flen >= 0);
/* allocate buffer for the string, and /* allocate buffer for the string, and
read the contents of the temporary file */ read the contents of the temporary file */
...@@ -4800,12 +4800,12 @@ innodb_show_status( ...@@ -4800,12 +4800,12 @@ innodb_show_status(
srv_printf_innodb_monitor(srv_monitor_file); srv_printf_innodb_monitor(srv_monitor_file);
flen = ftell(srv_monitor_file); flen = ftell(srv_monitor_file);
os_file_set_eof(srv_monitor_file); os_file_set_eof(srv_monitor_file);
if(flen > 64000 - 1) { if (flen < 0) {
flen = 0;
} else if (flen > 64000 - 1) {
flen = 64000 - 1; flen = 64000 - 1;
} }
ut_ad(flen > 0);
/* allocate buffer for the string, and /* allocate buffer for the string, and
read the contents of the temporary file */ read the contents of the temporary file */
......
...@@ -208,6 +208,7 @@ extern my_bool innobase_log_archive, ...@@ -208,6 +208,7 @@ extern my_bool innobase_log_archive,
extern "C" { extern "C" {
extern ulong srv_max_buf_pool_modified_pct; extern ulong srv_max_buf_pool_modified_pct;
extern ulong srv_max_purge_lag; extern ulong srv_max_purge_lag;
extern ulong srv_auto_extend_increment;
} }
extern TYPELIB innobase_lock_typelib; extern TYPELIB innobase_lock_typelib;
......
...@@ -469,6 +469,9 @@ int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields, ...@@ -469,6 +469,9 @@ int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds, List<Item> &values,COND *conds,
ORDER *order, ha_rows limit, ORDER *order, ha_rows limit,
enum enum_duplicates handle_duplicates); enum enum_duplicates handle_duplicates);
int mysql_multi_update_lock(THD *thd,
TABLE_LIST *table_list,
List<Item> *fields);
int mysql_multi_update(THD *thd, TABLE_LIST *table_list, int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
List<Item> *fields, List<Item> *values, List<Item> *fields, List<Item> *values,
COND *conds, ulong options, COND *conds, ulong options,
......
...@@ -3518,6 +3518,7 @@ enum options_mysqld { ...@@ -3518,6 +3518,7 @@ enum options_mysqld {
OPT_INNODB_FORCE_RECOVERY, OPT_INNODB_FORCE_RECOVERY,
OPT_INNODB_STATUS_FILE, OPT_INNODB_STATUS_FILE,
OPT_INNODB_MAX_DIRTY_PAGES_PCT, OPT_INNODB_MAX_DIRTY_PAGES_PCT,
OPT_INNODB_AUTOEXTEND_INCREMENT,
OPT_INNODB_TABLE_LOCKS, OPT_INNODB_TABLE_LOCKS,
OPT_BDB_CACHE_SIZE, OPT_BDB_CACHE_SIZE,
OPT_BDB_LOG_BUFFER_SIZE, OPT_BDB_LOG_BUFFER_SIZE,
...@@ -3659,6 +3660,11 @@ struct my_option my_long_options[] = ...@@ -3659,6 +3660,11 @@ struct my_option my_long_options[] =
"Path to individual files and their sizes", "Path to individual files and their sizes",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#ifdef HAVE_INNOBASE_DB #ifdef HAVE_INNOBASE_DB
{"innodb_autoextend_increment", OPT_INNODB_AUTOEXTEND_INCREMENT,
"Data file autoextend increment in megabytes",
(gptr*) &srv_auto_extend_increment,
(gptr*) &srv_auto_extend_increment,
0, GET_LONG, REQUIRED_ARG, 8L, 1L, 1000L, 0, 1L, 0},
{"innodb_data_home_dir", OPT_INNODB_DATA_HOME_DIR, {"innodb_data_home_dir", OPT_INNODB_DATA_HOME_DIR,
"The common part for Innodb table spaces", (gptr*) &innobase_data_home_dir, "The common part for Innodb table spaces", (gptr*) &innobase_data_home_dir,
(gptr*) &innobase_data_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, (gptr*) &innobase_data_home_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0,
......
...@@ -265,6 +265,8 @@ sys_var_long_ptr sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_p ...@@ -265,6 +265,8 @@ sys_var_long_ptr sys_innodb_max_dirty_pages_pct("innodb_max_dirty_pages_p
&srv_max_buf_pool_modified_pct); &srv_max_buf_pool_modified_pct);
sys_var_long_ptr sys_innodb_max_purge_lag("innodb_max_purge_lag", sys_var_long_ptr sys_innodb_max_purge_lag("innodb_max_purge_lag",
&srv_max_purge_lag); &srv_max_purge_lag);
sys_var_long_ptr sys_innodb_autoextend_increment("innodb_autoextend_increment",
&srv_auto_extend_increment);
sys_var_thd_bool sys_innodb_table_locks("innodb_table_locks", sys_var_thd_bool sys_innodb_table_locks("innodb_table_locks",
&SV::innodb_table_locks); &SV::innodb_table_locks);
#endif #endif
...@@ -454,6 +456,7 @@ sys_var *sys_variables[]= ...@@ -454,6 +456,7 @@ sys_var *sys_variables[]=
#ifdef HAVE_INNOBASE_DB #ifdef HAVE_INNOBASE_DB
&sys_innodb_max_dirty_pages_pct, &sys_innodb_max_dirty_pages_pct,
&sys_innodb_max_purge_lag, &sys_innodb_max_purge_lag,
&sys_innodb_autoextend_increment,
&sys_innodb_table_locks, &sys_innodb_table_locks,
#endif #endif
&sys_unique_checks &sys_unique_checks
...@@ -508,6 +511,7 @@ struct show_var_st init_vars[]= { ...@@ -508,6 +511,7 @@ struct show_var_st init_vars[]= {
{"init_file", (char*) &opt_init_file, SHOW_CHAR_PTR}, {"init_file", (char*) &opt_init_file, SHOW_CHAR_PTR},
#ifdef HAVE_INNOBASE_DB #ifdef HAVE_INNOBASE_DB
{"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG }, {"innodb_additional_mem_pool_size", (char*) &innobase_additional_mem_pool_size, SHOW_LONG },
{sys_innodb_autoextend_increment.name, (char*) &sys_innodb_autoextend_increment, SHOW_SYS},
{"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONG }, {"innodb_buffer_pool_size", (char*) &innobase_buffer_pool_size, SHOW_LONG },
{"innodb_data_file_path", (char*) &innobase_data_file_path, SHOW_CHAR_PTR}, {"innodb_data_file_path", (char*) &innobase_data_file_path, SHOW_CHAR_PTR},
{"innodb_data_home_dir", (char*) &innobase_data_home_dir, SHOW_CHAR_PTR}, {"innodb_data_home_dir", (char*) &innobase_data_home_dir, SHOW_CHAR_PTR},
......
...@@ -56,6 +56,8 @@ static int check_for_max_user_connections(USER_CONN *uc); ...@@ -56,6 +56,8 @@ static int check_for_max_user_connections(USER_CONN *uc);
static void decrease_user_connections(USER_CONN *uc); static void decrease_user_connections(USER_CONN *uc);
static bool check_db_used(THD *thd,TABLE_LIST *tables); static bool check_db_used(THD *thd,TABLE_LIST *tables);
static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables); static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables);
static bool check_multi_update_lock(THD *thd, TABLE_LIST *tables,
List<Item> *fields);
static void mysql_init_query(THD *thd); static void mysql_init_query(THD *thd);
static void remove_escape(char *name); static void remove_escape(char *name);
static void refresh_status(void); static void refresh_status(void);
...@@ -1338,10 +1340,28 @@ mysql_execute_command(void) ...@@ -1338,10 +1340,28 @@ mysql_execute_command(void)
LEX *lex= &thd->lex; LEX *lex= &thd->lex;
TABLE_LIST *tables=(TABLE_LIST*) lex->select_lex.table_list.first; TABLE_LIST *tables=(TABLE_LIST*) lex->select_lex.table_list.first;
SELECT_LEX *select_lex = lex->select; SELECT_LEX *select_lex = lex->select;
bool slave_fake_lock= 0;
MYSQL_LOCK *fake_prev_lock= 0;
DBUG_ENTER("mysql_execute_command"); DBUG_ENTER("mysql_execute_command");
if (thd->slave_thread) if (thd->slave_thread)
{ {
if (lex->sql_command == SQLCOM_MULTI_UPDATE)
{
DBUG_PRINT("info",("need faked locked tables"));
if (check_multi_update_lock(thd, tables, &select_lex->item_list))
goto error;
/* Fix for replication, the tables are opened and locked,
now we pretend that we have performed a LOCK TABLES action */
fake_prev_lock= thd->locked_tables;
if (thd->lock)
thd->locked_tables= thd->lock;
thd->lock= 0;
slave_fake_lock= 1;
}
/* /*
Skip if we are in the slave thread, some table rules have been Skip if we are in the slave thread, some table rules have been
given and the table list says the query should not be replicated given and the table list says the query should not be replicated
...@@ -1949,7 +1969,7 @@ mysql_execute_command(void) ...@@ -1949,7 +1969,7 @@ mysql_execute_command(void)
if (select_lex->item_list.elements != lex->value_list.elements) if (select_lex->item_list.elements != lex->value_list.elements)
{ {
send_error(&thd->net,ER_WRONG_VALUE_COUNT); send_error(&thd->net,ER_WRONG_VALUE_COUNT);
DBUG_VOID_RETURN; goto error;
} }
{ {
const char *msg= 0; const char *msg= 0;
...@@ -2641,6 +2661,14 @@ mysql_execute_command(void) ...@@ -2641,6 +2661,14 @@ mysql_execute_command(void)
send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0); send_error(&thd->net,thd->killed ? ER_SERVER_SHUTDOWN : 0);
error: error:
if (unlikely(slave_fake_lock))
{
DBUG_PRINT("info",("undoing faked lock"));
thd->lock= thd->locked_tables;
thd->locked_tables= fake_prev_lock;
if (thd->lock == thd->locked_tables)
thd->lock= 0;
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -3907,3 +3935,54 @@ bool check_simple_select() ...@@ -3907,3 +3935,54 @@ bool check_simple_select()
} }
return 0; return 0;
} }
/*
Setup locking for multi-table updates. Used by the replication slave.
Replication slave SQL thread examines (all_tables_not_ok()) the
locking state of referenced tables to determine if the query has to
be executed or ignored. Since in multi-table update, the
'default' lock is read-only, this lock is corrected early enough by
calling this function, before the slave decides to execute/ignore.
SYNOPSIS
check_multi_update_lock()
thd Current thread
tables List of user-supplied tables
fields List of fields requiring update
RETURN VALUES
0 ok
1 error
*/
static bool check_multi_update_lock(THD *thd, TABLE_LIST *tables,
List<Item> *fields)
{
bool res= 1;
TABLE_LIST *table;
DBUG_ENTER("check_multi_update_lock");
if (check_db_used(thd, tables))
goto error;
/*
Ensure that we have UPDATE or SELECT privilege for each table
The exact privilege is checked in mysql_multi_update()
*/
for (table= tables ; table ; table= table->next)
{
TABLE_LIST *save= table->next;
table->next= 0;
if (check_one_table_access(thd, UPDATE_ACL, table, 1) &&
check_one_table_access(thd, SELECT_ACL, table, 0))
goto error;
table->next= save;
}
if (mysql_multi_update_lock(thd, tables, fields))
goto error;
res= 0;
error:
DBUG_RETURN(res);
}
...@@ -403,26 +403,20 @@ static table_map get_table_map(List<Item> *items) ...@@ -403,26 +403,20 @@ static table_map get_table_map(List<Item> *items)
} }
/* /*
Setup multi-update handling and call SELECT to do the join Prepare tables for multi-update
Analyse which tables need specific privileges and perform locking
as required
*/ */
int mysql_multi_update(THD *thd, int mysql_multi_update_lock(THD *thd,
TABLE_LIST *table_list, TABLE_LIST *table_list,
List<Item> *fields, List<Item> *fields)
List<Item> *values,
COND *conds,
ulong options,
enum enum_duplicates handle_duplicates)
{ {
int res; int res;
multi_update *result;
TABLE_LIST *tl; TABLE_LIST *tl;
const bool using_lock_tables= thd->locked_tables != 0; const bool using_lock_tables= thd->locked_tables != 0;
DBUG_ENTER("mysql_multi_update"); DBUG_ENTER("mysql_multi_update_lock");
thd->select_limit= HA_POS_ERROR;
for (;;) for (;;)
{ {
...@@ -490,7 +484,7 @@ int mysql_multi_update(THD *thd, ...@@ -490,7 +484,7 @@ int mysql_multi_update(THD *thd,
(grant_option && check_grant(thd, wants, tl, 0, 0))) (grant_option && check_grant(thd, wants, tl, 0, 0)))
{ {
tl->next= save; tl->next= save;
DBUG_RETURN(0); DBUG_RETURN(1);
} }
tl->next= save; tl->next= save;
} }
...@@ -498,11 +492,7 @@ int mysql_multi_update(THD *thd, ...@@ -498,11 +492,7 @@ int mysql_multi_update(THD *thd,
/* Relock the tables with the correct modes */ /* Relock the tables with the correct modes */
res= lock_tables(thd,table_list); res= lock_tables(thd,table_list);
if (using_lock_tables) if (using_lock_tables)
{
if (res)
DBUG_RETURN(res);
break; // Don't have to do setup_field() break; // Don't have to do setup_field()
}
/* /*
We must setup fields again as the file may have been reopened We must setup fields again as the file may have been reopened
...@@ -535,6 +525,31 @@ int mysql_multi_update(THD *thd, ...@@ -535,6 +525,31 @@ int mysql_multi_update(THD *thd,
*/ */
close_thread_tables(thd); close_thread_tables(thd);
} }
DBUG_RETURN(res);
}
/*
Setup multi-update handling and call SELECT to do the join
*/
int mysql_multi_update(THD *thd,
TABLE_LIST *table_list,
List<Item> *fields,
List<Item> *values,
COND *conds,
ulong options,
enum enum_duplicates handle_duplicates)
{
int res;
TABLE_LIST *tl;
multi_update *result;
DBUG_ENTER("mysql_multi_update");
thd->select_limit= HA_POS_ERROR;
if ((res= mysql_multi_update_lock(thd, table_list, fields)))
DBUG_RETURN(res);
/* /*
Count tables and setup timestamp handling Count tables and setup timestamp handling
......
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