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 --- a/storage/innobase/handler/ha_innodb.cc
9 +++ b/storage/innobase/handler/ha_innodb.cc
11 #pragma implementation // gcc: Class implementation
16 #include <sql_table.h> // explain_filename, nz2, EXPLAIN_PARTITIONS_AS_COMMENT,
17 // EXPLAIN_FILENAME_MAX_EXTRA_LENGTH
20 #include <mysql/psi/psi.h>
26 +// Defined in slave.cc
27 +int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
28 +int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
29 + const char *default_val);
30 +#endif /* MYSQL_SERVER */
32 /** @file ha_innodb.cc */
34 /* Include necessary InnoDB headers */
36 #include "ha_innodb.h"
40 +// Defined in trx0sys.c
41 +extern char trx_sys_mysql_master_log_name[];
42 +extern ib_int64_t trx_sys_mysql_master_log_pos;
43 +extern char trx_sys_mysql_relay_log_name[];
44 +extern ib_int64_t trx_sys_mysql_relay_log_pos;
45 +#endif /* MYSQL_SERVER */
47 # ifndef MYSQL_PLUGIN_IMPORT
48 # define MYSQL_PLUGIN_IMPORT /* nothing */
49 # endif /* MYSQL_PLUGIN_IMPORT */
51 static my_bool innobase_use_doublewrite = TRUE;
52 static my_bool innobase_use_checksums = TRUE;
53 static my_bool innobase_locks_unsafe_for_binlog = FALSE;
54 +static my_bool innobase_overwrite_relay_log_info = FALSE;
55 static my_bool innobase_rollback_on_timeout = FALSE;
56 static my_bool innobase_create_status_file = FALSE;
57 static my_bool innobase_stats_on_metadata = TRUE;
58 @@ -2282,6 +2302,89 @@
63 + innodb_overwrite_relay_log_info = FALSE;
66 +#ifdef HAVE_REPLICATION
68 + /* read master log position from relay-log.info if exists */
69 + char fname[FN_REFLEN+128];
76 + if(innobase_overwrite_relay_log_info) {
79 + "InnoDB: Warning: innodb_overwrite_relay_log_info is enabled."
80 + " Updates by other storage engines may not be synchronized.\n");
82 + bzero((char*) &info_file, sizeof(info_file));
83 + fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
87 + if (!access(fname,F_OK)) {
89 + if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
91 + } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
92 + READ_CACHE, 0L, 0, MYF(MY_WME))) {
99 + my_close(info_fd, MYF(0));
108 + if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") || /* dummy (it is relay-log) */
109 + init_intvar_from_file(&pos, &info_file, BIN_LOG_HEADER_SIZE)) {
110 + end_io_cache(&info_file);
112 + goto relay_info_error;
116 + "InnoDB: relay-log.info is detected.\n"
117 + "InnoDB: relay log: position %u, file name %s\n",
120 + strncpy(trx_sys_mysql_relay_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
121 + trx_sys_mysql_relay_log_pos = (ib_int64_t) pos;
123 + if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") ||
124 + init_intvar_from_file(&pos, &info_file, 0)) {
125 + end_io_cache(&info_file);
127 + goto relay_info_error;
131 + "InnoDB: master log: position %u, file name %s\n",
134 + strncpy(trx_sys_mysql_master_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
135 + trx_sys_mysql_master_log_pos = (ib_int64_t) pos;
137 + end_io_cache(&info_file);
139 + my_close(info_fd, MYF(0));
142 +#endif /* MYSQL_SERVER */
143 +#endif /* HAVE_REPLICATION */
145 /* Check that values don't overflow on 32-bit systems. */
146 if (sizeof(ulint) == 4) {
147 if (innobase_buffer_pool_size > UINT_MAX32) {
148 @@ -2580,6 +2683,76 @@
149 goto mem_free_and_error;
152 +#ifdef HAVE_REPLICATION
154 + if(innobase_overwrite_relay_log_info) {
155 + /* If InnoDB progressed from relay-log.info, overwrite it */
156 + if (fname[0] == '\0') {
158 + "InnoDB: Something is wrong with the file relay-info.log. InnoDB will not overwrite it.\n");
159 + } else if (0 != strcmp(fname, trx_sys_mysql_master_log_name)
160 + || pos != trx_sys_mysql_master_log_pos) {
161 + /* Overwrite relay-log.info */
162 + bzero((char*) &info_file, sizeof(info_file));
163 + fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
167 + if (!access(fname,F_OK)) {
169 + if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
171 + } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
172 + WRITE_CACHE, 0L, 0, MYF(MY_WME))) {
178 + my_close(info_fd, MYF(0));
179 + goto skip_overwrite;
183 + goto skip_overwrite;
186 + char buff[FN_REFLEN*2+22*2+4], *pos;
188 + my_b_seek(&info_file, 0L);
189 + pos=strmov(buff, trx_sys_mysql_relay_log_name);
191 + pos=longlong2str(trx_sys_mysql_relay_log_pos, pos, 10);
193 + pos=strmov(pos, trx_sys_mysql_master_log_name);
195 + pos=longlong2str(trx_sys_mysql_master_log_pos, pos, 10);
198 + if (my_b_write(&info_file, (uchar*) buff, (size_t) (pos-buff)+1))
200 + if (flush_io_cache(&info_file))
203 + end_io_cache(&info_file);
205 + my_close(info_fd, MYF(0));
209 + "InnoDB: ERROR: An error occurred while overwriting relay-log.info.\n");
212 + "InnoDB: The file relay-log.info was successfully overwritten.\n");
216 + "InnoDB: InnoDB and relay-log.info are synchronized. InnoDB will not overwrite it.\n");
219 +#endif /* MYSQL_SERVER */
220 +#endif /* HAVE_REPLICATION */
222 innobase_old_blocks_pct = buf_LRU_old_ratio_update(
223 innobase_old_blocks_pct, TRUE);
225 @@ -2693,6 +2866,25 @@
226 trx_t* trx) /*!< in: transaction handle */
228 if (trx_is_started(trx)) {
229 +#ifdef HAVE_REPLICATION
231 + THD *thd=current_thd;
233 + if (thd && thd->slave_thread) {
234 + /* Update the replication position info inside InnoDB */
235 + trx->mysql_master_log_file_name
236 + = active_mi->rli.group_master_log_name;
237 + trx->mysql_master_log_pos
238 + = ((ib_int64_t)active_mi->rli.group_master_log_pos +
239 + ((ib_int64_t)active_mi->rli.future_event_relay_log_pos -
240 + (ib_int64_t)active_mi->rli.group_relay_log_pos));
241 + trx->mysql_relay_log_file_name
242 + = active_mi->rli.group_relay_log_name;
243 + trx->mysql_relay_log_pos
244 + = (ib_int64_t)active_mi->rli.future_event_relay_log_pos;
246 +#endif /* MYSQL_SERVER */
247 +#endif /* HAVE_REPLICATION */
249 trx_commit_for_mysql(trx);
251 @@ -11130,6 +11322,12 @@
252 "The common part for InnoDB table spaces.",
255 +static MYSQL_SYSVAR_BOOL(recovery_update_relay_log, innobase_overwrite_relay_log_info,
256 + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
257 + "During InnoDB crash recovery on slave overwrite relay-log.info "
258 + "to align master log file position if information in InnoDB and relay-log.info is different.",
259 + NULL, NULL, FALSE);
261 static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
262 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
263 "Enable InnoDB doublewrite buffer (enabled by default). "
264 @@ -11647,6 +11845,7 @@
265 MYSQL_SYSVAR(old_blocks_pct),
266 MYSQL_SYSVAR(old_blocks_time),
267 MYSQL_SYSVAR(open_files),
268 + MYSQL_SYSVAR(recovery_update_relay_log),
269 MYSQL_SYSVAR(rollback_on_timeout),
270 MYSQL_SYSVAR(stats_on_metadata),
271 MYSQL_SYSVAR(stats_sample_pages),
272 --- a/storage/innobase/include/trx0sys.h
273 +++ b/storage/innobase/include/trx0sys.h
275 extern ib_int64_t trx_sys_mysql_master_log_pos;
278 +extern char trx_sys_mysql_relay_log_name[];
279 +extern ib_int64_t trx_sys_mysql_relay_log_pos;
281 /** If this MySQL server uses binary logging, after InnoDB has been inited
282 and if it has done a crash recovery, we store the binlog file name and position
286 trx_sys_update_mysql_binlog_offset(
287 /*===============================*/
288 - const char* file_name,/*!< in: MySQL log file name */
289 + trx_sysf_t* sys_header,
290 + const char* file_name_in,/*!< in: MySQL log file name */
291 ib_int64_t offset, /*!< in: position in that log file */
292 ulint field, /*!< in: offset of the MySQL log info field in
293 the trx sys header */
295 @see trx_sys_mysql_master_log_name
296 @see trx_sys_mysql_bin_log_name */
297 #define TRX_SYS_MYSQL_LOG_NAME_LEN 512
298 +#define TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN 480 /* (500 - 12) is dead line. */
299 /** Contents of TRX_SYS_MYSQL_LOG_MAGIC_N_FLD */
300 #define TRX_SYS_MYSQL_LOG_MAGIC_N 873422344
303 /** The offset of the MySQL replication info in the trx system header;
304 this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
305 #define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
306 +#define TRX_SYS_MYSQL_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 1500)
308 /** The offset of the MySQL binlog offset info in the trx system header */
309 #define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)
310 --- a/storage/innobase/include/trx0trx.h
311 +++ b/storage/innobase/include/trx0trx.h
313 ib_int64_t mysql_log_offset;/* if MySQL binlog is used, this field
314 contains the end offset of the binlog
316 + const char* mysql_master_log_file_name;
317 + /* if the database server is a MySQL
318 + replication slave, we have here the
319 + master binlog name up to which
320 + replication has processed; otherwise
321 + this is a pointer to a null
323 + ib_int64_t mysql_master_log_pos;
324 + /* if the database server is a MySQL
325 + replication slave, this is the
326 + position in the log file up to which
327 + replication has processed */
328 + const char* mysql_relay_log_file_name;
329 + ib_int64_t mysql_relay_log_pos;
330 /*------------------------------*/
331 ulint n_mysql_tables_in_use; /* number of Innobase tables
332 used in the processing of the current
333 --- a/storage/innobase/trx/trx0sys.c
334 +++ b/storage/innobase/trx/trx0sys.c
336 file name and position here. */
338 /** Master binlog file name */
339 -UNIV_INTERN char trx_sys_mysql_master_log_name[TRX_SYS_MYSQL_LOG_NAME_LEN];
340 +UNIV_INTERN char trx_sys_mysql_master_log_name[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
341 /** Master binlog file position. We have successfully got the updates
342 up to this position. -1 means that no crash recovery was needed, or
343 there was no master log position info inside InnoDB.*/
344 UNIV_INTERN ib_int64_t trx_sys_mysql_master_log_pos = -1;
347 +UNIV_INTERN char trx_sys_mysql_relay_log_name[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
348 +UNIV_INTERN ib_int64_t trx_sys_mysql_relay_log_pos = -1;
350 /** If this MySQL server uses binary logging, after InnoDB has been inited
351 and if it has done a crash recovery, we store the binlog file name and position
353 @@ -684,23 +687,25 @@
355 trx_sys_update_mysql_binlog_offset(
356 /*===============================*/
357 - const char* file_name,/*!< in: MySQL log file name */
358 + trx_sysf_t* sys_header,
359 + const char* file_name_in,/*!< in: MySQL log file name */
360 ib_int64_t offset, /*!< in: position in that log file */
361 ulint field, /*!< in: offset of the MySQL log info field in
362 the trx sys header */
363 mtr_t* mtr) /*!< in: mtr */
365 - trx_sysf_t* sys_header;
366 + const char* file_name;
368 - if (ut_strlen(file_name) >= TRX_SYS_MYSQL_LOG_NAME_LEN) {
369 + if (ut_strlen(file_name_in) >= TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN) {
371 /* We cannot fit the name to the 512 bytes we have reserved */
372 + /* -> To store relay log file information, file_name must fit to the 480 bytes */
377 + file_name = file_name_in;
380 - sys_header = trx_sysf_get(mtr);
382 if (mach_read_from_4(sys_header + field
383 + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
384 != TRX_SYS_MYSQL_LOG_MAGIC_N) {
385 @@ -822,13 +827,26 @@
386 + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
387 sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
388 + TRX_SYS_MYSQL_LOG_NAME);
391 + "InnoDB: and relay log file\n"
392 + "InnoDB: position %lu %lu, file name %s\n",
393 + (ulong) mach_read_from_4(sys_header
394 + + TRX_SYS_MYSQL_RELAY_LOG_INFO
395 + + TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
396 + (ulong) mach_read_from_4(sys_header
397 + + TRX_SYS_MYSQL_RELAY_LOG_INFO
398 + + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
399 + sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
400 + + TRX_SYS_MYSQL_LOG_NAME);
402 /* Copy the master log position info to global variables we can
403 use in ha_innobase.cc to initialize glob_mi to right values */
405 ut_memcpy(trx_sys_mysql_master_log_name,
406 sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
407 + TRX_SYS_MYSQL_LOG_NAME,
408 - TRX_SYS_MYSQL_LOG_NAME_LEN);
409 + TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
411 trx_sys_mysql_master_log_pos
412 = (((ib_int64_t) mach_read_from_4(
414 + ((ib_int64_t) mach_read_from_4(
415 sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
416 + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
418 + ut_memcpy(trx_sys_mysql_relay_log_name,
419 + sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
420 + + TRX_SYS_MYSQL_LOG_NAME,
421 + TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
423 + trx_sys_mysql_relay_log_pos
424 + = (((ib_int64_t) mach_read_from_4(
425 + sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
426 + + TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
427 + + ((ib_int64_t) mach_read_from_4(
428 + sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
429 + + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
433 --- a/storage/innobase/trx/trx0trx.c
434 +++ b/storage/innobase/trx/trx0trx.c
437 trx->mysql_log_file_name = NULL;
438 trx->mysql_log_offset = 0;
439 + trx->mysql_master_log_file_name = "";
440 + trx->mysql_master_log_pos = 0;
441 + trx->mysql_relay_log_file_name = "";
442 + trx->mysql_relay_log_pos = 0;
444 mutex_create(trx_undo_mutex_key, &trx->undo_mutex, SYNC_TRX_UNDO);
450 + trx_sysf_t* sys_header = NULL;
452 ut_ad(!mutex_own(&kernel_mutex));
456 if (trx->mysql_log_file_name
457 && trx->mysql_log_file_name[0] != '\0') {
459 + sys_header = trx_sysf_get(&mtr);
462 trx_sys_update_mysql_binlog_offset(
464 trx->mysql_log_file_name,
465 trx->mysql_log_offset,
466 TRX_SYS_MYSQL_LOG_INFO, &mtr);
468 trx->mysql_log_file_name = NULL;
471 + if (trx->mysql_master_log_file_name[0] != '\0') {
472 + /* This database server is a MySQL replication slave */
474 + sys_header = trx_sysf_get(&mtr);
477 + trx_sys_update_mysql_binlog_offset(
479 + trx->mysql_relay_log_file_name,
480 + trx->mysql_relay_log_pos,
481 + TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
483 + trx_sys_update_mysql_binlog_offset(
485 + trx->mysql_master_log_file_name,
486 + trx->mysql_master_log_pos,
487 + TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
489 + trx->mysql_master_log_file_name = "";
492 /* The following call commits the mini-transaction, making the
493 whole transaction committed in the file-based world, at this
494 log sequence number. The transaction becomes 'durable' when