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/innodb_plugin/handler/ha_innodb.cc
9 +++ b/storage/innodb_plugin/handler/ha_innodb.cc
11 #pragma implementation // gcc: Class implementation
16 #include <mysql_priv.h>
20 +// Defined in slave.cc
21 +int init_intvar_from_file(int* var, IO_CACHE* f, int default_val);
22 +int init_strvar_from_file(char *var, int max_size, IO_CACHE *f,
23 + const char *default_val);
24 +#endif /* MYSQL_SERVER */
27 #include <mysys_err.h>
29 #include "ha_innodb.h"
33 +// Defined in trx0sys.c
34 +extern char trx_sys_mysql_master_log_name[];
35 +extern ib_int64_t trx_sys_mysql_master_log_pos;
36 +extern char trx_sys_mysql_relay_log_name[];
37 +extern ib_int64_t trx_sys_mysql_relay_log_pos;
38 +#endif /* MYSQL_SERVER */
41 # ifndef MYSQL_PLUGIN_IMPORT
42 # define MYSQL_PLUGIN_IMPORT /* nothing */
44 static my_bool innobase_use_checksums = TRUE;
45 static my_bool innobase_extra_undoslots = FALSE;
46 static my_bool innobase_locks_unsafe_for_binlog = FALSE;
47 +static my_bool innobase_overwrite_relay_log_info = FALSE;
48 static my_bool innobase_rollback_on_timeout = FALSE;
49 static my_bool innobase_create_status_file = FALSE;
50 static my_bool innobase_stats_on_metadata = TRUE;
51 @@ -2042,6 +2061,89 @@
53 #endif /* UNIV_DEBUG */
56 + innodb_overwrite_relay_log_info = FALSE;
59 +#ifdef HAVE_REPLICATION
61 + /* read master log position from relay-log.info if exists */
62 + char fname[FN_REFLEN+128];
69 + if(innobase_overwrite_relay_log_info) {
72 + "InnoDB: Warning: innodb_overwrite_relay_log_info is enabled."
73 + " Updates in other storage engines may have problem with consistency.\n");
75 + bzero((char*) &info_file, sizeof(info_file));
76 + fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
80 + if (!access(fname,F_OK)) {
82 + if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
84 + } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
85 + READ_CACHE, 0L, 0, MYF(MY_WME))) {
92 + my_close(info_fd, MYF(0));
101 + if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") || /* dummy (it is relay-log) */
102 + init_intvar_from_file(&pos, &info_file, BIN_LOG_HEADER_SIZE)) {
103 + end_io_cache(&info_file);
105 + goto relay_info_error;
109 + "InnoDB: relay-log.info is detected.\n"
110 + "InnoDB: relay log: position %u, file name %s\n",
113 + strncpy(trx_sys_mysql_relay_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
114 + trx_sys_mysql_relay_log_pos = (ib_int64_t) pos;
116 + if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") ||
117 + init_intvar_from_file(&pos, &info_file, 0)) {
118 + end_io_cache(&info_file);
120 + goto relay_info_error;
124 + "InnoDB: master log: position %u, file name %s\n",
127 + strncpy(trx_sys_mysql_master_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
128 + trx_sys_mysql_master_log_pos = (ib_int64_t) pos;
130 + end_io_cache(&info_file);
132 + my_close(info_fd, MYF(0));
135 +#endif /* MYSQL_SERVER */
136 +#endif /* HAVE_REPLICATION */
138 /* Check that values don't overflow on 32-bit systems. */
139 if (sizeof(ulint) == 4) {
140 if (innobase_buffer_pool_size > UINT_MAX32) {
141 @@ -2310,6 +2412,76 @@
142 goto mem_free_and_error;
145 +#ifdef HAVE_REPLICATION
147 + if(innobase_overwrite_relay_log_info) {
148 + /* If InnoDB progressed from relay-log.info, overwrite it */
149 + if (fname[0] == '\0') {
151 + "InnoDB: something wrong with relay-info.log. InnoDB will not overwrite it.\n");
152 + } else if (0 != strcmp(fname, trx_sys_mysql_master_log_name)
153 + || pos != trx_sys_mysql_master_log_pos) {
154 + /* Overwrite relay-log.info */
155 + bzero((char*) &info_file, sizeof(info_file));
156 + fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
160 + if (!access(fname,F_OK)) {
162 + if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
164 + } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
165 + WRITE_CACHE, 0L, 0, MYF(MY_WME))) {
171 + my_close(info_fd, MYF(0));
172 + goto skip_overwrite;
176 + goto skip_overwrite;
179 + char buff[FN_REFLEN*2+22*2+4], *pos;
181 + my_b_seek(&info_file, 0L);
182 + pos=strmov(buff, trx_sys_mysql_relay_log_name);
184 + pos=longlong2str(trx_sys_mysql_relay_log_pos, pos, 10);
186 + pos=strmov(pos, trx_sys_mysql_master_log_name);
188 + pos=longlong2str(trx_sys_mysql_master_log_pos, pos, 10);
191 + if (my_b_write(&info_file, (uchar*) buff, (size_t) (pos-buff)+1))
193 + if (flush_io_cache(&info_file))
196 + end_io_cache(&info_file);
198 + my_close(info_fd, MYF(0));
202 + "InnoDB: ERROR: error occured during overwriting relay-log.info.\n");
205 + "InnoDB: relay-log.info was overwritten.\n");
209 + "InnoDB: InnoDB and relay-log.info are synchronized. InnoDB will not overwrite it.\n");
212 +#endif /* MYSQL_SERVER */
213 +#endif /* HAVE_REPLICATION */
215 innobase_open_tables = hash_create(200);
216 pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
217 pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
218 @@ -2424,6 +2596,26 @@
222 +#ifdef HAVE_REPLICATION
224 + THD *thd=current_thd;
226 + if (thd && thd->slave_thread) {
227 + /* Update the replication position info inside InnoDB */
228 + trx->mysql_master_log_file_name
229 + = active_mi->rli.group_master_log_name;
230 + trx->mysql_master_log_pos
231 + = ((ib_int64_t)active_mi->rli.group_master_log_pos +
232 + ((ib_int64_t)active_mi->rli.future_event_relay_log_pos -
233 + (ib_int64_t)active_mi->rli.group_relay_log_pos));
234 + trx->mysql_relay_log_file_name
235 + = active_mi->rli.group_relay_log_name;
236 + trx->mysql_relay_log_pos
237 + = (ib_int64_t)active_mi->rli.future_event_relay_log_pos;
239 +#endif /* MYSQL_SERVER */
240 +#endif /* HAVE_REPLICATION */
242 trx_commit_for_mysql(trx);
245 @@ -10781,6 +10973,12 @@
246 "don't use the datafile for normal mysqld or ibbackup! ####",
249 +static MYSQL_SYSVAR_BOOL(overwrite_relay_log_info, innobase_overwrite_relay_log_info,
250 + PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
251 + "During InnoDB crash recovery on slave overwrite relay-log.info "
252 + "to align master log file position if information in InnoDB and relay-log.info is different.",
253 + NULL, NULL, FALSE);
255 static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
256 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
257 "Enable InnoDB doublewrite buffer (enabled by default). "
258 @@ -11211,6 +11409,7 @@
259 MYSQL_SYSVAR(old_blocks_pct),
260 MYSQL_SYSVAR(old_blocks_time),
261 MYSQL_SYSVAR(open_files),
262 + MYSQL_SYSVAR(overwrite_relay_log_info),
263 MYSQL_SYSVAR(rollback_on_timeout),
264 MYSQL_SYSVAR(stats_on_metadata),
265 MYSQL_SYSVAR(stats_sample_pages),
266 --- a/storage/innodb_plugin/handler/innodb_patch_info.h
267 +++ b/storage/innodb_plugin/handler/innodb_patch_info.h
269 {"innodb_buffer_pool_pages","Information of buffer pool content","","http://www.percona.com/docs/wiki/percona-xtradb"},
270 {"innodb_expand_undo_slots","expandable maximum number of undo slots","from 1024 (default) to about 4000","http://www.percona.com/docs/wiki/percona-xtradb"},
271 {"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"},
272 +{"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"},
273 {NULL, NULL, NULL, NULL}
275 --- a/storage/innodb_plugin/include/trx0sys.h
276 +++ b/storage/innodb_plugin/include/trx0sys.h
278 extern ib_int64_t trx_sys_mysql_master_log_pos;
281 +extern char trx_sys_mysql_relay_log_name[];
282 +extern ib_int64_t trx_sys_mysql_relay_log_pos;
284 /** If this MySQL server uses binary logging, after InnoDB has been inited
285 and if it has done a crash recovery, we store the binlog file name and position
289 trx_sys_update_mysql_binlog_offset(
290 /*===============================*/
291 - const char* file_name,/*!< in: MySQL log file name */
292 + trx_sysf_t* sys_header,
293 + const char* file_name_in,/*!< in: MySQL log file name */
294 ib_int64_t offset, /*!< in: position in that log file */
295 ulint field, /*!< in: offset of the MySQL log info field in
296 the trx sys header */
298 @see trx_sys_mysql_master_log_name
299 @see trx_sys_mysql_bin_log_name */
300 #define TRX_SYS_MYSQL_LOG_NAME_LEN 512
301 +#define TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN 480 /* (500 - 12) is dead line. */
302 /** Contents of TRX_SYS_MYSQL_LOG_MAGIC_N_FLD */
303 #define TRX_SYS_MYSQL_LOG_MAGIC_N 873422344
306 /** The offset of the MySQL replication info in the trx system header;
307 this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
308 #define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
309 +#define TRX_SYS_MYSQL_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 1500)
311 /** The offset of the MySQL binlog offset info in the trx system header */
312 #define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)
313 --- a/storage/innodb_plugin/include/trx0trx.h
314 +++ b/storage/innodb_plugin/include/trx0trx.h
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;
334 os_thread_id_t mysql_thread_id;/* id of the MySQL thread associated
335 with this transaction object */
336 ulint mysql_process_no;/* since in Linux, 'top' reports
337 --- a/storage/innodb_plugin/trx/trx0sys.c
338 +++ b/storage/innodb_plugin/trx/trx0sys.c
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 @@ -676,22 +679,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 */
382 + file_name = file_name_in;
385 - sys_header = trx_sysf_get(mtr);
387 if (mach_read_from_4(sys_header + field
388 + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
389 @@ -814,13 +820,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 --- a/storage/innodb_plugin/trx/trx0trx.c
438 +++ b/storage/innodb_plugin/trx/trx0trx.c
441 trx->mysql_log_file_name = NULL;
442 trx->mysql_log_offset = 0;
443 + trx->mysql_master_log_file_name = "";
444 + trx->mysql_master_log_pos = 0;
445 + trx->mysql_relay_log_file_name = "";
446 + trx->mysql_relay_log_pos = 0;
448 mutex_create(&trx->undo_mutex, SYNC_TRX_UNDO);
454 + trx_sysf_t* sys_header = NULL;
456 ut_ad(mutex_own(&kernel_mutex));
458 @@ -848,13 +853,35 @@
460 if (trx->mysql_log_file_name
461 && trx->mysql_log_file_name[0] != '\0') {
463 + sys_header = trx_sysf_get(&mtr);
465 trx_sys_update_mysql_binlog_offset(
467 trx->mysql_log_file_name,
468 trx->mysql_log_offset,
469 TRX_SYS_MYSQL_LOG_INFO, &mtr);
470 trx->mysql_log_file_name = NULL;
473 + if (trx->mysql_master_log_file_name[0] != '\0') {
474 + /* This database server is a MySQL replication slave */
476 + sys_header = trx_sysf_get(&mtr);
478 + trx_sys_update_mysql_binlog_offset(
480 + trx->mysql_relay_log_file_name,
481 + trx->mysql_relay_log_pos,
482 + 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);
488 + trx->mysql_master_log_file_name = "";
491 /* The following call commits the mini-transaction, making the
492 whole transaction committed in the file-based world, at this
493 log sequence number. The transaction becomes 'durable' when