mirror of
https://github.com/MariaDB/server.git
synced 2025-12-15 08:21:24 +03:00
branches/zip: Merge 1575:1664 from trunk.
This commit is contained in:
@@ -16,6 +16,9 @@
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX")
|
||||
ADD_DEFINITIONS(-DMYSQL_SERVER -D_WIN32 -DWIN32 -D_LIB)
|
||||
IF(EMBEDDED_ONLY)
|
||||
ADD_DEFINITIONS(-DUSE_TLS)
|
||||
ENDIF(EMBEDDED_ONLY)
|
||||
|
||||
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib
|
||||
include
|
||||
|
||||
@@ -56,7 +56,9 @@ noinst_HEADERS = include/btr0btr.h include/btr0btr.ic \
|
||||
include/ha0ha.ic include/hash0hash.h \
|
||||
include/hash0hash.ic include/ibuf0ibuf.h \
|
||||
include/ibuf0ibuf.ic include/ibuf0types.h \
|
||||
include/lock0iter.h \
|
||||
include/lock0lock.h include/lock0lock.ic \
|
||||
include/lock0priv.h include/lock0priv.ic \
|
||||
include/lock0types.h include/log0log.h \
|
||||
include/log0log.ic include/log0recv.h \
|
||||
include/log0recv.ic include/mach0data.h \
|
||||
@@ -134,7 +136,8 @@ libinnobase_a_SOURCES = btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c \
|
||||
eval/eval0eval.c eval/eval0proc.c \
|
||||
fil/fil0fil.c fsp/fsp0fsp.c fut/fut0fut.c \
|
||||
fut/fut0lst.c ha/ha0ha.c ha/hash0hash.c \
|
||||
ibuf/ibuf0ibuf.c lock/lock0lock.c \
|
||||
ibuf/ibuf0ibuf.c lock/lock0iter.c \
|
||||
lock/lock0lock.c \
|
||||
log/log0log.c log/log0recv.c mach/mach0data.c \
|
||||
mem/mem0mem.c mem/mem0pool.c mtr/mtr0log.c \
|
||||
mtr/mtr0mtr.c os/os0file.c os/os0proc.c \
|
||||
@@ -158,8 +161,8 @@ libinnobase_a_SOURCES = btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c \
|
||||
ut/ut0ut.c ut/ut0vec.c ut/ut0wqueue.c \
|
||||
handler/ha_innodb.cc
|
||||
|
||||
libinnobase_a_CXXFLAGS= $(AM_CFLAGS) -DMYSQL_SERVER
|
||||
libinnobase_a_CFLAGS = $(AM_CFLAGS) -DMYSQL_SERVER
|
||||
libinnobase_a_CXXFLAGS= $(AM_CFLAGS)
|
||||
libinnobase_a_CFLAGS = $(AM_CFLAGS)
|
||||
|
||||
EXTRA_LTLIBRARIES = ha_innodb.la
|
||||
pkglib_LTLIBRARIES = @plugin_innobase_shared_target@
|
||||
|
||||
@@ -895,7 +895,7 @@ btr_search_guess_on_hash(
|
||||
btr_search_n_succ++;
|
||||
#endif
|
||||
if (UNIV_LIKELY(!has_search_latch)
|
||||
&& buf_block_peek_if_too_old(block)) {
|
||||
&& buf_page_peek_if_too_old(&block->page)) {
|
||||
|
||||
buf_page_make_young(&block->page);
|
||||
}
|
||||
|
||||
@@ -1329,9 +1329,7 @@ buf_block_make_young(
|
||||
/* Note that we read freed_page_clock's without holding any mutex:
|
||||
this is allowed since the result is used only in heuristics */
|
||||
|
||||
if (buf_pool->freed_page_clock
|
||||
>= buf_page_get_freed_page_clock(bpage)
|
||||
+ 1 + (buf_pool->curr_size / 4)) {
|
||||
if (buf_page_peek_if_too_old(bpage)) {
|
||||
|
||||
mutex_enter(&buf_pool->mutex);
|
||||
/* There has been freeing activity in the LRU list:
|
||||
|
||||
102
dict/dict0dict.c
102
dict/dict0dict.c
@@ -350,6 +350,18 @@ dict_table_get_col_name(
|
||||
return(s);
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
Acquire the autoinc lock.*/
|
||||
|
||||
void
|
||||
dict_table_autoinc_lock(
|
||||
/*====================*/
|
||||
dict_table_t* table)
|
||||
{
|
||||
mutex_enter(&table->autoinc_mutex);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Initializes the autoinc counter. It is not an error to initialize an already
|
||||
initialized counter. */
|
||||
@@ -360,54 +372,8 @@ dict_table_autoinc_initialize(
|
||||
dict_table_t* table, /* in: table */
|
||||
ib_longlong value) /* in: next value to assign to a row */
|
||||
{
|
||||
mutex_enter(&(table->autoinc_mutex));
|
||||
|
||||
table->autoinc_inited = TRUE;
|
||||
table->autoinc = value;
|
||||
|
||||
mutex_exit(&(table->autoinc_mutex));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Gets the next autoinc value (== autoinc counter value), 0 if not yet
|
||||
initialized. If initialized, increments the counter by 1. */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_get(
|
||||
/*===================*/
|
||||
/* out: value for a new row, or 0 */
|
||||
dict_table_t* table) /* in: table */
|
||||
{
|
||||
ib_longlong value;
|
||||
|
||||
mutex_enter(&(table->autoinc_mutex));
|
||||
|
||||
if (!table->autoinc_inited) {
|
||||
|
||||
value = 0;
|
||||
} else {
|
||||
value = table->autoinc;
|
||||
table->autoinc = table->autoinc + 1;
|
||||
}
|
||||
|
||||
mutex_exit(&(table->autoinc_mutex));
|
||||
|
||||
return(value);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Decrements the autoinc counter value by 1. */
|
||||
|
||||
void
|
||||
dict_table_autoinc_decrement(
|
||||
/*=========================*/
|
||||
dict_table_t* table) /* in: table */
|
||||
{
|
||||
mutex_enter(&(table->autoinc_mutex));
|
||||
|
||||
table->autoinc = table->autoinc - 1;
|
||||
|
||||
mutex_exit(&(table->autoinc_mutex));
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@@ -422,32 +388,6 @@ dict_table_autoinc_read(
|
||||
{
|
||||
ib_longlong value;
|
||||
|
||||
mutex_enter(&(table->autoinc_mutex));
|
||||
|
||||
if (!table->autoinc_inited) {
|
||||
|
||||
value = 0;
|
||||
} else {
|
||||
value = table->autoinc;
|
||||
}
|
||||
|
||||
mutex_exit(&(table->autoinc_mutex));
|
||||
|
||||
return(value);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Peeks the autoinc counter value, 0 if not yet initialized. Does not
|
||||
increment the counter. The read not protected by any mutex! */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_peek(
|
||||
/*====================*/
|
||||
/* out: value of the counter */
|
||||
dict_table_t* table) /* in: table */
|
||||
{
|
||||
ib_longlong value;
|
||||
|
||||
if (!table->autoinc_inited) {
|
||||
|
||||
value = 0;
|
||||
@@ -459,7 +399,7 @@ dict_table_autoinc_peek(
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Updates the autoinc counter if the value supplied is equal or bigger than the
|
||||
Updates the autoinc counter if the value supplied is greater than the
|
||||
current value. If not inited, does nothing. */
|
||||
|
||||
void
|
||||
@@ -469,15 +409,21 @@ dict_table_autoinc_update(
|
||||
dict_table_t* table, /* in: table */
|
||||
ib_longlong value) /* in: value which was assigned to a row */
|
||||
{
|
||||
mutex_enter(&(table->autoinc_mutex));
|
||||
if (table->autoinc_inited && value > table->autoinc) {
|
||||
|
||||
if (table->autoinc_inited) {
|
||||
if (value >= table->autoinc) {
|
||||
table->autoinc = value + 1;
|
||||
table->autoinc = value;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_exit(&(table->autoinc_mutex));
|
||||
/************************************************************************
|
||||
Release the autoinc lock.*/
|
||||
|
||||
void
|
||||
dict_table_autoinc_unlock(
|
||||
/*======================*/
|
||||
dict_table_t* table) /* in: release autoinc lock for this table */
|
||||
{
|
||||
mutex_exit(&table->autoinc_mutex);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
||||
@@ -92,6 +92,11 @@ dict_mem_table_create(
|
||||
mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
|
||||
|
||||
table->autoinc_inited = FALSE;
|
||||
|
||||
/* The actual increment value will be set by MySQL, we simply
|
||||
default to 1 here.*/
|
||||
table->autoinc_increment = 1;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
table->magic_n = DICT_TABLE_MAGIC_N;
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
@@ -14,6 +14,9 @@ if [ $# -ne 2 ] ; then
|
||||
die "Usage: export.sh revision-number-of-last-snapshot current-revision-number"
|
||||
fi
|
||||
|
||||
START_REV=$(($1 + 1))
|
||||
END_REV=$2
|
||||
|
||||
set +u
|
||||
if test -z $EDITOR; then
|
||||
die "\$EDITOR is not set"
|
||||
@@ -22,10 +25,11 @@ set -u
|
||||
|
||||
rm -rf to-mysql
|
||||
mkdir to-mysql{,/storage,/patches,/mysql-test{,/t,/r,/include}}
|
||||
svn log -v -r "$(($1 + 1)):BASE" > to-mysql/log
|
||||
svn log -v -r "$START_REV:BASE" > to-mysql/log
|
||||
svn export -q . to-mysql/storage/innobase
|
||||
|
||||
seq $(($1+1)) $2|while read REV
|
||||
REV=$START_REV
|
||||
while [ $REV -le $END_REV ]
|
||||
do
|
||||
PATCH=to-mysql/patches/r$REV.patch
|
||||
svn log -v -r$REV > $PATCH
|
||||
@@ -35,6 +39,7 @@ do
|
||||
else
|
||||
rm $PATCH
|
||||
fi
|
||||
REV=$(($REV + 1))
|
||||
done
|
||||
|
||||
cd to-mysql/storage/innobase
|
||||
|
||||
@@ -2983,7 +2983,7 @@ will be able to insert new data to the database without running out the
|
||||
tablespace. Only free extents are taken into account and we also subtract
|
||||
the safety margin required by the above function fsp_reserve_free_extents. */
|
||||
|
||||
ulint
|
||||
ullint
|
||||
fsp_get_available_space_in_free_extents(
|
||||
/*====================================*/
|
||||
/* out: available space in kB */
|
||||
@@ -3056,10 +3056,12 @@ fsp_get_available_space_in_free_extents(
|
||||
}
|
||||
|
||||
if (!zip_size) {
|
||||
return(((n_free - reserve) * FSP_EXTENT_SIZE)
|
||||
return((ullint) (n_free - reserve)
|
||||
* FSP_EXTENT_SIZE
|
||||
* (UNIV_PAGE_SIZE / 1024));
|
||||
} else {
|
||||
return(((n_free - reserve) * FSP_EXTENT_SIZE)
|
||||
return((ullint) (n_free - reserve)
|
||||
* FSP_EXTENT_SIZE
|
||||
* (zip_size / 1024));
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,7 +32,10 @@ typedef struct st_innobase_share {
|
||||
} INNOBASE_SHARE;
|
||||
|
||||
|
||||
struct dict_index_struct;
|
||||
struct row_prebuilt_struct;
|
||||
|
||||
typedef struct dict_index_struct dict_index_t;
|
||||
typedef struct row_prebuilt_struct row_prebuilt_t;
|
||||
|
||||
/* The class defining a handle to an Innodb table */
|
||||
@@ -54,7 +57,7 @@ class ha_innobase: public handler
|
||||
ulong upd_and_key_val_buff_len;
|
||||
/* the length of each of the previous
|
||||
two buffers */
|
||||
ulong int_table_flags;
|
||||
Table_flags int_table_flags;
|
||||
uint primary_key;
|
||||
ulong start_of_scan; /* this is set to 1 when we are
|
||||
starting a table scan but have not
|
||||
@@ -70,6 +73,11 @@ class ha_innobase: public handler
|
||||
int change_active_index(uint keynr);
|
||||
int general_fetch(uchar* buf, uint direction, uint match_mode);
|
||||
int innobase_read_and_init_auto_inc(longlong* ret);
|
||||
ulong innobase_autoinc_lock();
|
||||
ulong innobase_set_max_autoinc(ulonglong auto_inc);
|
||||
ulong innobase_reset_autoinc(ulonglong auto_inc);
|
||||
ulong innobase_get_auto_increment(ulonglong* value);
|
||||
dict_index_t* innobase_get_index(uint keynr);
|
||||
|
||||
/* Init values for the class: */
|
||||
public:
|
||||
@@ -84,7 +92,7 @@ class ha_innobase: public handler
|
||||
const char* table_type() const { return("InnoDB");}
|
||||
const char *index_type(uint key_number) { return "BTREE"; }
|
||||
const char** bas_ext() const;
|
||||
ulonglong table_flags() const { return int_table_flags; }
|
||||
Table_flags table_flags() const;
|
||||
ulong index_flags(uint idx, uint part, bool all_parts) const {
|
||||
return(HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER
|
||||
| HA_READ_RANGE | HA_KEYREAD_ONLY);
|
||||
@@ -191,6 +199,52 @@ class ha_innobase: public handler
|
||||
uint table_changes);
|
||||
};
|
||||
|
||||
/* Some accessor functions which the InnoDB plugin needs, but which
|
||||
can not be added to mysql/plugin.h as part of the public interface;
|
||||
the definitions are bracketed with #ifdef INNODB_COMPATIBILITY_HOOKS */
|
||||
|
||||
#ifndef INNODB_COMPATIBILITY_HOOKS
|
||||
#error InnoDB needs MySQL to be built with #define INNODB_COMPATIBILITY_HOOKS
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
struct charset_info_st *thd_charset(MYSQL_THD thd);
|
||||
char **thd_query(MYSQL_THD thd);
|
||||
|
||||
/** Get the file name of the MySQL binlog.
|
||||
* @return the name of the binlog file
|
||||
*/
|
||||
const char* mysql_bin_log_file_name(void);
|
||||
|
||||
/** Get the current position of the MySQL binlog.
|
||||
* @return byte offset from the beginning of the binlog
|
||||
*/
|
||||
ulonglong mysql_bin_log_file_pos(void);
|
||||
|
||||
/**
|
||||
Check if a user thread is a replication slave thread
|
||||
@param thd user thread
|
||||
@retval 0 the user thread is not a replication slave thread
|
||||
@retval 1 the user thread is a replication slave thread
|
||||
*/
|
||||
int thd_slave_thread(const MYSQL_THD thd);
|
||||
|
||||
/**
|
||||
Check if a user thread is running a non-transactional update
|
||||
@param thd user thread
|
||||
@retval 0 the user thread is not running a non-transactional update
|
||||
@retval 1 the user thread is running a non-transactional update
|
||||
*/
|
||||
int thd_non_transactional_update(const MYSQL_THD thd);
|
||||
|
||||
/**
|
||||
Get the user thread's binary logging format
|
||||
@param thd user thread
|
||||
@return Value to be used as index into the binlog_format_names array
|
||||
*/
|
||||
int thd_binlog_format(const MYSQL_THD thd);
|
||||
}
|
||||
|
||||
/*
|
||||
don't delete it - it may be re-enabled later
|
||||
as an optimization for the most common case InnoDB+binlog
|
||||
|
||||
@@ -382,11 +382,11 @@ of dropping from the buffer pool. NOTE: does not reserve the buffer pool
|
||||
mutex. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
buf_block_peek_if_too_old(
|
||||
/*======================*/
|
||||
buf_page_peek_if_too_old(
|
||||
/*=====================*/
|
||||
/* out: TRUE if should be made
|
||||
younger */
|
||||
const buf_block_t* block); /* in: block to make younger */
|
||||
const buf_page_t* bpage); /* in: block to make younger */
|
||||
/************************************************************************
|
||||
Returns the current state of is_hashed of a page. FALSE if the page is
|
||||
not in the pool. NOTE that this operation does not fix the page in the
|
||||
|
||||
@@ -41,15 +41,15 @@ of dropping from the buffer pool. NOTE: does not reserve the buffer pool
|
||||
mutex. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
buf_block_peek_if_too_old(
|
||||
/*======================*/
|
||||
buf_page_peek_if_too_old(
|
||||
/*=====================*/
|
||||
/* out: TRUE if should be made
|
||||
younger */
|
||||
const buf_block_t* block) /* in: block to make younger */
|
||||
const buf_page_t* bpage) /* in: block to make younger */
|
||||
{
|
||||
return(buf_pool->freed_page_clock
|
||||
>= buf_block_get_freed_page_clock(block)
|
||||
+ 1 + (buf_pool->curr_size / 1024));
|
||||
>= buf_page_get_freed_page_clock(bpage)
|
||||
+ 1 + (buf_pool->curr_size / 4));
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
||||
@@ -164,6 +164,13 @@ dict_col_name_is_reserved(
|
||||
/* out: TRUE if name is reserved */
|
||||
const char* name); /* in: column name */
|
||||
/************************************************************************
|
||||
Acquire the autoinc lock.*/
|
||||
|
||||
void
|
||||
dict_table_autoinc_lock(
|
||||
/*====================*/
|
||||
dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Initializes the autoinc counter. It is not an error to initialize an already
|
||||
initialized counter. */
|
||||
|
||||
@@ -173,22 +180,6 @@ dict_table_autoinc_initialize(
|
||||
dict_table_t* table, /* in: table */
|
||||
ib_longlong value); /* in: next value to assign to a row */
|
||||
/************************************************************************
|
||||
Gets the next autoinc value (== autoinc counter value), 0 if not yet
|
||||
initialized. If initialized, increments the counter by 1. */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_get(
|
||||
/*===================*/
|
||||
/* out: value for a new row, or 0 */
|
||||
dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Decrements the autoinc counter value by 1. */
|
||||
|
||||
void
|
||||
dict_table_autoinc_decrement(
|
||||
/*=========================*/
|
||||
dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Reads the next autoinc value (== autoinc counter value), 0 if not yet
|
||||
initialized. */
|
||||
|
||||
@@ -198,15 +189,6 @@ dict_table_autoinc_read(
|
||||
/* out: value for a new row, or 0 */
|
||||
dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Peeks the autoinc counter value, 0 if not yet initialized. Does not
|
||||
increment the counter. The read not protected by any mutex! */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_peek(
|
||||
/*====================*/
|
||||
/* out: value of the counter */
|
||||
dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Updates the autoinc counter if the value supplied is equal or bigger than the
|
||||
current value. If not inited, does nothing. */
|
||||
|
||||
@@ -216,6 +198,13 @@ dict_table_autoinc_update(
|
||||
|
||||
dict_table_t* table, /* in: table */
|
||||
ib_longlong value); /* in: value which was assigned to a row */
|
||||
/************************************************************************
|
||||
Release the autoinc lock.*/
|
||||
|
||||
void
|
||||
dict_table_autoinc_unlock(
|
||||
/*======================*/
|
||||
dict_table_t* table); /* in: table */
|
||||
/**************************************************************************
|
||||
Adds system columns to a table object. */
|
||||
|
||||
|
||||
@@ -433,6 +433,10 @@ struct dict_table_struct{
|
||||
SELECT MAX(auto inc column) */
|
||||
ib_longlong autoinc;/* autoinc counter value to give to the
|
||||
next inserted row */
|
||||
ib_longlong autoinc_increment;
|
||||
/* The increment step of the auto increment
|
||||
column. Value must be greater than or equal
|
||||
to 1 */
|
||||
/*----------------------*/
|
||||
UT_LIST_BASE_NODE_T(row_prebuilt_t) prebuilts;
|
||||
/* base node for the prebuilts defined
|
||||
|
||||
@@ -257,7 +257,7 @@ will be able to insert new data to the database without running out the
|
||||
tablespace. Only free extents are taken into account and we also subtract
|
||||
the safety margin required by the above function fsp_reserve_free_extents. */
|
||||
|
||||
ulint
|
||||
ullint
|
||||
fsp_get_available_space_in_free_extents(
|
||||
/*====================================*/
|
||||
/* out: available space in kB */
|
||||
|
||||
52
include/lock0iter.h
Normal file
52
include/lock0iter.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/******************************************************
|
||||
Lock queue iterator type and function prototypes.
|
||||
|
||||
(c) 2007 Innobase Oy
|
||||
|
||||
Created July 16, 2007 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#ifndef lock0iter_h
|
||||
#define lock0iter_h
|
||||
|
||||
#include "univ.i"
|
||||
#include "lock0types.h"
|
||||
|
||||
typedef struct lock_queue_iterator_struct {
|
||||
const lock_t* current_lock;
|
||||
/* In case this is a record lock queue (not table lock queue)
|
||||
then bit_no is the record number within the heap in which the
|
||||
record is stored. */
|
||||
ulint bit_no;
|
||||
} lock_queue_iterator_t;
|
||||
|
||||
/***********************************************************************
|
||||
Initialize lock queue iterator so that it starts to iterate from
|
||||
"lock". bit_no specifies the record number within the heap where the
|
||||
record is stored. It can be undefined (ULINT_UNDEFINED) in two cases:
|
||||
1. If the lock is a table lock, thus we have a table lock queue;
|
||||
2. If the lock is a record lock and it is a wait lock. In this case
|
||||
bit_no is calculated in this function by using
|
||||
lock_rec_find_set_bit(). There is exactly one bit set in the bitmap
|
||||
of a wait lock. */
|
||||
|
||||
void
|
||||
lock_queue_iterator_reset(
|
||||
/*======================*/
|
||||
lock_queue_iterator_t* iter, /* out: iterator */
|
||||
const lock_t* lock, /* in: lock to start from */
|
||||
ulint bit_no);/* in: record number in the
|
||||
heap */
|
||||
|
||||
/***********************************************************************
|
||||
Gets the previous lock in the lock queue, returns NULL if there are no
|
||||
more locks (i.e. the current lock is the first one). The iterator is
|
||||
receded (if not-NULL is returned). */
|
||||
|
||||
const lock_t*
|
||||
lock_queue_iterator_get_prev(
|
||||
/*=========================*/
|
||||
/* out: previous lock or NULL */
|
||||
lock_queue_iterator_t* iter); /* in/out: iterator */
|
||||
|
||||
#endif /* lock0iter_h */
|
||||
@@ -597,6 +597,19 @@ lock_is_table_exclusive(
|
||||
dict_table_t* table, /* in: table */
|
||||
trx_t* trx); /* in: transaction */
|
||||
/*************************************************************************
|
||||
Checks if a lock request lock1 has to wait for request lock2. */
|
||||
|
||||
ibool
|
||||
lock_has_to_wait(
|
||||
/*=============*/
|
||||
/* out: TRUE if lock1 has to wait for
|
||||
lock2 to be removed */
|
||||
const lock_t* lock1, /* in: waiting lock */
|
||||
const lock_t* lock2); /* in: another lock; NOTE that it is
|
||||
assumed that this has a lock bit set
|
||||
on the same record as in lock1 if the
|
||||
locks are record locks */
|
||||
/*************************************************************************
|
||||
Checks that a transaction id is sensible, i.e., not in the future. */
|
||||
|
||||
ibool
|
||||
|
||||
101
include/lock0priv.h
Normal file
101
include/lock0priv.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/******************************************************
|
||||
Lock module internal structures and methods.
|
||||
|
||||
(c) 2007 Innobase Oy
|
||||
|
||||
Created July 12, 2007 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#ifndef lock0priv_h
|
||||
#define lock0priv_h
|
||||
|
||||
#ifndef LOCK_MODULE_IMPLEMENTATION
|
||||
/* If you need to access members of the structures defined in this
|
||||
file, please write appropriate functions that retrieve them and put
|
||||
those functions in lock/ */
|
||||
#error Do not include lock0priv.h outside of the lock/ module
|
||||
#endif
|
||||
|
||||
#include "univ.i"
|
||||
#include "dict0types.h"
|
||||
#include "hash0hash.h"
|
||||
#include "trx0types.h"
|
||||
#include "ut0lst.h"
|
||||
|
||||
/* A table lock */
|
||||
typedef struct lock_table_struct lock_table_t;
|
||||
struct lock_table_struct {
|
||||
dict_table_t* table; /* database table in dictionary
|
||||
cache */
|
||||
UT_LIST_NODE_T(lock_t)
|
||||
locks; /* list of locks on the same
|
||||
table */
|
||||
};
|
||||
|
||||
/* Record lock for a page */
|
||||
typedef struct lock_rec_struct lock_rec_t;
|
||||
struct lock_rec_struct {
|
||||
ulint space; /* space id */
|
||||
ulint page_no; /* page number */
|
||||
ulint n_bits; /* number of bits in the lock
|
||||
bitmap; NOTE: the lock bitmap is
|
||||
placed immediately after the
|
||||
lock struct */
|
||||
};
|
||||
|
||||
/* Lock struct */
|
||||
struct lock_struct {
|
||||
trx_t* trx; /* transaction owning the
|
||||
lock */
|
||||
UT_LIST_NODE_T(lock_t)
|
||||
trx_locks; /* list of the locks of the
|
||||
transaction */
|
||||
ulint type_mode; /* lock type, mode, LOCK_GAP or
|
||||
LOCK_REC_NOT_GAP,
|
||||
LOCK_INSERT_INTENTION,
|
||||
wait flag, ORed */
|
||||
hash_node_t hash; /* hash chain node for a record
|
||||
lock */
|
||||
dict_index_t* index; /* index for a record lock */
|
||||
union {
|
||||
lock_table_t tab_lock;/* table lock */
|
||||
lock_rec_t rec_lock;/* record lock */
|
||||
} un_member;
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
Gets the type of a lock. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
lock_get_type(
|
||||
/*==========*/
|
||||
/* out: LOCK_TABLE or LOCK_REC */
|
||||
const lock_t* lock); /* in: lock */
|
||||
|
||||
/**************************************************************************
|
||||
Looks for a set bit in a record lock bitmap. Returns ULINT_UNDEFINED,
|
||||
if none found. */
|
||||
|
||||
ulint
|
||||
lock_rec_find_set_bit(
|
||||
/*==================*/
|
||||
/* out: bit index == heap number of
|
||||
the record, or ULINT_UNDEFINED if none found */
|
||||
const lock_t* lock); /* in: record lock with at least one bit set */
|
||||
|
||||
/*************************************************************************
|
||||
Gets the previous record lock set on a record. */
|
||||
|
||||
const lock_t*
|
||||
lock_rec_get_prev(
|
||||
/*==============*/
|
||||
/* out: previous lock on the same
|
||||
record, NULL if none exists */
|
||||
const lock_t* in_lock,/* in: record lock */
|
||||
ulint heap_no);/* in: heap number of the record */
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "lock0priv.ic"
|
||||
#endif
|
||||
|
||||
#endif /* lock0priv_h */
|
||||
32
include/lock0priv.ic
Normal file
32
include/lock0priv.ic
Normal file
@@ -0,0 +1,32 @@
|
||||
/******************************************************
|
||||
Lock module internal inline methods.
|
||||
|
||||
(c) 2007 Innobase Oy
|
||||
|
||||
Created July 16, 2007 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
/* This file contains only methods which are used in
|
||||
lock/lock0* files, other than lock/lock0lock.c.
|
||||
I.e. lock/lock0lock.c contains more internal inline
|
||||
methods but they are used only in that file. */
|
||||
|
||||
#ifndef LOCK_MODULE_IMPLEMENTATION
|
||||
#error Do not include lock0priv.ic outside of the lock/ module
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
Gets the type of a lock. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
lock_get_type(
|
||||
/*==========*/
|
||||
/* out: LOCK_TABLE or LOCK_REC */
|
||||
const lock_t* lock) /* in: lock */
|
||||
{
|
||||
ut_ad(lock);
|
||||
|
||||
return(lock->type_mode & LOCK_TYPE_MASK);
|
||||
}
|
||||
|
||||
/* vim: set filetype=c: */
|
||||
@@ -766,6 +766,7 @@ struct row_prebuilt_struct {
|
||||
to this heap */
|
||||
mem_heap_t* old_vers_heap; /* memory heap where a previous
|
||||
version is built in consistent read */
|
||||
ulonglong last_value; /* last value of AUTO-INC interval */
|
||||
UT_LIST_NODE_T(row_prebuilt_t) prebuilts;
|
||||
/* list node of table->prebuilts */
|
||||
ulint magic_n2; /* this should be the same as
|
||||
|
||||
@@ -171,7 +171,17 @@ row_search_check_if_query_cache_permitted(
|
||||
trx_t* trx, /* in: transaction object */
|
||||
const char* norm_name); /* in: concatenation of database name,
|
||||
'/' char, table name */
|
||||
/***********************************************************************
|
||||
Read the max AUTOINC value from an index. */
|
||||
|
||||
ulint
|
||||
row_search_max_autoinc(
|
||||
/*===================*/
|
||||
/* out: DB_SUCCESS if all OK else
|
||||
error code */
|
||||
dict_index_t* index, /* in: index to search */
|
||||
const char* col_name, /* in: autoinc column name */
|
||||
ib_longlong* value); /* out: AUTOINC value read */
|
||||
|
||||
/* A structure for caching column values for prefetched rows */
|
||||
struct sel_buf_struct{
|
||||
|
||||
@@ -694,6 +694,9 @@ struct trx_struct{
|
||||
trx_undo_arr_t* undo_no_arr; /* array of undo numbers of undo log
|
||||
records which are currently processed
|
||||
by a rollback operation */
|
||||
ulint n_autoinc_rows; /* no. of AUTO-INC rows required for
|
||||
an SQL statement. This is useful for
|
||||
multi-row INSERTs */
|
||||
/*------------------------------*/
|
||||
char detailed_error[256]; /* detailed error message for last
|
||||
error, or empty. */
|
||||
|
||||
@@ -231,6 +231,8 @@ typedef longlong ib_longlong;
|
||||
typedef ulonglong ib_uint64_t;
|
||||
#endif
|
||||
|
||||
typedef unsigned long long int ullint;
|
||||
|
||||
#ifndef __WIN__
|
||||
#if SIZEOF_LONG != SIZEOF_VOIDP
|
||||
#error "Error: InnoDB's ulint must be of the same size as void*"
|
||||
|
||||
90
lock/lock0iter.c
Normal file
90
lock/lock0iter.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/******************************************************
|
||||
Lock queue iterator. Can iterate over table and record
|
||||
lock queues.
|
||||
|
||||
(c) 2007 Innobase Oy
|
||||
|
||||
Created July 16, 2007 Vasil Dimov
|
||||
*******************************************************/
|
||||
|
||||
#define LOCK_MODULE_IMPLEMENTATION
|
||||
|
||||
#include "univ.i"
|
||||
#include "lock0iter.h"
|
||||
#include "lock0lock.h"
|
||||
#include "lock0priv.h"
|
||||
#include "ut0dbg.h"
|
||||
#include "ut0lst.h"
|
||||
|
||||
/***********************************************************************
|
||||
Initialize lock queue iterator so that it starts to iterate from
|
||||
"lock". bit_no specifies the record number within the heap where the
|
||||
record is stored. It can be undefined (ULINT_UNDEFINED) in two cases:
|
||||
1. If the lock is a table lock, thus we have a table lock queue;
|
||||
2. If the lock is a record lock and it is a wait lock. In this case
|
||||
bit_no is calculated in this function by using
|
||||
lock_rec_find_set_bit(). There is exactly one bit set in the bitmap
|
||||
of a wait lock. */
|
||||
|
||||
void
|
||||
lock_queue_iterator_reset(
|
||||
/*======================*/
|
||||
lock_queue_iterator_t* iter, /* out: iterator */
|
||||
const lock_t* lock, /* in: lock to start from */
|
||||
ulint bit_no) /* in: record number in the
|
||||
heap */
|
||||
{
|
||||
iter->current_lock = lock;
|
||||
|
||||
if (bit_no != ULINT_UNDEFINED) {
|
||||
|
||||
iter->bit_no = bit_no;
|
||||
} else {
|
||||
|
||||
switch (lock_get_type(lock)) {
|
||||
case LOCK_TABLE:
|
||||
iter->bit_no = ULINT_UNDEFINED;
|
||||
break;
|
||||
case LOCK_REC:
|
||||
iter->bit_no = lock_rec_find_set_bit(lock);
|
||||
ut_a(iter->bit_no != ULINT_UNDEFINED);
|
||||
break;
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Gets the previous lock in the lock queue, returns NULL if there are no
|
||||
more locks (i.e. the current lock is the first one). The iterator is
|
||||
receded (if not-NULL is returned). */
|
||||
|
||||
const lock_t*
|
||||
lock_queue_iterator_get_prev(
|
||||
/*=========================*/
|
||||
/* out: previous lock or NULL */
|
||||
lock_queue_iterator_t* iter) /* in/out: iterator */
|
||||
{
|
||||
const lock_t* prev_lock;
|
||||
|
||||
switch (lock_get_type(iter->current_lock)) {
|
||||
case LOCK_REC:
|
||||
prev_lock = lock_rec_get_prev(
|
||||
iter->current_lock, iter->bit_no);
|
||||
break;
|
||||
case LOCK_TABLE:
|
||||
prev_lock = UT_LIST_GET_PREV(
|
||||
un_member.tab_lock.locks, iter->current_lock);
|
||||
break;
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
if (prev_lock != NULL) {
|
||||
|
||||
iter->current_lock = prev_lock;
|
||||
}
|
||||
|
||||
return(prev_lock);
|
||||
}
|
||||
@@ -6,10 +6,14 @@ The transaction lock system
|
||||
Created 5/7/1996 Heikki Tuuri
|
||||
*******************************************************/
|
||||
|
||||
#define LOCK_MODULE_IMPLEMENTATION
|
||||
|
||||
#include "lock0lock.h"
|
||||
#include "lock0priv.h"
|
||||
|
||||
#ifdef UNIV_NONINL
|
||||
#include "lock0lock.ic"
|
||||
#include "lock0priv.ic"
|
||||
#endif
|
||||
|
||||
#include "usr0sess.h"
|
||||
@@ -373,42 +377,6 @@ lock_rec_validate_page(
|
||||
/* The lock system */
|
||||
lock_sys_t* lock_sys = NULL;
|
||||
|
||||
/* A table lock */
|
||||
typedef struct lock_table_struct lock_table_t;
|
||||
struct lock_table_struct{
|
||||
dict_table_t* table; /* database table in dictionary cache */
|
||||
UT_LIST_NODE_T(lock_t)
|
||||
locks; /* list of locks on the same table */
|
||||
};
|
||||
|
||||
/* Record lock for a page */
|
||||
typedef struct lock_rec_struct lock_rec_t;
|
||||
struct lock_rec_struct{
|
||||
ulint space; /* space id */
|
||||
ulint page_no; /* page number */
|
||||
ulint n_bits; /* number of bits in the lock bitmap */
|
||||
/* NOTE: the lock bitmap is placed immediately
|
||||
after the lock struct */
|
||||
};
|
||||
|
||||
/* Lock struct */
|
||||
struct lock_struct{
|
||||
trx_t* trx; /* transaction owning the lock */
|
||||
UT_LIST_NODE_T(lock_t)
|
||||
trx_locks; /* list of the locks of the
|
||||
transaction */
|
||||
ulint type_mode; /* lock type, mode, LOCK_GAP or
|
||||
LOCK_REC_NOT_GAP,
|
||||
LOCK_INSERT_INTENTION,
|
||||
wait flag, ORed */
|
||||
hash_node_t hash; /* hash chain node for a record lock */
|
||||
dict_index_t* index; /* index for a record lock */
|
||||
union {
|
||||
lock_table_t tab_lock;/* table lock */
|
||||
lock_rec_t rec_lock;/* record lock */
|
||||
} un_member;
|
||||
};
|
||||
|
||||
/* We store info on the latest deadlock error to this buffer. InnoDB
|
||||
Monitor will then fetch it and print */
|
||||
ibool lock_deadlock_found = FALSE;
|
||||
@@ -454,20 +422,6 @@ lock_deadlock_recursive(
|
||||
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
|
||||
return LOCK_VICTIM_IS_START */
|
||||
|
||||
/*************************************************************************
|
||||
Gets the type of a lock. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
lock_get_type(
|
||||
/*==========*/
|
||||
/* out: LOCK_TABLE or LOCK_REC */
|
||||
const lock_t* lock) /* in: lock */
|
||||
{
|
||||
ut_ad(lock);
|
||||
|
||||
return(lock->type_mode & LOCK_TYPE_MASK);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Gets the nth bit of a record lock. */
|
||||
UNIV_INLINE
|
||||
@@ -1021,7 +975,7 @@ lock_rec_has_to_wait(
|
||||
|
||||
/*************************************************************************
|
||||
Checks if a lock request lock1 has to wait for request lock2. */
|
||||
static
|
||||
|
||||
ibool
|
||||
lock_has_to_wait(
|
||||
/*=============*/
|
||||
@@ -1095,7 +1049,7 @@ lock_rec_set_nth_bit(
|
||||
/**************************************************************************
|
||||
Looks for a set bit in a record lock bitmap. Returns ULINT_UNDEFINED,
|
||||
if none found. */
|
||||
static
|
||||
|
||||
ulint
|
||||
lock_rec_find_set_bit(
|
||||
/*==================*/
|
||||
@@ -1359,7 +1313,7 @@ lock_rec_copy(
|
||||
|
||||
/*************************************************************************
|
||||
Gets the previous record lock set on a record. */
|
||||
static
|
||||
|
||||
const lock_t*
|
||||
lock_rec_get_prev(
|
||||
/*==============*/
|
||||
|
||||
213
log/log0recv.c
213
log/log0recv.c
@@ -58,6 +58,16 @@ ibool recv_needed_recovery = FALSE;
|
||||
|
||||
ibool recv_lsn_checks_on = FALSE;
|
||||
|
||||
/* There are two conditions under which we scan the logs, the first
|
||||
is normal startup and the second is when we do a recovery from an
|
||||
archive.
|
||||
This flag is set if we are doing a scan from the last checkpoint during
|
||||
startup. If we find log entries that were written after the last checkpoint
|
||||
we know that the server was not cleanly shutdown. We must then initialize
|
||||
the crash recovery environment before attempting to store these entries in
|
||||
the log hash table. */
|
||||
ibool recv_log_scan_is_startup_type = FALSE;
|
||||
|
||||
/* 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
|
||||
the log record hash table becomes too full, and log records must be merged
|
||||
@@ -100,6 +110,16 @@ the recovery failed and the database may be corrupt. */
|
||||
|
||||
ib_uint64_t recv_max_page_lsn;
|
||||
|
||||
/* prototypes */
|
||||
|
||||
/***********************************************************
|
||||
Initialize crash recovery environment. Can be called iff
|
||||
recv_needed_recovery == FALSE. */
|
||||
static
|
||||
void
|
||||
recv_init_crash_recovery(void);
|
||||
/*===========================*/
|
||||
|
||||
/************************************************************
|
||||
Creates the recovery system. */
|
||||
|
||||
@@ -2339,6 +2359,20 @@ recv_scan_log_recs(
|
||||
|
||||
if (scanned_lsn > recv_sys->scanned_lsn) {
|
||||
|
||||
/* We have found more entries. If this scan is
|
||||
of startup type, we must initiate crash recovery
|
||||
environment before parsing these log records. */
|
||||
|
||||
if (recv_log_scan_is_startup_type
|
||||
&& !recv_needed_recovery) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Log scan progressed"
|
||||
" past the checkpoint lsn %llu\n",
|
||||
recv_sys->scanned_lsn);
|
||||
recv_init_crash_recovery();
|
||||
}
|
||||
|
||||
/* We were able to find more log data: add it to the
|
||||
parsing buffer if parse_start_lsn is already
|
||||
non-zero */
|
||||
@@ -2460,6 +2494,47 @@ recv_group_scan_log_recs(
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
Initialize crash recovery environment. Can be called iff
|
||||
recv_needed_recovery == FALSE. */
|
||||
static
|
||||
void
|
||||
recv_init_crash_recovery(void)
|
||||
/*==========================*/
|
||||
{
|
||||
ut_a(!recv_needed_recovery);
|
||||
|
||||
recv_needed_recovery = TRUE;
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
" InnoDB: Database was not"
|
||||
" shut down normally!\n"
|
||||
"InnoDB: Starting crash recovery.\n");
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Reading tablespace information"
|
||||
" from the .ibd files...\n");
|
||||
|
||||
fil_load_single_table_tablespaces();
|
||||
|
||||
/* If we are using the doublewrite method, we will
|
||||
check if there are half-written pages in data files,
|
||||
and restore them from the doublewrite buffer if
|
||||
possible */
|
||||
|
||||
if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Restoring possible"
|
||||
" half-written data pages from"
|
||||
" the doublewrite\n"
|
||||
"InnoDB: buffer...\n");
|
||||
trx_sys_doublewrite_init_or_restore_pages(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Recovers from a checkpoint. When this function returns, the database is able
|
||||
to start processing of new user transactions, but the function
|
||||
@@ -2589,81 +2664,6 @@ recv_recovery_from_checkpoint_start(
|
||||
recv_sys->recovered_lsn = checkpoint_lsn;
|
||||
|
||||
srv_start_lsn = checkpoint_lsn;
|
||||
|
||||
/* NOTE: we always do a 'recovery' at startup, but only if
|
||||
there is something wrong we will print a message to the
|
||||
user about recovery: */
|
||||
|
||||
if (checkpoint_lsn != max_flushed_lsn
|
||||
|| checkpoint_lsn != min_flushed_lsn) {
|
||||
|
||||
if (checkpoint_lsn < max_flushed_lsn) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: #########################"
|
||||
"#################################\n"
|
||||
"InnoDB: "
|
||||
"WARNING!\n"
|
||||
"InnoDB: The log sequence number"
|
||||
" in ibdata files is higher\n"
|
||||
"InnoDB: than the log sequence number"
|
||||
" in the ib_logfiles! Are you sure\n"
|
||||
"InnoDB: you are using the right"
|
||||
" ib_logfiles to start up"
|
||||
" the database?\n"
|
||||
"InnoDB: Log sequence number in"
|
||||
" ib_logfiles is %llu, log\n"
|
||||
"InnoDB: sequence numbers stamped"
|
||||
" to ibdata file headers are between\n"
|
||||
"InnoDB: %llu and %llu.\n"
|
||||
"InnoDB: #########################"
|
||||
"#################################\n",
|
||||
checkpoint_lsn,
|
||||
min_flushed_lsn,
|
||||
max_flushed_lsn);
|
||||
}
|
||||
|
||||
recv_needed_recovery = TRUE;
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
" InnoDB: Database was not"
|
||||
" shut down normally!\n"
|
||||
"InnoDB: Starting crash recovery.\n");
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Reading tablespace information"
|
||||
" from the .ibd files...\n");
|
||||
|
||||
fil_load_single_table_tablespaces();
|
||||
|
||||
/* If we are using the doublewrite method, we will
|
||||
check if there are half-written pages in data files,
|
||||
and restore them from the doublewrite buffer if
|
||||
possible */
|
||||
|
||||
if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Restoring possible"
|
||||
" half-written data pages from"
|
||||
" the doublewrite\n"
|
||||
"InnoDB: buffer...\n");
|
||||
trx_sys_doublewrite_init_or_restore_pages(
|
||||
TRUE);
|
||||
}
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
" InnoDB: Starting log scan"
|
||||
" based on checkpoint at\n"
|
||||
"InnoDB: log sequence number %llu.\n",
|
||||
checkpoint_lsn);
|
||||
} else {
|
||||
/* Init the doublewrite buffer memory structure */
|
||||
trx_sys_doublewrite_init_or_restore_pages(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
contiguous_lsn = ut_uint64_align_down(recv_sys->scanned_lsn,
|
||||
@@ -2713,6 +2713,8 @@ recv_recovery_from_checkpoint_start(
|
||||
group = UT_LIST_GET_NEXT(log_groups, group);
|
||||
}
|
||||
|
||||
/* Set the flag to publish that we are doing startup scan. */
|
||||
recv_log_scan_is_startup_type = (type == LOG_CHECKPOINT);
|
||||
while (group) {
|
||||
old_scanned_lsn = recv_sys->scanned_lsn;
|
||||
|
||||
@@ -2734,6 +2736,57 @@ recv_recovery_from_checkpoint_start(
|
||||
group = UT_LIST_GET_NEXT(log_groups, group);
|
||||
}
|
||||
|
||||
/* Done with startup scan. Clear the flag. */
|
||||
recv_log_scan_is_startup_type = FALSE;
|
||||
if (type == LOG_CHECKPOINT) {
|
||||
/* NOTE: we always do a 'recovery' at startup, but only if
|
||||
there is something wrong we will print a message to the
|
||||
user about recovery: */
|
||||
|
||||
if (checkpoint_lsn != max_flushed_lsn
|
||||
|| checkpoint_lsn != min_flushed_lsn) {
|
||||
|
||||
if (checkpoint_lsn < max_flushed_lsn) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: #########################"
|
||||
"#################################\n"
|
||||
"InnoDB: "
|
||||
"WARNING!\n"
|
||||
"InnoDB: The log sequence number"
|
||||
" in ibdata files is higher\n"
|
||||
"InnoDB: than the log sequence number"
|
||||
" in the ib_logfiles! Are you sure\n"
|
||||
"InnoDB: you are using the right"
|
||||
" ib_logfiles to start up"
|
||||
" the database?\n"
|
||||
"InnoDB: Log sequence number in"
|
||||
" ib_logfiles is %llu, log\n"
|
||||
"InnoDB: sequence numbers stamped"
|
||||
" to ibdata file headers are between\n"
|
||||
"InnoDB: %llu and %llu.\n"
|
||||
"InnoDB: #########################"
|
||||
"#################################\n",
|
||||
checkpoint_lsn,
|
||||
min_flushed_lsn,
|
||||
max_flushed_lsn);
|
||||
}
|
||||
|
||||
if (!recv_needed_recovery) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: The log sequence number"
|
||||
" in ibdata files does not match\n"
|
||||
"InnoDB: the log sequence number"
|
||||
" in the ib_logfiles!\n");
|
||||
recv_init_crash_recovery();
|
||||
}
|
||||
}
|
||||
|
||||
if (!recv_needed_recovery) {
|
||||
/* Init the doublewrite buffer memory structure */
|
||||
trx_sys_doublewrite_init_or_restore_pages(FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* We currently have only one log group */
|
||||
if (group_scanned_lsn < checkpoint_lsn) {
|
||||
ut_print_timestamp(stderr);
|
||||
@@ -2786,15 +2839,7 @@ recv_recovery_from_checkpoint_start(
|
||||
recv_synchronize_groups(up_to_date_group);
|
||||
|
||||
if (!recv_needed_recovery) {
|
||||
if (checkpoint_lsn != recv_sys->recovered_lsn) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Warning: we did not need to do"
|
||||
" crash recovery, but log scan\n"
|
||||
"InnoDB: progressed past the checkpoint"
|
||||
" lsn %llu up to lsn %llu\n",
|
||||
checkpoint_lsn,
|
||||
recv_sys->recovered_lsn);
|
||||
}
|
||||
ut_a(checkpoint_lsn == recv_sys->recovered_lsn);
|
||||
} else {
|
||||
srv_start_lsn = recv_sys->recovered_lsn;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
disable_query_log;
|
||||
--require r/true.require
|
||||
select support = 'Enabled' as `TRUE` from information_schema.engines where engine = 'innodb';
|
||||
select (support = 'YES' or support = 'DEFAULT') as `TRUE` from information_schema.engines where engine = 'innodb';
|
||||
enable_query_log;
|
||||
|
||||
@@ -501,7 +501,7 @@ ERROR 23000: Duplicate entry 'test2' for key 'ggid'
|
||||
select * from t1;
|
||||
id ggid email passwd
|
||||
1 this will work
|
||||
3 test2 this will work
|
||||
4 test2 this will work
|
||||
select * from t1 where id=1;
|
||||
id ggid email passwd
|
||||
1 this will work
|
||||
@@ -1086,6 +1086,39 @@ n d
|
||||
1 30
|
||||
2 20
|
||||
drop table t1,t2;
|
||||
CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL auto_increment,
|
||||
`b` int(11) default NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
|
||||
CREATE TABLE `t2` (
|
||||
`a` int(11) NOT NULL auto_increment,
|
||||
`b` int(11) default NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=INNODB DEFAULT CHARSET=latin1 ;
|
||||
insert into t1 values (1,1),(2,2);
|
||||
insert into t2 values (1,1),(4,4);
|
||||
reset master;
|
||||
UPDATE t2,t1 SET t2.a=t1.a+2;
|
||||
ERROR 23000: Duplicate entry '3' for key 'PRIMARY'
|
||||
select * from t2 /* must be (3,1), (4,4) */;
|
||||
a b
|
||||
1 1
|
||||
4 4
|
||||
show master status /* there must no UPDATE in binlog */;
|
||||
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||
master-bin.000001 106
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
insert into t1 values (1,2),(3,4),(4,4);
|
||||
insert into t2 values (1,2),(3,4),(4,4);
|
||||
reset master;
|
||||
UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a;
|
||||
ERROR 23000: Duplicate entry '4' for key 'PRIMARY'
|
||||
show master status /* there must be no UPDATE query event */;
|
||||
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||
master-bin.000001 106
|
||||
drop table t1, t2;
|
||||
create table t1 (a int, b int) engine=innodb;
|
||||
insert into t1 values(20,null);
|
||||
select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
|
||||
@@ -1607,7 +1640,7 @@ t2 CREATE TABLE `t2` (
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
drop table t2;
|
||||
create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb;
|
||||
ERROR HY000: Can't create table 'test.t2' (errno: 150)
|
||||
ERROR 42000: Incorrect foreign key definition for 't1_id_fk': Key reference and table reference don't match
|
||||
create table t2 (a int auto_increment primary key, b int, index(b), foreign key (b) references t1(id), unique(b)) engine=innodb;
|
||||
show create table t2;
|
||||
Table Create Table
|
||||
@@ -1632,30 +1665,6 @@ t2 CREATE TABLE `t2` (
|
||||
CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1
|
||||
drop table t2, t1;
|
||||
flush status;
|
||||
show status like "binlog_cache_use";
|
||||
Variable_name Value
|
||||
Binlog_cache_use 0
|
||||
show status like "binlog_cache_disk_use";
|
||||
Variable_name Value
|
||||
Binlog_cache_disk_use 0
|
||||
create table t1 (a int) engine=innodb;
|
||||
show status like "binlog_cache_use";
|
||||
Variable_name Value
|
||||
Binlog_cache_use 1
|
||||
show status like "binlog_cache_disk_use";
|
||||
Variable_name Value
|
||||
Binlog_cache_disk_use 1
|
||||
begin;
|
||||
delete from t1;
|
||||
commit;
|
||||
show status like "binlog_cache_use";
|
||||
Variable_name Value
|
||||
Binlog_cache_use 2
|
||||
show status like "binlog_cache_disk_use";
|
||||
Variable_name Value
|
||||
Binlog_cache_disk_use 1
|
||||
drop table t1;
|
||||
create table t1 (c char(10), index (c,c)) engine=innodb;
|
||||
ERROR 42S21: Duplicate column name 'c'
|
||||
create table t1 (c1 char(10), c2 char(10), index (c1,c2,c1)) engine=innodb;
|
||||
@@ -1775,13 +1784,13 @@ Variable_name Value
|
||||
Innodb_page_size 16384
|
||||
show status like "Innodb_rows_deleted";
|
||||
Variable_name Value
|
||||
Innodb_rows_deleted 2070
|
||||
Innodb_rows_deleted 72
|
||||
show status like "Innodb_rows_inserted";
|
||||
Variable_name Value
|
||||
Innodb_rows_inserted 3083
|
||||
Innodb_rows_inserted 1088
|
||||
show status like "Innodb_rows_updated";
|
||||
Variable_name Value
|
||||
Innodb_rows_updated 886
|
||||
Innodb_rows_updated 888
|
||||
show status like "Innodb_row_lock_waits";
|
||||
Variable_name Value
|
||||
Innodb_row_lock_waits 0
|
||||
|
||||
@@ -13,6 +13,11 @@
|
||||
|
||||
-- source include/not_embedded.inc
|
||||
-- source include/have_innodb.inc
|
||||
-- source include/have_log_bin.inc
|
||||
|
||||
# Disabling it temporarily for statement-based logging since some
|
||||
# tests are not safe while binlog is on.
|
||||
-- source include/have_binlog_format_mixed_or_row.inc
|
||||
|
||||
#
|
||||
# Small basic test with ignore
|
||||
@@ -53,7 +58,7 @@ INSERT INTO t1 VALUES (1,0,0),(3,1,1),(4,1,1),(8,2,2),(9,2,2),(17,3,2),(22,4,2),
|
||||
update t1 set parent_id=parent_id+100;
|
||||
select * from t1 where parent_id=102;
|
||||
update t1 set id=id+1000;
|
||||
-- error ER_DUP_ENTRY_WITH_KEY_NAME,1022
|
||||
-- error ER_DUP_ENTRY,1022
|
||||
update t1 set id=1024 where id=1009;
|
||||
select * from t1;
|
||||
update ignore t1 set id=id+1; # This will change all rows
|
||||
@@ -134,13 +139,13 @@ commit;
|
||||
select n, "after commit" from t1;
|
||||
commit;
|
||||
insert into t1 values (5);
|
||||
-- error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
-- error ER_DUP_ENTRY
|
||||
insert into t1 values (4);
|
||||
commit;
|
||||
select n, "after commit" from t1;
|
||||
set autocommit=1;
|
||||
insert into t1 values (6);
|
||||
-- error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
-- error ER_DUP_ENTRY
|
||||
insert into t1 values (4);
|
||||
select n from t1;
|
||||
set autocommit=0;
|
||||
@@ -214,7 +219,7 @@ drop table t1;
|
||||
|
||||
CREATE TABLE t1 (id char(8) not null primary key, val int not null) engine=innodb;
|
||||
insert into t1 values ('pippo', 12);
|
||||
-- error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
-- error ER_DUP_ENTRY
|
||||
insert into t1 values ('pippo', 12); # Gives error
|
||||
delete from t1;
|
||||
delete from t1 where id = 'pippo';
|
||||
@@ -342,9 +347,9 @@ CREATE TABLE t1 (
|
||||
|
||||
insert into t1 (ggid,passwd) values ('test1','xxx');
|
||||
insert into t1 (ggid,passwd) values ('test2','yyy');
|
||||
-- error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
-- error ER_DUP_ENTRY
|
||||
insert into t1 (ggid,passwd) values ('test2','this will fail');
|
||||
-- error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
-- error ER_DUP_ENTRY
|
||||
insert into t1 (ggid,id) values ('this will fail',1);
|
||||
|
||||
select * from t1 where ggid='test1';
|
||||
@@ -353,7 +358,7 @@ select * from t1 where id=2;
|
||||
|
||||
replace into t1 (ggid,id) values ('this will work',1);
|
||||
replace into t1 (ggid,passwd) values ('test2','this will work');
|
||||
-- error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
-- error ER_DUP_ENTRY
|
||||
update t1 set id=100,ggid='test2' where id=1;
|
||||
select * from t1;
|
||||
select * from t1 where id=1;
|
||||
@@ -524,7 +529,7 @@ drop table t1;
|
||||
create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(30),primary key (id,id2),index index_id3 (id3)) engine=innodb;
|
||||
insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
|
||||
LOCK TABLES t1 WRITE;
|
||||
--error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
--error ER_DUP_ENTRY
|
||||
insert into t1 values (99,1,2,'D'),(1,1,2,'D');
|
||||
select id from t1;
|
||||
select id from t1;
|
||||
@@ -535,7 +540,7 @@ create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(3
|
||||
insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
|
||||
LOCK TABLES t1 WRITE;
|
||||
begin;
|
||||
--error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
--error ER_DUP_ENTRY
|
||||
insert into t1 values (99,1,2,'D'),(1,1,2,'D');
|
||||
select id from t1;
|
||||
insert ignore into t1 values (100,1,2,'D'),(1,1,99,'D');
|
||||
@@ -754,6 +759,45 @@ select * from t1;
|
||||
select * from t2;
|
||||
drop table t1,t2;
|
||||
|
||||
#
|
||||
# Bug#27716 multi-update did partially and has not binlogged
|
||||
#
|
||||
|
||||
CREATE TABLE `t1` (
|
||||
`a` int(11) NOT NULL auto_increment,
|
||||
`b` int(11) default NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
|
||||
|
||||
CREATE TABLE `t2` (
|
||||
`a` int(11) NOT NULL auto_increment,
|
||||
`b` int(11) default NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=INNODB DEFAULT CHARSET=latin1 ;
|
||||
|
||||
# A. testing multi_update::send_eof() execution branch
|
||||
insert into t1 values (1,1),(2,2);
|
||||
insert into t2 values (1,1),(4,4);
|
||||
reset master;
|
||||
--error ER_DUP_ENTRY
|
||||
UPDATE t2,t1 SET t2.a=t1.a+2;
|
||||
# check
|
||||
select * from t2 /* must be (3,1), (4,4) */;
|
||||
show master status /* there must no UPDATE in binlog */;
|
||||
|
||||
# B. testing multi_update::send_error() execution branch
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
insert into t1 values (1,2),(3,4),(4,4);
|
||||
insert into t2 values (1,2),(3,4),(4,4);
|
||||
reset master;
|
||||
--error ER_DUP_ENTRY
|
||||
UPDATE t2,t1 SET t2.a=t2.b where t2.a=t1.a;
|
||||
show master status /* there must be no UPDATE query event */;
|
||||
|
||||
# cleanup bug#27716
|
||||
drop table t1, t2;
|
||||
|
||||
#
|
||||
# Testing of IFNULL
|
||||
#
|
||||
@@ -1134,7 +1178,7 @@ drop table t2;
|
||||
# Clean up filename -- embedded server reports whole path without .frm,
|
||||
# regular server reports relative path with .frm (argh!)
|
||||
--replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t2.frm t2
|
||||
--error 1005
|
||||
--error ER_WRONG_FK_DEF
|
||||
create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb;
|
||||
|
||||
# bug#3749
|
||||
@@ -1147,41 +1191,6 @@ show create table t2;
|
||||
drop table t2, t1;
|
||||
|
||||
|
||||
#
|
||||
# Let us test binlog_cache_use and binlog_cache_disk_use status vars.
|
||||
# Actually this test has nothing to do with innodb per se, it just requires
|
||||
# transactional table.
|
||||
#
|
||||
flush status;
|
||||
show status like "binlog_cache_use";
|
||||
show status like "binlog_cache_disk_use";
|
||||
|
||||
create table t1 (a int) engine=innodb;
|
||||
|
||||
# Now we are going to create transaction which is long enough so its
|
||||
# transaction binlog will be flushed to disk...
|
||||
let $1=2000;
|
||||
disable_query_log;
|
||||
begin;
|
||||
while ($1)
|
||||
{
|
||||
eval insert into t1 values( $1 );
|
||||
dec $1;
|
||||
}
|
||||
commit;
|
||||
enable_query_log;
|
||||
show status like "binlog_cache_use";
|
||||
show status like "binlog_cache_disk_use";
|
||||
|
||||
# Transaction which should not be flushed to disk and so should not
|
||||
# increase binlog_cache_disk_use.
|
||||
begin;
|
||||
delete from t1;
|
||||
commit;
|
||||
show status like "binlog_cache_use";
|
||||
show status like "binlog_cache_disk_use";
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Bug #6126: Duplicate columns in keys gives misleading error message
|
||||
#
|
||||
@@ -1408,7 +1417,7 @@ create table t1 (rowid int not null auto_increment, val int not null,primary
|
||||
key (rowid), unique(val)) engine=innodb;
|
||||
replace into t1 (val) values ('1'),('2');
|
||||
replace into t1 (val) values ('1'),('2');
|
||||
--error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
--error ER_DUP_ENTRY
|
||||
insert into t1 (val) values ('1'),('2');
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
@@ -1421,7 +1430,7 @@ create table t1 (a int not null auto_increment primary key, val int) engine=Inno
|
||||
insert into t1 (val) values (1);
|
||||
update t1 set a=2 where a=1;
|
||||
# We should get the following error because InnoDB does not update the counter
|
||||
--error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
--error ER_DUP_ENTRY
|
||||
insert into t1 (val) values (1);
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
@@ -1744,13 +1753,13 @@ create table t3 (s1 varchar(2) binary,primary key (s1)) engine=innodb;
|
||||
create table t4 (s1 char(2) binary,primary key (s1)) engine=innodb;
|
||||
|
||||
insert into t1 values (0x41),(0x4120),(0x4100);
|
||||
-- error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
-- error ER_DUP_ENTRY
|
||||
insert into t2 values (0x41),(0x4120),(0x4100);
|
||||
insert into t2 values (0x41),(0x4120);
|
||||
-- error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
-- error ER_DUP_ENTRY
|
||||
insert into t3 values (0x41),(0x4120),(0x4100);
|
||||
insert into t3 values (0x41),(0x4100);
|
||||
-- error ER_DUP_ENTRY_WITH_KEY_NAME
|
||||
-- error ER_DUP_ENTRY
|
||||
insert into t4 values (0x41),(0x4120),(0x4100);
|
||||
insert into t4 values (0x41),(0x4100);
|
||||
select hex(s1) from t1;
|
||||
|
||||
@@ -10,12 +10,18 @@
|
||||
|
||||
SET storage_engine=InnoDB;
|
||||
|
||||
# we do not really care about what gets output-ed, we are only
|
||||
# we do not really care about what gets printed, we are only
|
||||
# interested in getting the deadlock resolved according to our
|
||||
# expectations
|
||||
-- disable_query_log
|
||||
-- disable_result_log
|
||||
|
||||
# we want to use "-- eval statement1; statement2" which does not work with
|
||||
# prepared statements. Because this test should not behave differently with
|
||||
# or without prepared statements we disable them so the test does not fail
|
||||
# if someone runs ./mysql-test-run.pl --ps-protocol
|
||||
-- disable_ps_protocol
|
||||
|
||||
-- disable_warnings
|
||||
DROP TABLE IF EXISTS t1, t2, t3, t4, t5_nontrans;
|
||||
-- enable_warnings
|
||||
|
||||
@@ -456,10 +456,9 @@ os_file_handle_error_no_exit(
|
||||
|
||||
#undef USE_FILE_LOCK
|
||||
#define USE_FILE_LOCK
|
||||
#if defined(UNIV_HOTBACKUP) || defined(__WIN__) || defined(__FreeBSD__) || defined(__NETWARE__)
|
||||
#if defined(UNIV_HOTBACKUP) || defined(__WIN__) || defined(__NETWARE__)
|
||||
/* InnoDB Hot Backup does not lock the data files.
|
||||
* On Windows, mandatory locking is used.
|
||||
* On FreeBSD with LinuxThreads, advisory locking does not work properly.
|
||||
*/
|
||||
# undef USE_FILE_LOCK
|
||||
#endif
|
||||
|
||||
2
plug.in
2
plug.in
@@ -3,7 +3,6 @@ MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine],
|
||||
MYSQL_PLUGIN_DIRECTORY(innobase, [storage/innobase])
|
||||
MYSQL_PLUGIN_STATIC(innobase, [libinnobase.a])
|
||||
MYSQL_PLUGIN_DYNAMIC(innobase, [ha_innodb.la])
|
||||
MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(innobase, [handler/ha_innodb.cc])
|
||||
MYSQL_PLUGIN_ACTIONS(innobase, [
|
||||
AC_CHECK_LIB(rt, aio_read, [innodb_system_libs="-lrt"])
|
||||
AC_SUBST(innodb_system_libs)
|
||||
@@ -41,5 +40,4 @@ MYSQL_PLUGIN_ACTIONS(innobase, [
|
||||
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
|
||||
esac
|
||||
])
|
||||
MYSQL_PLUGIN_DEPENDS_ON_MYSQL_INTERNALS(innobase, [handler/ha_innodb.cc])
|
||||
|
||||
|
||||
@@ -3143,6 +3143,8 @@ next_rec:
|
||||
dict_table_change_id_in_cache(table, new_id);
|
||||
}
|
||||
|
||||
/* MySQL calls ha_innobase::reset_auto_increment() which does
|
||||
the same thing. */
|
||||
dict_table_autoinc_initialize(table, 0);
|
||||
dict_update_statistics(table);
|
||||
|
||||
|
||||
166
row/row0sel.c
166
row/row0sel.c
@@ -4577,3 +4577,169 @@ row_search_check_if_query_cache_permitted(
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Read the AUTOINC column from the current row. */
|
||||
static
|
||||
ib_longlong
|
||||
row_search_autoinc_read_column(
|
||||
/*===========================*/
|
||||
/* out: value read from the column */
|
||||
dict_index_t* index, /* in: index to read from */
|
||||
const rec_t* rec, /* in: current rec */
|
||||
ulint col_no, /* in: column number */
|
||||
ibool unsigned_type) /* in: signed or unsigned flag */
|
||||
{
|
||||
ulint len;
|
||||
byte* ptr;
|
||||
const byte* data;
|
||||
ib_longlong value;
|
||||
mem_heap_t* heap = NULL;
|
||||
byte dest[sizeof(value)];
|
||||
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
||||
ulint* offsets = offsets_;
|
||||
|
||||
*offsets_ = sizeof offsets_ / sizeof *offsets_;
|
||||
|
||||
/* TODO: We have to cast away the const of rec for now. This needs
|
||||
to be fixed later.*/
|
||||
offsets = rec_get_offsets(
|
||||
(rec_t*) rec, index, offsets, ULINT_UNDEFINED, &heap);
|
||||
|
||||
/* TODO: We have to cast away the const of rec for now. This needs
|
||||
to be fixed later.*/
|
||||
data = rec_get_nth_field((rec_t*)rec, offsets, col_no, &len);
|
||||
|
||||
ut_a(len != UNIV_SQL_NULL);
|
||||
ut_a(len <= sizeof value);
|
||||
|
||||
/* Convert integer data from Innobase to a little-endian format,
|
||||
sign bit restored to normal */
|
||||
|
||||
for (ptr = dest + len; ptr != dest; ++data) {
|
||||
--ptr;
|
||||
*ptr = *data;
|
||||
}
|
||||
|
||||
if (!unsigned_type) {
|
||||
dest[len - 1] ^= 128;
|
||||
}
|
||||
|
||||
/* The assumption here is that the AUTOINC value can't be negative.*/
|
||||
switch (len) {
|
||||
case 8:
|
||||
value = *(ib_longlong*) ptr;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
value = *(ib_uint32_t*) ptr;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
value = *(uint16 *) ptr;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
value = *ptr;
|
||||
break;
|
||||
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
ut_a(value >= 0);
|
||||
|
||||
return(value);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Get the last row. */
|
||||
static
|
||||
const rec_t*
|
||||
row_search_autoinc_get_rec(
|
||||
/*=======================*/
|
||||
/* out: current rec or NULL */
|
||||
btr_pcur_t* pcur, /* in: the current cursor */
|
||||
mtr_t* mtr) /* in: mini transaction */
|
||||
{
|
||||
do {
|
||||
const rec_t* rec = btr_pcur_get_rec(pcur);
|
||||
|
||||
if (page_rec_is_user_rec(rec)) {
|
||||
return(rec);
|
||||
}
|
||||
} while (btr_pcur_move_to_prev(pcur, mtr));
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
Read the max AUTOINC value from an index. */
|
||||
|
||||
ulint
|
||||
row_search_max_autoinc(
|
||||
/*===================*/
|
||||
/* out: DB_SUCCESS if all OK else
|
||||
error code, DB_RECORD_NOT_FOUND if
|
||||
column name can't be found in index */
|
||||
dict_index_t* index, /* in: index to search */
|
||||
const char* col_name, /* in: name of autoinc column */
|
||||
ib_longlong* value) /* out: AUTOINC value read */
|
||||
{
|
||||
ulint i;
|
||||
ulint n_cols;
|
||||
dict_field_t* dfield = NULL;
|
||||
ulint error = DB_SUCCESS;
|
||||
|
||||
n_cols = dict_index_get_n_ordering_defined_by_user(index);
|
||||
|
||||
/* Search the index for the AUTOINC column name */
|
||||
for (i = 0; i < n_cols; ++i) {
|
||||
dfield = dict_index_get_nth_field(index, i);
|
||||
|
||||
if (strcmp(col_name, dfield->name) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*value = 0;
|
||||
|
||||
/* Must find the AUTOINC column name */
|
||||
if (i < n_cols && dfield) {
|
||||
mtr_t mtr;
|
||||
btr_pcur_t pcur;
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
/* Open at the high/right end (FALSE), and INIT
|
||||
cursor (TRUE) */
|
||||
btr_pcur_open_at_index_side(
|
||||
FALSE, index, BTR_SEARCH_LEAF, &pcur, TRUE, &mtr);
|
||||
|
||||
if (page_get_n_recs(btr_pcur_get_page(&pcur)) > 0) {
|
||||
const rec_t* rec;
|
||||
|
||||
rec = row_search_autoinc_get_rec(&pcur, &mtr);
|
||||
|
||||
if (rec != NULL) {
|
||||
ibool unsigned_type = (
|
||||
dfield->col->prtype & DATA_UNSIGNED);
|
||||
|
||||
*value = row_search_autoinc_read_column(
|
||||
index, rec, i, unsigned_type);
|
||||
}
|
||||
}
|
||||
|
||||
btr_pcur_close(&pcur);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
} else {
|
||||
error = DB_RECORD_NOT_FOUND;
|
||||
}
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
@@ -15,16 +15,34 @@ Created 9/11/1995 Heikki Tuuri
|
||||
#include "mem0mem.h"
|
||||
#include "srv0srv.h"
|
||||
|
||||
/* number of system calls made during shared latching */
|
||||
ulint rw_s_system_call_count = 0;
|
||||
|
||||
/* number of spin waits on rw-latches,
|
||||
resulted during shared (read) locks */
|
||||
ulint rw_s_spin_wait_count = 0;
|
||||
|
||||
/* number of OS waits on rw-latches,
|
||||
resulted during shared (read) locks */
|
||||
ulint rw_s_os_wait_count = 0;
|
||||
|
||||
/* number of unlocks (that unlock shared locks),
|
||||
set only when UNIV_SYNC_PERF_STAT is defined */
|
||||
ulint rw_s_exit_count = 0;
|
||||
|
||||
/* number of system calls made during exclusive latching */
|
||||
ulint rw_x_system_call_count = 0;
|
||||
|
||||
/* number of spin waits on rw-latches,
|
||||
resulted during exclusive (write) locks */
|
||||
ulint rw_x_spin_wait_count = 0;
|
||||
|
||||
/* number of OS waits on rw-latches,
|
||||
resulted during exclusive (write) locks */
|
||||
ulint rw_x_os_wait_count = 0;
|
||||
|
||||
/* number of unlocks (that unlock exclusive locks),
|
||||
set only when UNIV_SYNC_PERF_STAT is defined */
|
||||
ulint rw_x_exit_count = 0;
|
||||
|
||||
/* The global list of rw-locks */
|
||||
|
||||
@@ -115,6 +115,7 @@ ulint mutex_system_call_count = 0;
|
||||
|
||||
/* Number of spin waits on mutexes: for performance monitoring */
|
||||
|
||||
/* round=one iteration of a spin loop */
|
||||
ulint mutex_spin_round_count = 0;
|
||||
ulint mutex_spin_wait_count = 0;
|
||||
ulint mutex_os_wait_count = 0;
|
||||
|
||||
@@ -182,6 +182,8 @@ trx_create(
|
||||
memset(&trx->xid, 0, sizeof(trx->xid));
|
||||
trx->xid.formatID = -1;
|
||||
|
||||
trx->n_autoinc_rows = 0;
|
||||
|
||||
trx_reset_new_rec_lock_info(trx);
|
||||
|
||||
return(trx);
|
||||
|
||||
Reference in New Issue
Block a user