summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--innobase/btr/btr0sea.c44
-rw-r--r--innobase/dict/dict0dict.c3
-rw-r--r--innobase/dict/dict0load.c20
-rw-r--r--innobase/fil/fil0fil.c83
-rw-r--r--innobase/include/univ.i6
-rw-r--r--innobase/os/os0sync.c30
-rw-r--r--innobase/srv/srv0start.c14
-rw-r--r--mysql-test/r/innodb.result71
-rw-r--r--mysql-test/t/innodb.test102
-rw-r--r--sql/ha_innodb.cc59
-rw-r--r--sql/ha_innodb.h13
11 files changed, 376 insertions, 69 deletions
diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c
index 81f23cfa99c..32e22aa51bc 100644
--- a/innobase/btr/btr0sea.c
+++ b/innobase/btr/btr0sea.c
@@ -191,7 +191,7 @@ static
void
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 */
{
dict_index_t* index;
@@ -452,7 +452,7 @@ Updates the search info. */
void
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 */
{
buf_block_t* block;
@@ -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_EX));
#endif /* UNIV_SYNC_DEBUG */
-
+retry:
rw_lock_s_lock(&btr_search_latch);
block = buf_block_align(page);
- if (!block->is_hashed) {
+ if (UNIV_LIKELY(!block->is_hashed)) {
rw_lock_s_unlock(&btr_search_latch);
@@ -958,6 +958,8 @@ btr_search_drop_page_hash_index(
tree_id = btr_page_get_index_id(page);
+ ut_a(0 == ut_dulint_cmp(tree_id, index->id));
+
prev_fold = 0;
heap = NULL;
@@ -992,6 +994,26 @@ next_rec:
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++) {
ha_remove_all_nodes_to_page(table, folds[i], page);
@@ -999,8 +1021,20 @@ next_rec:
block->is_hashed = FALSE;
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);
}
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index 8050eebddd8..58c4e3ed6a3 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -2803,7 +2803,8 @@ dict_table_get_highest_foreign_id(
if (ut_strlen(foreign->id) > ((sizeof dict_ibfk) - 1) + len
&& 0 == ut_memcmp(foreign->id, table->name, 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 */
id = strtoul(foreign->id + len + ((sizeof dict_ibfk) - 1),
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c
index 3281f9926f9..6415cc56b61 100644
--- a/innobase/dict/dict0load.c
+++ b/innobase/dict/dict0load.c
@@ -385,13 +385,23 @@ dict_load_columns(
field = rec_get_nth_field_old(rec, 6, &len);
prtype = mach_read_from_4(field);
- if (dtype_is_non_binary_string_type(mtype, prtype)
- && dtype_get_charset_coll(prtype) == 0) {
- /* This is a non-binary string type, and the table
- was created with < 4.1.2. Use the default charset. */
+ if (dtype_get_charset_coll(prtype) == 0
+ && dtype_is_string_type(mtype)) {
+ /* The table was created with < 4.1.2. */
- 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);
+ }
}
field = rec_get_nth_field_old(rec, 7, &len);
diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c
index 20f522c1a60..69c076d78f3 100644
--- a/innobase/fil/fil0fil.c
+++ b/innobase/fil/fil0fil.c
@@ -181,6 +181,11 @@ struct fil_space_struct {
hash_node_t name_hash;/* hash chain the name_hash table */
rw_lock_t latch; /* latch protecting the file space storage
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;
/* list of all spaces */
ibuf_data_t* ibuf_data;
@@ -213,6 +218,12 @@ struct fil_system_struct {
not put to this list: they are opened
after the startup, and kept open until
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 max_n_open; /* n_open is not allowed to exceed
this */
@@ -389,6 +400,36 @@ fil_space_get_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. */
@@ -841,6 +882,16 @@ fil_node_free(
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);
}
@@ -1004,6 +1055,8 @@ try_again:
HASH_INSERT(fil_space_t, name_hash, system->name_hash,
ut_fold_string(name), space);
+ space->is_in_unflushed_spaces = FALSE;
+
UT_LIST_ADD_LAST(space_list, system->space_list, space);
mutex_exit(&(system->mutex));
@@ -1099,6 +1152,13 @@ fil_space_free(
HASH_DELETE(fil_space_t, name_hash, system->name_hash,
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_a(space->magic_n == FIL_SPACE_MAGIC_N);
@@ -1250,6 +1310,7 @@ fil_system_create(
system->tablespace_version = 0;
+ UT_LIST_INIT(system->unflushed_spaces);
UT_LIST_INIT(system->space_list);
return(system);
@@ -3742,6 +3803,14 @@ fil_node_complete_io(
if (type == OS_FILE_WRITE) {
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
@@ -4162,6 +4231,16 @@ retry:
skip_flush:
if (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) {
@@ -4193,7 +4272,7 @@ fil_flush_file_spaces(
mutex_enter(&(system->mutex));
- space = UT_LIST_GET_FIRST(system->space_list);
+ space = UT_LIST_GET_FIRST(system->unflushed_spaces);
while (space) {
if (space->purpose == purpose && !space->is_being_deleted) {
@@ -4209,7 +4288,7 @@ fil_flush_file_spaces(
space->n_pending_flushes--;
}
- space = UT_LIST_GET_NEXT(space_list, space);
+ space = UT_LIST_GET_NEXT(unflushed_spaces, space);
}
mutex_exit(&(system->mutex));
diff --git a/innobase/include/univ.i b/innobase/include/univ.i
index 15650f22ed8..dd4862b3808 100644
--- a/innobase/include/univ.i
+++ b/innobase/include/univ.i
@@ -126,14 +126,8 @@ by one. */
#ifdef __WIN__
#define UNIV_INLINE __inline
#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
#endif
-#endif
#else
/* If we want to compile a noninlined version we use the following macro
diff --git a/innobase/os/os0sync.c b/innobase/os/os0sync.c
index 487e8f40a39..8bafb73baf8 100644
--- a/innobase/os/os0sync.c
+++ b/innobase/os/os0sync.c
@@ -317,28 +317,28 @@ os_event_wait(
os_fast_mutex_lock(&(event->os_mutex));
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);
- }
- /* Ok, we may return */
+ if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
- 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
- check if the event really has been signaled after we came here to
- wait */
+ pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
- 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
}
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 4f99f340e1c..b345a27af20 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -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_sizes = (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(
}
}
+ 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*));
/* Then store the actual values to our array */
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 0816d0de43c..163b9302b5c 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -3180,3 +3180,74 @@ a hex(b)
7 D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B2
update t1 set b = 'three' where a = 6;
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;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 8d2f18e2362..a47e635cf74 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -2047,3 +2047,105 @@ insert into t1 values(7,_utf8 0xD0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1D0B1
select a,hex(b) from t1 order by b;
update t1 set b = 'three' where a = 6;
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;
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index b33d2dfbd97..1b1326920ad 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -138,8 +138,6 @@ extern "C" {
#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
#define HA_INNOBASE_RANGE_COUNT 100
-uint innobase_init_flags = 0;
-ulong innobase_cache_size = 0;
ulong innobase_large_page_size = 0;
/* The default values for the following, type long or longlong, start-up
@@ -187,8 +185,6 @@ it every INNOBASE_WAKE_INTERVAL'th step. */
#define INNOBASE_WAKE_INTERVAL 32
ulong innobase_active_counter = 0;
-char* innobase_home = NULL;
-
static HASH innobase_open_tables;
#ifdef __NETWARE__ /* some special cleanup for NetWare */
@@ -814,7 +810,6 @@ ha_innobase::ha_innobase(TABLE *table_arg)
HA_PRIMARY_KEY_IN_READ_INDEX |
HA_CAN_GEOMETRY |
HA_TABLE_SCAN_ON_INDEX),
- last_dup_key((uint) -1),
start_of_scan(0),
num_write_row(0)
{}
@@ -983,6 +978,11 @@ innobase_query_caching_of_table_permitted(
sql_print_error("The calling thread is holding the adaptive "
"search, latch though calling "
"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);
@@ -6329,14 +6329,17 @@ ha_innobase::external_lock(
TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
an InnoDB table lock if it is released immediately at the end
of LOCK TABLES, and InnoDB's table locks in that case cause
- VERY easily deadlocks. We do not set InnoDB table locks when
- MySQL sets them at the start of a stored procedure call
- (MySQL does have thd->in_lock_tables TRUE there). */
+ VERY easily deadlocks.
+
+ 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 (thd->in_lock_tables &&
- thd->lex->sql_command != SQLCOM_CALL &&
+ thd->lex->sql_command == SQLCOM_LOCK_TABLES &&
thd->variables.innodb_table_locks &&
(thd->options & OPTION_NOT_AUTOCOMMIT)) {
@@ -6838,7 +6841,7 @@ ha_innobase::store_lock(
} 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 */
prebuilt->select_lock_type = LOCK_NONE;
@@ -6847,7 +6850,7 @@ ha_innobase::store_lock(
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
we weaken the locks set at the start of an SQL statement.
MySQL does set thd->in_lock_tables TRUE there, but in reality
@@ -6870,26 +6873,36 @@ ha_innobase::store_lock(
lock_type = TL_READ_NO_INSERT;
}
- /* If we are not doing a LOCK TABLE or DISCARD/IMPORT
- TABLESPACE or TRUNCATE TABLE, then allow multiple writers */
+ /* If we are not doing a LOCK TABLE, DISCARD/IMPORT
+ 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 &&
- lock_type <= TL_WRITE)
+ We especially allow multiple writers 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_WRITE_CONCURRENT_INSERT
+ && lock_type <= TL_WRITE)
&& (!thd->in_lock_tables
- || thd->lex->sql_command == SQLCOM_CALL)
+ || thd->lex->sql_command == SQLCOM_CALL)
&& !thd->tablespace_op
&& thd->lex->sql_command != SQLCOM_TRUNCATE
- && thd->lex->sql_command != SQLCOM_OPTIMIZE
- && thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
+ && thd->lex->sql_command != SQLCOM_OPTIMIZE
+ && 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 ...
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
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
&& (!thd->in_lock_tables
@@ -6898,10 +6911,10 @@ ha_innobase::store_lock(
lock_type = TL_READ;
}
- lock.type = lock_type;
- }
+ lock.type = lock_type;
+ }
- *to++= &lock;
+ *to++= &lock;
return(to);
}
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index aa8506abe6d..fb93b2abb0e 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -52,7 +52,6 @@ class ha_innobase: public handler
THR_LOCK_DATA lock;
INNOBASE_SHARE *share;
- gptr alloc_ptr;
byte* upd_buff; /* buffer used in updates */
byte* key_val_buff; /* buffer used in converting
search key values from MySQL format
@@ -62,7 +61,6 @@ class ha_innobase: public handler
two buffers */
ulong int_table_flags;
uint primary_key;
- uint last_dup_key;
ulong start_of_scan; /* this is set to 1 when we are
starting a table scan but have not
yet fetched any row, else 0 */
@@ -70,7 +68,6 @@ class ha_innobase: public handler
ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX,
or undefined */
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,
const byte* record);
@@ -199,11 +196,8 @@ class ha_innobase: public handler
};
extern struct show_var_st innodb_status_variables[];
-extern uint innobase_init_flags, innobase_lock_type;
-extern ulong innobase_cache_size, innobase_fast_shutdown;
+extern ulong innobase_fast_shutdown;
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 longlong innobase_buffer_pool_size, innobase_log_file_size;
extern long innobase_log_buffer_size;
@@ -240,8 +234,6 @@ extern ulong srv_commit_concurrency;
extern ulong srv_flush_log_at_trx_commit;
}
-extern TYPELIB innobase_lock_typelib;
-
bool innobase_init(void);
bool innobase_end(void);
bool innobase_flush_logs(void);
@@ -311,9 +303,6 @@ int innobase_rollback_by_xid(
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,
my_off_t end_offset);