summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <monty@hundin.mysql.fi>2002-08-08 15:24:47 +0300
committerunknown <monty@hundin.mysql.fi>2002-08-08 15:24:47 +0300
commit267b80834ad524c0d72976bc71e5b5bc9815ea1a (patch)
treee7f4a2013ed3d66e640f6574e62cb7e534a5d77f
parentca1875f54033c5ea067ec3ec07b00375de6975d7 (diff)
parent40d3c3901b0427eba76119730f46784f946990b3 (diff)
downloadmariadb-git-267b80834ad524c0d72976bc71e5b5bc9815ea1a.tar.gz
merge with 3.23.52
BitKeeper/etc/logging_ok: auto-union configure.in: Auto merged Docs/manual.texi: Auto merged include/my_pthread.h: Auto merged include/mysql_com.h: Auto merged include/mysql_version.h.in: Auto merged innobase/btr/btr0cur.c: Auto merged innobase/btr/btr0sea.c: Auto merged innobase/buf/buf0buf.c: Auto merged innobase/buf/buf0lru.c: Auto merged innobase/configure.in: Auto merged innobase/dict/dict0dict.c: Auto merged innobase/fil/fil0fil.c: Auto merged innobase/fsp/fsp0fsp.c: Auto merged innobase/include/buf0buf.ic: Auto merged innobase/include/dyn0dyn.ic: Auto merged innobase/include/ha0ha.ic: Auto merged innobase/include/sync0rw.ic: Auto merged innobase/include/univ.i: Auto merged innobase/lock/lock0lock.c: Auto merged innobase/log/log0log.c: Auto merged innobase/mem/mem0dbg.c: Auto merged innobase/os/os0file.c: Auto merged innobase/os/os0thread.c: Auto merged innobase/page/page0cur.c: Auto merged innobase/srv/srv0srv.c: Auto merged innobase/sync/sync0arr.c: Auto merged innobase/sync/sync0rw.c: Auto merged innobase/sync/sync0sync.c: Auto merged innobase/trx/trx0trx.c: Auto merged myisam/mi_create.c: Auto merged sql/ha_innodb.h: Auto merged sql/lex.h: Auto merged sql/log.cc: Auto merged sql/mysqld.cc: Auto merged sql/sql_acl.cc: Auto merged sql/sql_insert.cc: Auto merged strings/Makefile.am: Auto merged support-files/mysql.server.sh: Auto merged include/my_base.h: merge with 3.23.52 (use local file) include/sslopt-usage.h: merge with 3.23.52 (use local file) myisam/mi_search.c: merge with 3.23.52 (use local file) myisam/mi_write.c: merge with 3.23.52 (use local file) mysql-test/r/group_by.result: merge with 3.23.52 (Need to be fixed before push) mysys/my_pthread.c: merge with 3.23.52 (use local file) sql/gen_lex_hash.cc: merge with 3.23.52 (use local file) sql/ha_innodb.cc: Total hand-merge with 3.23.52 sql/sql_yacc.yy: merge with 3.23.52 (use local file) support-files/mysql.spec.sh: merge with 3.23.52 (use local file)
-rw-r--r--Docs/manual.texi21
-rw-r--r--include/mysql_version.h.in1
-rw-r--r--innobase/btr/btr0cur.c8
-rw-r--r--innobase/btr/btr0sea.c1
-rw-r--r--innobase/buf/buf0buf.c42
-rw-r--r--innobase/buf/buf0lru.c39
-rw-r--r--innobase/configure.in4
-rw-r--r--innobase/dict/dict0dict.c39
-rw-r--r--innobase/fil/fil0fil.c2
-rw-r--r--innobase/fsp/fsp0fsp.c32
-rw-r--r--innobase/ha/ha0ha.c19
-rw-r--r--innobase/include/btr0btr.h8
-rw-r--r--innobase/include/buf0buf.h6
-rw-r--r--innobase/include/buf0buf.ic37
-rw-r--r--innobase/include/dict0dict.h20
-rw-r--r--innobase/include/dict0mem.h4
-rw-r--r--innobase/include/dyn0dyn.h11
-rw-r--r--innobase/include/fsp0fsp.h10
-rw-r--r--innobase/include/ha0ha.h8
-rw-r--r--innobase/include/ha0ha.ic10
-rw-r--r--innobase/include/log0log.h40
-rw-r--r--innobase/include/log0log.ic85
-rw-r--r--innobase/include/log0recv.h7
-rw-r--r--innobase/include/os0file.h6
-rw-r--r--innobase/include/os0sync.ic14
-rw-r--r--innobase/include/os0thread.h28
-rw-r--r--innobase/include/srv0start.h2
-rw-r--r--innobase/include/sync0rw.ic3
-rw-r--r--innobase/include/sync0sync.ic4
-rw-r--r--innobase/include/trx0sys.h13
-rw-r--r--innobase/include/trx0trx.h4
-rw-r--r--innobase/include/univ.i12
-rw-r--r--innobase/include/ut0dbg.h13
-rw-r--r--innobase/lock/lock0lock.c103
-rw-r--r--innobase/log/log0log.c35
-rw-r--r--innobase/log/log0recv.c249
-rw-r--r--innobase/mem/mem0dbg.c2
-rw-r--r--innobase/mem/mem0pool.c53
-rw-r--r--innobase/mtr/mtr0log.c37
-rw-r--r--innobase/os/os0file.c19
-rw-r--r--innobase/os/os0thread.c76
-rw-r--r--innobase/page/page0cur.c24
-rw-r--r--innobase/row/row0mysql.c5
-rw-r--r--innobase/row/row0vers.c22
-rw-r--r--innobase/srv/srv0srv.c70
-rw-r--r--innobase/srv/srv0start.c50
-rw-r--r--innobase/sync/sync0arr.c23
-rw-r--r--innobase/sync/sync0rw.c23
-rw-r--r--innobase/sync/sync0sync.c22
-rw-r--r--innobase/thr/thr0loc.c12
-rw-r--r--innobase/trx/trx0sys.c28
-rw-r--r--innobase/trx/trx0trx.c64
-rw-r--r--libmysql/Makefile.am3
-rw-r--r--libmysql/Makefile.shared8
-rw-r--r--mysql-test/t/group_by.test11
-rw-r--r--scripts/mysqlhotcopy.sh15
-rw-r--r--sql/ha_innodb.cc369
-rw-r--r--sql/ha_innodb.h3
-rw-r--r--sql/lex.h4
-rw-r--r--sql/log.cc10
-rw-r--r--sql/mysqld.cc14
-rw-r--r--sql/sql_acl.cc7
-rw-r--r--sql/sql_base.cc40
-rw-r--r--sql/sql_insert.cc5
-rw-r--r--sql/sql_select.cc2
-rw-r--r--sql/sql_show.cc4
-rw-r--r--sql/sql_table.cc16
-rw-r--r--strings/Makefile.am3
68 files changed, 1479 insertions, 505 deletions
diff --git a/Docs/manual.texi b/Docs/manual.texi
index 51a40019f1e..0677c3525fe 100644
--- a/Docs/manual.texi
+++ b/Docs/manual.texi
@@ -50810,6 +50810,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
@@ -50817,7 +50834,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.
diff --git a/include/mysql_version.h.in b/include/mysql_version.h.in
index 5d738ce3326..1eb6f253d74 100644
--- a/include/mysql_version.h.in
+++ b/include/mysql_version.h.in
@@ -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
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c
index 1fe322be81e..bab5c78b712 100644
--- a/innobase/btr/btr0cur.c
+++ b/innobase/btr/btr0cur.c
@@ -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;
diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c
index cfdfefebd1a..cef3a4e4b38 100644
--- a/innobase/btr/btr0sea.c
+++ b/innobase/btr/btr0sea.c
@@ -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;
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index 663c6cefce6..8b946f4b2a1 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -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,
+ "Free buffers %lu\n", UT_LIST_GET_LEN(buf_pool->free));
+ buf += sprintf(buf,
+ "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,
- "LRU list length %lu \n", UT_LIST_GET_LEN(buf_pool->LRU));
+ "Hash index buffers %lu\n", buf_pool->n_adaptive_hash_pages);
+*/
buf += sprintf(buf,
- "Flush list length %lu \n",
+ "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. */
diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c
index 5ab045212c2..2ec1506c522 100644
--- a/innobase/buf/buf0lru.c
+++ b/innobase/buf/buf0lru.c
@@ -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));
diff --git a/innobase/configure.in b/innobase/configure.in
index c234e1e192d..100692e06ab 100644
--- a/innobase/configure.in
+++ b/innobase/configure.in
@@ -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*)
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 5abec8dbb1e..85199b90a5a 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -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;
}
}
diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c
index da4aee5db76..3e0f21395ef 100644
--- a/innobase/fil/fil0fil.c
+++ b/innobase/fil/fil0fil.c
@@ -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);
diff --git a/innobase/fsp/fsp0fsp.c b/innobase/fsp/fsp0fsp.c
index 32e7f5bcad7..1abb043fdc2 100644
--- a/innobase/fsp/fsp0fsp.c
+++ b/innobase/fsp/fsp0fsp.c
@@ -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"
diff --git a/innobase/ha/ha0ha.c b/innobase/ha/ha0ha.c
index c3ad6cdca76..4489b25ec2b 100644
--- a/innobase/ha/ha0ha.c
+++ b/innobase/ha/ha0ha.c
@@ -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);
+ }
}
diff --git a/innobase/include/btr0btr.h b/innobase/include/btr0btr.h
index bf433c0c264..f66ad3639d4 100644
--- a/innobase/include/btr0btr.h
+++ b/innobase/include/btr0btr.h
@@ -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. */
diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h
index b80ed96f54c..591c0ec54ab 100644
--- a/innobase/include/buf0buf.h
+++ b/innobase/include/buf0buf.h
@@ -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. */
diff --git a/innobase/include/buf0buf.ic b/innobase/include/buf0buf.ic
index e5a2c480922..7227c79dc6a 100644
--- a/innobase/include/buf0buf.ic
+++ b/innobase/include/buf0buf.ic
@@ -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);
}
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index fd79e17090a..832654d2666 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -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 */
/**************************************************************************
diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h
index ef15c99fdba..cc27f2bad12 100644
--- a/innobase/include/dict0mem.h
+++ b/innobase/include/dict0mem.h
@@ -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
diff --git a/innobase/include/dyn0dyn.h b/innobase/include/dyn0dyn.h
index 6f08da1533b..501fde05e90 100644
--- a/innobase/include/dyn0dyn.h
+++ b/innobase/include/dyn0dyn.h
@@ -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
diff --git a/innobase/include/fsp0fsp.h b/innobase/include/fsp0fsp.h
index a0197ec2d97..3494f336b1e 100644
--- a/innobase/include/fsp0fsp.h
+++ b/innobase/include/fsp0fsp.h
@@ -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
diff --git a/innobase/include/ha0ha.h b/innobase/include/ha0ha.h
index 945b1198a41..0beac928b7e 100644
--- a/innobase/include/ha0ha.h
+++ b/innobase/include/ha0ha.h
@@ -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"
diff --git a/innobase/include/ha0ha.ic b/innobase/include/ha0ha.ic
index 9d344bca04c..761bc3b20de 100644
--- a/innobase/include/ha0ha.ic
+++ b/innobase/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. */
diff --git a/innobase/include/log0log.h b/innobase/include/log0log.h
index 5d848b85658..f200371de9d 100644
--- a/innobase/include/log0log.h
+++ b/innobase/include/log0log.h
@@ -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 */
diff --git a/innobase/include/log0log.ic b/innobase/include/log0log.ic
index 36e65239374..8de239df0bd 100644
--- a/innobase/include/log0log.ic
+++ b/innobase/include/log0log.ic
@@ -170,33 +170,6 @@ log_block_set_checkpoint_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
ulint
@@ -217,6 +190,61 @@ log_block_convert_lsn_to_no(
}
/****************************************************************
+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
void
@@ -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);
}
diff --git a/innobase/include/log0recv.h b/innobase/include/log0recv.h
index 0825325965d..baa2ba50c7d 100644
--- a/innobase/include/log0recv.h
+++ b/innobase/include/log0recv.h
@@ -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)
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h
index b7911c5014a..d65c7fd47e3 100644
--- a/innobase/include/os0file.h
+++ b/innobase/include/os0file.h
@@ -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. */
diff --git a/innobase/include/os0sync.ic b/innobase/include/os0sync.ic
index 6bff75d8ec6..10b85c435e3 100644
--- a/innobase/include/os0sync.ic
+++ b/innobase/include/os0sync.ic
@@ -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
}
diff --git a/innobase/include/os0thread.h b/innobase/include/os0thread.h
index 0d6fa5a8f37..636cfd79e50 100644
--- a/innobase/include/os0thread.h
+++ b/innobase/include/os0thread.h
@@ -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
diff --git a/innobase/include/srv0start.h b/innobase/include/srv0start.h
index 01ac063e1c9..646d2c1bb06 100644
--- a/innobase/include/srv0start.h
+++ b/innobase/include/srv0start.h
@@ -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
diff --git a/innobase/include/sync0rw.ic b/innobase/include/sync0rw.ic
index 43e9202360b..36ef0a985ed 100644
--- a/innobase/include/sync0rw.ic
+++ b/innobase/include/sync0rw.ic
@@ -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();
diff --git a/innobase/include/sync0sync.ic b/innobase/include/sync0sync.ic
index 9014eb5fb54..c11cc0d196e 100644
--- a/innobase/include/sync0sync.ic
+++ b/innobase/include/sync0sync.ic
@@ -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;
}
diff --git a/innobase/include/trx0sys.h b/innobase/include/trx0sys.h
index b08df7f6901..a54a6424a4f 100644
--- a/innobase/include/trx0sys.h
+++ b/innobase/include/trx0sys.h
@@ -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
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 83789966514..6e98f22c34b 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -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
diff --git a/innobase/include/univ.i b/innobase/include/univ.i
index c852741d5ac..a4f29dc4cf3 100644
--- a/innobase/include/univ.i
+++ b/innobase/include/univ.i
@@ -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
diff --git a/innobase/include/ut0dbg.h b/innobase/include/ut0dbg.h
index fc5d493ca5e..3407483696c 100644
--- a/innobase/include/ut0dbg.h
+++ b/innobase/include/ut0dbg.h
@@ -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,\
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 7588a576a86..0bc7e9b4166 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -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);
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index 9748384183c..c798a08e2de 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -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);
+}
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index 53f75c176ea..1223f9b6041 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -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);
}
@@ -1766,14 +1752,70 @@ 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. */
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",
- 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",
+"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),
- 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;
diff --git a/innobase/mem/mem0dbg.c b/innobase/mem/mem0dbg.c
index f94119b7f38..23585e494b8 100644
--- a/innobase/mem/mem0dbg.c
+++ b/innobase/mem/mem0dbg.c
@@ -668,7 +668,7 @@ mem_print_info_low(
mem_pool_print_info(outfile, mem_comm_pool);
- mem_validate();
+/* mem_validate(); */
/* fclose(outfile); */
#endif
diff --git a/innobase/mem/mem0pool.c b/innobase/mem/mem0pool.c
index 3681c8ef779..61cf1e50ce9 100644
--- a/innobase/mem/mem0pool.c
+++ b/innobase/mem/mem0pool.c
@@ -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) {
diff --git a/innobase/mtr/mtr0log.c b/innobase/mtr/mtr0log.c
index b582afc5710..2cfe81d3261 100644
--- a/innobase/mtr/mtr0log.c
+++ b/innobase/mtr/mtr0log.c
@@ -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;
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index ae3c8a45f62..3ca0fbd68a4 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -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",
@@ -2518,6 +2518,21 @@ loop:
}
/**************************************************************************
+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. */
diff --git a/innobase/os/os0thread.c b/innobase/os/os0thread.c
index 49d4c8518fb..a8b417f4f3a 100644
--- a/innobase/os/os0thread.c
+++ b/innobase/os/os0thread.c
@@ -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. */
diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c
index 0eaf96f7e51..2909573b14b 100644
--- a/innobase/page/page0cur.c
+++ b/innobase/page/page0cur.c
@@ -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);
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index e0737f53213..3ee458f43bf 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -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) {
diff --git a/innobase/row/row0vers.c b/innobase/row/row0vers.c
index 9508e73f45d..cd8b18e5e12 100644
--- a/innobase/row/row0vers.c
+++ b/innobase/row/row0vers.c
@@ -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);
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index 3efb82eb8eb..3b16e9557fa 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -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));
@@ -2169,6 +2169,34 @@ srv_release_mysql_thread_if_suspended(
}
/**********************************************************************
+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. */
void
@@ -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
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 55e734be3bd..dfa122b2ece 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -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);
diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c
index 36dd8a7d80c..4d14c32b1ae 100644
--- a/innobase/sync/sync0arr.c
+++ b/innobase/sync/sync0arr.c
@@ -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);
}
+
diff --git a/innobase/sync/sync0rw.c b/innobase/sync/sync0rw.c
index 86ffed7ca95..fe837b119f3 100644
--- a/innobase/sync/sync0rw.c
+++ b/innobase/sync/sync0rw.c
@@ -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) {
diff --git a/innobase/sync/sync0sync.c b/innobase/sync/sync0sync.c
index 14a2a6f8cc1..3ea996afd6b 100644
--- a/innobase/sync/sync0sync.c
+++ b/innobase/sync/sync0sync.c
@@ -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");
diff --git a/innobase/thr/thr0loc.c b/innobase/thr/thr0loc.c
index d3d7a58d313..fbf3e3a1dad 100644
--- a/innobase/thr/thr0loc.c
+++ b/innobase/thr/thr0loc.c
@@ -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);
diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c
index 675cdf1b7e4..33c962772e8 100644
--- a/innobase/trx/trx0sys.c
+++ b/innobase/trx/trx0sys.c
@@ -494,6 +494,34 @@ trx_sys_update_mysql_binlog_offset(
}
/*********************************************************************
+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. */
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index 8d84967a49d..ef17588a2bb 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -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,45 +1468,57 @@ 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));
- if (ut_strlen(trx->op_info) > 0) {
- buf += sprintf(buf, " %s", trx->op_info);
- }
-
- if (trx->type != TRX_USER) {
- buf += sprintf(buf, " purge trx");
- }
-
switch (trx->conc_state) {
case TRX_NOT_STARTED: buf += sprintf(buf,
", not started"); break;
case TRX_ACTIVE: buf += sprintf(buf,
- ", active"); break;
+ ", ACTIVE %lu sec",
+ (ulint)difftime(time(NULL), trx->start_time)); break;
case TRX_COMMITTED_IN_MEMORY: buf += sprintf(buf,
- ", committed in memory");
+ ", 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);
+ }
+
+ if (trx->type != TRX_USER) {
+ buf += sprintf(buf, " purge trx");
+ }
+
+ buf += sprintf(buf, "\n");
+
+ 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);
diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am
index 3d380c14076..e72f73a39f9 100644
--- a/libmysql/Makefile.am
+++ b/libmysql/Makefile.am
@@ -49,6 +49,9 @@ 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; \
for f in $$qs; do \
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(srcdir)/../sql/$$f $(srcdir)/$$f; \
diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared
index 87f9fe42a3c..98bcd173fc6 100644
--- a/libmysql/Makefile.shared
+++ b/libmysql/Makefile.shared
@@ -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@ > \
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 0c9197febb5..072a1830f57 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -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;
diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh
index 707b4fc481c..1aad5c95c25 100644
--- a/scripts/mysqlhotcopy.sh
+++ b/scripts/mysqlhotcopy.sh
@@ -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=#
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index c82b4faf3f5..06931532f51 100644
--- a/sql/ha_innodb.cc
+++ b/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 */
-
- if (auto_inc != 0) {
- user_thd->next_insert_id = auto_inc;
- }
- }
-
- 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();
+ /* We can give the new value for MySQL to place in
+ the field */
- 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);
+ user_thd->next_insert_id = 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 */
+ /* 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 */
- prebuilt->sql_stat_start = TRUE;
- }
+ update_auto_increment();
+ }
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,7 +2392,11 @@ 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;
@@ -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 (error != DB_SUCCESS) {
+ error = convert_error_code_to_mysql(error, user_thd);
- if (nr != 0) {
+ goto func_exit;
+ }
- return(nr + 1);
+ /* 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();
+
+ *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);
+ return(nr);
}
#endif /* HAVE_INNOBASE_DB */
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index a9a7c9997ad..3d5db845fc6 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -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:
diff --git a/sql/lex.h b/sql/lex.h
index 39298323d75..1f7a121e262 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -251,7 +251,7 @@ 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},
+ { "FOREIGN_KEY_CHECKS", SYM(FOREIGN_KEY_CHECKS), 0, 0},
{ "NOT", SYM(NOT),0,0},
{ "NULL", SYM(NULL_SYM),0,0},
{ "NUMERIC", SYM(NUMERIC_SYM),0,0},
@@ -285,7 +285,7 @@ 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},
+ { "UNIQUE_CHECKS", SYM(UNIQUE_CHECKS), 0, 0},
{ "RENAME", SYM(RENAME),0,0},
{ "REPAIR", SYM(REPAIR),0,0},
{ "REPLACE", SYM(REPLACE),0,0},
diff --git a/sql/log.cc b/sql/log.cc
index 19f2db8403b..b6a07d9021f 100644
--- a/sql/log.cc
+++ b/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) ||
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index ffa606272e3..829614fdb2c 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -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 */
@@ -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();
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index e2d462aa73c..aad37477a70 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -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);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 58d251162ff..0f540a3a4fd 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -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,
@@ -275,6 +275,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 +719,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 +852,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 +947,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 +1188,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 +1252,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 +1272,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 +1312,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 +1373,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 +2212,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 +2223,7 @@ int init_ftfuncs(THD *thd, bool no_order)
thd->proc_info="FULLTEXT initialization";
while ((ifm=li++))
- {
ifm->init_search(no_order);
- }
}
return 0;
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 61d3544bfe0..e7a85c8262a 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -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;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 5a5745f87cd..169f95cc66b 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -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)
{
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 24f5ddeab7a..6041132bd20 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -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
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index df84bff0adc..f58201ae429 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -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
diff --git a/strings/Makefile.am b/strings/Makefile.am
index 433b4398b61..c29e7603520 100644
--- a/strings/Makefile.am
+++ b/strings/Makefile.am
@@ -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