mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
Many files:
Small improvements row0mysql.c: Small improvements + fix the ALTER TABLE problem by introducing a lazy drop table it can use ha_innobase.cc: Some fine-tuning of optimization sql/ha_innobase.cc: Some fine-tuning of optimization innobase/include/log0recv.h: Small improvements innobase/include/mem0mem.h: Small improvements innobase/include/mem0pool.h: Small improvements innobase/include/row0mysql.h: Small improvements innobase/include/srv0srv.h: Small improvements innobase/include/trx0trx.h: Small improvements innobase/buf/buf0lru.c: Small improvements innobase/fil/fil0fil.c: Small improvements innobase/log/log0recv.c: Small improvements innobase/mem/mem0mem.c: Small improvements innobase/mem/mem0pool.c: Small improvements innobase/row/row0mysql.c: Small improvements + fix the ALTER TABLE problem by introducing a lazy drop table it can use innobase/srv/srv0srv.c: Small improvements innobase/srv/srv0start.c: Small improvements innobase/trx/trx0purge.c: Small improvements innobase/trx/trx0trx.c: Small improvements
This commit is contained in:
parent
3518de828d
commit
9871a6d080
17 changed files with 610 additions and 123 deletions
|
@ -242,7 +242,6 @@ loop:
|
|||
if (n_iterations > 30) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" ***********************************************\n"
|
||||
"InnoDB: Warning: difficult to find free blocks from\n"
|
||||
"InnoDB: the buffer pool (%lu search iterations)! Consider\n"
|
||||
"InnoDB: increasing the buffer pool size.\n",
|
||||
|
|
|
@ -1088,7 +1088,15 @@ loop:
|
|||
node = UT_LIST_GET_FIRST(space->chain);
|
||||
|
||||
for (;;) {
|
||||
ut_a(node);
|
||||
if (node == NULL) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to access page number %lu in space %lu\n"
|
||||
"InnoDB: which is outside the tablespace bounds.\n"
|
||||
"InnoDB: Byte offset %lu, len %lu, i/o type %lu\n",
|
||||
block_offset, space_id, byte_offset, len, type);
|
||||
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
if (node->size > block_offset) {
|
||||
/* Found! */
|
||||
|
|
|
@ -258,6 +258,7 @@ struct recv_sys_struct{
|
|||
extern recv_sys_t* recv_sys;
|
||||
extern ibool recv_recovery_on;
|
||||
extern ibool recv_no_ibuf_operations;
|
||||
extern ibool recv_needed_recovery;
|
||||
|
||||
/* States of recv_addr_struct */
|
||||
#define RECV_NOT_PROCESSED 71
|
||||
|
|
|
@ -269,13 +269,24 @@ mem_realloc(
|
|||
ulint n, /* in: desired number of bytes */
|
||||
char* file_name,/* in: file name where called */
|
||||
ulint line); /* in: line where called */
|
||||
#ifdef MEM_PERIODIC_CHECK
|
||||
/**********************************************************************
|
||||
Goes through the list of all allocated mem blocks, checks their magic
|
||||
numbers, and reports possible corruption. */
|
||||
|
||||
void
|
||||
mem_validate_all_blocks(void);
|
||||
/*=========================*/
|
||||
#endif
|
||||
|
||||
/*#######################################################################*/
|
||||
|
||||
/* The info header of a block in a memory heap */
|
||||
|
||||
struct mem_block_info_struct {
|
||||
ulint magic_n;/* magic number for debugging */
|
||||
char file_name[8];/* file name where the mem heap was created */
|
||||
ulint line; /* line number where the mem heap was created */
|
||||
UT_LIST_BASE_NODE_T(mem_block_t) base; /* In the first block in the
|
||||
the list this is the base node of the list of blocks;
|
||||
in subsequent blocks this is undefined */
|
||||
|
@ -299,9 +310,11 @@ struct mem_block_info_struct {
|
|||
allocated buffer frame, which can be appended as a
|
||||
free block to the heap, if we need more space;
|
||||
otherwise, this is NULL */
|
||||
ulint magic_n;/* magic number for debugging */
|
||||
char file_name[8];/* file name where the mem heap was created */
|
||||
ulint line; /* line number where the mem heap was created */
|
||||
#ifdef MEM_PERIODIC_CHECK
|
||||
UT_LIST_NODE_T(mem_block_t) mem_block_list;
|
||||
/* List of all mem blocks allocated; protected
|
||||
by the mem_comm_pool mutex */
|
||||
#endif
|
||||
};
|
||||
|
||||
#define MEM_BLOCK_MAGIC_N 764741555
|
||||
|
|
|
@ -72,6 +72,18 @@ mem_pool_get_reserved(
|
|||
/* out: reserved mmeory in bytes */
|
||||
mem_pool_t* pool); /* in: memory pool */
|
||||
/************************************************************************
|
||||
Reserves the mem pool mutex. */
|
||||
|
||||
void
|
||||
mem_pool_mutex_enter(void);
|
||||
/*======================*/
|
||||
/************************************************************************
|
||||
Releases the mem pool mutex. */
|
||||
|
||||
void
|
||||
mem_pool_mutex_exit(void);
|
||||
/*=====================*/
|
||||
/************************************************************************
|
||||
Validates a memory pool. */
|
||||
|
||||
ibool
|
||||
|
|
|
@ -251,6 +251,24 @@ row_table_add_foreign_constraints(
|
|||
char* name); /* in: table full name in the normalized form
|
||||
database_name/table_name */
|
||||
/*************************************************************************
|
||||
The master thread in srv0srv.c calls this regularly to drop tables which
|
||||
we must drop in background after queries to them have ended. Such lazy
|
||||
dropping of tables is needed in ALTER TABLE on Unix. */
|
||||
|
||||
ulint
|
||||
row_drop_tables_for_mysql_in_background(void);
|
||||
/*=========================================*/
|
||||
/* out: how many tables dropped
|
||||
+ remaining tables in list */
|
||||
/*************************************************************************
|
||||
Get the background drop list length. NOTE: the caller must own the kernel
|
||||
mutex! */
|
||||
|
||||
ulint
|
||||
row_get_background_drop_list_len_low(void);
|
||||
/*======================================*/
|
||||
/* out: how many tables in list */
|
||||
/*************************************************************************
|
||||
Drops a table for MySQL. If the name of the dropped table ends to
|
||||
characters INNODB_MONITOR, then this also stops printing of monitor
|
||||
output by the master thread. */
|
||||
|
@ -426,7 +444,7 @@ struct row_prebuilt_struct {
|
|||
fetched row in fetch_cache */
|
||||
ulint n_fetch_cached; /* number of not yet fetched rows
|
||||
in fetch_cache */
|
||||
mem_heap_t* blob_heap; /* in SELECTS BLOB fields are copied
|
||||
mem_heap_t* blob_heap; /* in SELECTS BLOB fie lds are copied
|
||||
to this heap */
|
||||
mem_heap_t* old_vers_heap; /* memory heap where a previous
|
||||
version is built in consistent read */
|
||||
|
|
|
@ -249,6 +249,12 @@ mutex, for performace reasons). */
|
|||
void
|
||||
srv_active_wake_master_thread(void);
|
||||
/*===============================*/
|
||||
/***********************************************************************
|
||||
Wakes up the master thread if it is suspended or being suspended. */
|
||||
|
||||
void
|
||||
srv_wake_master_thread(void);
|
||||
/*========================*/
|
||||
/*************************************************************************
|
||||
Puts an OS thread to wait if there are too many concurrent threads
|
||||
(>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */
|
||||
|
|
|
@ -50,6 +50,13 @@ trx_allocate_for_mysql(void);
|
|||
/*========================*/
|
||||
/* out, own: transaction object */
|
||||
/************************************************************************
|
||||
Creates a transaction object for background operations by the master thread. */
|
||||
|
||||
trx_t*
|
||||
trx_allocate_for_background(void);
|
||||
/*=============================*/
|
||||
/* out, own: transaction object */
|
||||
/************************************************************************
|
||||
Frees a transaction object. */
|
||||
|
||||
void
|
||||
|
@ -63,6 +70,13 @@ void
|
|||
trx_free_for_mysql(
|
||||
/*===============*/
|
||||
trx_t* trx); /* in, own: trx object */
|
||||
/************************************************************************
|
||||
Frees a transaction object of a background operation of the master thread. */
|
||||
|
||||
void
|
||||
trx_free_for_background(
|
||||
/*====================*/
|
||||
trx_t* trx); /* in, own: trx object */
|
||||
/********************************************************************
|
||||
Creates trx objects for transactions and initializes the trx list of
|
||||
trx_sys at database start. Rollback segment and undo log lists must
|
||||
|
@ -266,11 +280,14 @@ struct trx_sig_struct{
|
|||
transaction is waiting a reply */
|
||||
};
|
||||
|
||||
#define TRX_MAGIC_N 91118598
|
||||
|
||||
/* The transaction handle; every session has a trx object which is freed only
|
||||
when the session is freed; in addition there may be session-less transactions
|
||||
rolling back after a database recovery */
|
||||
|
||||
struct trx_struct{
|
||||
ulint magic_n;
|
||||
/* All the next fields are protected by the kernel mutex, except the
|
||||
undo logs which are protected by undo_mutex */
|
||||
char* op_info; /* English text describing the
|
||||
|
|
|
@ -1020,8 +1020,9 @@ loop:
|
|||
|
||||
if (recv_addr->state == RECV_NOT_PROCESSED) {
|
||||
if (!has_printed) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Starting an apply batch of log records to the database...\n"
|
||||
" InnoDB: Starting an apply batch of log records to the database...\n"
|
||||
"InnoDB: Progress in percents: ");
|
||||
has_printed = TRUE;
|
||||
}
|
||||
|
|
|
@ -75,6 +75,14 @@ After freeing, all the blocks in the heap are set to random bytes
|
|||
to help us discover errors which result from the use of
|
||||
buffers in an already freed heap. */
|
||||
|
||||
#ifdef MEM_PERIODIC_CHECK
|
||||
|
||||
ibool mem_block_list_inited;
|
||||
/* List of all mem blocks allocated; protected by the mem_comm_pool mutex */
|
||||
UT_LIST_BASE_NODE_T(mem_block_t) mem_block_list;
|
||||
|
||||
#endif
|
||||
|
||||
/*******************************************************************
|
||||
NOTE: Use the corresponding macro instead of this function.
|
||||
Allocates a single buffer of memory from the dynamic memory of
|
||||
|
@ -169,7 +177,19 @@ mem_heap_create_block(
|
|||
7);
|
||||
block->file_name[7]='\0';
|
||||
block->line = line;
|
||||
|
||||
#ifdef MEM_PERIODIC_CHECK
|
||||
mem_pool_mutex_enter();
|
||||
|
||||
if (!mem_block_list_inited) {
|
||||
mem_block_list_inited = TRUE;
|
||||
UT_LIST_INIT(mem_block_list);
|
||||
}
|
||||
|
||||
UT_LIST_ADD_LAST(mem_block_list, mem_block_list, block);
|
||||
|
||||
mem_pool_mutex_exit();
|
||||
#endif
|
||||
mem_block_set_len(block, len);
|
||||
mem_block_set_type(block, type);
|
||||
mem_block_set_free(block, MEM_BLOCK_HEADER_SIZE);
|
||||
|
@ -261,6 +281,13 @@ mem_heap_block_free(
|
|||
|
||||
UT_LIST_REMOVE(list, heap->base, block);
|
||||
|
||||
#ifdef MEM_PERIODIC_CHECK
|
||||
mem_pool_mutex_enter();
|
||||
|
||||
UT_LIST_REMOVE(mem_block_list, mem_block_list, block);
|
||||
|
||||
mem_pool_mutex_exit();
|
||||
#endif
|
||||
type = heap->type;
|
||||
len = block->len;
|
||||
init_block = block->init_block;
|
||||
|
@ -306,3 +333,30 @@ mem_heap_free_block_free(
|
|||
heap->free_block = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MEM_PERIODIC_CHECK
|
||||
/**********************************************************************
|
||||
Goes through the list of all allocated mem blocks, checks their magic
|
||||
numbers, and reports possible corruption. */
|
||||
|
||||
void
|
||||
mem_validate_all_blocks(void)
|
||||
/*=========================*/
|
||||
{
|
||||
mem_block_t* block;
|
||||
|
||||
mem_pool_mutex_enter();
|
||||
|
||||
block = UT_LIST_GET_FIRST(mem_block_list);
|
||||
|
||||
while (block) {
|
||||
if (block->magic_n != MEM_BLOCK_MAGIC_N) {
|
||||
mem_analyze_corruption((byte*)block);
|
||||
}
|
||||
|
||||
block = UT_LIST_GET_NEXT(mem_block_list, block);
|
||||
}
|
||||
|
||||
mem_pool_mutex_exit();
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -78,9 +78,9 @@ pool, and after that its locks will grow into the buffer pool. */
|
|||
/* The smallest memory area total size */
|
||||
#define MEM_AREA_MIN_SIZE (2 * MEM_AREA_EXTRA_SIZE)
|
||||
|
||||
|
||||
/* Data structure for a memory pool. The space is allocated using the buddy
|
||||
algorithm, where free list i contains areas of size 2 to power i. */
|
||||
|
||||
struct mem_pool_struct{
|
||||
byte* buf; /* memory pool */
|
||||
ulint size; /* memory common pool size */
|
||||
|
@ -98,6 +98,26 @@ mem_pool_t* mem_comm_pool = NULL;
|
|||
|
||||
ulint mem_out_of_mem_err_msg_count = 0;
|
||||
|
||||
/************************************************************************
|
||||
Reserves the mem pool mutex. */
|
||||
|
||||
void
|
||||
mem_pool_mutex_enter(void)
|
||||
/*======================*/
|
||||
{
|
||||
mutex_enter(&(mem_comm_pool->mutex));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Releases the mem pool mutex. */
|
||||
|
||||
void
|
||||
mem_pool_mutex_exit(void)
|
||||
/*=====================*/
|
||||
{
|
||||
mutex_exit(&(mem_comm_pool->mutex));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Returns memory area size. */
|
||||
UNIV_INLINE
|
||||
|
@ -240,15 +260,15 @@ mem_pool_fill_free_list(
|
|||
|
||||
if (mem_out_of_mem_err_msg_count % 1000000000 == 0) {
|
||||
/* We do not print the message every time: */
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
"Innobase: Warning: out of memory in additional memory pool.\n");
|
||||
fprintf(stderr,
|
||||
"Innobase: Innobase will start allocating memory from the OS.\n");
|
||||
fprintf(stderr,
|
||||
"Innobase: You should restart the database with a bigger value in\n");
|
||||
fprintf(stderr,
|
||||
"Innobase: the MySQL .cnf file for innobase_additional_mem_pool_size.\n");
|
||||
" InnoDB: Out of memory in additional memory pool.\n"
|
||||
"InnoDB: InnoDB will start allocating memory from the OS.\n"
|
||||
"InnoDB: You may get better performance if you configure a bigger\n"
|
||||
"InnoDB: value in the MySQL my.cnf file for\n"
|
||||
"InnoDB: innodb_additional_mem_pool_size.\n");
|
||||
}
|
||||
|
||||
mem_out_of_mem_err_msg_count++;
|
||||
|
|
|
@ -26,6 +26,19 @@ Created 9/17/2000 Heikki Tuuri
|
|||
#include "trx0purge.h"
|
||||
#include "lock0lock.h"
|
||||
#include "rem0cmp.h"
|
||||
#include "log0log.h"
|
||||
|
||||
/* List of tables we should drop in background. ALTER TABLE in MySQL requires
|
||||
that the table handler can drop the table in background when there are no
|
||||
queries to it any more. Protected by the kernel mutex. */
|
||||
typedef struct row_mysql_drop_struct row_mysql_drop_t;
|
||||
struct row_mysql_drop_struct{
|
||||
char* table_name;
|
||||
UT_LIST_NODE_T(row_mysql_drop_t) row_mysql_drop_list;
|
||||
};
|
||||
|
||||
UT_LIST_BASE_NODE_T(row_mysql_drop_t) row_mysql_drop_list;
|
||||
ibool row_mysql_drop_list_inited = FALSE;
|
||||
|
||||
/***********************************************************************
|
||||
Reads a MySQL format variable-length field (like VARCHAR) length and
|
||||
|
@ -172,10 +185,22 @@ handle_new_error:
|
|||
trx_general_rollback_for_mysql(trx, TRUE, savept);
|
||||
}
|
||||
} else if (err == DB_TOO_BIG_RECORD) {
|
||||
if (savept) {
|
||||
/* Roll back the latest, possibly incomplete
|
||||
insertion or update */
|
||||
|
||||
trx_general_rollback_for_mysql(trx, TRUE, savept);
|
||||
}
|
||||
/* MySQL will roll back the latest SQL statement */
|
||||
} else if (err == DB_ROW_IS_REFERENCED
|
||||
|| err == DB_NO_REFERENCED_ROW
|
||||
|| err == DB_CANNOT_ADD_CONSTRAINT) {
|
||||
if (savept) {
|
||||
/* Roll back the latest, possibly incomplete
|
||||
insertion or update */
|
||||
|
||||
trx_general_rollback_for_mysql(trx, TRUE, savept);
|
||||
}
|
||||
/* MySQL will roll back the latest SQL statement */
|
||||
} else if (err == DB_LOCK_WAIT) {
|
||||
|
||||
|
@ -200,6 +225,12 @@ handle_new_error:
|
|||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
|
||||
} else if (err == DB_OUT_OF_FILE_SPACE) {
|
||||
if (savept) {
|
||||
/* Roll back the latest, possibly incomplete
|
||||
insertion or update */
|
||||
|
||||
trx_general_rollback_for_mysql(trx, TRUE, savept);
|
||||
}
|
||||
/* MySQL will roll back the latest SQL statement */
|
||||
|
||||
} else if (err == DB_MUST_GET_MORE_FILE_SPACE) {
|
||||
|
@ -375,13 +406,13 @@ row_update_prebuilt_trx(
|
|||
handle */
|
||||
trx_t* trx) /* in: transaction handle */
|
||||
{
|
||||
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
|
||||
if (trx->magic_n != TRX_MAGIC_N) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to free a corrupt\n"
|
||||
"InnoDB: table handle. Magic n %lu, table name %s\n",
|
||||
prebuilt->magic_n, prebuilt->table->name);
|
||||
"InnoDB: Error: trying to use a corrupt\n"
|
||||
"InnoDB: trx handle. Magic n %lu\n",
|
||||
trx->magic_n);
|
||||
|
||||
mem_analyze_corruption((byte*)prebuilt);
|
||||
mem_analyze_corruption((byte*)trx);
|
||||
|
||||
ut_a(0);
|
||||
}
|
||||
|
@ -1170,8 +1201,11 @@ row_create_table_for_mysql(
|
|||
row_drop_table_for_mysql(table->name, trx, TRUE);
|
||||
} else {
|
||||
ut_a(err == DB_DUPLICATE_KEY);
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: table %s already exists in InnoDB internal\n"
|
||||
" InnoDB: Error: table %s already exists in InnoDB internal\n"
|
||||
"InnoDB: data dictionary. Have you deleted the .frm file\n"
|
||||
"InnoDB: and not used DROP TABLE? Have you used DROP DATABASE\n"
|
||||
"InnoDB: for InnoDB tables in MySQL version <= 3.23.43?\n"
|
||||
|
@ -1349,6 +1383,164 @@ row_table_add_foreign_constraints(
|
|||
return((int) err);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Drops a table for MySQL as a background operation. MySQL relies on Unix
|
||||
in ALTER TABLE to the fact that the table handler does not remove the
|
||||
table before all handles to it has been removed. Furhermore, the MySQL's
|
||||
call to drop table must be non-blocking. Therefore we do the drop table
|
||||
as a background operation, which is taken care of by the master thread
|
||||
in srv0srv.c. */
|
||||
static
|
||||
int
|
||||
row_drop_table_for_mysql_in_background(
|
||||
/*===================================*/
|
||||
/* out: error code or DB_SUCCESS */
|
||||
char* name) /* in: table name */
|
||||
{
|
||||
ulint error;
|
||||
trx_t* trx;
|
||||
|
||||
trx = trx_allocate_for_background();
|
||||
|
||||
/* fprintf(stderr, "InnoDB: Dropping table %s in background drop list\n",
|
||||
name); */
|
||||
/* Drop the table in InnoDB */
|
||||
|
||||
error = row_drop_table_for_mysql(name, trx, FALSE);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: Dropping table %s in background drop list failed\n",
|
||||
name);
|
||||
}
|
||||
|
||||
/* Flush the log to reduce probability that the .frm files and
|
||||
the InnoDB data dictionary get out-of-sync if the user runs
|
||||
with innodb_flush_log_at_trx_commit = 0 */
|
||||
|
||||
log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
|
||||
|
||||
trx_commit_for_mysql(trx);
|
||||
|
||||
trx_free_for_background(trx);
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
The master thread in srv0srv.c calls this regularly to drop tables which
|
||||
we must drop in background after queries to them have ended. Such lazy
|
||||
dropping of tables is needed in ALTER TABLE on Unix. */
|
||||
|
||||
ulint
|
||||
row_drop_tables_for_mysql_in_background(void)
|
||||
/*=========================================*/
|
||||
/* out: how many tables dropped
|
||||
+ remaining tables in list */
|
||||
{
|
||||
row_mysql_drop_t* drop;
|
||||
dict_table_t* table;
|
||||
ulint n_tables;
|
||||
ulint n_tables_dropped = 0;
|
||||
loop:
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
if (!row_mysql_drop_list_inited) {
|
||||
|
||||
UT_LIST_INIT(row_mysql_drop_list);
|
||||
row_mysql_drop_list_inited = TRUE;
|
||||
}
|
||||
|
||||
drop = UT_LIST_GET_FIRST(row_mysql_drop_list);
|
||||
|
||||
n_tables = UT_LIST_GET_LEN(row_mysql_drop_list);
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
if (drop == NULL) {
|
||||
|
||||
return(n_tables + n_tables_dropped);
|
||||
}
|
||||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
table = dict_table_get_low(drop->table_name);
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
|
||||
if (table->n_mysql_handles_opened > 0) {
|
||||
|
||||
return(n_tables + n_tables_dropped);
|
||||
}
|
||||
|
||||
n_tables_dropped++;
|
||||
|
||||
row_drop_table_for_mysql_in_background(drop->table_name);
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
UT_LIST_REMOVE(row_mysql_drop_list, row_mysql_drop_list, drop);
|
||||
|
||||
mem_free(drop->table_name);
|
||||
|
||||
mem_free(drop);
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Get the background drop list length. NOTE: the caller must own the kernel
|
||||
mutex! */
|
||||
|
||||
ulint
|
||||
row_get_background_drop_list_len_low(void)
|
||||
/*======================================*/
|
||||
/* out: how many tables in list */
|
||||
{
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
if (!row_mysql_drop_list_inited) {
|
||||
|
||||
UT_LIST_INIT(row_mysql_drop_list);
|
||||
row_mysql_drop_list_inited = TRUE;
|
||||
}
|
||||
|
||||
return(UT_LIST_GET_LEN(row_mysql_drop_list));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Adds a table to the list of tables which the master thread drops in
|
||||
background. We need this on Unix because in ALTER TABLE MySQL may call
|
||||
drop table even if the table has running queries on it. */
|
||||
static
|
||||
void
|
||||
row_add_table_to_background_drop_list(
|
||||
/*==================================*/
|
||||
dict_table_t* table) /* in: table */
|
||||
{
|
||||
row_mysql_drop_t* drop;
|
||||
|
||||
drop = mem_alloc(sizeof(row_mysql_drop_t));
|
||||
|
||||
drop->table_name = mem_alloc(1 + ut_strlen(table->name));
|
||||
|
||||
ut_memcpy(drop->table_name, table->name, 1 + ut_strlen(table->name));
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
if (!row_mysql_drop_list_inited) {
|
||||
|
||||
UT_LIST_INIT(row_mysql_drop_list);
|
||||
row_mysql_drop_list_inited = TRUE;
|
||||
}
|
||||
|
||||
UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop);
|
||||
|
||||
/* fprintf(stderr, "InnoDB: Adding table %s to background drop list\n",
|
||||
drop->table_name); */
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Drops a table for MySQL. If the name of the dropped table ends to
|
||||
characters INNODB_MONITOR, then this also stops printing of monitor
|
||||
|
@ -1536,9 +1728,10 @@ row_drop_table_for_mysql(
|
|||
|
||||
if (!table) {
|
||||
err = DB_TABLE_NOT_FOUND;
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: table %s does not exist in the InnoDB internal\n"
|
||||
" InnoDB: Error: table %s does not exist in the InnoDB internal\n"
|
||||
"InnoDB: data dictionary though MySQL is trying to drop it.\n"
|
||||
"InnoDB: Have you copied the .frm file of the table to the\n"
|
||||
"InnoDB: MySQL database directory from another database?\n",
|
||||
|
@ -1546,41 +1739,18 @@ row_drop_table_for_mysql(
|
|||
goto funct_exit;
|
||||
}
|
||||
|
||||
if (table->n_mysql_handles_opened > 0) {
|
||||
|
||||
row_add_table_to_background_drop_list(table);
|
||||
|
||||
err = DB_SUCCESS;
|
||||
|
||||
goto funct_exit;
|
||||
}
|
||||
|
||||
/* Remove any locks there are on the table or its records */
|
||||
|
||||
lock_reset_all_on_table(table);
|
||||
loop:
|
||||
if (table->n_mysql_handles_opened > 0) {
|
||||
rw_lock_s_unlock(&(purge_sys->purge_is_running));
|
||||
|
||||
rw_lock_x_unlock(&(dict_foreign_key_check_lock));
|
||||
|
||||
mutex_exit(&(dict_sys->mutex));
|
||||
|
||||
if (rounds > 60) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: waiting for queries to table %s to end before dropping it\n",
|
||||
name);
|
||||
}
|
||||
|
||||
os_thread_sleep(1000000);
|
||||
|
||||
mutex_enter(&(dict_sys->mutex));
|
||||
|
||||
rw_lock_x_lock(&(dict_foreign_key_check_lock));
|
||||
|
||||
rw_lock_s_lock(&(purge_sys->purge_is_running));
|
||||
|
||||
rounds++;
|
||||
|
||||
if (rounds > 120) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Warning: queries to table %s have not ended but we continue anyway\n",
|
||||
name);
|
||||
} else {
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
|
||||
trx->dict_operation = TRUE;
|
||||
trx->table_id = table->id;
|
||||
|
@ -1617,6 +1787,8 @@ funct_exit:
|
|||
|
||||
trx->op_info = "";
|
||||
|
||||
srv_wake_master_thread();
|
||||
|
||||
return((int) err);
|
||||
}
|
||||
|
||||
|
@ -1788,7 +1960,31 @@ row_rename_table_for_mysql(
|
|||
err = trx->error_state;
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
row_mysql_handle_errors(&err, trx, thr, NULL);
|
||||
if (err == DB_DUPLICATE_KEY) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: table %s exists in the InnoDB internal data\n"
|
||||
"InnoDB: dictionary though MySQL is trying rename table %s to it.\n"
|
||||
"InnoDB: Have you deleted the .frm file and not used DROP TABLE?\n",
|
||||
new_name, old_name);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: If table %s is a temporary table #sql..., then it can be that\n"
|
||||
"InnoDB: there are still queries running on the table, and it will be\n"
|
||||
"InnoDB: dropped automatically when the queries end.\n", new_name);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: You can drop the orphaned table inside InnoDB by\n"
|
||||
"InnoDB: creating an InnoDB table with the same name in another\n"
|
||||
"InnoDB: database and moving the .frm file to the current database.\n"
|
||||
"InnoDB: Then MySQL thinks the table exists, and DROP TABLE will\n"
|
||||
"InnoDB: succeed.\n");
|
||||
}
|
||||
|
||||
trx->error_state = DB_SUCCESS;
|
||||
trx_general_rollback_for_mysql(trx, FALSE, NULL);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
} else {
|
||||
ut_a(dict_table_rename_in_cache(table, new_name));
|
||||
}
|
||||
|
@ -1945,7 +2141,7 @@ row_check_table_for_mysql(
|
|||
ulint ret = DB_SUCCESS;
|
||||
|
||||
prebuilt->trx->op_info = "checking table";
|
||||
|
||||
|
||||
index = dict_table_get_first_index(table);
|
||||
|
||||
while (index != NULL) {
|
||||
|
|
|
@ -20,7 +20,7 @@ Windows 2000 will have something called thread pooling
|
|||
Another possibility could be to use some very fast user space
|
||||
thread library. This might confuse NT though.
|
||||
|
||||
(c) 1995 InnoDB Oy
|
||||
(c) 1995 Innobase Oy
|
||||
|
||||
Created 10/8/1995 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
@ -49,6 +49,7 @@ Created 10/8/1995 Heikki Tuuri
|
|||
#include "btr0sea.h"
|
||||
#include "dict0load.h"
|
||||
#include "srv0start.h"
|
||||
#include "row0mysql.h"
|
||||
|
||||
/* Buffer which can be used in printing fatal error messages */
|
||||
char srv_fatal_errbuf[5000];
|
||||
|
@ -1911,17 +1912,12 @@ srv_boot(void)
|
|||
|
||||
srv_init();
|
||||
|
||||
/* Reserve the first slot for the current thread, i.e., the master
|
||||
thread */
|
||||
|
||||
srv_table_reserve_slot(SRV_MASTER);
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Reserves a slot in the thread table for the current MySQL OS thread.
|
||||
NOTE! The server mutex has to be reserved by the caller! */
|
||||
NOTE! The kernel mutex has to be reserved by the caller! */
|
||||
static
|
||||
srv_slot_t*
|
||||
srv_table_reserve_slot_for_mysql(void)
|
||||
|
@ -1931,6 +1927,8 @@ srv_table_reserve_slot_for_mysql(void)
|
|||
srv_slot_t* slot;
|
||||
ulint i;
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
i = 0;
|
||||
slot = srv_mysql_table + i;
|
||||
|
||||
|
@ -2352,6 +2350,22 @@ srv_active_wake_master_thread(void)
|
|||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Wakes up the master thread if it is suspended or being suspended. */
|
||||
|
||||
void
|
||||
srv_wake_master_thread(void)
|
||||
/*========================*/
|
||||
{
|
||||
srv_activity_count++;
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
srv_release_threads(SRV_MASTER, 1);
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
The master thread controlling the server. */
|
||||
|
||||
|
@ -2374,6 +2388,7 @@ srv_master_thread(
|
|||
ulint n_bytes_merged;
|
||||
ulint n_pages_flushed;
|
||||
ulint n_bytes_archived;
|
||||
ulint n_tables_to_drop;
|
||||
ulint n_ios;
|
||||
ulint n_ios_old;
|
||||
ulint n_ios_very_old;
|
||||
|
@ -2415,7 +2430,11 @@ loop:
|
|||
can drop tables lazily after there no longer are SELECT
|
||||
queries to them. */
|
||||
|
||||
/* row_drop_tables_for_mysql_in_background(); */
|
||||
srv_main_thread_op_info = "doing background drop tables";
|
||||
|
||||
row_drop_tables_for_mysql_in_background();
|
||||
|
||||
srv_main_thread_op_info = "";
|
||||
|
||||
if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
|
||||
|
||||
|
@ -2465,6 +2484,11 @@ loop:
|
|||
printf("Master thread wakes up!\n");
|
||||
}
|
||||
|
||||
#ifdef MEM_PERIODIC_CHECK
|
||||
/* Check magic numbers of every allocated mem block once in 10
|
||||
seconds */
|
||||
mem_validate_all_blocks();
|
||||
#endif
|
||||
/* If there were less than 200 i/os during the 10 second period,
|
||||
we assume that there is free disk i/o capacity available, and it
|
||||
makes sense to do a buffer pool flush. */
|
||||
|
@ -2521,6 +2545,12 @@ background_loop:
|
|||
/* In this loop we run background operations when the server
|
||||
is quiet and we also come here about once in 10 seconds */
|
||||
|
||||
srv_main_thread_op_info = "doing background drop tables";
|
||||
|
||||
n_tables_to_drop = row_drop_tables_for_mysql_in_background();
|
||||
|
||||
srv_main_thread_op_info = "";
|
||||
|
||||
srv_main_thread_op_info = "flushing buffer pool pages";
|
||||
|
||||
/* Flush a few oldest pages to make the checkpoint younger */
|
||||
|
@ -2604,11 +2634,13 @@ background_loop:
|
|||
log_archive_do(FALSE, &n_bytes_archived);
|
||||
|
||||
if (srv_fast_shutdown && srv_shutdown_state > 0) {
|
||||
if (n_pages_flushed + n_bytes_archived != 0) {
|
||||
if (n_tables_to_drop + n_pages_flushed
|
||||
+ n_bytes_archived != 0) {
|
||||
|
||||
goto background_loop;
|
||||
}
|
||||
} else if (n_pages_purged + n_bytes_merged + n_pages_flushed
|
||||
} else if (n_tables_to_drop +
|
||||
n_pages_purged + n_bytes_merged + n_pages_flushed
|
||||
+ n_bytes_archived != 0) {
|
||||
goto background_loop;
|
||||
}
|
||||
|
@ -2627,6 +2659,12 @@ suspend_thread:
|
|||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
if (row_get_background_drop_list_len_low() > 0) {
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
goto loop;
|
||||
}
|
||||
|
||||
event = srv_suspend_thread();
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
|
|
@ -270,13 +270,18 @@ open_or_create_log_file(
|
|||
} else {
|
||||
*log_file_created = TRUE;
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Log file %s did not exist: new to be created\n",
|
||||
" InnoDB: Log file %s did not exist: new to be created\n",
|
||||
name);
|
||||
fprintf(stderr, "InnoDB: Setting log file %s size to %lu MB\n",
|
||||
name, srv_log_file_size
|
||||
>> (20 - UNIV_PAGE_SIZE_SHIFT));
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Database physically writes the file full: wait...\n");
|
||||
|
||||
ret = os_file_set_size(name, files[i],
|
||||
srv_calc_low32(srv_log_file_size),
|
||||
srv_calc_high32(srv_log_file_size));
|
||||
|
@ -454,8 +459,9 @@ open_or_create_data_files(
|
|||
one_created = TRUE;
|
||||
|
||||
if (i > 0) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Data file %s did not exist: new to be created\n",
|
||||
" InnoDB: Data file %s did not exist: new to be created\n",
|
||||
name);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
|
@ -464,8 +470,9 @@ open_or_create_data_files(
|
|||
*create_new_db = TRUE;
|
||||
}
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Setting file %s size to %lu MB\n",
|
||||
" InnoDB: Setting file %s size to %lu MB\n",
|
||||
name, (srv_data_file_sizes[i]
|
||||
>> (20 - UNIV_PAGE_SIZE_SHIFT)));
|
||||
|
||||
|
@ -905,6 +912,12 @@ innobase_start_or_create_for_mysql(void)
|
|||
mtr_commit(&mtr);
|
||||
}
|
||||
|
||||
if (recv_needed_recovery) {
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Flushing modified pages from the buffer pool...\n");
|
||||
}
|
||||
|
||||
log_make_checkpoint_at(ut_dulint_max, TRUE);
|
||||
|
||||
if (!srv_log_archive_on) {
|
||||
|
@ -983,9 +996,8 @@ innobase_shutdown_for_mysql(void)
|
|||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Warning: shutting down a not properly started\n");
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: or created database!\n");
|
||||
" InnoDB: or created database!\n");
|
||||
}
|
||||
|
||||
return(DB_SUCCESS);
|
||||
|
|
|
@ -226,9 +226,9 @@ trx_purge_sys_create(void)
|
|||
value */
|
||||
purge_sys->sess = sess_open(com_endpoint, (byte*)"purge_system", 13);
|
||||
|
||||
purge_sys->trx = (purge_sys->sess)->trx;
|
||||
purge_sys->trx = purge_sys->sess->trx;
|
||||
|
||||
(purge_sys->trx)->type = TRX_PURGE;
|
||||
purge_sys->trx->type = TRX_PURGE;
|
||||
|
||||
ut_a(trx_start_low(purge_sys->trx, ULINT_UNDEFINED));
|
||||
|
||||
|
|
|
@ -26,9 +26,9 @@ Created 3/26/1996 Heikki Tuuri
|
|||
|
||||
|
||||
/* Copy of the prototype for innobase_mysql_print_thd: this
|
||||
copy must be equal to the one in mysql/sql/ha_innobase.cc ! */
|
||||
void innobase_mysql_print_thd(void* thd);
|
||||
copy must be equal to the one in mysql/sql/ha_innobase.cc ! */
|
||||
|
||||
void innobase_mysql_print_thd(void* thd);
|
||||
|
||||
/* Dummy session used currently in MySQL interface */
|
||||
sess_t* trx_dummy_sess = NULL;
|
||||
|
@ -64,6 +64,8 @@ trx_create(
|
|||
|
||||
trx = mem_alloc(sizeof(trx_t));
|
||||
|
||||
trx->magic_n = TRX_MAGIC_N;
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
trx->type = TRX_USER;
|
||||
|
@ -157,6 +159,32 @@ trx_allocate_for_mysql(void)
|
|||
return(trx);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Creates a transaction object for background operations by the master thread. */
|
||||
|
||||
trx_t*
|
||||
trx_allocate_for_background(void)
|
||||
/*=============================*/
|
||||
/* out, own: transaction object */
|
||||
{
|
||||
trx_t* trx;
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
/* Open a dummy session */
|
||||
|
||||
if (!trx_dummy_sess) {
|
||||
trx_dummy_sess = sess_open(NULL, (byte*)"Dummy sess",
|
||||
ut_strlen("Dummy sess"));
|
||||
}
|
||||
|
||||
trx = trx_create(trx_dummy_sess);
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
return(trx);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Releases the search latch if trx has reserved it. */
|
||||
|
||||
|
@ -181,6 +209,11 @@ trx_free(
|
|||
trx_t* trx) /* in, own: trx object */
|
||||
{
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
ut_a(trx->magic_n == TRX_MAGIC_N);
|
||||
|
||||
trx->magic_n = 11112222;
|
||||
|
||||
ut_a(trx->conc_state == TRX_NOT_STARTED);
|
||||
|
||||
mutex_free(&(trx->undo_mutex));
|
||||
|
@ -242,6 +275,21 @@ trx_free_for_mysql(
|
|||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Frees a transaction object of a background operation of the master thread. */
|
||||
|
||||
void
|
||||
trx_free_for_background(
|
||||
/*====================*/
|
||||
trx_t* trx) /* in, own: trx object */
|
||||
{
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
trx_free(trx);
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Inserts the trx handle in the trx system trx list in the right position.
|
||||
The list is sorted on the trx id so that the biggest id is at the list
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
/* This file defines the InnoDB handler: the interface between MySQL and
|
||||
InnoDB */
|
||||
|
||||
|
||||
/* TODO list for the InnoDB handler:
|
||||
- Ask Monty if strings of different languages can exist in the same
|
||||
database. Answer: in near future yes, but not yet.
|
||||
|
@ -229,7 +229,7 @@ convert_error_code_to_mysql(
|
|||
extern "C" {
|
||||
/*****************************************************************
|
||||
Prints info of a THD object (== user session thread) to the
|
||||
standatd output. NOTE that mysql/innobase/trx/trx0trx.c must contain
|
||||
standard output. NOTE that mysql/innobase/trx/trx0trx.c must contain
|
||||
the prototype for this function! */
|
||||
|
||||
void
|
||||
|
@ -298,6 +298,8 @@ check_trx_exists(
|
|||
|
||||
thd->transaction.stmt.innobase_tid =
|
||||
(void*)&innodb_dummy_stmt_trx_handle;
|
||||
} else {
|
||||
ut_a(trx->magic_n == TRX_MAGIC_N);
|
||||
}
|
||||
|
||||
return(trx);
|
||||
|
@ -835,6 +837,7 @@ innobase_close_connection(
|
|||
whose transaction should be rolled back */
|
||||
{
|
||||
if (NULL != thd->transaction.all.innobase_tid) {
|
||||
|
||||
trx_rollback_for_mysql((trx_t*)
|
||||
(thd->transaction.all.innobase_tid));
|
||||
trx_free_for_mysql((trx_t*)
|
||||
|
@ -2435,44 +2438,6 @@ ha_innobase::position(
|
|||
ref_stored_len = len;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Tells something additional to the handler about how to do things. */
|
||||
|
||||
int
|
||||
ha_innobase::extra(
|
||||
/*===============*/
|
||||
/* out: 0 or error number */
|
||||
enum ha_extra_function operation)
|
||||
/* in: HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE */
|
||||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
|
||||
switch (operation) {
|
||||
case HA_EXTRA_RESET:
|
||||
case HA_EXTRA_RESET_STATE:
|
||||
prebuilt->read_just_key = 0;
|
||||
break;
|
||||
case HA_EXTRA_NO_KEYREAD:
|
||||
prebuilt->read_just_key = 0;
|
||||
break;
|
||||
case HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE:
|
||||
prebuilt->in_update_remember_pos = FALSE;
|
||||
break;
|
||||
case HA_EXTRA_KEYREAD:
|
||||
prebuilt->read_just_key = 1;
|
||||
break;
|
||||
default:/* Do nothing */
|
||||
;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int ha_innobase::reset(void)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Creates a table definition to an InnoDB database. */
|
||||
static
|
||||
|
@ -2952,6 +2917,10 @@ ha_innobase::records_in_range(
|
|||
void* heap2;
|
||||
|
||||
DBUG_ENTER("records_in_range");
|
||||
|
||||
/* Warning: since it is not sure that MySQL calls external_lock
|
||||
before calling this function, the trx field in prebuilt can be
|
||||
obsolete! */
|
||||
|
||||
active_index = keynr;
|
||||
|
||||
|
@ -2984,6 +2953,10 @@ ha_innobase::records_in_range(
|
|||
dtuple_free_for_mysql(heap2);
|
||||
|
||||
my_free((char*) key_val_buff2, MYF(0));
|
||||
|
||||
if (prebuilt->trx) {
|
||||
prebuilt->trx->op_info = "";
|
||||
}
|
||||
|
||||
DBUG_RETURN((ha_rows) n_rows);
|
||||
}
|
||||
|
@ -3005,6 +2978,10 @@ ha_innobase::estimate_number_of_rows(void)
|
|||
ulonglong estimate;
|
||||
ulonglong data_file_length;
|
||||
|
||||
/* Warning: since it is not sure that MySQL calls external_lock
|
||||
before calling this function, the trx field in prebuilt can be
|
||||
obsolete! */
|
||||
|
||||
DBUG_ENTER("info");
|
||||
|
||||
index = dict_table_get_first_index_noninline(prebuilt->table);
|
||||
|
@ -3035,10 +3012,12 @@ ha_innobase::scan_time()
|
|||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
|
||||
/* In the following formula we assume that scanning 10 pages
|
||||
takes the same time as a disk seek: */
|
||||
|
||||
return((double) (prebuilt->table->stat_clustered_index_size / 10));
|
||||
/* Since MySQL seems to favor table scans too much over index
|
||||
searches, we pretend that a sequential read takes the same time
|
||||
as a random disk read, that is, we do not divide the following
|
||||
by 10, which would be physically realistic. */
|
||||
|
||||
return((double) (prebuilt->table->stat_clustered_index_size));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -3058,7 +3037,11 @@ ha_innobase::info(
|
|||
ulong i;
|
||||
|
||||
DBUG_ENTER("info");
|
||||
|
||||
|
||||
/* Warning: since it is not sure that MySQL calls external_lock
|
||||
before calling this function, the trx field in prebuilt can be
|
||||
obsolete! */
|
||||
|
||||
ib_table = prebuilt->table;
|
||||
|
||||
if (flag & HA_STATUS_TIME) {
|
||||
|
@ -3105,6 +3088,13 @@ ha_innobase::info(
|
|||
index->stat_n_diff_key_vals[j + 1]);
|
||||
}
|
||||
|
||||
/* Since MySQL seems to favor table scans
|
||||
too much over index searches, we pretend
|
||||
index selectivity is 2 times better than
|
||||
our estimate: */
|
||||
|
||||
rec_per_key = rec_per_key / 2;
|
||||
|
||||
if (rec_per_key == 0) {
|
||||
rec_per_key = 1;
|
||||
}
|
||||
|
@ -3124,11 +3114,13 @@ ha_innobase::info(
|
|||
pointer and cause a seg fault. */
|
||||
|
||||
if (flag & HA_STATUS_ERRKEY) {
|
||||
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
|
||||
|
||||
errkey = (unsigned int) row_get_mysql_key_number_for_index(
|
||||
(dict_index_t*)
|
||||
trx_get_error_info(prebuilt->trx));
|
||||
}
|
||||
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -3148,7 +3140,9 @@ ha_innobase::check(
|
|||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
ulint ret;
|
||||
|
||||
|
||||
ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
|
||||
|
||||
if (prebuilt->mysql_template == NULL) {
|
||||
/* Build the template; we will use a dummy template
|
||||
in index scans done in checking */
|
||||
|
@ -3182,6 +3176,10 @@ ha_innobase::update_table_comment(
|
|||
char* str = my_malloc(length + 550, MYF(0));
|
||||
char* pos;
|
||||
|
||||
/* Warning: since it is not sure that MySQL calls external_lock
|
||||
before calling this function, the trx field in prebuilt can be
|
||||
obsolete! */
|
||||
|
||||
if (!str) {
|
||||
return((char*)comment);
|
||||
}
|
||||
|
@ -3203,6 +3201,53 @@ ha_innobase::update_table_comment(
|
|||
return(str);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Tells something additional to the handler about how to do things. */
|
||||
|
||||
int
|
||||
ha_innobase::extra(
|
||||
/*===============*/
|
||||
/* out: 0 or error number */
|
||||
enum ha_extra_function operation)
|
||||
/* in: HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE */
|
||||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
|
||||
/* Warning: since it is not sure that MySQL calls external_lock
|
||||
before calling this function, the trx field in prebuilt can be
|
||||
obsolete! */
|
||||
|
||||
switch (operation) {
|
||||
case HA_EXTRA_RESET:
|
||||
case HA_EXTRA_RESET_STATE:
|
||||
prebuilt->read_just_key = 0;
|
||||
break;
|
||||
case HA_EXTRA_NO_KEYREAD:
|
||||
prebuilt->read_just_key = 0;
|
||||
break;
|
||||
case HA_EXTRA_DONT_USE_CURSOR_TO_UPDATE:
|
||||
prebuilt->in_update_remember_pos = FALSE;
|
||||
break;
|
||||
case HA_EXTRA_KEYREAD:
|
||||
prebuilt->read_just_key = 1;
|
||||
break;
|
||||
default:/* Do nothing */
|
||||
;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
????????????? */
|
||||
|
||||
int
|
||||
ha_innobase::reset(void)
|
||||
/*====================*/
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
As MySQL will execute an external lock for every new table it uses when it
|
||||
starts to process an SQL statement, we can use this function to store the
|
||||
|
@ -3427,5 +3472,4 @@ ha_innobase::get_auto_increment()
|
|||
return(nr);
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_INNOBASE_DB */
|
||||
|
|
Loading…
Reference in a new issue