Commit 6a9a96dc authored by unknown's avatar unknown

Fixed: BUG#15653, BUG#16157, BUG#16229, BUG#16298, BUG#16387, BUG#16582.

  Applied innodb-5.0-ss149/162 snapshots.


innobase/btr/btr0sea.c:
  Applied innodb-5.0-149/162 snapshots.
    Account for a race condition when dropping the adaptive hash
    index for a B-tree page (Bug #16582).
    btr_search_drop_page_hash_index(): Retry the operation if a
      hash index with different parameters was built meanwhile.
      Add diagnostics for the case that hash node pointers to
      the page remain. This fix is from Heikki.
    btr_search_info-update_hash(), btr_search_info_update_slow():
      Document the parameter "info" as in/out.
innobase/dict/dict0dict.c:
  Applied innodb-5.0-149/162 snapshots.
    Do not mistake TABLENAME_ibfk_0 for auto generated id (Bug #16387).
    dict_table_get_highest_foreign_id(): Ignore foreign constraint
      identifiers starting with the pattern TABLENAME_ibfk_0.
innobase/dict/dict0load.c:
  Applied innodb-5.0-149/162 snapshots.
    dict_load_columns(): Set the charset-collation code
    DATA_MYSQL_BINARY_CHARSET_COLL for those binary string columns
    that lack a charset-collation code, i.e., the tables were created
    with an older version of MySQL/InnoDB than 4.1.2 (Bug #16298).
innobase/fil/fil0fil.c:
  Applied innodb-5.0-149/162 snapshots.
    Keep track on unflushed modifications to file spaces. When there
    are tens of thousands of file spaces, flushing all files in
    fil_flush_file_spaces() would be very slow (Bug #15653).
    fil_flush_file_spaces(): Only flush unflushed file spaces.
    fil_space_t, fil_system_t: Add a list of unflushed spaces.
innobase/include/univ.i:
  Applied innodb-5.0-149/162 snapshots.
    Avoid breaking --with-debug builds on QNS and other systems
    whose compiler pretends to be GCC 2.
    Outside __WIN__ define UNIV_INLINE as static inline.
innobase/os/os0sync.c:
  Applied innodb-5.0-149/162 snapshots.
    Replace goto in os_event_wait with a normal loop.
innobase/srv/srv0start.c:
  Applied innodb-5.0-149/162 snapshots.
    Fix bug #16157, a crash when innodb_log_group_home_dir is set
    to an empty string. This patch is from Heikki.
mysql-test/r/innodb.result:
  Applied innodb-5.0-149/162 snapshots.
    Fixed results for added test cases.
mysql-test/t/innodb.test:
  Applied innodb-5.0-149/162 snapshots.
    Added test cases.
sql/ha_innodb.cc:
  Applied innodb-5.0-149/162 snapshots.
    Remove some declarations of unused global variables and member
      variables of class ha_innobase.
    Added diagnostic code trx_print() to
      innobase_query_caching_of_table_permitted() to find reason
      why we are holding adaptive search latch.
    Fixed bug #16229 MySQL/InnoDB uses full explicit table locks
      in trigger processing. Take a InnoDB table lock only if user
      has explicitly requested a table lock. Added some additional
      comments to store_lock() and external_lock(). Fixed some
      code style errors.
    Remember to use noninlined versions of the functions on
      ha_innodb.cc !
sql/ha_innodb.h:
  Applied innodb-5.0-149/162 snapshots.
    Remove some declarations of unused global variables and member
    variables of class ha_innobase.
parent 107ad3a0
...@@ -191,7 +191,7 @@ static ...@@ -191,7 +191,7 @@ static
void void
btr_search_info_update_hash( btr_search_info_update_hash(
/*========================*/ /*========================*/
btr_search_t* info, /* in: search info */ btr_search_t* info, /* in/out: search info */
btr_cur_t* cursor) /* in: cursor which was just positioned */ btr_cur_t* cursor) /* in: cursor which was just positioned */
{ {
dict_index_t* index; dict_index_t* index;
...@@ -452,7 +452,7 @@ Updates the search info. */ ...@@ -452,7 +452,7 @@ Updates the search info. */
void void
btr_search_info_update_slow( btr_search_info_update_slow(
/*========================*/ /*========================*/
btr_search_t* info, /* in: search info */ btr_search_t* info, /* in/out: search info */
btr_cur_t* cursor) /* in: cursor which was just positioned */ btr_cur_t* cursor) /* in: cursor which was just positioned */
{ {
buf_block_t* block; buf_block_t* block;
...@@ -912,12 +912,12 @@ btr_search_drop_page_hash_index( ...@@ -912,12 +912,12 @@ btr_search_drop_page_hash_index(
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED)); ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX)); ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */ #endif /* UNIV_SYNC_DEBUG */
retry:
rw_lock_s_lock(&btr_search_latch); rw_lock_s_lock(&btr_search_latch);
block = buf_block_align(page); block = buf_block_align(page);
if (!block->is_hashed) { if (UNIV_LIKELY(!block->is_hashed)) {
rw_lock_s_unlock(&btr_search_latch); rw_lock_s_unlock(&btr_search_latch);
...@@ -958,6 +958,8 @@ btr_search_drop_page_hash_index( ...@@ -958,6 +958,8 @@ btr_search_drop_page_hash_index(
tree_id = btr_page_get_index_id(page); tree_id = btr_page_get_index_id(page);
ut_a(0 == ut_dulint_cmp(tree_id, index->id));
prev_fold = 0; prev_fold = 0;
heap = NULL; heap = NULL;
...@@ -992,6 +994,26 @@ next_rec: ...@@ -992,6 +994,26 @@ next_rec:
rw_lock_x_lock(&btr_search_latch); rw_lock_x_lock(&btr_search_latch);
if (UNIV_UNLIKELY(!block->is_hashed)) {
/* Someone else has meanwhile dropped the hash index */
goto cleanup;
}
ut_a(block->index == index);
if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
|| UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
/* Someone else has meanwhile built a new hash index on the
page, with different parameters */
rw_lock_x_unlock(&btr_search_latch);
mem_free(folds);
goto retry;
}
for (i = 0; i < n_cached; i++) { for (i = 0; i < n_cached; i++) {
ha_remove_all_nodes_to_page(table, folds[i], page); ha_remove_all_nodes_to_page(table, folds[i], page);
...@@ -999,8 +1021,20 @@ next_rec: ...@@ -999,8 +1021,20 @@ next_rec:
block->is_hashed = FALSE; block->is_hashed = FALSE;
block->index = NULL; block->index = NULL;
cleanup:
if (UNIV_UNLIKELY(block->n_pointers)) {
/* Corruption */
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Corruption of adaptive hash index. After dropping\n"
"InnoDB: the hash index to a page of %s, still %lu hash nodes remain.\n",
index->name, (ulong) block->n_pointers);
rw_lock_x_unlock(&btr_search_latch);
rw_lock_x_unlock(&btr_search_latch); btr_search_validate();
} else {
rw_lock_x_unlock(&btr_search_latch);
}
mem_free(folds); mem_free(folds);
} }
......
...@@ -2803,7 +2803,8 @@ dict_table_get_highest_foreign_id( ...@@ -2803,7 +2803,8 @@ dict_table_get_highest_foreign_id(
if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len
&& 0 == ut_memcmp(foreign->id, table->name, len) && 0 == ut_memcmp(foreign->id, table->name, len)
&& 0 == ut_memcmp(foreign->id + len, && 0 == ut_memcmp(foreign->id + len,
dict_ibfk, (sizeof dict_ibfk) - 1)) { dict_ibfk, (sizeof dict_ibfk) - 1)
&& foreign->id[len + ((sizeof dict_ibfk) - 1)] != '0') {
/* It is of the >= 4.0.18 format */ /* It is of the >= 4.0.18 format */
id = strtoul(foreign->id + len + ((sizeof dict_ibfk) - 1), id = strtoul(foreign->id + len + ((sizeof dict_ibfk) - 1),
......
...@@ -385,13 +385,23 @@ dict_load_columns( ...@@ -385,13 +385,23 @@ dict_load_columns(
field = rec_get_nth_field_old(rec, 6, &len); field = rec_get_nth_field_old(rec, 6, &len);
prtype = mach_read_from_4(field); prtype = mach_read_from_4(field);
if (dtype_is_non_binary_string_type(mtype, prtype) if (dtype_get_charset_coll(prtype) == 0
&& dtype_get_charset_coll(prtype) == 0) { && dtype_is_string_type(mtype)) {
/* This is a non-binary string type, and the table /* The table was created with < 4.1.2. */
was created with < 4.1.2. Use the default charset. */
prtype = dtype_form_prtype(prtype, if (dtype_is_binary_string_type(mtype, prtype)) {
/* Use the binary collation for
string columns of binary type. */
prtype = dtype_form_prtype(prtype,
DATA_MYSQL_BINARY_CHARSET_COLL);
} else {
/* Use the default charset for
other than binary columns. */
prtype = dtype_form_prtype(prtype,
data_mysql_default_charset_coll); data_mysql_default_charset_coll);
}
} }
field = rec_get_nth_field_old(rec, 7, &len); field = rec_get_nth_field_old(rec, 7, &len);
......
...@@ -181,6 +181,11 @@ struct fil_space_struct { ...@@ -181,6 +181,11 @@ struct fil_space_struct {
hash_node_t name_hash;/* hash chain the name_hash table */ hash_node_t name_hash;/* hash chain the name_hash table */
rw_lock_t latch; /* latch protecting the file space storage rw_lock_t latch; /* latch protecting the file space storage
allocation */ allocation */
UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
/* list of spaces with at least one unflushed
file we have written to */
ibool is_in_unflushed_spaces; /* TRUE if this space is
currently in the list above */
UT_LIST_NODE_T(fil_space_t) space_list; UT_LIST_NODE_T(fil_space_t) space_list;
/* list of all spaces */ /* list of all spaces */
ibuf_data_t* ibuf_data; ibuf_data_t* ibuf_data;
...@@ -213,6 +218,12 @@ struct fil_system_struct { ...@@ -213,6 +218,12 @@ struct fil_system_struct {
not put to this list: they are opened not put to this list: they are opened
after the startup, and kept open until after the startup, and kept open until
shutdown */ shutdown */
UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
/* base node for the list of those
tablespaces whose files contain
unflushed writes; those spaces have
at least one file node where
modification_counter > flush_counter */
ulint n_open; /* number of files currently open */ ulint n_open; /* number of files currently open */
ulint max_n_open; /* n_open is not allowed to exceed ulint max_n_open; /* n_open is not allowed to exceed
this */ this */
...@@ -389,6 +400,36 @@ fil_space_get_ibuf_data( ...@@ -389,6 +400,36 @@ fil_space_get_ibuf_data(
return(space->ibuf_data); return(space->ibuf_data);
} }
/**************************************************************************
Checks if all the file nodes in a space are flushed. The caller must hold
the fil_system mutex. */
static
ibool
fil_space_is_flushed(
/*=================*/
/* out: TRUE if all are flushed */
fil_space_t* space) /* in: space */
{
fil_node_t* node;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(fil_system->mutex)));
#endif /* UNIV_SYNC_DEBUG */
node = UT_LIST_GET_FIRST(space->chain);
while (node) {
if (node->modification_counter > node->flush_counter) {
return(FALSE);
}
node = UT_LIST_GET_NEXT(chain, node);
}
return(TRUE);
}
/*********************************************************************** /***********************************************************************
Appends a new file to the chain of files of a space. File must be closed. */ Appends a new file to the chain of files of a space. File must be closed. */
...@@ -841,6 +882,16 @@ fil_node_free( ...@@ -841,6 +882,16 @@ fil_node_free(
node->modification_counter = node->flush_counter; node->modification_counter = node->flush_counter;
if (space->is_in_unflushed_spaces
&& fil_space_is_flushed(space)) {
space->is_in_unflushed_spaces = FALSE;
UT_LIST_REMOVE(unflushed_spaces,
system->unflushed_spaces,
space);
}
fil_node_close_file(node, system); fil_node_close_file(node, system);
} }
...@@ -1004,6 +1055,8 @@ try_again: ...@@ -1004,6 +1055,8 @@ try_again:
HASH_INSERT(fil_space_t, name_hash, system->name_hash, HASH_INSERT(fil_space_t, name_hash, system->name_hash,
ut_fold_string(name), space); ut_fold_string(name), space);
space->is_in_unflushed_spaces = FALSE;
UT_LIST_ADD_LAST(space_list, system->space_list, space); UT_LIST_ADD_LAST(space_list, system->space_list, space);
mutex_exit(&(system->mutex)); mutex_exit(&(system->mutex));
...@@ -1099,6 +1152,13 @@ fil_space_free( ...@@ -1099,6 +1152,13 @@ fil_space_free(
HASH_DELETE(fil_space_t, name_hash, system->name_hash, HASH_DELETE(fil_space_t, name_hash, system->name_hash,
ut_fold_string(space->name), space); ut_fold_string(space->name), space);
if (space->is_in_unflushed_spaces) {
space->is_in_unflushed_spaces = FALSE;
UT_LIST_REMOVE(unflushed_spaces, system->unflushed_spaces,
space);
}
UT_LIST_REMOVE(space_list, system->space_list, space); UT_LIST_REMOVE(space_list, system->space_list, space);
ut_a(space->magic_n == FIL_SPACE_MAGIC_N); ut_a(space->magic_n == FIL_SPACE_MAGIC_N);
...@@ -1250,6 +1310,7 @@ fil_system_create( ...@@ -1250,6 +1310,7 @@ fil_system_create(
system->tablespace_version = 0; system->tablespace_version = 0;
UT_LIST_INIT(system->unflushed_spaces);
UT_LIST_INIT(system->space_list); UT_LIST_INIT(system->space_list);
return(system); return(system);
...@@ -3742,6 +3803,14 @@ fil_node_complete_io( ...@@ -3742,6 +3803,14 @@ fil_node_complete_io(
if (type == OS_FILE_WRITE) { if (type == OS_FILE_WRITE) {
system->modification_counter++; system->modification_counter++;
node->modification_counter = system->modification_counter; node->modification_counter = system->modification_counter;
if (!node->space->is_in_unflushed_spaces) {
node->space->is_in_unflushed_spaces = TRUE;
UT_LIST_ADD_FIRST(unflushed_spaces,
system->unflushed_spaces,
node->space);
}
} }
if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE
...@@ -4162,6 +4231,16 @@ retry: ...@@ -4162,6 +4231,16 @@ retry:
skip_flush: skip_flush:
if (node->flush_counter < old_mod_counter) { if (node->flush_counter < old_mod_counter) {
node->flush_counter = old_mod_counter; node->flush_counter = old_mod_counter;
if (space->is_in_unflushed_spaces
&& fil_space_is_flushed(space)) {
space->is_in_unflushed_spaces = FALSE;
UT_LIST_REMOVE(unflushed_spaces,
system->unflushed_spaces,
space);
}
} }
if (space->purpose == FIL_TABLESPACE) { if (space->purpose == FIL_TABLESPACE) {
...@@ -4193,7 +4272,7 @@ fil_flush_file_spaces( ...@@ -4193,7 +4272,7 @@ fil_flush_file_spaces(
mutex_enter(&(system->mutex)); mutex_enter(&(system->mutex));
space = UT_LIST_GET_FIRST(system->space_list); space = UT_LIST_GET_FIRST(system->unflushed_spaces);
while (space) { while (space) {
if (space->purpose == purpose && !space->is_being_deleted) { if (space->purpose == purpose && !space->is_being_deleted) {
...@@ -4209,7 +4288,7 @@ fil_flush_file_spaces( ...@@ -4209,7 +4288,7 @@ fil_flush_file_spaces(
space->n_pending_flushes--; space->n_pending_flushes--;
} }
space = UT_LIST_GET_NEXT(space_list, space); space = UT_LIST_GET_NEXT(unflushed_spaces, space);
} }
mutex_exit(&(system->mutex)); mutex_exit(&(system->mutex));
......
...@@ -126,14 +126,8 @@ by one. */ ...@@ -126,14 +126,8 @@ by one. */
#ifdef __WIN__ #ifdef __WIN__
#define UNIV_INLINE __inline #define UNIV_INLINE __inline
#else #else
/* config.h contains the right def for 'inline' for the current compiler */
#if (__GNUC__ == 2)
#define UNIV_INLINE extern inline
#else
/* extern inline doesn't work with gcc 3.0.2 */
#define UNIV_INLINE static inline #define UNIV_INLINE static inline
#endif #endif
#endif
#else #else
/* If we want to compile a noninlined version we use the following macro /* If we want to compile a noninlined version we use the following macro
......
...@@ -317,28 +317,28 @@ os_event_wait( ...@@ -317,28 +317,28 @@ os_event_wait(
os_fast_mutex_lock(&(event->os_mutex)); os_fast_mutex_lock(&(event->os_mutex));
old_signal_count = event->signal_count; old_signal_count = event->signal_count;
loop:
if (event->is_set == TRUE
|| event->signal_count != old_signal_count) {
os_fast_mutex_unlock(&(event->os_mutex)); for (;;) {
if (event->is_set == TRUE
|| event->signal_count != old_signal_count) {
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) { os_fast_mutex_unlock(&(event->os_mutex));
os_thread_exit(NULL); if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
}
/* Ok, we may return */
return; os_thread_exit(NULL);
} }
/* Ok, we may return */
pthread_cond_wait(&(event->cond_var), &(event->os_mutex)); return;
}
/* Solaris manual said that spurious wakeups may occur: we have to pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
check if the event really has been signaled after we came here to
wait */
goto loop; /* Solaris manual said that spurious wakeups may occur: we
have to check if the event really has been signaled after
we came here to wait */
}
#endif #endif
} }
......
...@@ -233,6 +233,13 @@ srv_parse_data_file_paths_and_sizes( ...@@ -233,6 +233,13 @@ srv_parse_data_file_paths_and_sizes(
} }
} }
if (i == 0) {
/* If innodb_data_file_path was defined it must contain
at least one data file definition */
return(FALSE);
}
*data_file_names = (char**)ut_malloc(i * sizeof(void*)); *data_file_names = (char**)ut_malloc(i * sizeof(void*));
*data_file_sizes = (ulint*)ut_malloc(i * sizeof(ulint)); *data_file_sizes = (ulint*)ut_malloc(i * sizeof(ulint));
*data_file_is_raw_partition = (ulint*)ut_malloc(i * sizeof(ulint)); *data_file_is_raw_partition = (ulint*)ut_malloc(i * sizeof(ulint));
...@@ -379,6 +386,13 @@ srv_parse_log_group_home_dirs( ...@@ -379,6 +386,13 @@ srv_parse_log_group_home_dirs(
} }
} }
if (i != 1) {
/* If innodb_log_group_home_dir was defined it must
contain exactly one path definition under current MySQL */
return(FALSE);
}
*log_group_home_dirs = (char**) ut_malloc(i * sizeof(void*)); *log_group_home_dirs = (char**) ut_malloc(i * sizeof(void*));
/* Then store the actual values to our array */ /* Then store the actual values to our array */
......
...@@ -3180,3 +3180,74 @@ a hex(b) ...@@ -3180,3 +3180,74 @@ a hex(b)
7 D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2 7 D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2
update t1 set b = 'three' where a = 6; update t1 set b = 'three' where a = 6;
drop table t1; drop table t1;
CREATE TABLE t1(a INT, PRIMARY KEY(a)) ENGINE=InnoDB;
CREATE TABLE t2(a INT) ENGINE=InnoDB;
ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1(a);
ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_1;
ALTER TABLE t2 ADD CONSTRAINT t2_ibfk_0 FOREIGN KEY (a) REFERENCES t1(a);
ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_0;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
`a` int(11) default NULL,
KEY `t2_ibfk_0` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
DROP TABLE t2,t1;
create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
insert into t1(a) values (1),(2),(3);
commit;
set autocommit = 0;
update t1 set b = 5 where a = 2;
create trigger t1t before insert on t1 for each row begin set NEW.b = NEW.a * 10 + 5, NEW.c = NEW.a / 10; end |
set autocommit = 0;
insert into t1(a) values (10),(20),(30),(40),(50),(60),(70),(80),(90),(100),
(11),(21),(31),(41),(51),(61),(71),(81),(91),(101),
(12),(22),(32),(42),(52),(62),(72),(82),(92),(102),
(13),(23),(33),(43),(53),(63),(73),(83),(93),(103),
(14),(24),(34),(44),(54),(64),(74),(84),(94),(104);
commit;
commit;
drop trigger t1t;
drop table t1;
create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
create table t2(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
create table t3(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
create table t4(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
create table t5(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
insert into t1(a) values (1),(2),(3);
insert into t2(a) values (1),(2),(3);
insert into t3(a) values (1),(2),(3);
insert into t4(a) values (1),(2),(3);
insert into t3(a) values (5),(7),(8);
insert into t4(a) values (5),(7),(8);
insert into t5(a) values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12);
create trigger t1t before insert on t1 for each row begin
INSERT INTO t2 SET a = NEW.a;
end |
create trigger t2t before insert on t2 for each row begin
DELETE FROM t3 WHERE a = NEW.a;
end |
create trigger t3t before delete on t3 for each row begin
UPDATE t4 SET b = b + 1 WHERE a = OLD.a;
end |
create trigger t4t before update on t4 for each row begin
UPDATE t5 SET b = b + 1 where a = NEW.a;
end |
commit;
set autocommit = 0;
update t1 set b = b + 5 where a = 1;
update t2 set b = b + 5 where a = 1;
update t3 set b = b + 5 where a = 1;
update t4 set b = b + 5 where a = 1;
insert into t5(a) values(20);
set autocommit = 0;
insert into t1(a) values(7);
insert into t2(a) values(8);
delete from t2 where a = 3;
update t4 set b = b + 1 where a = 3;
commit;
drop trigger t1t;
drop trigger t2t;
drop trigger t3t;
drop trigger t4t;
drop table t1, t2, t3, t4, t5;
...@@ -2047,3 +2047,105 @@ insert into t1 values(7,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1 ...@@ -2047,3 +2047,105 @@ insert into t1 values(7,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1
select a,hex(b) from t1 order by b; select a,hex(b) from t1 order by b;
update t1 set b = 'three' where a = 6; update t1 set b = 'three' where a = 6;
drop table t1; drop table t1;
# Ensure that <tablename>_ibfk_0 is not mistreated as a
# generated foreign key identifier. (Bug #16387)
CREATE TABLE t1(a INT, PRIMARY KEY(a)) ENGINE=InnoDB;
CREATE TABLE t2(a INT) ENGINE=InnoDB;
ALTER TABLE t2 ADD FOREIGN KEY (a) REFERENCES t1(a);
ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_1;
ALTER TABLE t2 ADD CONSTRAINT t2_ibfk_0 FOREIGN KEY (a) REFERENCES t1(a);
ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_0;
SHOW CREATE TABLE t2;
DROP TABLE t2,t1;
#
# Test case for bug #16229: MySQL/InnoDB uses full explicit table locks in trigger processing
#
connect (a,localhost,root,,);
connect (b,localhost,root,,);
connection a;
create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
insert into t1(a) values (1),(2),(3);
commit;
connection b;
set autocommit = 0;
update t1 set b = 5 where a = 2;
connection a;
delimiter |;
create trigger t1t before insert on t1 for each row begin set NEW.b = NEW.a * 10 + 5, NEW.c = NEW.a / 10; end |
delimiter ;|
set autocommit = 0;
connection a;
insert into t1(a) values (10),(20),(30),(40),(50),(60),(70),(80),(90),(100),
(11),(21),(31),(41),(51),(61),(71),(81),(91),(101),
(12),(22),(32),(42),(52),(62),(72),(82),(92),(102),
(13),(23),(33),(43),(53),(63),(73),(83),(93),(103),
(14),(24),(34),(44),(54),(64),(74),(84),(94),(104);
connection b;
commit;
connection a;
commit;
drop trigger t1t;
drop table t1;
disconnect a;
disconnect b;
#
# Another trigger test
#
connect (a,localhost,root,,);
connect (b,localhost,root,,);
connection a;
create table t1(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
create table t2(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
create table t3(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
create table t4(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
create table t5(a int not null, b int, c int, d int, primary key(a)) engine=innodb;
insert into t1(a) values (1),(2),(3);
insert into t2(a) values (1),(2),(3);
insert into t3(a) values (1),(2),(3);
insert into t4(a) values (1),(2),(3);
insert into t3(a) values (5),(7),(8);
insert into t4(a) values (5),(7),(8);
insert into t5(a) values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12);
delimiter |;
create trigger t1t before insert on t1 for each row begin
INSERT INTO t2 SET a = NEW.a;
end |
create trigger t2t before insert on t2 for each row begin
DELETE FROM t3 WHERE a = NEW.a;
end |
create trigger t3t before delete on t3 for each row begin
UPDATE t4 SET b = b + 1 WHERE a = OLD.a;
end |
create trigger t4t before update on t4 for each row begin
UPDATE t5 SET b = b + 1 where a = NEW.a;
end |
delimiter ;|
commit;
set autocommit = 0;
update t1 set b = b + 5 where a = 1;
update t2 set b = b + 5 where a = 1;
update t3 set b = b + 5 where a = 1;
update t4 set b = b + 5 where a = 1;
insert into t5(a) values(20);
connection b;
set autocommit = 0;
insert into t1(a) values(7);
insert into t2(a) values(8);
delete from t2 where a = 3;
update t4 set b = b + 1 where a = 3;
commit;
drop trigger t1t;
drop trigger t2t;
drop trigger t3t;
drop trigger t4t;
drop table t1, t2, t3, t4, t5;
disconnect a;
disconnect b;
...@@ -138,8 +138,6 @@ extern "C" { ...@@ -138,8 +138,6 @@ extern "C" {
#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */ #define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
#define HA_INNOBASE_RANGE_COUNT 100 #define HA_INNOBASE_RANGE_COUNT 100
uint innobase_init_flags = 0;
ulong innobase_cache_size = 0;
ulong innobase_large_page_size = 0; ulong innobase_large_page_size = 0;
/* The default values for the following, type long or longlong, start-up /* The default values for the following, type long or longlong, start-up
...@@ -187,8 +185,6 @@ it every INNOBASE_WAKE_INTERVAL'th step. */ ...@@ -187,8 +185,6 @@ it every INNOBASE_WAKE_INTERVAL'th step. */
#define INNOBASE_WAKE_INTERVAL 32 #define INNOBASE_WAKE_INTERVAL 32
ulong innobase_active_counter = 0; ulong innobase_active_counter = 0;
char* innobase_home = NULL;
static HASH innobase_open_tables; static HASH innobase_open_tables;
#ifdef __NETWARE__ /* some special cleanup for NetWare */ #ifdef __NETWARE__ /* some special cleanup for NetWare */
...@@ -814,7 +810,6 @@ ha_innobase::ha_innobase(TABLE *table_arg) ...@@ -814,7 +810,6 @@ ha_innobase::ha_innobase(TABLE *table_arg)
HA_PRIMARY_KEY_IN_READ_INDEX | HA_PRIMARY_KEY_IN_READ_INDEX |
HA_CAN_GEOMETRY | HA_CAN_GEOMETRY |
HA_TABLE_SCAN_ON_INDEX), HA_TABLE_SCAN_ON_INDEX),
last_dup_key((uint) -1),
start_of_scan(0), start_of_scan(0),
num_write_row(0) num_write_row(0)
{} {}
...@@ -983,6 +978,11 @@ innobase_query_caching_of_table_permitted( ...@@ -983,6 +978,11 @@ innobase_query_caching_of_table_permitted(
sql_print_error("The calling thread is holding the adaptive " sql_print_error("The calling thread is holding the adaptive "
"search, latch though calling " "search, latch though calling "
"innobase_query_caching_of_table_permitted."); "innobase_query_caching_of_table_permitted.");
mutex_enter_noninline(&kernel_mutex);
trx_print(stderr, trx, 1024);
mutex_exit_noninline(&kernel_mutex);
ut_error;
} }
innobase_release_stat_resources(trx); innobase_release_stat_resources(trx);
...@@ -6329,14 +6329,17 @@ ha_innobase::external_lock( ...@@ -6329,14 +6329,17 @@ ha_innobase::external_lock(
TABLES if AUTOCOMMIT=1. It does not make much sense to acquire TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
an InnoDB table lock if it is released immediately at the end an InnoDB table lock if it is released immediately at the end
of LOCK TABLES, and InnoDB's table locks in that case cause of LOCK TABLES, and InnoDB's table locks in that case cause
VERY easily deadlocks. We do not set InnoDB table locks when VERY easily deadlocks.
MySQL sets them at the start of a stored procedure call
(MySQL does have thd->in_lock_tables TRUE there). */ We do not set InnoDB table locks if user has not explicitly
requested a table lock. Note that thd->in_lock_tables
can be TRUE on some cases e.g. at the start of a stored
procedure call (SQLCOM_CALL). */
if (prebuilt->select_lock_type != LOCK_NONE) { if (prebuilt->select_lock_type != LOCK_NONE) {
if (thd->in_lock_tables && if (thd->in_lock_tables &&
thd->lex->sql_command != SQLCOM_CALL && thd->lex->sql_command == SQLCOM_LOCK_TABLES &&
thd->variables.innodb_table_locks && thd->variables.innodb_table_locks &&
(thd->options & OPTION_NOT_AUTOCOMMIT)) { (thd->options & OPTION_NOT_AUTOCOMMIT)) {
...@@ -6838,7 +6841,7 @@ ha_innobase::store_lock( ...@@ -6838,7 +6841,7 @@ ha_innobase::store_lock(
} else if (lock_type != TL_IGNORE) { } else if (lock_type != TL_IGNORE) {
/* We set possible LOCK_X value in external_lock, not yet /* We set possible LOCK_X value in external_lock, not yet
here even if this would be SELECT ... FOR UPDATE */ here even if this would be SELECT ... FOR UPDATE */
prebuilt->select_lock_type = LOCK_NONE; prebuilt->select_lock_type = LOCK_NONE;
...@@ -6847,7 +6850,7 @@ ha_innobase::store_lock( ...@@ -6847,7 +6850,7 @@ ha_innobase::store_lock(
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) { if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
/* Starting from 5.0.7, we weaken also the table locks /* Starting from 5.0.7, we weaken also the table locks
set at the start of a MySQL stored procedure call, just like set at the start of a MySQL stored procedure call, just like
we weaken the locks set at the start of an SQL statement. we weaken the locks set at the start of an SQL statement.
MySQL does set thd->in_lock_tables TRUE there, but in reality MySQL does set thd->in_lock_tables TRUE there, but in reality
...@@ -6870,26 +6873,36 @@ ha_innobase::store_lock( ...@@ -6870,26 +6873,36 @@ ha_innobase::store_lock(
lock_type = TL_READ_NO_INSERT; lock_type = TL_READ_NO_INSERT;
} }
/* If we are not doing a LOCK TABLE or DISCARD/IMPORT /* If we are not doing a LOCK TABLE, DISCARD/IMPORT
TABLESPACE or TRUNCATE TABLE, then allow multiple writers */ TABLESPACE or TRUNCATE TABLE then allow multiple
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
< TL_WRITE_CONCURRENT_INSERT.
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && We especially allow multiple writers if MySQL is at the
lock_type <= TL_WRITE) start of a stored procedure call (SQLCOM_CALL)
(MySQL does have thd->in_lock_tables TRUE there). */
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
&& lock_type <= TL_WRITE)
&& (!thd->in_lock_tables && (!thd->in_lock_tables
|| thd->lex->sql_command == SQLCOM_CALL) || thd->lex->sql_command == SQLCOM_CALL)
&& !thd->tablespace_op && !thd->tablespace_op
&& thd->lex->sql_command != SQLCOM_TRUNCATE && thd->lex->sql_command != SQLCOM_TRUNCATE
&& thd->lex->sql_command != SQLCOM_OPTIMIZE && thd->lex->sql_command != SQLCOM_OPTIMIZE
&& thd->lex->sql_command != SQLCOM_CREATE_TABLE) { && thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
lock_type = TL_WRITE_ALLOW_WRITE; lock_type = TL_WRITE_ALLOW_WRITE;
} }
/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ... /* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
MySQL would use the lock TL_READ_NO_INSERT on t2, and that MySQL would use the lock TL_READ_NO_INSERT on t2, and that
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
to t2. Convert the lock to a normal read lock to allow to t2. Convert the lock to a normal read lock to allow
concurrent inserts to t2. */ concurrent inserts to t2.
We especially allow concurrent inserts if MySQL is at the
start of a stored procedure call (SQLCOM_CALL)
(MySQL does have thd->in_lock_tables TRUE there). */
if (lock_type == TL_READ_NO_INSERT if (lock_type == TL_READ_NO_INSERT
&& (!thd->in_lock_tables && (!thd->in_lock_tables
...@@ -6898,10 +6911,10 @@ ha_innobase::store_lock( ...@@ -6898,10 +6911,10 @@ ha_innobase::store_lock(
lock_type = TL_READ; lock_type = TL_READ;
} }
lock.type = lock_type; lock.type = lock_type;
} }
*to++= &lock; *to++= &lock;
return(to); return(to);
} }
......
...@@ -52,7 +52,6 @@ class ha_innobase: public handler ...@@ -52,7 +52,6 @@ class ha_innobase: public handler
THR_LOCK_DATA lock; THR_LOCK_DATA lock;
INNOBASE_SHARE *share; INNOBASE_SHARE *share;
gptr alloc_ptr;
byte* upd_buff; /* buffer used in updates */ byte* upd_buff; /* buffer used in updates */
byte* key_val_buff; /* buffer used in converting byte* key_val_buff; /* buffer used in converting
search key values from MySQL format search key values from MySQL format
...@@ -62,7 +61,6 @@ class ha_innobase: public handler ...@@ -62,7 +61,6 @@ class ha_innobase: public handler
two buffers */ two buffers */
ulong int_table_flags; ulong int_table_flags;
uint primary_key; uint primary_key;
uint last_dup_key;
ulong start_of_scan; /* this is set to 1 when we are ulong start_of_scan; /* this is set to 1 when we are
starting a table scan but have not starting a table scan but have not
yet fetched any row, else 0 */ yet fetched any row, else 0 */
...@@ -70,7 +68,6 @@ class ha_innobase: public handler ...@@ -70,7 +68,6 @@ class ha_innobase: public handler
ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX, ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX,
or undefined */ or undefined */
uint num_write_row; /* number of write_row() calls */ uint num_write_row; /* number of write_row() calls */
ulong max_supported_row_length(const byte *buf);
uint store_key_val_for_row(uint keynr, char* buff, uint buff_len, uint store_key_val_for_row(uint keynr, char* buff, uint buff_len,
const byte* record); const byte* record);
...@@ -199,11 +196,8 @@ class ha_innobase: public handler ...@@ -199,11 +196,8 @@ class ha_innobase: public handler
}; };
extern struct show_var_st innodb_status_variables[]; extern struct show_var_st innodb_status_variables[];
extern uint innobase_init_flags, innobase_lock_type; extern ulong innobase_fast_shutdown;
extern ulong innobase_cache_size, innobase_fast_shutdown;
extern ulong innobase_large_page_size; extern ulong innobase_large_page_size;
extern char *innobase_home, *innobase_tmpdir, *innobase_logdir;
extern long innobase_lock_scan_time;
extern long innobase_mirrored_log_groups, innobase_log_files_in_group; extern long innobase_mirrored_log_groups, innobase_log_files_in_group;
extern longlong innobase_buffer_pool_size, innobase_log_file_size; extern longlong innobase_buffer_pool_size, innobase_log_file_size;
extern long innobase_log_buffer_size; extern long innobase_log_buffer_size;
...@@ -240,8 +234,6 @@ extern ulong srv_commit_concurrency; ...@@ -240,8 +234,6 @@ extern ulong srv_commit_concurrency;
extern ulong srv_flush_log_at_trx_commit; extern ulong srv_flush_log_at_trx_commit;
} }
extern TYPELIB innobase_lock_typelib;
bool innobase_init(void); bool innobase_init(void);
bool innobase_end(void); bool innobase_end(void);
bool innobase_flush_logs(void); bool innobase_flush_logs(void);
...@@ -311,9 +303,6 @@ int innobase_rollback_by_xid( ...@@ -311,9 +303,6 @@ int innobase_rollback_by_xid(
XID *xid); /* in : X/Open XA Transaction Identification */ XID *xid); /* in : X/Open XA Transaction Identification */
int innobase_xa_end(THD *thd);
int innobase_repl_report_sent_binlog(THD *thd, char *log_file_name, int innobase_repl_report_sent_binlog(THD *thd, char *log_file_name,
my_off_t end_offset); my_off_t end_offset);
......
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