mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 21:12:26 +01:00
InnoDB 5.6.21
This commit is contained in:
commit
a9a6bd5256
22 changed files with 556 additions and 131 deletions
|
@ -205,9 +205,9 @@ struct ib_tuple_t {
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The following counter is used to convey information to InnoDB
|
/** The following counter is used to convey information to InnoDB
|
||||||
about server activity: in selects it is not sensible to call
|
about server activity: in case of normal DML ops it is not
|
||||||
srv_active_wake_master_thread after each fetch or search, we only do
|
sensible to call srv_active_wake_master_thread after each
|
||||||
it every INNOBASE_WAKE_INTERVAL'th step. */
|
operation, we only do it every INNOBASE_WAKE_INTERVAL'th step. */
|
||||||
|
|
||||||
#define INNOBASE_WAKE_INTERVAL 32
|
#define INNOBASE_WAKE_INTERVAL 32
|
||||||
|
|
||||||
|
@ -707,8 +707,6 @@ ib_trx_rollback(
|
||||||
/* It should always succeed */
|
/* It should always succeed */
|
||||||
ut_a(err == DB_SUCCESS);
|
ut_a(err == DB_SUCCESS);
|
||||||
|
|
||||||
ib_wake_master_thread();
|
|
||||||
|
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1658,7 +1656,7 @@ ib_cursor_insert_row(
|
||||||
src_tuple->index->table, q_proc->grph.ins, node->ins);
|
src_tuple->index->table, q_proc->grph.ins, node->ins);
|
||||||
}
|
}
|
||||||
|
|
||||||
srv_active_wake_master_thread();
|
ib_wake_master_thread();
|
||||||
|
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
@ -1952,7 +1950,7 @@ ib_cursor_update_row(
|
||||||
err = ib_execute_update_query_graph(cursor, pcur);
|
err = ib_execute_update_query_graph(cursor, pcur);
|
||||||
}
|
}
|
||||||
|
|
||||||
srv_active_wake_master_thread();
|
ib_wake_master_thread();
|
||||||
|
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
@ -2094,7 +2092,7 @@ ib_cursor_delete_row(
|
||||||
err = DB_RECORD_NOT_FOUND;
|
err = DB_RECORD_NOT_FOUND;
|
||||||
}
|
}
|
||||||
|
|
||||||
srv_active_wake_master_thread();
|
ib_wake_master_thread();
|
||||||
|
|
||||||
return(err);
|
return(err);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2802,6 +2802,134 @@ btr_page_tuple_smaller(
|
||||||
return(cmp_dtuple_rec(tuple, first_rec, *offsets) < 0);
|
return(cmp_dtuple_rec(tuple, first_rec, *offsets) < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Insert the tuple into the right sibling page, if the cursor is at the end
|
||||||
|
of a page.
|
||||||
|
@param[in] flags undo logging and locking flags
|
||||||
|
@param[in,out] cursor cursor at which to insert; when the function succeeds,
|
||||||
|
the cursor is positioned before the insert point.
|
||||||
|
@param[out] offsets offsets on inserted record
|
||||||
|
@param[in,out] heap memory heap for allocating offsets
|
||||||
|
@param[in] tuple tuple to insert
|
||||||
|
@param[in] n_ext number of externally stored columns
|
||||||
|
@param[in,out] mtr mini-transaction
|
||||||
|
@return inserted record (first record on the right sibling page);
|
||||||
|
the cursor will be positioned on the page infimum
|
||||||
|
@retval NULL if the operation was not performed */
|
||||||
|
static
|
||||||
|
rec_t*
|
||||||
|
btr_insert_into_right_sibling(
|
||||||
|
ulint flags,
|
||||||
|
btr_cur_t* cursor,
|
||||||
|
ulint** offsets,
|
||||||
|
mem_heap_t* heap,
|
||||||
|
const dtuple_t* tuple,
|
||||||
|
ulint n_ext,
|
||||||
|
mtr_t* mtr)
|
||||||
|
{
|
||||||
|
buf_block_t* block = btr_cur_get_block(cursor);
|
||||||
|
page_t* page = buf_block_get_frame(block);
|
||||||
|
ulint next_page_no = btr_page_get_next(page, mtr);
|
||||||
|
|
||||||
|
ut_ad(mtr_memo_contains(mtr, dict_index_get_lock(cursor->index),
|
||||||
|
MTR_MEMO_X_LOCK));
|
||||||
|
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
|
||||||
|
ut_ad(heap);
|
||||||
|
|
||||||
|
if (next_page_no == FIL_NULL || !page_rec_is_supremum(
|
||||||
|
page_rec_get_next(btr_cur_get_rec(cursor)))) {
|
||||||
|
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
page_cur_t next_page_cursor;
|
||||||
|
buf_block_t* next_block;
|
||||||
|
page_t* next_page;
|
||||||
|
btr_cur_t next_father_cursor;
|
||||||
|
rec_t* rec = NULL;
|
||||||
|
ulint zip_size = buf_block_get_zip_size(block);
|
||||||
|
ulint max_size;
|
||||||
|
|
||||||
|
next_block = btr_block_get(
|
||||||
|
buf_block_get_space(block), zip_size,
|
||||||
|
next_page_no, RW_X_LATCH, cursor->index, mtr);
|
||||||
|
next_page = buf_block_get_frame(next_block);
|
||||||
|
|
||||||
|
bool is_leaf = page_is_leaf(next_page);
|
||||||
|
|
||||||
|
btr_page_get_father(
|
||||||
|
cursor->index, next_block, mtr, &next_father_cursor);
|
||||||
|
|
||||||
|
page_cur_search(
|
||||||
|
next_block, cursor->index, tuple, PAGE_CUR_LE,
|
||||||
|
&next_page_cursor);
|
||||||
|
|
||||||
|
max_size = page_get_max_insert_size_after_reorganize(next_page, 1);
|
||||||
|
|
||||||
|
/* Extends gap lock for the next page */
|
||||||
|
lock_update_split_left(next_block, block);
|
||||||
|
|
||||||
|
rec = page_cur_tuple_insert(
|
||||||
|
&next_page_cursor, tuple, cursor->index, offsets, &heap,
|
||||||
|
n_ext, mtr);
|
||||||
|
|
||||||
|
if (rec == NULL) {
|
||||||
|
if (zip_size && is_leaf
|
||||||
|
&& !dict_index_is_clust(cursor->index)) {
|
||||||
|
/* Reset the IBUF_BITMAP_FREE bits, because
|
||||||
|
page_cur_tuple_insert() will have attempted page
|
||||||
|
reorganize before failing. */
|
||||||
|
ibuf_reset_free_bits(next_block);
|
||||||
|
}
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ibool compressed;
|
||||||
|
dberr_t err;
|
||||||
|
ulint level = btr_page_get_level(next_page, mtr);
|
||||||
|
|
||||||
|
/* adjust cursor position */
|
||||||
|
*btr_cur_get_page_cur(cursor) = next_page_cursor;
|
||||||
|
|
||||||
|
ut_ad(btr_cur_get_rec(cursor) == page_get_infimum_rec(next_page));
|
||||||
|
ut_ad(page_rec_get_next(page_get_infimum_rec(next_page)) == rec);
|
||||||
|
|
||||||
|
/* We have to change the parent node pointer */
|
||||||
|
|
||||||
|
compressed = btr_cur_pessimistic_delete(
|
||||||
|
&err, TRUE, &next_father_cursor,
|
||||||
|
BTR_CREATE_FLAG, RB_NONE, mtr);
|
||||||
|
|
||||||
|
ut_a(err == DB_SUCCESS);
|
||||||
|
|
||||||
|
if (!compressed) {
|
||||||
|
btr_cur_compress_if_useful(&next_father_cursor, FALSE, mtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
dtuple_t* node_ptr = dict_index_build_node_ptr(
|
||||||
|
cursor->index, rec, buf_block_get_page_no(next_block),
|
||||||
|
heap, level);
|
||||||
|
|
||||||
|
btr_insert_on_non_leaf_level(
|
||||||
|
flags, cursor->index, level + 1, node_ptr, mtr);
|
||||||
|
|
||||||
|
ut_ad(rec_offs_validate(rec, cursor->index, *offsets));
|
||||||
|
|
||||||
|
if (is_leaf && !dict_index_is_clust(cursor->index)) {
|
||||||
|
/* Update the free bits of the B-tree page in the
|
||||||
|
insert buffer bitmap. */
|
||||||
|
|
||||||
|
if (zip_size) {
|
||||||
|
ibuf_update_free_bits_zip(next_block, mtr);
|
||||||
|
} else {
|
||||||
|
ibuf_update_free_bits_if_full(
|
||||||
|
next_block, max_size,
|
||||||
|
rec_offs_size(*offsets) + PAGE_DIR_SLOT_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return(rec);
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************//**
|
/*************************************************************//**
|
||||||
Splits an index page to halves and inserts the tuple. It is assumed
|
Splits an index page to halves and inserts the tuple. It is assumed
|
||||||
that mtr holds an x-latch to the index tree. NOTE: the tree x-latch is
|
that mtr holds an x-latch to the index tree. NOTE: the tree x-latch is
|
||||||
|
@ -2872,6 +3000,14 @@ func_start:
|
||||||
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
|
ut_ad(mtr_memo_contains(mtr, block, MTR_MEMO_PAGE_X_FIX));
|
||||||
ut_ad(!page_is_empty(page));
|
ut_ad(!page_is_empty(page));
|
||||||
|
|
||||||
|
/* try to insert to the next page if possible before split */
|
||||||
|
rec = btr_insert_into_right_sibling(
|
||||||
|
flags, cursor, offsets, *heap, tuple, n_ext, mtr);
|
||||||
|
|
||||||
|
if (rec != NULL) {
|
||||||
|
return(rec);
|
||||||
|
}
|
||||||
|
|
||||||
page_no = buf_block_get_page_no(block);
|
page_no = buf_block_get_page_no(block);
|
||||||
|
|
||||||
/* 1. Decide the split record; split_rec == NULL means that the
|
/* 1. Decide the split record; split_rec == NULL means that the
|
||||||
|
|
|
@ -1247,7 +1247,7 @@ btr_cur_optimistic_insert(
|
||||||
rec_t* dummy;
|
rec_t* dummy;
|
||||||
ibool leaf;
|
ibool leaf;
|
||||||
ibool reorg;
|
ibool reorg;
|
||||||
ibool inherit;
|
ibool inherit = TRUE;
|
||||||
ulint zip_size;
|
ulint zip_size;
|
||||||
ulint rec_size;
|
ulint rec_size;
|
||||||
dberr_t err;
|
dberr_t err;
|
||||||
|
@ -1525,7 +1525,7 @@ btr_cur_pessimistic_insert(
|
||||||
ulint zip_size = dict_table_zip_size(index->table);
|
ulint zip_size = dict_table_zip_size(index->table);
|
||||||
big_rec_t* big_rec_vec = NULL;
|
big_rec_t* big_rec_vec = NULL;
|
||||||
dberr_t err;
|
dberr_t err;
|
||||||
ibool dummy_inh;
|
ibool inherit = FALSE;
|
||||||
ibool success;
|
ibool success;
|
||||||
ulint n_reserved = 0;
|
ulint n_reserved = 0;
|
||||||
|
|
||||||
|
@ -1547,7 +1547,7 @@ btr_cur_pessimistic_insert(
|
||||||
/* Check locks and write to undo log, if specified */
|
/* Check locks and write to undo log, if specified */
|
||||||
|
|
||||||
err = btr_cur_ins_lock_and_undo(flags, cursor, entry,
|
err = btr_cur_ins_lock_and_undo(flags, cursor, entry,
|
||||||
thr, mtr, &dummy_inh);
|
thr, mtr, &inherit);
|
||||||
|
|
||||||
if (err != DB_SUCCESS) {
|
if (err != DB_SUCCESS) {
|
||||||
|
|
||||||
|
@ -1607,10 +1607,31 @@ btr_cur_pessimistic_insert(
|
||||||
|
|
||||||
ut_ad(page_rec_get_next(btr_cur_get_rec(cursor)) == *rec);
|
ut_ad(page_rec_get_next(btr_cur_get_rec(cursor)) == *rec);
|
||||||
|
|
||||||
|
if (!(flags & BTR_NO_LOCKING_FLAG)) {
|
||||||
|
/* The cursor might be moved to the other page,
|
||||||
|
and the max trx id field should be updated after
|
||||||
|
the cursor was fixed. */
|
||||||
|
if (!dict_index_is_clust(index)) {
|
||||||
|
page_update_max_trx_id(
|
||||||
|
btr_cur_get_block(cursor),
|
||||||
|
btr_cur_get_page_zip(cursor),
|
||||||
|
thr_get_trx(thr)->id, mtr);
|
||||||
|
}
|
||||||
|
if (!page_rec_is_infimum(btr_cur_get_rec(cursor))
|
||||||
|
|| btr_page_get_prev(
|
||||||
|
buf_block_get_frame(
|
||||||
|
btr_cur_get_block(cursor)), mtr)
|
||||||
|
== FIL_NULL) {
|
||||||
|
/* split and inserted need to call
|
||||||
|
lock_update_insert() always. */
|
||||||
|
inherit = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef BTR_CUR_ADAPT
|
#ifdef BTR_CUR_ADAPT
|
||||||
btr_search_update_hash_on_insert(cursor);
|
btr_search_update_hash_on_insert(cursor);
|
||||||
#endif
|
#endif
|
||||||
if (!(flags & BTR_NO_LOCKING_FLAG)) {
|
if (inherit && !(flags & BTR_NO_LOCKING_FLAG)) {
|
||||||
|
|
||||||
lock_update_insert(btr_cur_get_block(cursor), *rec);
|
lock_update_insert(btr_cur_get_block(cursor), *rec);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4192,6 +4192,7 @@ corrupt:
|
||||||
" because of"
|
" because of"
|
||||||
" a corrupt database page.\n",
|
" a corrupt database page.\n",
|
||||||
stderr);
|
stderr);
|
||||||
|
|
||||||
ut_error;
|
ut_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1698,6 +1698,10 @@ dict_table_rename_in_cache(
|
||||||
|
|
||||||
foreign = *it;
|
foreign = *it;
|
||||||
|
|
||||||
|
if (foreign->referenced_table) {
|
||||||
|
foreign->referenced_table->referenced_set.erase(foreign);
|
||||||
|
}
|
||||||
|
|
||||||
if (ut_strlen(foreign->foreign_table_name)
|
if (ut_strlen(foreign->foreign_table_name)
|
||||||
< ut_strlen(table->name)) {
|
< ut_strlen(table->name)) {
|
||||||
/* Allocate a longer name buffer;
|
/* Allocate a longer name buffer;
|
||||||
|
@ -1849,6 +1853,10 @@ dict_table_rename_in_cache(
|
||||||
|
|
||||||
table->foreign_set.erase(it);
|
table->foreign_set.erase(it);
|
||||||
fk_set.insert(foreign);
|
fk_set.insert(foreign);
|
||||||
|
|
||||||
|
if (foreign->referenced_table) {
|
||||||
|
foreign->referenced_table->referenced_set.insert(foreign);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_a(table->foreign_set.empty());
|
ut_a(table->foreign_set.empty());
|
||||||
|
@ -3257,6 +3265,9 @@ dict_foreign_find(
|
||||||
{
|
{
|
||||||
ut_ad(mutex_own(&(dict_sys->mutex)));
|
ut_ad(mutex_own(&(dict_sys->mutex)));
|
||||||
|
|
||||||
|
ut_ad(dict_foreign_set_validate(table->foreign_set));
|
||||||
|
ut_ad(dict_foreign_set_validate(table->referenced_set));
|
||||||
|
|
||||||
dict_foreign_set::iterator it = table->foreign_set.find(foreign);
|
dict_foreign_set::iterator it = table->foreign_set.find(foreign);
|
||||||
|
|
||||||
if (it != table->foreign_set.end()) {
|
if (it != table->foreign_set.end()) {
|
||||||
|
@ -5591,6 +5602,11 @@ dict_find_table_by_space(
|
||||||
|
|
||||||
ut_ad(space_id > 0);
|
ut_ad(space_id > 0);
|
||||||
|
|
||||||
|
if (dict_sys == NULL) {
|
||||||
|
/* This could happen when it's in redo processing. */
|
||||||
|
return(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
|
table = UT_LIST_GET_FIRST(dict_sys->table_LRU);
|
||||||
num_item = UT_LIST_GET_LEN(dict_sys->table_LRU);
|
num_item = UT_LIST_GET_LEN(dict_sys->table_LRU);
|
||||||
|
|
||||||
|
|
|
@ -2537,6 +2537,8 @@ func_exit:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ut_ad(err != DB_SUCCESS || dict_foreign_set_validate(*table));
|
||||||
|
|
||||||
return(table);
|
return(table);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@ Created 1/8/1996 Heikki Tuuri
|
||||||
#include "mach0data.h"
|
#include "mach0data.h"
|
||||||
#include "dict0dict.h"
|
#include "dict0dict.h"
|
||||||
#include "fts0priv.h"
|
#include "fts0priv.h"
|
||||||
|
#include "ut0crc32.h"
|
||||||
#ifndef UNIV_HOTBACKUP
|
#ifndef UNIV_HOTBACKUP
|
||||||
# include "ha_prototypes.h" /* innobase_casedn_str(),
|
# include "ha_prototypes.h" /* innobase_casedn_str(),
|
||||||
innobase_get_lower_case_table_names */
|
innobase_get_lower_case_table_names */
|
||||||
|
@ -44,6 +45,7 @@ Created 1/8/1996 Heikki Tuuri
|
||||||
#ifdef UNIV_BLOB_DEBUG
|
#ifdef UNIV_BLOB_DEBUG
|
||||||
# include "ut0rbt.h"
|
# include "ut0rbt.h"
|
||||||
#endif /* UNIV_BLOB_DEBUG */
|
#endif /* UNIV_BLOB_DEBUG */
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#define DICT_HEAP_SIZE 100 /*!< initial memory heap size when
|
#define DICT_HEAP_SIZE 100 /*!< initial memory heap size when
|
||||||
creating a table or index object */
|
creating a table or index object */
|
||||||
|
@ -61,6 +63,10 @@ static const char* innobase_system_databases[] = {
|
||||||
NullS
|
NullS
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** An interger randomly initialized at startup used to make a temporary
|
||||||
|
table name as unique as possible. */
|
||||||
|
static ib_uint32_t dict_temp_file_num;
|
||||||
|
|
||||||
/**********************************************************************//**
|
/**********************************************************************//**
|
||||||
Creates a table memory object.
|
Creates a table memory object.
|
||||||
@return own: table object */
|
@return own: table object */
|
||||||
|
@ -653,26 +659,120 @@ dict_mem_index_free(
|
||||||
mem_heap_free(index->heap);
|
mem_heap_free(index->heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************//**
|
/** Create a temporary tablename like "#sql-ibtid-inc where
|
||||||
Create a temporary tablename.
|
tid = the Table ID
|
||||||
@return temporary tablename suitable for InnoDB use */
|
inc = a randomly initialized number that is incremented for each file
|
||||||
|
The table ID is a 64 bit integer, can use up to 20 digits, and is
|
||||||
|
initialized at bootstrap. The second number is 32 bits, can use up to 10
|
||||||
|
digits, and is initialized at startup to a randomly distributed number.
|
||||||
|
It is hoped that the combination of these two numbers will provide a
|
||||||
|
reasonably unique temporary file name.
|
||||||
|
@param[in] heap A memory heap
|
||||||
|
@param[in] dbtab Table name in the form database/table name
|
||||||
|
@param[in] id Table id
|
||||||
|
@return A unique temporary tablename suitable for InnoDB use */
|
||||||
UNIV_INTERN
|
UNIV_INTERN
|
||||||
char*
|
char*
|
||||||
dict_mem_create_temporary_tablename(
|
dict_mem_create_temporary_tablename(
|
||||||
/*================================*/
|
mem_heap_t* heap,
|
||||||
mem_heap_t* heap, /*!< in: memory heap */
|
const char* dbtab,
|
||||||
const char* dbtab, /*!< in: database/table name */
|
table_id_t id)
|
||||||
table_id_t id) /*!< in: InnoDB table id */
|
|
||||||
{
|
{
|
||||||
const char* dbend = strchr(dbtab, '/');
|
size_t size;
|
||||||
|
char* name;
|
||||||
|
const char* dbend = strchr(dbtab, '/');
|
||||||
ut_ad(dbend);
|
ut_ad(dbend);
|
||||||
size_t dblen = dbend - dbtab + 1;
|
size_t dblen = dbend - dbtab + 1;
|
||||||
size_t size = tmp_file_prefix_length + 4 + 9 + 9 + dblen;
|
|
||||||
|
|
||||||
char* name = static_cast<char*>(mem_heap_alloc(heap, size));
|
#ifdef HAVE_ATOMIC_BUILTINS
|
||||||
|
/* Increment a randomly initialized number for each temp file. */
|
||||||
|
os_atomic_increment_uint32(&dict_temp_file_num, 1);
|
||||||
|
#else /* HAVE_ATOMIC_BUILTINS */
|
||||||
|
dict_temp_file_num++;
|
||||||
|
#endif /* HAVE_ATOMIC_BUILTINS */
|
||||||
|
|
||||||
|
size = tmp_file_prefix_length + 3 + 20 + 1 + 10 + dblen;
|
||||||
|
name = static_cast<char*>(mem_heap_alloc(heap, size));
|
||||||
memcpy(name, dbtab, dblen);
|
memcpy(name, dbtab, dblen);
|
||||||
ut_snprintf(name + dblen, size - dblen,
|
ut_snprintf(name + dblen, size - dblen,
|
||||||
tmp_file_prefix "-ib" UINT64PF, id);
|
TEMP_FILE_PREFIX_INNODB UINT64PF "-" UINT32PF,
|
||||||
|
id, dict_temp_file_num);
|
||||||
|
|
||||||
return(name);
|
return(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Initialize dict memory variables */
|
||||||
|
|
||||||
|
void
|
||||||
|
dict_mem_init(void)
|
||||||
|
{
|
||||||
|
/* Initialize a randomly distributed temporary file number */
|
||||||
|
ib_uint32_t now = static_cast<ib_uint32_t>(ut_time());
|
||||||
|
|
||||||
|
const byte* buf = reinterpret_cast<const byte*>(&now);
|
||||||
|
ut_ad(ut_crc32 != NULL);
|
||||||
|
|
||||||
|
dict_temp_file_num = ut_crc32(buf, sizeof(now));
|
||||||
|
|
||||||
|
DBUG_PRINT("dict_mem_init",
|
||||||
|
("Starting Temporary file number is " UINT32PF,
|
||||||
|
dict_temp_file_num));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Validate the search order in the foreign key set.
|
||||||
|
@param[in] fk_set the foreign key set to be validated
|
||||||
|
@return true if search order is fine in the set, false otherwise. */
|
||||||
|
bool
|
||||||
|
dict_foreign_set_validate(
|
||||||
|
const dict_foreign_set& fk_set)
|
||||||
|
{
|
||||||
|
dict_foreign_not_exists not_exists(fk_set);
|
||||||
|
|
||||||
|
dict_foreign_set::iterator it = std::find_if(
|
||||||
|
fk_set.begin(), fk_set.end(), not_exists);
|
||||||
|
|
||||||
|
if (it == fk_set.end()) {
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
dict_foreign_t* foreign = *it;
|
||||||
|
std::cerr << "Foreign key lookup failed: " << *foreign;
|
||||||
|
std::cerr << fk_set;
|
||||||
|
ut_ad(0);
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Validate the search order in the foreign key sets of the table
|
||||||
|
(foreign_set and referenced_set).
|
||||||
|
@param[in] table table whose foreign key sets are to be validated
|
||||||
|
@return true if foreign key sets are fine, false otherwise. */
|
||||||
|
bool
|
||||||
|
dict_foreign_set_validate(
|
||||||
|
const dict_table_t& table)
|
||||||
|
{
|
||||||
|
return(dict_foreign_set_validate(table.foreign_set)
|
||||||
|
&& dict_foreign_set_validate(table.referenced_set));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream&
|
||||||
|
operator<< (std::ostream& out, const dict_foreign_t& foreign)
|
||||||
|
{
|
||||||
|
out << "[dict_foreign_t: id='" << foreign.id << "'";
|
||||||
|
|
||||||
|
if (foreign.foreign_table_name != NULL) {
|
||||||
|
out << ",for: '" << foreign.foreign_table_name << "'";
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "]";
|
||||||
|
return(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream&
|
||||||
|
operator<< (std::ostream& out, const dict_foreign_set& fk_set)
|
||||||
|
{
|
||||||
|
out << "[dict_foreign_set:";
|
||||||
|
std::for_each(fk_set.begin(), fk_set.end(), dict_foreign_print(out));
|
||||||
|
out << "]" << std::endl;
|
||||||
|
return(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -243,9 +243,9 @@ static TYPELIB innodb_checksum_algorithm_typelib = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* The following counter is used to convey information to InnoDB
|
/* The following counter is used to convey information to InnoDB
|
||||||
about server activity: in selects it is not sensible to call
|
about server activity: in case of normal DML ops it is not
|
||||||
srv_active_wake_master_thread after each fetch or search, we only do
|
sensible to call srv_active_wake_master_thread after each
|
||||||
it every INNOBASE_WAKE_INTERVAL'th step. */
|
operation, we only do it every INNOBASE_WAKE_INTERVAL'th step. */
|
||||||
|
|
||||||
#define INNOBASE_WAKE_INTERVAL 32
|
#define INNOBASE_WAKE_INTERVAL 32
|
||||||
static ulong innobase_active_counter = 0;
|
static ulong innobase_active_counter = 0;
|
||||||
|
@ -2540,11 +2540,25 @@ innobase_invalidate_query_cache(
|
||||||
above the InnoDB trx_sys_t->lock. The caller of this function must
|
above the InnoDB trx_sys_t->lock. The caller of this function must
|
||||||
not have latches of a lower rank. */
|
not have latches of a lower rank. */
|
||||||
|
|
||||||
/* Argument TRUE below means we are using transactions */
|
|
||||||
#ifdef HAVE_QUERY_CACHE
|
#ifdef HAVE_QUERY_CACHE
|
||||||
|
char qcache_key_name[2 * (NAME_LEN + 1)];
|
||||||
|
size_t tabname_len;
|
||||||
|
size_t dbname_len;
|
||||||
|
|
||||||
|
/* Construct the key("db-name\0table$name\0") for the query cache using
|
||||||
|
the path name("db@002dname\0table@0024name\0") of the table in its
|
||||||
|
canonical form. */
|
||||||
|
dbname_len = filename_to_tablename(full_name, qcache_key_name,
|
||||||
|
sizeof(qcache_key_name));
|
||||||
|
tabname_len = filename_to_tablename(full_name + strlen(full_name) + 1,
|
||||||
|
qcache_key_name + dbname_len + 1,
|
||||||
|
sizeof(qcache_key_name)
|
||||||
|
- dbname_len - 1);
|
||||||
|
|
||||||
|
/* Argument TRUE below means we are using transactions */
|
||||||
mysql_query_cache_invalidate4(trx->mysql_thd,
|
mysql_query_cache_invalidate4(trx->mysql_thd,
|
||||||
full_name,
|
qcache_key_name,
|
||||||
(uint32) full_name_len,
|
(dbname_len + tabname_len + 2),
|
||||||
TRUE);
|
TRUE);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -3758,10 +3772,6 @@ innobase_commit(
|
||||||
|
|
||||||
innobase_srv_conc_force_exit_innodb(trx);
|
innobase_srv_conc_force_exit_innodb(trx);
|
||||||
|
|
||||||
/* Tell the InnoDB server that there might be work for utility
|
|
||||||
threads: */
|
|
||||||
srv_active_wake_master_thread();
|
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7854,7 +7864,8 @@ ha_innobase::index_read(
|
||||||
|
|
||||||
row_sel_convert_mysql_key_to_innobase(
|
row_sel_convert_mysql_key_to_innobase(
|
||||||
prebuilt->search_tuple,
|
prebuilt->search_tuple,
|
||||||
srch_key_val1, sizeof(srch_key_val1),
|
prebuilt->srch_key_val1,
|
||||||
|
prebuilt->srch_key_val_len,
|
||||||
index,
|
index,
|
||||||
(byte*) key_ptr,
|
(byte*) key_ptr,
|
||||||
(ulint) key_len,
|
(ulint) key_len,
|
||||||
|
@ -10471,11 +10482,6 @@ ha_innobase::delete_table(
|
||||||
|
|
||||||
log_buffer_flush_to_disk();
|
log_buffer_flush_to_disk();
|
||||||
|
|
||||||
/* Tell the InnoDB server that there might be work for
|
|
||||||
utility threads: */
|
|
||||||
|
|
||||||
srv_active_wake_master_thread();
|
|
||||||
|
|
||||||
innobase_commit_low(trx);
|
innobase_commit_low(trx);
|
||||||
|
|
||||||
trx_free_for_mysql(trx);
|
trx_free_for_mysql(trx);
|
||||||
|
@ -10557,11 +10563,6 @@ innobase_drop_database(
|
||||||
|
|
||||||
log_buffer_flush_to_disk();
|
log_buffer_flush_to_disk();
|
||||||
|
|
||||||
/* Tell the InnoDB server that there might be work for
|
|
||||||
utility threads: */
|
|
||||||
|
|
||||||
srv_active_wake_master_thread();
|
|
||||||
|
|
||||||
innobase_commit_low(trx);
|
innobase_commit_low(trx);
|
||||||
trx_free_for_mysql(trx);
|
trx_free_for_mysql(trx);
|
||||||
}
|
}
|
||||||
|
@ -10711,11 +10712,6 @@ ha_innobase::rename_table(
|
||||||
|
|
||||||
DEBUG_SYNC(thd, "after_innobase_rename_table");
|
DEBUG_SYNC(thd, "after_innobase_rename_table");
|
||||||
|
|
||||||
/* Tell the InnoDB server that there might be work for
|
|
||||||
utility threads: */
|
|
||||||
|
|
||||||
srv_active_wake_master_thread();
|
|
||||||
|
|
||||||
innobase_commit_low(trx);
|
innobase_commit_low(trx);
|
||||||
trx_free_for_mysql(trx);
|
trx_free_for_mysql(trx);
|
||||||
|
|
||||||
|
@ -10831,7 +10827,8 @@ ha_innobase::records_in_range(
|
||||||
|
|
||||||
row_sel_convert_mysql_key_to_innobase(
|
row_sel_convert_mysql_key_to_innobase(
|
||||||
range_start,
|
range_start,
|
||||||
srch_key_val1, sizeof(srch_key_val1),
|
prebuilt->srch_key_val1,
|
||||||
|
prebuilt->srch_key_val_len,
|
||||||
index,
|
index,
|
||||||
(byte*) (min_key ? min_key->key :
|
(byte*) (min_key ? min_key->key :
|
||||||
(const uchar*) 0),
|
(const uchar*) 0),
|
||||||
|
@ -10843,7 +10840,8 @@ ha_innobase::records_in_range(
|
||||||
|
|
||||||
row_sel_convert_mysql_key_to_innobase(
|
row_sel_convert_mysql_key_to_innobase(
|
||||||
range_end,
|
range_end,
|
||||||
srch_key_val2, sizeof(srch_key_val2),
|
prebuilt->srch_key_val2,
|
||||||
|
prebuilt->srch_key_val_len,
|
||||||
index,
|
index,
|
||||||
(byte*) (max_key ? max_key->key :
|
(byte*) (max_key ? max_key->key :
|
||||||
(const uchar*) 0),
|
(const uchar*) 0),
|
||||||
|
@ -14043,11 +14041,6 @@ innobase_xa_prepare(
|
||||||
trx_mark_sql_stat_end(trx);
|
trx_mark_sql_stat_end(trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tell the InnoDB server that there might be work for utility
|
|
||||||
threads: */
|
|
||||||
|
|
||||||
srv_active_wake_master_thread();
|
|
||||||
|
|
||||||
return(error);
|
return(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,13 +71,6 @@ class ha_innobase: public handler
|
||||||
|
|
||||||
uchar* upd_buf; /*!< buffer used in updates */
|
uchar* upd_buf; /*!< buffer used in updates */
|
||||||
ulint upd_buf_size; /*!< the size of upd_buf in bytes */
|
ulint upd_buf_size; /*!< the size of upd_buf in bytes */
|
||||||
uchar srch_key_val1[MAX_KEY_LENGTH + MAX_REF_PARTS*2];
|
|
||||||
uchar srch_key_val2[MAX_KEY_LENGTH + MAX_REF_PARTS*2];
|
|
||||||
/*!< buffers used in converting
|
|
||||||
search key values from MySQL format
|
|
||||||
to InnoDB format. For each column
|
|
||||||
2 bytes are used to store length,
|
|
||||||
hence MAX_REF_PARTS*2. */
|
|
||||||
Table_flags int_table_flags;
|
Table_flags int_table_flags;
|
||||||
uint primary_key;
|
uint primary_key;
|
||||||
ulong start_of_scan; /*!< this is set to 1 when we are
|
ulong start_of_scan; /*!< this is set to 1 when we are
|
||||||
|
|
|
@ -3244,9 +3244,6 @@ err_exit:
|
||||||
delete ctx;
|
delete ctx;
|
||||||
ha_alter_info->handler_ctx = NULL;
|
ha_alter_info->handler_ctx = NULL;
|
||||||
|
|
||||||
/* There might be work for utility threads.*/
|
|
||||||
srv_active_wake_master_thread();
|
|
||||||
|
|
||||||
DBUG_RETURN(true);
|
DBUG_RETURN(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4272,7 +4269,6 @@ func_exit:
|
||||||
}
|
}
|
||||||
|
|
||||||
trx_commit_for_mysql(prebuilt->trx);
|
trx_commit_for_mysql(prebuilt->trx);
|
||||||
srv_active_wake_master_thread();
|
|
||||||
MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE);
|
MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE);
|
||||||
DBUG_RETURN(fail);
|
DBUG_RETURN(fail);
|
||||||
}
|
}
|
||||||
|
@ -4785,14 +4781,17 @@ innobase_update_foreign_try(
|
||||||
/** Update the foreign key constraint definitions in the data dictionary cache
|
/** Update the foreign key constraint definitions in the data dictionary cache
|
||||||
after the changes to data dictionary tables were committed.
|
after the changes to data dictionary tables were committed.
|
||||||
@param ctx In-place ALTER TABLE context
|
@param ctx In-place ALTER TABLE context
|
||||||
|
@param user_thd MySQL connection
|
||||||
@return InnoDB error code (should always be DB_SUCCESS) */
|
@return InnoDB error code (should always be DB_SUCCESS) */
|
||||||
static __attribute__((nonnull, warn_unused_result))
|
static __attribute__((nonnull, warn_unused_result))
|
||||||
dberr_t
|
dberr_t
|
||||||
innobase_update_foreign_cache(
|
innobase_update_foreign_cache(
|
||||||
/*==========================*/
|
/*==========================*/
|
||||||
ha_innobase_inplace_ctx* ctx)
|
ha_innobase_inplace_ctx* ctx,
|
||||||
|
THD* user_thd)
|
||||||
{
|
{
|
||||||
dict_table_t* user_table;
|
dict_table_t* user_table;
|
||||||
|
dberr_t err = DB_SUCCESS;
|
||||||
|
|
||||||
DBUG_ENTER("innobase_update_foreign_cache");
|
DBUG_ENTER("innobase_update_foreign_cache");
|
||||||
|
|
||||||
|
@ -4827,9 +4826,34 @@ innobase_update_foreign_cache(
|
||||||
/* Load the old or added foreign keys from the data dictionary
|
/* Load the old or added foreign keys from the data dictionary
|
||||||
and prevent the table from being evicted from the data
|
and prevent the table from being evicted from the data
|
||||||
dictionary cache (work around the lack of WL#6049). */
|
dictionary cache (work around the lack of WL#6049). */
|
||||||
DBUG_RETURN(dict_load_foreigns(user_table->name,
|
err = dict_load_foreigns(user_table->name,
|
||||||
ctx->col_names, false, true,
|
ctx->col_names, false, true,
|
||||||
DICT_ERR_IGNORE_NONE));
|
DICT_ERR_IGNORE_NONE);
|
||||||
|
|
||||||
|
if (err == DB_CANNOT_ADD_CONSTRAINT) {
|
||||||
|
/* It is possible there are existing foreign key are
|
||||||
|
loaded with "foreign_key checks" off,
|
||||||
|
so let's retry the loading with charset_check is off */
|
||||||
|
err = dict_load_foreigns(user_table->name,
|
||||||
|
ctx->col_names, false, false,
|
||||||
|
DICT_ERR_IGNORE_NONE);
|
||||||
|
|
||||||
|
/* The load with "charset_check" off is successful, warn
|
||||||
|
the user that the foreign key has loaded with mis-matched
|
||||||
|
charset */
|
||||||
|
if (err == DB_SUCCESS) {
|
||||||
|
push_warning_printf(
|
||||||
|
user_thd,
|
||||||
|
Sql_condition::WARN_LEVEL_WARN,
|
||||||
|
ER_ALTER_INFO,
|
||||||
|
"Foreign key constraints for table '%s'"
|
||||||
|
" are loaded with charset check off",
|
||||||
|
user_table->name);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DBUG_RETURN(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Commit the changes made during prepare_inplace_alter_table()
|
/** Commit the changes made during prepare_inplace_alter_table()
|
||||||
|
@ -5705,12 +5729,12 @@ ha_innobase::commit_inplace_alter_table(
|
||||||
/* Rename the tablespace files. */
|
/* Rename the tablespace files. */
|
||||||
commit_cache_rebuild(ctx);
|
commit_cache_rebuild(ctx);
|
||||||
|
|
||||||
error = innobase_update_foreign_cache(ctx);
|
error = innobase_update_foreign_cache(ctx, user_thd);
|
||||||
if (error != DB_SUCCESS) {
|
if (error != DB_SUCCESS) {
|
||||||
goto foreign_fail;
|
goto foreign_fail;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
error = innobase_update_foreign_cache(ctx);
|
error = innobase_update_foreign_cache(ctx, user_thd);
|
||||||
|
|
||||||
if (error != DB_SUCCESS) {
|
if (error != DB_SUCCESS) {
|
||||||
foreign_fail:
|
foreign_fail:
|
||||||
|
|
|
@ -49,6 +49,7 @@ Created 1/8/1996 Heikki Tuuri
|
||||||
#include "os0once.h"
|
#include "os0once.h"
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
/* Forward declaration. */
|
/* Forward declaration. */
|
||||||
struct ib_rbt_t;
|
struct ib_rbt_t;
|
||||||
|
@ -392,16 +393,29 @@ dict_mem_referenced_table_name_lookup_set(
|
||||||
dict_foreign_t* foreign, /*!< in/out: foreign struct */
|
dict_foreign_t* foreign, /*!< in/out: foreign struct */
|
||||||
ibool do_alloc); /*!< in: is an alloc needed */
|
ibool do_alloc); /*!< in: is an alloc needed */
|
||||||
|
|
||||||
/*******************************************************************//**
|
/** Create a temporary tablename like "#sql-ibtid-inc where
|
||||||
Create a temporary tablename.
|
tid = the Table ID
|
||||||
@return temporary tablename suitable for InnoDB use */
|
inc = a randomly initialized number that is incremented for each file
|
||||||
UNIV_INTERN __attribute__((nonnull, warn_unused_result))
|
The table ID is a 64 bit integer, can use up to 20 digits, and is
|
||||||
|
initialized at bootstrap. The second number is 32 bits, can use up to 10
|
||||||
|
digits, and is initialized at startup to a randomly distributed number.
|
||||||
|
It is hoped that the combination of these two numbers will provide a
|
||||||
|
reasonably unique temporary file name.
|
||||||
|
@param[in] heap A memory heap
|
||||||
|
@param[in] dbtab Table name in the form database/table name
|
||||||
|
@param[in] id Table id
|
||||||
|
@return A unique temporary tablename suitable for InnoDB use */
|
||||||
|
UNIV_INTERN
|
||||||
char*
|
char*
|
||||||
dict_mem_create_temporary_tablename(
|
dict_mem_create_temporary_tablename(
|
||||||
/*================================*/
|
mem_heap_t* heap,
|
||||||
mem_heap_t* heap, /*!< in: memory heap */
|
const char* dbtab,
|
||||||
const char* dbtab, /*!< in: database/table name */
|
table_id_t id);
|
||||||
table_id_t id); /*!< in: InnoDB table id */
|
|
||||||
|
/** Initialize dict memory variables */
|
||||||
|
|
||||||
|
void
|
||||||
|
dict_mem_init(void);
|
||||||
|
|
||||||
/** Data structure for a column in a table */
|
/** Data structure for a column in a table */
|
||||||
struct dict_col_t{
|
struct dict_col_t{
|
||||||
|
@ -718,6 +732,22 @@ struct dict_foreign_t{
|
||||||
dict_index_t* referenced_index;/*!< referenced index */
|
dict_index_t* referenced_index;/*!< referenced index */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::ostream&
|
||||||
|
operator<< (std::ostream& out, const dict_foreign_t& foreign);
|
||||||
|
|
||||||
|
struct dict_foreign_print {
|
||||||
|
|
||||||
|
dict_foreign_print(std::ostream& out)
|
||||||
|
: m_out(out)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void operator()(const dict_foreign_t* foreign) {
|
||||||
|
m_out << *foreign;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::ostream& m_out;
|
||||||
|
};
|
||||||
|
|
||||||
/** Compare two dict_foreign_t objects using their ids. Used in the ordering
|
/** Compare two dict_foreign_t objects using their ids. Used in the ordering
|
||||||
of dict_table_t::foreign_set and dict_table_t::referenced_set. It returns
|
of dict_table_t::foreign_set and dict_table_t::referenced_set. It returns
|
||||||
true if the first argument is considered to go before the second in the
|
true if the first argument is considered to go before the second in the
|
||||||
|
@ -787,6 +817,40 @@ struct dict_foreign_matches_id {
|
||||||
|
|
||||||
typedef std::set<dict_foreign_t*, dict_foreign_compare> dict_foreign_set;
|
typedef std::set<dict_foreign_t*, dict_foreign_compare> dict_foreign_set;
|
||||||
|
|
||||||
|
std::ostream&
|
||||||
|
operator<< (std::ostream& out, const dict_foreign_set& fk_set);
|
||||||
|
|
||||||
|
/** Function object to check if a foreign key object is there
|
||||||
|
in the given foreign key set or not. It returns true if the
|
||||||
|
foreign key is not found, false otherwise */
|
||||||
|
struct dict_foreign_not_exists {
|
||||||
|
dict_foreign_not_exists(const dict_foreign_set& obj_)
|
||||||
|
: m_foreigns(obj_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
/* Return true if the given foreign key is not found */
|
||||||
|
bool operator()(dict_foreign_t* const & foreign) const {
|
||||||
|
return(m_foreigns.find(foreign) == m_foreigns.end());
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
const dict_foreign_set& m_foreigns;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Validate the search order in the foreign key set.
|
||||||
|
@param[in] fk_set the foreign key set to be validated
|
||||||
|
@return true if search order is fine in the set, false otherwise. */
|
||||||
|
bool
|
||||||
|
dict_foreign_set_validate(
|
||||||
|
const dict_foreign_set& fk_set);
|
||||||
|
|
||||||
|
/** Validate the search order in the foreign key sets of the table
|
||||||
|
(foreign_set and referenced_set).
|
||||||
|
@param[in] table table whose foreign key sets are to be validated
|
||||||
|
@return true if foreign key sets are fine, false otherwise. */
|
||||||
|
bool
|
||||||
|
dict_foreign_set_validate(
|
||||||
|
const dict_table_t& table);
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
Frees a foreign key struct. */
|
Frees a foreign key struct. */
|
||||||
inline
|
inline
|
||||||
|
|
|
@ -78,6 +78,7 @@ enum ib_quiesce_t {
|
||||||
/** Prefix for tmp tables, adopted from sql/table.h */
|
/** Prefix for tmp tables, adopted from sql/table.h */
|
||||||
#define tmp_file_prefix "#sql"
|
#define tmp_file_prefix "#sql"
|
||||||
#define tmp_file_prefix_length 4
|
#define tmp_file_prefix_length 4
|
||||||
|
#define TEMP_FILE_PREFIX_INNODB "#sql-ib"
|
||||||
|
|
||||||
#define TEMP_TABLE_PREFIX "#sql"
|
#define TEMP_TABLE_PREFIX "#sql"
|
||||||
#define TEMP_TABLE_PATH_PREFIX "/" TEMP_TABLE_PREFIX
|
#define TEMP_TABLE_PATH_PREFIX "/" TEMP_TABLE_PREFIX
|
||||||
|
|
|
@ -871,6 +871,14 @@ struct row_prebuilt_t {
|
||||||
unsigned innodb_api:1; /*!< whether this is a InnoDB API
|
unsigned innodb_api:1; /*!< whether this is a InnoDB API
|
||||||
query */
|
query */
|
||||||
const rec_t* innodb_api_rec; /*!< InnoDB API search result */
|
const rec_t* innodb_api_rec; /*!< InnoDB API search result */
|
||||||
|
byte* srch_key_val1; /*!< buffer used in converting
|
||||||
|
search key values from MySQL format
|
||||||
|
to InnoDB format.*/
|
||||||
|
byte* srch_key_val2; /*!< buffer used in converting
|
||||||
|
search key values from MySQL format
|
||||||
|
to InnoDB format.*/
|
||||||
|
uint srch_key_val_len; /*!< Size of search key */
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Callback for row_mysql_sys_index_iterate() */
|
/** Callback for row_mysql_sys_index_iterate() */
|
||||||
|
|
|
@ -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 20
|
#define INNODB_VERSION_BUGFIX 21
|
||||||
|
|
||||||
/* 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;
|
||||||
|
|
|
@ -6037,6 +6037,7 @@ lock_rec_insert_check_and_lock(
|
||||||
lock_t* lock;
|
lock_t* lock;
|
||||||
dberr_t err;
|
dberr_t err;
|
||||||
ulint next_rec_heap_no;
|
ulint next_rec_heap_no;
|
||||||
|
ibool inherit_in = *inherit;
|
||||||
|
|
||||||
ut_ad(block->frame == page_align(rec));
|
ut_ad(block->frame == page_align(rec));
|
||||||
ut_ad(!dict_index_is_online_ddl(index)
|
ut_ad(!dict_index_is_online_ddl(index)
|
||||||
|
@ -6069,7 +6070,7 @@ lock_rec_insert_check_and_lock(
|
||||||
|
|
||||||
lock_mutex_exit();
|
lock_mutex_exit();
|
||||||
|
|
||||||
if (!dict_index_is_clust(index)) {
|
if (inherit_in && !dict_index_is_clust(index)) {
|
||||||
/* Update the page max trx id field */
|
/* Update the page max trx id field */
|
||||||
page_update_max_trx_id(block,
|
page_update_max_trx_id(block,
|
||||||
buf_block_get_page_zip(block),
|
buf_block_get_page_zip(block),
|
||||||
|
@ -6117,7 +6118,7 @@ lock_rec_insert_check_and_lock(
|
||||||
err = DB_SUCCESS;
|
err = DB_SUCCESS;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case DB_SUCCESS:
|
case DB_SUCCESS:
|
||||||
if (dict_index_is_clust(index)) {
|
if (!inherit_in || dict_index_is_clust(index)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* Update the page max trx id field */
|
/* Update the page max trx id field */
|
||||||
|
|
|
@ -1946,7 +1946,7 @@ row_ins_scan_sec_index_for_duplicate(
|
||||||
do {
|
do {
|
||||||
const rec_t* rec = btr_pcur_get_rec(&pcur);
|
const rec_t* rec = btr_pcur_get_rec(&pcur);
|
||||||
const buf_block_t* block = btr_pcur_get_block(&pcur);
|
const buf_block_t* block = btr_pcur_get_block(&pcur);
|
||||||
ulint lock_type;
|
const ulint lock_type = LOCK_ORDINARY;
|
||||||
|
|
||||||
if (page_rec_is_infimum(rec)) {
|
if (page_rec_is_infimum(rec)) {
|
||||||
|
|
||||||
|
@ -1956,16 +1956,6 @@ row_ins_scan_sec_index_for_duplicate(
|
||||||
offsets = rec_get_offsets(rec, index, offsets,
|
offsets = rec_get_offsets(rec, index, offsets,
|
||||||
ULINT_UNDEFINED, &offsets_heap);
|
ULINT_UNDEFINED, &offsets_heap);
|
||||||
|
|
||||||
/* If the transaction isolation level is no stronger than
|
|
||||||
READ COMMITTED, then avoid gap locks. */
|
|
||||||
if (!page_rec_is_supremum(rec)
|
|
||||||
&& thr_get_trx(thr)->isolation_level
|
|
||||||
<= TRX_ISO_READ_COMMITTED) {
|
|
||||||
lock_type = LOCK_REC_NOT_GAP;
|
|
||||||
} else {
|
|
||||||
lock_type = LOCK_ORDINARY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags & BTR_NO_LOCKING_FLAG) {
|
if (flags & BTR_NO_LOCKING_FLAG) {
|
||||||
/* Set no locks when applying log
|
/* Set no locks when applying log
|
||||||
in online table rebuild. */
|
in online table rebuild. */
|
||||||
|
|
|
@ -33,6 +33,7 @@ Created 9/17/2000 Heikki Tuuri
|
||||||
#include <debug_sync.h>
|
#include <debug_sync.h>
|
||||||
#include <my_dbug.h>
|
#include <my_dbug.h>
|
||||||
|
|
||||||
|
#include <sql_const.h>
|
||||||
#include "row0ins.h"
|
#include "row0ins.h"
|
||||||
#include "row0merge.h"
|
#include "row0merge.h"
|
||||||
#include "row0sel.h"
|
#include "row0sel.h"
|
||||||
|
@ -711,8 +712,10 @@ row_create_prebuilt(
|
||||||
row_prebuilt_t* prebuilt;
|
row_prebuilt_t* prebuilt;
|
||||||
mem_heap_t* heap;
|
mem_heap_t* heap;
|
||||||
dict_index_t* clust_index;
|
dict_index_t* clust_index;
|
||||||
|
dict_index_t* temp_index;
|
||||||
dtuple_t* ref;
|
dtuple_t* ref;
|
||||||
ulint ref_len;
|
ulint ref_len;
|
||||||
|
uint srch_key_len = 0;
|
||||||
ulint search_tuple_n_fields;
|
ulint search_tuple_n_fields;
|
||||||
|
|
||||||
search_tuple_n_fields = 2 * dict_table_get_n_cols(table);
|
search_tuple_n_fields = 2 * dict_table_get_n_cols(table);
|
||||||
|
@ -724,6 +727,14 @@ row_create_prebuilt(
|
||||||
|
|
||||||
ref_len = dict_index_get_n_unique(clust_index);
|
ref_len = dict_index_get_n_unique(clust_index);
|
||||||
|
|
||||||
|
|
||||||
|
/* Maximum size of the buffer needed for conversion of INTs from
|
||||||
|
little endian format to big endian format in an index. An index
|
||||||
|
can have maximum 16 columns (MAX_REF_PARTS) in it. Therfore
|
||||||
|
Max size for PK: 16 * 8 bytes (BIGINT's size) = 128 bytes
|
||||||
|
Max size Secondary index: 16 * 8 bytes + PK = 256 bytes. */
|
||||||
|
#define MAX_SRCH_KEY_VAL_BUFFER 2* (8 * MAX_REF_PARTS)
|
||||||
|
|
||||||
#define PREBUILT_HEAP_INITIAL_SIZE \
|
#define PREBUILT_HEAP_INITIAL_SIZE \
|
||||||
( \
|
( \
|
||||||
sizeof(*prebuilt) \
|
sizeof(*prebuilt) \
|
||||||
|
@ -752,10 +763,38 @@ row_create_prebuilt(
|
||||||
+ sizeof(que_thr_t) \
|
+ sizeof(que_thr_t) \
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/* Calculate size of key buffer used to store search key in
|
||||||
|
InnoDB format. MySQL stores INTs in little endian format and
|
||||||
|
InnoDB stores INTs in big endian format with the sign bit
|
||||||
|
flipped. All other field types are stored/compared the same
|
||||||
|
in MySQL and InnoDB, so we must create a buffer containing
|
||||||
|
the INT key parts in InnoDB format.We need two such buffers
|
||||||
|
since both start and end keys are used in records_in_range(). */
|
||||||
|
|
||||||
|
for (temp_index = dict_table_get_first_index(table); temp_index;
|
||||||
|
temp_index = dict_table_get_next_index(temp_index)) {
|
||||||
|
DBUG_EXECUTE_IF("innodb_srch_key_buffer_max_value",
|
||||||
|
ut_a(temp_index->n_user_defined_cols
|
||||||
|
== MAX_REF_PARTS););
|
||||||
|
uint temp_len = 0;
|
||||||
|
for (uint i = 0; i < temp_index->n_uniq; i++) {
|
||||||
|
if (temp_index->fields[i].col->mtype == DATA_INT) {
|
||||||
|
temp_len +=
|
||||||
|
temp_index->fields[i].fixed_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
srch_key_len = max(srch_key_len,temp_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
ut_a(srch_key_len <= MAX_SRCH_KEY_VAL_BUFFER);
|
||||||
|
|
||||||
|
DBUG_EXECUTE_IF("innodb_srch_key_buffer_max_value",
|
||||||
|
ut_a(srch_key_len == MAX_SRCH_KEY_VAL_BUFFER););
|
||||||
|
|
||||||
/* We allocate enough space for the objects that are likely to
|
/* We allocate enough space for the objects that are likely to
|
||||||
be created later in order to minimize the number of malloc()
|
be created later in order to minimize the number of malloc()
|
||||||
calls */
|
calls */
|
||||||
heap = mem_heap_create(PREBUILT_HEAP_INITIAL_SIZE);
|
heap = mem_heap_create(PREBUILT_HEAP_INITIAL_SIZE + 2 * srch_key_len);
|
||||||
|
|
||||||
prebuilt = static_cast<row_prebuilt_t*>(
|
prebuilt = static_cast<row_prebuilt_t*>(
|
||||||
mem_heap_zalloc(heap, sizeof(*prebuilt)));
|
mem_heap_zalloc(heap, sizeof(*prebuilt)));
|
||||||
|
@ -768,6 +807,18 @@ row_create_prebuilt(
|
||||||
prebuilt->sql_stat_start = TRUE;
|
prebuilt->sql_stat_start = TRUE;
|
||||||
prebuilt->heap = heap;
|
prebuilt->heap = heap;
|
||||||
|
|
||||||
|
prebuilt->srch_key_val_len = srch_key_len;
|
||||||
|
if (prebuilt->srch_key_val_len) {
|
||||||
|
prebuilt->srch_key_val1 = static_cast<byte*>(
|
||||||
|
mem_heap_alloc(prebuilt->heap,
|
||||||
|
2 * prebuilt->srch_key_val_len));
|
||||||
|
prebuilt->srch_key_val2 = prebuilt->srch_key_val1 +
|
||||||
|
prebuilt->srch_key_val_len;
|
||||||
|
} else {
|
||||||
|
prebuilt->srch_key_val1 = NULL;
|
||||||
|
prebuilt->srch_key_val2 = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
btr_pcur_reset(&prebuilt->pcur);
|
btr_pcur_reset(&prebuilt->pcur);
|
||||||
btr_pcur_reset(&prebuilt->clust_pcur);
|
btr_pcur_reset(&prebuilt->clust_pcur);
|
||||||
|
|
||||||
|
@ -1060,7 +1111,6 @@ row_update_statistics_if_needed(
|
||||||
threshold= ut_min(srv_stats_modified_counter, threshold);
|
threshold= ut_min(srv_stats_modified_counter, threshold);
|
||||||
|
|
||||||
if (counter > threshold) {
|
if (counter > threshold) {
|
||||||
ib_uint64_t threshold= 16 + n_rows / 16; /* 6.25% */
|
|
||||||
|
|
||||||
ut_ad(!mutex_own(&dict_sys->mutex));
|
ut_ad(!mutex_own(&dict_sys->mutex));
|
||||||
/* this will reset table->stat_modified_counter to 0 */
|
/* this will reset table->stat_modified_counter to 0 */
|
||||||
|
|
|
@ -337,9 +337,24 @@ row_purge_remove_sec_if_poss_tree(
|
||||||
if (row_purge_poss_sec(node, index, entry)) {
|
if (row_purge_poss_sec(node, index, entry)) {
|
||||||
/* Remove the index record, which should have been
|
/* Remove the index record, which should have been
|
||||||
marked for deletion. */
|
marked for deletion. */
|
||||||
ut_ad(REC_INFO_DELETED_FLAG
|
if (!rec_get_deleted_flag(btr_cur_get_rec(btr_cur),
|
||||||
& rec_get_info_bits(btr_cur_get_rec(btr_cur),
|
dict_table_is_comp(index->table))) {
|
||||||
dict_table_is_comp(index->table)));
|
fputs("InnoDB: tried to purge sec index entry not"
|
||||||
|
" marked for deletion in\n"
|
||||||
|
"InnoDB: ", stderr);
|
||||||
|
dict_index_name_print(stderr, NULL, index);
|
||||||
|
fputs("\n"
|
||||||
|
"InnoDB: tuple ", stderr);
|
||||||
|
dtuple_print(stderr, entry);
|
||||||
|
fputs("\n"
|
||||||
|
"InnoDB: record ", stderr);
|
||||||
|
rec_print(stderr, btr_cur_get_rec(btr_cur), index);
|
||||||
|
putc('\n', stderr);
|
||||||
|
|
||||||
|
ut_ad(0);
|
||||||
|
|
||||||
|
goto func_exit;
|
||||||
|
}
|
||||||
|
|
||||||
btr_cur_pessimistic_delete(&err, FALSE, btr_cur, 0,
|
btr_cur_pessimistic_delete(&err, FALSE, btr_cur, 0,
|
||||||
RB_NONE, &mtr);
|
RB_NONE, &mtr);
|
||||||
|
@ -428,10 +443,29 @@ row_purge_remove_sec_if_poss_leaf(
|
||||||
btr_cur_t* btr_cur = btr_pcur_get_btr_cur(&pcur);
|
btr_cur_t* btr_cur = btr_pcur_get_btr_cur(&pcur);
|
||||||
|
|
||||||
/* Only delete-marked records should be purged. */
|
/* Only delete-marked records should be purged. */
|
||||||
ut_ad(REC_INFO_DELETED_FLAG
|
if (!rec_get_deleted_flag(
|
||||||
& rec_get_info_bits(
|
btr_cur_get_rec(btr_cur),
|
||||||
btr_cur_get_rec(btr_cur),
|
dict_table_is_comp(index->table))) {
|
||||||
dict_table_is_comp(index->table)));
|
|
||||||
|
fputs("InnoDB: tried to purge sec index"
|
||||||
|
" entry not marked for deletion in\n"
|
||||||
|
"InnoDB: ", stderr);
|
||||||
|
dict_index_name_print(stderr, NULL, index);
|
||||||
|
fputs("\n"
|
||||||
|
"InnoDB: tuple ", stderr);
|
||||||
|
dtuple_print(stderr, entry);
|
||||||
|
fputs("\n"
|
||||||
|
"InnoDB: record ", stderr);
|
||||||
|
rec_print(stderr, btr_cur_get_rec(btr_cur),
|
||||||
|
index);
|
||||||
|
putc('\n', stderr);
|
||||||
|
|
||||||
|
ut_ad(0);
|
||||||
|
|
||||||
|
btr_pcur_close(&pcur);
|
||||||
|
|
||||||
|
goto func_exit_no_pcur;
|
||||||
|
}
|
||||||
|
|
||||||
if (!btr_cur_optimistic_delete(btr_cur, 0, &mtr)) {
|
if (!btr_cur_optimistic_delete(btr_cur, 0, &mtr)) {
|
||||||
|
|
||||||
|
|
|
@ -2451,13 +2451,12 @@ row_sel_convert_mysql_key_to_innobase(
|
||||||
/* Storing may use at most data_len bytes of buf */
|
/* Storing may use at most data_len bytes of buf */
|
||||||
|
|
||||||
if (UNIV_LIKELY(!is_null)) {
|
if (UNIV_LIKELY(!is_null)) {
|
||||||
ut_a(buf + data_len <= original_buf + buf_len);
|
buf = row_mysql_store_col_in_innobase_format(
|
||||||
row_mysql_store_col_in_innobase_format(
|
dfield, buf,
|
||||||
dfield, buf,
|
FALSE, /* MySQL key value format col */
|
||||||
FALSE, /* MySQL key value format col */
|
key_ptr + data_offset, data_len,
|
||||||
key_ptr + data_offset, data_len,
|
dict_table_is_comp(index->table));
|
||||||
dict_table_is_comp(index->table));
|
ut_a(buf <= original_buf + buf_len);
|
||||||
buf += data_len;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
key_ptr += data_field_len;
|
key_ptr += data_field_len;
|
||||||
|
@ -2501,9 +2500,6 @@ row_sel_convert_mysql_key_to_innobase(
|
||||||
dfield++;
|
dfield++;
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_EXECUTE_IF("innodb_srch_key_buffer_full",
|
|
||||||
ut_a(buf == (original_buf + buf_len)););
|
|
||||||
|
|
||||||
ut_a(buf <= original_buf + buf_len);
|
ut_a(buf <= original_buf + buf_len);
|
||||||
|
|
||||||
/* We set the length of tuple to n_fields: we assume that the memory
|
/* We set the length of tuple to n_fields: we assume that the memory
|
||||||
|
|
|
@ -1005,6 +1005,8 @@ srv_init(void)
|
||||||
trx_i_s_cache_init(trx_i_s_cache);
|
trx_i_s_cache_init(trx_i_s_cache);
|
||||||
|
|
||||||
ut_crc32_init();
|
ut_crc32_init();
|
||||||
|
|
||||||
|
dict_mem_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************//**
|
/*********************************************************************//**
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1996, 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
|
||||||
|
@ -126,6 +126,9 @@ trx_rollback_to_savepoint_low(
|
||||||
|
|
||||||
mem_heap_free(heap);
|
mem_heap_free(heap);
|
||||||
|
|
||||||
|
/* There might be work for utility threads.*/
|
||||||
|
srv_active_wake_master_thread();
|
||||||
|
|
||||||
MONITOR_DEC(MONITOR_TRX_ACTIVE);
|
MONITOR_DEC(MONITOR_TRX_ACTIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,20 +146,10 @@ trx_rollback_to_savepoint(
|
||||||
{
|
{
|
||||||
ut_ad(!trx_mutex_own(trx));
|
ut_ad(!trx_mutex_own(trx));
|
||||||
|
|
||||||
/* Tell Innobase server that there might be work for
|
|
||||||
utility threads: */
|
|
||||||
|
|
||||||
srv_active_wake_master_thread();
|
|
||||||
|
|
||||||
trx_start_if_not_started_xa(trx);
|
trx_start_if_not_started_xa(trx);
|
||||||
|
|
||||||
trx_rollback_to_savepoint_low(trx, savept);
|
trx_rollback_to_savepoint_low(trx, savept);
|
||||||
|
|
||||||
/* Tell Innobase server that there might be work for
|
|
||||||
utility threads: */
|
|
||||||
|
|
||||||
srv_active_wake_master_thread();
|
|
||||||
|
|
||||||
return(trx->error_state);
|
return(trx->error_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,8 +162,6 @@ trx_rollback_for_mysql_low(
|
||||||
/*=======================*/
|
/*=======================*/
|
||||||
trx_t* trx) /*!< in/out: transaction */
|
trx_t* trx) /*!< in/out: transaction */
|
||||||
{
|
{
|
||||||
srv_active_wake_master_thread();
|
|
||||||
|
|
||||||
trx->op_info = "rollback";
|
trx->op_info = "rollback";
|
||||||
|
|
||||||
/* If we are doing the XA recovery of prepared transactions,
|
/* If we are doing the XA recovery of prepared transactions,
|
||||||
|
@ -184,8 +175,6 @@ trx_rollback_for_mysql_low(
|
||||||
|
|
||||||
ut_a(trx->error_state == DB_SUCCESS);
|
ut_a(trx->error_state == DB_SUCCESS);
|
||||||
|
|
||||||
srv_active_wake_master_thread();
|
|
||||||
|
|
||||||
return(trx->error_state);
|
return(trx->error_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
|
|
||||||
Copyright (c) 1996, 2013, Oracle and/or its affiliates. All Rights Reserved.
|
Copyright (c) 1996, 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
|
||||||
|
@ -1282,6 +1282,12 @@ trx_commit_in_memory(
|
||||||
}
|
}
|
||||||
|
|
||||||
trx->commit_lsn = lsn;
|
trx->commit_lsn = lsn;
|
||||||
|
|
||||||
|
/* Tell server some activity has happened, since the trx
|
||||||
|
does changes something. Background utility threads like
|
||||||
|
master thread, purge thread or page_cleaner thread might
|
||||||
|
have some work to do. */
|
||||||
|
srv_active_wake_master_thread();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* undo_no is non-zero if we're doing the final commit. */
|
/* undo_no is non-zero if we're doing the final commit. */
|
||||||
|
|
Loading…
Reference in a new issue