Commit 9cbc19c8 authored by unknown's avatar unknown

slave-skip-errors

added extra/mysql_install.c - will work on it in 4.0, but it does not hurt
to have it sit in 3.23 tree for now since it will eventually be backported 
to 3.23 anyway 


Docs/manual.texi:
  documented slave-skip-errors
  updated change history
extra/resolve_stack_dump.c:
  fixed wrong help message
include/my_bitmap.h:
  bitmap code updates
mysql-test/r/rpl_get_lock.result:
  test for a possible bug in release_lock() replication
mysql-test/t/rpl_get_lock.test:
  test for possible bug in release_lock replication
mysys/my_bitmap.c:
  bitmap code updates/clean-up
sql/mysqld.cc:
  slave-skip-errors
sql/slave.cc:
  slave-skip-errors
sql/slave.h:
  slave skip errors
parent 77629c20
......@@ -23738,6 +23738,33 @@ Updates to a database with a different name than the original
Example: @code{replicate-rewrite-db=master_db_name->slave_db_name}.
@item @code{slave-skip-errors=err_code1,err_code2,..} @tab
Available only in 3.23.47 and later. Tells the slave thread to continue
replication when a query returns an error from the provided
list. Normally, replication will discontinue when an error is
encountered giving the user a chance to resolve the inconsistency in the
data manually. Do not use this option unless you fully understand why
you are getting the errors. If there are no bugs in your
replication setup and client programs, and no bugs in MySQL itself, you
should never get an abort with error.Indiscriminate use of this option
will result in slaves being hopelessly out of sync with the master and
you having no idea how the problem happened.
For error codes, you should use the numbers provided by the error message in
your slave error log and in the output of @code{SHOW SLAVE STATUS}. Full list
of error messages can be found in the source distribution in
@code{Docs/mysqld_error.txt}.
You can ( but should not) also use a very non-recommended value of @code{all}
which will ignore all error messages and keep barging along regardless.
Needless to say, if you use it, we make no promises regarding your data
integrity. Please do not complain if your data on the slave is not anywhere
close to what it is on the master in this case - you have been warned.
Example:
@code{slave-skip-errors=1062,1053} or @code{slave-skip-errors=all}
@item @code{skip-slave-start} @tab
Tells the slave server not to start the slave on the startup. The user
can start it later with @code{SLAVE START}.
......@@ -46839,17 +46866,21 @@ not yet 100% confident in this code.
@appendixsubsec Changes in release 3.23.47
@itemize @bullet
@item
Added @code{slave-skip-errors} option
@item
Fixed that @code{GROUP BY expr DESC} works.
@item
Fixed bug when using @code{t1 LEFT JOIN t2 ON t2.key=constant}.
@item
@code{mysqlconfig} now also work with binary (relocated) distributions.
@code{mysql_config} now also work with binary (relocated) distributions.
@end itemize
@node News-3.23.46, News-3.23.45, News-3.23.47, News-3.23.x
@appendixsubsec Changes in release 3.23.46
@itemize @bullet
@item
Fixed problem with aliased temporary tables replication
@item
InnoDB and BDB tables will now use index when doing an @code{ORDER BY}
on the whole table.
@item
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA */
/* Install or upgrade MySQL server. By Sasha Pachev <sasha@mysql.com>
*/
#define INSTALL_VERSION "1.0"
#define DONT_USE_RAID
#include <global.h>
#include <m_ctype.h>
#include <my_sys.h>
#include <m_string.h>
#include <mysql_version.h>
#include <errno.h>
#include <getopt.h>
struct option long_options[] =
{
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{0, 0,0,0}
};
static void print_version(void)
{
printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,INSTALL_VERSION,
MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
}
static void usage()
{
print_version();
printf("MySQL AB, by Sasha Pachev\n");
printf("This software comes with ABSOLUTELY NO WARRANTY\n\n");
printf("Install or upgrade MySQL server.\n\n");
printf("Usage: %s [OPTIONS] \n", my_progname);
printf("\n\
-?, --help Display this help and exit.\n\
-h, --host=... Connect to host.\n\
-V, --version Output version information and exit.\n");
}
......@@ -75,7 +75,8 @@ static void usage()
printf("Usage: %s [OPTIONS] symbols-file [numeric-dump-file]\n", my_progname);
printf("\n\
-?, --help Display this help and exit.\n\
-h, --host=... Connect to host.\n\
-s, --symbols-file=... Use specified symbols file.\n\
-n, --numeric-dump-file=... Read the dump from specified file.\n\
-V, --version Output version information and exit.\n");
printf("\n\
The symbols-file should include the output from: 'nm --numeric-sort mysqld'.\n\
......
......@@ -26,6 +26,11 @@ typedef struct st_bitmap
{
uchar *bitmap;
uint bitmap_size;
my_bool thread_safe; /* set if several threads access the bitmap */
/* mutex will be acquired for the duration of each bitmap operation if
thread_safe flag is set. Otherwise, we optimize by not acquiring the
mutex
*/
#ifdef THREAD
pthread_mutex_t mutex;
#endif
......@@ -34,10 +39,14 @@ typedef struct st_bitmap
#ifdef __cplusplus
extern "C" {
#endif
extern my_bool bitmap_init(MY_BITMAP *bitmap, uint bitmap_size);
extern my_bool bitmap_init(MY_BITMAP *bitmap, uint bitmap_size,
my_bool thread_safe);
extern void bitmap_free(MY_BITMAP *bitmap);
extern void bitmap_set_bit(MY_BITMAP *bitmap, uint bitmap_bit);
extern uint bitmap_set_next(MY_BITMAP *bitmap);
extern void bitmap_set_all(MY_BITMAP* bitmap);
extern my_bool bitmap_is_set(MY_BITMAP* bitmap, uint bitmap_bit);
extern void bitmap_clear_all(MY_BITMAP* bitmap);
extern void bitmap_clear_bit(MY_BITMAP *bitmap, uint bitmap_bit);
#ifdef __cplusplus
}
......
release_lock("lock")
0
get_lock("lock",3)
1
n
......
......@@ -4,6 +4,7 @@ create table t1(n int);
insert into t1 values(get_lock("lock",2));
dirty_close master;
connection master1;
select release_lock("lock");
save_master_pos;
connection slave;
sync_with_master;
......
--slave-skip-error=1053,1062
source include/master-slave.inc;
connection master;
drop table if exists t1;
create table t1 (n int not null primary key);
save_master_pos;
connection slave;
sync_with_master;
insert into t1 values (1);
connection master;
insert into t1 values (1);
insert into t1 values (2),(3);
save_master_pos;
connection slave;
sync_with_master;
select * from t1;
......@@ -26,14 +26,32 @@
#include "mysys_priv.h"
#include <my_bitmap.h>
#include <assert.h>
#include <string.h>
my_bool bitmap_init(MY_BITMAP *map, uint bitmap_size)
inline void bitmap_lock(MY_BITMAP* map)
{
#ifdef THREAD
if (map->thread_safe)
pthread_mutex_lock(&map->mutex);
#endif
}
inline void bitmap_unlock(MY_BITMAP* map)
{
#ifdef THREAD
if (map->thread_safe)
pthread_mutex_unlock(&map->mutex);
#endif
}
my_bool bitmap_init(MY_BITMAP *map, uint bitmap_size, my_bool thread_safe)
{
if (!(map->bitmap=(uchar*) my_malloc((bitmap_size+7)/8,
MYF(MY_WME | MY_ZEROFILL))))
return 1;
dbug_assert(bitmap_size != ~(uint) 0);
#ifdef THREAD
map->thread_safe = thread_safe;
pthread_mutex_init(&map->mutex, MY_MUTEX_INIT_FAST);
#endif
map->bitmap_size=bitmap_size;
......@@ -56,9 +74,9 @@ void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit)
{
if (bitmap_bit < map->bitmap_size)
{
pthread_mutex_lock(&map->mutex);
bitmap_lock(map);
map->bitmap[bitmap_bit / 8] |= (1 << (bitmap_bit & 7));
pthread_mutex_unlock(&map->mutex);
bitmap_unlock(map);
}
}
......@@ -70,7 +88,7 @@ uint bitmap_set_next(MY_BITMAP *map)
uint bitmap_size=map->bitmap_size;
uint i;
pthread_mutex_lock(&map->mutex);
bitmap_lock(map);
for (i=0; i < bitmap_size ; i++, bitmap++)
{
if (*bitmap != 0xff)
......@@ -88,7 +106,7 @@ uint bitmap_set_next(MY_BITMAP *map)
break; /* Found bit */
}
}
pthread_mutex_unlock(&map->mutex);
bitmap_unlock(map);
return bit_found;
}
......@@ -97,9 +115,29 @@ void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit)
{
if (bitmap_bit < map->bitmap_size)
{
pthread_mutex_lock(&map->mutex);
bitmap_lock(map);
map->bitmap[bitmap_bit / 8] &= ~ (1 << (bitmap_bit & 7));
pthread_mutex_unlock(&map->mutex);
bitmap_unlock(map);
}
}
void bitmap_set_all(MY_BITMAP* map)
{
bitmap_lock(map);
memset(map->bitmap, 0xff, (map->bitmap_size+7)/8);
bitmap_unlock(map);
}
my_bool bitmap_is_set(MY_BITMAP* map, uint bitmap_bit)
{
return (bitmap_bit < map->bitmap_size) ?
(map->bitmap[bitmap_bit / 8] & (1 << (bitmap_bit & 7))) :
0;
}
void bitmap_clear_all(MY_BITMAP* map)
{
bitmap_lock(map);
bzero(map->bitmap,(map->bitmap_size+7)/8);
bitmap_unlock(map);
}
......@@ -707,6 +707,8 @@ void clean_up(bool print_message)
DBUG_PRINT("exit",("clean_up"));
if (cleanup_done++)
return; /* purecov: inspected */
if (use_slave_mask)
bitmap_free(&slave_error_mask);
acl_free(1);
grant_free();
sql_cache_free();
......@@ -1757,7 +1759,7 @@ int main(int argc, char **argv)
#endif
select_thread=pthread_self();
select_thread_in_use=1;
if (use_temp_pool && bitmap_init(&temp_pool,1024))
if (use_temp_pool && bitmap_init(&temp_pool,1024,1))
unireg_abort(1);
/*
......@@ -2600,7 +2602,8 @@ enum options {
OPT_GEMINI_UNBUFFERED_IO, OPT_SKIP_SAFEMALLOC,
OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL,
OPT_SAFE_USER_CREATE, OPT_SQL_MODE
OPT_SAFE_USER_CREATE, OPT_SQL_MODE,
OPT_SLAVE_SKIP_ERRORS
};
static struct option long_options[] = {
......@@ -2735,6 +2738,8 @@ static struct option long_options[] = {
{"skip-stack-trace", no_argument, 0, (int) OPT_SKIP_STACK_TRACE},
{"skip-symlink", no_argument, 0, (int) OPT_SKIP_SYMLINKS},
{"skip-thread-priority", no_argument, 0, (int) OPT_SKIP_PRIOR},
{"slave-skip-errors", required_argument,0,
(int) OPT_SLAVE_SKIP_ERRORS},
{"socket", required_argument, 0, (int) OPT_SOCKET},
{"sql-bin-update-same", no_argument, 0, (int) OPT_SQL_BIN_UPDATE_SAME},
{"sql-mode", required_argument, 0, (int) OPT_SQL_MODE},
......@@ -3396,6 +3401,9 @@ static void get_options(int argc,char **argv)
case 'P':
mysql_port= (unsigned int) atoi(optarg);
break;
case OPT_SLAVE_SKIP_ERRORS:
init_slave_skip_errors(optarg);
break;
case OPT_SAFEMALLOC_MEM_LIMIT:
#if !defined(DBUG_OFF) && defined(SAFEMALLOC)
safemalloc_mem_limit = atoi(optarg);
......
......@@ -29,6 +29,8 @@
volatile bool slave_running = 0;
pthread_t slave_real_id;
MASTER_INFO glob_mi;
MY_BITMAP slave_error_mask;
bool use_slave_mask = 0;
HASH replicate_do_table, replicate_ignore_table;
DYNAMIC_ARRAY replicate_wild_do_table, replicate_wild_ignore_table;
bool do_table_inited = 0, ignore_table_inited = 0;
......@@ -73,6 +75,50 @@ static byte* get_table_key(TABLE_RULE_ENT* e, uint* len,
return (byte*)e->db;
}
/* called from get_options() in mysqld.cc on start-up */
void init_slave_skip_errors(char* arg)
{
char* p,*end;
int err_code = 0;
my_bool last_was_digit = 0;
if (bitmap_init(&slave_error_mask,MAX_SLAVE_ERROR,0))
{
fprintf(stderr, "Badly out of memory, please check your system status\n");
exit(1);
}
use_slave_mask = 1;
for (;isspace(*arg);++arg)
/* empty */;
/* force first three chars to lower case */
for (p = arg, end = arg + 3; *p && p < end; ++p)
*p = tolower(*p);
if (!memcmp(arg,"all",3))
{
bitmap_set_all(&slave_error_mask);
return;
}
for (p = arg, end = strend(arg); p < end; ++p)
{
int digit = *p - '0';
if (digit >= 0 && digit < 10) /* found real digit */
{
err_code = err_code * 10 + digit;
last_was_digit = 1;
}
else /* delimiter */
{
if (last_was_digit)
{
if (err_code < MAX_SLAVE_ERROR)
{
bitmap_set_bit(&slave_error_mask,err_code);
}
err_code = 0;
last_was_digit = 0;
}
}
}
}
void init_table_rule_hash(HASH* h, bool* h_inited)
{
......@@ -869,6 +915,11 @@ point. If you are sure that your master is ok, run this query manually on the\
}
}
inline int ignored_error_code(int err_code)
{
return use_slave_mask && bitmap_is_set(&slave_error_mask, err_code);
}
static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
{
Log_event * ev = Log_event::read_log_event((const char*)net->read_pos + 1,
......@@ -925,11 +976,13 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
// sanity check to make sure the master did not get a really bad
// error on the query
if (!check_expected_error(thd, (expected_error = qev->error_code)))
if (ignored_error_code((expected_error=qev->error_code)) ||
!check_expected_error(thd, expected_error))
{
mysql_parse(thd, thd->query, q_len);
if (expected_error !=
(actual_error = thd->net.last_errno) && expected_error)
(actual_error = thd->net.last_errno) && expected_error &&
!ignored_error_code(actual_error))
{
const char* errmsg = "Slave: did not get the expected error\
running query from master - expected: '%s' (%d), got '%s' (%d)";
......@@ -939,7 +992,8 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len)
actual_error);
thd->query_error = 1;
}
else if (expected_error == actual_error)
else if (expected_error == actual_error ||
ignored_error_code(actual_error))
{
thd->query_error = 0;
*last_slave_error = 0;
......
......@@ -2,8 +2,11 @@
#define SLAVE_H
#define SLAVE_NET_TIMEOUT 3600
#define MAX_SLAVE_ERROR 2000
extern ulong slave_net_timeout, master_retry_count;
extern MY_BITMAP slave_error_mask;
extern bool use_slave_mask;
typedef struct st_master_info
{
......@@ -89,6 +92,7 @@ int add_table_rule(HASH* h, const char* table_spec);
int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec);
void init_table_rule_hash(HASH* h, bool* h_inited);
void init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited);
void init_slave_skip_errors(char* arg);
void end_slave(); // clean up
int init_master_info(MASTER_INFO* mi);
......
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