1 # name : innodb_overwrite_relay_log_info.patch
2 # introduced : 11 or before
3 # maintainer : Yasufumi
6 # Any small change to this file in the main branch
7 # should be done or reviewed by the maintainer!
8 diff -ruN a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
9 --- a/storage/innobase/handler/ha_innodb.cc 2010-12-03 15:37:45.516105468 +0900
10 +++ b/storage/innobase/handler/ha_innodb.cc 2010-12-03 15:38:20.318952987 +0900
12 #pragma implementation // gcc: Class implementation
17 #include <sql_table.h> // explain_filename, nz2, EXPLAIN_PARTITIONS_AS_COMMENT,
18 // EXPLAIN_FILENAME_MAX_EXTRA_LENGTH
21 #include <mysql/psi/psi.h>
27 +// Defined in slave.cc
28 +int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
29 +int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
30 + const char *default_val);
31 +#endif /* MYSQL_SERVER */
33 /** @file ha_innodb.cc */
35 /* Include necessary InnoDB headers */
37 #include "ha_innodb.h"
41 +// Defined in trx0sys.c
42 +extern char trx_sys_mysql_master_log_name[];
43 +extern ib_int64_t trx_sys_mysql_master_log_pos;
44 +extern char trx_sys_mysql_relay_log_name[];
45 +extern ib_int64_t trx_sys_mysql_relay_log_pos;
46 +#endif /* MYSQL_SERVER */
48 # ifndef MYSQL_PLUGIN_IMPORT
49 # define MYSQL_PLUGIN_IMPORT /* nothing */
50 # endif /* MYSQL_PLUGIN_IMPORT */
52 static my_bool innobase_use_doublewrite = TRUE;
53 static my_bool innobase_use_checksums = TRUE;
54 static my_bool innobase_locks_unsafe_for_binlog = FALSE;
55 +static my_bool innobase_overwrite_relay_log_info = FALSE;
56 static my_bool innobase_rollback_on_timeout = FALSE;
57 static my_bool innobase_create_status_file = FALSE;
58 static my_bool innobase_stats_on_metadata = TRUE;
59 @@ -2248,6 +2268,89 @@
64 + innodb_overwrite_relay_log_info = FALSE;
67 +#ifdef HAVE_REPLICATION
69 + /* read master log position from relay-log.info if exists */
70 + char fname[FN_REFLEN+128];
77 + if(innobase_overwrite_relay_log_info) {
80 + "InnoDB: Warning: innodb_overwrite_relay_log_info is enabled."
81 + " Updates by other storage engines may not be synchronized.\n");
83 + bzero((char*) &info_file, sizeof(info_file));
84 + fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
88 + if (!access(fname,F_OK)) {
90 + if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
92 + } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
93 + READ_CACHE, 0L, 0, MYF(MY_WME))) {
100 + my_close(info_fd, MYF(0));
109 + if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") || /* dummy (it is relay-log) */
110 + init_intvar_from_file(&pos, &info_file, BIN_LOG_HEADER_SIZE)) {
111 + end_io_cache(&info_file);
113 + goto relay_info_error;
117 + "InnoDB: relay-log.info is detected.\n"
118 + "InnoDB: relay log: position %u, file name %s\n",
121 + strncpy(trx_sys_mysql_relay_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
122 + trx_sys_mysql_relay_log_pos = (ib_int64_t) pos;
124 + if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") ||
125 + init_intvar_from_file(&pos, &info_file, 0)) {
126 + end_io_cache(&info_file);
128 + goto relay_info_error;
132 + "InnoDB: master log: position %u, file name %s\n",
135 + strncpy(trx_sys_mysql_master_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
136 + trx_sys_mysql_master_log_pos = (ib_int64_t) pos;
138 + end_io_cache(&info_file);
140 + my_close(info_fd, MYF(0));
143 +#endif /* MYSQL_SERVER */
144 +#endif /* HAVE_REPLICATION */
146 /* Check that values don't overflow on 32-bit systems. */
147 if (sizeof(ulint) == 4) {
148 if (innobase_buffer_pool_size > UINT_MAX32) {
149 @@ -2546,6 +2649,76 @@
150 goto mem_free_and_error;
153 +#ifdef HAVE_REPLICATION
155 + if(innobase_overwrite_relay_log_info) {
156 + /* If InnoDB progressed from relay-log.info, overwrite it */
157 + if (fname[0] == '\0') {
159 + "InnoDB: Something is wrong with the file relay-info.log. InnoDB will not overwrite it.\n");
160 + } else if (0 != strcmp(fname, trx_sys_mysql_master_log_name)
161 + || pos != trx_sys_mysql_master_log_pos) {
162 + /* Overwrite relay-log.info */
163 + bzero((char*) &info_file, sizeof(info_file));
164 + fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
168 + if (!access(fname,F_OK)) {
170 + if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
172 + } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
173 + WRITE_CACHE, 0L, 0, MYF(MY_WME))) {
179 + my_close(info_fd, MYF(0));
180 + goto skip_overwrite;
184 + goto skip_overwrite;
187 + char buff[FN_REFLEN*2+22*2+4], *pos;
189 + my_b_seek(&info_file, 0L);
190 + pos=strmov(buff, trx_sys_mysql_relay_log_name);
192 + pos=longlong2str(trx_sys_mysql_relay_log_pos, pos, 10);
194 + pos=strmov(pos, trx_sys_mysql_master_log_name);
196 + pos=longlong2str(trx_sys_mysql_master_log_pos, pos, 10);
199 + if (my_b_write(&info_file, (uchar*) buff, (size_t) (pos-buff)+1))
201 + if (flush_io_cache(&info_file))
204 + end_io_cache(&info_file);
206 + my_close(info_fd, MYF(0));
210 + "InnoDB: ERROR: An error occurred while overwriting relay-log.info.\n");
213 + "InnoDB: The file relay-log.info was successfully overwritten.\n");
217 + "InnoDB: InnoDB and relay-log.info are synchronized. InnoDB will not overwrite it.\n");
220 +#endif /* MYSQL_SERVER */
221 +#endif /* HAVE_REPLICATION */
223 innobase_old_blocks_pct = buf_LRU_old_ratio_update(
224 innobase_old_blocks_pct, TRUE);
226 @@ -2658,6 +2831,25 @@
227 trx_t* trx) /*!< in: transaction handle */
229 if (trx_is_started(trx)) {
230 +#ifdef HAVE_REPLICATION
232 + THD *thd=current_thd;
234 + if (thd && thd->slave_thread) {
235 + /* Update the replication position info inside InnoDB */
236 + trx->mysql_master_log_file_name
237 + = active_mi->rli.group_master_log_name;
238 + trx->mysql_master_log_pos
239 + = ((ib_int64_t)active_mi->rli.group_master_log_pos +
240 + ((ib_int64_t)active_mi->rli.future_event_relay_log_pos -
241 + (ib_int64_t)active_mi->rli.group_relay_log_pos));
242 + trx->mysql_relay_log_file_name
243 + = active_mi->rli.group_relay_log_name;
244 + trx->mysql_relay_log_pos
245 + = (ib_int64_t)active_mi->rli.future_event_relay_log_pos;
247 +#endif /* MYSQL_SERVER */
248 +#endif /* HAVE_REPLICATION */
250 trx_commit_for_mysql(trx);
252 @@ -11014,6 +11206,12 @@
253 "The common part for InnoDB table spaces.",
256 +static MYSQL_SYSVAR_BOOL(recovery_update_relay_log, innobase_overwrite_relay_log_info,
257 + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
258 + "During InnoDB crash recovery on slave overwrite relay-log.info "
259 + "to align master log file position if information in InnoDB and relay-log.info is different.",
260 + NULL, NULL, FALSE);
262 static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
263 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
264 "Enable InnoDB doublewrite buffer (enabled by default). "
265 @@ -11474,6 +11672,7 @@
266 MYSQL_SYSVAR(old_blocks_pct),
267 MYSQL_SYSVAR(old_blocks_time),
268 MYSQL_SYSVAR(open_files),
269 + MYSQL_SYSVAR(recovery_update_relay_log),
270 MYSQL_SYSVAR(rollback_on_timeout),
271 MYSQL_SYSVAR(stats_on_metadata),
272 MYSQL_SYSVAR(stats_sample_pages),
273 diff -ruN a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h
274 --- a/storage/innobase/include/trx0sys.h 2010-11-03 07:01:13.000000000 +0900
275 +++ b/storage/innobase/include/trx0sys.h 2010-12-03 15:38:20.321953297 +0900
277 extern ib_int64_t trx_sys_mysql_master_log_pos;
280 +extern char trx_sys_mysql_relay_log_name[];
281 +extern ib_int64_t trx_sys_mysql_relay_log_pos;
283 /** If this MySQL server uses binary logging, after InnoDB has been inited
284 and if it has done a crash recovery, we store the binlog file name and position
288 trx_sys_update_mysql_binlog_offset(
289 /*===============================*/
290 - const char* file_name,/*!< in: MySQL log file name */
291 + trx_sysf_t* sys_header,
292 + const char* file_name_in,/*!< in: MySQL log file name */
293 ib_int64_t offset, /*!< in: position in that log file */
294 ulint field, /*!< in: offset of the MySQL log info field in
295 the trx sys header */
297 @see trx_sys_mysql_master_log_name
298 @see trx_sys_mysql_bin_log_name */
299 #define TRX_SYS_MYSQL_LOG_NAME_LEN 512
300 +#define TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN 480 /* (500 - 12) is dead line. */
301 /** Contents of TRX_SYS_MYSQL_LOG_MAGIC_N_FLD */
302 #define TRX_SYS_MYSQL_LOG_MAGIC_N 873422344
305 /** The offset of the MySQL replication info in the trx system header;
306 this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
307 #define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
308 +#define TRX_SYS_MYSQL_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 1500)
310 /** The offset of the MySQL binlog offset info in the trx system header */
311 #define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)
312 diff -ruN a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
313 --- a/storage/innobase/include/trx0trx.h 2010-12-03 15:18:48.894955550 +0900
314 +++ b/storage/innobase/include/trx0trx.h 2010-12-03 15:38:20.323953416 +0900
316 ib_int64_t mysql_log_offset;/* if MySQL binlog is used, this field
317 contains the end offset of the binlog
319 + const char* mysql_master_log_file_name;
320 + /* if the database server is a MySQL
321 + replication slave, we have here the
322 + master binlog name up to which
323 + replication has processed; otherwise
324 + this is a pointer to a null
326 + ib_int64_t mysql_master_log_pos;
327 + /* if the database server is a MySQL
328 + replication slave, this is the
329 + position in the log file up to which
330 + replication has processed */
331 + const char* mysql_relay_log_file_name;
332 + ib_int64_t mysql_relay_log_pos;
333 /*------------------------------*/
334 ulint n_mysql_tables_in_use; /* number of Innobase tables
335 used in the processing of the current
336 diff -ruN a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c
337 --- a/storage/innobase/trx/trx0sys.c 2010-11-03 07:01:13.000000000 +0900
338 +++ b/storage/innobase/trx/trx0sys.c 2010-12-03 15:38:20.325956917 +0900
340 file name and position here. */
342 /** Master binlog file name */
343 -UNIV_INTERN char trx_sys_mysql_master_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN];
344 +UNIV_INTERN char trx_sys_mysql_master_log_name[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
345 /** Master binlog file position. We have successfully got the updates
346 up to this position. -1 means that no crash recovery was needed, or
347 there was no master log position info inside InnoDB.*/
348 UNIV_INTERN ib_int64_t trx_sys_mysql_master_log_pos = -1;
351 +UNIV_INTERN char trx_sys_mysql_relay_log_name[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
352 +UNIV_INTERN ib_int64_t trx_sys_mysql_relay_log_pos = -1;
354 /** If this MySQL server uses binary logging, after InnoDB has been inited
355 and if it has done a crash recovery, we store the binlog file name and position
357 @@ -684,23 +687,25 @@
359 trx_sys_update_mysql_binlog_offset(
360 /*===============================*/
361 - const char* file_name,/*!< in: MySQL log file name */
362 + trx_sysf_t* sys_header,
363 + const char* file_name_in,/*!< in: MySQL log file name */
364 ib_int64_t offset, /*!< in: position in that log file */
365 ulint field, /*!< in: offset of the MySQL log info field in
366 the trx sys header */
367 mtr_t* mtr) /*!< in: mtr */
369 - trx_sysf_t* sys_header;
370 + const char* file_name;
372 - if (ut_strlen(file_name) >= TRX_SYS_MYSQL_LOG_NAME_LEN) {
373 + if (ut_strlen(file_name_in) >= TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN) {
375 /* We cannot fit the name to the 512 bytes we have reserved */
376 + /* -> To store relay log file information, file_name must fit to the 480 bytes */
381 + file_name = file_name_in;
384 - sys_header = trx_sysf_get(mtr);
386 if (mach_read_from_4(sys_header + field
387 + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
388 != TRX_SYS_MYSQL_LOG_MAGIC_N) {
389 @@ -822,13 +827,26 @@
390 + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
391 sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
392 + TRX_SYS_MYSQL_LOG_NAME);
395 + "InnoDB: and relay log file\n"
396 + "InnoDB: position %lu %lu, file name %s\n",
397 + (ulong) mach_read_from_4(sys_header
398 + + TRX_SYS_MYSQL_RELAY_LOG_INFO
399 + + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
400 + (ulong) mach_read_from_4(sys_header
401 + + TRX_SYS_MYSQL_RELAY_LOG_INFO
402 + + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
403 + sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
404 + + TRX_SYS_MYSQL_LOG_NAME);
406 /* Copy the master log position info to global variables we can
407 use in ha_innobase.cc to initialize glob_mi to right values */
409 ut_memcpy(trx_sys_mysql_master_log_name,
410 sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
411 + TRX_SYS_MYSQL_LOG_NAME,
412 - TRX_SYS_MYSQL_LOG_NAME_LEN);
413 + TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
415 trx_sys_mysql_master_log_pos
416 = (((ib_int64_t) mach_read_from_4(
418 + ((ib_int64_t) mach_read_from_4(
419 sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
420 + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
422 + ut_memcpy(trx_sys_mysql_relay_log_name,
423 + sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
424 + + TRX_SYS_MYSQL_LOG_NAME,
425 + TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
427 + trx_sys_mysql_relay_log_pos
428 + = (((ib_int64_t) mach_read_from_4(
429 + sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
430 + + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
431 + + ((ib_int64_t) mach_read_from_4(
432 + sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
433 + + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
437 diff -ruN a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c
438 --- a/storage/innobase/trx/trx0trx.c 2010-12-03 15:37:45.549028990 +0900
439 +++ b/storage/innobase/trx/trx0trx.c 2010-12-03 15:38:20.328957217 +0900
442 trx->mysql_log_file_name = NULL;
443 trx->mysql_log_offset = 0;
444 + trx->mysql_master_log_file_name = "";
445 + trx->mysql_master_log_pos = 0;
446 + trx->mysql_relay_log_file_name = "";
447 + trx->mysql_relay_log_pos = 0;
449 mutex_create(trx_undo_mutex_key, &trx->undo_mutex, SYNC_TRX_UNDO);
455 + trx_sysf_t* sys_header = NULL;
457 ut_ad(!mutex_own(&kernel_mutex));
461 if (trx->mysql_log_file_name
462 && trx->mysql_log_file_name[0] != '\0') {
464 + sys_header = trx_sysf_get(&mtr);
467 trx_sys_update_mysql_binlog_offset(
469 trx->mysql_log_file_name,
470 trx->mysql_log_offset,
471 TRX_SYS_MYSQL_LOG_INFO, &mtr);
473 trx->mysql_log_file_name = NULL;
476 + if (trx->mysql_master_log_file_name[0] != '\0') {
477 + /* This database server is a MySQL replication slave */
479 + sys_header = trx_sysf_get(&mtr);
482 + trx_sys_update_mysql_binlog_offset(
484 + trx->mysql_relay_log_file_name,
485 + trx->mysql_relay_log_pos,
486 + TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
488 + trx_sys_update_mysql_binlog_offset(
490 + trx->mysql_master_log_file_name,
491 + trx->mysql_master_log_pos,
492 + TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
494 + trx->mysql_master_log_file_name = "";
497 /* The following call commits the mini-transaction, making the
498 whole transaction committed in the file-based world, at this
499 log sequence number. The transaction becomes 'durable' when