1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

InnoDB 5.6.22

This commit is contained in:
Sergei Golubchik
2015-01-21 14:33:39 +01:00
22 changed files with 756 additions and 259 deletions

View File

@@ -234,6 +234,8 @@ col226 text,
col227 text, col227 text,
col228 text col228 text
) ENGINE=InnoDB; ) ENGINE=InnoDB;
Warnings:
Warning 139 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.
set innodb_strict_mode = 1; set innodb_strict_mode = 1;
alter table t1 engine=InnoDB; alter table t1 engine=InnoDB;
ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

View File

@@ -2364,6 +2364,38 @@ btr_cur_pess_upd_restore_supremum(
page_rec_get_heap_no(rec)); page_rec_get_heap_no(rec));
} }
/*************************************************************//**
Check if the total length of the modified blob for the row is within 10%
of the total redo log size. This constraint on the blob length is to
avoid overwriting the redo logs beyond the last checkpoint lsn.
@return DB_SUCCESS or DB_TOO_BIG_RECORD. */
static
dberr_t
btr_check_blob_limit(const big_rec_t* big_rec_vec)
{
const ib_uint64_t redo_size = srv_n_log_files * srv_log_file_size
* UNIV_PAGE_SIZE;
const ulint redo_10p = redo_size / 10;
ulint total_blob_len = 0;
dberr_t err = DB_SUCCESS;
/* Calculate the total number of bytes for blob data */
for (ulint i = 0; i < big_rec_vec->n_fields; i++) {
total_blob_len += big_rec_vec->fields[i].len;
}
if (total_blob_len > redo_10p) {
ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data"
" length (" ULINTPF ") is greater than"
" 10%% of the total redo log size (" UINT64PF
"). Please increase total redo log size.",
total_blob_len, redo_size);
err = DB_TOO_BIG_RECORD;
}
return(err);
}
/*************************************************************//** /*************************************************************//**
Performs an update of a record on a page of a tree. It is assumed Performs an update of a record on a page of a tree. It is assumed
that mtr holds an x-latch on the tree and on the cursor page. If the that mtr holds an x-latch on the tree and on the cursor page. If the
@@ -2579,26 +2611,14 @@ make_external:
} }
if (big_rec_vec) { if (big_rec_vec) {
const ulint redo_10p = srv_log_file_size * UNIV_PAGE_SIZE / 10;
ulint total_blob_len = 0;
/* Calculate the total number of bytes for blob data */ err = btr_check_blob_limit(big_rec_vec);
for (ulint i = 0; i < big_rec_vec->n_fields; i++) {
total_blob_len += big_rec_vec->fields[i].len;
}
if (total_blob_len > redo_10p) { if (err != DB_SUCCESS) {
ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data"
" length (" ULINTPF ") is greater than"
" 10%% of the redo log file size (" UINT64PF
"). Please increase innodb_log_file_size.",
total_blob_len, srv_log_file_size);
if (n_reserved > 0) { if (n_reserved > 0) {
fil_space_release_free_extents( fil_space_release_free_extents(
index->space, n_reserved); index->space, n_reserved);
} }
err = DB_TOO_BIG_RECORD;
goto err_exit; goto err_exit;
} }
} }
@@ -4470,7 +4490,6 @@ btr_store_big_rec_extern_fields(
buf_block_t** freed_pages = NULL; buf_block_t** freed_pages = NULL;
ulint n_freed_pages = 0; ulint n_freed_pages = 0;
dberr_t error = DB_SUCCESS; dberr_t error = DB_SUCCESS;
ulint total_blob_len = 0;
ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(rec_offs_any_extern(offsets)); ut_ad(rec_offs_any_extern(offsets));
@@ -4490,21 +4509,11 @@ btr_store_big_rec_extern_fields(
rec_page_no = buf_block_get_page_no(rec_block); rec_page_no = buf_block_get_page_no(rec_block);
ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX); ut_a(fil_page_get_type(page_align(rec)) == FIL_PAGE_INDEX);
const ulint redo_10p = (srv_log_file_size * UNIV_PAGE_SIZE / 10); error = btr_check_blob_limit(big_rec_vec);
/* Calculate the total number of bytes for blob data */ if (error != DB_SUCCESS) {
for (ulint i = 0; i < big_rec_vec->n_fields; i++) {
total_blob_len += big_rec_vec->fields[i].len;
}
if (total_blob_len > redo_10p) {
ut_ad(op == BTR_STORE_INSERT); ut_ad(op == BTR_STORE_INSERT);
ib_logf(IB_LOG_LEVEL_ERROR, "The total blob data length" return(error);
" (" ULINTPF ") is greater than 10%% of the"
" redo log file size (" UINT64PF "). Please"
" increase innodb_log_file_size.",
total_blob_len, srv_log_file_size);
return(DB_TOO_BIG_RECORD);
} }
if (page_zip) { if (page_zip) {

View File

@@ -564,9 +564,14 @@ buf_page_is_corrupted(
checksum_field2 = mach_read_from_4( checksum_field2 = mach_read_from_4(
read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM); read_buf + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM);
#if FIL_PAGE_LSN % 8
#error "FIL_PAGE_LSN must be 64 bit aligned"
#endif
/* declare empty pages non-corrupted */ /* declare empty pages non-corrupted */
if (checksum_field1 == 0 && checksum_field2 == 0 if (checksum_field1 == 0 && checksum_field2 == 0
&& mach_read_from_4(read_buf + FIL_PAGE_LSN) == 0) { && *reinterpret_cast<const ib_uint64_t*>(read_buf +
FIL_PAGE_LSN) == 0) {
/* make sure that the page is really empty */ /* make sure that the page is really empty */
for (ulint i = 0; i < UNIV_PAGE_SIZE; i++) { for (ulint i = 0; i < UNIV_PAGE_SIZE; i++) {
if (read_buf[i] != 0) { if (read_buf[i] != 0) {

View File

@@ -837,39 +837,35 @@ buf_flush_init_for_writing(
case SRV_CHECKSUM_ALGORITHM_CRC32: case SRV_CHECKSUM_ALGORITHM_CRC32:
case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
checksum = buf_calc_page_crc32(page); checksum = buf_calc_page_crc32(page);
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum);
break; break;
case SRV_CHECKSUM_ALGORITHM_INNODB: case SRV_CHECKSUM_ALGORITHM_INNODB:
case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB: case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
checksum = (ib_uint32_t) buf_calc_page_new_checksum(page); checksum = (ib_uint32_t) buf_calc_page_new_checksum(page);
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum);
checksum = (ib_uint32_t) buf_calc_page_old_checksum(page);
break; break;
case SRV_CHECKSUM_ALGORITHM_NONE: case SRV_CHECKSUM_ALGORITHM_NONE:
case SRV_CHECKSUM_ALGORITHM_STRICT_NONE: case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
checksum = BUF_NO_CHECKSUM_MAGIC; checksum = BUF_NO_CHECKSUM_MAGIC;
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum);
break; break;
/* no default so the compiler will emit a warning if new enum /* no default so the compiler will emit a warning if new enum
is added and not handled here */ is added and not handled here */
} }
mach_write_to_4(page + FIL_PAGE_SPACE_OR_CHKSUM, checksum); /* With the InnoDB checksum, we overwrite the first 4 bytes of
the end lsn field to store the old formula checksum. Since it
depends also on the field FIL_PAGE_SPACE_OR_CHKSUM, it has to
be calculated after storing the new formula checksum.
/* We overwrite the first 4 bytes of the end lsn field to store In other cases we write the same value to both fields.
the old formula checksum. Since it depends also on the field If CRC32 is used then it is faster to use that checksum
FIL_PAGE_SPACE_OR_CHKSUM, it has to be calculated after storing the (calculated above) instead of calculating another one.
new formula checksum. */ We can afford to store something other than
buf_calc_page_old_checksum() or BUF_NO_CHECKSUM_MAGIC in
if (srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_STRICT_INNODB this field because the file will not be readable by old
|| srv_checksum_algorithm == SRV_CHECKSUM_ALGORITHM_INNODB) { versions of MySQL/InnoDB anyway (older than MySQL 5.6.3) */
checksum = (ib_uint32_t) buf_calc_page_old_checksum(page);
/* In other cases we use the value assigned from above.
If CRC32 is used then it is faster to use that checksum
(calculated above) instead of calculating another one.
We can afford to store something other than
buf_calc_page_old_checksum() or BUF_NO_CHECKSUM_MAGIC in
this field because the file will not be readable by old
versions of MySQL/InnoDB anyway (older than MySQL 5.6.3) */
}
mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, mach_write_to_4(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM,
checksum); checksum);

View File

@@ -39,6 +39,16 @@ UNIV_INTERN dict_index_t* dict_ind_redundant;
/** dummy index for ROW_FORMAT=COMPACT supremum and infimum records */ /** dummy index for ROW_FORMAT=COMPACT supremum and infimum records */
UNIV_INTERN dict_index_t* dict_ind_compact; UNIV_INTERN dict_index_t* dict_ind_compact;
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
/** Flag to control insert buffer debugging. */
extern UNIV_INTERN uint ibuf_debug;
#endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */
/**********************************************************************
Issue a warning that the row is too big. */
void
ib_warn_row_too_big(const dict_table_t* table);
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
#include "buf0buf.h" #include "buf0buf.h"
#include "data0type.h" #include "data0type.h"
@@ -2410,11 +2420,18 @@ dict_index_add_to_cache(
new_index->n_fields = new_index->n_def; new_index->n_fields = new_index->n_def;
new_index->trx_id = index->trx_id; new_index->trx_id = index->trx_id;
if (strict && dict_index_too_big_for_tree(table, new_index)) { if (dict_index_too_big_for_tree(table, new_index)) {
if (strict) {
too_big: too_big:
dict_mem_index_free(new_index); dict_mem_index_free(new_index);
dict_mem_index_free(index); dict_mem_index_free(index);
return(DB_TOO_BIG_RECORD); return(DB_TOO_BIG_RECORD);
} else {
ib_warn_row_too_big(table);
}
} }
if (dict_index_is_univ(index)) { if (dict_index_is_univ(index)) {
@@ -5721,11 +5738,11 @@ dict_set_corrupted(
dict_index_copy_types(tuple, sys_index, 2); dict_index_copy_types(tuple, sys_index, 2);
btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_GE, btr_cur_search_to_nth_level(sys_index, 0, tuple, PAGE_CUR_LE,
BTR_MODIFY_LEAF, BTR_MODIFY_LEAF,
&cursor, 0, __FILE__, __LINE__, &mtr); &cursor, 0, __FILE__, __LINE__, &mtr);
if (cursor.up_match == dtuple_get_n_fields(tuple)) { if (cursor.low_match == dtuple_get_n_fields(tuple)) {
/* UPDATE SYS_INDEXES SET TYPE=index->type /* UPDATE SYS_INDEXES SET TYPE=index->type
WHERE TABLE_ID=index->table->id AND INDEX_ID=index->id */ WHERE TABLE_ID=index->table->id AND INDEX_ID=index->id */
ulint len; ulint len;

View File

@@ -1941,7 +1941,8 @@ UNIV_INTERN
ibool ibool
fil_inc_pending_ops( fil_inc_pending_ops(
/*================*/ /*================*/
ulint id) /*!< in: space id */ ulint id, /*!< in: space id */
ibool print_err) /*!< in: need to print error or not */
{ {
fil_space_t* space; fil_space_t* space;
@@ -1950,10 +1951,12 @@ fil_inc_pending_ops(
space = fil_space_get_by_id(id); space = fil_space_get_by_id(id);
if (space == NULL) { if (space == NULL) {
fprintf(stderr, if (print_err) {
"InnoDB: Error: trying to do an operation on a" fprintf(stderr,
" dropped tablespace %lu\n", "InnoDB: Error: trying to do an operation on a"
(ulong) id); " dropped tablespace %lu\n",
(ulong) id);
}
} }
if (space == NULL || space->stop_new_ops) { if (space == NULL || space->stop_new_ops) {
@@ -4109,7 +4112,18 @@ fil_load_single_table_tablespace(
/* Build up the tablename in the standard form database/table. */ /* Build up the tablename in the standard form database/table. */
tablename = static_cast<char*>( tablename = static_cast<char*>(
mem_alloc(dbname_len + filename_len + 2)); mem_alloc(dbname_len + filename_len + 2));
sprintf(tablename, "%s/%s", dbname, filename);
/* When lower_case_table_names = 2 it is possible that the
dbname is in upper case ,but while storing it in fil_space_t
we must convert it into lower case */
sprintf(tablename, "%s" , dbname);
tablename[dbname_len] = '\0';
if (lower_case_file_system) {
dict_casedn_str(tablename);
}
sprintf(tablename+dbname_len,"/%s",filename);
tablename_len = strlen(tablename) - strlen(".ibd"); tablename_len = strlen(tablename) - strlen(".ibd");
tablename[tablename_len] = '\0'; tablename[tablename_len] = '\0';

View File

@@ -36,6 +36,7 @@ Full Text Search interface
#include "dict0priv.h" #include "dict0priv.h"
#include "dict0stats.h" #include "dict0stats.h"
#include "btr0pcur.h" #include "btr0pcur.h"
#include <vector>
#include "ha_prototypes.h" #include "ha_prototypes.h"
@@ -899,12 +900,14 @@ fts_drop_index(
index_cache = fts_find_index_cache(cache, index); index_cache = fts_find_index_cache(cache, index);
if (index_cache->words) { if (index_cache != NULL) {
fts_words_free(index_cache->words); if (index_cache->words) {
rbt_free(index_cache->words); fts_words_free(index_cache->words);
} rbt_free(index_cache->words);
}
ib_vector_remove(cache->indexes, *(void**) index_cache); ib_vector_remove(cache->indexes, *(void**) index_cache);
}
if (cache->get_docs) { if (cache->get_docs) {
fts_reset_get_doc(cache); fts_reset_get_doc(cache);
@@ -1255,7 +1258,8 @@ fts_tokenizer_word_get(
#endif #endif
/* If it is a stopword, do not index it */ /* If it is a stopword, do not index it */
if (rbt_search(cache->stopword_info.cached_stopword, if (cache->stopword_info.cached_stopword != NULL
&& rbt_search(cache->stopword_info.cached_stopword,
&parent, text) == 0) { &parent, text) == 0) {
return(NULL); return(NULL);
@@ -3558,6 +3562,12 @@ fts_add_doc_by_id(
rw_lock_x_lock(&table->fts->cache->lock); rw_lock_x_lock(&table->fts->cache->lock);
if (table->fts->cache->stopword_info.status
& STOPWORD_NOT_INIT) {
fts_load_stopword(table, NULL, NULL,
NULL, TRUE, TRUE);
}
fts_cache_add_doc( fts_cache_add_doc(
table->fts->cache, table->fts->cache,
get_doc->index_cache, get_doc->index_cache,
@@ -6072,8 +6082,6 @@ fts_update_hex_format_flag(
return (err); return (err);
} }
#ifdef _WIN32
/*********************************************************************//** /*********************************************************************//**
Rename an aux table to HEX format. It's called when "%016llu" is used Rename an aux table to HEX format. It's called when "%016llu" is used
to format an object id in table name, which only happens in Windows. */ to format an object id in table name, which only happens in Windows. */
@@ -6170,8 +6178,8 @@ This function should make sure that either all the parent table and aux tables
are set DICT_TF2_FTS_AUX_HEX_NAME with flags2 or none of them are set */ are set DICT_TF2_FTS_AUX_HEX_NAME with flags2 or none of them are set */
static __attribute__((nonnull, warn_unused_result)) static __attribute__((nonnull, warn_unused_result))
dberr_t dberr_t
fts_rename_aux_tables_to_hex_format( fts_rename_aux_tables_to_hex_format_low(
/*================================*/ /*====================================*/
trx_t* trx, /*!< in: transaction */ trx_t* trx, /*!< in: transaction */
dict_table_t* parent_table, /*!< in: parent table */ dict_table_t* parent_table, /*!< in: parent table */
ib_vector_t* tables) /*!< in: aux tables to rename. */ ib_vector_t* tables) /*!< in: aux tables to rename. */
@@ -6295,12 +6303,14 @@ fts_rename_aux_tables_to_hex_format(
"table %s. Please revert manually.", "table %s. Please revert manually.",
table->name); table->name);
fts_sql_rollback(trx_bg); fts_sql_rollback(trx_bg);
trx_free_for_background(trx_bg);
/* Continue to clear aux tables' flags2 */ /* Continue to clear aux tables' flags2 */
not_rename = true; not_rename = true;
continue; continue;
} }
fts_sql_commit(trx_bg); fts_sql_commit(trx_bg);
trx_free_for_background(trx_bg);
} }
DICT_TF2_FLAG_UNSET(parent_table, DICT_TF2_FTS_AUX_HEX_NAME); DICT_TF2_FLAG_UNSET(parent_table, DICT_TF2_FTS_AUX_HEX_NAME);
@@ -6324,7 +6334,11 @@ fts_fake_hex_to_dec(
ret = sprintf(tmp_id, UINT64PFx, id); ret = sprintf(tmp_id, UINT64PFx, id);
ut_ad(ret == 16); ut_ad(ret == 16);
#ifdef _WIN32
ret = sscanf(tmp_id, "%016llu", &dec_id); ret = sscanf(tmp_id, "%016llu", &dec_id);
#else
ret = sscanf(tmp_id, "%016"PRIu64, &dec_id);
#endif /* _WIN32 */
ut_ad(ret == 1); ut_ad(ret == 1);
return dec_id; return dec_id;
@@ -6346,7 +6360,293 @@ fts_check_aux_table_parent_id_cmp(
return static_cast<int>(fa1->parent_id - fa2->parent_id); return static_cast<int>(fa1->parent_id - fa2->parent_id);
} }
#endif /* _WIN32 */ /** Mark all the fts index associated with the parent table as corrupted.
@param[in] trx transaction
@param[in, out] parent_table fts index associated with this parent table
will be marked as corrupted. */
static
void
fts_parent_all_index_set_corrupt(
trx_t* trx,
dict_table_t* parent_table)
{
fts_t* fts = parent_table->fts;
if (trx_get_dict_operation(trx) == TRX_DICT_OP_NONE) {
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
}
for (ulint j = 0; j < ib_vector_size(fts->indexes); j++) {
dict_index_t* index = static_cast<dict_index_t*>(
ib_vector_getp_const(fts->indexes, j));
dict_set_corrupted(index,
trx, "DROP ORPHANED TABLE");
}
}
/** Mark the fts index which index id matches the id as corrupted.
@param[in] trx transaction
@param[in] id index id to search
@param[in, out] parent_table parent table to check with all
the index. */
static
void
fts_set_index_corrupt(
trx_t* trx,
index_id_t id,
dict_table_t* table)
{
fts_t* fts = table->fts;
if (trx_get_dict_operation(trx) == TRX_DICT_OP_NONE) {
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
}
for (ulint j = 0; j < ib_vector_size(fts->indexes); j++) {
dict_index_t* index = static_cast<dict_index_t*>(
ib_vector_getp_const(fts->indexes, j));
if (index->id == id) {
dict_set_corrupted(index, trx,
"DROP ORPHANED TABLE");
break;
}
}
}
/** Check the index for the aux table is corrupted.
@param[in] aux_table auxiliary table
@retval nonzero if index is corrupted, zero for valid index */
static
ulint
fts_check_corrupt_index(
fts_aux_table_t* aux_table)
{
dict_table_t* table;
dict_index_t* index;
table = dict_table_open_on_id(
aux_table->parent_id, TRUE, DICT_TABLE_OP_NORMAL);
if (table == NULL) {
return(0);
}
for (index = UT_LIST_GET_FIRST(table->indexes);
index;
index = UT_LIST_GET_NEXT(indexes, index)) {
if (index->id == aux_table->index_id) {
ut_ad(index->type & DICT_FTS);
dict_table_close(table, true, false);
return(dict_index_is_corrupted(index));
}
}
dict_table_close(table, true, false);
return(0);
}
/** Check the validity of the parent table.
@param[in] aux_table auxiliary table
@return true if it is a valid table or false if it is not */
static
bool
fts_valid_parent_table(
const fts_aux_table_t* aux_table)
{
dict_table_t* parent_table;
bool valid = false;
parent_table = dict_table_open_on_id(
aux_table->parent_id, TRUE, DICT_TABLE_OP_NORMAL);
if (parent_table != NULL && parent_table->fts != NULL) {
if (aux_table->index_id == 0) {
valid = true;
} else {
index_id_t id = aux_table->index_id;
dict_index_t* index;
/* Search for the FT index in the table's list. */
for (index = UT_LIST_GET_FIRST(parent_table->indexes);
index;
index = UT_LIST_GET_NEXT(indexes, index)) {
if (index->id == id) {
valid = true;
break;
}
}
}
}
if (parent_table) {
dict_table_close(parent_table, TRUE, FALSE);
}
return(valid);
}
/** Try to rename all aux tables of the specified parent table.
@param[in] aux_tables aux_tables to be renamed
@param[in] parent_table parent table of all aux
tables stored in tables. */
static
void
fts_rename_aux_tables_to_hex_format(
ib_vector_t* aux_tables,
dict_table_t* parent_table)
{
dberr_t err;
trx_t* trx_rename = trx_allocate_for_background();
trx_rename->op_info = "Rename aux tables to hex format";
trx_rename->dict_operation_lock_mode = RW_X_LATCH;
trx_start_for_ddl(trx_rename, TRX_DICT_OP_TABLE);
err = fts_rename_aux_tables_to_hex_format_low(trx_rename,
parent_table, aux_tables);
trx_rename->dict_operation_lock_mode = 0;
if (err != DB_SUCCESS) {
ib_logf(IB_LOG_LEVEL_WARN,
"Rollback operations on all aux tables of table %s. "
"All the fts index associated with the table are "
"marked as corrupted. Please rebuild the "
"index again.", parent_table->name);
fts_sql_rollback(trx_rename);
/* Corrupting the fts index related to parent table. */
trx_t* trx_corrupt;
trx_corrupt = trx_allocate_for_background();
trx_corrupt->dict_operation_lock_mode = RW_X_LATCH;
trx_start_for_ddl(trx_corrupt, TRX_DICT_OP_TABLE);
fts_parent_all_index_set_corrupt(trx_corrupt, parent_table);
trx_corrupt->dict_operation_lock_mode = 0;
fts_sql_commit(trx_corrupt);
trx_free_for_background(trx_corrupt);
} else {
fts_sql_commit(trx_rename);
}
trx_free_for_background(trx_rename);
ib_vector_reset(aux_tables);
}
/** Set the hex format flag for the parent table.
@param[in, out] parent_table parent table
@param[in] trx transaction */
static
void
fts_set_parent_hex_format_flag(
dict_table_t* parent_table,
trx_t* trx)
{
if (!DICT_TF2_FLAG_IS_SET(parent_table,
DICT_TF2_FTS_AUX_HEX_NAME)) {
DBUG_EXECUTE_IF("parent_table_flag_fail",
ib_logf(IB_LOG_LEVEL_FATAL,
"Setting parent table %s to hex format "
"failed. Please try to restart the server "
"again, if it doesn't work, the system "
"tables might be corrupted.",
parent_table->name);
return;);
dberr_t err = fts_update_hex_format_flag(
trx, parent_table->id, true);
if (err != DB_SUCCESS) {
ib_logf(IB_LOG_LEVEL_FATAL,
"Setting parent table %s to hex format "
"failed. Please try to restart the server "
"again, if it doesn't work, the system "
"tables might be corrupted.",
parent_table->name);
} else {
DICT_TF2_FLAG_SET(
parent_table, DICT_TF2_FTS_AUX_HEX_NAME);
}
}
}
/** Drop the obsolete auxilary table.
@param[in] tables tables to be dropped. */
static
void
fts_drop_obsolete_aux_table_from_vector(
ib_vector_t* tables)
{
dberr_t err;
for (ulint count = 0; count < ib_vector_size(tables);
++count) {
fts_aux_table_t* aux_drop_table;
aux_drop_table = static_cast<fts_aux_table_t*>(
ib_vector_get(tables, count));
trx_t* trx_drop = trx_allocate_for_background();
trx_drop->op_info = "Drop obsolete aux tables";
trx_drop->dict_operation_lock_mode = RW_X_LATCH;
trx_start_for_ddl(trx_drop, TRX_DICT_OP_TABLE);
err = row_drop_table_for_mysql(
aux_drop_table->name, trx_drop, false, true);
trx_drop->dict_operation_lock_mode = 0;
if (err != DB_SUCCESS) {
/* We don't need to worry about the
failure, since server would try to
drop it on next restart, even if
the table was broken. */
ib_logf(IB_LOG_LEVEL_WARN,
"Fail to drop obsolete aux table '%s', which "
"is harmless. will try to drop it on next "
"restart.", aux_drop_table->name);
fts_sql_rollback(trx_drop);
} else {
ib_logf(IB_LOG_LEVEL_INFO,
"Dropped obsolete aux table '%s'.",
aux_drop_table->name);
fts_sql_commit(trx_drop);
}
trx_free_for_background(trx_drop);
}
}
/** Drop all the auxiliary table present in the vector.
@param[in] trx transaction
@param[in] tables tables to be dropped */
static
void
fts_drop_aux_table_from_vector(
trx_t* trx,
ib_vector_t* tables)
{
for (ulint count = 0; count < ib_vector_size(tables);
++count) {
fts_aux_table_t* aux_drop_table;
aux_drop_table = static_cast<fts_aux_table_t*>(
ib_vector_get(tables, count));
/* Check for the validity of the parent table */
if (!fts_valid_parent_table(aux_drop_table)) {
ib_logf(IB_LOG_LEVEL_WARN,
"Parent table of FTS auxiliary table %s not "
"found.", aux_drop_table->name);
dberr_t err = fts_drop_table(trx, aux_drop_table->name);
if (err == DB_FAIL) {
char* path = fil_make_ibd_name(
aux_drop_table->name, false);
os_file_delete_if_exists(innodb_file_data_key,
path);
mem_free(path);
}
}
}
}
/**********************************************************************//** /**********************************************************************//**
Check and drop all orphaned FTS auxiliary tables, those that don't have Check and drop all orphaned FTS auxiliary tables, those that don't have
@@ -6359,9 +6659,12 @@ fts_check_and_drop_orphaned_tables(
trx_t* trx, /*!< in: transaction */ trx_t* trx, /*!< in: transaction */
ib_vector_t* tables) /*!< in: tables to check */ ib_vector_t* tables) /*!< in: tables to check */
{ {
#ifdef _WIN32
mem_heap_t* heap; mem_heap_t* heap;
ib_vector_t* aux_tables_to_rename; ib_vector_t* aux_tables_to_rename;
ib_vector_t* invalid_aux_tables;
ib_vector_t* valid_aux_tables;
ib_vector_t* drop_aux_tables;
ib_vector_t* obsolete_aux_tables;
ib_alloc_t* heap_alloc; ib_alloc_t* heap_alloc;
heap = mem_heap_create(1024); heap = mem_heap_create(1024);
@@ -6372,38 +6675,99 @@ fts_check_and_drop_orphaned_tables(
aux_tables_to_rename = ib_vector_create(heap_alloc, aux_tables_to_rename = ib_vector_create(heap_alloc,
sizeof(fts_aux_table_t), 128); sizeof(fts_aux_table_t), 128);
/* We store all fake auxiliary table and orphaned table here. */
invalid_aux_tables = ib_vector_create(heap_alloc,
sizeof(fts_aux_table_t), 128);
/* We store all valid aux tables. We use this to filter the
fake auxiliary table from invalid auxiliary tables. */
valid_aux_tables = ib_vector_create(heap_alloc,
sizeof(fts_aux_table_t), 128);
/* We store all auxiliary tables to be dropped. */
drop_aux_tables = ib_vector_create(heap_alloc,
sizeof(fts_aux_table_t), 128);
/* We store all obsolete auxiliary tables to be dropped. */
obsolete_aux_tables = ib_vector_create(heap_alloc,
sizeof(fts_aux_table_t), 128);
/* Sort by parent_id first, in case rename will fail */ /* Sort by parent_id first, in case rename will fail */
ib_vector_sort(tables, fts_check_aux_table_parent_id_cmp); ib_vector_sort(tables, fts_check_aux_table_parent_id_cmp);
#endif /* _WIN32 */
for (ulint i = 0; i < ib_vector_size(tables); ++i) { for (ulint i = 0; i < ib_vector_size(tables); ++i) {
dict_table_t* parent_table; dict_table_t* parent_table;
fts_aux_table_t* aux_table; fts_aux_table_t* aux_table;
bool drop = false; bool drop = false;
#ifdef _WIN32
dict_table_t* table; dict_table_t* table;
fts_aux_table_t* next_aux_table = NULL; fts_aux_table_t* next_aux_table = NULL;
ib_id_t orig_parent_id = 0; ib_id_t orig_parent_id = 0;
ib_id_t orig_index_id = 0;
bool rename = false; bool rename = false;
#endif /* _WIN32 */
aux_table = static_cast<fts_aux_table_t*>( aux_table = static_cast<fts_aux_table_t*>(
ib_vector_get(tables, i)); ib_vector_get(tables, i));
#ifdef _WIN32
table = dict_table_open_on_id( table = dict_table_open_on_id(
aux_table->id, TRUE, DICT_TABLE_OP_NORMAL); aux_table->id, TRUE, DICT_TABLE_OP_NORMAL);
orig_parent_id = aux_table->parent_id; orig_parent_id = aux_table->parent_id;
orig_index_id = aux_table->index_id;
if (table == NULL || strcmp(table->name, aux_table->name)) { if (table == NULL || strcmp(table->name, aux_table->name)) {
/* Skip these aux tables, which are common tables
with wrong table ids */ bool fake_aux = false;
if (table) {
if (table != NULL) {
dict_table_close(table, TRUE, FALSE); dict_table_close(table, TRUE, FALSE);
} }
continue; if (i + 1 < ib_vector_size(tables)) {
next_aux_table = static_cast<fts_aux_table_t*>(
ib_vector_get(tables, i + 1));
}
/* To know whether aux table is fake fts or
orphan fts table. */
for (ulint count = 0;
count < ib_vector_size(valid_aux_tables);
count++) {
fts_aux_table_t* valid_aux;
valid_aux = static_cast<fts_aux_table_t*>(
ib_vector_get(valid_aux_tables, count));
if (strcmp(valid_aux->name,
aux_table->name) == 0) {
fake_aux = true;
break;
}
}
/* All aux tables of parent table, whose id is
last_parent_id, have been checked, try to rename
them if necessary. */
if ((next_aux_table == NULL
|| orig_parent_id != next_aux_table->parent_id)
&& (!ib_vector_is_empty(aux_tables_to_rename))) {
ulint parent_id = fts_fake_hex_to_dec(
aux_table->parent_id);
parent_table = dict_table_open_on_id(
parent_id, TRUE,
DICT_TABLE_OP_NORMAL);
fts_rename_aux_tables_to_hex_format(
aux_tables_to_rename, parent_table);
dict_table_close(parent_table, TRUE,
FALSE);
}
/* If the aux table is fake aux table. Skip it. */
if (!fake_aux) {
ib_vector_push(invalid_aux_tables, aux_table);
}
continue;
} else if (!DICT_TF2_FLAG_IS_SET(table, } else if (!DICT_TF2_FLAG_IS_SET(table,
DICT_TF2_FTS_AUX_HEX_NAME)) { DICT_TF2_FTS_AUX_HEX_NAME)) {
@@ -6416,65 +6780,99 @@ fts_check_and_drop_orphaned_tables(
} }
ut_ad(aux_table->id > aux_table->parent_id); ut_ad(aux_table->id > aux_table->parent_id);
rename = true;
/* Check whether parent table id and index id
are stored as decimal format. */
if (fts_valid_parent_table(aux_table)) {
parent_table = dict_table_open_on_id(
aux_table->parent_id, true,
DICT_TABLE_OP_NORMAL);
ut_ad(parent_table != NULL);
ut_ad(parent_table->fts != NULL);
if (!DICT_TF2_FLAG_IS_SET(
parent_table,
DICT_TF2_FTS_AUX_HEX_NAME)) {
rename = true;
}
dict_table_close(parent_table, TRUE, FALSE);
}
if (!rename) {
/* Reassign the original value of
aux table if it is not in decimal format */
aux_table->parent_id = orig_parent_id;
aux_table->index_id = orig_index_id;
}
} }
if (table) { if (table != NULL) {
dict_table_close(table, TRUE, FALSE); dict_table_close(table, true, false);
}
if (!rename) {
/* Check the validity of the parent table. */
if (!fts_valid_parent_table(aux_table)) {
drop = true;
}
}
/* Filter out the fake aux table by comparing with the
current valid auxiliary table name . */
for (ulint count = 0;
count < ib_vector_size(invalid_aux_tables); count++) {
fts_aux_table_t* invalid_aux;
invalid_aux = static_cast<fts_aux_table_t*>(
ib_vector_get(invalid_aux_tables, count));
if (strcmp(invalid_aux->name, aux_table->name) == 0) {
ib_vector_remove(
invalid_aux_tables,
*reinterpret_cast<void**>(invalid_aux));
break;
}
}
ib_vector_push(valid_aux_tables, aux_table);
/* If the index associated with aux table is corrupted,
skip it. */
if (fts_check_corrupt_index(aux_table) > 0) {
if (i + 1 < ib_vector_size(tables)) {
next_aux_table = static_cast<fts_aux_table_t*>(
ib_vector_get(tables, i + 1));
}
if (next_aux_table == NULL
|| orig_parent_id != next_aux_table->parent_id) {
parent_table = dict_table_open_on_id(
aux_table->parent_id, TRUE,
DICT_TABLE_OP_NORMAL);
if (!ib_vector_is_empty(aux_tables_to_rename)) {
fts_rename_aux_tables_to_hex_format(
aux_tables_to_rename, parent_table);
} else {
fts_set_parent_hex_format_flag(
parent_table, trx);
}
dict_table_close(parent_table, TRUE, FALSE);
}
continue;
} }
#endif /* _WIN32 */
parent_table = dict_table_open_on_id( parent_table = dict_table_open_on_id(
aux_table->parent_id, TRUE, DICT_TABLE_OP_NORMAL); aux_table->parent_id, TRUE, DICT_TABLE_OP_NORMAL);
if (parent_table == NULL || parent_table->fts == NULL) {
drop = true;
} else if (aux_table->index_id != 0) {
index_id_t id;
fts_t* fts;
drop = true;
fts = parent_table->fts;
id = aux_table->index_id;
/* Search for the FT index in the table's list. */
for (ulint j = 0;
j < ib_vector_size(fts->indexes);
++j) {
const dict_index_t* index;
index = static_cast<const dict_index_t*>(
ib_vector_getp_const(fts->indexes, j));
if (index->id == id) {
drop = false;
break;
}
}
}
if (drop) { if (drop) {
ib_vector_push(drop_aux_tables, aux_table);
ib_logf(IB_LOG_LEVEL_WARN,
"Parent table of FTS auxiliary table %s not "
"found.", aux_table->name);
dberr_t err = fts_drop_table(trx, aux_table->name);
if (err == DB_FAIL) {
char* path;
path = fil_make_ibd_name(
aux_table->name, false);
os_file_delete_if_exists(innodb_file_data_key,
path);
mem_free(path);
}
} else { } else {
if (FTS_IS_OBSOLETE_AUX_TABLE(aux_table->name)) { if (FTS_IS_OBSOLETE_AUX_TABLE(aux_table->name)) {
@@ -6484,49 +6882,13 @@ fts_check_and_drop_orphaned_tables(
This could happen when we try to upgrade This could happen when we try to upgrade
from older server to later one, which doesn't from older server to later one, which doesn't
contain these obsolete tables. */ contain these obsolete tables. */
drop = true; ib_vector_push(obsolete_aux_tables, aux_table);
continue;
dberr_t err;
trx_t* trx_drop =
trx_allocate_for_background();
trx_drop->op_info = "Drop obsolete aux tables";
trx_drop->dict_operation_lock_mode = RW_X_LATCH;
trx_start_for_ddl(trx_drop, TRX_DICT_OP_TABLE);
err = row_drop_table_for_mysql(
aux_table->name, trx_drop, false, true);
trx_drop->dict_operation_lock_mode = 0;
if (err != DB_SUCCESS) {
/* We don't need to worry about the
failure, since server would try to
drop it on next restart, even if
the table was broken. */
ib_logf(IB_LOG_LEVEL_WARN,
"Fail to drop obsolete aux"
" table '%s', which is"
" harmless. will try to drop"
" it on next restart.",
aux_table->name);
fts_sql_rollback(trx_drop);
} else {
ib_logf(IB_LOG_LEVEL_INFO,
"Dropped obsolete aux"
" table '%s'.",
aux_table->name);
fts_sql_commit(trx_drop);
}
trx_free_for_background(trx_drop);
} }
} }
#ifdef _WIN32
/* If the aux table is in decimal format, we should
rename it, so push it to aux_tables_to_rename */
if (!drop && rename) { if (!drop && rename) {
ib_vector_push(aux_tables_to_rename, aux_table); ib_vector_push(aux_tables_to_rename, aux_table);
} }
@@ -6544,38 +6906,16 @@ fts_check_and_drop_orphaned_tables(
them if necessary. We had better use a new background them if necessary. We had better use a new background
trx to rename rather than the original trx, in case trx to rename rather than the original trx, in case
any failure would cause a complete rollback. */ any failure would cause a complete rollback. */
dberr_t err; ut_ad(rename);
trx_t* trx_rename = trx_allocate_for_background(); ut_ad(!DICT_TF2_FLAG_IS_SET(
trx_rename->op_info = "Rename aux tables to " parent_table, DICT_TF2_FTS_AUX_HEX_NAME));
"hex format";
trx_rename->dict_operation_lock_mode = RW_X_LATCH;
trx_start_for_ddl(trx_rename, TRX_DICT_OP_TABLE);
err = fts_rename_aux_tables_to_hex_format(trx_rename, fts_rename_aux_tables_to_hex_format(
parent_table, aux_tables_to_rename); aux_tables_to_rename,parent_table);
trx_rename->dict_operation_lock_mode = 0;
if (err != DB_SUCCESS) {
ib_logf(IB_LOG_LEVEL_WARN,
"Rollback operations on all "
"aux tables of table %s. "
"Please check why renaming aux tables "
"failed, and restart the server to "
"upgrade again to "
"get the table work.",
parent_table->name);
fts_sql_rollback(trx_rename);
} else {
fts_sql_commit(trx_rename);
}
trx_free_for_background(trx_rename);
ib_vector_reset(aux_tables_to_rename);
} }
#else /* _WIN32 */
if (!drop) { /* The IDs are already in correct hex format. */
if (!drop && !rename) {
dict_table_t* table; dict_table_t* table;
table = dict_table_open_on_id( table = dict_table_open_on_id(
@@ -6590,6 +6930,16 @@ fts_check_and_drop_orphaned_tables(
&& !DICT_TF2_FLAG_IS_SET( && !DICT_TF2_FLAG_IS_SET(
table, table,
DICT_TF2_FTS_AUX_HEX_NAME)) { DICT_TF2_FTS_AUX_HEX_NAME)) {
DBUG_EXECUTE_IF("aux_table_flag_fail",
ib_logf(IB_LOG_LEVEL_WARN,
"Setting aux table %s to hex "
"format failed.", table->name);
fts_set_index_corrupt(
trx, aux_table->index_id,
parent_table);
goto table_exit;);
dberr_t err = fts_update_hex_format_flag( dberr_t err = fts_update_hex_format_flag(
trx, table->id, true); trx, table->id, true);
@@ -6597,49 +6947,44 @@ fts_check_and_drop_orphaned_tables(
ib_logf(IB_LOG_LEVEL_WARN, ib_logf(IB_LOG_LEVEL_WARN,
"Setting aux table %s to hex " "Setting aux table %s to hex "
"format failed.", table->name); "format failed.", table->name);
fts_set_index_corrupt(
trx, aux_table->index_id,
parent_table);
} else { } else {
DICT_TF2_FLAG_SET(table, DICT_TF2_FLAG_SET(table,
DICT_TF2_FTS_AUX_HEX_NAME); DICT_TF2_FTS_AUX_HEX_NAME);
} }
} }
#ifndef DBUG_OFF
table_exit:
#endif /* !DBUG_OFF */
if (table != NULL) { if (table != NULL) {
dict_table_close(table, TRUE, FALSE); dict_table_close(table, TRUE, FALSE);
} }
ut_ad(parent_table != NULL); ut_ad(parent_table != NULL);
if (!DICT_TF2_FLAG_IS_SET(parent_table,
DICT_TF2_FTS_AUX_HEX_NAME)) {
dberr_t err = fts_update_hex_format_flag(
trx, parent_table->id, true);
if (err != DB_SUCCESS) { fts_set_parent_hex_format_flag(
ib_logf(IB_LOG_LEVEL_WARN, parent_table, trx);
"Setting parent table %s of "
"FTS auxiliary %s to hex "
"format failed.",
parent_table->name,
aux_table->name);
} else {
DICT_TF2_FLAG_SET(parent_table,
DICT_TF2_FTS_AUX_HEX_NAME);
}
}
} }
#endif /* _WIN32 */ if (parent_table != NULL) {
if (parent_table) {
dict_table_close(parent_table, TRUE, FALSE); dict_table_close(parent_table, TRUE, FALSE);
} }
} }
#ifdef _WIN32 fts_drop_aux_table_from_vector(trx, invalid_aux_tables);
fts_drop_aux_table_from_vector(trx, drop_aux_tables);
fts_sql_commit(trx);
fts_drop_obsolete_aux_table_from_vector(obsolete_aux_tables);
/* Free the memory allocated at the beginning */ /* Free the memory allocated at the beginning */
if (heap != NULL) { if (heap != NULL) {
mem_heap_free(heap); mem_heap_free(heap);
} }
#endif /* _WIN32 */
} }
/**********************************************************************//** /**********************************************************************//**
@@ -6738,7 +7083,6 @@ fts_drop_orphaned_tables(void)
if (error == DB_SUCCESS) { if (error == DB_SUCCESS) {
fts_check_and_drop_orphaned_tables(trx, tables); fts_check_and_drop_orphaned_tables(trx, tables);
fts_sql_commit(trx);
break; /* Exit the loop. */ break; /* Exit the loop. */
} else { } else {
ib_vector_reset(tables); ib_vector_reset(tables);

View File

@@ -190,6 +190,8 @@ cycle for a table. */
struct fts_slot_t { struct fts_slot_t {
dict_table_t* table; /*!< Table to optimize */ dict_table_t* table; /*!< Table to optimize */
table_id_t table_id; /*!< Table id */
fts_state_t state; /*!< State of this slot */ fts_state_t state; /*!< State of this slot */
ulint added; /*!< Number of doc ids added since the ulint added; /*!< Number of doc ids added since the
@@ -2575,6 +2577,8 @@ fts_optimize_add_table(
return; return;
} }
ut_ad(table->cached && table->fts != NULL);
/* Make sure table with FTS index cannot be evicted */ /* Make sure table with FTS index cannot be evicted */
if (table->can_be_evicted) { if (table->can_be_evicted) {
dict_table_move_from_lru_to_non_lru(table); dict_table_move_from_lru_to_non_lru(table);
@@ -2741,6 +2745,7 @@ fts_optimize_new_table(
memset(slot, 0x0, sizeof(*slot)); memset(slot, 0x0, sizeof(*slot));
slot->table = table; slot->table = table;
slot->table_id = table->id;
slot->state = FTS_STATE_LOADED; slot->state = FTS_STATE_LOADED;
slot->interval_time = FTS_OPTIMIZE_INTERVAL_IN_SECS; slot->interval_time = FTS_OPTIMIZE_INTERVAL_IN_SECS;
@@ -2865,7 +2870,8 @@ fts_is_sync_needed(
slot = static_cast<const fts_slot_t*>( slot = static_cast<const fts_slot_t*>(
ib_vector_get_const(tables, i)); ib_vector_get_const(tables, i));
if (slot->table && slot->table->fts) { if (slot->state != FTS_STATE_EMPTY && slot->table
&& slot->table->fts) {
total_memory += slot->table->fts->cache->total_size; total_memory += slot->table->fts->cache->total_size;
} }
@@ -2948,6 +2954,7 @@ fts_optimize_thread(
ib_wqueue_t* wq = (ib_wqueue_t*) arg; ib_wqueue_t* wq = (ib_wqueue_t*) arg;
ut_ad(!srv_read_only_mode); ut_ad(!srv_read_only_mode);
my_thread_init();
heap = mem_heap_create(sizeof(dict_table_t*) * 64); heap = mem_heap_create(sizeof(dict_table_t*) * 64);
heap_alloc = ib_heap_allocator_create(heap); heap_alloc = ib_heap_allocator_create(heap);
@@ -3076,9 +3083,11 @@ fts_optimize_thread(
if (slot->state != FTS_STATE_EMPTY) { if (slot->state != FTS_STATE_EMPTY) {
dict_table_t* table = NULL; dict_table_t* table = NULL;
table = dict_table_open_on_name( /*slot->table may be freed, so we try to open
slot->table->name, FALSE, FALSE, table by slot->table_id.*/
DICT_ERR_IGNORE_INDEX_ROOT); table = dict_table_open_on_id(
slot->table_id, FALSE,
DICT_TABLE_OP_NORMAL);
if (table) { if (table) {
@@ -3101,6 +3110,7 @@ fts_optimize_thread(
ib_logf(IB_LOG_LEVEL_INFO, "FTS optimize thread exiting."); ib_logf(IB_LOG_LEVEL_INFO, "FTS optimize thread exiting.");
os_event_set(exit_event); os_event_set(exit_event);
my_thread_end();
/* We count the number of threads in os_thread_exit(). A created /* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */ thread should always use that to exit and not use return() to exit. */

View File

@@ -2903,7 +2903,8 @@ innobase_init(
innobase_hton->flush_logs = innobase_flush_logs; innobase_hton->flush_logs = innobase_flush_logs;
innobase_hton->show_status = innobase_show_status; innobase_hton->show_status = innobase_show_status;
innobase_hton->flags = HTON_SUPPORTS_EXTENDED_KEYS; innobase_hton->flags =
HTON_SUPPORTS_EXTENDED_KEYS | HTON_SUPPORTS_FOREIGN_KEYS;
innobase_hton->release_temporary_latches = innobase_hton->release_temporary_latches =
innobase_release_temporary_latches; innobase_release_temporary_latches;
@@ -12414,6 +12415,7 @@ ha_innobase::start_stmt(
thr_lock_type lock_type) thr_lock_type lock_type)
{ {
trx_t* trx; trx_t* trx;
DBUG_ENTER("ha_innobase::start_stmt");
update_thd(thd); update_thd(thd);
@@ -12437,6 +12439,29 @@ ha_innobase::start_stmt(
prebuilt->hint_need_to_fetch_extra_cols = 0; prebuilt->hint_need_to_fetch_extra_cols = 0;
reset_template(); reset_template();
if (dict_table_is_temporary(prebuilt->table)
&& prebuilt->mysql_has_locked
&& prebuilt->select_lock_type == LOCK_NONE) {
dberr_t error;
switch (thd_sql_command(thd)) {
case SQLCOM_INSERT:
case SQLCOM_UPDATE:
case SQLCOM_DELETE:
init_table_handle_for_HANDLER();
prebuilt->select_lock_type = LOCK_X;
prebuilt->stored_select_lock_type = LOCK_X;
error = row_lock_table_for_mysql(prebuilt, NULL, 1);
if (error != DB_SUCCESS) {
int st = convert_error_code_to_mysql(
error, 0, thd);
DBUG_RETURN(st);
}
break;
}
}
if (!prebuilt->mysql_has_locked) { if (!prebuilt->mysql_has_locked) {
/* This handle is for a temporary table created inside /* This handle is for a temporary table created inside
this same LOCK TABLES; since MySQL does NOT call external_lock this same LOCK TABLES; since MySQL does NOT call external_lock
@@ -12474,7 +12499,7 @@ ha_innobase::start_stmt(
++trx->will_lock; ++trx->will_lock;
} }
return(0); DBUG_RETURN(0);
} }
/******************************************************************//** /******************************************************************//**
@@ -17559,3 +17584,27 @@ innobase_convert_to_system_charset(
static_cast<uint>(len), errors)); static_cast<uint>(len), errors));
} }
/**********************************************************************
Issue a warning that the row is too big. */
void
ib_warn_row_too_big(const dict_table_t* table)
{
/* If prefix is true then a 768-byte prefix is stored
locally for BLOB fields. Refer to dict_table_get_format() */
const bool prefix = (dict_tf_get_format(table->flags)
== UNIV_FORMAT_A);
const ulint free_space = page_get_free_space_of_empty(
table->flags & DICT_TF_COMPACT) / 2;
THD* thd = current_thd;
push_warning_printf(
thd, Sql_condition::WARN_LEVEL_WARN, HA_ERR_TO_BIG_ROW,
"Row size too large (> %lu). Changing some columns to TEXT"
" or BLOB %smay help. In current row format, BLOB prefix of"
" %d bytes is stored inline.", free_space
, prefix ? "or using ROW_FORMAT=DYNAMIC or"
" ROW_FORMAT=COMPRESSED ": ""
, prefix ? DICT_MAX_FIXED_COL_LEN : 0);
}

View File

@@ -3362,9 +3362,7 @@ ha_innobase::prepare_inplace_alter_table(
ulint fts_doc_col_no = ULINT_UNDEFINED; ulint fts_doc_col_no = ULINT_UNDEFINED;
bool add_fts_doc_id = false; bool add_fts_doc_id = false;
bool add_fts_doc_id_idx = false; bool add_fts_doc_id_idx = false;
#ifdef _WIN32
bool add_fts_idx = false; bool add_fts_idx = false;
#endif /* _WIN32 */
DBUG_ENTER("prepare_inplace_alter_table"); DBUG_ENTER("prepare_inplace_alter_table");
DBUG_ASSERT(!ha_alter_info->handler_ctx); DBUG_ASSERT(!ha_alter_info->handler_ctx);
@@ -3509,9 +3507,7 @@ check_if_ok_to_rename:
& ~(HA_FULLTEXT & ~(HA_FULLTEXT
| HA_PACK_KEY | HA_PACK_KEY
| HA_BINARY_PACK_KEY))); | HA_BINARY_PACK_KEY)));
#ifdef _WIN32
add_fts_idx = true; add_fts_idx = true;
#endif /* _WIN32 */
continue; continue;
} }
@@ -3522,19 +3518,16 @@ check_if_ok_to_rename:
} }
} }
#ifdef _WIN32
/* We won't be allowed to add fts index to a table with /* We won't be allowed to add fts index to a table with
fts indexes already but without AUX_HEX_NAME set. fts indexes already but without AUX_HEX_NAME set.
This means the aux tables of the table failed to This means the aux tables of the table failed to
rename to hex format but new created aux tables rename to hex format but new created aux tables
shall be in hex format, which is contradictory. shall be in hex format, which is contradictory. */
It's only for Windows. */
if (!DICT_TF2_FLAG_IS_SET(indexed_table, DICT_TF2_FTS_AUX_HEX_NAME) if (!DICT_TF2_FLAG_IS_SET(indexed_table, DICT_TF2_FTS_AUX_HEX_NAME)
&& indexed_table->fts != NULL && add_fts_idx) { && indexed_table->fts != NULL && add_fts_idx) {
my_error(ER_INNODB_FT_AUX_NOT_HEX_ID, MYF(0)); my_error(ER_INNODB_FT_AUX_NOT_HEX_ID, MYF(0));
goto err_exit_no_heap; goto err_exit_no_heap;
} }
#endif /* _WIN32 */
/* Check existing index definitions for too-long column /* Check existing index definitions for too-long column
prefixes as well, in case max_col_len shrunk. */ prefixes as well, in case max_col_len shrunk. */

View File

@@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1997, 2013, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1997, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@@ -4614,7 +4614,7 @@ ibuf_merge_or_delete_for_page(
function. When the counter is > 0, that prevents tablespace function. When the counter is > 0, that prevents tablespace
from being dropped. */ from being dropped. */
tablespace_being_deleted = fil_inc_pending_ops(space); tablespace_being_deleted = fil_inc_pending_ops(space, true);
if (UNIV_UNLIKELY(tablespace_being_deleted)) { if (UNIV_UNLIKELY(tablespace_being_deleted)) {
/* Do not try to read the bitmap page from space; /* Do not try to read the bitmap page from space;

View File

@@ -1,6 +1,6 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1994, 2012, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@@ -28,7 +28,7 @@ Created 10/16/1994 Heikki Tuuri
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
# define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE)\ # define LIMIT_OPTIMISTIC_INSERT_DEBUG(NREC, CODE)\
if (btr_cur_limit_optimistic_insert_debug\ if (btr_cur_limit_optimistic_insert_debug > 1\
&& (NREC) >= (ulint)btr_cur_limit_optimistic_insert_debug) {\ && (NREC) >= (ulint)btr_cur_limit_optimistic_insert_debug) {\
CODE;\ CODE;\
} }

View File

@@ -85,7 +85,7 @@ dict_get_referenced_table(
mem_heap_t* heap); /*!< in: heap memory */ mem_heap_t* heap); /*!< in: heap memory */
/*********************************************************************//** /*********************************************************************//**
Frees a foreign key struct. */ Frees a foreign key struct. */
UNIV_INTERN
void void
dict_foreign_free( dict_foreign_free(
/*==============*/ /*==============*/

View File

@@ -42,6 +42,7 @@ Created 10/25/1995 Heikki Tuuri
#include <list> #include <list>
extern my_bool lower_case_file_system;
// Forward declaration // Forward declaration
struct trx_t; struct trx_t;
struct fil_space_t; struct fil_space_t;
@@ -590,7 +591,8 @@ UNIV_INTERN
ibool ibool
fil_inc_pending_ops( fil_inc_pending_ops(
/*================*/ /*================*/
ulint id); /*!< in: space id */ ulint id, /*!< in: space id */
ibool print_err); /*!< in: need to print error or not */
/*******************************************************************//** /*******************************************************************//**
Decrements the count of pending operations. */ Decrements the count of pending operations. */
UNIV_INTERN UNIV_INTERN

View File

@@ -37,18 +37,38 @@ fts_write_object_id(
/* in: true for fixed hex format, /* in: true for fixed hex format,
false for old ambiguous format */ false for old ambiguous format */
{ {
#ifdef _WIN32 #ifdef _WIN32
/* Use this to construct old(5.6.14 and 5.7.3) ambiguous
aux table names */ DBUG_EXECUTE_IF("innodb_test_wrong_non_windows_fts_aux_table_name",
return(sprintf(str, UINT64PFx, id)););
/* Use this to construct old(5.6.14 and 5.7.3) windows
ambiguous aux table names */
DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name", DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name",
return(sprintf(str, "%016llu", id));); return(sprintf(str, "%016llu", id)););
#else /* _WIN32 */
/* Use this to construct old(5.6.14 and 5.7.3) windows
ambiguous aux table names */
DBUG_EXECUTE_IF("innodb_test_wrong_windows_fts_aux_table_name",
return(sprintf(str, "%016"PRIu64, id)););
DBUG_EXECUTE_IF("innodb_test_wrong_fts_aux_table_name",
return(sprintf(str, UINT64PFx, id)););
#endif /* _WIN32 */
/* As above, but this is only for those tables failing to rename. */ /* As above, but this is only for those tables failing to rename. */
if (!hex_format) { if (!hex_format) {
#ifdef _WIN32
// FIXME: Use ut_snprintf(), so does following one. // FIXME: Use ut_snprintf(), so does following one.
return(sprintf(str, "%016llu", id)); return(sprintf(str, "%016llu", id));
} #else /* _WIN32 */
return(sprintf(str, "%016"PRIu64, id));
#endif /* _WIN32 */ #endif /* _WIN32 */
}
return(sprintf(str, UINT64PFx, id)); return(sprintf(str, UINT64PFx, id));
} }

View File

@@ -44,7 +44,7 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 5 #define INNODB_VERSION_MAJOR 5
#define INNODB_VERSION_MINOR 6 #define INNODB_VERSION_MINOR 6
#define INNODB_VERSION_BUGFIX 21 #define INNODB_VERSION_BUGFIX 22
/* The following is the InnoDB version as shown in /* The following is the InnoDB version as shown in
SELECT plugin_version FROM information_schema.plugins; SELECT plugin_version FROM information_schema.plugins;

View File

@@ -5497,6 +5497,7 @@ loop:
ulint space = lock->un_member.rec_lock.space; ulint space = lock->un_member.rec_lock.space;
ulint zip_size= fil_space_get_zip_size(space); ulint zip_size= fil_space_get_zip_size(space);
ulint page_no = lock->un_member.rec_lock.page_no; ulint page_no = lock->un_member.rec_lock.page_no;
ibool tablespace_being_deleted = FALSE;
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) { if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
@@ -5515,12 +5516,28 @@ loop:
lock_mutex_exit(); lock_mutex_exit();
mutex_exit(&trx_sys->mutex); mutex_exit(&trx_sys->mutex);
mtr_start(&mtr); DEBUG_SYNC_C("innodb_monitor_before_lock_page_read");
buf_page_get_with_no_latch( /* Check if the space is exists or not. only when the space
space, zip_size, page_no, &mtr); is valid, try to get the page. */
tablespace_being_deleted = fil_inc_pending_ops(space, false);
mtr_commit(&mtr); if (!tablespace_being_deleted) {
mtr_start(&mtr);
buf_page_get_gen(space, zip_size, page_no,
RW_NO_LATCH, NULL,
BUF_GET_POSSIBLY_FREED,
__FILE__, __LINE__, &mtr);
mtr_commit(&mtr);
fil_decr_pending_ops(space);
} else {
fprintf(file, "RECORD LOCKS on"
" non-existing space %lu\n",
(ulong) space);
}
load_page_first = FALSE; load_page_first = FALSE;
@@ -5943,7 +5960,7 @@ lock_rec_block_validate(
/* Make sure that the tablespace is not deleted while we are /* Make sure that the tablespace is not deleted while we are
trying to access the page. */ trying to access the page. */
if (!fil_inc_pending_ops(space)) { if (!fil_inc_pending_ops(space, true)) {
mtr_start(&mtr); mtr_start(&mtr);
block = buf_page_get_gen( block = buf_page_get_gen(
space, fil_space_get_zip_size(space), space, fil_space_get_zip_size(space),

View File

@@ -3407,7 +3407,11 @@ loop:
lsn = log_sys->lsn; lsn = log_sys->lsn;
if (lsn != log_sys->last_checkpoint_lsn ut_ad(srv_force_recovery != SRV_FORCE_NO_LOG_REDO
|| lsn == log_sys->last_checkpoint_lsn + LOG_BLOCK_HDR_SIZE);
if ((srv_force_recovery != SRV_FORCE_NO_LOG_REDO
&& lsn != log_sys->last_checkpoint_lsn)
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
|| (srv_log_archive_on || (srv_log_archive_on
&& lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE) && lsn != log_sys->archived_lsn + LOG_BLOCK_HDR_SIZE)

View File

@@ -114,6 +114,9 @@ os_thread_create_func(
os_thread_id_t* thread_id) /*!< out: id of the created os_thread_id_t* thread_id) /*!< out: id of the created
thread, or NULL */ thread, or NULL */
{ {
/* the new thread should look recent changes up here so far. */
os_wmb;
#ifdef __WIN__ #ifdef __WIN__
os_thread_t thread; os_thread_t thread;
DWORD win_thread_id; DWORD win_thread_id;

View File

@@ -4926,12 +4926,19 @@ page_zip_verify_checksum(
stored = static_cast<ib_uint32_t>(mach_read_from_4( stored = static_cast<ib_uint32_t>(mach_read_from_4(
static_cast<const unsigned char*>(data) + FIL_PAGE_SPACE_OR_CHKSUM)); static_cast<const unsigned char*>(data) + FIL_PAGE_SPACE_OR_CHKSUM));
#if FIL_PAGE_LSN % 8
#error "FIL_PAGE_LSN must be 64 bit aligned"
#endif
#ifndef UNIV_INNOCHECKSUM #ifndef UNIV_INNOCHECKSUM
/* innochecksum doesn't compile with ut_d. Since we don't /* innochecksum doesn't compile with ut_d. Since we don't
need to check for empty pages when running innochecksum, need to check for empty pages when running innochecksum,
just don't include this code. */ just don't include this code. */
/* declare empty pages non-corrupted */ /* Check if page is empty */
if (stored == 0) { if (stored == 0
&& *reinterpret_cast<const ib_uint64_t*>(static_cast<const char*>(
data)
+ FIL_PAGE_LSN) == 0) {
/* make sure that the page is really empty */ /* make sure that the page is really empty */
ulint i; ulint i;
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
@@ -4939,7 +4946,7 @@ page_zip_verify_checksum(
return(FALSE); return(FALSE);
} }
} }
/* Empty page */
return(TRUE); return(TRUE);
} }
#endif #endif

View File

@@ -3792,6 +3792,10 @@ row_drop_table_for_mysql(
pars_info_t* info = NULL; pars_info_t* info = NULL;
mem_heap_t* heap = NULL; mem_heap_t* heap = NULL;
DBUG_ENTER("row_drop_table_for_mysql");
DBUG_PRINT("row_drop_table_for_mysql", ("table: %s", name));
ut_a(name != NULL); ut_a(name != NULL);
if (srv_created_new_raw) { if (srv_created_new_raw) {
@@ -3801,7 +3805,7 @@ row_drop_table_for_mysql(
"InnoDB: Shut down mysqld and edit my.cnf so that newraw" "InnoDB: Shut down mysqld and edit my.cnf so that newraw"
" is replaced with raw.\n", stderr); " is replaced with raw.\n", stderr);
return(DB_ERROR); DBUG_RETURN(DB_ERROR);
} }
/* The table name is prefixed with the database name and a '/'. /* The table name is prefixed with the database name and a '/'.
@@ -4429,7 +4433,7 @@ funct_exit:
srv_wake_master_thread(); srv_wake_master_thread();
return(err); DBUG_RETURN(err);
} }
/*********************************************************************//** /*********************************************************************//**

View File

@@ -286,6 +286,7 @@ rw_lock_free_func(
ib_mutex_t* mutex; ib_mutex_t* mutex;
#endif /* !INNODB_RW_LOCKS_USE_ATOMICS */ #endif /* !INNODB_RW_LOCKS_USE_ATOMICS */
os_rmb;
ut_ad(rw_lock_validate(lock)); ut_ad(rw_lock_validate(lock));
ut_a(lock->lock_word == X_LOCK_DECR); ut_a(lock->lock_word == X_LOCK_DECR);