Skip to content

Commit 5b3c100

Browse files
committed
Merge branch 'merge/merge-innodb-5.6' into 10.0
2 parents 1623995 + e9eaaa4 commit 5b3c100

File tree

11 files changed

+388
-83
lines changed

11 files changed

+388
-83
lines changed

storage/innobase/btr/btr0btr.cc

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*****************************************************************************
22
3-
Copyright (c) 1994, 2013, Oracle and/or its affiliates. All Rights Reserved.
3+
Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved.
44
Copyright (c) 2012, Facebook Inc.
55
66
This program is free software; you can redistribute it and/or modify it under
@@ -2101,7 +2101,7 @@ the tuple. It is assumed that mtr contains an x-latch on the tree.
21012101
NOTE that the operation of this function must always succeed,
21022102
we cannot reverse it: therefore enough free disk space must be
21032103
guaranteed to be available before this function is called.
2104-
@return inserted record */
2104+
@return inserted record or NULL if run out of space */
21052105
UNIV_INTERN
21062106
rec_t*
21072107
btr_root_raise_and_insert(
@@ -2162,6 +2162,11 @@ btr_root_raise_and_insert(
21622162
level = btr_page_get_level(root, mtr);
21632163

21642164
new_block = btr_page_alloc(index, 0, FSP_NO_DIR, level, mtr, mtr);
2165+
2166+
if (new_block == NULL && os_has_said_disk_full) {
2167+
return(NULL);
2168+
}
2169+
21652170
new_page = buf_block_get_frame(new_block);
21662171
new_page_zip = buf_block_get_page_zip(new_block);
21672172
ut_a(!new_page_zip == !root_page_zip);
@@ -2938,7 +2943,7 @@ function must always succeed, we cannot reverse it: therefore enough
29382943
free disk space (2 pages) must be guaranteed to be available before
29392944
this function is called.
29402945
2941-
@return inserted record */
2946+
@return inserted record or NULL if run out of space */
29422947
UNIV_INTERN
29432948
rec_t*
29442949
btr_page_split_and_insert(
@@ -3052,9 +3057,18 @@ btr_page_split_and_insert(
30523057
}
30533058
}
30543059

3060+
DBUG_EXECUTE_IF("disk_is_full",
3061+
os_has_said_disk_full = true;
3062+
return(NULL););
3063+
30553064
/* 2. Allocate a new page to the index */
30563065
new_block = btr_page_alloc(cursor->index, hint_page_no, direction,
30573066
btr_page_get_level(page, mtr), mtr, mtr);
3067+
3068+
if (new_block == NULL && os_has_said_disk_full) {
3069+
return(NULL);
3070+
}
3071+
30583072
new_page = buf_block_get_frame(new_block);
30593073
new_page_zip = buf_block_get_page_zip(new_block);
30603074
btr_page_create(new_block, new_page_zip, cursor->index,

storage/innobase/btr/btr0cur.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,6 +1605,10 @@ btr_cur_pessimistic_insert(
16051605
flags, cursor, offsets, heap, entry, n_ext, mtr);
16061606
}
16071607

1608+
if (*rec == NULL && os_has_said_disk_full) {
1609+
return(DB_OUT_OF_FILE_SPACE);
1610+
}
1611+
16081612
ut_ad(page_rec_get_next(btr_cur_get_rec(cursor)) == *rec);
16091613

16101614
if (!(flags & BTR_NO_LOCKING_FLAG)) {

storage/innobase/dict/dict0dict.cc

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1628,10 +1628,13 @@ dict_table_rename_in_cache(
16281628
to preserve the original table name
16291629
in constraints which reference it */
16301630
{
1631+
dberr_t err;
16311632
dict_foreign_t* foreign;
16321633
dict_index_t* index;
16331634
ulint fold;
16341635
char old_name[MAX_FULL_NAME_LEN + 1];
1636+
os_file_type_t ftype;
1637+
ibool exists;
16351638

16361639
ut_ad(mutex_own(&(dict_sys->mutex)));
16371640

@@ -1669,8 +1672,6 @@ dict_table_rename_in_cache(
16691672
.ibd file and rebuild the .isl file if needed. */
16701673

16711674
if (dict_table_is_discarded(table)) {
1672-
os_file_type_t type;
1673-
ibool exists;
16741675
char* filepath;
16751676

16761677
ut_ad(table->space != TRX_SYS_SPACE);
@@ -1689,7 +1690,7 @@ dict_table_rename_in_cache(
16891690
fil_delete_tablespace(table->space, BUF_REMOVE_ALL_NO_WRITE);
16901691

16911692
/* Delete any temp file hanging around. */
1692-
if (os_file_status(filepath, &exists, &type)
1693+
if (os_file_status(filepath, &exists, &ftype)
16931694
&& exists
16941695
&& !os_file_delete_if_exists(innodb_file_temp_key,
16951696
filepath)) {
@@ -1701,8 +1702,6 @@ dict_table_rename_in_cache(
17011702
mem_free(filepath);
17021703

17031704
} else if (table->space != TRX_SYS_SPACE) {
1704-
char* new_path = NULL;
1705-
17061705
if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_TEMPORARY)) {
17071706
ut_print_timestamp(stderr);
17081707
fputs(" InnoDB: Error: trying to rename a"
@@ -1716,34 +1715,43 @@ dict_table_rename_in_cache(
17161715
}
17171716

17181717
return(DB_ERROR);
1718+
}
17191719

1720-
} else if (DICT_TF_HAS_DATA_DIR(table->flags)) {
1721-
char* old_path;
1722-
1723-
old_path = fil_space_get_first_path(table->space);
1720+
char* new_path = NULL;
1721+
char* old_path = fil_space_get_first_path(table->space);
17241722

1723+
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
17251724
new_path = os_file_make_new_pathname(
17261725
old_path, new_name);
17271726

1728-
mem_free(old_path);
1729-
1730-
dberr_t err = fil_create_link_file(
1731-
new_name, new_path);
1732-
1727+
err = fil_create_link_file(new_name, new_path);
17331728
if (err != DB_SUCCESS) {
17341729
mem_free(new_path);
1730+
mem_free(old_path);
17351731
return(DB_TABLESPACE_EXISTS);
17361732
}
1733+
} else {
1734+
new_path = fil_make_ibd_name(new_name, false);
1735+
}
1736+
1737+
/* New filepath must not exist. */
1738+
err = fil_rename_tablespace_check(
1739+
table->space, old_path, new_path, false);
1740+
if (err != DB_SUCCESS) {
1741+
mem_free(old_path);
1742+
mem_free(new_path);
1743+
return(err);
17371744
}
17381745

17391746
ibool success = fil_rename_tablespace(
17401747
old_name, table->space, new_name, new_path);
17411748

1749+
mem_free(old_path);
1750+
mem_free(new_path);
1751+
17421752
/* If the tablespace is remote, a new .isl file was created
17431753
If success, delete the old one. If not, delete the new one. */
1744-
if (new_path) {
1745-
1746-
mem_free(new_path);
1754+
if (DICT_TF_HAS_DATA_DIR(table->flags)) {
17471755
fil_delete_link_file(success ? old_name : new_name);
17481756
}
17491757

storage/innobase/fil/fil0fil.cc

Lines changed: 140 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2821,6 +2821,48 @@ fil_make_isl_name(
28212821
return(filename);
28222822
}
28232823

2824+
/** Test if a tablespace file can be renamed to a new filepath by checking
2825+
if that the old filepath exists and the new filepath does not exist.
2826+
@param[in] space_id tablespace id
2827+
@param[in] old_path old filepath
2828+
@param[in] new_path new filepath
2829+
@param[in] is_discarded whether the tablespace is discarded
2830+
@return innodb error code */
2831+
dberr_t
2832+
fil_rename_tablespace_check(
2833+
ulint space_id,
2834+
const char* old_path,
2835+
const char* new_path,
2836+
bool is_discarded)
2837+
{
2838+
ulint exists = false;
2839+
os_file_type_t ftype;
2840+
2841+
if (!is_discarded
2842+
&& os_file_status(old_path, &exists, &ftype)
2843+
&& !exists) {
2844+
ib_logf(IB_LOG_LEVEL_ERROR,
2845+
"Cannot rename '%s' to '%s' for space ID %lu"
2846+
" because the source file does not exist.",
2847+
old_path, new_path, space_id);
2848+
2849+
return(DB_TABLESPACE_NOT_FOUND);
2850+
}
2851+
2852+
exists = false;
2853+
if (!os_file_status(new_path, &exists, &ftype) || exists) {
2854+
ib_logf(IB_LOG_LEVEL_ERROR,
2855+
"Cannot rename '%s' to '%s' for space ID %lu"
2856+
" because the target file exists."
2857+
" Remove the target file and try again.",
2858+
old_path, new_path, space_id);
2859+
2860+
return(DB_TABLESPACE_EXISTS);
2861+
}
2862+
2863+
return(DB_SUCCESS);
2864+
}
2865+
28242866
/*******************************************************************//**
28252867
Renames a single-table tablespace. The tablespace must be cached in the
28262868
tablespace memory cache.
@@ -6400,29 +6442,108 @@ fil_get_space_names(
64006442
return(err);
64016443
}
64026444

6403-
/****************************************************************//**
6404-
Generate redo logs for swapping two .ibd files */
6445+
/** Generate redo log for swapping two .ibd files
6446+
@param[in] old_table old table
6447+
@param[in] new_table new table
6448+
@param[in] tmp_name temporary table name
6449+
@param[in,out] mtr mini-transaction
6450+
@return innodb error code */
64056451
UNIV_INTERN
6406-
void
6452+
dberr_t
64076453
fil_mtr_rename_log(
6408-
/*===============*/
6409-
ulint old_space_id, /*!< in: tablespace id of the old
6410-
table. */
6411-
const char* old_name, /*!< in: old table name */
6412-
ulint new_space_id, /*!< in: tablespace id of the new
6413-
table */
6414-
const char* new_name, /*!< in: new table name */
6415-
const char* tmp_name, /*!< in: temp table name used while
6416-
swapping */
6417-
mtr_t* mtr) /*!< in/out: mini-transaction */
6454+
const dict_table_t* old_table,
6455+
const dict_table_t* new_table,
6456+
const char* tmp_name,
6457+
mtr_t* mtr)
64186458
{
6419-
if (old_space_id != TRX_SYS_SPACE) {
6420-
fil_op_write_log(MLOG_FILE_RENAME, old_space_id,
6421-
0, 0, old_name, tmp_name, mtr);
6459+
dberr_t err = DB_SUCCESS;
6460+
char* old_path;
6461+
6462+
/* If neither table is file-per-table,
6463+
there will be no renaming of files. */
6464+
if (old_table->space == TRX_SYS_SPACE
6465+
&& new_table->space == TRX_SYS_SPACE) {
6466+
return(DB_SUCCESS);
6467+
}
6468+
6469+
if (DICT_TF_HAS_DATA_DIR(old_table->flags)) {
6470+
old_path = os_file_make_remote_pathname(
6471+
old_table->data_dir_path, old_table->name, "ibd");
6472+
} else {
6473+
old_path = fil_make_ibd_name(old_table->name, false);
6474+
}
6475+
if (old_path == NULL) {
6476+
return(DB_OUT_OF_MEMORY);
6477+
}
6478+
6479+
if (old_table->space != TRX_SYS_SPACE) {
6480+
char* tmp_path;
6481+
6482+
if (DICT_TF_HAS_DATA_DIR(old_table->flags)) {
6483+
tmp_path = os_file_make_remote_pathname(
6484+
old_table->data_dir_path, tmp_name, "ibd");
6485+
}
6486+
else {
6487+
tmp_path = fil_make_ibd_name(tmp_name, false);
6488+
}
6489+
6490+
if (tmp_path == NULL) {
6491+
mem_free(old_path);
6492+
return(DB_OUT_OF_MEMORY);
6493+
}
6494+
6495+
/* Temp filepath must not exist. */
6496+
err = fil_rename_tablespace_check(
6497+
old_table->space, old_path, tmp_path,
6498+
dict_table_is_discarded(old_table));
6499+
mem_free(tmp_path);
6500+
if (err != DB_SUCCESS) {
6501+
mem_free(old_path);
6502+
return(err);
6503+
}
6504+
6505+
fil_op_write_log(MLOG_FILE_RENAME, old_table->space,
6506+
0, 0, old_table->name, tmp_name, mtr);
64226507
}
64236508

6424-
if (new_space_id != TRX_SYS_SPACE) {
6425-
fil_op_write_log(MLOG_FILE_RENAME, new_space_id,
6426-
0, 0, new_name, old_name, mtr);
6509+
if (new_table->space != TRX_SYS_SPACE) {
6510+
6511+
/* Destination filepath must not exist unless this ALTER
6512+
TABLE starts and ends with a file_per-table tablespace. */
6513+
if (old_table->space == TRX_SYS_SPACE) {
6514+
char* new_path = NULL;
6515+
6516+
if (DICT_TF_HAS_DATA_DIR(new_table->flags)) {
6517+
new_path = os_file_make_remote_pathname(
6518+
new_table->data_dir_path,
6519+
new_table->name, "ibd");
6520+
}
6521+
else {
6522+
new_path = fil_make_ibd_name(
6523+
new_table->name, false);
6524+
}
6525+
6526+
if (new_path == NULL) {
6527+
mem_free(old_path);
6528+
return(DB_OUT_OF_MEMORY);
6529+
}
6530+
6531+
err = fil_rename_tablespace_check(
6532+
new_table->space, new_path, old_path,
6533+
dict_table_is_discarded(new_table));
6534+
mem_free(new_path);
6535+
if (err != DB_SUCCESS) {
6536+
mem_free(old_path);
6537+
return(err);
6538+
}
6539+
}
6540+
6541+
fil_op_write_log(MLOG_FILE_RENAME, new_table->space,
6542+
0, 0, new_table->name, old_table->name, mtr);
6543+
64276544
}
6545+
6546+
mem_free(old_path);
6547+
6548+
return(err);
64286549
}

storage/innobase/fsp/fsp0fsp.cc

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -952,10 +952,20 @@ fsp_try_extend_data_file(
952952
}
953953
} else {
954954
/* We extend single-table tablespaces first one extent
955-
at a time, but for bigger tablespaces more. It is not
956-
enough to extend always by one extent, because some
957-
extents are frag page extents. */
955+
at a time, but 4 at a time for bigger tablespaces. It is
956+
not enough to extend always by one extent, because we need
957+
to add at least one extent to FSP_FREE.
958+
A single extent descriptor page will track many extents.
959+
And the extent that uses its extent descriptor page is
960+
put onto the FSP_FREE_FRAG list. Extents that do not
961+
use their extent descriptor page are added to FSP_FREE.
962+
The physical page size is used to determine how many
963+
extents are tracked on one extent descriptor page. */
958964
ulint extent_size; /*!< one megabyte, in pages */
965+
ulint threshold; /*!< The size of the tablespace
966+
(in number of pages) where we
967+
start allocating more than one
968+
extent at a time. */
959969

960970
if (!zip_size) {
961971
extent_size = FSP_EXTENT_SIZE;
@@ -964,6 +974,14 @@ fsp_try_extend_data_file(
964974
* UNIV_PAGE_SIZE / zip_size;
965975
}
966976

977+
/* Threshold is set at 32mb except when the page
978+
size is small enough that it must be done sooner.
979+
For page size less than 4k, we may reach the
980+
extent contains extent descriptor page before
981+
32 mb. */
982+
threshold = ut_min((32 * extent_size),
983+
(zip_size ? zip_size : UNIV_PAGE_SIZE));
984+
967985
if (size < extent_size) {
968986
/* Let us first extend the file to extent_size */
969987
success = fsp_try_extend_data_file_with_pages(
@@ -980,7 +998,7 @@ fsp_try_extend_data_file(
980998
size = extent_size;
981999
}
9821000

983-
if (size < 32 * extent_size) {
1001+
if (size < threshold) {
9841002
size_increase = extent_size;
9851003
} else {
9861004
/* Below in fsp_fill_free_list() we assume

0 commit comments

Comments
 (0)