mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 05:22:25 +01:00
Merge mysql.com:/home/pz/mysql/mysql-4.0-root
into mysql.com:/home/pz/mysql/mysql-4.0
This commit is contained in:
commit
2440182b1e
79 changed files with 1631 additions and 542 deletions
|
@ -3554,10 +3554,13 @@ string) in it instead. (This behaviour can, however, be changed with the
|
|||
-DDONT_USE_DEFAULT_FIELDS compile option.)
|
||||
|
||||
@item
|
||||
MySQL allows you to store some wrong date values into
|
||||
@code{DATE} and @code{DATETIME} columns (like 2000-02-31 or 2000-02-00).
|
||||
If the date is totally wrong, MySQL Server will store the special
|
||||
0000-00-00 date value in the column.
|
||||
MySQL allows you to store some wrong date values into @code{DATE} and
|
||||
@code{DATETIME} columns (like 2000-02-31 or 2000-02-00). The idea is
|
||||
that it's not the SQL server job to vaildate date. If MySQL can store a
|
||||
date and retrieve exactly the same date, then MySQL will store the
|
||||
date. If the date is totally wrong (outside of MySQL abilty to store
|
||||
it), MySQL Server will store the special 0000-00-00 date value in the
|
||||
column.
|
||||
|
||||
@item
|
||||
If you set an @code{ENUM} column to an unsupported value, it will be set to
|
||||
|
@ -8170,6 +8173,9 @@ Renamed mysqld startup options @code{--skip-locking} to
|
|||
@code{--skip-external-locking} and @code{--enable-locking} to
|
||||
@code{--external-locking}.
|
||||
@item
|
||||
mysqld now has the option @code{--temp-pool} enabled by default as this
|
||||
gives better performance with some OS.
|
||||
@item
|
||||
@code{DOUBLE} and @code{FLOAT} columns now honour the
|
||||
@code{UNSIGNED} flag on storage (before, @code{UNSIGNED} was ignored for
|
||||
these columns).
|
||||
|
@ -32555,6 +32561,31 @@ mysql> SELECT WEEK('1998-12-31',1);
|
|||
Note: in Version 4.0, @code{WEEK(#,0)} was changed to match the
|
||||
calendar in the USA.
|
||||
|
||||
Note that if a week is the last week of the previous year, MySQL will
|
||||
return 0:
|
||||
|
||||
@example
|
||||
mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0);
|
||||
-> 2000, 0
|
||||
@end example
|
||||
|
||||
One could argue that MySQL should return @code{52} for the @code{WEEK()}
|
||||
function as the given date is actually the 52 second week of 1999. We
|
||||
decided to return 0 instead as we want the function to return 'the week
|
||||
number in the given year'. This makes the usage of the @code{WEEK()}
|
||||
function reliable when combined with other functions that extracts a
|
||||
date part from a date.
|
||||
|
||||
If you would prefer to know the correct year-week, then you should use
|
||||
the @code{YEARWEEK()} function instead:
|
||||
|
||||
@example
|
||||
mysql> SELECT YEARWEEK('2000-01-01');
|
||||
-> 199952
|
||||
mysql> SELECT MID(YEARWEEK('2000-01-01'),5,2);
|
||||
-> 52
|
||||
@end example
|
||||
|
||||
@findex YEAR()
|
||||
@item YEAR(date)
|
||||
Returns the year for @code{date}, in the range @code{1000} to @code{9999}:
|
||||
|
@ -32576,6 +32607,10 @@ mysql> SELECT YEARWEEK('1987-01-01');
|
|||
-> 198653
|
||||
@end example
|
||||
|
||||
Note that the week number is different from what the @code{WEEK()} function
|
||||
would return (@code{0}) as the week function returns the week in the
|
||||
context of the given year.
|
||||
|
||||
@findex HOUR()
|
||||
@item HOUR(time)
|
||||
Returns the hour for @code{time}, in the range @code{0} to @code{23}:
|
||||
|
@ -48180,13 +48215,33 @@ mysql> SELECT idate FROM tbl_name WHERE STRCMP(idate,'19970505')=0;
|
|||
a string and performs a string comparison. It does not convert
|
||||
@code{'19970505'} to a date and perform a date comparison.
|
||||
|
||||
Note that MySQL does no checking whether the date is
|
||||
Note that MySQL does very limited checking whether the date is
|
||||
correct. If you store an incorrect date, such as @code{'1998-2-31'}, the
|
||||
wrong date will be stored. If the date cannot be converted to any reasonable
|
||||
value, a @code{0} is stored in the @code{DATE} field. This is mainly a speed
|
||||
issue and we think it is up to the application to check the dates, and not
|
||||
the server.
|
||||
wrong date will be stored.
|
||||
|
||||
Because MySQL packs dates for storage, it can't store any given date as
|
||||
it would not fit onto the result buffer. The rules for accepting a date
|
||||
are:
|
||||
@itemize @bullet
|
||||
@item
|
||||
If MySQL can store it and retrieve a date, the wrong date is accepted
|
||||
for @code{DATE} and @code{DATETIME} columns.
|
||||
@item
|
||||
All days values between 0-31 are accepted for any date. This makes it
|
||||
very convenient for web applications where you ask year, month and day
|
||||
in 3 different fields.
|
||||
@item
|
||||
The day or month field may be zero. This is convenient if you want
|
||||
to store a birthdate in a @code{DATE} column and you only know part
|
||||
of the date.
|
||||
@end itemize
|
||||
|
||||
If the date cannot be converted to any reasonable value, a @code{0} is
|
||||
stored in the @code{DATE} field, which will be retrieved as
|
||||
@code{0000-00-00}. This is both a speed and convinient issue as we
|
||||
belive that the databases responsiblity etrive the same date you stored
|
||||
(even if the data was not logicall correct in all cases). We think it is
|
||||
up to the application to check the dates, and not the server.
|
||||
|
||||
@node Problems with NULL, Problems with alias, Using DATE, Query Issues
|
||||
@appendixsubsec Problems with @code{NULL} Values
|
||||
|
@ -50167,6 +50222,9 @@ each individual 4.0.x release.
|
|||
|
||||
@itemize @bullet
|
||||
@item
|
||||
mysqld now has the option @code{--temp-pool} enabled by default as this
|
||||
gives better performance with some OS.
|
||||
@item
|
||||
Big code cleanup in replication code.
|
||||
@item
|
||||
If one specifies @code{--code-file}, call @code{setrlmit()} to change allowed
|
||||
|
@ -50804,6 +50862,23 @@ not yet 100% confident in this code.
|
|||
@appendixsubsec Changes in release 3.23.52
|
||||
@itemize @bullet
|
||||
@item
|
||||
Fixed a security bug with empty db column in db table
|
||||
@item
|
||||
Changed initialisation of @code{RND()} to make it less predicatable.
|
||||
@item
|
||||
Fixed problem with @code{GROUP BY} on result with expression that created a
|
||||
@code{BLOB} field.
|
||||
@item
|
||||
Fixed problem with privilege tables when downgrading from 4.0.2 to 3.23.
|
||||
@item
|
||||
Fixed thread bug in @code{SLAVE START}, @code{SLAVE STOP} and automatic repair
|
||||
of MyISAM tables that could cause table cache to be corrupted.
|
||||
@item
|
||||
Fixed possible thread related key-cache-corruption problem with
|
||||
@code{OPTIMIZE TABLE} and @code{REPAIR TABLE}.
|
||||
@item
|
||||
Added name of 'administrator command' logs.
|
||||
@item
|
||||
Fixed bug with creating an auto-increment value on second part of a
|
||||
@code{UNIQUE()} key where first part could contain NULL values.
|
||||
@item
|
||||
|
@ -50811,7 +50886,9 @@ Don't write slave-timeout reconnects to the error log.
|
|||
@item
|
||||
Fixed bug with slave net read timeouting
|
||||
@item
|
||||
Fixed bug in ALTERing TABLE of BDB type.
|
||||
Fixed a core-dump bug with @code{MERGE} tables and @code{MAX()} function.
|
||||
@item
|
||||
Fixed bug in @code{ALTER TABLE} with BDB tables.
|
||||
@item
|
||||
Fixed bug when logging @code{LOAD DATA INFILE} to binary log with no
|
||||
active database.
|
||||
|
|
13
configure.in
13
configure.in
|
@ -1554,6 +1554,17 @@ AC_SUBST(TERMCAP_LIB)
|
|||
#########################################################################
|
||||
|
||||
dnl Checks for library functions.
|
||||
|
||||
#
|
||||
# The following code disables intrinsic function support while we test for
|
||||
# library functions. This is to avoid configure problems with Intel ecc
|
||||
# compiler
|
||||
|
||||
ORG_CFLAGS="$CFLAGS"
|
||||
if test "$GCC" != "yes"; then
|
||||
AC_SYS_COMPILER_FLAG(-nolib_inline,nolib_inline,CFLAGS,[],[])
|
||||
fi
|
||||
|
||||
AC_FUNC_MMAP
|
||||
AC_TYPE_SIGNAL
|
||||
MYSQL_TYPE_QSORT
|
||||
|
@ -1576,6 +1587,8 @@ AC_CHECK_FUNCS(alarm bmove \
|
|||
pthread_condattr_create rwlock_init pthread_rwlock_rdlock \
|
||||
fchmod getpass getpassphrase initgroups mlockall)
|
||||
|
||||
CFLAGS="$ORG_CFLAGS"
|
||||
|
||||
# Sanity check: We chould not have any fseeko symbol unless
|
||||
# large_file_support=yes
|
||||
AC_CHECK_FUNCS(fseeko,
|
||||
|
|
|
@ -121,14 +121,6 @@
|
|||
/* #define _AIX32_CURSES */ /* XXX: this breaks AIX 4.3.3 (others?). */
|
||||
#endif
|
||||
|
||||
#ifdef __QNXNTO__
|
||||
#define HAVE_ERRNO_AS_DEFINE
|
||||
#define HAVE_FCNTL_LOCK
|
||||
#undef HAVE_SYS_UN_H
|
||||
#undef HAVE_FINITE
|
||||
#undef HAVE_RINT
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_BROKEN_SNPRINTF /* HPUX 10.20 don't have this defined */
|
||||
#undef HAVE_SNPRINTF
|
||||
#endif
|
||||
|
@ -253,6 +245,17 @@
|
|||
#define setrlimit cma_setrlimit64
|
||||
#endif
|
||||
|
||||
#ifdef __QNXNTO__
|
||||
/* 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
|
||||
|
||||
/* We can not live without the following defines */
|
||||
|
||||
#define USE_MYFUNC 1 /* Must use syscall indirection */
|
||||
|
@ -548,11 +551,6 @@ extern double my_atof(const char*);
|
|||
#define HAVE_LONG_LONG 1
|
||||
#endif
|
||||
|
||||
#ifdef __QNXNTO__
|
||||
#undef LONGLONG_MIN /* These get wrongly defined in QNX 6.2 */
|
||||
#undef LONGLONG_MAX /* standard system library 'limits.h' */
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LONG_LONG) && !defined(LONGLONG_MIN)
|
||||
#define LONGLONG_MIN ((long long) 0x8000000000000000LL)
|
||||
#define LONGLONG_MAX ((long long) 0x7FFFFFFFFFFFFFFFLL)
|
||||
|
|
|
@ -430,8 +430,9 @@ struct tm *localtime_r(const time_t *clock, struct tm *res);
|
|||
|
||||
#if defined(HPUX) && !defined(DONT_REMAP_PTHREAD_FUNCTIONS)
|
||||
#undef pthread_cond_timedwait
|
||||
#undef pthread_mutex_trylock
|
||||
#define pthread_cond_timedwait(a,b,c) my_pthread_cond_timedwait((a),(b),(c))
|
||||
#define pthread_mutex_trylock(a) my_pthread_mutex_trylock((a))
|
||||
#define pthread_mutex_trylock(a) my_pthread_mutex_trylock((a))
|
||||
int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||
struct timespec *abstime);
|
||||
int my_pthread_mutex_trylock(pthread_mutex_t *mutex);
|
||||
|
|
|
@ -35,8 +35,6 @@ C_MODE_START
|
|||
#ifdef HAVE_SEMAPHORE_H
|
||||
#include <semaphore.h>
|
||||
#elif defined(__bsdi__)
|
||||
#include <sys/errno.h>
|
||||
#else
|
||||
#ifdef __WIN__
|
||||
typedef HANDLE sem_t;
|
||||
#else
|
||||
|
@ -45,7 +43,7 @@ typedef struct {
|
|||
pthread_cond_t cond;
|
||||
uint count;
|
||||
} sem_t;
|
||||
#endif
|
||||
#endif /* __WIN__ */
|
||||
|
||||
int sem_init(sem_t * sem, int pshared, unsigned int value);
|
||||
int sem_destroy(sem_t * sem);
|
||||
|
@ -55,7 +53,7 @@ int sem_post(sem_t * sem);
|
|||
int sem_post_multiple(sem_t * sem, unsigned int count);
|
||||
int sem_getvalue(sem_t * sem, unsigned int * sval);
|
||||
|
||||
#endif
|
||||
#endif /* !__bsdi__ */
|
||||
|
||||
C_MODE_END
|
||||
#endif /* !_my_semaphore_h_ */
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#define MYSQL_VERSION_ID @MYSQL_VERSION_ID@
|
||||
#define MYSQL_PORT @MYSQL_TCP_PORT@
|
||||
#define MYSQL_UNIX_ADDR "@MYSQL_UNIX_ADDR@"
|
||||
#define MYSQL_CONFIG_NAME "my"
|
||||
|
||||
/* mysqld compile time options */
|
||||
#ifndef MYSQL_CHARSET
|
||||
|
|
|
@ -808,7 +808,7 @@ btr_cur_optimistic_insert(
|
|||
|
||||
if (!dtuple_check_typed_no_assert(entry)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error in a tuple to insert into table %lu index %lu\n",
|
||||
"InnoDB: Error in a tuple to insert into table %lu index %s\n",
|
||||
index->table_name, index->name);
|
||||
}
|
||||
|
||||
|
@ -1213,6 +1213,8 @@ btr_cur_parse_update_in_place(
|
|||
rec_offset = mach_read_from_2(ptr);
|
||||
ptr += 2;
|
||||
|
||||
ut_a(rec_offset <= UNIV_PAGE_SIZE);
|
||||
|
||||
heap = mem_heap_create(256);
|
||||
|
||||
ptr = row_upd_index_parse(ptr, end_ptr, heap, &update);
|
||||
|
@ -1977,6 +1979,8 @@ btr_cur_parse_del_mark_set_clust_rec(
|
|||
offset = mach_read_from_2(ptr);
|
||||
ptr += 2;
|
||||
|
||||
ut_a(offset <= UNIV_PAGE_SIZE);
|
||||
|
||||
if (page) {
|
||||
rec = page + offset;
|
||||
|
||||
|
@ -2127,6 +2131,8 @@ btr_cur_parse_del_mark_set_sec_rec(
|
|||
offset = mach_read_from_2(ptr);
|
||||
ptr += 2;
|
||||
|
||||
ut_a(offset <= UNIV_PAGE_SIZE);
|
||||
|
||||
if (page) {
|
||||
rec = page + offset;
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ Created 2/17/1996 Heikki Tuuri
|
|||
#include "btr0cur.h"
|
||||
#include "btr0pcur.h"
|
||||
#include "btr0btr.h"
|
||||
#include "ha0ha.h"
|
||||
|
||||
ulint btr_search_n_succ = 0;
|
||||
ulint btr_search_n_hash_fail = 0;
|
||||
|
|
|
@ -286,7 +286,7 @@ buf_page_print(
|
|||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Page dump in ascii and hex (%u bytes):\n%s",
|
||||
UNIV_PAGE_SIZE, buf);
|
||||
(ulint)UNIV_PAGE_SIZE, buf);
|
||||
fprintf(stderr, "InnoDB: End of page dump\n");
|
||||
|
||||
mem_free(buf);
|
||||
|
@ -1707,10 +1707,11 @@ buf_print(void)
|
|||
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
printf("LRU len %lu \n", UT_LIST_GET_LEN(buf_pool->LRU));
|
||||
printf("free len %lu \n", UT_LIST_GET_LEN(buf_pool->free));
|
||||
printf("flush len %lu \n", UT_LIST_GET_LEN(buf_pool->flush_list));
|
||||
printf("buf_pool size %lu \n", size);
|
||||
printf("database pages %lu \n", UT_LIST_GET_LEN(buf_pool->LRU));
|
||||
printf("free pages %lu \n", UT_LIST_GET_LEN(buf_pool->free));
|
||||
printf("modified database pages %lu \n",
|
||||
UT_LIST_GET_LEN(buf_pool->flush_list));
|
||||
|
||||
printf("n pending reads %lu \n", buf_pool->n_pend_reads);
|
||||
|
||||
|
@ -1819,13 +1820,20 @@ buf_print_io(
|
|||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
buf += sprintf(buf,
|
||||
"Free list length %lu \n", UT_LIST_GET_LEN(buf_pool->free));
|
||||
"Buffer pool size %lu\n", size);
|
||||
buf += sprintf(buf,
|
||||
"LRU list length %lu \n", UT_LIST_GET_LEN(buf_pool->LRU));
|
||||
"Free buffers %lu\n", UT_LIST_GET_LEN(buf_pool->free));
|
||||
buf += sprintf(buf,
|
||||
"Flush list length %lu \n",
|
||||
"Database pages %lu\n", UT_LIST_GET_LEN(buf_pool->LRU));
|
||||
/*
|
||||
buf += sprintf(buf,
|
||||
"Lock heap buffers %lu\n", buf_pool->n_lock_heap_pages);
|
||||
buf += sprintf(buf,
|
||||
"Hash index buffers %lu\n", buf_pool->n_adaptive_hash_pages);
|
||||
*/
|
||||
buf += sprintf(buf,
|
||||
"Modified db pages %lu\n",
|
||||
UT_LIST_GET_LEN(buf_pool->flush_list));
|
||||
buf += sprintf(buf, "Buffer pool size %lu\n", size);
|
||||
|
||||
buf += sprintf(buf, "Pending reads %lu \n", buf_pool->n_pend_reads);
|
||||
|
||||
|
@ -1836,8 +1844,8 @@ buf_print_io(
|
|||
buf_pool->n_flush[BUF_FLUSH_SINGLE_PAGE]);
|
||||
|
||||
current_time = time(NULL);
|
||||
time_elapsed = difftime(current_time, buf_pool->last_printout_time);
|
||||
|
||||
time_elapsed = 0.001 + difftime(current_time,
|
||||
buf_pool->last_printout_time);
|
||||
buf_pool->last_printout_time = current_time;
|
||||
|
||||
buf += sprintf(buf, "Pages read %lu, created %lu, written %lu\n",
|
||||
|
@ -1870,6 +1878,20 @@ buf_print_io(
|
|||
mutex_exit(&(buf_pool->mutex));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Refreshes the statistics used to print per-second averages. */
|
||||
|
||||
void
|
||||
buf_refresh_io_stats(void)
|
||||
/*======================*/
|
||||
{
|
||||
buf_pool->last_printout_time = time(NULL);
|
||||
buf_pool->n_page_gets_old = buf_pool->n_page_gets;
|
||||
buf_pool->n_pages_read_old = buf_pool->n_pages_read;
|
||||
buf_pool->n_pages_created_old = buf_pool->n_pages_created;
|
||||
buf_pool->n_pages_written_old = buf_pool->n_pages_written;
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
Checks that all file pages in the buffer are in a replaceable state. */
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ Created 11/5/1995 Heikki Tuuri
|
|||
#include "buf0rea.h"
|
||||
#include "btr0sea.h"
|
||||
#include "os0file.h"
|
||||
#include "log0recv.h"
|
||||
|
||||
/* The number of blocks from the LRU_old pointer onward, including the block
|
||||
pointed to, must be 3/8 of the whole LRU list length, except that the
|
||||
|
@ -205,6 +206,44 @@ buf_LRU_get_free_block(void)
|
|||
loop:
|
||||
mutex_enter(&(buf_pool->mutex));
|
||||
|
||||
if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
|
||||
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 10) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
" InnoDB: ERROR: over 9 / 10 of the buffer pool is occupied by\n"
|
||||
"InnoDB: lock heaps or the adaptive hash index!\n"
|
||||
"InnoDB: We intentionally generate a seg fault to print a stack trace\n"
|
||||
"InnoDB: on Linux!\n");
|
||||
|
||||
ut_a(0);
|
||||
|
||||
} else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
|
||||
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 5) {
|
||||
|
||||
/* Over 80 % of the buffer pool is occupied by lock heaps
|
||||
or the adaptive hash index. This may be a memory leak! */
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
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");
|
||||
|
||||
srv_print_innodb_monitor = TRUE;
|
||||
|
||||
} else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
|
||||
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) {
|
||||
|
||||
/* Switch off the InnoDB Monitor; this is a simple way
|
||||
to stop the monitor if the situation becomes less urgent,
|
||||
but may also surprise users! */
|
||||
|
||||
srv_print_innodb_monitor = FALSE;
|
||||
}
|
||||
|
||||
if (buf_pool->LRU_flush_ended > 0) {
|
||||
mutex_exit(&(buf_pool->mutex));
|
||||
|
||||
|
|
|
@ -86,8 +86,10 @@ else
|
|||
fi
|
||||
|
||||
case "$target_os" in
|
||||
hpux10*)
|
||||
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX -DUNIV_HPUX10";;
|
||||
hp*)
|
||||
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
|
||||
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX";;
|
||||
irix*)
|
||||
CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
|
||||
osf*)
|
||||
|
|
|
@ -261,7 +261,7 @@ dict_table_get_index_noninline(
|
|||
{
|
||||
return(dict_table_get_index(table, name));
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
Initializes the autoinc counter. It is not an error to initialize an already
|
||||
initialized counter. */
|
||||
|
@ -270,7 +270,7 @@ void
|
|||
dict_table_autoinc_initialize(
|
||||
/*==========================*/
|
||||
dict_table_t* table, /* in: table */
|
||||
ib_longlong value) /* in: value which was assigned to a row */
|
||||
ib_longlong value) /* in: next value to assign to a row */
|
||||
{
|
||||
mutex_enter(&(table->autoinc_mutex));
|
||||
|
||||
|
@ -281,8 +281,8 @@ dict_table_autoinc_initialize(
|
|||
}
|
||||
|
||||
/************************************************************************
|
||||
Gets the next autoinc value, 0 if not yet initialized. If initialized,
|
||||
increments the counter by 1. */
|
||||
Gets the next autoinc value (== autoinc counter value), 0 if not yet
|
||||
initialized. If initialized, increments the counter by 1. */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_get(
|
||||
|
@ -298,8 +298,8 @@ dict_table_autoinc_get(
|
|||
|
||||
value = 0;
|
||||
} else {
|
||||
table->autoinc = table->autoinc + 1;
|
||||
value = table->autoinc;
|
||||
table->autoinc = table->autoinc + 1;
|
||||
}
|
||||
|
||||
mutex_exit(&(table->autoinc_mutex));
|
||||
|
@ -334,20 +334,43 @@ dict_table_autoinc_read(
|
|||
}
|
||||
|
||||
/************************************************************************
|
||||
Updates the autoinc counter if the value supplied is bigger than the
|
||||
Peeks the autoinc counter value, 0 if not yet initialized. Does not
|
||||
increment the counter. The read not protected by any mutex! */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_peek(
|
||||
/*====================*/
|
||||
/* out: value of the counter */
|
||||
dict_table_t* table) /* in: table */
|
||||
{
|
||||
ib_longlong value;
|
||||
|
||||
if (!table->autoinc_inited) {
|
||||
|
||||
value = 0;
|
||||
} else {
|
||||
value = table->autoinc;
|
||||
}
|
||||
|
||||
return(value);
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Updates the autoinc counter if the value supplied is equal or bigger than the
|
||||
current value. If not inited, does nothing. */
|
||||
|
||||
void
|
||||
dict_table_autoinc_update(
|
||||
/*======================*/
|
||||
|
||||
dict_table_t* table, /* in: table */
|
||||
ib_longlong value) /* in: value which was assigned to a row */
|
||||
{
|
||||
mutex_enter(&(table->autoinc_mutex));
|
||||
|
||||
if (table->autoinc_inited) {
|
||||
if (value > table->autoinc) {
|
||||
table->autoinc = value;
|
||||
if (value >= table->autoinc) {
|
||||
table->autoinc = value + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -578,7 +578,7 @@ fil_read_flushed_lsn_and_arch_log_no(
|
|||
ulint arch_log_no;
|
||||
|
||||
buf2 = ut_malloc(2 * UNIV_PAGE_SIZE);
|
||||
/* Align the memory for a possibel read from a raw device */
|
||||
/* Align the memory for a possible read from a raw device */
|
||||
buf = ut_align(buf2, UNIV_PAGE_SIZE);
|
||||
|
||||
os_file_read(data_file, buf, 0, 0, UNIV_PAGE_SIZE);
|
||||
|
|
|
@ -933,6 +933,36 @@ fsp_header_get_free_limit(
|
|||
return(limit);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Gets the size of the tablespace from the tablespace header. If we do not
|
||||
have an auto-extending data file, this should be equal to the size of the
|
||||
data files. If there is an auto-extending data file, this can be smaller. */
|
||||
|
||||
ulint
|
||||
fsp_header_get_tablespace_size(
|
||||
/*===========================*/
|
||||
/* out: size in pages */
|
||||
ulint space) /* in: space id */
|
||||
{
|
||||
fsp_header_t* header;
|
||||
ulint size;
|
||||
mtr_t mtr;
|
||||
|
||||
ut_a(space == 0); /* We have only one log_fsp_current_... variable */
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
mtr_x_lock(fil_space_get_latch(space), &mtr);
|
||||
|
||||
header = fsp_get_space_header(space, &mtr);
|
||||
|
||||
size = mtr_read_ulint(header + FSP_SIZE, MLOG_4BYTES, &mtr);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
return(size);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Tries to extend the last data file file if it is defined as auto-extending. */
|
||||
static
|
||||
|
@ -2629,7 +2659,7 @@ fseg_free_page_low(
|
|||
"InnoDB: Dump of the tablespace extent descriptor: %s\n", errbuf);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Serious error! InnoDB is trying to free page %lu\n",
|
||||
"InnoDB: Serious error! InnoDB is trying to free page %lu\n"
|
||||
"InnoDB: though it is already marked as free in the tablespace!\n"
|
||||
"InnoDB: The tablespace free space info is corrupt.\n"
|
||||
"InnoDB: You may need to dump your InnoDB tables and recreate the whole\n"
|
||||
|
|
|
@ -298,6 +298,7 @@ ha_print_info(
|
|||
ulint cells = 0;
|
||||
ulint len = 0;
|
||||
ulint max_len = 0;
|
||||
ulint n_bufs;
|
||||
ulint i;
|
||||
|
||||
if (buf_end - buf < 200) {
|
||||
|
@ -335,6 +336,20 @@ ha_print_info(
|
|||
}
|
||||
}
|
||||
|
||||
buf += sprintf(buf, "Hash table size %lu, used cells %lu\n",
|
||||
hash_get_n_cells(table), cells);
|
||||
buf += sprintf(buf,
|
||||
"Hash table size %lu, used cells %lu", hash_get_n_cells(table), cells);
|
||||
|
||||
if (table->heaps == NULL && table->heap != NULL) {
|
||||
|
||||
/* This calculation is intended for the adaptive hash
|
||||
index: how many buffer frames we have reserved? */
|
||||
|
||||
n_bufs = UT_LIST_GET_LEN(table->heap->base) - 1;
|
||||
|
||||
if (table->heap->free_block) {
|
||||
n_bufs++;
|
||||
}
|
||||
|
||||
buf += sprintf(buf, ", node heap has %lu buffer(s)\n", n_bufs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -313,14 +313,6 @@ btr_discard_page(
|
|||
btr_cur_t* cursor, /* in: cursor on the page to discard: not on
|
||||
the root page */
|
||||
mtr_t* mtr); /* in: mtr */
|
||||
/************************************************************************
|
||||
Declares the latching order level for the page latch in the debug version. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
btr_declare_page_latch(
|
||||
/*===================*/
|
||||
page_t* page, /* in: page */
|
||||
ibool leaf); /* in: TRUE if a leaf */
|
||||
/********************************************************************
|
||||
Parses the redo log record for setting an index record as the predefined
|
||||
minimum record. */
|
||||
|
|
|
@ -463,6 +463,12 @@ buf_print_io(
|
|||
/*=========*/
|
||||
char* buf, /* in/out: buffer where to print */
|
||||
char* buf_end);/* in: buffer end */
|
||||
/**************************************************************************
|
||||
Refreshes the statistics used to print per-second averages. */
|
||||
|
||||
void
|
||||
buf_refresh_io_stats(void);
|
||||
/*======================*/
|
||||
/*************************************************************************
|
||||
Checks that all file pages in the buffer are in a replaceable state. */
|
||||
|
||||
|
|
|
@ -211,8 +211,15 @@ buf_block_align(
|
|||
|
||||
block = buf_pool_get_nth_block(buf_pool, ((ulint)(ptr - frame_zero))
|
||||
>> UNIV_PAGE_SIZE_SHIFT);
|
||||
ut_a(block >= buf_pool->blocks);
|
||||
ut_a(block < buf_pool->blocks + buf_pool->max_size);
|
||||
if (block < buf_pool->blocks
|
||||
|| block >= buf_pool->blocks + buf_pool->max_size) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to access a stray pointer %lx\n"
|
||||
"InnoDB: buf pool start is at %lx, number of pages %lu\n", (ulint)ptr,
|
||||
(ulint)frame_zero, buf_pool->max_size);
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
return(block);
|
||||
}
|
||||
|
@ -238,8 +245,15 @@ buf_block_align_low(
|
|||
|
||||
block = buf_pool_get_nth_block(buf_pool, ((ulint)(ptr - frame_zero))
|
||||
>> UNIV_PAGE_SIZE_SHIFT);
|
||||
ut_a(block >= buf_pool->blocks);
|
||||
ut_a(block < buf_pool->blocks + buf_pool->max_size);
|
||||
if (block < buf_pool->blocks
|
||||
|| block >= buf_pool->blocks + buf_pool->max_size) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to access a stray pointer %lx\n"
|
||||
"InnoDB: buf pool start is at %lx, number of pages %lu\n", (ulint)ptr,
|
||||
(ulint)frame_zero, buf_pool->max_size);
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
return(block);
|
||||
}
|
||||
|
@ -259,10 +273,17 @@ buf_frame_align(
|
|||
|
||||
frame = ut_align_down(ptr, UNIV_PAGE_SIZE);
|
||||
|
||||
ut_a((ulint)frame
|
||||
>= (ulint)(buf_pool_get_nth_block(buf_pool, 0)->frame));
|
||||
ut_a((ulint)frame <= (ulint)(buf_pool_get_nth_block(buf_pool,
|
||||
buf_pool->max_size - 1)->frame));
|
||||
if (((ulint)frame
|
||||
< (ulint)(buf_pool->frame_zero))
|
||||
|| ((ulint)frame > (ulint)(buf_pool_get_nth_block(buf_pool,
|
||||
buf_pool->max_size - 1)->frame))) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: trying to access a stray pointer %lx\n"
|
||||
"InnoDB: buf pool start is at %lx, number of pages %lu\n", (ulint)ptr,
|
||||
(ulint)(buf_pool->frame_zero), buf_pool->max_size);
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
return(frame);
|
||||
}
|
||||
|
||||
|
|
|
@ -96,17 +96,17 @@ dict_col_get_clust_pos(
|
|||
/*===================*/
|
||||
dict_col_t* col);
|
||||
/************************************************************************
|
||||
Initializes the autoinc counter. It is not an error to initialize already
|
||||
Initializes the autoinc counter. It is not an error to initialize an already
|
||||
initialized counter. */
|
||||
|
||||
void
|
||||
dict_table_autoinc_initialize(
|
||||
/*==========================*/
|
||||
dict_table_t* table, /* in: table */
|
||||
ib_longlong value); /* in: value which was assigned to a row */
|
||||
ib_longlong value); /* in: next value to assign to a row */
|
||||
/************************************************************************
|
||||
Gets the next autoinc value, 0 if not yet initialized. If initialized,
|
||||
increments the counter by 1. */
|
||||
Gets the next autoinc value (== autoinc counter value), 0 if not yet
|
||||
initialized. If initialized, increments the counter by 1. */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_get(
|
||||
|
@ -123,12 +123,22 @@ dict_table_autoinc_read(
|
|||
/* out: value of the counter */
|
||||
dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Updates the autoinc counter if the value supplied is bigger than the
|
||||
Peeks the autoinc counter value, 0 if not yet initialized. Does not
|
||||
increment the counter. The read not protected by any mutex! */
|
||||
|
||||
ib_longlong
|
||||
dict_table_autoinc_peek(
|
||||
/*====================*/
|
||||
/* out: value of the counter */
|
||||
dict_table_t* table); /* in: table */
|
||||
/************************************************************************
|
||||
Updates the autoinc counter if the value supplied is equal or bigger than the
|
||||
current value. If not inited, does nothing. */
|
||||
|
||||
void
|
||||
dict_table_autoinc_update(
|
||||
/*======================*/
|
||||
|
||||
dict_table_t* table, /* in: table */
|
||||
ib_longlong value); /* in: value which was assigned to a row */
|
||||
/**************************************************************************
|
||||
|
|
|
@ -388,8 +388,8 @@ struct dict_table_struct{
|
|||
/* TRUE if the autoinc counter has been
|
||||
inited; MySQL gets the init value by executing
|
||||
SELECT MAX(auto inc column) */
|
||||
ib_longlong autoinc;/* autoinc counter value already given to
|
||||
a row */
|
||||
ib_longlong autoinc;/* autoinc counter value to give to the
|
||||
next inserted row */
|
||||
ulint magic_n;/* magic number */
|
||||
};
|
||||
#define DICT_TABLE_MAGIC_N 76333786
|
||||
|
|
|
@ -17,7 +17,8 @@ typedef struct dyn_block_struct dyn_block_t;
|
|||
typedef dyn_block_t dyn_array_t;
|
||||
|
||||
|
||||
/* This must be > MLOG_BUF_MARGIN + 30 */
|
||||
/* This is the initial 'payload' size of a dynamic array;
|
||||
this must be > MLOG_BUF_MARGIN + 30! */
|
||||
#define DYN_ARRAY_DATA_SIZE 512
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -123,14 +124,6 @@ dyn_block_get_data(
|
|||
/*===============*/
|
||||
/* out: pointer to data */
|
||||
dyn_block_t* block); /* in: dyn array block */
|
||||
/************************************************************************
|
||||
Gets the next block in a dyn array. */
|
||||
UNIV_INLINE
|
||||
dyn_block_t*
|
||||
dyn_block_get_next(
|
||||
/*===============*/
|
||||
/* out: pointer to next, NULL if end of list */
|
||||
dyn_block_t* block); /* in: dyn array block */
|
||||
/************************************************************
|
||||
Pushes n bytes to a dyn array. */
|
||||
UNIV_INLINE
|
||||
|
|
|
@ -57,6 +57,16 @@ fsp_header_get_free_limit(
|
|||
/* out: free limit in megabytes */
|
||||
ulint space); /* in: space id */
|
||||
/**************************************************************************
|
||||
Gets the size of the tablespace from the tablespace header. If we do not
|
||||
have an auto-extending data file, this should be equal to the size of the
|
||||
data files. If there is an auto-extending data file, this can be smaller. */
|
||||
|
||||
ulint
|
||||
fsp_header_get_tablespace_size(
|
||||
/*===========================*/
|
||||
/* out: size in pages */
|
||||
ulint space); /* in: space id */
|
||||
/**************************************************************************
|
||||
Initializes the space header of a new created space. */
|
||||
|
||||
void
|
||||
|
|
|
@ -131,6 +131,14 @@ ha_print_info(
|
|||
char* buf_end,/* in: buffer end */
|
||||
hash_table_t* table); /* in: hash table */
|
||||
|
||||
/* The hash table external chain node */
|
||||
|
||||
typedef struct ha_node_struct ha_node_t;
|
||||
struct ha_node_struct {
|
||||
ha_node_t* next; /* next chain node or NULL if none */
|
||||
void* data; /* pointer to the data */
|
||||
ulint fold; /* fold value for the data */
|
||||
};
|
||||
|
||||
#ifndef UNIV_NONINL
|
||||
#include "ha0ha.ic"
|
||||
|
|
|
@ -9,16 +9,6 @@ Created 8/18/1994 Heikki Tuuri
|
|||
#include "ut0rnd.h"
|
||||
#include "mem0mem.h"
|
||||
|
||||
/* The hash table external chain node */
|
||||
|
||||
typedef struct ha_node_struct ha_node_t;
|
||||
|
||||
struct ha_node_struct {
|
||||
ha_node_t* next; /* next chain node or NULL if none */
|
||||
void* data; /* pointer to the data */
|
||||
ulint fold; /* fold value for the data */
|
||||
};
|
||||
|
||||
/***************************************************************
|
||||
Deletes a hash node. */
|
||||
|
||||
|
|
|
@ -431,15 +431,30 @@ log_block_set_data_len(
|
|||
byte* log_block, /* in: log block */
|
||||
ulint len); /* in: data length */
|
||||
/****************************************************************
|
||||
Gets a log block number stored in the trailer. */
|
||||
Calculates the checksum for a log block. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_get_trl_no(
|
||||
/*=================*/
|
||||
/* out: log block number stored in the block
|
||||
trailer */
|
||||
log_block_calc_checksum(
|
||||
/*====================*/
|
||||
/* out: checksum */
|
||||
byte* block); /* in: log block */
|
||||
/****************************************************************
|
||||
Gets a log block checksum field value. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_get_checksum(
|
||||
/*===================*/
|
||||
/* out: checksum */
|
||||
byte* log_block); /* in: log block */
|
||||
/****************************************************************
|
||||
Sets a log block checksum field value. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_set_checksum(
|
||||
/*===================*/
|
||||
byte* log_block, /* in: log block */
|
||||
ulint checksum); /* in: checksum */
|
||||
/****************************************************************
|
||||
Gets a log block first mtr log record group offset. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
|
@ -497,6 +512,12 @@ log_print(
|
|||
/*======*/
|
||||
char* buf, /* in/out: buffer where to print */
|
||||
char* buf_end);/* in: buffer end */
|
||||
/**************************************************************************
|
||||
Refreshes the statistics used to print per-second averages. */
|
||||
|
||||
void
|
||||
log_refresh_stats(void);
|
||||
/*===================*/
|
||||
|
||||
extern log_t* log_sys;
|
||||
|
||||
|
@ -544,10 +565,11 @@ extern log_t* log_sys;
|
|||
bytes */
|
||||
|
||||
/* Offsets of a log block trailer from the end of the block */
|
||||
#define LOG_BLOCK_TRL_CHECKSUM 4 /* 1 byte checksum of the log block
|
||||
contents */
|
||||
#define LOG_BLOCK_TRL_NO 3 /* 3 lowest bytes of the log block
|
||||
number */
|
||||
#define LOG_BLOCK_CHECKSUM 4 /* 4 byte checksum of the log block
|
||||
contents; in InnoDB versions
|
||||
< 3.23.52 this did not contain the
|
||||
checksum but the same value as
|
||||
.._HDR_NO */
|
||||
#define LOG_BLOCK_TRL_SIZE 4 /* trailer size in bytes */
|
||||
|
||||
/* Offsets for a checkpoint field */
|
||||
|
|
|
@ -169,33 +169,6 @@ log_block_set_checkpoint_no(
|
|||
ut_dulint_get_low(no));
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Gets a log block number stored in the trailer. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_get_trl_no(
|
||||
/*=================*/
|
||||
/* out: log block number stored in the block
|
||||
trailer */
|
||||
byte* log_block) /* in: log block */
|
||||
{
|
||||
return(mach_read_from_3(log_block + OS_FILE_LOG_BLOCK_SIZE
|
||||
- LOG_BLOCK_TRL_NO));
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Sets the log block number stored in the trailer. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_set_trl_no(
|
||||
/*=================*/
|
||||
byte* log_block, /* in: log block */
|
||||
ulint n) /* in: log block number */
|
||||
{
|
||||
mach_write_to_3(log_block + OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_NO,
|
||||
n & 0xFFFFFF);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Converts a lsn to a log block number. */
|
||||
UNIV_INLINE
|
||||
|
@ -216,6 +189,61 @@ log_block_convert_lsn_to_no(
|
|||
return(no + 1);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Calculates the checksum for a log block. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_calc_checksum(
|
||||
/*====================*/
|
||||
/* out: checksum */
|
||||
byte* block) /* in: log block */
|
||||
{
|
||||
ulint sum;
|
||||
ulint sh;
|
||||
ulint i;
|
||||
|
||||
sum = 1;
|
||||
sh = 0;
|
||||
|
||||
for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
|
||||
sum = sum & 0x7FFFFFFF;
|
||||
sum += (((ulint)(*(block + i))) << sh) + (ulint)(*(block + i));
|
||||
sh++;
|
||||
if (sh > 24) {
|
||||
sh = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return(sum);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Gets a log block checksum field value. */
|
||||
UNIV_INLINE
|
||||
ulint
|
||||
log_block_get_checksum(
|
||||
/*===================*/
|
||||
/* out: checksum */
|
||||
byte* log_block) /* in: log block */
|
||||
{
|
||||
return(mach_read_from_4(log_block + OS_FILE_LOG_BLOCK_SIZE
|
||||
- LOG_BLOCK_CHECKSUM));
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Sets a log block checksum field value. */
|
||||
UNIV_INLINE
|
||||
void
|
||||
log_block_set_checksum(
|
||||
/*===================*/
|
||||
byte* log_block, /* in: log block */
|
||||
ulint checksum) /* in: checksum */
|
||||
{
|
||||
mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
|
||||
- LOG_BLOCK_CHECKSUM,
|
||||
checksum);
|
||||
}
|
||||
|
||||
/****************************************************************
|
||||
Initializes a log block in the log buffer. */
|
||||
UNIV_INLINE
|
||||
|
@ -232,7 +260,6 @@ log_block_init(
|
|||
no = log_block_convert_lsn_to_no(lsn);
|
||||
|
||||
log_block_set_hdr_no(log_block, no);
|
||||
log_block_set_trl_no(log_block, no);
|
||||
|
||||
log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
|
||||
log_block_set_first_rec_group(log_block, 0);
|
||||
|
@ -256,7 +283,7 @@ log_block_init_in_old_format(
|
|||
|
||||
log_block_set_hdr_no(log_block, no);
|
||||
mach_write_to_4(log_block + OS_FILE_LOG_BLOCK_SIZE
|
||||
- LOG_BLOCK_TRL_NO - 1, no);
|
||||
- LOG_BLOCK_CHECKSUM, no);
|
||||
log_block_set_data_len(log_block, LOG_BLOCK_HDR_SIZE);
|
||||
log_block_set_first_rec_group(log_block, 0);
|
||||
}
|
||||
|
|
|
@ -313,6 +313,11 @@ struct recv_sys_struct{
|
|||
this lsn */
|
||||
dulint limit_lsn;/* recovery should be made at most up to this
|
||||
lsn */
|
||||
ibool found_corrupt_log;
|
||||
/* this is set to TRUE if we during log
|
||||
scan find a corrupt log block, or a corrupt
|
||||
log record, or there is a log parsing
|
||||
buffer overflow */
|
||||
log_group_t* archive_group;
|
||||
/* in archive recovery: the log group whose
|
||||
archive is read */
|
||||
|
@ -328,6 +333,8 @@ extern ibool recv_recovery_on;
|
|||
extern ibool recv_no_ibuf_operations;
|
||||
extern ibool recv_needed_recovery;
|
||||
|
||||
extern ibool recv_is_making_a_backup;
|
||||
|
||||
/* Size of the parsing buffer; it must accommodate RECV_SCAN_SIZE many
|
||||
times! */
|
||||
#define RECV_PARSING_BUF_SIZE (2 * 1024 * 1024)
|
||||
|
|
|
@ -408,6 +408,12 @@ os_aio_print(
|
|||
char* buf, /* in/out: buffer where to print */
|
||||
char* buf_end);/* in: buffer end */
|
||||
/**************************************************************************
|
||||
Refreshes the statistics used to print per-second averages. */
|
||||
|
||||
void
|
||||
os_aio_refresh_stats(void);
|
||||
/*======================*/
|
||||
/**************************************************************************
|
||||
Checks that all slots in the system have been freed, that is, there are
|
||||
no pending io operations. */
|
||||
|
||||
|
|
|
@ -27,7 +27,21 @@ os_fast_mutex_trylock(
|
|||
|
||||
return(0);
|
||||
#else
|
||||
#if defined(UNIV_HOTBACKUP) && defined(UNIV_HPUX10)
|
||||
/* Since the hot backup version is standalone, MySQL does not redefine
|
||||
pthread_mutex_trylock for HP-UX-10.20, and consequently we must invert
|
||||
the return value here */
|
||||
|
||||
return((ulint) (1 - pthread_mutex_trylock(fast_mutex)));
|
||||
#else
|
||||
/* NOTE that the MySQL my_pthread.h redefines pthread_mutex_trylock
|
||||
so that it returns 0 on success. In the operating system
|
||||
libraries, HP-UX-10.20 follows the old Posix 1003.4a Draft 4 and
|
||||
returns 1 on success (but MySQL remaps that to 0), while Linux,
|
||||
FreeBSD, Solaris, AIX, Tru64 Unix, HP-UX-11.0 return 0 on success. */
|
||||
|
||||
return((ulint) pthread_mutex_trylock(fast_mutex));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -28,12 +28,30 @@ typedef void* os_thread_t;
|
|||
#else
|
||||
typedef pthread_t os_thread_t;
|
||||
#endif
|
||||
typedef unsigned long int os_thread_id_t;
|
||||
|
||||
#define os_thread_id_t os_thread_t
|
||||
|
||||
/* Define a function pointer type to use in a typecast */
|
||||
typedef void* (*os_posix_f_t) (void*);
|
||||
|
||||
/*******************************************************************
|
||||
Compares two threads or thread ids for equality */
|
||||
|
||||
ibool
|
||||
os_thread_eq(
|
||||
/*=========*/
|
||||
/* out: TRUE if equal */
|
||||
os_thread_t a, /* in: OS thread or thread id */
|
||||
os_thread_t b); /* in: OS thread or thread id */
|
||||
/********************************************************************
|
||||
Converts an OS thread or thread id to a ulint. It is NOT guaranteed that
|
||||
the ulint is unique for the thread though! */
|
||||
|
||||
ulint
|
||||
os_thread_pf(
|
||||
/*=========*/
|
||||
/* out: unsigned long int */
|
||||
os_thread_t a); /* in: thread or thread id */
|
||||
/********************************************************************
|
||||
Creates a new thread of execution. The execution starts from
|
||||
the function given. The start function takes a void* parameter
|
||||
|
@ -73,14 +91,6 @@ os_thread_t
|
|||
os_thread_get_curr(void);
|
||||
/*====================*/
|
||||
/*********************************************************************
|
||||
Converts a thread id to a ulint. */
|
||||
|
||||
ulint
|
||||
os_thread_conv_id_to_ulint(
|
||||
/*=======================*/
|
||||
/* out: converted to ulint */
|
||||
os_thread_id_t id); /* in: thread id */
|
||||
/*********************************************************************
|
||||
Waits for a thread to terminate. */
|
||||
|
||||
void
|
||||
|
|
|
@ -85,7 +85,7 @@ extern ibool srv_is_being_shut_down;
|
|||
/* At a shutdown the value first climbs from 0 to SRV_SHUTDOWN_CLEANUP
|
||||
and then to SRV_SHUTDOWN_LAST_PHASE */
|
||||
|
||||
extern ulint srv_shutdown_state;
|
||||
extern ulint srv_shutdown_state;
|
||||
|
||||
#define SRV_SHUTDOWN_CLEANUP 1
|
||||
#define SRV_SHUTDOWN_LAST_PHASE 2
|
||||
|
|
|
@ -312,7 +312,8 @@ rw_lock_x_lock_func_nowait(
|
|||
&& ((rw_lock_get_writer(lock) == RW_LOCK_NOT_LOCKED)
|
||||
|| ((rw_lock_get_writer(lock) == RW_LOCK_EX)
|
||||
&& (lock->pass == 0)
|
||||
&& (lock->writer_thread == os_thread_get_curr_id())))) {
|
||||
&& os_thread_eq(lock->writer_thread,
|
||||
os_thread_get_curr_id())))) {
|
||||
|
||||
rw_lock_set_writer(lock, RW_LOCK_EX);
|
||||
lock->writer_thread = os_thread_get_curr_id();
|
||||
|
|
|
@ -104,6 +104,10 @@ mutex_test_and_set(
|
|||
ret = os_fast_mutex_trylock(&(mutex->os_fast_mutex));
|
||||
|
||||
if (ret == 0) {
|
||||
/* We check that os_fast_mutex_trylock does not leak
|
||||
and allow race conditions */
|
||||
ut_a(mutex->lock_word == 0);
|
||||
|
||||
mutex->lock_word = 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -257,6 +257,15 @@ void
|
|||
trx_sys_print_mysql_binlog_offset(void);
|
||||
/*===================================*/
|
||||
/*********************************************************************
|
||||
Prints to stdout the MySQL binlog info in the system header if the
|
||||
magic number shows it valid. */
|
||||
|
||||
void
|
||||
trx_sys_print_mysql_binlog_offset_from_page(
|
||||
/*========================================*/
|
||||
byte* page); /* in: buffer containing the trx system header page,
|
||||
i.e., page number TRX_SYS_PAGE_NO in the tablespace */
|
||||
/*********************************************************************
|
||||
Prints to stderr the MySQL master log offset info in the trx system header if
|
||||
the magic number shows it valid. */
|
||||
|
||||
|
@ -300,11 +309,11 @@ therefore 256; each slot is currently 8 bytes in size */
|
|||
#define TRX_SYS_MYSQL_LOG_NAME_LEN 512
|
||||
#define TRX_SYS_MYSQL_LOG_MAGIC_N 873422344
|
||||
|
||||
/* The offset of the MySQL replication info on the trx system header page;
|
||||
/* The offset of the MySQL replication info in the trx system header;
|
||||
this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
|
||||
#define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
|
||||
|
||||
/* The offset of the MySQL binlog offset info on the trx system header page */
|
||||
/* The offset of the MySQL binlog offset info in the trx system header */
|
||||
#define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)
|
||||
#define TRX_SYS_MYSQL_LOG_MAGIC_N_FLD 0 /* magic number which shows
|
||||
if we have valid data in the
|
||||
|
|
|
@ -309,6 +309,9 @@ struct trx_struct{
|
|||
of view of concurrency control:
|
||||
TRX_ACTIVE, TRX_COMMITTED_IN_MEMORY,
|
||||
... */
|
||||
time_t start_time; /* time the trx object was created
|
||||
or the state last time became
|
||||
TRX_ACTIVE */
|
||||
ibool check_foreigns; /* normally TRUE, but if the user
|
||||
wants to suppress foreign key checks,
|
||||
(in table imports, for example) we
|
||||
|
@ -468,6 +471,7 @@ struct trx_struct{
|
|||
TRX_QUE_LOCK_WAIT, this points to
|
||||
the lock request, otherwise this is
|
||||
NULL */
|
||||
time_t wait_started; /* lock wait started at this time */
|
||||
UT_LIST_BASE_NODE_T(que_thr_t)
|
||||
wait_thrs; /* query threads belonging to this
|
||||
trx that are in the QUE_THR_LOCK_WAIT
|
||||
|
|
|
@ -80,8 +80,8 @@ memory is read outside the allocated blocks. */
|
|||
|
||||
/*
|
||||
#define UNIV_DEBUG
|
||||
#define UNIV_MEM_DEBUG
|
||||
#define UNIV_SYNC_DEBUG
|
||||
#define UNIV_MEM_DEBUG
|
||||
|
||||
#define UNIV_IBUF_DEBUG
|
||||
#define UNIV_SEARCH_DEBUG
|
||||
|
@ -116,7 +116,7 @@ memory is read outside the allocated blocks. */
|
|||
#define UNIV_INLINE extern inline
|
||||
#else
|
||||
/* extern inline doesn't work with gcc 3.0.2 */
|
||||
#define UNIV_INLINE static inline
|
||||
#define UNIV_INLINE static inline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -204,8 +204,12 @@ headers may define 'bool' differently. Do not assume that 'bool' is a ulint! */
|
|||
#endif
|
||||
|
||||
/* The following number as the length of a logical field means that the field
|
||||
has the SQL NULL as its value. */
|
||||
#define UNIV_SQL_NULL ULINT_UNDEFINED
|
||||
has the SQL NULL as its value. NOTE that because we assume that the length
|
||||
of a field is a 32-bit integer when we store it, for example, to an undo log
|
||||
on disk, we must have also this number fit in 32 bits, also in 64-bit
|
||||
computers! */
|
||||
|
||||
#define UNIV_SQL_NULL ULINT32_UNDEFINED
|
||||
|
||||
/* Lengths which are not UNIV_SQL_NULL, but bigger than the following
|
||||
number indicate that a field contains a reference to an externally
|
||||
|
|
|
@ -26,9 +26,11 @@ extern ulint* ut_dbg_null_ptr;
|
|||
ulint dbg_i;\
|
||||
\
|
||||
if (!((ulint)(EXPR) + ut_dbg_zero)) {\
|
||||
ut_print_timestamp(stderr);\
|
||||
fprintf(stderr,\
|
||||
"InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\
|
||||
os_thread_get_curr_id(), IB__FILE__, (ulint)__LINE__);\
|
||||
" 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: We intentionally generate a memory trap.\n");\
|
||||
fprintf(stderr,\
|
||||
|
@ -42,16 +44,17 @@ extern ulint* ut_dbg_null_ptr;
|
|||
if (ut_dbg_stop_threads) {\
|
||||
fprintf(stderr,\
|
||||
"InnoDB: Thread %lu stopped in file %s line %lu\n",\
|
||||
os_thread_get_curr_id(), IB__FILE__, (ulint)__LINE__);\
|
||||
os_thread_pf(os_thread_get_curr_id()), IB__FILE__, (ulint)__LINE__);\
|
||||
os_thread_sleep(1000000000);\
|
||||
}\
|
||||
}
|
||||
|
||||
#define ut_error {\
|
||||
ulint dbg_i;\
|
||||
ut_print_timestamp(stderr);\
|
||||
fprintf(stderr,\
|
||||
"InnoDB: Assertion failure in thread %lu in file %s line %lu\n",\
|
||||
os_thread_get_curr_id(), IB__FILE__, (ulint)__LINE__);\
|
||||
" 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: We intentionally generate a memory trap.\n");\
|
||||
fprintf(stderr,\
|
||||
|
|
|
@ -301,6 +301,11 @@ struct lock_struct{
|
|||
} un_member;
|
||||
};
|
||||
|
||||
/* We store info on the latest deadlock error to this buffer. InnoDB
|
||||
Monitor will then fetch it and print */
|
||||
ibool lock_deadlock_found = FALSE;
|
||||
char* lock_latest_err_buf; /* We allocate 5000 bytes for this */
|
||||
|
||||
/************************************************************************
|
||||
Checks if a lock request results in a deadlock. */
|
||||
static
|
||||
|
@ -576,6 +581,8 @@ lock_sys_create(
|
|||
lock_sys->rec_hash = hash_create(n_cells);
|
||||
|
||||
/* hash_create_mutexes(lock_sys->rec_hash, 2, SYNC_REC_LOCK); */
|
||||
|
||||
lock_latest_err_buf = mem_alloc(5000);
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
|
@ -1566,6 +1573,7 @@ index->table_name);
|
|||
}
|
||||
|
||||
trx->que_state = TRX_QUE_LOCK_WAIT;
|
||||
trx->wait_started = time(NULL);
|
||||
|
||||
ut_a(que_thr_stop(thr));
|
||||
|
||||
|
@ -2698,6 +2706,7 @@ lock_deadlock_occurs(
|
|||
trx_t* mark_trx;
|
||||
ibool ret;
|
||||
ulint cost = 0;
|
||||
char* err_buf;
|
||||
|
||||
ut_ad(trx && lock);
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
@ -2723,6 +2732,29 @@ lock_deadlock_occurs(
|
|||
index = lock->index;
|
||||
table = index->table;
|
||||
}
|
||||
|
||||
lock_deadlock_found = TRUE;
|
||||
|
||||
err_buf = lock_latest_err_buf + strlen(lock_latest_err_buf);
|
||||
|
||||
err_buf += sprintf(err_buf,
|
||||
"*** (2) WAITING FOR THIS LOCK TO BE GRANTED:\n");
|
||||
|
||||
ut_a(err_buf <= lock_latest_err_buf + 4000);
|
||||
|
||||
if (lock_get_type(lock) == LOCK_REC) {
|
||||
lock_rec_print(err_buf, lock);
|
||||
err_buf += strlen(err_buf);
|
||||
} else {
|
||||
lock_table_print(err_buf, lock);
|
||||
err_buf += strlen(err_buf);
|
||||
}
|
||||
|
||||
ut_a(err_buf <= lock_latest_err_buf + 4000);
|
||||
|
||||
err_buf += sprintf(err_buf,
|
||||
"*** WE ROLL BACK TRANSACTION (2)\n");
|
||||
|
||||
/*
|
||||
sess_raise_error_low(trx, DB_DEADLOCK, lock->type_mode, table,
|
||||
index, NULL, NULL, NULL);
|
||||
|
@ -2750,6 +2782,7 @@ lock_deadlock_recursive(
|
|||
lock_t* lock;
|
||||
ulint bit_no = 0; /* remove warning */
|
||||
trx_t* lock_trx;
|
||||
char* err_buf;
|
||||
|
||||
ut_a(trx && start && wait_lock);
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
@ -2801,6 +2834,53 @@ lock_deadlock_recursive(
|
|||
lock_trx = lock->trx;
|
||||
|
||||
if (lock_trx == start) {
|
||||
err_buf = lock_latest_err_buf;
|
||||
|
||||
ut_sprintf_timestamp(err_buf);
|
||||
err_buf += strlen(err_buf);
|
||||
|
||||
err_buf += sprintf(err_buf,
|
||||
" LATEST DETECTED DEADLOCK:\n"
|
||||
"*** (1) TRANSACTION:\n");
|
||||
|
||||
trx_print(err_buf, wait_lock->trx);
|
||||
err_buf += strlen(err_buf);
|
||||
|
||||
err_buf += sprintf(err_buf,
|
||||
"*** (1) WAITING FOR THIS LOCK TO BE GRANTED:\n");
|
||||
|
||||
ut_a(err_buf <= lock_latest_err_buf + 4000);
|
||||
|
||||
if (lock_get_type(wait_lock) == LOCK_REC) {
|
||||
lock_rec_print(err_buf, wait_lock);
|
||||
err_buf += strlen(err_buf);
|
||||
} else {
|
||||
lock_table_print(err_buf, wait_lock);
|
||||
err_buf += strlen(err_buf);
|
||||
}
|
||||
|
||||
ut_a(err_buf <= lock_latest_err_buf + 4000);
|
||||
err_buf += sprintf(err_buf,
|
||||
"*** (2) TRANSACTION:\n");
|
||||
|
||||
trx_print(err_buf, lock->trx);
|
||||
err_buf += strlen(err_buf);
|
||||
|
||||
err_buf += sprintf(err_buf,
|
||||
"*** (2) HOLDS THE LOCK(S):\n");
|
||||
|
||||
ut_a(err_buf <= lock_latest_err_buf + 4000);
|
||||
|
||||
if (lock_get_type(lock) == LOCK_REC) {
|
||||
lock_rec_print(err_buf, lock);
|
||||
err_buf += strlen(err_buf);
|
||||
} else {
|
||||
lock_table_print(err_buf, lock);
|
||||
err_buf += strlen(err_buf);
|
||||
}
|
||||
|
||||
ut_a(err_buf <= lock_latest_err_buf + 4000);
|
||||
|
||||
if (lock_print_waits) {
|
||||
printf("Deadlock detected\n");
|
||||
}
|
||||
|
@ -2962,6 +3042,7 @@ table->name);
|
|||
}
|
||||
|
||||
trx->que_state = TRX_QUE_LOCK_WAIT;
|
||||
trx->wait_started = time(NULL);
|
||||
|
||||
ut_a(que_thr_stop(thr));
|
||||
|
||||
|
@ -3432,6 +3513,9 @@ lock_rec_print(
|
|||
|
||||
buf += sprintf(buf,
|
||||
"Suppressing further record lock prints for this page\n");
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3520,6 +3604,22 @@ lock_print_info(
|
|||
buf += sprintf(buf,
|
||||
"Total number of lock structs in row lock hash table %lu\n",
|
||||
lock_get_n_rec_locks());
|
||||
if (lock_deadlock_found) {
|
||||
|
||||
if ((ulint)(buf_end - buf)
|
||||
< 100 + strlen(lock_latest_err_buf)) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
buf += sprintf(buf, "%s", lock_latest_err_buf);
|
||||
}
|
||||
|
||||
if (buf_end - buf < 600) {
|
||||
return;
|
||||
}
|
||||
|
||||
buf += sprintf(buf, "LIST OF TRANSACTIONS FOR EACH SESSION:\n");
|
||||
|
||||
/* First print info on non-active transactions */
|
||||
|
||||
|
@ -3588,7 +3688,8 @@ loop:
|
|||
|
||||
if (trx->que_state == TRX_QUE_LOCK_WAIT) {
|
||||
buf += sprintf(buf,
|
||||
"------------------TRX IS WAITING FOR THE LOCK:\n");
|
||||
"------- TRX HAS BEEN WAITING %lu SEC FOR THIS LOCK TO BE GRANTED:\n",
|
||||
(ulint)difftime(time(NULL), trx->wait_started));
|
||||
|
||||
if (lock_get_type(trx->wait_lock) == LOCK_REC) {
|
||||
lock_rec_print(buf, trx->wait_lock);
|
||||
|
|
|
@ -270,7 +270,7 @@ part_loop:
|
|||
|
||||
log->lsn = ut_dulint_add(log->lsn, len);
|
||||
|
||||
/* Initialize the next block header and trailer */
|
||||
/* Initialize the next block header */
|
||||
log_block_init(log_block + OS_FILE_LOG_BLOCK_SIZE, log->lsn);
|
||||
} else {
|
||||
log->lsn = ut_dulint_add(log->lsn, len);
|
||||
|
@ -1070,28 +1070,16 @@ log_group_file_header_flush(
|
|||
}
|
||||
|
||||
/**********************************************************
|
||||
Stores a 1-byte checksum to the trailer checksum field of a log block
|
||||
Stores a 4-byte checksum to the trailer checksum field of a log block
|
||||
before writing it to a log file. This checksum is used in recovery to
|
||||
check the consistency of a log block. The checksum is simply the 8 low
|
||||
bits of 1 + the sum of the bytes in the log block except the trailer bytes. */
|
||||
check the consistency of a log block. */
|
||||
static
|
||||
void
|
||||
log_block_store_checksum(
|
||||
/*=====================*/
|
||||
byte* block) /* in/out: pointer to a log block */
|
||||
{
|
||||
ulint i;
|
||||
ulint sum;
|
||||
|
||||
sum = 1;
|
||||
|
||||
for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
|
||||
sum += (ulint)(*(block + i));
|
||||
}
|
||||
|
||||
mach_write_to_1(block + OS_FILE_LOG_BLOCK_SIZE
|
||||
- LOG_BLOCK_TRL_CHECKSUM,
|
||||
0xFF & sum);
|
||||
log_block_set_checksum(block, log_block_calc_checksum(block));
|
||||
}
|
||||
|
||||
/**********************************************************
|
||||
|
@ -3113,8 +3101,8 @@ log_print(
|
|||
|
||||
current_time = time(NULL);
|
||||
|
||||
time_elapsed = difftime(current_time, log_sys->last_printout_time);
|
||||
|
||||
time_elapsed = 0.001 + difftime(current_time,
|
||||
log_sys->last_printout_time);
|
||||
buf += sprintf(buf,
|
||||
"%lu pending log writes, %lu pending chkp writes\n"
|
||||
"%lu log i/o's done, %.2f log i/o's/second\n",
|
||||
|
@ -3128,3 +3116,14 @@ log_print(
|
|||
|
||||
mutex_exit(&(log_sys->mutex));
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Refreshes the statistics used to print per-second averages. */
|
||||
|
||||
void
|
||||
log_refresh_stats(void)
|
||||
/*===================*/
|
||||
{
|
||||
log_sys->n_log_ios_old = log_sys->n_log_ios;
|
||||
log_sys->last_printout_time = time(NULL);
|
||||
}
|
||||
|
|
|
@ -58,12 +58,16 @@ yet: the variable name is misleading */
|
|||
|
||||
ibool recv_no_ibuf_operations = FALSE;
|
||||
|
||||
/* the following counter is used to decide when to print info on
|
||||
/* The following counter is used to decide when to print info on
|
||||
log scan */
|
||||
ulint recv_scan_print_counter = 0;
|
||||
|
||||
ibool recv_is_from_backup = FALSE;
|
||||
ibool recv_is_making_a_backup = FALSE;
|
||||
|
||||
ulint recv_previous_parsed_rec_type = 999999;
|
||||
ulint recv_previous_parsed_rec_offset = 0;
|
||||
ulint recv_previous_parsed_rec_is_multi = 0;
|
||||
|
||||
/************************************************************
|
||||
Creates the recovery system. */
|
||||
|
@ -124,6 +128,8 @@ recv_sys_init(
|
|||
|
||||
recv_sys->last_block = ut_align(recv_sys->last_block_buf_start,
|
||||
OS_FILE_LOG_BLOCK_SIZE);
|
||||
recv_sys->found_corrupt_log = FALSE;
|
||||
|
||||
mutex_exit(&(recv_sys->mutex));
|
||||
}
|
||||
|
||||
|
@ -569,9 +575,9 @@ recv_read_cp_info_for_backup(
|
|||
}
|
||||
|
||||
/**********************************************************
|
||||
Checks the 1-byte checksum to the trailer checksum field of a log block.
|
||||
We also accept a log block in the old format where the checksum field
|
||||
contained the highest byte of the log block number. */
|
||||
Checks the 4-byte checksum to the trailer checksum field of a log block.
|
||||
We also accept a log block in the old format < InnoDB-3.23.52 where the
|
||||
checksum field contains the log block number. */
|
||||
static
|
||||
ibool
|
||||
log_block_checksum_is_ok_or_old_format(
|
||||
|
@ -580,29 +586,12 @@ log_block_checksum_is_ok_or_old_format(
|
|||
format of InnoDB version < 3.23.52 */
|
||||
byte* block) /* in: pointer to a log block */
|
||||
{
|
||||
ulint i;
|
||||
ulint sum;
|
||||
|
||||
sum = 1;
|
||||
|
||||
for (i = 0; i < OS_FILE_LOG_BLOCK_SIZE - LOG_BLOCK_TRL_SIZE; i++) {
|
||||
sum += (ulint)(*(block + i));
|
||||
}
|
||||
|
||||
/* printf("Checksum %lu, byte %lu\n", 0xFF & sum,
|
||||
mach_read_from_1(block + OS_FILE_LOG_BLOCK_SIZE
|
||||
- LOG_BLOCK_TRL_CHECKSUM));
|
||||
*/
|
||||
if (mach_read_from_1(block + OS_FILE_LOG_BLOCK_SIZE
|
||||
- LOG_BLOCK_TRL_CHECKSUM)
|
||||
== (0xFF & sum)) {
|
||||
if (log_block_calc_checksum(block) == log_block_get_checksum(block)) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
if (((0xFF000000 & log_block_get_hdr_no(block)) >> 24)
|
||||
== mach_read_from_1(block + OS_FILE_LOG_BLOCK_SIZE
|
||||
- LOG_BLOCK_TRL_CHECKSUM)) {
|
||||
if (log_block_get_hdr_no(block) == log_block_get_checksum(block)) {
|
||||
|
||||
/* We assume the log block is in the format of
|
||||
InnoDB version < 3.23.52 and the block is ok */
|
||||
|
@ -649,23 +638,20 @@ recv_scan_log_seg_for_backup(
|
|||
|
||||
/* fprintf(stderr, "Log block header no %lu\n", no); */
|
||||
|
||||
if ((no & 0xFFFFFF) != log_block_get_trl_no(log_block)
|
||||
|| no != log_block_convert_lsn_to_no(*scanned_lsn)
|
||||
if (no != log_block_convert_lsn_to_no(*scanned_lsn)
|
||||
|| !log_block_checksum_is_ok_or_old_format(log_block)) {
|
||||
/*
|
||||
printf(
|
||||
"Log block n:o %lu, trailer n:o %lu, scanned lsn n:o %lu\n",
|
||||
no, log_block_get_trl_no(log_block),
|
||||
log_block_convert_lsn_to_no(*scanned_lsn));
|
||||
"Log block n:o %lu, scanned lsn n:o %lu\n",
|
||||
no, log_block_convert_lsn_to_no(*scanned_lsn));
|
||||
*/
|
||||
/* Garbage or an incompletely written log block */
|
||||
|
||||
log_block += OS_FILE_LOG_BLOCK_SIZE;
|
||||
/*
|
||||
printf(
|
||||
"Next log block n:o %lu, trailer n:o %lu\n",
|
||||
log_block_get_hdr_no(log_block),
|
||||
log_block_get_trl_no(log_block));
|
||||
"Next log block n:o %lu\n",
|
||||
log_block_get_hdr_no(log_block));
|
||||
*/
|
||||
break;
|
||||
}
|
||||
|
@ -788,14 +774,8 @@ recv_parse_or_apply_log_rec_body(
|
|||
new_ptr = mlog_parse_string(ptr, end_ptr, page);
|
||||
} else {
|
||||
new_ptr = NULL;
|
||||
|
||||
fprintf(stderr,
|
||||
"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: Corrupt log record type %lu\n",
|
||||
(ulint)type);
|
||||
|
||||
recv_sys->found_corrupt_log = TRUE;
|
||||
}
|
||||
|
||||
ut_ad(!page || new_ptr);
|
||||
|
@ -1399,18 +1379,30 @@ recv_apply_log_recs_for_backup(
|
|||
OS_FILE_OPEN,
|
||||
OS_FILE_READ_WRITE,
|
||||
&success);
|
||||
ut_a(success);
|
||||
if (!success) {
|
||||
printf(
|
||||
"InnoDB: Error: cannot open %lu'th data file %s\n", nth_file);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
recv_addr = recv_get_fil_addr_struct(0, i);
|
||||
|
||||
if (recv_addr != NULL) {
|
||||
os_file_read(data_file, page,
|
||||
success = os_file_read(data_file, page,
|
||||
(nth_page_in_file << UNIV_PAGE_SIZE_SHIFT)
|
||||
& 0xFFFFFFFF,
|
||||
nth_page_in_file >> (32 - UNIV_PAGE_SIZE_SHIFT),
|
||||
UNIV_PAGE_SIZE);
|
||||
if (!success) {
|
||||
printf(
|
||||
"InnoDB: Error: cannot read page no %lu from %lu'th data file %s\n",
|
||||
nth_page_in_file, nth_file);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* We simulate a page read made by the buffer pool,
|
||||
to make sure recovery works ok. We must init the
|
||||
block corresponding to buf_pool->frame_zero
|
||||
|
@ -1425,12 +1417,19 @@ recv_apply_log_recs_for_backup(
|
|||
mach_read_from_8(page + FIL_PAGE_LSN),
|
||||
0, i);
|
||||
|
||||
os_file_write(data_files[nth_file],
|
||||
success = os_file_write(data_files[nth_file],
|
||||
data_file, page,
|
||||
(nth_page_in_file << UNIV_PAGE_SIZE_SHIFT)
|
||||
& 0xFFFFFFFF,
|
||||
nth_page_in_file >> (32 - UNIV_PAGE_SIZE_SHIFT),
|
||||
UNIV_PAGE_SIZE);
|
||||
if (!success) {
|
||||
printf(
|
||||
"InnoDB: Error: cannot write page no %lu to %lu'th data file %s\n",
|
||||
nth_page_in_file, nth_file);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if ((100 * i) / n_pages_total
|
||||
|
@ -1679,29 +1678,16 @@ recv_parse_log_rec(
|
|||
|
||||
new_ptr = mlog_parse_initial_log_record(ptr, end_ptr, type, space,
|
||||
page_no);
|
||||
|
||||
/* If the operating system writes to the log complete 512-byte
|
||||
blocks, we should not get the warnings below in recovery.
|
||||
A warning means that the header and the trailer appeared ok
|
||||
in a 512-byte block, but in the middle there was something wrong.
|
||||
TODO: (1) add similar warnings in the case there is an incompletely
|
||||
written log record which does not extend to the boundary of a
|
||||
512-byte block. (2) Add a checksum to a log block. */
|
||||
|
||||
if (!new_ptr) {
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Check that space id and page_no are sensible */
|
||||
|
||||
if (*space != 0 || *page_no > 0x8FFFFFFF) {
|
||||
fprintf(stderr,
|
||||
"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: Corrupt log record type %lu, space id %lu, page no %lu\n",
|
||||
(ulint)(*type), *space, *page_no);
|
||||
|
||||
recv_sys->found_corrupt_log = TRUE;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
@ -1765,6 +1751,63 @@ recv_check_incomplete_log_recs(
|
|||
}
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
Prints diagnostic info of corrupt log. */
|
||||
static
|
||||
void
|
||||
recv_report_corrupt_log(
|
||||
/*====================*/
|
||||
byte* ptr, /* in: pointer to corrupt log record */
|
||||
byte type, /* in: type of the record */
|
||||
ulint space, /* in: space id, this may also be garbage */
|
||||
ulint page_no)/* in: page number, this may also be garbage */
|
||||
{
|
||||
char* err_buf;
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: ############### CORRUPT LOG RECORD FOUND\n"
|
||||
"InnoDB: Log record type %lu, space id %lu, page number %lu\n"
|
||||
"InnoDB: Log parsing proceeded successfully up to %lu %lu\n",
|
||||
(ulint)type, space, page_no,
|
||||
ut_dulint_get_high(recv_sys->recovered_lsn),
|
||||
ut_dulint_get_low(recv_sys->recovered_lsn));
|
||||
|
||||
err_buf = ut_malloc(1000000);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Previous log record type %lu, is multi %lu\n"
|
||||
"InnoDB: Recv offset %lu, prev %lu\n",
|
||||
recv_previous_parsed_rec_type,
|
||||
recv_previous_parsed_rec_is_multi,
|
||||
ptr - recv_sys->buf,
|
||||
recv_previous_parsed_rec_offset);
|
||||
|
||||
if ((ulint)(ptr - recv_sys->buf + 100)
|
||||
> recv_previous_parsed_rec_offset
|
||||
&& (ulint)(ptr - recv_sys->buf + 100
|
||||
- recv_previous_parsed_rec_offset)
|
||||
< 200000) {
|
||||
|
||||
ut_sprintf_buf(err_buf,
|
||||
recv_sys->buf + recv_previous_parsed_rec_offset - 100,
|
||||
ptr - recv_sys->buf + 200 -
|
||||
recv_previous_parsed_rec_offset);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Hex dump of corrupt log starting 100 bytes before the start\n"
|
||||
"InnoDB: of the previous log rec,\n"
|
||||
"InnoDB: and ending 100 bytes after the start of the corrupt rec:\n%s\n",
|
||||
err_buf);
|
||||
}
|
||||
|
||||
ut_free(err_buf);
|
||||
|
||||
fprintf(stderr,
|
||||
"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");
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
Parses log records from a buffer and stores them to a hash table to wait
|
||||
merging to file pages. */
|
||||
|
@ -1772,8 +1815,7 @@ static
|
|||
ibool
|
||||
recv_parse_log_recs(
|
||||
/*================*/
|
||||
/* out: TRUE if the hash table of parsed log
|
||||
records became full */
|
||||
/* out: currently always returns FALSE */
|
||||
ibool store_to_hash) /* in: TRUE if the records should be stored
|
||||
to the hash table; this is set to FALSE if just
|
||||
debug checking is needed */
|
||||
|
@ -1812,8 +1854,13 @@ loop:
|
|||
|
||||
len = recv_parse_log_rec(ptr, end_ptr, &type, &space,
|
||||
&page_no, &body);
|
||||
if (len == 0) {
|
||||
if (len == 0 || recv_sys->found_corrupt_log) {
|
||||
if (recv_sys->found_corrupt_log) {
|
||||
|
||||
recv_report_corrupt_log(ptr,
|
||||
type, space, page_no);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
|
@ -1828,6 +1875,10 @@ loop:
|
|||
return(FALSE);
|
||||
}
|
||||
|
||||
recv_previous_parsed_rec_type = (ulint)type;
|
||||
recv_previous_parsed_rec_offset = recv_sys->recovered_offset;
|
||||
recv_previous_parsed_rec_is_multi = 0;
|
||||
|
||||
recv_sys->recovered_offset += len;
|
||||
recv_sys->recovered_lsn = new_recovered_lsn;
|
||||
|
||||
|
@ -1851,9 +1902,10 @@ loop:
|
|||
#ifdef UNIV_LOG_DEBUG
|
||||
recv_check_incomplete_log_recs(ptr, len);
|
||||
#endif
|
||||
recv_update_replicate(type, space, page_no, body,
|
||||
/* recv_update_replicate(type, space, page_no, body,
|
||||
ptr + len);
|
||||
recv_compare_replicate(space, page_no);
|
||||
*/
|
||||
}
|
||||
} else {
|
||||
/* Check that all the records associated with the single mtr
|
||||
|
@ -1865,19 +1917,32 @@ loop:
|
|||
for (;;) {
|
||||
len = recv_parse_log_rec(ptr, end_ptr, &type, &space,
|
||||
&page_no, &body);
|
||||
if (len == 0) {
|
||||
if (len == 0 || recv_sys->found_corrupt_log) {
|
||||
|
||||
return(FALSE);
|
||||
if (recv_sys->found_corrupt_log) {
|
||||
|
||||
recv_report_corrupt_log(ptr,
|
||||
type, space, page_no);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
recv_previous_parsed_rec_type = (ulint)type;
|
||||
recv_previous_parsed_rec_offset
|
||||
= recv_sys->recovered_offset + total_len;
|
||||
recv_previous_parsed_rec_is_multi = 1;
|
||||
|
||||
if ((!store_to_hash) && (type != MLOG_MULTI_REC_END)) {
|
||||
/* In debug checking, update a replicate page
|
||||
according to the log record */
|
||||
#ifdef UNIV_LOG_DEBUG
|
||||
recv_check_incomplete_log_recs(ptr, len);
|
||||
#endif
|
||||
/*
|
||||
recv_update_replicate(type, space, page_no,
|
||||
body, ptr + len);
|
||||
*/
|
||||
}
|
||||
|
||||
if (log_debug_writes) {
|
||||
|
@ -1919,6 +1984,12 @@ loop:
|
|||
old_lsn = recv_sys->recovered_lsn;
|
||||
len = recv_parse_log_rec(ptr, end_ptr, &type, &space,
|
||||
&page_no, &body);
|
||||
if (recv_sys->found_corrupt_log) {
|
||||
|
||||
recv_report_corrupt_log(ptr,
|
||||
type, space, page_no);
|
||||
}
|
||||
|
||||
ut_a(len != 0);
|
||||
ut_a(0 == ((ulint)*ptr & MLOG_SINGLE_REC_FLAG));
|
||||
|
||||
|
@ -1941,7 +2012,7 @@ loop:
|
|||
page has become identical with the original
|
||||
page */
|
||||
|
||||
recv_compare_replicate(space, page_no);
|
||||
/* recv_compare_replicate(space, page_no); */
|
||||
}
|
||||
|
||||
ptr += len;
|
||||
|
@ -2095,32 +2166,19 @@ recv_scan_log_recs(
|
|||
|
||||
/* fprintf(stderr, "Log block header no %lu\n", no); */
|
||||
|
||||
if ((no & 0xFFFFFF) != log_block_get_trl_no(log_block)
|
||||
|| no != log_block_convert_lsn_to_no(scanned_lsn)
|
||||
if (no != log_block_convert_lsn_to_no(scanned_lsn)
|
||||
|| !log_block_checksum_is_ok_or_old_format(log_block)) {
|
||||
|
||||
if ((no & 0xFFFFFF) == log_block_get_trl_no(log_block)
|
||||
&& no == log_block_convert_lsn_to_no(scanned_lsn)
|
||||
if (no == log_block_convert_lsn_to_no(scanned_lsn)
|
||||
&& !log_block_checksum_is_ok_or_old_format(
|
||||
log_block)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Log block no %lu at lsn %lu %lu has\n"
|
||||
"InnoDB: ok header and trailer, but checksum field contains %lu\n",
|
||||
"InnoDB: ok header, but checksum field contains %lu, should be %lu\n",
|
||||
no, ut_dulint_get_high(scanned_lsn),
|
||||
ut_dulint_get_low(scanned_lsn),
|
||||
mach_read_from_1(log_block
|
||||
+ OS_FILE_LOG_BLOCK_SIZE
|
||||
- LOG_BLOCK_TRL_CHECKSUM));
|
||||
}
|
||||
|
||||
if ((no & 0xFFFFFF)
|
||||
!= log_block_get_trl_no(log_block)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Log block with header no %lu at lsn %lu %lu has\n"
|
||||
"InnoDB: trailer no %lu\n",
|
||||
no, ut_dulint_get_high(scanned_lsn),
|
||||
ut_dulint_get_low(scanned_lsn),
|
||||
log_block_get_trl_no(log_block));
|
||||
log_block_get_checksum(log_block),
|
||||
log_block_calc_checksum(log_block));
|
||||
}
|
||||
|
||||
/* Garbage or an incompletely written log block */
|
||||
|
@ -2192,11 +2250,14 @@ recv_scan_log_recs(
|
|||
>= RECV_PARSING_BUF_SIZE) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: log parsing buffer overflow. Recovery may have failed!\n");
|
||||
finished = TRUE;
|
||||
|
||||
recv_sys->found_corrupt_log = TRUE;
|
||||
|
||||
} else if (!recv_sys->found_corrupt_log) {
|
||||
more_data = recv_sys_add_to_parsing_buf(
|
||||
log_block, scanned_lsn);
|
||||
}
|
||||
|
||||
more_data = recv_sys_add_to_parsing_buf(log_block,
|
||||
scanned_lsn);
|
||||
recv_sys->scanned_lsn = scanned_lsn;
|
||||
recv_sys->scanned_checkpoint_no =
|
||||
log_block_get_checkpoint_no(log_block);
|
||||
|
@ -2213,7 +2274,8 @@ recv_scan_log_recs(
|
|||
|
||||
*group_scanned_lsn = scanned_lsn;
|
||||
|
||||
if (recv_needed_recovery || recv_is_from_backup) {
|
||||
if (recv_needed_recovery
|
||||
|| (recv_is_from_backup && !recv_is_making_a_backup)) {
|
||||
recv_scan_print_counter++;
|
||||
|
||||
if (finished || (recv_scan_print_counter % 80 == 0)) {
|
||||
|
@ -2225,7 +2287,7 @@ recv_scan_log_recs(
|
|||
}
|
||||
}
|
||||
|
||||
if (more_data) {
|
||||
if (more_data && !recv_sys->found_corrupt_log) {
|
||||
/* Try to parse more log records */
|
||||
|
||||
recv_parse_log_recs(store_to_hash);
|
||||
|
@ -2602,6 +2664,17 @@ recv_recovery_from_checkpoint_finish(void)
|
|||
trx_sys_print_mysql_binlog_offset();
|
||||
}
|
||||
|
||||
if (recv_sys->found_corrupt_log) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: WARNING: the log file may have been corrupt and it\n"
|
||||
"InnoDB: is possible that the log scan or parsing 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: It may be safest to recover your InnoDB database from\n"
|
||||
"InnoDB: a backup!\n");
|
||||
}
|
||||
|
||||
/* Free the resources of the recovery system */
|
||||
|
||||
recv_recovery_on = FALSE;
|
||||
|
|
|
@ -668,7 +668,7 @@ mem_print_info_low(
|
|||
|
||||
mem_pool_print_info(outfile, mem_comm_pool);
|
||||
|
||||
mem_validate();
|
||||
/* mem_validate(); */
|
||||
|
||||
/* fclose(outfile); */
|
||||
#endif
|
||||
|
|
|
@ -251,6 +251,7 @@ mem_pool_fill_free_list(
|
|||
mem_area_t* area;
|
||||
mem_area_t* area2;
|
||||
ibool ret;
|
||||
char err_buf[500];
|
||||
|
||||
ut_ad(mutex_own(&(pool->mutex)));
|
||||
|
||||
|
@ -279,15 +280,34 @@ mem_pool_fill_free_list(
|
|||
area = UT_LIST_GET_FIRST(pool->free_list[i + 1]);
|
||||
|
||||
if (area == NULL) {
|
||||
if (UT_LIST_GET_LEN(pool->free_list[i + 1]) > 0) {
|
||||
ut_print_timestamp(stderr);
|
||||
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: mem pool free list %lu length is %lu\n"
|
||||
"InnoDB: though the list is empty!\n",
|
||||
i + 1, UT_LIST_GET_LEN(pool->free_list[i + 1]));
|
||||
}
|
||||
|
||||
ret = mem_pool_fill_free_list(i + 1, pool);
|
||||
|
||||
if (ret == FALSE) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
area = UT_LIST_GET_FIRST(pool->free_list[i + 1]);
|
||||
}
|
||||
|
||||
|
||||
if (UT_LIST_GET_LEN(pool->free_list[i + 1]) == 0) {
|
||||
ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: Removing element from mem pool free list %lu\n"
|
||||
"InnoDB: though the list length is 0! Dump of 100 bytes around element:\n%s\n",
|
||||
i + 1, err_buf);
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
UT_LIST_REMOVE(free_list, pool->free_list[i + 1], area);
|
||||
|
||||
area2 = (mem_area_t*)(((byte*)area) + ut_2_exp(i));
|
||||
|
@ -320,6 +340,7 @@ mem_area_alloc(
|
|||
mem_area_t* area;
|
||||
ulint n;
|
||||
ibool ret;
|
||||
char err_buf[500];
|
||||
|
||||
n = ut_2_log(ut_max(size + MEM_AREA_EXTRA_SIZE, MEM_AREA_MIN_SIZE));
|
||||
|
||||
|
@ -342,7 +363,24 @@ mem_area_alloc(
|
|||
area = UT_LIST_GET_FIRST(pool->free_list[n]);
|
||||
}
|
||||
|
||||
ut_a(mem_area_get_free(area));
|
||||
if (!mem_area_get_free(area)) {
|
||||
ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: Removing element from mem pool free list %lu though the\n"
|
||||
"InnoDB: element is not marked free! Dump of 100 bytes around element:\n%s\n",
|
||||
n, err_buf);
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
if (UT_LIST_GET_LEN(pool->free_list[n]) == 0) {
|
||||
ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: Removing element from mem pool free list %lu\n"
|
||||
"InnoDB: though the list length is 0! Dump of 100 bytes around element:\n%s\n",
|
||||
n, err_buf);
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
ut_ad(mem_area_get_size(area) == ut_2_exp(n));
|
||||
|
||||
mem_area_set_free(area, FALSE);
|
||||
|
@ -413,6 +451,7 @@ mem_area_free(
|
|||
void* new_ptr;
|
||||
ulint size;
|
||||
ulint n;
|
||||
char err_buf[500];
|
||||
|
||||
if (mem_out_of_mem_err_msg_count > 0) {
|
||||
/* It may be that the area was really allocated from the
|
||||
|
@ -429,10 +468,18 @@ mem_area_free(
|
|||
|
||||
area = (mem_area_t*) (((byte*)ptr) - MEM_AREA_EXTRA_SIZE);
|
||||
|
||||
if (mem_area_get_free(area)) {
|
||||
ut_sprintf_buf(err_buf, ((byte*)area) - 50, 100);
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: Freeing element to mem pool free list though the\n"
|
||||
"InnoDB: element is marked free! Dump of 100 bytes around element:\n%s\n",
|
||||
err_buf);
|
||||
ut_a(0);
|
||||
}
|
||||
|
||||
size = mem_area_get_size(area);
|
||||
|
||||
ut_ad(size != 0);
|
||||
ut_a(!mem_area_get_free(area));
|
||||
|
||||
#ifdef UNIV_LIGHT_MEM_DEBUG
|
||||
if (((byte*)area) + size < pool->buf + pool->size) {
|
||||
|
|
|
@ -14,6 +14,7 @@ Created 12/7/1995 Heikki Tuuri
|
|||
|
||||
#include "buf0buf.h"
|
||||
#include "dict0boot.h"
|
||||
#include "log0recv.h"
|
||||
|
||||
/************************************************************
|
||||
Catenates n bytes to the mtr log. */
|
||||
|
@ -121,7 +122,7 @@ byte*
|
|||
mlog_parse_nbytes(
|
||||
/*==============*/
|
||||
/* out: parsed record end, NULL if not a complete
|
||||
record */
|
||||
record or a corrupt record */
|
||||
ulint type, /* in: log record type: MLOG_1BYTE, ... */
|
||||
byte* ptr, /* in: buffer */
|
||||
byte* end_ptr,/* in: buffer end */
|
||||
|
@ -141,6 +142,12 @@ mlog_parse_nbytes(
|
|||
offset = mach_read_from_2(ptr);
|
||||
ptr += 2;
|
||||
|
||||
if (offset >= UNIV_PAGE_SIZE) {
|
||||
recv_sys->found_corrupt_log = TRUE;
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (type == MLOG_8BYTES) {
|
||||
ptr = mach_dulint_parse_compressed(ptr, end_ptr, &dval);
|
||||
|
||||
|
@ -163,13 +170,33 @@ mlog_parse_nbytes(
|
|||
return(NULL);
|
||||
}
|
||||
|
||||
if (type == MLOG_1BYTE) {
|
||||
if (val > 0xFF) {
|
||||
recv_sys->found_corrupt_log = TRUE;
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
} else if (type == MLOG_2BYTES) {
|
||||
if (val > 0xFFFF) {
|
||||
recv_sys->found_corrupt_log = TRUE;
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
} else {
|
||||
if (type != MLOG_4BYTES) {
|
||||
recv_sys->found_corrupt_log = TRUE;
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (page) {
|
||||
if (type == MLOG_1BYTE) {
|
||||
mach_write_to_1(page + offset, val);
|
||||
} else if (type == MLOG_2BYTES) {
|
||||
mach_write_to_2(page + offset, val);
|
||||
} else {
|
||||
ut_ad(type == MLOG_4BYTES);
|
||||
ut_a(type == MLOG_4BYTES);
|
||||
mach_write_to_4(page + offset, val);
|
||||
}
|
||||
}
|
||||
|
@ -338,7 +365,11 @@ mlog_parse_string(
|
|||
offset = mach_read_from_2(ptr);
|
||||
ptr += 2;
|
||||
|
||||
ut_a(offset < UNIV_PAGE_SIZE);
|
||||
if (offset >= UNIV_PAGE_SIZE) {
|
||||
recv_sys->found_corrupt_log = TRUE;
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
len = mach_read_from_2(ptr);
|
||||
ptr += 2;
|
||||
|
|
|
@ -22,7 +22,7 @@ Created 10/21/1995 Heikki Tuuri
|
|||
|
||||
#endif
|
||||
|
||||
/* This specifies the file permissions InnoDB uses when it craetes files in
|
||||
/* This specifies the file permissions InnoDB uses when it creates files in
|
||||
Unix; the value of os_innodb_umask is initialized in ha_innodb.cc to
|
||||
my_umask */
|
||||
|
||||
|
@ -2483,7 +2483,7 @@ loop:
|
|||
buf += sprintf(buf, "\n");
|
||||
|
||||
current_time = time(NULL);
|
||||
time_elapsed = difftime(current_time, os_last_printout);
|
||||
time_elapsed = 0.001 + difftime(current_time, os_last_printout);
|
||||
|
||||
buf += sprintf(buf,
|
||||
"Pending flushes (fsync) log: %lu; buffer pool: %lu\n",
|
||||
|
@ -2517,6 +2517,21 @@ loop:
|
|||
os_last_printout = current_time;
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Refreshes the statistics used to print per-second averages. */
|
||||
|
||||
void
|
||||
os_aio_refresh_stats(void)
|
||||
/*======================*/
|
||||
{
|
||||
os_n_file_reads_old = os_n_file_reads;
|
||||
os_n_file_writes_old = os_n_file_writes;
|
||||
os_n_fsyncs_old = os_n_fsyncs;
|
||||
os_bytes_read_since_printout = 0;
|
||||
|
||||
os_last_printout = time(NULL);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
Checks that all slots in the system have been freed, that is, there are
|
||||
no pending io operations. */
|
||||
|
|
|
@ -18,26 +18,63 @@ Created 9/8/1995 Heikki Tuuri
|
|||
|
||||
#include "srv0srv.h"
|
||||
|
||||
/*******************************************************************
|
||||
Compares two threads or thread ids for equality */
|
||||
|
||||
ibool
|
||||
os_thread_eq(
|
||||
/*=========*/
|
||||
/* out: TRUE if equal */
|
||||
os_thread_t a, /* in: OS thread or thread id */
|
||||
os_thread_t b) /* in: OS thread or thread id */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
if (a == b) {
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
#else
|
||||
if (pthread_equal(a, b)) {
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
return(FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Converts an OS thread or thread id to a ulint. It is NOT guaranteed that
|
||||
the ulint is unique for the thread though! */
|
||||
|
||||
ulint
|
||||
os_thread_pf(
|
||||
/*=========*/
|
||||
os_thread_t a)
|
||||
{
|
||||
#ifdef UNIV_HPUX
|
||||
/* In HP-UX a pthread_t is a struct of 3 fields: field1, field2,
|
||||
field3. We do not know if field1 determines the thread uniquely. */
|
||||
|
||||
return((ulint)(a.field1));
|
||||
#else
|
||||
return((ulint)a);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Returns the thread identifier of current thread. */
|
||||
Returns the thread identifier of current thread. Currently the thread
|
||||
identifier is the thread handle itself. Note that in HP-UX pthread_t is
|
||||
a struct of 3 fields. */
|
||||
|
||||
os_thread_id_t
|
||||
os_thread_get_curr_id(void)
|
||||
/*=======================*/
|
||||
{
|
||||
#ifdef __WIN__
|
||||
return(GetCurrentThreadId());
|
||||
return(GetCurrentThread());
|
||||
#else
|
||||
pthread_t pthr;
|
||||
|
||||
pthr = pthread_self();
|
||||
|
||||
/* TODO: in the future we have to change os_thread_id
|
||||
to pthread_t; the following cast may work in a wrong way on some
|
||||
systems if pthread_t is a struct; this is just a quick fix
|
||||
for HP-UX to eliminate a compiler warning */
|
||||
|
||||
return(*(os_thread_id_t*)((void*) (&pthr)));
|
||||
return(pthread_self());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -71,7 +108,6 @@ os_thread_create(
|
|||
arg,
|
||||
0, /* thread runs immediately */
|
||||
thread_id);
|
||||
ut_a(thread);
|
||||
|
||||
if (srv_set_thread_priorities) {
|
||||
|
||||
|
@ -108,7 +144,7 @@ Returns handle to the current thread. */
|
|||
|
||||
os_thread_t
|
||||
os_thread_get_curr(void)
|
||||
/*=======================*/
|
||||
/*====================*/
|
||||
{
|
||||
#ifdef __WIN__
|
||||
return(GetCurrentThread());
|
||||
|
@ -116,18 +152,6 @@ os_thread_get_curr(void)
|
|||
return(pthread_self());
|
||||
#endif
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Converts a thread id to a ulint. */
|
||||
|
||||
ulint
|
||||
os_thread_conv_id_to_ulint(
|
||||
/*=======================*/
|
||||
/* out: converted to ulint */
|
||||
os_thread_id_t id) /* in: thread id */
|
||||
{
|
||||
return((ulint)id);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Advises the os to give up remainder of the thread's time slice. */
|
||||
|
|
|
@ -13,6 +13,7 @@ Created 10/4/1994 Heikki Tuuri
|
|||
|
||||
#include "rem0cmp.h"
|
||||
#include "mtr0log.h"
|
||||
#include "log0recv.h"
|
||||
|
||||
ulint page_cur_short_succ = 0;
|
||||
|
||||
|
@ -481,6 +482,9 @@ page_cur_insert_rec_write_log(
|
|||
|
||||
/* Write the mismatch index */
|
||||
log_ptr += mach_write_compressed(log_ptr, i);
|
||||
|
||||
ut_a(i < UNIV_PAGE_SIZE);
|
||||
ut_a(extra_size < UNIV_PAGE_SIZE);
|
||||
}
|
||||
|
||||
/* Write to the log the inserted index record end segment which
|
||||
|
@ -533,6 +537,13 @@ page_cur_parse_insert_rec(
|
|||
}
|
||||
|
||||
offset = mach_read_from_2(ptr);
|
||||
|
||||
if (offset >= UNIV_PAGE_SIZE) {
|
||||
|
||||
recv_sys->found_corrupt_log = TRUE;
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ptr += 2;
|
||||
}
|
||||
|
@ -546,6 +557,12 @@ page_cur_parse_insert_rec(
|
|||
|
||||
extra_info_yes = end_seg_len & 0x1;
|
||||
end_seg_len = end_seg_len / 2;
|
||||
|
||||
if (end_seg_len >= UNIV_PAGE_SIZE) {
|
||||
recv_sys->found_corrupt_log = TRUE;
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (extra_info_yes) {
|
||||
/* Read the info bits */
|
||||
|
@ -565,12 +582,16 @@ page_cur_parse_insert_rec(
|
|||
return(NULL);
|
||||
}
|
||||
|
||||
ut_a(origin_offset < UNIV_PAGE_SIZE);
|
||||
|
||||
ptr = mach_parse_compressed(ptr, end_ptr, &mismatch_index);
|
||||
|
||||
if (ptr == NULL) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
ut_a(mismatch_index < UNIV_PAGE_SIZE);
|
||||
}
|
||||
|
||||
if (end_ptr < ptr + end_seg_len) {
|
||||
|
@ -607,7 +628,6 @@ page_cur_parse_insert_rec(
|
|||
/* Build the inserted record to buf */
|
||||
|
||||
ut_a(mismatch_index < UNIV_PAGE_SIZE);
|
||||
ut_a(end_seg_len < UNIV_PAGE_SIZE);
|
||||
|
||||
ut_memcpy(buf, rec_get_start(cursor_rec), mismatch_index);
|
||||
ut_memcpy(buf + mismatch_index, ptr, end_seg_len);
|
||||
|
@ -1010,6 +1030,8 @@ page_cur_parse_delete_rec(
|
|||
offset = mach_read_from_2(ptr);
|
||||
ptr += 2;
|
||||
|
||||
ut_a(offset <= UNIV_PAGE_SIZE);
|
||||
|
||||
if (page) {
|
||||
page_cur_position(page + offset, &cursor);
|
||||
|
||||
|
|
|
@ -595,6 +595,11 @@ row_lock_table_autoinc_for_mysql(
|
|||
ut_ad(trx);
|
||||
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
|
||||
|
||||
if (trx->auto_inc_lock) {
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
trx->op_info = (char *) "setting auto-inc lock";
|
||||
|
||||
if (node == NULL) {
|
||||
|
|
|
@ -58,6 +58,7 @@ row_vers_impl_x_locked_off_kernel(
|
|||
ibool rec_del;
|
||||
ulint err;
|
||||
mtr_t mtr;
|
||||
char err_buf[1000];
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
|
||||
|
@ -74,7 +75,26 @@ row_vers_impl_x_locked_off_kernel(
|
|||
|
||||
clust_rec = row_get_clust_rec(BTR_SEARCH_LEAF, rec, index,
|
||||
&clust_index, &mtr);
|
||||
ut_a(clust_rec);
|
||||
if (!clust_rec) {
|
||||
rec_sprintf(err_buf, 900, rec);
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Error: cannot find the clustered index record\n"
|
||||
"InnoDB: for a secondary index record in table %s index %s.\n"
|
||||
"InnoDB: Secondary index record %s.\n"
|
||||
"InnoDB: The table is probably corrupt. Please run CHECK TABLE on it.\n"
|
||||
"InnoDB: You can try to repair the table by dump + drop + reimport.\n"
|
||||
"InnoDB: Send a detailed bug report to mysql@lists.mysql.com.\n",
|
||||
index->table_name, index->name, err_buf);
|
||||
mutex_enter(&kernel_mutex);
|
||||
mtr_commit(&mtr);
|
||||
|
||||
/* We assume there is no lock on the record, though this
|
||||
is not certain because the table is apparently corrupt */
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
trx_id = row_get_rec_trx_id(clust_rec, clust_index);
|
||||
|
||||
|
|
|
@ -2024,7 +2024,7 @@ srv_table_reserve_slot_for_mysql(void)
|
|||
|
||||
fprintf(stderr,
|
||||
"Slot %lu: thread id %lu, type %lu, in use %lu, susp %lu, time %lu\n",
|
||||
i, (ulint)(slot->id),
|
||||
i, os_thread_pf(slot->id),
|
||||
slot->type, slot->in_use,
|
||||
slot->suspended,
|
||||
(ulint)difftime(ut_time(), slot->suspend_time));
|
||||
|
@ -2168,6 +2168,34 @@ srv_release_mysql_thread_if_suspended(
|
|||
/* not found */
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Refreshes the values used to calculate per-second averages. */
|
||||
static
|
||||
void
|
||||
srv_refresh_innodb_monitor_stats(void)
|
||||
/*==================================*/
|
||||
{
|
||||
mutex_enter(&srv_innodb_monitor_mutex);
|
||||
|
||||
srv_last_monitor_time = time(NULL);
|
||||
|
||||
os_aio_refresh_stats();
|
||||
|
||||
btr_cur_n_sea_old = btr_cur_n_sea;
|
||||
btr_cur_n_non_sea_old = btr_cur_n_non_sea;
|
||||
|
||||
log_refresh_stats();
|
||||
|
||||
buf_refresh_io_stats();
|
||||
|
||||
srv_n_rows_inserted_old = srv_n_rows_inserted;
|
||||
srv_n_rows_updated_old = srv_n_rows_updated;
|
||||
srv_n_rows_deleted_old = srv_n_rows_deleted;
|
||||
srv_n_rows_read_old = srv_n_rows_read;
|
||||
|
||||
mutex_exit(&srv_innodb_monitor_mutex);
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
Sprintfs to a buffer the output of the InnoDB Monitor. */
|
||||
|
||||
|
@ -2205,7 +2233,7 @@ srv_sprintf_innodb_monitor(
|
|||
"=====================================\n");
|
||||
|
||||
buf += sprintf(buf,
|
||||
"Per second values calculated from the last %lu seconds\n",
|
||||
"Per second averages calculated from the last %lu seconds\n",
|
||||
(ulint)time_elapsed);
|
||||
|
||||
buf += sprintf(buf, "----------\n"
|
||||
|
@ -2242,8 +2270,8 @@ srv_sprintf_innodb_monitor(
|
|||
/ time_elapsed,
|
||||
(btr_cur_n_non_sea - btr_cur_n_non_sea_old)
|
||||
/ time_elapsed);
|
||||
btr_cur_n_sea_old = btr_cur_n_sea;
|
||||
btr_cur_n_non_sea_old = btr_cur_n_non_sea;
|
||||
btr_cur_n_sea_old = btr_cur_n_sea;
|
||||
btr_cur_n_non_sea_old = btr_cur_n_non_sea;
|
||||
|
||||
buf += sprintf(buf,"---\n"
|
||||
"LOG\n"
|
||||
|
@ -2285,10 +2313,10 @@ srv_sprintf_innodb_monitor(
|
|||
(srv_n_rows_read - srv_n_rows_read_old)
|
||||
/ time_elapsed);
|
||||
|
||||
srv_n_rows_inserted_old = srv_n_rows_inserted;
|
||||
srv_n_rows_updated_old = srv_n_rows_updated;
|
||||
srv_n_rows_deleted_old = srv_n_rows_deleted;
|
||||
srv_n_rows_read_old = srv_n_rows_read;
|
||||
srv_n_rows_inserted_old = srv_n_rows_inserted;
|
||||
srv_n_rows_updated_old = srv_n_rows_updated;
|
||||
srv_n_rows_deleted_old = srv_n_rows_deleted;
|
||||
srv_n_rows_read_old = srv_n_rows_read;
|
||||
|
||||
buf += sprintf(buf, "----------------------------\n"
|
||||
"END OF INNODB MONITOR OUTPUT\n"
|
||||
|
@ -2331,7 +2359,7 @@ loop:
|
|||
/* When someone is waiting for a lock, we wake up every second
|
||||
and check if a timeout has passed for a lock wait */
|
||||
|
||||
os_thread_sleep(1000000);
|
||||
os_thread_sleep(1000000);
|
||||
|
||||
/* In case mutex_exit is not a memory barrier, it is
|
||||
theoretically possible some threads are left waiting though
|
||||
|
@ -2348,9 +2376,9 @@ loop:
|
|||
|
||||
if (srv_print_innodb_monitor) {
|
||||
|
||||
buf = mem_alloc(100000);
|
||||
buf = mem_alloc(100000);
|
||||
|
||||
srv_sprintf_innodb_monitor(buf, 100000);
|
||||
srv_sprintf_innodb_monitor(buf, 100000);
|
||||
|
||||
printf("%s", buf);
|
||||
|
||||
|
@ -2481,12 +2509,30 @@ srv_error_monitor_thread(
|
|||
void* arg) /* in: a dummy parameter required by
|
||||
os_thread_create */
|
||||
{
|
||||
ulint cnt = 0;
|
||||
|
||||
UT_NOT_USED(arg);
|
||||
loop:
|
||||
srv_error_monitor_active = TRUE;
|
||||
|
||||
os_thread_sleep(10000000);
|
||||
cnt++;
|
||||
|
||||
os_thread_sleep(2000000);
|
||||
|
||||
if (difftime(time(NULL), srv_last_monitor_time) > 60) {
|
||||
/* We referesh InnoDB Monitor values so that averages are
|
||||
printed from at most 60 last seconds */
|
||||
|
||||
srv_refresh_innodb_monitor_stats();
|
||||
}
|
||||
|
||||
/* mem_print_new_info();
|
||||
|
||||
if (cnt % 10 == 0) {
|
||||
|
||||
mem_print_info();
|
||||
}
|
||||
*/
|
||||
sync_array_print_long_waits();
|
||||
|
||||
/* Flush stdout and stderr so that a database user gets their output
|
||||
|
|
|
@ -74,6 +74,12 @@ ulint ios;
|
|||
ulint n[SRV_MAX_N_IO_THREADS + 5];
|
||||
os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 5];
|
||||
|
||||
/* We use this mutex to test the return value of pthread_mutex_trylock
|
||||
on successful locking. HP-UX does NOT return 0, though Linux et al do. */
|
||||
os_fast_mutex_t srv_os_test_mutex;
|
||||
|
||||
ibool srv_os_test_mutex_is_locked = FALSE;
|
||||
|
||||
#define SRV_N_PENDING_IOS_PER_THREAD OS_AIO_N_PENDING_IOS_PER_THREAD
|
||||
#define SRV_MAX_N_PENDING_SYNC_IOS 100
|
||||
|
||||
|
@ -927,6 +933,8 @@ innobase_start_or_create_for_mysql(void)
|
|||
ulint max_arch_log_no;
|
||||
ibool start_archive;
|
||||
ulint sum_of_new_sizes;
|
||||
ulint sum_of_data_file_sizes;
|
||||
ulint tablespace_size_in_header;
|
||||
ulint err;
|
||||
ulint i;
|
||||
ulint k;
|
||||
|
@ -1324,7 +1332,49 @@ innobase_start_or_create_for_mysql(void)
|
|||
os_thread_create(&srv_master_thread, NULL, thread_ids + 1 +
|
||||
SRV_MAX_N_IO_THREADS);
|
||||
/* buf_debug_prints = TRUE; */
|
||||
|
||||
sum_of_data_file_sizes = 0;
|
||||
|
||||
for (i = 0; i < srv_n_data_files; i++) {
|
||||
sum_of_data_file_sizes += srv_data_file_sizes[i];
|
||||
}
|
||||
|
||||
tablespace_size_in_header = fsp_header_get_tablespace_size(0);
|
||||
|
||||
if (!srv_auto_extend_last_data_file
|
||||
&& sum_of_data_file_sizes != tablespace_size_in_header) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: tablespace size stored in header is %lu pages, but\n"
|
||||
"InnoDB: the sum of data file sizes is %lu pages\n",
|
||||
tablespace_size_in_header, sum_of_data_file_sizes);
|
||||
}
|
||||
|
||||
if (srv_auto_extend_last_data_file
|
||||
&& sum_of_data_file_sizes < tablespace_size_in_header) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: tablespace size stored in header is %lu pages, but\n"
|
||||
"InnoDB: the sum of data file sizes is only %lu pages\n",
|
||||
tablespace_size_in_header, sum_of_data_file_sizes);
|
||||
}
|
||||
|
||||
/* Check that os_fast_mutexes work as exptected */
|
||||
os_fast_mutex_init(&srv_os_test_mutex);
|
||||
|
||||
if (0 != os_fast_mutex_trylock(&srv_os_test_mutex)) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: pthread_mutex_trylock returns an unexpected value on\n"
|
||||
"InnoDB: success! Cannot continue.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
os_fast_mutex_unlock(&srv_os_test_mutex);
|
||||
|
||||
os_fast_mutex_lock(&srv_os_test_mutex);
|
||||
|
||||
os_fast_mutex_unlock(&srv_os_test_mutex);
|
||||
|
||||
if (srv_print_verbose_log)
|
||||
{
|
||||
ut_print_timestamp(stderr);
|
||||
|
|
|
@ -454,7 +454,7 @@ sync_array_cell_print(
|
|||
|
||||
buf += sprintf(buf,
|
||||
"--Thread %lu has waited at %s line %lu for %.2f seconds the semaphore:\n",
|
||||
(ulint)cell->thread, cell->file, cell->line,
|
||||
os_thread_pf(cell->thread), cell->file, cell->line,
|
||||
difftime(time(NULL), cell->reservation_time));
|
||||
|
||||
if (type == SYNC_MUTEX) {
|
||||
|
@ -486,7 +486,7 @@ sync_array_cell_print(
|
|||
if (rwlock->writer != RW_LOCK_NOT_LOCKED) {
|
||||
buf += sprintf(buf,
|
||||
"a writer (thread id %lu) has reserved it in mode",
|
||||
(ulint)rwlock->writer_thread);
|
||||
os_thread_pf(rwlock->writer_thread));
|
||||
if (rwlock->writer == RW_LOCK_EX) {
|
||||
buf += sprintf(buf, " exclusive\n");
|
||||
} else {
|
||||
|
@ -535,8 +535,8 @@ sync_array_find_thread(
|
|||
|
||||
cell = sync_array_get_nth_cell(arr, i);
|
||||
|
||||
if ((cell->wait_object != NULL)
|
||||
&& (cell->thread == thread)) {
|
||||
if (cell->wait_object != NULL
|
||||
&& os_thread_eq(cell->thread, thread)) {
|
||||
|
||||
return(cell); /* Found */
|
||||
}
|
||||
|
@ -651,9 +651,9 @@ sync_array_detect_deadlock(
|
|||
sync_array_cell_print(buf, cell);
|
||||
printf(
|
||||
"Mutex %lx owned by thread %lu file %s line %lu\n%s",
|
||||
(ulint)mutex, mutex->thread_id,
|
||||
mutex->file_name, mutex->line,
|
||||
buf);
|
||||
(ulint)mutex, os_thread_pf(mutex->thread_id),
|
||||
mutex->file_name, mutex->line, buf);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
@ -671,9 +671,9 @@ sync_array_detect_deadlock(
|
|||
thread = debug->thread_id;
|
||||
|
||||
if (((debug->lock_type == RW_LOCK_EX)
|
||||
&& (thread != cell->thread))
|
||||
&& !os_thread_eq(thread, cell->thread))
|
||||
|| ((debug->lock_type == RW_LOCK_WAIT_EX)
|
||||
&& (thread != cell->thread))
|
||||
&& !os_thread_eq(thread, cell->thread))
|
||||
|| (debug->lock_type == RW_LOCK_SHARED)) {
|
||||
|
||||
/* The (wait) x-lock request can block infinitely
|
||||
|
@ -771,7 +771,7 @@ sync_arr_cell_can_wake_up(
|
|||
|
||||
if (rw_lock_get_reader_count(lock) == 0
|
||||
&& rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX
|
||||
&& lock->writer_thread == cell->thread) {
|
||||
&& os_thread_eq(lock->writer_thread, cell->thread)) {
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
@ -927,7 +927,7 @@ sync_array_print_long_waits(void)
|
|||
&& difftime(time(NULL), cell->reservation_time) > 420) {
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: semaphore wait has lasted > 420 seconds\n"
|
||||
"InnoDB: Error: semaphore wait has lasted > 600 seconds\n"
|
||||
"InnoDB: We intentionally crash the server, because it appears to be hung.\n"
|
||||
);
|
||||
|
||||
|
@ -1011,3 +1011,4 @@ sync_array_print_info(
|
|||
|
||||
sync_array_exit(arr);
|
||||
}
|
||||
|
||||
|
|
|
@ -223,7 +223,7 @@ lock_loop:
|
|||
if (srv_print_latch_waits) {
|
||||
printf(
|
||||
"Thread %lu spin wait rw-s-lock at %lx cfile %s cline %lu rnds %lu\n",
|
||||
os_thread_get_curr_id(), (ulint)lock,
|
||||
os_thread_pf(os_thread_get_curr_id()), (ulint)lock,
|
||||
lock->cfile_name, lock->cline, i);
|
||||
}
|
||||
|
||||
|
@ -253,7 +253,7 @@ lock_loop:
|
|||
if (srv_print_latch_waits) {
|
||||
printf(
|
||||
"Thread %lu OS wait rw-s-lock at %lx cfile %s cline %lu\n",
|
||||
os_thread_get_curr_id(), (ulint)lock,
|
||||
os_thread_pf(os_thread_get_curr_id()), (ulint)lock,
|
||||
lock->cfile_name, lock->cline);
|
||||
}
|
||||
|
||||
|
@ -343,7 +343,8 @@ rw_lock_x_lock_low(
|
|||
}
|
||||
|
||||
} else if ((rw_lock_get_writer(lock) == RW_LOCK_WAIT_EX)
|
||||
&& (lock->writer_thread == os_thread_get_curr_id())) {
|
||||
&& os_thread_eq(lock->writer_thread,
|
||||
os_thread_get_curr_id())) {
|
||||
|
||||
if (rw_lock_get_reader_count(lock) == 0) {
|
||||
|
||||
|
@ -368,7 +369,8 @@ rw_lock_x_lock_low(
|
|||
return(RW_LOCK_WAIT_EX);
|
||||
|
||||
} else if ((rw_lock_get_writer(lock) == RW_LOCK_EX)
|
||||
&& (lock->writer_thread == os_thread_get_curr_id())
|
||||
&& os_thread_eq(lock->writer_thread,
|
||||
os_thread_get_curr_id())
|
||||
&& (lock->pass == 0)
|
||||
&& (pass == 0)) {
|
||||
|
||||
|
@ -469,7 +471,7 @@ lock_loop:
|
|||
if (srv_print_latch_waits) {
|
||||
printf(
|
||||
"Thread %lu spin wait rw-x-lock at %lx cfile %s cline %lu rnds %lu\n",
|
||||
os_thread_get_curr_id(), (ulint)lock,
|
||||
os_thread_pf(os_thread_get_curr_id()), (ulint)lock,
|
||||
lock->cfile_name, lock->cline, i);
|
||||
}
|
||||
|
||||
|
@ -502,8 +504,8 @@ lock_loop:
|
|||
if (srv_print_latch_waits) {
|
||||
printf(
|
||||
"Thread %lu OS wait for rw-x-lock at %lx cfile %s cline %lu\n",
|
||||
os_thread_get_curr_id(), (ulint)lock, lock->cfile_name,
|
||||
lock->cline);
|
||||
os_thread_pf(os_thread_get_curr_id()), (ulint)lock,
|
||||
lock->cfile_name, lock->cline);
|
||||
}
|
||||
|
||||
rw_x_system_call_count++;
|
||||
|
@ -621,7 +623,8 @@ rw_lock_remove_debug_info(
|
|||
while (info != NULL) {
|
||||
if ((pass == info->pass)
|
||||
&& ((pass != 0)
|
||||
|| (info->thread_id == os_thread_get_curr_id()))
|
||||
|| os_thread_eq(info->thread_id,
|
||||
os_thread_get_curr_id()))
|
||||
&& (info->lock_type == lock_type)) {
|
||||
|
||||
/* Found! */
|
||||
|
@ -676,7 +679,7 @@ rw_lock_own(
|
|||
|
||||
while (info != NULL) {
|
||||
|
||||
if ((info->thread_id == os_thread_get_curr_id())
|
||||
if (os_thread_eq(info->thread_id, os_thread_get_curr_id())
|
||||
&& (info->pass == 0)
|
||||
&& (info->lock_type == lock_type)) {
|
||||
|
||||
|
@ -834,7 +837,7 @@ rw_lock_debug_print(
|
|||
rwt = info->lock_type;
|
||||
|
||||
printf("Locked: thread %ld file %s line %ld ",
|
||||
info->thread_id, info->file_name, info->line);
|
||||
os_thread_pf(info->thread_id), info->file_name, info->line);
|
||||
if (rwt == RW_LOCK_SHARED) {
|
||||
printf("S-LOCK");
|
||||
} else if (rwt == RW_LOCK_EX) {
|
||||
|
|
|
@ -230,7 +230,6 @@ mutex_create_func(
|
|||
mutex->magic_n = MUTEX_MAGIC_N;
|
||||
mutex->line = 0;
|
||||
mutex->file_name = (char *) "not yet reserved";
|
||||
mutex->thread_id = ULINT_UNDEFINED;
|
||||
mutex->level = SYNC_LEVEL_NONE;
|
||||
mutex->cfile_name = cfile_name;
|
||||
mutex->cline = cline;
|
||||
|
@ -392,8 +391,8 @@ spin_loop:
|
|||
if (srv_print_latch_waits) {
|
||||
printf(
|
||||
"Thread %lu spin wait mutex at %lx cfile %s cline %lu rnds %lu\n",
|
||||
os_thread_get_curr_id(), (ulint)mutex, mutex->cfile_name,
|
||||
mutex->cline, i);
|
||||
os_thread_pf(os_thread_get_curr_id()), (ulint)mutex,
|
||||
mutex->cfile_name, mutex->cline, i);
|
||||
}
|
||||
|
||||
mutex_spin_round_count += i;
|
||||
|
@ -458,7 +457,7 @@ spin_loop:
|
|||
if (srv_print_latch_waits) {
|
||||
printf(
|
||||
"Thread %lu spin wait succeeds at 2: mutex at %lx\n",
|
||||
os_thread_get_curr_id(), (ulint)mutex);
|
||||
os_thread_pf(os_thread_get_curr_id()), (ulint)mutex);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -476,8 +475,8 @@ spin_loop:
|
|||
if (srv_print_latch_waits) {
|
||||
printf(
|
||||
"Thread %lu OS wait mutex at %lx cfile %s cline %lu rnds %lu\n",
|
||||
os_thread_get_curr_id(), (ulint)mutex, mutex->cfile_name,
|
||||
mutex->cline, i);
|
||||
os_thread_pf(os_thread_get_curr_id()), (ulint)mutex,
|
||||
mutex->cfile_name, mutex->cline, i);
|
||||
}
|
||||
|
||||
mutex_system_call_count++;
|
||||
|
@ -572,7 +571,7 @@ mutex_own(
|
|||
return(FALSE);
|
||||
}
|
||||
|
||||
if (mutex->thread_id != os_thread_get_curr_id()) {
|
||||
if (!os_thread_eq(mutex->thread_id, os_thread_get_curr_id())) {
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
|
@ -611,7 +610,8 @@ mutex_list_print_info(void)
|
|||
&thread_id);
|
||||
printf(
|
||||
"Locked mutex: addr %lx thread %ld file %s line %ld\n",
|
||||
(ulint)mutex, thread_id, file_name, line);
|
||||
(ulint)mutex, os_thread_pf(thread_id),
|
||||
file_name, line);
|
||||
}
|
||||
|
||||
mutex = UT_LIST_GET_NEXT(list, mutex);
|
||||
|
@ -716,7 +716,7 @@ sync_thread_level_arrays_find_slot(void)
|
|||
|
||||
slot = sync_thread_level_arrays_get_nth(i);
|
||||
|
||||
if (slot->levels && (slot->id == id)) {
|
||||
if (slot->levels && os_thread_eq(slot->id, id)) {
|
||||
|
||||
return(slot);
|
||||
}
|
||||
|
@ -780,7 +780,7 @@ sync_thread_levels_g(
|
|||
{
|
||||
char* file_name;
|
||||
ulint line;
|
||||
ulint thread_id;
|
||||
os_thread_id_t thread_id;
|
||||
sync_level_t* slot;
|
||||
rw_lock_t* lock;
|
||||
mutex_t* mutex;
|
||||
|
@ -810,7 +810,7 @@ sync_thread_levels_g(
|
|||
&file_name, &line, &thread_id);
|
||||
|
||||
printf("InnoDB: Locked mutex: addr %lx thread %ld file %s line %ld\n",
|
||||
(ulint)mutex, thread_id,
|
||||
(ulint)mutex, os_thread_pf(thread_id),
|
||||
file_name, line);
|
||||
} else {
|
||||
printf("Not locked\n");
|
||||
|
|
|
@ -69,8 +69,8 @@ try_again:
|
|||
|
||||
local = NULL;
|
||||
|
||||
HASH_SEARCH(hash, thr_local_hash, os_thread_conv_id_to_ulint(id),
|
||||
local, local->id == id);
|
||||
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
|
||||
local, os_thread_eq(local->id, id));
|
||||
if (local == NULL) {
|
||||
mutex_exit(&thr_local_mutex);
|
||||
|
||||
|
@ -173,7 +173,7 @@ thr_local_create(void)
|
|||
mutex_enter(&thr_local_mutex);
|
||||
|
||||
HASH_INSERT(thr_local_t, hash, thr_local_hash,
|
||||
os_thread_conv_id_to_ulint(os_thread_get_curr_id()),
|
||||
os_thread_pf(os_thread_get_curr_id()),
|
||||
local);
|
||||
|
||||
mutex_exit(&thr_local_mutex);
|
||||
|
@ -193,8 +193,8 @@ thr_local_free(
|
|||
|
||||
/* Look for the local struct in the hash table */
|
||||
|
||||
HASH_SEARCH(hash, thr_local_hash, os_thread_conv_id_to_ulint(id),
|
||||
local, local->id == id);
|
||||
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
|
||||
local, os_thread_eq(local->id, id));
|
||||
if (local == NULL) {
|
||||
mutex_exit(&thr_local_mutex);
|
||||
|
||||
|
@ -202,7 +202,7 @@ thr_local_free(
|
|||
}
|
||||
|
||||
HASH_DELETE(thr_local_t, hash, thr_local_hash,
|
||||
os_thread_conv_id_to_ulint(id), local);
|
||||
os_thread_pf(id), local);
|
||||
|
||||
mutex_exit(&thr_local_mutex);
|
||||
|
||||
|
|
|
@ -493,6 +493,34 @@ trx_sys_update_mysql_binlog_offset(
|
|||
MLOG_4BYTES, mtr);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Prints to stdout the MySQL binlog info in the system header if the
|
||||
magic number shows it valid. */
|
||||
|
||||
void
|
||||
trx_sys_print_mysql_binlog_offset_from_page(
|
||||
/*========================================*/
|
||||
byte* page) /* in: buffer containing the trx system header page,
|
||||
i.e., page number TRX_SYS_PAGE_NO in the tablespace */
|
||||
{
|
||||
trx_sysf_t* sys_header;
|
||||
|
||||
sys_header = page + TRX_SYS;
|
||||
|
||||
if (mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
|
||||
== TRX_SYS_MYSQL_LOG_MAGIC_N) {
|
||||
|
||||
printf(
|
||||
"ibbackup: Last MySQL binlog file position %lu %lu, file name %s\n",
|
||||
mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
|
||||
mach_read_from_4(sys_header + TRX_SYS_MYSQL_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW),
|
||||
sys_header + TRX_SYS_MYSQL_LOG_INFO + TRX_SYS_MYSQL_LOG_NAME);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Prints to stderr the MySQL binlog offset info in the trx system header if
|
||||
the magic number shows it valid. */
|
||||
|
|
|
@ -72,6 +72,7 @@ trx_create(
|
|||
|
||||
trx->type = TRX_USER;
|
||||
trx->conc_state = TRX_NOT_STARTED;
|
||||
trx->start_time = time(NULL);
|
||||
|
||||
trx->check_foreigns = TRUE;
|
||||
trx->check_unique_secondary = TRUE;
|
||||
|
@ -516,6 +517,7 @@ trx_start_low(
|
|||
if (trx->type == TRX_PURGE) {
|
||||
trx->id = ut_dulint_zero;
|
||||
trx->conc_state = TRX_ACTIVE;
|
||||
trx->start_time = time(NULL);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
@ -539,6 +541,7 @@ trx_start_low(
|
|||
trx->rseg = rseg;
|
||||
|
||||
trx->conc_state = TRX_ACTIVE;
|
||||
trx->start_time = time(NULL);
|
||||
|
||||
UT_LIST_ADD_FIRST(trx_list, trx_sys->trx_list, trx);
|
||||
|
||||
|
@ -1465,10 +1468,26 @@ trx_print(
|
|||
500 bytes */
|
||||
trx_t* trx) /* in: transaction */
|
||||
{
|
||||
buf += sprintf(buf, "TRANSACTION %lu %lu, OS thread id %lu",
|
||||
char* start_of_line;
|
||||
|
||||
buf += sprintf(buf, "TRANSACTION %lu %lu",
|
||||
ut_dulint_get_high(trx->id),
|
||||
ut_dulint_get_low(trx->id),
|
||||
(ulint)trx->mysql_thread_id);
|
||||
ut_dulint_get_low(trx->id));
|
||||
|
||||
switch (trx->conc_state) {
|
||||
case TRX_NOT_STARTED: buf += sprintf(buf,
|
||||
", not started"); break;
|
||||
case TRX_ACTIVE: buf += sprintf(buf,
|
||||
", ACTIVE %lu sec",
|
||||
(ulint)difftime(time(NULL), trx->start_time)); break;
|
||||
case TRX_COMMITTED_IN_MEMORY: buf += sprintf(buf,
|
||||
", COMMITTED IN MEMORY");
|
||||
break;
|
||||
default: buf += sprintf(buf, " state %lu", trx->conc_state);
|
||||
}
|
||||
|
||||
buf += sprintf(buf, ", OS thread id %lu",
|
||||
os_thread_pf(trx->mysql_thread_id));
|
||||
|
||||
if (ut_strlen(trx->op_info) > 0) {
|
||||
buf += sprintf(buf, " %s", trx->op_info);
|
||||
|
@ -1477,33 +1496,29 @@ trx_print(
|
|||
if (trx->type != TRX_USER) {
|
||||
buf += sprintf(buf, " purge trx");
|
||||
}
|
||||
|
||||
buf += sprintf(buf, "\n");
|
||||
|
||||
switch (trx->conc_state) {
|
||||
case TRX_NOT_STARTED: buf += sprintf(buf,
|
||||
", not started"); break;
|
||||
case TRX_ACTIVE: buf += sprintf(buf,
|
||||
", active"); break;
|
||||
case TRX_COMMITTED_IN_MEMORY: buf += sprintf(buf,
|
||||
", committed in memory");
|
||||
break;
|
||||
default: buf += sprintf(buf, " state %lu", trx->conc_state);
|
||||
}
|
||||
start_of_line = buf;
|
||||
|
||||
switch (trx->que_state) {
|
||||
case TRX_QUE_RUNNING: buf += sprintf(buf,
|
||||
", runs or sleeps"); break;
|
||||
case TRX_QUE_RUNNING: break;
|
||||
case TRX_QUE_LOCK_WAIT: buf += sprintf(buf,
|
||||
", lock wait"); break;
|
||||
"LOCK WAIT "); break;
|
||||
case TRX_QUE_ROLLING_BACK: buf += sprintf(buf,
|
||||
", rolling back"); break;
|
||||
"ROLLING BACK "); break;
|
||||
case TRX_QUE_COMMITTING: buf += sprintf(buf,
|
||||
", committing"); break;
|
||||
default: buf += sprintf(buf, " que state %lu", trx->que_state);
|
||||
"COMMITTING "); break;
|
||||
default: buf += sprintf(buf, "que state %lu", trx->que_state);
|
||||
}
|
||||
|
||||
if (0 < UT_LIST_GET_LEN(trx->trx_locks)) {
|
||||
buf += sprintf(buf, ", has %lu lock struct(s)",
|
||||
UT_LIST_GET_LEN(trx->trx_locks));
|
||||
if (0 < UT_LIST_GET_LEN(trx->trx_locks) ||
|
||||
mem_heap_get_size(trx->lock_heap) > 400) {
|
||||
|
||||
buf += sprintf(buf,
|
||||
"%lu lock struct(s), heap size %lu",
|
||||
UT_LIST_GET_LEN(trx->trx_locks),
|
||||
mem_heap_get_size(trx->lock_heap));
|
||||
}
|
||||
|
||||
if (trx->has_search_latch) {
|
||||
|
@ -1515,7 +1530,10 @@ trx_print(
|
|||
ut_dulint_get_low(trx->undo_no));
|
||||
}
|
||||
|
||||
buf += sprintf(buf, "\n");
|
||||
if (buf != start_of_line) {
|
||||
|
||||
buf += sprintf(buf, "\n");
|
||||
}
|
||||
|
||||
if (trx->mysql_thd != NULL) {
|
||||
innobase_mysql_print_thd(buf, trx->mysql_thd);
|
||||
|
|
|
@ -49,6 +49,10 @@ link_sources:
|
|||
rm -f $(srcdir)/$$f; \
|
||||
@LN_CP_F@ $(srcdir)/../strings/$$f $(srcdir)/$$f; \
|
||||
done; \
|
||||
for f in $(mystringsgen); do \
|
||||
rm -f $(srcdir)/$$f; \
|
||||
@LN_CP_F@ ../strings/$$f $(srcdir)/$$f; \
|
||||
done; \
|
||||
for f in $$qs; do \
|
||||
rm -f $(srcdir)/$$f; \
|
||||
@LN_CP_F@ $(srcdir)/../sql/$$f $(srcdir)/$$f; \
|
||||
|
|
|
@ -42,7 +42,8 @@ mystringsobjects = strmov.lo strxmov.lo strxnmov.lo strnmov.lo \
|
|||
bchange.lo bmove.lo bmove_upp.lo longlong2str.lo \
|
||||
strtoull.lo strtoll.lo llstr.lo \
|
||||
ctype.lo $(LTCHARSET_OBJS)
|
||||
mystringsextra= strto.c ctype_autoconf.c
|
||||
mystringsextra= strto.c
|
||||
mystringsgen= ctype_autoconf.c
|
||||
dbugobjects = dbug.lo # IT IS IN SAFEMALLOC.C sanity.lo
|
||||
mysysheaders = mysys_priv.h my_static.h
|
||||
mysysobjects1 = my_init.lo my_static.lo my_malloc.lo my_realloc.lo \
|
||||
|
@ -83,9 +84,8 @@ clean-local:
|
|||
rm -f `echo $(mystringsobjects) | sed "s;\.lo;.c;g"` \
|
||||
`echo $(dbugobjects) | sed "s;\.lo;.c;g"` \
|
||||
`echo $(mysysobjects) | sed "s;\.lo;.c;g"` \
|
||||
`echo $(vio_objects) | sed "s;\.lo;.c;g"` \
|
||||
$(mystringsextra) $(mysysheaders) ctype_extra_sources.c \
|
||||
net.c ../linked_client_sources
|
||||
$(mystringsextra) $(mystringsgen) $(mysysheaders) \
|
||||
ctype_extra_sources.c net.c ../linked_client_sources
|
||||
|
||||
ctype_extra_sources.c: conf_to_src
|
||||
./conf_to_src $(top_srcdir) @CHARSETS_NEED_SOURCE@ > \
|
||||
|
|
|
@ -151,7 +151,7 @@ int vio_write(Vio * vio, const gptr buf, int size)
|
|||
DBUG_RETURN(size);
|
||||
}
|
||||
|
||||
int vio_blocking(Vio * vio, my_bool set_blocking_mode)
|
||||
int vio_blocking(Vio * vio, my_bool set_blocking_mode, my_bool *old_mode)
|
||||
{
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -395,3 +395,25 @@ gender dist_count percentage
|
|||
M 1 20.00
|
||||
F 3 60.00
|
||||
drop table t1,t2;
|
||||
CREATE TABLE t1 (ID1 int, ID2 int, ID int NOT NULL AUTO_INCREMENT,PRIMARY KEY(ID
|
||||
));
|
||||
insert into t1 values (1,244,NULL),(2,243,NULL),(134,223,NULL),(185,186,NULL);
|
||||
select S.ID as xID, S.ID1 as xID1 from t1 as S left join t1 as yS on S.ID1 between yS.ID1 and yS.ID2;
|
||||
xID xID1
|
||||
1 1
|
||||
2 2
|
||||
2 2
|
||||
3 134
|
||||
3 134
|
||||
3 134
|
||||
4 185
|
||||
4 185
|
||||
4 185
|
||||
4 185
|
||||
select S.ID as xID, S.ID1 as xID1, repeat('*',count(distinct yS.ID)) as Level from t1 as S left join t1 as yS on S.ID1 between yS.ID1 and yS.ID2 group by xID order by xID1;
|
||||
xID xID1 Level
|
||||
1 1 *
|
||||
2 2 **
|
||||
3 134 ***
|
||||
4 185 ****
|
||||
drop table t1;
|
||||
|
|
|
@ -301,3 +301,14 @@ insert into t2 values (1, '2002-06-09'),(2, '2002-06-09'),(1, '2002-06-09'),(3,
|
|||
select u.gender as gender, count(distinct u.id) as dist_count, (count(distinct u.id)/5*100) as percentage from t1 u, t2 l where l.user_id = u.id group by u.gender;
|
||||
select u.gender as gender, count(distinct u.id) as dist_count, (count(distinct u.id)/5*100) as percentage from t1 u, t2 l where l.user_id = u.id group by u.gender order by percentage;
|
||||
drop table t1,t2;
|
||||
|
||||
#
|
||||
# The GROUP BY returned rows in wrong order in 3.23.51
|
||||
#
|
||||
|
||||
CREATE TABLE t1 (ID1 int, ID2 int, ID int NOT NULL AUTO_INCREMENT,PRIMARY KEY(ID
|
||||
));
|
||||
insert into t1 values (1,244,NULL),(2,243,NULL),(134,223,NULL),(185,186,NULL);
|
||||
select S.ID as xID, S.ID1 as xID1 from t1 as S left join t1 as yS on S.ID1 between yS.ID1 and yS.ID2;
|
||||
select S.ID as xID, S.ID1 as xID1, repeat('*',count(distinct yS.ID)) as Level from t1 as S left join t1 as yS on S.ID1 between yS.ID1 and yS.ID2 group by xID order by xID1;
|
||||
drop table t1;
|
||||
|
|
|
@ -438,6 +438,12 @@ int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
|||
|
||||
|
||||
#ifdef HPUX
|
||||
/*
|
||||
In HP-UX-10.20 and other old Posix 1003.4a Draft 4 implementations
|
||||
pthread_mutex_trylock returns 1 on success, not 0 like
|
||||
pthread_mutex_lock
|
||||
*/
|
||||
|
||||
int my_pthread_mutex_trylock(pthread_mutex_t *mutex)
|
||||
{
|
||||
int error=pthread_mutex_trylock(mutex);
|
||||
|
@ -447,9 +453,9 @@ int my_pthread_mutex_trylock(pthread_mutex_t *mutex)
|
|||
error=errno;
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Some help functions */
|
||||
|
||||
int pthread_no_free(void *not_used __attribute__((unused)))
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include <my_global.h>
|
||||
#include <my_semaphore.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if !defined(__WIN__) && !defined(HAVE_SEMAPHORE_H)
|
||||
|
||||
|
|
|
@ -50,7 +50,8 @@ Usage: $0 db_name[./table_regex/] [new_db_name | directory]
|
|||
-?, --help display this helpscreen and exit
|
||||
-u, --user=# user for database login if not current user
|
||||
-p, --password=# password to use when connecting to server
|
||||
-P, --port=# port to use when connecting to local server
|
||||
-h, --host=# Hostname for local server when connecting over TCP/IP
|
||||
-P, --port=# port to use when connecting to local server with TCP/IP
|
||||
-S, --socket=# socket to use when connecting to local server
|
||||
|
||||
--allowold don\'t abort if target already exists (rename it _old)
|
||||
|
@ -155,8 +156,8 @@ $opt{quiet} = 0 if $opt{debug};
|
|||
$opt{allowold} = 1 if $opt{keepold};
|
||||
|
||||
# --- connect to the database ---
|
||||
my $dsn = ";host=localhost";
|
||||
$dsn = ";host=127.0.0.1" if $opt{port}; # use TCP/IP if port was given
|
||||
my $dsn;
|
||||
$dsn = ";host=" . (defined($opt{host}) ? $opt{host} : "localhost");
|
||||
$dsn .= ";port=$opt{port}" if $opt{port};
|
||||
$dsn .= ";mysql_socket=$opt{socket}" if $opt{socket};
|
||||
|
||||
|
@ -891,9 +892,15 @@ user for database login if not current user
|
|||
|
||||
password to use when connecting to server
|
||||
|
||||
=item -h, -h, --host=#
|
||||
|
||||
Hostname for local server when connecting over TCP/IP. By specifying this
|
||||
different from 'localhost' will trigger mysqlhotcopy to use TCP/IP connection.
|
||||
|
||||
=item -P, --port=#
|
||||
|
||||
port to use when connecting to local server
|
||||
port to use when connecting to MySQL server with TCP/IP. This is only used
|
||||
when using the --host option.
|
||||
|
||||
=item -S, --socket=#
|
||||
|
||||
|
|
371
sql/ha_innodb.cc
371
sql/ha_innodb.cc
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 2000 MySQL AB & InnoDB Oy
|
||||
/* Copyright (C) 2000 MySQL AB & Innobase Oy
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -55,6 +55,7 @@ typedef byte mysql_byte;
|
|||
extern "C" {
|
||||
#include "../innobase/include/univ.i"
|
||||
#include "../innobase/include/os0file.h"
|
||||
#include "../innobase/include/os0thread.h"
|
||||
#include "../innobase/include/srv0start.h"
|
||||
#include "../innobase/include/srv0srv.h"
|
||||
#include "../innobase/include/trx0roll.h"
|
||||
|
@ -110,8 +111,6 @@ my_bool innobase_fast_shutdown = TRUE;
|
|||
specify any startup options.
|
||||
*/
|
||||
|
||||
/* innobase_data_file_path=ibdata:15,idata2:1,... */
|
||||
|
||||
char *innobase_data_file_path= (char*) "ibdata1:10M:autoextend";
|
||||
static char *internal_innobase_data_file_path=0;
|
||||
|
||||
|
@ -138,8 +137,9 @@ static void innobase_print_error(const char* db_errpfx, char* buffer);
|
|||
/* General functions */
|
||||
|
||||
/**********************************************************************
|
||||
Releases possible search latch, auto inc lock, and InnoDB thread FIFO ticket.
|
||||
These should be released at each SQL statement end. */
|
||||
Releases possible search latch and InnoDB thread FIFO ticket. These should
|
||||
be released at each SQL statement end. It does no harm to release these
|
||||
also in the middle of an SQL statement. */
|
||||
static
|
||||
void
|
||||
innobase_release_stat_resources(
|
||||
|
@ -150,16 +150,6 @@ innobase_release_stat_resources(
|
|||
trx_search_latch_release_if_reserved(trx);
|
||||
}
|
||||
|
||||
if (trx->auto_inc_lock) {
|
||||
|
||||
/* If we had reserved the auto-inc lock for
|
||||
some table in this SQL statement, we release it now */
|
||||
|
||||
srv_conc_enter_innodb(trx);
|
||||
row_unlock_table_autoinc_for_mysql(trx);
|
||||
srv_conc_exit_innodb(trx);
|
||||
}
|
||||
|
||||
if (trx->declared_to_be_inside_innodb) {
|
||||
/* Release our possible ticket in the FIFO */
|
||||
|
||||
|
@ -646,6 +636,16 @@ innobase_commit(
|
|||
|
||||
trx = check_trx_exists(thd);
|
||||
|
||||
if (trx->auto_inc_lock) {
|
||||
|
||||
/* If we had reserved the auto-inc lock for
|
||||
some table in this SQL statement, we release it now */
|
||||
|
||||
srv_conc_enter_innodb(trx);
|
||||
row_unlock_table_autoinc_for_mysql(trx);
|
||||
srv_conc_exit_innodb(trx);
|
||||
}
|
||||
|
||||
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
|
||||
innobase_commit_low(trx);
|
||||
}
|
||||
|
@ -714,6 +714,16 @@ innobase_rollback(
|
|||
|
||||
trx = check_trx_exists(thd);
|
||||
|
||||
if (trx->auto_inc_lock) {
|
||||
|
||||
/* If we had reserved the auto-inc lock for
|
||||
some table in this SQL statement, we release it now */
|
||||
|
||||
srv_conc_enter_innodb(trx);
|
||||
row_unlock_table_autoinc_for_mysql(trx);
|
||||
srv_conc_exit_innodb(trx);
|
||||
}
|
||||
|
||||
srv_conc_enter_innodb(trx);
|
||||
|
||||
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle) {
|
||||
|
@ -842,7 +852,7 @@ normalize_table_name(
|
|||
}
|
||||
|
||||
/*********************************************************************
|
||||
Creates and opens a handle to a table which already exists in an Innobase
|
||||
Creates and opens a handle to a table which already exists in an InnoDB
|
||||
database. */
|
||||
|
||||
int
|
||||
|
@ -913,13 +923,13 @@ have moved .frm files to another database?",
|
|||
|
||||
primary_key = MAX_KEY;
|
||||
|
||||
if (!row_table_got_default_clust_index(ib_table)) {
|
||||
/* Allocate a buffer for a 'row reference'. A row reference is
|
||||
a string of bytes of length ref_length which uniquely specifies
|
||||
a row in our table. Note that MySQL may also compare two row
|
||||
references for equality by doing a simple memcmp on the strings
|
||||
of length ref_length! */
|
||||
|
||||
/* If we automatically created the clustered index,
|
||||
then MySQL does not know about it and it must not be aware
|
||||
of the index used on scan, to avoid checking if we update
|
||||
the column of the index. The column is the row id in
|
||||
the automatical case, and it will not be updated. */
|
||||
if (!row_table_got_default_clust_index(ib_table)) {
|
||||
|
||||
((row_prebuilt_t*)innobase_prebuilt)
|
||||
->clust_index_was_generated = FALSE;
|
||||
|
@ -928,13 +938,13 @@ have moved .frm files to another database?",
|
|||
key_used_on_scan = 0;
|
||||
|
||||
/*
|
||||
MySQL allocates the buffer for ref.
|
||||
This includes all keys + one byte for each column
|
||||
that may be NULL.
|
||||
The ref_length must be exact as possible as
|
||||
all reference buffers are allocated based on this.
|
||||
MySQL allocates the buffer for ref. key_info->key_length
|
||||
includes space for all key columns + one byte for each column
|
||||
that may be NULL. ref_length must be as exact as possible to
|
||||
save space, because all row reference buffers are allocated
|
||||
based on ref_length.
|
||||
*/
|
||||
|
||||
|
||||
ref_length = table->key_info->key_length;
|
||||
} else {
|
||||
((row_prebuilt_t*)innobase_prebuilt)
|
||||
|
@ -942,6 +952,15 @@ have moved .frm files to another database?",
|
|||
|
||||
ref_length = DATA_ROW_ID_LEN;
|
||||
|
||||
/*
|
||||
If we automatically created the clustered index, then
|
||||
MySQL does not know about it, and MySQL must NOT be aware
|
||||
of the index used on scan, to make it avoid checking if we
|
||||
update the column of the index. That is why we assert below
|
||||
that key_used_on_scan is the undefined value MAX_KEY.
|
||||
The column is the row id in the automatical generation case,
|
||||
and it will never be updated anyway.
|
||||
*/
|
||||
DBUG_ASSERT(key_used_on_scan == MAX_KEY);
|
||||
}
|
||||
|
||||
|
@ -1188,7 +1207,8 @@ get_innobase_type_from_mysql_type(
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
Stores a key value for a row to a buffer. */
|
||||
Stores a key value for a row to a buffer. This must currently only be used
|
||||
to store a row reference to the 'ref' buffer of this table handle! */
|
||||
|
||||
uint
|
||||
ha_innobase::store_key_val_for_row(
|
||||
|
@ -1196,7 +1216,8 @@ ha_innobase::store_key_val_for_row(
|
|||
/* out: key value length as stored in buff */
|
||||
uint keynr, /* in: key number */
|
||||
char* buff, /* in/out: buffer for the key value (in MySQL
|
||||
format) */
|
||||
format); currently this MUST be the 'ref'
|
||||
buffer! */
|
||||
const mysql_byte* record)/* in: row in MySQL format */
|
||||
{
|
||||
KEY* key_info = table->key_info + keynr;
|
||||
|
@ -1225,8 +1246,9 @@ ha_innobase::store_key_val_for_row(
|
|||
}
|
||||
|
||||
/*
|
||||
We have to zero-fill the buffer to be able to compare two
|
||||
keys to see if they are equal
|
||||
We have to zero-fill the 'ref' buffer so that MySQL is able to
|
||||
use a simple memcmp to compare two key values to determine if they
|
||||
are equal
|
||||
*/
|
||||
bzero(buff, (ref_length- (uint) (buff - buff_start)));
|
||||
DBUG_RETURN(ref_length);
|
||||
|
@ -1404,6 +1426,7 @@ ha_innobase::write_row(
|
|||
row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
|
||||
int error;
|
||||
longlong auto_inc;
|
||||
longlong dummy;
|
||||
|
||||
DBUG_ENTER("ha_innobase::write_row");
|
||||
|
||||
|
@ -1426,7 +1449,31 @@ ha_innobase::write_row(
|
|||
if (table->next_number_field && record == table->record[0]) {
|
||||
/* This is the case where the table has an
|
||||
auto-increment column */
|
||||
|
||||
|
||||
/* Initialize the auto-inc counter if it has not been
|
||||
initialized yet */
|
||||
|
||||
if (0 == dict_table_autoinc_peek(prebuilt->table)) {
|
||||
|
||||
/* This call initializes the counter */
|
||||
error = innobase_read_and_init_auto_inc(&dummy);
|
||||
|
||||
if (error) {
|
||||
/* Deadlock or lock wait timeout */
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
/* We have to set sql_stat_start to TRUE because
|
||||
the above call probably has called a select, and
|
||||
has reset that flag; row_insert_for_mysql has to
|
||||
know to set the IX intention lock on the table,
|
||||
something it only does at the start of each
|
||||
statement */
|
||||
|
||||
prebuilt->sql_stat_start = TRUE;
|
||||
}
|
||||
|
||||
/* Fetch the value the user possibly has set in the
|
||||
autoincrement field */
|
||||
|
||||
|
@ -1459,10 +1506,9 @@ ha_innobase::write_row(
|
|||
}
|
||||
|
||||
if (auto_inc != 0) {
|
||||
/* This call will calculate the max of the
|
||||
current value and the value supplied by the user, if
|
||||
the auto_inc counter is already initialized
|
||||
for the table */
|
||||
/* This call will calculate the max of the current
|
||||
value and the value supplied by the user and
|
||||
update the counter accordingly */
|
||||
|
||||
/* We have to use the transactional lock mechanism
|
||||
on the auto-inc counter of the table to ensure
|
||||
|
@ -1502,46 +1548,18 @@ ha_innobase::write_row(
|
|||
auto_inc = dict_table_autoinc_get(prebuilt->table);
|
||||
srv_conc_exit_innodb(prebuilt->trx);
|
||||
|
||||
/* If auto_inc is now != 0 the autoinc counter
|
||||
was already initialized for the table: we can give
|
||||
the new value for MySQL to place in the field */
|
||||
/* We can give the new value for MySQL to place in
|
||||
the field */
|
||||
|
||||
if (auto_inc != 0) {
|
||||
user_thd->next_insert_id = auto_inc;
|
||||
}
|
||||
user_thd->next_insert_id = auto_inc;
|
||||
}
|
||||
|
||||
/* This call of a handler.cc function places
|
||||
user_thd->next_insert_id to the column value, if the column
|
||||
value was not set by the user */
|
||||
|
||||
update_auto_increment();
|
||||
|
||||
if (auto_inc == 0) {
|
||||
/* The autoinc counter for our table was not yet
|
||||
initialized, initialize it now */
|
||||
|
||||
auto_inc = table->next_number_field->val_int();
|
||||
|
||||
srv_conc_enter_innodb(prebuilt->trx);
|
||||
error = row_lock_table_autoinc_for_mysql(prebuilt);
|
||||
srv_conc_exit_innodb(prebuilt->trx);
|
||||
|
||||
if (error != DB_SUCCESS) {
|
||||
|
||||
error = convert_error_code_to_mysql(error,
|
||||
user_thd);
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
dict_table_autoinc_initialize(prebuilt->table,
|
||||
auto_inc);
|
||||
}
|
||||
|
||||
/* We have to set sql_stat_start to TRUE because
|
||||
update_auto_increment may have called a select, and
|
||||
has reset that flag; row_insert_for_mysql has to
|
||||
know to set the IX intention lock on the table, something
|
||||
it only does at the start of each statement */
|
||||
|
||||
prebuilt->sql_stat_start = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (prebuilt->mysql_template == NULL
|
||||
|| prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
|
||||
|
@ -1901,6 +1919,55 @@ convert_search_mode_to_innobase(
|
|||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
BACKGROUND INFO: HOW A SELECT SQL QUERY IS EXECUTED
|
||||
---------------------------------------------------
|
||||
The following does not cover all the details, but explains how we determine
|
||||
the start of a new SQL statement, and what is associated with it.
|
||||
|
||||
For each table in the database the MySQL interpreter may have several
|
||||
table handle instances in use, also in a single SQL query. For each table
|
||||
handle instance there is an InnoDB 'prebuilt' struct which contains most
|
||||
of the InnoDB data associated with this table handle instance.
|
||||
|
||||
A) if the user has not explicitly set any MySQL table level locks:
|
||||
|
||||
1) MySQL calls ::external_lock to set an 'intention' table level lock on
|
||||
the table of the handle instance. There we set
|
||||
prebuilt->sql_stat_start = TRUE. The flag sql_stat_start should be set
|
||||
true if we are taking this table handle instance to use in a new SQL
|
||||
statement issued by the user. We also increment trx->n_mysql_tables_in_use.
|
||||
|
||||
2) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
|
||||
instructions to prebuilt->template of the table handle instance in
|
||||
::index_read. The template is used to save CPU time in large joins.
|
||||
|
||||
3) In row_search_for_mysql, if prebuilt->sql_stat_start is true, we
|
||||
allocate a new consistent read view for the trx if it does not yet have one,
|
||||
or in the case of a locking read, set an InnoDB 'intention' table level
|
||||
lock on the table.
|
||||
|
||||
4) We do the SELECT. MySQL may repeatedly call ::index_read for the
|
||||
same table handle instance, if it is a join.
|
||||
|
||||
5) When the SELECT ends, MySQL removes its intention table level locks
|
||||
in ::external_lock. When trx->n_mysql_tables_in_use drops to zero,
|
||||
(a) we execute a COMMIT there if the autocommit is on,
|
||||
(b) we also release possible 'SQL statement level resources' InnoDB may
|
||||
have for this SQL statement. The MySQL interpreter does NOT execute
|
||||
autocommit for pure read transactions, though it should. That is why the
|
||||
table handler in that case has to execute the COMMIT in ::external_lock.
|
||||
|
||||
B) If the user has explicitly set MySQL table level locks, then MySQL
|
||||
does NOT call ::external_lock at the start of the statement. To determine
|
||||
when we are at the start of a new SQL statement we at the start of
|
||||
::index_read also compare the query id to the latest query id where the
|
||||
table handle instance was used. If it has changed, we know we are at the
|
||||
start of a new SQL statement. Since the query id can theoretically
|
||||
overwrap, we use this test only as a secondary way of determining the
|
||||
start of a new SQL statement. */
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
Positions an index cursor to the index specified in the handle. Fetches the
|
||||
row if any. */
|
||||
|
@ -1914,7 +1981,10 @@ ha_innobase::index_read(
|
|||
row */
|
||||
const mysql_byte* key_ptr,/* in: key value; if this is NULL
|
||||
we position the cursor at the
|
||||
start or end of index */
|
||||
start or end of index; this can
|
||||
also contain an InnoDB row id, in
|
||||
which case key_len is the InnoDB
|
||||
row id length */
|
||||
uint key_len,/* in: key value length */
|
||||
enum ha_rkey_function find_flag)/* in: search flags from my_base.h */
|
||||
{
|
||||
|
@ -1941,10 +2011,8 @@ ha_innobase::index_read(
|
|||
|
||||
index = prebuilt->index;
|
||||
|
||||
/* Note that if the select is used for an update, we always
|
||||
fetch the clustered index record: therefore the index for which the
|
||||
template is built is not necessarily prebuilt->index, but can also
|
||||
be the clustered index */
|
||||
/* Note that if the index for which the search template is built is not
|
||||
necessarily prebuilt->index, but can also be the clustered index */
|
||||
|
||||
if (prebuilt->sql_stat_start) {
|
||||
build_template(prebuilt, user_thd, table,
|
||||
|
@ -1952,6 +2020,9 @@ ha_innobase::index_read(
|
|||
}
|
||||
|
||||
if (key_ptr) {
|
||||
/* Convert the search key value to InnoDB format into
|
||||
prebuilt->search_tuple */
|
||||
|
||||
row_sel_convert_mysql_key_to_innobase(prebuilt->search_tuple,
|
||||
(byte*) key_val_buff,
|
||||
index,
|
||||
|
@ -2313,8 +2384,7 @@ ha_innobase::rnd_next(
|
|||
}
|
||||
|
||||
/**************************************************************************
|
||||
Fetches a row from the table based on a reference. TODO: currently we use
|
||||
'ref_stored_len' of the handle as the key length. This may change. */
|
||||
Fetches a row from the table based on a row reference. */
|
||||
|
||||
int
|
||||
ha_innobase::rnd_pos(
|
||||
|
@ -2322,13 +2392,17 @@ ha_innobase::rnd_pos(
|
|||
/* out: 0, HA_ERR_KEY_NOT_FOUND,
|
||||
or error code */
|
||||
mysql_byte* buf, /* in/out: buffer for the row */
|
||||
mysql_byte* pos) /* in: primary key value in MySQL format */
|
||||
mysql_byte* pos) /* in: primary key value of the row in the
|
||||
MySQL format, or the row id if the clustered
|
||||
index was internally generated by InnoDB;
|
||||
the length of data in pos has to be
|
||||
ref_length */
|
||||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
int error;
|
||||
uint keynr = active_index;
|
||||
DBUG_ENTER("rnd_pos");
|
||||
DBUG_DUMP("key", (char*) pos, ref_stored_len);
|
||||
DBUG_DUMP("key", (char*) pos, ref_length);
|
||||
|
||||
statistic_increment(ha_read_rnd_count, &LOCK_status);
|
||||
|
||||
|
@ -2339,7 +2413,7 @@ ha_innobase::rnd_pos(
|
|||
/* No primary key was defined for the table and we
|
||||
generated the clustered index from the row id: the
|
||||
row reference is the row id, not any key value
|
||||
that MySQL knows */
|
||||
that MySQL knows of */
|
||||
|
||||
error = change_active_index(MAX_KEY);
|
||||
} else {
|
||||
|
@ -2351,7 +2425,10 @@ ha_innobase::rnd_pos(
|
|||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
error = index_read(buf, pos, ref_stored_len, HA_READ_KEY_EXACT);
|
||||
/* Note that we assume the length of the row reference is fixed
|
||||
for the table, and it is == ref_length */
|
||||
|
||||
error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
|
||||
if (error)
|
||||
{
|
||||
DBUG_PRINT("error",("Got error: %ld",error));
|
||||
|
@ -2363,8 +2440,8 @@ ha_innobase::rnd_pos(
|
|||
|
||||
/*************************************************************************
|
||||
Stores a reference to the current row to 'ref' field of the handle. Note
|
||||
that the function parameter is illogical: we must assume that 'record'
|
||||
is the current 'position' of the handle, because if row ref is actually
|
||||
that in the case where we have generated the clustered index for the
|
||||
table, the function parameter is illogical: we MUST ASSUME that 'record'
|
||||
the row id internally generated in InnoDB, then 'record' does not contain
|
||||
it. We just guess that the row id must be for the record where the handle
|
||||
was positioned the last time. */
|
||||
|
@ -2384,7 +2461,7 @@ ha_innobase::position(
|
|||
/* No primary key was defined for the table and we
|
||||
generated the clustered index from row id: the
|
||||
row reference will be the row id, not any key value
|
||||
that MySQL knows */
|
||||
that MySQL knows of */
|
||||
|
||||
len = DATA_ROW_ID_LEN;
|
||||
|
||||
|
@ -2393,8 +2470,11 @@ ha_innobase::position(
|
|||
len = store_key_val_for_row(primary_key, (char*) ref, record);
|
||||
}
|
||||
|
||||
DBUG_ASSERT(len == ref_length);
|
||||
ref_stored_len = len;
|
||||
/* Since we do not store len to the buffer 'ref', we must assume
|
||||
that len is always fixed for this table. The following assertion
|
||||
checks this. */
|
||||
|
||||
ut_a(len == ref_length);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2612,7 +2692,7 @@ ha_innobase::create(
|
|||
/* Our function row_get_mysql_key_number_for_index assumes
|
||||
the primary key is always number 0, if it exists */
|
||||
|
||||
assert(primary_key_no == -1 || primary_key_no == 0);
|
||||
DBUG_ASSERT(primary_key_no == -1 || primary_key_no == 0);
|
||||
|
||||
/* Create the keys */
|
||||
|
||||
|
@ -2693,7 +2773,7 @@ ha_innobase::create(
|
|||
|
||||
innobase_table = dict_table_get(norm_name, NULL);
|
||||
|
||||
assert(innobase_table != 0);
|
||||
DBUG_ASSERT(innobase_table != 0);
|
||||
|
||||
/* Tell the InnoDB server that there might be work for
|
||||
utility threads: */
|
||||
|
@ -3519,37 +3599,53 @@ ha_innobase::store_lock(
|
|||
}
|
||||
|
||||
/***********************************************************************
|
||||
Returns the next auto-increment column value for the table. write_row
|
||||
normally fetches the value from the cache in the data dictionary. This
|
||||
function in used by SHOW TABLE STATUS and when the first insert to the table
|
||||
is done after database startup. */
|
||||
This function initializes the auto-inc counter if it has not been
|
||||
initialized yet. This function does not change the value of the auto-inc
|
||||
counter if it already has been initialized. In parameter ret returns
|
||||
the value of the auto-inc counter. */
|
||||
|
||||
longlong
|
||||
ha_innobase::get_auto_increment()
|
||||
/*=============================*/
|
||||
/* out: the next auto-increment column value */
|
||||
int
|
||||
ha_innobase::innobase_read_and_init_auto_inc(
|
||||
/*=========================================*/
|
||||
/* out: 0 or error code: deadlock or
|
||||
lock wait timeout */
|
||||
longlong* ret) /* out: auto-inc value */
|
||||
{
|
||||
row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
|
||||
longlong nr;
|
||||
longlong auto_inc;
|
||||
int error;
|
||||
|
||||
ut_a(prebuilt);
|
||||
ut_a(prebuilt->trx ==
|
||||
(trx_t*) current_thd->transaction.all.innobase_tid);
|
||||
ut_a(prebuilt->table);
|
||||
|
||||
auto_inc = dict_table_autoinc_read(prebuilt->table);
|
||||
|
||||
/* Also SHOW TABLE STATUS calls this function. Previously, when we did
|
||||
always read the max autoinc key value, setting x-locks, users were
|
||||
surprised that SHOW TABLE STATUS could end up in a deadlock with
|
||||
ordinary SQL queries. We avoid these deadlocks if the auto-inc
|
||||
counter for the table has been initialized by fetching the value
|
||||
from the table struct in dictionary cache. */
|
||||
if (auto_inc != 0) {
|
||||
/* Already initialized */
|
||||
*ret = auto_inc;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
assert(prebuilt->table);
|
||||
|
||||
nr = dict_table_autoinc_read(prebuilt->table);
|
||||
srv_conc_enter_innodb(prebuilt->trx);
|
||||
error = row_lock_table_autoinc_for_mysql(prebuilt);
|
||||
srv_conc_exit_innodb(prebuilt->trx);
|
||||
|
||||
if (nr != 0) {
|
||||
if (error != DB_SUCCESS) {
|
||||
error = convert_error_code_to_mysql(error, user_thd);
|
||||
|
||||
return(nr + 1);
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
/* Check again if someone has initialized the counter meanwhile */
|
||||
auto_inc = dict_table_autoinc_read(prebuilt->table);
|
||||
|
||||
if (auto_inc != 0) {
|
||||
*ret = auto_inc;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
(void) extra(HA_EXTRA_KEYREAD);
|
||||
|
@ -3569,22 +3665,63 @@ ha_innobase::get_auto_increment()
|
|||
|
||||
prebuilt->hint_no_need_to_fetch_extra_cols = FALSE;
|
||||
|
||||
prebuilt->trx->mysql_n_tables_locked += 1;
|
||||
prebuilt->trx->mysql_n_tables_locked += 1;
|
||||
|
||||
error = index_last(table->record[1]);
|
||||
error = index_last(table->record[1]);
|
||||
|
||||
if (error) {
|
||||
nr = 1;
|
||||
if (error == HA_ERR_END_OF_FILE) {
|
||||
/* The table was empty, initialize to 1 */
|
||||
auto_inc = 1;
|
||||
|
||||
error = 0;
|
||||
} else {
|
||||
/* Deadlock or a lock wait timeout */
|
||||
auto_inc = -1;
|
||||
|
||||
goto func_exit;
|
||||
}
|
||||
} else {
|
||||
nr = (longlong) table->next_number_field->
|
||||
/* Initialize to max(col) + 1 */
|
||||
auto_inc = (longlong) table->next_number_field->
|
||||
val_int_offset(table->rec_buff_length) + 1;
|
||||
}
|
||||
|
||||
dict_table_autoinc_initialize(prebuilt->table, auto_inc);
|
||||
|
||||
func_exit:
|
||||
(void) extra(HA_EXTRA_NO_KEYREAD);
|
||||
|
||||
index_end();
|
||||
index_end();
|
||||
|
||||
return(nr);
|
||||
*ret = auto_inc;
|
||||
|
||||
return(error);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
This function initializes the auto-inc counter if it has not been
|
||||
initialized yet. This function does not change the value of the auto-inc
|
||||
counter if it already has been initialized. Returns the value of the
|
||||
auto-inc counter. */
|
||||
|
||||
longlong
|
||||
ha_innobase::get_auto_increment()
|
||||
/*=============================*/
|
||||
/* out: auto-increment column value, -1 if error
|
||||
(deadlock or lock wait timeout) */
|
||||
{
|
||||
longlong nr;
|
||||
int error;
|
||||
|
||||
error = innobase_read_and_init_auto_inc(&nr);
|
||||
|
||||
if (error) {
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(nr);
|
||||
}
|
||||
|
||||
#endif /* HAVE_INNOBASE_DB */
|
||||
|
|
|
@ -52,8 +52,6 @@ class ha_innobase: public handler
|
|||
byte* key_val_buff; /* buffer used in converting
|
||||
search key values from MySQL format
|
||||
to Innodb format */
|
||||
uint ref_stored_len; /* length of the key value stored to
|
||||
'ref' buffer of the handle, if any */
|
||||
ulong int_table_flags;
|
||||
uint primary_key;
|
||||
uint last_dup_key;
|
||||
|
@ -71,6 +69,7 @@ class ha_innobase: public handler
|
|||
int update_thd(THD* thd);
|
||||
int change_active_index(uint keynr);
|
||||
int general_fetch(byte* buf, uint direction, uint match_mode);
|
||||
int innobase_read_and_init_auto_inc(longlong* ret);
|
||||
|
||||
/* Init values for the class: */
|
||||
public:
|
||||
|
|
|
@ -251,7 +251,6 @@ static SYMBOL symbols[] = {
|
|||
{ "NEW", SYM(NEW_SYM),0,0},
|
||||
{ "NCHAR", SYM(NCHAR_SYM),0,0},
|
||||
{ "NO", SYM(NO_SYM),0,0},
|
||||
{ "NO_FOREIGN_KEY_CHECKS", SYM(NO_FOREIGN_KEY_CHECKS), 0, 0},
|
||||
{ "NOT", SYM(NOT),0,0},
|
||||
{ "NULL", SYM(NULL_SYM),0,0},
|
||||
{ "NUMERIC", SYM(NUMERIC_SYM),0,0},
|
||||
|
@ -285,7 +284,6 @@ static SYMBOL symbols[] = {
|
|||
{ "RELAY_LOG_POS", SYM(RELAY_LOG_POS_SYM),0,0},
|
||||
{ "RELOAD", SYM(RELOAD),0,0},
|
||||
{ "REGEXP", SYM(REGEXP),0,0},
|
||||
{ "RELAXED_UNIQUE_CHECKS", SYM(RELAXED_UNIQUE_CHECKS), 0, 0},
|
||||
{ "RENAME", SYM(RENAME),0,0},
|
||||
{ "REPAIR", SYM(REPAIR),0,0},
|
||||
{ "REPLACE", SYM(REPLACE),0,0},
|
||||
|
|
10
sql/log.cc
10
sql/log.cc
|
@ -1320,16 +1320,16 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
|
|||
if (end != buff)
|
||||
{
|
||||
*end++=';';
|
||||
*end++='\n';
|
||||
*end=0;
|
||||
*end='\n';
|
||||
if (my_b_write(&log_file, (byte*) "SET ",4) ||
|
||||
my_b_write(&log_file, (byte*) buff+1,(uint) (end-buff)-1))
|
||||
my_b_write(&log_file, (byte*) buff+1,(uint) (end-buff)))
|
||||
tmp_errno=errno;
|
||||
}
|
||||
if (!query)
|
||||
{
|
||||
query="#adminstrator command";
|
||||
query_length=21;
|
||||
end=strxmov(buff, "# administrator command: ",
|
||||
command_name[thd->command], NullS);
|
||||
query_length=(ulong) (end-buff);
|
||||
}
|
||||
if (my_b_write(&log_file, (byte*) query,query_length) ||
|
||||
my_b_write(&log_file, (byte*) ";\n",2) ||
|
||||
|
|
|
@ -1809,7 +1809,7 @@ int main(int argc, char **argv)
|
|||
exit( 1 );
|
||||
}
|
||||
#endif
|
||||
load_defaults("my",load_default_groups,&argc,&argv);
|
||||
load_defaults(MYSQL_CONFIG_NAME,load_default_groups,&argc,&argv);
|
||||
defaults_argv=argv;
|
||||
|
||||
/* Get default temporary directory */
|
||||
|
@ -2373,7 +2373,15 @@ static void create_new_thread(THD *thd)
|
|||
for (uint i=0; i < 8 ; i++) // Generate password teststring
|
||||
thd->scramble[i]= (char) (rnd(&sql_rand)*94+33);
|
||||
thd->scramble[8]=0;
|
||||
thd->rand=sql_rand;
|
||||
/*
|
||||
We need good random number initialization for new thread
|
||||
Just coping global one will not work
|
||||
*/
|
||||
{
|
||||
ulong tmp=(ulong) (rnd(&sql_rand) * 3000000);
|
||||
randominit(&(thd->rand), tmp + (ulong) start_time,
|
||||
tmp + (ulong) thread_id);
|
||||
}
|
||||
thd->real_id=pthread_self(); // Keep purify happy
|
||||
|
||||
/* Start a new thread to handle connection */
|
||||
|
@ -3260,8 +3268,8 @@ struct my_option my_long_options[] =
|
|||
#endif
|
||||
{"temp-pool", OPT_TEMP_POOL,
|
||||
"Using this option will cause most temporary files created to use a small set of names, rather than a unique name for each new file.",
|
||||
(gptr*) &use_temp_pool, (gptr*) &use_temp_pool, 0, GET_BOOL, NO_ARG, 0, 0,
|
||||
0, 0, 0, 0},
|
||||
(gptr*) &use_temp_pool, (gptr*) &use_temp_pool, 0, GET_BOOL, NO_ARG, 1,
|
||||
0, 0, 0, 0, 0},
|
||||
{"tmpdir", 't', "Path for temporary files", (gptr*) &opt_mysql_tmpdir,
|
||||
(gptr*) &opt_mysql_tmpdir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
|
||||
{"transaction-isolation", OPT_TX_ISOLATION,
|
||||
|
@ -3805,7 +3813,7 @@ Starts the MySQL server\n");
|
|||
");
|
||||
puts("");
|
||||
#endif
|
||||
print_defaults("my",load_default_groups);
|
||||
print_defaults(MYSQL_CONFIG_NAME,load_default_groups);
|
||||
puts("");
|
||||
fix_paths();
|
||||
set_ports();
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "sql_repl.h"
|
||||
#include "repl_failsafe.h"
|
||||
#include <thr_alarm.h>
|
||||
#include <my_dir.h>
|
||||
#include <assert.h>
|
||||
|
||||
bool use_slave_mask = 0;
|
||||
|
@ -1029,7 +1030,6 @@ void end_master_info(MASTER_INFO* mi)
|
|||
|
||||
int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname)
|
||||
{
|
||||
MY_STAT stat_area;
|
||||
char fname[FN_REFLEN+128];
|
||||
int info_fd;
|
||||
const char* msg = 0;
|
||||
|
@ -1069,7 +1069,7 @@ int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname)
|
|||
DBUG_RETURN(1);
|
||||
|
||||
/* if file does not exist */
|
||||
if (!my_stat(fname, &stat_area, MYF(0)))
|
||||
if (access(fname,F_OK))
|
||||
{
|
||||
/*
|
||||
If someone removed the file from underneath our feet, just close
|
||||
|
|
|
@ -253,7 +253,7 @@ int acl_init(bool dont_read_acl_tables)
|
|||
continue; /* purecov: tested */
|
||||
}
|
||||
get_salt_from_password(user.salt,user.password);
|
||||
user.access=get_access(table,3);
|
||||
user.access=get_access(table,3) & GLOBAL_ACLS;
|
||||
user.sort=get_sort(2,user.host.hostname,user.user);
|
||||
user.hostname_length= (user.host.hostname ?
|
||||
(uint) strlen(user.host.hostname) : 0);
|
||||
|
@ -321,6 +321,11 @@ int acl_init(bool dont_read_acl_tables)
|
|||
ACL_DB db;
|
||||
update_hostname(&db.host,get_field(&mem, table,0));
|
||||
db.db=get_field(&mem, table,1);
|
||||
if (!db.db)
|
||||
{
|
||||
sql_print_error("Found an entry in the 'db' table with empty database name; Skipped");
|
||||
continue;
|
||||
}
|
||||
db.user=get_field(&mem, table,2);
|
||||
db.access=get_access(table,3);
|
||||
db.access=fix_rights_for_db(db.access);
|
||||
|
|
|
@ -32,7 +32,7 @@ TABLE *unused_tables; /* Used by mysql_test */
|
|||
HASH open_cache; /* Used by mysql_test */
|
||||
|
||||
static int open_unireg_entry(THD *thd,TABLE *entry,const char *db,
|
||||
const char *name, const char *alias, bool locked);
|
||||
const char *name, const char *alias);
|
||||
static void free_cache_entry(TABLE *entry);
|
||||
static void mysql_rm_tmp_tables(void);
|
||||
static key_map get_key_map_from_key_list(TABLE *table,
|
||||
|
@ -108,6 +108,24 @@ static void check_unused(void)
|
|||
#define check_unused()
|
||||
#endif
|
||||
|
||||
/*
|
||||
Create a list for all open tables matching SQL expression
|
||||
|
||||
SYNOPSIS
|
||||
list_open_tables()
|
||||
thd Thread THD
|
||||
wild SQL like expression
|
||||
|
||||
NOTES
|
||||
One gets only a list of tables for which one has any kind of privilege.
|
||||
db and table names are allocated in result struct, so one doesn't need
|
||||
a lock on LOCK_open when traversing the return list.
|
||||
|
||||
RETURN VALUES
|
||||
NULL Error (Probably OOM)
|
||||
# Pointer to list of names of open tables.
|
||||
*/
|
||||
|
||||
OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild)
|
||||
{
|
||||
int result = 0;
|
||||
|
@ -275,6 +293,16 @@ void intern_close_table(TABLE *table)
|
|||
VOID(closefrm(table)); // close file
|
||||
}
|
||||
|
||||
/*
|
||||
Remove table from the open table cache
|
||||
|
||||
SYNOPSIS
|
||||
free_cache_entry()
|
||||
table Table to remove
|
||||
|
||||
NOTE
|
||||
We need to have a lock on LOCK_open when calling this
|
||||
*/
|
||||
|
||||
static void free_cache_entry(TABLE *table)
|
||||
{
|
||||
|
@ -709,7 +737,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
|
|||
key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
|
||||
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
if (open_unireg_entry(thd, table, db, table_name, table_name, 1) ||
|
||||
if (open_unireg_entry(thd, table, db, table_name, table_name) ||
|
||||
!(table->table_cache_key =memdup_root(&table->mem_root,(char*) key,
|
||||
key_length)))
|
||||
{
|
||||
|
@ -842,8 +870,11 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
|
|||
|
||||
/* make a new table */
|
||||
if (!(table=(TABLE*) my_malloc(sizeof(*table),MYF(MY_WME))))
|
||||
{
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
DBUG_RETURN(NULL);
|
||||
if (open_unireg_entry(thd, table,db,table_name,alias,1) ||
|
||||
}
|
||||
if (open_unireg_entry(thd, table,db,table_name,alias) ||
|
||||
!(table->table_cache_key=memdup_root(&table->mem_root,(char*) key,
|
||||
key_length)))
|
||||
{
|
||||
|
@ -934,8 +965,7 @@ bool reopen_table(TABLE *table,bool locked)
|
|||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
safe_mutex_assert_owner(&LOCK_open);
|
||||
|
||||
if (open_unireg_entry(current_thd,&tmp,db,table_name,table->table_name,
|
||||
locked))
|
||||
if (open_unireg_entry(current_thd,&tmp,db,table_name,table->table_name))
|
||||
goto end;
|
||||
free_io_cache(table);
|
||||
|
||||
|
@ -1176,7 +1206,6 @@ bool wait_for_tables(THD *thd)
|
|||
/* Now we can open all tables without any interference */
|
||||
thd->proc_info="Reopen tables";
|
||||
result=reopen_tables(thd,0,0);
|
||||
|
||||
}
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
thd->proc_info=0;
|
||||
|
@ -1241,7 +1270,7 @@ void abort_locked_tables(THD *thd,const char *db, const char *table_name)
|
|||
*/
|
||||
|
||||
static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
|
||||
const char *name, const char *alias, bool locked)
|
||||
const char *name, const char *alias)
|
||||
{
|
||||
char path[FN_REFLEN];
|
||||
int error;
|
||||
|
@ -1261,23 +1290,17 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
|
|||
table_list.db=(char*) db;
|
||||
table_list.name=(char*) name;
|
||||
table_list.next=0;
|
||||
if (!locked)
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
safe_mutex_assert_owner(&LOCK_open);
|
||||
|
||||
if ((error=lock_table_name(thd,&table_list)))
|
||||
{
|
||||
if (error < 0)
|
||||
{
|
||||
if (!locked)
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
goto err;
|
||||
}
|
||||
if (wait_for_locked_table_names(thd,&table_list))
|
||||
{
|
||||
unlock_table_name(thd,&table_list);
|
||||
if (!locked)
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
@ -1307,9 +1330,9 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
|
|||
thd->net.last_error[0]=0; // Clear error message
|
||||
thd->net.last_errno=0;
|
||||
}
|
||||
if (locked)
|
||||
pthread_mutex_lock(&LOCK_open); // Get back original lock
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
unlock_table_name(thd,&table_list);
|
||||
|
||||
if (error)
|
||||
goto err;
|
||||
}
|
||||
|
@ -1368,9 +1391,9 @@ int open_tables(THD *thd,TABLE_LIST *start)
|
|||
}
|
||||
}
|
||||
*prev_table=0;
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
if (found)
|
||||
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
goto restart;
|
||||
}
|
||||
result= -1; // Fatal error
|
||||
|
@ -2207,6 +2230,7 @@ int setup_ftfuncs(THD *thd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int init_ftfuncs(THD *thd, bool no_order)
|
||||
{
|
||||
if (thd->lex.select->ftfunc_list.elements)
|
||||
|
@ -2217,9 +2241,7 @@ int init_ftfuncs(THD *thd, bool no_order)
|
|||
thd->proc_info="FULLTEXT initialization";
|
||||
|
||||
while ((ifm=li++))
|
||||
{
|
||||
ifm->init_search(no_order);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1454,6 +1454,11 @@ bool select_create::send_eof()
|
|||
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
mysql_unlock_tables(thd, lock);
|
||||
/*
|
||||
TODO:
|
||||
Check if we can remove the following two rows.
|
||||
We should be able to just keep the table in the table cache.
|
||||
*/
|
||||
if (!table->tmp_table)
|
||||
hash_delete(&open_cache,(byte*) table);
|
||||
lock=0;
|
||||
|
|
|
@ -1493,7 +1493,7 @@ mysql_execute_command(void)
|
|||
/* Check that the first table has CREATE privilege */
|
||||
TABLE_LIST *tmp_table_list=tables->next;
|
||||
tables->next=0;
|
||||
bool error=check_grant(thd,CREATE_ACL,tables);
|
||||
bool error=check_grant(thd, want_priv, tables);
|
||||
tables->next=tmp_table_list;
|
||||
if (error)
|
||||
goto error;
|
||||
|
|
|
@ -3674,7 +3674,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
|
|||
field_count= (uint) (reg_field - table->field);
|
||||
|
||||
/* If result table is small; use a heap */
|
||||
if (blob_count || using_unique_constraint ||
|
||||
if (blob_count || using_unique_constraint || group_null_items ||
|
||||
(select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
|
||||
OPTION_BIG_TABLES)
|
||||
{
|
||||
|
|
|
@ -124,13 +124,15 @@ int mysqld_show_open_tables(THD *thd,const char *wild)
|
|||
net_store_data(&thd->packet,open_list->in_use);
|
||||
net_store_data(&thd->packet,open_list->locked);
|
||||
if (my_net_write(&thd->net,(char*) thd->packet.ptr(),thd->packet.length()))
|
||||
{
|
||||
DBUG_RETURN(-1);
|
||||
}
|
||||
}
|
||||
|
||||
send_eof(&thd->net);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
** List all tables in a database (fast version)
|
||||
** A table is a .frm file in the current databasedir
|
||||
|
|
|
@ -782,7 +782,9 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
|||
table->reginfo.lock_type=TL_WRITE;
|
||||
if (!((*lock)=mysql_lock_tables(thd,&table,1)))
|
||||
{
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
hash_delete(&open_cache,(byte*) table);
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
quick_rm_table(create_info->db_type,db,name);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
@ -977,19 +979,25 @@ static int prepare_for_repair(THD* thd, TABLE_LIST* table,
|
|||
|
||||
if (my_rename(from, tmp, MYF(MY_WME)))
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
unlock_table_name(thd, table);
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
DBUG_RETURN(send_check_errmsg(thd, table, "repair",
|
||||
"Failed renaming .MYD file"));
|
||||
}
|
||||
if (mysql_truncate(thd, table, 1))
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
unlock_table_name(thd, table);
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
DBUG_RETURN(send_check_errmsg(thd, table, "repair",
|
||||
"Failed generating table from .frm file"));
|
||||
}
|
||||
if (my_rename(tmp, from, MYF(MY_WME)))
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
unlock_table_name(thd, table);
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
DBUG_RETURN(send_check_errmsg(thd, table, "repair",
|
||||
"Failed restoring .MYD file"));
|
||||
}
|
||||
|
@ -1000,7 +1008,11 @@ static int prepare_for_repair(THD* thd, TABLE_LIST* table,
|
|||
to finish the repair in the handler later on.
|
||||
*/
|
||||
if (!(table->table = reopen_name_locked_table(thd, table)))
|
||||
unlock_table_name(thd, table);
|
||||
{
|
||||
pthread_mutex_lock(&LOCK_open);
|
||||
unlock_table_name(thd, table);
|
||||
pthread_mutex_unlock(&LOCK_open);
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -1855,8 +1867,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||
error=1;
|
||||
if (error)
|
||||
{
|
||||
VOID(pthread_cond_broadcast(&COND_refresh));
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
VOID(pthread_cond_broadcast(&COND_refresh));
|
||||
goto err;
|
||||
}
|
||||
#ifdef HAVE_BERKELEY_DB
|
||||
|
|
|
@ -44,7 +44,6 @@ noinst_PROGRAMS = conf_to_src
|
|||
EXTRA_DIST = ctype-big5.c ctype-czech.c ctype-euc_kr.c \
|
||||
ctype-gb2312.c ctype-gbk.c ctype-sjis.c \
|
||||
ctype-tis620.c ctype-ujis.c ctype-latin1_de.c \
|
||||
ctype_autoconf.c \
|
||||
strto.c strings-x86.s \
|
||||
longlong2str.c longlong2str-x86.s \
|
||||
strxmov.c bmove_upp.c strappend.c strcont.c strend.c \
|
||||
|
@ -80,7 +79,7 @@ conf_to_src_LDFLAGS= @NOINST_LDFLAGS@
|
|||
strtoull.o: @CHARSET_OBJS@
|
||||
|
||||
clean-local:
|
||||
rm -f ctype_extra_sources.c
|
||||
rm -f ctype_extra_sources.c ctype_autoconf.c
|
||||
|
||||
if ASSEMBLER
|
||||
# On Linux gcc can compile the assembly files
|
||||
|
|
|
@ -59,6 +59,7 @@ main( int argc,
|
|||
char* ca_file = 0, *ca_path = 0;
|
||||
char* cipher=0;
|
||||
int child_pid,sv[2];
|
||||
my_bool unused;
|
||||
struct st_VioSSLAcceptorFd* ssl_acceptor=0;
|
||||
struct st_VioSSLConnectorFd* ssl_connector=0;
|
||||
Vio* client_vio=0, *server_vio=0;
|
||||
|
@ -96,11 +97,11 @@ main( int argc,
|
|||
|
||||
client_vio = (struct st_vio*)my_malloc(sizeof(struct st_vio),MYF(0));
|
||||
client_vio->sd = sv[0];
|
||||
client_vio->vioblocking(client_vio,0);
|
||||
client_vio->vioblocking(client_vio, 0, &unused);
|
||||
sslconnect(ssl_connector,client_vio,60L);
|
||||
server_vio = (struct st_vio*)my_malloc(sizeof(struct st_vio),MYF(0));
|
||||
server_vio->sd = sv[1];
|
||||
server_vio->vioblocking(client_vio,0);
|
||||
server_vio->vioblocking(client_vio, 0, &unused);
|
||||
sslaccept(ssl_acceptor,server_vio,60L);
|
||||
|
||||
printf("Socketpair: %d , %d\n", client_vio->sd, server_vio->sd);
|
||||
|
|
Loading…
Reference in a new issue