mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Fixed: BUG#15653, BUG#16157, BUG#16229, BUG#16298, BUG#16387, BUG#16582.
Applied innodb-5.0-ss149/162 snapshots.
This commit is contained in:
@ -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);
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
if (srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS) {
|
||||
|
||||
os_thread_exit(NULL);
|
||||
}
|
||||
/* Ok, we may return */
|
||||
|
||||
return;
|
||||
}
|
||||
/* Ok, we may return */
|
||||
|
||||
return;
|
||||
pthread_cond_wait(&(event->cond_var), &(event->os_mutex));
|
||||
|
||||
/* 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));
|
||||
|
||||
/* 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 */
|
||||
|
||||
goto loop;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
Reference in New Issue
Block a user