Skip to content

Commit a3c7abf

Browse files
author
Shaohua Wang
committed
BUG#17339606 - INNODDB - FTS CREATE INDEX FAILS WITH INCORRECT KEY FILE ERROR
The root cause is out of temp table space, but the error message is misleading. In this patch, we change error message to temporary file write failure, and make fts index build stop as soon as error occurs. rb://3211 approved by Jimmy.Yang
1 parent 71ea45a commit a3c7abf

11 files changed

Lines changed: 96 additions & 16 deletions

File tree

include/my_base.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,8 @@ is the global server default. */
481481
#define HA_ERR_ROW_IN_WRONG_PARTITION 186 /* Row in wrong partition */
482482
#define HA_ERR_INNODB_READ_ONLY 187 /* InnoDB is in read only mode. */
483483
#define HA_ERR_FTS_EXCEED_RESULT_CACHE_LIMIT 188 /* FTS query exceeds result cache limit */
484-
#define HA_ERR_LAST 188 /* Copy of last error nr */
484+
#define HA_ERR_TEMP_FILE_WRITE_FAILURE 189 /* Temporary file write failure */
485+
#define HA_ERR_LAST 189 /* Copy of last error nr */
485486

486487
/* Number of different errors */
487488
#define HA_ERR_ERRORS (HA_ERR_LAST - HA_ERR_FIRST + 1)

mysys/my_handler_errors.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ static const char *handler_error_messages[]=
9191
"Too many columns",
9292
"Row in wrong partition",
9393
"InnoDB is in read only mode",
94-
"FTS query exceeds result cache memory limit"
94+
"FTS query exceeds result cache memory limit",
95+
"Temporary file write failure"
9596
};
9697

9798
extern void my_handler_error_register(void);

sql/handler.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ int ha_init_errors(void)
555555
SETMSG(HA_ERR_TABLE_IN_FK_CHECK, ER_DEFAULT(ER_TABLE_IN_FK_CHECK));
556556
SETMSG(HA_ERR_TABLESPACE_EXISTS, "Tablespace already exists");
557557
SETMSG(HA_ERR_FTS_EXCEED_RESULT_CACHE_LIMIT, "FTS query exceeds result cache limit");
558+
SETMSG(HA_ERR_TEMP_FILE_WRITE_FAILURE, ER_DEFAULT(ER_TEMP_FILE_WRITE_FAILURE));
558559

559560
/* Register the error messages for use with my_error(). */
560561
return my_error_register(get_handler_errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
@@ -3705,6 +3706,9 @@ void handler::print_error(int error, myf errflag)
37053706
case HA_ERR_INNODB_READ_ONLY:
37063707
textno= ER_INNODB_READ_ONLY;
37073708
break;
3709+
case HA_ERR_TEMP_FILE_WRITE_FAILURE:
3710+
textno= ER_TEMP_FILE_WRITE_FAILURE;
3711+
break;
37083712
default:
37093713
{
37103714
/* The error was "unknown" to this function.

sql/share/errmsg-utf8.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7085,6 +7085,9 @@ ER_STOP_SLAVE_IO_THREAD_TIMEOUT
70857085
ER_TABLE_CORRUPT
70867086
eng "Operation cannot be performed. The table '%-.64s.%-.64s' is missing, corrupt or contains bad data."
70877087

7088+
ER_TEMP_FILE_WRITE_FAILURE
7089+
eng "Temporary file write failure."
7090+
70887091
#
70897092
# End of 5.6 error messages.
70907093
#

storage/innobase/handler/ha_innodb.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,6 +1443,9 @@ convert_error_code_to_mysql(
14431443
case DB_OUT_OF_FILE_SPACE:
14441444
return(HA_ERR_RECORD_FILE_FULL);
14451445

1446+
case DB_TEMP_FILE_WRITE_FAILURE:
1447+
return(HA_ERR_TEMP_FILE_WRITE_FAILURE);
1448+
14461449
case DB_TABLE_IN_FK_CHECK:
14471450
return(HA_ERR_TABLE_IN_FK_CHECK);
14481451

storage/innobase/handler/handler0alter.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ my_error_innodb(
126126
case DB_OUT_OF_FILE_SPACE:
127127
my_error(ER_RECORD_FILE_FULL, MYF(0), table);
128128
break;
129+
case DB_TEMP_FILE_WRITE_FAILURE:
130+
my_error(ER_TEMP_FILE_WRITE_FAILURE, MYF(0));
131+
break;
129132
case DB_TOO_BIG_INDEX_COL:
130133
my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
131134
DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));

storage/innobase/include/db0err.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ enum dberr_t {
127127
DB_IDENTIFIER_TOO_LONG, /*!< Identifier name too long */
128128
DB_FTS_EXCEED_RESULT_CACHE_LIMIT, /*!< FTS query memory
129129
exceeds result cache limit */
130+
DB_TEMP_FILE_WRITE_FAILURE, /*!< Temp file write failure */
130131

131132
/* The following are partial failure codes */
132133
DB_FAIL = 1000,

storage/innobase/include/row0ftsort.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ struct fts_psort_t {
8888
fts_doc_list_t fts_doc_list; /*!< doc list to process */
8989
fts_psort_common_t* psort_common; /*!< ptr to all psort info */
9090
os_thread_t thread_hdl; /*!< thread handler */
91+
dberr_t error; /*!< db error during psort */
9192
};
9293

9394
/** Structure stores information from string tokenization operation */
@@ -124,6 +125,7 @@ typedef struct fts_psort_insert fts_psort_insert_t;
124125

125126
/** status bit used for communication between parent and child thread */
126127
#define FTS_PARENT_COMPLETE 1
128+
#define FTS_PARENT_EXITING 2
127129
#define FTS_CHILD_COMPLETE 1
128130
#define FTS_CHILD_EXITING 2
129131

storage/innobase/row/row0ftsort.cc

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ row_fts_psort_info_init(
265265
psort_info[j].child_status = 0;
266266
psort_info[j].state = 0;
267267
psort_info[j].psort_common = common_info;
268+
psort_info[j].error = DB_SUCCESS;
268269
}
269270

270271
/* Initialize merge_info structures parallel merge and insert
@@ -707,9 +708,14 @@ fts_parallel_tokenization(
707708
row_merge_buf_write(buf[t_ctx.buf_used],
708709
merge_file[t_ctx.buf_used],
709710
block[t_ctx.buf_used]);
710-
row_merge_write(merge_file[t_ctx.buf_used]->fd,
711-
merge_file[t_ctx.buf_used]->offset++,
712-
block[t_ctx.buf_used]);
711+
712+
if (!row_merge_write(merge_file[t_ctx.buf_used]->fd,
713+
merge_file[t_ctx.buf_used]->offset++,
714+
block[t_ctx.buf_used])) {
715+
psort_info->error = DB_TEMP_FILE_WRITE_FAILURE;
716+
goto func_exit;
717+
}
718+
713719
UNIV_MEM_INVALID(block[t_ctx.buf_used][0], srv_sort_buf_size);
714720
buf[t_ctx.buf_used] = row_merge_buf_empty(buf[t_ctx.buf_used]);
715721
mycount[t_ctx.buf_used] += t_ctx.rows_added[t_ctx.buf_used];
@@ -735,6 +741,9 @@ fts_parallel_tokenization(
735741
psort_info->fts_doc_list));
736742
goto exit;
737743
}
744+
} else if (psort_info->state == FTS_PARENT_EXITING) {
745+
/* Parent abort */
746+
goto func_exit;
738747
}
739748

740749
if (doc_item) {
@@ -799,9 +808,12 @@ fts_parallel_tokenization(
799808
never flush to temp file, it can be held all in
800809
memory */
801810
if (merge_file[i]->offset != 0) {
802-
row_merge_write(merge_file[i]->fd,
811+
if (!row_merge_write(merge_file[i]->fd,
803812
merge_file[i]->offset++,
804-
block[i]);
813+
block[i])) {
814+
psort_info->error = DB_TEMP_FILE_WRITE_FAILURE;
815+
goto func_exit;
816+
}
805817

806818
UNIV_MEM_INVALID(block[i][0],
807819
srv_sort_buf_size);
@@ -817,19 +829,27 @@ fts_parallel_tokenization(
817829
}
818830

819831
for (i = 0; i < FTS_NUM_AUX_INDEX; i++) {
832+
dberr_t error;
820833

821834
if (!merge_file[i]->offset) {
822835
continue;
823836
}
824837

825838
tmpfd[i] = row_merge_file_create_low();
826839
if (tmpfd[i] < 0) {
840+
psort_info->error = DB_OUT_OF_MEMORY;
841+
goto func_exit;
842+
}
843+
844+
error = row_merge_sort(psort_info->psort_common->trx,
845+
psort_info->psort_common->dup,
846+
merge_file[i], block[i], &tmpfd[i]);
847+
if (error != DB_SUCCESS) {
848+
close(tmpfd[i]);
849+
psort_info->error = error;
827850
goto func_exit;
828851
}
829852

830-
row_merge_sort(psort_info->psort_common->trx,
831-
psort_info->psort_common->dup,
832-
merge_file[i], block[i], &tmpfd[i]);
833853
total_rec += merge_file[i]->n_rec;
834854
close(tmpfd[i]);
835855
}

storage/innobase/row/row0merge.cc

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1574,9 +1574,23 @@ row_merge_read_clustered_index(
15741574
continue;
15751575
}
15761576

1577-
if ((buf->index->type & DICT_FTS)
1578-
&& (!row || !doc_id)) {
1579-
continue;
1577+
if (buf->index->type & DICT_FTS) {
1578+
if (!row || !doc_id) {
1579+
continue;
1580+
}
1581+
1582+
/* Check if error occurs in child thread */
1583+
for (ulint j = 0; j < fts_sort_pll_degree; j++) {
1584+
if (psort_info[j].error != DB_SUCCESS) {
1585+
err = psort_info[j].error;
1586+
trx->error_key_num = i;
1587+
break;
1588+
}
1589+
}
1590+
1591+
if (err != DB_SUCCESS) {
1592+
break;
1593+
}
15801594
}
15811595

15821596
/* The buffer must be sufficiently large
@@ -1634,7 +1648,7 @@ row_merge_read_clustered_index(
16341648

16351649
if (!row_merge_write(file->fd, file->offset++,
16361650
block)) {
1637-
err = DB_OUT_OF_FILE_SPACE;
1651+
err = DB_TEMP_FILE_WRITE_FAILURE;
16381652
trx->error_key_num = i;
16391653
break;
16401654
}
@@ -1689,11 +1703,25 @@ row_merge_read_clustered_index(
16891703
ulint trial_count = 0;
16901704
const ulint max_trial_count = 10000;
16911705

1706+
wait_again:
1707+
/* Check if error occurs in child thread */
1708+
for (ulint j = 0; j < fts_sort_pll_degree; j++) {
1709+
if (psort_info[j].error != DB_SUCCESS) {
1710+
err = psort_info[j].error;
1711+
trx->error_key_num = j;
1712+
break;
1713+
}
1714+
}
1715+
16921716
/* Tell all children that parent has done scanning */
16931717
for (ulint i = 0; i < fts_sort_pll_degree; i++) {
1694-
psort_info[i].state = FTS_PARENT_COMPLETE;
1718+
if (err == DB_SUCCESS) {
1719+
psort_info[i].state = FTS_PARENT_COMPLETE;
1720+
} else {
1721+
psort_info[i].state = FTS_PARENT_EXITING;
1722+
}
16951723
}
1696-
wait_again:
1724+
16971725
/* Now wait all children to report back to be completed */
16981726
os_event_wait_time_low(fts_parallel_sort_event,
16991727
1000000, sig_count);
@@ -3389,6 +3417,7 @@ row_merge_build_indexes(
33893417
fts_psort_t* psort_info = NULL;
33903418
fts_psort_t* merge_info = NULL;
33913419
ib_int64_t sig_count = 0;
3420+
bool fts_psort_initiated = false;
33923421
DBUG_ENTER("row_merge_build_indexes");
33933422

33943423
ut_ad(!srv_read_only_mode);
@@ -3445,6 +3474,10 @@ row_merge_build_indexes(
34453474
row_fts_psort_info_init(
34463475
trx, dup, new_table, opt_doc_id_size,
34473476
&psort_info, &merge_info);
3477+
3478+
/* "We need to ensure that we free the resources
3479+
allocated */
3480+
fts_psort_initiated = true;
34483481
}
34493482
}
34503483

@@ -3567,6 +3600,7 @@ row_merge_build_indexes(
35673600

35683601
if (indexes[i]->type & DICT_FTS) {
35693602
row_fts_psort_info_destroy(psort_info, merge_info);
3603+
fts_psort_initiated = false;
35703604
} else if (error != DB_SUCCESS || !online) {
35713605
/* Do not apply any online log. */
35723606
} else if (old_table != new_table) {
@@ -3603,6 +3637,12 @@ row_merge_build_indexes(
36033637
error = DB_TOO_MANY_CONCURRENT_TRXS;
36043638
trx->error_state = error;);
36053639

3640+
if (fts_psort_initiated) {
3641+
/* Clean up FTS psort related resource */
3642+
row_fts_psort_info_destroy(psort_info, merge_info);
3643+
fts_psort_initiated = false;
3644+
}
3645+
36063646
row_merge_file_destroy_low(tmpfd);
36073647

36083648
for (i = 0; i < n_indexes; i++) {

0 commit comments

Comments
 (0)