]> git.pld-linux.org Git - packages/mysql.git/blame - innodb_overwrite_relay_log_info.patch
mysqlhotcopy: do not fail storing slave status if master status can't be fetched
[packages/mysql.git] / innodb_overwrite_relay_log_info.patch
CommitLineData
b4e1fa2c
AM
1# name : innodb_overwrite_relay_log_info.patch
2# introduced : 11 or before
3# maintainer : Yasufumi
4#
5#!!! notice !!!
6# Any small change to this file in the main branch
7# should be done or reviewed by the maintainer!
db82db79
AM
8--- a/storage/innobase/handler/ha_innodb.cc
9+++ b/storage/innobase/handler/ha_innodb.cc
b4e1fa2c
AM
10@@ -42,6 +42,8 @@
11 #pragma implementation // gcc: Class implementation
12 #endif
13
14+#define MYSQL_SERVER
15+
16 #include <sql_table.h> // explain_filename, nz2, EXPLAIN_PARTITIONS_AS_COMMENT,
17 // EXPLAIN_FILENAME_MAX_EXTRA_LENGTH
18
adf0fb13 19@@ -53,6 +55,15 @@
b4e1fa2c 20 #include <mysql/psi/psi.h>
adf0fb13 21 #include <my_sys.h>
b4e1fa2c
AM
22
23+#ifdef MYSQL_SERVER
24+#include <rpl_mi.h>
25+#include <slave.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 */
31+
32 /** @file ha_innodb.cc */
33
34 /* Include necessary InnoDB headers */
35@@ -91,6 +102,14 @@
36 #include "ha_innodb.h"
37 #include "i_s.h"
38
39+#ifdef MYSQL_SERVER
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 */
46+
47 # ifndef MYSQL_PLUGIN_IMPORT
48 # define MYSQL_PLUGIN_IMPORT /* nothing */
49 # endif /* MYSQL_PLUGIN_IMPORT */
50@@ -163,6 +182,7 @@
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;
734d6226 58@@ -2282,6 +2302,89 @@
b4e1fa2c 59 }
d8778560 60 #endif /* DBUG_OFF */
b4e1fa2c
AM
61
62+#ifndef MYSQL_SERVER
63+ innodb_overwrite_relay_log_info = FALSE;
64+#endif
65+
66+#ifdef HAVE_REPLICATION
67+#ifdef MYSQL_SERVER
68+ /* read master log position from relay-log.info if exists */
69+ char fname[FN_REFLEN+128];
70+ int pos;
71+ int info_fd;
72+ IO_CACHE info_file;
73+
74+ fname[0] = '\0';
75+
76+ if(innobase_overwrite_relay_log_info) {
77+
78+ fprintf(stderr,
79+ "InnoDB: Warning: innodb_overwrite_relay_log_info is enabled."
d8778560 80+ " Updates by other storage engines may not be synchronized.\n");
b4e1fa2c
AM
81+
82+ bzero((char*) &info_file, sizeof(info_file));
83+ fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
84+
85+ int error=0;
86+
87+ if (!access(fname,F_OK)) {
88+ /* exist */
89+ if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
90+ error=1;
91+ } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
92+ READ_CACHE, 0L, 0, MYF(MY_WME))) {
93+ error=1;
94+ }
95+
96+ if (error) {
97+relay_info_error:
98+ if (info_fd >= 0)
99+ my_close(info_fd, MYF(0));
100+ fname[0] = '\0';
101+ goto skip_relay;
102+ }
103+ } else {
104+ fname[0] = '\0';
105+ goto skip_relay;
106+ }
107+
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);
111+ error=1;
112+ goto relay_info_error;
113+ }
114+
115+ fprintf(stderr,
116+ "InnoDB: relay-log.info is detected.\n"
117+ "InnoDB: relay log: position %u, file name %s\n",
118+ pos, fname);
119+
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;
122+
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);
126+ error=1;
127+ goto relay_info_error;
128+ }
129+
130+ fprintf(stderr,
131+ "InnoDB: master log: position %u, file name %s\n",
132+ pos, fname);
133+
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;
136+
137+ end_io_cache(&info_file);
138+ if (info_fd >= 0)
139+ my_close(info_fd, MYF(0));
140+ }
141+skip_relay:
142+#endif /* MYSQL_SERVER */
143+#endif /* HAVE_REPLICATION */
144+
145 /* Check that values don't overflow on 32-bit systems. */
146 if (sizeof(ulint) == 4) {
147 if (innobase_buffer_pool_size > UINT_MAX32) {
734d6226 148@@ -2580,6 +2683,76 @@
b4e1fa2c
AM
149 goto mem_free_and_error;
150 }
151
152+#ifdef HAVE_REPLICATION
153+#ifdef MYSQL_SERVER
154+ if(innobase_overwrite_relay_log_info) {
155+ /* If InnoDB progressed from relay-log.info, overwrite it */
156+ if (fname[0] == '\0') {
157+ fprintf(stderr,
d8778560 158+ "InnoDB: Something is wrong with the file relay-info.log. InnoDB will not overwrite it.\n");
b4e1fa2c
AM
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);
164+
165+ int error = 0;
166+
167+ if (!access(fname,F_OK)) {
168+ /* exist */
169+ if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
170+ error = 1;
171+ } else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
172+ WRITE_CACHE, 0L, 0, MYF(MY_WME))) {
173+ error = 1;
174+ }
175+
176+ if (error) {
177+ if (info_fd >= 0)
178+ my_close(info_fd, MYF(0));
179+ goto skip_overwrite;
180+ }
181+ } else {
182+ error = 1;
183+ goto skip_overwrite;
184+ }
185+
186+ char buff[FN_REFLEN*2+22*2+4], *pos;
187+
188+ my_b_seek(&info_file, 0L);
189+ pos=strmov(buff, trx_sys_mysql_relay_log_name);
190+ *pos++='\n';
191+ pos=longlong2str(trx_sys_mysql_relay_log_pos, pos, 10);
192+ *pos++='\n';
193+ pos=strmov(pos, trx_sys_mysql_master_log_name);
194+ *pos++='\n';
195+ pos=longlong2str(trx_sys_mysql_master_log_pos, pos, 10);
196+ *pos='\n';
197+
198+ if (my_b_write(&info_file, (uchar*) buff, (size_t) (pos-buff)+1))
199+ error = 1;
200+ if (flush_io_cache(&info_file))
201+ error = 1;
202+
203+ end_io_cache(&info_file);
204+ if (info_fd >= 0)
205+ my_close(info_fd, MYF(0));
206+skip_overwrite:
207+ if (error) {
208+ fprintf(stderr,
d8778560 209+ "InnoDB: ERROR: An error occurred while overwriting relay-log.info.\n");
b4e1fa2c
AM
210+ } else {
211+ fprintf(stderr,
d8778560 212+ "InnoDB: The file relay-log.info was successfully overwritten.\n");
b4e1fa2c
AM
213+ }
214+ } else {
215+ fprintf(stderr,
216+ "InnoDB: InnoDB and relay-log.info are synchronized. InnoDB will not overwrite it.\n");
217+ }
218+ }
219+#endif /* MYSQL_SERVER */
220+#endif /* HAVE_REPLICATION */
221+
222 innobase_old_blocks_pct = buf_LRU_old_ratio_update(
223 innobase_old_blocks_pct, TRUE);
224
13ceb006 225@@ -2693,6 +2866,25 @@
b4e1fa2c
AM
226 trx_t* trx) /*!< in: transaction handle */
227 {
228 if (trx_is_started(trx)) {
229+#ifdef HAVE_REPLICATION
230+#ifdef MYSQL_SERVER
231+ THD *thd=current_thd;
232+
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;
245+ }
246+#endif /* MYSQL_SERVER */
247+#endif /* HAVE_REPLICATION */
248
249 trx_commit_for_mysql(trx);
250 }
29ffd636 251@@ -11130,6 +11322,12 @@
b4e1fa2c
AM
252 "The common part for InnoDB table spaces.",
253 NULL, NULL, NULL);
254
a9ee80b9 255+static MYSQL_SYSVAR_BOOL(recovery_update_relay_log, innobase_overwrite_relay_log_info,
b4e1fa2c
AM
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);
260+
261 static MYSQL_SYSVAR_BOOL(doublewrite, innobase_use_doublewrite,
262 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
263 "Enable InnoDB doublewrite buffer (enabled by default). "
29ffd636 264@@ -11647,6 +11845,7 @@
b4e1fa2c
AM
265 MYSQL_SYSVAR(old_blocks_pct),
266 MYSQL_SYSVAR(old_blocks_time),
267 MYSQL_SYSVAR(open_files),
a9ee80b9 268+ MYSQL_SYSVAR(recovery_update_relay_log),
b4e1fa2c
AM
269 MYSQL_SYSVAR(rollback_on_timeout),
270 MYSQL_SYSVAR(stats_on_metadata),
271 MYSQL_SYSVAR(stats_sample_pages),
db82db79
AM
272--- a/storage/innobase/include/trx0sys.h
273+++ b/storage/innobase/include/trx0sys.h
11822e22 274@@ -53,6 +53,9 @@
b4e1fa2c
AM
275 extern ib_int64_t trx_sys_mysql_master_log_pos;
276 /* @} */
277
278+extern char trx_sys_mysql_relay_log_name[];
279+extern ib_int64_t trx_sys_mysql_relay_log_pos;
280+
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
283 here. */
db82db79 284@@ -298,7 +301,8 @@
b4e1fa2c
AM
285 void
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 */
db82db79 294@@ -493,6 +497,7 @@
b4e1fa2c
AM
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
301
db82db79 302@@ -502,6 +507,7 @@
b4e1fa2c
AM
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)
307
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)
db82db79
AM
310--- a/storage/innobase/include/trx0trx.h
311+++ b/storage/innobase/include/trx0trx.h
adf0fb13 312@@ -580,6 +580,20 @@
b4e1fa2c
AM
313 ib_int64_t mysql_log_offset;/* if MySQL binlog is used, this field
314 contains the end offset of the binlog
315 entry */
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
322+ character */
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;
adf0fb13
AM
330 /*------------------------------*/
331 ulint n_mysql_tables_in_use; /* number of Innobase tables
332 used in the processing of the current
db82db79
AM
333--- a/storage/innobase/trx/trx0sys.c
334+++ b/storage/innobase/trx/trx0sys.c
adf0fb13 335@@ -76,13 +76,16 @@
b4e1fa2c
AM
336 file name and position here. */
337 /* @{ */
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;
345 /* @} */
346
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;
349+
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
352 here. */
adf0fb13 353@@ -684,23 +687,25 @@
b4e1fa2c
AM
354 void
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 */
364 {
365- trx_sysf_t* sys_header;
366+ const char* file_name;
367
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) {
370
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 */
373
374- return;
375+ file_name = "";
376+ } else {
377+ file_name = file_name_in;
378 }
379
380- sys_header = trx_sysf_get(mtr);
381-
382 if (mach_read_from_4(sys_header + field
383 + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
384 != TRX_SYS_MYSQL_LOG_MAGIC_N) {
adf0fb13 385@@ -822,13 +827,26 @@
b4e1fa2c
AM
386 + TRX_SYS_MYSQL_LOG_OFFSET_LOW),
387 sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
388 + TRX_SYS_MYSQL_LOG_NAME);
389+
390+ fprintf(stderr,
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);
401+
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 */
404
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);
410
411 trx_sys_mysql_master_log_pos
412 = (((ib_int64_t) mach_read_from_4(
adf0fb13 413@@ -837,6 +855,19 @@
b4e1fa2c
AM
414 + ((ib_int64_t) mach_read_from_4(
415 sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
416 + TRX_SYS_MYSQL_LOG_OFFSET_LOW));
417+
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);
422+
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));
430 mtr_commit(&mtr);
431 }
432
db82db79
AM
433--- a/storage/innobase/trx/trx0trx.c
434+++ b/storage/innobase/trx/trx0trx.c
adf0fb13 435@@ -138,6 +138,10 @@
b4e1fa2c
AM
436
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;
443
444 mutex_create(trx_undo_mutex_key, &trx->undo_mutex, SYNC_TRX_UNDO);
445
adf0fb13 446@@ -820,6 +824,7 @@
11822e22 447 {
b4e1fa2c 448 mtr_t mtr;
11822e22 449 trx_rseg_t* rseg;
b4e1fa2c
AM
450+ trx_sysf_t* sys_header = NULL;
451
11822e22 452 ut_ad(!mutex_own(&kernel_mutex));
b4e1fa2c 453
adf0fb13 454@@ -873,8 +878,12 @@
b4e1fa2c 455
11822e22
AM
456 if (trx->mysql_log_file_name
457 && trx->mysql_log_file_name[0] != '\0') {
458+ if (!sys_header) {
459+ sys_header = trx_sysf_get(&mtr);
460+ }
b4e1fa2c 461
11822e22
AM
462 trx_sys_update_mysql_binlog_offset(
463+ sys_header,
464 trx->mysql_log_file_name,
465 trx->mysql_log_offset,
466 TRX_SYS_MYSQL_LOG_INFO, &mtr);
adf0fb13 467@@ -882,6 +891,27 @@
11822e22
AM
468 trx->mysql_log_file_name = NULL;
469 }
470
471+ if (trx->mysql_master_log_file_name[0] != '\0') {
472+ /* This database server is a MySQL replication slave */
473+ if (!sys_header) {
474+ sys_header = trx_sysf_get(&mtr);
b4e1fa2c
AM
475+ }
476+
11822e22
AM
477+ trx_sys_update_mysql_binlog_offset(
478+ sys_header,
479+ trx->mysql_relay_log_file_name,
480+ trx->mysql_relay_log_pos,
481+ TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
482+
483+ trx_sys_update_mysql_binlog_offset(
484+ sys_header,
485+ trx->mysql_master_log_file_name,
486+ trx->mysql_master_log_pos,
487+ TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
488+
489+ trx->mysql_master_log_file_name = "";
490+ }
491+
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
This page took 0.149578 seconds and 4 git commands to generate.