Merge from 3.23.48 tree
This commit is contained in:
commit
79796e989f
@ -5,13 +5,17 @@ Miguel@light.local
|
|||||||
Sinisa@sinisa.nasamreza.org
|
Sinisa@sinisa.nasamreza.org
|
||||||
ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
|
ahlentz@co3064164-a.rochd1.qld.optusnet.com.au
|
||||||
arjen@co3064164-a.bitbike.com
|
arjen@co3064164-a.bitbike.com
|
||||||
|
bell@sanja.is.com.ua
|
||||||
davida@isil.mysql.com
|
davida@isil.mysql.com
|
||||||
heikki@donna.mysql.fi
|
heikki@donna.mysql.fi
|
||||||
jani@hynda.mysql.fi
|
jani@hynda.mysql.fi
|
||||||
jani@janikt.pp.saunalahti.fi
|
jani@janikt.pp.saunalahti.fi
|
||||||
|
jani@rhols221.adsl.netsonic.fi
|
||||||
jcole@abel.spaceapes.com
|
jcole@abel.spaceapes.com
|
||||||
jcole@main.burghcom.com
|
jcole@main.burghcom.com
|
||||||
|
jcole@sarvik.tfr.cafe.ee
|
||||||
jcole@tetra.spaceapes.com
|
jcole@tetra.spaceapes.com
|
||||||
|
kaj@work.mysql.com
|
||||||
miguel@light.local
|
miguel@light.local
|
||||||
monty@bitch.mysql.fi
|
monty@bitch.mysql.fi
|
||||||
monty@donna.mysql.fi
|
monty@donna.mysql.fi
|
||||||
@ -19,6 +23,7 @@ monty@hundin.mysql.fi
|
|||||||
monty@tik.mysql.fi
|
monty@tik.mysql.fi
|
||||||
monty@tramp.mysql.fi
|
monty@tramp.mysql.fi
|
||||||
monty@work.mysql.com
|
monty@work.mysql.com
|
||||||
|
mwagner@cash.mwagner.org
|
||||||
mwagner@evoq.mwagner.org
|
mwagner@evoq.mwagner.org
|
||||||
paul@central.snake.net
|
paul@central.snake.net
|
||||||
paul@teton.kitebird.com
|
paul@teton.kitebird.com
|
||||||
@ -32,14 +37,9 @@ tim@hundin.mysql.fi
|
|||||||
tim@threads.polyesthetic.msg
|
tim@threads.polyesthetic.msg
|
||||||
tim@white.box
|
tim@white.box
|
||||||
tim@work.mysql.com
|
tim@work.mysql.com
|
||||||
|
tom@basil-firewall.home.com
|
||||||
tonu@hundin.mysql.fi
|
tonu@hundin.mysql.fi
|
||||||
tonu@volk.internalnet
|
tonu@volk.internalnet
|
||||||
tonu@x153.internalnet
|
tonu@x153.internalnet
|
||||||
tonu@x3.internalnet
|
tonu@x3.internalnet
|
||||||
jcole@sarvik.tfr.cafe.ee
|
|
||||||
venu@work.mysql.com
|
venu@work.mysql.com
|
||||||
bell@sanja.is.com.ua
|
|
||||||
kaj@work.mysql.com
|
|
||||||
mwagner@cash.mwagner.org
|
|
||||||
tom@basil-firewall.home.com
|
|
||||||
jani@rhols221.adsl.netsonic.fi
|
|
||||||
|
@ -48667,6 +48667,7 @@ users use this code as the rest of the code and because of this we are
|
|||||||
not yet 100% confident in this code.
|
not yet 100% confident in this code.
|
||||||
|
|
||||||
@menu
|
@menu
|
||||||
|
* News-3.23.48:: Changes in release 3.23.48
|
||||||
* News-3.23.47:: Changes in release 3.23.47
|
* News-3.23.47:: Changes in release 3.23.47
|
||||||
* News-3.23.46:: Changes in release 3.23.46
|
* News-3.23.46:: Changes in release 3.23.46
|
||||||
* News-3.23.45:: Changes in release 3.23.45
|
* News-3.23.45:: Changes in release 3.23.45
|
||||||
@ -48718,7 +48719,18 @@ not yet 100% confident in this code.
|
|||||||
* News-3.23.0:: Changes in release 3.23.0
|
* News-3.23.0:: Changes in release 3.23.0
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
@node News-3.23.47, News-3.23.46, News-3.23.x, News-3.23.x
|
@node News-3.23.48, News-3.23.47, News-3.23.x, News-3.23.x
|
||||||
|
@appendixsubsec Changes in release 3.23.48
|
||||||
|
@itemize @bullet
|
||||||
|
@item
|
||||||
|
Fixed bug in complicated join with @code{const} tables.
|
||||||
|
@item
|
||||||
|
Added internal safety checks for InnoDB.
|
||||||
|
@item
|
||||||
|
@code{SHOW GRANTS} now shows @code{REFERENCES} instead of @code{REFERENCE}.
|
||||||
|
@end itemize
|
||||||
|
|
||||||
|
@node News-3.23.47, News-3.23.46, News-3.23.48, News-3.23.x
|
||||||
@appendixsubsec Changes in release 3.23.47
|
@appendixsubsec Changes in release 3.23.47
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
@item
|
||||||
|
@ -195,6 +195,38 @@ dict_mutex_exit_for_mysql(void)
|
|||||||
mutex_exit(&(dict_sys->mutex));
|
mutex_exit(&(dict_sys->mutex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
Increments the count of open MySQL handles to a table. */
|
||||||
|
|
||||||
|
void
|
||||||
|
dict_table_increment_handle_count(
|
||||||
|
/*==============================*/
|
||||||
|
dict_table_t* table) /* in: table */
|
||||||
|
{
|
||||||
|
mutex_enter(&(dict_sys->mutex));
|
||||||
|
|
||||||
|
table->n_mysql_handles_opened++;
|
||||||
|
|
||||||
|
mutex_exit(&(dict_sys->mutex));
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
Decrements the count of open MySQL handles to a table. */
|
||||||
|
|
||||||
|
void
|
||||||
|
dict_table_decrement_handle_count(
|
||||||
|
/*==============================*/
|
||||||
|
dict_table_t* table) /* in: table */
|
||||||
|
{
|
||||||
|
mutex_enter(&(dict_sys->mutex));
|
||||||
|
|
||||||
|
ut_a(table->n_mysql_handles_opened > 0);
|
||||||
|
|
||||||
|
table->n_mysql_handles_opened--;
|
||||||
|
|
||||||
|
mutex_exit(&(dict_sys->mutex));
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
Gets the nth column of a table. */
|
Gets the nth column of a table. */
|
||||||
|
|
||||||
|
@ -59,6 +59,9 @@ dict_mem_table_create(
|
|||||||
table->n_def = 0;
|
table->n_def = 0;
|
||||||
table->n_cols = n_cols + DATA_N_SYS_COLS;
|
table->n_cols = n_cols + DATA_N_SYS_COLS;
|
||||||
table->mem_fix = 0;
|
table->mem_fix = 0;
|
||||||
|
|
||||||
|
table->n_mysql_handles_opened = 0;
|
||||||
|
|
||||||
table->cached = FALSE;
|
table->cached = FALSE;
|
||||||
|
|
||||||
table->cols = mem_heap_alloc(heap, (n_cols + DATA_N_SYS_COLS)
|
table->cols = mem_heap_alloc(heap, (n_cols + DATA_N_SYS_COLS)
|
||||||
|
@ -26,6 +26,20 @@ Created 1/8/1996 Heikki Tuuri
|
|||||||
#include "ut0byte.h"
|
#include "ut0byte.h"
|
||||||
#include "trx0types.h"
|
#include "trx0types.h"
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
Increments the count of open MySQL handles to a table. */
|
||||||
|
|
||||||
|
void
|
||||||
|
dict_table_increment_handle_count(
|
||||||
|
/*==============================*/
|
||||||
|
dict_table_t* table); /* in: table */
|
||||||
|
/************************************************************************
|
||||||
|
Decrements the count of open MySQL handles to a table. */
|
||||||
|
|
||||||
|
void
|
||||||
|
dict_table_decrement_handle_count(
|
||||||
|
/*==============================*/
|
||||||
|
dict_table_t* table); /* in: table */
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
Inits the data dictionary module. */
|
Inits the data dictionary module. */
|
||||||
|
|
||||||
|
@ -307,6 +307,12 @@ struct dict_table_struct{
|
|||||||
ulint mem_fix;/* count of how many times the table
|
ulint mem_fix;/* count of how many times the table
|
||||||
and its indexes has been fixed in memory;
|
and its indexes has been fixed in memory;
|
||||||
currently NOT used */
|
currently NOT used */
|
||||||
|
ulint n_mysql_handles_opened;
|
||||||
|
/* count of how many handles MySQL has opened
|
||||||
|
to this table; dropping of the table is
|
||||||
|
NOT allowed until this count gets to zero;
|
||||||
|
MySQL does NOT itself check the number of
|
||||||
|
open handles at drop */
|
||||||
ibool cached; /* TRUE if the table object has been added
|
ibool cached; /* TRUE if the table object has been added
|
||||||
to the dictionary cache */
|
to the dictionary cache */
|
||||||
lock_t* auto_inc_lock;/* a buffer for an auto-inc lock
|
lock_t* auto_inc_lock;/* a buffer for an auto-inc lock
|
||||||
|
@ -10,11 +10,14 @@ Created 6/9/1994 Heikki Tuuri
|
|||||||
/* In the debug version each allocated field is surrounded with
|
/* In the debug version each allocated field is surrounded with
|
||||||
check fields whose sizes are given below */
|
check fields whose sizes are given below */
|
||||||
|
|
||||||
|
#ifdef UNIV_MEM_DEBUG
|
||||||
#define MEM_FIELD_HEADER_SIZE ut_calc_align(2 * sizeof(ulint),\
|
#define MEM_FIELD_HEADER_SIZE ut_calc_align(2 * sizeof(ulint),\
|
||||||
UNIV_MEM_ALIGNMENT)
|
UNIV_MEM_ALIGNMENT)
|
||||||
#define MEM_FIELD_TRAILER_SIZE sizeof(ulint)
|
#define MEM_FIELD_TRAILER_SIZE sizeof(ulint)
|
||||||
|
#else
|
||||||
|
#define MEM_FIELD_HEADER_SIZE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MEM_BLOCK_MAGIC_N 764741
|
|
||||||
|
|
||||||
/* Space needed when allocating for a user a field of
|
/* Space needed when allocating for a user a field of
|
||||||
length N. The space is allocated only in multiples of
|
length N. The space is allocated only in multiples of
|
||||||
@ -115,3 +118,12 @@ ibool
|
|||||||
mem_validate(void);
|
mem_validate(void);
|
||||||
/*===============*/
|
/*===============*/
|
||||||
/* out: TRUE if ok */
|
/* out: TRUE if ok */
|
||||||
|
/****************************************************************
|
||||||
|
Tries to find neigboring memory allocation blocks and dumps to stderr
|
||||||
|
the neighborhood of a given pointer. */
|
||||||
|
|
||||||
|
void
|
||||||
|
mem_analyze_corruption(
|
||||||
|
/*===================*/
|
||||||
|
byte* ptr); /* in: pointer to place of possible corruption */
|
||||||
|
|
||||||
|
@ -61,58 +61,41 @@ mem_init(
|
|||||||
/******************************************************************
|
/******************************************************************
|
||||||
Use this macro instead of the corresponding function! Macro for memory
|
Use this macro instead of the corresponding function! Macro for memory
|
||||||
heap creation. */
|
heap creation. */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
|
||||||
#define mem_heap_create(N) mem_heap_create_func(\
|
#define mem_heap_create(N) mem_heap_create_func(\
|
||||||
(N), NULL, MEM_HEAP_DYNAMIC,\
|
(N), NULL, MEM_HEAP_DYNAMIC,\
|
||||||
IB__FILE__, __LINE__)
|
IB__FILE__, __LINE__)
|
||||||
#else
|
|
||||||
#define mem_heap_create(N) mem_heap_create_func(N, NULL, MEM_HEAP_DYNAMIC)
|
|
||||||
#endif
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
Use this macro instead of the corresponding function! Macro for memory
|
Use this macro instead of the corresponding function! Macro for memory
|
||||||
heap creation. */
|
heap creation. */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
|
||||||
#define mem_heap_create_in_buffer(N) mem_heap_create_func(\
|
#define mem_heap_create_in_buffer(N) mem_heap_create_func(\
|
||||||
(N), NULL, MEM_HEAP_BUFFER,\
|
(N), NULL, MEM_HEAP_BUFFER,\
|
||||||
IB__FILE__, __LINE__)
|
IB__FILE__, __LINE__)
|
||||||
#else
|
|
||||||
#define mem_heap_create_in_buffer(N) mem_heap_create_func(N, NULL,\
|
|
||||||
MEM_HEAP_BUFFER)
|
|
||||||
#endif
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
Use this macro instead of the corresponding function! Macro for memory
|
Use this macro instead of the corresponding function! Macro for memory
|
||||||
heap creation. */
|
heap creation. */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
|
||||||
#define mem_heap_create_in_btr_search(N) mem_heap_create_func(\
|
#define mem_heap_create_in_btr_search(N) mem_heap_create_func(\
|
||||||
(N), NULL, MEM_HEAP_BTR_SEARCH |\
|
(N), NULL, MEM_HEAP_BTR_SEARCH |\
|
||||||
MEM_HEAP_BUFFER,\
|
MEM_HEAP_BUFFER,\
|
||||||
IB__FILE__, __LINE__)
|
IB__FILE__, __LINE__)
|
||||||
#else
|
|
||||||
#define mem_heap_create_in_btr_search(N) mem_heap_create_func(N, NULL,\
|
|
||||||
MEM_HEAP_BTR_SEARCH | MEM_HEAP_BUFFER)
|
|
||||||
#endif
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
Use this macro instead of the corresponding function! Macro for fast
|
Use this macro instead of the corresponding function! Macro for fast
|
||||||
memory heap creation. An initial block of memory B is given by the
|
memory heap creation. An initial block of memory B is given by the
|
||||||
caller, N is its size, and this memory block is not freed by
|
caller, N is its size, and this memory block is not freed by
|
||||||
mem_heap_free. See the parameter comment in mem_heap_create_func below. */
|
mem_heap_free. See the parameter comment in mem_heap_create_func below. */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
|
||||||
#define mem_heap_fast_create(N, B) mem_heap_create_func(\
|
#define mem_heap_fast_create(N, B) mem_heap_create_func(\
|
||||||
(N), (B), MEM_HEAP_DYNAMIC,\
|
(N), (B), MEM_HEAP_DYNAMIC,\
|
||||||
IB__FILE__, __LINE__)
|
IB__FILE__, __LINE__)
|
||||||
#else
|
|
||||||
#define mem_heap_fast_create(N, B) mem_heap_create_func(N, (B),\
|
|
||||||
MEM_HEAP_DYNAMIC)
|
|
||||||
#endif
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
Use this macro instead of the corresponding function! Macro for memory
|
Use this macro instead of the corresponding function! Macro for memory
|
||||||
heap freeing. */
|
heap freeing. */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
|
||||||
#define mem_heap_free(heap) mem_heap_free_func(\
|
#define mem_heap_free(heap) mem_heap_free_func(\
|
||||||
(heap), IB__FILE__, __LINE__)
|
(heap), IB__FILE__, __LINE__)
|
||||||
#else
|
|
||||||
#define mem_heap_free(heap) mem_heap_free_func(heap)
|
|
||||||
#endif
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
NOTE: Use the corresponding macros instead of this function. Creates a
|
NOTE: Use the corresponding macros instead of this function. Creates a
|
||||||
memory heap which allocates memory from dynamic space. For debugging
|
memory heap which allocates memory from dynamic space. For debugging
|
||||||
@ -139,11 +122,9 @@ mem_heap_create_func(
|
|||||||
block is not unintentionally erased
|
block is not unintentionally erased
|
||||||
(if allocated in the stack), before
|
(if allocated in the stack), before
|
||||||
the memory heap is explicitly freed. */
|
the memory heap is explicitly freed. */
|
||||||
ulint type /* in: MEM_HEAP_DYNAMIC or MEM_HEAP_BUFFER */
|
ulint type, /* in: MEM_HEAP_DYNAMIC or MEM_HEAP_BUFFER */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
char* file_name, /* in: file name where created */
|
||||||
,char* file_name, /* in: file name where created */
|
|
||||||
ulint line /* in: line where created */
|
ulint line /* in: line where created */
|
||||||
#endif
|
|
||||||
);
|
);
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
NOTE: Use the corresponding macro instead of this function.
|
NOTE: Use the corresponding macro instead of this function.
|
||||||
@ -152,11 +133,9 @@ UNIV_INLINE
|
|||||||
void
|
void
|
||||||
mem_heap_free_func(
|
mem_heap_free_func(
|
||||||
/*===============*/
|
/*===============*/
|
||||||
mem_heap_t* heap /* in, own: heap to be freed */
|
mem_heap_t* heap, /* in, own: heap to be freed */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
char* file_name, /* in: file name where freed */
|
||||||
,char* file_name, /* in: file name where freed */
|
ulint line /* in: line where freed */
|
||||||
ulint line /* in: line where freed */
|
|
||||||
#endif
|
|
||||||
);
|
);
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
Allocates n bytes of memory from a memory heap. */
|
Allocates n bytes of memory from a memory heap. */
|
||||||
@ -220,25 +199,18 @@ UNIV_INLINE
|
|||||||
ulint
|
ulint
|
||||||
mem_heap_get_size(
|
mem_heap_get_size(
|
||||||
/*==============*/
|
/*==============*/
|
||||||
mem_heap_t* heap); /* in: heap */
|
mem_heap_t* heap); /* in: heap */
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
Use this macro instead of the corresponding function!
|
Use this macro instead of the corresponding function!
|
||||||
Macro for memory buffer allocation */
|
Macro for memory buffer allocation */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
|
||||||
#define mem_alloc(N) mem_alloc_func(\
|
#define mem_alloc(N) mem_alloc_func((N), IB__FILE__, __LINE__)
|
||||||
(N), IB__FILE__, __LINE__)
|
|
||||||
#else
|
|
||||||
#define mem_alloc(N) mem_alloc_func(N)
|
|
||||||
#endif
|
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
Use this macro instead of the corresponding function!
|
Use this macro instead of the corresponding function!
|
||||||
Macro for memory buffer allocation */
|
Macro for memory buffer allocation */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
|
||||||
#define mem_alloc_noninline(N) mem_alloc_func_noninline(\
|
#define mem_alloc_noninline(N) mem_alloc_func_noninline(\
|
||||||
(N), IB__FILE__, __LINE__)
|
(N), IB__FILE__, __LINE__)
|
||||||
#else
|
|
||||||
#define mem_alloc_noninline(N) mem_alloc_func_noninline(N)
|
|
||||||
#endif
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
NOTE: Use the corresponding macro instead of this function.
|
NOTE: Use the corresponding macro instead of this function.
|
||||||
Allocates a single buffer of memory from the dynamic memory of
|
Allocates a single buffer of memory from the dynamic memory of
|
||||||
@ -250,11 +222,9 @@ mem_alloc_func(
|
|||||||
/*===========*/
|
/*===========*/
|
||||||
/* out, own: free storage, NULL
|
/* out, own: free storage, NULL
|
||||||
if did not succeed */
|
if did not succeed */
|
||||||
ulint n /* in: desired number of bytes */
|
ulint n, /* in: desired number of bytes */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
char* file_name, /* in: file name where created */
|
||||||
,char* file_name, /* in: file name where created */
|
ulint line /* in: line where created */
|
||||||
ulint line /* in: line where created */
|
|
||||||
#endif
|
|
||||||
);
|
);
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
NOTE: Use the corresponding macro instead of this function.
|
NOTE: Use the corresponding macro instead of this function.
|
||||||
@ -267,21 +237,15 @@ mem_alloc_func_noninline(
|
|||||||
/*=====================*/
|
/*=====================*/
|
||||||
/* out, own: free storage, NULL if did not
|
/* out, own: free storage, NULL if did not
|
||||||
succeed */
|
succeed */
|
||||||
ulint n /* in: desired number of bytes */
|
ulint n, /* in: desired number of bytes */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
char* file_name, /* in: file name where created */
|
||||||
,char* file_name, /* in: file name where created */
|
|
||||||
ulint line /* in: line where created */
|
ulint line /* in: line where created */
|
||||||
#endif
|
|
||||||
);
|
);
|
||||||
/******************************************************************
|
/******************************************************************
|
||||||
Use this macro instead of the corresponding function!
|
Use this macro instead of the corresponding function!
|
||||||
Macro for memory buffer freeing */
|
Macro for memory buffer freeing */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
|
||||||
#define mem_free(PTR) mem_free_func(\
|
#define mem_free(PTR) mem_free_func((PTR), IB__FILE__, __LINE__)
|
||||||
(PTR), IB__FILE__, __LINE__)
|
|
||||||
#else
|
|
||||||
#define mem_free(PTR) mem_free_func(PTR)
|
|
||||||
#endif
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
NOTE: Use the corresponding macro instead of this function.
|
NOTE: Use the corresponding macro instead of this function.
|
||||||
Frees a single buffer of storage from
|
Frees a single buffer of storage from
|
||||||
@ -290,11 +254,9 @@ UNIV_INLINE
|
|||||||
void
|
void
|
||||||
mem_free_func(
|
mem_free_func(
|
||||||
/*==========*/
|
/*==========*/
|
||||||
void* ptr /* in, own: buffer to be freed */
|
void* ptr, /* in, own: buffer to be freed */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
char* file_name, /* in: file name where created */
|
||||||
,char* file_name, /* in: file name where created */
|
ulint line /* in: line where created */
|
||||||
ulint line /* in: line where created */
|
|
||||||
#endif
|
|
||||||
);
|
);
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
Implements realloc. */
|
Implements realloc. */
|
||||||
@ -304,7 +266,9 @@ mem_realloc(
|
|||||||
/*========*/
|
/*========*/
|
||||||
/* out, own: free storage, NULL if did not succeed */
|
/* out, own: free storage, NULL if did not succeed */
|
||||||
void* buf, /* in: pointer to an old buffer */
|
void* buf, /* in: pointer to an old buffer */
|
||||||
ulint n); /* in: desired number of bytes */
|
ulint n, /* in: desired number of bytes */
|
||||||
|
char* file_name,/* in: file name where called */
|
||||||
|
ulint line); /* in: line where called */
|
||||||
|
|
||||||
|
|
||||||
/*#######################################################################*/
|
/*#######################################################################*/
|
||||||
@ -336,8 +300,13 @@ struct mem_block_info_struct {
|
|||||||
free block to the heap, if we need more space;
|
free block to the heap, if we need more space;
|
||||||
otherwise, this is NULL */
|
otherwise, this is NULL */
|
||||||
ulint magic_n;/* magic number for debugging */
|
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 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MEM_BLOCK_MAGIC_N 764741555
|
||||||
|
#define MEM_FREED_BLOCK_MAGIC_N 547711122
|
||||||
|
|
||||||
/* Header size for a memory heap block */
|
/* Header size for a memory heap block */
|
||||||
#define MEM_BLOCK_HEADER_SIZE ut_calc_align(sizeof(mem_block_info_t),\
|
#define MEM_BLOCK_HEADER_SIZE ut_calc_align(sizeof(mem_block_info_t),\
|
||||||
UNIV_MEM_ALIGNMENT)
|
UNIV_MEM_ALIGNMENT)
|
||||||
|
@ -24,8 +24,10 @@ mem_heap_create_block(
|
|||||||
if init_block is not NULL, its size in bytes */
|
if init_block is not NULL, its size in bytes */
|
||||||
void* init_block, /* in: init block in fast create, type must be
|
void* init_block, /* in: init block in fast create, type must be
|
||||||
MEM_HEAP_DYNAMIC */
|
MEM_HEAP_DYNAMIC */
|
||||||
ulint type); /* in: type of heap: MEM_HEAP_DYNAMIC or
|
ulint type, /* in: type of heap: MEM_HEAP_DYNAMIC or
|
||||||
MEM_HEAP_BUFFER */
|
MEM_HEAP_BUFFER */
|
||||||
|
char* file_name,/* in: file name where created */
|
||||||
|
ulint line); /* in: line where created */
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
Frees a block from a memory heap. */
|
Frees a block from a memory heap. */
|
||||||
|
|
||||||
@ -392,21 +394,20 @@ mem_heap_create_func(
|
|||||||
block is not unintentionally erased
|
block is not unintentionally erased
|
||||||
(if allocated in the stack), before
|
(if allocated in the stack), before
|
||||||
the memory heap is explicitly freed. */
|
the memory heap is explicitly freed. */
|
||||||
ulint type /* in: MEM_HEAP_DYNAMIC, or MEM_HEAP_BUFFER
|
ulint type, /* in: MEM_HEAP_DYNAMIC, or MEM_HEAP_BUFFER
|
||||||
possibly ORed to MEM_HEAP_BTR_SEARCH */
|
possibly ORed to MEM_HEAP_BTR_SEARCH */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
char* file_name, /* in: file name where created */
|
||||||
,char* file_name, /* in: file name where created */
|
|
||||||
ulint line /* in: line where created */
|
ulint line /* in: line where created */
|
||||||
#endif
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
mem_block_t* block;
|
mem_block_t* block;
|
||||||
|
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
block = mem_heap_create_block(NULL, n, init_block, type);
|
block = mem_heap_create_block(NULL, n, init_block, type,
|
||||||
|
file_name, line);
|
||||||
} else {
|
} else {
|
||||||
block = mem_heap_create_block(NULL, MEM_BLOCK_START_SIZE,
|
block = mem_heap_create_block(NULL, MEM_BLOCK_START_SIZE,
|
||||||
init_block, type);
|
init_block, type, file_name, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
ut_ad(block);
|
ut_ad(block);
|
||||||
@ -438,11 +439,9 @@ UNIV_INLINE
|
|||||||
void
|
void
|
||||||
mem_heap_free_func(
|
mem_heap_free_func(
|
||||||
/*===============*/
|
/*===============*/
|
||||||
mem_heap_t* heap /* in, own: heap to be freed */
|
mem_heap_t* heap, /* in, own: heap to be freed */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
char* file_name, /* in: file name where freed */
|
||||||
,char* file_name, /* in: file name where freed */
|
|
||||||
ulint line /* in: line where freed */
|
ulint line /* in: line where freed */
|
||||||
#endif
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
mem_block_t* block;
|
mem_block_t* block;
|
||||||
@ -488,14 +487,12 @@ mem_alloc_func(
|
|||||||
/*===========*/
|
/*===========*/
|
||||||
/* out, own: free storage, NULL if did not
|
/* out, own: free storage, NULL if did not
|
||||||
succeed */
|
succeed */
|
||||||
ulint n /* in: desired number of bytes */
|
ulint n, /* in: desired number of bytes */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
char* file_name, /* in: file name where created */
|
||||||
,char* file_name, /* in: file name where created */
|
|
||||||
ulint line /* in: line where created */
|
ulint line /* in: line where created */
|
||||||
#endif
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
#ifndef UNIV_MEM_DEBUG
|
#ifdef notdefined
|
||||||
void* buf;
|
void* buf;
|
||||||
|
|
||||||
buf = mem_area_alloc(n, mem_comm_pool);
|
buf = mem_area_alloc(n, mem_comm_pool);
|
||||||
@ -505,7 +502,7 @@ mem_alloc_func(
|
|||||||
#endif
|
#endif
|
||||||
return(buf);
|
return(buf);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
mem_heap_t* heap;
|
mem_heap_t* heap;
|
||||||
void* buf;
|
void* buf;
|
||||||
@ -524,11 +521,11 @@ mem_alloc_func(
|
|||||||
|
|
||||||
buf = mem_heap_alloc(heap, n);
|
buf = mem_heap_alloc(heap, n);
|
||||||
|
|
||||||
ut_ad((byte*)heap == (byte*)buf - MEM_BLOCK_HEADER_SIZE
|
ut_a((byte*)heap == (byte*)buf - MEM_BLOCK_HEADER_SIZE
|
||||||
- MEM_FIELD_HEADER_SIZE);
|
- MEM_FIELD_HEADER_SIZE);
|
||||||
return(buf);
|
return(buf);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
@ -539,26 +536,22 @@ UNIV_INLINE
|
|||||||
void
|
void
|
||||||
mem_free_func(
|
mem_free_func(
|
||||||
/*==========*/
|
/*==========*/
|
||||||
void* ptr /* in, own: buffer to be freed */
|
void* ptr, /* in, own: buffer to be freed */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
char* file_name, /* in: file name where created */
|
||||||
,char* file_name, /* in: file name where created */
|
|
||||||
ulint line /* in: line where created */
|
ulint line /* in: line where created */
|
||||||
#endif
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
#ifndef UNIV_MEM_DEBUG
|
#ifdef notdefined
|
||||||
|
|
||||||
mem_area_free(ptr, mem_comm_pool);
|
mem_area_free(ptr, mem_comm_pool);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
mem_heap_t* heap;
|
mem_heap_t* heap;
|
||||||
|
|
||||||
heap = (mem_heap_t*)((byte*)ptr - MEM_BLOCK_HEADER_SIZE
|
heap = (mem_heap_t*)((byte*)ptr - MEM_BLOCK_HEADER_SIZE
|
||||||
- MEM_FIELD_HEADER_SIZE);
|
- MEM_FIELD_HEADER_SIZE);
|
||||||
mem_heap_free_func(heap, file_name, line);
|
mem_heap_free_func(heap, file_name, line);
|
||||||
|
#endif
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
@ -567,7 +560,7 @@ UNIV_INLINE
|
|||||||
ulint
|
ulint
|
||||||
mem_heap_get_size(
|
mem_heap_get_size(
|
||||||
/*==============*/
|
/*==============*/
|
||||||
mem_heap_t* heap) /* in: heap */
|
mem_heap_t* heap) /* in: heap */
|
||||||
{
|
{
|
||||||
mem_block_t* block;
|
mem_block_t* block;
|
||||||
ulint size = 0;
|
ulint size = 0;
|
||||||
@ -597,9 +590,11 @@ mem_realloc(
|
|||||||
/*========*/
|
/*========*/
|
||||||
/* out, own: free storage, NULL if did not succeed */
|
/* out, own: free storage, NULL if did not succeed */
|
||||||
void* buf, /* in: pointer to an old buffer */
|
void* buf, /* in: pointer to an old buffer */
|
||||||
ulint n) /* in: desired number of bytes */
|
ulint n, /* in: desired number of bytes */
|
||||||
|
char* file_name,/* in: file name where called */
|
||||||
|
ulint line) /* in: line where called */
|
||||||
{
|
{
|
||||||
mem_free(buf);
|
mem_free(buf);
|
||||||
|
|
||||||
return(mem_alloc(n));
|
return(mem_alloc_func(n, file_name, line));
|
||||||
}
|
}
|
||||||
|
@ -512,6 +512,8 @@ page_dir_find_owner_slot(
|
|||||||
slot = page_dir_get_nth_slot(page, i);
|
slot = page_dir_get_nth_slot(page, i);
|
||||||
|
|
||||||
while (page_dir_slot_get_rec(slot) != rec) {
|
while (page_dir_slot_get_rec(slot) != rec) {
|
||||||
|
ut_a(i > 0);
|
||||||
|
|
||||||
i--;
|
i--;
|
||||||
slot = page_dir_get_nth_slot(page, i);
|
slot = page_dir_get_nth_slot(page, i);
|
||||||
}
|
}
|
||||||
|
@ -327,6 +327,8 @@ mutex with the exceptions named below */
|
|||||||
|
|
||||||
struct que_thr_struct{
|
struct que_thr_struct{
|
||||||
que_common_t common; /* type: QUE_NODE_THR */
|
que_common_t common; /* type: QUE_NODE_THR */
|
||||||
|
ulint magic_n; /* magic number to catch memory
|
||||||
|
corruption */
|
||||||
que_node_t* child; /* graph child node */
|
que_node_t* child; /* graph child node */
|
||||||
que_t* graph; /* graph where this node belongs */
|
que_t* graph; /* graph where this node belongs */
|
||||||
ibool is_active; /* TRUE if the thread has been set
|
ibool is_active; /* TRUE if the thread has been set
|
||||||
@ -357,6 +359,9 @@ struct que_thr_struct{
|
|||||||
thus far */
|
thus far */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define QUE_THR_MAGIC_N 8476583
|
||||||
|
#define QUE_THR_MAGIC_FREED 123461526
|
||||||
|
|
||||||
/* Query graph fork node: its fields are protected by the kernel mutex */
|
/* Query graph fork node: its fields are protected by the kernel mutex */
|
||||||
struct que_fork_struct{
|
struct que_fork_struct{
|
||||||
que_common_t common; /* type: QUE_NODE_FORK */
|
que_common_t common; /* type: QUE_NODE_FORK */
|
||||||
|
@ -323,11 +323,18 @@ struct mysql_row_templ_struct {
|
|||||||
/* After fetching this many rows, we start caching them in fetch_cache */
|
/* After fetching this many rows, we start caching them in fetch_cache */
|
||||||
#define MYSQL_FETCH_CACHE_THRESHOLD 4
|
#define MYSQL_FETCH_CACHE_THRESHOLD 4
|
||||||
|
|
||||||
|
#define ROW_PREBUILT_ALLOCATED 78540783
|
||||||
|
#define ROW_PREBUILT_FREED 26423527
|
||||||
|
|
||||||
/* A struct for (sometimes lazily) prebuilt structures in an Innobase table
|
/* A struct for (sometimes lazily) prebuilt structures in an Innobase table
|
||||||
handle used within MySQL; these are used to save CPU time. */
|
handle used within MySQL; these are used to save CPU time. */
|
||||||
|
|
||||||
struct row_prebuilt_struct {
|
struct row_prebuilt_struct {
|
||||||
|
ulint magic_n; /* this magic number is set to
|
||||||
|
ROW_PREBUILT_ALLOCATED when created
|
||||||
|
and to ROW_PREBUILT_FREED when the
|
||||||
|
struct has been freed; used in
|
||||||
|
debugging */
|
||||||
dict_table_t* table; /* Innobase table handle */
|
dict_table_t* table; /* Innobase table handle */
|
||||||
trx_t* trx; /* current transaction handle */
|
trx_t* trx; /* current transaction handle */
|
||||||
ibool sql_stat_start; /* TRUE when we start processing of
|
ibool sql_stat_start; /* TRUE when we start processing of
|
||||||
|
@ -17,6 +17,8 @@ Created 10/10/1995 Heikki Tuuri
|
|||||||
#include "que0types.h"
|
#include "que0types.h"
|
||||||
#include "trx0types.h"
|
#include "trx0types.h"
|
||||||
|
|
||||||
|
/* Buffer which can be used in printing fatal error messages */
|
||||||
|
extern char srv_fatal_errbuf[];
|
||||||
|
|
||||||
/* When this event is set the lock timeout and InnoDB monitor
|
/* When this event is set the lock timeout and InnoDB monitor
|
||||||
thread starts running */
|
thread starts running */
|
||||||
@ -262,15 +264,27 @@ This lets a thread enter InnoDB regardless of the number of threads inside
|
|||||||
InnoDB. This must be called when a thread ends a lock wait. */
|
InnoDB. This must be called when a thread ends a lock wait. */
|
||||||
|
|
||||||
void
|
void
|
||||||
srv_conc_force_enter_innodb(void);
|
srv_conc_force_enter_innodb(
|
||||||
/*=============================*/
|
/*========================*/
|
||||||
|
trx_t* trx); /* in: transaction object associated with the
|
||||||
|
thread */
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
This must be called when a thread exits InnoDB. This must also be called
|
This must be called when a thread exits InnoDB in a lock wait or at the
|
||||||
when a thread goes to wait for a lock. */
|
end of an SQL statement. */
|
||||||
|
|
||||||
void
|
void
|
||||||
srv_conc_exit_innodb(void);
|
srv_conc_force_exit_innodb(
|
||||||
/*======================*/
|
/*=======================*/
|
||||||
|
trx_t* trx); /* in: transaction object associated with the
|
||||||
|
thread */
|
||||||
|
/*************************************************************************
|
||||||
|
This must be called when a thread exits InnoDB. */
|
||||||
|
|
||||||
|
void
|
||||||
|
srv_conc_exit_innodb(
|
||||||
|
/*=================*/
|
||||||
|
trx_t* trx); /* in: transaction object associated with the
|
||||||
|
thread */
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
Puts a MySQL OS thread to wait for a lock to be released. */
|
Puts a MySQL OS thread to wait for a lock to be released. */
|
||||||
|
|
||||||
|
@ -218,6 +218,22 @@ trx_in_trx_list(
|
|||||||
/*============*/
|
/*============*/
|
||||||
/* out: TRUE if is in */
|
/* out: TRUE if is in */
|
||||||
trx_t* in_trx);/* in: trx */
|
trx_t* in_trx);/* in: trx */
|
||||||
|
/*********************************************************************
|
||||||
|
Updates the offset information about the end of the MySQL binlog entry
|
||||||
|
which corresponds to the transaction just being committed. */
|
||||||
|
|
||||||
|
void
|
||||||
|
trx_sys_update_mysql_binlog_offset(
|
||||||
|
/*===============================*/
|
||||||
|
trx_t* trx, /* in: transaction being committed */
|
||||||
|
mtr_t* mtr); /* in: mtr */
|
||||||
|
/*********************************************************************
|
||||||
|
Prints to stderr the MySQL binlog offset info in the trx system header if
|
||||||
|
the magic number shows it valid. */
|
||||||
|
|
||||||
|
void
|
||||||
|
trx_sys_print_mysql_binlog_offset(void);
|
||||||
|
/*===================================*/
|
||||||
|
|
||||||
/* The automatically created system rollback segment has this id */
|
/* The automatically created system rollback segment has this id */
|
||||||
#define TRX_SYS_SYSTEM_RSEG_ID 0
|
#define TRX_SYS_SYSTEM_RSEG_ID 0
|
||||||
@ -236,7 +252,7 @@ therefore 256 */
|
|||||||
|
|
||||||
/* Transaction system header; protected by trx_sys->mutex */
|
/* Transaction system header; protected by trx_sys->mutex */
|
||||||
/*-------------------------------------------------------------*/
|
/*-------------------------------------------------------------*/
|
||||||
#define TRX_SYS_TRX_ID_STORE 0 /* The maximum trx id or trx number
|
#define TRX_SYS_TRX_ID_STORE 0 /* the maximum trx id or trx number
|
||||||
modulo TRX_SYS_TRX_ID_UPDATE_MARGIN
|
modulo TRX_SYS_TRX_ID_UPDATE_MARGIN
|
||||||
written to a file page by any
|
written to a file page by any
|
||||||
transaction; the assignment of
|
transaction; the assignment of
|
||||||
@ -252,6 +268,23 @@ therefore 256 */
|
|||||||
segment specification slots */
|
segment specification slots */
|
||||||
/*-------------------------------------------------------------*/
|
/*-------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define TRX_SYS_MYSQL_LOG_NAME_LEN 32
|
||||||
|
#define TRX_SYS_MYSQL_LOG_MAGIC_N 873422344
|
||||||
|
|
||||||
|
/* The offset of the MySQL binlog offset info on the trx system header page */
|
||||||
|
#define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 300)
|
||||||
|
#define TRX_SYS_MYSQL_LOG_MAGIC_N_FLD 0 /* magic number which shows
|
||||||
|
if we have valid data in the
|
||||||
|
MySQL binlog info; the value
|
||||||
|
is ..._MAGIC_N if yes */
|
||||||
|
#define TRX_SYS_MYSQL_LOG_NAME 4 /* MySQL log file name */
|
||||||
|
#define TRX_SYS_MYSQL_LOG_OFFSET_HIGH (4 + TRX_SYS_MYSQL_LOG_NAME_LEN)
|
||||||
|
/* high 4 bytes of the offset
|
||||||
|
within that file */
|
||||||
|
#define TRX_SYS_MYSQL_LOG_OFFSET_LOW (8 + TRX_SYS_MYSQL_LOG_NAME_LEN)
|
||||||
|
/* low 4 bytes of the offset
|
||||||
|
within that file */
|
||||||
|
|
||||||
/* The offset of the doublewrite buffer header on the trx system header page */
|
/* The offset of the doublewrite buffer header on the trx system header page */
|
||||||
#define TRX_SYS_DOUBLEWRITE (UNIV_PAGE_SIZE - 200)
|
#define TRX_SYS_DOUBLEWRITE (UNIV_PAGE_SIZE - 200)
|
||||||
/*-------------------------------------------------------------*/
|
/*-------------------------------------------------------------*/
|
||||||
|
@ -290,10 +290,20 @@ struct trx_struct{
|
|||||||
table */
|
table */
|
||||||
dulint table_id; /* table id if the preceding field is
|
dulint table_id; /* table id if the preceding field is
|
||||||
TRUE */
|
TRUE */
|
||||||
|
/*------------------------------*/
|
||||||
void* mysql_thd; /* MySQL thread handle corresponding
|
void* mysql_thd; /* MySQL thread handle corresponding
|
||||||
to this trx, or NULL */
|
to this trx, or NULL */
|
||||||
|
char* mysql_log_file_name;
|
||||||
|
/* If MySQL binlog is used, this field
|
||||||
|
contains a pointer to the latest file
|
||||||
|
name; this is NULL if binlog is not
|
||||||
|
used */
|
||||||
|
ib_longlong mysql_log_offset;/* If MySQL binlog is used, this field
|
||||||
|
contains the end offset of the binlog
|
||||||
|
entry */
|
||||||
os_thread_id_t mysql_thread_id;/* id of the MySQL thread associated
|
os_thread_id_t mysql_thread_id;/* id of the MySQL thread associated
|
||||||
with this transaction object */
|
with this transaction object */
|
||||||
|
/*------------------------------*/
|
||||||
ulint n_mysql_tables_in_use; /* number of Innobase tables
|
ulint n_mysql_tables_in_use; /* number of Innobase tables
|
||||||
used in the processing of the current
|
used in the processing of the current
|
||||||
SQL statement in MySQL */
|
SQL statement in MySQL */
|
||||||
@ -314,6 +324,18 @@ struct trx_struct{
|
|||||||
calls from MySQL; this is intended
|
calls from MySQL; this is intended
|
||||||
to reduce contention on the search
|
to reduce contention on the search
|
||||||
latch */
|
latch */
|
||||||
|
/*------------------------------*/
|
||||||
|
ibool declared_to_be_inside_innodb;
|
||||||
|
/* this is TRUE if we have declared
|
||||||
|
this transaction in
|
||||||
|
srv_conc_enter_innodb to be inside the
|
||||||
|
InnoDB engine */
|
||||||
|
ulint n_tickets_to_enter_innodb;
|
||||||
|
/* this can be > 0 only when
|
||||||
|
declared_to_... is TRUE; when we come
|
||||||
|
to srv_conc_innodb_enter, if the value
|
||||||
|
here is > 0, we decrement this by 1 */
|
||||||
|
/*------------------------------*/
|
||||||
lock_t* auto_inc_lock; /* possible auto-inc lock reserved by
|
lock_t* auto_inc_lock; /* possible auto-inc lock reserved by
|
||||||
the transaction; note that it is also
|
the transaction; note that it is also
|
||||||
in the lock list trx_locks */
|
in the lock list trx_locks */
|
||||||
|
@ -51,6 +51,8 @@ recv_sys_t* recv_sys = NULL;
|
|||||||
ibool recv_recovery_on = FALSE;
|
ibool recv_recovery_on = FALSE;
|
||||||
ibool recv_recovery_from_backup_on = FALSE;
|
ibool recv_recovery_from_backup_on = FALSE;
|
||||||
|
|
||||||
|
ibool recv_needed_recovery = FALSE;
|
||||||
|
|
||||||
/* If the following is TRUE, the buffer pool file pages must be invalidated
|
/* If the following is TRUE, the buffer pool file pages must be invalidated
|
||||||
after recovery and no ibuf operations are allowed; this becomes TRUE if
|
after recovery and no ibuf operations are allowed; this becomes TRUE if
|
||||||
the log record hash table becomes too full, and log records must be merged
|
the log record hash table becomes too full, and log records must be merged
|
||||||
@ -1020,7 +1022,7 @@ loop:
|
|||||||
if (!has_printed) {
|
if (!has_printed) {
|
||||||
fprintf(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:");
|
"InnoDB: Progress in percents: ");
|
||||||
has_printed = TRUE;
|
has_printed = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2032,12 +2034,16 @@ recv_recovery_from_checkpoint_start(
|
|||||||
if (ut_dulint_cmp(checkpoint_lsn, max_flushed_lsn) != 0
|
if (ut_dulint_cmp(checkpoint_lsn, max_flushed_lsn) != 0
|
||||||
|| ut_dulint_cmp(checkpoint_lsn, min_flushed_lsn) != 0) {
|
|| ut_dulint_cmp(checkpoint_lsn, min_flushed_lsn) != 0) {
|
||||||
|
|
||||||
|
recv_needed_recovery = TRUE;
|
||||||
|
|
||||||
|
ut_print_timestamp(stderr);
|
||||||
|
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Database was not shut down normally.\n"
|
" InnoDB: Database was not shut down normally.\n"
|
||||||
"InnoDB: Starting recovery from log files...\n");
|
"InnoDB: Starting recovery from log files...\n");
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Starting log scan based on checkpoint at\n"
|
"InnoDB: Starting log scan based on checkpoint at\n"
|
||||||
"InnoDB: log sequence number %lu %lu\n",
|
"InnoDB: log sequence number %lu %lu\n",
|
||||||
ut_dulint_get_high(checkpoint_lsn),
|
ut_dulint_get_high(checkpoint_lsn),
|
||||||
ut_dulint_get_low(checkpoint_lsn));
|
ut_dulint_get_low(checkpoint_lsn));
|
||||||
}
|
}
|
||||||
@ -2199,6 +2205,10 @@ recv_recovery_from_checkpoint_finish(void)
|
|||||||
"InnoDB: Log records applied to the database\n");
|
"InnoDB: Log records applied to the database\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (recv_needed_recovery) {
|
||||||
|
trx_sys_print_mysql_binlog_offset();
|
||||||
|
}
|
||||||
|
|
||||||
/* Free the resources of the recovery system */
|
/* Free the resources of the recovery system */
|
||||||
|
|
||||||
recv_recovery_on = FALSE;
|
recv_recovery_on = FALSE;
|
||||||
|
@ -810,7 +810,7 @@ mem_validate_no_assert(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
mutex_exit(&mem_hash_mutex);
|
mutex_exit(&mem_hash_mutex);
|
||||||
|
|
||||||
return(error);
|
return(error);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -834,3 +834,95 @@ mem_validate(void)
|
|||||||
|
|
||||||
return(TRUE);
|
return(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************
|
||||||
|
Tries to find neigboring memory allocation blocks and dumps to stderr
|
||||||
|
the neighborhood of a given pointer. */
|
||||||
|
|
||||||
|
void
|
||||||
|
mem_analyze_corruption(
|
||||||
|
/*===================*/
|
||||||
|
byte* ptr) /* in: pointer to place of possible corruption */
|
||||||
|
{
|
||||||
|
byte* p;
|
||||||
|
ulint i;
|
||||||
|
ulint dist;
|
||||||
|
|
||||||
|
ut_sprintf_buf(srv_fatal_errbuf, ptr - 250, 500);
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: Apparent memory corruption: mem dump %s\n", srv_fatal_errbuf);
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: Scanning backward trying to find previous allocated mem blocks\n");
|
||||||
|
|
||||||
|
p = ptr;
|
||||||
|
dist = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
for (;;) {
|
||||||
|
if (((ulint)p) % 4 == 0) {
|
||||||
|
|
||||||
|
if (*((ulint*)p) == MEM_BLOCK_MAGIC_N) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Mem block at - %lu, file %s, line %lu\n",
|
||||||
|
dist, p + sizeof(ulint),
|
||||||
|
*(ulint*)(p + 8 + sizeof(ulint)));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*((ulint*)p) == MEM_FREED_BLOCK_MAGIC_N) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Freed mem block at - %lu, file %s, line %lu\n",
|
||||||
|
dist, p + sizeof(ulint),
|
||||||
|
*(ulint*)(p + 8 + sizeof(ulint)));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p--;
|
||||||
|
dist++;
|
||||||
|
}
|
||||||
|
|
||||||
|
p--;
|
||||||
|
dist++;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: Scanning forward trying to find next allocated mem blocks\n");
|
||||||
|
|
||||||
|
p = ptr;
|
||||||
|
dist = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
for (;;) {
|
||||||
|
if (((ulint)p) % 4 == 0) {
|
||||||
|
|
||||||
|
if (*((ulint*)p) == MEM_BLOCK_MAGIC_N) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Mem block at + %lu, file %s, line %lu\n",
|
||||||
|
dist, p + sizeof(ulint),
|
||||||
|
*(ulint*)(p + 8 + sizeof(ulint)));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*((ulint*)p) == MEM_FREED_BLOCK_MAGIC_N) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Freed mem block at + %lu, file %s, line %lu\n",
|
||||||
|
dist, p + sizeof(ulint),
|
||||||
|
*(ulint*)(p + 8 + sizeof(ulint)));
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p++;
|
||||||
|
dist++;
|
||||||
|
}
|
||||||
|
|
||||||
|
p++;
|
||||||
|
dist++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -14,8 +14,9 @@ Created 6/9/1994 Heikki Tuuri
|
|||||||
|
|
||||||
#include "mach0data.h"
|
#include "mach0data.h"
|
||||||
#include "buf0buf.h"
|
#include "buf0buf.h"
|
||||||
#include "mem0dbg.c"
|
|
||||||
#include "btr0sea.h"
|
#include "btr0sea.h"
|
||||||
|
#include "srv0srv.h"
|
||||||
|
#include "mem0dbg.c"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
THE MEMORY MANAGEMENT
|
THE MEMORY MANAGEMENT
|
||||||
@ -49,7 +50,7 @@ of the blocks stay the same. An exception is, of course, the case
|
|||||||
where the caller requests a memory buffer whose size is
|
where the caller requests a memory buffer whose size is
|
||||||
bigger than the threshold. In that case a block big enough must
|
bigger than the threshold. In that case a block big enough must
|
||||||
be allocated.
|
be allocated.
|
||||||
|
|
||||||
The heap is physically arranged so that if the current block
|
The heap is physically arranged so that if the current block
|
||||||
becomes full, a new block is allocated and always inserted in the
|
becomes full, a new block is allocated and always inserted in the
|
||||||
chain of blocks as the last block.
|
chain of blocks as the last block.
|
||||||
@ -85,18 +86,12 @@ mem_alloc_func_noninline(
|
|||||||
/*=====================*/
|
/*=====================*/
|
||||||
/* out, own: free storage, NULL if did not
|
/* out, own: free storage, NULL if did not
|
||||||
succeed */
|
succeed */
|
||||||
ulint n /* in: desired number of bytes */
|
ulint n, /* in: desired number of bytes */
|
||||||
#ifdef UNIV_MEM_DEBUG
|
char* file_name, /* in: file name where created */
|
||||||
,char* file_name, /* in: file name where created */
|
|
||||||
ulint line /* in: line where created */
|
ulint line /* in: line where created */
|
||||||
#endif
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return(mem_alloc_func(n
|
return(mem_alloc_func(n, file_name, line));
|
||||||
#ifdef UNIV_MEM_DEBUG
|
|
||||||
, file_name, line
|
|
||||||
#endif
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************
|
/*******************************************************************
|
||||||
@ -113,8 +108,10 @@ mem_heap_create_block(
|
|||||||
if init_block is not NULL, its size in bytes */
|
if init_block is not NULL, its size in bytes */
|
||||||
void* init_block, /* in: init block in fast create, type must be
|
void* init_block, /* in: init block in fast create, type must be
|
||||||
MEM_HEAP_DYNAMIC */
|
MEM_HEAP_DYNAMIC */
|
||||||
ulint type) /* in: type of heap: MEM_HEAP_DYNAMIC, or
|
ulint type, /* in: type of heap: MEM_HEAP_DYNAMIC, or
|
||||||
MEM_HEAP_BUFFER possibly ORed to MEM_HEAP_BTR_SEARCH */
|
MEM_HEAP_BUFFER possibly ORed to MEM_HEAP_BTR_SEARCH */
|
||||||
|
char* file_name,/* in: file name where created */
|
||||||
|
ulint line) /* in: line where created */
|
||||||
{
|
{
|
||||||
mem_block_t* block;
|
mem_block_t* block;
|
||||||
ulint len;
|
ulint len;
|
||||||
@ -122,6 +119,10 @@ mem_heap_create_block(
|
|||||||
ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
|
ut_ad((type == MEM_HEAP_DYNAMIC) || (type == MEM_HEAP_BUFFER)
|
||||||
|| (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));
|
|| (type == MEM_HEAP_BUFFER + MEM_HEAP_BTR_SEARCH));
|
||||||
|
|
||||||
|
if (heap && heap->magic_n != MEM_BLOCK_MAGIC_N) {
|
||||||
|
mem_analyze_corruption((byte*)heap);
|
||||||
|
}
|
||||||
|
|
||||||
/* In dynamic allocation, calculate the size: block header + data. */
|
/* In dynamic allocation, calculate the size: block header + data. */
|
||||||
|
|
||||||
if (init_block != NULL) {
|
if (init_block != NULL) {
|
||||||
@ -164,7 +165,11 @@ mem_heap_create_block(
|
|||||||
}
|
}
|
||||||
|
|
||||||
block->magic_n = MEM_BLOCK_MAGIC_N;
|
block->magic_n = MEM_BLOCK_MAGIC_N;
|
||||||
|
ut_memcpy(&(block->file_name), file_name + ut_strlen(file_name) - 7,
|
||||||
|
7);
|
||||||
|
block->file_name[7]='\0';
|
||||||
|
block->line = line;
|
||||||
|
|
||||||
mem_block_set_len(block, len);
|
mem_block_set_len(block, len);
|
||||||
mem_block_set_type(block, type);
|
mem_block_set_type(block, type);
|
||||||
mem_block_set_free(block, MEM_BLOCK_HEADER_SIZE);
|
mem_block_set_free(block, MEM_BLOCK_HEADER_SIZE);
|
||||||
@ -223,8 +228,8 @@ mem_heap_add_block(
|
|||||||
new_size = n;
|
new_size = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_block = mem_heap_create_block(heap, new_size, NULL, heap->type);
|
new_block = mem_heap_create_block(heap, new_size, NULL, heap->type,
|
||||||
|
heap->file_name, heap->line);
|
||||||
if (new_block == NULL) {
|
if (new_block == NULL) {
|
||||||
|
|
||||||
return(NULL);
|
return(NULL);
|
||||||
@ -250,12 +255,17 @@ mem_heap_block_free(
|
|||||||
ulint len;
|
ulint len;
|
||||||
ibool init_block;
|
ibool init_block;
|
||||||
|
|
||||||
|
if (block->magic_n != MEM_BLOCK_MAGIC_N) {
|
||||||
|
mem_analyze_corruption((byte*)block);
|
||||||
|
}
|
||||||
|
|
||||||
UT_LIST_REMOVE(list, heap->base, block);
|
UT_LIST_REMOVE(list, heap->base, block);
|
||||||
|
|
||||||
type = heap->type;
|
type = heap->type;
|
||||||
len = block->len;
|
len = block->len;
|
||||||
init_block = block->init_block;
|
init_block = block->init_block;
|
||||||
|
block->magic_n = MEM_FREED_BLOCK_MAGIC_N;
|
||||||
|
|
||||||
#ifdef UNIV_MEM_DEBUG
|
#ifdef UNIV_MEM_DEBUG
|
||||||
/* In the debug version we set the memory to a random combination
|
/* In the debug version we set the memory to a random combination
|
||||||
of hex 0xDE and 0xAD. */
|
of hex 0xDE and 0xAD. */
|
||||||
|
@ -169,8 +169,25 @@ os_file_get_last_error(void)
|
|||||||
|
|
||||||
if (err != ERROR_FILE_EXISTS) {
|
if (err != ERROR_FILE_EXISTS) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Warning: operating system error number %li in a file operation.\n",
|
"InnoDB: Operating system error number %li in a file operation.\n"
|
||||||
|
"InnoDB: See http://www.innodb.com/ibman.html for installation help.\n",
|
||||||
(long) err);
|
(long) err);
|
||||||
|
|
||||||
|
if (err == ERROR_PATH_NOT_FOUND) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: The error means the system cannot find the path specified.\n"
|
||||||
|
"InnoDB: In installation you must create directories yourself, InnoDB\n"
|
||||||
|
"InnoDB: does not create them.\n");
|
||||||
|
} else if (err == ERROR_ACCESS_DENIED) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: The error means mysqld does not have the access rights to\n"
|
||||||
|
"InnoDB: the directory. It may also be you have created a subdirectory\n"
|
||||||
|
"InnoDB: of the same name as a data file.\n");
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n"
|
||||||
|
"InnoDB: what the error number means.\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err == ERROR_FILE_NOT_FOUND) {
|
if (err == ERROR_FILE_NOT_FOUND) {
|
||||||
@ -186,9 +203,25 @@ os_file_get_last_error(void)
|
|||||||
err = (ulint) errno;
|
err = (ulint) errno;
|
||||||
|
|
||||||
if (err != EEXIST) {
|
if (err != EEXIST) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Warning: operating system error number %i in a file operation.\n",
|
"InnoDB: Operating system error number %li in a file operation.\n"
|
||||||
errno);
|
"InnoDB: See http://www.innodb.com/ibman.html for installation help.\n",
|
||||||
|
(long) err);
|
||||||
|
|
||||||
|
if (err == ENOENT) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: The error means the system cannot find the path specified.\n"
|
||||||
|
"InnoDB: In installation you must create directories yourself, InnoDB\n"
|
||||||
|
"InnoDB: does not create them.\n");
|
||||||
|
} else if (err == EACCES) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: The error means mysqld does not have the access rights to\n"
|
||||||
|
"InnoDB: the directory.\n");
|
||||||
|
} else {
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: Look from section 13.2 at http://www.innodb.com/ibman.html\n"
|
||||||
|
"InnoDB: what the error number means or use the perror program of MySQL.\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err == ENOSPC ) {
|
if (err == ENOSPC ) {
|
||||||
@ -228,11 +261,11 @@ os_file_handle_error(
|
|||||||
if (err == OS_FILE_DISK_FULL) {
|
if (err == OS_FILE_DISK_FULL) {
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
if (name) {
|
if (name) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Encountered a problem with file %s.\n",
|
"InnoDB: Encountered a problem with file %s.\n",
|
||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Cannot continue operation.\n"
|
"InnoDB: Cannot continue operation.\n"
|
||||||
"InnoDB: Disk is full. Try to clean the disk to free space.\n"
|
"InnoDB: Disk is full. Try to clean the disk to free space.\n"
|
||||||
"InnoDB: Delete a possible created file and restart.\n");
|
"InnoDB: Delete a possible created file and restart.\n");
|
||||||
@ -245,6 +278,10 @@ os_file_handle_error(
|
|||||||
} else if (err == OS_FILE_ALREADY_EXISTS) {
|
} else if (err == OS_FILE_ALREADY_EXISTS) {
|
||||||
return(FALSE);
|
return(FALSE);
|
||||||
} else {
|
} else {
|
||||||
|
if (name) {
|
||||||
|
fprintf(stderr, "InnoDB: File name %s\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
fprintf(stderr, "InnoDB: Cannot continue operation.\n");
|
fprintf(stderr, "InnoDB: Cannot continue operation.\n");
|
||||||
|
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -7373,7 +7373,7 @@ void *ptr;
|
|||||||
unsigned int size;
|
unsigned int size;
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
return (void *) mem_realloc( ptr, size );
|
return (void *) mem_realloc( ptr, size, __FILE__, __LINE__ );
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef YY_USE_PROTOS
|
#ifdef YY_USE_PROTOS
|
||||||
|
@ -183,6 +183,8 @@ que_thr_create(
|
|||||||
thr->common.type = QUE_NODE_THR;
|
thr->common.type = QUE_NODE_THR;
|
||||||
thr->common.parent = parent;
|
thr->common.parent = parent;
|
||||||
|
|
||||||
|
thr->magic_n = QUE_THR_MAGIC_N;
|
||||||
|
|
||||||
thr->graph = parent->graph;
|
thr->graph = parent->graph;
|
||||||
|
|
||||||
thr->state = QUE_THR_COMMAND_WAIT;
|
thr->state = QUE_THR_COMMAND_WAIT;
|
||||||
@ -485,7 +487,6 @@ que_graph_free_recursive(
|
|||||||
tab_node_t* cre_tab;
|
tab_node_t* cre_tab;
|
||||||
ind_node_t* cre_ind;
|
ind_node_t* cre_ind;
|
||||||
|
|
||||||
|
|
||||||
if (node == NULL) {
|
if (node == NULL) {
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -509,6 +510,16 @@ que_graph_free_recursive(
|
|||||||
|
|
||||||
thr = node;
|
thr = node;
|
||||||
|
|
||||||
|
if (thr->magic_n != QUE_THR_MAGIC_N) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"que_thr struct appears corrupt; magic n %lu\n",
|
||||||
|
thr->magic_n);
|
||||||
|
mem_analyze_corruption((byte*)thr);
|
||||||
|
ut_a(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
thr->magic_n = QUE_THR_MAGIC_FREED;
|
||||||
|
|
||||||
que_graph_free_recursive(thr->child);
|
que_graph_free_recursive(thr->child);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -606,6 +617,10 @@ que_graph_free_recursive(
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
fprintf(stderr,
|
||||||
|
"que_node struct appears corrupt; type %lu\n",
|
||||||
|
que_node_get_type(node));
|
||||||
|
mem_analyze_corruption((byte*)node);
|
||||||
ut_a(0);
|
ut_a(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1068,20 +1083,29 @@ que_thr_stop_for_mysql(
|
|||||||
mutex_exit(&kernel_mutex);
|
mutex_exit(&kernel_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
Moves a thread from another state to the QUE_THR_RUNNING state. Increments
|
Moves a thread from another state to the QUE_THR_RUNNING state. Increments
|
||||||
the n_active_thrs counters of the query graph and transaction if thr was
|
the n_active_thrs counters of the query graph and transaction if thr was
|
||||||
not active. */
|
not active. */
|
||||||
|
|
||||||
void
|
void
|
||||||
que_thr_move_to_run_state_for_mysql(
|
que_thr_move_to_run_state_for_mysql(
|
||||||
/*================================*/
|
/*================================*/
|
||||||
que_thr_t* thr, /* in: an query thread */
|
que_thr_t* thr, /* in: an query thread */
|
||||||
trx_t* trx) /* in: transaction */
|
trx_t* trx) /* in: transaction */
|
||||||
{
|
{
|
||||||
|
if (thr->magic_n != QUE_THR_MAGIC_N) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"que_thr struct appears corrupt; magic n %lu\n", thr->magic_n);
|
||||||
|
|
||||||
|
mem_analyze_corruption((byte*)thr);
|
||||||
|
|
||||||
|
ut_a(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (!thr->is_active) {
|
if (!thr->is_active) {
|
||||||
|
|
||||||
(thr->graph)->n_active_thrs++;
|
thr->graph->n_active_thrs++;
|
||||||
|
|
||||||
trx->n_active_thrs++;
|
trx->n_active_thrs++;
|
||||||
|
|
||||||
@ -1097,6 +1121,7 @@ que_thr_move_to_run_state_for_mysql(
|
|||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
A patch for MySQL used to 'stop' a dummy query thread used in MySQL
|
A patch for MySQL used to 'stop' a dummy query thread used in MySQL
|
||||||
select, when there is no error or lock wait. */
|
select, when there is no error or lock wait. */
|
||||||
|
|
||||||
void
|
void
|
||||||
que_thr_stop_for_mysql_no_error(
|
que_thr_stop_for_mysql_no_error(
|
||||||
/*============================*/
|
/*============================*/
|
||||||
@ -1105,6 +1130,15 @@ que_thr_stop_for_mysql_no_error(
|
|||||||
{
|
{
|
||||||
ut_ad(thr->state == QUE_THR_RUNNING);
|
ut_ad(thr->state == QUE_THR_RUNNING);
|
||||||
|
|
||||||
|
if (thr->magic_n != QUE_THR_MAGIC_N) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"que_thr struct appears corrupt; magic n %lu\n", thr->magic_n);
|
||||||
|
|
||||||
|
mem_analyze_corruption((byte*)thr);
|
||||||
|
|
||||||
|
ut_a(0);
|
||||||
|
}
|
||||||
|
|
||||||
thr->state = QUE_THR_COMPLETED;
|
thr->state = QUE_THR_COMPLETED;
|
||||||
|
|
||||||
thr->is_active = FALSE;
|
thr->is_active = FALSE;
|
||||||
|
@ -105,6 +105,17 @@ rec_get_nth_field(
|
|||||||
ut_ad(rec && len);
|
ut_ad(rec && len);
|
||||||
ut_ad(n < rec_get_n_fields(rec));
|
ut_ad(n < rec_get_n_fields(rec));
|
||||||
|
|
||||||
|
if (n > 1024) {
|
||||||
|
fprintf(stderr, "Error: trying to access field %lu in rec\n",
|
||||||
|
n);
|
||||||
|
ut_a(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rec == NULL) {
|
||||||
|
fprintf(stderr, "Error: rec is NULL pointer\n");
|
||||||
|
ut_a(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (rec_get_1byte_offs_flag(rec)) {
|
if (rec_get_1byte_offs_flag(rec)) {
|
||||||
os = rec_1_get_field_start_offs(rec, n);
|
os = rec_1_get_field_start_offs(rec, n);
|
||||||
|
|
||||||
|
@ -242,10 +242,14 @@ row_create_prebuilt(
|
|||||||
ulint ref_len;
|
ulint ref_len;
|
||||||
ulint i;
|
ulint i;
|
||||||
|
|
||||||
|
dict_table_increment_handle_count(table);
|
||||||
|
|
||||||
heap = mem_heap_create(128);
|
heap = mem_heap_create(128);
|
||||||
|
|
||||||
prebuilt = mem_heap_alloc(heap, sizeof(row_prebuilt_t));
|
prebuilt = mem_heap_alloc(heap, sizeof(row_prebuilt_t));
|
||||||
|
|
||||||
|
prebuilt->magic_n = ROW_PREBUILT_ALLOCATED;
|
||||||
|
|
||||||
prebuilt->table = table;
|
prebuilt->table = table;
|
||||||
|
|
||||||
prebuilt->trx = NULL;
|
prebuilt->trx = NULL;
|
||||||
@ -294,7 +298,7 @@ row_create_prebuilt(
|
|||||||
prebuilt->blob_heap = NULL;
|
prebuilt->blob_heap = NULL;
|
||||||
|
|
||||||
prebuilt->old_vers_heap = NULL;
|
prebuilt->old_vers_heap = NULL;
|
||||||
|
|
||||||
return(prebuilt);
|
return(prebuilt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,6 +312,19 @@ row_prebuilt_free(
|
|||||||
{
|
{
|
||||||
ulint i;
|
ulint i;
|
||||||
|
|
||||||
|
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
mem_analyze_corruption((byte*)prebuilt);
|
||||||
|
|
||||||
|
ut_a(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
prebuilt->magic_n = ROW_PREBUILT_FREED;
|
||||||
|
|
||||||
btr_pcur_free_for_mysql(prebuilt->pcur);
|
btr_pcur_free_for_mysql(prebuilt->pcur);
|
||||||
btr_pcur_free_for_mysql(prebuilt->clust_pcur);
|
btr_pcur_free_for_mysql(prebuilt->clust_pcur);
|
||||||
|
|
||||||
@ -341,6 +358,8 @@ row_prebuilt_free(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dict_table_decrement_handle_count(prebuilt->table);
|
||||||
|
|
||||||
mem_heap_free(prebuilt->heap);
|
mem_heap_free(prebuilt->heap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,6 +375,28 @@ row_update_prebuilt_trx(
|
|||||||
handle */
|
handle */
|
||||||
trx_t* trx) /* in: transaction handle */
|
trx_t* trx) /* in: transaction handle */
|
||||||
{
|
{
|
||||||
|
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
mem_analyze_corruption((byte*)prebuilt);
|
||||||
|
|
||||||
|
ut_a(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: Error: trying to use a corrupt\n"
|
||||||
|
"InnoDB: table handle. Magic n %lu, table name %s\n",
|
||||||
|
prebuilt->magic_n, prebuilt->table->name);
|
||||||
|
|
||||||
|
mem_analyze_corruption((byte*)prebuilt);
|
||||||
|
|
||||||
|
ut_a(0);
|
||||||
|
}
|
||||||
|
|
||||||
prebuilt->trx = trx;
|
prebuilt->trx = trx;
|
||||||
|
|
||||||
if (prebuilt->ins_graph) {
|
if (prebuilt->ins_graph) {
|
||||||
@ -563,6 +604,17 @@ row_insert_for_mysql(
|
|||||||
ut_ad(trx);
|
ut_ad(trx);
|
||||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||||
|
|
||||||
|
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
mem_analyze_corruption((byte*)prebuilt);
|
||||||
|
|
||||||
|
ut_a(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (srv_created_new_raw || srv_force_recovery) {
|
if (srv_created_new_raw || srv_force_recovery) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: A new raw disk partition was initialized or\n"
|
"InnoDB: A new raw disk partition was initialized or\n"
|
||||||
@ -748,6 +800,17 @@ row_update_for_mysql(
|
|||||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||||
UT_NOT_USED(mysql_rec);
|
UT_NOT_USED(mysql_rec);
|
||||||
|
|
||||||
|
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
mem_analyze_corruption((byte*)prebuilt);
|
||||||
|
|
||||||
|
ut_a(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (srv_created_new_raw || srv_force_recovery) {
|
if (srv_created_new_raw || srv_force_recovery) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: A new raw disk partition was initialized or\n"
|
"InnoDB: A new raw disk partition was initialized or\n"
|
||||||
@ -782,38 +845,6 @@ row_update_for_mysql(
|
|||||||
generated for the table: MySQL does not know anything about
|
generated for the table: MySQL does not know anything about
|
||||||
the row id used as the clustered index key */
|
the row id used as the clustered index key */
|
||||||
|
|
||||||
#ifdef notdefined
|
|
||||||
/* We have to search for the correct cursor position */
|
|
||||||
|
|
||||||
ref_len = dict_index_get_n_unique(clust_index);
|
|
||||||
|
|
||||||
heap = mem_heap_create(450);
|
|
||||||
|
|
||||||
row_tuple = dtuple_create(heap, dict_table_get_n_cols(table));
|
|
||||||
dict_table_copy_types(row_tuple, table);
|
|
||||||
|
|
||||||
if (prebuilt->ins_upd_rec_buff == NULL) {
|
|
||||||
prebuilt->ins_upd_rec_buff = mem_heap_alloc(prebuilt->heap,
|
|
||||||
prebuilt->mysql_row_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
row_mysql_convert_row_to_innobase(row_tuple, prebuilt, mysql_rec);
|
|
||||||
|
|
||||||
search_tuple = dtuple_create(heap, ref_len);
|
|
||||||
|
|
||||||
row_build_row_ref_from_row(search_tuple, table, row_tuple);
|
|
||||||
|
|
||||||
mtr_start(&mtr);
|
|
||||||
|
|
||||||
btr_pcur_open_with_no_init(clust_index, search_tuple, PAGE_CUR_LE,
|
|
||||||
BTR_SEARCH_LEAF, node->pcur, 0, &mtr);
|
|
||||||
|
|
||||||
btr_pcur_store_position(node->pcur, &mtr);
|
|
||||||
|
|
||||||
mtr_commit(&mtr);
|
|
||||||
|
|
||||||
mem_heap_free(heap);
|
|
||||||
#endif
|
|
||||||
savept = trx_savept_take(trx);
|
savept = trx_savept_take(trx);
|
||||||
|
|
||||||
thr = que_fork_get_first_thr(prebuilt->upd_graph);
|
thr = que_fork_get_first_thr(prebuilt->upd_graph);
|
||||||
@ -922,6 +953,50 @@ row_get_mysql_key_number_for_index(
|
|||||||
return(i);
|
return(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
Recovers an orphaned tmp table inside InnoDB by renaming it. In the table
|
||||||
|
name #sql becomes rsql, and "_recover_innodb_tmp_table" is catenated to
|
||||||
|
the end of name. table->name should be of the form
|
||||||
|
"dbname/rsql..._recover_innodb_tmp_table". This renames a table whose
|
||||||
|
name is "#sql..." */
|
||||||
|
static
|
||||||
|
int
|
||||||
|
row_mysql_recover_tmp_table(
|
||||||
|
/*========================*/
|
||||||
|
/* out: error code or DB_SUCCESS */
|
||||||
|
dict_table_t* table, /* in: table definition */
|
||||||
|
trx_t* trx) /* in: transaction handle */
|
||||||
|
{
|
||||||
|
char* ptr;
|
||||||
|
char old_name[1000];
|
||||||
|
|
||||||
|
ut_memcpy(old_name, table->name, ut_strlen(table->name) + 1);
|
||||||
|
|
||||||
|
ptr = old_name;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if (ptr >= old_name + ut_strlen(table->name) - 6) {
|
||||||
|
trx_commit_for_mysql(trx);
|
||||||
|
|
||||||
|
return(DB_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 == ut_memcmp(ptr, "/rsql", 5)) {
|
||||||
|
ptr++;
|
||||||
|
*ptr = '#';
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
|
old_name[ut_strlen(table->name)
|
||||||
|
- ut_strlen("_recover_innodb_tmp_table")] = '\0';
|
||||||
|
|
||||||
|
return(row_rename_table_for_mysql(old_name, table->name, trx));
|
||||||
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Does a table creation operation for MySQL. If the name of the created
|
Does a table creation operation for MySQL. If the name of the created
|
||||||
table ends to characters INNODB_MONITOR, then this also starts
|
table ends to characters INNODB_MONITOR, then this also starts
|
||||||
@ -976,6 +1051,24 @@ row_create_table_for_mysql(
|
|||||||
|
|
||||||
namelen = ut_strlen(table->name);
|
namelen = ut_strlen(table->name);
|
||||||
|
|
||||||
|
keywordlen = ut_strlen("_recover_innodb_tmp_table");
|
||||||
|
|
||||||
|
if (namelen >= keywordlen
|
||||||
|
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
|
||||||
|
"_recover_innodb_tmp_table", keywordlen)) {
|
||||||
|
|
||||||
|
/* MySQL prevents accessing of tables whose name begins
|
||||||
|
with #sql, that is temporary tables. If mysqld crashes in
|
||||||
|
the middle of an ALTER TABLE, we may get an orphaned
|
||||||
|
#sql-table in the tablespace. We have here a special
|
||||||
|
mechanism to recover such tables by renaming them to
|
||||||
|
rsql... */
|
||||||
|
|
||||||
|
return(row_mysql_recover_tmp_table(table, trx));
|
||||||
|
}
|
||||||
|
|
||||||
|
namelen = ut_strlen(table->name);
|
||||||
|
|
||||||
keywordlen = ut_strlen((char *) "innodb_monitor");
|
keywordlen = ut_strlen((char *) "innodb_monitor");
|
||||||
|
|
||||||
if (namelen >= keywordlen
|
if (namelen >= keywordlen
|
||||||
@ -1120,6 +1213,8 @@ row_create_index_for_mysql(
|
|||||||
ind_node_t* node;
|
ind_node_t* node;
|
||||||
mem_heap_t* heap;
|
mem_heap_t* heap;
|
||||||
que_thr_t* thr;
|
que_thr_t* thr;
|
||||||
|
ulint namelen;
|
||||||
|
ulint keywordlen;
|
||||||
ulint err;
|
ulint err;
|
||||||
|
|
||||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||||
@ -1128,6 +1223,18 @@ row_create_index_for_mysql(
|
|||||||
|
|
||||||
trx_start_if_not_started(trx);
|
trx_start_if_not_started(trx);
|
||||||
|
|
||||||
|
namelen = ut_strlen(index->table_name);
|
||||||
|
|
||||||
|
keywordlen = ut_strlen("_recover_innodb_tmp_table");
|
||||||
|
|
||||||
|
if (namelen >= keywordlen
|
||||||
|
&& 0 == ut_memcmp(
|
||||||
|
index->table_name + namelen - keywordlen,
|
||||||
|
"_recover_innodb_tmp_table", keywordlen)) {
|
||||||
|
|
||||||
|
return(DB_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
/* Serialize data dictionary operations with dictionary mutex:
|
/* Serialize data dictionary operations with dictionary mutex:
|
||||||
no deadlocks can occur then in these operations */
|
no deadlocks can occur then in these operations */
|
||||||
|
|
||||||
@ -1191,6 +1298,8 @@ row_table_add_foreign_constraints(
|
|||||||
char* name) /* in: table full name in the normalized form
|
char* name) /* in: table full name in the normalized form
|
||||||
database_name/table_name */
|
database_name/table_name */
|
||||||
{
|
{
|
||||||
|
ulint namelen;
|
||||||
|
ulint keywordlen;
|
||||||
ulint err;
|
ulint err;
|
||||||
|
|
||||||
ut_a(sql_string);
|
ut_a(sql_string);
|
||||||
@ -1199,6 +1308,18 @@ row_table_add_foreign_constraints(
|
|||||||
|
|
||||||
trx_start_if_not_started(trx);
|
trx_start_if_not_started(trx);
|
||||||
|
|
||||||
|
namelen = ut_strlen(name);
|
||||||
|
|
||||||
|
keywordlen = ut_strlen("_recover_innodb_tmp_table");
|
||||||
|
|
||||||
|
if (namelen >= keywordlen
|
||||||
|
&& 0 == ut_memcmp(
|
||||||
|
name + namelen - keywordlen,
|
||||||
|
"_recover_innodb_tmp_table", keywordlen)) {
|
||||||
|
|
||||||
|
return(DB_SUCCESS);
|
||||||
|
}
|
||||||
|
|
||||||
/* Serialize data dictionary operations with dictionary mutex:
|
/* Serialize data dictionary operations with dictionary mutex:
|
||||||
no deadlocks can occur then in these operations */
|
no deadlocks can occur then in these operations */
|
||||||
|
|
||||||
@ -1253,6 +1374,7 @@ row_drop_table_for_mysql(
|
|||||||
ulint len;
|
ulint len;
|
||||||
ulint namelen;
|
ulint namelen;
|
||||||
ulint keywordlen;
|
ulint keywordlen;
|
||||||
|
ulint rounds = 0;
|
||||||
char buf[10000];
|
char buf[10000];
|
||||||
|
|
||||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||||
@ -1432,11 +1554,38 @@ row_drop_table_for_mysql(
|
|||||||
/* Remove any locks there are on the table or its records */
|
/* Remove any locks there are on the table or its records */
|
||||||
|
|
||||||
lock_reset_all_on_table(table);
|
lock_reset_all_on_table(table);
|
||||||
|
loop:
|
||||||
|
if (table->n_mysql_handles_opened > 0) {
|
||||||
|
rw_lock_s_unlock(&(purge_sys->purge_is_running));
|
||||||
|
|
||||||
/* TODO: check that MySQL prevents users from accessing the table
|
rw_lock_x_unlock(&(dict_foreign_key_check_lock));
|
||||||
after this function row_drop_table_for_mysql has been called:
|
|
||||||
otherwise anyone with an open handle to the table could, for example,
|
mutex_exit(&(dict_sys->mutex));
|
||||||
come to read the table! Monty said that it prevents. */
|
|
||||||
|
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->dict_operation = TRUE;
|
||||||
trx->table_id = table->id;
|
trx->table_id = table->id;
|
||||||
|
@ -2493,6 +2493,17 @@ row_search_for_mysql(
|
|||||||
|
|
||||||
ut_ad(sync_thread_levels_empty_gen(FALSE));
|
ut_ad(sync_thread_levels_empty_gen(FALSE));
|
||||||
|
|
||||||
|
if (prebuilt->magic_n != ROW_PREBUILT_ALLOCATED) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
mem_analyze_corruption((byte*)prebuilt);
|
||||||
|
|
||||||
|
ut_a(0);
|
||||||
|
}
|
||||||
|
|
||||||
/* printf("Match mode %lu\n search tuple ", match_mode);
|
/* printf("Match mode %lu\n search tuple ", match_mode);
|
||||||
dtuple_print(search_tuple);
|
dtuple_print(search_tuple);
|
||||||
|
|
||||||
|
@ -50,6 +50,9 @@ Created 10/8/1995 Heikki Tuuri
|
|||||||
#include "dict0load.h"
|
#include "dict0load.h"
|
||||||
#include "srv0start.h"
|
#include "srv0start.h"
|
||||||
|
|
||||||
|
/* Buffer which can be used in printing fatal error messages */
|
||||||
|
char srv_fatal_errbuf[5000];
|
||||||
|
|
||||||
/* The following counter is incremented whenever there is some user activity
|
/* The following counter is incremented whenever there is some user activity
|
||||||
in the server */
|
in the server */
|
||||||
ulint srv_activity_count = 0;
|
ulint srv_activity_count = 0;
|
||||||
@ -132,6 +135,9 @@ lint srv_conc_n_threads = 0; /* number of OS threads currently
|
|||||||
thread increments this, but a thread
|
thread increments this, but a thread
|
||||||
waiting for a lock decrements this
|
waiting for a lock decrements this
|
||||||
temporarily */
|
temporarily */
|
||||||
|
ulint srv_conc_n_waiting_threads = 0; /* number of OS threads waiting in the
|
||||||
|
FIFO for a permission to enter InnoDB
|
||||||
|
*/
|
||||||
|
|
||||||
typedef struct srv_conc_slot_struct srv_conc_slot_t;
|
typedef struct srv_conc_slot_struct srv_conc_slot_t;
|
||||||
struct srv_conc_slot_struct{
|
struct srv_conc_slot_struct{
|
||||||
@ -152,6 +158,11 @@ UT_LIST_BASE_NODE_T(srv_conc_slot_t) srv_conc_queue; /* queue of threads
|
|||||||
waiting to get in */
|
waiting to get in */
|
||||||
srv_conc_slot_t srv_conc_slots[OS_THREAD_MAX_N]; /* array of wait
|
srv_conc_slot_t srv_conc_slots[OS_THREAD_MAX_N]; /* array of wait
|
||||||
slots */
|
slots */
|
||||||
|
|
||||||
|
/* Number of times a thread is allowed to enter InnoDB within the same
|
||||||
|
SQL query after it has once got the ticket at srv_conc_enter_innodb */
|
||||||
|
#define SRV_FREE_TICKETS_TO_ENTER 500
|
||||||
|
|
||||||
/*-----------------------*/
|
/*-----------------------*/
|
||||||
/* If the following is set TRUE then we do not run purge and insert buffer
|
/* If the following is set TRUE then we do not run purge and insert buffer
|
||||||
merge to completion before shutdown */
|
merge to completion before shutdown */
|
||||||
@ -1636,6 +1647,8 @@ srv_general_init(void)
|
|||||||
thr_local_init();
|
thr_local_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*======================= InnoDB Server FIFO queue =======================*/
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Puts an OS thread to wait if there are too many concurrent threads
|
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. */
|
(>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */
|
||||||
@ -1649,11 +1662,29 @@ srv_conc_enter_innodb(
|
|||||||
srv_conc_slot_t* slot;
|
srv_conc_slot_t* slot;
|
||||||
ulint i;
|
ulint i;
|
||||||
|
|
||||||
|
if (srv_thread_concurrency >= 500) {
|
||||||
|
/* Disable the concurrency check */
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If trx has 'free tickets' to enter the engine left, then use one
|
||||||
|
such ticket */
|
||||||
|
|
||||||
|
if (trx->n_tickets_to_enter_innodb > 0) {
|
||||||
|
trx->n_tickets_to_enter_innodb--;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
os_fast_mutex_lock(&srv_conc_mutex);
|
os_fast_mutex_lock(&srv_conc_mutex);
|
||||||
|
|
||||||
if (srv_conc_n_threads < (lint)srv_thread_concurrency) {
|
if (srv_conc_n_threads < (lint)srv_thread_concurrency) {
|
||||||
srv_conc_n_threads++;
|
|
||||||
|
|
||||||
|
srv_conc_n_threads++;
|
||||||
|
trx->declared_to_be_inside_innodb = TRUE;
|
||||||
|
trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER;
|
||||||
|
|
||||||
os_fast_mutex_unlock(&srv_conc_mutex);
|
os_fast_mutex_unlock(&srv_conc_mutex);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -1674,6 +1705,8 @@ srv_conc_enter_innodb(
|
|||||||
thread enter */
|
thread enter */
|
||||||
|
|
||||||
srv_conc_n_threads++;
|
srv_conc_n_threads++;
|
||||||
|
trx->declared_to_be_inside_innodb = TRUE;
|
||||||
|
trx->n_tickets_to_enter_innodb = 0;
|
||||||
|
|
||||||
os_fast_mutex_unlock(&srv_conc_mutex);
|
os_fast_mutex_unlock(&srv_conc_mutex);
|
||||||
|
|
||||||
@ -1693,6 +1726,8 @@ srv_conc_enter_innodb(
|
|||||||
|
|
||||||
os_event_reset(slot->event);
|
os_event_reset(slot->event);
|
||||||
|
|
||||||
|
srv_conc_n_waiting_threads++;
|
||||||
|
|
||||||
os_fast_mutex_unlock(&srv_conc_mutex);
|
os_fast_mutex_unlock(&srv_conc_mutex);
|
||||||
|
|
||||||
/* Go to wait for the event; when a thread leaves InnoDB it will
|
/* Go to wait for the event; when a thread leaves InnoDB it will
|
||||||
@ -1702,6 +1737,8 @@ srv_conc_enter_innodb(
|
|||||||
|
|
||||||
os_fast_mutex_lock(&srv_conc_mutex);
|
os_fast_mutex_lock(&srv_conc_mutex);
|
||||||
|
|
||||||
|
srv_conc_n_waiting_threads--;
|
||||||
|
|
||||||
/* NOTE that the thread which released this thread already
|
/* NOTE that the thread which released this thread already
|
||||||
incremented the thread counter on behalf of this thread */
|
incremented the thread counter on behalf of this thread */
|
||||||
|
|
||||||
@ -1709,6 +1746,9 @@ srv_conc_enter_innodb(
|
|||||||
|
|
||||||
UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot);
|
UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot);
|
||||||
|
|
||||||
|
trx->declared_to_be_inside_innodb = TRUE;
|
||||||
|
trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER;
|
||||||
|
|
||||||
os_fast_mutex_unlock(&srv_conc_mutex);
|
os_fast_mutex_unlock(&srv_conc_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1717,29 +1757,52 @@ This lets a thread enter InnoDB regardless of the number of threads inside
|
|||||||
InnoDB. This must be called when a thread ends a lock wait. */
|
InnoDB. This must be called when a thread ends a lock wait. */
|
||||||
|
|
||||||
void
|
void
|
||||||
srv_conc_force_enter_innodb(void)
|
srv_conc_force_enter_innodb(
|
||||||
/*=============================*/
|
/*========================*/
|
||||||
|
trx_t* trx) /* in: transaction object associated with the
|
||||||
|
thread */
|
||||||
{
|
{
|
||||||
|
if (srv_thread_concurrency >= 500) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
os_fast_mutex_lock(&srv_conc_mutex);
|
os_fast_mutex_lock(&srv_conc_mutex);
|
||||||
|
|
||||||
srv_conc_n_threads++;
|
srv_conc_n_threads++;
|
||||||
|
trx->declared_to_be_inside_innodb = TRUE;
|
||||||
|
trx->n_tickets_to_enter_innodb = 0;
|
||||||
|
|
||||||
os_fast_mutex_unlock(&srv_conc_mutex);
|
os_fast_mutex_unlock(&srv_conc_mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
This must be called when a thread exits InnoDB. This must also be called
|
This must be called when a thread exits InnoDB in a lock wait or at the
|
||||||
when a thread goes to wait for a lock. */
|
end of an SQL statement. */
|
||||||
|
|
||||||
void
|
void
|
||||||
srv_conc_exit_innodb(void)
|
srv_conc_force_exit_innodb(
|
||||||
/*======================*/
|
/*=======================*/
|
||||||
|
trx_t* trx) /* in: transaction object associated with the
|
||||||
|
thread */
|
||||||
{
|
{
|
||||||
srv_conc_slot_t* slot = NULL;
|
srv_conc_slot_t* slot = NULL;
|
||||||
|
|
||||||
|
if (srv_thread_concurrency >= 500) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trx->declared_to_be_inside_innodb == FALSE) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
os_fast_mutex_lock(&srv_conc_mutex);
|
os_fast_mutex_lock(&srv_conc_mutex);
|
||||||
|
|
||||||
srv_conc_n_threads--;
|
srv_conc_n_threads--;
|
||||||
|
trx->declared_to_be_inside_innodb = FALSE;
|
||||||
|
trx->n_tickets_to_enter_innodb = 0;
|
||||||
|
|
||||||
if (srv_conc_n_threads < (lint)srv_thread_concurrency) {
|
if (srv_conc_n_threads < (lint)srv_thread_concurrency) {
|
||||||
/* Look for a slot where a thread is waiting and no other
|
/* Look for a slot where a thread is waiting and no other
|
||||||
@ -1768,6 +1831,38 @@ srv_conc_exit_innodb(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
This must be called when a thread exits InnoDB. */
|
||||||
|
|
||||||
|
void
|
||||||
|
srv_conc_exit_innodb(
|
||||||
|
/*=================*/
|
||||||
|
trx_t* trx) /* in: transaction object associated with the
|
||||||
|
thread */
|
||||||
|
{
|
||||||
|
srv_conc_slot_t* slot = NULL;
|
||||||
|
|
||||||
|
if (srv_thread_concurrency >= 500) {
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trx->n_tickets_to_enter_innodb > 0) {
|
||||||
|
/* We will pretend the thread is still inside InnoDB though it
|
||||||
|
now leaves the InnoDB engine. In this way we save
|
||||||
|
a lot of semaphore operations. srv_conc_force_exit_innodb is
|
||||||
|
used to declare the thread definitely outside InnoDB. It
|
||||||
|
should be called when there is a lock wait or an SQL statement
|
||||||
|
ends. */
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
srv_conc_force_exit_innodb(trx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*========================================================================*/
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Normalizes init parameter values to use units we use inside InnoDB. */
|
Normalizes init parameter values to use units we use inside InnoDB. */
|
||||||
static
|
static
|
||||||
@ -1914,7 +2009,7 @@ srv_suspend_mysql_thread(
|
|||||||
other thread holding a lock which this thread waits for must be
|
other thread holding a lock which this thread waits for must be
|
||||||
allowed to enter, sooner or later */
|
allowed to enter, sooner or later */
|
||||||
|
|
||||||
srv_conc_exit_innodb();
|
srv_conc_force_exit_innodb(thr_get_trx(thr));
|
||||||
|
|
||||||
/* Wait for the release */
|
/* Wait for the release */
|
||||||
|
|
||||||
@ -1922,7 +2017,7 @@ srv_suspend_mysql_thread(
|
|||||||
|
|
||||||
/* Return back inside InnoDB */
|
/* Return back inside InnoDB */
|
||||||
|
|
||||||
srv_conc_force_enter_innodb();
|
srv_conc_force_enter_innodb(thr_get_trx(thr));
|
||||||
|
|
||||||
mutex_enter(&kernel_mutex);
|
mutex_enter(&kernel_mutex);
|
||||||
|
|
||||||
@ -2061,8 +2156,9 @@ loop:
|
|||||||
"ROW OPERATIONS\n"
|
"ROW OPERATIONS\n"
|
||||||
"--------------\n");
|
"--------------\n");
|
||||||
printf(
|
printf(
|
||||||
"%ld queries inside InnoDB; main thread: %s\n",
|
"%ld queries inside InnoDB, %ld queries in queue; main thread: %s\n",
|
||||||
srv_conc_n_threads, srv_main_thread_op_info);
|
srv_conc_n_threads, srv_conc_n_waiting_threads,
|
||||||
|
srv_main_thread_op_info);
|
||||||
printf(
|
printf(
|
||||||
"Number of rows inserted %lu, updated %lu, deleted %lu, read %lu\n",
|
"Number of rows inserted %lu, updated %lu, deleted %lu, read %lu\n",
|
||||||
srv_n_rows_inserted,
|
srv_n_rows_inserted,
|
||||||
@ -2324,6 +2420,12 @@ loop:
|
|||||||
srv_main_thread_op_info = (char *) "sleeping";
|
srv_main_thread_op_info = (char *) "sleeping";
|
||||||
os_thread_sleep(1000000);
|
os_thread_sleep(1000000);
|
||||||
|
|
||||||
|
/* ALTER TABLE in MySQL requires on Unix that the table handler
|
||||||
|
can drop tables lazily after there no longer are SELECT
|
||||||
|
queries to them. */
|
||||||
|
|
||||||
|
/* row_drop_tables_for_mysql_in_background(); */
|
||||||
|
|
||||||
if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
|
if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
|
||||||
|
|
||||||
goto suspend_thread;
|
goto suspend_thread;
|
||||||
|
@ -815,7 +815,7 @@ innobase_start_or_create_for_mysql(void)
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"InnoDB: Cannot initialize created log files because\n"
|
"InnoDB: Cannot initialize created log files because\n"
|
||||||
"InnoDB: data files were not in sync with each other\n"
|
"InnoDB: data files were not in sync with each other\n"
|
||||||
"InnoDB: or the data files are corrupt./n");
|
"InnoDB: or the data files are corrupt.\n");
|
||||||
|
|
||||||
return(DB_ERROR);
|
return(DB_ERROR);
|
||||||
}
|
}
|
||||||
|
@ -913,6 +913,17 @@ sync_array_print_long_waits(void)
|
|||||||
|
|
||||||
noticed = TRUE;
|
noticed = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cell->wait_object != NULL
|
||||||
|
&& difftime(time(NULL), cell->reservation_time) > 420) {
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: Error: semaphore wait has lasted > 420 seconds\n"
|
||||||
|
"InnoDB: We intentionally crash the server, because it appears to be hung.\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
ut_a(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (noticed) {
|
if (noticed) {
|
||||||
|
@ -389,6 +389,115 @@ trx_sys_flush_max_trx_id(void)
|
|||||||
mtr_commit(&mtr);
|
mtr_commit(&mtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
Updates the offset information about the end of the MySQL binlog entry
|
||||||
|
which corresponds to the transaction just being committed. */
|
||||||
|
|
||||||
|
void
|
||||||
|
trx_sys_update_mysql_binlog_offset(
|
||||||
|
/*===============================*/
|
||||||
|
trx_t* trx, /* in: transaction being committed */
|
||||||
|
mtr_t* mtr) /* in: mtr */
|
||||||
|
{
|
||||||
|
trx_sysf_t* sys_header;
|
||||||
|
char namebuf[TRX_SYS_MYSQL_LOG_NAME_LEN];
|
||||||
|
|
||||||
|
ut_ad(mutex_own(&kernel_mutex));
|
||||||
|
ut_ad(trx->mysql_log_file_name);
|
||||||
|
|
||||||
|
memset(namebuf, ' ', TRX_SYS_MYSQL_LOG_NAME_LEN - 1);
|
||||||
|
namebuf[TRX_SYS_MYSQL_LOG_NAME_LEN - 1] = '\0';
|
||||||
|
|
||||||
|
/* Copy the whole MySQL log file name to the buffer, or only the
|
||||||
|
last characters, if it does not fit */
|
||||||
|
|
||||||
|
if (ut_strlen(trx->mysql_log_file_name)
|
||||||
|
> TRX_SYS_MYSQL_LOG_NAME_LEN - 1) {
|
||||||
|
ut_memcpy(namebuf, trx->mysql_log_file_name
|
||||||
|
+ ut_strlen(trx->mysql_log_file_name)
|
||||||
|
- (TRX_SYS_MYSQL_LOG_NAME_LEN - 1),
|
||||||
|
TRX_SYS_MYSQL_LOG_NAME_LEN - 1);
|
||||||
|
} else {
|
||||||
|
ut_memcpy(namebuf, trx->mysql_log_file_name,
|
||||||
|
1 + ut_strlen(trx->mysql_log_file_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
namebuf[TRX_SYS_MYSQL_LOG_NAME_LEN - 1] = '\0';
|
||||||
|
|
||||||
|
sys_header = trx_sysf_get(mtr);
|
||||||
|
|
||||||
|
if (mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
|
||||||
|
+ TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
|
||||||
|
!= TRX_SYS_MYSQL_LOG_MAGIC_N) {
|
||||||
|
|
||||||
|
mlog_write_ulint(sys_header + TRX_SYS_MYSQL_LOG_INFO
|
||||||
|
+ TRX_SYS_MYSQL_LOG_MAGIC_N_FLD,
|
||||||
|
TRX_SYS_MYSQL_LOG_MAGIC_N,
|
||||||
|
MLOG_4BYTES, mtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (0 != ut_memcmp(sys_header + TRX_SYS_MYSQL_LOG_INFO
|
||||||
|
+ TRX_SYS_MYSQL_LOG_NAME,
|
||||||
|
namebuf, TRX_SYS_MYSQL_LOG_NAME_LEN)) {
|
||||||
|
|
||||||
|
mlog_write_string(sys_header + TRX_SYS_MYSQL_LOG_INFO
|
||||||
|
+ TRX_SYS_MYSQL_LOG_NAME,
|
||||||
|
namebuf, TRX_SYS_MYSQL_LOG_NAME_LEN, mtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
|
||||||
|
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH) > 0
|
||||||
|
|| (trx->mysql_log_offset >> 32) > 0) {
|
||||||
|
|
||||||
|
mlog_write_ulint(sys_header + TRX_SYS_MYSQL_LOG_INFO
|
||||||
|
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH,
|
||||||
|
(ulint)(trx->mysql_log_offset >> 32),
|
||||||
|
MLOG_4BYTES, mtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
mlog_write_ulint(sys_header + TRX_SYS_MYSQL_LOG_INFO
|
||||||
|
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW,
|
||||||
|
(ulint)(trx->mysql_log_offset & 0xFFFFFFFF),
|
||||||
|
MLOG_4BYTES, mtr);
|
||||||
|
|
||||||
|
trx->mysql_log_file_name = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
Prints to stderr the MySQL binlog offset info in the trx system header if
|
||||||
|
the magic number shows it valid. */
|
||||||
|
|
||||||
|
void
|
||||||
|
trx_sys_print_mysql_binlog_offset(void)
|
||||||
|
/*===================================*/
|
||||||
|
{
|
||||||
|
trx_sysf_t* sys_header;
|
||||||
|
mtr_t mtr;
|
||||||
|
|
||||||
|
mtr_start(&mtr);
|
||||||
|
|
||||||
|
sys_header = trx_sysf_get(&mtr);
|
||||||
|
|
||||||
|
if (mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
|
||||||
|
+ TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
|
||||||
|
!= TRX_SYS_MYSQL_LOG_MAGIC_N) {
|
||||||
|
|
||||||
|
mtr_commit(&mtr);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"InnoDB: Last MySQL binlog file offset %lu %lu, file name %s\n",
|
||||||
|
mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
|
||||||
|
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
|
||||||
|
mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
|
||||||
|
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW),
|
||||||
|
sys_header + TRX_SYS_MYSQL_LOG_INFO + TRX_SYS_MYSQL_LOG_NAME);
|
||||||
|
|
||||||
|
mtr_commit(&mtr);
|
||||||
|
}
|
||||||
|
|
||||||
/********************************************************************
|
/********************************************************************
|
||||||
Looks for a free slot for a rollback segment in the trx system file copy. */
|
Looks for a free slot for a rollback segment in the trx system file copy. */
|
||||||
|
|
||||||
@ -519,7 +628,7 @@ trx_sys_init_at_db_start(void)
|
|||||||
"InnoDB: %lu uncommitted transaction(s) which must be rolled back\n",
|
"InnoDB: %lu uncommitted transaction(s) which must be rolled back\n",
|
||||||
UT_LIST_GET_LEN(trx_sys->trx_list));
|
UT_LIST_GET_LEN(trx_sys->trx_list));
|
||||||
|
|
||||||
fprintf(stderr, "Trx id counter is %lu %lu\n",
|
fprintf(stderr, "InnoDB: Trx id counter is %lu %lu\n",
|
||||||
ut_dulint_get_high(trx_sys->max_trx_id),
|
ut_dulint_get_high(trx_sys->max_trx_id),
|
||||||
ut_dulint_get_low(trx_sys->max_trx_id));
|
ut_dulint_get_low(trx_sys->max_trx_id));
|
||||||
}
|
}
|
||||||
|
@ -76,6 +76,9 @@ trx_create(
|
|||||||
trx->n_mysql_tables_in_use = 0;
|
trx->n_mysql_tables_in_use = 0;
|
||||||
trx->mysql_n_tables_locked = 0;
|
trx->mysql_n_tables_locked = 0;
|
||||||
|
|
||||||
|
trx->mysql_log_file_name = NULL;
|
||||||
|
trx->mysql_log_offset = 0;
|
||||||
|
|
||||||
trx->ignore_duplicates_in_insert = FALSE;
|
trx->ignore_duplicates_in_insert = FALSE;
|
||||||
|
|
||||||
mutex_create(&(trx->undo_mutex));
|
mutex_create(&(trx->undo_mutex));
|
||||||
@ -111,6 +114,9 @@ trx_create(
|
|||||||
trx->has_search_latch = FALSE;
|
trx->has_search_latch = FALSE;
|
||||||
trx->search_latch_timeout = BTR_SEA_TIMEOUT;
|
trx->search_latch_timeout = BTR_SEA_TIMEOUT;
|
||||||
|
|
||||||
|
trx->declared_to_be_inside_innodb = FALSE;
|
||||||
|
trx->n_tickets_to_enter_innodb = 0;
|
||||||
|
|
||||||
trx->auto_inc_lock = NULL;
|
trx->auto_inc_lock = NULL;
|
||||||
|
|
||||||
trx->read_view_heap = mem_heap_create(256);
|
trx->read_view_heap = mem_heap_create(256);
|
||||||
@ -568,6 +574,13 @@ trx_commit_off_kernel(
|
|||||||
|
|
||||||
mutex_exit(&(rseg->mutex));
|
mutex_exit(&(rseg->mutex));
|
||||||
|
|
||||||
|
/* Update the latest MySQL binlog name and offset info
|
||||||
|
in trx sys header if MySQL binlogging is on */
|
||||||
|
|
||||||
|
if (trx->mysql_log_file_name) {
|
||||||
|
trx_sys_update_mysql_binlog_offset(trx, &mtr);
|
||||||
|
}
|
||||||
|
|
||||||
/* If we did not take the shortcut, the following call
|
/* If we did not take the shortcut, the following call
|
||||||
commits the mini-transaction, making the whole transaction
|
commits the mini-transaction, making the whole transaction
|
||||||
committed in the file-based world at this log sequence number;
|
committed in the file-based world at this log sequence number;
|
||||||
|
@ -1310,9 +1310,10 @@ trx_undo_mem_init_for_reuse(
|
|||||||
{
|
{
|
||||||
ut_ad(mutex_own(&((undo->rseg)->mutex)));
|
ut_ad(mutex_own(&((undo->rseg)->mutex)));
|
||||||
|
|
||||||
if (undo->id >= TRX_RSEG_N_SLOTS) {
|
if (undo->id >= TRX_RSEG_N_SLOTS) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n", undo->id);
|
||||||
"InnoDB: Error: undo->id is %lu\n", undo->id);
|
|
||||||
|
mem_analyze_corruption((byte*)undo);
|
||||||
ut_a(0);
|
ut_a(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1399,7 +1400,7 @@ trx_undo_create(
|
|||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
Reuses a cached undo log. */
|
Reuses a cached undo log. */
|
||||||
UNIV_INLINE
|
static
|
||||||
trx_undo_t*
|
trx_undo_t*
|
||||||
trx_undo_reuse_cached(
|
trx_undo_reuse_cached(
|
||||||
/*==================*/
|
/*==================*/
|
||||||
@ -1442,6 +1443,12 @@ trx_undo_reuse_cached(
|
|||||||
ut_ad(undo->size == 1);
|
ut_ad(undo->size == 1);
|
||||||
ut_ad(undo->hdr_page_no == undo->top_page_no);
|
ut_ad(undo->hdr_page_no == undo->top_page_no);
|
||||||
|
|
||||||
|
if (undo->id >= TRX_RSEG_N_SLOTS) {
|
||||||
|
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n", undo->id);
|
||||||
|
mem_analyze_corruption((byte*)undo);
|
||||||
|
ut_a(0);
|
||||||
|
}
|
||||||
|
|
||||||
undo_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr);
|
undo_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr);
|
||||||
|
|
||||||
if (type == TRX_UNDO_INSERT) {
|
if (type == TRX_UNDO_INSERT) {
|
||||||
@ -1572,8 +1579,8 @@ trx_undo_set_state_at_finish(
|
|||||||
ut_ad(trx && undo && mtr);
|
ut_ad(trx && undo && mtr);
|
||||||
|
|
||||||
if (undo->id >= TRX_RSEG_N_SLOTS) {
|
if (undo->id >= TRX_RSEG_N_SLOTS) {
|
||||||
fprintf(stderr,
|
fprintf(stderr, "InnoDB: Error: undo->id is %lu\n", undo->id);
|
||||||
"InnoDB: Error: undo->id is %lu\n", undo->id);
|
mem_analyze_corruption((byte*)undo);
|
||||||
ut_a(0);
|
ut_a(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,8 +81,10 @@ ut_malloc_low(
|
|||||||
"InnoDB: by InnoDB %lu bytes. Operating system errno: %d\n"
|
"InnoDB: by InnoDB %lu bytes. Operating system errno: %d\n"
|
||||||
"InnoDB: Cannot continue operation!\n"
|
"InnoDB: Cannot continue operation!\n"
|
||||||
"InnoDB: Check if you should increase the swap file or\n"
|
"InnoDB: Check if you should increase the swap file or\n"
|
||||||
"InnoDB: ulimits of your operating system.\n",
|
"InnoDB: ulimits of your operating system.\n"
|
||||||
n, ut_total_allocated_memory, errno);
|
"InnoDB: On FreeBSD check you have compiled the OS with\n"
|
||||||
|
"InnoDB: a big enough maximum process size.\n",
|
||||||
|
n, ut_total_allocated_memory, errno);
|
||||||
|
|
||||||
os_fast_mutex_unlock(&ut_list_mutex);
|
os_fast_mutex_unlock(&ut_list_mutex);
|
||||||
|
|
||||||
|
@ -384,6 +384,8 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
|
|||||||
bzero((char*) ¶m->unique_count,sizeof(param->unique_count));
|
bzero((char*) ¶m->unique_count,sizeof(param->unique_count));
|
||||||
if ((!(param->testflag & T_SILENT)))
|
if ((!(param->testflag & T_SILENT)))
|
||||||
printf ("- check data record references index: %d\n",key+1);
|
printf ("- check data record references index: %d\n",key+1);
|
||||||
|
if (keyinfo->flag & HA_FULLTEXT)
|
||||||
|
full_text_keys++;
|
||||||
if (share->state.key_root[key] == HA_OFFSET_ERROR &&
|
if (share->state.key_root[key] == HA_OFFSET_ERROR &&
|
||||||
(info->state->records == 0 || keyinfo->flag & HA_FULLTEXT))
|
(info->state->records == 0 || keyinfo->flag & HA_FULLTEXT))
|
||||||
continue;
|
continue;
|
||||||
@ -434,8 +436,6 @@ int chk_key(MI_CHECK *param, register MI_INFO *info)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
full_text_keys++;
|
|
||||||
if ((uint) share->base.auto_key -1 == key)
|
if ((uint) share->base.auto_key -1 == key)
|
||||||
{
|
{
|
||||||
/* Check that auto_increment key is bigger than max key value */
|
/* Check that auto_increment key is bigger than max key value */
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#
|
#
|
||||||
# This failed for lia Perminov
|
# This failed for lia Perminov
|
||||||
#
|
#
|
||||||
drop table if exists t1,t2;
|
drop table if exists t1,t2,t3;
|
||||||
|
|
||||||
create table t1 (id int primary key);
|
create table t1 (id int primary key);
|
||||||
create table t2 (id int);
|
create table t2 (id int);
|
||||||
insert into t1 values (75);
|
insert into t1 values (75);
|
||||||
@ -120,3 +121,76 @@ INSERT INTO t1 (d) VALUES ('2001-08-01'),('0000-00-00');
|
|||||||
SELECT * FROM t1 LEFT JOIN t2 USING (d) WHERE t2.d IS NULL;
|
SELECT * FROM t1 LEFT JOIN t2 USING (d) WHERE t2.d IS NULL;
|
||||||
SELECT * from t1 WHERE t1.d IS NULL;
|
SELECT * from t1 WHERE t1.d IS NULL;
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Problem with reference from const tables
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (
|
||||||
|
Document_ID varchar(50) NOT NULL default '',
|
||||||
|
Contractor_ID varchar(6) NOT NULL default '',
|
||||||
|
Language_ID char(3) NOT NULL default '',
|
||||||
|
Expiration_Date datetime default NULL,
|
||||||
|
Publishing_Date datetime default NULL,
|
||||||
|
Title text,
|
||||||
|
Column_ID varchar(50) NOT NULL default '',
|
||||||
|
PRIMARY KEY (Language_ID,Document_ID,Contractor_ID)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES ('xep80','1','ger','2001-12-31 20:00:00','2001-11-12 10:58:00','Kartenbestellung - jetzt auch online','anle'),('','999998','',NULL,NULL,NULL,'');
|
||||||
|
|
||||||
|
CREATE TABLE t2 (
|
||||||
|
Contractor_ID char(6) NOT NULL default '',
|
||||||
|
Language_ID char(3) NOT NULL default '',
|
||||||
|
Document_ID char(50) NOT NULL default '',
|
||||||
|
CanRead char(1) default NULL,
|
||||||
|
Customer_ID int(11) NOT NULL default '0',
|
||||||
|
PRIMARY KEY (Contractor_ID,Language_ID,Document_ID,Customer_ID)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO t2 VALUES ('5','ger','xep80','1',999999),('1','ger','xep80','1',999999);
|
||||||
|
CREATE TABLE t3 (
|
||||||
|
Language_ID char(3) NOT NULL default '',
|
||||||
|
Column_ID char(50) NOT NULL default '',
|
||||||
|
Contractor_ID char(6) NOT NULL default '',
|
||||||
|
CanRead char(1) default NULL,
|
||||||
|
Active char(1) default NULL,
|
||||||
|
PRIMARY KEY (Language_ID,Column_ID,Contractor_ID)
|
||||||
|
);
|
||||||
|
INSERT INTO t3 VALUES ('ger','home','1','1','1'),('ger','Test','1','0','0'),('ger','derclu','1','0','0'),('ger','clubne','1','0','0'),('ger','philos','1','0','0'),('ger','clubko','1','0','0'),('ger','clubim','1','1','1'),('ger','progra','1','0','0'),('ger','progvo','1','0','0'),('ger','progsp','1','0','0'),('ger','progau','1','0','0'),('ger','progku','1','0','0'),('ger','progss','1','0','0'),('ger','nachl','1','0','0'),('ger','mitgli','1','0','0'),('ger','mitsu','1','0','0'),('ger','mitbus','1','0','0'),('ger','ergmar','1','1','1'),('ger','home','4','1','1'),('ger','derclu','4','1','1'),('ger','clubne','4','0','0'),('ger','philos','4','1','1'),('ger','clubko','4','1','1'),('ger','clubim','4','1','1'),('ger','progra','4','1','1'),('ger','progvo','4','1','1'),('ger','progsp','4','1','1'),('ger','progau','4','0','0'),('ger','progku','4','1','1'),('ger','progss','4','1','1'),('ger','nachl','4','1','1'),('ger','mitgli','4','0','0'),('ger','mitsu','4','0','0'),('ger','mitbus','4','0','0'),('ger','ergmar','4','1','1'),('ger','progra2','1','0','0'),('ger','archiv','4','1','1'),('ger','anmeld','4','1','1'),('ger','thema','4','1','1'),('ger','edito','4','1','1'),('ger','madis','4','1','1'),('ger','enma','4','1','1'),('ger','madis','1','1','1'),('ger','enma','1','1','1'),('ger','vorsch','4','0','0'),('ger','veranst','4','0','0'),('ger','anle','4','1','1'),('ger','redak','4','1','1'),('ger','nele','4','1','1'),('ger','aukt','4','1','1'),('ger','callcenter','4','1','1'),('ger','anle','1','0','0');
|
||||||
|
delete from t1 where Contractor_ID='999998';
|
||||||
|
insert into t1 (Contractor_ID) Values ('999998');
|
||||||
|
SELECT DISTINCT COUNT(t1.Title) FROM t1,
|
||||||
|
t2, t3 WHERE
|
||||||
|
t1.Document_ID='xep80' AND t1.Contractor_ID='1' AND
|
||||||
|
t1.Language_ID='ger' AND '2001-12-21 23:14:24' >=
|
||||||
|
Publishing_Date AND '2001-12-21 23:14:24' <= Expiration_Date AND
|
||||||
|
t1.Document_ID = t2.Document_ID AND
|
||||||
|
t1.Language_ID = t2.Language_ID AND
|
||||||
|
t1.Contractor_ID = t2.Contractor_ID AND (
|
||||||
|
t2.Customer_ID = '4' OR
|
||||||
|
t2.Customer_ID = '999999' OR
|
||||||
|
t2.Customer_ID = '1' )AND t2.CanRead
|
||||||
|
= '1' AND t1.Column_ID=t3.Column_ID AND
|
||||||
|
t1.Language_ID=t3.Language_ID AND (
|
||||||
|
t3.Contractor_ID = '4' OR
|
||||||
|
t3.Contractor_ID = '999999' OR
|
||||||
|
t3.Contractor_ID = '1') AND
|
||||||
|
t3.CanRead='1' AND t3.Active='1';
|
||||||
|
SELECT DISTINCT COUNT(t1.Title) FROM t1,
|
||||||
|
t2, t3 WHERE
|
||||||
|
t1.Document_ID='xep80' AND t1.Contractor_ID='1' AND
|
||||||
|
t1.Language_ID='ger' AND '2001-12-21 23:14:24' >=
|
||||||
|
Publishing_Date AND '2001-12-21 23:14:24' <= Expiration_Date AND
|
||||||
|
t1.Document_ID = t2.Document_ID AND
|
||||||
|
t1.Language_ID = t2.Language_ID AND
|
||||||
|
t1.Contractor_ID = t2.Contractor_ID AND (
|
||||||
|
t2.Customer_ID = '4' OR
|
||||||
|
t2.Customer_ID = '999999' OR
|
||||||
|
t2.Customer_ID = '1' )AND t2.CanRead
|
||||||
|
= '1' AND t1.Column_ID=t3.Column_ID AND
|
||||||
|
t1.Language_ID=t3.Language_ID AND (
|
||||||
|
t3.Contractor_ID = '4' OR
|
||||||
|
t3.Contractor_ID = '999999' OR
|
||||||
|
t3.Contractor_ID = '1') AND
|
||||||
|
t3.CanRead='1' AND t3.Active='1';
|
||||||
|
drop table t1,t2,t3;
|
||||||
|
@ -58,12 +58,16 @@ fix_path ()
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
abs_path=`expr \( substr $0 1 1 \) = '/'`
|
get_full_path ()
|
||||||
if [ "x$abs_path" = "x1" ] ; then
|
{
|
||||||
me=$0
|
case $1 in
|
||||||
else
|
/*) echo "$1";;
|
||||||
me=`which $0`
|
./*) tmp=`pwd`/$1; echo $tmp | sed -e 's;/./;/;' ;;
|
||||||
fi
|
*) which $1 ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
me=`get_full_path $0`
|
||||||
|
|
||||||
basedir=`echo $me | sed -e 's;/bin/mysql_config;;'`
|
basedir=`echo $me | sed -e 's;/bin/mysql_config;;'`
|
||||||
|
|
||||||
@ -81,6 +85,7 @@ ldflags='@LDFLAGS@'
|
|||||||
client_libs='@CLIENT_LIBS@'
|
client_libs='@CLIENT_LIBS@'
|
||||||
|
|
||||||
libs="$ldflags -L'$pkglibdir' -lmysqlclient $client_libs"
|
libs="$ldflags -L'$pkglibdir' -lmysqlclient $client_libs"
|
||||||
|
libs=`echo $libs | sed -e 's; +;;'`
|
||||||
cflags="-I'$pkgincludedir'"
|
cflags="-I'$pkgincludedir'"
|
||||||
embedded_libs="$ldflags -L'$pkglibdir' -lmysqld @LIBS@ @innodb_system_libs@"
|
embedded_libs="$ldflags -L'$pkglibdir' -lmysqld @LIBS@ @innodb_system_libs@"
|
||||||
|
|
||||||
|
269
sql/ha_innodb.cc
269
sql/ha_innodb.cc
@ -14,8 +14,8 @@
|
|||||||
along with this program; if not, write to the Free Software
|
along with this program; if not, write to the Free Software
|
||||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
||||||
|
|
||||||
/* This file defines the InnoDB handler: the interface between MySQL and
|
/*
|
||||||
InnoDB */
|
This file defines the InnoDB handler: the interface between MySQL and InnoDB */
|
||||||
|
|
||||||
/* TODO list for the InnoDB handler:
|
/* TODO list for the InnoDB handler:
|
||||||
- Ask Monty if strings of different languages can exist in the same
|
- Ask Monty if strings of different languages can exist in the same
|
||||||
@ -118,6 +118,36 @@ static void innobase_print_error(const char* db_errpfx, char* buffer);
|
|||||||
|
|
||||||
/* General functions */
|
/* General functions */
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
Releases possible search latch, auto inc lock, and InnoDB thread FIFO ticket.
|
||||||
|
These should be released at each SQL statement end. */
|
||||||
|
static
|
||||||
|
void
|
||||||
|
innobase_release_stat_resources(
|
||||||
|
/*============================*/
|
||||||
|
trx_t* trx) /* in: transaction object */
|
||||||
|
{
|
||||||
|
if (trx->has_search_latch) {
|
||||||
|
trx_search_latch_release_if_reserved(trx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trx->auto_inc_lock) {
|
||||||
|
|
||||||
|
/* If we had reserved the auto-inc lock for
|
||||||
|
some table in this SQL statement, we release it now */
|
||||||
|
|
||||||
|
srv_conc_enter_innodb(trx);
|
||||||
|
row_unlock_table_autoinc_for_mysql(trx);
|
||||||
|
srv_conc_exit_innodb(trx);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trx->declared_to_be_inside_innodb) {
|
||||||
|
/* Release our possible ticket in the FIFO */
|
||||||
|
|
||||||
|
srv_conc_force_exit_innodb(trx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
|
Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
|
||||||
time calls srv_active_wake_master_thread. This function should be used
|
time calls srv_active_wake_master_thread. This function should be used
|
||||||
@ -715,13 +745,12 @@ innobase_commit(
|
|||||||
trx = check_trx_exists(thd);
|
trx = check_trx_exists(thd);
|
||||||
|
|
||||||
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
|
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
|
||||||
srv_conc_enter_innodb(trx);
|
|
||||||
|
|
||||||
trx_commit_for_mysql(trx);
|
trx_commit_for_mysql(trx);
|
||||||
|
|
||||||
srv_conc_exit_innodb();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Release possible statement level resources */
|
||||||
|
innobase_release_stat_resources(trx);
|
||||||
trx_mark_sql_stat_end(trx);
|
trx_mark_sql_stat_end(trx);
|
||||||
|
|
||||||
#ifndef DBUG_OFF
|
#ifndef DBUG_OFF
|
||||||
@ -737,6 +766,32 @@ innobase_commit(
|
|||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*********************************************************************
|
||||||
|
This is called when MySQL writes the binlog entry for the current
|
||||||
|
transaction. Writes to the InnoDB tablespace info which tells where the
|
||||||
|
MySQL binlog entry for the current transaction ended. Also commits the
|
||||||
|
transaction inside InnoDB. */
|
||||||
|
|
||||||
|
int
|
||||||
|
innobase_report_binlog_offset_and_commit(
|
||||||
|
/*=====================================*/
|
||||||
|
/* out: 0 or error code */
|
||||||
|
THD* thd, /* in: user thread */
|
||||||
|
void* trx_handle, /* in: InnoDB trx handle */
|
||||||
|
char* log_file_name, /* in: latest binlog file name */
|
||||||
|
my_off_t end_offset) /* in: the offset in the binlog file
|
||||||
|
up to which we wrote */
|
||||||
|
{
|
||||||
|
trx_t* trx;
|
||||||
|
|
||||||
|
trx = (trx_t*)trx_handle;
|
||||||
|
|
||||||
|
trx->mysql_log_file_name = log_file_name;
|
||||||
|
trx->mysql_log_offset = (ib_longlong)end_offset;
|
||||||
|
|
||||||
|
return(innobase_commit(thd, trx_handle));
|
||||||
|
}
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
Rolls back a transaction in an InnoDB database. */
|
Rolls back a transaction in an InnoDB database. */
|
||||||
|
|
||||||
@ -764,7 +819,10 @@ innobase_rollback(
|
|||||||
error = trx_rollback_last_sql_stat_for_mysql(trx);
|
error = trx_rollback_last_sql_stat_for_mysql(trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
srv_conc_exit_innodb();
|
srv_conc_exit_innodb(trx);
|
||||||
|
|
||||||
|
/* Release possible statement level resources */
|
||||||
|
innobase_release_stat_resources(trx);
|
||||||
|
|
||||||
trx_mark_sql_stat_end(trx);
|
trx_mark_sql_stat_end(trx);
|
||||||
|
|
||||||
@ -1437,6 +1495,8 @@ ha_innobase::write_row(
|
|||||||
if (last_query_id != user_thd->query_id) {
|
if (last_query_id != user_thd->query_id) {
|
||||||
prebuilt->sql_stat_start = TRUE;
|
prebuilt->sql_stat_start = TRUE;
|
||||||
last_query_id = user_thd->query_id;
|
last_query_id = user_thd->query_id;
|
||||||
|
|
||||||
|
innobase_release_stat_resources(prebuilt->trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (table->next_number_field && record == table->record[0]) {
|
if (table->next_number_field && record == table->record[0]) {
|
||||||
@ -1487,7 +1547,7 @@ ha_innobase::write_row(
|
|||||||
|
|
||||||
srv_conc_enter_innodb(prebuilt->trx);
|
srv_conc_enter_innodb(prebuilt->trx);
|
||||||
error = row_lock_table_autoinc_for_mysql(prebuilt);
|
error = row_lock_table_autoinc_for_mysql(prebuilt);
|
||||||
srv_conc_exit_innodb();
|
srv_conc_exit_innodb(prebuilt->trx);
|
||||||
|
|
||||||
if (error != DB_SUCCESS) {
|
if (error != DB_SUCCESS) {
|
||||||
|
|
||||||
@ -1504,7 +1564,7 @@ ha_innobase::write_row(
|
|||||||
error = row_lock_table_autoinc_for_mysql(
|
error = row_lock_table_autoinc_for_mysql(
|
||||||
prebuilt);
|
prebuilt);
|
||||||
if (error != DB_SUCCESS) {
|
if (error != DB_SUCCESS) {
|
||||||
srv_conc_exit_innodb();
|
srv_conc_exit_innodb(prebuilt->trx);
|
||||||
|
|
||||||
error = convert_error_code_to_mysql(
|
error = convert_error_code_to_mysql(
|
||||||
error);
|
error);
|
||||||
@ -1513,7 +1573,7 @@ ha_innobase::write_row(
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto_inc = dict_table_autoinc_get(prebuilt->table);
|
auto_inc = dict_table_autoinc_get(prebuilt->table);
|
||||||
srv_conc_exit_innodb();
|
srv_conc_exit_innodb(prebuilt->trx);
|
||||||
|
|
||||||
/* If auto_inc is now != 0 the autoinc counter
|
/* If auto_inc is now != 0 the autoinc counter
|
||||||
was already initialized for the table: we can give
|
was already initialized for the table: we can give
|
||||||
@ -1540,7 +1600,7 @@ ha_innobase::write_row(
|
|||||||
|
|
||||||
srv_conc_enter_innodb(prebuilt->trx);
|
srv_conc_enter_innodb(prebuilt->trx);
|
||||||
error = row_lock_table_autoinc_for_mysql(prebuilt);
|
error = row_lock_table_autoinc_for_mysql(prebuilt);
|
||||||
srv_conc_exit_innodb();
|
srv_conc_exit_innodb(prebuilt->trx);
|
||||||
|
|
||||||
if (error != DB_SUCCESS) {
|
if (error != DB_SUCCESS) {
|
||||||
|
|
||||||
@ -1580,7 +1640,7 @@ ha_innobase::write_row(
|
|||||||
|
|
||||||
error = row_insert_for_mysql((byte*) record, prebuilt);
|
error = row_insert_for_mysql((byte*) record, prebuilt);
|
||||||
|
|
||||||
srv_conc_exit_innodb();
|
srv_conc_exit_innodb(prebuilt->trx);
|
||||||
|
|
||||||
prebuilt->trx->ignore_duplicates_in_insert = FALSE;
|
prebuilt->trx->ignore_duplicates_in_insert = FALSE;
|
||||||
|
|
||||||
@ -1775,6 +1835,8 @@ ha_innobase::update_row(
|
|||||||
if (last_query_id != user_thd->query_id) {
|
if (last_query_id != user_thd->query_id) {
|
||||||
prebuilt->sql_stat_start = TRUE;
|
prebuilt->sql_stat_start = TRUE;
|
||||||
last_query_id = user_thd->query_id;
|
last_query_id = user_thd->query_id;
|
||||||
|
|
||||||
|
innobase_release_stat_resources(prebuilt->trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prebuilt->upd_node) {
|
if (prebuilt->upd_node) {
|
||||||
@ -1799,7 +1861,7 @@ ha_innobase::update_row(
|
|||||||
|
|
||||||
error = row_update_for_mysql((byte*) old_row, prebuilt);
|
error = row_update_for_mysql((byte*) old_row, prebuilt);
|
||||||
|
|
||||||
srv_conc_exit_innodb();
|
srv_conc_exit_innodb(prebuilt->trx);
|
||||||
|
|
||||||
error = convert_error_code_to_mysql(error);
|
error = convert_error_code_to_mysql(error);
|
||||||
|
|
||||||
@ -1828,6 +1890,8 @@ ha_innobase::delete_row(
|
|||||||
if (last_query_id != user_thd->query_id) {
|
if (last_query_id != user_thd->query_id) {
|
||||||
prebuilt->sql_stat_start = TRUE;
|
prebuilt->sql_stat_start = TRUE;
|
||||||
last_query_id = user_thd->query_id;
|
last_query_id = user_thd->query_id;
|
||||||
|
|
||||||
|
innobase_release_stat_resources(prebuilt->trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!prebuilt->upd_node) {
|
if (!prebuilt->upd_node) {
|
||||||
@ -1843,7 +1907,7 @@ ha_innobase::delete_row(
|
|||||||
|
|
||||||
error = row_update_for_mysql((byte*) record, prebuilt);
|
error = row_update_for_mysql((byte*) record, prebuilt);
|
||||||
|
|
||||||
srv_conc_exit_innodb();
|
srv_conc_exit_innodb(prebuilt->trx);
|
||||||
|
|
||||||
error = convert_error_code_to_mysql(error);
|
error = convert_error_code_to_mysql(error);
|
||||||
|
|
||||||
@ -1942,6 +2006,8 @@ ha_innobase::index_read(
|
|||||||
if (last_query_id != user_thd->query_id) {
|
if (last_query_id != user_thd->query_id) {
|
||||||
prebuilt->sql_stat_start = TRUE;
|
prebuilt->sql_stat_start = TRUE;
|
||||||
last_query_id = user_thd->query_id;
|
last_query_id = user_thd->query_id;
|
||||||
|
|
||||||
|
innobase_release_stat_resources(prebuilt->trx);
|
||||||
}
|
}
|
||||||
|
|
||||||
index = prebuilt->index;
|
index = prebuilt->index;
|
||||||
@ -1987,7 +2053,7 @@ ha_innobase::index_read(
|
|||||||
|
|
||||||
ret = row_search_for_mysql((byte*) buf, mode, prebuilt, match_mode, 0);
|
ret = row_search_for_mysql((byte*) buf, mode, prebuilt, match_mode, 0);
|
||||||
|
|
||||||
srv_conc_exit_innodb();
|
srv_conc_exit_innodb(prebuilt->trx);
|
||||||
|
|
||||||
if (ret == DB_SUCCESS) {
|
if (ret == DB_SUCCESS) {
|
||||||
error = 0;
|
error = 0;
|
||||||
@ -2126,7 +2192,7 @@ ha_innobase::general_fetch(
|
|||||||
|
|
||||||
ret = row_search_for_mysql((byte*)buf, 0, prebuilt, match_mode,
|
ret = row_search_for_mysql((byte*)buf, 0, prebuilt, match_mode,
|
||||||
direction);
|
direction);
|
||||||
srv_conc_exit_innodb();
|
srv_conc_exit_innodb(prebuilt->trx);
|
||||||
|
|
||||||
if (ret == DB_SUCCESS) {
|
if (ret == DB_SUCCESS) {
|
||||||
error = 0;
|
error = 0;
|
||||||
@ -2426,88 +2492,6 @@ int ha_innobase::reset(void)
|
|||||||
return(0);
|
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
|
|
||||||
pointer to the THD in the handle. We will also use this function to communicate
|
|
||||||
to InnoDB that a new SQL statement has started and that we must store a
|
|
||||||
savepoint to our transaction handle, so that we are able to roll back
|
|
||||||
the SQL statement in case of an error. */
|
|
||||||
|
|
||||||
int
|
|
||||||
ha_innobase::external_lock(
|
|
||||||
/*=======================*/
|
|
||||||
THD* thd, /* in: handle to the user thread */
|
|
||||||
int lock_type) /* in: lock type */
|
|
||||||
{
|
|
||||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
|
||||||
int error = 0;
|
|
||||||
trx_t* trx;
|
|
||||||
|
|
||||||
DBUG_ENTER("ha_innobase::external_lock");
|
|
||||||
|
|
||||||
update_thd(thd);
|
|
||||||
|
|
||||||
trx = prebuilt->trx;
|
|
||||||
|
|
||||||
prebuilt->sql_stat_start = TRUE;
|
|
||||||
prebuilt->in_update_remember_pos = TRUE;
|
|
||||||
|
|
||||||
prebuilt->read_just_key = 0;
|
|
||||||
|
|
||||||
if (lock_type == F_WRLCK) {
|
|
||||||
|
|
||||||
/* If this is a SELECT, then it is in UPDATE TABLE ...
|
|
||||||
or SELECT ... FOR UPDATE */
|
|
||||||
prebuilt->select_lock_type = LOCK_X;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lock_type != F_UNLCK) {
|
|
||||||
if (trx->n_mysql_tables_in_use == 0) {
|
|
||||||
trx_mark_sql_stat_end(trx);
|
|
||||||
}
|
|
||||||
|
|
||||||
thd->transaction.all.innodb_active_trans = 1;
|
|
||||||
trx->n_mysql_tables_in_use++;
|
|
||||||
|
|
||||||
if (prebuilt->select_lock_type != LOCK_NONE) {
|
|
||||||
|
|
||||||
trx->mysql_n_tables_locked++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
trx->n_mysql_tables_in_use--;
|
|
||||||
auto_inc_counter_for_this_stat = 0;
|
|
||||||
|
|
||||||
if (trx->n_mysql_tables_in_use == 0) {
|
|
||||||
|
|
||||||
trx->mysql_n_tables_locked = 0;
|
|
||||||
|
|
||||||
if (trx->has_search_latch) {
|
|
||||||
|
|
||||||
trx_search_latch_release_if_reserved(trx);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (trx->auto_inc_lock) {
|
|
||||||
|
|
||||||
/* If we had reserved the auto-inc lock for
|
|
||||||
some table in this SQL statement, we release
|
|
||||||
it now */
|
|
||||||
|
|
||||||
srv_conc_enter_innodb(trx);
|
|
||||||
row_unlock_table_autoinc_for_mysql(trx);
|
|
||||||
srv_conc_exit_innodb();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(thd->options
|
|
||||||
& (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))) {
|
|
||||||
|
|
||||||
innobase_commit(thd, trx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DBUG_RETURN(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************
|
/*********************************************************************
|
||||||
Creates a table definition to an InnoDB database. */
|
Creates a table definition to an InnoDB database. */
|
||||||
@ -2684,7 +2668,7 @@ ha_innobase::create(
|
|||||||
|
|
||||||
/* Create the table definition in InnoDB */
|
/* Create the table definition in InnoDB */
|
||||||
|
|
||||||
if ((error = create_table_def(trx, form, norm_name))) {
|
if (error = create_table_def(trx, form, norm_name)) {
|
||||||
|
|
||||||
trx_commit_for_mysql(trx);
|
trx_commit_for_mysql(trx);
|
||||||
|
|
||||||
@ -3166,7 +3150,22 @@ ha_innobase::info(
|
|||||||
rec_per_key = 1;
|
rec_per_key = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
table->key_info[i].rec_per_key[j]
|
/* Since the MySQL optimizer is often too
|
||||||
|
pessimistic in the assumption that a table
|
||||||
|
does not fit in the buffer pool, we
|
||||||
|
increase the attractiveness of indexes
|
||||||
|
by assuming the selectivity of any prefix
|
||||||
|
of an index is 1 / 100 or better.
|
||||||
|
(Actually, we should look at the table
|
||||||
|
size, and if the table is smaller than
|
||||||
|
the buffer pool, we should uniformly
|
||||||
|
increase the attractiveness of indexes,
|
||||||
|
regardless of the estimated selectivity.) */
|
||||||
|
|
||||||
|
if (rec_per_key > records / 100) {
|
||||||
|
rec_per_key = records / 100;
|
||||||
|
}
|
||||||
|
table->key_info[i].rec_per_key[j]
|
||||||
= rec_per_key;
|
= rec_per_key;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3264,6 +3263,78 @@ ha_innobase::update_table_comment(
|
|||||||
return(str);
|
return(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
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
|
||||||
|
pointer to the THD in the handle. We will also use this function to communicate
|
||||||
|
to InnoDB that a new SQL statement has started and that we must store a
|
||||||
|
savepoint to our transaction handle, so that we are able to roll back
|
||||||
|
the SQL statement in case of an error. */
|
||||||
|
|
||||||
|
int
|
||||||
|
ha_innobase::external_lock(
|
||||||
|
/*=======================*/
|
||||||
|
THD* thd, /* in: handle to the user thread */
|
||||||
|
int lock_type) /* in: lock type */
|
||||||
|
{
|
||||||
|
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||||
|
int error = 0;
|
||||||
|
trx_t* trx;
|
||||||
|
|
||||||
|
DBUG_ENTER("ha_innobase::external_lock");
|
||||||
|
|
||||||
|
update_thd(thd);
|
||||||
|
|
||||||
|
trx = prebuilt->trx;
|
||||||
|
|
||||||
|
prebuilt->sql_stat_start = TRUE;
|
||||||
|
prebuilt->in_update_remember_pos = TRUE;
|
||||||
|
|
||||||
|
prebuilt->read_just_key = 0;
|
||||||
|
|
||||||
|
if (lock_type == F_WRLCK) {
|
||||||
|
|
||||||
|
/* If this is a SELECT, then it is in UPDATE TABLE ...
|
||||||
|
or SELECT ... FOR UPDATE */
|
||||||
|
prebuilt->select_lock_type = LOCK_X;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lock_type != F_UNLCK) {
|
||||||
|
if (trx->n_mysql_tables_in_use == 0) {
|
||||||
|
trx_mark_sql_stat_end(trx);
|
||||||
|
}
|
||||||
|
|
||||||
|
thd->transaction.all.innodb_active_trans = 1;
|
||||||
|
trx->n_mysql_tables_in_use++;
|
||||||
|
|
||||||
|
if (prebuilt->select_lock_type != LOCK_NONE) {
|
||||||
|
|
||||||
|
trx->mysql_n_tables_locked++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
trx->n_mysql_tables_in_use--;
|
||||||
|
auto_inc_counter_for_this_stat = 0;
|
||||||
|
|
||||||
|
if (trx->n_mysql_tables_in_use == 0) {
|
||||||
|
|
||||||
|
trx->mysql_n_tables_locked = 0;
|
||||||
|
|
||||||
|
/* Here we release the search latch, auto_inc_lock,
|
||||||
|
and InnoDB thread FIFO ticket if they were reserved. */
|
||||||
|
|
||||||
|
innobase_release_stat_resources(trx);
|
||||||
|
|
||||||
|
if (!(thd->options
|
||||||
|
& (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))) {
|
||||||
|
|
||||||
|
innobase_commit(thd, trx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DBUG_RETURN(error);
|
||||||
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
Handling the shared INNOBASE_SHARE structure that is needed to provide table
|
Handling the shared INNOBASE_SHARE structure that is needed to provide table
|
||||||
locking.
|
locking.
|
||||||
|
@ -189,6 +189,11 @@ bool innobase_flush_logs(void);
|
|||||||
uint innobase_get_free_space(void);
|
uint innobase_get_free_space(void);
|
||||||
|
|
||||||
int innobase_commit(THD *thd, void* trx_handle);
|
int innobase_commit(THD *thd, void* trx_handle);
|
||||||
|
int innobase_report_binlog_offset_and_commit(
|
||||||
|
THD* thd,
|
||||||
|
void* trx_handle,
|
||||||
|
char* log_file_name,
|
||||||
|
my_off_t end_offset);
|
||||||
int innobase_rollback(THD *thd, void* trx_handle);
|
int innobase_rollback(THD *thd, void* trx_handle);
|
||||||
int innobase_close_connection(THD *thd);
|
int innobase_close_connection(THD *thd);
|
||||||
int innobase_drop_database(char *path);
|
int innobase_drop_database(char *path);
|
||||||
|
@ -221,6 +221,44 @@ int ha_autocommit_or_rollback(THD *thd, int error)
|
|||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function is called when MySQL writes the log segment of a transaction
|
||||||
|
to the binlog. It is called when the LOCK_log mutex is reserved. Here we
|
||||||
|
communicate to transactional table handlers whta binlog position corresponds
|
||||||
|
to the current transaction. The handler can store it and in recovery print
|
||||||
|
to the user, so that the user knows from what position in the binlog to
|
||||||
|
start possible roll-forward, for example, if the crashed server was a slave
|
||||||
|
in replication. This function also calls the commit of the table handler,
|
||||||
|
because the order of trasnactions in the log of the table handler must be
|
||||||
|
the same as in the binlog. */
|
||||||
|
|
||||||
|
int ha_report_binlog_offset_and_commit(
|
||||||
|
THD *thd, /* in: user thread */
|
||||||
|
char *log_file_name, /* in: latest binlog file name */
|
||||||
|
my_off_t end_offset) /* in: the offset in the binlog file
|
||||||
|
up to which we wrote */
|
||||||
|
{
|
||||||
|
THD_TRANS *trans;
|
||||||
|
int error = 0;
|
||||||
|
|
||||||
|
trans = &thd->transaction.all;
|
||||||
|
|
||||||
|
#ifdef HAVE_INNOBASE_DB
|
||||||
|
if (trans->innobase_tid)
|
||||||
|
{
|
||||||
|
if ((error=innobase_report_binlog_offset_and_commit(thd,
|
||||||
|
trans->innobase_tid,
|
||||||
|
log_file_name,
|
||||||
|
end_offset)))
|
||||||
|
{
|
||||||
|
my_error(ER_ERROR_DURING_COMMIT, MYF(0), error);
|
||||||
|
error=1;
|
||||||
|
}
|
||||||
|
trans->innodb_active_trans=0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
int ha_commit_trans(THD *thd, THD_TRANS* trans)
|
int ha_commit_trans(THD *thd, THD_TRANS* trans)
|
||||||
{
|
{
|
||||||
@ -233,7 +271,7 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
|
|||||||
if (trans == &thd->transaction.all && mysql_bin_log.is_open() &&
|
if (trans == &thd->transaction.all && mysql_bin_log.is_open() &&
|
||||||
my_b_tell(&thd->transaction.trans_log))
|
my_b_tell(&thd->transaction.trans_log))
|
||||||
{
|
{
|
||||||
mysql_bin_log.write(&thd->transaction.trans_log);
|
mysql_bin_log.write(thd, &thd->transaction.trans_log);
|
||||||
reinit_io_cache(&thd->transaction.trans_log,
|
reinit_io_cache(&thd->transaction.trans_log,
|
||||||
WRITE_CACHE, (my_off_t) 0, 0, 1);
|
WRITE_CACHE, (my_off_t) 0, 0, 1);
|
||||||
thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
|
thd->transaction.trans_log.end_of_file= max_binlog_cache_size;
|
||||||
|
@ -361,6 +361,10 @@ int ha_delete_table(enum db_type db_type, const char *path);
|
|||||||
void ha_drop_database(char* path);
|
void ha_drop_database(char* path);
|
||||||
void ha_key_cache(void);
|
void ha_key_cache(void);
|
||||||
int ha_start_stmt(THD *thd);
|
int ha_start_stmt(THD *thd);
|
||||||
|
int ha_report_binlog_offset_and_commit(
|
||||||
|
THD *thd,
|
||||||
|
char *log_file_name,
|
||||||
|
my_off_t end_offset);
|
||||||
int ha_commit_trans(THD *thd, THD_TRANS *trans);
|
int ha_commit_trans(THD *thd, THD_TRANS *trans);
|
||||||
int ha_rollback_trans(THD *thd, THD_TRANS *trans);
|
int ha_rollback_trans(THD *thd, THD_TRANS *trans);
|
||||||
int ha_autocommit_or_rollback(THD *thd, int error);
|
int ha_autocommit_or_rollback(THD *thd, int error);
|
||||||
|
33
sql/log.cc
33
sql/log.cc
@ -873,9 +873,12 @@ bool MYSQL_LOG::write(Log_event* event_info)
|
|||||||
VOID(pthread_mutex_unlock(&LOCK_log));
|
VOID(pthread_mutex_unlock(&LOCK_log));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
error=1;
|
error=1;
|
||||||
// no check for auto events flag here - this write method should
|
/*
|
||||||
// never be called if auto-events are enabled
|
No check for auto events flag here - this write method should
|
||||||
|
never be called if auto-events are enabled
|
||||||
|
*/
|
||||||
if (thd && thd->last_insert_id_used)
|
if (thd && thd->last_insert_id_used)
|
||||||
{
|
{
|
||||||
Intvar_log_event e(thd,(uchar)LAST_INSERT_ID_EVENT,thd->last_insert_id);
|
Intvar_log_event e(thd,(uchar)LAST_INSERT_ID_EVENT,thd->last_insert_id);
|
||||||
@ -913,8 +916,24 @@ bool MYSQL_LOG::write(Log_event* event_info)
|
|||||||
file == &log_file && flush_io_cache(file))
|
file == &log_file && flush_io_cache(file))
|
||||||
goto err;
|
goto err;
|
||||||
error=0;
|
error=0;
|
||||||
should_rotate = (file == &log_file &&
|
|
||||||
(uint)my_b_tell(file) >= max_binlog_size);
|
/*
|
||||||
|
Tell for transactional table handlers up to which position in the
|
||||||
|
binlog file we wrote. The table handler can store this info, and
|
||||||
|
after crash recovery print for the user the offset of the last
|
||||||
|
transactions which were recovered. Actually, we must also call
|
||||||
|
the table handler commit here, protected by the LOCK_log mutex,
|
||||||
|
because otherwise the transactions may end up in a different order
|
||||||
|
in the table handler log!
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (file == &log_file)
|
||||||
|
{
|
||||||
|
error = ha_report_binlog_offset_and_commit(thd, log_file_name,
|
||||||
|
file->pos_in_file);
|
||||||
|
should_rotate= (my_b_tell(file) >= (my_off_t) max_binlog_size);
|
||||||
|
}
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (error)
|
if (error)
|
||||||
{
|
{
|
||||||
@ -948,7 +967,7 @@ uint MYSQL_LOG::next_file_id()
|
|||||||
'cache' needs to be reinitialized after this functions returns.
|
'cache' needs to be reinitialized after this functions returns.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool MYSQL_LOG::write(IO_CACHE *cache)
|
bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache)
|
||||||
{
|
{
|
||||||
VOID(pthread_mutex_lock(&LOCK_log));
|
VOID(pthread_mutex_lock(&LOCK_log));
|
||||||
bool error=1;
|
bool error=1;
|
||||||
@ -984,6 +1003,10 @@ bool MYSQL_LOG::write(IO_CACHE *cache)
|
|||||||
sql_print_error(ER(ER_ERROR_ON_READ), cache->file_name, errno);
|
sql_print_error(ER(ER_ERROR_ON_READ), cache->file_name, errno);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
error = ha_report_binlog_offset_and_commit(thd, log_file_name,
|
||||||
|
log_file.pos_in_file);
|
||||||
|
if (error)
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
error=0;
|
error=0;
|
||||||
|
|
||||||
|
@ -103,10 +103,12 @@ public:
|
|||||||
bool write(THD *thd, const char *query, uint query_length,
|
bool write(THD *thd, const char *query, uint query_length,
|
||||||
time_t query_start=0);
|
time_t query_start=0);
|
||||||
bool write(Log_event* event_info); // binary log write
|
bool write(Log_event* event_info); // binary log write
|
||||||
bool write(IO_CACHE *cache);
|
bool write(THD *thd, IO_CACHE *cache);
|
||||||
|
|
||||||
//v stands for vector
|
/*
|
||||||
//invoked as appendv(buf1,len1,buf2,len2,...,bufn,lenn,0)
|
v stands for vector
|
||||||
|
invoked as appendv(buf1,len1,buf2,len2,...,bufn,lenn,0)
|
||||||
|
*/
|
||||||
bool appendv(const char* buf,uint len,...);
|
bool appendv(const char* buf,uint len,...);
|
||||||
bool append(Log_event* ev);
|
bool append(Log_event* ev);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user