]> git.pld-linux.org Git - packages/mysql.git/blob - innodb_overwrite_relay_log_info.patch
- rel 2; up to percona rel 30.0
[packages/mysql.git] / innodb_overwrite_relay_log_info.patch
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!
8 --- a/storage/innobase/handler/ha_innodb.cc
9 +++ b/storage/innobase/handler/ha_innodb.cc
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  
19 @@ -53,6 +55,15 @@
20  #include <mysql/psi/psi.h>
21  #include <my_sys.h>
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;
58 @@ -2282,6 +2302,89 @@
59         }
60  #endif /* DBUG_OFF */
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."
80 +               " Updates by other storage engines may not be synchronized.\n");
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) {
148 @@ -2580,6 +2683,76 @@
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,
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);
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,
209 +                               "InnoDB: ERROR: An error occurred while overwriting relay-log.info.\n");
210 +               } else {
211 +                       fprintf(stderr,
212 +                               "InnoDB: The file relay-log.info was successfully overwritten.\n");
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  
225 @@ -2693,6 +2866,25 @@
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         }
251 @@ -11130,6 +11322,12 @@
252    "The common part for InnoDB table spaces.",
253    NULL, NULL, NULL);
254  
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);
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). "
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
274 @@ -53,6 +53,9 @@
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. */
284 @@ -298,7 +301,8 @@
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 */
294 @@ -493,6 +497,7 @@
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  
302 @@ -502,6 +507,7 @@
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)
310 --- a/storage/innobase/include/trx0trx.h
311 +++ b/storage/innobase/include/trx0trx.h
312 @@ -580,6 +580,20 @@
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;
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
335 @@ -76,13 +76,16 @@
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. */
353 @@ -684,23 +687,25 @@
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) {
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);
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(
413 @@ -837,6 +855,19 @@
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  
433 --- a/storage/innobase/trx/trx0trx.c
434 +++ b/storage/innobase/trx/trx0trx.c
435 @@ -138,6 +138,10 @@
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  
446 @@ -820,6 +824,7 @@
447  {
448         mtr_t           mtr;
449         trx_rseg_t*     rseg;
450 +       trx_sysf_t*     sys_header = NULL;
451  
452         ut_ad(!mutex_own(&kernel_mutex));
453  
454 @@ -873,8 +878,12 @@
455  
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 +               }
461  
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);
467 @@ -882,6 +891,27 @@
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);
475 +               }
476 +
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.104506 seconds and 3 git commands to generate.