Commit fee8858e authored by Vadim Tkachenko's avatar Vadim Tkachenko

added innodb_overwrite_relay_log_info.patch

parent a992bf5a
......@@ -35,7 +35,17 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#pragma implementation // gcc: Class implementation
#endif
#define MYSQL_SERVER
#include <mysql_priv.h>
#ifdef MYSQL_SERVER
#include <rpl_mi.h>
#include <slave.h>
// Defined in slave.cc
int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
const char *default_val);
#endif /* MYSQL_SERVER */
#include <m_ctype.h>
#include <mysys_err.h>
......@@ -78,6 +88,14 @@ extern "C" {
#include "i_s.h"
#include "handler0vars.h"
#ifdef MYSQL_SERVER
// Defined in trx0sys.c
extern char trx_sys_mysql_master_log_name[];
extern ib_int64_t trx_sys_mysql_master_log_pos;
extern char trx_sys_mysql_relay_log_name[];
extern ib_int64_t trx_sys_mysql_relay_log_pos;
#endif /* MYSQL_SERVER */
#ifndef MYSQL_SERVER
/* This is needed because of Bug #3596. Let us hope that pthread_mutex_t
is defined the same in both builds: the MySQL server and the InnoDB plugin. */
......@@ -176,6 +194,7 @@ static my_bool innobase_use_doublewrite = TRUE;
static my_bool innobase_use_checksums = TRUE;
static my_bool innobase_extra_undoslots = FALSE;
static my_bool innobase_locks_unsafe_for_binlog = FALSE;
static my_bool innobase_overwrite_relay_log_info = FALSE;
static my_bool innobase_rollback_on_timeout = FALSE;
static my_bool innobase_create_status_file = FALSE;
static my_bool innobase_stats_on_metadata = TRUE;
......@@ -1920,6 +1939,89 @@ innobase_init(
}
#endif /* UNIV_DEBUG */
#ifndef MYSQL_SERVER
innodb_overwrite_relay_log_info = FALSE;
#endif
#ifdef HAVE_REPLICATION
#ifdef MYSQL_SERVER
/* read master log position from relay-log.info if exists */
char fname[FN_REFLEN+128];
int pos;
int info_fd;
IO_CACHE info_file;
fname[0] = '\0';
if(innobase_overwrite_relay_log_info) {
fprintf(stderr,
"InnoDB: Warning: innodb_overwrite_relay_log_info is enabled."
" Updates in other storage engines may have problem with consistency.\n");
bzero((char*) &info_file, sizeof(info_file));
fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
int error=0;
if (!access(fname,F_OK)) {
/* exist */
if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
error=1;
} else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
READ_CACHE, 0L, 0, MYF(MY_WME))) {
error=1;
}
if (error) {
relay_info_error:
if (info_fd >= 0)
my_close(info_fd, MYF(0));
fname[0] = '\0';
goto skip_relay;
}
} else {
fname[0] = '\0';
goto skip_relay;
}
if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") || /* dummy (it is relay-log) */
init_intvar_from_file(&pos, &info_file, BIN_LOG_HEADER_SIZE)) {
end_io_cache(&info_file);
error=1;
goto relay_info_error;
}
fprintf(stderr,
"InnoDB: relay-log.info is detected.\n"
"InnoDB: relay log: position %u, file name %s\n",
pos, fname);
strncpy(trx_sys_mysql_relay_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
trx_sys_mysql_relay_log_pos = (ib_int64_t) pos;
if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") ||
init_intvar_from_file(&pos, &info_file, 0)) {
end_io_cache(&info_file);
error=1;
goto relay_info_error;
}
fprintf(stderr,
"InnoDB: master log: position %u, file name %s\n",
pos, fname);
strncpy(trx_sys_mysql_master_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
trx_sys_mysql_master_log_pos = (ib_int64_t) pos;
end_io_cache(&info_file);
if (info_fd >= 0)
my_close(info_fd, MYF(0));
}
skip_relay:
#endif /* MYSQL_SERVER */
#endif /* HAVE_REPLICATION */
/* Check that values don't overflow on 32-bit systems. */
if (sizeof(ulint) == 4) {
if (innobase_buffer_pool_size > UINT_MAX32) {
......@@ -2003,6 +2105,77 @@ innobase_init(
goto error;
}
#ifdef HAVE_REPLICATION
#ifdef MYSQL_SERVER
if(innobase_overwrite_relay_log_info) {
/* If InnoDB progressed from relay-log.info, overwrite it */
if (fname[0] == '\0') {
fprintf(stderr,
"InnoDB: something wrong with relay-info.log. InnoDB will not overwrite it.\n");
} else if (0 != strcmp(fname, trx_sys_mysql_master_log_name)
|| pos != trx_sys_mysql_master_log_pos) {
/* Overwrite relay-log.info */
bzero((char*) &info_file, sizeof(info_file));
fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
int error = 0;
if (!access(fname,F_OK)) {
/* exist */
if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
error = 1;
} else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
WRITE_CACHE, 0L, 0, MYF(MY_WME))) {
error = 1;
}
if (error) {
if (info_fd >= 0)
my_close(info_fd, MYF(0));
goto skip_overwrite;
}
} else {
error = 1;
goto skip_overwrite;
}
char buff[FN_REFLEN*2+22*2+4], *pos;
my_b_seek(&info_file, 0L);
pos=strmov(buff, trx_sys_mysql_relay_log_name);
*pos++='\n';
pos=longlong2str(trx_sys_mysql_relay_log_pos, pos, 10);
*pos++='\n';
pos=strmov(pos, trx_sys_mysql_master_log_name);
*pos++='\n';
pos=longlong2str(trx_sys_mysql_master_log_pos, pos, 10);
*pos='\n';
if (my_b_write(&info_file, (uchar*) buff, (size_t) (pos-buff)+1))
error = 1;
if (flush_io_cache(&info_file))
error = 1;
end_io_cache(&info_file);
if (info_fd >= 0)
my_close(info_fd, MYF(0));
skip_overwrite:
if (error) {
fprintf(stderr,
"InnoDB: ERROR: error occured during overwriting relay-log.info.\n");
} else {
fprintf(stderr,
"InnoDB: relay-log.info was overwritten.\n");
}
} else {
fprintf(stderr,
"InnoDB: InnoDB and relay-log.info are synchronized. InnoDB will not overwrite it.\n");
}
}
#endif /* MYSQL_SERVER */
#endif /* HAVE_REPLICATION */
srv_extra_undoslots = (ibool) innobase_extra_undoslots;
/* -------------- Log files ---------------------------*/
......@@ -2270,6 +2443,26 @@ innobase_commit_low(
return;
}
#ifdef HAVE_REPLICATION
#ifdef MYSQL_SERVER
THD *thd=current_thd;
if (thd && thd->slave_thread) {
/* Update the replication position info inside InnoDB */
trx->mysql_master_log_file_name
= active_mi->rli.group_master_log_name;
trx->mysql_master_log_pos
= ((ib_int64_t)active_mi->rli.group_master_log_pos +
((ib_int64_t)active_mi->rli.future_event_relay_log_pos -
(ib_int64_t)active_mi->rli.group_relay_log_pos));
trx->mysql_relay_log_file_name
= active_mi->rli.group_relay_log_name;
trx->mysql_relay_log_pos
= (ib_int64_t)active_mi->rli.future_event_relay_log_pos;
}
#endif /* MYSQL_SERVER */
#endif /* HAVE_REPLICATION */
trx_commit_for_mysql(trx);
}
......@@ -9509,6 +9702,12 @@ static MYSQL_SYSVAR_BOOL(extra_undoslots, innobase_extra_undoslots,
"don't use the datafile for normal mysqld or ibbackup! ####",
NULL, NULL, FALSE);
static MYSQL_SYSVAR_BOOL(overwrite_relay_log_info, innobase_overwrite_relay_log_info,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"During InnoDB crash recovery on slave overwrite relay-log.info "
"to align master log file position if information in InnoDB and relay-log.info is different.",
NULL, NULL, FALSE);
static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Enable InnoDB doublewrite buffer (enabled by default). "
......@@ -9851,6 +10050,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(max_purge_lag),
MYSQL_SYSVAR(mirrored_log_groups),
MYSQL_SYSVAR(open_files),
MYSQL_SYSVAR(overwrite_relay_log_info),
MYSQL_SYSVAR(rollback_on_timeout),
MYSQL_SYSVAR(stats_on_metadata),
MYSQL_SYSVAR(stats_sample_pages),
......
......@@ -32,5 +32,6 @@ struct innodb_enhancement {
{"innodb_split_buf_pool_mutex","More fix of buffer_pool mutex","Spliting buf_pool_mutex and optimizing based on innodb_opt_lru_count","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_expand_undo_slots","expandable maximum number of undo slots","from 1024 (default) to about 4000","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_extra_rseg","allow to create extra rollback segments","When create new db, the new parameter allows to create more rollback segments","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_overwrite_relay_log_info","overwrite relay-log.info when slave recovery","Building as plugin, it is not used.","http://www.percona.com/docs/wiki/percona-xtradb:innodb_overwrite_relay_log_info"},
{NULL, NULL, NULL, NULL}
};
......@@ -49,6 +49,9 @@ or there was no master log position info inside InnoDB. */
extern char trx_sys_mysql_master_log_name[];
extern ib_int64_t trx_sys_mysql_master_log_pos;
extern char trx_sys_mysql_relay_log_name[];
extern ib_int64_t trx_sys_mysql_relay_log_pos;
/* If this MySQL server uses binary logging, after InnoDB has been inited
and if it has done a crash recovery, we store the binlog file name and position
here. If .._pos is -1, it means there was no binlog position info inside
......@@ -290,7 +293,7 @@ UNIV_INTERN
void
trx_sys_update_mysql_binlog_offset(
/*===============================*/
const char* file_name,/* in: MySQL log file name */
const char* file_name_in,/* in: MySQL log file name */
ib_int64_t offset, /* in: position in that log file */
ulint field, /* in: offset of the MySQL log info field in
the trx sys header */
......@@ -421,6 +424,7 @@ therefore 256; each slot is currently 8 bytes in size */
#define TRX_SYS_N_RSEGS 256
#define TRX_SYS_MYSQL_LOG_NAME_LEN 512
#define TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN 480 /* (500 - 12) is dead line. */
#define TRX_SYS_MYSQL_LOG_MAGIC_N 873422344
#if UNIV_PAGE_SIZE < 4096
......@@ -429,6 +433,7 @@ therefore 256; each slot is currently 8 bytes in size */
/* The offset of the MySQL replication info in the trx system header;
this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
#define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
#define TRX_SYS_MYSQL_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 1500)
/* The offset of the MySQL binlog offset info in the trx system header */
#define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)
......
......@@ -579,6 +579,21 @@ struct trx_struct{
ib_int64_t mysql_log_offset;/* if MySQL binlog is used, this field
contains the end offset of the binlog
entry */
const char* mysql_master_log_file_name;
/* if the database server is a MySQL
replication slave, we have here the
master binlog name up to which
replication has processed; otherwise
this is a pointer to a null
character */
ib_int64_t mysql_master_log_pos;
/* if the database server is a MySQL
replication slave, this is the
position in the log file up to which
replication has processed */
const char* mysql_relay_log_file_name;
ib_int64_t mysql_relay_log_pos;
os_thread_id_t mysql_thread_id;/* id of the MySQL thread associated
with this transaction object */
ulint mysql_process_no;/* since in Linux, 'top' reports
......
......@@ -69,9 +69,12 @@ file name and position here. We have successfully got the updates to InnoDB
up to this position. If .._pos is -1, it means no crash recovery was needed,
or there was no master log position info inside InnoDB. */
UNIV_INTERN char trx_sys_mysql_master_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN];
UNIV_INTERN char trx_sys_mysql_master_log_name[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
UNIV_INTERN ib_int64_t trx_sys_mysql_master_log_pos = -1;
UNIV_INTERN char trx_sys_mysql_relay_log_name[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
UNIV_INTERN ib_int64_t trx_sys_mysql_relay_log_pos = -1;
/* If this MySQL server uses binary logging, after InnoDB has been inited
and if it has done a crash recovery, we store the binlog file name and position
here. If .._pos is -1, it means there was no binlog position info inside
......@@ -661,19 +664,24 @@ UNIV_INTERN
void
trx_sys_update_mysql_binlog_offset(
/*===============================*/
const char* file_name,/* in: MySQL log file name */
const char* file_name_in,/* in: MySQL log file name */
ib_int64_t offset, /* in: position in that log file */
ulint field, /* in: offset of the MySQL log info field in
the trx sys header */
mtr_t* mtr) /* in: mtr */
{
trx_sysf_t* sys_header;
const char* file_name;
if (ut_strlen(file_name) >= TRX_SYS_MYSQL_LOG_NAME_LEN) {
if (ut_strlen(file_name) >= TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN) {
/* We cannot fit the name to the 512 bytes we have reserved */
/* -> To store relay log file information, file_name must fit to the 480 bytes */
return;
file_name = "";
}
else {
file_name = file_name_in;
}
sys_header = trx_sysf_get(mtr);
......@@ -834,13 +842,26 @@ trx_sys_print_mysql_master_log_pos(void)
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW),
sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
+ TRX_SYS_MYSQL_LOG_NAME);
fprintf(stderr,
"InnoDB: and relay log file\n"
"InnoDB: position %lu %lu, file name %s\n",
(ulong) mach_read_from_4(sys_header
+ TRX_SYS_MYSQL_RELAY_LOG_INFO
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
(ulong) mach_read_from_4(sys_header
+ TRX_SYS_MYSQL_RELAY_LOG_INFO
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW),
sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
+ TRX_SYS_MYSQL_LOG_NAME);
/* Copy the master log position info to global variables we can
use in ha_innobase.cc to initialize glob_mi to right values */
ut_memcpy(trx_sys_mysql_master_log_name,
sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
+ TRX_SYS_MYSQL_LOG_NAME,
TRX_SYS_MYSQL_LOG_NAME_LEN);
TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
trx_sys_mysql_master_log_pos
= (((ib_int64_t) mach_read_from_4(
......@@ -849,6 +870,19 @@ trx_sys_print_mysql_master_log_pos(void)
+ ((ib_int64_t) mach_read_from_4(
sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW));
ut_memcpy(trx_sys_mysql_relay_log_name,
sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
+ TRX_SYS_MYSQL_LOG_NAME,
TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
trx_sys_mysql_relay_log_pos
= (((ib_int64_t) mach_read_from_4(
sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
+ ((ib_int64_t) mach_read_from_4(
sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW));
mtr_commit(&mtr);
}
......
......@@ -127,6 +127,10 @@ trx_create(
trx->mysql_log_file_name = NULL;
trx->mysql_log_offset = 0;
trx->mysql_master_log_file_name = "";
trx->mysql_master_log_pos = 0;
trx->mysql_relay_log_file_name = "";
trx->mysql_relay_log_pos = 0;
mutex_create(&trx->undo_mutex, SYNC_TRX_UNDO);
......@@ -792,6 +796,19 @@ trx_commit_off_kernel(
trx->mysql_log_file_name = NULL;
}
if (trx->mysql_master_log_file_name[0] != '\0') {
/* This database server is a MySQL replication slave */
trx_sys_update_mysql_binlog_offset(
trx->mysql_relay_log_file_name,
trx->mysql_relay_log_pos,
TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
trx_sys_update_mysql_binlog_offset(
trx->mysql_master_log_file_name,
trx->mysql_master_log_pos,
TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
trx->mysql_master_log_file_name = "";
}
/* The following call commits the mini-transaction, making the
whole transaction committed in the file-based world, at this
log sequence number. The transaction becomes 'durable' when
......
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