Merge with 4.0.13

This commit is contained in:
monty@narttu.mysql.fi 2003-05-19 16:35:49 +03:00
commit dd2b7918cd
317 changed files with 6662 additions and 3466 deletions

View File

@ -38,7 +38,11 @@ COPYING.LIB
Docs/#manual.texi#
Docs/INSTALL-BINARY
Docs/include.texi
Docs/internals.html
Docs/internals.info
Docs/internals.pdf
Docs/internals.txt
Docs/internals_toc.html
Docs/manual.aux
Docs/manual.cp
Docs/manual.cps
@ -239,6 +243,7 @@ client/select_test
client/ssl_test
client/thimble
client/thread_test
client_test
cmd-line-utils/libedit/common.h
comon.h
config.cache
@ -287,6 +292,7 @@ innobase/conftest.subs
innobase/ib_config.h
innobase/ib_config.h.in
innobase/stamp-h1
insert_test
isam/isamchk
isam/isamlog
isam/pack_isam
@ -513,6 +519,7 @@ scripts/mysqld_safe
scripts/mysqldumpslow
scripts/mysqlhotcopy
scripts/safe_mysqld
select_test
sql-bench/Results-linux/ATIS-mysql_bdb-Linux_2.2.14_my_SMP_i686
sql-bench/bench-count-distinct
sql-bench/bench-init.pl
@ -578,6 +585,7 @@ strings/ctype_autoconf.c
strings/ctype_extra_sources.c
support-files/MacOSX/Description.plist
support-files/MacOSX/Info.plist
support-files/MacOSX/ReadMe.txt
support-files/MacOSX/StartupParameters.plist
support-files/MacOSX/postinstall
support-files/MacOSX/preinstall
@ -597,6 +605,7 @@ support-files/mysql.spec
tags
test_xml
tests/client_test
thread_test
tmp/*
tools/my_vsnprintf.c
tools/mysqlmanager
@ -607,7 +616,3 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
client_test
thread_test
select_test
insert_test

View File

@ -71,4 +71,6 @@ else
make=make
fi
CXX=gcc
if test -z $CXX ; then
CXX=gcc
fi

View File

@ -51,6 +51,7 @@ miguel@hegel.br
miguel@hegel.local
miguel@light.
miguel@light.local
mmatthew@markslaptop.
monty@bitch.mysql.fi
monty@butch.
monty@donna.mysql.fi
@ -67,6 +68,7 @@ mwagner@cash.mwagner.org
mwagner@evoq.mwagner.org
mwagner@work.mysql.com
mysql@home.(none)
mysqldev@build.mysql2.com
nick@mysql.com
nick@nick.leippe.com
papa@gbichot.local
@ -75,6 +77,7 @@ paul@teton.kitebird.com
pem@mysql.com
peter@linux.local
peter@mysql.com
peterg@mysql.com
pgulutzan@linux.local
ram@gw.udmsearch.izhnet.ru
ram@mysql.r18.ru

View File

@ -276,7 +276,11 @@ if ($opt_stage <= 3)
my $flags= "";
log_timestamp();
log_system("rm -fr mysql-3* mysql-4* $pwd/$host/*.tar.gz");
log_system("nm -n sql/mysqld | gzip -9 -v 2>&1 > sql/mysqld.sym.gz | cat");
# No need to add the debug symbols, if the binaries are not stripped (saves space)
unless ($opt_with_debug || $opt_no_strip)
{
log_system("nm -n sql/mysqld | gzip -9 -v 2>&1 > sql/mysqld.sym.gz | cat");
}
$flags.= "--no-strip" if ($opt_no_strip || $opt_with_debug);
check_system("scripts/make_binary_distribution --tmp=$opt_tmp --suffix=$opt_suffix $flags",".tar.gz created");

View File

@ -27,7 +27,7 @@ EXTRA_DIST = $(noinst_SCRIPTS) $(BUILT_SOURCES) mysqld_error.txt \
all: $(targets) txt_files
txt_files: ../INSTALL-SOURCE ../COPYING ../COPYING.LIB \
INSTALL-BINARY
INSTALL-BINARY ../support-files/MacOSX/ReadMe.txt
CLEAN_FILES: $(BUILD_SOURCES)
touch $(BUILD_SOURCES)
@ -254,5 +254,8 @@ INSTALL-BINARY: mysql.info $(GT)
../COPYING.LIB: mysql.info $(GT)
perl -w $(GT) mysql.info "LGPL license" "Function Index" > $@
../support-files/MacOSX/ReadMe.txt: mysql.info $(GT)
perl -w $(GT) mysql.info "Mac OS X installation" "Netware installation" > $@
# Don't update the files from bitkeeper
%::SCCS/s.%

File diff suppressed because it is too large Load Diff

9
Docs/manual_toc.html Normal file
View File

@ -0,0 +1,9 @@
<html>
<head>
<title>Place holder for manual_toc.html</title>
</head>
<body>
This is just a place holder for the autogenerated manual_toc.html
to make "make dist" happy.
</body>
</html>

View File

@ -1 +0,0 @@
logo_nusphere_b.tif

View File

@ -25,7 +25,7 @@ CFG=libmysql - Win32 Debug
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
CPP=xicl6.exe
MTL=midl.exe
RSC=rc.exe
@ -52,7 +52,7 @@ RSC=rc.exe
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
LINK32=xilink6.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386
# ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /machine:I386 /def:"libmysql.def" /out:"..\lib_release\libmysql.dll" /libpath:"." /libpath:"..\lib_release"
# SUBTRACT LINK32 /pdb:none
@ -85,7 +85,7 @@ PostBuild_Cmds=xcopy release\libmysql.lib ..\lib_release /y
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
LINK32=xilink6.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 zlib.lib wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /dll /incremental:no /map /debug /machine:I386 /def:"libmysql.def" /out:"..\lib_debug\libmysql.dll" /pdbtype:sept /libpath:"." /libpath:"..\lib_debug"
# SUBTRACT LINK32 /pdb:none
@ -251,6 +251,10 @@ SOURCE=..\mysys\mf_pack.c
# End Source File
# Begin Source File
SOURCE=..\mysys\mf_path.c
# End Source File
# Begin Source File
SOURCE=..\mysys\mf_unixpath.c
# End Source File
# Begin Source File

View File

@ -605,6 +605,9 @@ Package=<5>
Package=<4>
{{{
Begin Project Dependency
Project_Dep_Name strings
End Project Dependency
}}}
###############################################################################

View File

@ -78,7 +78,7 @@ AC_LANG_SAVE
AC_LANG_CPLUSPLUS
if test "$ac_cv_prog_gxx" = "yes"
then
CXXFLAGS="$CXXFLAGS -Werror"
CXXFLAGS=`echo $CXXFLAGS -Werror | sed 's/-fbranch-probabilities//'`
fi
mysql_cv_btype_last_arg_accept=none
[AC_TRY_COMPILE([#if defined(inline)

View File

@ -1091,7 +1091,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
{ // Add found char to buffer
if (inchar == *in_string)
*in_string=0;
else if (!*in_string && (inchar == '\'' || inchar == '"'))
else if (!*in_string && (inchar == '\'' || inchar == '"' || inchar == '`'))
*in_string=(char) inchar;
if (!(*ml_comment))
*out++ = (char) inchar;
@ -2709,31 +2709,32 @@ select_limit, max_join_size);
static int
put_info(const char *str,INFO_TYPE info_type,uint error)
{
FILE *file= (info_type == INFO_ERROR ? stderr : stdout);
static int inited=0;
if (status.batch)
{
if (info_type == INFO_ERROR)
{
(void) fflush(stdout);
fprintf(stderr,"ERROR");
(void) fflush(file);
fprintf(file,"ERROR");
if (error)
(void) fprintf(stderr," %d",error);
(void) fprintf(file," %d",error);
if (status.query_start_line && line_numbers)
{
(void) fprintf(stderr," at line %lu",status.query_start_line);
(void) fprintf(file," at line %lu",status.query_start_line);
if (status.file_name)
(void) fprintf(stderr," in file: '%s'", status.file_name);
(void) fprintf(file," in file: '%s'", status.file_name);
}
(void) fprintf(stderr,": %s\n",str);
(void) fflush(stderr);
(void) fprintf(file,": %s\n",str);
(void) fflush(file);
if (!ignore_errors)
return 1;
}
else if (info_type == INFO_RESULT && verbose > 1)
tee_puts(str, stdout);
tee_puts(str, file);
if (unbuffered)
fflush(stdout);
fflush(file);
return info_type == INFO_ERROR ? -1 : 0;
}
if (!opt_silent || info_type == INFO_ERROR)
@ -2751,17 +2752,17 @@ put_info(const char *str,INFO_TYPE info_type,uint error)
putchar('\007'); /* This should make a bell */
vidattr(A_STANDOUT);
if (error)
(void) tee_fprintf(stderr, "ERROR %d: ", error);
(void) tee_fprintf(file, "ERROR %d: ", error);
else
tee_puts("ERROR: ", stdout);
tee_puts("ERROR: ", file);
}
else
vidattr(A_BOLD);
(void) tee_puts(str, stdout);
(void) tee_puts(str, file);
vidattr(A_NORMAL);
}
if (unbuffered)
fflush(stdout);
fflush(file);
return info_type == INFO_ERROR ? -1 : 0;
}

View File

@ -44,6 +44,7 @@ static const char* default_dbug_option = "d:t:o,/tmp/mysqlbinlog.trace";
void sql_print_error(const char *format, ...);
static bool one_database = 0;
static bool force_opt= 0;
static const char* database;
static bool short_form = 0;
static ulonglong offset = 0;
@ -199,6 +200,9 @@ static struct my_option my_long_options[] =
{"database", 'd', "List entries for just this database (local log only)",
(gptr*) &database, (gptr*) &database, 0, GET_STR_ALLOC, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
{"force-read", 'f', "Force reading unknown binlog events",
(gptr*) &force_opt, (gptr*) &force_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
{"help", '?', "Display this help and exit",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"host", 'h', "Get the binlog from server", (gptr*) &host, (gptr*) &host,

View File

@ -1613,7 +1613,7 @@ int main(int argc, char **argv)
else
{
row = mysql_fetch_row(master);
if (row[0] && row[1])
if (row && row[0] && row[1])
{
fprintf(md_result_file,
"\n--\n-- Position to start replication from\n--\n\n");

View File

@ -1005,8 +1005,9 @@ case $SYSTEM_TYPE in
*darwin5*)
if test "$ac_cv_prog_gcc" = "yes"
then
CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE"
CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DFN_NO_CASE_SENCE"
FLAGS="-traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE"
CFLAGS="$CFLAGS $FLAGS"
CXXFLAGS="$CXXFLAGS $FLAGS"
MAX_C_OPTIMIZE="-O"
with_named_curses=""
fi
@ -1014,8 +1015,9 @@ case $SYSTEM_TYPE in
*darwin6*)
if test "$ac_cv_prog_gcc" = "yes"
then
CFLAGS="$CFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE"
CXXFLAGS="$CXXFLAGS -traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DFN_NO_CASE_SENCE"
FLAGS="-traditional-cpp -DHAVE_DARWIN_THREADS -D_P1003_1B_VISIBLE -DSIGNAL_WITH_VIO_CLOSE -DSIGNALS_DONT_BREAK_READ -DHAVE_BROKEN_REALPATH -DFN_NO_CASE_SENCE"
CFLAGS="$CFLAGS $FLAGS"
CXXFLAGS="$CXXFLAGS $FLAGS"
MAX_C_OPTIMIZE="-O"
fi
;;
@ -1365,10 +1367,8 @@ then
with_named_thread="-Kthread -lsocket -lnsl"
if expr "$SYSTEM_TYPE" : ".*unixware7.0.0" > /dev/null
then
# AC_DEFINE(HAVE_OpenUNIX8_THREADS)
AC_DEFINE(HAVE_UNIXWARE7_THREADS)
else
# AC_DEFINE(HAVE_OpenUNIX8_POSIX)
AC_DEFINE(HAVE_UNIXWARE7_POSIX)
fi
# We must have cc
@ -1377,10 +1377,8 @@ then
then
{ echo "configure: error: On OpenUNIX8 and UnixWare7 MySQL must be compiled with cc. See the Installation chapter in the Reference Manual." 1>&2; exit 1; };
else
# CC="$CC -Kthread -DOpenUNIX8";
# CXX="$CXX -Kthread -DOpenUNIX8";
CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK"
CC="$CC -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
CXX="$CXX -Kthread -DUNIXWARE_7 -DHAVE_BROKEN_RWLOCK";
fi
AC_MSG_RESULT("yes")
else
@ -1877,7 +1875,7 @@ AC_LANG_SAVE
AC_LANG_CPLUSPLUS
if test "$ac_cv_prog_gxx" = "yes" -a "$with_other_libc" = "no"
then
CXXFLAGS="$CXXFLAGS -Werror"
CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed 's/-fbranch-probabilities//'`
fi
AC_TRY_COMPILE(
[#undef inline
@ -1909,7 +1907,7 @@ AC_LANG_SAVE
AC_LANG_CPLUSPLUS
if test "$ac_cv_prog_gxx" = "yes" -a "$with_other_libc" = "no"
then
CXXFLAGS="$CXXFLAGS -Werror"
CXXFLAGS=`echo "$CXXFLAGS -Werror" | sed 's/-fbranch-probabilities//'`
fi
AC_TRY_COMPILE(
[#undef inline

View File

@ -35,7 +35,7 @@ noinst_HEADERS = config-win.h config-os2.h config-netware.h \
SUPERCLEANFILES = mysql_version.h my_config.h
# Some include files that may be moved and patched by configure
DISTCLEANFILES = sched.h
DISTCLEANFILES = sched.h $(SUPERCLEANFILES)
clean:
$(RM) -f readline/*

View File

@ -153,6 +153,9 @@ typedef uint rf_SetTimer;
#define USE_MB_IDENT 1
#define USE_STRCOLL 1
/* If LOAD DATA LOCAL INFILE should be enabled by default */
#define ENABLED_LOCAL_INFILE 1
/* Convert some simple functions to Posix */
#define sigset(A,B) signal((A),(B))

View File

@ -225,6 +225,7 @@ enum ha_base_keytype {
/* Errorcodes given by functions */
/* opt_sum_query() assumes these codes are > 1 */
#define HA_ERR_KEY_NOT_FOUND 120 /* Didn't find key on read or update */
#define HA_ERR_FOUND_DUPP_KEY 121 /* Dupplicate key on write */
#define HA_ERR_RECORD_CHANGED 123 /* Uppdate with is recoverable */

View File

@ -287,6 +287,10 @@ C_MODE_END
#include <asm/atomic.h>
#endif
#include <errno.h> /* Recommended by debian */
/* We need the following to go around a problem with openssl on solaris */
#if defined(HAVE_CRYPT_H)
#include <crypt.h>
#endif
/* Go around some bugs in different OS and compilers */
#if defined(_HPUX_SOURCE) && defined(HAVE_SYS_STREAM_H)
@ -306,9 +310,7 @@ C_MODE_END
/* This has to be after include limits.h */
#define HAVE_ERRNO_AS_DEFINE
#define HAVE_FCNTL_LOCK
#undef HAVE_SYS_UN_H
#undef HAVE_FINITE
#undef HAVE_RINT
#undef LONGLONG_MIN /* These get wrongly defined in QNX 6.2 */
#undef LONGLONG_MAX /* standard system library 'limits.h' */
#endif
@ -377,7 +379,7 @@ typedef unsigned short ushort;
#define set_bits(type, bit_count) (sizeof(type)*8 <= (bit_count) ? ~(type) 0 : ((((type) 1) << (bit_count)) - (type) 1))
#define array_elements(A) ((uint) (sizeof(A)/sizeof(A[0])))
#ifndef HAVE_RINT
#define rint(A) floor((A)+0.5)
#define rint(A) floor((A)+(((A) < 0)? -0.5 : 0.5))
#endif
/* Define some general constants */

View File

@ -248,6 +248,11 @@ extern int my_sigwait(const sigset_t *set,int *sig);
#error Requires at least rev 2 of EMX pthreads library.
#endif
#ifdef __NETWARE__
void my_pthread_exit(void *status);
#define pthread_exit(A) my_pthread_exit(A)
#endif
extern int my_pthread_getprio(pthread_t thread_id);
#define pthread_key(T,V) pthread_key_t V

View File

@ -31,6 +31,8 @@
#ifndef _my_semaphore_h_
#define _my_semaphore_h_
#ifdef THREAD
C_MODE_START
#ifdef HAVE_SEMAPHORE_H
#include <semaphore.h>
@ -56,4 +58,7 @@ int sem_getvalue(sem_t * sem, unsigned int * sval);
#endif /* !__bsdi__ */
C_MODE_END
#endif /* THREAD */
#endif /* !_my_semaphore_h_ */

View File

@ -744,6 +744,7 @@ extern my_bool my_uncompress(byte *, ulong *, ulong *);
extern byte *my_compress_alloc(const byte *packet, ulong *len, ulong *complen);
extern ulong checksum(const byte *mem, uint count);
extern uint my_bit_log2(ulong value);
uint my_count_bits(ulonglong v);
extern void my_sleep(ulong m_seconds);
#ifdef __WIN__

View File

@ -165,7 +165,7 @@ my_bool vio_ssl_should_retry(Vio* vio);
int vio_ssl_close(Vio* vio);
/* Return last error number */
int vio_ssl_errno(Vio *vio);
my_bool vio_ssl_peer_addr(Vio* vio, char *buf);
my_bool vio_ssl_peer_addr(Vio* vio, char *buf, uint16 *port);
void vio_ssl_in_addr(Vio *vio, struct in_addr *in);
int vio_ssl_blocking(Vio * vio, my_bool set_blocking_mode, my_bool *old_mode);
@ -242,7 +242,7 @@ struct st_vio
my_bool (*is_blocking)(Vio*);
int (*viokeepalive)(Vio*, my_bool);
int (*fastsend)(Vio*);
my_bool (*peer_addr)(Vio*, gptr, uint16*);
my_bool (*peer_addr)(Vio*, char *, uint16*);
void (*in_addr)(Vio*, struct in_addr*);
my_bool (*should_retry)(Vio*);
int (*vioclose)(Vio*);

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libbtr.a
noinst_LIBRARIES = libbtr.a
libbtr_a_SOURCES = btr0btr.c btr0cur.c btr0pcur.c btr0sea.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libbuf.a
noinst_LIBRARIES = libbuf.a
libbuf_a_SOURCES = buf0buf.c buf0flu.c buf0lru.c buf0rea.c

View File

@ -597,8 +597,9 @@ buf_pool_init(
/* Wipe contents of frame to eliminate a Purify
warning */
#ifdef HAVE_purify
memset(block->frame, '\0', UNIV_PAGE_SIZE);
#endif
if (srv_use_awe) {
/* Add to the list of blocks mapped to
frames */
@ -1837,7 +1838,7 @@ buf_pool_invalidate(void)
freed = TRUE;
while (freed) {
freed = buf_LRU_search_and_free_block(0);
freed = buf_LRU_search_and_free_block(100);
}
mutex_enter(&(buf_pool->mutex));
@ -2056,6 +2057,29 @@ buf_get_n_pending_ios(void)
+ buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
}
/*************************************************************************
Returns the ratio in percents of modified pages in the buffer pool /
database pages in the buffer pool. */
ulint
buf_get_modified_ratio_pct(void)
/*============================*/
{
ulint ratio;
mutex_enter(&(buf_pool->mutex));
ratio = (100 * UT_LIST_GET_LEN(buf_pool->flush_list))
/ (1 + UT_LIST_GET_LEN(buf_pool->LRU)
+ UT_LIST_GET_LEN(buf_pool->free));
/* 1 + is there to avoid division by zero */
mutex_exit(&(buf_pool->mutex));
return(ratio);
}
/*************************************************************************
Prints info of the buffer i/o. */
@ -2109,8 +2133,10 @@ buf_print_io(
buf += sprintf(buf,
"Pending writes: LRU %lu, flush list %lu, single page %lu\n",
buf_pool->n_flush[BUF_FLUSH_LRU],
buf_pool->n_flush[BUF_FLUSH_LIST],
buf_pool->n_flush[BUF_FLUSH_LRU]
+ buf_pool->init_flush[BUF_FLUSH_LRU],
buf_pool->n_flush[BUF_FLUSH_LIST]
+ buf_pool->init_flush[BUF_FLUSH_LIST],
buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
current_time = time(NULL);
@ -2144,7 +2170,7 @@ buf_print_io(
/ (buf_pool->n_page_gets - buf_pool->n_page_gets_old)));
} else {
buf += sprintf(buf,
"No buffer pool activity since the last printout\n");
"No buffer pool page gets since the last printout\n");
}
buf_pool->n_page_gets_old = buf_pool->n_page_gets;

View File

@ -107,7 +107,7 @@ buf_flush_ready_for_replace(
BUF_BLOCK_FILE_PAGE and in the LRU list */
{
ut_ad(mutex_own(&(buf_pool->mutex)));
ut_ad(block->state == BUF_BLOCK_FILE_PAGE);
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if ((ut_dulint_cmp(block->oldest_modification, ut_dulint_zero) > 0)
|| (block->buf_fix_count != 0)
@ -227,7 +227,9 @@ buf_flush_buffered_writes(void)
}
for (i = 0; i < trx_doublewrite->first_free; i++) {
block = trx_doublewrite->buf_block_arr[i];
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if (block->check_index_page_at_flush
&& !page_simple_validate(block->frame)) {
@ -236,10 +238,12 @@ buf_flush_buffered_writes(void)
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Apparent corruption of an index page\n"
" InnoDB: Apparent corruption of an index page n:o %lu in space %lu\n"
"InnoDB: to be written to data file. We intentionally crash server\n"
"InnoDB: to prevent corrupt data from ending up in data\n"
"InnoDB: files.\n");
"InnoDB: files.\n",
block->offset, block->space);
ut_a(0);
}
}
@ -394,7 +398,7 @@ buf_flush_write_block_low(
"Warning: cannot force log to disk in the log debug version!\n");
#else
/* Force the log to the disk before writing the modified block */
log_flush_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS);
log_write_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS, TRUE);
#endif
buf_flush_init_for_writing(block->frame, block->newest_modification,
block->space, block->offset);
@ -432,6 +436,8 @@ buf_flush_try_page(
block = buf_page_hash_get(space, offset);
ut_a(block->state == BUF_BLOCK_FILE_PAGE);
if (flush_type == BUF_FLUSH_LIST
&& block && buf_flush_ready_for_flush(block, flush_type)) {
@ -567,7 +573,8 @@ buf_flush_try_page(
rw_lock_s_lock_gen(&(block->lock), BUF_IO_WRITE);
if (buf_debug_prints) {
printf("Flushing single page space %lu, page no %lu \n",
printf(
"Flushing single page space %lu, page no %lu \n",
block->space, block->offset);
}
@ -608,15 +615,7 @@ buf_flush_try_neighbors(
low = offset;
high = offset + 1;
} else if (flush_type == BUF_FLUSH_LIST) {
/* Since semaphore waits require us to flush the
doublewrite buffer to disk, it is best that the
search area is just the page itself, to minimize
chances for semaphore waits */
low = offset;
high = offset + 1;
}
}
/* printf("Flush area: low %lu high %lu\n", low, high); */
@ -633,13 +632,20 @@ buf_flush_try_neighbors(
if (block && flush_type == BUF_FLUSH_LRU && i != offset
&& !block->old) {
/* We avoid flushing 'non-old' blocks in an LRU flush,
because the flushed blocks are soon freed */
/* We avoid flushing 'non-old' blocks in an LRU flush,
because the flushed blocks are soon freed */
continue;
continue;
}
if (block && buf_flush_ready_for_flush(block, flush_type)) {
if (block && buf_flush_ready_for_flush(block, flush_type)
&& (i == offset || block->buf_fix_count == 0)) {
/* We only try to flush those neighbors != offset
where the buf fix count is zero, as we then know that
we probably can latch the page without a semaphore
wait. Semaphore waits are expensive because we must
flush the doublewrite buffer before we start
waiting. */
mutex_exit(&(buf_pool->mutex));
@ -758,7 +764,6 @@ buf_flush_batch(
page_count +=
buf_flush_try_neighbors(space, offset,
flush_type);
/* printf(
"Flush type %lu, page no %lu, neighb %lu\n",
flush_type, offset,
@ -884,11 +889,19 @@ buf_flush_free_margin(void)
/*=======================*/
{
ulint n_to_flush;
ulint n_flushed;
n_to_flush = buf_flush_LRU_recommendation();
if (n_to_flush > 0) {
buf_flush_batch(BUF_FLUSH_LRU, n_to_flush, ut_dulint_zero);
n_flushed = buf_flush_batch(BUF_FLUSH_LRU, n_to_flush,
ut_dulint_zero);
if (n_flushed == ULINT_UNDEFINED) {
/* There was an LRU type flush batch already running;
let us wait for it to end */
buf_flush_wait_batch_end(BUF_FLUSH_LRU);
}
}
}

View File

@ -104,12 +104,15 @@ ibool
buf_LRU_search_and_free_block(
/*==========================*/
/* out: TRUE if freed */
ulint n_iterations __attribute__((unused))) /* in: how many times
this has been called repeatedly without
result: a high value means that we should
search farther */
ulint n_iterations) /* in: how many times this has been called
repeatedly without result: a high value means
that we should search farther; if value is
k < 10, then we only search k/10 * [number
of pages in the buffer pool] from the end
of the LRU list */
{
buf_block_t* block;
ulint distance = 0;
ibool freed;
mutex_enter(&(buf_pool->mutex));
@ -152,6 +155,18 @@ buf_LRU_search_and_free_block(
}
block = UT_LIST_GET_PREV(LRU, block);
distance++;
if (!freed && n_iterations <= 10
&& distance > 100 + (n_iterations * buf_pool->curr_size)
/ 10) {
buf_pool->LRU_flush_ended = 0;
mutex_exit(&(buf_pool->mutex));
return(FALSE);
}
}
if (buf_pool->LRU_flush_ended > 0) {
@ -186,7 +201,7 @@ buf_LRU_try_free_flushed_blocks(void)
mutex_exit(&(buf_pool->mutex));
buf_LRU_search_and_free_block(0);
buf_LRU_search_and_free_block(1);
mutex_enter(&(buf_pool->mutex));
}
@ -208,7 +223,7 @@ buf_LRU_get_free_block(void)
{
buf_block_t* block = NULL;
ibool freed;
ulint n_iterations = 0;
ulint n_iterations = 1;
ibool mon_value_was = 0; /* remove bug */
ibool started_monitor = FALSE;
loop:
@ -236,9 +251,12 @@ loop:
fprintf(stderr,
" InnoDB: WARNING: over 4 / 5 of the buffer pool is occupied by\n"
"InnoDB: lock heaps or the adaptive hash index! Check that your\n"
"InnoDB: transactions do not set too many row locks. Starting InnoDB\n"
"InnoDB: Monitor to print diagnostics, including lock heap and hash index\n"
"InnoDB: sizes.\n");
"InnoDB: transactions do not set too many row locks.\n"
"InnoDB: Your buffer pool size is %lu MB. Maybe you should make\n"
"InnoDB: the buffer pool bigger?\n"
"InnoDB: Starting the InnoDB Monitor to print diagnostics, including\n"
"InnoDB: lock heap and hash index sizes.\n",
buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE));
srv_print_innodb_monitor = TRUE;
@ -251,14 +269,6 @@ loop:
srv_print_innodb_monitor = FALSE;
}
if (buf_pool->LRU_flush_ended > 0) {
mutex_exit(&(buf_pool->mutex));
buf_LRU_try_free_flushed_blocks();
mutex_enter(&(buf_pool->mutex));
}
/* If there is a block in the free list, take it */
if (UT_LIST_GET_LEN(buf_pool->free) > 0) {
@ -340,6 +350,20 @@ loop:
os_aio_simulated_wake_handler_threads();
mutex_enter(&(buf_pool->mutex));
if (buf_pool->LRU_flush_ended > 0) {
/* We have written pages in an LRU flush. To make the insert
buffer more efficient, we try to move these pages to the free
list. */
mutex_exit(&(buf_pool->mutex));
buf_LRU_try_free_flushed_blocks();
} else {
mutex_exit(&(buf_pool->mutex));
}
if (n_iterations > 10) {
os_thread_sleep(500000);

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libcom.a
noinst_LIBRARIES = libcom.a
libcom_a_SOURCES = com0com.c com0shm.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libdata.a
noinst_LIBRARIES = libdata.a
libdata_a_SOURCES = data0data.c data0type.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libdict.a
noinst_LIBRARIES = libdict.a
libdict_a_SOURCES = dict0boot.c dict0crea.c dict0dict.c dict0load.c\
dict0mem.c

View File

@ -1173,6 +1173,7 @@ dict_create_add_foreigns_to_dictionary(
if (NULL == dict_table_get_low((char *) "SYS_FOREIGN")) {
fprintf(stderr,
"InnoDB: table SYS_FOREIGN not found from internal data dictionary\n");
return(DB_ERROR);
}
@ -1259,6 +1260,13 @@ loop:
"InnoDB: at http://www.innodb.com/ibman.html\n");
}
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf),
" Internal error in foreign key constraint creation for table %.500s.\n"
"See the MySQL .err log in the datadir for more information.\n", table->name);
mutex_exit(&dict_foreign_err_mutex);
return(error);
}

View File

@ -185,6 +185,14 @@ dict_foreign_free(
/*==============*/
dict_foreign_t* foreign); /* in, own: foreign key struct */
/* Buffers for storing detailed information about the latest foreign key
and unique key errors */
char* dict_foreign_err_buf = NULL;
char* dict_unique_err_buf = NULL;
mutex_t dict_foreign_err_mutex; /* mutex protecting the foreign
and unique error buffers */
/************************************************************************
Checks if the database name in two table names is the same. */
static
@ -573,6 +581,13 @@ dict_init(void)
rw_lock_create(&dict_operation_lock);
rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION);
dict_foreign_err_buf = mem_alloc(DICT_FOREIGN_ERR_BUF_LEN);
dict_foreign_err_buf[0] = '\0';
dict_unique_err_buf = mem_alloc(DICT_FOREIGN_ERR_BUF_LEN);
dict_unique_err_buf[0] = '\0';
mutex_create(&dict_foreign_err_mutex);
mutex_set_level(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
}
/**************************************************************************
@ -1818,6 +1833,7 @@ dict_foreign_add_to_cache(
dict_foreign_t* for_in_cache = NULL;
dict_index_t* index;
ibool added_to_referenced_list = FALSE;
char* buf = dict_foreign_err_buf;
ut_ad(mutex_own(&(dict_sys->mutex)));
@ -1850,9 +1866,29 @@ dict_foreign_add_to_cache(
for_in_cache->foreign_index);
if (index == NULL) {
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf),
" Error in foreign key constraint of table %.500s:\n"
"there is no index in referenced table which would contain\n"
"the columns as the first columns, or the data types in the\n"
"referenced table do not match to the ones in table. Constraint:\n",
for_in_cache->foreign_table_name);
dict_print_info_on_foreign_key_in_create_format(
for_in_cache, buf + strlen(buf));
if (for_in_cache->foreign_index) {
sprintf(buf + strlen(buf),
"\nThe index in the foreign key in table is %.500s\n"
"See http://www.innodb.com/ibman.html about correct foreign key definition.\n",
for_in_cache->foreign_index->name);
}
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
if (for_in_cache == foreign) {
mem_heap_free(foreign->heap);
}
return(DB_CANNOT_ADD_CONSTRAINT);
}
@ -1871,6 +1907,25 @@ dict_foreign_add_to_cache(
for_in_cache->referenced_index);
if (index == NULL) {
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf),
" Error in foreign key constraint of table %.500s:\n"
"there is no index in the table which would contain\n"
"the columns as the first columns, or the data types in the\n"
"table do not match to the ones in the referenced table. Constraint:\n",
for_in_cache->foreign_table_name);
dict_print_info_on_foreign_key_in_create_format(
for_in_cache, buf + strlen(buf));
if (for_in_cache->foreign_index) {
sprintf(buf + strlen(buf),
"\nIndex of the foreign key in the referenced table is %.500s\n"
"See http://www.innodb.com/ibman.html about correct foreign key definition.\n",
for_in_cache->referenced_index->name);
}
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
if (for_in_cache == foreign) {
if (added_to_referenced_list) {
UT_LIST_REMOVE(referenced_list,
@ -2038,7 +2093,7 @@ dict_scan_col(
if (*ptr == '`') {
ptr++;
}
return(ptr);
}
@ -2141,18 +2196,21 @@ dict_scan_table_name(
}
/*************************************************************************
Skips one 'word', like an id. For the lexical definition of 'word', see the
code below. */
Scans an id. For the lexical definition of an 'id', see the code below.
Strips backquotes from around the id. */
static
char*
dict_skip_word(
/*===========*/
dict_scan_id(
/*=========*/
/* out: scanned to */
char* ptr, /* in: scanned to */
ibool* success)/* out: TRUE if success, FALSE if just spaces left in
string */
char** start, /* out: start of the id; NULL if no id was
scannable */
ulint* len) /* out: length of the id */
{
*success = FALSE;
ibool scanned_backquote = FALSE;
*start = NULL;
while (isspace(*ptr)) {
ptr++;
@ -2164,24 +2222,61 @@ dict_skip_word(
}
if (*ptr == '`') {
scanned_backquote = TRUE;
ptr++;
}
while (!isspace(*ptr) && *ptr != ',' && *ptr != '(' && *ptr != '`'
&& *ptr != '\0') {
*start = ptr;
while (!isspace(*ptr) && *ptr != ',' && *ptr != '(' && *ptr != ')'
&& *ptr != '\0' && *ptr != '`') {
ptr++;
}
*success = TRUE;
*len = (ulint) (ptr - *start);
if (scanned_backquote) {
if (*ptr == '`') {
ptr++;
} else {
/* Syntax error */
*start = NULL;
}
}
return(ptr);
}
/*************************************************************************
Skips one id. */
static
char*
dict_skip_word(
/*===========*/
/* out: scanned to */
char* ptr, /* in: scanned to */
ibool* success)/* out: TRUE if success, FALSE if just spaces left in
string or a syntax error */
{
char* start;
ulint len;
*success = FALSE;
ptr = dict_scan_id(ptr, &start, &len);
if (start) {
*success = TRUE;
}
return(ptr);
}
#ifdef currentlynotused
/*************************************************************************
Returns the number of opening brackets '(' subtracted by the number
of closing brackets ')' between string and ptr. */
#ifdef NOT_USED
static
int
dict_bracket_count(
@ -2206,16 +2301,116 @@ dict_bracket_count(
return(count);
}
#endif
/*************************************************************************
Removes MySQL comments from an SQL string. A comment is either
(a) '#' to the end of the line,
(b) '--<space>' to the end of the line, or
(c) '<slash><asterisk>' till the next '<asterisk><slash>' (like the familiar
C comment syntax). */
static
char*
dict_strip_comments(
/*================*/
/* out, own: SQL string stripped from
comments; the caller must free this
with mem_free()! */
char* sql_string) /* in: SQL string */
{
char* str;
char* sptr;
char* ptr;
str = mem_alloc(strlen(sql_string) + 1);
sptr = sql_string;
ptr = str;
for (;;) {
if (*sptr == '\0') {
*ptr = '\0';
return(str);
}
if (*sptr == '#'
|| (strlen(sptr) >= 3 && 0 == memcmp("-- ", sptr, 3))) {
for (;;) {
/* In Unix a newline is 0x0D while in Windows
it is 0x0A followed by 0x0D */
if (*sptr == (char)0x0A
|| *sptr == (char)0x0D
|| *sptr == '\0') {
break;
}
sptr++;
}
}
if (strlen(sptr) >= 2 && *sptr == '/' && *(sptr + 1) == '*') {
for (;;) {
if (strlen(sptr) >= 2
&& *sptr == '*' && *(sptr + 1) == '/') {
sptr += 2;
break;
}
if (*sptr == '\0') {
break;
}
sptr++;
}
}
*ptr = *sptr;
ptr++;
sptr++;
}
}
/*************************************************************************
Reports a simple foreign key create clause syntax error. */
static
void
dict_foreign_report_syntax_err(
/*===========================*/
char* name, /* in: table name */
char* start_of_latest_foreign,/* in: start of the foreign key clause
in the SQL string */
char* ptr) /* in: place of the syntax error */
{
char* buf = dict_foreign_err_buf;
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf),
" Error in foreign key constraint of table %.500s,\n%.500s.\n"
"Syntax error close to:\n%.500s\n", name, start_of_latest_foreign, ptr);
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
}
/*************************************************************************
Scans a table create SQL string and adds to the data dictionary the foreign
key constraints declared in the string. This function should be called after
the indexes for a table have been created. Each foreign key constraint must
be accompanied with indexes in both participating tables. The indexes are
allowed to contain more fields than mentioned in the constraint. */
static
ulint
dict_create_foreign_constraints(
/*============================*/
dict_create_foreign_constraints_low(
/*================================*/
/* out: error code or DB_SUCCESS */
trx_t* trx, /* in: transaction */
char* sql_string, /* in: table create or ALTER TABLE
@ -2231,7 +2426,9 @@ dict_create_foreign_constraints(
dict_table_t* referenced_table;
dict_index_t* index;
dict_foreign_t* foreign;
char* ptr = sql_string;
char* ptr = sql_string;
char* start_of_latest_foreign = sql_string;
char* buf = dict_foreign_err_buf;
ibool success;
ulint error;
ulint i;
@ -2249,6 +2446,15 @@ dict_create_foreign_constraints(
table = dict_table_get_low(name);
if (table == NULL) {
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf),
" Error in foreign key constraint of table %.500s.\n"
"Cannot find the table from the internal data dictionary of InnoDB.\n"
"Create table statement:\n%.2000\n", name, sql_string);
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
return(DB_ERROR);
}
loop:
@ -2264,6 +2470,8 @@ loop:
return(error);
}
start_of_latest_foreign = ptr;
ptr = dict_accept(ptr, (char *) "FOREIGN", &success);
if (!isspace(*ptr)) {
@ -2284,13 +2492,19 @@ loop:
ptr = dict_skip_word(ptr, &success);
if (!success) {
dict_foreign_report_syntax_err(name,
start_of_latest_foreign, ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
ptr = dict_accept(ptr, (char *) "(", &success);
if (!success) {
return(DB_CANNOT_ADD_CONSTRAINT);
/* We do not flag a syntax error here because in an
ALTER TABLE we may also have DROP FOREIGN KEY abc */
goto loop;
}
}
@ -2301,6 +2515,15 @@ col_loop1:
ptr = dict_scan_col(ptr, &success, table, columns + i,
column_names + i, column_name_lens + i);
if (!success) {
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf),
" Error in foreign key constraint of table %.500s,\n%.500s.\n"
"Cannot resolve column name close to:\n%.500s\n", name,
start_of_latest_foreign, ptr);
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@ -2315,6 +2538,8 @@ col_loop1:
ptr = dict_accept(ptr, (char *) ")", &success);
if (!success) {
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@ -2324,12 +2549,24 @@ col_loop1:
index = dict_foreign_find_index(table, column_names, i, NULL);
if (!index) {
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf),
" Error in foreign key constraint of table %.500s:\n"
"There is no index in the table %.500s where the columns appear\n"
"as the first columns. Constraint:\n%.500s\n"
"See http://www.innodb.com/ibman.html for correct foreign key definition.\n",
name, name, start_of_latest_foreign);
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
return(DB_CANNOT_ADD_CONSTRAINT);
}
ptr = dict_accept(ptr, (char *) "REFERENCES", &success);
if (!success || !isspace(*ptr)) {
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@ -2359,6 +2596,15 @@ col_loop1:
if (!success || (!referenced_table && trx->check_foreigns)) {
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf),
" Error in foreign key constraint of table %.500s,\n%.500s.\n"
"Cannot resolve table name close to:\n"
"%.500s\n", name, start_of_latest_foreign, ptr);
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@ -2366,7 +2612,8 @@ col_loop1:
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@ -2381,6 +2628,15 @@ col_loop2:
if (!success) {
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf),
" Error in foreign key constraint of table %.500s,\n%.500s\n"
"Cannot resolve column name close to:\n"
"%.500s\n", name, start_of_latest_foreign, ptr);
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@ -2395,6 +2651,8 @@ col_loop2:
if (!success || foreign->n_fields != i) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@ -2417,9 +2675,10 @@ scan_on_conditions:
ptr = dict_accept(ptr, "UPDATE", &success);
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name,
start_of_latest_foreign, ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@ -2455,6 +2714,8 @@ scan_on_conditions:
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name,
start_of_latest_foreign, ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@ -2472,7 +2733,8 @@ scan_on_conditions:
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@ -2480,7 +2742,8 @@ scan_on_conditions:
if (!success) {
dict_foreign_free(foreign);
dict_foreign_report_syntax_err(name, start_of_latest_foreign,
ptr);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@ -2494,6 +2757,15 @@ scan_on_conditions:
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf),
" Error in foreign key constraint of table %.500s,\n%.500s.\n"
"You have defined a SET NULL condition though some of the\n"
"columns is defined as NOT NULL.\n", name, start_of_latest_foreign);
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
return(DB_CANNOT_ADD_CONSTRAINT);
}
}
@ -2512,6 +2784,15 @@ try_find_index:
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf),
" Error in foreign key constraint of table %.500s,\n%.500s.\n"
"You have twice an ON DELETE clause or twice an ON UPDATE clause.\n",
name, start_of_latest_foreign);
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
return(DB_CANNOT_ADD_CONSTRAINT);
}
@ -2525,6 +2806,18 @@ try_find_index:
foreign->foreign_index);
if (!index) {
dict_foreign_free(foreign);
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf),
" Error in foreign key constraint of table %.500s:\n"
"Cannot find an index in the referenced table where the\n"
"referenced columns appear as the first columns, or column types\n"
"in the table and the referenced table do not match for constraint:\n%.500s\n"
"See http://www.innodb.com/ibman.html for correct foreign key definition.\n",
name, start_of_latest_foreign);
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
return(DB_CANNOT_ADD_CONSTRAINT);
}
} else {
@ -2565,6 +2858,165 @@ try_find_index:
goto loop;
}
/*************************************************************************
Scans a table create SQL string and adds to the data dictionary the foreign
key constraints declared in the string. This function should be called after
the indexes for a table have been created. Each foreign key constraint must
be accompanied with indexes in both participating tables. The indexes are
allowed to contain more fields than mentioned in the constraint. */
ulint
dict_create_foreign_constraints(
/*============================*/
/* out: error code or DB_SUCCESS */
trx_t* trx, /* in: transaction */
char* sql_string, /* in: table create or ALTER TABLE
statement where foreign keys are declared like:
FOREIGN KEY (a, b) REFERENCES table2(c, d),
table2 can be written also with the database
name before it: test.table2; the default
database id the database of parameter name */
char* name) /* in: table full name in the normalized form
database_name/table_name */
{
char* str;
ulint err;
str = dict_strip_comments(sql_string);
err = dict_create_foreign_constraints_low(trx, str, name);
mem_free(str);
return(err);
}
/**************************************************************************
Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */
ulint
dict_foreign_parse_drop_constraints(
/*================================*/
/* out: DB_SUCCESS or
DB_CANNOT_DROP_CONSTRAINT if
syntax error or the constraint
id does not match */
mem_heap_t* heap, /* in: heap from which we can
allocate memory */
trx_t* trx, /* in: transaction */
dict_table_t* table, /* in: table */
ulint* n, /* out: number of constraints
to drop */
char*** constraints_to_drop) /* out: id's of the
constraints to drop */
{
dict_foreign_t* foreign;
ibool success;
char* str;
char* ptr;
char* buf = dict_foreign_err_buf;
char* start;
char* id;
ulint len;
*n = 0;
*constraints_to_drop = mem_heap_alloc(heap, 1000 * sizeof(char*));
str = dict_strip_comments(*(trx->mysql_query_str));
ptr = str;
ut_ad(mutex_own(&(dict_sys->mutex)));
loop:
ptr = dict_scan_to(ptr, (char *) "DROP");
if (*ptr == '\0') {
ut_a(*n < 1000);
mem_free(str);
return(DB_SUCCESS);
}
ptr = dict_accept(ptr, (char *) "DROP", &success);
if (!isspace(*ptr)) {
goto loop;
}
ptr = dict_accept(ptr, (char *) "FOREIGN", &success);
if (!success) {
goto loop;
}
ptr = dict_accept(ptr, (char *) "KEY", &success);
if (!success) {
goto syntax_error;
}
ptr = dict_scan_id(ptr, &start, &len);
if (start == NULL) {
goto syntax_error;
}
id = mem_heap_alloc(heap, len + 1);
ut_memcpy(id, start, len);
id[len] = '\0';
(*constraints_to_drop)[*n] = id;
(*n)++;
/* Look for the given constraint id */
foreign = UT_LIST_GET_FIRST(table->foreign_list);
while (foreign != NULL) {
if (0 == ut_strcmp(foreign->id, id)) {
/* Found */
break;
}
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
if (foreign == NULL) {
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf),
" Error in dropping of a foreign key constraint of table %.500s,\n"
"just before:\n%s\n in SQL command\n%s\nCannot find a constraint with the\n"
"given id %s.\n", table->name, ptr, str, id);
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
mem_free(str);
return(DB_CANNOT_DROP_CONSTRAINT);
}
goto loop;
syntax_error:
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf),
" Syntax error in dropping of a foreign key constraint of table %.500s,\n"
"close to:\n%s\n in SQL command\n%s\n", table->name, ptr, str);
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
mem_free(str);
return(DB_CANNOT_DROP_CONSTRAINT);
}
/*==================== END OF FOREIGN KEY PROCESSING ====================*/
/**************************************************************************
@ -3286,7 +3738,6 @@ dict_index_print_low(
n_vals = index->stat_n_diff_key_vals[1];
}
printf(
" INDEX: name %s, table name %s, id %lu %lu, fields %lu/%lu, type %lu\n",
index->name, index->table_name,
@ -3327,6 +3778,99 @@ dict_field_print_low(
printf(" %s", field->name);
}
/**************************************************************************
Sprintfs to a string info on a foreign key of a table in a format suitable
for CREATE TABLE. */
char*
dict_print_info_on_foreign_key_in_create_format(
/*============================================*/
/* out: how far in buf we printed */
dict_foreign_t* foreign,/* in: foreign key constraint */
char* buf) /* in: buffer of at least 5000 bytes */
{
char* buf2 = buf;
ulint i;
buf2 += sprintf(buf2, ",\n CONSTRAINT `%s` FOREIGN KEY (",
foreign->id);
for (i = 0; i < foreign->n_fields; i++) {
if ((ulint)(buf2 - buf) >= 4000) {
goto no_space;
}
buf2 += sprintf(buf2, "`%.250s`",
foreign->foreign_col_names[i]);
if (i + 1 < foreign->n_fields) {
buf2 += sprintf(buf2, ", ");
}
}
if (dict_tables_have_same_db(foreign->foreign_table_name,
foreign->referenced_table_name)) {
/* Do not print the database name of the referenced
table */
buf2 += sprintf(buf2, ") REFERENCES `%.500s` (",
dict_remove_db_name(
foreign->referenced_table_name));
} else {
buf2 += sprintf(buf2, ") REFERENCES `%.500s` (",
foreign->referenced_table_name);
/* Change the '/' in the table name to '.' */
for (i = ut_strlen(buf); i > 0; i--) {
if (buf[i] == '/') {
buf[i] = '.';
break;
}
}
}
for (i = 0; i < foreign->n_fields; i++) {
if ((ulint)(buf2 - buf) >= 4000) {
goto no_space;
}
buf2 += sprintf(buf2, "`%.250s`",
foreign->referenced_col_names[i]);
if (i + 1 < foreign->n_fields) {
buf2 += sprintf(buf2, ", ");
}
}
buf2 += sprintf(buf2, ")");
if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
buf2 += sprintf(buf2, " ON DELETE CASCADE");
}
if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
buf2 += sprintf(buf2, " ON DELETE SET NULL");
}
if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
buf2 += sprintf(buf2, " ON DELETE NO ACTION");
}
if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
buf2 += sprintf(buf2, " ON UPDATE CASCADE");
}
if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
buf2 += sprintf(buf2, " ON UPDATE SET NULL");
}
if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
buf2 += sprintf(buf2, " ON UPDATE NO ACTION");
}
no_space:
return(buf2);
}
/**************************************************************************
Sprintfs to a string info on foreign keys of a table in a format suitable
for CREATE TABLE. */
@ -3336,13 +3880,12 @@ dict_print_info_on_foreign_keys_in_create_format(
/*=============================================*/
char* buf, /* in: auxiliary buffer */
char* str, /* in/out: pointer to a string */
ulint len, /* in: str has to be a buffer at least
len + 5000 bytes */
ulint len, /* in: buf has to be a buffer of at least
len + 5000 bytes; str must have at least
len + 1 bytes */
dict_table_t* table) /* in: table */
{
dict_foreign_t* foreign;
ulint i;
char* buf2;
buf2 = buf;
@ -3358,78 +3901,12 @@ dict_print_info_on_foreign_keys_in_create_format(
}
while (foreign != NULL) {
buf2 += sprintf(buf2, ",\n FOREIGN KEY (");
if ((ulint)(buf2 - buf) >= len) {
goto no_space;
}
for (i = 0; i < foreign->n_fields; i++) {
if ((ulint)(buf2 - buf) >= len) {
goto no_space;
}
buf2 += sprintf(buf2, "`%s`",
foreign->foreign_col_names[i]);
if (i + 1 < foreign->n_fields) {
buf2 += sprintf(buf2, ", ");
}
}
if (dict_tables_have_same_db(table->name,
foreign->referenced_table_name)) {
/* Do not print the database name of the referenced
table */
buf2 += sprintf(buf2, ") REFERENCES `%s` (",
dict_remove_db_name(
foreign->referenced_table_name));
} else {
buf2 += sprintf(buf2, ") REFERENCES `%s` (",
foreign->referenced_table_name);
/* Change the '/' in the table name to '.' */
for (i = ut_strlen(buf); i > 0; i--) {
if (buf[i] == '/') {
buf[i] = '.';
break;
}
}
}
for (i = 0; i < foreign->n_fields; i++) {
if ((ulint)(buf2 - buf) >= len) {
goto no_space;
}
buf2 += sprintf(buf2, "`%s`",
foreign->referenced_col_names[i]);
if (i + 1 < foreign->n_fields) {
buf2 += sprintf(buf2, ", ");
}
}
buf2 += sprintf(buf2, ")");
if (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE) {
buf2 += sprintf(buf2, " ON DELETE CASCADE");
}
if (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) {
buf2 += sprintf(buf2, " ON DELETE SET NULL");
}
if (foreign->type & DICT_FOREIGN_ON_DELETE_NO_ACTION) {
buf2 += sprintf(buf2, " ON DELETE NO ACTION");
}
if (foreign->type & DICT_FOREIGN_ON_UPDATE_CASCADE) {
buf2 += sprintf(buf2, " ON UPDATE CASCADE");
}
if (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) {
buf2 += sprintf(buf2, " ON UPDATE SET NULL");
}
if (foreign->type & DICT_FOREIGN_ON_UPDATE_NO_ACTION) {
buf2 += sprintf(buf2, " ON UPDATE NO ACTION");
}
buf2 = dict_print_info_on_foreign_key_in_create_format(
foreign, buf2);
foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
}
@ -3490,7 +3967,7 @@ dict_print_info_on_foreign_keys(
goto no_space;
}
buf2 += sprintf(buf2, "%s",
buf2 += sprintf(buf2, "%.500s",
foreign->foreign_col_names[i]);
if (i + 1 < foreign->n_fields) {
@ -3498,14 +3975,14 @@ dict_print_info_on_foreign_keys(
}
}
buf2 += sprintf(buf2, ") REFER %s(",
buf2 += sprintf(buf2, ") REFER %.500s(",
foreign->referenced_table_name);
for (i = 0; i < foreign->n_fields; i++) {
if ((ulint)(buf2 - buf) >= len) {
goto no_space;
}
buf2 += sprintf(buf2, "%s",
buf2 += sprintf(buf2, "%.500s",
foreign->referenced_col_names[i]);
if (i + 1 < foreign->n_fields) {
buf2 += sprintf(buf2, " ");

View File

@ -456,7 +456,7 @@ dict_load_indexes(
ut_ad(len == 8);
id = mach_read_from_8(field);
ut_a(0 == ut_strcmp((void*) "NAME",
ut_a(0 == ut_strcmp((char*) "NAME",
dict_field_get_col(
dict_index_get_nth_field(
dict_table_get_first_index(sys_indexes), 4))->name));
@ -515,7 +515,7 @@ dict_load_indexes(
&& ((type & DICT_CLUSTERED)
|| ((table == dict_sys->sys_tables)
&& (name_len == ut_strlen("ID_IND"))
&& (0 == ut_memcmp(name_buf, (void*) "ID_IND",
&& (0 == ut_memcmp(name_buf, (char*) "ID_IND",
name_len))))) {
/* The index was created in memory already in
@ -566,6 +566,7 @@ dict_load_table(
char* buf;
ulint space;
ulint n_cols;
ulint err;
mtr_t mtr;
ut_ad(mutex_own(&(dict_sys->mutex)));
@ -674,8 +675,25 @@ dict_load_table(
dict_load_indexes(table, heap);
ut_a(DB_SUCCESS == dict_load_foreigns(table->name));
err = dict_load_foreigns(table->name);
/*
if (err != DB_SUCCESS) {
mutex_enter(&dict_foreign_err_mutex);
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Error: could not make a foreign key definition to match\n"
"InnoDB: the foreign key table or the referenced table!\n"
"InnoDB: The data dictionary of InnoDB is corrupt. You may need to drop\n"
"InnoDB: and recreate the foreign key table or the referenced table.\n"
"InnoDB: Send a detailed bug report to mysql@lists.mysql.com\n"
"InnoDB: Latest foreign key error printout:\n%s\n", dict_foreign_err_buf);
mutex_exit(&dict_foreign_err_mutex);
}
*/
mem_heap_free(heap);
return(table);
@ -978,8 +996,8 @@ dict_load_foreign(
field = rec_get_nth_field(rec, 4, &len);
foreign->referenced_table_name = mem_heap_alloc(foreign->heap, 1 + len);
foreign->referenced_table_name = mem_heap_alloc(foreign->heap,
1 + len);
ut_memcpy(foreign->referenced_table_name, field, len);
foreign->referenced_table_name[len] = '\0';
@ -988,10 +1006,19 @@ dict_load_foreign(
dict_load_foreign_cols(id, foreign);
/* If the foreign table is not yet in the dictionary cache, we
have to load it so that we are able to make type comparisons
in the next function call. */
dict_table_get_low(foreign->foreign_table_name);
/* Note that there may already be a foreign constraint object in
the dictionary cache for this constraint: then the following
call only sets the pointers in it to point to the appropriate table
and index objects and frees the newly created object foreign. */
and index objects and frees the newly created object foreign.
Adding to the cache should always succeed since we are not creating
a new foreign key constraint but loading one from the data
dictionary. */
err = dict_foreign_add_to_cache(foreign);

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libdyn.a
noinst_LIBRARIES = libdyn.a
libdyn_a_SOURCES = dyn0dyn.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libeval.a
noinst_LIBRARIES = libeval.a
libeval_a_SOURCES = eval0eval.c eval0proc.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libfil.a
noinst_LIBRARIES = libfil.a
libfil_a_SOURCES = fil0fil.c

View File

@ -18,7 +18,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libfsp.a
noinst_LIBRARIES = libfsp.a
libfsp_a_SOURCES = fsp0fsp.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libfut.a
noinst_LIBRARIES = libfut.a
libfut_a_SOURCES = fut0fut.c fut0lst.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libha.a
noinst_LIBRARIES = libha.a
libha_a_SOURCES = ha0ha.c hash0hash.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libibuf.a
noinst_LIBRARIES = libibuf.a
libibuf_a_SOURCES = ibuf0ibuf.c

View File

@ -2391,7 +2391,7 @@ ibuf_delete_rec(
ut_ad(ibuf_inside());
success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr);
success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr);
if (success) {
#ifdef UNIV_IBUF_DEBUG
@ -2401,7 +2401,7 @@ ibuf_delete_rec(
return(FALSE);
}
/* We have to resort to a pessimistic delete from ibuf */
/* We have to resort to a pessimistic delete from ibuf */
btr_pcur_store_position(pcur, mtr);
btr_pcur_commit_specify_mtr(pcur, mtr);
@ -2420,17 +2420,22 @@ ibuf_delete_rec(
fprintf(stderr, "InnoDB: ibuf cursor restoration fails!\n");
fprintf(stderr, "InnoDB: ibuf record inserted to page %lu\n",
page_no);
fflush(stderr);
rec_print(btr_pcur_get_rec(pcur));
rec_print(pcur->old_rec);
dtuple_print(search_tuple);
rec_print(page_rec_get_next(btr_pcur_get_rec(pcur)));
fflush(stdout);
mtr_commit(mtr);
fprintf(stderr, "InnoDB: Validating insert buffer tree:\n");
ut_a(btr_validate_tree(ibuf_data->index->tree));
fprintf(stderr, "InnoDB: Ibuf tree ok\n");
ut_a(btr_validate_tree(ibuf_data->index->tree));
fprintf(stderr, "InnoDB: ibuf tree ok\n");
fflush(stderr);
}
ut_a(success);

View File

@ -1,7 +1,5 @@
# Makefile included in Makefile.am in every subdirectory
libsdir = ../libs
INCLUDES = -I$(srcdir)/../include -I$(srcdir)/../../include -I../../include
# Don't update the files from bitkeeper

View File

@ -496,6 +496,13 @@ buf_print_io(
/*=========*/
char* buf, /* in/out: buffer where to print */
char* buf_end);/* in: buffer end */
/*************************************************************************
Returns the ratio in percents of modified pages in the buffer pool /
database pages in the buffer pool. */
ulint
buf_get_modified_ratio_pct(void);
/*============================*/
/**************************************************************************
Refreshes the statistics used to print per-second averages. */

View File

@ -46,6 +46,20 @@ buf_LRU_get_recent_limit(void);
/*==========================*/
/* out: the limit; zero if could not determine it */
/**********************************************************************
Look for a replaceable block from the end of the LRU list and put it to
the free list if found. */
ibool
buf_LRU_search_and_free_block(
/*==========================*/
/* out: TRUE if freed */
ulint n_iterations); /* in: how many times this has been called
repeatedly without result: a high value means
that we should search farther; if value is
k < 10, then we only search k/10 * number
of pages in the buffer pool from the end
of the LRU list */
/**********************************************************************
Returns a free block from the buf_pool. The block is taken off the
free list. If it is empty, blocks are moved from the end of the
LRU list to the free list. */
@ -88,17 +102,6 @@ void
buf_LRU_make_block_old(
/*===================*/
buf_block_t* block); /* in: control block */
/**********************************************************************
Look for a replaceable block from the end of the LRU list and put it to
the free list if found. */
ibool
buf_LRU_search_and_free_block(
/*==========================*/
/* out: TRUE if freed */
ulint n_iterations); /* in: how many times this has been called
repeatedly without result: a high value
means that we should search farther */
/**************************************************************************
Validates the LRU list. */

View File

@ -44,6 +44,8 @@ Created 5/24/1996 Heikki Tuuri
#define DB_CORRUPTION 39 /* data structure corruption noticed */
#define DB_COL_APPEARS_TWICE_IN_INDEX 40 /* InnoDB cannot handle an index
where same column appears twice */
#define DB_CANNOT_DROP_CONSTRAINT 40 /* dropping a foreign key constraint
from a table failed */
/* The following are partial failure codes */
#define DB_FAIL 1000

View File

@ -219,6 +219,24 @@ dict_create_foreign_constraints(
char* name); /* in: table full name in the normalized form
database_name/table_name */
/**************************************************************************
Parses the CONSTRAINT id's to be dropped in an ALTER TABLE statement. */
ulint
dict_foreign_parse_drop_constraints(
/*================================*/
/* out: DB_SUCCESS or
DB_CANNOT_DROP_CONSTRAINT if
syntax error or the constraint
id does not match */
mem_heap_t* heap, /* in: heap from which we can
allocate memory */
trx_t* trx, /* in: transaction */
dict_table_t* table, /* in: table */
ulint* n, /* out: number of constraints
to drop */
char*** constraints_to_drop); /* out: id's of the
constraints to drop */
/**************************************************************************
Returns a table object and memoryfixes it. NOTE! This is a high-level
function to be used mainly from outside the 'dict' directory. Inside this
directory dict_table_get_low is usually the appropriate function. */
@ -333,6 +351,16 @@ dict_print_info_on_foreign_keys(
char* str, /* in/out: pointer to a string */
ulint len, /* in: space in str available for info */
dict_table_t* table); /* in: table */
/**************************************************************************
Sprintfs to a string info on a foreign key of a table in a format suitable
for CREATE TABLE. */
char*
dict_print_info_on_foreign_key_in_create_format(
/*============================================*/
/* out: how far in buf we printed */
dict_foreign_t* foreign,/* in: foreign key constraint */
char* buf); /* in: buffer of at least 5000 bytes */
/************************************************************************
Gets the first index on the table (the clustered index). */
UNIV_INLINE
@ -808,6 +836,14 @@ void
dict_mutex_exit_for_mysql(void);
/*===========================*/
/* The following len must be at least 10000 bytes! */
#define DICT_FOREIGN_ERR_BUF_LEN 10000
/* Buffers for storing detailed information about the latest foreign key
and unique key errors */
extern char* dict_foreign_err_buf;
extern char* dict_unique_err_buf;
extern mutex_t dict_foreign_err_mutex; /* mutex protecting the buffers */
extern dict_sys_t* dict_sys; /* the dictionary system */
extern rw_lock_t dict_operation_lock;

View File

@ -20,7 +20,7 @@ typedef struct log_group_struct log_group_t;
extern ibool log_do_write;
extern ibool log_debug_writes;
/* Wait modes for log_flush_up_to */
/* Wait modes for log_write_up_to */
#define LOG_NO_WAIT 91
#define LOG_WAIT_ONE_GROUP 92
#define LOG_WAIT_ALL_GROUPS 93
@ -157,26 +157,21 @@ log_io_complete(
/*============*/
log_group_t* group); /* in: log group */
/**********************************************************
Flushes the log files to the disk, using, for example, the Unix fsync.
This function does the flush even if the user has set
srv_flush_log_at_trx_commit = FALSE. */
void
log_flush_to_disk(void);
/*===================*/
/**********************************************************
This function is called, e.g., when a transaction wants to commit. It checks
that the log has been flushed to disk up to the last log entry written by the
transaction. If there is a flush running, it waits and checks if the flush
flushed enough. If not, starts a new flush. */
that the log has been written to the log file up to the last log entry written
by the transaction. If there is a flush running, it waits and checks if the
flush flushed enough. If not, starts a new flush. */
void
log_flush_up_to(
log_write_up_to(
/*============*/
dulint lsn, /* in: log sequence number up to which the log should
be flushed, ut_dulint_max if not specified */
ulint wait); /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP,
be written, ut_dulint_max if not specified */
ulint wait, /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP,
or LOG_WAIT_ALL_GROUPS */
ibool flush_to_disk);
/* in: TRUE if we want the written log also to be
flushed to disk */
/********************************************************************
Advances the smallest lsn for which there are unflushed dirty blocks in the
buffer pool and also may make a new checkpoint. NOTE: this function may only
@ -741,27 +736,37 @@ struct log_struct{
be advanced, it is enough that the
write i/o has been completed for all
log groups */
dulint flush_lsn; /* end lsn for the current flush */
ulint flush_end_offset;/* the data in buffer has been flushed
dulint write_lsn; /* end lsn for the current running
write */
ulint write_end_offset;/* the data in buffer has been written
up to this offset when the current
flush ends: this field will then
write ends: this field will then
be copied to buf_next_to_write */
ulint n_pending_writes;/* number of currently pending flush
writes */
dulint current_flush_lsn;/* end lsn for the current running
write + flush operation */
dulint flushed_to_disk_lsn;
/* how far we have written the log
AND flushed to disk */
ulint n_pending_writes;/* number of currently pending flushes
or writes */
/* NOTE on the 'flush' in names of the fields below: starting from
4.0.14, we separate the write of the log file and the actual fsync()
or other method to flush it to disk. The names below shhould really
be 'flush_or_write'! */
os_event_t no_flush_event; /* this event is in the reset state
when a flush is running; a thread
should wait for this without owning
the log mutex, but NOTE that to set or
reset this event, the thread MUST own
the log mutex! */
when a flush or a write is running;
a thread should wait for this without
owning the log mutex, but NOTE that
to set or reset this event, the
thread MUST own the log mutex! */
ibool one_flushed; /* during a flush, this is first FALSE
and becomes TRUE when one log group
has been flushed */
has been written or flushed */
os_event_t one_flushed_event;/* this event is reset when the
flush has not yet completed for any
log group; e.g., this means that a
transaction has been committed when
this is set; a thread should wait
flush or write has not yet completed
for any log group; e.g., this means
that a transaction has been committed
when this is set; a thread should wait
for this without owning the log mutex,
but NOTE that to set or reset this
event, the thread MUST own the log

View File

@ -35,7 +35,6 @@ row_ins_check_foreign_constraint(
dictionary cache if they exist at all */
dict_table_t* table, /* in: if check_ref is TRUE, then the foreign
table, else the referenced table */
dict_index_t* index, /* in: index in table */
dtuple_t* entry, /* in: index entry for index */
que_thr_t* thr); /* in: query thread */
/*************************************************************************

View File

@ -427,13 +427,21 @@ struct row_prebuilt_struct {
index where the ordering column is
the row id: in this case this flag
is set to TRUE */
dict_index_t* index; /* current index for a search, if any */
dict_index_t* index; /* current index for a search, if
any */
ulint read_just_key; /* set to 1 when MySQL calls
ha_innobase::extra with the
argument HA_EXTRA_KEYREAD; it is enough
to read just columns defined in
the index (i.e., no read of the
clustered index record necessary) */
ibool used_in_HANDLER;/* TRUE if we have been using this
handle in a MySQL HANDLER low level
index cursor command: then we must
store the pcur position even in a
unique search from a clustered index,
because HANDLER allows NEXT and PREV
in such a situation */
ulint template_type; /* ROW_MYSQL_WHOLE_ROW,
ROW_MYSQL_REC_FIELDS,
ROW_MYSQL_DUMMY_TEMPLATE, or

View File

@ -75,6 +75,9 @@ extern ulint srv_lock_wait_timeout;
extern char* srv_file_flush_method_str;
extern ulint srv_unix_file_flush_method;
extern ulint srv_win_file_flush_method;
extern ulint srv_max_dirty_pages_pct;
extern ulint srv_force_recovery;
extern ulint srv_thread_concurrency;

View File

@ -157,6 +157,15 @@ trx_commit_for_mysql(
/* out: 0 or error number */
trx_t* trx); /* in: trx handle */
/**************************************************************************
If required, flushes the log to disk if we called trx_commit_for_mysql()
with trx->flush_log_later == TRUE. */
ulint
trx_commit_complete_for_mysql(
/*==========================*/
/* out: 0 or error number */
trx_t* trx); /* in: trx handle */
/**************************************************************************
Marks the latest SQL statement ended. */
void
@ -343,6 +352,11 @@ struct trx_struct{
dulint no; /* transaction serialization number ==
max trx id when the transaction is
moved to COMMITTED_IN_MEMORY state */
ibool flush_log_later;/* when we commit the transaction
in MySQL's binlog write, we will
flush the log to disk later in
a separate call */
dulint commit_lsn; /* lsn at the time of the commit */
ibool dict_operation; /* TRUE if the trx is used to create
a table, create an index, or drop a
table */
@ -418,10 +432,6 @@ struct trx_struct{
lock_t* auto_inc_lock; /* possible auto-inc lock reserved by
the transaction; note that it is also
in the lock list trx_locks */
ibool ignore_duplicates_in_insert;
/* in an insert roll back only insert
of the latest row in case
of a duplicate key error */
UT_LIST_NODE_T(trx_t)
trx_list; /* list of transactions */
UT_LIST_NODE_T(trx_t)

View File

@ -100,6 +100,15 @@ memory is read outside the allocated blocks. */
#define YYDEBUG 1
#ifdef HAVE_purify
/* The following sets all new allocated memory to zero before use:
this can be used to eliminate unnecessary Purify warnings, but note that
it also masks many bugs Purify could detect. For detailed Purify analysis it
is best to remove the define below and look through the warnings one
by one. */
#define UNIV_SET_MEM_TO_ZERO
#endif
/*
#define UNIV_SQL_DEBUG
#define UNIV_LOG_DEBUG

View File

@ -20,7 +20,6 @@ extern ibool ut_dbg_stop_threads;
extern ulint* ut_dbg_null_ptr;
#define ut_a(EXPR)\
{\
ulint dbg_i;\
@ -31,8 +30,10 @@ extern ulint* ut_dbg_null_ptr;
" InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\
os_thread_pf(os_thread_get_curr_id()), IB__FILE__,\
(ulint)__LINE__);\
fprintf(stderr,\
"InnoDB: Failing assertion: " #EXPR);\
fprintf(stderr,\
"InnoDB: We intentionally generate a memory trap.\n");\
"\nInnoDB: We intentionally generate a memory trap.\n");\
fprintf(stderr,\
"InnoDB: Send a detailed bug report to mysql@lists.mysql.com\n");\
ut_dbg_stop_threads = TRUE;\

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = liblock.a
noinst_LIBRARIES = liblock.a
liblock_a_SOURCES = lock0lock.c

View File

@ -3092,8 +3092,7 @@ lock_deadlock_recursive(
err_buf += strlen(err_buf);
err_buf += sprintf(err_buf,
" LATEST DETECTED DEADLOCK:\n"
"*** (1) TRANSACTION:\n");
"\n*** (1) TRANSACTION:\n");
trx_print(err_buf, wait_lock->trx);
err_buf += strlen(err_buf);
@ -3935,24 +3934,15 @@ lock_print_info(
return;
}
buf += sprintf(buf, "Trx id counter %lu %lu\n",
ut_dulint_get_high(trx_sys->max_trx_id),
ut_dulint_get_low(trx_sys->max_trx_id));
buf += sprintf(buf,
"Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu\n",
ut_dulint_get_high(purge_sys->purge_trx_no),
ut_dulint_get_low(purge_sys->purge_trx_no),
ut_dulint_get_high(purge_sys->purge_undo_no),
ut_dulint_get_low(purge_sys->purge_undo_no));
lock_mutex_enter_kernel();
buf += sprintf(buf,
"Total number of lock structs in row lock hash table %lu\n",
lock_get_n_rec_locks());
if (lock_deadlock_found) {
buf += sprintf(buf,
"------------------------\n"
"LATEST DETECTED DEADLOCK\n"
"------------------------\n");
if ((ulint)(buf_end - buf)
< 100 + strlen(lock_latest_err_buf)) {
@ -3973,6 +3963,26 @@ lock_print_info(
return;
}
buf += sprintf(buf,
"------------\n"
"TRANSACTIONS\n"
"------------\n");
buf += sprintf(buf, "Trx id counter %lu %lu\n",
ut_dulint_get_high(trx_sys->max_trx_id),
ut_dulint_get_low(trx_sys->max_trx_id));
buf += sprintf(buf,
"Purge done for trx's n:o < %lu %lu undo n:o < %lu %lu\n",
ut_dulint_get_high(purge_sys->purge_trx_no),
ut_dulint_get_low(purge_sys->purge_trx_no),
ut_dulint_get_high(purge_sys->purge_undo_no),
ut_dulint_get_low(purge_sys->purge_undo_no));
buf += sprintf(buf,
"Total number of lock structs in row lock hash table %lu\n",
lock_get_n_rec_locks());
buf += sprintf(buf, "LIST OF TRANSACTIONS FOR EACH SESSION:\n");
/* First print info on non-active transactions */

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = liblog.a
noinst_LIBRARIES = liblog.a
liblog_a_SOURCES = log0log.c log0recv.c

View File

@ -178,7 +178,7 @@ loop:
/* Not enough free space, do a syncronous flush of the log
buffer */
log_flush_up_to(ut_dulint_max, LOG_WAIT_ALL_GROUPS);
log_write_up_to(ut_dulint_max, LOG_WAIT_ALL_GROUPS, TRUE);
count++;
@ -675,7 +675,9 @@ log_init(void)
log_sys->buf_next_to_write = 0;
log_sys->flush_lsn = ut_dulint_zero;
log_sys->write_lsn = ut_dulint_zero;
log_sys->current_flush_lsn = ut_dulint_zero;
log_sys->flushed_to_disk_lsn = ut_dulint_zero;
log_sys->written_to_some_lsn = log_sys->lsn;
log_sys->written_to_all_lsn = log_sys->lsn;
@ -867,7 +869,7 @@ log_group_check_flush_completion(
printf("Log flushed first to group %lu\n", group->id);
}
log_sys->written_to_some_lsn = log_sys->flush_lsn;
log_sys->written_to_some_lsn = log_sys->write_lsn;
log_sys->one_flushed = TRUE;
return(LOG_UNLOCK_NONE_FLUSHED_LOCK);
@ -896,15 +898,15 @@ log_sys_check_flush_completion(void)
if (log_sys->n_pending_writes == 0) {
log_sys->written_to_all_lsn = log_sys->flush_lsn;
log_sys->buf_next_to_write = log_sys->flush_end_offset;
log_sys->written_to_all_lsn = log_sys->write_lsn;
log_sys->buf_next_to_write = log_sys->write_end_offset;
if (log_sys->flush_end_offset > log_sys->max_buf_free / 2) {
if (log_sys->write_end_offset > log_sys->max_buf_free / 2) {
/* Move the log buffer content to the start of the
buffer */
move_start = ut_calc_align_down(
log_sys->flush_end_offset,
log_sys->write_end_offset,
OS_FILE_LOG_BLOCK_SIZE);
move_end = ut_calc_align(log_sys->buf_free,
OS_FILE_LOG_BLOCK_SIZE);
@ -981,57 +983,6 @@ log_io_complete(
mutex_exit(&(log_sys->mutex));
}
/**********************************************************
Flushes the log files to the disk, using, for example, the Unix fsync.
This function does the flush even if the user has set
srv_flush_log_at_trx_commit = FALSE. */
void
log_flush_to_disk(void)
/*===================*/
{
log_group_t* group;
loop:
mutex_enter(&(log_sys->mutex));
if (log_sys->n_pending_writes > 0) {
/* A log file write is running */
mutex_exit(&(log_sys->mutex));
/* Wait for the log file write to complete and try again */
os_event_wait(log_sys->no_flush_event);
goto loop;
}
group = UT_LIST_GET_FIRST(log_sys->log_groups);
log_sys->n_pending_writes++;
group->n_pending_writes++;
os_event_reset(log_sys->no_flush_event);
os_event_reset(log_sys->one_flushed_event);
mutex_exit(&(log_sys->mutex));
fil_flush(group->space_id);
mutex_enter(&(log_sys->mutex));
ut_a(group->n_pending_writes == 1);
ut_a(log_sys->n_pending_writes == 1);
group->n_pending_writes--;
log_sys->n_pending_writes--;
os_event_set(log_sys->no_flush_event);
os_event_set(log_sys->one_flushed_event);
mutex_exit(&(log_sys->mutex));
}
/**********************************************************
Writes a log file header to a log file space. */
static
@ -1205,12 +1156,15 @@ by the transaction. If there is a flush running, it waits and checks if the
flush flushed enough. If not, starts a new flush. */
void
log_flush_up_to(
log_write_up_to(
/*============*/
dulint lsn, /* in: log sequence number up to which the log should
be written, ut_dulint_max if not specified */
ulint wait) /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP,
ulint wait, /* in: LOG_NO_WAIT, LOG_WAIT_ONE_GROUP,
or LOG_WAIT_ALL_GROUPS */
ibool flush_to_disk)
/* in: TRUE if we want the written log also to be
flushed to disk */
{
log_group_t* group;
ulint start_offset;
@ -1239,9 +1193,18 @@ loop:
mutex_enter(&(log_sys->mutex));
if ((ut_dulint_cmp(log_sys->written_to_all_lsn, lsn) >= 0)
|| ((ut_dulint_cmp(log_sys->written_to_some_lsn, lsn) >= 0)
&& (wait != LOG_WAIT_ALL_GROUPS))) {
if (flush_to_disk
&& ut_dulint_cmp(log_sys->flushed_to_disk_lsn, lsn) >= 0) {
mutex_exit(&(log_sys->mutex));
return;
}
if (!flush_to_disk
&& (ut_dulint_cmp(log_sys->written_to_all_lsn, lsn) >= 0
|| (ut_dulint_cmp(log_sys->written_to_some_lsn, lsn) >= 0
&& wait != LOG_WAIT_ALL_GROUPS))) {
mutex_exit(&(log_sys->mutex));
@ -1249,10 +1212,19 @@ loop:
}
if (log_sys->n_pending_writes > 0) {
/* A flush is running */
/* A write (+ possibly flush to disk) is running */
if (ut_dulint_cmp(log_sys->flush_lsn, lsn) >= 0) {
/* The flush will flush enough: wait for it to
if (flush_to_disk
&& ut_dulint_cmp(log_sys->current_flush_lsn, lsn) >= 0) {
/* The write + flush will write enough: wait for it to
complete */
goto do_waits;
}
if (!flush_to_disk
&& ut_dulint_cmp(log_sys->write_lsn, lsn) >= 0) {
/* The write will write enough: wait for it to
complete */
goto do_waits;
@ -1260,16 +1232,17 @@ loop:
mutex_exit(&(log_sys->mutex));
/* Wait for the flush to complete and try to start a new
flush */
/* Wait for the write to complete and try to start a new
write */
os_event_wait(log_sys->no_flush_event);
goto loop;
}
if (log_sys->buf_free == log_sys->buf_next_to_write) {
/* Nothing to flush */
if (!flush_to_disk
&& log_sys->buf_free == log_sys->buf_next_to_write) {
/* Nothing to write and no flush to disk requested */
mutex_exit(&(log_sys->mutex));
@ -1277,7 +1250,7 @@ loop:
}
if (log_debug_writes) {
printf("Flushing log from %lu %lu up to lsn %lu %lu\n",
printf("Writing log from %lu %lu up to lsn %lu %lu\n",
ut_dulint_get_high(log_sys->written_to_all_lsn),
ut_dulint_get_low(log_sys->written_to_all_lsn),
ut_dulint_get_high(log_sys->lsn),
@ -1301,7 +1274,12 @@ loop:
ut_ad(area_end - area_start > 0);
log_sys->flush_lsn = log_sys->lsn;
log_sys->write_lsn = log_sys->lsn;
if (flush_to_disk) {
log_sys->current_flush_lsn = log_sys->lsn;
}
log_sys->one_flushed = FALSE;
log_block_set_flush_bit(log_sys->buf + area_start, TRUE);
@ -1318,10 +1296,12 @@ loop:
OS_FILE_LOG_BLOCK_SIZE);
log_sys->buf_free += OS_FILE_LOG_BLOCK_SIZE;
log_sys->flush_end_offset = log_sys->buf_free;
log_sys->write_end_offset = log_sys->buf_free;
group = UT_LIST_GET_FIRST(log_sys->log_groups);
/* Do the write to the log files */
while (group) {
log_group_write_buf(LOG_FLUSH, group,
log_sys->buf + area_start,
@ -1330,20 +1310,25 @@ loop:
OS_FILE_LOG_BLOCK_SIZE),
start_offset - area_start);
log_group_set_fields(group, log_sys->flush_lsn);
log_group_set_fields(group, log_sys->write_lsn);
group = UT_LIST_GET_NEXT(log_groups, group);
}
mutex_exit(&(log_sys->mutex));
if (srv_unix_file_flush_method != SRV_UNIX_O_DSYNC
&& srv_unix_file_flush_method != SRV_UNIX_NOSYNC
&& srv_flush_log_at_trx_commit != 2) {
if (srv_unix_file_flush_method == SRV_UNIX_O_DSYNC) {
/* O_DSYNC means the OS did not buffer the log file at all:
so we have also flushed to disk what we have written */
log_sys->flushed_to_disk_lsn = log_sys->write_lsn;
} else if (flush_to_disk) {
group = UT_LIST_GET_FIRST(log_sys->log_groups);
fil_flush(group->space_id);
log_sys->flushed_to_disk_lsn = log_sys->write_lsn;
}
mutex_enter(&(log_sys->mutex));
@ -1403,7 +1388,7 @@ log_flush_margin(void)
mutex_exit(&(log->mutex));
if (do_flush) {
log_flush_up_to(ut_dulint_max, LOG_NO_WAIT);
log_write_up_to(ut_dulint_max, LOG_NO_WAIT, FALSE);
}
}
@ -1555,7 +1540,8 @@ log_group_checkpoint(
buf = group->checkpoint_buf;
mach_write_to_8(buf + LOG_CHECKPOINT_NO, log_sys->next_checkpoint_no);
mach_write_to_8(buf + LOG_CHECKPOINT_LSN, log_sys->next_checkpoint_lsn);
mach_write_to_8(buf + LOG_CHECKPOINT_LSN,
log_sys->next_checkpoint_lsn);
mach_write_to_4(buf + LOG_CHECKPOINT_OFFSET,
log_group_calc_lsn_offset(
@ -1664,8 +1650,10 @@ log_reset_first_header_and_checkpoint(
lsn = ut_dulint_add(start, LOG_BLOCK_HDR_SIZE);
/* Write the label of ibbackup --restore */
sprintf((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP, "ibbackup ");
ut_sprintf_timestamp((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP
sprintf((char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
"ibbackup ");
ut_sprintf_timestamp(
(char*) hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP
+ strlen("ibbackup "));
buf = hdr_buf + LOG_CHECKPOINT_1;
@ -1773,7 +1761,7 @@ log_checkpoint(
write-ahead-logging algorithm ensures that the log has been flushed
up to oldest_lsn. */
log_flush_up_to(oldest_lsn, LOG_WAIT_ALL_GROUPS);
log_write_up_to(oldest_lsn, LOG_WAIT_ALL_GROUPS, TRUE);
mutex_enter(&(log_sys->mutex));
@ -2466,7 +2454,7 @@ loop:
mutex_exit(&(log_sys->mutex));
log_flush_up_to(limit_lsn, LOG_WAIT_ALL_GROUPS);
log_write_up_to(limit_lsn, LOG_WAIT_ALL_GROUPS, TRUE);
calc_new_limit = FALSE;
@ -3104,8 +3092,8 @@ log_print(
"Last checkpoint at %lu %lu\n",
ut_dulint_get_high(log_sys->lsn),
ut_dulint_get_low(log_sys->lsn),
ut_dulint_get_high(log_sys->written_to_some_lsn),
ut_dulint_get_low(log_sys->written_to_some_lsn),
ut_dulint_get_high(log_sys->flushed_to_disk_lsn),
ut_dulint_get_low(log_sys->flushed_to_disk_lsn),
ut_dulint_get_high(log_sys->last_checkpoint_lsn),
ut_dulint_get_low(log_sys->last_checkpoint_lsn));

View File

@ -1833,7 +1833,12 @@ recv_report_corrupt_log(
"InnoDB: WARNING: the log file may have been corrupt and it\n"
"InnoDB: is possible that the log scan did not proceed\n"
"InnoDB: far enough in recovery! Please run CHECK TABLE\n"
"InnoDB: on your InnoDB tables to check that they are ok!\n");
"InnoDB: on your InnoDB tables to check that they are ok!\n"
"InnoDB: If mysqld crashes after this recovery, look at\n"
"InnoDB: section 6.1 of http://www.innodb.com/ibman.html\n"
"InnoDB: about forcing recovery.\n");
fflush(stderr);
}
/***********************************************************
@ -2470,7 +2475,7 @@ recv_recovery_from_checkpoint_start(
log_hdr_buf, max_cp_group);
if (0 == ut_memcmp(log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
"ibbackup", ut_strlen("ibbackup"))) {
(byte*)"ibbackup", ut_strlen((char*)"ibbackup"))) {
/* This log file was created by ibbackup --restore: print
a note to the user about it */
@ -2481,7 +2486,7 @@ recv_recovery_from_checkpoint_start(
/* Wipe over the label now */
ut_memcpy(log_hdr_buf + LOG_FILE_WAS_CREATED_BY_HOT_BACKUP,
" ", 4);
(char*)" ", 4);
/* Write to the log file to wipe over the label */
fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE,
max_cp_group->space_id,

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libmach.a
noinst_LIBRARIES = libmach.a
libmach_a_SOURCES = mach0data.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libmem.a
noinst_LIBRARIES = libmem.a
libmem_a_SOURCES = mem0mem.c mem0pool.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libmtr.a
noinst_LIBRARIES = libmtr.a
libmtr_a_SOURCES = mtr0mtr.c mtr0log.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libodbc.a
noinst_LIBRARIES = libodbc.a
libodbc_a_SOURCES = odbc0odbc.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libos.a
noinst_LIBRARIES = libos.a
libos_a_SOURCES = os0proc.c os0shm.c os0sync.c os0thread.c os0file.c

View File

@ -214,9 +214,14 @@ os_file_get_last_error(void)
"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 (strerror((int)err) != NULL) {
fprintf(stderr,
"InnoDB: Error number %lu means '%s'.\n", err, strerror((int)err));
}
fprintf(stderr,
"InnoDB: See also section 13.2 at http://www.innodb.com/ibman.html\n"
"InnoDB: about operating system error numbers.\n");
}
}
@ -252,9 +257,14 @@ os_file_get_last_error(void)
"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 (strerror((int)err) != NULL) {
fprintf(stderr,
"InnoDB: Error number %lu means '%s'.\n", err, strerror((int)err));
}
fprintf(stderr,
"InnoDB: See also section 13.2 at http://www.innodb.com/ibman.html\n"
"InnoDB: about operating system error numbers.\n");
}
}
@ -511,10 +521,11 @@ try_again:
}
#endif
#ifdef UNIV_NON_BUFFERED_IO
if (type == OS_LOG_FILE && srv_flush_log_at_trx_commit == 2) {
if (type == OS_LOG_FILE) {
/* Do not use unbuffered i/o to log files because
value 2 denotes that we do not flush the log at every
commit, but only once per second */
to allow group commit to work when MySQL binlogging
is used we must separate log file write and log
file flush to disk. */
} else {
if (srv_win_file_flush_method ==
SRV_WIN_IO_UNBUFFERED) {
@ -741,7 +752,12 @@ os_file_set_size(
offset = 0;
low = (ib_longlong)size + (((ib_longlong)size_high) << 32);
if (low >= (ib_longlong)(100 * 1024 * 1024)) {
fprintf(stderr, "InnoDB: Progress in MB:");
}
while (offset < low) {
if (low - offset < UNIV_PAGE_SIZE * 512) {
n_bytes = (ulint)(low - offset);
@ -757,9 +773,24 @@ os_file_set_size(
ut_free(buf2);
goto error_handling;
}
/* Print about progress for each 100 MB written */
if ((offset + n_bytes) / (ib_longlong)(100 * 1024 * 1024)
!= offset / (ib_longlong)(100 * 1024 * 1024)) {
fprintf(stderr, " %lu00",
(ulint)((offset + n_bytes)
/ (ib_longlong)(100 * 1024 * 1024)));
}
offset += n_bytes;
}
if (low >= (ib_longlong)(100 * 1024 * 1024)) {
fprintf(stderr, "\n");
}
ut_free(buf2);
ret = os_file_flush(file);

View File

@ -68,9 +68,10 @@ os_event_create(
os_fast_mutex_init(&(event->os_mutex));
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
pthread_cond_init(&(event->cond_var), pthread_condattr_default);
ut_a(0 == pthread_cond_init(&(event->cond_var),
pthread_condattr_default));
#else
pthread_cond_init(&(event->cond_var), NULL);
ut_a(0 == pthread_cond_init(&(event->cond_var), NULL));
#endif
event->is_set = FALSE;
@ -130,7 +131,7 @@ os_event_set(
/* Do nothing */
} else {
event->is_set = TRUE;
pthread_cond_broadcast(&(event->cond_var));
ut_a(0 == pthread_cond_broadcast(&(event->cond_var)));
}
os_fast_mutex_unlock(&(event->os_mutex));
@ -182,7 +183,7 @@ os_event_free(
ut_a(event);
os_fast_mutex_free(&(event->os_mutex));
pthread_cond_destroy(&(event->cond_var));
ut_a(0 == pthread_cond_destroy(&(event->cond_var)));
ut_free(event);
#endif
@ -446,9 +447,9 @@ os_fast_mutex_init(
InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex);
#else
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
pthread_mutex_init(fast_mutex, pthread_mutexattr_default);
ut_a(0 == pthread_mutex_init(fast_mutex, pthread_mutexattr_default));
#else
pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST);
ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST));
#endif
#endif
}
@ -495,10 +496,7 @@ os_fast_mutex_free(
ut_a(fast_mutex);
DeleteCriticalSection((LPCRITICAL_SECTION) fast_mutex);
#elif defined(__NETWARE__) || defined(SAFE_MUTEX_DETECT_DESTROY)
pthread_mutex_destroy(fast_mutex);
#else
UT_NOT_USED(fast_mutex);
ut_a(0 == pthread_mutex_destroy(fast_mutex));
#endif
}

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libpage.a
noinst_LIBRARIES = libpage.a
libpage_a_SOURCES = page0page.c page0cur.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libpars.a
noinst_LIBRARIES = libpars.a
noinst_HEADERS = pars0grm.h

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libque.a
noinst_LIBRARIES = libque.a
libque_a_SOURCES = que0que.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libread.a
noinst_LIBRARIES = libread.a
libread_a_SOURCES = read0read.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = librem.a
noinst_LIBRARIES = librem.a
librem_a_SOURCES = rem0rec.c rem0cmp.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = librow.a
noinst_LIBRARIES = librow.a
librow_a_SOURCES = row0ins.c row0mysql.c row0purge.c row0row.c row0sel.c\
row0uins.c row0umod.c row0undo.c row0upd.c row0vers.c

View File

@ -323,7 +323,7 @@ row_ins_clust_index_entry_by_modify(
/*************************************************************************
Returns TRUE if in a cascaded update/delete an ancestor node of node
updates table. */
updates (not DELETE, but UPDATE) table. */
static
ibool
row_ins_cascade_ancestor_updates_table(
@ -341,7 +341,7 @@ row_ins_cascade_ancestor_updates_table(
upd_node = parent;
if (upd_node->table == table) {
if (upd_node->table == table && upd_node->is_delete == FALSE) {
return(TRUE);
}
@ -437,6 +437,111 @@ row_ins_cascade_calc_update_vec(
return(n_fields_updated);
}
/*************************************************************************
Reports a foreign key error associated with an update or a delete of a
parent table index entry. */
static
void
row_ins_foreign_report_err(
/*=======================*/
char* errstr, /* in: error string from the viewpoint
of the parent table */
que_thr_t* thr, /* in: query thread whose run_node
is an update node */
dict_foreign_t* foreign, /* in: foreign key constraint */
rec_t* rec, /* in: a matching index record in the
child table */
dtuple_t* entry) /* in: index entry in the parent
table */
{
char* buf = dict_foreign_err_buf;
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf), " Transaction:\n");
trx_print(buf + strlen(buf), thr_get_trx(thr));
sprintf(buf + strlen(buf),
"Foreign key constraint fails for table %.500s:\n",
foreign->foreign_table_name);
dict_print_info_on_foreign_key_in_create_format(
foreign, buf + strlen(buf));
sprintf(buf + strlen(buf), "\n%s", errstr);
sprintf(buf + strlen(buf),
" in parent table, in index %.500s tuple:\n",
foreign->referenced_index->name);
if (entry) {
dtuple_sprintf(buf + strlen(buf), 1000, entry);
}
sprintf(buf + strlen(buf),
"\nBut in child table %.500s, in index %.500s, there is a record:\n",
foreign->foreign_table_name, foreign->foreign_index->name);
if (rec) {
rec_sprintf(buf + strlen(buf), 1000, rec);
}
sprintf(buf + strlen(buf), "\n");
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
}
/*************************************************************************
Reports a foreign key error to dict_foreign_err_buf when we are trying
to add an index entry to a child table. Note that the adding may be the result
of an update, too. */
static
void
row_ins_foreign_report_add_err(
/*===========================*/
que_thr_t* thr, /* in: query thread whose run_node
is an insert node */
dict_foreign_t* foreign, /* in: foreign key constraint */
rec_t* rec, /* in: a record in the parent table:
it does not match entry because we
have an error! */
dtuple_t* entry) /* in: index entry to insert in the
child table */
{
char* buf = dict_foreign_err_buf;
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf), " Transaction:\n");
trx_print(buf + strlen(buf), thr_get_trx(thr));
sprintf(buf + strlen(buf),
"Foreign key constraint fails for table %.500s:\n",
foreign->foreign_table_name);
dict_print_info_on_foreign_key_in_create_format(
foreign, buf + strlen(buf));
sprintf(buf + strlen(buf),
"\nTrying to add in child table, in index %.500s tuple:\n",
foreign->foreign_index->name);
if (entry) {
dtuple_sprintf(buf + strlen(buf), 1000, entry);
}
sprintf(buf + strlen(buf),
"\nBut in parent table %.500s, in index %.500s,\n"
"the closest match we can find is record:\n",
foreign->referenced_table_name,
foreign->referenced_index->name);
if (rec && page_rec_is_supremum(rec)) {
/* If the cursor ended on a supremum record, it is better
to report the previous record in the error message, so that
the user gets a more descriptive error message. */
rec = page_rec_get_prev(rec);
}
if (rec) {
rec_sprintf(buf + strlen(buf), 1000, rec);
}
sprintf(buf + strlen(buf), "\n");
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
}
/*************************************************************************
Perform referential actions or checks when a parent row is deleted or updated
and the constraint had an ON DELETE or ON UPDATE condition which was not
@ -453,6 +558,8 @@ row_ins_foreign_check_on_constraint(
type is != 0 */
btr_pcur_t* pcur, /* in: cursor placed on a matching
index record in the child table */
dtuple_t* entry, /* in: index entry in the parent
table */
mtr_t* mtr) /* in: mtr holding the latch of pcur
page */
{
@ -506,6 +613,10 @@ row_ins_foreign_check_on_constraint(
return(DB_SUCCESS);
}
row_ins_foreign_report_err((char*)"Trying to delete",
thr, foreign,
btr_pcur_get_rec(pcur), entry);
return(DB_ROW_IS_REFERENCED);
}
@ -523,6 +634,10 @@ row_ins_foreign_check_on_constraint(
return(DB_SUCCESS);
}
row_ins_foreign_report_err((char*)"Trying to update",
thr, foreign,
btr_pcur_get_rec(pcur), entry);
return(DB_ROW_IS_REFERENCED);
}
@ -563,14 +678,13 @@ row_ins_foreign_check_on_constraint(
}
}
/* We do not allow cyclic cascaded updating of the same
table. Check that we are not updating the same table which
is already being modified in this cascade chain. We have to
check this because the modification of the indexes of a
'parent' table may still be incomplete, and we must avoid
seeing the indexes of the parent table in an inconsistent
state! In this way we also prevent possible infinite
update loops caused by cyclic cascaded updates. */
/* We do not allow cyclic cascaded updating (DELETE is allowed,
but not UPDATE) of the same table, as this can lead to an infinite
cycle. Check that we are not updating the same table which is
already being modified in this cascade chain. We have to check
this also because the modification of the indexes of a 'parent'
table may still be incomplete, and we must avoid seeing the indexes
of the parent table in an inconsistent state! */
if (!cascade->is_delete
&& row_ins_cascade_ancestor_updates_table(cascade, table)) {
@ -580,6 +694,10 @@ row_ins_foreign_check_on_constraint(
err = DB_ROW_IS_REFERENCED;
row_ins_foreign_report_err(
(char*)"Trying an update, possibly causing a cyclic cascaded update\n"
"in the child table,", thr, foreign, btr_pcur_get_rec(pcur), entry);
goto nonstandard_exit_func;
}
@ -809,11 +927,10 @@ row_ins_check_foreign_constraint(
dictionary cache if they exist at all */
dict_table_t* table, /* in: if check_ref is TRUE, then the foreign
table, else the referenced table */
dict_index_t* index __attribute__((unused)),/* in: index in table */
dtuple_t* entry, /* in: index entry for index */
que_thr_t* thr) /* in: query thread */
{
upd_node_t* upd_node;
upd_node_t* upd_node;
dict_table_t* check_table;
dict_index_t* check_index;
ulint n_fields_cmp;
@ -824,6 +941,7 @@ row_ins_check_foreign_constraint(
int cmp;
ulint err;
ulint i;
char* buf = dict_foreign_err_buf;
mtr_t mtr;
run_again:
@ -884,6 +1002,25 @@ run_again:
if (check_table == NULL) {
if (check_ref) {
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf), " Transaction:\n");
trx_print(buf + strlen(buf), thr_get_trx(thr));
sprintf(buf + strlen(buf),
"Foreign key constraint fails for table %.500s:\n",
foreign->foreign_table_name);
dict_print_info_on_foreign_key_in_create_format(
foreign, buf + strlen(buf));
sprintf(buf + strlen(buf),
"\nTrying to add to index %.500s tuple:\n", foreign->foreign_index->name);
dtuple_sprintf(buf + strlen(buf), 1000, entry);
sprintf(buf + strlen(buf),
"\nBut the parent table %.500s does not currently exist!\n",
foreign->referenced_table_name);
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
return(DB_NO_REFERENCED_ROW);
}
@ -949,7 +1086,8 @@ run_again:
if (cmp == 0) {
if (rec_get_deleted_flag(rec)) {
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY,
err = row_ins_set_shared_rec_lock(
LOCK_ORDINARY,
rec, check_index, thr);
if (err != DB_SUCCESS) {
@ -989,13 +1127,17 @@ run_again:
err =
row_ins_foreign_check_on_constraint(
thr, foreign, &pcur, &mtr);
thr, foreign, &pcur, entry,
&mtr);
if (err != DB_SUCCESS) {
break;
}
} else {
row_ins_foreign_report_err(
(char*)"Trying to delete or update",
thr, foreign, rec, entry);
err = DB_ROW_IS_REFERENCED;
break;
}
@ -1012,6 +1154,8 @@ run_again:
if (check_ref) {
err = DB_NO_REFERENCED_ROW;
row_ins_foreign_report_add_err(
thr, foreign, rec, entry);
} else {
err = DB_SUCCESS;
}
@ -1025,6 +1169,9 @@ next_rec:
if (!moved) {
if (check_ref) {
rec = btr_pcur_get_rec(&pcur);
row_ins_foreign_report_add_err(
thr, foreign, rec, entry);
err = DB_NO_REFERENCED_ROW;
} else {
err = DB_SUCCESS;
@ -1100,7 +1247,7 @@ row_ins_check_foreign_constraints(
}
err = row_ins_check_foreign_constraint(TRUE, foreign,
table, index, entry, thr);
table, entry, thr);
if (got_s_lock) {
row_mysql_unfreeze_data_dictionary(trx);
}
@ -1116,6 +1263,48 @@ row_ins_check_foreign_constraints(
return(DB_SUCCESS);
}
/*************************************************************************
Reports a UNIQUE key error to dict_unique_err_buf so that SHOW INNODB
STATUS can print it. */
static
void
row_ins_unique_report_err(
/*======================*/
que_thr_t* thr, /* in: query thread */
rec_t* rec, /* in: a record in the index */
dtuple_t* entry, /* in: index entry to insert in the index */
dict_index_t* index) /* in: index */
{
char* buf = dict_unique_err_buf;
/* The foreign err mutex protects also dict_unique_err_buf */
mutex_enter(&dict_foreign_err_mutex);
ut_sprintf_timestamp(buf);
sprintf(buf + strlen(buf), " Transaction:\n");
trx_print(buf + strlen(buf), thr_get_trx(thr));
sprintf(buf + strlen(buf),
"Unique key constraint fails for table %.500s.\n", index->table_name);
sprintf(buf + strlen(buf),
"Trying to add in index %.500s (%lu fields unique) tuple:\n", index->name,
dict_index_get_n_unique(index));
dtuple_sprintf(buf + strlen(buf), 1000, entry);
sprintf(buf + strlen(buf),
"\nBut there is already a record:\n");
rec_sprintf(buf + strlen(buf), 1000, rec);
sprintf(buf + strlen(buf), "\n");
ut_a(strlen(buf) < DICT_FOREIGN_ERR_BUF_LEN);
mutex_exit(&dict_foreign_err_mutex);
}
/*******************************************************************
Checks if a unique key violation to rec would occur at the index entry
insert. */
@ -1246,10 +1435,8 @@ row_ins_scan_sec_index_for_duplicate(
if (cmp == 0) {
if (row_ins_dupl_error_with_rec(rec, entry, index)) {
/* printf("Duplicate key in index %s\n",
index->name);
dtuple_print(entry); */
row_ins_unique_report_err(thr, rec, entry,
index);
err = DB_DUPLICATE_KEY;
thr_get_trx(thr)->error_info = index;
@ -1344,7 +1531,8 @@ row_ins_duplicate_error_in_clust(
if (row_ins_dupl_error_with_rec(rec, entry,
cursor->index)) {
trx->error_info = cursor->index;
row_ins_unique_report_err(thr, rec, entry,
cursor->index);
return(DB_DUPLICATE_KEY);
}
}
@ -1368,6 +1556,8 @@ row_ins_duplicate_error_in_clust(
cursor->index)) {
trx->error_info = cursor->index;
row_ins_unique_report_err(thr, rec, entry,
cursor->index);
return(DB_DUPLICATE_KEY);
}
}

View File

@ -6,7 +6,7 @@ Contains also create table and other data dictionary operations.
Created 9/17/2000 Heikki Tuuri
*******************************************************/
#include "row0mysql.h"
#ifdef UNIV_NONINL
@ -289,6 +289,17 @@ handle_new_error:
"InnoDB: my.cnf and restart the database.\n");
exit(1);
} else if (err == DB_CORRUPTION) {
fprintf(stderr,
"InnoDB: We detected index corruption in an InnoDB type table.\n"
"InnoDB: You have to dump + drop + reimport the table or, in\n"
"InnoDB: a case of widespread corruption, dump all InnoDB\n"
"InnoDB: tables and recreate the whole InnoDB tablespace.\n"
"InnoDB: If the mysqld server crashes after the startup or when\n"
"InnoDB: you dump the tables, look at section 6.1 of\n"
"InnoDB: http://www.innodb.com/ibman.html for help.\n");
} else {
fprintf(stderr, "InnoDB: unknown error code %lu\n", err);
ut_a(0);
@ -337,6 +348,9 @@ row_create_prebuilt(
prebuilt->mysql_has_locked = FALSE;
prebuilt->index = NULL;
prebuilt->used_in_HANDLER = FALSE;
prebuilt->n_template = 0;
prebuilt->mysql_template = NULL;
@ -1169,7 +1183,7 @@ row_mysql_recover_tmp_table(
return(DB_ERROR);
}
if (0 == ut_memcmp(ptr, "/rsql", 5)) {
if (0 == ut_memcmp(ptr, (char*)"/rsql", 5)) {
ptr++;
*ptr = '#';
@ -1293,10 +1307,10 @@ row_create_table_for_mysql(
}
trx->op_info = (char *) "creating table";
if (0 == ut_strcmp(table->name, "mysql/host")
|| 0 == ut_strcmp(table->name, "mysql/user")
|| 0 == ut_strcmp(table->name, "mysql/db")) {
if (0 == ut_strcmp(table->name, (char*)"mysql/host")
|| 0 == ut_strcmp(table->name, (char*)"mysql/user")
|| 0 == ut_strcmp(table->name, (char*)"mysql/db")) {
fprintf(stderr,
"InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n"
@ -1316,7 +1330,7 @@ row_create_table_for_mysql(
if (namelen >= keywordlen
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
"_recover_innodb_tmp_table", keywordlen)) {
(char*)"_recover_innodb_tmp_table", keywordlen)) {
/* MySQL prevents accessing of tables whose name begins
with #sql, that is temporary tables. If mysqld crashes in
@ -1384,7 +1398,7 @@ row_create_table_for_mysql(
if (namelen >= keywordlen
&& 0 == ut_memcmp(table->name + namelen - keywordlen,
"innodb_mem_validate", keywordlen)) {
(char*)"innodb_mem_validate", keywordlen)) {
/* We define here a debugging feature intended for
developers */
@ -1494,7 +1508,7 @@ row_create_index_for_mysql(
if (namelen >= keywordlen
&& 0 == ut_memcmp(
index->table_name + namelen - keywordlen,
"_recover_innodb_tmp_table", keywordlen)) {
(char*)"_recover_innodb_tmp_table", keywordlen)) {
return(DB_SUCCESS);
}
@ -1599,7 +1613,7 @@ row_table_add_foreign_constraints(
if (namelen >= keywordlen
&& 0 == ut_memcmp(
name + namelen - keywordlen,
"_recover_innodb_tmp_table", keywordlen)) {
(char*)"_recover_innodb_tmp_table", keywordlen)) {
return(DB_SUCCESS);
}
@ -1663,7 +1677,7 @@ row_drop_table_for_mysql_in_background(
the InnoDB data dictionary get out-of-sync if the user runs
with innodb_flush_log_at_trx_commit = 0 */
log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
trx_commit_for_mysql(trx);
@ -1821,7 +1835,6 @@ row_drop_table_for_mysql(
ulint len;
ulint namelen;
ulint keywordlen;
ulint rounds = 0;
ibool locked_dictionary = FALSE;
char buf[10000];
@ -2168,7 +2181,7 @@ row_is_mysql_tmp_table_name(
ulint i;
for (i = 0; i <= ut_strlen(name) - 5; i++) {
if (ut_memcmp(name + i, "/#sql", 5) == 0) {
if (ut_memcmp(name + i, (char*)"/#sql", 5) == 0) {
return(TRUE);
}
@ -2190,12 +2203,16 @@ row_rename_table_for_mysql(
{
dict_table_t* table;
que_thr_t* thr;
que_t* graph;
que_t* graph = NULL;
ulint err;
char* str1;
char* str2;
char* str3;
mem_heap_t* heap = NULL;
char** constraints_to_drop = NULL;
ulint n_constraints_to_drop = 0;
ulint len;
ulint i;
char buf[10000];
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
@ -2213,10 +2230,10 @@ row_rename_table_for_mysql(
trx_commit_for_mysql(trx);
return(DB_ERROR);
}
if (0 == ut_strcmp(new_name, "mysql/host")
|| 0 == ut_strcmp(new_name, "mysql/user")
|| 0 == ut_strcmp(new_name, "mysql/db")) {
if (0 == ut_strcmp(new_name, (char*)"mysql/host")
|| 0 == ut_strcmp(new_name, (char*)"mysql/user")
|| 0 == ut_strcmp(new_name, (char*)"mysql/db")) {
fprintf(stderr,
"InnoDB: Error: trying to create a MySQL system table %s of type InnoDB.\n"
@ -2230,6 +2247,19 @@ row_rename_table_for_mysql(
trx->op_info = (char *) "renaming table";
trx_start_if_not_started(trx);
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
row_mysql_lock_data_dictionary(trx);
table = dict_table_get_low(old_name);
if (!table) {
err = DB_TABLE_NOT_FOUND;
goto funct_exit;
}
str1 = (char *)
"PROCEDURE RENAME_TABLE_PROC () IS\n"
"new_table_name CHAR;\n"
@ -2242,14 +2272,43 @@ row_rename_table_for_mysql(
if (row_is_mysql_tmp_table_name(new_name)) {
/* We want to preserve the original foreign key
constraint definitions despite the name change */
/* MySQL is doing an ALTER TABLE command and it renames the
original table to a temporary table name. We want to preserve
the original foreign key constraint definitions despite the
name change. An exception is those constraints for which
the ALTER TABLE contained DROP FOREIGN KEY <foreign key id>.*/
str3 = (char*)
"';\n"
"UPDATE SYS_TABLES SET NAME = new_table_name\n"
"WHERE NAME = old_table_name;\n"
"END;\n";
heap = mem_heap_create(100);
err = dict_foreign_parse_drop_constraints(heap, trx,
table,
&n_constraints_to_drop,
&constraints_to_drop);
if (err != DB_SUCCESS) {
goto funct_exit;
}
str3 = mem_heap_alloc(heap,
1000 + 500 * n_constraints_to_drop);
*str3 = '\0';
sprintf(str3,
"';\n"
"UPDATE SYS_TABLES SET NAME = new_table_name\n"
"WHERE NAME = old_table_name;\n");
for (i = 0; i < n_constraints_to_drop; i++) {
sprintf(str3 + strlen(str3),
"DELETE FROM SYS_FOREIGN_COLS WHERE ID = '%s';\n"
"DELETE FROM SYS_FOREIGN WHERE ID = '%s';\n",
constraints_to_drop[i],
constraints_to_drop[i]);
}
sprintf(str3 + strlen(str3),
"END;\n");
ut_a(strlen(str3) < 1000 + 500 * n_constraints_to_drop);
} else {
str3 = (char*)
"';\n"
@ -2280,13 +2339,6 @@ row_rename_table_for_mysql(
ut_memcpy(buf + len, str3, ut_strlen(str3) + 1);
/* Serialize data dictionary operations with dictionary mutex:
no deadlocks can occur then in these operations */
row_mysql_lock_data_dictionary(trx);
table = dict_table_get_low(old_name);
graph = pars_sql(buf);
ut_a(graph);
@ -2296,12 +2348,6 @@ row_rename_table_for_mysql(
graph->fork_type = QUE_FORK_MYSQL_INTERFACE;
if (!table) {
err = DB_TABLE_NOT_FOUND;
goto funct_exit;
}
ut_a(thr = que_fork_start_command(graph, SESS_COMM_EXECUTE, 0));
que_run_threads(thr);
@ -2342,6 +2388,13 @@ row_rename_table_for_mysql(
if (row_is_mysql_tmp_table_name(old_name)) {
/* MySQL is doing an ALTER TABLE command and it
renames the created temporary table to the name
of the original table. In the ALTER TABLE we maybe
created some FOREIGN KEY constraints for the temporary
table. But we want to load also the foreign key
constraint definitions for the original table name. */
err = dict_load_foreigns(new_name);
if (err != DB_SUCCESS) {
@ -2367,7 +2420,13 @@ row_rename_table_for_mysql(
funct_exit:
row_mysql_unlock_data_dictionary(trx);
que_graph_free(graph);
if (graph) {
que_graph_free(graph);
}
if (heap) {
mem_heap_free(heap);
}
trx_commit_for_mysql(trx);

View File

@ -2619,6 +2619,24 @@ row_search_for_mysql(
printf("N tables locked %lu\n", trx->mysql_n_tables_locked);
*/
/*-------------------------------------------------------------*/
/* PHASE 0: Release a possible s-latch we are holding on the
adaptive hash index latch if there is someone waiting behind */
if (trx->has_search_latch
&& btr_search_latch.writer != RW_LOCK_NOT_LOCKED) {
/* There is an x-latch request on the adaptive hash index:
release the s-latch to reduce starvation and wait for
BTR_SEA_TIMEOUT rounds before trying to keep it again over
calls from MySQL */
rw_lock_s_unlock(&btr_search_latch);
trx->has_search_latch = FALSE;
trx->search_latch_timeout = BTR_SEA_TIMEOUT;
}
/*-------------------------------------------------------------*/
/* PHASE 1: Try to pop the row from the prefetch cache */
@ -2685,16 +2703,31 @@ row_search_for_mysql(
mode = pcur->search_mode;
}
if ((direction == ROW_SEL_NEXT || direction == ROW_SEL_PREV)
&& pcur->old_stored != BTR_PCUR_OLD_STORED) {
/* MySQL sometimes seems to do fetch next or fetch prev even
if the search condition is unique; this can, for example,
happen with the HANDLER commands; we do not always store the
pcur position in this case, so we cannot restore cursor
position, and must return immediately */
/* printf("%s record not found 1\n", index->name); */
trx->op_info = (char *) "";
return(DB_RECORD_NOT_FOUND);
}
mtr_start(&mtr);
/* In a search where at most one record in the index may match, we
can use a LOCK_REC_NOT_GAP type record lock when locking a non-delete
can use a LOCK_REC_NOT_GAP type record lock when locking a non-delete-
marked matching record.
Note that in a unique secondary index there may be different delete
Note that in a unique secondary index there may be different delete-
marked versions of a record where only the primary key values differ:
thus in a secondary index we must use next-key locks when locking
delete marked records. */
delete-marked records. */
if (match_mode == ROW_SEL_EXACT
&& index->type & DICT_UNIQUE
@ -2715,25 +2748,9 @@ row_search_for_mysql(
if (unique_search
&& index->type & DICT_CLUSTERED
&& !prebuilt->templ_contains_blob
&& !prebuilt->used_in_HANDLER
&& (prebuilt->mysql_row_len < UNIV_PAGE_SIZE / 8)) {
if (direction == ROW_SEL_NEXT) {
/* MySQL sometimes seems to do fetch next even
if the search condition is unique; we do not store
pcur position in this case, so we cannot
restore cursor position, and must return
immediately */
mtr_commit(&mtr);
/* printf("%s record not found 1\n", index->name); */
trx->op_info = (char *) "";
return(DB_RECORD_NOT_FOUND);
}
ut_a(direction == 0); /* We cannot do fetch prev, as we have
not stored the cursor position */
mode = PAGE_CUR_GE;
unique_search_from_clust_index = TRUE;
@ -2754,23 +2771,7 @@ row_search_for_mysql(
NOT prepared to inserts interleaved with the SELECT,
and if we try that, we can deadlock on the adaptive
hash index semaphore! */
if (btr_search_latch.writer != RW_LOCK_NOT_LOCKED) {
/* There is an x-latch request: release
a possible s-latch to reduce starvation
and wait for BTR_SEA_TIMEOUT rounds before
trying to keep it again over calls from
MySQL */
if (trx->has_search_latch) {
rw_lock_s_unlock(&btr_search_latch);
trx->has_search_latch = FALSE;
}
trx->search_latch_timeout = BTR_SEA_TIMEOUT;
goto no_shortcut;
}
#ifndef UNIV_SEARCH_DEBUG
if (!trx->has_search_latch) {
rw_lock_s_lock(&btr_search_latch);
@ -2806,6 +2807,10 @@ row_search_for_mysql(
}
trx->op_info = (char *) "";
/* NOTE that we do NOT store the cursor
position */
return(DB_SUCCESS);
} else if (shortcut == SEL_EXHAUSTED) {
@ -2825,6 +2830,10 @@ row_search_for_mysql(
}
trx->op_info = (char *) "";
/* NOTE that we do NOT store the cursor
position */
return(DB_RECORD_NOT_FOUND);
}
@ -2833,7 +2842,6 @@ row_search_for_mysql(
}
}
no_shortcut:
/*-------------------------------------------------------------*/
/* PHASE 3: Open or restore index cursor position */
@ -3206,6 +3214,7 @@ rec_loop:
&& prebuilt->select_lock_type == LOCK_NONE
&& !prebuilt->templ_contains_blob
&& !prebuilt->clust_index_was_generated
&& !prebuilt->used_in_HANDLER
&& prebuilt->template_type
!= ROW_MYSQL_DUMMY_TEMPLATE) {
@ -3214,7 +3223,9 @@ rec_loop:
update, that is why we require ...lock_type == LOCK_NONE.
Since we keep space in prebuilt only for the BLOBs of
a single row, we cannot cache rows in the case there
are BLOBs in the fields to be fetched. */
are BLOBs in the fields to be fetched. In HANDLER we do
not cache rows because there the cursor is a scrollable
cursor. */
row_sel_push_cache_row_for_mysql(prebuilt, rec);
@ -3243,11 +3254,16 @@ rec_loop:
}
}
got_row:
/* TODO: should we in every case store the cursor position, even
if this is just a join, for example? */
/* We have an optimization to save CPU time: if this is a consistent
read on a unique condition on the clustered index, then we do not
store the pcur position, because any fetch next or prev will anyway
return 'end of file'. An exception is the MySQL HANDLER command
where the user can move the cursor with PREV or NEXT even after
a unique search. */
if (!unique_search_from_clust_index
|| prebuilt->select_lock_type == LOCK_X) {
|| prebuilt->select_lock_type == LOCK_X
|| prebuilt->used_in_HANDLER) {
/* Inside an update always store the cursor position */

View File

@ -218,7 +218,7 @@ row_upd_check_references_constraints(
being dropped while the check is running. */
err = row_ins_check_foreign_constraint(FALSE, foreign,
table, index, entry, thr);
table, entry, thr);
if (foreign->foreign_table) {
mutex_enter(&(dict_sys->mutex));

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libsrv.a
noinst_LIBRARIES = libsrv.a
libsrv_a_SOURCES = srv0srv.c srv0que.c srv0start.c

View File

@ -162,6 +162,13 @@ char* srv_file_flush_method_str = NULL;
ulint srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
ulint srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
/* The InnoDB main thread tries to keep the ratio of modified pages
in the buffer pool to all database pages in the buffer pool smaller than
the following number. But it is not guaranteed that the value stays below
that during a time of heavy update/insert activity. */
ulint srv_max_buf_pool_modified_pct = 90;
/* If the following is != 0 we do not allow inserts etc. This protects
the user from forgetting the innodb_force_recovery keyword to my.cnf */
@ -1881,11 +1888,11 @@ retry:
/* Go to wait for the event; when a thread leaves InnoDB it will
release this thread */
trx->op_info = "waiting in InnoDB queue";
trx->op_info = (char*)"waiting in InnoDB queue";
os_event_wait(slot->event);
trx->op_info = "";
trx->op_info = (char*)"";
os_fast_mutex_lock(&srv_conc_mutex);
@ -2368,12 +2375,35 @@ srv_sprintf_innodb_monitor(
buf = buf + strlen(buf);
ut_a(buf < buf_end + 1500);
buf += sprintf(buf, "------------\n"
"TRANSACTIONS\n"
"------------\n");
if (*dict_foreign_err_buf != '\0') {
buf += sprintf(buf,
"------------------------\n"
"LATEST FOREIGN KEY ERROR\n"
"------------------------\n");
if (buf_end - buf > 6000) {
buf+= sprintf(buf, "%.4000s", dict_foreign_err_buf);
}
}
ut_a(buf < buf_end + 1500);
if (*dict_unique_err_buf != '\0') {
buf += sprintf(buf,
"---------------------------------------------------------------\n"
"LATEST UNIQUE KEY ERROR (is masked in REPLACE or INSERT IGNORE)\n"
"---------------------------------------------------------------\n");
if (buf_end - buf > 6000) {
buf+= sprintf(buf, "%.4000s", dict_unique_err_buf);
}
}
ut_a(buf < buf_end + 1500);
lock_print_info(buf, buf_end);
buf = buf + strlen(buf);
buf += sprintf(buf, "--------\n"
"FILE I/O\n"
"--------\n");
@ -2777,6 +2807,7 @@ srv_master_thread(
ulint n_ios_old;
ulint n_ios_very_old;
ulint n_pend_ios;
ibool skip_sleep = FALSE;
ulint i;
UT_NOT_USED(arg);
@ -2794,24 +2825,42 @@ srv_master_thread(
os_event_set(srv_sys->operational);
loop:
/*****************************************************************/
/* ---- When there is database activity by users, we cycle in this
loop */
srv_main_thread_op_info = (char*) "reserving kernel mutex";
n_ios_very_old = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
mutex_enter(&kernel_mutex);
/* Store the user activity counter at the start of this loop */
old_activity_count = srv_activity_count;
mutex_exit(&kernel_mutex);
/* We run purge and a batch of ibuf_contract every 10 seconds, even
if the server were active: */
if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
goto suspend_thread;
}
/* ---- We run the following loop approximately once per second
when there is database activity */
skip_sleep = FALSE;
for (i = 0; i < 10; i++) {
n_ios_old = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
srv_main_thread_op_info = (char*)"sleeping";
os_thread_sleep(1000000);
if (!skip_sleep) {
os_thread_sleep(1000000);
}
skip_sleep = FALSE;
/* ALTER TABLE in MySQL requires on Unix that the table handler
can drop tables lazily after there no longer are SELECT
@ -2824,9 +2873,9 @@ loop:
srv_main_thread_op_info = (char*)"";
if (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND) {
if (srv_fast_shutdown && srv_shutdown_state > 0) {
goto suspend_thread;
goto background_loop;
}
/* We flush the log once in a second even if no commit
@ -2834,10 +2883,9 @@ loop:
at transaction commit */
srv_main_thread_op_info = (char*)"flushing log";
log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
log_flush_to_disk();
log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
/* If there were less than 10 i/os during the
/* If there were less than 5 i/os during the
one second sleep, we assume that there is free
disk i/o capacity available, and it makes sense to
do an insert buffer merge. */
@ -2846,35 +2894,45 @@ loop:
+ log_sys->n_pending_writes;
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
+ buf_pool->n_pages_written;
if (n_pend_ios < 3 && (n_ios - n_ios_old < 10)) {
if (n_pend_ios < 3 && (n_ios - n_ios_old < 5)) {
srv_main_thread_op_info =
(char*)"doing insert buffer merge";
ibuf_contract_for_n_pages(TRUE, 5);
srv_main_thread_op_info =
(char*)"flushing log";
log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
log_flush_to_disk();
log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP,
TRUE);
}
if (srv_fast_shutdown && srv_shutdown_state > 0) {
goto background_loop;
if (buf_get_modified_ratio_pct() >
srv_max_buf_pool_modified_pct) {
/* Try to keep the number of modified pages in the
buffer pool under the limit wished by the user */
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100,
ut_dulint_max);
/* If we had to do the flush, it may have taken
even more than 1 second, and also, there may be more
to flush. Do not sleep 1 second during the next
iteration of this loop. */
skip_sleep = TRUE;
}
if (srv_activity_count == old_activity_count) {
if (srv_print_thread_releases) {
printf("Master thread wakes up!\n");
}
/* There is no user activity at the moment, go to
the background loop */
goto background_loop;
}
}
if (srv_print_thread_releases) {
printf("Master thread wakes up!\n");
}
/* ---- We perform the following code approximately once per
10 seconds when there is database activity */
#ifdef MEM_PERIODIC_CHECK
/* Check magic numbers of every allocated mem block once in 10
@ -2883,7 +2941,7 @@ loop:
#endif
/* If there were less than 200 i/os during the 10 second period,
we assume that there is free disk i/o capacity available, and it
makes sense to do a buffer pool flush. */
makes sense to flush 100 pages. */
n_pend_ios = buf_get_n_pending_ios() + log_sys->n_pending_writes;
n_ios = log_sys->n_log_ios + buf_pool->n_pages_read
@ -2891,11 +2949,10 @@ loop:
if (n_pend_ios < 3 && (n_ios - n_ios_very_old < 200)) {
srv_main_thread_op_info = (char*) "flushing buffer pool pages";
buf_flush_batch(BUF_FLUSH_LIST, 50, ut_dulint_max);
buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max);
srv_main_thread_op_info = (char*) "flushing log";
log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
log_flush_to_disk();
log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
}
/* We run a batch of insert buffer merge every 10 seconds,
@ -2905,8 +2962,7 @@ loop:
ibuf_contract_for_n_pages(TRUE, 5);
srv_main_thread_op_info = (char*)"flushing log";
log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
log_flush_to_disk();
log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP, TRUE);
/* We run a full purge every 10 seconds, even if the server
were active */
@ -2930,27 +2986,32 @@ loop:
if (difftime(current_time, last_flush_time) > 1) {
srv_main_thread_op_info = (char*) "flushing log";
log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP);
log_flush_to_disk();
log_write_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP,
TRUE);
last_flush_time = current_time;
}
}
background_loop:
/* In this loop we run background operations when the server
is quiet and we also come here about once in 10 seconds */
srv_main_thread_op_info = (char*)"doing background drop tables";
n_tables_to_drop = row_drop_tables_for_mysql_in_background();
srv_main_thread_op_info = (char*)"";
srv_main_thread_op_info = (char*)"flushing buffer pool pages";
/* Flush a few oldest pages to make the checkpoint younger */
/* Flush a few oldest pages to make a new checkpoint younger */
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10, ut_dulint_max);
if (buf_get_modified_ratio_pct() > 70) {
/* If there are lots of modified pages in the buffer pool
(> 70 %), we assume we can afford reserving the disk(s) for
the time it requires to flush 100 pages */
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100,
ut_dulint_max);
} else {
/* Otherwise, we only flush a small number of pages so that
we do not unnecessarily use much disk i/o capacity from
other work */
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 10,
ut_dulint_max);
}
srv_main_thread_op_info = (char*)"making checkpoint";
@ -2961,16 +3022,31 @@ background_loop:
srv_main_thread_op_info = (char*)"reserving kernel mutex";
mutex_enter(&kernel_mutex);
/* ---- When there is database activity, we jump from here back to
the start of loop */
if (srv_activity_count != old_activity_count) {
mutex_exit(&kernel_mutex);
goto loop;
}
old_activity_count = srv_activity_count;
mutex_exit(&kernel_mutex);
/* If the database is quiet, we enter the background loop */
/*****************************************************************/
background_loop:
/* ---- In this loop we run background operations when the server
is quiet from user activity */
/* The server has been quiet for a while: start running background
operations */
srv_main_thread_op_info = (char*)"doing background drop tables";
n_tables_to_drop = row_drop_tables_for_mysql_in_background();
srv_main_thread_op_info = (char*)"purging";
if (srv_fast_shutdown && srv_shutdown_state > 0) {
@ -3005,6 +3081,7 @@ background_loop:
}
mutex_exit(&kernel_mutex);
flush_loop:
srv_main_thread_op_info = (char*)"flushing buffer pool pages";
n_pages_flushed = buf_flush_batch(BUF_FLUSH_LIST, 100, ut_dulint_max);
@ -3017,13 +3094,22 @@ background_loop:
}
mutex_exit(&kernel_mutex);
srv_main_thread_op_info = (char*) "waiting for buffer pool flush to end";
srv_main_thread_op_info =
(char*) "waiting for buffer pool flush to end";
buf_flush_wait_batch_end(BUF_FLUSH_LIST);
srv_main_thread_op_info = (char*)"making checkpoint";
log_checkpoint(TRUE, FALSE);
if (buf_get_modified_ratio_pct() > srv_max_buf_pool_modified_pct) {
/* Try to keep the number of modified pages in the
buffer pool under the limit wished by the user */
goto flush_loop;
}
srv_main_thread_op_info = (char*)"reserving kernel mutex";
mutex_enter(&kernel_mutex);
@ -3038,15 +3124,24 @@ background_loop:
log_archive_do(FALSE, &n_bytes_archived);
/* Keep looping in the background loop if still work to do */
if (srv_fast_shutdown && srv_shutdown_state > 0) {
if (n_tables_to_drop + n_pages_flushed
+ n_bytes_archived != 0) {
/* If we are doing a fast shutdown (= the default)
we do not do purge or insert buffer merge. But we
flush the buffer pool completely to disk. */
goto background_loop;
}
} else if (n_tables_to_drop +
n_pages_purged + n_bytes_merged + n_pages_flushed
n_pages_purged + n_bytes_merged + n_pages_flushed
+ n_bytes_archived != 0) {
/* In a 'slow' shutdown we run purge and the insert buffer
merge to completion */
goto background_loop;
}
@ -3078,6 +3173,9 @@ suspend_thread:
os_event_wait(event);
/* When there is user activity, InnoDB will set the event and the main
thread goes back to loop: */
goto loop;
#ifndef __WIN__

View File

@ -161,13 +161,13 @@ srv_parse_data_file_paths_and_sizes(
}
if (strlen(str) >= ut_strlen(":autoextend")
&& 0 == ut_memcmp(str, ":autoextend",
&& 0 == ut_memcmp(str, (char*)":autoextend",
ut_strlen(":autoextend"))) {
str += ut_strlen(":autoextend");
if (strlen(str) >= ut_strlen(":max:")
&& 0 == ut_memcmp(str, ":max:",
&& 0 == ut_memcmp(str, (char*)":max:",
ut_strlen(":max:"))) {
str += ut_strlen(":max:");
@ -265,7 +265,7 @@ srv_parse_data_file_paths_and_sizes(
(*data_file_sizes)[i] = size;
if (strlen(str) >= ut_strlen(":autoextend")
&& 0 == ut_memcmp(str, ":autoextend",
&& 0 == ut_memcmp(str, (char*)":autoextend",
ut_strlen(":autoextend"))) {
*is_auto_extending = TRUE;
@ -273,7 +273,7 @@ srv_parse_data_file_paths_and_sizes(
str += ut_strlen(":autoextend");
if (strlen(str) >= ut_strlen(":max:")
&& 0 == ut_memcmp(str, ":max:",
&& 0 == ut_memcmp(str, (char*)":max:",
ut_strlen(":max:"))) {
str += ut_strlen(":max:");
@ -864,6 +864,7 @@ open_or_create_data_files(
return(DB_SUCCESS);
}
#ifdef notdefined
/*********************************************************************
This thread is used to measure contention of latches. */
static
@ -935,6 +936,7 @@ test_measure_cont(
return(0);
}
#endif
/********************************************************************
Starts InnoDB and creates a new database if database files
@ -1053,20 +1055,24 @@ innobase_start_or_create_for_mysql(void)
srv_win_file_flush_method = SRV_WIN_IO_UNBUFFERED;
#ifndef __WIN__
} else if (0 == ut_strcmp(srv_file_flush_method_str, "fdatasync")) {
} else if (0 == ut_strcmp(srv_file_flush_method_str,
(char*)"fdatasync")) {
srv_unix_file_flush_method = SRV_UNIX_FDATASYNC;
} else if (0 == ut_strcmp(srv_file_flush_method_str, "O_DSYNC")) {
} else if (0 == ut_strcmp(srv_file_flush_method_str,
(char*)"O_DSYNC")) {
srv_unix_file_flush_method = SRV_UNIX_O_DSYNC;
} else if (0 == ut_strcmp(srv_file_flush_method_str,
"littlesync")) {
(char*)"littlesync")) {
srv_unix_file_flush_method = SRV_UNIX_LITTLESYNC;
} else if (0 == ut_strcmp(srv_file_flush_method_str, "nosync")) {
} else if (0 == ut_strcmp(srv_file_flush_method_str,
(char*)"nosync")) {
srv_unix_file_flush_method = SRV_UNIX_NOSYNC;
#else
} else if (0 == ut_strcmp(srv_file_flush_method_str, "normal")) {
} else if (0 == ut_strcmp(srv_file_flush_method_str,
(char*)"normal")) {
srv_win_file_flush_method = SRV_WIN_IO_NORMAL;
os_aio_use_native_aio = FALSE;
@ -1196,7 +1202,14 @@ innobase_start_or_create_for_mysql(void)
&max_flushed_lsn, &max_arch_log_no,
&sum_of_new_sizes);
if (err != DB_SUCCESS) {
fprintf(stderr, "InnoDB: Could not open data files\n");
fprintf(stderr,
"InnoDB: Could not open or create data files.\n"
"InnoDB: If you tried to add new data files, and it failed here,\n"
"InnoDB: you should now edit innodb_data_file_path in my.cnf back\n"
"InnoDB: to what it was, and remove the new ibdata files InnoDB created\n"
"InnoDB: in this failed attempt. InnoDB only wrote those files full of\n"
"InnoDB: zeros, but did not yet use them in any way. But be careful: do not\n"
"InnoDB: remove old data files which contain your precious data!\n");
return((int) err);
}
@ -1207,7 +1220,10 @@ innobase_start_or_create_for_mysql(void)
and restore them from the doublewrite buffer if
possible */
trx_sys_doublewrite_restore_corrupt_pages();
if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) {
trx_sys_doublewrite_restore_corrupt_pages();
}
}
srv_normalize_path_for_win(srv_arch_dir);
@ -1478,7 +1494,9 @@ innobase_start_or_create_for_mysql(void)
fprintf(stderr,
"InnoDB: !!! innodb_force_recovery is set to %lu !!!\n",
srv_force_recovery);
}
}
fflush(stderr);
return((int) DB_SUCCESS);
}

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libsync.a
noinst_LIBRARIES = libsync.a
libsync_a_SOURCES = sync0arr.c sync0ipm.c sync0rw.c sync0sync.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libthr.a
noinst_LIBRARIES = libthr.a
libthr_a_SOURCES = thr0loc.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libtrx.a
noinst_LIBRARIES = libtrx.a
libtrx_a_SOURCES = trx0purge.c trx0rec.c trx0roll.c trx0rseg.c\
trx0sys.c trx0trx.c trx0undo.c

View File

@ -340,7 +340,6 @@ trx_sys_doublewrite_restore_corrupt_pages(void)
/* It is an unwritten doublewrite buffer page:
do nothing */
} else {
/* Read in the actual page from the data files */
@ -357,9 +356,19 @@ trx_sys_doublewrite_restore_corrupt_pages(void)
"InnoDB: Trying to recover it from the doublewrite buffer.\n");
if (buf_page_is_corrupted(page)) {
fprintf(stderr,
"InnoDB: Dump of the page:\n");
buf_page_print(read_buf);
fprintf(stderr,
"InnoDB: Dump of corresponding page in doublewrite buffer:\n");
buf_page_print(page);
fprintf(stderr,
"InnoDB: Also the page in the doublewrite buffer is corrupt.\n"
"InnoDB: Cannot continue operation.\n");
"InnoDB: Cannot continue operation.\n"
"InnoDB: You can try to recover the database with the my.cnf\n"
"InnoDB: option:\n"
"InnoDB: set-variable=innodb_force_recovery=6\n");
exit(1);
}

View File

@ -89,6 +89,8 @@ trx_create(
trx->check_foreigns = TRUE;
trx->check_unique_secondary = TRUE;
trx->flush_log_later = FALSE;
trx->dict_operation = FALSE;
trx->mysql_thd = NULL;
@ -102,8 +104,6 @@ trx_create(
trx->mysql_master_log_file_name = "";
trx->mysql_master_log_pos = 0;
trx->ignore_duplicates_in_insert = FALSE;
mutex_create(&(trx->undo_mutex));
mutex_set_level(&(trx->undo_mutex), SYNC_TRX_UNDO);
@ -782,13 +782,26 @@ trx_commit_off_kernel(
/*-------------------------------------*/
/* Most MySQL users run with srv_flush_.. set to FALSE: */
/* Most MySQL users run with srv_flush_.. set to 0: */
if (srv_flush_log_at_trx_commit) {
log_flush_up_to(lsn, LOG_WAIT_ONE_GROUP);
if (srv_flush_log_at_trx_commit != 0) {
if (srv_unix_file_flush_method != SRV_UNIX_NOSYNC
&& srv_flush_log_at_trx_commit != 2
&& !trx->flush_log_later) {
/* Write the log to the log files AND flush
them to disk */
log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE);
} else {
/* Write the log but do not flush it to disk */
log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, FALSE);
}
}
trx->commit_lsn = lsn;
/*-------------------------------------*/
mutex_enter(&kernel_mutex);
@ -1469,6 +1482,33 @@ trx_commit_for_mysql(
return(0);
}
/**************************************************************************
If required, flushes the log to disk if we called trx_commit_for_mysql()
with trx->flush_log_later == TRUE. */
ulint
trx_commit_complete_for_mysql(
/*==========================*/
/* out: 0 or error number */
trx_t* trx) /* in: trx handle */
{
ut_a(trx);
if (srv_flush_log_at_trx_commit == 1
&& srv_unix_file_flush_method != SRV_UNIX_NOSYNC) {
trx->op_info = (char *) "flushing log";
/* Flush the log files to disk */
log_write_up_to(trx->commit_lsn, LOG_WAIT_ONE_GROUP, TRUE);
trx->op_info = (char *) "";
}
return(0);
}
/**************************************************************************
Marks the latest SQL statement ended. */

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libusr.a
noinst_LIBRARIES = libusr.a
libusr_a_SOURCES = usr0sess.c

View File

@ -17,7 +17,7 @@
include ../include/Makefile.i
libs_LIBRARIES = libut.a
noinst_LIBRARIES = libut.a
libut_a_SOURCES = ut0byte.c ut0dbg.c ut0mem.c ut0rnd.c ut0ut.c

View File

@ -206,7 +206,7 @@ ut_get_year_month_day(
cal_tm_ptr = localtime(&tm);
*year = (ulint)cal_tm_ptr->tm_year;
*year = (ulint)cal_tm_ptr->tm_year + 1900;
*month = (ulint)cal_tm_ptr->tm_mon + 1;
*day = (ulint)cal_tm_ptr->tm_mday;
#endif

View File

@ -124,12 +124,7 @@ EXPORTS
mysql_autocommit
load_defaults
free_defaults
my_path

View File

@ -66,7 +66,7 @@ TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
#define closesocket(A) close(A)
#endif
void mysql_once_init(void);
void mysqld_once_init(void);
static void end_server(MYSQL *mysql);
static void append_wild(char *to,char *end,const char *wild);
static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
@ -373,7 +373,7 @@ static void mysql_read_default_options(struct st_mysql_options *options,
MYSQL * STDCALL
mysql_init(MYSQL *mysql)
{
mysql_once_init();
mysqld_once_init();
if (!mysql)
{
if (!(mysql=(MYSQL*) my_malloc(sizeof(*mysql),MYF(MY_WME | MY_ZEROFILL))))
@ -386,7 +386,7 @@ mysql_init(MYSQL *mysql)
}
void mysql_once_init()
void mysqld_once_init()
{
if (!mysql_client_init)
{

View File

@ -19,7 +19,7 @@
man_MANS = mysql.1 isamchk.1 isamlog.1 mysql_zap.1 mysqlaccess.1 \
mysqladmin.1 mysqld.1 mysqld_multi.1 mysqldump.1 mysqlshow.1 \
perror.1 replace.1 mysqld_safe.1
perror.1 replace.1 mysqld_safe.1 mysql_fix_privilege_tables.1
EXTRA_DIST = $(man_MANS)

View File

@ -1,4 +1,4 @@
.TH isamchk 1 "19 December 2000" "MySQL 3.23" "MySQL database"
.TH isamchk 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
.BR isamchk
\- Description, check and repair of ISAM tables.

View File

@ -1,4 +1,4 @@
.TH isamlog 1 "19 December 2000" "MySQL 3.23" "MySQL database"
.TH isamlog 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
isamlog - Write info about whats in a nisam log file.
.SH USAGE

View File

@ -1,4 +1,4 @@
.TH mysql 1 "19 December 2000" "MySQL 3.23" "MySQL database"
.TH mysql 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
mysql \- text-based client for mysqld, a SQL-based relational database daemon
.SH SYNOPSIS

View File

@ -0,0 +1,23 @@
.TH mysql 1 "17 March 2003" "MySQL 4.0" "MySQL database"
.SH NAME
mysql_fix_privilege_tables \- Fixes MySQL privilege tables.
.SH SYNOPSIS
mysql_fix_privilege_tables [options]
.SH DESCRIPTION
This scripts updates the mysql.user, mysql.db, mysql.host and the
mysql.func tables to MySQL 3.22.14 and above.
This is needed if you want to use the new GRANT functions,
CREATE AGGREGATE FUNCTION or want to use the more secure passwords in 3.23
If you get 'Access denied' errors, you should run this script again
and give the MySQL root user password as an argument!
For more information start the program with '--help'.
.SH "SEE ALSO"
mysql (1), mysqld (1)
.SH AUTHOR
This manpage was written by Christian Hammers <ch@debian.org>.
MySQL is available at http://www.mysql.com/.
.\" end of man page

View File

@ -1,4 +1,4 @@
.TH zap 1 "19 December 2000" "MySQL 3.23" "MySQL database"
.TH zap 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
zap - a perl script used to kill processes
.SH USAGE

View File

@ -1,4 +1,4 @@
.TH mysqlaccess 1 "19 December 2000" "MySQL 3.23" "MySQL database"
.TH mysqlaccess 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
.BR mysqlaccess
\- Create new users to mysql.

View File

@ -1,4 +1,4 @@
.TH mysqladmin 1 "19 December 2000" "MySQL 3.23" "MySQL database"
.TH mysqladmin 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
mysqladmin [OPTIONS] command command.... \- A utility for performing administrative operations
.SH OPTION SYNOPSIS

View File

@ -1,4 +1,4 @@
.TH mysqld 1 "19 December 2000" "MySQL 3.23" "MySQL database"
.TH mysqld 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
.BR mysqld
\- Starts the MySQL server demon

View File

@ -1,4 +1,4 @@
.TH mysqld_multi 1 "19 December 2000" "MySQL 3.23" "MySQL database"
.TH mysqld_multi 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
mysqld_multi - is meant for managing several mysqld processes running in different UNIX sockets and TCP/IP ports.
.SH USAGE

View File

@ -1,4 +1,4 @@
.TH safe_mysqld 1 "19 December 2000" "MySQL 3.23" "MySQL database"
.TH safe_mysqld 1 "19 December 2000" "MySQL 4.0" "MySQL database"
.SH NAME
mysqld_safe \- start the mysqld daemon on Unix.
.SH SYNOPSIS

Some files were not shown because too many files have changed in this diff Show More