diff options
-rwxr-xr-x | Build-tools/Do-compile | 26 | ||||
-rw-r--r-- | innobase/btr/btr0cur.c | 11 | ||||
-rw-r--r-- | innobase/include/lock0lock.h | 5 | ||||
-rw-r--r-- | innobase/include/row0mysql.h | 7 | ||||
-rw-r--r-- | innobase/include/srv0srv.h | 1 | ||||
-rw-r--r-- | innobase/include/sync0arr.h | 2 | ||||
-rw-r--r-- | innobase/include/trx0trx.h | 5 | ||||
-rw-r--r-- | innobase/lock/lock0lock.c | 40 | ||||
-rw-r--r-- | innobase/row/row0ins.c | 81 | ||||
-rw-r--r-- | innobase/row/row0mysql.c | 21 | ||||
-rw-r--r-- | innobase/srv/srv0srv.c | 3 | ||||
-rw-r--r-- | innobase/srv/srv0start.c | 2 | ||||
-rw-r--r-- | innobase/sync/sync0arr.c | 12 | ||||
-rw-r--r-- | innobase/trx/trx0trx.c | 4 | ||||
-rw-r--r-- | mysql-test/r/create_select_tmp.result | 19 | ||||
-rw-r--r-- | mysql-test/r/rpl_drop.result | 10 | ||||
-rw-r--r-- | mysql-test/t/create_select_tmp.test | 27 | ||||
-rw-r--r-- | mysql-test/t/innodb.test | 17 | ||||
-rw-r--r-- | mysql-test/t/rpl_drop.test | 10 | ||||
-rw-r--r-- | sql/ha_innodb.cc | 4 | ||||
-rw-r--r-- | sql/sql_insert.cc | 8 | ||||
-rw-r--r-- | sql/sql_load.cc | 5 |
22 files changed, 248 insertions, 72 deletions
diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile index f47ae794b00..e6e71582c74 100755 --- a/Build-tools/Do-compile +++ b/Build-tools/Do-compile @@ -171,6 +171,17 @@ info("PATH is $ENV{PATH}"); log_timestamp(); +$md5_result= safe_system("perl $ENV{HOME}/my_md5sum -c ${opt_distribution}.md5"); + +if ($md5_result != 0) +{ + abort("MD5 check failed for $opt_distribution!"); +} +else +{ + info("SUCCESS: MD5 checks for $opt_distribution"); +} + if (-x "$host/bin/mysqladmin") { log_system("$host/bin/mysqladmin $mysqladmin_args -S $mysql_unix_port -s shutdown"); @@ -204,17 +215,6 @@ if ($opt_stage == 0) safe_cd($host); if ($opt_stage == 0 && ! $opt_use_old_distribution) { - $md5_result= safe_system("./my_md5sum -c ${opt_distribution}.md5"); - - if ($md5_result != 0) - { - abort("MD5 failed for $opt_distribution!"); - } - else - { - info("SUCCESS: MD5 checks for $opt_distribution"); - } - safe_system("gunzip < $opt_distribution | $tar xf -"); # Fix file times; This is needed because the time for files may be @@ -343,7 +343,9 @@ $tar_file=<$pwd/$host/mysql*.t*gz>; abort ("Could not find tarball!") unless ($tar_file); # Generate the MD5 for the binary distribution -safe_system("./my_md5sum $tar_file > ${tar_file}.md5}"); +$tar_file=~ /(mysql[^\/]*)\.(tar\.gz|tgz)/; +$tar_file_lite= "$1.$2"; +system("cd $pwd/$host; perl $ENV{HOME}/my_md5sum $tar_file_lite > ${tar_file_lite}.md5"); # # Unpack the binary distribution diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c index 2e9194ff30f..be201da4510 100644 --- a/innobase/btr/btr0cur.c +++ b/innobase/btr/btr0cur.c @@ -2717,8 +2717,11 @@ btr_estimate_number_of_different_key_vals( rec = page_rec_get_next(rec); } + if (n_cols == dict_index_get_n_unique_in_tree(index)) { - /* We add one because we know that the first record + + /* If there is more than one leaf page in the tree, + we add one because we know that the first record on the page certainly had a different prefix than the last record on the previous index page in the alphabetical order. Before this fix, if there was @@ -2726,7 +2729,11 @@ btr_estimate_number_of_different_key_vals( algorithm grossly underestimated the number of rows in the table. */ - n_diff[n_cols]++; + if (btr_page_get_prev(page, &mtr) != FIL_NULL + || btr_page_get_next(page, &mtr) != FIL_NULL) { + + n_diff[n_cols]++; + } } total_external_size += diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h index 9c5f35c6674..9f525042dcc 100644 --- a/innobase/include/lock0lock.h +++ b/innobase/include/lock0lock.h @@ -418,7 +418,8 @@ lock_release_off_kernel( /*====================*/ trx_t* trx); /* in: transaction */ /************************************************************************* -Releases table locks, and releases possible other transactions waiting +Releases table locks explicitly requested with LOCK TABLES (indicated by +lock type LOCK_TABLE_EXP), and releases possible other transactions waiting because of these locks. */ void @@ -548,7 +549,7 @@ extern lock_sys_t* lock_sys; /* Lock types */ #define LOCK_TABLE 16 /* these type values should be so high that */ #define LOCK_REC 32 /* they can be ORed to the lock mode */ -#define LOCK_TABLE_EXP 80 /* explicit table lock */ +#define LOCK_TABLE_EXP 80 /* explicit table lock (80 = 16 + 64) */ #define LOCK_TYPE_MASK 0xF0UL /* mask used to extract lock type from the type_mode field in a lock */ /* Waiting lock flag */ diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h index 390e8c4da57..8f6264944ce 100644 --- a/innobase/include/row0mysql.h +++ b/innobase/include/row0mysql.h @@ -161,11 +161,12 @@ row_lock_table_autoinc_for_mysql( row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL table handle */ /************************************************************************* -Unlocks a table lock possibly reserved by trx. */ +Unlocks all table locks explicitly requested by trx (with LOCK TABLES, +lock type LOCK_TABLE_EXP). */ void -row_unlock_table_for_mysql( -/*=======================*/ +row_unlock_tables_for_mysql( +/*========================*/ trx_t* trx); /* in: transaction */ /************************************************************************* Sets a table lock on the table mentioned in prebuilt. */ diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h index c527d40bc79..c7ba39aaaf1 100644 --- a/innobase/include/srv0srv.h +++ b/innobase/include/srv0srv.h @@ -157,6 +157,7 @@ extern ulint srv_test_n_mutexes; extern ulint srv_test_array_size; extern ulint srv_activity_count; +extern ulint srv_fatal_semaphore_wait_threshold; extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs, query threads, and lock table: we allocate diff --git a/innobase/include/sync0arr.h b/innobase/include/sync0arr.h index e7d511f8137..92691d5fdd9 100644 --- a/innobase/include/sync0arr.h +++ b/innobase/include/sync0arr.h @@ -95,7 +95,7 @@ void sync_arr_wake_threads_if_sema_free(void); /*====================================*/ /************************************************************************** -Prints warnings of long semaphore waits to stderr. Currently > 120 sec. */ +Prints warnings of long semaphore waits to stderr. */ void sync_array_print_long_waits(void); diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h index a8c1df534da..7eb91048684 100644 --- a/innobase/include/trx0trx.h +++ b/innobase/include/trx0trx.h @@ -423,8 +423,9 @@ struct trx_struct{ lock_t* auto_inc_lock; /* possible auto-inc lock reserved by the transaction; note that it is also in the lock list trx_locks */ - ulint n_tables_locked;/* number of table locks reserved by - the transaction, stored in trx_locks */ + ulint n_lock_table_exp;/* number of explicit table locks + (LOCK TABLES) reserved by the + transaction, stored in trx_locks */ UT_LIST_NODE_T(trx_t) trx_list; /* list of transactions */ UT_LIST_NODE_T(trx_t) diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c index be0806590a9..92e8f224dea 100644 --- a/innobase/lock/lock0lock.c +++ b/innobase/lock/lock0lock.c @@ -2023,9 +2023,8 @@ lock_grant( lock->trx->auto_inc_lock = lock; } else if (lock_get_type(lock) == LOCK_TABLE_EXP) { - ut_ad(lock_get_mode(lock) == LOCK_S + ut_a(lock_get_mode(lock) == LOCK_S || lock_get_mode(lock) == LOCK_X); - lock->trx->n_tables_locked++; } if (lock_print_waits) { @@ -3203,6 +3202,10 @@ lock_table_create( lock->type_mode = type_mode | LOCK_TABLE; lock->trx = trx; + if (lock_get_type(lock) == LOCK_TABLE_EXP) { + lock->trx->n_lock_table_exp++; + } + lock->un_member.tab_lock.table = table; UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); @@ -3238,7 +3241,11 @@ lock_table_remove_low( if (lock == trx->auto_inc_lock) { trx->auto_inc_lock = NULL; } - + + if (lock_get_type(lock) == LOCK_TABLE_EXP) { + lock->trx->n_lock_table_exp--; + } + UT_LIST_REMOVE(trx_locks, trx->trx_locks, lock); UT_LIST_REMOVE(un_member.tab_lock.locks, table->locks, lock); } @@ -3386,7 +3393,7 @@ lock_table( return(DB_SUCCESS); } - ut_ad(flags == 0 || flags == LOCK_TABLE_EXP); + ut_a(flags == 0 || flags == LOCK_TABLE_EXP); trx = thr_get_trx(thr); @@ -3418,10 +3425,7 @@ lock_table( lock_table_create(table, mode | flags, trx); - if (flags) { - ut_ad(mode == LOCK_S || mode == LOCK_X); - trx->n_tables_locked++; - } + ut_a(!flags || mode == LOCK_S || mode == LOCK_X); lock_mutex_exit_kernel(); @@ -3502,13 +3506,13 @@ lock_table_dequeue( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&kernel_mutex)); #endif /* UNIV_SYNC_DEBUG */ - ut_ad(lock_get_type(in_lock) == LOCK_TABLE || + ut_a(lock_get_type(in_lock) == LOCK_TABLE || lock_get_type(in_lock) == LOCK_TABLE_EXP); lock = UT_LIST_GET_NEXT(un_member.tab_lock.locks, in_lock); lock_table_remove_low(in_lock); - + /* Check if waiting locks in the queue can now be granted: grant locks if there are no conflicting locks ahead. */ @@ -3608,9 +3612,8 @@ lock_release_off_kernel( lock_table_dequeue(lock); if (lock_get_type(lock) == LOCK_TABLE_EXP) { - ut_ad(lock_get_mode(lock) == LOCK_S + ut_a(lock_get_mode(lock) == LOCK_S || lock_get_mode(lock) == LOCK_X); - trx->n_tables_locked--; } } @@ -3631,11 +3634,12 @@ lock_release_off_kernel( mem_heap_empty(trx->lock_heap); ut_a(trx->auto_inc_lock == NULL); - ut_a(trx->n_tables_locked == 0); + ut_a(trx->n_lock_table_exp == 0); } /************************************************************************* -Releases table locks, and releases possible other transactions waiting +Releases table locks explicitly requested with LOCK TABLES (indicated by +lock type LOCK_TABLE_EXP), and releases possible other transactions waiting because of these locks. */ void @@ -3660,7 +3664,7 @@ lock_release_tables_off_kernel( count++; if (lock_get_type(lock) == LOCK_TABLE_EXP) { - ut_ad(lock_get_mode(lock) == LOCK_S + ut_a(lock_get_mode(lock) == LOCK_S || lock_get_mode(lock) == LOCK_X); if (trx->insert_undo || trx->update_undo) { @@ -3676,7 +3680,7 @@ lock_release_tables_off_kernel( } lock_table_dequeue(lock); - trx->n_tables_locked--; + lock = UT_LIST_GET_LAST(trx->trx_locks); continue; } @@ -3695,9 +3699,7 @@ lock_release_tables_off_kernel( lock = UT_LIST_GET_PREV(trx_locks, lock); } - mem_heap_empty(trx->lock_heap); - - ut_a(trx->n_tables_locked == 0); + ut_a(trx->n_lock_table_exp == 0); } /************************************************************************* diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c index 7f1852c70f2..0da749212d2 100644 --- a/innobase/row/row0ins.c +++ b/innobase/row/row0ins.c @@ -370,6 +370,32 @@ row_ins_cascade_ancestor_updates_table( return(FALSE); } +/************************************************************************* +Returns the number of ancestor UPDATE or DELETE nodes of a +cascaded update/delete node. */ +static +ulint +row_ins_cascade_n_ancestors( +/*========================*/ + /* out: number of ancestors */ + que_node_t* node) /* in: node in a query graph */ +{ + que_node_t* parent; + ulint n_ancestors = 0; + + parent = que_node_get_parent(node); + + while (que_node_get_type(parent) == QUE_NODE_UPDATE) { + n_ancestors++; + + parent = que_node_get_parent(parent); + + ut_a(parent); + } + + return(n_ancestors); +} + /********************************************************************** Calculates the update vector node->cascade->update for a child table in a cascaded update. */ @@ -616,6 +642,34 @@ row_ins_foreign_report_add_err( } /************************************************************************* +Invalidate the query cache for the given table. */ +static +void +row_ins_invalidate_query_cache( +/*===========================*/ + que_thr_t* thr, /* in: query thread whose run_node + is an update node */ + const char* name) /* in: table name prefixed with + database name and a '/' character */ +{ + char* buf; + char* ptr; + ulint len = strlen(name) + 1; + + buf = mem_strdupl(name, len); + + ptr = strchr(buf, '/'); + ut_a(ptr); + *ptr = '\0'; + + /* We call a function in ha_innodb.cc */ +#ifndef UNIV_HOTBACKUP + innobase_invalidate_query_cache(thr_get_trx(thr), buf, len); +#endif + mem_free(buf); +} + +/************************************************************************* Perform referential actions or checks when a parent row is deleted or updated and the constraint had an ON DELETE or ON UPDATE condition which was not RESTRICT. */ @@ -650,26 +704,15 @@ row_ins_foreign_check_on_constraint( ulint n_to_update; ulint err; ulint i; - char* ptr; - char* table_name_buf; + + ut_a(thr && foreign && pcur && mtr); /* Since we are going to delete or update a row, we have to invalidate the MySQL query cache for table */ - table_name_buf = mem_strdup(table->name); - - ptr = strchr(table_name_buf, '/'); - ut_a(ptr); - *ptr = '\0'; - -#ifndef UNIV_HOTBACKUP - /* We call a function in ha_innodb.cc */ - innobase_invalidate_query_cache(thr_get_trx(thr), table_name_buf, - strlen(table->name) + 1); -#endif - mem_free(table_name_buf); + row_ins_invalidate_query_cache(thr, table->name); node = thr->run_node; @@ -757,6 +800,16 @@ row_ins_foreign_check_on_constraint( goto nonstandard_exit_func; } + if (row_ins_cascade_n_ancestors(cascade) >= 15) { + err = DB_ROW_IS_REFERENCED; + + row_ins_foreign_report_err( +(char*)"Trying a too deep cascaded delete or update\n", + thr, foreign, btr_pcur_get_rec(pcur), entry); + + goto nonstandard_exit_func; + } + index = btr_pcur_get_btr_cur(pcur)->index; ut_a(index == foreign->foreign_index); diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c index c4408de2a85..556c80c948d 100644 --- a/innobase/row/row0mysql.c +++ b/innobase/row/row0mysql.c @@ -741,14 +741,15 @@ run_again: } /************************************************************************* -Unlocks a table lock possibly reserved by trx. */ +Unlocks all table locks explicitly requested by trx (with LOCK TABLES, +lock type LOCK_TABLE_EXP). */ void -row_unlock_table_for_mysql( -/*=======================*/ +row_unlock_tables_for_mysql( +/*========================*/ trx_t* trx) /* in: transaction */ { - if (!trx->n_tables_locked) { + if (!trx->n_lock_table_exp) { return; } @@ -3175,7 +3176,12 @@ row_check_table_for_mysql( REPEATABLE READ here */ prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ; - + + /* Enlarge the fatal lock wait timeout during CHECK TABLE. */ + mutex_enter(&kernel_mutex); + srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */ + mutex_exit(&kernel_mutex); + index = dict_table_get_first_index(table); while (index != NULL) { @@ -3223,6 +3229,11 @@ row_check_table_for_mysql( ret = DB_ERROR; } + /* Restore the fatal lock wait timeout after CHECK TABLE. */ + mutex_enter(&kernel_mutex); + srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */ + mutex_exit(&kernel_mutex); + prebuilt->trx->op_info = ""; return(ret); diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c index fc46c95a8a6..4bc5b0dc795 100644 --- a/innobase/srv/srv0srv.c +++ b/innobase/srv/srv0srv.c @@ -55,6 +55,9 @@ ibool srv_lower_case_table_names = FALSE; in the server */ ulint srv_activity_count = 0; +/* The following is the maximum allowed duration of a lock wait. */ +ulint srv_fatal_semaphore_wait_threshold = 600; + ibool srv_lock_timeout_and_monitor_active = FALSE; ibool srv_error_monitor_active = FALSE; diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c index dd38eddb20b..74dd23e4252 100644 --- a/innobase/srv/srv0start.c +++ b/innobase/srv/srv0start.c @@ -1115,7 +1115,7 @@ NetWare. */ srv_monitor_file_name = mem_alloc( strlen(fil_path_to_mysql_datadir) + 20 + sizeof "/innodb_status."); - sprintf(srv_monitor_file_name, "%s/innodb.status.%lu", + sprintf(srv_monitor_file_name, "%s/innodb_status.%lu", fil_path_to_mysql_datadir, os_proc_get_number()); srv_monitor_file = fopen(srv_monitor_file_name, "w+"); if (!srv_monitor_file) { diff --git a/innobase/sync/sync0arr.c b/innobase/sync/sync0arr.c index d1644412fbb..7cd221df6a5 100644 --- a/innobase/sync/sync0arr.c +++ b/innobase/sync/sync0arr.c @@ -895,7 +895,7 @@ sync_arr_wake_threads_if_sema_free(void) } /************************************************************************** -Prints warnings of long semaphore waits to stderr. Currently > 120 sec. */ +Prints warnings of long semaphore waits to stderr. */ void sync_array_print_long_waits(void) @@ -905,6 +905,7 @@ sync_array_print_long_waits(void) ibool old_val; ibool noticed = FALSE; ulint i; + ulint fatal_timeout = srv_fatal_semaphore_wait_threshold; for (i = 0; i < sync_primary_wait_array->n_cells; i++) { @@ -919,12 +920,13 @@ sync_array_print_long_waits(void) } if (cell->wait_object != NULL - && difftime(time(NULL), cell->reservation_time) > 600) { + && difftime(time(NULL), cell->reservation_time) + > fatal_timeout) { - fputs( -"InnoDB: Error: semaphore wait has lasted > 600 seconds\n" + fprintf(stderr, +"InnoDB: Error: semaphore wait has lasted > %lu seconds\n" "InnoDB: We intentionally crash the server, because it appears to be hung.\n", - stderr); + fatal_timeout); ut_error; } diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c index a9aae48dae6..f7497ac4090 100644 --- a/innobase/trx/trx0trx.c +++ b/innobase/trx/trx0trx.c @@ -151,7 +151,7 @@ trx_create( trx->n_tickets_to_enter_innodb = 0; trx->auto_inc_lock = NULL; - trx->n_tables_locked = 0; + trx->n_lock_table_exp = 0; trx->read_view_heap = mem_heap_create(256); trx->read_view = NULL; @@ -279,7 +279,7 @@ trx_free( ut_a(!trx->has_search_latch); ut_a(!trx->auto_inc_lock); - ut_a(!trx->n_tables_locked); + ut_a(!trx->n_lock_table_exp); ut_a(trx->dict_operation_lock_mode == 0); diff --git a/mysql-test/r/create_select_tmp.result b/mysql-test/r/create_select_tmp.result new file mode 100644 index 00000000000..610ee70b3e3 --- /dev/null +++ b/mysql-test/r/create_select_tmp.result @@ -0,0 +1,19 @@ +drop table if exists t1, t2; +CREATE TABLE t1 ( a int ); +INSERT INTO t1 VALUES (1),(2),(1); +CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1; +Duplicate entry '1' for key 1 +select * from t2; +Table 'test.t2' doesn't exist +CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1; +Duplicate entry '1' for key 1 +select * from t2; +Table 'test.t2' doesn't exist +CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1; +Duplicate entry '1' for key 1 +select * from t2; +Table 'test.t2' doesn't exist +CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1; +Duplicate entry '1' for key 1 +select * from t2; +Table 'test.t2' doesn't exist diff --git a/mysql-test/r/rpl_drop.result b/mysql-test/r/rpl_drop.result new file mode 100644 index 00000000000..ce1f5b6ee81 --- /dev/null +++ b/mysql-test/r/rpl_drop.result @@ -0,0 +1,10 @@ +slave stop; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +slave start; +drop table if exists t1, t2; +create table t1 (a int); +drop table t1, t2; +Unknown table 't2' diff --git a/mysql-test/t/create_select_tmp.test b/mysql-test/t/create_select_tmp.test new file mode 100644 index 00000000000..36292abd899 --- /dev/null +++ b/mysql-test/t/create_select_tmp.test @@ -0,0 +1,27 @@ +# Testcase for BUG#4551 +# The bug was that when the table was TEMPORARY, it was not deleted if +# the CREATE SELECT failed (the code intended too, but it actually +# didn't). And as the CREATE TEMPORARY TABLE was not written to the +# binlog if it was a transactional table, it resulted in an +# inconsistency between binlog and the internal list of temp tables. + +-- source include/have_innodb.inc +drop table if exists t1, t2; +CREATE TABLE t1 ( a int ); +INSERT INTO t1 VALUES (1),(2),(1); +--error 1062; +CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1; +--error 1146; +select * from t2; +--error 1062; +CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=INNODB SELECT a FROM t1; +--error 1146; +select * from t2; +--error 1062; +CREATE TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1; +--error 1146; +select * from t2; +--error 1062; +CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) TYPE=MYISAM SELECT a FROM t1; +--error 1146; +select * from t2; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index e0cc96ccb32..50ab3bdb8bd 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -960,6 +960,23 @@ update t3 set t3.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id; drop table t3,t2,t1; # +# test for recursion depth limit +# +create table t1( + id int primary key, + pid int, + index(pid), + foreign key(pid) references t1(id) on delete cascade) engine=innodb; +insert into t1 values(0,0),(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6), + (8,7),(9,8),(10,9),(11,10),(12,11),(13,12),(14,13),(15,14); +-- error 1217 +delete from t1 where id=0; +delete from t1 where id=15; +delete from t1 where id=0; + +drop table t1; + +# # Test timestamps # diff --git a/mysql-test/t/rpl_drop.test b/mysql-test/t/rpl_drop.test new file mode 100644 index 00000000000..6fc2500fc97 --- /dev/null +++ b/mysql-test/t/rpl_drop.test @@ -0,0 +1,10 @@ +# Testcase for BUG#4552 (DROP on two tables, one of which does not +# exist, must be binlogged with a non-zero error code) +source include/master-slave.inc; +drop table if exists t1, t2; +create table t1 (a int); +--error 1051; +drop table t1, t2; +save_master_pos; +connection slave; +sync_with_master; diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 6eae315e443..21a2e338812 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -4783,8 +4783,8 @@ ha_innobase::external_lock( trx->n_mysql_tables_in_use--; prebuilt->mysql_has_locked = FALSE; auto_inc_counter_for_this_stat = 0; - if (trx->n_tables_locked) { - row_unlock_table_for_mysql(trx); + if (trx->n_lock_table_exp) { + row_unlock_tables_for_mysql(trx); } /* If the MySQL lock count drops to zero we know that the current SQL diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b769178565b..406bff6d273 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1696,9 +1696,13 @@ void select_create::abort() table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); enum db_type table_type=table->db_type; if (!table->tmp_table) + { hash_delete(&open_cache,(byte*) table); - if (!create_info->table_existed) - quick_rm_table(table_type,db,name); + if (!create_info->table_existed) + quick_rm_table(table_type, db, name); + } + else if (!create_info->table_existed) + close_temporary_table(thd, db, name); table=0; } VOID(pthread_mutex_unlock(&LOCK_open)); diff --git a/sql/sql_load.cc b/sql/sql_load.cc index 167fb2daf8b..8442d03c1d9 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -310,6 +310,11 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, { if (transactional_table) ha_autocommit_or_rollback(thd,error); + + if (read_file_from_client) + while (!read_info.next_line()) + ; + #ifndef EMBEDDED_LIBRARY if (mysql_bin_log.is_open()) { |