MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
row0quiesce.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 2012, Oracle and/or its affiliates. All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free Software
7 Foundation; version 2 of the License.
8 
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License along with
14 this program; if not, write to the Free Software Foundation, Inc.,
15 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
16 
17 *****************************************************************************/
18 
19 /**************************************************/
26 #include "row0quiesce.h"
27 #include "row0mysql.h"
28 
29 #ifdef UNIV_NONINL
30 #include "row0quiesce.ic"
31 #endif
32 
33 #include "ibuf0ibuf.h"
34 #include "srv0start.h"
35 #include "trx0purge.h"
36 
37 /*********************************************************************/
40 static __attribute__((nonnull, warn_unused_result))
41 dberr_t
42 row_quiesce_write_index_fields(
43 /*===========================*/
44  const dict_index_t* index,
46  FILE* file,
47  THD* thd)
48 {
49  byte row[sizeof(ib_uint32_t) * 2];
50 
51  for (ulint i = 0; i < index->n_fields; ++i) {
52  byte* ptr = row;
53  const dict_field_t* field = &index->fields[i];
54 
55  mach_write_to_4(ptr, field->prefix_len);
56  ptr += sizeof(ib_uint32_t);
57 
58  mach_write_to_4(ptr, field->fixed_len);
59 
60  DBUG_EXECUTE_IF("ib_export_io_write_failure_9",
61  close(fileno(file)););
62 
63  if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
64 
66  thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
67  errno, strerror(errno),
68  "while writing index fields.");
69 
70  return(DB_IO_ERROR);
71  }
72 
73  /* Include the NUL byte in the length. */
74  ib_uint32_t len = strlen(field->name) + 1;
75  ut_a(len > 1);
76 
77  mach_write_to_4(row, len);
78 
79  DBUG_EXECUTE_IF("ib_export_io_write_failure_10",
80  close(fileno(file)););
81 
82  if (fwrite(row, 1, sizeof(len), file) != sizeof(len)
83  || fwrite(field->name, 1, len, file) != len) {
84 
86  thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
87  errno, strerror(errno),
88  "while writing index column.");
89 
90  return(DB_IO_ERROR);
91  }
92  }
93 
94  return(DB_SUCCESS);
95 }
96 
97 /*********************************************************************/
100 static __attribute__((nonnull, warn_unused_result))
101 dberr_t
102 row_quiesce_write_indexes(
103 /*======================*/
104  const dict_table_t* table,
106  FILE* file,
107  THD* thd)
108 {
109  {
110  byte row[sizeof(ib_uint32_t)];
111 
112  /* Write the number of indexes in the table. */
113  mach_write_to_4(row, UT_LIST_GET_LEN(table->indexes));
114 
115  DBUG_EXECUTE_IF("ib_export_io_write_failure_11",
116  close(fileno(file)););
117 
118  if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
119  ib_senderrf(
120  thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
121  errno, strerror(errno),
122  "while writing index count.");
123 
124  return(DB_IO_ERROR);
125  }
126  }
127 
128  dberr_t err = DB_SUCCESS;
129 
130  /* Write the index meta data. */
131  for (const dict_index_t* index = UT_LIST_GET_FIRST(table->indexes);
132  index != 0 && err == DB_SUCCESS;
133  index = UT_LIST_GET_NEXT(indexes, index)) {
134 
135  byte* ptr;
136  byte row[sizeof(index_id_t)
137  + sizeof(ib_uint32_t) * 8];
138 
139  ptr = row;
140 
141  ut_ad(sizeof(index_id_t) == 8);
142  mach_write_to_8(ptr, index->id);
143  ptr += sizeof(index_id_t);
144 
145  mach_write_to_4(ptr, index->space);
146  ptr += sizeof(ib_uint32_t);
147 
148  mach_write_to_4(ptr, index->page);
149  ptr += sizeof(ib_uint32_t);
150 
151  mach_write_to_4(ptr, index->type);
152  ptr += sizeof(ib_uint32_t);
153 
154  mach_write_to_4(ptr, index->trx_id_offset);
155  ptr += sizeof(ib_uint32_t);
156 
157  mach_write_to_4(ptr, index->n_user_defined_cols);
158  ptr += sizeof(ib_uint32_t);
159 
160  mach_write_to_4(ptr, index->n_uniq);
161  ptr += sizeof(ib_uint32_t);
162 
163  mach_write_to_4(ptr, index->n_nullable);
164  ptr += sizeof(ib_uint32_t);
165 
167 
168  DBUG_EXECUTE_IF("ib_export_io_write_failure_12",
169  close(fileno(file)););
170 
171  if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
172 
173  ib_senderrf(
174  thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
175  errno, strerror(errno),
176  "while writing index meta-data.");
177 
178  return(DB_IO_ERROR);
179  }
180 
181  /* Write the length of the index name.
182  NUL byte is included in the length. */
183  ib_uint32_t len = strlen(index->name) + 1;
184  ut_a(len > 1);
185 
186  mach_write_to_4(row, len);
187 
188  DBUG_EXECUTE_IF("ib_export_io_write_failure_1",
189  close(fileno(file)););
190 
191  if (fwrite(row, 1, sizeof(len), file) != sizeof(len)
192  || fwrite(index->name, 1, len, file) != len) {
193 
194  ib_senderrf(
195  thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
196  errno, strerror(errno),
197  "while writing index name.");
198 
199  return(DB_IO_ERROR);
200  }
201 
202  err = row_quiesce_write_index_fields(index, file, thd);
203  }
204 
205  return(err);
206 }
207 
208 /*********************************************************************/
213 static __attribute__((nonnull, warn_unused_result))
214 dberr_t
215 row_quiesce_write_table(
216 /*====================*/
217  const dict_table_t* table,
219  FILE* file,
220  THD* thd)
221 {
222  dict_col_t* col;
223  byte row[sizeof(ib_uint32_t) * 7];
224 
225  col = table->cols;
226 
227  for (ulint i = 0; i < table->n_cols; ++i, ++col) {
228  byte* ptr = row;
229 
230  mach_write_to_4(ptr, col->prtype);
231  ptr += sizeof(ib_uint32_t);
232 
233  mach_write_to_4(ptr, col->mtype);
234  ptr += sizeof(ib_uint32_t);
235 
236  mach_write_to_4(ptr, col->len);
237  ptr += sizeof(ib_uint32_t);
238 
239  mach_write_to_4(ptr, col->mbminmaxlen);
240  ptr += sizeof(ib_uint32_t);
241 
242  mach_write_to_4(ptr, col->ind);
243  ptr += sizeof(ib_uint32_t);
244 
245  mach_write_to_4(ptr, col->ord_part);
246  ptr += sizeof(ib_uint32_t);
247 
248  mach_write_to_4(ptr, col->max_prefix);
249 
250  DBUG_EXECUTE_IF("ib_export_io_write_failure_2",
251  close(fileno(file)););
252 
253  if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
254  ib_senderrf(
255  thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
256  errno, strerror(errno),
257  "while writing table column data.");
258 
259  return(DB_IO_ERROR);
260  }
261 
262  /* Write out the column name as [len, byte array]. The len
263  includes the NUL byte. */
264  ib_uint32_t len;
265  const char* col_name;
266 
267  col_name = dict_table_get_col_name(table, dict_col_get_no(col));
268 
269  /* Include the NUL byte in the length. */
270  len = strlen(col_name) + 1;
271  ut_a(len > 1);
272 
273  mach_write_to_4(row, len);
274 
275  DBUG_EXECUTE_IF("ib_export_io_write_failure_3",
276  close(fileno(file)););
277 
278  if (fwrite(row, 1, sizeof(len), file) != sizeof(len)
279  || fwrite(col_name, 1, len, file) != len) {
280 
281  ib_senderrf(
282  thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
283  errno, strerror(errno),
284  "while writing column name.");
285 
286  return(DB_IO_ERROR);
287  }
288  }
289 
290  return(DB_SUCCESS);
291 }
292 
293 /*********************************************************************/
296 static __attribute__((nonnull, warn_unused_result))
297 dberr_t
298 row_quiesce_write_header(
299 /*=====================*/
300  const dict_table_t* table,
302  FILE* file,
303  THD* thd)
304 {
305  byte value[sizeof(ib_uint32_t)];
306 
307  /* Write the meta-data version number. */
309 
310  DBUG_EXECUTE_IF("ib_export_io_write_failure_4", close(fileno(file)););
311 
312  if (fwrite(&value, 1, sizeof(value), file) != sizeof(value)) {
313  ib_senderrf(
314  thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
315  errno, strerror(errno),
316  "while writing meta-data version number.");
317 
318  return(DB_IO_ERROR);
319  }
320 
321  /* Write the server hostname. */
322  ib_uint32_t len;
323  const char* hostname = server_get_hostname();
324 
325  /* Play it safe and check for NULL. */
326  if (hostname == 0) {
327  static const char NullHostname[] = "Hostname unknown";
328 
329  ib_logf(IB_LOG_LEVEL_WARN,
330  "Unable to determine server hostname.");
331 
332  hostname = NullHostname;
333  }
334 
335  /* The server hostname includes the NUL byte. */
336  len = strlen(hostname) + 1;
337  mach_write_to_4(value, len);
338 
339  DBUG_EXECUTE_IF("ib_export_io_write_failure_5", close(fileno(file)););
340 
341  if (fwrite(&value, 1, sizeof(value), file) != sizeof(value)
342  || fwrite(hostname, 1, len, file) != len) {
343 
344  ib_senderrf(
345  thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
346  errno, strerror(errno),
347  "while writing hostname.");
348 
349  return(DB_IO_ERROR);
350  }
351 
352  /* The table name includes the NUL byte. */
353  ut_a(table->name != 0);
354  len = strlen(table->name) + 1;
355 
356  /* Write the table name. */
357  mach_write_to_4(value, len);
358 
359  DBUG_EXECUTE_IF("ib_export_io_write_failure_6", close(fileno(file)););
360 
361  if (fwrite(&value, 1, sizeof(value), file) != sizeof(value)
362  || fwrite(table->name, 1, len, file) != len) {
363 
364  ib_senderrf(
365  thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
366  errno, strerror(errno),
367  "while writing table name.");
368 
369  return(DB_IO_ERROR);
370  }
371 
372  byte row[sizeof(ib_uint32_t) * 3];
373 
374  /* Write the next autoinc value. */
375  mach_write_to_8(row, table->autoinc);
376 
377  DBUG_EXECUTE_IF("ib_export_io_write_failure_7", close(fileno(file)););
378 
379  if (fwrite(row, 1, sizeof(ib_uint64_t), file) != sizeof(ib_uint64_t)) {
380  ib_senderrf(
381  thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
382  errno, strerror(errno),
383  "while writing table autoinc value.");
384 
385  return(DB_IO_ERROR);
386  }
387 
388  byte* ptr = row;
389 
390  /* Write the system page size. */
391  mach_write_to_4(ptr, UNIV_PAGE_SIZE);
392  ptr += sizeof(ib_uint32_t);
393 
394  /* Write the table->flags. */
395  mach_write_to_4(ptr, table->flags);
396  ptr += sizeof(ib_uint32_t);
397 
398  /* Write the number of columns in the table. */
399  mach_write_to_4(ptr, table->n_cols);
400 
401  DBUG_EXECUTE_IF("ib_export_io_write_failure_8", close(fileno(file)););
402 
403  if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
404  ib_senderrf(
405  thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
406  errno, strerror(errno),
407  "while writing table meta-data.");
408 
409  return(DB_IO_ERROR);
410  }
411 
412  return(DB_SUCCESS);
413 }
414 
415 /*********************************************************************/
418 static __attribute__((nonnull, warn_unused_result))
419 dberr_t
420 row_quiesce_write_cfg(
421 /*==================*/
422  dict_table_t* table,
424  THD* thd)
425 {
426  dberr_t err;
427  char name[OS_FILE_MAX_PATH];
428 
429  srv_get_meta_data_filename(table, name, sizeof(name));
430 
431  ib_logf(IB_LOG_LEVEL_INFO, "Writing table metadata to '%s'", name);
432 
433  FILE* file = fopen(name, "w+b");
434 
435  if (file == NULL) {
436  ib_errf(thd, IB_LOG_LEVEL_WARN, ER_CANT_CREATE_FILE,
437  name, errno, strerror(errno));
438 
439  err = DB_IO_ERROR;
440  } else {
441  err = row_quiesce_write_header(table, file, thd);
442 
443  if (err == DB_SUCCESS) {
444  err = row_quiesce_write_table(table, file, thd);
445  }
446 
447  if (err == DB_SUCCESS) {
448  err = row_quiesce_write_indexes(table, file, thd);
449  }
450 
451  if (fflush(file) != 0) {
452 
453  char msg[BUFSIZ];
454 
455  ut_snprintf(msg, sizeof(msg), "%s flush() failed",
456  name);
457 
458  ib_senderrf(
459  thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
460  errno, strerror(errno), msg);
461  }
462 
463  if (fclose(file) != 0) {
464  char msg[BUFSIZ];
465 
466  ut_snprintf(msg, sizeof(msg), "%s flose() failed",
467  name);
468 
469  ib_senderrf(
470  thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
471  errno, strerror(errno), msg);
472  }
473  }
474 
475  return(err);
476 }
477 
478 /*********************************************************************/
481 static
482 bool
483 row_quiesce_table_has_fts_index(
484 /*============================*/
485  const dict_table_t* table)
486 {
487  bool exists = false;
488 
490 
491  for (const dict_index_t* index = UT_LIST_GET_FIRST(table->indexes);
492  index != 0;
493  index = UT_LIST_GET_NEXT(indexes, index)) {
494 
495  if (index->type & DICT_FTS) {
496  exists = true;
497  break;
498  }
499  }
500 
502 
503  return(exists);
504 }
505 
506 /*********************************************************************/
508 UNIV_INTERN
509 void
511 /*====================*/
512  dict_table_t* table,
513  trx_t* trx)
514 {
515  ut_a(trx->mysql_thd != 0);
516  ut_a(srv_n_purge_threads > 0);
518 
519  char table_name[MAX_FULL_NAME_LEN + 1];
520 
521  ut_a(trx->mysql_thd != 0);
522 
524  table_name, sizeof(table_name), table->name, FALSE);
525 
526  ib_logf(IB_LOG_LEVEL_INFO,
527  "Sync to disk of '%s' started.", table_name);
528 
530  trx_purge_stop();
531  }
532 
533  ut_a(table->id > 0);
534 
535  for (ulint count = 0;
536  ibuf_contract_in_background(table->id, TRUE) != 0
537  && !trx_is_interrupted(trx);
538  ++count) {
539  if (!(count % 20)) {
540  ib_logf(IB_LOG_LEVEL_INFO,
541  "Merging change buffer entries for '%s'",
542  table_name);
543  }
544  }
545 
546  if (!trx_is_interrupted(trx)) {
548  table->space, BUF_REMOVE_FLUSH_WRITE, trx);
549 
550  if (trx_is_interrupted(trx)) {
551 
552  ib_logf(IB_LOG_LEVEL_WARN, "Quiesce aborted!");
553 
554  } else if (row_quiesce_write_cfg(table, trx->mysql_thd)
555  != DB_SUCCESS) {
556 
557  ib_logf(IB_LOG_LEVEL_WARN,
558  "There was an error writing to the "
559  "meta data file");
560  } else {
561  ib_logf(IB_LOG_LEVEL_INFO,
562  "Table '%s' flushed to disk", table_name);
563  }
564  } else {
565  ib_logf(IB_LOG_LEVEL_WARN, "Quiesce aborted!");
566  }
567 
569  ut_a(err == DB_SUCCESS);
570 }
571 
572 /*********************************************************************/
574 UNIV_INTERN
575 void
577 /*=======================*/
578  dict_table_t* table,
579  trx_t* trx)
580 {
581  ulint count = 0;
582  char table_name[MAX_FULL_NAME_LEN + 1];
583 
584  ut_a(trx->mysql_thd != 0);
585 
587  table_name, sizeof(table_name), table->name, FALSE);
588 
589  /* We need to wait for the operation to complete if the
590  transaction has been killed. */
591 
592  while (table->quiesce != QUIESCE_COMPLETE) {
593 
594  /* Print a warning after every minute. */
595  if (!(count % 60)) {
596  ib_logf(IB_LOG_LEVEL_WARN,
597  "Waiting for quiesce of '%s' to complete",
598  table_name);
599  }
600 
601  /* Sleep for a second. */
602  os_thread_sleep(1000000);
603 
604  ++count;
605  }
606 
607  /* Remove the .cfg file now that the user has resumed
608  normal operations. Otherwise it will cause problems when
609  the user tries to drop the database (remove directory). */
610  char cfg_name[OS_FILE_MAX_PATH];
611 
612  srv_get_meta_data_filename(table, cfg_name, sizeof(cfg_name));
613 
614  os_file_delete_if_exists(innodb_file_data_key, cfg_name);
615 
616  ib_logf(IB_LOG_LEVEL_INFO,
617  "Deleting the meta-data file '%s'", cfg_name);
618 
620  trx_purge_run();
621  }
622 
623  dberr_t err = row_quiesce_set_state(table, QUIESCE_NONE, trx);
624  ut_a(err == DB_SUCCESS);
625 }
626 
627 /*********************************************************************/
630 UNIV_INTERN
631 dberr_t
633 /*==================*/
634  dict_table_t* table,
635  ib_quiesce_t state,
636  trx_t* trx)
637 {
638  ut_a(srv_n_purge_threads > 0);
639 
640  if (srv_read_only_mode) {
641 
642  ib_senderrf(trx->mysql_thd,
643  IB_LOG_LEVEL_WARN, ER_READ_ONLY_MODE);
644 
645  return(DB_UNSUPPORTED);
646 
647  } else if (table->space == TRX_SYS_SPACE) {
648 
649  char table_name[MAX_FULL_NAME_LEN + 1];
650 
652  table_name, sizeof(table_name), table->name, FALSE);
653 
654  ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_WARN,
655  ER_TABLE_IN_SYSTEM_TABLESPACE, table_name);
656 
657  return(DB_UNSUPPORTED);
658  } else if (row_quiesce_table_has_fts_index(table)) {
659 
660  ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_WARN,
661  ER_NOT_SUPPORTED_YET,
662  "FLUSH TABLES on tables that have an FTS index. "
663  "FTS auxiliary tables will not be flushed.");
664 
665  } else if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)) {
666  /* If this flag is set then the table may not have any active
667  FTS indexes but it will still have the auxiliary tables. */
668 
669  ib_senderrf(trx->mysql_thd, IB_LOG_LEVEL_WARN,
670  ER_NOT_SUPPORTED_YET,
671  "FLUSH TABLES on a table that had an FTS index, "
672  "created on a hidden column, the "
673  "auxiliary tables haven't been dropped as yet. "
674  "FTS auxiliary tables will not be flushed.");
675  }
676 
677  row_mysql_lock_data_dictionary(trx);
678 
680 
681  switch (state) {
682  case QUIESCE_START:
683  ut_a(table->quiesce == QUIESCE_NONE);
684  break;
685 
686  case QUIESCE_COMPLETE:
687  ut_a(table->quiesce == QUIESCE_START);
688  break;
689 
690  case QUIESCE_NONE:
691  ut_a(table->quiesce == QUIESCE_COMPLETE);
692  break;
693  }
694 
695  table->quiesce = state;
696 
698 
700 
701  return(DB_SUCCESS);
702 }
703