MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
dict0boot.cc
Go to the documentation of this file.
1 /*****************************************************************************
2 
3 Copyright (c) 1996, 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 "dict0boot.h"
27 
28 #ifdef UNIV_NONINL
29 #include "dict0boot.ic"
30 #endif
31 
32 #include "dict0crea.h"
33 #include "btr0btr.h"
34 #include "dict0load.h"
35 #include "trx0trx.h"
36 #include "srv0srv.h"
37 #include "ibuf0ibuf.h"
38 #include "buf0flu.h"
39 #include "log0recv.h"
40 #include "os0file.h"
41 
42 /**********************************************************************/
45 UNIV_INTERN
46 dict_hdr_t*
48 /*=========*/
49  mtr_t* mtr)
50 {
52  dict_hdr_t* header;
53 
54  block = buf_page_get(DICT_HDR_SPACE, 0, DICT_HDR_PAGE_NO,
55  RW_X_LATCH, mtr);
56  header = DICT_HDR + buf_block_get_frame(block);
57 
58  buf_block_dbg_add_level(block, SYNC_DICT_HEADER);
59 
60  return(header);
61 }
62 
63 /**********************************************************************/
65 UNIV_INTERN
66 void
68 /*================*/
69  table_id_t* table_id,
71  index_id_t* index_id,
73  ulint* space_id)
75 {
76  dict_hdr_t* dict_hdr;
77  ib_id_t id;
78  mtr_t mtr;
79 
80  mtr_start(&mtr);
81 
82  dict_hdr = dict_hdr_get(&mtr);
83 
84  if (table_id) {
85  id = mach_read_from_8(dict_hdr + DICT_HDR_TABLE_ID);
86  id++;
87  mlog_write_ull(dict_hdr + DICT_HDR_TABLE_ID, id, &mtr);
88  *table_id = id;
89  }
90 
91  if (index_id) {
92  id = mach_read_from_8(dict_hdr + DICT_HDR_INDEX_ID);
93  id++;
94  mlog_write_ull(dict_hdr + DICT_HDR_INDEX_ID, id, &mtr);
95  *index_id = id;
96  }
97 
98  if (space_id) {
99  *space_id = mtr_read_ulint(dict_hdr + DICT_HDR_MAX_SPACE_ID,
100  MLOG_4BYTES, &mtr);
101  if (fil_assign_new_space_id(space_id)) {
102  mlog_write_ulint(dict_hdr + DICT_HDR_MAX_SPACE_ID,
103  *space_id, MLOG_4BYTES, &mtr);
104  }
105  }
106 
107  mtr_commit(&mtr);
108 }
109 
110 /**********************************************************************/
113 UNIV_INTERN
114 void
116 /*=======================*/
117 {
118  dict_hdr_t* dict_hdr;
119  row_id_t id;
120  mtr_t mtr;
121 
122  ut_ad(mutex_own(&(dict_sys->mutex)));
123 
124  id = dict_sys->row_id;
125 
126  mtr_start(&mtr);
127 
128  dict_hdr = dict_hdr_get(&mtr);
129 
130  mlog_write_ull(dict_hdr + DICT_HDR_ROW_ID, id, &mtr);
131 
132  mtr_commit(&mtr);
133 }
134 
135 /*****************************************************************/
139 static
140 ibool
141 dict_hdr_create(
142 /*============*/
143  mtr_t* mtr)
144 {
146  dict_hdr_t* dict_header;
147  ulint root_page_no;
148 
149  ut_ad(mtr);
150 
151  /* Create the dictionary header file block in a new, allocated file
152  segment in the system tablespace */
153  block = fseg_create(DICT_HDR_SPACE, 0,
154  DICT_HDR + DICT_HDR_FSEG_HEADER, mtr);
155 
156  ut_a(DICT_HDR_PAGE_NO == buf_block_get_page_no(block));
157 
158  dict_header = dict_hdr_get(mtr);
159 
160  /* Start counting row, table, index, and tree ids from
161  DICT_HDR_FIRST_ID */
162  mlog_write_ull(dict_header + DICT_HDR_ROW_ID,
163  DICT_HDR_FIRST_ID, mtr);
164 
165  mlog_write_ull(dict_header + DICT_HDR_TABLE_ID,
166  DICT_HDR_FIRST_ID, mtr);
167 
168  mlog_write_ull(dict_header + DICT_HDR_INDEX_ID,
169  DICT_HDR_FIRST_ID, mtr);
170 
171  mlog_write_ulint(dict_header + DICT_HDR_MAX_SPACE_ID,
172  0, MLOG_4BYTES, mtr);
173 
174  /* Obsolete, but we must initialize it anyway. */
175  mlog_write_ulint(dict_header + DICT_HDR_MIX_ID_LOW,
176  DICT_HDR_FIRST_ID, MLOG_4BYTES, mtr);
177 
178  /* Create the B-tree roots for the clustered indexes of the basic
179  system tables */
180 
181  /*--------------------------*/
182  root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
183  DICT_HDR_SPACE, 0, DICT_TABLES_ID,
184  dict_ind_redundant, mtr);
185  if (root_page_no == FIL_NULL) {
186 
187  return(FALSE);
188  }
189 
190  mlog_write_ulint(dict_header + DICT_HDR_TABLES, root_page_no,
191  MLOG_4BYTES, mtr);
192  /*--------------------------*/
193  root_page_no = btr_create(DICT_UNIQUE, DICT_HDR_SPACE, 0,
194  DICT_TABLE_IDS_ID,
195  dict_ind_redundant, mtr);
196  if (root_page_no == FIL_NULL) {
197 
198  return(FALSE);
199  }
200 
201  mlog_write_ulint(dict_header + DICT_HDR_TABLE_IDS, root_page_no,
202  MLOG_4BYTES, mtr);
203  /*--------------------------*/
204  root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
205  DICT_HDR_SPACE, 0, DICT_COLUMNS_ID,
206  dict_ind_redundant, mtr);
207  if (root_page_no == FIL_NULL) {
208 
209  return(FALSE);
210  }
211 
212  mlog_write_ulint(dict_header + DICT_HDR_COLUMNS, root_page_no,
213  MLOG_4BYTES, mtr);
214  /*--------------------------*/
215  root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
216  DICT_HDR_SPACE, 0, DICT_INDEXES_ID,
217  dict_ind_redundant, mtr);
218  if (root_page_no == FIL_NULL) {
219 
220  return(FALSE);
221  }
222 
223  mlog_write_ulint(dict_header + DICT_HDR_INDEXES, root_page_no,
224  MLOG_4BYTES, mtr);
225  /*--------------------------*/
226  root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
227  DICT_HDR_SPACE, 0, DICT_FIELDS_ID,
228  dict_ind_redundant, mtr);
229  if (root_page_no == FIL_NULL) {
230 
231  return(FALSE);
232  }
233 
234  mlog_write_ulint(dict_header + DICT_HDR_FIELDS, root_page_no,
235  MLOG_4BYTES, mtr);
236  /*--------------------------*/
237 
238  return(TRUE);
239 }
240 
241 /*****************************************************************/
245 UNIV_INTERN
246 dberr_t
248 /*===========*/
249 {
252  dict_hdr_t* dict_hdr;
253  mem_heap_t* heap;
254  mtr_t mtr;
255  dberr_t error;
256 
257  /* Be sure these constants do not ever change. To avoid bloat,
258  only check the *NUM_FIELDS* in each table */
259 
260  ut_ad(DICT_NUM_COLS__SYS_TABLES == 8);
261  ut_ad(DICT_NUM_FIELDS__SYS_TABLES == 10);
262  ut_ad(DICT_NUM_FIELDS__SYS_TABLE_IDS == 2);
263  ut_ad(DICT_NUM_COLS__SYS_COLUMNS == 7);
264  ut_ad(DICT_NUM_FIELDS__SYS_COLUMNS == 9);
265  ut_ad(DICT_NUM_COLS__SYS_INDEXES == 7);
266  ut_ad(DICT_NUM_FIELDS__SYS_INDEXES == 9);
267  ut_ad(DICT_NUM_COLS__SYS_FIELDS == 3);
268  ut_ad(DICT_NUM_FIELDS__SYS_FIELDS == 5);
269  ut_ad(DICT_NUM_COLS__SYS_FOREIGN == 4);
270  ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN == 6);
271  ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN_FOR_NAME == 2);
272  ut_ad(DICT_NUM_COLS__SYS_FOREIGN_COLS == 4);
273  ut_ad(DICT_NUM_FIELDS__SYS_FOREIGN_COLS == 6);
274 
275  mtr_start(&mtr);
276 
277  /* Create the hash tables etc. */
278  dict_init();
279 
280  heap = mem_heap_create(450);
281 
282  mutex_enter(&(dict_sys->mutex));
283 
284  /* Get the dictionary header */
285  dict_hdr = dict_hdr_get(&mtr);
286 
287  /* Because we only write new row ids to disk-based data structure
288  (dictionary header) when it is divisible by
289  DICT_HDR_ROW_ID_WRITE_MARGIN, in recovery we will not recover
290  the latest value of the row id counter. Therefore we advance
291  the counter at the database startup to avoid overlapping values.
292  Note that when a user after database startup first time asks for
293  a new row id, then because the counter is now divisible by
294  ..._MARGIN, it will immediately be updated to the disk-based
295  header. */
296 
297  dict_sys->row_id = DICT_HDR_ROW_ID_WRITE_MARGIN
298  + ut_uint64_align_up(mach_read_from_8(dict_hdr + DICT_HDR_ROW_ID),
299  DICT_HDR_ROW_ID_WRITE_MARGIN);
300 
301  /* Insert into the dictionary cache the descriptions of the basic
302  system tables */
303  /*-------------------------*/
304  table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, 0, 0);
305 
306  dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
307  dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
308  /* ROW_FORMAT = (N_COLS >> 31) ? COMPACT : REDUNDANT */
309  dict_mem_table_add_col(table, heap, "N_COLS", DATA_INT, 0, 4);
310  /* The low order bit of TYPE is always set to 1. If the format
311  is UNIV_FORMAT_B or higher, this field matches table->flags. */
312  dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
313  dict_mem_table_add_col(table, heap, "MIX_ID", DATA_BINARY, 0, 0);
314  /* MIX_LEN may contain additional table flags when
315  ROW_FORMAT!=REDUNDANT. Currently, these flags include
316  DICT_TF2_TEMPORARY. */
317  dict_mem_table_add_col(table, heap, "MIX_LEN", DATA_INT, 0, 4);
318  dict_mem_table_add_col(table, heap, "CLUSTER_NAME", DATA_BINARY, 0, 0);
319  dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
320 
321  table->id = DICT_TABLES_ID;
322 
323  dict_table_add_to_cache(table, FALSE, heap);
325  mem_heap_empty(heap);
326 
327  index = dict_mem_index_create("SYS_TABLES", "CLUST_IND",
328  DICT_HDR_SPACE,
330 
331  dict_mem_index_add_field(index, "NAME", 0);
332 
333  index->id = DICT_TABLES_ID;
334 
335  error = dict_index_add_to_cache(table, index,
336  mtr_read_ulint(dict_hdr
337  + DICT_HDR_TABLES,
338  MLOG_4BYTES, &mtr),
339  FALSE);
340  ut_a(error == DB_SUCCESS);
341 
342  /*-------------------------*/
343  index = dict_mem_index_create("SYS_TABLES", "ID_IND",
344  DICT_HDR_SPACE, DICT_UNIQUE, 1);
345  dict_mem_index_add_field(index, "ID", 0);
346 
347  index->id = DICT_TABLE_IDS_ID;
348  error = dict_index_add_to_cache(table, index,
349  mtr_read_ulint(dict_hdr
350  + DICT_HDR_TABLE_IDS,
351  MLOG_4BYTES, &mtr),
352  FALSE);
353  ut_a(error == DB_SUCCESS);
354 
355  /*-------------------------*/
356  table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, 0, 0);
357 
358  dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
359  dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
360  dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
361  dict_mem_table_add_col(table, heap, "MTYPE", DATA_INT, 0, 4);
362  dict_mem_table_add_col(table, heap, "PRTYPE", DATA_INT, 0, 4);
363  dict_mem_table_add_col(table, heap, "LEN", DATA_INT, 0, 4);
364  dict_mem_table_add_col(table, heap, "PREC", DATA_INT, 0, 4);
365 
366  table->id = DICT_COLUMNS_ID;
367 
368  dict_table_add_to_cache(table, FALSE, heap);
370  mem_heap_empty(heap);
371 
372  index = dict_mem_index_create("SYS_COLUMNS", "CLUST_IND",
373  DICT_HDR_SPACE,
375 
376  dict_mem_index_add_field(index, "TABLE_ID", 0);
377  dict_mem_index_add_field(index, "POS", 0);
378 
379  index->id = DICT_COLUMNS_ID;
380  error = dict_index_add_to_cache(table, index,
381  mtr_read_ulint(dict_hdr
382  + DICT_HDR_COLUMNS,
383  MLOG_4BYTES, &mtr),
384  FALSE);
385  ut_a(error == DB_SUCCESS);
386 
387  /*-------------------------*/
388  table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, 0, 0);
389 
390  dict_mem_table_add_col(table, heap, "TABLE_ID", DATA_BINARY, 0, 0);
391  dict_mem_table_add_col(table, heap, "ID", DATA_BINARY, 0, 0);
392  dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0);
393  dict_mem_table_add_col(table, heap, "N_FIELDS", DATA_INT, 0, 4);
394  dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
395  dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
396  dict_mem_table_add_col(table, heap, "PAGE_NO", DATA_INT, 0, 4);
397 
398  table->id = DICT_INDEXES_ID;
399 
400  dict_table_add_to_cache(table, FALSE, heap);
402  mem_heap_empty(heap);
403 
404  index = dict_mem_index_create("SYS_INDEXES", "CLUST_IND",
405  DICT_HDR_SPACE,
407 
408  dict_mem_index_add_field(index, "TABLE_ID", 0);
409  dict_mem_index_add_field(index, "ID", 0);
410 
411  index->id = DICT_INDEXES_ID;
412  error = dict_index_add_to_cache(table, index,
413  mtr_read_ulint(dict_hdr
414  + DICT_HDR_INDEXES,
415  MLOG_4BYTES, &mtr),
416  FALSE);
417  ut_a(error == DB_SUCCESS);
418 
419  /*-------------------------*/
420  table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, 0, 0);
421 
422  dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
423  dict_mem_table_add_col(table, heap, "POS", DATA_INT, 0, 4);
424  dict_mem_table_add_col(table, heap, "COL_NAME", DATA_BINARY, 0, 0);
425 
426  table->id = DICT_FIELDS_ID;
427 
428  dict_table_add_to_cache(table, FALSE, heap);
430  mem_heap_free(heap);
431 
432  index = dict_mem_index_create("SYS_FIELDS", "CLUST_IND",
433  DICT_HDR_SPACE,
435 
436  dict_mem_index_add_field(index, "INDEX_ID", 0);
437  dict_mem_index_add_field(index, "POS", 0);
438 
439  index->id = DICT_FIELDS_ID;
440  error = dict_index_add_to_cache(table, index,
441  mtr_read_ulint(dict_hdr
442  + DICT_HDR_FIELDS,
443  MLOG_4BYTES, &mtr),
444  FALSE);
445  ut_a(error == DB_SUCCESS);
446 
447  mtr_commit(&mtr);
448 
449  /*-------------------------*/
450 
451  /* Initialize the insert buffer table and index for each tablespace */
452 
454 
455  dberr_t err = DB_SUCCESS;
456 
457  if (srv_read_only_mode && !ibuf_is_empty()) {
458 
459  ib_logf(IB_LOG_LEVEL_ERROR,
460  "Change buffer must be empty when --innodb-read-only "
461  "is set!");
462 
463  err = DB_ERROR;
464  } else {
465  /* Load definitions of other indexes on system tables */
466 
471  }
472 
473  mutex_exit(&(dict_sys->mutex));
474 
475  return(err);
476 }
477 
478 /*****************************************************************/
481 static
482 void
483 dict_insert_initial_data(void)
484 /*==========================*/
485 {
486  /* Does nothing yet */
487 }
488 
489 /*****************************************************************/
492 UNIV_INTERN
493 dberr_t
495 /*=============*/
496 {
497  mtr_t mtr;
498 
499  mtr_start(&mtr);
500 
501  dict_hdr_create(&mtr);
502 
503  mtr_commit(&mtr);
504 
505  dberr_t err = dict_boot();
506 
507  if (err == DB_SUCCESS) {
508  dict_insert_initial_data();
509  }
510 
511  return(err);
512 }