Commit 86b85252 authored by marko's avatar marko

branches/innodb+: Merge revisions 3602:3931 from branches/zip:

  ------------------------------------------------------------------------
  r3607 | marko | 2008-12-30 22:33:31 +0200 (Tue, 30 Dec 2008) | 20 lines

  branches/zip: Remove the dependency on the MySQL HASH table implementation.
  Use the InnoDB hash table for keeping track of INNOBASE_SHARE objects.

  struct st_innobase_share: Make table_name const uchar*.  Add the member
  table_name_hash.

  innobase_open_tables: Change the type from HASH to hash_table_t*.

  innobase_get_key(): Remove.

  innobase_fold_name(): New function, for computing the fold value for the
  InnoDB hash table.

  get_share(), free_share(): Use the InnoDB hash functions.

  innobase_end(): Free innobase_open_tables before shutting down InnoDB.
  Shutting down InnoDB will invalidate all memory allocated via InnoDB.

  rb://65 approved by Heikki Tuuri.  This addresses Issue #104.
  ------------------------------------------------------------------------
  r3608 | marko | 2008-12-30 22:45:04 +0200 (Tue, 30 Dec 2008) | 22 lines

  branches/zip: When setting the PAGE_LEVEL of a compressed B-tree page
  from or to 0, compress the page at the same time.  This is necessary,
  because the column information stored on the compressed page will
  differ between leaf and non-leaf pages.  Leaf pages are identified by
  PAGE_LEVEL=0.  This bug was reported as Issue #150.

  Document the similarity between btr_page_create() and
  btr_page_empty().  Make the function signature of btr_page_empty()
  identical with btr_page_create().  (This will add the parameter "level".)

  btr_root_raise_and_insert(): Replace some code with a call to
  btr_page_empty().

  btr_attach_half_pages(): Assert that the page level has already been
  set on both block and new_block.  Do not set it again.

  btr_discard_only_page_on_level(): Document that this function is
  probably never called.  Make it work on any height tree.  (Tested on
  2-high tree by disabling btr_lift_page_up().)

  rb://68
  ------------------------------------------------------------------------
  r3612 | marko | 2009-01-02 11:02:44 +0200 (Fri, 02 Jan 2009) | 14 lines

  branches/zip: Merge c2998 from branches/6.0, so that the same InnoDB Plugin
  source tree will work both under 5.1 and 6.0.  Do not add the test case
  innodb_ctype_ldml.test, because it would not work under MySQL 5.1.

  Refuse to create tables whose columns contain collation IDs above 255.
  This removes an assertion failure that was introduced in WL#4164
  (Two-byte collation IDs).

  create_table_def(): Do not fail an assertion if a column contains a
  charset-collation ID greater than 256. Instead, issue an error and
  refuse to create the table.

  The original change (branches/6.0 r2998) was rb://51 approved by Calvin Sun.
  ------------------------------------------------------------------------
  r3613 | inaam | 2009-01-02 15:10:50 +0200 (Fri, 02 Jan 2009) | 6 lines

  branches/zip: Implement the parameter innodb_use_sys_malloc
  (false by default), for disabling InnoDB's internal memory allocator
  and using system malloc/free instead.

  rb://62 approved by Marko
  ------------------------------------------------------------------------
  r3614 | marko | 2009-01-02 15:55:12 +0200 (Fri, 02 Jan 2009) | 1 line

  branches/zip: ChangeLog: Document r3608 and r3613.
  ------------------------------------------------------------------------
  r3615 | marko | 2009-01-02 15:57:51 +0200 (Fri, 02 Jan 2009) | 1 line

  branches/zip: ChangeLog: Clarify the impact of r3608.
  ------------------------------------------------------------------------
  r3616 | marko | 2009-01-03 00:23:30 +0200 (Sat, 03 Jan 2009) | 1 line

  branches/zip: srv_suspend_mysql_thread(): Add some clarifying comments.
  ------------------------------------------------------------------------
  r3618 | marko | 2009-01-05 12:54:53 +0200 (Mon, 05 Jan 2009) | 15 lines

  branches/zip: Merge revisions 3598:3601 from branches/5.1:

    ------------------------------------------------------------------------
    r3601 | marko | 2008-12-22 16:05:19 +0200 (Mon, 22 Dec 2008) | 9 lines

    branches/5.1: Make
    SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED
    a true replacement of SET GLOBAL INNODB_LOCKS_UNSAFE_FOR_BINLOG=1.
    This fixes an error that was introduced in r370, causing
    semi-consistent read not to not unlock rows in READ COMMITTED mode.
    (Bug #41671, Issue #146)

    rb://67 approved by Heikki Tuuri
    ------------------------------------------------------------------------
  ------------------------------------------------------------------------
  r3623 | vasil | 2009-01-06 09:56:32 +0200 (Tue, 06 Jan 2009) | 7 lines

  branches/zip:

  Add patch to fix the failing main.variables mysql-test. It started failing
  after the variable innodb_use_sys_malloc was added because it matches
  '%alloc%' and the test is badly written and expects that no new variables
  like that will ever be added.
  ------------------------------------------------------------------------
  r3795 | marko | 2009-01-07 16:17:47 +0200 (Wed, 07 Jan 2009) | 7 lines

  branches/zip: row_merge_tuple_cmp(): Do not report a duplicate key value
  if any of the fields are NULL.  While the tuples are equal in the
  sorting order, SQL NULL is defined to be logically inequal to
  anything else. (Bug #41904)

  rb://70 approved by Heikki Tuuri
  ------------------------------------------------------------------------
  r3796 | marko | 2009-01-07 16:19:32 +0200 (Wed, 07 Jan 2009) | 1 line

  branches/zip: Add the tests that were forgotten from r3795.
  ------------------------------------------------------------------------
  r3797 | marko | 2009-01-07 16:22:18 +0200 (Wed, 07 Jan 2009) | 22 lines

  branches/zip: Do not call trx_allocate_for_mysql() directly, but use
  helper functions that initialize some members of the transaction struct.
  (Bug #41680)

  innobase_trx_init(): New function: initialize some fields of a
  transaction struct from a MySQL THD object.

  innobase_trx_allocate(): New function: allocate and initialize a
  transaction struct.

  check_trx_exists(): Use the above two functions.

  ha_innobase::delete_table(), ha_innobase::rename_table(),
  ha_innobase::add_index(), ha_innobase::final_drop_index():
  Use innobase_trx_allocate().

  innobase_drop_database(): In the Windows plugin, initialize the trx_t
  specially, because the THD is not available.  Otherwise, use
  innobase_trx_allocate().

  rb://69 accepted by Heikki Tuuri
  ------------------------------------------------------------------------
  r3798 | marko | 2009-01-07 16:42:42 +0200 (Wed, 07 Jan 2009) | 8 lines

  branches/zip: row_merge_drop_temp_indexes(): Do not lock the rows of
  SYS_INDEXES when looking for partially created indexes.  Use the
  transaction isolation level READ UNCOMMITTED to avoid interfering with
  locks held by incomplete transactions that will be rolled back in a
  subsequent step in the recovery.  (Issue #152)

  Approved by Heikki Tuuri
  ------------------------------------------------------------------------
  r3852 | vasil | 2009-01-08 22:10:10 +0200 (Thu, 08 Jan 2009) | 4 lines

  branches/zip:

  Add ChangeLog entries for r3795 r3796 r3797 r3798.

  ------------------------------------------------------------------------
  r3866 | marko | 2009-01-09 15:09:51 +0200 (Fri, 09 Jan 2009) | 2 lines

  branches/zip: buf_flush_try_page(): Move some common code from each
  switch case before the switch block.
  ------------------------------------------------------------------------
  r3867 | marko | 2009-01-09 15:13:14 +0200 (Fri, 09 Jan 2009) | 2 lines

  branches/zip: buf_flush_try_page(): Introduce the variable is_compressed
  for caching the result of buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE.
  ------------------------------------------------------------------------
  r3868 | marko | 2009-01-09 15:40:11 +0200 (Fri, 09 Jan 2009) | 4 lines

  branches/zip: buf_flush_insert_into_flush_list(),
  buf_flush_insert_sorted_into_flush_list(): Remove unused code.
  Change the parameter to buf_block_t* block and assert that
  block->state == BUF_BLOCK_FILE_PAGE.  This is part of Issue #155.
  ------------------------------------------------------------------------
  r3873 | marko | 2009-01-09 22:27:40 +0200 (Fri, 09 Jan 2009) | 17 lines

  branches/zip: Some non-functional changes related to Issue #155.

  buf_page_struct: Note that space and offset are also protected by
  buf_pool_mutex.  They are only assigned to by
  buf_block_set_file_page().  Thus, it suffices for buf_flush_batch() to
  hold just buf_pool_mutex when checking these fields.

  buf_flush_try_page(): Rename "locked" to "is_s_latched", per Heikki's request.

  buf_flush_batch(): Move the common statement mutex_exit(block_mutex)
  from all if-else if-else branches before the if block.  Remove the
  redundant test (buf_pool->init_flush[flush_type] == FALSE) that was
  apparently copied from buf_flush_write_complete().

  buf_flush_write_block_low(): Note why it is safe not to hold buf_pool_mutex
  or block_mutex.  Enumerate the assumptions in debug assertions.
  ------------------------------------------------------------------------
  r3874 | marko | 2009-01-09 23:09:06 +0200 (Fri, 09 Jan 2009) | 4 lines

  branches/zip: Add comments related to Issue #155.

  buf_flush_try_page(): Note why it is safe to access bpage without
  holding buf_pool_mutex or block_mutex.
  ------------------------------------------------------------------------
  r3875 | marko | 2009-01-09 23:15:12 +0200 (Fri, 09 Jan 2009) | 11 lines

  branches/zip: Non-functional change: Tighten debug assertions and
  remove dead code.

  buf_flush_ready_for_flush(), buf_flush_try_page(): Assert that
  flush_type is one of BUF_FLUSH_LRU or BUF_FLUSH_LIST.  The flush_type
  comes from buf_flush_batch(), which already asserts this.  The
  assertion holds for all calls in the source code.

  buf_flush_try_page(): Remove the dead case BUF_FLUSH_SINGLE_PAGE
  of switch (flush_type).
  ------------------------------------------------------------------------
  r3879 | marko | 2009-01-12 12:46:44 +0200 (Mon, 12 Jan 2009) | 14 lines

  branches/zip: Simplify the flushing of dirty pages from the buffer pool.

  buf_flush_try_page(): Rename to buf_flush_page(), and change the
  return type to void.  Replace the parameters space, offset with bpage,
  and remove the second page hash lookup.  Note and assert that both
  buf_pool_mutex and block_mutex must now be held upon entering the
  function.  They will still be released by this function.

  buf_flush_try_neighbors(): Replace buf_flush_try_page() with
  buf_flush_page().  Make the logic easier to follow by not negating the
  precondition of buf_flush_page().

  rb://73 approved by Sunny Bains.  This is related to Issue #157.
  ------------------------------------------------------------------------
  r3880 | marko | 2009-01-12 13:24:37 +0200 (Mon, 12 Jan 2009) | 2 lines

  branches/zip: buf_flush_page(): Fix a comment that should have been fixed
  in r3879.  Spotted by Sunny.
  ------------------------------------------------------------------------
  r3881 | marko | 2009-01-12 14:25:22 +0200 (Mon, 12 Jan 2009) | 2 lines

  branches/zip: buf_page_get_newest_modification(): Use the block mutex
  instead of the buffer pool mutex.  This is related to Issue #157.
  ------------------------------------------------------------------------
  r3882 | marko | 2009-01-12 14:40:08 +0200 (Mon, 12 Jan 2009) | 3 lines

  branches/zip: struct mtr_struct: Remove the unused field magic_n
  unless UNIV_DEBUG is defined.  mtr->magic_n is only assigned to
  and checked in UNIV_DEBUG builds.
  ------------------------------------------------------------------------
  r3883 | marko | 2009-01-12 14:48:59 +0200 (Mon, 12 Jan 2009) | 1 line

  branches/zip: Non-functional change: Use ut_d when assigning to mtr->state.
  ------------------------------------------------------------------------
  r3884 | marko | 2009-01-12 18:56:11 +0200 (Mon, 12 Jan 2009) | 16 lines

  branches/zip: Non-functional change: Add some debug assertions and comments.

  buf_page_t: Note that the LRU fields are protected by buf_pool_mutex
  only, not block->mutex or buf_pool_zip_mutex.

  buf_page_get_freed_page_clock(): Note that this is sometimes invoked
  without mutex protection.

  buf_pool_get_oldest_modification(): Note that the result may be out of
  date.

  buf_page_get_LRU_position(), buf_page_is_old(): Assert that the buffer
  pool mutex is being held.

  buf_page_release(): Assert that dirty blocks are in the flush list.
  ------------------------------------------------------------------------
  r3896 | marko | 2009-01-13 09:30:26 +0200 (Tue, 13 Jan 2009) | 2 lines

  branches/zip: buf_flush_try_neighbors(): Fix a bug
  that was introduced in r3879 (rb://73).
  ------------------------------------------------------------------------
  r3900 | marko | 2009-01-13 10:32:24 +0200 (Tue, 13 Jan 2009) | 1 line

  branches/zip: Fix some comments to say buf_pool_mutex.
  ------------------------------------------------------------------------
  r3907 | marko | 2009-01-13 11:54:01 +0200 (Tue, 13 Jan 2009) | 3 lines

  branches/zip: row_merge_create_temporary_table(): On error,
  row_create_table_for_mysql() already frees new_table.
  Do not attempt to free it again.
  ------------------------------------------------------------------------
  r3908 | marko | 2009-01-13 12:34:32 +0200 (Tue, 13 Jan 2009) | 1 line

  branches/zip: Enable HASH_ASSERT_OWNED independently of UNIV_SYNC_DEBUG.
  ------------------------------------------------------------------------
  r3914 | marko | 2009-01-13 21:46:22 +0200 (Tue, 13 Jan 2009) | 37 lines

  branches/zip: In hash table lookups, assert that the traversed items
  satisfy some conditions when UNIV_DEBUG is defined.

  HASH_SEARCH(): New parameter: ASSERTION. All users will pass an appropriate
  ut_ad() or nothing.

  dict_table_add_to_columns(): Assert that the table being added to the data
  dictionary cache is not already being pointed to by the name_hash and
  id_hash tables.

  HASH_SEARCH_ALL(): New macro, for use in dict_table_add_to_columns().

  dict_mem_table_free(): Set ut_d(table->cached = FALSE), so that we can
  check ut_ad(table->cached) when traversing the hash tables, as in
  HASH_SEARCH(name_hash, dict_sys->table_hash, ...) and
  HASH_SEARCH(id_hash, dict_sys->table_id_hash, ...).

  dict_table_get_low(), dict_table_get_on_id_low(): Assert
  ut_ad(!table || table->cached).

  fil_space_get_by_id(): Check ut_ad(space->magic_n == FIL_SPACE_MAGIC_N)
  in HASH_SEARCH(hash, fil_system->spaces, ...).

  fil_space_get_by_name(): Check ut_ad(space->magic_n == FIL_SPACE_MAGIC_N)
  in HASH_SEARCH(name_hash, fil_system->name_hash, ...).

  buf_buddy_block_free(): Check that the blocks are in valid state in
  HASH_SEARCH(hash, buf_pool->zip_hash, ...).

  buf_page_hash_get(): Check that the blocks are in valid state in
  HASH_SEARCH(hash, buf_pool->page_hash, ...).

  get_share(), free_share(): Check ut_ad(share->use_count > 0) in
  HASH_SEARCH(table_name_hash, innobase_open_tables, ...).

  This was posted as rb://75 for tracking down errors similar to Issue #153.
  ------------------------------------------------------------------------
  r3931 | marko | 2009-01-14 16:06:22 +0200 (Wed, 14 Jan 2009) | 26 lines

  branches/zip: Merge revisions 3601:3930 from branches/5.1:

    ------------------------------------------------------------------------
    r3911 | sunny | 2009-01-13 14:15:24 +0200 (Tue, 13 Jan 2009) | 13 lines

    branches/5.1: Fix Bug#38187 Error 153 when creating savepoints
    InnoDB previously treated savepoints as a stack e.g.,
      SAVEPOINT a;
      SAVEPOINT b;
      SAVEPOINT c;
      SAVEPOINT b; <- This would delete b and c.

    This fix changes the behavior to:
      SAVEPOINT a;
      SAVEPOINT b;
      SAVEPOINT c;
      SAVEPOINT b; <- Does not delete savepoint c
    ------------------------------------------------------------------------
    r3930 | marko | 2009-01-14 15:51:30 +0200 (Wed, 14 Jan 2009) | 4 lines

    branches/5.1: dict_load_table(): If dict_load_indexes() fails,
    invoke dict_table_remove_from_cache() instead of dict_mem_table_free(),
    so that the data dictionary will not point to freed data.
    (Bug #42075, Issue #153, rb://76 approved by Heikki Tuuri)
    ------------------------------------------------------------------------
  ------------------------------------------------------------------------
parent c922320f
2009-01-13 The InnoDB Team
* include/hash0hash.h, include/dict0dict.ic, dict/dict0dict.c,
include/buf0buf.ic, buf/buf0buddy.c, trx/trx0i_s.c,
handler/ha_innodb.cc, handler/win_delay_loader.cc,
dict/dict0mem.c, ha/ha0storage.c, thr/thr0loc.c, fil/fil0fil.c:
Add the parameter ASSERTION to HASH_SEARCH() macro, and use it for
light validation of the traversed items in hash table lookups when
UNIV_DEBUG is enabled.
2009-01-09 The InnoDB Team
* include/buf0flu.h, include/buf0flu.ic, buf/buf0flu.c:
Remove unused code from the functions
buf_flush_insert_into_flush_list() and
buf_flush_insert_sorted_into_flush_list().
2009-01-09 The InnoDB Team
* buf/buf0flu.c: Simplify the functions buf_flush_try_page() and
buf_flush_batch(). Add debug assertions and an explanation to
buf_flush_write_block_low().
2009-01-07 The InnoDB Team
* row/row0merge.c:
Fix a bug in recovery when dropping temporary indexes
2009-01-07 The InnoDB Team
* handler/ha_innodb.cc, handler/ha_innodb.h, handler/handler0alter.cc:
Fix Bug#41680 calls to trx_allocate_for_mysql are not consistent
2009-01-07 The InnoDB Team
* mysql-test/innodb_bug41904.result, mysql-test/innodb_bug41904.test,
row/row0merge.c:
Fix Bug#41904 create unique index problem
2009-01-02 The InnoDB Team
* handler/ha_innodb.cc, include/srv0srv.h, srv/srv0srv.c,
srv/srv0start.c, mem/mem0pool.c,
mysql-test/innodb-use-sys-malloc-master.opt,
mysql-test/innodb-use-sys-malloc.result,
mysql-test/innodb-use-sys-malloc.test:
Implement the configuration parameter innodb_use_sys_malloc
(false by default), for disabling InnoDB's internal memory allocator
and using system malloc/free instead.
2008-12-30 The InnoDB Team
* btr/btr0btr.c:
When setting the PAGE_LEVEL of a compressed B-tree page from or to
0, compress the page at the same time. This is necessary, because
the column information stored on the compressed page will differ
between leaf and non-leaf pages. Leaf pages are identified by
PAGE_LEVEL=0. This bug can make InnoDB crash when all rows of a
compressed table are deleted.
2008-12-17 The InnoDB Team
* include/row0upd.h, include/row0sel.h, pars/pars0pars.c,
......
......@@ -172,6 +172,8 @@ buf_buddy_block_free(
ut_a(!ut_align_offset(buf, UNIV_PAGE_SIZE));
HASH_SEARCH(hash, buf_pool->zip_hash, fold, buf_page_t*, bpage,
ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_MEMORY
&& bpage->in_zip_hash && !bpage->in_page_hash),
((buf_block_t*) bpage)->frame == buf);
ut_a(bpage);
ut_a(buf_page_get_state(bpage) == BUF_BLOCK_MEMORY);
......
......@@ -245,7 +245,7 @@ static ulint buf_dbg_counter = 0; /* This is used to insert validation
operations in excution in the
debug version */
/** Flag to forbid the release of the buffer pool mutex.
Protected by buf_pool->mutex. */
Protected by buf_pool_mutex. */
UNIV_INTERN ulint buf_pool_mutex_exit_forbidden = 0;
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
#ifdef UNIV_DEBUG
......
This diff is collapsed.
......@@ -251,7 +251,7 @@ buf_LRU_drop_page_hash_for_tablespace(
if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
goto next_page;
}
/* Array full. We release the buf_pool->mutex to
/* Array full. We release the buf_pool_mutex to
obey the latching order. */
buf_pool_mutex_exit();
......
......@@ -751,18 +751,34 @@ dict_table_add_to_cache(
{
dict_table_t* table2;
HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
dict_table_t*, table2,
(ut_strcmp(table2->name, table->name) == 0));
dict_table_t*, table2, ut_ad(table2->cached),
ut_strcmp(table2->name, table->name) == 0);
ut_a(table2 == NULL);
#ifdef UNIV_DEBUG
/* Look for the same table pointer with a different name */
HASH_SEARCH_ALL(name_hash, dict_sys->table_hash,
dict_table_t*, table2, ut_ad(table2->cached),
table2 == table);
ut_ad(table2 == NULL);
#endif /* UNIV_DEBUG */
}
/* Look for a table with the same id: error if such exists */
{
dict_table_t* table2;
HASH_SEARCH(id_hash, dict_sys->table_id_hash, id_fold,
dict_table_t*, table2,
(ut_dulint_cmp(table2->id, table->id) == 0));
dict_table_t*, table2, ut_ad(table2->cached),
ut_dulint_cmp(table2->id, table->id) == 0);
ut_a(table2 == NULL);
#ifdef UNIV_DEBUG
/* Look for the same table pointer with a different id */
HASH_SEARCH_ALL(id_hash, dict_sys->table_id_hash,
dict_table_t*, table2, ut_ad(table2->cached),
table2 == table);
ut_ad(table2 == NULL);
#endif /* UNIV_DEBUG */
}
/* Add table to hash table of tables */
......@@ -844,7 +860,7 @@ dict_table_rename_in_cache(
{
dict_table_t* table2;
HASH_SEARCH(name_hash, dict_sys->table_hash, fold,
dict_table_t*, table2,
dict_table_t*, table2, ut_ad(table2->cached),
(ut_strcmp(table2->name, new_name) == 0));
if (UNIV_LIKELY_NULL(table2)) {
ut_print_timestamp(stderr);
......
......@@ -949,11 +949,11 @@ dict_load_table(
of the error condition, since the user may want to dump data from the
clustered index. However we load the foreign key information only if
all indexes were loaded. */
if (err != DB_SUCCESS && !srv_force_recovery) {
dict_mem_table_free(table);
table = NULL;
} else if (err == DB_SUCCESS) {
if (err == DB_SUCCESS) {
err = dict_load_foreigns(table->name, TRUE);
} else if (!srv_force_recovery) {
dict_table_remove_from_cache(table);
table = NULL;
}
# if 0
if (err != DB_SUCCESS && table != NULL) {
......
......@@ -84,6 +84,7 @@ dict_mem_table_free(
{
ut_ad(table);
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
ut_d(table->cached = FALSE);
mutex_free(&(table->autoinc_mutex));
mem_heap_free(table->heap);
......
......@@ -363,7 +363,9 @@ fil_space_get_by_id(
ut_ad(mutex_own(&fil_system->mutex));
HASH_SEARCH(hash, fil_system->spaces, id,
fil_space_t*, space, space->id == id);
fil_space_t*, space,
ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
space->id == id);
return(space);
}
......@@ -384,7 +386,9 @@ fil_space_get_by_name(
fold = ut_fold_string(name);
HASH_SEARCH(name_hash, fil_system->name_hash, fold,
fil_space_t*, space, !strcmp(name, space->name));
fil_space_t*, space,
ut_ad(space->magic_n == FIL_SPACE_MAGIC_N),
!strcmp(name, space->name));
return(space);
}
......
......@@ -45,6 +45,7 @@ ha_storage_get(
fold, /* key */
ha_storage_node_t*, /* type of node->next */
node, /* auxiliary variable */
, /* assertion */
IS_FOUND); /* search criteria */
if (node == NULL) {
......
......@@ -1211,6 +1211,53 @@ innobase_next_autoinc(
return(next_value);
}
/*************************************************************************
Initializes some fields in an InnoDB transaction object. */
static
void
innobase_trx_init(
/*==============*/
THD* thd, /* in: user thread handle */
trx_t* trx) /* in/out: InnoDB transaction handle */
{
DBUG_ENTER("innobase_trx_init");
DBUG_ASSERT(EQ_CURRENT_THD(thd));
DBUG_ASSERT(thd == trx->mysql_thd);
trx->check_foreigns = !thd_test_options(
thd, OPTION_NO_FOREIGN_KEY_CHECKS);
trx->check_unique_secondary = !thd_test_options(
thd, OPTION_RELAXED_UNIQUE_CHECKS);
DBUG_VOID_RETURN;
}
/*************************************************************************
Allocates an InnoDB transaction for a MySQL handler object. */
extern "C" UNIV_INTERN
trx_t*
innobase_trx_allocate(
/*==================*/
/* out: InnoDB transaction handle */
THD* thd) /* in: user thread handle */
{
trx_t* trx;
DBUG_ENTER("innobase_trx_allocate");
DBUG_ASSERT(thd != NULL);
DBUG_ASSERT(EQ_CURRENT_THD(thd));
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
trx->mysql_query_str = thd_query(thd);
innobase_trx_init(thd, trx);
DBUG_RETURN(trx);
}
/*************************************************************************
Gets the InnoDB transaction handle for a MySQL handler object, creates
an InnoDB transaction struct if the corresponding MySQL thread struct still
......@@ -1227,31 +1274,13 @@ check_trx_exists(
ut_ad(EQ_CURRENT_THD(thd));
if (trx == NULL) {
DBUG_ASSERT(thd != NULL);
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
trx->mysql_query_str = thd_query(thd);
} else {
if (trx->magic_n != TRX_MAGIC_N) {
trx = innobase_trx_allocate(thd);
} else if (UNIV_UNLIKELY(trx->magic_n != TRX_MAGIC_N)) {
mem_analyze_corruption(trx);
ut_error;
}
}
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
trx->check_foreigns = FALSE;
} else {
trx->check_foreigns = TRUE;
}
if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
trx->check_unique_secondary = FALSE;
} else {
trx->check_unique_secondary = TRUE;
}
innobase_trx_init(thd, trx);
return(trx);
}
......@@ -4621,7 +4650,8 @@ ha_innobase::unlock_row(void)
switch (prebuilt->row_read_type) {
case ROW_READ_WITH_LOCKS:
if (!srv_locks_unsafe_for_binlog
|| prebuilt->trx->isolation_level == TRX_ISO_READ_COMMITTED) {
&& prebuilt->trx->isolation_level
!= TRX_ISO_READ_COMMITTED) {
break;
}
/* fall through */
......@@ -5480,9 +5510,19 @@ create_table_def(
charset_no = (ulint)field->charset()->number;
ut_a(charset_no < 256); /* in data0type.h we assume
that the number fits in one
byte */
if (UNIV_UNLIKELY(charset_no >= 256)) {
/* in data0type.h we assume that the
number fits in one byte in prtype */
push_warning_printf(
(THD*) trx->mysql_thd,
MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_CANT_CREATE_TABLE,
"In InnoDB, charset-collation codes"
" must be below 256."
" Unsupported code %lu.",
(ulong) charset_no);
DBUG_RETURN(ER_CANT_CREATE_TABLE);
}
}
ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
......@@ -5927,18 +5967,7 @@ ha_innobase::create(
trx_search_latch_release_if_reserved(parent_trx);
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
trx->mysql_query_str = thd_query(thd);
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
trx->check_foreigns = FALSE;
}
if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
trx->check_unique_secondary = FALSE;
}
trx = innobase_trx_allocate(thd);
if (lower_case_table_names) {
srv_lower_case_table_names = TRUE;
......@@ -6344,25 +6373,14 @@ ha_innobase::delete_table(
trx_search_latch_release_if_reserved(parent_trx);
trx = innobase_trx_allocate(thd);
if (lower_case_table_names) {
srv_lower_case_table_names = TRUE;
} else {
srv_lower_case_table_names = FALSE;
}
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
trx->mysql_query_str = thd_query(thd);
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
trx->check_foreigns = FALSE;
}
if (thd_test_options(thd, OPTION_RELAXED_UNIQUE_CHECKS)) {
trx->check_unique_secondary = FALSE;
}
name_len = strlen(name);
ut_a(name_len < 1000);
......@@ -6445,19 +6463,14 @@ innobase_drop_database(
#ifdef __WIN__
innobase_casedn_str(namebuf);
#endif
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
if (thd) {
trx->mysql_query_str = thd_query(thd);
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
trx->check_foreigns = FALSE;
}
} else {
#if defined __WIN__ && !defined MYSQL_SERVER
/* In the Windows plugin, thd = current_thd is always NULL */
trx = trx_allocate_for_mysql();
trx->mysql_thd = NULL;
trx->mysql_query_str = NULL;
}
#else
trx = innobase_trx_allocate(thd);
#endif
error = row_drop_database_for_mysql(namebuf, trx);
my_free(namebuf, MYF(0));
......@@ -6567,13 +6580,7 @@ ha_innobase::rename_table(
trx_search_latch_release_if_reserved(parent_trx);
trx = trx_allocate_for_mysql();
trx->mysql_thd = thd;
trx->mysql_query_str = thd_query(thd);
if (thd_test_options(thd, OPTION_NO_FOREIGN_KEY_CHECKS)) {
trx->check_foreigns = FALSE;
}
trx = innobase_trx_allocate(thd);
error = innobase_rename_table(trx, from, to, TRUE);
......@@ -8164,6 +8171,7 @@ static INNOBASE_SHARE* get_share(const char* table_name)
HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
INNOBASE_SHARE*, share,
ut_ad(share->use_count > 0),
!my_strnncoll(system_charset_info,
share->table_name,
share->table_name_length,
......@@ -8205,6 +8213,7 @@ static void free_share(INNOBASE_SHARE* share)
HASH_SEARCH(table_name_hash, innobase_open_tables, fold,
INNOBASE_SHARE*, share2,
ut_ad(share->use_count > 0),
!my_strnncoll(system_charset_info,
share->table_name,
share->table_name_length,
......@@ -9580,6 +9589,11 @@ static MYSQL_SYSVAR_STR(version, innodb_version_str,
PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
"InnoDB version", NULL, NULL, INNODB_VERSION_STR);
static MYSQL_SYSVAR_BOOL(use_sys_malloc, srv_use_sys_malloc,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Use OS memory allocator instead of InnoDB's internal memory allocator",
NULL, NULL, FALSE);
static MYSQL_SYSVAR_BOOL(use_native_aio, srv_use_native_aio,
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
"Use native AIO if supported on this platform.",
......@@ -9631,6 +9645,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(thread_sleep_delay),
MYSQL_SYSVAR(autoinc_lock_mode),
MYSQL_SYSVAR(version),
MYSQL_SYSVAR(use_sys_malloc),
MYSQL_SYSVAR(use_native_aio),
NULL
};
......
......@@ -269,3 +269,12 @@ convert_error_code_to_mysql(
int error, /* in: InnoDB error code */
ulint flags, /* in: InnoDB table flags, or 0 */
MYSQL_THD thd); /* in: user thread handle or NULL */
/*************************************************************************
Allocates an InnoDB transaction for a MySQL handler object. */
extern "C"
trx_t*
innobase_trx_allocate(
/*==================*/
/* out: InnoDB transaction handle */
MYSQL_THD thd); /* in: user thread handle */
......@@ -633,12 +633,9 @@ ha_innobase::add_index(
/* Create a background transaction for the operations on
the data dictionary tables. */
trx = trx_allocate_for_mysql();
trx = innobase_trx_allocate(user_thd);
trx_start_if_not_started(trx);
trx->mysql_thd = user_thd;
trx->mysql_query_str = thd_query(user_thd);
innodb_table = indexed_table
= dict_table_get(prebuilt->table->name, FALSE);
......@@ -1125,12 +1122,9 @@ ha_innobase::final_drop_index(
/* Create a background transaction for the operations on
the data dictionary tables. */
trx = trx_allocate_for_mysql();
trx = innobase_trx_allocate(user_thd);
trx_start_if_not_started(trx);
trx->mysql_thd = user_thd;
trx->mysql_query_str = thd_query(user_thd);
/* Flag this transaction as a dictionary operation, so that
the data dictionary will be locked in crash recovery. */
trx_set_dict_operation(trx, TRX_DICT_OP_INDEX);
......
......@@ -453,6 +453,7 @@ wdl_get_procaddr_from_map(
map_fold,
map_hash_chain_t*,
hash_chain,
,
(ut_strcmp(hash_chain->symbol, import_proc) == 0));
if (hash_chain == NULL) {
......@@ -472,6 +473,7 @@ wdl_get_procaddr_from_map(
map_fold,
map_hash_chain_t*,
hash_chain,
,
(ut_strcmp(hash_chain->symbol, import_proc) == 0));
if (hash_chain == NULL) {
......@@ -515,6 +517,7 @@ wdl_get_varaddr_from_map(
map_fold,
map_hash_chain_t*,
hash_chain,
,
(ut_strcmp(hash_chain->symbol, import_variable) == 0));
if (hash_chain == NULL) {
......@@ -534,6 +537,7 @@ wdl_get_varaddr_from_map(
map_fold,
map_hash_chain_t*,
hash_chain,
,
(ut_strcmp(hash_chain->symbol, import_variable) == 0));
if (hash_chain == NULL) {
......
......@@ -1010,8 +1010,10 @@ struct buf_page_struct{
since they can be stored in the same machine word. Some of them are
additionally protected by buf_pool_mutex. */
unsigned space:32; /* tablespace id */
unsigned offset:32; /* page number */
unsigned space:32; /* tablespace id; also protected
by buf_pool_mutex. */
unsigned offset:32; /* page number; also protected
by buf_pool_mutex. */
unsigned state:3; /* state of the control block
(@see enum buf_page_state); also
......@@ -1080,7 +1082,8 @@ struct buf_page_struct{
not yet been flushed on disk; zero if
all modifications are on disk */
/* 3. LRU replacement algorithm fields; protected by buf_pool_mutex */
/* 3. LRU replacement algorithm fields; protected by
buf_pool_mutex only (not buf_pool_zip_mutex or block->mutex) */
UT_LIST_NODE_T(buf_page_t) LRU;
/* node of the LRU list */
......
......@@ -20,6 +20,7 @@ buf_page_get_freed_page_clock(
/* out: freed_page_clock */
const buf_page_t* bpage) /* in: block */
{
/* This is sometimes read without holding buf_pool_mutex. */
return(bpage->freed_page_clock);
}
......@@ -89,6 +90,9 @@ buf_pool_get_oldest_modification(void)
buf_pool_mutex_exit();
/* The returned answer may be out of date: the flush_list can
change after the mutex has been released. */
return(lsn);
}
......@@ -261,6 +265,7 @@ buf_page_get_LRU_position(
const buf_page_t* bpage) /* in: control block */
{
ut_ad(buf_page_in_file(bpage));
ut_ad(buf_pool_mutex_own());
return(bpage->LRU_position);
}
......@@ -429,6 +434,7 @@ buf_page_is_old(
const buf_page_t* bpage) /* in: control block */
{
ut_ad(buf_page_in_file(bpage));
ut_ad(buf_pool_mutex_own());
return(bpage->old);
}
......@@ -805,8 +811,9 @@ buf_page_get_newest_modification(
page frame */
{
ib_uint64_t lsn;
mutex_t* block_mutex = buf_page_get_mutex(bpage);
buf_pool_mutex_enter();
mutex_enter(block_mutex);
if (buf_page_in_file(bpage)) {
lsn = bpage->newest_modification;
......@@ -814,7 +821,7 @@ buf_page_get_newest_modification(
lsn = 0;
}
buf_pool_mutex_exit();
mutex_exit(block_mutex);
return(lsn);
}
......@@ -921,6 +928,8 @@ buf_page_hash_get(
fold = buf_page_address_fold(space, offset);
HASH_SEARCH(hash, buf_pool->page_hash, fold, buf_page_t*, bpage,
ut_ad(bpage->in_page_hash && !bpage->in_zip_hash
&& buf_page_in_file(bpage)),
bpage->space == space && bpage->offset == offset);
if (bpage) {
ut_a(buf_page_in_file(bpage));
......@@ -1040,6 +1049,10 @@ buf_page_release(
#endif
block->page.buf_fix_count--;
/* Dirty blocks should be in the flush list. */
ut_ad(!block->page.oldest_modification
|| block->page.in_flush_list);
mutex_exit(&block->mutex);
if (rw_latch == RW_S_LATCH) {
......
......@@ -14,13 +14,6 @@ Created 11/5/1995 Heikki Tuuri
#include "ut0byte.h"
#include "mtr0types.h"
/************************************************************************
Inserts a modified block into the flush list. */
UNIV_INTERN
void
buf_flush_insert_into_flush_list(
/*=============================*/
buf_page_t* bpage); /* in: block which is modified */
/************************************************************************
Remove a block from the flush list of modified blocks. */
UNIV_INTERN
......
......@@ -9,6 +9,13 @@ Created 11/5/1995 Heikki Tuuri
#include "buf0buf.h"
#include "mtr0mtr.h"
/************************************************************************
Inserts a modified block into the flush list. */
UNIV_INTERN
void
buf_flush_insert_into_flush_list(
/*=============================*/
buf_block_t* block); /* in/out: block which is modified */
/************************************************************************
Inserts a modified block into the flush list in the right sorted position.
This function is used by recovery, because there the modifications do not
......@@ -17,7 +24,7 @@ UNIV_INTERN
void
buf_flush_insert_sorted_into_flush_list(
/*====================================*/
buf_page_t* bpage); /* in: block which is modified */
buf_block_t* block); /* in/out: block which is modified */
/************************************************************************
This function should be called at a mini-transaction commit, if a page was
......@@ -49,7 +56,7 @@ buf_flush_note_modification(
block->page.oldest_modification = mtr->start_lsn;
ut_ad(block->page.oldest_modification != 0);
buf_flush_insert_into_flush_list(&block->page);
buf_flush_insert_into_flush_list(block);
} else {
ut_ad(block->page.oldest_modification <= mtr->start_lsn);
}
......@@ -88,7 +95,7 @@ buf_flush_recv_note_modification(
ut_ad(block->page.oldest_modification != 0);
buf_flush_insert_sorted_into_flush_list(&block->page);
buf_flush_insert_sorted_into_flush_list(block);
} else {
ut_ad(block->page.oldest_modification <= start_lsn);
}
......
......@@ -720,7 +720,8 @@ dict_table_check_if_in_cache_low(
table_fold = ut_fold_string(table_name);
HASH_SEARCH(name_hash, dict_sys->table_hash, table_fold,
dict_table_t*, table, !strcmp(table->name, table_name));
dict_table_t*, table, ut_ad(table->cached),
!strcmp(table->name, table_name));
return(table);
}
......@@ -745,6 +746,8 @@ dict_table_get_low(
table = dict_load_table(table_name);
}
ut_ad(!table || table->cached);
return(table);
}
......@@ -766,11 +769,14 @@ dict_table_get_on_id_low(
fold = ut_fold_dulint(table_id);
HASH_SEARCH(id_hash, dict_sys->table_id_hash, fold,
dict_table_t*, table, !ut_dulint_cmp(table->id, table_id));
dict_table_t*, table, ut_ad(table->cached),
!ut_dulint_cmp(table->id, table_id));
if (table == NULL) {
table = dict_load_table_on_id(table_id);
}
ut_ad(!table || table->cached);
/* TODO: should get the type information from MySQL */
return(table);
......
......@@ -66,12 +66,8 @@ hash_calc_hash(
hash_table_t* table); /* in: hash table */
/************************************************************************
Assert that the mutex for the table in a hash operation is owned. */
#ifdef UNIV_SYNC_DEBUG
# define HASH_ASSERT_OWNED(TABLE, FOLD) \
#define HASH_ASSERT_OWNED(TABLE, FOLD) \
ut_ad(!(TABLE)->mutexes || mutex_own(hash_get_mutex(TABLE, FOLD)));
#else
# define HASH_ASSERT_OWNED(TABLE, FOLD)
#endif
/***********************************************************************
Inserts a struct to a hash table. */
......@@ -151,7 +147,7 @@ Gets the next struct in a hash chain, NULL if none. */
/************************************************************************
Looks for a struct in a hash table. */
#define HASH_SEARCH(NAME, TABLE, FOLD, TYPE, DATA, TEST)\
#define HASH_SEARCH(NAME, TABLE, FOLD, TYPE, DATA, ASSERTION, TEST)\
{\
\
HASH_ASSERT_OWNED(TABLE, FOLD)\
......@@ -160,6 +156,7 @@ Looks for a struct in a hash table. */
HASH_ASSERT_VALID(DATA);\
\
while ((DATA) != NULL) {\
ASSERTION;\
if (TEST) {\
break;\
} else {\
......@@ -169,6 +166,32 @@ Looks for a struct in a hash table. */
}\
}
/************************************************************************
Looks for an item in all hash buckets. */
#define HASH_SEARCH_ALL(NAME, TABLE, TYPE, DATA, ASSERTION, TEST) \
do { \
ulint i3333; \
\
for (i3333 = (TABLE)->n_cells; i3333--; ) { \
(DATA) = (TYPE) HASH_GET_FIRST(TABLE, i3333); \
\
while ((DATA) != NULL) { \
HASH_ASSERT_VALID(DATA); \
ASSERTION; \
\
if (TEST) { \
break; \
} \
\
(DATA) = (TYPE) HASH_GET_NEXT(NAME, DATA); \
} \
\
if ((DATA) != NULL) { \
break; \
} \
} \
} while (0)
/****************************************************************
Gets the nth cell in a hash table. */
UNIV_INLINE
......
......@@ -344,10 +344,14 @@ struct mtr_struct{
this mtr */
ib_uint64_t end_lsn;/* end lsn of the possible log entry for
this mtr */
#ifdef UNIV_DEBUG
ulint magic_n;
#endif /* UNIV_DEBUG */
};
#define MTR_MAGIC_N 54551
#ifdef UNIV_DEBUG
# define MTR_MAGIC_N 54551
#endif /* UNIV_DEBUG */
#define MTR_ACTIVE 12231
#define MTR_COMMITTING 56456
......
......@@ -28,10 +28,9 @@ mtr_start(
mtr->modifications = FALSE;
mtr->n_log_recs = 0;
#ifdef UNIV_DEBUG
mtr->state = MTR_ACTIVE;
mtr->magic_n = MTR_MAGIC_N;
#endif
ut_d(mtr->state = MTR_ACTIVE);
ut_d(mtr->magic_n = MTR_MAGIC_N);
return(mtr);
}
......
......@@ -98,6 +98,7 @@ extern ulong srv_flush_log_at_trx_commit;
/* The sort order table of the MySQL latin1_swedish_ci character set
collation */
extern const byte* srv_latin1_ordering;
extern my_bool srv_use_sys_malloc;
extern ulint srv_buf_pool_size; /* requested size in bytes */
extern ulint srv_buf_pool_old_size; /* previously requested size */
extern ulint srv_buf_pool_curr_size; /* current size in bytes */
......
......@@ -15,6 +15,8 @@ Created 3/26/1996 Heikki Tuuri
#include "mtr0mtr.h"
#include "trx0sys.h"
#define trx_roll_free_all_savepoints(s) trx_roll_savepoints_free((s), NULL)
/***********************************************************************
Determines if this transaction is rolling back an incomplete transaction
in crash recovery. */
......@@ -249,8 +251,18 @@ trx_release_savepoint_for_mysql(
const char* savepoint_name); /* in: savepoint name */
/***********************************************************************
Frees savepoint structs. */
Frees a single savepoint struct. */
UNIV_INTERN
void
trx_roll_savepoint_free(
/*=====================*/
trx_t* trx, /* in: transaction handle */
trx_named_savept_t* savep); /* in: savepoint to free */
/***********************************************************************
Frees savepoint structs starting from savep, if savep == NULL then
free all savepoints. */
void
trx_roll_savepoints_free(
/*=====================*/
......
......@@ -11,6 +11,7 @@ Created 5/12/1997 Heikki Tuuri
#include "mem0pool.ic"
#endif
#include "srv0srv.h"
#include "sync0sync.h"
#include "ut0mem.h"
#include "ut0lst.h"
......@@ -336,6 +337,12 @@ mem_area_alloc(
ulint n;
ibool ret;
/* If we are using os allocator just make a simple call
to malloc */
if (srv_use_sys_malloc) {
return(malloc(*psize));
}
size = *psize;
n = ut_2_log(ut_max(size + MEM_AREA_EXTRA_SIZE, MEM_AREA_MIN_SIZE));
......@@ -470,6 +477,10 @@ mem_area_free(
ulint size;
ulint n;
if (srv_use_sys_malloc) {
return(free(ptr));
}
/* It may be that the area was really allocated from the OS with
regular malloc: check if ptr points within our memory pool */
......
......@@ -158,9 +158,8 @@ mtr_commit(
ut_ad(mtr);
ut_ad(mtr->magic_n == MTR_MAGIC_N);
ut_ad(mtr->state == MTR_ACTIVE);
#ifdef UNIV_DEBUG
mtr->state = MTR_COMMITTING;
#endif
ut_d(mtr->state = MTR_COMMITTING);
write_log = mtr->modifications && mtr->n_log_recs;
if (write_log) {
......@@ -181,9 +180,7 @@ mtr_commit(
log_release();
}
#ifdef UNIV_DEBUG
mtr->state = MTR_COMMITTED;
#endif
ut_d(mtr->state = MTR_COMMITTED);
dyn_array_free(&(mtr->memo));
dyn_array_free(&(mtr->log));
}
......
--innodb_locks_unsafe_for_binlog=true --innodb_lock_wait_timeout=2
--innodb_lock_wait_timeout=2
drop table if exists t1;
set binlog_format=mixed;
set session transaction isolation level read committed;
set session transaction isolation level repeatable read;
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
insert into t1 values (1),(2),(3),(4),(5),(6),(7);
set autocommit=0;
......@@ -8,11 +8,12 @@ select * from t1 where a=3 lock in share mode;
a
3
set binlog_format=mixed;
set session transaction isolation level read committed;
set session transaction isolation level repeatable read;
set autocommit=0;
update t1 set a=10 where a=5;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
commit;
set session transaction isolation level read committed;
update t1 set a=10 where a=5;
select * from t1 where a=2 for update;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
......
......@@ -11,7 +11,7 @@ connect (a,localhost,root,,);
connect (b,localhost,root,,);
connection a;
set binlog_format=mixed;
set session transaction isolation level read committed;
set session transaction isolation level repeatable read;
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
insert into t1 values (1),(2),(3),(4),(5),(6),(7);
set autocommit=0;
......@@ -19,13 +19,15 @@ set autocommit=0;
select * from t1 where a=3 lock in share mode;
connection b;
set binlog_format=mixed;
set session transaction isolation level read committed;
set session transaction isolation level repeatable read;
set autocommit=0;
-- error ER_LOCK_WAIT_TIMEOUT
update t1 set a=10 where a=5;
connection a;
commit;
connection b;
# perform a semi-consisent read (and unlock non-matching rows)
set session transaction isolation level read committed;
update t1 set a=10 where a=5;
connection a;
-- error ER_LOCK_WAIT_TIMEOUT
......@@ -33,6 +35,7 @@ select * from t1 where a=2 for update;
# this should lock the records (1),(2)
select * from t1 where a=2 limit 1 for update;
connection b;
# semi-consistent read will skip non-matching locked rows a=1, a=2
update t1 set a=11 where a=6;
-- error ER_LOCK_WAIT_TIMEOUT
update t1 set a=12 where a=2;
......
--innodb-use-sys-malloc=true
--innodb-use-sys-malloc=true
SELECT @@GLOBAL.innodb_use_sys_malloc;
@@GLOBAL.innodb_use_sys_malloc
1
1 Expected
SET @@GLOBAL.innodb_use_sys_malloc=0;
ERROR HY000: Variable 'innodb_use_sys_malloc' is a read only variable
Expected error 'Read only variable'
SELECT @@GLOBAL.innodb_use_sys_malloc;
@@GLOBAL.innodb_use_sys_malloc
1
1 Expected
drop table if exists t1;
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
insert into t1 values (1),(2),(3),(4),(5),(6),(7);
select * from t1;
a
1
2
3
4
5
6
7
drop table t1;
SELECT @@GLOBAL.innodb_use_sys_malloc;
@@GLOBAL.innodb_use_sys_malloc
1
1 Expected
SET @@GLOBAL.innodb_use_sys_malloc=0;
ERROR HY000: Variable 'innodb_use_sys_malloc' is a read only variable
Expected error 'Read only variable'
SELECT @@GLOBAL.innodb_use_sys_malloc;
@@GLOBAL.innodb_use_sys_malloc
1
1 Expected
drop table if exists t1;
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
insert into t1 values (1),(2),(3),(4),(5),(6),(7);
select * from t1;
a
1
2
3
4
5
6
7
drop table t1;
--source include/have_innodb.inc
#display current value of innodb_use_sys_malloc
SELECT @@GLOBAL.innodb_use_sys_malloc;
--echo 1 Expected
#try changing it. Should fail.
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
SET @@GLOBAL.innodb_use_sys_malloc=0;
--echo Expected error 'Read only variable'
SELECT @@GLOBAL.innodb_use_sys_malloc;
--echo 1 Expected
#do some stuff to see if it works.
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
insert into t1 values (1),(2),(3),(4),(5),(6),(7);
select * from t1;
drop table t1;
--source include/have_innodb.inc
#display current value of innodb_use_sys_malloc
SELECT @@GLOBAL.innodb_use_sys_malloc;
--echo 1 Expected
#try changing it. Should fail.
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
SET @@GLOBAL.innodb_use_sys_malloc=0;
--echo Expected error 'Read only variable'
SELECT @@GLOBAL.innodb_use_sys_malloc;
--echo 1 Expected
#do some stuff to see if it works.
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1;
insert into t1 values (1),(2),(3),(4),(5),(6),(7);
select * from t1;
drop table t1;
CREATE TABLE bug41904 (id INT PRIMARY KEY, uniquecol CHAR(15)) ENGINE=InnoDB;
INSERT INTO bug41904 VALUES (1,NULL), (2,NULL);
CREATE UNIQUE INDEX ui ON bug41904 (uniquecol);
DROP TABLE bug41904;
#
# Make sure http://bugs.mysql.com/41904 remains fixed.
#
-- source include/not_embedded.inc
-- source include/have_innodb.inc
CREATE TABLE bug41904 (id INT PRIMARY KEY, uniquecol CHAR(15)) ENGINE=InnoDB;
INSERT INTO bug41904 VALUES (1,NULL), (2,NULL);
CREATE UNIQUE INDEX ui ON bug41904 (uniquecol);
DROP TABLE bug41904;
=== modified file 'mysql-test/r/variables.result'
--- mysql-test/r/variables.result 2008-11-27 10:50:28 +0000
+++ mysql-test/r/variables.result 2009-01-06 07:33:27 +0000
@@ -297,14 +297,14 @@
select ROUND(RAND(),5);
ROUND(RAND(),5)
0.02887
-show variables like '%alloc%';
+show variables where variable_name in ('query_alloc_block_size', 'query_prealloc_size', 'range_alloc_block_size', 'transaction_alloc_block_size', 'transaction_prealloc_size');
Variable_name Value
query_alloc_block_size 8192
query_prealloc_size 8192
range_alloc_block_size 4096
transaction_alloc_block_size 8192
transaction_prealloc_size 4096
-select * from information_schema.session_variables where variable_name like '%alloc%' order by 1;
+select * from information_schema.session_variables where variable_name in ('query_alloc_block_size', 'query_prealloc_size', 'range_alloc_block_size', 'transaction_alloc_block_size', 'transaction_prealloc_size') order by 1;
VARIABLE_NAME VARIABLE_VALUE
QUERY_ALLOC_BLOCK_SIZE 8192
QUERY_PREALLOC_SIZE 8192
@@ -319,14 +319,14 @@
select @@query_alloc_block_size;
@@query_alloc_block_size
17408
-show variables like '%alloc%';
+show variables where variable_name in ('query_alloc_block_size', 'query_prealloc_size', 'range_alloc_block_size', 'transaction_alloc_block_size', 'transaction_prealloc_size');
Variable_name Value
query_alloc_block_size 17408
query_prealloc_size 18432
range_alloc_block_size 16384
transaction_alloc_block_size 19456
transaction_prealloc_size 20480
-select * from information_schema.session_variables where variable_name like '%alloc%' order by 1;
+select * from information_schema.session_variables where variable_name in ('query_alloc_block_size', 'query_prealloc_size', 'range_alloc_block_size', 'transaction_alloc_block_size', 'transaction_prealloc_size') order by 1;
VARIABLE_NAME VARIABLE_VALUE
QUERY_ALLOC_BLOCK_SIZE 17408
QUERY_PREALLOC_SIZE 18432
@@ -336,14 +336,14 @@
set @@range_alloc_block_size=default;
set @@query_alloc_block_size=default, @@query_prealloc_size=default;
set transaction_alloc_block_size=default, @@transaction_prealloc_size=default;
-show variables like '%alloc%';
+show variables where variable_name in ('query_alloc_block_size', 'query_prealloc_size', 'range_alloc_block_size', 'transaction_alloc_block_size', 'transaction_prealloc_size');
Variable_name Value
query_alloc_block_size 8192
query_prealloc_size 8192
range_alloc_block_size 4096
transaction_alloc_block_size 8192
transaction_prealloc_size 4096
-select * from information_schema.session_variables where variable_name like '%alloc%' order by 1;
+select * from information_schema.session_variables where variable_name in ('query_alloc_block_size', 'query_prealloc_size', 'range_alloc_block_size', 'transaction_alloc_block_size', 'transaction_prealloc_size') order by 1;
VARIABLE_NAME VARIABLE_VALUE
QUERY_ALLOC_BLOCK_SIZE 8192
QUERY_PREALLOC_SIZE 8192
=== modified file 'mysql-test/t/variables.test'
--- mysql-test/t/variables.test 2008-11-27 10:50:28 +0000
+++ mysql-test/t/variables.test 2009-01-06 07:28:12 +0000
@@ -172,21 +172,21 @@
set @@rand_seed1=10000000,@@rand_seed2=1000000;
select ROUND(RAND(),5);
-show variables like '%alloc%';
-select * from information_schema.session_variables where variable_name like '%alloc%' order by 1;
+show variables where variable_name in ('query_alloc_block_size', 'query_prealloc_size', 'range_alloc_block_size', 'transaction_alloc_block_size', 'transaction_prealloc_size');
+select * from information_schema.session_variables where variable_name in ('query_alloc_block_size', 'query_prealloc_size', 'range_alloc_block_size', 'transaction_alloc_block_size', 'transaction_prealloc_size') order by 1;
set @@range_alloc_block_size=1024*16;
set @@query_alloc_block_size=1024*17+2;
set @@query_prealloc_size=1024*18;
set @@transaction_alloc_block_size=1024*20-1;
set @@transaction_prealloc_size=1024*21-1;
select @@query_alloc_block_size;
-show variables like '%alloc%';
-select * from information_schema.session_variables where variable_name like '%alloc%' order by 1;
+show variables where variable_name in ('query_alloc_block_size', 'query_prealloc_size', 'range_alloc_block_size', 'transaction_alloc_block_size', 'transaction_prealloc_size');
+select * from information_schema.session_variables where variable_name in ('query_alloc_block_size', 'query_prealloc_size', 'range_alloc_block_size', 'transaction_alloc_block_size', 'transaction_prealloc_size') order by 1;
set @@range_alloc_block_size=default;
set @@query_alloc_block_size=default, @@query_prealloc_size=default;
set transaction_alloc_block_size=default, @@transaction_prealloc_size=default;
-show variables like '%alloc%';
-select * from information_schema.session_variables where variable_name like '%alloc%' order by 1;
+show variables where variable_name in ('query_alloc_block_size', 'query_prealloc_size', 'range_alloc_block_size', 'transaction_alloc_block_size', 'transaction_prealloc_size');
+select * from information_schema.session_variables where variable_name in ('query_alloc_block_size', 'query_prealloc_size', 'range_alloc_block_size', 'transaction_alloc_block_size', 'transaction_prealloc_size') order by 1;
#
# Bug #10904 Illegal mix of collations between
......@@ -447,14 +447,29 @@ row_merge_tuple_cmp(
int cmp;
const dfield_t* field = a;
/* Compare the fields of the tuples until a difference is
found or we run out of fields to compare. If !cmp at the
end, the tuples are equal. */
do {
cmp = cmp_dfield_dfield(a++, b++);
} while (!cmp && --n_field);
if (UNIV_UNLIKELY(!cmp) && UNIV_LIKELY_NULL(dup)) {
/* Report a duplicate value error if the tuples are
logically equal. NULL columns are logically inequal,
although they are equal in the sorting order. Find
out if any of the fields are NULL. */
for (b = field; b != a; b++) {
if (dfield_is_null(b)) {
goto func_exit;
}
}
row_merge_dup_report(dup, field);
}
func_exit:
return(cmp);
}
......@@ -1839,7 +1854,7 @@ row_merge_drop_temp_indexes(void)
"PROCEDURE DROP_TEMP_INDEXES_PROC () IS\n"
"indexid CHAR;\n"
"DECLARE CURSOR c IS SELECT ID FROM SYS_INDEXES\n"
"WHERE SUBSTR(NAME,0,1)='\377' FOR UPDATE;\n"
"WHERE SUBSTR(NAME,0,1)='\377';\n"
"BEGIN\n"
"\tOPEN c;\n"
"\tWHILE 1=1 LOOP\n"
......@@ -1848,7 +1863,7 @@ row_merge_drop_temp_indexes(void)
"\t\t\tEXIT;\n"
"\t\tEND IF;\n"
"\t\tDELETE FROM SYS_FIELDS WHERE INDEX_ID = indexid;\n"
"\t\tDELETE FROM SYS_INDEXES WHERE CURRENT OF c;\n"
"\t\tDELETE FROM SYS_INDEXES WHERE ID = indexid;\n"
"\tEND LOOP;\n"
"\tCLOSE c;\n"
"\tCOMMIT WORK;\n"
......@@ -1858,6 +1873,15 @@ row_merge_drop_temp_indexes(void)
trx->op_info = "dropping partially created indexes";
row_mysql_lock_data_dictionary(trx);
/* Incomplete transactions may be holding some locks on the
data dictionary tables. However, they should never have been
able to lock the records corresponding to the partially
created indexes that we are attempting to delete, because the
table was locked when the indexes were being created. We will
drop the partially created indexes before the rollback of
incomplete transactions is initiated. Thus, this should not
interfere with the incomplete transactions. */
trx->isolation_level = TRX_ISO_READ_UNCOMMITTED;
err = que_eval_sql(NULL, drop_temp_indexes, FALSE, trx);
ut_a(err == DB_SUCCESS);
......@@ -1974,7 +1998,6 @@ row_merge_create_temporary_table(
if (error != DB_SUCCESS) {
trx->error_state = error;
dict_mem_table_free(new_table);
new_table = NULL;
}
......
......@@ -1443,12 +1443,13 @@ row_unlock_for_mysql(
ut_ad(prebuilt && trx);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
if (!(srv_locks_unsafe_for_binlog
|| trx->isolation_level == TRX_ISO_READ_COMMITTED)) {
if (UNIV_UNLIKELY
(!srv_locks_unsafe_for_binlog
&& trx->isolation_level != TRX_ISO_READ_COMMITTED)) {
fprintf(stderr,
"InnoDB: Error: calling row_unlock_for_mysql though\n"
"InnoDB: srv_locks_unsafe_for_binlog is FALSE and\n"
"InnoDB: innodb_locks_unsafe_for_binlog is FALSE and\n"
"InnoDB: this session is not using"
" READ COMMITTED isolation level.\n");
......
......@@ -142,6 +142,8 @@ UNIV_INTERN ulong srv_flush_log_at_trx_commit = 1;
collation */
UNIV_INTERN const byte* srv_latin1_ordering;
/* use os/external memory allocator */
UNIV_INTERN my_bool srv_use_sys_malloc = FALSE;
/* requested size in kilobytes */
UNIV_INTERN ulint srv_buf_pool_size = ULINT_MAX;
/* previously requested size */
......@@ -1463,10 +1465,13 @@ srv_suspend_mysql_thread(
ut_a(trx->dict_operation_lock_mode == 0);
/* Wait for the release */
/* Suspend this thread and wait for the event. */
os_event_wait(event);
/* After resuming, reacquire the data dictionary latch if
necessary. */
switch (had_dict_lock) {
case RW_S_LATCH:
row_mysql_freeze_data_dictionary(trx);
......
......@@ -1048,6 +1048,11 @@ innobase_start_or_create_for_mysql(void)
"InnoDB: !!!!!!!! UNIV_MEM_DEBUG switched on !!!!!!!!!\n");
#endif
if (srv_use_sys_malloc) {
fprintf(stderr,
"InnoDB: The InnoDB memory heap is disabled\n");
}
/* Since InnoDB does not currently clean up all its internal data
structures in MySQL Embedded Server Library server_end(), we
print an error message if someone tries to start up InnoDB a
......
......@@ -71,7 +71,7 @@ thr_local_get(
local = NULL;
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
thr_local_t*, local, os_thread_eq(local->id, id));
thr_local_t*, local,, os_thread_eq(local->id, id));
if (local == NULL) {
mutex_exit(&thr_local_mutex);
......@@ -195,7 +195,7 @@ thr_local_free(
/* Look for the local struct in the hash table */
HASH_SEARCH(hash, thr_local_hash, os_thread_pf(id),
thr_local_t*, local, os_thread_eq(local->id, id));
thr_local_t*, local,, os_thread_eq(local->id, id));
if (local == NULL) {
mutex_exit(&thr_local_mutex);
......
......@@ -821,6 +821,8 @@ search_innodb_locks(
i_s_hash_chain_t*,
/* auxiliary variable */
hash_chain,
/* assertion on every traversed item */
,
/* this determines if we have found the lock */
locks_row_eq_lock(hash_chain->value, lock, heap_no));
......
......@@ -171,8 +171,26 @@ trx_rollback_last_sql_stat_for_mysql(
}
/***********************************************************************
Frees savepoint structs. */
Frees a single savepoint struct. */
UNIV_INTERN
void
trx_roll_savepoint_free(
/*=====================*/
trx_t* trx, /* in: transaction handle */
trx_named_savept_t* savep) /* in: savepoint to free */
{
ut_a(savep != NULL);
ut_a(UT_LIST_GET_LEN(trx->trx_savepoints) > 0);
UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep);
mem_free(savep->name);
mem_free(savep);
}
/***********************************************************************
Frees savepoint structs starting from savep, if savep == NULL then
free all savepoints. */
void
trx_roll_savepoints_free(
/*=====================*/
......@@ -192,9 +210,7 @@ trx_roll_savepoints_free(
while (savep != NULL) {
next_savep = UT_LIST_GET_NEXT(trx_savepoints, savep);
UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep);
mem_free(savep->name);
mem_free(savep);
trx_roll_savepoint_free(trx, savep);
savep = next_savep;
}
......@@ -329,8 +345,8 @@ trx_savepoint_for_mysql(
}
/***********************************************************************
Releases a named savepoint. Savepoints which
were set after this savepoint are deleted. */
Releases only the named savepoint. Savepoints which were set after this
savepoint are left as is. */
UNIV_INTERN
ulint
trx_release_savepoint_for_mysql(
......@@ -346,31 +362,16 @@ trx_release_savepoint_for_mysql(
savep = UT_LIST_GET_FIRST(trx->trx_savepoints);
/* Search for the savepoint by name and free if found. */
while (savep != NULL) {
if (0 == ut_strcmp(savep->name, savepoint_name)) {
/* Found */
break;
trx_roll_savepoint_free(trx, savep);
return(DB_SUCCESS);
}
savep = UT_LIST_GET_NEXT(trx_savepoints, savep);
}
if (savep == NULL) {
return(DB_NO_SAVEPOINT);
}
/* We can now free all savepoints strictly later than this one */
trx_roll_savepoints_free(trx, savep);
/* Now we can free this savepoint too */
UT_LIST_REMOVE(trx_savepoints, trx->trx_savepoints, savep);
mem_free(savep->name);
mem_free(savep);
return(DB_SUCCESS);
}
/***********************************************************************
......
......@@ -917,8 +917,8 @@ trx_commit_off_kernel(
mutex_enter(&kernel_mutex);
}
/* Free savepoints */
trx_roll_savepoints_free(trx, NULL);
/* Free all savepoints */
trx_roll_free_all_savepoints(trx);
trx->conc_state = TRX_NOT_STARTED;
trx->rseg = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment