1
diff -ruN a/storage/innodb_plugin/buf/buf0buf.c b/storage/innodb_plugin/buf/buf0buf.c
2
--- a/storage/innodb_plugin/buf/buf0buf.c 2010-05-19 18:55:03.000000000 +0900
3
+++ b/storage/innodb_plugin/buf/buf0buf.c 2010-05-19 18:55:53.000000000 +0900
5
read_space_id = mach_read_from_4(
6
frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
8
- if (bpage->space == TRX_SYS_SPACE
9
+ if ((bpage->space == TRX_SYS_SPACE
10
+ || (srv_doublewrite_path && bpage->space == TRX_DOUBLEWRITE_SPACE))
11
&& trx_doublewrite_page_inside(bpage->offset)) {
13
ut_print_timestamp(stderr);
14
diff -ruN a/storage/innodb_plugin/buf/buf0flu.c b/storage/innodb_plugin/buf/buf0flu.c
15
--- a/storage/innodb_plugin/buf/buf0flu.c 2010-05-19 18:55:03.000000000 +0900
16
+++ b/storage/innodb_plugin/buf/buf0flu.c 2010-05-19 18:55:53.000000000 +0900
18
write_buf = trx_doublewrite->write_buf;
21
- fil_io(OS_FILE_WRITE, TRUE, TRX_SYS_SPACE, 0,
22
+ fil_io(OS_FILE_WRITE, TRUE,
23
+ (srv_doublewrite_path ? TRX_DOUBLEWRITE_SPACE : TRX_SYS_SPACE), 0,
24
trx_doublewrite->block1, 0, len,
25
(void*) write_buf, NULL);
28
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE;
29
ut_ad(i == TRX_SYS_DOUBLEWRITE_BLOCK_SIZE);
31
- fil_io(OS_FILE_WRITE, TRUE, TRX_SYS_SPACE, 0,
32
+ fil_io(OS_FILE_WRITE, TRUE,
33
+ (srv_doublewrite_path ? TRX_DOUBLEWRITE_SPACE : TRX_SYS_SPACE), 0,
34
trx_doublewrite->block2, 0, len,
35
(void*) write_buf, NULL);
39
/* Now flush the doublewrite buffer data to disk */
41
- fil_flush(TRX_SYS_SPACE);
42
+ fil_flush(srv_doublewrite_path ? TRX_DOUBLEWRITE_SPACE : TRX_SYS_SPACE);
44
/* We know that the writes have been flushed to disk now
45
and in recovery we will find them in the doublewrite buffer
46
diff -ruN a/storage/innodb_plugin/buf/buf0rea.c b/storage/innodb_plugin/buf/buf0rea.c
47
--- a/storage/innodb_plugin/buf/buf0rea.c 2010-05-19 18:55:03.000000000 +0900
48
+++ b/storage/innodb_plugin/buf/buf0rea.c 2010-05-19 18:55:53.000000000 +0900
50
wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
51
mode = mode & ~OS_AIO_SIMULATED_WAKE_LATER;
53
- if (trx_doublewrite && space == TRX_SYS_SPACE
55
+ && (space == TRX_SYS_SPACE
56
+ || (srv_doublewrite_path && space == TRX_DOUBLEWRITE_SPACE))
57
&& ( (offset >= trx_doublewrite->block1
58
&& offset < trx_doublewrite->block1
59
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE)
60
diff -ruN a/storage/innodb_plugin/dict/dict0load.c b/storage/innodb_plugin/dict/dict0load.c
61
--- a/storage/innodb_plugin/dict/dict0load.c 2010-05-19 18:55:03.000000000 +0900
62
+++ b/storage/innodb_plugin/dict/dict0load.c 2010-05-19 18:55:53.000000000 +0900
67
- if (space_id == 0) {
68
+ if (trx_sys_sys_space(space_id)) {
69
/* The system tablespace always exists. */
70
} else if (in_crash_recovery) {
71
/* Check that the tablespace (the .ibd file) really
73
space = mach_read_from_4(field);
75
/* Check if the tablespace exists and has the right name */
77
+ if (!trx_sys_sys_space(space)) {
78
flags = dict_sys_tables_get_flags(rec);
80
if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
84
/* See if the tablespace is available. */
86
+ if (trx_sys_sys_space(space)) {
87
/* The system tablespace is always available. */
88
} else if (!fil_space_for_table_exists_in_mem(
90
diff -ruN a/storage/innodb_plugin/fil/fil0fil.c b/storage/innodb_plugin/fil/fil0fil.c
91
--- a/storage/innodb_plugin/fil/fil0fil.c 2010-05-19 18:55:03.000000000 +0900
92
+++ b/storage/innodb_plugin/fil/fil0fil.c 2010-05-19 18:55:53.000000000 +0900
94
size_bytes = (((ib_int64_t)size_high) << 32)
95
+ (ib_int64_t)size_low;
97
- if (space->id == 0) {
98
+ if (trx_sys_sys_space(space->id)) {
99
node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
100
os_file_close(node->handle);
103
#endif /* UNIV_HOTBACKUP */
104
ut_a(space->purpose != FIL_LOG);
105
- ut_a(space->id != 0);
106
+ ut_a(!trx_sys_sys_space(space->id));
108
if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
113
if (UNIV_UNLIKELY(space_id == ULINT_UNDEFINED
114
- || space_id == 0)) {
115
+ || trx_sys_sys_space(space_id))) {
117
"InnoDB: Error: tablespace id %lu"
118
" in file %s is not sensible\n",
123
- if (space->purpose == FIL_TABLESPACE && space->id != 0) {
124
+ if (space->purpose == FIL_TABLESPACE && !trx_sys_sys_space(space->id)) {
125
/* Put the node to the LRU list */
126
UT_LIST_ADD_FIRST(LRU, system->LRU, node);
129
ut_a(system->n_open > 0);
132
- if (node->space->purpose == FIL_TABLESPACE && node->space->id != 0) {
133
+ if (node->space->purpose == FIL_TABLESPACE && !trx_sys_sys_space(node->space->id)) {
134
ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
136
/* The node is in the LRU list, remove it */
139
mutex_enter(&fil_system->mutex);
141
- if (space_id == 0 || space_id >= SRV_LOG_SPACE_FIRST_ID) {
142
+ if (trx_sys_sys_space(space_id) || space_id >= SRV_LOG_SPACE_FIRST_ID) {
143
/* We keep log files and system tablespace files always open;
144
this is important in preventing deadlocks in this module, as
145
a page read completion often performs another read from the
146
@@ -1137,7 +1137,7 @@
147
" tablespace memory cache!\n",
150
- if (id == 0 || purpose != FIL_TABLESPACE) {
151
+ if (trx_sys_sys_space(id) || purpose != FIL_TABLESPACE) {
153
mutex_exit(&fil_system->mutex);
155
@@ -1529,7 +1529,7 @@
156
fil_system->max_n_open = max_n_open;
158
fil_system->modification_counter = 0;
159
- fil_system->max_assigned_id = 0;
160
+ fil_system->max_assigned_id = TRX_SYS_SPACE_MAX;
162
fil_system->tablespace_version = 0;
164
@@ -1556,7 +1556,7 @@
165
space = UT_LIST_GET_FIRST(fil_system->space_list);
167
while (space != NULL) {
168
- if (space->purpose != FIL_TABLESPACE || space->id == 0) {
169
+ if (space->purpose != FIL_TABLESPACE || trx_sys_sys_space(space->id)) {
170
node = UT_LIST_GET_FIRST(space->chain);
172
while (node != NULL) {
173
@@ -3599,7 +3599,7 @@
176
#ifndef UNIV_HOTBACKUP
177
- if (space_id == ULINT_UNDEFINED || space_id == 0) {
178
+ if (space_id == ULINT_UNDEFINED || trx_sys_sys_space(space_id)) {
180
"InnoDB: Error: tablespace id %lu in file %s"
181
" is not sensible\n",
182
@@ -3608,7 +3608,7 @@
186
- if (space_id == ULINT_UNDEFINED || space_id == 0) {
187
+ if (space_id == ULINT_UNDEFINED || trx_sys_sys_space(space_id)) {
191
@@ -3887,7 +3887,7 @@
192
space = UT_LIST_GET_FIRST(fil_system->space_list);
195
- if (space->purpose == FIL_TABLESPACE && space->id != 0
196
+ if (space->purpose == FIL_TABLESPACE && !trx_sys_sys_space(space->id)
198
fputs("InnoDB: Warning: tablespace ", stderr);
199
ut_print_filename(stderr, space->name);
200
@@ -4462,7 +4462,7 @@
203
if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE
204
- && space->id != 0) {
205
+ && !trx_sys_sys_space(space->id)) {
206
/* The node is in the LRU list, remove it */
208
ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
209
@@ -4508,7 +4508,7 @@
212
if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE
213
- && node->space->id != 0) {
214
+ && !trx_sys_sys_space(node->space->id)) {
215
/* The node must be put back to the LRU list */
216
UT_LIST_ADD_FIRST(LRU, system->LRU, node);
218
@@ -5121,7 +5121,7 @@
219
ut_a(fil_node->n_pending == 0);
220
ut_a(fil_node->open);
221
ut_a(fil_node->space->purpose == FIL_TABLESPACE);
222
- ut_a(fil_node->space->id != 0);
223
+ ut_a(!trx_sys_sys_space(fil_node->space->id));
225
fil_node = UT_LIST_GET_NEXT(LRU, fil_node);
227
diff -ruN a/storage/innodb_plugin/fsp/fsp0fsp.c b/storage/innodb_plugin/fsp/fsp0fsp.c
228
--- a/storage/innodb_plugin/fsp/fsp0fsp.c 2010-04-06 23:07:12.000000000 +0900
229
+++ b/storage/innodb_plugin/fsp/fsp0fsp.c 2010-05-19 18:55:53.000000000 +0900
230
@@ -1002,10 +1002,10 @@
231
flst_init(header + FSP_SEG_INODES_FREE, mtr);
233
mlog_write_dulint(header + FSP_SEG_ID, ut_dulint_create(0, 1), mtr);
235
+ if (space == TRX_SYS_SPACE || space == TRX_DOUBLEWRITE_SPACE) {
236
fsp_fill_free_list(FALSE, space, header, mtr);
237
btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,
238
- 0, 0, ut_dulint_add(DICT_IBUF_ID_MIN, space),
239
+ space, 0, ut_dulint_add(DICT_IBUF_ID_MIN, space),
240
dict_ind_redundant, mtr);
242
fsp_fill_free_list(TRUE, space, header, mtr);
243
diff -ruN a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
244
--- a/storage/innodb_plugin/handler/ha_innodb.cc 2010-05-19 18:55:03.000000000 +0900
245
+++ b/storage/innodb_plugin/handler/ha_innodb.cc 2010-05-19 18:55:53.000000000 +0900
247
static char* innobase_log_group_home_dir = NULL;
248
static char* innobase_file_format_name = NULL;
249
static char* innobase_change_buffering = NULL;
250
+static char* innobase_doublewrite_path = NULL;
252
/* Note: This variable can be set to on/off and any of the supported
253
file formats in the configuration file, but can only be set to any
254
@@ -2182,6 +2183,8 @@
258
+ srv_doublewrite_path = innobase_doublewrite_path;
260
srv_extra_undoslots = (ibool) innobase_extra_undoslots;
262
/* -------------- Log files ---------------------------*/
263
@@ -11060,6 +11063,11 @@
264
"Path to individual files and their sizes.",
267
+static MYSQL_SYSVAR_STR(doublewrite_path, innobase_doublewrite_path,
268
+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
269
+ "Path to special datafile for doublewrite buffer. (default is "": not used) ### ONLY FOR EXPERTS!!! ###",
272
static MYSQL_SYSVAR_LONG(autoinc_lock_mode, innobase_autoinc_lock_mode,
273
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
274
"The AUTOINC lock modes supported by InnoDB: "
275
@@ -11216,6 +11224,7 @@
276
MYSQL_SYSVAR(commit_concurrency),
277
MYSQL_SYSVAR(concurrency_tickets),
278
MYSQL_SYSVAR(data_file_path),
279
+ MYSQL_SYSVAR(doublewrite_path),
280
MYSQL_SYSVAR(data_home_dir),
281
MYSQL_SYSVAR(doublewrite),
282
MYSQL_SYSVAR(extra_undoslots),
283
diff -ruN a/storage/innodb_plugin/handler/innodb_patch_info.h b/storage/innodb_plugin/handler/innodb_patch_info.h
284
--- a/storage/innodb_plugin/handler/innodb_patch_info.h 2010-05-19 18:55:03.000000000 +0900
285
+++ b/storage/innodb_plugin/handler/innodb_patch_info.h 2010-05-19 19:20:08.000000000 +0900
287
{"innodb_extend_slow","Extended statistics in slow.log","It is InnoDB-part only. It needs to patch also to mysqld.","http://www.percona.com/docs/wiki/percona-xtradb"},
288
{"innodb_relax_table_creation","Relax limitation of column size at table creation as builtin InnoDB.","","http://www.percona.com/docs/wiki/percona-xtradb"},
289
{"innodb_lru_dump_restore","Dump and restore command for content of buffer pool","","http://www.percona.com/docs/wiki/percona-xtradb"},
290
+{"innodb_separate_doublewrite","Add option 'innodb_doublewrite_path' to separate doublewrite dedicated tablespace","","http://www.percona.com/docs/wiki/percona-xtradb"},
291
{NULL, NULL, NULL, NULL}
293
diff -ruN a/storage/innodb_plugin/include/mtr0log.ic b/storage/innodb_plugin/include/mtr0log.ic
294
--- a/storage/innodb_plugin/include/mtr0log.ic 2010-04-06 23:07:12.000000000 +0900
295
+++ b/storage/innodb_plugin/include/mtr0log.ic 2010-05-19 18:55:53.000000000 +0900
297
the doublewrite buffer is located in pages
298
FSP_EXTENT_SIZE, ..., 3 * FSP_EXTENT_SIZE - 1 in the
300
- if (space == TRX_SYS_SPACE
301
+ if ((space == TRX_SYS_SPACE
302
+ || (srv_doublewrite_path && space == TRX_DOUBLEWRITE_SPACE))
303
&& offset >= FSP_EXTENT_SIZE && offset < 3 * FSP_EXTENT_SIZE) {
304
if (trx_doublewrite_buf_is_being_created) {
305
/* Do nothing: we only come to this branch in an
306
diff -ruN a/storage/innodb_plugin/include/srv0srv.h b/storage/innodb_plugin/include/srv0srv.h
307
--- a/storage/innodb_plugin/include/srv0srv.h 2010-05-19 18:55:03.000000000 +0900
308
+++ b/storage/innodb_plugin/include/srv0srv.h 2010-05-19 18:55:53.000000000 +0900
310
extern ulint* srv_data_file_sizes;
311
extern ulint* srv_data_file_is_raw_partition;
313
+extern char* srv_doublewrite_path;
315
extern ibool srv_extra_undoslots;
317
extern ibool srv_fast_recovery;
318
diff -ruN a/storage/innodb_plugin/include/trx0sys.h b/storage/innodb_plugin/include/trx0sys.h
319
--- a/storage/innodb_plugin/include/trx0sys.h 2010-05-19 18:55:03.000000000 +0900
320
+++ b/storage/innodb_plugin/include/trx0sys.h 2010-05-19 18:55:53.000000000 +0900
323
ulint space, /*!< in: space */
324
ulint page_no);/*!< in: page number */
325
+/***************************************************************//**
326
+Checks if a space is the system tablespaces.
327
+@return TRUE if system tablespace */
332
+ ulint space); /*!< in: space */
333
+/***************************************************************//**
334
+Checks if a space is the doublewrite tablespace.
335
+@return TRUE if doublewrite tablespace */
338
+trx_sys_doublewrite_space(
339
+/*======================*/
340
+ ulint space); /*!< in: space */
341
/*****************************************************************//**
342
Creates and initializes the central memory structures for the transaction
343
system. This is called when the database is started. */
346
trx_sys_create(void);
348
+/*****************************************************************//**
349
+Creates and initializes the dummy transaction system page for tablespace. */
352
+trx_sys_dummy_create(
353
+/*=================*/
355
/*********************************************************************
356
Create extra rollback segments when create_new_db */
360
/* Space id and page no where the trx system file copy resides */
361
#define TRX_SYS_SPACE 0 /* the SYSTEM tablespace */
362
+#define TRX_DOUBLEWRITE_SPACE 1 /* the doublewrite buffer tablespace if used */
363
+#define TRX_SYS_SPACE_MAX 9 /* reserved max space id for system tablespaces */
365
#define TRX_SYS_PAGE_NO FSP_TRX_SYS_PAGE_NO
367
diff -ruN a/storage/innodb_plugin/include/trx0sys.ic b/storage/innodb_plugin/include/trx0sys.ic
368
--- a/storage/innodb_plugin/include/trx0sys.ic 2010-04-06 23:07:13.000000000 +0900
369
+++ b/storage/innodb_plugin/include/trx0sys.ic 2010-05-19 18:55:53.000000000 +0900
373
/***************************************************************//**
374
+Checks if a space is the system tablespaces.
375
+@return TRUE if system tablespace */
380
+ ulint space) /*!< in: space */
382
+ if (srv_doublewrite_path) {
383
+ /* several spaces are reserved */
384
+ return((ibool)(space <= TRX_SYS_SPACE_MAX));
386
+ return((ibool)(space == TRX_SYS_SPACE));
390
+/***************************************************************//**
391
+Checks if a space is the doublewrite tablespace.
392
+@return TRUE if doublewrite tablespace */
395
+trx_sys_doublewrite_space(
396
+/*======================*/
397
+ ulint space) /*!< in: space */
399
+ if (srv_doublewrite_path) {
400
+ /* doublewrite buffer is separated */
401
+ return((ibool)(space == TRX_DOUBLEWRITE_SPACE));
403
+ return((ibool)(space == TRX_SYS_SPACE));
407
+/***************************************************************//**
408
Gets the pointer in the nth slot of the rseg array.
409
@return pointer to rseg object, NULL if slot not in use */
411
diff -ruN a/storage/innodb_plugin/row/row0mysql.c b/storage/innodb_plugin/row/row0mysql.c
412
--- a/storage/innodb_plugin/row/row0mysql.c 2010-05-19 18:55:03.000000000 +0900
413
+++ b/storage/innodb_plugin/row/row0mysql.c 2010-05-19 18:55:53.000000000 +0900
414
@@ -3297,7 +3297,7 @@
415
/* Do not drop possible .ibd tablespace if something went
416
wrong: we do not want to delete valuable data of the user */
418
- if (err == DB_SUCCESS && space_id > 0) {
419
+ if (err == DB_SUCCESS && !trx_sys_sys_space(space_id)) {
420
if (!fil_space_for_table_exists_in_mem(space_id,
423
diff -ruN a/storage/innodb_plugin/srv/srv0srv.c b/storage/innodb_plugin/srv/srv0srv.c
424
--- a/storage/innodb_plugin/srv/srv0srv.c 2010-05-19 18:55:03.000000000 +0900
425
+++ b/storage/innodb_plugin/srv/srv0srv.c 2010-05-19 18:55:53.000000000 +0900
427
/* size in database pages */
428
UNIV_INTERN ulint* srv_data_file_sizes = NULL;
430
+UNIV_INTERN char* srv_doublewrite_path = NULL;
432
UNIV_INTERN ibool srv_extra_undoslots = FALSE;
434
UNIV_INTERN ibool srv_fast_recovery = FALSE;
435
diff -ruN a/storage/innodb_plugin/srv/srv0start.c b/storage/innodb_plugin/srv/srv0start.c
436
--- a/storage/innodb_plugin/srv/srv0start.c 2010-05-19 18:55:03.000000000 +0900
437
+++ b/storage/innodb_plugin/srv/srv0start.c 2010-05-19 18:55:53.000000000 +0900
439
/*======================*/
440
ibool* create_new_db, /*!< out: TRUE if new database should be
442
+ ibool* create_new_doublewrite_file,
443
#ifdef UNIV_LOG_ARCHIVE
444
ulint* min_arch_log_no,/*!< out: min of archived log
445
numbers in data files */
447
*sum_of_new_sizes = 0;
449
*create_new_db = FALSE;
450
+ *create_new_doublewrite_file = FALSE;
452
srv_normalize_path_for_win(srv_data_home);
454
@@ -975,6 +977,153 @@
455
srv_data_file_is_raw_partition[i] != 0);
458
+ /* special file for doublewrite buffer */
459
+ if (srv_doublewrite_path)
463
+ srv_normalize_path_for_win(srv_doublewrite_path);
464
+ dirnamelen = strlen(srv_data_home);
467
+ "InnoDB: Notice: innodb_doublewrite_path is specified.\n"
468
+ "InnoDB: This is for expert only. Don't use if you don't understand what is it 'WELL'.\n"
469
+ "InnoDB: ### Don't specify older file than the last checkpoint ###\n"
470
+ "InnoDB: otherwise the older doublewrite buffer will break your data during recovery!\n");
472
+ ut_a(dirnamelen + strlen(srv_doublewrite_path)
473
+ < (sizeof name) - 1);
474
+ memcpy(name, srv_data_home, dirnamelen);
475
+ /* Add a path separator if needed. */
476
+ if (dirnamelen && name[dirnamelen - 1] != SRV_PATH_SEPARATOR) {
477
+ name[dirnamelen++] = SRV_PATH_SEPARATOR;
480
+ strcpy(name + dirnamelen, srv_doublewrite_path);
482
+ /* First we try to create the file: if it already
483
+ exists, ret will get value FALSE */
485
+ files[i] = os_file_create(name, OS_FILE_CREATE,
487
+ OS_DATA_FILE, &ret);
489
+ if (ret == FALSE && os_file_get_last_error(FALSE)
490
+ != OS_FILE_ALREADY_EXISTS
492
+ /* AIX 5.1 after security patch ML7 may have
493
+ errno set to 0 here, which causes our function
494
+ to return 100; work around that AIX problem */
495
+ && os_file_get_last_error(FALSE) != 100
499
+ "InnoDB: Error in creating"
500
+ " or opening %s\n",
506
+ if (ret == FALSE) {
507
+ /* We open the data file */
509
+ files[i] = os_file_create(
510
+ name, OS_FILE_OPEN, OS_FILE_NORMAL,
511
+ OS_DATA_FILE, &ret);
515
+ "InnoDB: Error in opening %s\n", name);
516
+ os_file_get_last_error(TRUE);
521
+ ret = os_file_get_size(files[i], &size, &size_high);
523
+ /* Round size downward to megabytes */
526
+ = (size / (1024 * 1024) + 4096 * size_high)
527
+ << (20 - UNIV_PAGE_SIZE_SHIFT);
529
+ if (rounded_size_pages != TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9) {
532
+ "InnoDB: Warning: doublewrite buffer file %s"
533
+ " is of a different size\n"
534
+ "InnoDB: %lu pages"
535
+ " (rounded down to MB)\n"
536
+ "InnoDB: than intended size"
539
+ (ulong) rounded_size_pages,
540
+ (ulong) TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9);
543
+ fil_read_flushed_lsn_and_arch_log_no(
544
+ files[i], one_opened,
545
+#ifdef UNIV_LOG_ARCHIVE
546
+ min_arch_log_no, max_arch_log_no,
547
+#endif /* UNIV_LOG_ARCHIVE */
548
+ min_flushed_lsn, max_flushed_lsn);
551
+ /* We created the data file and now write it full of
554
+ *create_new_doublewrite_file = TRUE;
556
+ ut_print_timestamp(stderr);
558
+ " InnoDB: Doublewrite buffer file %s did not"
559
+ " exist: new to be created\n",
562
+ if (*create_new_db == FALSE) {
564
+ "InnoDB: Warning: Previous version's ibdata files may cause crash.\n"
565
+ " If you use that, please use the ibdata files of this version.\n");
568
+ ut_print_timestamp(stderr);
570
+ " InnoDB: Setting file %s size to %lu MB\n",
572
+ (ulong) ((TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9)
573
+ >> (20 - UNIV_PAGE_SIZE_SHIFT)));
576
+ "InnoDB: Database physically writes the"
577
+ " file full: wait...\n");
579
+ ret = os_file_set_size(
581
+ srv_calc_low32(TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9),
582
+ srv_calc_high32(TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9));
586
+ "InnoDB: Error in creating %s:"
587
+ " probably out of disk space\n", name);
593
+ ret = os_file_close(files[i]);
596
+ fil_space_create(name, TRX_DOUBLEWRITE_SPACE, 0, FIL_TABLESPACE);
598
+ ut_a(fil_validate());
600
+ fil_node_create(name, TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9, TRX_DOUBLEWRITE_SPACE, FALSE);
607
mutex_create(&ios_mutex, SYNC_NO_ORDER_CHECK);
612
+ ibool create_new_doublewrite_file;
613
ibool log_file_created;
614
ibool log_created = FALSE;
615
ibool log_opened = FALSE;
616
@@ -1381,6 +1531,7 @@
619
err = open_or_create_data_files(&create_new_db,
620
+ &create_new_doublewrite_file,
621
#ifdef UNIV_LOG_ARCHIVE
622
&min_arch_log_no, &max_arch_log_no,
623
#endif /* UNIV_LOG_ARCHIVE */
624
@@ -1497,6 +1648,14 @@
626
trx_sys_file_format_init();
628
+ if (create_new_doublewrite_file) {
630
+ fsp_header_init(TRX_DOUBLEWRITE_SPACE, TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 9, &mtr);
633
+ trx_sys_dummy_create(TRX_DOUBLEWRITE_SPACE);
638
fsp_header_init(0, sum_of_new_sizes, &mtr);
639
diff -ruN a/storage/innodb_plugin/trx/trx0sys.c b/storage/innodb_plugin/trx/trx0sys.c
640
--- a/storage/innodb_plugin/trx/trx0sys.c 2010-05-19 18:55:03.000000000 +0900
641
+++ b/storage/innodb_plugin/trx/trx0sys.c 2010-05-19 18:55:53.000000000 +0900
642
@@ -402,6 +402,149 @@
647
+ if (srv_doublewrite_path) {
648
+ /* the same doublewrite buffer to TRX_SYS_SPACE should exist.
649
+ check and create if not exist.*/
652
+ trx_doublewrite_buf_is_being_created = TRUE;
654
+ block = buf_page_get(TRX_DOUBLEWRITE_SPACE, 0, TRX_SYS_PAGE_NO,
656
+ buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
658
+ doublewrite = buf_block_get_frame(block) + TRX_SYS_DOUBLEWRITE;
660
+ if (mach_read_from_4(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC)
661
+ == TRX_SYS_DOUBLEWRITE_MAGIC_N) {
662
+ /* The doublewrite buffer has already been created:
663
+ just read in some numbers */
668
+ "InnoDB: Doublewrite buffer not found in the doublewrite file:"
669
+ " creating new\n");
671
+ if (buf_pool_get_curr_size()
672
+ < ((2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
673
+ + FSP_EXTENT_SIZE / 2 + 100)
674
+ * UNIV_PAGE_SIZE)) {
676
+ "InnoDB: Cannot create doublewrite buffer:"
678
+ "InnoDB: increase your buffer pool size.\n"
679
+ "InnoDB: Cannot continue operation.\n");
684
+ block2 = fseg_create(TRX_DOUBLEWRITE_SPACE, TRX_SYS_PAGE_NO,
685
+ TRX_SYS_DOUBLEWRITE
686
+ + TRX_SYS_DOUBLEWRITE_FSEG, &mtr);
688
+ /* fseg_create acquires a second latch on the page,
689
+ therefore we must declare it: */
691
+ buf_block_dbg_add_level(block2, SYNC_NO_ORDER_CHECK);
693
+ if (block2 == NULL) {
695
+ "InnoDB: Cannot create doublewrite buffer:"
697
+ "InnoDB: increase your tablespace size.\n"
698
+ "InnoDB: Cannot continue operation.\n");
700
+ /* We exit without committing the mtr to prevent
701
+ its modifications to the database getting to disk */
706
+ fseg_header = buf_block_get_frame(block)
707
+ + TRX_SYS_DOUBLEWRITE + TRX_SYS_DOUBLEWRITE_FSEG;
710
+ for (i = 0; i < 2 * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
711
+ + FSP_EXTENT_SIZE / 2; i++) {
712
+ page_no = fseg_alloc_free_page(fseg_header,
715
+ if (page_no == FIL_NULL) {
717
+ "InnoDB: Cannot create doublewrite"
718
+ " buffer: you must\n"
719
+ "InnoDB: increase your"
720
+ " tablespace size.\n"
721
+ "InnoDB: Cannot continue operation.\n"
727
+ /* We read the allocated pages to the buffer pool;
728
+ when they are written to disk in a flush, the space
729
+ id and page number fields are also written to the
730
+ pages. When we at database startup read pages
731
+ from the doublewrite buffer, we know that if the
732
+ space id and page number in them are the same as
733
+ the page position in the tablespace, then the page
734
+ has not been written to in doublewrite. */
736
+ new_block = buf_page_get(TRX_DOUBLEWRITE_SPACE, 0, page_no,
738
+ buf_block_dbg_add_level(new_block,
739
+ SYNC_NO_ORDER_CHECK);
741
+ if (i == FSP_EXTENT_SIZE / 2) {
742
+ ut_a(page_no == FSP_EXTENT_SIZE);
743
+ mlog_write_ulint(doublewrite
744
+ + TRX_SYS_DOUBLEWRITE_BLOCK1,
745
+ page_no, MLOG_4BYTES, &mtr);
746
+ mlog_write_ulint(doublewrite
747
+ + TRX_SYS_DOUBLEWRITE_REPEAT
748
+ + TRX_SYS_DOUBLEWRITE_BLOCK1,
749
+ page_no, MLOG_4BYTES, &mtr);
750
+ } else if (i == FSP_EXTENT_SIZE / 2
751
+ + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
752
+ ut_a(page_no == 2 * FSP_EXTENT_SIZE);
753
+ mlog_write_ulint(doublewrite
754
+ + TRX_SYS_DOUBLEWRITE_BLOCK2,
755
+ page_no, MLOG_4BYTES, &mtr);
756
+ mlog_write_ulint(doublewrite
757
+ + TRX_SYS_DOUBLEWRITE_REPEAT
758
+ + TRX_SYS_DOUBLEWRITE_BLOCK2,
759
+ page_no, MLOG_4BYTES, &mtr);
760
+ } else if (i > FSP_EXTENT_SIZE / 2) {
761
+ ut_a(page_no == prev_page_no + 1);
764
+ prev_page_no = page_no;
767
+ mlog_write_ulint(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC,
768
+ TRX_SYS_DOUBLEWRITE_MAGIC_N,
769
+ MLOG_4BYTES, &mtr);
770
+ mlog_write_ulint(doublewrite + TRX_SYS_DOUBLEWRITE_MAGIC
771
+ + TRX_SYS_DOUBLEWRITE_REPEAT,
772
+ TRX_SYS_DOUBLEWRITE_MAGIC_N,
773
+ MLOG_4BYTES, &mtr);
775
+ mlog_write_ulint(doublewrite
776
+ + TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED,
777
+ TRX_SYS_DOUBLEWRITE_SPACE_ID_STORED_N,
778
+ MLOG_4BYTES, &mtr);
781
+ /* Flush the modified pages to disk and make a checkpoint */
782
+ log_make_checkpoint_at(IB_ULONGLONG_MAX, TRUE);
784
+ fprintf(stderr, "InnoDB: Doublewrite buffer created in the doublewrite file\n");
787
+ trx_doublewrite_buf_is_being_created = FALSE;
791
/****************************************************************//**
792
@@ -425,10 +568,19 @@
793
ulint source_page_no;
796
+ ulint doublewrite_space_id;
801
+ doublewrite_space_id = (srv_doublewrite_path ? TRX_DOUBLEWRITE_SPACE : TRX_SYS_SPACE);
803
+ if (srv_doublewrite_path) {
805
+ "InnoDB: doublewrite file '%s' is used.\n",
806
+ srv_doublewrite_path);
809
/* We do the file i/o past the buffer pool */
811
unaligned_read_buf = ut_malloc(2 * UNIV_PAGE_SIZE);
813
/* Read the trx sys header to check if we are using the doublewrite
816
- fil_io(OS_FILE_READ, TRUE, TRX_SYS_SPACE, 0, TRX_SYS_PAGE_NO, 0,
817
+ fil_io(OS_FILE_READ, TRUE, doublewrite_space_id, 0, TRX_SYS_PAGE_NO, 0,
818
UNIV_PAGE_SIZE, read_buf, NULL);
819
doublewrite = read_buf + TRX_SYS_DOUBLEWRITE;
821
@@ -475,10 +627,10 @@
823
/* Read the pages from the doublewrite buffer to memory */
825
- fil_io(OS_FILE_READ, TRUE, TRX_SYS_SPACE, 0, block1, 0,
826
+ fil_io(OS_FILE_READ, TRUE, doublewrite_space_id, 0, block1, 0,
827
TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE,
829
- fil_io(OS_FILE_READ, TRUE, TRX_SYS_SPACE, 0, block2, 0,
830
+ fil_io(OS_FILE_READ, TRUE, doublewrite_space_id, 0, block2, 0,
831
TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE,
832
buf + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE,
835
" doublewrite buf.\n",
836
(ulong) space_id, (ulong) page_no, (ulong) i);
838
- } else if (space_id == TRX_SYS_SPACE
839
+ } else if ((space_id == TRX_SYS_SPACE
840
+ || (srv_doublewrite_path && space_id == TRX_DOUBLEWRITE_SPACE))
841
&& ((page_no >= block1
843
< block1 + TRX_SYS_DOUBLEWRITE_BLOCK_SIZE)
844
@@ -982,6 +1135,87 @@
847
/*****************************************************************//**
848
+Creates dummy of the file page for the transaction system. */
851
+trx_sysf_dummy_create(
852
+/*==================*/
856
+ trx_sysf_t* sys_header;
858
+ buf_block_t* block;
865
+ /* Note that below we first reserve the file space x-latch, and
866
+ then enter the kernel: we must do it in this order to conform
867
+ to the latching order rules. */
869
+ mtr_x_lock(fil_space_get_latch(space, NULL), mtr);
870
+ mutex_enter(&kernel_mutex);
872
+ /* Create the trx sys file block in a new allocated file segment */
873
+ block = fseg_create(space, 0, TRX_SYS + TRX_SYS_FSEG_HEADER,
875
+ buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER);
877
+ fprintf(stderr, "%lu\n", buf_block_get_page_no(block));
878
+ ut_a(buf_block_get_page_no(block) == TRX_SYS_PAGE_NO);
880
+ page = buf_block_get_frame(block);
882
+ mlog_write_ulint(page + FIL_PAGE_TYPE, FIL_PAGE_TYPE_TRX_SYS,
885
+ /* Reset the doublewrite buffer magic number to zero so that we
886
+ know that the doublewrite buffer has not yet been created (this
887
+ suppresses a Valgrind warning) */
889
+ mlog_write_ulint(page + TRX_SYS_DOUBLEWRITE
890
+ + TRX_SYS_DOUBLEWRITE_MAGIC, 0, MLOG_4BYTES, mtr);
893
+ /* TODO: REMOVE IT: The bellow is not needed, I think */
894
+ sys_header = trx_sysf_get(mtr);
896
+ /* Start counting transaction ids from number 1 up */
897
+ mlog_write_dulint(sys_header + TRX_SYS_TRX_ID_STORE,
898
+ ut_dulint_create(0, 1), mtr);
900
+ /* Reset the rollback segment slots */
901
+ for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
903
+ trx_sysf_rseg_set_space(sys_header, i, ULINT_UNDEFINED, mtr);
904
+ trx_sysf_rseg_set_page_no(sys_header, i, FIL_NULL, mtr);
907
+ /* The remaining area (up to the page trailer) is uninitialized.
908
+ Silence Valgrind warnings about it. */
909
+ UNIV_MEM_VALID(sys_header + (TRX_SYS_RSEGS
910
+ + TRX_SYS_N_RSEGS * TRX_SYS_RSEG_SLOT_SIZE
911
+ + TRX_SYS_RSEG_SPACE),
912
+ (UNIV_PAGE_SIZE - FIL_PAGE_DATA_END
914
+ + TRX_SYS_N_RSEGS * TRX_SYS_RSEG_SLOT_SIZE
915
+ + TRX_SYS_RSEG_SPACE))
916
+ + page - sys_header);
918
+ /* Create the first rollback segment in the SYSTEM tablespace */
919
+ page_no = trx_rseg_header_create(space, 0, ULINT_MAX, &slot_no,
921
+ ut_a(slot_no == TRX_SYS_SYSTEM_RSEG_ID);
922
+ ut_a(page_no != FIL_NULL);
925
+ mutex_exit(&kernel_mutex);
928
+/*****************************************************************//**
929
Creates and initializes the central memory structures for the transaction
930
system. This is called when the database is started. */
932
@@ -1087,6 +1321,26 @@
933
trx_sys_init_at_db_start();
936
+/*****************************************************************//**
937
+Creates and initializes the dummy transaction system page for tablespace. */
940
+trx_sys_dummy_create(
941
+/*=================*/
946
+ /* This function is only for doublewrite file for now */
947
+ ut_a(space == TRX_DOUBLEWRITE_SPACE);
951
+ trx_sysf_dummy_create(space, &mtr);
956
/*********************************************************************
957
Create extra rollback segments when create_new_db */