Below is the list of changes that have just been committed into a local
5.1 repository of mats. When mats does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-02-23 14:59:48+01:00, mats@romeo.(none) +5 -0
Merge romeo.(none):/home/bkroot/mysql-5.1-new-rpl
into romeo.(none):/home/bk/b19033-mysql-5.1-new-rpl
MERGE: 1.2408.1.4
sql/log.cc@stripped, 2007-02-23 14:59:41+01:00, mats@romeo.(none) +0 -0
Auto merged
MERGE: 1.253.1.1
sql/log_event.cc@stripped, 2007-02-23 14:59:41+01:00, mats@romeo.(none) +0 -0
Auto merged
MERGE: 1.262.1.1
sql/log_event.h@stripped, 2007-02-23 14:59:42+01:00, mats@romeo.(none) +0 -0
Auto merged
MERGE: 1.145.1.1
sql/slave.h@stripped, 2007-02-23 14:59:42+01:00, mats@romeo.(none) +0 -0
Auto merged
MERGE: 1.103.1.1
sql/sql_insert.cc@stripped, 2007-02-23 14:59:42+01:00, mats@romeo.(none) +0 -0
Auto merged
MERGE: 1.244.1.2
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: mats
# Host: romeo.(none)
# Root: /home/bk/b19033-mysql-5.1-new-rpl/RESYNC
--- 1.254/sql/log.cc 2007-02-23 14:59:57 +01:00
+++ 1.255/sql/log.cc 2007-02-23 14:59:57 +01:00
@@ -4528,7 +4528,7 @@
goto err;
if (using_heuristic_recover())
return 1;
- if ((fd= my_create(logname, O_RDWR, 0, MYF(MY_WME))) < 0)
+ if ((fd= my_create(logname, CREATE_MODE, O_RDWR, MYF(MY_WME))) < 0)
goto err;
inited=1;
file_length= opt_tc_log_size;
--- 1.263/sql/log_event.cc 2007-02-23 14:59:57 +01:00
+++ 1.264/sql/log_event.cc 2007-02-23 14:59:57 +01:00
@@ -2254,6 +2254,8 @@
binlog_version= uint2korr(buf+ST_BINLOG_VER_OFFSET);
memcpy(server_version, buf+ST_SERVER_VER_OFFSET,
ST_SERVER_VER_LEN);
+ // prevent overrun if log is corrupted on disk
+ server_version[ST_SERVER_VER_LEN-1]= 0;
created= uint4korr(buf+ST_CREATED_OFFSET);
/* We use log_pos to mark if this was an artificial event or not */
artificial_event= (log_pos == 0);
@@ -2377,6 +2379,8 @@
switch (binlog_ver) {
case 4: /* MySQL 5.0 */
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
+ DBUG_EXECUTE_IF("pretend_version_50034_in_binlog",
+ strmov(server_version, "5.0.34"););
common_header_len= LOG_EVENT_HEADER_LEN;
number_of_event_types= LOG_EVENT_TYPES;
/* we'll catch my_malloc() error in is_valid() */
@@ -2467,6 +2471,7 @@
post_header_len= 0; /* will make is_valid() fail */
break;
}
+ calc_server_version_split();
}
@@ -2506,6 +2511,7 @@
post_header_len= (uint8*) my_memdup((byte*)buf+ST_COMMON_HEADER_LEN_OFFSET+1,
number_of_event_types*
sizeof(*post_header_len), MYF(0));
+ calc_server_version_split();
DBUG_VOID_RETURN;
}
@@ -2605,6 +2611,37 @@
DBUG_RETURN(Start_log_event_v3::exec_event(rli));
}
#endif
+
+
+/**
+ Splits the event's 'server_version' string into three numeric pieces stored
+ into 'server_version_split':
+ X.Y.Zabc (X,Y,Z numbers, a not a digit) -> {X,Y,Z}
+ X.Yabc -> {X,Y,0}
+ Xabc -> {X,0,0}
+ 'server_version_split' is then used for lookups to find if the server which
+ created this event has some known bug.
+*/
+void Format_description_log_event::calc_server_version_split()
+{
+ char *p= server_version, *r;
+ ulong number;
+ for (uint i= 0; i<=2; i++)
+ {
+ number= strtoul(p, &r, 10);
+ server_version_split[i]= (uchar)number;
+ DBUG_ASSERT(number < 256); // fit in uchar
+ p= r;
+ DBUG_ASSERT(!((i == 0) && (*r != '.'))); // should be true in practice
+ if (*r == '.')
+ p++; // skip the dot
+ }
+ DBUG_PRINT("info",("Format_description_log_event::server_version_split:"
+ " '%s' %d %d %d", server_version,
+ server_version_split[0],
+ server_version_split[1], server_version_split[2]));
+}
+
/**************************************************************************
Load_log_event methods
--- 1.146/sql/log_event.h 2007-02-23 14:59:57 +01:00
+++ 1.147/sql/log_event.h 2007-02-23 14:59:57 +01:00
@@ -1153,6 +1153,7 @@
uint8 number_of_event_types;
/* The list of post-headers' lengthes */
uint8 *post_header_len;
+ uchar server_version_split[3];
Format_description_log_event(uint8 binlog_ver, const char* server_ver=0);
@@ -1184,6 +1185,7 @@
*/
return FORMAT_DESCRIPTION_HEADER_LEN;
}
+ void calc_server_version_split();
};
--- 1.245/sql/sql_insert.cc 2007-02-23 14:59:57 +01:00
+++ 1.246/sql/sql_insert.cc 2007-02-23 14:59:57 +01:00
@@ -59,6 +59,7 @@
#include "sql_trigger.h"
#include "sql_select.h"
#include "sql_show.h"
+#include "slave.h"
static int check_null_fields(THD *thd,TABLE *entry);
#ifndef EMBEDDED_LIBRARY
@@ -341,6 +342,36 @@
(duplic == DUP_UPDATE))
lock_type=TL_WRITE;
#endif
+ if ((lock_type == TL_WRITE_DELAYED) &&
+ (global_system_variables.binlog_format == BINLOG_FORMAT_STMT) &&
+ log_on && mysql_bin_log.is_open() &&
+ (values_list.elements > 1))
+ {
+ /*
+ Statement-based binary logging does not work in this case, because:
+ a) two concurrent statements may have their rows intermixed in the
+ queue, leading to autoincrement replication problems on slave (because
+ the values generated used for one statement don't depend only on the
+ value generated for the first row of this statement, so are not
+ replicable)
+ b) if first row of the statement has an error the full statement is
+ not binlogged, while next rows of the statement may be inserted.
+ c) if first row succeeds, statement is binlogged immediately with a
+ zero error code (i.e. "no error"), if then second row fails, query
+ will fail on slave too and slave will stop (wrongly believing that the
+ master got no error).
+ So we fallback to non-delayed INSERT.
+ Note that to be fully correct, we should test the "binlog format which
+ the delayed thread is going to use for this row". But in the common case
+ where the global binlog format is not changed and the session binlog
+ format may be changed, that is equal to the global binlog format.
+ We test it without mutex for speed reasons (condition rarely true), and
+ in the common case (global not changed) it is as good as without mutex;
+ if global value is changed, anyway there is uncertainty as the delayed
+ thread may be old and use the before-the-change value.
+ */
+ lock_type= TL_WRITE;
+ }
table_list->lock_type= lock_type;
#ifndef EMBEDDED_LIBRARY
@@ -454,6 +485,14 @@
thd->cuted_fields = 0L;
table->next_number_field=table->found_next_number_field;
+#ifdef HAVE_REPLICATION
+ if (thd->slave_thread &&
+ (info.handle_duplicates == DUP_UPDATE) &&
+ (table->next_number_field != NULL) &&
+ rpl_master_has_bug(&active_mi->rli, 24432))
+ goto abort;
+#endif
+
error=0;
thd->proc_info="update";
if (duplic != DUP_ERROR || ignore)
@@ -1146,13 +1185,13 @@
if (res == VIEW_CHECK_ERROR)
goto before_trg_err;
+ table->file->restore_auto_increment(prev_insert_id);
if ((error=table->file->ha_update_row(table->record[1],
table->record[0])))
{
if (info->ignore &&
!table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
{
- table->file->restore_auto_increment(prev_insert_id);
goto ok_or_after_trg_err;
}
goto err;
@@ -2489,6 +2528,15 @@
}
restore_record(table,s->default_values); // Get empty record
table->next_number_field=table->found_next_number_field;
+
+#ifdef HAVE_REPLICATION
+ if (thd->slave_thread &&
+ (info.handle_duplicates == DUP_UPDATE) &&
+ (table->next_number_field != NULL) &&
+ rpl_master_has_bug(&active_mi->rli, 24432))
+ DBUG_RETURN(1);
+#endif
+
thd->cuted_fields=0;
if (info.ignore || info.handle_duplicates != DUP_ERROR)
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
--- 1.104/sql/slave.h 2007-02-23 14:59:57 +01:00
+++ 1.105/sql/slave.h 2007-02-23 14:59:57 +01:00
@@ -161,6 +161,7 @@
bool show_master_info(THD* thd, MASTER_INFO* mi);
bool show_binlog_info(THD* thd);
+bool rpl_master_has_bug(RELAY_LOG_INFO *rli, uint bug_id);
const char *print_slave_db_safe(const char *db);
int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code);
| Thread |
|---|
| • bk commit into 5.1 tree (mats:1.2410) | Mats Kindahl | 23 Feb |