1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

WWe now store the catalog in Query_log_event in binlog WITHOUT its end zero.

This saves one byte per Query_log_event on disk compared to 5.0.[0..3]. Compatibility problems with 5.0.x where x<4
are explained in the comments in log_event.cc. Putting back s/my_open(O_TRUNC)/(my_delete+my_create) change which had
been wiped away by somebody doing a wrong 4.1->5.0 merge (which happened just
before 5.0.3 :( ). Applying it to new events for LOAD DATA INFILE.
If slave fails in Execute_load_query_log_event::exec_event(),
don't delete the file (so that it's re-usable at next START SLAVE).
And (youpi!) fix for BUG#3247 "a partially completed LOAD DATA INFILE is not
executed at all on the slave" (storing an Execute_load_query_log_event
to binlog, with its error code, instead of Delete_file_log_event).


mysql-test/r/mix_innodb_myisam_binlog.result:
  we now use one less byte when storing the catalog in binlog so positions change
mysql-test/r/rpl_change_master.result:
  we now use one less byte when storing the catalog in binlog so positions change
mysql-test/r/rpl_deadlock.result:
  we now use one less byte when storing the catalog in binlog so positions change
mysql-test/r/rpl_error_ignored_table.result:
  we now use one less byte when storing the catalog in binlog so positions change
mysql-test/r/rpl_flush_log_loop.result:
  we now use one less byte when storing the catalog in binlog so positions change
mysql-test/r/rpl_loaddata.result:
  we now use one less byte when storing the catalog in binlog so positions change.
  Plus testing replication of LOAD DATA INFILE if duplicate key and non-transactional table.
mysql-test/r/rpl_log.result:
  we now use one less byte when storing the catalog in binlog so positions change
mysql-test/r/rpl_max_relay_size.result:
  we now use one less byte when storing the catalog in binlog so positions change
mysql-test/r/rpl_relayrotate.result:
  we now use one less byte when storing the catalog in binlog so positions change
mysql-test/r/rpl_replicate_do.result:
  we now use one less byte when storing the catalog in binlog so positions change
mysql-test/r/rpl_rotate_logs.result:
  we now use one less byte when storing the catalog in binlog so positions change
mysql-test/r/rpl_until.result:
  we now use one less byte when storing the catalog in binlog so positions change
mysql-test/t/mysqlbinlog.test:
  we now use one less byte when storing the catalog in binlog so positions change
mysql-test/t/mysqlbinlog2.test:
  we now use one less byte when storing the catalog in binlog so positions change
mysql-test/t/rpl_deadlock.test:
  we now use one less byte when storing the catalog in binlog so positions change
mysql-test/t/rpl_loaddata.test:
  we now use one less byte when storing the catalog in binlog so positions change.
  Plus testing replication of LOAD DATA INFILE if duplicate key and non-transactional table.
mysql-test/t/rpl_until.test:
  we now use one less byte when storing the catalog in binlog so positions change
sql/log_event.cc:
  a) We now store the catalog in Query_log_event in binlog WITHOUT its end zero.
  This saves one byte per Query_log_event on disk. Compatibility problems with 5.0.x where x<4
  are explained in the comments in this file.
  b) putting back s/my_open(O_TRUNC)/(my_delete+my_create) change which had
  been wiped away by somebody doing a wrong 4.1->5.0 merge (which happened just
  before 5.0.3 :( ). Applying it to new events for LOAD DATA INFILE.
  c) if slave fails in Execute_load_query_log_event::exec_event(),
  don't delete the file (so that it's re-usable at next START SLAVE).
sql/log_event.h:
  We now store the catalog in Query_log_event in binlog WITHOUT its end zero.
  This saves one byte per Query_log_event on disk. This new storage for
  the catalog is denoted by Q_CATALOG_NZ_CODE (couldn't re-use Q_CATALOG_CODE
  as 5.0.3 slaves of this 5.0.4 master would segfault because it would
  expect a 0 when there is none.
  Renaming get_open_mode() to get_create_or_append() (see log_event.cc)
sql/sql_load.cc:
  Fix for BUG#3247: if LOAD DATA INFILE fails but has permanently updated a table
  (i.e. has deleted/added/modified some rows in a non-transactional table),
  we must write an Execute_load_query_log_event to binlog (with the error code,
  as this class beautifully inherits from Query_log_event, it can store
  the error code - thanks Dmitri) and not a Delete_file_log_event (we use
  to write a Delete_file_log_event: no update happened on slave, bug).
This commit is contained in:
unknown
2005-03-25 14:51:17 +01:00
parent fa4a075b6c
commit f07e4850d0
20 changed files with 271 additions and 185 deletions

View File

@@ -1041,25 +1041,28 @@ bool Query_log_event::write(IO_CACHE* file)
}
if (catalog_len) // i.e. "catalog inited" (false for 4.0 events)
{
*start++= Q_CATALOG_CODE;
*start++= Q_CATALOG_NZ_CODE;
*start++= (uchar) catalog_len;
bmove(start, catalog, catalog_len);
start+= catalog_len;
/*
We write a \0 at the end. As we also have written the length, it's
apparently useless; but in fact it enables us to just do
catalog= a_pointer_to_the_buffer_of_the_read_event
later in the slave SQL thread.
If we didn't have the \0, we would need to memdup to build the catalog in
the slave SQL thread.
And still the interest of having the length too is that in the slave SQL
thread we immediately know at which position the catalog ends (no need to
search for '\0'. In other words: length saves search, \0 saves mem alloc,
at the cost of 1 redundant byte on the disk.
Note that this is only a fix until we change 'catalog' to LEX_STRING
(then we won't need the \0).
*/
*(start++)= '\0';
In 5.0.x where x<4 masters we used to store the end zero here. This was
a waste of one byte so we don't do it in x>=4 masters. We change code to
Q_CATALOG_NZ_CODE, because re-using the old code would make x<4 slaves
of this x>=4 master segfault (expecting a zero when there is
none). Remaining compatibility problems are: the older slave will not
find the catalog; but it is will not crash, and it's not an issue
that it does not find the catalog as catalogs were not used in these older
MySQL versions (we store it in binlog and read it from relay log but do
nothing useful with it). What is an issue is that the older slave will
stop processing the Q_* blocks (and jumps to the db/query) as soon as it
sees unknown Q_CATALOG_NZ_CODE; so it will not be able to read
Q_AUTO_INCREMENT*, Q_CHARSET and so replication will fail silently in
various ways. Documented that you should not mix alpha/beta versions if
they are not exactly the same version, with example of 5.0.2<->5.0.3 and
5.0.3<->5.0.4. If replication is from older to new, the new won't find
the catalog and will have the same problems.
*/
}
if (auto_increment_increment != 1)
{
@@ -1259,10 +1262,10 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
pos+= 8;
break;
}
case Q_CATALOG_CODE:
case Q_CATALOG_NZ_CODE:
if ((catalog_len= *pos))
catalog= (char*) pos+1; // Will be copied later
pos+= catalog_len+2;
pos+= catalog_len+1;
break;
case Q_AUTO_INCREMENT:
auto_increment_increment= uint2korr(pos);
@@ -1297,9 +1300,10 @@ Query_log_event::Query_log_event(const char* buf, uint event_len,
DBUG_VOID_RETURN;
if (catalog_len) // If catalog is given
{
memcpy(start, catalog, catalog_len+1); // Copy name and end \0
memcpy(start, catalog, catalog_len);
catalog= start;
start+= catalog_len+1;
start+= catalog_len;
*start++= 0;
}
if (time_zone_len)
{
@@ -4006,8 +4010,10 @@ int Create_file_log_event::exec_event(struct st_relay_log_info* rli)
strmov(p, ".info"); // strmov takes less code than memcpy
strnmov(proc_info, "Making temp file ", 17); // no end 0
thd->proc_info= proc_info;
if ((fd = my_open(fname_buf, O_WRONLY|O_CREAT|O_BINARY|O_TRUNC,
MYF(MY_WME))) < 0 ||
my_delete(fname_buf, MYF(0)); // old copy may exist already
if ((fd= my_create(fname_buf, CREATE_MODE,
O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
MYF(MY_WME))) < 0 ||
init_io_cache(&file, fd, IO_SIZE, WRITE_CACHE, (my_off_t)0, 0,
MYF(MY_WME|MY_NABP)))
{
@@ -4031,8 +4037,10 @@ int Create_file_log_event::exec_event(struct st_relay_log_info* rli)
my_close(fd, MYF(0));
// fname_buf now already has .data, not .info, because we did our trick
if ((fd = my_open(fname_buf, O_WRONLY|O_CREAT|O_BINARY|O_TRUNC,
MYF(MY_WME))) < 0)
my_delete(fname_buf, MYF(0)); // old copy may exist already
if ((fd= my_create(fname_buf, CREATE_MODE,
O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
MYF(MY_WME))) < 0)
{
slave_print_error(rli,my_errno, "Error in Create_file event: could not open file '%s'", fname_buf);
goto err;
@@ -4148,12 +4156,12 @@ void Append_block_log_event::pack_info(Protocol *protocol)
/*
Append_block_log_event::get_open_mode()
Append_block_log_event::get_create_or_append()
*/
int Append_block_log_event::get_open_mode() const
int Append_block_log_event::get_create_or_append() const
{
return O_WRONLY | O_APPEND | O_BINARY;
return 0; /* append to the file, fail if not exists */
}
/*
@@ -4171,7 +4179,20 @@ int Append_block_log_event::exec_event(struct st_relay_log_info* rli)
memcpy(p, ".data", 6);
strnmov(proc_info, "Making temp file ", 17); // no end 0
thd->proc_info= proc_info;
if ((fd = my_open(fname, get_open_mode(), MYF(MY_WME))) < 0)
if (get_create_or_append())
{
my_delete(fname, MYF(0)); // old copy may exist already
if ((fd= my_create(fname, CREATE_MODE,
O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
MYF(MY_WME))) < 0)
{
slave_print_error(rli, my_errno,
"Error in %s event: could not create file '%s'",
get_type_str(), fname);
goto err;
}
}
else if ((fd = my_open(fname, O_WRONLY|O_APPEND|O_BINARY|O_NOFOLLOW, MYF(MY_WME))) < 0)
{
slave_print_error(rli, my_errno,
"Error in %s event: could not open file '%s'",
@@ -4384,7 +4405,7 @@ int Execute_load_log_event::exec_event(struct st_relay_log_info* rli)
Load_log_event* lev = 0;
memcpy(p, ".info", 6);
if ((fd = my_open(fname, O_RDONLY|O_BINARY, MYF(MY_WME))) < 0 ||
if ((fd = my_open(fname, O_RDONLY|O_BINARY|O_NOFOLLOW, MYF(MY_WME))) < 0 ||
init_io_cache(&file, fd, IO_SIZE, READ_CACHE, (my_off_t)0, 0,
MYF(MY_WME|MY_NABP)))
{
@@ -4483,9 +4504,9 @@ Begin_load_query_log_event(const char* buf, uint len,
#if defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
int Begin_load_query_log_event::get_open_mode() const
int Begin_load_query_log_event::get_create_or_append() const
{
return O_CREAT | O_WRONLY | O_BINARY | O_TRUNC;
return 1; /* create the file */
}
#endif /* defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
@@ -4662,7 +4683,12 @@ Execute_load_query_log_event::exec_event(struct st_relay_log_info* rli)
/* Forging file name for deletion in same buffer */
*fname_end= 0;
(void) my_delete(fname, MYF(MY_WME));
/*
If there was an error the slave is going to stop, leave the
file so that we can re-execute this event at START SLAVE.
*/
if (!error)
(void) my_delete(fname, MYF(MY_WME));
my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
return error;