updated with changes from Percona-Server-5.1.47-11.2

This commit is contained in:
unknown 2010-08-03 12:54:05 +02:00
parent 3e4d2be619
commit 0c6afe17dc
152 changed files with 10152 additions and 2307 deletions

View file

@ -29,9 +29,9 @@ IF (CMAKE_SIZEOF_VOID_P MATCHES 8)
SET(WIN64 TRUE)
ENDIF (CMAKE_SIZEOF_VOID_P MATCHES 8)
# Include directories under innobase
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/storage/innobase/include
${CMAKE_SOURCE_DIR}/storage/innobase/handler)
# Include directories under innodb_plugin
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/storage/innodb_plugin/include
${CMAKE_SOURCE_DIR}/storage/innodb_plugin/handler)
# Include directories under mysql
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include
@ -47,7 +47,7 @@ IF (MSVC AND $(WIN64))
PROPERTIES COMPILE_FLAGS -Od)
ENDIF (MSVC AND $(WIN64))
SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
SET(INNODB_PLUGIN_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
buf/buf0buddy.c buf/buf0buf.c buf/buf0flu.c buf/buf0lru.c buf/buf0rea.c
data/data0data.c data/data0type.c
dict/dict0boot.c dict/dict0crea.c dict/dict0dict.c dict/dict0load.c dict/dict0mem.c
@ -78,22 +78,11 @@ SET(INNOBASE_SOURCES btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c
trx/trx0i_s.c trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c
trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c
usr/usr0sess.c
ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c
ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rbt.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c
ut/ut0list.c ut/ut0wqueue.c)
ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS -DIB_HAVE_PAUSE_INSTRUCTION)
# Windows atomics do not perform well. Disable Windows atomics by default.
# See bug#52102 for details.
#ADD_DEFINITIONS(-DHAVE_WINDOWS_ATOMICS -DINNODB_RW_LOCKS_USE_ATOMICS -DHAVE_IB_PAUSE_INSTRUCTION)
ADD_DEFINITIONS(-DHAVE_IB_PAUSE_INSTRUCTION)
IF (MYSQL_VERSION_ID GREATER "50137")
MYSQL_STORAGE_ENGINE(INNOBASE)
# Use ha_innodb for plugin name, if plugin is built
GET_TARGET_PROPERTY(LIB_LOCATION ha_innobase LOCATION)
IF(LIB_LOCATION)
SET_TARGET_PROPERTIES(ha_innobase PROPERTIES OUTPUT_NAME ha_innodb)
ENDIF(LIB_LOCATION)
ELSE (MYSQL_VERSION_ID GREATER "50137")
IF (NOT SOURCE_SUBLIBS)
ADD_DEFINITIONS(-D_WIN32 -DMYSQL_SERVER)
ADD_LIBRARY(innobase STATIC ${INNOBASE_SOURCES})
# Require mysqld_error.h, which is built as part of the GenError
ADD_DEPENDENCIES(innobase GenError)
ENDIF (NOT SOURCE_SUBLIBS)
ENDIF (MYSQL_VERSION_ID GREATER "50137")
MYSQL_STORAGE_ENGINE(INNODB_PLUGIN)

271
ChangeLog
View file

@ -1,3 +1,262 @@
2010-05-03 The InnoDB Team
* buf0buf.c:
Fix Bug#53248 compressed tables page checksum mismatch after
re-enabling innodb_checksums
2010-04-28 The InnoDB Team
* log/log0recv.h, log/log0recv.c:
Fix Bug#53122 InnoDB recovery uses too big a hash table for redo
log records
2010-04-27 The InnoDB Team
* handler/ha_innodb.cc, lock/lock0lock.c, row/row0mysql.c,
row/row0sel.c:
Fix Bug#48607 READ UNCOMMITTED uses more locks than READ COMMITTED
in InnoDB 5.1+
2010-04-26 The InnoDB Team
* row/row0sel.c:
Fix Bug#52663 Lost update incrementing column value under
READ COMMITTED isolation level
2010-04-22 The InnoDB Team
* include/dict0boot.h, dict/dict0boot.c:
Fix a bug that prevented the crash recovery of fast CREATE INDEX
from dropping partially created indexes.
2010-04-21 The InnoDB Team
* btr/btr0btr.c:
Fix Bug#52964 Infinite loop in btr_page_split_and_insert()
in ROW_FORMAT=COMPRESSED
2010-04-21 The InnoDB Team
* data/data0data.c:
Fix Bug#52745 Failing assertion: blob_no < page_zip->n_blobs
2010-04-20 The InnoDB Team
* dict/dict0crea.c, handler/ha_innodb.cc, include/trx0trx.h:
Fix Bug#50495 'Row size too large' for plugin, but works for
built-in InnoDB
Only check the record size at index creation time when
innodb_strict_mode is set or when ROW_FORMAT is DYNAMIC or COMPRESSED.
2010-04-20 The InnoDB Team
* btr/btr0btr.c, include/univ.i:
Implement UNIV_BTR_AVOID_COPY, for avoiding writes when a B-tree
node is split at the first or last record.
2010-04-15 The InnoDB Team
* trx/trx0rec.c:
Fix Bug#52746 InnoDB purge thread crashed with table containing
prefix indexed blobs
2010-03-31 The InnoDB Team
* mysql-test/innodb_bug51920.test, mysql-test/innodb_bug51920.result,
srv/srv0srv.c:
Fix Bug#51920 InnoDB connections in row lock wait ignore KILL
until lock wait timeout
2010-03-31 The InnoDB Team
* mysql-test/innodb_bug38231.test:
Remove non-determinism in the test case.
2010-03-18 The InnoDB Team
* CMakeLists.txt:
Fix Bug#52102 InnoDB Plugin shows performance drop compared to
InnoDB (Windows)
2010-03-18 The InnoDB Team
* buf0buf.ic:
When comparing the time of the first access to a block against
innodb_old_blocks_time, use 32-bit arithmetics. The comparison was
incorrect on 64-bit systems.
2010-03-11 The InnoDB Team
* buf0buf.h, buf0buf.ic:
Fix and clarify the latching of some buf_block_t members.
Note that check_index_page_at_flush is not protected by any mutex.
Note and assert that lock_hash_val is protected by the rw-latch.
2010-03-10 The InnoDB Team
* trx/trx0sys.c:
Fix Bug#51653 outdated reference to set-variable
2010-03-10 The InnoDB Team
* handler/ha_innodb.cc, mysql-test/innodb_bug21704.result,
mysql-test/innodb_bug47621.result, mysql-test/innodb_bug47621.test:
Fix Bug#47621 MySQL and InnoDB data dictionaries will become out of
sync when renaming columns
2010-03-10 The InnoDB Team
* handler/ha_innodb.cc:
Fix Bug#51356 Many Valgrind errors in error messages
with concurrent DDL
2010-03-10 The InnoDB Team
* handler/ha_innodb.cc, handler/handler0alter.cc,
mysql-test/innodb_bug51378.result, mysql-test/innodb_bug51378.test:
Fix Bug#51378 Init 'ref_length' to correct value, in case an out
of bound MySQL primary_key
2010-03-10 The InnoDB Team
* log/log0recv.c:
Remove a bogus assertion about page numbers exceeding 0x90000000
in the redo log. Abort when encountering a corrupted redo log
record, unless innodb_force_recovery is set.
2010-03-09 The InnoDB Team
* handler/ha_innodb.cc:
Make SHOW ENGINE INNODB MUTEX STATUS display SUM(os_waits)
for the buffer pool block mutexes and locks.
2010-03-08 The InnoDB Team
* fil/fil0fil.c:
Fix ALTER TABLE ... IMPORT TABLESPACE of compressed tables.
2010-03-03 The InnoDB Team
* handler/handler0alter.cc, innodb-index.result, innodb-index.test,
innodb.result, innodb.test:
Disallow a duplicate index name when creating an index.
2010-02-11 The InnoDB Team
* include/mem0mem.h, include/mem0mem.ic, mem/mem0mem.c:
Fix Bug#49535 Available memory check slows down crash
recovery tens of times
2010-02-09 The InnoDB Team
* buf/buf0buf.c:
Fix Bug#38901 InnoDB logs error repeatedly when trying to load
page into buffer pool
2010-02-09 The InnoDB Team
* srv/srv0srv.c:
Let the master thread sleep if the amount of work to be done is
calibrated as taking less than a second.
2010-02-04 The InnoDB Team
* btr/btr0btr.c, btr/btr0cur.c, btr/btr0pcur.c, buf/buf0buf.c,
include/btr0btr.h, include/btr0cur.h, include/btr0pcur.h,
include/btr0pcur.ic, include/buf0buf.h, row/row0ins.c, row/row0sel.c:
Pass the file name and line number of the caller of the
b-tree cursor functions to the buffer pool requests, in order
to make the latch diagnostics more accurate.
2010-02-03 The InnoDB Team
* lock/lock0lock.c:
Fix Bug#49001 SHOW INNODB STATUS deadlock info incorrect
when deadlock detection aborts
2010-02-03 The InnoDB Team
* buf/buf0lru.c:
Fix Bug#35077 Very slow DROP TABLE (ALTER TABLE, OPTIMIZE TABLE)
on compressed tables
2010-02-03 The InnoDB Team
* handler/ha_innodb.cc, include/row0mysql.h, row/row0mysql.c:
Clean up CHECK TABLE error handling.
2010-02-01 The InnoDB Team
* handler/ha_innodb.cc, mysql-test/innodb-autoinc.test,
mysql-test/innodb-autoinc.result,
mysql-test/innodb-autoinc-44030.test,
mysql-test/innodb-autoinc-44030.result:
Fix Bug#49497 Error 1467 (ER_AUTOINC_READ_FAILED) on inserting
a negative value
2010-01-27 The InnoDB Team
* include/row0mysql.h, log/log0recv.c, row/row0mysql.c:
Drop temporary tables at startup.
This addresses the third aspect of
Bug#41609 Crash recovery does not work for InnoDB temporary tables.
2010-01-21 The InnoDB Team
* buf/buf0buf.c:
Do not merge buffered inserts to compressed pages before
the redo log has been applied in crash recovery.
2010-01-13 The InnoDB Team
* row/row0sel.c:
On the READ UNCOMMITTED isolation level, do not attempt to access
a clustered index record that has been marked for deletion. The
built-in InnoDB in MySQL 5.1 and earlier would attempt to retrieve
a previous version of the record in this case.
2010-01-13 The InnoDB Team
* buf/buf0buf.c:
When disabling the adaptive hash index, check the block state
before checking block->is_hashed, because the latter may be
uninitialized right after server startup.
2010-01-12 The InnoDB Team
* handler/ha_innodb.cc, handler/ha_innodb.h:
Fix Bug#46193 crash when accessing tables after enabling
innodb_force_recovery option
2010-01-12 The InnoDB Team
* row/row0mysql.c:
Fix Bug#49238 Creating/Dropping a temporary table while at 1023
transactions will cause assert.
2009-12-02 The InnoDB Team
* srv/srv0start.c:
Display the zlib version number at startup.
InnoDB compressed tables use zlib, and the implementation depends
on the zlib function compressBound(), whose definition was slightly
changed in zlib version 1.2.3.1 in 2006. MySQL bundles zlib 1.2.3
from 2005, but some installations use a more recent zlib.
2009-11-30 The InnoDB Team
* dict/dict0crea.c, dict/dict0mem.c, dict/dict0load.c,
dict/dict0boot.c, fil/fil0fil.c, handler/ha_innodb.cc,
include/dict0mem.h, row/row0mysql.c:
Fix the bogus warning messages for non-existing temporary
tables that were reported in
Bug#41609 Crash recovery does not work for InnoDB temporary tables.
The actual crash recovery bug was corrected on 2009-04-29.
2009-11-27 The InnoDB Team
InnoDB Plugin 1.0.6 released
2009-11-20 The InnoDB Team
* handler/ha_innodb.cc:
@ -79,8 +338,8 @@
sync/sync0arr.c, sync/sync0sync.c, thr/thr0loc.c, trx/trx0i_s.c,
trx/trx0purge.c, trx/trx0rseg.c, trx/trx0sys.c, trx/trx0undo.c,
usr/usr0sess.c, ut/ut0mem.c:
Fix Bug #45992 innodb memory not freed after shutdown
Fix Bug #46656 InnoDB plugin: memory leaks (Valgrind)
Fix Bug#45992 innodb memory not freed after shutdown
Fix Bug#46656 InnoDB plugin: memory leaks (Valgrind)
2009-10-29 The InnoDB Team
@ -422,7 +681,7 @@
* dict/dict0dict.c:
When an index column cannot be found in the table during index
creation, display additional diagnostic before an assertion failure.
This does NOT fix Bug #44571 InnoDB Plugin crashes on ADD INDEX,
This does NOT fix Bug#44571 InnoDB Plugin crashes on ADD INDEX,
but it helps understand the reason of the crash.
2009-06-17 The InnoDB Team
@ -535,6 +794,12 @@
Fix Bug#44320 InnoDB: missing DB_ROLL_PTR in Table Monitor COLUMNS
output
2009-04-29 The InnoDB Team
* fil/fil0fil.c, include/fil0fil.h, include/mtr0mtr.h,
log/log0recv.c:
Fix Bug#41609 Crash recovery does not work for InnoDB temporary tables
2009-04-23 The InnoDB Team
* row/row0mysql.c:

View file

@ -217,6 +217,7 @@ noinst_HEADERS= \
include/ut0lst.h \
include/ut0mem.h \
include/ut0mem.ic \
include/ut0rbt.h \
include/ut0rnd.h \
include/ut0rnd.ic \
include/ut0sort.h \
@ -229,7 +230,7 @@ noinst_HEADERS= \
mem/mem0dbg.c
EXTRA_LIBRARIES= libinnobase.a
noinst_LIBRARIES= @plugin_innobase_static_target@
noinst_LIBRARIES= @plugin_innodb_plugin_static_target@
libinnobase_a_SOURCES= \
btr/btr0btr.c \
btr/btr0cur.c \
@ -319,6 +320,7 @@ libinnobase_a_SOURCES= \
ut/ut0dbg.c \
ut/ut0list.c \
ut/ut0mem.c \
ut/ut0rbt.c \
ut/ut0rnd.c \
ut/ut0ut.c \
ut/ut0vec.c \
@ -327,13 +329,13 @@ libinnobase_a_SOURCES= \
libinnobase_a_CXXFLAGS= $(AM_CFLAGS)
libinnobase_a_CFLAGS= $(AM_CFLAGS)
EXTRA_LTLIBRARIES= ha_innodb.la
pkgplugin_LTLIBRARIES= @plugin_innobase_shared_target@
EXTRA_LTLIBRARIES= ha_innodb_plugin.la
pkgplugin_LTLIBRARIES= @plugin_innodb_plugin_shared_target@
ha_innodb_la_LDFLAGS= -module -rpath $(pkgplugindir)
ha_innodb_la_CXXFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
ha_innodb_la_CFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
ha_innodb_la_SOURCES= $(libinnobase_a_SOURCES)
ha_innodb_plugin_la_LDFLAGS= -module -rpath $(pkgplugindir)
ha_innodb_plugin_la_CXXFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
ha_innodb_plugin_la_CFLAGS= $(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
ha_innodb_plugin_la_SOURCES= $(libinnobase_a_SOURCES)
EXTRA_DIST= CMakeLists.txt plug.in \
pars/make_bison.sh pars/make_flex.sh \

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -604,13 +604,15 @@ an x-latch on the tree.
@return rec_get_offsets() of the node pointer record */
static
ulint*
btr_page_get_father_node_ptr(
/*=========================*/
btr_page_get_father_node_ptr_func(
/*==============================*/
ulint* offsets,/*!< in: work area for the return value */
mem_heap_t* heap, /*!< in: memory heap to use */
btr_cur_t* cursor, /*!< in: cursor pointing to user record,
out: cursor on node pointer record,
its page x-latched */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
{
dtuple_t* tuple;
@ -634,7 +636,8 @@ btr_page_get_father_node_ptr(
tuple = dict_index_build_node_ptr(index, user_rec, 0, heap, level);
btr_cur_search_to_nth_level(index, level + 1, tuple, PAGE_CUR_LE,
BTR_CONT_MODIFY_TREE, cursor, 0, mtr);
BTR_CONT_MODIFY_TREE, cursor, 0,
file, line, mtr);
node_ptr = btr_cur_get_rec(cursor);
ut_ad(!page_rec_is_comp(node_ptr)
@ -682,6 +685,9 @@ btr_page_get_father_node_ptr(
return(offsets);
}
#define btr_page_get_father_node_ptr(of,heap,cur,mtr) \
btr_page_get_father_node_ptr_func(of,heap,cur,__FILE__,__LINE__,mtr)
/************************************************************//**
Returns the upper level node pointer to a page. It is assumed that mtr holds
an x-latch on the tree.
@ -1475,11 +1481,11 @@ Calculates a split record such that the tuple will certainly fit on
its half-page when the split is performed. We assume in this function
only that the cursor page has at least one user record.
@return split record, or NULL if tuple will be the first record on
upper half-page */
the lower or upper half-page (determined by btr_page_tuple_smaller()) */
static
rec_t*
btr_page_get_sure_split_rec(
/*========================*/
btr_page_get_split_rec(
/*===================*/
btr_cur_t* cursor, /*!< in: cursor at which insert should be made */
const dtuple_t* tuple, /*!< in: tuple to insert */
ulint n_ext) /*!< in: number of externally stored columns */
@ -1692,11 +1698,13 @@ Inserts a data tuple to a tree on a non-leaf level. It is assumed
that mtr holds an x-latch on the tree. */
UNIV_INTERN
void
btr_insert_on_non_leaf_level(
/*=========================*/
btr_insert_on_non_leaf_level_func(
/*==============================*/
dict_index_t* index, /*!< in: index */
ulint level, /*!< in: level, must be > 0 */
dtuple_t* tuple, /*!< in: the record to be inserted */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
{
big_rec_t* dummy_big_rec;
@ -1708,7 +1716,7 @@ btr_insert_on_non_leaf_level(
btr_cur_search_to_nth_level(index, level, tuple, PAGE_CUR_LE,
BTR_CONT_MODIFY_TREE,
&cursor, 0, mtr);
&cursor, 0, file, line, mtr);
err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG
| BTR_KEEP_SYS_FLAG
@ -1853,6 +1861,37 @@ btr_attach_half_pages(
btr_page_set_next(upper_page, upper_page_zip, next_page_no, mtr);
}
/*************************************************************//**
Determine if a tuple is smaller than any record on the page.
@return TRUE if smaller */
static
ibool
btr_page_tuple_smaller(
/*===================*/
btr_cur_t* cursor, /*!< in: b-tree cursor */
const dtuple_t* tuple, /*!< in: tuple to consider */
ulint* offsets,/*!< in/out: temporary storage */
ulint n_uniq, /*!< in: number of unique fields
in the index page records */
mem_heap_t** heap) /*!< in/out: heap for offsets */
{
buf_block_t* block;
const rec_t* first_rec;
page_cur_t pcur;
/* Read the first user record in the page. */
block = btr_cur_get_block(cursor);
page_cur_set_before_first(block, &pcur);
page_cur_move_to_next(&pcur);
first_rec = page_cur_get_rec(&pcur);
offsets = rec_get_offsets(
first_rec, cursor->index, offsets,
n_uniq, heap);
return(cmp_dtuple_rec(tuple, first_rec, offsets) < 0);
}
/*************************************************************//**
Splits an index page to halves and inserts the tuple. It is assumed
that mtr holds an x-latch to the index tree. NOTE: the tree x-latch is
@ -1923,12 +1962,17 @@ func_start:
/* 1. Decide the split record; split_rec == NULL means that the
tuple to be inserted should be the first record on the upper
half-page */
insert_left = FALSE;
if (n_iterations > 0) {
direction = FSP_UP;
hint_page_no = page_no + 1;
split_rec = btr_page_get_sure_split_rec(cursor, tuple, n_ext);
split_rec = btr_page_get_split_rec(cursor, tuple, n_ext);
if (UNIV_UNLIKELY(split_rec == NULL)) {
insert_left = btr_page_tuple_smaller(
cursor, tuple, offsets, n_uniq, &heap);
}
} else if (btr_page_get_split_rec_to_right(cursor, &split_rec)) {
direction = FSP_UP;
hint_page_no = page_no + 1;
@ -1936,37 +1980,24 @@ func_start:
} else if (btr_page_get_split_rec_to_left(cursor, &split_rec)) {
direction = FSP_DOWN;
hint_page_no = page_no - 1;
ut_ad(split_rec);
} else {
direction = FSP_UP;
hint_page_no = page_no + 1;
if (page_get_n_recs(page) == 1) {
page_cur_t pcur;
/* If there is only one record in the index page, we
can't split the node in the middle by default. We need
to determine whether the new record will be inserted
to the left or right. */
/* There is only one record in the index page
therefore we can't split the node in the middle
by default. We need to determine whether the
new record will be inserted to the left or right. */
/* Read the first (and only) record in the page. */
page_cur_set_before_first(block, &pcur);
page_cur_move_to_next(&pcur);
first_rec = page_cur_get_rec(&pcur);
offsets = rec_get_offsets(
first_rec, cursor->index, offsets,
n_uniq, &heap);
/* If the new record is less than the existing record
the split in the middle will copy the existing
record to the new node. */
if (cmp_dtuple_rec(tuple, first_rec, offsets) < 0) {
split_rec = page_get_middle_rec(page);
} else {
split_rec = NULL;
}
} else {
if (page_get_n_recs(page) > 1) {
split_rec = page_get_middle_rec(page);
} else if (btr_page_tuple_smaller(cursor, tuple,
offsets, n_uniq, &heap)) {
split_rec = page_rec_get_next(
page_get_infimum_rec(page));
} else {
split_rec = NULL;
}
}
@ -1996,11 +2027,15 @@ func_start:
avoid further splits by inserting the record
to an empty page. */
split_rec = NULL;
goto insert_right;
goto insert_empty;
}
} else if (UNIV_UNLIKELY(insert_left)) {
first_rec = page_rec_get_next(page_get_infimum_rec(page));
move_limit = page_rec_get_next(btr_cur_get_rec(cursor));
} else {
insert_right:
insert_left = FALSE;
insert_empty:
ut_ad(!split_rec);
ut_ad(!insert_left);
buf = mem_alloc(rec_get_converted_size(cursor->index,
tuple, n_ext));
@ -2024,7 +2059,11 @@ insert_right:
&& btr_page_insert_fits(cursor, split_rec,
offsets, tuple, n_ext, heap);
} else {
mem_free(buf);
if (!insert_left) {
mem_free(buf);
buf = NULL;
}
insert_will_fit = !new_page_zip
&& btr_page_insert_fits(cursor, NULL,
NULL, tuple, n_ext, heap);
@ -2037,7 +2076,17 @@ insert_right:
}
/* 5. Move then the records to the new page */
if (direction == FSP_DOWN) {
if (direction == FSP_DOWN
#ifdef UNIV_BTR_AVOID_COPY
&& page_rec_is_supremum(move_limit)) {
/* Instead of moving all records, make the new page
the empty page. */
left_block = block;
right_block = new_block;
} else if (direction == FSP_DOWN
#endif /* UNIV_BTR_AVOID_COPY */
) {
/* fputs("Split left\n", stderr); */
if (0
@ -2080,6 +2129,14 @@ insert_right:
right_block = block;
lock_update_split_left(right_block, left_block);
#ifdef UNIV_BTR_AVOID_COPY
} else if (!split_rec) {
/* Instead of moving all records, make the new page
the empty page. */
left_block = new_block;
right_block = block;
#endif /* UNIV_BTR_AVOID_COPY */
} else {
/* fputs("Split right\n", stderr); */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@ -372,6 +372,8 @@ btr_cur_search_to_nth_level(
ulint has_search_latch,/*!< in: info on the latch mode the
caller currently has on btr_search_latch:
RW_S_LATCH, or 0 */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
{
page_cur_t* page_cursor;
@ -550,7 +552,7 @@ btr_cur_search_to_nth_level(
retry_page_get:
block = buf_page_get_gen(space, zip_size, page_no,
rw_latch, guess, buf_mode,
__FILE__, __LINE__, mtr);
file, line, mtr);
if (block == NULL) {
if (srv_pass_corrupt_table && buf_mode != BUF_GET_IF_IN_POOL) {
page_cursor->block = 0;
@ -727,13 +729,15 @@ func_exit:
Opens a cursor at either end of an index. */
UNIV_INTERN
void
btr_cur_open_at_index_side(
/*=======================*/
btr_cur_open_at_index_side_func(
/*============================*/
ibool from_left, /*!< in: TRUE if open to the low end,
FALSE if to the high end */
dict_index_t* index, /*!< in: index */
ulint latch_mode, /*!< in: latch mode */
btr_cur_t* cursor, /*!< in: cursor */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
{
page_cur_t* page_cursor;
@ -778,7 +782,7 @@ btr_cur_open_at_index_side(
page_t* page;
block = buf_page_get_gen(space, zip_size, page_no,
RW_NO_LATCH, NULL, BUF_GET,
__FILE__, __LINE__, mtr);
file, line, mtr);
page = buf_block_get_frame(block);
if (srv_pass_corrupt_table && !page) {
@ -869,11 +873,13 @@ btr_cur_open_at_index_side(
Positions a cursor at a randomly chosen position within a B-tree. */
UNIV_INTERN
void
btr_cur_open_at_rnd_pos(
/*====================*/
btr_cur_open_at_rnd_pos_func(
/*=========================*/
dict_index_t* index, /*!< in: index */
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
btr_cur_t* cursor, /*!< in/out: B-tree cursor */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
{
page_cur_t* page_cursor;
@ -908,7 +914,7 @@ btr_cur_open_at_rnd_pos(
block = buf_page_get_gen(space, zip_size, page_no,
RW_NO_LATCH, NULL, BUF_GET,
__FILE__, __LINE__, mtr);
file, line, mtr);
page = buf_block_get_frame(block);
if (srv_pass_corrupt_table && !page) {
@ -1229,7 +1235,6 @@ btr_cur_optimistic_insert(
ibool inherit;
ulint zip_size;
ulint rec_size;
mem_heap_t* heap = NULL;
ulint err;
*big_rec = NULL;
@ -1315,10 +1320,6 @@ btr_cur_optimistic_insert(
index, entry, big_rec_vec);
}
if (heap) {
mem_heap_free(heap);
}
return(DB_TOO_BIG_RECORD);
}
}
@ -1341,15 +1342,11 @@ fail_err:
dtuple_convert_back_big_rec(index, entry, big_rec_vec);
}
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
return(err);
}
if (UNIV_UNLIKELY(max_size < BTR_CUR_PAGE_REORGANIZE_LIMIT
|| max_size < rec_size)
|| max_size < rec_size)
&& UNIV_LIKELY(page_get_n_recs(page) > 1)
&& page_get_max_insert_size(page, 1) < rec_size) {
@ -1415,10 +1412,6 @@ fail_err:
}
}
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
#ifdef BTR_CUR_HASH_ADAPT
if (!reorg && leaf && (cursor->flag == BTR_CUR_HASH)) {
btr_search_update_hash_node_on_insert(cursor);
@ -3282,7 +3275,8 @@ btr_estimate_n_rows_in_range(
btr_cur_search_to_nth_level(index, 0, tuple1, mode1,
BTR_SEARCH_LEAF | BTR_ESTIMATE,
&cursor, 0, &mtr);
&cursor, 0,
__FILE__, __LINE__, &mtr);
} else {
btr_cur_open_at_index_side(TRUE, index,
BTR_SEARCH_LEAF | BTR_ESTIMATE,
@ -3299,7 +3293,8 @@ btr_estimate_n_rows_in_range(
btr_cur_search_to_nth_level(index, 0, tuple2, mode2,
BTR_SEARCH_LEAF | BTR_ESTIMATE,
&cursor, 0, &mtr);
&cursor, 0,
__FILE__, __LINE__, &mtr);
} else {
btr_cur_open_at_index_side(FALSE, index,
BTR_SEARCH_LEAF | BTR_ESTIMATE,
@ -3438,7 +3433,7 @@ btr_estimate_n_pages_not_null(
btr_cur_search_to_nth_level(index, 0, tuple1, PAGE_CUR_G,
BTR_SEARCH_LEAF | BTR_ESTIMATE,
&cursor, 0, &mtr);
&cursor, 0, __FILE__, __LINE__, &mtr);
mtr_commit(&mtr);
@ -3588,9 +3583,11 @@ btr_estimate_number_of_different_key_vals(
effective_pages = btr_estimate_n_pages_not_null(index, 1 /*k*/, first_rec_path);
if (!effective_pages) {
dict_index_stat_mutex_enter(index);
for (j = 0; j <= n_cols; j++) {
index->stat_n_diff_key_vals[j] = (ib_int64_t)index->stat_n_leaf_pages;
}
dict_index_stat_mutex_exit(index);
return;
} else if (effective_pages > index->stat_n_leaf_pages) {
effective_pages = index->stat_n_leaf_pages;
@ -3732,6 +3729,8 @@ btr_estimate_number_of_different_key_vals(
also the pages used for external storage of fields (those pages are
included in index->stat_n_leaf_pages) */
dict_index_stat_mutex_enter(index);
for (j = 0; j <= n_cols; j++) {
index->stat_n_diff_key_vals[j]
= ((n_diff[j]
@ -3770,8 +3769,9 @@ btr_estimate_number_of_different_key_vals(
}
}
mem_free(n_diff);
dict_index_stat_mutex_exit(index);
mem_free(n_diff);
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
}
@ -4639,7 +4639,7 @@ btr_free_externally_stored_field(
/* In the rollback of uncommitted transactions, we may
encounter a clustered index record whose BLOBs have
not been written. There is nothing to free then. */
ut_a(rb_ctx == RB_RECOVERY);
ut_a(rb_ctx == RB_RECOVERY || rb_ctx == RB_RECOVERY_PURGE_REC);
return;
}
@ -4685,7 +4685,7 @@ btr_free_externally_stored_field(
|| (mach_read_from_1(field_ref + BTR_EXTERN_LEN)
& BTR_EXTERN_OWNER_FLAG)
/* Rollback and inherited field */
|| (rb_ctx != RB_NONE
|| ((rb_ctx == RB_NORMAL || rb_ctx == RB_RECOVERY)
&& (mach_read_from_1(field_ref + BTR_EXTERN_LEN)
& BTR_EXTERN_INHERITED_FLAG))) {

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -211,10 +211,12 @@ record and it can be restored on a user record whose ordering fields
are identical to the ones of the original user record */
UNIV_INTERN
ibool
btr_pcur_restore_position(
/*======================*/
btr_pcur_restore_position_func(
/*===========================*/
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /*!< in: detached persistent cursor */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
{
dict_index_t* index;
@ -223,6 +225,9 @@ btr_pcur_restore_position(
ulint old_mode;
mem_heap_t* heap;
ut_ad(mtr);
ut_ad(mtr->state == MTR_ACTIVE);
index = btr_cur_get_index(btr_pcur_get_btr_cur(cursor));
if (UNIV_UNLIKELY(cursor->old_stored != BTR_PCUR_OLD_STORED)
@ -263,7 +268,8 @@ btr_pcur_restore_position(
if (UNIV_LIKELY(buf_page_optimistic_get(
latch_mode,
cursor->block_when_stored,
cursor->modify_clock, mtr))) {
cursor->modify_clock,
file, line, mtr))) {
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
buf_block_dbg_add_level(btr_pcur_get_block(cursor),
@ -318,8 +324,8 @@ btr_pcur_restore_position(
mode = PAGE_CUR_L;
}
btr_pcur_open_with_no_init(index, tuple, mode, latch_mode,
cursor, 0, mtr);
btr_pcur_open_with_no_init_func(index, tuple, mode, latch_mode,
cursor, 0, file, line, mtr);
/* Restore the old search mode */
cursor->search_mode = old_mode;
@ -568,8 +574,8 @@ before first in tree. The latching mode must be BTR_SEARCH_LEAF or
BTR_MODIFY_LEAF. */
UNIV_INTERN
void
btr_pcur_open_on_user_rec(
/*======================*/
btr_pcur_open_on_user_rec_func(
/*===========================*/
dict_index_t* index, /*!< in: index */
const dtuple_t* tuple, /*!< in: tuple on which search done */
ulint mode, /*!< in: PAGE_CUR_L, ... */
@ -577,9 +583,12 @@ btr_pcur_open_on_user_rec(
BTR_MODIFY_LEAF */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent
cursor */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
{
btr_pcur_open(index, tuple, mode, latch_mode, cursor, mtr);
btr_pcur_open_func(index, tuple, mode, latch_mode, cursor,
file, line, mtr);
if ((mode == PAGE_CUR_GE) || (mode == PAGE_CUR_G)) {

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 2006, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -430,6 +430,8 @@ buf_buddy_relocate_block(
}
mutex_exit(&flush_list_mutex);
UNIV_MEM_INVALID(bpage, sizeof *bpage);
mutex_exit(&buf_pool_zip_mutex);
mutex_exit(&zip_free_mutex);
return(TRUE);

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@ -277,6 +277,8 @@ the read requests for the whole area.
#ifndef UNIV_HOTBACKUP
/** Value in microseconds */
static const int WAIT_FOR_READ = 5000;
/** Number of attemtps made to read in a page in the buffer pool */
static const ulint BUF_PAGE_READ_MAX_RETRIES = 100;
/** The buffer buf_pool of the database */
UNIV_INTERN buf_pool_t* buf_pool = NULL;
@ -1150,7 +1152,9 @@ buf_pool_drop_hash_index(void)
when we have an x-latch on btr_search_latch;
see the comment in buf0buf.h */
if (!block->is_hashed) {
if (buf_block_get_state(block)
!= BUF_BLOCK_FILE_PAGE
|| !block->is_hashed) {
continue;
}
@ -1283,8 +1287,6 @@ buf_relocate(
HASH_DELETE(buf_page_t, hash, buf_pool->page_hash, fold, bpage);
HASH_INSERT(buf_page_t, hash, buf_pool->page_hash, fold, dpage);
UNIV_MEM_INVALID(bpage, sizeof *bpage);
}
/********************************************************************//**
@ -1980,14 +1982,14 @@ buf_zip_decompress(
buf_block_t* block, /*!< in/out: block */
ibool check) /*!< in: TRUE=verify the page checksum */
{
const byte* frame = block->page.zip.data;
const byte* frame = block->page.zip.data;
ulint stamp_checksum = mach_read_from_4(
frame + FIL_PAGE_SPACE_OR_CHKSUM);
ut_ad(buf_block_get_zip_size(block));
ut_a(buf_block_get_space(block) != 0);
if (UNIV_LIKELY(check)) {
ulint stamp_checksum = mach_read_from_4(
frame + FIL_PAGE_SPACE_OR_CHKSUM);
if (UNIV_LIKELY(check && stamp_checksum != BUF_NO_CHECKSUM_MAGIC)) {
ulint calc_checksum = page_zip_calc_checksum(
frame, page_zip_get_size(&block->page.zip));
@ -2196,6 +2198,7 @@ buf_page_get_gen(
unsigned access_time;
ulint fix_type;
ibool must_read;
ulint retries = 0;
mutex_t* block_mutex;
trx_t* trx = NULL;
ulint sec;
@ -2204,6 +2207,7 @@ buf_page_get_gen(
ib_uint64_t finish_time;
ut_ad(mtr);
ut_ad(mtr->state == MTR_ACTIVE);
ut_ad((rw_latch == RW_S_LATCH)
|| (rw_latch == RW_X_LATCH)
|| (rw_latch == RW_NO_LATCH));
@ -2271,7 +2275,29 @@ loop2:
return(NULL);
}
buf_read_page(space, zip_size, offset, trx);
if (buf_read_page(space, zip_size, offset, trx)) {
retries = 0;
} else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
++retries;
} else {
fprintf(stderr, "InnoDB: Error: Unable"
" to read tablespace %lu page no"
" %lu into the buffer pool after"
" %lu attempts\n"
"InnoDB: The most probable cause"
" of this error may be that the"
" table has been corrupted.\n"
"InnoDB: You can try to fix this"
" problem by using"
" innodb_force_recovery.\n"
"InnoDB: Please see reference manual"
" for more details.\n"
"InnoDB: Aborting...\n",
space, offset,
BUF_PAGE_READ_MAX_RETRIES);
ut_error;
}
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(++buf_dbg_counter % 37 || buf_validate());
@ -2414,22 +2440,8 @@ wait_until_unfixed:
ut_ad(!block->page.in_flush_list);
} else {
/* Relocate buf_pool->flush_list. */
buf_page_t* b;
b = UT_LIST_GET_PREV(flush_list, &block->page);
ut_ad(block->page.in_flush_list);
UT_LIST_REMOVE(flush_list, buf_pool->flush_list,
&block->page);
if (b) {
UT_LIST_INSERT_AFTER(
flush_list, buf_pool->flush_list, b,
&block->page);
} else {
UT_LIST_ADD_FIRST(
flush_list, buf_pool->flush_list,
&block->page);
}
buf_flush_relocate_on_flush_list(bpage,
&block->page);
}
mutex_exit(&flush_list_mutex);
@ -2447,6 +2459,9 @@ wait_until_unfixed:
block->page.buf_fix_count = 1;
buf_block_set_io_fix(block, BUF_IO_READ);
rw_lock_x_lock(&block->lock);
UNIV_MEM_INVALID(bpage, sizeof *bpage);
mutex_exit(block_mutex);
mutex_exit(&buf_pool_zip_mutex);
@ -2461,8 +2476,9 @@ wait_until_unfixed:
/* Decompress the page and apply buffered operations
while not holding buf_pool_mutex or block->mutex. */
success = buf_zip_decompress(block, srv_use_checksums);
ut_a(success);
if (UNIV_LIKELY(success)) {
if (UNIV_LIKELY(!recv_no_ibuf_operations)) {
ibuf_merge_or_delete_for_page(block, space, offset,
zip_size, TRUE);
}
@ -2478,14 +2494,6 @@ wait_until_unfixed:
buf_pool->n_pend_unzip--;
mutex_exit(&buf_pool_mutex);
rw_lock_x_unlock(&block->lock);
if (UNIV_UNLIKELY(!success)) {
//buf_pool_mutex_exit();
mutex_exit(block_mutex);
return(NULL);
}
break;
case BUF_BLOCK_ZIP_FREE:
@ -2603,8 +2611,8 @@ page.
@return TRUE if success */
UNIV_INTERN
ibool
buf_page_optimistic_get_func(
/*=========================*/
buf_page_optimistic_get(
/*====================*/
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */
buf_block_t* block, /*!< in: guessed buffer block */
ib_uint64_t modify_clock,/*!< in: modify clock value if mode is
@ -2618,7 +2626,9 @@ buf_page_optimistic_get_func(
ulint fix_type;
trx_t* trx = NULL;
ut_ad(mtr && block);
ut_ad(block);
ut_ad(mtr);
ut_ad(mtr->state == MTR_ACTIVE);
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
mutex_enter(&block->mutex);
@ -2738,6 +2748,7 @@ buf_page_get_known_nowait(
trx_t* trx = NULL;
ut_ad(mtr);
ut_ad(mtr->state == MTR_ACTIVE);
ut_ad((rw_latch == RW_S_LATCH) || (rw_latch == RW_X_LATCH));
mutex_enter(&block->mutex);
@ -2846,6 +2857,9 @@ buf_page_try_get_func(
ibool success;
ulint fix_type;
ut_ad(mtr);
ut_ad(mtr->state == MTR_ACTIVE);
//buf_pool_mutex_enter();
rw_lock_s_lock(&page_hash_latch);
block = buf_block_hash_get(space_id, page_no);
@ -3249,6 +3263,7 @@ buf_page_create(
ulint time_ms = ut_time_ms();
ut_ad(mtr);
ut_ad(mtr->state == MTR_ACTIVE);
ut_ad(space || !zip_size);
free_block = buf_LRU_get_free_block(0);
@ -3431,7 +3446,8 @@ buf_page_io_complete(
read_space_id = mach_read_from_4(
frame + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID);
if (bpage->space == TRX_SYS_SPACE
if ((bpage->space == TRX_SYS_SPACE
|| (srv_doublewrite_file && bpage->space == TRX_DOUBLEWRITE_SPACE))
&& trx_doublewrite_page_inside(bpage->offset)) {
ut_print_timestamp(stderr);
@ -3503,7 +3519,7 @@ corrupt:
REFMAN "forcing-recovery.html\n"
"InnoDB: about forcing recovery.\n", stderr);
if (srv_pass_corrupt_table && bpage->space > 0
if (srv_pass_corrupt_table && !trx_sys_sys_space(bpage->space)
&& bpage->space < SRV_LOG_SPACE_FIRST_ID) {
fprintf(stderr,
"InnoDB: space %lu will be treated as corrupt.\n",

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -87,6 +87,146 @@ buf_flush_validate_low(void);
/*========================*/
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
/********************************************************************//**
Insert a block in the flush_rbt and returns a pointer to its
predecessor or NULL if no predecessor. The ordering is maintained
on the basis of the <oldest_modification, space, offset> key.
@return pointer to the predecessor or NULL if no predecessor. */
static
buf_page_t*
buf_flush_insert_in_flush_rbt(
/*==========================*/
buf_page_t* bpage) /*!< in: bpage to be inserted. */
{
buf_page_t* prev = NULL;
const ib_rbt_node_t* c_node;
const ib_rbt_node_t* p_node;
//ut_ad(buf_pool_mutex_own());
ut_ad(mutex_own(&flush_list_mutex));
/* Insert this buffer into the rbt. */
c_node = rbt_insert(buf_pool->flush_rbt, &bpage, &bpage);
ut_a(c_node != NULL);
/* Get the predecessor. */
p_node = rbt_prev(buf_pool->flush_rbt, c_node);
if (p_node != NULL) {
prev = *rbt_value(buf_page_t*, p_node);
ut_a(prev != NULL);
}
return(prev);
}
/********************************************************************//**
Delete a bpage from the flush_rbt. */
static
void
buf_flush_delete_from_flush_rbt(
/*============================*/
buf_page_t* bpage) /*!< in: bpage to be removed. */
{
ibool ret = FALSE;
//ut_ad(buf_pool_mutex_own());
ut_ad(mutex_own(&flush_list_mutex));
ret = rbt_delete(buf_pool->flush_rbt, &bpage);
ut_ad(ret);
}
/********************************************************************//**
Compare two modified blocks in the buffer pool. The key for comparison
is:
key = <oldest_modification, space, offset>
This comparison is used to maintian ordering of blocks in the
buf_pool->flush_rbt.
Note that for the purpose of flush_rbt, we only need to order blocks
on the oldest_modification. The other two fields are used to uniquely
identify the blocks.
@return < 0 if b2 < b1, 0 if b2 == b1, > 0 if b2 > b1 */
static
int
buf_flush_block_cmp(
/*================*/
const void* p1, /*!< in: block1 */
const void* p2) /*!< in: block2 */
{
int ret;
const buf_page_t* b1;
const buf_page_t* b2;
ut_ad(p1 != NULL);
ut_ad(p2 != NULL);
b1 = *(const buf_page_t**) p1;
b2 = *(const buf_page_t**) p2;
ut_ad(b1 != NULL);
ut_ad(b2 != NULL);
ut_ad(b1->in_flush_list);
ut_ad(b2->in_flush_list);
if (b2->oldest_modification
> b1->oldest_modification) {
return(1);
}
if (b2->oldest_modification
< b1->oldest_modification) {
return(-1);
}
/* If oldest_modification is same then decide on the space. */
ret = (int)(b2->space - b1->space);
/* Or else decide ordering on the offset field. */
return(ret ? ret : (int)(b2->offset - b1->offset));
}
/********************************************************************//**
Initialize the red-black tree to speed up insertions into the flush_list
during recovery process. Should be called at the start of recovery
process before any page has been read/written. */
UNIV_INTERN
void
buf_flush_init_flush_rbt(void)
/*==========================*/
{
//buf_pool_mutex_enter();
mutex_enter(&flush_list_mutex);
/* Create red black tree for speedy insertions in flush list. */
buf_pool->flush_rbt = rbt_create(sizeof(buf_page_t*),
buf_flush_block_cmp);
//buf_pool_mutex_exit();
mutex_exit(&flush_list_mutex);
}
/********************************************************************//**
Frees up the red-black tree. */
UNIV_INTERN
void
buf_flush_free_flush_rbt(void)
/*==========================*/
{
//buf_pool_mutex_enter();
mutex_enter(&flush_list_mutex);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(buf_flush_validate_low());
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
rbt_free(buf_pool->flush_rbt);
buf_pool->flush_rbt = NULL;
//buf_pool_mutex_exit();
mutex_exit(&flush_list_mutex);
}
/********************************************************************//**
Inserts a modified block into the flush list. */
UNIV_INTERN
@ -102,6 +242,13 @@ buf_flush_insert_into_flush_list(
|| (UT_LIST_GET_FIRST(buf_pool->flush_list)->oldest_modification
<= block->page.oldest_modification));
/* If we are in the recovery then we need to update the flush
red-black tree as well. */
if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
buf_flush_insert_sorted_into_flush_list(block);
return;
}
ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
ut_ad(block->page.in_LRU_list);
ut_ad(block->page.in_page_hash);
@ -140,26 +287,27 @@ buf_flush_insert_sorted_into_flush_list(
ut_d(block->page.in_flush_list = TRUE);
prev_b = NULL;
b = UT_LIST_GET_FIRST(buf_pool->flush_list);
if (srv_fast_recovery) {
/* speed hack */
if (b == NULL || b->oldest_modification < block->page.oldest_modification) {
UT_LIST_ADD_FIRST(flush_list, buf_pool->flush_list, &block->page);
/* For the most part when this function is called the flush_rbt
should not be NULL. In a very rare boundary case it is possible
that the flush_rbt has already been freed by the recovery thread
before the last page was hooked up in the flush_list by the
io-handler thread. In that case we'll just do a simple
linear search in the else block. */
if (buf_pool->flush_rbt) {
prev_b = buf_flush_insert_in_flush_rbt(&block->page);
} else {
b = UT_LIST_GET_LAST(buf_pool->flush_list);
if (b->oldest_modification < block->page.oldest_modification) {
/* align oldest_modification not to sort */
block->page.oldest_modification = b->oldest_modification;
b = UT_LIST_GET_FIRST(buf_pool->flush_list);
while (b && b->oldest_modification
> block->page.oldest_modification) {
ut_ad(b->in_flush_list);
prev_b = b;
b = UT_LIST_GET_NEXT(flush_list, b);
}
UT_LIST_ADD_LAST(flush_list, buf_pool->flush_list, &block->page);
}
} else {
/* normal */
while (b && b->oldest_modification > block->page.oldest_modification) {
ut_ad(b->in_flush_list);
prev_b = b;
b = UT_LIST_GET_NEXT(flush_list, b);
}
if (prev_b == NULL) {
@ -168,7 +316,6 @@ buf_flush_insert_sorted_into_flush_list(
UT_LIST_INSERT_AFTER(flush_list, buf_pool->flush_list,
prev_b, &block->page);
}
}
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(buf_flush_validate_low());
@ -262,7 +409,6 @@ buf_flush_remove(
mutex_enter(&flush_list_mutex);
ut_ad(bpage->in_flush_list);
ut_d(bpage->in_flush_list = FALSE);
switch (buf_page_get_state(bpage)) {
case BUF_BLOCK_ZIP_PAGE:
@ -285,6 +431,15 @@ buf_flush_remove(
break;
}
/* If the flush_rbt is active then delete from it as well. */
if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
buf_flush_delete_from_flush_rbt(bpage);
}
/* Must be done after we have removed it from the flush_rbt
because we assert on in_flush_list in comparison function. */
ut_d(bpage->in_flush_list = FALSE);
bpage->oldest_modification = 0;
ut_d(UT_LIST_VALIDATE(flush_list, buf_page_t, buf_pool->flush_list,
@ -292,6 +447,64 @@ buf_flush_remove(
mutex_exit(&flush_list_mutex);
}
/********************************************************************//**
Relocates a buffer control block on the flush_list.
Note that it is assumed that the contents of bpage has already been
copied to dpage. */
UNIV_INTERN
void
buf_flush_relocate_on_flush_list(
/*=============================*/
buf_page_t* bpage, /*!< in/out: control block being moved */
buf_page_t* dpage) /*!< in/out: destination block */
{
buf_page_t* prev;
buf_page_t* prev_b = NULL;
//ut_ad(buf_pool_mutex_own());
ut_ad(mutex_own(&flush_list_mutex));
ut_ad(mutex_own(buf_page_get_mutex(bpage)));
ut_ad(bpage->in_flush_list);
ut_ad(dpage->in_flush_list);
/* If recovery is active we must swap the control blocks in
the flush_rbt as well. */
if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
buf_flush_delete_from_flush_rbt(bpage);
prev_b = buf_flush_insert_in_flush_rbt(dpage);
}
/* Must be done after we have removed it from the flush_rbt
because we assert on in_flush_list in comparison function. */
ut_d(bpage->in_flush_list = FALSE);
prev = UT_LIST_GET_PREV(flush_list, bpage);
UT_LIST_REMOVE(flush_list, buf_pool->flush_list, bpage);
if (prev) {
ut_ad(prev->in_flush_list);
UT_LIST_INSERT_AFTER(
flush_list,
buf_pool->flush_list,
prev, dpage);
} else {
UT_LIST_ADD_FIRST(
flush_list,
buf_pool->flush_list,
dpage);
}
/* Just an extra check. Previous in flush_list
should be the same control block as in flush_rbt. */
ut_a(!buf_pool->flush_rbt || prev_b == prev);
#if defined UNIV_DEBUG || defined UNIV_BUF_DEBUG
ut_a(buf_flush_validate_low());
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
}
/********************************************************************//**
Updates the flush system data structures when a write is completed. */
UNIV_INTERN
@ -452,7 +665,8 @@ corrupted_page:
write_buf = trx_doublewrite->write_buf;
i = 0;
fil_io(OS_FILE_WRITE, TRUE, TRX_SYS_SPACE, 0,
fil_io(OS_FILE_WRITE, TRUE,
(srv_doublewrite_file ? TRX_DOUBLEWRITE_SPACE : TRX_SYS_SPACE), 0,
trx_doublewrite->block1, 0, len,
(void*) write_buf, NULL);
@ -489,7 +703,8 @@ corrupted_page:
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE;
ut_ad(i == TRX_SYS_DOUBLEWRITE_BLOCK_SIZE);
fil_io(OS_FILE_WRITE, TRUE, TRX_SYS_SPACE, 0,
fil_io(OS_FILE_WRITE, TRUE,
(srv_doublewrite_file ? TRX_DOUBLEWRITE_SPACE : TRX_SYS_SPACE), 0,
trx_doublewrite->block2, 0, len,
(void*) write_buf, NULL);
@ -519,7 +734,7 @@ corrupted_page:
flush:
/* Now flush the doublewrite buffer data to disk */
fil_flush(TRX_SYS_SPACE);
fil_flush(srv_doublewrite_file ? TRX_DOUBLEWRITE_SPACE : TRX_SYS_SPACE);
/* We know that the writes have been flushed to disk now
and in recovery we will find them in the doublewrite buffer
@ -1473,24 +1688,45 @@ ibool
buf_flush_validate_low(void)
/*========================*/
{
buf_page_t* bpage;
buf_page_t* bpage;
const ib_rbt_node_t* rnode = NULL;
UT_LIST_VALIDATE(flush_list, buf_page_t, buf_pool->flush_list,
ut_ad(ut_list_node_313->in_flush_list));
bpage = UT_LIST_GET_FIRST(buf_pool->flush_list);
/* If we are in recovery mode i.e.: flush_rbt != NULL
then each block in the flush_list must also be present
in the flush_rbt. */
if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
rnode = rbt_first(buf_pool->flush_rbt);
}
while (bpage != NULL) {
const ib_uint64_t om = bpage->oldest_modification;
ut_ad(bpage->in_flush_list);
//ut_a(buf_page_in_file(bpage)); /* optimistic */
ut_a(om > 0);
if (UNIV_LIKELY_NULL(buf_pool->flush_rbt)) {
ut_a(rnode);
buf_page_t* rpage = *rbt_value(buf_page_t*,
rnode);
ut_a(rpage);
ut_a(rpage == bpage);
rnode = rbt_next(buf_pool->flush_rbt, rnode);
}
bpage = UT_LIST_GET_NEXT(flush_list, bpage);
ut_a(!bpage || om >= bpage->oldest_modification);
}
/* By this time we must have exhausted the traversal of
flush_rbt (if active) as well. */
ut_a(rnode == NULL);
return(TRUE);
}

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -371,21 +371,39 @@ scan_again:
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
while (bpage != NULL) {
mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
buf_page_t* prev_bpage;
ibool prev_bpage_buf_fix = FALSE;
ut_a(buf_page_in_file(bpage));
prev_bpage = UT_LIST_GET_PREV(LRU, bpage);
if (!block_mutex) {
bpage = prev_bpage;
continue;
}
/* bpage->space and bpage->io_fix are protected by
buf_pool_mutex and block_mutex. It is safe to check
them while holding buf_pool_mutex only. */
if (buf_page_get_space(bpage) == id) {
if (bpage->buf_fix_count > 0
|| buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
if (buf_page_get_space(bpage) != id) {
/* Skip this block, as it does not belong to
the space that is being invalidated. */
} else if (buf_page_get_io_fix(bpage) != BUF_IO_NONE) {
/* We cannot remove this page during this scan
yet; maybe the system is currently reading it
in, or flushing the modifications to the file */
all_freed = FALSE;
} else {
mutex_t* block_mutex = buf_page_get_mutex_enter(bpage);
if (!block_mutex) {
/* It may be impossible case...
Something wrong, so will be scan_again */
all_freed = FALSE;
goto next_page_no_mutex;
}
if (bpage->buf_fix_count > 0) {
/* We cannot remove this page during
this scan yet; maybe the system is
@ -405,8 +423,40 @@ scan_again:
(ulong) buf_page_get_page_no(bpage));
}
#endif
if (buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE
&& ((buf_block_t*) bpage)->is_hashed) {
if (buf_page_get_state(bpage) != BUF_BLOCK_FILE_PAGE) {
/* This is a compressed-only block
descriptor. Ensure that prev_bpage
cannot be relocated when bpage is freed. */
if (UNIV_LIKELY(prev_bpage != NULL)) {
switch (buf_page_get_state(
prev_bpage)) {
case BUF_BLOCK_FILE_PAGE:
/* Descriptors of uncompressed
blocks will not be relocated,
because we are holding the
buf_pool_mutex. */
break;
case BUF_BLOCK_ZIP_PAGE:
case BUF_BLOCK_ZIP_DIRTY:
/* Descriptors of compressed-
only blocks can be relocated,
unless they are buffer-fixed.
Because both bpage and
prev_bpage are protected by
buf_pool_zip_mutex, it is
not necessary to acquire
further mutexes. */
ut_ad(&buf_pool_zip_mutex
== block_mutex);
ut_ad(mutex_own(block_mutex));
prev_bpage_buf_fix = TRUE;
prev_bpage->buf_fix_count++;
break;
default:
ut_error;
}
}
} else if (((buf_block_t*) bpage)->is_hashed) {
ulint page_no;
ulint zip_size;
@ -432,7 +482,8 @@ scan_again:
buf_flush_remove(bpage);
}
/* Remove from the LRU list */
/* Remove from the LRU list. */
if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
!= BUF_BLOCK_ZIP_FREE) {
buf_LRU_block_free_hashed_page((buf_block_t*)
@ -444,18 +495,27 @@ scan_again:
ut_ad(block_mutex == &buf_pool_zip_mutex);
ut_ad(!mutex_own(block_mutex));
/* The compressed block descriptor
(bpage) has been deallocated and
block_mutex released. Also,
buf_buddy_free() may have relocated
prev_bpage. Rescan the LRU list. */
if (prev_bpage_buf_fix) {
/* We temporarily buffer-fixed
prev_bpage, so that
buf_buddy_free() could not
relocate it, in case it was a
compressed-only block
descriptor. */
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
continue;
mutex_enter(block_mutex);
ut_ad(prev_bpage->buf_fix_count > 0);
prev_bpage->buf_fix_count--;
mutex_exit(block_mutex);
}
goto next_page_no_mutex;
}
}
next_page:
mutex_exit(block_mutex);
mutex_exit(block_mutex);
}
next_page_no_mutex:
bpage = prev_bpage;
}
@ -1600,26 +1660,8 @@ not_freed:
if (b->state == BUF_BLOCK_ZIP_PAGE) {
buf_LRU_insert_zip_clean(b);
} else {
buf_page_t* prev;
ut_ad(b->in_flush_list);
ut_d(bpage->in_flush_list = FALSE);
prev = UT_LIST_GET_PREV(flush_list, b);
UT_LIST_REMOVE(flush_list, buf_pool->flush_list, b);
if (prev) {
ut_ad(prev->in_flush_list);
UT_LIST_INSERT_AFTER(
flush_list,
buf_pool->flush_list,
prev, b);
} else {
UT_LIST_ADD_FIRST(
flush_list,
buf_pool->flush_list,
b);
}
/* Relocate on buf_pool->flush_list. */
buf_flush_relocate_on_flush_list(bpage, b);
}
mutex_exit(&flush_list_mutex);

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -86,7 +86,9 @@ buf_read_page_low(
wake_later = mode & OS_AIO_SIMULATED_WAKE_LATER;
mode = mode & ~OS_AIO_SIMULATED_WAKE_LATER;
if (trx_doublewrite && space == TRX_SYS_SPACE
if (trx_doublewrite
&& (space == TRX_SYS_SPACE
|| (srv_doublewrite_file && space == TRX_DOUBLEWRITE_SPACE))
&& ( (offset >= trx_doublewrite->block1
&& offset < trx_doublewrite->block1
+ TRX_SYS_DOUBLEWRITE_BLOCK_SIZE)
@ -656,6 +658,50 @@ buf_read_recv_pages(
/* It is a single table tablespace and the .ibd file is
missing: do nothing */
/* the log records should be treated here same reason
for http://bugs.mysql.com/bug.php?id=43948 */
if (recv_recovery_is_on()) {
recv_addr_t* recv_addr;
mutex_enter(&(recv_sys->mutex));
if (recv_sys->apply_log_recs == FALSE) {
mutex_exit(&(recv_sys->mutex));
goto not_to_recover;
}
for (i = 0; i < n_stored; i++) {
/* recv_get_fil_addr_struct() */
recv_addr = HASH_GET_FIRST(recv_sys->addr_hash,
hash_calc_hash(ut_fold_ulint_pair(space, page_nos[i]),
recv_sys->addr_hash));
while (recv_addr) {
if ((recv_addr->space == space)
&& (recv_addr->page_no == page_nos[i])) {
break;
}
recv_addr = HASH_GET_NEXT(addr_hash, recv_addr);
}
if ((recv_addr == NULL)
|| (recv_addr->state == RECV_BEING_PROCESSED)
|| (recv_addr->state == RECV_PROCESSED)) {
continue;
}
recv_addr->state = RECV_PROCESSED;
ut_a(recv_sys->n_addrs);
recv_sys->n_addrs--;
}
mutex_exit(&(recv_sys->mutex));
fprintf(stderr, " (cannot find space: %lu)", space);
}
not_to_recover:
return;
}
@ -674,10 +720,10 @@ buf_read_recv_pages(
count++;
if (count > 5000) {
if (count > 1000) {
fprintf(stderr,
"InnoDB: Error: InnoDB has waited for"
" 50 seconds for pending\n"
" 10 seconds for pending\n"
"InnoDB: reads to the buffer pool to"
" be finished.\n"
"InnoDB: Number of pending reads %lu,"

View file

@ -666,6 +666,21 @@ dtuple_convert_big_rec(
goto skip_field;
}
/* In DYNAMIC and COMPRESSED format, store
locally any non-BLOB columns whose maximum
length does not exceed 256 bytes. This is
because there is no room for the "external
storage" flag when the maximum length is 255
bytes or less. This restriction trivially
holds in REDUNDANT and COMPACT format, because
there we always store locally columns whose
length is up to local_len == 788 bytes.
@see rec_init_offsets_comp_ordinary */
if (ifield->col->mtype != DATA_BLOB
&& ifield->col->len < 256) {
goto skip_field;
}
longest_i = i;
longest = savings;

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -275,6 +275,9 @@ dict_boot(void)
and (TYPE & DICT_TF_FORMAT_MASK) are nonzero and TYPE = table->flags */
dict_mem_table_add_col(table, heap, "TYPE", DATA_INT, 0, 4);
dict_mem_table_add_col(table, heap, "MIX_ID", DATA_BINARY, 0, 0);
/* MIX_LEN may contain additional table flags when
ROW_FORMAT!=REDUNDANT. Currently, these flags include
DICT_TF2_TEMPORARY. */
dict_mem_table_add_col(table, heap, "MIX_LEN", DATA_INT, 0, 4);
dict_mem_table_add_col(table, heap, "CLUSTER_NAME", DATA_BINARY, 0, 0);
dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
@ -358,7 +361,7 @@ dict_boot(void)
dict_mem_table_add_col(table, heap, "SPACE", DATA_INT, 0, 4);
dict_mem_table_add_col(table, heap, "PAGE_NO", DATA_INT, 0, 4);
/* The '+ 2' below comes from the 2 system fields */
/* The '+ 2' below comes from the fields DB_TRX_ID, DB_ROLL_PTR */
#if DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2
#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 6 + 2"
#endif
@ -367,6 +370,9 @@ dict_boot(void)
#endif
#if DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2
#error "DICT_SYS_INDEXES_TYPE_FIELD != 4 + 2"
#endif
#if DICT_SYS_INDEXES_NAME_FIELD != 2 + 2
#error "DICT_SYS_INDEXES_NAME_FIELD != 2 + 2"
#endif
table->id = DICT_INDEXES_ID;

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -51,16 +51,18 @@ static
dtuple_t*
dict_create_sys_tables_tuple(
/*=========================*/
dict_table_t* table, /*!< in: table */
mem_heap_t* heap) /*!< in: memory heap from which the memory for
the built tuple is allocated */
const dict_table_t* table, /*!< in: table */
mem_heap_t* heap) /*!< in: memory heap from
which the memory for the built
tuple is allocated */
{
dict_table_t* sys_tables;
dtuple_t* entry;
dfield_t* dfield;
byte* ptr;
ut_ad(table && heap);
ut_ad(table);
ut_ad(heap);
sys_tables = dict_sys->sys_tables;
@ -69,18 +71,18 @@ dict_create_sys_tables_tuple(
dict_table_copy_types(entry, sys_tables);
/* 0: NAME -----------------------------*/
dfield = dtuple_get_nth_field(entry, 0);
dfield = dtuple_get_nth_field(entry, 0/*NAME*/);
dfield_set_data(dfield, table->name, ut_strlen(table->name));
/* 3: ID -------------------------------*/
dfield = dtuple_get_nth_field(entry, 1);
dfield = dtuple_get_nth_field(entry, 1/*ID*/);
ptr = mem_heap_alloc(heap, 8);
mach_write_to_8(ptr, table->id);
dfield_set_data(dfield, ptr, 8);
/* 4: N_COLS ---------------------------*/
dfield = dtuple_get_nth_field(entry, 2);
dfield = dtuple_get_nth_field(entry, 2/*N_COLS*/);
#if DICT_TF_COMPACT != 1
#error
@ -91,40 +93,41 @@ dict_create_sys_tables_tuple(
| ((table->flags & DICT_TF_COMPACT) << 31));
dfield_set_data(dfield, ptr, 4);
/* 5: TYPE -----------------------------*/
dfield = dtuple_get_nth_field(entry, 3);
dfield = dtuple_get_nth_field(entry, 3/*TYPE*/);
ptr = mem_heap_alloc(heap, 4);
if (table->flags & ~DICT_TF_COMPACT) {
if (table->flags & (~DICT_TF_COMPACT & ~(~0 << DICT_TF_BITS))) {
ut_a(table->flags & DICT_TF_COMPACT);
ut_a(dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
ut_a((table->flags & DICT_TF_ZSSIZE_MASK)
<= (DICT_TF_ZSSIZE_MAX << DICT_TF_ZSSIZE_SHIFT));
ut_a(!(table->flags & (~0 << DICT_TF_BITS)));
mach_write_to_4(ptr, table->flags);
ut_a(!(table->flags & (~0 << DICT_TF2_BITS)));
mach_write_to_4(ptr, table->flags & ~(~0 << DICT_TF_BITS));
} else {
mach_write_to_4(ptr, DICT_TABLE_ORDINARY);
}
dfield_set_data(dfield, ptr, 4);
/* 6: MIX_ID (obsolete) ---------------------------*/
dfield = dtuple_get_nth_field(entry, 4);
dfield = dtuple_get_nth_field(entry, 4/*MIX_ID*/);
ptr = mem_heap_zalloc(heap, 8);
dfield_set_data(dfield, ptr, 8);
/* 7: MIX_LEN (obsolete) --------------------------*/
/* 7: MIX_LEN (additional flags) --------------------------*/
dfield = dtuple_get_nth_field(entry, 5);
dfield = dtuple_get_nth_field(entry, 5/*MIX_LEN*/);
ptr = mem_heap_zalloc(heap, 4);
ptr = mem_heap_alloc(heap, 4);
mach_write_to_4(ptr, table->flags >> DICT_TF2_SHIFT);
dfield_set_data(dfield, ptr, 4);
/* 8: CLUSTER_NAME ---------------------*/
dfield = dtuple_get_nth_field(entry, 6);
dfield = dtuple_get_nth_field(entry, 6/*CLUSTER_NAME*/);
dfield_set_null(dfield); /* not supported */
/* 9: SPACE ----------------------------*/
dfield = dtuple_get_nth_field(entry, 7);
dfield = dtuple_get_nth_field(entry, 7/*SPACE*/);
ptr = mem_heap_alloc(heap, 4);
mach_write_to_4(ptr, table->space);
@ -143,19 +146,21 @@ static
dtuple_t*
dict_create_sys_columns_tuple(
/*==========================*/
dict_table_t* table, /*!< in: table */
ulint i, /*!< in: column number */
mem_heap_t* heap) /*!< in: memory heap from which the memory for
the built tuple is allocated */
const dict_table_t* table, /*!< in: table */
ulint i, /*!< in: column number */
mem_heap_t* heap) /*!< in: memory heap from
which the memory for the built
tuple is allocated */
{
dict_table_t* sys_columns;
dtuple_t* entry;
const dict_col_t* column;
dfield_t* dfield;
byte* ptr;
const char* col_name;
const char* col_name;
ut_ad(table && heap);
ut_ad(table);
ut_ad(heap);
column = dict_table_get_nth_col(table, i);
@ -166,47 +171,47 @@ dict_create_sys_columns_tuple(
dict_table_copy_types(entry, sys_columns);
/* 0: TABLE_ID -----------------------*/
dfield = dtuple_get_nth_field(entry, 0);
dfield = dtuple_get_nth_field(entry, 0/*TABLE_ID*/);
ptr = mem_heap_alloc(heap, 8);
mach_write_to_8(ptr, table->id);
dfield_set_data(dfield, ptr, 8);
/* 1: POS ----------------------------*/
dfield = dtuple_get_nth_field(entry, 1);
dfield = dtuple_get_nth_field(entry, 1/*POS*/);
ptr = mem_heap_alloc(heap, 4);
mach_write_to_4(ptr, i);
dfield_set_data(dfield, ptr, 4);
/* 4: NAME ---------------------------*/
dfield = dtuple_get_nth_field(entry, 2);
dfield = dtuple_get_nth_field(entry, 2/*NAME*/);
col_name = dict_table_get_col_name(table, i);
dfield_set_data(dfield, col_name, ut_strlen(col_name));
/* 5: MTYPE --------------------------*/
dfield = dtuple_get_nth_field(entry, 3);
dfield = dtuple_get_nth_field(entry, 3/*MTYPE*/);
ptr = mem_heap_alloc(heap, 4);
mach_write_to_4(ptr, column->mtype);
dfield_set_data(dfield, ptr, 4);
/* 6: PRTYPE -------------------------*/
dfield = dtuple_get_nth_field(entry, 4);
dfield = dtuple_get_nth_field(entry, 4/*PRTYPE*/);
ptr = mem_heap_alloc(heap, 4);
mach_write_to_4(ptr, column->prtype);
dfield_set_data(dfield, ptr, 4);
/* 7: LEN ----------------------------*/
dfield = dtuple_get_nth_field(entry, 5);
dfield = dtuple_get_nth_field(entry, 5/*LEN*/);
ptr = mem_heap_alloc(heap, 4);
mach_write_to_4(ptr, column->len);
dfield_set_data(dfield, ptr, 4);
/* 8: PREC ---------------------------*/
dfield = dtuple_get_nth_field(entry, 6);
dfield = dtuple_get_nth_field(entry, 6/*PREC*/);
ptr = mem_heap_alloc(heap, 4);
mach_write_to_4(ptr, 0/* unused */);
@ -230,6 +235,7 @@ dict_build_table_def_step(
dict_table_t* table;
dtuple_t* row;
ulint error;
ulint flags;
const char* path_or_name;
ibool is_path;
mtr_t mtr;
@ -268,9 +274,10 @@ dict_build_table_def_step(
ut_ad(!dict_table_zip_size(table)
|| dict_table_get_format(table) >= DICT_TF_FORMAT_ZIP);
flags = table->flags & ~(~0 << DICT_TF_BITS);
error = fil_create_new_single_table_tablespace(
&space, path_or_name, is_path,
table->flags == DICT_TF_COMPACT ? 0 : table->flags,
flags == DICT_TF_COMPACT ? 0 : flags,
FIL_IBD_FILE_INITIAL_SIZE);
table->space = (unsigned int) space;
@ -286,7 +293,7 @@ dict_build_table_def_step(
mtr_commit(&mtr);
} else {
/* Create in the system tablespace: disallow new features */
table->flags &= DICT_TF_COMPACT;
table->flags &= (~0 << DICT_TF_BITS) | DICT_TF_COMPACT;
}
row = dict_create_sys_tables_tuple(table, node->heap);
@ -322,9 +329,10 @@ static
dtuple_t*
dict_create_sys_indexes_tuple(
/*==========================*/
dict_index_t* index, /*!< in: index */
mem_heap_t* heap) /*!< in: memory heap from which the memory for
the built tuple is allocated */
const dict_index_t* index, /*!< in: index */
mem_heap_t* heap) /*!< in: memory heap from
which the memory for the built
tuple is allocated */
{
dict_table_t* sys_indexes;
dict_table_t* table;
@ -333,7 +341,8 @@ dict_create_sys_indexes_tuple(
byte* ptr;
ut_ad(mutex_own(&(dict_sys->mutex)));
ut_ad(index && heap);
ut_ad(index);
ut_ad(heap);
sys_indexes = dict_sys->sys_indexes;
@ -344,32 +353,32 @@ dict_create_sys_indexes_tuple(
dict_table_copy_types(entry, sys_indexes);
/* 0: TABLE_ID -----------------------*/
dfield = dtuple_get_nth_field(entry, 0);
dfield = dtuple_get_nth_field(entry, 0/*TABLE_ID*/);
ptr = mem_heap_alloc(heap, 8);
mach_write_to_8(ptr, table->id);
dfield_set_data(dfield, ptr, 8);
/* 1: ID ----------------------------*/
dfield = dtuple_get_nth_field(entry, 1);
dfield = dtuple_get_nth_field(entry, 1/*ID*/);
ptr = mem_heap_alloc(heap, 8);
mach_write_to_8(ptr, index->id);
dfield_set_data(dfield, ptr, 8);
/* 4: NAME --------------------------*/
dfield = dtuple_get_nth_field(entry, 2);
dfield = dtuple_get_nth_field(entry, 2/*NAME*/);
dfield_set_data(dfield, index->name, ut_strlen(index->name));
/* 5: N_FIELDS ----------------------*/
dfield = dtuple_get_nth_field(entry, 3);
dfield = dtuple_get_nth_field(entry, 3/*N_FIELDS*/);
ptr = mem_heap_alloc(heap, 4);
mach_write_to_4(ptr, index->n_fields);
dfield_set_data(dfield, ptr, 4);
/* 6: TYPE --------------------------*/
dfield = dtuple_get_nth_field(entry, 4);
dfield = dtuple_get_nth_field(entry, 4/*TYPE*/);
ptr = mem_heap_alloc(heap, 4);
mach_write_to_4(ptr, index->type);
@ -381,7 +390,7 @@ dict_create_sys_indexes_tuple(
#error "DICT_SYS_INDEXES_SPACE_NO_FIELD != 7"
#endif
dfield = dtuple_get_nth_field(entry, 5);
dfield = dtuple_get_nth_field(entry, 5/*SPACE*/);
ptr = mem_heap_alloc(heap, 4);
mach_write_to_4(ptr, index->space);
@ -393,7 +402,7 @@ dict_create_sys_indexes_tuple(
#error "DICT_SYS_INDEXES_PAGE_NO_FIELD != 8"
#endif
dfield = dtuple_get_nth_field(entry, 6);
dfield = dtuple_get_nth_field(entry, 6/*PAGE_NO*/);
ptr = mem_heap_alloc(heap, 4);
mach_write_to_4(ptr, FIL_NULL);
@ -412,10 +421,11 @@ static
dtuple_t*
dict_create_sys_fields_tuple(
/*=========================*/
dict_index_t* index, /*!< in: index */
ulint i, /*!< in: field number */
mem_heap_t* heap) /*!< in: memory heap from which the memory for
the built tuple is allocated */
const dict_index_t* index, /*!< in: index */
ulint i, /*!< in: field number */
mem_heap_t* heap) /*!< in: memory heap from
which the memory for the built
tuple is allocated */
{
dict_table_t* sys_fields;
dtuple_t* entry;
@ -425,7 +435,8 @@ dict_create_sys_fields_tuple(
ibool index_contains_column_prefix_field = FALSE;
ulint j;
ut_ad(index && heap);
ut_ad(index);
ut_ad(heap);
for (j = 0; j < index->n_fields; j++) {
if (dict_index_get_nth_field(index, j)->prefix_len > 0) {
@ -443,7 +454,7 @@ dict_create_sys_fields_tuple(
dict_table_copy_types(entry, sys_fields);
/* 0: INDEX_ID -----------------------*/
dfield = dtuple_get_nth_field(entry, 0);
dfield = dtuple_get_nth_field(entry, 0/*INDEX_ID*/);
ptr = mem_heap_alloc(heap, 8);
mach_write_to_8(ptr, index->id);
@ -451,7 +462,7 @@ dict_create_sys_fields_tuple(
dfield_set_data(dfield, ptr, 8);
/* 1: POS + PREFIX LENGTH ----------------------------*/
dfield = dtuple_get_nth_field(entry, 1);
dfield = dtuple_get_nth_field(entry, 1/*POS*/);
ptr = mem_heap_alloc(heap, 4);
@ -471,7 +482,7 @@ dict_create_sys_fields_tuple(
dfield_set_data(dfield, ptr, 4);
/* 4: COL_NAME -------------------------*/
dfield = dtuple_get_nth_field(entry, 2);
dfield = dtuple_get_nth_field(entry, 2/*COL_NAME*/);
dfield_set_data(dfield, field->name,
ut_strlen(field->name));
@ -602,6 +613,7 @@ dict_create_index_tree_step(
dict_table_t* sys_indexes;
dict_table_t* table;
dtuple_t* search_tuple;
ulint zip_size;
btr_pcur_t pcur;
mtr_t mtr;
@ -626,8 +638,9 @@ dict_create_index_tree_step(
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
node->page_no = btr_create(index->type, index->space,
dict_table_zip_size(index->table),
zip_size = dict_table_zip_size(index->table);
node->page_no = btr_create(index->type, index->space, zip_size,
index->id, index, &mtr);
/* printf("Created a new index tree in space %lu root page %lu\n",
index->space, index->page_no); */
@ -1092,8 +1105,11 @@ dict_create_index_step(
dulint index_id = node->index->id;
err = dict_index_add_to_cache(node->table, node->index,
FIL_NULL, TRUE);
err = dict_index_add_to_cache(
node->table, node->index, FIL_NULL,
trx_is_strict(trx)
|| dict_table_get_format(node->table)
>= DICT_TF_FORMAT_ZIP);
node->index = dict_index_get_if_in_cache_low(index_id);
ut_a(!node->index == (err != DB_SUCCESS));

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -81,6 +81,10 @@ UNIV_INTERN rw_lock_t dict_operation_lock;
/** Identifies generated InnoDB foreign key names */
static char dict_ibfk[] = "_ibfk_";
/** array of mutexes protecting dict_index_t::stat_n_diff_key_vals[] */
#define DICT_INDEX_STAT_MUTEX_SIZE 32
mutex_t dict_index_stat_mutex[DICT_INDEX_STAT_MUTEX_SIZE];
/*******************************************************************//**
Tries to find column names for the index and sets the col field of the
index.
@ -141,7 +145,7 @@ static
void
dict_field_print_low(
/*=================*/
dict_field_t* field); /*!< in: field */
const dict_field_t* field); /*!< in: field */
/*********************************************************************//**
Frees a foreign key struct. */
static
@ -240,6 +244,45 @@ dict_mutex_exit_for_mysql(void)
mutex_exit(&(dict_sys->mutex));
}
/** Get the mutex that protects index->stat_n_diff_key_vals[] */
#define GET_INDEX_STAT_MUTEX(index) \
(&dict_index_stat_mutex[ut_fold_dulint(index->id) \
% DICT_INDEX_STAT_MUTEX_SIZE])
/**********************************************************************//**
Lock the appropriate mutex to protect index->stat_n_diff_key_vals[].
index->id is used to pick the right mutex and it should not change
before dict_index_stat_mutex_exit() is called on this index. */
UNIV_INTERN
void
dict_index_stat_mutex_enter(
/*========================*/
const dict_index_t* index) /*!< in: index */
{
ut_ad(index != NULL);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
ut_ad(index->cached);
ut_ad(!index->to_be_dropped);
mutex_enter(GET_INDEX_STAT_MUTEX(index));
}
/**********************************************************************//**
Unlock the appropriate mutex that protects index->stat_n_diff_key_vals[]. */
UNIV_INTERN
void
dict_index_stat_mutex_exit(
/*=======================*/
const dict_index_t* index) /*!< in: index */
{
ut_ad(index != NULL);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
ut_ad(index->cached);
ut_ad(!index->to_be_dropped);
mutex_exit(GET_INDEX_STAT_MUTEX(index));
}
/********************************************************************//**
Decrements the count of open MySQL handles to a table. */
UNIV_INTERN
@ -608,6 +651,8 @@ void
dict_init(void)
/*===========*/
{
int i;
dict_sys = mem_alloc(sizeof(dict_sys_t));
mutex_create(&dict_sys->mutex, SYNC_DICT);
@ -628,6 +673,10 @@ dict_init(void)
ut_a(dict_foreign_err_file);
mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH);
for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
mutex_create(&dict_index_stat_mutex[i], SYNC_INDEX_TREE);
}
}
/**********************************************************************//**
@ -1442,11 +1491,7 @@ dict_index_too_big_for_tree(
goto add_field_size;
}
if (srv_relax_table_creation) {
field_max_size = dict_col_get_min_size(col);
} else {
field_max_size = dict_col_get_max_size(col);
}
field_ext_max_size = field_max_size < 256 ? 1 : 2;
if (field->prefix_len) {
@ -1527,6 +1572,7 @@ dict_index_add_to_cache(
if (!dict_index_find_cols(table, index)) {
dict_mem_index_free(index);
return(DB_CORRUPTION);
}
@ -4247,9 +4293,13 @@ dict_update_statistics_low(
index = dict_table_get_first_index(table);
dict_index_stat_mutex_enter(index);
table->stat_n_rows = index->stat_n_diff_key_vals[
dict_index_get_n_unique(index)];
dict_index_stat_mutex_exit(index);
table->stat_clustered_index_size = index->stat_index_size;
table->stat_sum_of_other_index_sizes = sum_of_index_sizes
@ -4428,6 +4478,8 @@ dict_index_print_low(
ut_ad(mutex_own(&(dict_sys->mutex)));
dict_index_stat_mutex_enter(index);
if (index->n_user_defined_cols > 0) {
n_vals = index->stat_n_diff_key_vals[
index->n_user_defined_cols];
@ -4435,6 +4487,8 @@ dict_index_print_low(
n_vals = index->stat_n_diff_key_vals[1];
}
dict_index_stat_mutex_exit(index);
if (dict_index_is_clust(index)) {
type_string = "clustered index";
} else if (dict_index_is_unique(index)) {
@ -4480,7 +4534,7 @@ static
void
dict_field_print_low(
/*=================*/
dict_field_t* field) /*!< in: field */
const dict_field_t* field) /*!< in: field */
{
ut_ad(mutex_own(&(dict_sys->mutex)));
@ -4844,8 +4898,10 @@ UNIV_INTERN
void
dict_table_check_for_dup_indexes(
/*=============================*/
const dict_table_t* table) /*!< in: Check for dup indexes
const dict_table_t* table, /*!< in: Check for dup indexes
in this table */
ibool tmp_ok) /*!< in: TRUE=allow temporary
index names */
{
/* Check for duplicates, ignoring indexes that are marked
as to be dropped */
@ -4853,13 +4909,17 @@ dict_table_check_for_dup_indexes(
const dict_index_t* index1;
const dict_index_t* index2;
ut_ad(mutex_own(&dict_sys->mutex));
/* The primary index _must_ exist */
ut_a(UT_LIST_GET_LEN(table->indexes) > 0);
index1 = UT_LIST_GET_FIRST(table->indexes);
index2 = UT_LIST_GET_NEXT(indexes, index1);
while (index1 && index2) {
do {
ut_ad(tmp_ok || *index1->name != TEMP_INDEX_PREFIX);
index2 = UT_LIST_GET_NEXT(indexes, index1);
while (index2) {
@ -4871,8 +4931,7 @@ dict_table_check_for_dup_indexes(
}
index1 = UT_LIST_GET_NEXT(indexes, index1);
index2 = UT_LIST_GET_NEXT(indexes, index1);
}
} while (index1);
}
#endif /* UNIV_DEBUG */
@ -4925,6 +4984,10 @@ dict_close(void)
mem_free(dict_sys);
dict_sys = NULL;
for (i = 0; i < DICT_INDEX_STAT_MUTEX_SIZE; i++) {
mutex_free(&dict_index_stat_mutex[i]);
}
}
/*************************************************************************
@ -4939,7 +5002,7 @@ dict_table_set_corrupt_by_space(
dict_table_t* table;
ibool found = FALSE;
ut_a(space_id != 0 && space_id < SRV_LOG_SPACE_FIRST_ID);
ut_a(!trx_sys_sys_space(space_id) && space_id < SRV_LOG_SPACE_FIRST_ID);
if (need_mutex)
mutex_enter(&(dict_sys->mutex));

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -260,7 +260,7 @@ dict_sys_tables_get_flags(
return(0);
}
field = rec_get_nth_field_old(rec, 4, &len);
field = rec_get_nth_field_old(rec, 4/*N_COLS*/, &len);
n_cols = mach_read_from_4(field);
if (UNIV_UNLIKELY(!(n_cols & 0x80000000UL))) {
@ -390,15 +390,35 @@ loop:
mtr_commit(&mtr);
if (space_id != 0 && in_crash_recovery) {
if (trx_sys_sys_space(space_id)) {
/* The system tablespace always exists. */
} else if (in_crash_recovery) {
/* Check that the tablespace (the .ibd file) really
exists; print a warning to the .err log if not */
exists; print a warning to the .err log if not.
Do not print warnings for temporary tables. */
ibool is_temp;
fil_space_for_table_exists_in_mem(space_id, name,
FALSE, TRUE, TRUE);
}
field = rec_get_nth_field_old(rec, 4, &len);
if (0x80000000UL & mach_read_from_4(field)) {
/* ROW_FORMAT=COMPACT: read the is_temp
flag from SYS_TABLES.MIX_LEN. */
field = rec_get_nth_field_old(rec, 7, &len);
is_temp = mach_read_from_4(field)
& DICT_TF2_TEMPORARY;
} else {
/* For tables created with old versions
of InnoDB, SYS_TABLES.MIX_LEN may contain
garbage. Such tables would always be
in ROW_FORMAT=REDUNDANT. Pretend that
all such tables are non-temporary. That is,
do not suppress error printouts about
temporary tables not being found. */
is_temp = FALSE;
}
if (space_id != 0 && !in_crash_recovery) {
fil_space_for_table_exists_in_mem(
space_id, name, is_temp, TRUE, !is_temp);
} else {
/* It is a normal database startup: create the space
object and check that the .ibd file exists. */
@ -878,7 +898,7 @@ err_exit:
space = mach_read_from_4(field);
/* Check if the tablespace exists and has the right name */
if (space != 0) {
if (!trx_sys_sys_space(space)) {
flags = dict_sys_tables_get_flags(rec);
if (UNIV_UNLIKELY(flags == ULINT_UNDEFINED)) {
@ -894,31 +914,6 @@ err_exit:
(ulong) flags);
goto err_exit;
}
if (fil_space_for_table_exists_in_mem(space, name, FALSE,
FALSE, FALSE)) {
/* Ok; (if we did a crash recovery then the tablespace
can already be in the memory cache) */
} else {
/* In >= 4.1.9, InnoDB scans the data dictionary also
at a normal mysqld startup. It is an error if the
space object does not exist in memory. */
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: error: space object of table %s,\n"
"InnoDB: space id %lu did not exist in memory."
" Retrying an open.\n",
name, (ulong)space);
/* Try to open the tablespace */
if (!fil_open_single_table_tablespace(
TRUE, space, flags, name)) {
/* We failed to find a sensible tablespace
file */
ibd_file_missing = TRUE;
}
}
} else {
flags = 0;
}
@ -928,9 +923,63 @@ err_exit:
field = rec_get_nth_field_old(rec, 4, &len);
n_cols = mach_read_from_4(field);
/* The high-order bit of N_COLS is the "compact format" flag. */
/* The high-order bit of N_COLS is the "compact format" flag.
For tables in that format, MIX_LEN may hold additional flags. */
if (n_cols & 0x80000000UL) {
ulint flags2;
flags |= DICT_TF_COMPACT;
ut_a(name_of_col_is(sys_tables, sys_index, 7, "MIX_LEN"));
field = rec_get_nth_field_old(rec, 7, &len);
flags2 = mach_read_from_4(field);
if (flags2 & (~0 << (DICT_TF2_BITS - DICT_TF2_SHIFT))) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Warning: table ", stderr);
ut_print_filename(stderr, name);
fprintf(stderr, "\n"
"InnoDB: in InnoDB data dictionary"
" has unknown flags %lx.\n",
(ulong) flags2);
flags2 &= ~(~0 << (DICT_TF2_BITS - DICT_TF2_SHIFT));
}
flags |= flags2 << DICT_TF2_SHIFT;
}
/* See if the tablespace is available. */
if (trx_sys_sys_space(space)) {
/* The system tablespace is always available. */
} else if (!fil_space_for_table_exists_in_mem(
space, name,
(flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY,
FALSE, FALSE)) {
if ((flags >> DICT_TF2_SHIFT) & DICT_TF2_TEMPORARY) {
/* Do not bother to retry opening temporary tables. */
ibd_file_missing = TRUE;
} else {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: error: space object of table");
ut_print_filename(stderr, name);
fprintf(stderr, ",\n"
"InnoDB: space id %lu did not exist in memory."
" Retrying an open.\n",
(ulong) space);
/* Try to open the tablespace */
if (!fil_open_single_table_tablespace(
TRUE, space,
flags & ~(~0 << DICT_TF_BITS), name)) {
/* We failed to find a sensible
tablespace file */
ibd_file_missing = TRUE;
}
}
}
table = dict_mem_table_create(name, space, n_cols & ~0x80000000UL,

View file

@ -59,7 +59,7 @@ dict_mem_table_create(
mem_heap_t* heap;
ut_ad(name);
ut_a(!(flags & (~0 << DICT_TF_BITS)));
ut_a(!(flags & (~0 << DICT_TF2_BITS)));
heap = mem_heap_create(DICT_HEAP_SIZE);

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -38,6 +38,7 @@ Created 10/25/1995 Heikki Tuuri
#include "mtr0mtr.h"
#include "mtr0log.h"
#include "dict0dict.h"
#include "page0page.h"
#include "page0zip.h"
#include "trx0trx.h"
#include "trx0sys.h"
@ -673,14 +674,14 @@ fil_node_open_file(
size_bytes = (((ib_int64_t)size_high) << 32)
+ (ib_int64_t)size_low;
#ifdef UNIV_HOTBACKUP
if (space->id == 0) {
if (trx_sys_sys_space(space->id)) {
node->size = (ulint) (size_bytes / UNIV_PAGE_SIZE);
os_file_close(node->handle);
goto add_size;
}
#endif /* UNIV_HOTBACKUP */
ut_a(space->purpose != FIL_LOG);
ut_a(space->id != 0);
ut_a(!trx_sys_sys_space(space->id));
if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
fprintf(stderr,
@ -726,7 +727,7 @@ fil_node_open_file(
}
if (UNIV_UNLIKELY(space_id == ULINT_UNDEFINED
|| space_id == 0)) {
|| trx_sys_sys_space(space_id))) {
fprintf(stderr,
"InnoDB: Error: tablespace id %lu"
" in file %s is not sensible\n",
@ -788,7 +789,7 @@ add_size:
system->n_open++;
if (space->purpose == FIL_TABLESPACE && space->id != 0) {
if (space->purpose == FIL_TABLESPACE && !trx_sys_sys_space(space->id)) {
/* Put the node to the LRU list */
UT_LIST_ADD_FIRST(LRU, system->LRU, node);
}
@ -821,7 +822,7 @@ fil_node_close_file(
ut_a(system->n_open > 0);
system->n_open--;
if (node->space->purpose == FIL_TABLESPACE && node->space->id != 0) {
if (node->space->purpose == FIL_TABLESPACE && !trx_sys_sys_space(node->space->id)) {
ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
/* The node is in the LRU list, remove it */
@ -907,7 +908,7 @@ fil_mutex_enter_and_prepare_for_io(
retry:
mutex_enter(&fil_system->mutex);
if (space_id == 0 || space_id >= SRV_LOG_SPACE_FIRST_ID) {
if (trx_sys_sys_space(space_id) || space_id >= SRV_LOG_SPACE_FIRST_ID) {
/* We keep log files and system tablespace files always open;
this is important in preventing deadlocks in this module, as
a page read completion often performs another read from the
@ -1102,10 +1103,13 @@ fil_space_create(
fil_space_t* space;
/* The tablespace flags (FSP_SPACE_FLAGS) should be 0 for
ROW_FORMAT=COMPACT (table->flags == DICT_TF_COMPACT) and
ROW_FORMAT=COMPACT
((table->flags & ~(~0 << DICT_TF_BITS)) == DICT_TF_COMPACT) and
ROW_FORMAT=REDUNDANT (table->flags == 0). For any other
format, the tablespace flags should equal table->flags. */
format, the tablespace flags should equal
(table->flags & ~(~0 << DICT_TF_BITS)). */
ut_a(flags != DICT_TF_COMPACT);
ut_a(!(flags & (~0UL << DICT_TF_BITS)));
try_again:
/*printf(
@ -1134,7 +1138,7 @@ try_again:
" tablespace memory cache!\n",
(ulong) space->id);
if (id == 0 || purpose != FIL_TABLESPACE) {
if (trx_sys_sys_space(id) || purpose != FIL_TABLESPACE) {
mutex_exit(&fil_system->mutex);
@ -1528,7 +1532,7 @@ fil_init(
fil_system->max_n_open = max_n_open;
fil_system->modification_counter = 0;
fil_system->max_assigned_id = 0;
fil_system->max_assigned_id = TRX_SYS_SPACE_MAX;
fil_system->tablespace_version = 0;
@ -1555,7 +1559,7 @@ fil_open_log_and_system_tablespace_files(void)
space = UT_LIST_GET_FIRST(fil_system->space_list);
while (space != NULL) {
if (space->purpose != FIL_TABLESPACE || space->id == 0) {
if (space->purpose != FIL_TABLESPACE || trx_sys_sys_space(space->id)) {
node = UT_LIST_GET_FIRST(space->chain);
while (node != NULL) {
@ -2589,10 +2593,13 @@ fil_create_new_single_table_tablespace(
ut_a(size >= FIL_IBD_FILE_INITIAL_SIZE);
/* The tablespace flags (FSP_SPACE_FLAGS) should be 0 for
ROW_FORMAT=COMPACT (table->flags == DICT_TF_COMPACT) and
ROW_FORMAT=COMPACT
((table->flags & ~(~0 << DICT_TF_BITS)) == DICT_TF_COMPACT) and
ROW_FORMAT=REDUNDANT (table->flags == 0). For any other
format, the tablespace flags should equal table->flags. */
format, the tablespace flags should equal
(table->flags & ~(~0 << DICT_TF_BITS)). */
ut_a(flags != DICT_TF_COMPACT);
ut_a(!(flags & (~0UL << DICT_TF_BITS)));
path = fil_make_ibd_name(tablename, is_temp);
@ -2793,6 +2800,7 @@ fil_reset_too_high_lsns(
ib_int64_t offset;
ulint zip_size;
ibool success;
page_zip_des_t page_zip;
filepath = fil_make_ibd_name(name, FALSE);
@ -2840,6 +2848,12 @@ fil_reset_too_high_lsns(
space_id = fsp_header_get_space_id(page);
zip_size = fsp_header_get_zip_size(page);
page_zip_des_init(&page_zip);
page_zip_set_size(&page_zip, zip_size);
if (zip_size) {
page_zip.data = page + UNIV_PAGE_SIZE;
}
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Flush lsn in the tablespace file %lu"
@ -2874,20 +2888,23 @@ fil_reset_too_high_lsns(
/* We have to reset the lsn */
if (zip_size) {
memcpy(page + UNIV_PAGE_SIZE, page, zip_size);
memcpy(page_zip.data, page, zip_size);
buf_flush_init_for_writing(
page, page + UNIV_PAGE_SIZE,
current_lsn);
page, &page_zip, current_lsn);
success = os_file_write(
filepath, file, page_zip.data,
(ulint) offset & 0xFFFFFFFFUL,
(ulint) (offset >> 32), zip_size);
} else {
buf_flush_init_for_writing(
page, NULL, current_lsn);
success = os_file_write(
filepath, file, page,
(ulint)(offset & 0xFFFFFFFFUL),
(ulint)(offset >> 32),
UNIV_PAGE_SIZE);
}
success = os_file_write(filepath, file, page,
(ulint)(offset & 0xFFFFFFFFUL),
(ulint)(offset >> 32),
zip_size
? zip_size
: UNIV_PAGE_SIZE);
if (!success) {
goto func_exit;
@ -2963,10 +2980,13 @@ fil_open_single_table_tablespace(
filepath = fil_make_ibd_name(name, FALSE);
/* The tablespace flags (FSP_SPACE_FLAGS) should be 0 for
ROW_FORMAT=COMPACT (table->flags == DICT_TF_COMPACT) and
ROW_FORMAT=COMPACT
((table->flags & ~(~0 << DICT_TF_BITS)) == DICT_TF_COMPACT) and
ROW_FORMAT=REDUNDANT (table->flags == 0). For any other
format, the tablespace flags should equal table->flags. */
format, the tablespace flags should equal
(table->flags & ~(~0 << DICT_TF_BITS)). */
ut_a(flags != DICT_TF_COMPACT);
ut_a(!(flags & (~0UL << DICT_TF_BITS)));
file = os_file_create_simple_no_error_handling(
filepath, OS_FILE_OPEN, OS_FILE_READ_WRITE, &success);
@ -3016,7 +3036,8 @@ fil_open_single_table_tablespace(
space_id = fsp_header_get_space_id(page);
space_flags = fsp_header_get_flags(page);
if (srv_expand_import && (space_id != id || space_flags != flags)) {
if (srv_expand_import
&& (space_id != id || space_flags != (flags & ~(~0 << DICT_TF_BITS)))) {
dulint old_id[31];
dulint new_id[31];
ulint root_page[31];
@ -3357,7 +3378,8 @@ skip_write:
ut_free(buf2);
if (UNIV_UNLIKELY(space_id != id || space_flags != flags)) {
if (UNIV_UNLIKELY(space_id != id
|| space_flags != (flags & ~(~0 << DICT_TF_BITS)))) {
ut_print_timestamp(stderr);
fputs(" InnoDB: Error: tablespace id and flags in file ",
@ -3596,7 +3618,7 @@ fil_load_single_table_tablespace(
}
#ifndef UNIV_HOTBACKUP
if (space_id == ULINT_UNDEFINED || space_id == 0) {
if (space_id == ULINT_UNDEFINED || trx_sys_sys_space(space_id)) {
fprintf(stderr,
"InnoDB: Error: tablespace id %lu in file %s"
" is not sensible\n",
@ -3605,7 +3627,7 @@ fil_load_single_table_tablespace(
goto func_exit;
}
#else
if (space_id == ULINT_UNDEFINED || space_id == 0) {
if (space_id == ULINT_UNDEFINED || trx_sys_sys_space(space_id)) {
char* new_path;
fprintf(stderr,
@ -3884,7 +3906,7 @@ fil_print_orphaned_tablespaces(void)
space = UT_LIST_GET_FIRST(fil_system->space_list);
while (space) {
if (space->purpose == FIL_TABLESPACE && space->id != 0
if (space->purpose == FIL_TABLESPACE && !trx_sys_sys_space(space->id)
&& !space->mark) {
fputs("InnoDB: Warning: tablespace ", stderr);
ut_print_filename(stderr, space->name);
@ -4459,7 +4481,7 @@ fil_node_prepare_for_io(
}
if (node->n_pending == 0 && space->purpose == FIL_TABLESPACE
&& space->id != 0) {
&& !trx_sys_sys_space(space->id)) {
/* The node is in the LRU list, remove it */
ut_a(UT_LIST_GET_LEN(system->LRU) > 0);
@ -4505,7 +4527,7 @@ fil_node_complete_io(
}
if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE
&& node->space->id != 0) {
&& !trx_sys_sys_space(node->space->id)) {
/* The node must be put back to the LRU list */
UT_LIST_ADD_FIRST(LRU, system->LRU, node);
}
@ -5136,7 +5158,7 @@ fil_validate(void)
ut_a(fil_node->n_pending == 0);
ut_a(fil_node->open);
ut_a(fil_node->space->purpose == FIL_TABLESPACE);
ut_a(fil_node->space->id != 0);
ut_a(!trx_sys_sys_space(fil_node->space->id));
fil_node = UT_LIST_GET_NEXT(LRU, fil_node);
}
@ -5218,8 +5240,10 @@ void
fil_close(void)
/*===========*/
{
#ifndef UNIV_HOTBACKUP
/* The mutex should already have been freed. */
ut_ad(fil_system->mutex.magic_n == 0);
#endif /* !UNIV_HOTBACKUP */
hash_table_free(fil_system->spaces);

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -48,7 +48,7 @@ Created 11/29/1995 Heikki Tuuri
# include "log0log.h"
#endif /* UNIV_HOTBACKUP */
#include "dict0mem.h"
#include "trx0sys.h"
#define FSP_HEADER_OFFSET FIL_PAGE_DATA /* Offset of the space header
within a file page */
@ -392,11 +392,11 @@ UNIV_INLINE
ibool
xdes_get_bit(
/*=========*/
xdes_t* descr, /*!< in: descriptor */
ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */
ulint offset, /*!< in: page offset within extent:
0 ... FSP_EXTENT_SIZE - 1 */
mtr_t* mtr) /*!< in: mtr */
const xdes_t* descr, /*!< in: descriptor */
ulint bit, /*!< in: XDES_FREE_BIT or XDES_CLEAN_BIT */
ulint offset, /*!< in: page offset within extent:
0 ... FSP_EXTENT_SIZE - 1 */
mtr_t* mtr) /*!< in: mtr */
{
ulint index;
ulint byte_index;
@ -533,8 +533,8 @@ UNIV_INLINE
ulint
xdes_get_n_used(
/*============*/
xdes_t* descr, /*!< in: descriptor */
mtr_t* mtr) /*!< in: mtr */
const xdes_t* descr, /*!< in: descriptor */
mtr_t* mtr) /*!< in: mtr */
{
ulint i;
ulint count = 0;
@ -557,8 +557,8 @@ UNIV_INLINE
ibool
xdes_is_free(
/*=========*/
xdes_t* descr, /*!< in: descriptor */
mtr_t* mtr) /*!< in: mtr */
const xdes_t* descr, /*!< in: descriptor */
mtr_t* mtr) /*!< in: mtr */
{
if (0 == xdes_get_n_used(descr, mtr)) {
@ -575,8 +575,8 @@ UNIV_INLINE
ibool
xdes_is_full(
/*=========*/
xdes_t* descr, /*!< in: descriptor */
mtr_t* mtr) /*!< in: mtr */
const xdes_t* descr, /*!< in: descriptor */
mtr_t* mtr) /*!< in: mtr */
{
if (FSP_EXTENT_SIZE == xdes_get_n_used(descr, mtr)) {
@ -592,7 +592,7 @@ UNIV_INLINE
void
xdes_set_state(
/*===========*/
xdes_t* descr, /*!< in: descriptor */
xdes_t* descr, /*!< in/out: descriptor */
ulint state, /*!< in: state to set */
mtr_t* mtr) /*!< in: mtr handle */
{
@ -611,8 +611,8 @@ UNIV_INLINE
ulint
xdes_get_state(
/*===========*/
xdes_t* descr, /*!< in: descriptor */
mtr_t* mtr) /*!< in: mtr handle */
const xdes_t* descr, /*!< in: descriptor */
mtr_t* mtr) /*!< in: mtr handle */
{
ulint state;
@ -712,7 +712,7 @@ UNIV_INLINE
xdes_t*
xdes_get_descriptor_with_space_hdr(
/*===============================*/
fsp_header_t* sp_header,/*!< in: space header, x-latched */
fsp_header_t* sp_header,/*!< in/out: space header, x-latched */
ulint space, /*!< in: space id */
ulint offset, /*!< in: page offset;
if equal to the free limit,
@ -882,9 +882,7 @@ fsp_init_file_page_low(
return;
}
#ifdef UNIV_BASIC_LOG_DEBUG
memset(page, 0xff, UNIV_PAGE_SIZE);
#endif
UNIV_MEM_INVALID(page, UNIV_PAGE_SIZE);
mach_write_to_4(page + FIL_PAGE_OFFSET, buf_block_get_page_no(block));
memset(page + FIL_PAGE_LSN, 0, 8);
mach_write_to_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID,
@ -1017,10 +1015,10 @@ fsp_header_init(
flst_init(header + FSP_SEG_INODES_FREE, mtr);
mlog_write_dulint(header + FSP_SEG_ID, ut_dulint_create(0, 1), mtr);
if (space == 0) {
if (space == TRX_SYS_SPACE || space == TRX_DOUBLEWRITE_SPACE) {
fsp_fill_free_list(FALSE, space, header, mtr);
btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,
0, 0, ut_dulint_add(DICT_IBUF_ID_MIN, space),
space, 0, ut_dulint_add(DICT_IBUF_ID_MIN, space),
dict_ind_redundant, mtr);
} else {
fsp_fill_free_list(TRUE, space, header, mtr);
@ -1355,7 +1353,7 @@ fsp_fill_free_list(
descriptor page and ibuf bitmap page;
then we do not allocate more extents */
ulint space, /*!< in: space */
fsp_header_t* header, /*!< in: space header */
fsp_header_t* header, /*!< in/out: space header */
mtr_t* mtr) /*!< in: mtr */
{
ulint limit;

View file

@ -101,6 +101,8 @@ ha_clear(
ulint i;
ulint n;
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EXCLUSIVE));
#endif /* UNIV_SYNC_DEBUG */
@ -146,7 +148,9 @@ ha_insert_for_fold_func(
ha_node_t* prev_node;
ulint hash;
ut_ad(table && data);
ut_ad(data);
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(block->frame == page_align(data));
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
@ -237,6 +241,8 @@ ha_delete_hash_node(
hash_table_t* table, /*!< in: hash table */
ha_node_t* del_node) /*!< in: node to be deleted */
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
# ifndef UNIV_HOTBACKUP
if (table->adaptive) {
@ -267,6 +273,8 @@ ha_search_and_update_if_found_func(
{
ha_node_t* node;
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ASSERT_HASH_MUTEX_OWN(table, fold);
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
ut_a(new_block->frame == page_align(new_data));
@ -304,6 +312,8 @@ ha_remove_all_nodes_to_page(
{
ha_node_t* node;
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ASSERT_HASH_MUTEX_OWN(table, fold);
node = ha_chain_get_first(table, fold);
@ -353,6 +363,8 @@ ha_validate(
ibool ok = TRUE;
ulint i;
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ut_a(start_index <= end_index);
ut_a(start_index < hash_get_n_cells(table));
ut_a(end_index < hash_get_n_cells(table));
@ -404,6 +416,8 @@ builds, see http://bugs.mysql.com/36941 */
#endif /* PRINT_USED_CELLS */
ulint n_bufs;
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
#ifdef PRINT_USED_CELLS
for (i = 0; i < hash_get_n_cells(table); i++) {

View file

@ -119,7 +119,7 @@ hash_create(
table->heaps = NULL;
#endif /* !UNIV_HOTBACKUP */
table->heap = NULL;
table->magic_n = HASH_TABLE_MAGIC_N;
ut_d(table->magic_n = HASH_TABLE_MAGIC_N);
/* Initialize the cell array */
hash_table_clear(table);
@ -135,6 +135,8 @@ hash_table_free(
/*============*/
hash_table_t* table) /*!< in, own: hash table */
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
#ifndef UNIV_HOTBACKUP
ut_a(table->mutexes == NULL);
#endif /* !UNIV_HOTBACKUP */
@ -160,6 +162,8 @@ hash_create_mutexes_func(
{
ulint i;
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ut_a(n_mutexes > 0);
ut_a(ut_is_2pow(n_mutexes));

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2000, 2009, MySQL AB & Innobase Oy. All Rights Reserved.
Copyright (c) 2000, 2010, MySQL AB & Innobase Oy. All Rights Reserved.
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 the Free Software
@ -27,16 +27,32 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#pragma interface /* gcc class implementation */
#endif
/* Structure defines translation table between mysql index and innodb
index structures */
typedef struct innodb_idx_translate_struct {
ulint index_count; /*!< number of valid index entries
in the index_mapping array */
ulint array_size; /*!< array size of index_mapping */
dict_index_t** index_mapping; /*!< index pointer array directly
maps to index in Innodb from MySQL
array index */
} innodb_idx_translate_t;
/** InnoDB table share */
typedef struct st_innobase_share {
THR_LOCK lock; /*!< MySQL lock protecting
this structure */
const char* table_name; /*!< InnoDB table name */
uint use_count; /*!< reference count,
incremented in get_share()
and decremented in free_share() */
void* table_name_hash;/*!< hash table chain node */
dict_table_t* ib_table;
THR_LOCK lock; /*!< MySQL lock protecting
this structure */
const char* table_name; /*!< InnoDB table name */
uint use_count; /*!< reference count,
incremented in get_share()
and decremented in
free_share() */
void* table_name_hash;/*!< hash table chain node */
innodb_idx_translate_t idx_trans_tbl; /*!< index translation
table between MySQL and
Innodb */
dict_table_t* ib_table;
} INNOBASE_SHARE;
@ -92,9 +108,8 @@ class ha_innobase: public handler
ulint innobase_reset_autoinc(ulonglong auto_inc);
ulint innobase_get_autoinc(ulonglong* value);
ulint innobase_update_autoinc(ulonglong auto_inc);
ulint innobase_initialize_autoinc();
void innobase_initialize_autoinc();
dict_index_t* innobase_get_index(uint keynr);
ulonglong innobase_get_int_col_max_value(const Field* field);
/* Init values for the class: */
public:

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2005, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 2005, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -229,9 +229,11 @@ static
int
innobase_check_index_keys(
/*======================*/
const KEY* key_info, /*!< in: Indexes to be created */
ulint num_of_keys) /*!< in: Number of indexes to
be created */
const KEY* key_info, /*!< in: Indexes to be
created */
ulint num_of_keys, /*!< in: Number of
indexes to be created */
const dict_table_t* table) /*!< in: Existing indexes */
{
ulint key_num;
@ -248,9 +250,22 @@ innobase_check_index_keys(
const KEY& key2 = key_info[i];
if (0 == strcmp(key.name, key2.name)) {
sql_print_error("InnoDB: key name `%s` appears"
" twice in CREATE INDEX\n",
key.name);
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
key.name);
return(ER_WRONG_NAME_FOR_INDEX);
}
}
/* Check that the same index name does not already exist. */
for (const dict_index_t* index
= dict_table_get_first_index(table);
index; index = dict_table_get_next_index(index)) {
if (0 == strcmp(key.name, index->name)) {
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
key.name);
return(ER_WRONG_NAME_FOR_INDEX);
}
@ -258,7 +273,7 @@ innobase_check_index_keys(
/* Check that MySQL does not try to create a column
prefix index field on an inappropriate data type and
that the same colum does not appear twice in the index. */
that the same column does not appear twice in the index. */
for (ulint i = 0; i < key.key_parts; i++) {
const KEY_PART_INFO& key_part1
@ -289,14 +304,8 @@ innobase_check_index_keys(
}
}
sql_print_error("InnoDB: MySQL is trying to"
" create a column prefix"
" index field on an"
" inappropriate data type."
" column `%s`,"
" index `%s`.\n",
field->field_name,
key.name);
my_error(ER_WRONG_KEY_COLUMN, MYF(0),
field->field_name);
return(ER_WRONG_KEY_COLUMN);
}
@ -309,11 +318,8 @@ innobase_check_index_keys(
continue;
}
sql_print_error("InnoDB: column `%s`"
" is not allowed to occur"
" twice in index `%s`.\n",
key_part1.field->field_name,
key.name);
my_error(ER_WRONG_KEY_COLUMN, MYF(0),
key_part1.field->field_name);
return(ER_WRONG_KEY_COLUMN);
}
}
@ -522,12 +528,14 @@ innobase_create_key_def(
key_info->name, "PRIMARY");
/* If there is a UNIQUE INDEX consisting entirely of NOT NULL
columns, MySQL will treat it as a PRIMARY KEY unless the
table already has one. */
columns and if the index does not contain column prefix(es)
(only prefix/part of the column is indexed), MySQL will treat the
index as a PRIMARY KEY unless the table already has one. */
if (!new_primary && (key_info->flags & HA_NOSAME)
&& (!(key_info->flags & HA_KEY_HAS_PART_KEY_SEG))
&& row_table_got_default_clust_index(table)) {
uint key_part = key_info->key_parts;
uint key_part = key_info->key_parts;
new_primary = TRUE;
@ -656,12 +664,18 @@ ha_innobase::add_index(
innodb_table = indexed_table
= dict_table_get(prebuilt->table->name, FALSE);
if (UNIV_UNLIKELY(!innodb_table)) {
error = HA_ERR_NO_SUCH_TABLE;
goto err_exit;
}
/* Check if the index name is reserved. */
if (innobase_index_name_is_reserved(trx, key_info, num_of_keys)) {
error = -1;
} else {
/* Check that index keys are sensible */
error = innobase_check_index_keys(key_info, num_of_keys);
error = innobase_check_index_keys(key_info, num_of_keys,
innodb_table);
}
if (UNIV_UNLIKELY(error)) {
@ -708,6 +722,8 @@ err_exit:
row_mysql_lock_data_dictionary(trx);
dict_locked = TRUE;
ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
/* If a new primary key is defined for the table we need
to drop the original table and rebuild all indexes. */
@ -740,6 +756,8 @@ err_exit:
user_thd);
}
ut_d(dict_table_check_for_dup_indexes(innodb_table,
FALSE));
row_mysql_unlock_data_dictionary(trx);
goto err_exit;
}
@ -764,6 +782,10 @@ err_exit:
ut_ad(error == DB_SUCCESS);
/* We will need to rebuild index translation table. Set
valid index entry count in the translation table to zero */
share->idx_trans_tbl.index_count = 0;
/* Commit the data dictionary transaction in order to release
the table locks on the system tables. This means that if
MySQL crashes while creating a new primary key inside
@ -799,18 +821,6 @@ err_exit:
index, num_of_idx, table);
error_handling:
#ifdef UNIV_DEBUG
/* TODO: At the moment we can't handle the following statement
in our debugging code below:
alter table t drop index b, add index (b);
The fix will have to parse the SQL and note that the index
being added has the same name as the one being dropped and
ignore that in the dup index check.*/
//dict_table_check_for_dup_indexes(prebuilt->table);
#endif
/* After an error, remove all those index definitions from the
dictionary which were defined. */
@ -822,6 +832,8 @@ error_handling:
row_mysql_lock_data_dictionary(trx);
dict_locked = TRUE;
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, TRUE));
if (!new_primary) {
error = row_merge_rename_indexes(trx, indexed_table);
@ -909,6 +921,7 @@ convert_error:
}
if (dict_locked) {
ut_d(dict_table_check_for_dup_indexes(innodb_table, FALSE));
row_mysql_unlock_data_dictionary(trx);
}
@ -951,6 +964,7 @@ ha_innobase::prepare_drop_index(
/* Test and mark all the indexes to be dropped */
row_mysql_lock_data_dictionary(trx);
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
/* Check that none of the indexes have previously been flagged
for deletion. */
@ -1116,6 +1130,7 @@ func_exit:
} while (index);
}
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
row_mysql_unlock_data_dictionary(trx);
DBUG_RETURN(err);
@ -1162,6 +1177,7 @@ ha_innobase::final_drop_index(
prebuilt->table->flags, user_thd);
row_mysql_lock_data_dictionary(trx);
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
if (UNIV_UNLIKELY(err)) {
@ -1198,11 +1214,12 @@ ha_innobase::final_drop_index(
ut_a(!index->to_be_dropped);
}
#ifdef UNIV_DEBUG
dict_table_check_for_dup_indexes(prebuilt->table);
#endif
/* We will need to rebuild index translation table. Set
valid index entry count in the translation table to zero */
share->idx_trans_tbl.index_count = 0;
func_exit:
ut_d(dict_table_check_for_dup_indexes(prebuilt->table, FALSE));
trx_commit_for_mysql(trx);
trx_commit_for_mysql(prebuilt->trx);
row_mysql_unlock_data_dictionary(trx);

View file

@ -2900,6 +2900,9 @@ i_s_innodb_index_stats_fill(
i_s_table->field[3]->store(index->n_uniq);
row_per_keys[0] = '\0';
/* It is remained optimistic operation still for now */
//dict_index_stat_mutex_enter(index);
if (index->stat_n_diff_key_vals) {
for (i = 1; i <= index->n_uniq; i++) {
ib_int64_t rec_per_key;
@ -2913,6 +2916,8 @@ i_s_innodb_index_stats_fill(
strncat(row_per_keys, buff, 256 - strlen(row_per_keys));
}
}
//dict_index_stat_mutex_exit(index);
field_store_string(i_s_table->field[4], row_per_keys);
i_s_table->field[5]->store(index->stat_index_size);
@ -3169,6 +3174,14 @@ UNIV_INTERN struct st_mysql_plugin i_s_innodb_admin_command =
static ST_FIELD_INFO i_s_innodb_sys_tables_info[] =
{
{STRUCT_FLD(field_name, "SCHEMA"),
STRUCT_FLD(field_length, NAME_LEN),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
STRUCT_FLD(value, 0),
STRUCT_FLD(field_flags, 0),
STRUCT_FLD(old_name, ""),
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
{STRUCT_FLD(field_name, "NAME"),
STRUCT_FLD(field_length, NAME_LEN),
STRUCT_FLD(field_type, MYSQL_TYPE_STRING),
@ -3325,6 +3338,54 @@ copy_string_field(
return status;
}
static
int
copy_name_fields(
/*=============*/
TABLE* table,
int table_field_1,
const rec_t* rec,
int rec_field)
{
int status;
const byte* data;
ulint len;
data = rec_get_nth_field_old(rec, rec_field, &len);
if (len == UNIV_SQL_NULL) {
table->field[table_field_1]->set_null();
table->field[table_field_1 + 1]->set_null();
status = 0; /* success */
} else {
char buf[NAME_LEN * 2 + 2];
char* ptr;
if (len > NAME_LEN * 2 + 1) {
table->field[table_field_1]->set_null();
status = field_store_string(table->field[table_field_1 + 1],
"###TOO LONG NAME###");
goto end_func;
}
strncpy(buf, (char*)data, len);
buf[len] = '\0';
ptr = strchr(buf, '/');
if (ptr) {
*ptr = '\0';
++ptr;
status = field_store_string(table->field[table_field_1], buf);
status |= field_store_string(table->field[table_field_1 + 1], ptr);
} else {
table->field[table_field_1]->set_null();
status = field_store_string(table->field[table_field_1 + 1], buf);
}
}
end_func:
return status;
}
static
int
copy_int_field(
@ -3395,49 +3456,49 @@ copy_sys_tables_rec(
/* NAME */
field = dict_index_get_nth_col_pos(index, 0);
status = copy_string_field(table, 0, rec, field);
status = copy_name_fields(table, 0, rec, field);
if (status) {
return status;
}
/* ID */
field = dict_index_get_nth_col_pos(index, 1);
status = copy_id_field(table, 1, rec, field);
status = copy_id_field(table, 2, rec, field);
if (status) {
return status;
}
/* N_COLS */
field = dict_index_get_nth_col_pos(index, 2);
status = copy_int_field(table, 2, rec, field);
status = copy_int_field(table, 3, rec, field);
if (status) {
return status;
}
/* TYPE */
field = dict_index_get_nth_col_pos(index, 3);
status = copy_int_field(table, 3, rec, field);
status = copy_int_field(table, 4, rec, field);
if (status) {
return status;
}
/* MIX_ID */
field = dict_index_get_nth_col_pos(index, 4);
status = copy_id_field(table, 4, rec, field);
status = copy_id_field(table, 5, rec, field);
if (status) {
return status;
}
/* MIX_LEN */
field = dict_index_get_nth_col_pos(index, 5);
status = copy_int_field(table, 5, rec, field);
status = copy_int_field(table, 6, rec, field);
if (status) {
return status;
}
/* CLUSTER_NAME */
field = dict_index_get_nth_col_pos(index, 6);
status = copy_string_field(table, 6, rec, field);
status = copy_string_field(table, 7, rec, field);
if (status) {
return status;
}
/* SPACE */
field = dict_index_get_nth_col_pos(index, 7);
status = copy_int_field(table, 7, rec, field);
status = copy_int_field(table, 8, rec, field);
if (status) {
return status;
}

View file

@ -41,8 +41,8 @@ struct innodb_enhancement {
{"innodb_admin_command_base","XtraDB specific command interface through i_s","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_show_lock_name","Show mutex/lock name instead of crated file/line","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_extend_slow","Extended statistics in slow.log","It is InnoDB-part only. It needs to patch also to mysqld.","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_relax_table_creation","Relax limitation of column size at table creation as builtin InnoDB.","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_lru_dump_restore","Dump and restore command for content of buffer pool","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_separate_doublewrite","Add option 'innodb_doublewrite_file' to separate doublewrite dedicated tablespace","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_pass_corrupt_table","Treat tables as corrupt instead of crash, when meet corrupt blocks","","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_fast_checksum","Using the checksum on 32bit-unit calculation","incompatible for unpatched ver.","http://www.percona.com/docs/wiki/percona-xtradb"},
{"innodb_files_extend","allow >4GB transaction log files, and can vary universal page size of datafiles","incompatible for unpatched ver.","http://www.percona.com/docs/wiki/percona-xtradb"},

View file

@ -733,24 +733,41 @@ page containing the descriptor bits for the file page; the bitmap page
is x-latched */
static
page_t*
ibuf_bitmap_get_map_page(
/*=====================*/
ulint space, /*!< in: space id of the file page */
ulint page_no,/*!< in: page number of the file page */
ulint zip_size,/*!< in: compressed page size in bytes;
0 for uncompressed pages */
mtr_t* mtr) /*!< in: mtr */
ibuf_bitmap_get_map_page_func(
/*==========================*/
ulint space, /*!< in: space id of the file page */
ulint page_no,/*!< in: page number of the file page */
ulint zip_size,/*!< in: compressed page size in bytes;
0 for uncompressed pages */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
{
buf_block_t* block;
block = buf_page_get(space, zip_size,
ibuf_bitmap_page_no_calc(zip_size, page_no),
RW_X_LATCH, mtr);
block = buf_page_get_gen(space, zip_size,
ibuf_bitmap_page_no_calc(zip_size, page_no),
RW_X_LATCH, NULL, BUF_GET,
file, line, mtr);
buf_block_dbg_add_level(block, SYNC_IBUF_BITMAP);
return(buf_block_get_frame(block));
}
/********************************************************************//**
Gets the ibuf bitmap page where the bits describing a given file page are
stored.
@return bitmap page where the file page is mapped, that is, the bitmap
page containing the descriptor bits for the file page; the bitmap page
is x-latched
@param space in: space id of the file page
@param page_no in: page number of the file page
@param zip_size in: compressed page size in bytes; 0 for uncompressed pages
@param mtr in: mini-transaction */
#define ibuf_bitmap_get_map_page(space, page_no, zip_size, mtr) \
ibuf_bitmap_get_map_page_func(space, page_no, zip_size, \
__FILE__, __LINE__, mtr)
/************************************************************************//**
Sets the free bits of the page in the ibuf bitmap. This is done in a separate
mini-transaction, hence this operation does not restrict further work to only

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -193,6 +193,10 @@ btr_leaf_page_release(
mtr_t* mtr); /*!< in: mtr */
/**************************************************************//**
Gets the child node file address in a node pointer.
NOTE: the offsets array must contain all offsets for the record since
we read the last field according to offsets and assume that it contains
the child page number. In other words offsets must have been retrieved
with rec_get_offsets(n_fields=ULINT_UNDEFINED).
@return child node address */
UNIV_INLINE
ulint
@ -317,12 +321,16 @@ Inserts a data tuple to a tree on a non-leaf level. It is assumed
that mtr holds an x-latch on the tree. */
UNIV_INTERN
void
btr_insert_on_non_leaf_level(
/*=========================*/
btr_insert_on_non_leaf_level_func(
/*==============================*/
dict_index_t* index, /*!< in: index */
ulint level, /*!< in: level, must be > 0 */
dtuple_t* tuple, /*!< in: the record to be inserted */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mtr */
# define btr_insert_on_non_leaf_level(i,l,t,m) \
btr_insert_on_non_leaf_level_func(i,l,t,__FILE__,__LINE__,m)
#endif /* !UNIV_HOTBACKUP */
/****************************************************************//**
Sets a record as the predefined minimum record. */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -257,6 +257,10 @@ btr_page_set_prev(
/**************************************************************//**
Gets the child node file address in a node pointer.
NOTE: the offsets array must contain all offsets for the record since
we read the last field according to offsets and assume that it contains
the child page number. In other words offsets must have been retrieved
with rec_get_offsets(n_fields=ULINT_UNDEFINED).
@return child node address */
UNIV_INLINE
ulint

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -152,29 +152,39 @@ btr_cur_search_to_nth_level(
ulint has_search_latch,/*!< in: latch mode the caller
currently has on btr_search_latch:
RW_S_LATCH, or 0 */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mtr */
/*****************************************************************//**
Opens a cursor at either end of an index. */
UNIV_INTERN
void
btr_cur_open_at_index_side(
/*=======================*/
btr_cur_open_at_index_side_func(
/*============================*/
ibool from_left, /*!< in: TRUE if open to the low end,
FALSE if to the high end */
dict_index_t* index, /*!< in: index */
ulint latch_mode, /*!< in: latch mode */
btr_cur_t* cursor, /*!< in: cursor */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mtr */
#define btr_cur_open_at_index_side(f,i,l,c,m) \
btr_cur_open_at_index_side_func(f,i,l,c,__FILE__,__LINE__,m)
/**********************************************************************//**
Positions a cursor at a randomly chosen position within a B-tree. */
UNIV_INTERN
void
btr_cur_open_at_rnd_pos(
/*====================*/
btr_cur_open_at_rnd_pos_func(
/*=========================*/
dict_index_t* index, /*!< in: index */
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
btr_cur_t* cursor, /*!< in/out: B-tree cursor */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mtr */
#define btr_cur_open_at_rnd_pos(i,l,c,m) \
btr_cur_open_at_rnd_pos_func(i,l,c,__FILE__,__LINE__,m)
/*************************************************************//**
Tries to perform an insert to a page in an index tree, next to cursor.
It is assumed that mtr holds an x-latch on the page. The operation does

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -82,8 +82,8 @@ Initializes and opens a persistent cursor to an index tree. It should be
closed with btr_pcur_close. */
UNIV_INLINE
void
btr_pcur_open(
/*==========*/
btr_pcur_open_func(
/*===============*/
dict_index_t* index, /*!< in: index */
const dtuple_t* tuple, /*!< in: tuple on which search done */
ulint mode, /*!< in: PAGE_CUR_L, ...;
@ -94,14 +94,18 @@ btr_pcur_open(
record! */
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mtr */
#define btr_pcur_open(i,t,md,l,c,m) \
btr_pcur_open_func(i,t,md,l,c,__FILE__,__LINE__,m)
/**************************************************************//**
Opens an persistent cursor to an index tree without initializing the
cursor. */
UNIV_INLINE
void
btr_pcur_open_with_no_init(
/*=======================*/
btr_pcur_open_with_no_init_func(
/*============================*/
dict_index_t* index, /*!< in: index */
const dtuple_t* tuple, /*!< in: tuple on which search done */
ulint mode, /*!< in: PAGE_CUR_L, ...;
@ -119,7 +123,12 @@ btr_pcur_open_with_no_init(
ulint has_search_latch,/*!< in: latch mode the caller
currently has on btr_search_latch:
RW_S_LATCH, or 0 */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mtr */
#define btr_pcur_open_with_no_init(ix,t,md,l,cur,has,m) \
btr_pcur_open_with_no_init_func(ix,t,md,l,cur,has,__FILE__,__LINE__,m)
/*****************************************************************//**
Opens a persistent cursor at either end of an index. */
UNIV_INLINE
@ -160,8 +169,8 @@ before first in tree. The latching mode must be BTR_SEARCH_LEAF or
BTR_MODIFY_LEAF. */
UNIV_INTERN
void
btr_pcur_open_on_user_rec(
/*======================*/
btr_pcur_open_on_user_rec_func(
/*===========================*/
dict_index_t* index, /*!< in: index */
const dtuple_t* tuple, /*!< in: tuple on which search done */
ulint mode, /*!< in: PAGE_CUR_L, ... */
@ -169,17 +178,25 @@ btr_pcur_open_on_user_rec(
BTR_MODIFY_LEAF */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent
cursor */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mtr */
#define btr_pcur_open_on_user_rec(i,t,md,l,c,m) \
btr_pcur_open_on_user_rec_func(i,t,md,l,c,__FILE__,__LINE__,m)
/**********************************************************************//**
Positions a cursor at a randomly chosen position within a B-tree. */
UNIV_INLINE
void
btr_pcur_open_at_rnd_pos(
/*=====================*/
btr_pcur_open_at_rnd_pos_func(
/*==========================*/
dict_index_t* index, /*!< in: index */
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /*!< in/out: B-tree pcur */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mtr */
#define btr_pcur_open_at_rnd_pos(i,l,c,m) \
btr_pcur_open_at_rnd_pos_func(i,l,c,__FILE__,__LINE__,m)
/**************************************************************//**
Frees the possible old_rec_buf buffer of a persistent cursor and sets the
latch mode of the persistent cursor to BTR_NO_LATCHES. */
@ -218,11 +235,15 @@ record and it can be restored on a user record whose ordering fields
are identical to the ones of the original user record */
UNIV_INTERN
ibool
btr_pcur_restore_position(
/*======================*/
btr_pcur_restore_position_func(
/*===========================*/
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /*!< in: detached persistent cursor */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr); /*!< in: mtr */
#define btr_pcur_restore_position(l,cur,mtr) \
btr_pcur_restore_position_func(l,cur,__FILE__,__LINE__,mtr)
/**************************************************************//**
If the latch mode of the cursor is BTR_LEAF_SEARCH or BTR_LEAF_MODIFY,
releases the page latch and bufferfix reserved by the cursor.
@ -260,20 +281,13 @@ btr_pcur_get_mtr(
/*=============*/
btr_pcur_t* cursor); /*!< in: persistent cursor */
/**************************************************************//**
Commits the pcur mtr and sets the pcur latch mode to BTR_NO_LATCHES,
Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
that is, the cursor becomes detached. If there have been modifications
to the page where pcur is positioned, this can be used instead of
btr_pcur_release_leaf. Function btr_pcur_store_position should be used
before calling this, if restoration of cursor is wanted later. */
UNIV_INLINE
void
btr_pcur_commit(
/*============*/
btr_pcur_t* pcur); /*!< in: persistent cursor */
/**************************************************************//**
Differs from btr_pcur_commit in that we can specify the mtr to commit. */
UNIV_INLINE
void
btr_pcur_commit_specify_mtr(
/*========================*/
btr_pcur_t* pcur, /*!< in: persistent cursor */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -395,30 +395,13 @@ btr_pcur_move_to_next(
}
/**************************************************************//**
Commits the pcur mtr and sets the pcur latch mode to BTR_NO_LATCHES,
Commits the mtr and sets the pcur latch mode to BTR_NO_LATCHES,
that is, the cursor becomes detached. If there have been modifications
to the page where pcur is positioned, this can be used instead of
btr_pcur_release_leaf. Function btr_pcur_store_position should be used
before calling this, if restoration of cursor is wanted later. */
UNIV_INLINE
void
btr_pcur_commit(
/*============*/
btr_pcur_t* pcur) /*!< in: persistent cursor */
{
ut_a(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
pcur->latch_mode = BTR_NO_LATCHES;
mtr_commit(pcur->mtr);
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
}
/**************************************************************//**
Differs from btr_pcur_commit in that we can specify the mtr to commit. */
UNIV_INLINE
void
btr_pcur_commit_specify_mtr(
/*========================*/
btr_pcur_t* pcur, /*!< in: persistent cursor */
@ -483,8 +466,8 @@ Initializes and opens a persistent cursor to an index tree. It should be
closed with btr_pcur_close. */
UNIV_INLINE
void
btr_pcur_open(
/*==========*/
btr_pcur_open_func(
/*===============*/
dict_index_t* index, /*!< in: index */
const dtuple_t* tuple, /*!< in: tuple on which search done */
ulint mode, /*!< in: PAGE_CUR_L, ...;
@ -495,6 +478,8 @@ btr_pcur_open(
record! */
ulint latch_mode,/*!< in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /*!< in: memory buffer for persistent cursor */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
{
btr_cur_t* btr_cursor;
@ -511,7 +496,7 @@ btr_pcur_open(
btr_cursor = btr_pcur_get_btr_cur(cursor);
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
btr_cursor, 0, mtr);
btr_cursor, 0, file, line, mtr);
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
cursor->trx_if_known = NULL;
@ -522,8 +507,8 @@ Opens an persistent cursor to an index tree without initializing the
cursor. */
UNIV_INLINE
void
btr_pcur_open_with_no_init(
/*=======================*/
btr_pcur_open_with_no_init_func(
/*============================*/
dict_index_t* index, /*!< in: index */
const dtuple_t* tuple, /*!< in: tuple on which search done */
ulint mode, /*!< in: PAGE_CUR_L, ...;
@ -541,6 +526,8 @@ btr_pcur_open_with_no_init(
ulint has_search_latch,/*!< in: latch mode the caller
currently has on btr_search_latch:
RW_S_LATCH, or 0 */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
{
btr_cur_t* btr_cursor;
@ -553,7 +540,8 @@ btr_pcur_open_with_no_init(
btr_cursor = btr_pcur_get_btr_cur(cursor);
btr_cur_search_to_nth_level(index, 0, tuple, mode, latch_mode,
btr_cursor, has_search_latch, mtr);
btr_cursor, has_search_latch,
file, line, mtr);
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
@ -600,11 +588,13 @@ btr_pcur_open_at_index_side(
Positions a cursor at a randomly chosen position within a B-tree. */
UNIV_INLINE
void
btr_pcur_open_at_rnd_pos(
/*=====================*/
btr_pcur_open_at_rnd_pos_func(
/*==========================*/
dict_index_t* index, /*!< in: index */
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
btr_pcur_t* cursor, /*!< in/out: B-tree pcur */
const char* file, /*!< in: file name */
ulint line, /*!< in: line where called */
mtr_t* mtr) /*!< in: mtr */
{
/* Initialize the cursor */
@ -614,8 +604,9 @@ btr_pcur_open_at_rnd_pos(
btr_pcur_init(cursor);
btr_cur_open_at_rnd_pos(index, latch_mode,
btr_pcur_get_btr_cur(cursor), mtr);
btr_cur_open_at_rnd_pos_func(index, latch_mode,
btr_pcur_get_btr_cur(cursor),
file, line, mtr);
cursor->pos_state = BTR_PCUR_IS_POSITIONED;
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -33,6 +33,7 @@ Created 11/5/1995 Heikki Tuuri
#include "hash0hash.h"
#include "ut0byte.h"
#include "page0types.h"
#include "ut0rbt.h"
#ifndef UNIV_HOTBACKUP
#include "os0proc.h"
@ -202,20 +203,14 @@ with care. */
#define buf_page_get_with_no_latch(SP, ZS, OF, MTR) buf_page_get_gen(\
SP, ZS, OF, RW_NO_LATCH, NULL,\
BUF_GET_NO_LATCH, __FILE__, __LINE__, MTR)
/**************************************************************//**
NOTE! The following macros should be used instead of
buf_page_optimistic_get_func, to improve debugging. Only values RW_S_LATCH and
RW_X_LATCH are allowed as LA! */
#define buf_page_optimistic_get(LA, BL, MC, MTR) \
buf_page_optimistic_get_func(LA, BL, MC, __FILE__, __LINE__, MTR)
/********************************************************************//**
This is the general function used to get optimistic access to a database
page.
@return TRUE if success */
UNIV_INTERN
ibool
buf_page_optimistic_get_func(
/*=========================*/
buf_page_optimistic_get(
/*====================*/
ulint rw_latch,/*!< in: RW_S_LATCH, RW_X_LATCH */
buf_block_t* block, /*!< in: guessed block */
ib_uint64_t modify_clock,/*!< in: modify clock value if mode is
@ -1205,15 +1200,21 @@ struct buf_block_struct{
rw_lock_t lock; /*!< read-write lock of the buffer
frame */
unsigned lock_hash_val:32;/*!< hashed value of the page address
in the record lock hash table */
unsigned check_index_page_at_flush:1;
in the record lock hash table;
protected by buf_block_t::lock
(or buf_block_t::mutex, buf_pool_mutex
in buf_page_get_gen(),
buf_page_init_for_read()
and buf_page_create()) */
ibool check_index_page_at_flush;
/*!< TRUE if we know that this is
an index page, and want the database
to check its consistency before flush;
note that there may be pages in the
buffer pool which are index pages,
but this flag is not set because
we do not keep track of all pages */
we do not keep track of all pages;
NOT protected by any mutex */
/* @} */
/** @name Optimistic search field */
/* @{ */
@ -1379,6 +1380,19 @@ struct buf_pool_struct{
/*!< this is in the set state
when there is no flush batch
of the given type running */
ib_rbt_t* flush_rbt; /* !< a red-black tree is used
exclusively during recovery to
speed up insertions in the
flush_list. This tree contains
blocks in order of
oldest_modification LSN and is
kept in sync with the
flush_list.
Each member of the tree MUST
also be on the flush_list.
This tree is relevant only in
recovery and is set to NULL
once the recovery is over. */
ulint freed_page_clock;/*!< a sequence number used
to count the number of buffer
blocks removed from the end of

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@ -81,7 +81,7 @@ buf_page_peek_if_too_old(
unsigned access_time = buf_page_is_accessed(bpage);
if (access_time > 0
&& (ut_time_ms() - access_time)
&& ((ib_uint32_t) (ut_time_ms() - access_time))
>= buf_LRU_old_threshold_ms) {
return(TRUE);
}
@ -743,6 +743,12 @@ buf_block_get_lock_hash_val(
/*========================*/
const buf_block_t* block) /*!< in: block */
{
ut_ad(block);
ut_ad(buf_page_in_file(&block->page));
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(((buf_block_t*) block)->lock), RW_LOCK_EXCLUSIVE)
|| rw_lock_own(&(((buf_block_t*) block)->lock), RW_LOCK_SHARED));
#endif /* UNIV_SYNC_DEBUG */
return(block->lock_hash_val);
}

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -40,6 +40,16 @@ buf_flush_remove(
/*=============*/
buf_page_t* bpage); /*!< in: pointer to the block in question */
/********************************************************************//**
Relocates a buffer control block on the flush_list.
Note that it is assumed that the contents of bpage has already been
copied to dpage. */
UNIV_INTERN
void
buf_flush_relocate_on_flush_list(
/*=============================*/
buf_page_t* bpage, /*!< in/out: control block being moved */
buf_page_t* dpage); /*!< in/out: destination block */
/********************************************************************//**
Updates the flush system data structures when a write is completed. */
UNIV_INTERN
void
@ -140,8 +150,8 @@ how much redo the workload is generating and at what rate. */
struct buf_flush_stat_struct
{
ib_uint64_t redo; /**< amount of redo generated. */
ulint n_flushed; /**< number of pages flushed. */
ib_uint64_t redo; /*!< amount of redo generated. */
ulint n_flushed; /*!< number of pages flushed. */
};
/** Statistics for selecting flush rate of dirty pages. */
@ -176,6 +186,22 @@ buf_flush_validate(void);
/*====================*/
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
/******************************************************************//**
Initialize the red-black tree to speed up insertions into the flush_list
during recovery process. Should be called at the start of recovery
process before any page has been read/written. */
UNIV_INTERN
void
buf_flush_init_flush_rbt(void);
/*==========================*/
/******************************************************************//**
Frees up the red-black tree. */
UNIV_INTERN
void
buf_flush_free_flush_rbt(void);
/*==========================*/
/** When buf_flush_free_margin is called, it tries to make this many blocks
available to replacement in the free list and at the end of the LRU list (to
make sure that a read-ahead batch can be read efficiently in a single

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -285,6 +285,10 @@ dtype_new_store_for_order_and_null_size(
#endif
ulint len;
ut_ad(type);
ut_ad(type->mtype >= DATA_VARCHAR);
ut_ad(type->mtype <= DATA_MYSQL);
buf[0] = (byte)(type->mtype & 0xFFUL);
if (type->prtype & DATA_BINARY_TYPE) {

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -137,6 +137,7 @@ clustered index */
#define DICT_SYS_INDEXES_PAGE_NO_FIELD 8
#define DICT_SYS_INDEXES_SPACE_NO_FIELD 7
#define DICT_SYS_INDEXES_TYPE_FIELD 6
#define DICT_SYS_INDEXES_NAME_FIELD 4
/* When a row id which is zero modulo this number (which must be a power of
two) is assigned, the field DICT_HDR_ROW_ID on the dictionary header page is

View file

@ -928,9 +928,10 @@ UNIV_INTERN
void
dict_table_check_for_dup_indexes(
/*=============================*/
const dict_table_t* table); /*!< in: Check for dup indexes
const dict_table_t* table, /*!< in: Check for dup indexes
in this table */
ibool tmp_ok);/*!< in: TRUE=allow temporary
index names */
#endif /* UNIV_DEBUG */
/**********************************************************************//**
Builds a node pointer out of a physical record and a page number.
@ -1060,6 +1061,22 @@ UNIV_INTERN
void
dict_mutex_exit_for_mysql(void);
/*===========================*/
/**********************************************************************//**
Lock the appropriate mutex to protect index->stat_n_diff_key_vals[].
index->id is used to pick the right mutex and it should not change
before dict_index_stat_mutex_exit() is called on this index. */
UNIV_INTERN
void
dict_index_stat_mutex_enter(
/*========================*/
const dict_index_t* index); /*!< in: index */
/**********************************************************************//**
Unlock the appropriate mutex that protects index->stat_n_diff_key_vals[]. */
UNIV_INTERN
void
dict_index_stat_mutex_exit(
/*=======================*/
const dict_index_t* index); /*!< in: index */
/********************************************************************//**
Checks if the database name in two table names is the same.
@return TRUE if same db name */

View file

@ -80,21 +80,39 @@ combination of types */
/** File format */
/* @{ */
#define DICT_TF_FORMAT_SHIFT 5 /* file format */
#define DICT_TF_FORMAT_MASK (127 << DICT_TF_FORMAT_SHIFT)
#define DICT_TF_FORMAT_MASK \
((~(~0 << (DICT_TF_BITS - DICT_TF_FORMAT_SHIFT))) << DICT_TF_FORMAT_SHIFT)
#define DICT_TF_FORMAT_51 0 /*!< InnoDB/MySQL up to 5.1 */
#define DICT_TF_FORMAT_ZIP 1 /*!< InnoDB plugin for 5.1:
compressed tables,
new BLOB treatment */
/** Maximum supported file format */
#define DICT_TF_FORMAT_MAX DICT_TF_FORMAT_ZIP
/* @} */
#define DICT_TF_BITS 6 /*!< number of flag bits */
#if (1 << (DICT_TF_BITS - DICT_TF_FORMAT_SHIFT)) <= DICT_TF_FORMAT_MAX
# error "DICT_TF_BITS is insufficient for DICT_TF_FORMAT_MAX"
#endif
/* @} */
/** @brief Additional table flags.
These flags will be stored in SYS_TABLES.MIX_LEN. All unused flags
will be written as 0. The column may contain garbage for tables
created with old versions of InnoDB that only implemented
ROW_FORMAT=REDUNDANT. */
/* @{ */
#define DICT_TF2_SHIFT DICT_TF_BITS
/*!< Shift value for
table->flags. */
#define DICT_TF2_TEMPORARY 1 /*!< TRUE for tables from
CREATE TEMPORARY TABLE. */
#define DICT_TF2_BITS (DICT_TF2_SHIFT + 1)
/*!< Total number of bits
in table->flags. */
/* @} */
/**********************************************************************//**
Creates a table memory object.
@return own: table object */
@ -374,7 +392,7 @@ struct dict_table_struct{
unsigned space:32;
/*!< space where the clustered index of the
table is placed */
unsigned flags:DICT_TF_BITS;/*!< DICT_TF_COMPACT, ... */
unsigned flags:DICT_TF2_BITS;/*!< DICT_TF_COMPACT, ... */
unsigned ibd_file_missing:1;
/*!< TRUE if this is in a single-table
tablespace and the .ibd file is missing; then

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -110,9 +110,10 @@ extern fil_addr_t fil_addr_null;
contents of this field is valid
for all uncompressed pages. */
#define FIL_PAGE_FILE_FLUSH_LSN 26 /*!< this is only defined for the
first page in a data file: the file
has been flushed to disk at least up
to this lsn */
first page in a system tablespace
data file (ibdata*, not *.ibd):
the file has been flushed to disk
at least up to this lsn */
#define FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID 34 /*!< starting from 4.1.x this
contains the space id of the page */
#define FIL_PAGE_DATA 38 /*!< start of the data on the page */

View file

@ -434,11 +434,12 @@ struct hash_table_struct {
these heaps */
#endif /* !UNIV_HOTBACKUP */
mem_heap_t* heap;
#ifdef UNIV_DEBUG
ulint magic_n;
# define HASH_TABLE_MAGIC_N 76561114
#endif /* UNIV_DEBUG */
};
#define HASH_TABLE_MAGIC_N 76561114
#ifndef UNIV_NONINL
#include "hash0hash.ic"
#endif

View file

@ -35,6 +35,8 @@ hash_get_nth_cell(
hash_table_t* table, /*!< in: hash table */
ulint n) /*!< in: cell index */
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ut_ad(n < table->n_cells);
return(table->array + n);
@ -48,6 +50,8 @@ hash_table_clear(
/*=============*/
hash_table_t* table) /*!< in/out: hash table */
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
memset(table->array, 0x0,
table->n_cells * sizeof(*table->array));
}
@ -61,6 +65,8 @@ hash_get_n_cells(
/*=============*/
hash_table_t* table) /*!< in: table */
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
return(table->n_cells);
}
@ -74,6 +80,8 @@ hash_calc_hash(
ulint fold, /*!< in: folded value */
hash_table_t* table) /*!< in: hash table */
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
return(ut_hash_ulint(fold, table->n_cells));
}
@ -88,6 +96,8 @@ hash_get_mutex_no(
hash_table_t* table, /*!< in: hash table */
ulint fold) /*!< in: fold */
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ut_ad(ut_is_2pow(table->n_mutexes));
return(ut_2pow_remainder(hash_calc_hash(fold, table),
table->n_mutexes));
@ -103,6 +113,8 @@ hash_get_nth_heap(
hash_table_t* table, /*!< in: hash table */
ulint i) /*!< in: index of the heap */
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ut_ad(i < table->n_mutexes);
return(table->heaps[i]);
@ -120,6 +132,9 @@ hash_get_heap(
{
ulint i;
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
if (table->heap) {
return(table->heap);
}
@ -139,6 +154,8 @@ hash_get_nth_mutex(
hash_table_t* table, /*!< in: hash table */
ulint i) /*!< in: index of the mutex */
{
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
ut_ad(i < table->n_mutexes);
return(table->mutexes + i);
@ -156,6 +173,9 @@ hash_get_mutex(
{
ulint i;
ut_ad(table);
ut_ad(table->magic_n == HASH_TABLE_MAGIC_N);
i = hash_get_mutex_no(table, fold);
return(hash_get_nth_mutex(table, i));

View file

@ -43,6 +43,7 @@ extern ibool lock_print_waits;
#endif /* UNIV_DEBUG */
/* Buffer for storing information about the most recent deadlock error */
extern FILE* lock_latest_err_file;
extern ulint srv_n_lock_deadlock_count;
/*********************************************************************//**
Gets the size of a lock struct.
@ -613,13 +614,16 @@ lock_rec_print(
FILE* file, /*!< in: file where to print */
const lock_t* lock); /*!< in: record type lock */
/*********************************************************************//**
Prints info of locks for all transactions. */
Prints info of locks for all transactions.
@return FALSE if not able to obtain kernel mutex
and exits without printing info */
UNIV_INTERN
void
ibool
lock_print_info_summary(
/*====================*/
FILE* file); /*!< in: file where to print */
/*********************************************************************//**
FILE* file, /*!< in: file where to print */
ibool nowait);/*!< in: whether to wait for the kernel mutex */
/*************************************************************************
Prints info of locks for each transaction. */
UNIV_INTERN
void

View file

@ -1,23 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
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 the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2009, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@ -825,7 +808,17 @@ struct log_struct{
written to some log group; for this to
be advanced, it is enough that the
write i/o has been completed for all
log groups */
log groups.
Note that since InnoDB currently
has only one log group therefore
this value is redundant. Also it
is possible that this value
falls behind the
flushed_to_disk_lsn transiently.
It is appropriate to use either
flushed_to_disk_lsn or
write_lsn which are always
up-to-date and accurate. */
ib_uint64_t write_lsn; /*!< end lsn for the current running
write */
ulint write_end_offset;/*!< the data in buffer has

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -314,12 +314,15 @@ log_reserve_and_write_fast(
ulint data_len;
#ifdef UNIV_LOG_LSN_DEBUG
/* length of the LSN pseudo-record */
ulint lsn_len = 1
+ mach_get_compressed_size(log_sys->lsn >> 32)
+ mach_get_compressed_size(log_sys->lsn & 0xFFFFFFFFUL);
ulint lsn_len;
#endif /* UNIV_LOG_LSN_DEBUG */
mutex_enter(&log_sys->mutex);
#ifdef UNIV_LOG_LSN_DEBUG
lsn_len = 1
+ mach_get_compressed_size(log_sys->lsn >> 32)
+ mach_get_compressed_size(log_sys->lsn & 0xFFFFFFFFUL);
#endif /* UNIV_LOG_LSN_DEBUG */
data_len = len
#ifdef UNIV_LOG_LSN_DEBUG

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -176,6 +176,12 @@ UNIV_INTERN
void
recv_recovery_from_checkpoint_finish(void);
/*======================================*/
/********************************************************//**
Initiates the rollback of active transactions. */
UNIV_INTERN
void
recv_recovery_rollback_active(void);
/*===============================*/
/*******************************************************//**
Scans log from a buffer and stores new log data to the parsing buffer.
Parses and hashes the log records if new data found. Unless
@ -258,12 +264,14 @@ void
recv_sys_init(
/*==========*/
ulint available_memory); /*!< in: available memory in bytes */
#ifndef UNIV_HOTBACKUP
/********************************************************//**
Reset the state of the recovery system variables. */
UNIV_INTERN
void
recv_sys_var_init(void);
/*===================*/
#endif /* !UNIV_HOTBACKUP */
/*******************************************************************//**
Empties the hash table of stored log records, applying them to appropriate
pages. */
@ -360,8 +368,8 @@ typedef struct recv_addr_struct recv_addr_t;
struct recv_addr_struct{
enum recv_addr_state state;
/*!< recovery state of the page */
ulint space; /*!< space id */
ulint page_no;/*!< page number */
unsigned space:32;/*!< space id */
unsigned page_no:32;/*!< page number */
UT_LIST_BASE_NODE_T(recv_t)
rec_list;/*!< list of log records for this page */
hash_node_t addr_hash;/*!< hash node in the hash bucket chain */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -28,6 +28,13 @@ Created 6/9/1994 Heikki Tuuri
check fields whose sizes are given below */
#ifdef UNIV_MEM_DEBUG
# ifndef UNIV_HOTBACKUP
/* The mutex which protects in the debug version the hash table
containing the list of live memory heaps, and also the global
variables in mem0dbg.c. */
extern mutex_t mem_hash_mutex;
# endif /* !UNIV_HOTBACKUP */
#define MEM_FIELD_HEADER_SIZE ut_calc_align(2 * sizeof(ulint),\
UNIV_MEM_ALIGNMENT)
#define MEM_FIELD_TRAILER_SIZE sizeof(ulint)

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -25,9 +25,6 @@ Created 6/8/1994 Heikki Tuuri
*************************************************************************/
#ifdef UNIV_MEM_DEBUG
# ifndef UNIV_HOTBACKUP
extern mutex_t mem_hash_mutex;
# endif /* !UNIV_HOTBACKUP */
extern ulint mem_current_allocated_memory;
/******************************************************************//**

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -359,6 +359,9 @@ struct mem_block_info_struct {
to the heap is also the first block in this list,
though it also contains the base node of the list. */
ulint len; /*!< physical length of this block in bytes */
ulint total_size; /* physical length in bytes of all blocks
in the heap. This is defined only in the base
node and is set to ULINT_UNDEFINED in others. */
ulint type; /*!< type of heap: MEM_HEAP_DYNAMIC, or
MEM_HEAP_BUF possibly ORed to MEM_HEAP_BTR_SEARCH */
ulint free; /*!< offset in bytes of the first free position for

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -579,18 +579,12 @@ mem_heap_get_size(
/*==============*/
mem_heap_t* heap) /*!< in: heap */
{
mem_block_t* block;
ulint size = 0;
ut_ad(mem_heap_check(heap));
block = heap;
size = heap->total_size;
while (block != NULL) {
size += mem_block_get_len(block);
block = UT_LIST_GET_NEXT(list, block);
}
#ifndef UNIV_HOTBACKUP
if (heap->free_block) {
size += UNIV_PAGE_SIZE;

View file

@ -27,8 +27,8 @@ Created 12/7/1995 Heikki Tuuri
#include "ut0lst.h"
#include "buf0buf.h"
#include "fsp0types.h"
#include "srv0srv.h"
#include "trx0sys.h"
/********************************************************//**
Opens a buffer to mlog. It must be closed with mlog_close.
@return buffer, NULL if log mode MTR_LOG_NONE */
@ -201,7 +201,8 @@ mlog_write_initial_log_record_fast(
the doublewrite buffer is located in pages
FSP_EXTENT_SIZE, ..., 3 * FSP_EXTENT_SIZE - 1 in the
system tablespace */
if (space == TRX_SYS_SPACE
if ((space == TRX_SYS_SPACE
|| (srv_doublewrite_file && space == TRX_DOUBLEWRITE_SPACE))
&& offset >= FSP_EXTENT_SIZE && offset < 3 * FSP_EXTENT_SIZE) {
if (trx_doublewrite_buf_is_being_created) {
/* Do nothing: we only come to this branch in an

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -70,6 +70,7 @@ mtr_memo_push(
ut_ad(type <= MTR_MEMO_X_LOCK);
ut_ad(mtr);
ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_ACTIVE);
memo = &(mtr->memo);
@ -92,6 +93,7 @@ mtr_set_savepoint(
ut_ad(mtr);
ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_ACTIVE);
memo = &(mtr->memo);
@ -149,6 +151,7 @@ mtr_memo_contains(
ut_ad(mtr);
ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_ACTIVE || mtr->state == MTR_COMMITTING);
memo = &(mtr->memo);

View file

@ -1,23 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
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 the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/***********************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Portions of this file contain modifications contributed and copyrighted

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -30,6 +30,7 @@ Created 5/27/1996 Heikki Tuuri
#include "data0data.h"
#include "dict0types.h"
#include "trx0trx.h"
#include "trx0roll.h"
#include "srv0srv.h"
#include "usr0types.h"
#include "que0types.h"
@ -215,6 +216,16 @@ trx_t*
thr_get_trx(
/*========*/
que_thr_t* thr); /*!< in: query thread */
/*******************************************************************//**
Determines if this thread is rolling back an incomplete transaction
in crash recovery.
@return TRUE if thr is rolling back an incomplete transaction in crash
recovery */
UNIV_INLINE
ibool
thr_is_recv(
/*========*/
const que_thr_t* thr); /*!< in: query thread */
/***********************************************************************//**
Gets the type of a graph node. */
UNIV_INLINE

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -38,6 +38,20 @@ thr_get_trx(
return(thr->graph->trx);
}
/*******************************************************************//**
Determines if this thread is rolling back an incomplete transaction
in crash recovery.
@return TRUE if thr is rolling back an incomplete transaction in crash
recovery */
UNIV_INLINE
ibool
thr_is_recv(
/*========*/
const que_thr_t* thr) /*!< in: query thread */
{
return(trx_is_recv(thr->graph->trx));
}
/***********************************************************************//**
Gets the first thr in a fork. */
UNIV_INLINE

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2000, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 2000, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -451,6 +451,12 @@ row_drop_table_for_mysql(
const char* name, /*!< in: table name */
trx_t* trx, /*!< in: transaction handle */
ibool drop_db);/*!< in: TRUE=dropping whole database */
/*********************************************************************//**
Drop all temporary tables during crash recovery. */
UNIV_INTERN
void
row_mysql_drop_temp_tables(void);
/*============================*/
/*********************************************************************//**
Discards the tablespace of a table which stored in an .ibd file. Discarding
@ -494,14 +500,19 @@ row_rename_table_for_mysql(
trx_t* trx, /*!< in: transaction handle */
ibool commit); /*!< in: if TRUE then commit trx */
/*********************************************************************//**
Checks a table for corruption.
@return DB_ERROR or DB_SUCCESS */
Checks that the index contains entries in an ascending order, unique
constraint is not broken, and calculates the number of index entries
in the read view of the current transaction.
@return DB_SUCCESS if ok */
UNIV_INTERN
ulint
row_check_table_for_mysql(
row_check_index_for_mysql(
/*======================*/
row_prebuilt_t* prebuilt); /*!< in: prebuilt struct in MySQL
handle */
row_prebuilt_t* prebuilt, /*!< in: prebuilt struct
in MySQL handle */
const dict_index_t* index, /*!< in: index */
ulint* n_rows); /*!< out: number of entries
seen in the consistent read */
/*********************************************************************//**
Determines if a table is a magic monitor table.

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -105,17 +105,6 @@ row_fetch_print(
/*============*/
void* row, /*!< in: sel_node_t* */
void* user_arg); /*!< in: not used */
/****************************************************************//**
Callback function for fetch that stores an unsigned 4 byte integer to the
location pointed. The column's type must be DATA_INT, DATA_UNSIGNED, length
= 4.
@return always returns NULL */
UNIV_INTERN
void*
row_fetch_store_uint4(
/*==================*/
void* row, /*!< in: sel_node_t* */
void* user_arg); /*!< in: data pointer */
/***********************************************************//**
Prints a row in a select result.
@return query thread to run next or NULL */

View file

@ -1,7 +1,8 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, 2009, Google Inc.
Copyright (c) 2009, Percona Inc.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@ -9,6 +10,13 @@ briefly in the InnoDB documentation. The contributions by Google are
incorporated with their permission, and subject to the conditions contained in
the file COPYING.Google.
Portions of this file contain modifications contributed and copyrighted
by Percona Inc.. Those modifications are
gratefully acknowledged and are described briefly in the InnoDB
documentation. The contributions by Percona Inc. are incorporated with
their permission, and subject to the conditions contained in the file
COPYING.Percona.
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 the Free Software
Foundation; version 2 of the License.
@ -22,32 +30,6 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/***********************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Portions of this file contain modifications contributed and copyrighted
by Percona Inc.. Those modifications are
gratefully acknowledged and are described briefly in the InnoDB
documentation. The contributions by Percona Inc. are incorporated with
their permission, and subject to the conditions contained in the file
COPYING.Percona.
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 the
Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
***********************************************************************/
/**************************************************//**
@file include/srv0srv.h
@ -133,9 +115,10 @@ extern char** srv_data_file_names;
extern ulint* srv_data_file_sizes;
extern ulint* srv_data_file_is_raw_partition;
extern char* srv_doublewrite_file;
extern ibool srv_extra_undoslots;
extern ibool srv_fast_recovery;
extern ibool srv_recovery_stats;
extern ulint srv_use_purge_thread;
@ -247,7 +230,6 @@ extern ulint srv_read_ahead;
extern ulint srv_adaptive_checkpoint;
extern ulint srv_expand_import;
extern ulint srv_relax_table_creation;
extern ulint srv_pass_corrupt_table;
extern ulint srv_extra_rsegments;
@ -265,7 +247,8 @@ extern ibool srv_print_innodb_tablespace_monitor;
extern ibool srv_print_verbose_log;
extern ibool srv_print_innodb_table_monitor;
extern ibool srv_lock_timeout_and_monitor_active;
extern ibool srv_lock_timeout_active;
extern ibool srv_monitor_active;
extern ibool srv_error_monitor_active;
extern ulong srv_n_spin_wait_rounds;
@ -595,15 +578,23 @@ srv_release_mysql_thread_if_suspended(
MySQL OS thread */
/*********************************************************************//**
A thread which wakes up threads whose lock wait may have lasted too long.
This also prints the info output by various InnoDB monitors.
@return a dummy parameter */
UNIV_INTERN
os_thread_ret_t
srv_lock_timeout_and_monitor_thread(
/*================================*/
srv_lock_timeout_thread(
/*====================*/
void* arg); /*!< in: a dummy parameter required by
os_thread_create */
/*********************************************************************//**
A thread which prints the info output by various InnoDB monitors.
@return a dummy parameter */
UNIV_INTERN
os_thread_ret_t
srv_monitor_thread(
/*===============*/
void* arg); /*!< in: a dummy parameter required by
os_thread_create */
/*************************************************************************
A thread which prints warnings about semaphore waits which have lasted
too long. These can be used to track bugs which cause hangs.
@return a dummy parameter */
@ -614,12 +605,15 @@ srv_error_monitor_thread(
void* arg); /*!< in: a dummy parameter required by
os_thread_create */
/******************************************************************//**
Outputs to a file the output of the InnoDB Monitor. */
Outputs to a file the output of the InnoDB Monitor.
@return FALSE if not all information printed
due to failure to obtain necessary mutex */
UNIV_INTERN
void
ibool
srv_printf_innodb_monitor(
/*======================*/
FILE* file, /*!< in: output stream */
ibool nowait, /*!< in: whether to wait for kernel mutex */
ulint* trx_start, /*!< out: file position of the start of
the list of active transactions */
ulint* trx_end); /*!< out: file position of the end of
@ -664,6 +658,7 @@ struct export_var_struct{
ulint innodb_buffer_pool_write_requests;/*!< srv_buf_pool_write_requests */
ulint innodb_buffer_pool_read_ahead; /*!< srv_read_ahead */
ulint innodb_buffer_pool_read_ahead_evicted;/*!< srv_read_ahead evicted*/
ulint innodb_deadlocks; /* ??? */
ulint innodb_dblwr_pages_written; /*!< srv_dblwr_pages_written */
ulint innodb_dblwr_writes; /*!< srv_dblwr_writes */
ibool innodb_have_atomic_builtins; /*!< HAVE_ATOMIC_BUILTINS */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@ -429,8 +429,9 @@ ibool
rw_lock_own(
/*========*/
rw_lock_t* lock, /*!< in: rw-lock */
ulint lock_type); /*!< in: lock type: RW_LOCK_SHARED,
ulint lock_type) /*!< in: lock type: RW_LOCK_SHARED,
RW_LOCK_EX */
__attribute__((warn_unused_result));
#endif /* UNIV_SYNC_DEBUG */
/******************************************************************//**
Checks if somebody has locked the rw-lock in the specified mode. */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@ -206,7 +206,8 @@ UNIV_INTERN
ibool
mutex_own(
/*======*/
const mutex_t* mutex); /*!< in: mutex */
const mutex_t* mutex) /*!< in: mutex */
__attribute__((warn_unused_result));
#endif /* UNIV_DEBUG */
#ifdef UNIV_SYNC_DEBUG
/******************************************************************//**
@ -238,16 +239,27 @@ ibool
sync_thread_levels_empty(void);
/*==========================*/
/******************************************************************//**
Checks that the level array for the current thread is empty.
@return TRUE if empty except the exceptions specified below */
Checks if the level array for the current thread contains a
mutex or rw-latch at the specified level.
@return a matching latch, or NULL if not found */
UNIV_INTERN
ibool
sync_thread_levels_empty_gen(
/*=========================*/
void*
sync_thread_levels_contains(
/*========================*/
ulint level); /*!< in: latching order level
(SYNC_DICT, ...)*/
/******************************************************************//**
Checks if the level array for the current thread is empty.
@return a latch, or NULL if empty except the exceptions specified below */
UNIV_INTERN
void*
sync_thread_levels_nonempty_gen(
/*============================*/
ibool dict_mutex_allowed); /*!< in: TRUE if dictionary mutex is
allowed to be owned by the thread,
also purge_is_running mutex is
allowed */
#define sync_thread_levels_empty_gen(d) (!sync_thread_levels_nonempty_gen(d))
/******************************************************************//**
Gets the debug information for a reserved mutex. */
UNIV_INTERN

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software

View file

@ -124,6 +124,22 @@ trx_sys_hdr_page(
/*=============*/
ulint space, /*!< in: space */
ulint page_no);/*!< in: page number */
/***************************************************************//**
Checks if a space is the system tablespaces.
@return TRUE if system tablespace */
UNIV_INLINE
ibool
trx_sys_sys_space(
/*==============*/
ulint space); /*!< in: space */
/***************************************************************//**
Checks if a space is the doublewrite tablespace.
@return TRUE if doublewrite tablespace */
UNIV_INLINE
ibool
trx_sys_doublewrite_space(
/*======================*/
ulint space); /*!< in: space */
/*****************************************************************//**
Creates and initializes the central memory structures for the transaction
system. This is called when the database is started. */
@ -137,6 +153,13 @@ UNIV_INTERN
void
trx_sys_create(void);
/*================*/
/*****************************************************************//**
Creates and initializes the dummy transaction system page for tablespace. */
UNIV_INTERN
void
trx_sys_dummy_create(
/*=================*/
ulint space);
/*********************************************************************
Create extra rollback segments when create_new_db */
UNIV_INTERN
@ -343,12 +366,14 @@ UNIV_INTERN
void
trx_sys_file_format_tag_init(void);
/*==============================*/
#ifndef UNIV_HOTBACKUP
/*****************************************************************//**
Shutdown/Close the transaction system. */
UNIV_INTERN
void
trx_sys_close(void);
/*===============*/
#endif /* !UNIV_HOTBACKUP */
/*****************************************************************//**
Get the name representation of the file format from its id.
@return pointer to the name */
@ -444,6 +469,8 @@ trx_sys_file_format_id_to_name(
/* Space id and page no where the trx system file copy resides */
#define TRX_SYS_SPACE 0 /* the SYSTEM tablespace */
#define TRX_DOUBLEWRITE_SPACE 1 /* the doublewrite buffer tablespace if used */
#define TRX_SYS_SPACE_MAX 9 /* reserved max space id for system tablespaces */
#include "fsp0fsp.h"
#define TRX_SYS_PAGE_NO FSP_TRX_SYS_PAGE_NO
@ -507,7 +534,6 @@ this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
within that file */
#define TRX_SYS_MYSQL_LOG_NAME 12 /*!< MySQL log file name */
#ifndef UNIV_HOTBACKUP
/** Doublewrite buffer */
/* @{ */
/** The offset of the doublewrite buffer header on the trx system header page */
@ -559,6 +585,7 @@ FIL_PAGE_ARCH_LOG_NO_OR_SPACE_NO. */
#define TRX_SYS_DOUBLEWRITE_BLOCK_SIZE FSP_EXTENT_SIZE
/* @} */
#ifndef UNIV_HOTBACKUP
/** File format tag */
/* @{ */
/** The offset of the file format tag on the trx system header page

View file

@ -70,6 +70,40 @@ trx_sys_hdr_page(
return(FALSE);
}
/***************************************************************//**
Checks if a space is the system tablespaces.
@return TRUE if system tablespace */
UNIV_INLINE
ibool
trx_sys_sys_space(
/*==============*/
ulint space) /*!< in: space */
{
if (srv_doublewrite_file) {
/* several spaces are reserved */
return((ibool)(space <= TRX_SYS_SPACE_MAX));
} else {
return((ibool)(space == TRX_SYS_SPACE));
}
}
/***************************************************************//**
Checks if a space is the doublewrite tablespace.
@return TRUE if doublewrite tablespace */
UNIV_INLINE
ibool
trx_sys_doublewrite_space(
/*======================*/
ulint space) /*!< in: space */
{
if (srv_doublewrite_file) {
/* doublewrite buffer is separated */
return((ibool)(space == TRX_DOUBLEWRITE_SPACE));
} else {
return((ibool)(space == TRX_SYS_SPACE));
}
}
/***************************************************************//**
Gets the pointer in the nth slot of the rseg array.
@return pointer to rseg object, NULL if slot not in use */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -338,9 +338,7 @@ trx_commit_step(
/**********************************************************************//**
Prints info about a transaction to the given file. The caller must own the
kernel mutex and must have called
innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL
or InnoDB cannot meanwhile change the info printed here. */
kernel mutex. */
UNIV_INTERN
void
trx_print(
@ -351,7 +349,7 @@ trx_print(
use the default max length */
/** Type of data dictionary operation */
enum trx_dict_op {
typedef enum trx_dict_op {
/** The transaction is not modifying the data dictionary. */
TRX_DICT_OP_NONE = 0,
/** The transaction is creating a table or an index, or
@ -363,7 +361,7 @@ enum trx_dict_op {
existing table. In crash recovery, the data dictionary
must be locked, but the table must not be dropped. */
TRX_DICT_OP_INDEX = 2
};
} trx_dict_op_t;
/**********************************************************************//**
Determine if a transaction is a dictionary operation.
@ -393,6 +391,14 @@ ibool
trx_is_interrupted(
/*===============*/
trx_t* trx); /*!< in: transaction */
/**********************************************************************//**
Determines if the currently running transaction is in strict mode.
@return TRUE if strict */
UNIV_INTERN
ibool
trx_is_strict(
/*==========*/
trx_t* trx); /*!< in: transaction */
#else /* !UNIV_HOTBACKUP */
#define trx_is_interrupted(trx) FALSE
#endif /* !UNIV_HOTBACKUP */
@ -465,69 +471,79 @@ rolling back after a database recovery */
struct trx_struct{
ulint magic_n;
/* All the next fields are protected by the kernel mutex, except the
undo logs which are protected by undo_mutex */
/* These fields are not protected by any mutex. */
const char* op_info; /*!< English text describing the
current operation, or an empty
string */
unsigned is_purge:1; /*!< 0=user transaction, 1=purge */
unsigned is_recovered:1; /*!< 0=normal transaction,
1=recovered, must be rolled back */
unsigned conc_state:2; /*!< state of the trx from the point
ulint conc_state; /*!< state of the trx from the point
of view of concurrency control:
TRX_ACTIVE, TRX_COMMITTED_IN_MEMORY,
... */
unsigned que_state:2; /*!< valid when conc_state == TRX_ACTIVE:
TRX_QUE_RUNNING, TRX_QUE_LOCK_WAIT,
... */
unsigned isolation_level:2;/* TRX_ISO_REPEATABLE_READ, ... */
unsigned check_foreigns:1;/* normally TRUE, but if the user
ulint isolation_level;/* TRX_ISO_REPEATABLE_READ, ... */
ulint check_foreigns; /* normally TRUE, but if the user
wants to suppress foreign key checks,
(in table imports, for example) we
set this FALSE */
unsigned check_unique_secondary:1;
ulint check_unique_secondary;
/* normally TRUE, but if the user
wants to speed up inserts by
suppressing unique key checks
for secondary indexes when we decide
if we can use the insert buffer for
them, we set this FALSE */
unsigned support_xa:1; /*!< normally we do the XA two-phase
ulint support_xa; /*!< normally we do the XA two-phase
commit steps, but by setting this to
FALSE, one can save CPU time and about
150 bytes in the undo log size as then
we skip XA steps */
unsigned flush_log_later:1;/* In 2PC, we hold the
ulint flush_log_later;/* In 2PC, we hold the
prepare_commit mutex across
both phases. In that case, we
defer flush of the logs to disk
until after we release the
mutex. */
unsigned must_flush_log_later:1;/* this flag is set to TRUE in
ulint must_flush_log_later;/* this flag is set to TRUE in
trx_commit_off_kernel() if
flush_log_later was TRUE, and there
were modifications by the transaction;
in that case we must flush the log
in trx_commit_complete_for_mysql() */
unsigned dict_operation:2;/**< @see enum trx_dict_op */
unsigned duplicates:2; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */
unsigned active_trans:2; /*!< 1 - if a transaction in MySQL
ulint duplicates; /*!< TRX_DUP_IGNORE | TRX_DUP_REPLACE */
ulint active_trans; /*!< 1 - if a transaction in MySQL
is active. 2 - if prepare_commit_mutex
was taken */
unsigned has_search_latch:1;
ulint has_search_latch;
/* TRUE if this trx has latched the
search system latch in S-mode */
unsigned declared_to_be_inside_innodb:1;
ulint deadlock_mark; /*!< a mark field used in deadlock
checking algorithm. */
trx_dict_op_t dict_operation; /**< @see enum trx_dict_op */
/* Fields protected by the srv_conc_mutex. */
ulint declared_to_be_inside_innodb;
/* this is TRUE if we have declared
this transaction in
srv_conc_enter_innodb to be inside the
InnoDB engine */
unsigned handling_signals:1;/* this is TRUE as long as the trx
is handling signals */
unsigned dict_operation_lock_mode:2;
/* 0, RW_S_LATCH, or RW_X_LATCH:
/* Fields protected by dict_operation_lock. The very latch
it is used to track. */
ulint dict_operation_lock_mode;
/*!< 0, RW_S_LATCH, or RW_X_LATCH:
the latch mode trx currently holds
on dict_operation_lock */
/* All the next fields are protected by the kernel mutex, except the
undo logs which are protected by undo_mutex */
ulint is_purge; /*!< 0=user transaction, 1=purge */
ulint is_recovered; /*!< 0=normal transaction,
1=recovered, must be rolled back */
ulint que_state; /*!< valid when conc_state
== TRX_ACTIVE: TRX_QUE_RUNNING,
TRX_QUE_LOCK_WAIT, ... */
ulint handling_signals;/* this is TRUE as long as the trx
is handling signals */
time_t start_time; /*!< time the trx object was created
or the state last time became
TRX_ACTIVE */
@ -657,11 +673,6 @@ struct trx_struct{
wait_thrs; /*!< query threads belonging to this
trx that are in the QUE_THR_LOCK_WAIT
state */
ulint deadlock_mark; /*!< a mark field used in deadlock
checking algorithm. This must be
in its own machine word, because
it can be changed by other
threads while holding kernel_mutex. */
/*------------------------------*/
mem_heap_t* lock_heap; /*!< memory heap for the locks of the
transaction */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -70,6 +70,13 @@ typedef struct trx_named_savept_struct trx_named_savept_t;
enum trx_rb_ctx {
RB_NONE = 0, /*!< no rollback */
RB_NORMAL, /*!< normal rollback */
RB_RECOVERY_PURGE_REC,
/*!< rolling back an incomplete transaction,
in crash recovery, rolling back an
INSERT that was performed by updating a
delete-marked record; if the delete-marked record
no longer exists in an active read view, it will
be purged */
RB_RECOVERY /*!< rolling back an incomplete transaction,
in crash recovery */
};

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2008, Google Inc.
Copyright (c) 2009, Sun Microsystems, Inc.
@ -46,10 +46,10 @@ Created 1/20/1994 Heikki Tuuri
#define INNODB_VERSION_MAJOR 1
#define INNODB_VERSION_MINOR 0
#define INNODB_VERSION_BUGFIX 6
#define INNODB_VERSION_BUGFIX 8
#ifndef PERCONA_INNODB_VERSION
#define PERCONA_INNODB_VERSION unknown
#define PERCONA_INNODB_VERSION 11.2
#endif
@ -122,7 +122,7 @@ if we are compiling on Windows. */
/* Include <sys/stat.h> to get S_I... macros defined for os0file.c */
# include <sys/stat.h>
# if !defined(__NETWARE__) && !defined(__WIN__)
# if !defined(__NETWARE__) && !defined(__WIN__)
# include <sys/mman.h> /* mmap() for os0proc.c */
# endif
@ -172,6 +172,9 @@ command. Not tested on Windows. */
#define UNIV_COMPILE_TEST_FUNCS
*/
#ifdef HAVE_purify
# define UNIV_DEBUG_VALGRIND
#endif /* HAVE_purify */
#if 0
#define UNIV_DEBUG_VALGRIND /* Enable extra
Valgrind instrumentation */
@ -209,6 +212,10 @@ operations (very slow); also UNIV_DEBUG must be defined */
adaptive hash index */
#define UNIV_SRV_PRINT_LATCH_WAITS /* enable diagnostic output
in sync0sync.c */
#define UNIV_BTR_AVOID_COPY /* when splitting B-tree nodes,
do not move any records when
all the records would
be moved */
#define UNIV_BTR_PRINT /* enable functions for
printing B-trees */
#define UNIV_ZIP_DEBUG /* extensive consistency checks
@ -236,11 +243,6 @@ by one. */
/* the above option prevents forcing of log to disk
at a buffer page write: it should be tested with this
option off; also some ibuf tests are suppressed */
/*
#define UNIV_BASIC_LOG_DEBUG
*/
/* the above option enables basic recovery debugging:
new allocated file pages are reset */
/* Linkage specifier for non-static InnoDB symbols (variables and functions)
that are only referenced from within InnoDB, not from MySQL */

309
include/ut0rbt.h Normal file
View file

@ -0,0 +1,309 @@
/*****************************************************************************
Copyright (c) 2006, 2009, Innobase Oy. All Rights Reserved.
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 the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/*******************************************************************//**
@file include/ut0rbt.h
Red-Black tree implementation.
Created 2007-03-20 Sunny Bains
************************************************************************/
#ifndef INNOBASE_UT0RBT_H
#define INNOBASE_UT0RBT_H
#if !defined(IB_RBT_TESTING)
#include "univ.i"
#include "ut0mem.h"
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define ut_malloc malloc
#define ut_free free
#define ulint unsigned long
#define ut_a(c) assert(c)
#define ut_error assert(0)
#define ibool unsigned int
#define TRUE 1
#define FALSE 0
#endif
/* Red black tree typedefs */
typedef struct ib_rbt_struct ib_rbt_t;
typedef struct ib_rbt_node_struct ib_rbt_node_t;
/* FIXME: Iterator is a better name than _bound_ */
typedef struct ib_rbt_bound_struct ib_rbt_bound_t;
typedef void (*ib_rbt_print_node)(const ib_rbt_node_t* node);
typedef int (*ib_rbt_compare)(const void* p1, const void* p2);
/* Red black tree color types */
enum ib_rbt_color_enum {
IB_RBT_RED,
IB_RBT_BLACK
};
typedef enum ib_rbt_color_enum ib_rbt_color_t;
/* Red black tree node */
struct ib_rbt_node_struct {
ib_rbt_color_t color; /* color of this node */
ib_rbt_node_t* left; /* points left child */
ib_rbt_node_t* right; /* points right child */
ib_rbt_node_t* parent; /* points parent node */
char value[1]; /* Data value */
};
/* Red black tree instance.*/
struct ib_rbt_struct {
ib_rbt_node_t* nil; /* Black colored node that is
used as a sentinel. This is
pre-allocated too.*/
ib_rbt_node_t* root; /* Root of the tree, this is
pre-allocated and the first
data node is the left child.*/
ulint n_nodes; /* Total number of data nodes */
ib_rbt_compare compare; /* Fn. to use for comparison */
ulint sizeof_value; /* Sizeof the item in bytes */
};
/* The result of searching for a key in the tree, this is useful for
a speedy lookup and insert if key doesn't exist.*/
struct ib_rbt_bound_struct {
const ib_rbt_node_t*
last; /* Last node visited */
int result; /* Result of comparing with
the last non-nil node that
was visited */
};
/* Size in elements (t is an rb tree instance) */
#define rbt_size(t) (t->n_nodes)
/* Check whether the rb tree is empty (t is an rb tree instance) */
#define rbt_empty(t) (rbt_size(t) == 0)
/* Get data value (t is the data type, n is an rb tree node instance) */
#define rbt_value(t, n) ((t*) &n->value[0])
/* Compare a key with the node value (t is tree, k is key, n is node)*/
#define rbt_compare(t, k, n) (t->compare(k, n->value))
/****************************************************************//**
Free an instance of a red black tree */
UNIV_INTERN
void
rbt_free(
/*=====*/
ib_rbt_t* tree); /*!< in: rb tree to free */
/****************************************************************//**
Create an instance of a red black tree
@return rb tree instance */
UNIV_INTERN
ib_rbt_t*
rbt_create(
/*=======*/
size_t sizeof_value, /*!< in: size in bytes */
ib_rbt_compare compare); /*!< in: comparator */
/****************************************************************//**
Delete a node from the red black tree, identified by key.
@return TRUE if success FALSE if not found */
UNIV_INTERN
ibool
rbt_delete(
/*=======*/
ib_rbt_t* tree, /*!< in: rb tree */
const void* key); /*!< in: key to delete */
/****************************************************************//**
Remove a node from the rb tree, the node is not free'd, that is the
callers responsibility.
@return the deleted node with the const. */
UNIV_INTERN
ib_rbt_node_t*
rbt_remove_node(
/*============*/
ib_rbt_t* tree, /*!< in: rb tree */
const ib_rbt_node_t*
node); /*!< in: node to delete, this
is a fudge and declared const
because the caller has access
only to const nodes.*/
/****************************************************************//**
Find a matching node in the rb tree.
@return node if found else return NULL */
UNIV_INTERN
const ib_rbt_node_t*
rbt_lookup(
/*=======*/
const ib_rbt_t* tree, /*!< in: rb tree to search */
const void* key); /*!< in: key to lookup */
/****************************************************************//**
Generic insert of a value in the rb tree.
@return inserted node */
UNIV_INTERN
const ib_rbt_node_t*
rbt_insert(
/*=======*/
ib_rbt_t* tree, /*!< in: rb tree */
const void* key, /*!< in: key for ordering */
const void* value); /*!< in: data that will be
copied to the node.*/
/****************************************************************//**
Add a new node to the tree, useful for data that is pre-sorted.
@return appended node */
UNIV_INTERN
const ib_rbt_node_t*
rbt_add_node(
/*=========*/
ib_rbt_t* tree, /*!< in: rb tree */
ib_rbt_bound_t* parent, /*!< in: parent */
const void* value); /*!< in: this value is copied
to the node */
/****************************************************************//**
Return the left most data node in the tree
@return left most node */
UNIV_INTERN
const ib_rbt_node_t*
rbt_first(
/*======*/
const ib_rbt_t* tree); /*!< in: rb tree */
/****************************************************************//**
Return the right most data node in the tree
@return right most node */
UNIV_INTERN
const ib_rbt_node_t*
rbt_last(
/*=====*/
const ib_rbt_t* tree); /*!< in: rb tree */
/****************************************************************//**
Return the next node from current.
@return successor node to current that is passed in. */
UNIV_INTERN
const ib_rbt_node_t*
rbt_next(
/*=====*/
const ib_rbt_t* tree, /*!< in: rb tree */
const ib_rbt_node_t* /*!< in: current node */
current);
/****************************************************************//**
Return the prev node from current.
@return precedessor node to current that is passed in */
UNIV_INTERN
const ib_rbt_node_t*
rbt_prev(
/*=====*/
const ib_rbt_t* tree, /*!< in: rb tree */
const ib_rbt_node_t* /*!< in: current node */
current);
/****************************************************************//**
Find the node that has the lowest key that is >= key.
@return node that satisfies the lower bound constraint or NULL */
UNIV_INTERN
const ib_rbt_node_t*
rbt_lower_bound(
/*============*/
const ib_rbt_t* tree, /*!< in: rb tree */
const void* key); /*!< in: key to search */
/****************************************************************//**
Find the node that has the greatest key that is <= key.
@return node that satisifies the upper bound constraint or NULL */
UNIV_INTERN
const ib_rbt_node_t*
rbt_upper_bound(
/*============*/
const ib_rbt_t* tree, /*!< in: rb tree */
const void* key); /*!< in: key to search */
/****************************************************************//**
Search for the key, a node will be retuned in parent.last, whether it
was found or not. If not found then parent.last will contain the
parent node for the possibly new key otherwise the matching node.
@return result of last comparison */
UNIV_INTERN
int
rbt_search(
/*=======*/
const ib_rbt_t* tree, /*!< in: rb tree */
ib_rbt_bound_t* parent, /*!< in: search bounds */
const void* key); /*!< in: key to search */
/****************************************************************//**
Search for the key, a node will be retuned in parent.last, whether it
was found or not. If not found then parent.last will contain the
parent node for the possibly new key otherwise the matching node.
@return result of last comparison */
UNIV_INTERN
int
rbt_search_cmp(
/*===========*/
const ib_rbt_t* tree, /*!< in: rb tree */
ib_rbt_bound_t* parent, /*!< in: search bounds */
const void* key, /*!< in: key to search */
ib_rbt_compare compare); /*!< in: comparator */
/****************************************************************//**
Clear the tree, deletes (and free's) all the nodes. */
UNIV_INTERN
void
rbt_clear(
/*======*/
ib_rbt_t* tree); /*!< in: rb tree */
/****************************************************************//**
Merge the node from dst into src. Return the number of nodes merged.
@return no. of recs merged */
UNIV_INTERN
ulint
rbt_merge_uniq(
/*===========*/
ib_rbt_t* dst, /*!< in: dst rb tree */
const ib_rbt_t* src); /*!< in: src rb tree */
/****************************************************************//**
Merge the node from dst into src. Return the number of nodes merged.
Delete the nodes from src after copying node to dst. As a side effect
the duplicates will be left untouched in the src, since we don't support
duplicates (yet). NOTE: src and dst must be similar, the function doesn't
check for this condition (yet).
@return no. of recs merged */
UNIV_INTERN
ulint
rbt_merge_uniq_destructive(
/*=======================*/
ib_rbt_t* dst, /*!< in: dst rb tree */
ib_rbt_t* src); /*!< in: src rb tree */
/****************************************************************//**
Verify the integrity of the RB tree. For debugging. 0 failure else height
of tree (in count of black nodes).
@return TRUE if OK FALSE if tree invalid. */
UNIV_INTERN
ibool
rbt_validate(
/*=========*/
const ib_rbt_t* tree); /*!< in: tree to validate */
/****************************************************************//**
Iterate over the tree in depth first order. */
UNIV_INTERN
void
rbt_print(
/*======*/
const ib_rbt_t* tree, /*!< in: tree to traverse */
ib_rbt_print_node print); /*!< in: print function */
#endif /* INNOBASE_UT0RBT_H */

View file

@ -152,6 +152,7 @@ ut_hash_ulint(
ulint key, /*!< in: value to be hashed */
ulint table_size) /*!< in: hash table size */
{
ut_ad(table_size);
key = key ^ UT_HASH_RANDOM_MASK2;
return(key % table_size);

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1996, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -376,6 +376,7 @@ UNIV_INTERN FILE* lock_latest_err_file;
/* Flags for recursive deadlock search */
#define LOCK_VICTIM_IS_START 1
#define LOCK_VICTIM_IS_OTHER 2
#define LOCK_EXCEED_MAX_DEPTH 3
/********************************************************************//**
Checks if a lock request results in a deadlock.
@ -394,24 +395,25 @@ Looks recursively for a deadlock.
deadlock and we chose 'start' as the victim, LOCK_VICTIM_IS_OTHER if a
deadlock was found and we chose some other trx as a victim: we must do
the search again in this last case because there may be another
deadlock! */
deadlock!
LOCK_EXCEED_MAX_DEPTH if the lock search exceeds max steps or max depth. */
static
ulint
lock_deadlock_recursive(
/*====================*/
trx_t* start, /*!< in: recursion starting point */
trx_t* trx, /*!< in: a transaction waiting for a lock */
lock_t* wait_lock, /*!< in: the lock trx is waiting to be granted */
lock_t* wait_lock, /*!< in: lock that is waiting to be granted */
ulint* cost, /*!< in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_...
we return LOCK_VICTIM_IS_START */
we return LOCK_EXCEED_MAX_DEPTH */
ulint depth); /*!< in: recursion depth: if this exceeds
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
return LOCK_VICTIM_IS_START */
return LOCK_EXCEED_MAX_DEPTH */
/*********************************************************************//**
Gets the nth bit of a record lock.
@return TRUE if bit set */
@return TRUE if bit set also if i == ULINT_UNDEFINED return FALSE*/
UNIV_INLINE
ibool
lock_rec_get_nth_bit(
@ -1222,7 +1224,7 @@ lock_rec_get_first_on_page(
/*********************************************************************//**
Gets the next explicit lock request on a record.
@return next lock, NULL if none exists */
@return next lock, NULL if none exists or if heap_no == ULINT_UNDEFINED */
UNIV_INLINE
lock_t*
lock_rec_get_next(
@ -2404,7 +2406,7 @@ lock_rec_inherit_to_gap(
if (!lock_rec_get_insert_intention(lock)
&& !((srv_locks_unsafe_for_binlog
|| lock->trx->isolation_level
== TRX_ISO_READ_COMMITTED)
<= TRX_ISO_READ_COMMITTED)
&& lock_get_mode(lock) == LOCK_X)) {
lock_rec_add_to_queue(LOCK_REC | LOCK_GAP
@ -3267,8 +3269,6 @@ lock_deadlock_occurs(
lock_t* lock, /*!< in: lock the transaction is requesting */
trx_t* trx) /*!< in: transaction */
{
dict_table_t* table;
dict_index_t* index;
trx_t* mark_trx;
ulint ret;
ulint cost = 0;
@ -3290,31 +3290,51 @@ retry:
ret = lock_deadlock_recursive(trx, trx, lock, &cost, 0);
if (ret == LOCK_VICTIM_IS_OTHER) {
switch (ret) {
case LOCK_VICTIM_IS_OTHER:
/* We chose some other trx as a victim: retry if there still
is a deadlock */
goto retry;
}
if (UNIV_UNLIKELY(ret == LOCK_VICTIM_IS_START)) {
if (lock_get_type_low(lock) & LOCK_TABLE) {
table = lock->un_member.tab_lock.table;
index = NULL;
} else {
index = lock->index;
table = index->table;
}
case LOCK_EXCEED_MAX_DEPTH:
/* If the lock search exceeds the max step
or the max depth, the current trx will be
the victim. Print its information. */
rewind(lock_latest_err_file);
ut_print_timestamp(lock_latest_err_file);
lock_deadlock_found = TRUE;
fputs("*** WE ROLL BACK TRANSACTION (2)\n",
fputs("TOO DEEP OR LONG SEARCH IN THE LOCK TABLE"
" WAITS-FOR GRAPH, WE WILL ROLL BACK"
" FOLLOWING TRANSACTION \n",
lock_latest_err_file);
return(TRUE);
fputs("\n*** TRANSACTION:\n", lock_latest_err_file);
trx_print(lock_latest_err_file, trx, 3000);
fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n",
lock_latest_err_file);
if (lock_get_type(lock) == LOCK_REC) {
lock_rec_print(lock_latest_err_file, lock);
} else {
lock_table_print(lock_latest_err_file, lock);
}
break;
case LOCK_VICTIM_IS_START:
srv_n_lock_deadlock_count++;
fputs("*** WE ROLL BACK TRANSACTION (2)\n",
lock_latest_err_file);
break;
default:
/* No deadlock detected*/
return(FALSE);
}
return(FALSE);
lock_deadlock_found = TRUE;
return(TRUE);
}
/********************************************************************//**
@ -3323,25 +3343,26 @@ Looks recursively for a deadlock.
deadlock and we chose 'start' as the victim, LOCK_VICTIM_IS_OTHER if a
deadlock was found and we chose some other trx as a victim: we must do
the search again in this last case because there may be another
deadlock! */
deadlock!
LOCK_EXCEED_MAX_DEPTH if the lock search exceeds max steps or max depth. */
static
ulint
lock_deadlock_recursive(
/*====================*/
trx_t* start, /*!< in: recursion starting point */
trx_t* trx, /*!< in: a transaction waiting for a lock */
lock_t* wait_lock, /*!< in: the lock trx is waiting to be granted */
lock_t* wait_lock, /*!< in: lock that is waiting to be granted */
ulint* cost, /*!< in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_...
we return LOCK_VICTIM_IS_START */
we return LOCK_EXCEED_MAX_DEPTH */
ulint depth) /*!< in: recursion depth: if this exceeds
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
return LOCK_VICTIM_IS_START */
return LOCK_EXCEED_MAX_DEPTH */
{
lock_t* lock;
ulint bit_no = ULINT_UNDEFINED;
trx_t* lock_trx;
ulint ret;
lock_t* lock;
trx_t* lock_trx;
ulint heap_no = ULINT_UNDEFINED;
ut_a(trx);
ut_a(start);
@ -3357,27 +3378,44 @@ lock_deadlock_recursive(
*cost = *cost + 1;
lock = wait_lock;
if (lock_get_type_low(wait_lock) == LOCK_REC) {
ulint space;
ulint page_no;
bit_no = lock_rec_find_set_bit(wait_lock);
heap_no = lock_rec_find_set_bit(wait_lock);
ut_a(heap_no != ULINT_UNDEFINED);
ut_a(bit_no != ULINT_UNDEFINED);
space = wait_lock->un_member.rec_lock.space;
page_no = wait_lock->un_member.rec_lock.page_no;
lock = lock_rec_get_first_on_page_addr(space, page_no);
/* Position the iterator on the first matching record lock. */
while (lock != NULL
&& lock != wait_lock
&& !lock_rec_get_nth_bit(lock, heap_no)) {
lock = lock_rec_get_next_on_page(lock);
}
if (lock == wait_lock) {
lock = NULL;
}
ut_ad(lock == NULL || lock_rec_get_nth_bit(lock, heap_no));
} else {
lock = wait_lock;
}
/* Look at the locks ahead of wait_lock in the lock queue */
for (;;) {
if (lock_get_type_low(lock) & LOCK_TABLE) {
/* Get previous table lock. */
if (heap_no == ULINT_UNDEFINED) {
lock = UT_LIST_GET_PREV(un_member.tab_lock.locks,
lock);
} else {
ut_ad(lock_get_type_low(lock) == LOCK_REC);
ut_a(bit_no != ULINT_UNDEFINED);
lock = (lock_t*) lock_rec_get_prev(lock, bit_no);
lock = UT_LIST_GET_PREV(
un_member.tab_lock.locks, lock);
}
if (lock == NULL) {
@ -3395,7 +3433,7 @@ lock_deadlock_recursive(
lock_trx = lock->trx;
if (lock_trx == start || too_far) {
if (lock_trx == start) {
/* We came back to the recursion starting
point: a deadlock detected; or we have
@ -3442,19 +3480,10 @@ lock_deadlock_recursive(
}
#ifdef UNIV_DEBUG
if (lock_print_waits) {
fputs("Deadlock detected"
" or too long search\n",
fputs("Deadlock detected\n",
stderr);
}
#endif /* UNIV_DEBUG */
if (too_far) {
fputs("TOO DEEP OR LONG SEARCH"
" IN THE LOCK TABLE"
" WAITS-FOR GRAPH\n", ef);
return(LOCK_VICTIM_IS_START);
}
if (trx_weight_cmp(wait_lock->trx,
start) >= 0) {
@ -3490,6 +3519,21 @@ lock_deadlock_recursive(
return(LOCK_VICTIM_IS_OTHER);
}
if (too_far) {
#ifdef UNIV_DEBUG
if (lock_print_waits) {
fputs("Deadlock search exceeds"
" max steps or depth.\n",
stderr);
}
#endif /* UNIV_DEBUG */
/* The information about transaction/lock
to be rolled back is available in the top
level. Do not print anything here. */
return(LOCK_EXCEED_MAX_DEPTH);
}
if (lock_trx->que_state == TRX_QUE_LOCK_WAIT) {
/* Another trx ahead has requested lock in an
@ -3499,12 +3543,28 @@ lock_deadlock_recursive(
ret = lock_deadlock_recursive(
start, lock_trx,
lock_trx->wait_lock, cost, depth + 1);
if (ret != 0) {
return(ret);
}
}
}
/* Get the next record lock to check. */
if (heap_no != ULINT_UNDEFINED) {
ut_a(lock != NULL);
do {
lock = lock_rec_get_next_on_page(lock);
} while (lock != NULL
&& lock != wait_lock
&& !lock_rec_get_nth_bit(lock, heap_no));
if (lock == wait_lock) {
lock = NULL;
}
}
}/* end of the 'for (;;)'-loop */
}
@ -3706,9 +3766,10 @@ lock_table_enqueue_waiting(
/*********************************************************************//**
Checks if other transactions have an incompatible mode lock request in
the lock queue. */
the lock queue.
@return lock or NULL */
UNIV_INLINE
ibool
lock_t*
lock_table_other_has_incompatible(
/*==============================*/
trx_t* trx, /*!< in: transaction, or NULL if all
@ -3730,13 +3791,13 @@ lock_table_other_has_incompatible(
&& (!lock_mode_compatible(lock_get_mode(lock), mode))
&& (wait || !(lock_get_wait(lock)))) {
return(TRUE);
return(lock);
}
lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);
}
return(FALSE);
return(NULL);
}
/*********************************************************************//**
@ -4260,31 +4321,34 @@ lock_rec_print(
putc('\n', file);
if ( srv_show_verbose_locks ) {
block = buf_page_try_get(space, page_no, &mtr);
if (block) {
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
block = buf_page_try_get(space, page_no, &mtr);
if (lock_rec_get_nth_bit(lock, i)) {
for (i = 0; i < lock_rec_get_n_bits(lock); ++i) {
const rec_t* rec
= page_find_rec_with_heap_no(
buf_block_get_frame(block), i);
offsets = rec_get_offsets(
rec, lock->index, offsets,
ULINT_UNDEFINED, &heap);
fprintf(file, "Record lock, heap no %lu ",
(ulong) i);
rec_print_new(file, rec, offsets);
putc('\n', file);
}
}
} else {
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
fprintf(file, "Record lock, heap no %lu\n", (ulong) i);
}
if (!lock_rec_get_nth_bit(lock, i)) {
continue;
}
fprintf(file, "Record lock, heap no %lu", (ulong) i);
if (block) {
const rec_t* rec;
rec = page_find_rec_with_heap_no(
buf_block_get_frame(block), i);
offsets = rec_get_offsets(
rec, lock->index, offsets,
ULINT_UNDEFINED, &heap);
putc(' ', file);
rec_print_new(file, rec, offsets);
}
putc('\n', file);
}
}
mtr_commit(&mtr);
if (UNIV_LIKELY_NULL(heap)) {
mem_heap_free(heap);
@ -4329,14 +4393,26 @@ lock_get_n_rec_locks(void)
#endif /* PRINT_NUM_OF_LOCK_STRUCTS */
/*********************************************************************//**
Prints info of locks for all transactions. */
Prints info of locks for all transactions.
@return FALSE if not able to obtain kernel mutex
and exits without printing info */
UNIV_INTERN
void
ibool
lock_print_info_summary(
/*====================*/
FILE* file) /*!< in: file where to print */
FILE* file, /*!< in: file where to print */
ibool nowait) /*!< in: whether to wait for the kernel mutex */
{
lock_mutex_enter_kernel();
/* if nowait is FALSE, wait on the kernel mutex,
otherwise return immediately if fail to obtain the
mutex. */
if (!nowait) {
lock_mutex_enter_kernel();
} else if (mutex_enter_nowait(&kernel_mutex)) {
fputs("FAIL TO OBTAIN KERNEL MUTEX, "
"SKIP LOCK INFO PRINTING\n", file);
return(FALSE);
}
if (lock_deadlock_found) {
fputs("------------------------\n"
@ -4368,6 +4444,7 @@ lock_print_info_summary(
"Total number of lock structs in row lock hash table %lu\n",
(ulong) lock_get_n_rec_locks());
#endif /* PRINT_NUM_OF_LOCK_STRUCTS */
return(TRUE);
}
/*********************************************************************//**
@ -4648,6 +4725,7 @@ lock_rec_queue_validate(
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
block, heap_no, impl_trx));
}
#if 0
} else {
/* The kernel mutex may get released temporarily in the
@ -4658,6 +4736,27 @@ lock_rec_queue_validate(
(fil_space_t::latch), the following check WILL break
latching order and may cause a deadlock of threads. */
/* NOTE: This is a bogus check that would fail in the
following case: Our transaction is updating a
row. After it has updated the clustered index record,
it goes to a secondary index record and finds someone
else holding an explicit S- or X-lock on that
secondary index record, presumably from a locking
read. Our transaction cannot update the secondary
index immediately, but places a waiting X-lock request
on the secondary index record. There is nothing
illegal in this. The assertion is simply too strong. */
/* From the locking point of view, each secondary
index is a separate table. A lock that is held on
secondary index rec does not give any rights to modify
or read the clustered index rec. Therefore, we can
think of the sec index as a separate 'table' from the
clust index 'table'. Conversely, a transaction that
has acquired a lock on and modified a clustered index
record may need to wait for a lock on the
corresponding record in a secondary index. */
impl_trx = lock_sec_rec_some_has_impl_off_kernel(
rec, index, offsets);
@ -4668,6 +4767,7 @@ lock_rec_queue_validate(
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
block, heap_no, impl_trx));
}
#endif
}
lock = lock_rec_get_first(block, heap_no);
@ -4765,6 +4865,13 @@ loop:
|| lock->trx->conc_state == TRX_PREPARED
|| lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY);
# ifdef UNIV_SYNC_DEBUG
/* Only validate the record queues when this thread is not
holding a space->latch. Deadlocks are possible due to
latching order violation when UNIV_DEBUG is defined while
UNIV_SYNC_DEBUG is not. */
if (!sync_thread_levels_contains(SYNC_FSP))
# endif /* UNIV_SYNC_DEBUG */
for (i = nth_bit; i < lock_rec_get_n_bits(lock); i++) {
if (i == 1 || lock_rec_get_nth_bit(lock, i)) {
@ -4930,7 +5037,7 @@ lock_rec_insert_check_and_lock(
}
trx = thr_get_trx(thr);
next_rec = page_rec_get_next((rec_t*) rec);
next_rec = page_rec_get_next_const(rec);
next_rec_heap_no = page_rec_get_heap_no(next_rec);
lock_mutex_enter_kernel();

View file

@ -1,23 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
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 the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2009, Google Inc.
Portions of this file contain modifications contributed and copyrighted by
@ -2045,7 +2028,7 @@ log_checkpoint(
return(TRUE);
}
ut_ad(log_sys->written_to_all_lsn >= oldest_lsn);
ut_ad(log_sys->flushed_to_disk_lsn >= oldest_lsn);
if (log_sys->n_pending_checkpoint_writes > 0) {
/* A checkpoint write is running */
@ -3127,7 +3110,7 @@ loop:
if (srv_fast_shutdown < 2
&& (srv_error_monitor_active
|| srv_lock_timeout_and_monitor_active)) {
|| srv_lock_timeout_active || srv_monitor_active)) {
mutex_exit(&kernel_mutex);

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1997, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1997, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -138,7 +138,9 @@ UNIV_INTERN ulint recv_max_parsed_page_no;
/** This many frames must be left free in the buffer pool when we scan
the log and store the scanned log records in the buffer pool: we will
use these free frames to read in pages when we start applying the
log records to the database. */
log records to the database.
This is the default value. If the actual size of the buffer pool is
larger than 10 MB we'll set this value to 512. */
UNIV_INTERN ulint recv_n_pool_free_frames;
/** The maximum lsn we see for a page during the recovery process. If this
@ -242,6 +244,7 @@ recv_sys_mem_free(void)
}
}
#ifndef UNIV_HOTBACKUP
/************************************************************
Reset the state of the recovery system variables. */
UNIV_INTERN
@ -251,7 +254,7 @@ recv_sys_var_init(void)
{
recv_lsn_checks_on = FALSE;
recv_n_pool_free_frames = 1024;
recv_n_pool_free_frames = 256;
recv_recovery_on = FALSE;
@ -277,10 +280,11 @@ recv_sys_var_init(void)
recv_max_parsed_page_no = 0;
recv_n_pool_free_frames = 1024;
recv_n_pool_free_frames = 256;
recv_max_page_lsn = 0;
}
#endif /* !UNIV_HOTBACKUP */
/************************************************************
Inits the recovery system for a recovery operation. */
@ -295,20 +299,37 @@ recv_sys_init(
return;
}
/* Initialize red-black tree for fast insertions into the
flush_list during recovery process.
As this initialization is done while holding the buffer pool
mutex we perform it before acquiring recv_sys->mutex. */
#ifndef UNIV_HOTBACKUP
buf_flush_init_flush_rbt();
mutex_enter(&(recv_sys->mutex));
#ifndef UNIV_HOTBACKUP
recv_sys->heap = mem_heap_create_in_buffer(256);
#else /* !UNIV_HOTBACKUP */
recv_sys->heap = mem_heap_create(256);
recv_is_from_backup = TRUE;
#endif /* !UNIV_HOTBACKUP */
/* Set appropriate value of recv_n_pool_free_frames. */
if (buf_pool_get_curr_size() >= (10 * 1024 * 1024)) {
/* Buffer pool of size greater than 10 MB. */
recv_n_pool_free_frames = 512;
}
if (buf_pool_get_curr_size() >= (32 * 1024 * 1024)) {
/* Buffer pool of size greater than 32 MB. */
recv_n_pool_free_frames = 1024;
}
recv_sys->buf = ut_malloc(RECV_PARSING_BUF_SIZE);
recv_sys->len = 0;
recv_sys->recovered_offset = 0;
recv_sys->addr_hash = hash_create(available_memory / 64);
recv_sys->addr_hash = hash_create(available_memory / 512);
recv_sys->n_addrs = 0;
recv_sys->apply_log_recs = FALSE;
@ -348,7 +369,7 @@ recv_sys_empty_hash(void)
hash_table_free(recv_sys->addr_hash);
mem_heap_empty(recv_sys->heap);
recv_sys->addr_hash = hash_create(buf_pool_get_curr_size() / 256);
recv_sys->addr_hash = hash_create(buf_pool_get_curr_size() / 512);
}
#ifndef UNIV_HOTBACKUP
@ -373,6 +394,9 @@ recv_sys_debug_free(void)
recv_sys->last_block_buf_start = NULL;
mutex_exit(&(recv_sys->mutex));
/* Free up the flush_rbt. */
buf_flush_free_flush_rbt();
}
# endif /* UNIV_LOG_DEBUG */
@ -2117,15 +2141,6 @@ recv_parse_log_rec(
}
#endif /* UNIV_LOG_LSN_DEBUG */
/* Check that page_no is sensible */
if (UNIV_UNLIKELY(*page_no > 0x8FFFFFFFUL)) {
recv_sys->found_corrupt_log = TRUE;
return(0);
}
new_ptr = recv_parse_or_apply_log_rec_body(*type, new_ptr, end_ptr,
NULL, NULL);
if (UNIV_UNLIKELY(new_ptr == NULL)) {
@ -2234,6 +2249,14 @@ recv_report_corrupt_log(
putc('\n', stderr);
}
#ifndef UNIV_HOTBACKUP
if (!srv_force_recovery) {
fputs("InnoDB: Set innodb_force_recovery"
" to ignore this error.\n", stderr);
ut_error;
}
#endif /* !UNIV_HOTBACKUP */
fputs("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"
@ -2623,7 +2646,7 @@ recv_scan_log_recs(
ut_ad(start_lsn % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(len % OS_FILE_LOG_BLOCK_SIZE == 0);
ut_ad(len > 0);
ut_ad(len >= OS_FILE_LOG_BLOCK_SIZE);
ut_a(store_to_hash <= TRUE);
finished = FALSE;
@ -2748,6 +2771,16 @@ recv_scan_log_recs(
recv_sys->found_corrupt_log = TRUE;
#ifndef UNIV_HOTBACKUP
if (!srv_force_recovery) {
fputs("InnoDB: Set"
" innodb_force_recovery"
" to ignore this error.\n",
stderr);
ut_error;
}
#endif /* !UNIV_HOTBACKUP */
} else if (!recv_sys->found_corrupt_log) {
more_data = recv_sys_add_to_parsing_buf(
log_block, scanned_lsn);
@ -3277,8 +3310,6 @@ void
recv_recovery_from_checkpoint_finish(void)
/*======================================*/
{
int i;
/* Apply the hashed log records to the respective file pages */
if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) {
@ -3404,9 +3435,16 @@ recv_recovery_from_checkpoint_finish(void)
The data dictionary latch should guarantee that there is at
most one data dictionary transaction active at a time. */
trx_rollback_or_clean_recovered(FALSE);
}
/* Drop partially created indexes. */
row_merge_drop_temp_indexes();
/********************************************************//**
Initiates the rollback of active transactions. */
UNIV_INTERN
void
recv_recovery_rollback_active(void)
/*===============================*/
{
int i;
#ifdef UNIV_SYNC_DEBUG
/* Wait for a while so that created threads have time to suspend
@ -3416,6 +3454,11 @@ recv_recovery_from_checkpoint_finish(void)
/* Switch latching order checks on in sync0sync.c */
sync_order_checks_on = TRUE;
#endif
/* Drop partially created indexes. */
row_merge_drop_temp_indexes();
/* Drop temporary tables. */
row_mysql_drop_temp_tables();
if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) {
/* Rollback the uncommitted transactions which have no user
session */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -180,6 +180,10 @@ mem_close(void)
{
mem_pool_free(mem_comm_pool);
mem_comm_pool = NULL;
#ifdef UNIV_MEM_DEBUG
mutex_free(&mem_hash_mutex);
mem_hash_initialized = FALSE;
#endif /* UNIV_MEM_DEBUG */
}
#endif /* !UNIV_HOTBACKUP */

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -383,6 +383,20 @@ mem_heap_create_block(
mem_block_set_free(block, MEM_BLOCK_HEADER_SIZE);
mem_block_set_start(block, MEM_BLOCK_HEADER_SIZE);
if (UNIV_UNLIKELY(heap == NULL)) {
/* This is the first block of the heap. The field
total_size should be initialized here */
block->total_size = len;
} else {
/* Not the first allocation for the heap. This block's
total_length field should be set to undefined. */
ut_d(block->total_size = ULINT_UNDEFINED);
UNIV_MEM_INVALID(&block->total_size,
sizeof block->total_size);
heap->total_size += len;
}
ut_ad((ulint)MEM_BLOCK_HEADER_SIZE < len);
return(block);
@ -471,6 +485,10 @@ mem_heap_block_free(
mem_pool_mutex_exit();
#endif
ut_ad(heap->total_size >= block->len);
heap->total_size -= block->len;
type = heap->type;
len = block->len;
block->magic_n = MEM_FREED_BLOCK_MAGIC_N;

View file

@ -1,23 +1,6 @@
/*****************************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
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 the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
/***********************************************************************
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
Copyright (c) 2009, Percona Inc.
Portions of this file contain modifications contributed and copyrighted
@ -846,7 +829,15 @@ next_file:
#ifdef HAVE_READDIR_R
ret = readdir_r(dir, (struct dirent*)dirent_buf, &ent);
if (ret != 0) {
if (ret != 0
#ifdef UNIV_AIX
/* On AIX, only if we got non-NULL 'ent' (result) value and
a non-zero 'ret' (return) value, it indicates a failed
readdir_r() call. An NULL 'ent' with an non-zero 'ret'
would indicate the "end of the directory" is reached. */
&& ent != NULL
#endif
) {
fprintf(stderr,
"InnoDB: cannot read directory %s, error %lu\n",
dirname, (ulong)ret);
@ -4030,6 +4021,9 @@ os_aio_simulated_handle(
ulint i;
time_t now;
/* Fix compiler warning */
*consecutive_ios = NULL;
segment = os_aio_get_array_and_local_segment(&array, global_segment);
restart:

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 1994, 2009, Innobase Oy. All Rights Reserved.
Copyright (c) 1994, 2010, Innobase Oy. All Rights Reserved.
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 the Free Software
@ -658,6 +658,14 @@ page_copy_rec_list_end(
index, mtr);
}
/* Update PAGE_MAX_TRX_ID on the uncompressed page.
Modifications will be redo logged and copied to the compressed
page in page_zip_compress() or page_zip_reorganize() below. */
if (dict_index_is_sec_or_ibuf(index) && page_is_leaf(page)) {
page_update_max_trx_id(new_block, NULL,
page_get_max_trx_id(page), mtr);
}
if (UNIV_LIKELY_NULL(new_page_zip)) {
mtr_set_log_mode(mtr, log_mode);
@ -696,15 +704,10 @@ page_copy_rec_list_end(
}
}
/* Update the lock table, MAX_TRX_ID, and possible hash index */
/* Update the lock table and possible hash index */
lock_move_rec_list_end(new_block, block, rec);
if (dict_index_is_sec_or_ibuf(index) && page_is_leaf(page)) {
page_update_max_trx_id(new_block, new_page_zip,
page_get_max_trx_id(page), mtr);
}
btr_search_move_or_delete_hash_entries(new_block, block, index);
return(ret);
@ -772,6 +775,16 @@ page_copy_rec_list_start(
mem_heap_free(heap);
}
/* Update PAGE_MAX_TRX_ID on the uncompressed page.
Modifications will be redo logged and copied to the compressed
page in page_zip_compress() or page_zip_reorganize() below. */
if (dict_index_is_sec_or_ibuf(index)
&& page_is_leaf(page_align(rec))) {
page_update_max_trx_id(new_block, NULL,
page_get_max_trx_id(page_align(rec)),
mtr);
}
if (UNIV_LIKELY_NULL(new_page_zip)) {
mtr_set_log_mode(mtr, log_mode);
@ -809,14 +822,7 @@ page_copy_rec_list_start(
}
}
/* Update MAX_TRX_ID, the lock table, and possible hash index */
if (dict_index_is_sec_or_ibuf(index)
&& page_is_leaf(page_align(rec))) {
page_update_max_trx_id(new_block, new_page_zip,
page_get_max_trx_id(page_align(rec)),
mtr);
}
/* Update the lock table and possible hash index */
lock_move_rec_list_start(new_block, block, rec, ret);
@ -2408,8 +2414,13 @@ page_validate(
}
offs = page_offset(rec_get_start(rec, offsets));
i = rec_offs_size(offsets);
if (UNIV_UNLIKELY(offs + i >= UNIV_PAGE_SIZE)) {
fputs("InnoDB: record offset out of bounds\n", stderr);
goto func_exit;
}
for (i = rec_offs_size(offsets); i--; ) {
while (i--) {
if (UNIV_UNLIKELY(buf[offs + i])) {
/* No other record may overlap this */
@ -2517,8 +2528,13 @@ n_owned_zero:
count++;
offs = page_offset(rec_get_start(rec, offsets));
i = rec_offs_size(offsets);
if (UNIV_UNLIKELY(offs + i >= UNIV_PAGE_SIZE)) {
fputs("InnoDB: record offset out of bounds\n", stderr);
goto func_exit;
}
for (i = rec_offs_size(offsets); i--; ) {
while (i--) {
if (UNIV_UNLIKELY(buf[offs + i])) {
fputs("InnoDB: Record overlaps another"

View file

@ -0,0 +1,28 @@
# Establish connection con1 (user=root)
# Establish connection con2 (user=root)
# Establish connection con3 (user=root)
# Drop test table
drop table if exists t;
# Create test table
create table t(a INT PRIMARY KEY, b INT) engine=InnoDB;
# Insert two rows to test table
insert into t values(2,1);
insert into t values(1,2);
# Switch to connection con1
BEGIN;
SELECT b FROM t WHERE a=1 FOR UPDATE;
b
2
# Switch to connection con2
BEGIN;
SELECT b FROM t WHERE a=2 FOR UPDATE;
b
1
# Switch to connection con1
SELECT b FROM t WHERE a=2 FOR UPDATE;
# Switch to connection con2
SELECT b FROM t WHERE a=1 FOR UPDATE;
# Switch to connection con3
1
# Drop test table
drop table t;

View file

@ -0,0 +1,49 @@
--source include/have_innodb.inc
--echo # Establish connection con1 (user=root)
connect (con1,localhost,root,,);
--echo # Establish connection con2 (user=root)
connect (con2,localhost,root,,);
--echo # Establish connection con3 (user=root)
connect (con3,localhost,root,,);
--echo # Drop test table
--disable_warnings
drop table if exists t;
--enable_warnings
disable_abort_on_error;
--echo # Create test table
create table t(a INT PRIMARY KEY, b INT) engine=InnoDB;
--echo # Insert two rows to test table
insert into t values(2,1);
insert into t values(1,2);
#--echo # Save current deadlock count
let $current = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Innodb_deadlocks'`;
--echo # Switch to connection con1
connection con1;
BEGIN; SELECT b FROM t WHERE a=1 FOR UPDATE;
#show engine innodb status;
--echo # Switch to connection con2
connection con2;
BEGIN; SELECT b FROM t WHERE a=2 FOR UPDATE;
--echo # Switch to connection con1
connection con1;
SEND SELECT b FROM t WHERE a=2 FOR UPDATE;
--echo # Switch to connection con2
connection con2;
SEND SELECT b FROM t WHERE a=1 FOR UPDATE;
SLEEP 0.2;
--echo # Switch to connection con3
connection con3;
let $result = `SELECT VARIABLE_VALUE FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'Innodb_deadlocks'`;
let $diff = `SELECT $result - $current`;
echo $diff;
--echo # Drop test table
drop table t;

View file

@ -0,0 +1 @@
--innodb_doublewrite_file=ib_doublewrite

View file

@ -0,0 +1,4 @@
show variables like 'innodb_doublewrite%';
Variable_name Value
innodb_doublewrite ON
innodb_doublewrite_file ib_doublewrite

View file

@ -0,0 +1,2 @@
--source include/have_innodb.inc
show variables like 'innodb_doublewrite%';

View file

@ -0,0 +1 @@
--slow-query-log-file=percona_log_slow_slave_statements-master.log --long-query-time=1

View file

@ -0,0 +1 @@
--slow-query-log-file=percona_log_slow_slave_statements-slave.log --long-query-time=1

View file

@ -0,0 +1,103 @@
# Activate master-slave replication
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
# Make table t for test
DROP TABLE IF EXISTS t;
CREATE TABLE t(id INT);
# Start slave replication
START SLAVE;
INSERT INTO t VALUES (1);
# Read information about master binlog
# Sync(1) slave thread
# Read and change log_slow_slave_statements to ON on slave
show variables like 'log_slow_slave_statements';
Variable_name Value
log_slow_slave_statements OFF
set global log_slow_slave_statements=ON;
show variables like 'log_slow_slave_statements';
Variable_name Value
log_slow_slave_statements ON
INSERT INTO t VALUES (2);
# Read information about master binlog
# Sync slave(2) thread
# Restart slave
STOP SLAVE;
START SLAVE;
INSERT INTO t VALUES (3);
# Read information about master binlog
# Sync(3) slave thread
show variables like 'long_query_time';
Variable_name Value
long_query_time 1.000000
show global variables like 'long_query_time';
Variable_name Value
long_query_time 1.000000
show global variables like 'use_global_long_query_time';
Variable_name Value
use_global_long_query_time OFF
set global long_query_time=0;
show variables like 'long_query_time';
Variable_name Value
long_query_time 1.000000
show global variables like 'long_query_time';
Variable_name Value
long_query_time 0.000000
show global variables like 'use_global_long_query_time';
Variable_name Value
use_global_long_query_time OFF
INSERT INTO t VALUES (4);
# Read information about master binlog
# Sync slave(4) thread
show variables like 'long_query_time';
Variable_name Value
long_query_time 1.000000
show global variables like 'long_query_time';
Variable_name Value
long_query_time 0.000000
show global variables like 'use_global_long_query_time';
Variable_name Value
use_global_long_query_time OFF
set global use_global_long_query_time=1;
show variables like 'long_query_time';
Variable_name Value
long_query_time 0.000000
show global variables like 'long_query_time';
Variable_name Value
long_query_time 0.000000
show global variables like 'use_global_long_query_time';
Variable_name Value
use_global_long_query_time ON
INSERT INTO t VALUES (5);
# Read information about master binlog
# Sync slave(5) thread
show variables like 'long_query_time';
Variable_name Value
long_query_time 0.000000
show global variables like 'long_query_time';
Variable_name Value
long_query_time 0.000000
show global variables like 'use_global_long_query_time';
Variable_name Value
use_global_long_query_time ON
set global long_query_time=1;
set global use_global_long_query_time=0;
# Analyse master slow_query_log
0
0
0
0
0
# Analyse slave slow_query_log
0
0
0
0
1
set global log_slow_slave_statements=OFF;
DROP TABLE t;
# Read information about master binlog
# Sync slave(6) thread

View file

@ -0,0 +1,137 @@
-- echo # Activate master-slave replication
-- source include/master-slave.inc
connection master;
-- echo # Make table t for test
-- disable_warnings
DROP TABLE IF EXISTS t;
-- enable_warnings
CREATE TABLE t(id INT);
-- echo # Start slave replication
-- disable_warnings
connection slave;
START SLAVE;
-- source include/wait_for_slave_to_start.inc
-- enable_warnings
#-- echo # Make insert(1) on master
connection master;
INSERT INTO t VALUES (1);
-- echo # Read information about master binlog
let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1);
let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
-- echo # Sync(1) slave thread
connection slave;
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;
-- echo # Read and change log_slow_slave_statements to ON on slave
show variables like 'log_slow_slave_statements';
set global log_slow_slave_statements=ON;
show variables like 'log_slow_slave_statements';
#-- echo # Make insert(2) on master
connection master;
INSERT INTO t VALUES (2);
-- echo # Read information about master binlog
let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1);
let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
-- echo # Sync slave(2) thread
connection slave;
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;
-- echo # Restart slave
STOP SLAVE;
-- source include/wait_for_slave_to_stop.inc
START SLAVE;
-- source include/wait_for_slave_to_start.inc
#-- echo # Make insert(3) on master
connection master;
INSERT INTO t VALUES (3);
-- echo # Read information about master binlog
let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1);
let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
-- echo # Sync(3) slave thread
connection slave;
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;
show variables like 'long_query_time';
show global variables like 'long_query_time';
show global variables like 'use_global_long_query_time';
set global long_query_time=0;
show variables like 'long_query_time';
show global variables like 'long_query_time';
show global variables like 'use_global_long_query_time';
#-- echo # Make insert(4) on master
connection master;
INSERT INTO t VALUES (4);
-- echo # Read information about master binlog
let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1);
let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
-- echo # Sync slave(4) thread
connection slave;
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;
show variables like 'long_query_time';
show global variables like 'long_query_time';
show global variables like 'use_global_long_query_time';
set global use_global_long_query_time=1;
show variables like 'long_query_time';
show global variables like 'long_query_time';
show global variables like 'use_global_long_query_time';
#-- echo # Make insert(5) on master
connection master;
INSERT INTO t VALUES (5);
-- echo # Read information about master binlog
let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1);
let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
-- echo # Sync slave(5) thread
connection slave;
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;
show variables like 'long_query_time';
show global variables like 'long_query_time';
show global variables like 'use_global_long_query_time';
set global long_query_time=1;
set global use_global_long_query_time=0;
-- echo # Analyse master slow_query_log
let $i=5;
let $k=1;
let $cmd=cat ./var/mysqld.1/data/percona_log_slow_slave_statements-master.log | grep;
while($i)
{
let $current_cmd = $cmd "INSERT INTO t VALUES ($k)" | wc -l;
exec $current_cmd;
dec $i;
inc $k;
}
-- echo # Analyse slave slow_query_log
let $i=5;
let $k=1;
let $cmd=cat ./var/mysqld.2/data/percona_log_slow_slave_statements-slave.log | grep;
while($i)
{
let $current_cmd = $cmd "INSERT INTO t VALUES ($k)" | wc -l;
exec $current_cmd;
dec $i;
inc $k;
}
set global log_slow_slave_statements=OFF;
connection master;
DROP TABLE t;
-- echo # Read information about master binlog
let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1);
let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
-- echo # Sync slave(6) thread
connection slave;
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;

View file

@ -0,0 +1 @@
--slow-query-log-file=percona_log_slow_slave_statements-master.log --long-query-time=0

View file

@ -0,0 +1 @@
--slow-query-log-file=percona_log_slow_slave_statements-slave.log --long-query-time=0

View file

@ -0,0 +1,86 @@
# Activate master-slave replication
stop slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
reset master;
reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave;
# Make table t for test
DROP TABLE IF EXISTS t;
CREATE TABLE t(id INT);
# Start slave replication
START SLAVE;
INSERT INTO t VALUES (1);
# Read information about master binlog
# Sync(1) slave thread
# Read and change log_slow_slave_statements to ON on slave
show variables like 'log_slow_slave_statements';
Variable_name Value
log_slow_slave_statements OFF
set global log_slow_slave_statements=ON;
show variables like 'log_slow_slave_statements';
Variable_name Value
log_slow_slave_statements ON
INSERT INTO t VALUES (2);
# Read information about master binlog
# Sync slave(2) thread
# Restart slave
STOP SLAVE;
START SLAVE;
INSERT INTO t VALUES (3);
# Read information about master binlog
# Sync(3) slave thread
# Read and change log_slow_slave_statements to OFF on slave
show variables like 'log_slow_slave_statements';
Variable_name Value
log_slow_slave_statements ON
set global log_slow_slave_statements=OFF;
show variables like 'log_slow_slave_statements';
Variable_name Value
log_slow_slave_statements OFF
INSERT INTO t VALUES (4);
# Read information about master binlog
# Sync slave(4) thread
# Restart slave
STOP SLAVE;
START SLAVE;
INSERT INTO t VALUES (5);
# Read information about master binlog
# Sync slave(5) thread
# Read and change log_slow_slave_statements to ON on slave
show variables like 'log_slow_slave_statements';
Variable_name Value
log_slow_slave_statements OFF
set global log_slow_slave_statements=ON;
show variables like 'log_slow_slave_statements';
Variable_name Value
log_slow_slave_statements ON
INSERT INTO t VALUES (6);
# Read information about master binlog
# Sync slave(6) thread
# Restart slave
STOP SLAVE;
START SLAVE;
INSERT INTO t VALUES (7);
# Read information about master binlog
# Sync slave(7) thread
# Analyse master slow_query_log
1
1
1
1
1
1
1
# Analyse slave slow_query_log
0
0
1
0
0
0
1
set global log_slow_slave_statements=OFF;
DROP TABLE t;
# Read information about master binlog
# Sync slave(8) thread

View file

@ -0,0 +1,158 @@
-- echo # Activate master-slave replication
-- source include/master-slave.inc
connection master;
-- echo # Make table t for test
-- disable_warnings
DROP TABLE IF EXISTS t;
-- enable_warnings
CREATE TABLE t(id INT);
-- echo # Start slave replication
-- disable_warnings
connection slave;
START SLAVE;
-- source include/wait_for_slave_to_start.inc
-- enable_warnings
#-- echo # Make insert(1) on master
connection master;
INSERT INTO t VALUES (1);
-- echo # Read information about master binlog
let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1);
let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
-- echo # Sync(1) slave thread
connection slave;
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;
-- echo # Read and change log_slow_slave_statements to ON on slave
show variables like 'log_slow_slave_statements';
set global log_slow_slave_statements=ON;
show variables like 'log_slow_slave_statements';
#-- echo # Make insert(2) on master
connection master;
INSERT INTO t VALUES (2);
-- echo # Read information about master binlog
let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1);
let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
-- echo # Sync slave(2) thread
connection slave;
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;
-- echo # Restart slave
STOP SLAVE;
-- source include/wait_for_slave_to_stop.inc
START SLAVE;
-- source include/wait_for_slave_to_start.inc
#-- echo # Make insert(3) on master
connection master;
INSERT INTO t VALUES (3);
-- echo # Read information about master binlog
let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1);
let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
-- echo # Sync(3) slave thread
connection slave;
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;
-- echo # Read and change log_slow_slave_statements to OFF on slave
show variables like 'log_slow_slave_statements';
set global log_slow_slave_statements=OFF;
show variables like 'log_slow_slave_statements';
#-- echo # Make insert(4) on master
connection master;
INSERT INTO t VALUES (4);
-- echo # Read information about master binlog
let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1);
let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
-- echo # Sync slave(4) thread
connection slave;
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;
-- echo # Restart slave
STOP SLAVE;
-- source include/wait_for_slave_to_stop.inc
START SLAVE;
-- source include/wait_for_slave_to_start.inc
#-- echo # Make insert(5) on master
connection master;
INSERT INTO t VALUES (5);
-- echo # Read information about master binlog
let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1);
let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
-- echo # Sync slave(5) thread
connection slave;
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;
-- echo # Read and change log_slow_slave_statements to ON on slave
show variables like 'log_slow_slave_statements';
set global log_slow_slave_statements=ON;
show variables like 'log_slow_slave_statements';
#-- echo # Make insert(6) on master
connection master;
INSERT INTO t VALUES (6);
-- echo # Read information about master binlog
let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1);
let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
-- echo # Sync slave(6) thread
connection slave;
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;
-- echo # Restart slave
STOP SLAVE;
-- source include/wait_for_slave_to_stop.inc
START SLAVE;
-- source include/wait_for_slave_to_start.inc
#-- echo # Make insert(7) on master
connection master;
INSERT INTO t VALUES (7);
-- echo # Read information about master binlog
let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1);
let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
-- echo # Sync slave(7) thread
connection slave;
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;
-- echo # Analyse master slow_query_log
let $i=7;
let $k=1;
let $cmd=cat ./var/mysqld.1/data/percona_log_slow_slave_statements-master.log | grep;
while($i)
{
let $current_cmd = $cmd "INSERT INTO t VALUES ($k)" | wc -l;
exec $current_cmd;
dec $i;
inc $k;
}
-- echo # Analyse slave slow_query_log
let $i=7;
let $k=1;
let $cmd=cat ./var/mysqld.2/data/percona_log_slow_slave_statements-slave.log | grep;
while($i)
{
let $current_cmd = $cmd "INSERT INTO t VALUES ($k)" | wc -l;
exec $current_cmd;
dec $i;
inc $k;
}
set global log_slow_slave_statements=OFF;
connection master;
DROP TABLE t;
-- echo # Read information about master binlog
let $binlog_file = query_get_value(SHOW MASTER STATUS,File,1);
let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
-- echo # Sync slave(8) thread
connection slave;
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;

View file

@ -0,0 +1,95 @@
--source include/percona_query_cache_with_comments_clear.inc
let $query=/* with comment first */select * from t1;
eval $query;
--source include/percona_query_cache_with_comments_eval.inc
let $query=# with comment first
select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=-- with comment first
select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=/* with comment first and "quote" */select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=# with comment first and "quote"
select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=-- with comment first and "quote"
select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=
/* with comment and whitespaces first */select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=
# with comment and whitespaces first
select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=
-- with comment and whitespaces first
select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $internal=* internal comment *;
let $query=select * /$internal/ from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select */$internal/ from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select */$internal/from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $internal=* internal comment with "quote" *;
let $query=select * /$internal/ from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select */$internal/ from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select */$internal/from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1
;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1 ;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1 ;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1
/* comment in the end */;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1
/* *\/ */;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1
/* comment in the end */
;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1 #comment in the end;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1 #comment in the end
;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1 -- comment in the end;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1 -- comment in the end
;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select ' \' ' from t1;
--source include/percona_query_cache_with_comments_eval.inc

View file

@ -0,0 +1,88 @@
--source include/percona_query_cache_with_comments_clear.inc
let $query=/* with comment first */select * from t1;
eval $query;
--source include/percona_query_cache_with_comments_eval.inc
let $query=# with comment first
select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=-- with comment first
select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=/* with comment first and "quote" */select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=# with comment first and "quote"
select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=-- with comment first and "quote"
select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=
/* with comment and whitespaces first */select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=
# with comment and whitespaces first
select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=
-- with comment and whitespaces first
select * from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $internal=* internal comment *;
let $query=select * /$internal/ from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select */$internal/ from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select */$internal/from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $internal=* internal comment with "quote" *;
let $query=select * /$internal/ from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select */$internal/ from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select */$internal/from t1;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1
;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1 ;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1 ;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1
/* comment in the end */;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1
/* comment in the end */
;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1 #comment in the end;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1 #comment in the end
;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1 -- comment in the end;
--source include/percona_query_cache_with_comments_eval.inc
let $query=select * from t1 -- comment in the end
;
--source include/percona_query_cache_with_comments_eval.inc

View file

@ -0,0 +1,866 @@
set global query_cache_strip_comments=ON;
set GLOBAL query_cache_size=1355776;
drop table if exists t1;
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
flush query cache;
flush query cache;
reset query cache;
flush status;
flush query cache;
flush query cache;
reset query cache;
flush status;
/* with comment first */select * from t1;
a
1
2
3
-----------------------------------------------------
/* with comment first */select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
/* with comment first */select * from t1;
a
1
2
3
/* with comment first */select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 2
-----------------------------------------------------
# with comment first
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 2
# with comment first
select * from t1;
a
1
2
3
# with comment first
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 4
-----------------------------------------------------
-- with comment first
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 4
-- with comment first
select * from t1;
a
1
2
3
-- with comment first
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 6
-----------------------------------------------------
/* with comment first and "quote" */select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 6
/* with comment first and "quote" */select * from t1;
a
1
2
3
/* with comment first and "quote" */select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 8
-----------------------------------------------------
# with comment first and "quote"
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 8
# with comment first and "quote"
select * from t1;
a
1
2
3
# with comment first and "quote"
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 10
-----------------------------------------------------
-- with comment first and "quote"
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 10
-- with comment first and "quote"
select * from t1;
a
1
2
3
-- with comment first and "quote"
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 12
-----------------------------------------------------
/* with comment and whitespaces first */select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 12
/* with comment and whitespaces first */select * from t1;
a
1
2
3
/* with comment and whitespaces first */select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 14
-----------------------------------------------------
# with comment and whitespaces first
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 14
# with comment and whitespaces first
select * from t1;
a
1
2
3
# with comment and whitespaces first
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 16
-----------------------------------------------------
-- with comment and whitespaces first
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 16
-- with comment and whitespaces first
select * from t1;
a
1
2
3
-- with comment and whitespaces first
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 18
-----------------------------------------------------
select * /* internal comment */ from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 18
select * /* internal comment */ from t1;
a
1
2
3
select * /* internal comment */ from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 20
-----------------------------------------------------
select */* internal comment */ from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 20
select */* internal comment */ from t1;
a
1
2
3
select */* internal comment */ from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 22
-----------------------------------------------------
select */* internal comment */from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 22
select */* internal comment */from t1;
a
1
2
3
select */* internal comment */from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 24
-----------------------------------------------------
select * /* internal comment with "quote" */ from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 24
select * /* internal comment with "quote" */ from t1;
a
1
2
3
select * /* internal comment with "quote" */ from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 26
-----------------------------------------------------
select */* internal comment with "quote" */ from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 26
select */* internal comment with "quote" */ from t1;
a
1
2
3
select */* internal comment with "quote" */ from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 28
-----------------------------------------------------
select */* internal comment with "quote" */from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 28
select */* internal comment with "quote" */from t1;
a
1
2
3
select */* internal comment with "quote" */from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 30
-----------------------------------------------------
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 30
select * from t1
;
a
1
2
3
select * from t1
;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 32
-----------------------------------------------------
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 32
select * from t1 ;
a
1
2
3
select * from t1 ;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 34
-----------------------------------------------------
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 34
select * from t1 ;
a
1
2
3
select * from t1 ;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 36
-----------------------------------------------------
select * from t1
/* comment in the end */
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 36
select * from t1
/* comment in the end */;
a
1
2
3
select * from t1
/* comment in the end */;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 38
-----------------------------------------------------
select * from t1
/* *\/ */
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 38
select * from t1
/* *\/ */;
a
1
2
3
select * from t1
/* *\/ */;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 40
-----------------------------------------------------
select * from t1
/* comment in the end */
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 40
select * from t1
/* comment in the end */
;
a
1
2
3
select * from t1
/* comment in the end */
;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 42
-----------------------------------------------------
select * from t1 #comment in the end
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 42
select * from t1 #comment in the end;
a
1
2
3
select * from t1 #comment in the end;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 44
-----------------------------------------------------
select * from t1 #comment in the end
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 44
select * from t1 #comment in the end
;
a
1
2
3
select * from t1 #comment in the end
;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 46
-----------------------------------------------------
select * from t1 -- comment in the end
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 46
select * from t1 -- comment in the end;
a
1
2
3
select * from t1 -- comment in the end;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 48
-----------------------------------------------------
select * from t1 -- comment in the end
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 48
select * from t1 -- comment in the end
;
a
1
2
3
select * from t1 -- comment in the end
;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 50
-----------------------------------------------------
select ' \' ' from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 50
select ' \' ' from t1;
'
'
'
'
select ' \' ' from t1;
'
'
'
'
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 2
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 2
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 51
DROP TABLE t1;
SET GLOBAL query_cache_size=default;
set global query_cache_strip_comments=OFF;

View file

@ -0,0 +1,4 @@
set global query_cache_strip_comments=ON;
-- source include/percona_query_cache_with_comments_begin.inc
-- source include/percona_query_cache_with_comments.inc
-- source include/percona_query_cache_with_comments_end.inc

View file

@ -0,0 +1,12 @@
-- source include/have_query_cache.inc
set GLOBAL query_cache_size=1355776;
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
--source include/percona_query_cache_with_comments_clear.inc

View file

@ -0,0 +1,5 @@
# Reset query cache variables.
flush query cache; # This crashed in some versions
flush query cache; # This crashed in some versions
reset query cache;
flush status;

View file

@ -0,0 +1,21 @@
set GLOBAL query_cache_size=1355776;
drop table if exists t1;
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
flush query cache;
flush query cache;
reset query cache;
flush status;
( select * from t1 );
a
1
2
3
/*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, @@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), @OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, @@SQL_QUOTE_SHOW_CREATE := 1 */;
/* only comment */;
# only comment
;
-- only comment
;
DROP TABLE t1;
SET GLOBAL query_cache_size= default;

View file

@ -0,0 +1,22 @@
-- source include/have_query_cache.inc
set GLOBAL query_cache_size=1355776;
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
flush query cache; # This crashed in some versions
flush query cache; # This crashed in some versions
reset query cache;
flush status;
( select * from t1 );
/*!40101 SET @OLD_SQL_MODE := @@SQL_MODE, @@SQL_MODE := REPLACE(REPLACE(@@SQL_MODE, 'ANSI_QUOTES', ''), ',,', ','), @OLD_QUOTE := @@SQL_QUOTE_SHOW_CREATE, @@SQL_QUOTE_SHOW_CREATE := 1 */;
/* only comment */;
let query=# only comment
;
eval $query;
let query=-- only comment
;
eval $query;
DROP TABLE t1;
SET GLOBAL query_cache_size= default;

View file

@ -0,0 +1,865 @@
set GLOBAL query_cache_size=1355776;
drop table if exists t1;
create table t1 (a int not null);
insert into t1 values (1),(2),(3);
flush query cache;
flush query cache;
reset query cache;
flush status;
flush query cache;
flush query cache;
reset query cache;
flush status;
/* with comment first */select * from t1;
a
1
2
3
-----------------------------------------------------
/* with comment first */select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
/* with comment first */select * from t1;
a
1
2
3
/* with comment first */select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 2
-----------------------------------------------------
# with comment first
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 1
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 2
# with comment first
select * from t1;
a
1
2
3
# with comment first
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 2
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 2
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 2
-----------------------------------------------------
-- with comment first
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 2
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 2
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 2
-- with comment first
select * from t1;
a
1
2
3
-- with comment first
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 2
-----------------------------------------------------
/* with comment first and "quote" */select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 2
/* with comment first and "quote" */select * from t1;
a
1
2
3
/* with comment first and "quote" */select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 4
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 4
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 3
-----------------------------------------------------
# with comment first and "quote"
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 4
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 4
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 3
# with comment first and "quote"
select * from t1;
a
1
2
3
# with comment first and "quote"
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 5
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 5
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 3
-----------------------------------------------------
-- with comment first and "quote"
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 5
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 5
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 3
-- with comment first and "quote"
select * from t1;
a
1
2
3
-- with comment first and "quote"
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 6
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 6
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 3
-----------------------------------------------------
/* with comment and whitespaces first */select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 6
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 6
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 3
/* with comment and whitespaces first */select * from t1;
a
1
2
3
/* with comment and whitespaces first */select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 7
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 7
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 4
-----------------------------------------------------
# with comment and whitespaces first
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 7
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 7
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 4
# with comment and whitespaces first
select * from t1;
a
1
2
3
# with comment and whitespaces first
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 8
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 8
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 4
-----------------------------------------------------
-- with comment and whitespaces first
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 8
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 8
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 4
-- with comment and whitespaces first
select * from t1;
a
1
2
3
-- with comment and whitespaces first
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 9
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 9
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 4
-----------------------------------------------------
select * /* internal comment */ from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 9
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 9
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 4
select * /* internal comment */ from t1;
a
1
2
3
select * /* internal comment */ from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 10
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 10
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 5
-----------------------------------------------------
select */* internal comment */ from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 10
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 10
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 5
select */* internal comment */ from t1;
a
1
2
3
select */* internal comment */ from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 11
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 11
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 6
-----------------------------------------------------
select */* internal comment */from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 11
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 11
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 6
select */* internal comment */from t1;
a
1
2
3
select */* internal comment */from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 12
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 12
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 7
-----------------------------------------------------
select * /* internal comment with "quote" */ from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 12
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 12
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 7
select * /* internal comment with "quote" */ from t1;
a
1
2
3
select * /* internal comment with "quote" */ from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 13
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 13
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 8
-----------------------------------------------------
select */* internal comment with "quote" */ from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 13
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 13
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 8
select */* internal comment with "quote" */ from t1;
a
1
2
3
select */* internal comment with "quote" */ from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 14
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 14
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 9
-----------------------------------------------------
select */* internal comment with "quote" */from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 14
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 14
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 9
select */* internal comment with "quote" */from t1;
a
1
2
3
select */* internal comment with "quote" */from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 15
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 15
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 10
-----------------------------------------------------
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 15
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 15
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 10
select * from t1
;
a
1
2
3
select * from t1
;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 16
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 16
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 11
-----------------------------------------------------
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 16
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 16
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 11
select * from t1 ;
a
1
2
3
select * from t1 ;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 16
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 16
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 13
-----------------------------------------------------
select * from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 16
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 16
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 13
select * from t1 ;
a
1
2
3
select * from t1 ;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 16
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 16
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 15
-----------------------------------------------------
select * from t1
/* comment in the end */
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 16
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 16
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 15
select * from t1
/* comment in the end */;
a
1
2
3
select * from t1
/* comment in the end */;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 17
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 17
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 16
-----------------------------------------------------
select * from t1
/* *\/ */
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 17
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 17
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 16
select * from t1
/* *\/ */;
a
1
2
3
select * from t1
/* *\/ */;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 18
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 18
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 17
-----------------------------------------------------
select * from t1
/* comment in the end */
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 18
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 18
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 17
select * from t1
/* comment in the end */
;
a
1
2
3
select * from t1
/* comment in the end */
;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 18
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 18
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 19
-----------------------------------------------------
select * from t1 #comment in the end
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 18
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 18
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 19
select * from t1 #comment in the end;
a
1
2
3
select * from t1 #comment in the end;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 19
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 19
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 20
-----------------------------------------------------
select * from t1 #comment in the end
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 19
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 19
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 20
select * from t1 #comment in the end
;
a
1
2
3
select * from t1 #comment in the end
;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 19
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 19
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 22
-----------------------------------------------------
select * from t1 -- comment in the end
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 19
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 19
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 22
select * from t1 -- comment in the end;
a
1
2
3
select * from t1 -- comment in the end;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 20
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 20
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 23
-----------------------------------------------------
select * from t1 -- comment in the end
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 20
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 20
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 23
select * from t1 -- comment in the end
;
a
1
2
3
select * from t1 -- comment in the end
;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 20
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 20
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 25
-----------------------------------------------------
select ' \' ' from t1
-----------------------------------------------------
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 20
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 20
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 25
select ' \' ' from t1;
'
'
'
'
select ' \' ' from t1;
'
'
'
'
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 21
show status like "Qcache_inserts";
Variable_name Value
Qcache_inserts 21
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 26
DROP TABLE t1;
SET GLOBAL query_cache_size=default;
set global query_cache_strip_comments=OFF;

View file

@ -0,0 +1,3 @@
-- source include/percona_query_cache_with_comments_begin.inc
-- source include/percona_query_cache_with_comments.inc
-- source include/percona_query_cache_with_comments_end.inc

View file

@ -0,0 +1,3 @@
DROP TABLE t1;
SET GLOBAL query_cache_size=default;
set global query_cache_strip_comments=OFF;

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