From 00be3292b3074492484b0023f053412b0225349c Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Fri, 17 Jan 2003 13:52:23 +0200 Subject: [PATCH 1/6] Fixed typo --- myisam/mi_create.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 5a5a49533da..d0ba37a77c6 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -447,7 +447,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, share.base.records=ci->max_rows; share.base.reloc= ci->reloc_rows; share.base.reclength=real_reclength; - share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM);; + share.base.pack_reclength=reclength+ test(options & HA_OPTION_CHECKSUM); share.base.max_pack_length=pack_reclength; share.base.min_pack_length=min_pack_length; share.base.pack_bits=packed; From 9fb477569bb19710ae1a368ca8c144e086134ea5 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Fri, 17 Jan 2003 15:56:16 +0200 Subject: [PATCH 2/6] Fixed bug with the --slow-log when logging an administrator command (like FLUSH TABLES). (Code is already in 4.0) --- sql/log.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/log.cc b/sql/log.cc index b6c842e551d..ab3277fe58b 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -963,6 +963,7 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, end=strxmov(buff, "# administrator command: ", command_name[thd->command], NullS); query_length=(ulong) (end-buff); + query=buff; } if (my_b_write(&log_file, (byte*) query,query_length) || my_b_write(&log_file, (byte*) ";\n",2) || From 8fc51bb42776e4463923413b6a4371a5812c5de0 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 18 Jan 2003 15:01:56 +0200 Subject: [PATCH 3/6] btr0sea.h, btr0sea.c: Fix a crash in page_dir_find_owner_slot if an adaptive hash index search coincides with purge or an insert --- innobase/btr/btr0sea.c | 28 +++++++++++++++++++++++++++- innobase/include/btr0sea.h | 14 ++++++++++---- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index de3fe6e196e..5c5ed934a9b 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -508,6 +508,14 @@ btr_search_check_guess( /*===================*/ /* out: TRUE if success */ btr_cur_t* cursor, /* in: guessed cursor position */ + ibool can_only_compare_to_cursor_rec, + /* in: if we do not have a latch on the page + of cursor, but only a latch on + btr_search_latch, then ONLY the columns + of the record UNDER the cursor are + protected, not the next or previous record + in the chain: we cannot look at the next or + previous record to check our guess! */ dtuple_t* tuple, /* in: data tuple */ ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G, or PAGE_CUR_GE */ @@ -566,6 +574,13 @@ btr_search_check_guess( } } + if (can_only_compare_to_cursor_rec) { + /* Since we could not determine if our guess is right just by + looking at the record under the cursor, return FALSE */ + + return(FALSE); + } + match = 0; bytes = 0; @@ -670,6 +685,7 @@ btr_search_guess_on_hash( ulint fold; ulint tuple_n_fields; dulint tree_id; + ibool can_only_compare_to_cursor_rec = TRUE; #ifdef notdefined btr_cur_t cursor2; btr_pcur_t pcur; @@ -744,6 +760,8 @@ btr_search_guess_on_hash( goto failure; } + can_only_compare_to_cursor_rec = FALSE; + buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH); } @@ -775,7 +793,15 @@ btr_search_guess_on_hash( fold); */ } else { - success = btr_search_check_guess(cursor, tuple, mode, mtr); + /* If we only have the latch on btr_search_latch, not on the + page, it only protects the columns of the record the cursor + is positioned on. We cannot look at the next of the previous + record to determine if our guess for the cursor position is + right. */ + + success = btr_search_check_guess(cursor, + can_only_compare_to_cursor_rec, + tuple, mode, mtr); } if (!success) { diff --git a/innobase/include/btr0sea.h b/innobase/include/btr0sea.h index 14feca5d5c5..ee762a12221 100644 --- a/innobase/include/btr0sea.h +++ b/innobase/include/btr0sea.h @@ -234,10 +234,16 @@ struct btr_search_sys_struct{ extern btr_search_sys_t* btr_search_sys; /* The latch protecting the adaptive search system: this latch protects the -(1) positions of records on those pages where a hash index has been built. -NOTE: It does not protect values of non-ordering fields within a record from -being updated in-place! We can use fact (1) to perform unique searches to -indexes. */ +(1) hash index; +(2) columns of a record to which we have a pointer in the hash index; + +but does NOT protect: + +(3) next record offset field in a record; +(4) next or previous records on the same page. + +Bear in mind (3) and (4) when using the hash index. +*/ extern rw_lock_t* btr_search_latch_temp; From 375fcfa5805d837dca51a11186500d935fb25a75 Mon Sep 17 00:00:00 2001 From: "heikki@hundin.mysql.fi" <> Date: Sat, 18 Jan 2003 15:16:26 +0200 Subject: [PATCH 4/6] btr0sea.c: Backport from 4.0: fix bug in adaptive hash index search --- innobase/btr/btr0sea.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c index 421aafba1c5..fd65a98cc0f 100644 --- a/innobase/btr/btr0sea.c +++ b/innobase/btr/btr0sea.c @@ -470,6 +470,7 @@ btr_search_check_guess( /*===================*/ /* out: TRUE if success */ btr_cur_t* cursor, /* in: guessed cursor position */ + ibool can_only_compare_to_cursor_rec, dtuple_t* tuple, /* in: data tuple */ ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G, or PAGE_CUR_GE */ @@ -528,6 +529,10 @@ btr_search_check_guess( } } + if (can_only_compare_to_cursor_rec) { + return(FALSE); + } + match = 0; bytes = 0; @@ -632,6 +637,7 @@ btr_search_guess_on_hash( ulint fold; ulint tuple_n_fields; dulint tree_id; + ibool can_only_compare_to_cursor_rec = TRUE; #ifdef notdefined btr_cur_t cursor2; btr_pcur_t pcur; @@ -706,6 +712,8 @@ btr_search_guess_on_hash( goto failure; } + can_only_compare_to_cursor_rec = FALSE; + buf_page_dbg_add_level(page, SYNC_TREE_NODE_FROM_HASH); } @@ -737,7 +745,9 @@ btr_search_guess_on_hash( fold); */ } else { - success = btr_search_check_guess(cursor, tuple, mode, mtr); + success = btr_search_check_guess(cursor, + can_only_compare_to_cursor_rec, + tuple, mode, mtr); } if (!success) { From dd4d4cc8b5de7ca534db37fcfefad59ab67dddcb Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Sat, 18 Jan 2003 23:38:55 +0200 Subject: [PATCH 5/6] Only set thd->query to 0 if LOCK_thread_count is hold This fixes a possible core dump problem in SHOW PROCESSLIST --- sql/slave.cc | 34 ++++++++++++++++++++++++++-------- sql/sql_db.cc | 10 ++++++---- sql/sql_parse.cc | 17 ++++++++--------- 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/sql/slave.cc b/sql/slave.cc index f2f37807128..0bbf9bf227d 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -22,6 +22,7 @@ #include "slave.h" #include #include +#include #define RPL_LOG_NAME (glob_mi.log_file_name[0] ? glob_mi.log_file_name :\ "FIRST") @@ -362,6 +363,7 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, TABLE_LIST tables; int error= 1; handler *file; + char *query; if (packet_len == packet_error) { @@ -375,15 +377,23 @@ static int create_table_from_dump(THD* thd, NET* net, const char* db, return 1; } thd->command = COM_TABLE_DUMP; - thd->query = sql_alloc(packet_len + 1); - if (!thd->query) + /* Note that we should not set thd->query until the area is initalized */ + if (!(query = sql_alloc(packet_len + 1))) { sql_print_error("create_table_from_dump: out of memory"); net_printf(&thd->net, ER_GET_ERRNO, "Out of memory"); return 1; } - memcpy(thd->query, net->read_pos, packet_len); - thd->query[packet_len] = 0; + memcpy(query, net->read_pos, packet_len); + query[packet_len]= 0; + thd->query_length= packet_len; + /* + We make the following lock in an attempt to ensure that the compiler will + not rearrange the code so that thd->query is set too soon + */ + VOID(pthread_mutex_lock(&LOCK_thread_count)); + thd->query= query; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->current_tablenr = 0; thd->query_error = 0; thd->net.no_send_ok = 1; @@ -967,10 +977,11 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len) thd->db = rewrite_db((char*)qev->db); if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) { - thd->query = (char*)qev->query; + thd->query_length= q_len; thd->set_time((time_t)qev->when); thd->current_tablenr = 0; VOID(pthread_mutex_lock(&LOCK_thread_count)); + thd->query = (char*)qev->query; thd->query_id = query_id++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->last_nx_table = thd->last_nx_db = 0; @@ -1008,7 +1019,9 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len) else { // master could be inconsistent, abort and tell DBA to check/fix it + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->db = thd->query = 0; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->convert_set = 0; close_thread_tables(thd); free_root(&thd->mem_root,0); @@ -1017,7 +1030,9 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len) } } thd->db = 0; // prevent db from being freed + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = 0; // just to be sure + VOID(pthread_mutex_unlock(&LOCK_thread_count)); // assume no convert for next query unless set explictly thd->convert_set = 0; close_thread_tables(thd); @@ -1059,10 +1074,11 @@ static int exec_event(THD* thd, NET* net, MASTER_INFO* mi, int event_len) Load_log_event* lev = (Load_log_event*)ev; init_sql_alloc(&thd->mem_root, 8192,0); thd->db = rewrite_db((char*)lev->db); + DBUG_ASSERT(thd->query == 0); thd->query = 0; thd->query_error = 0; - if(db_ok(thd->db, replicate_do_db, replicate_ignore_db)) + if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) { thd->set_time((time_t)lev->when); thd->current_tablenr = 0; @@ -1490,9 +1506,11 @@ the slave thread with \"mysqladmin start-slave\". We stopped at log \ sql_print_error("Slave thread exiting, replication stopped in log '%s' at \ position %s", RPL_LOG_NAME, llstr(glob_mi.pos,llbuff)); + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = thd->db = 0; // extra safety - if(mysql) - mc_mysql_close(mysql); + VOID(pthread_mutex_unlock(&LOCK_thread_count)); + if (mysql) + mc_mysql_close(mysql); thd->proc_info = "Waiting for slave mutex on exit"; pthread_mutex_lock(&LOCK_slave); slave_running = 0; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 0be1b7b0411..1ba02bb416c 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -89,9 +89,9 @@ void mysql_create_db(THD *thd, char *db, uint create_options) } if (!thd->query) { - thd->query = path; thd->query_length = (uint) (strxmov(path,"create database ", db, NullS)- path); + thd->query = path; } { mysql_update_log.write(thd,thd->query, thd->query_length); @@ -103,8 +103,9 @@ void mysql_create_db(THD *thd, char *db, uint create_options) } if (thd->query == path) { + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = 0; // just in case - thd->query_length = 0; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); } send_ok(&thd->net, result); @@ -178,9 +179,9 @@ void mysql_rm_db(THD *thd,char *db,bool if_exists) if (!thd->query) { - thd->query = path; thd->query_length = (uint) (strxmov(path,"drop database ", db, NullS)- path); + thd->query = path; } mysql_update_log.write(thd, thd->query, thd->query_length); if (mysql_bin_log.is_open()) @@ -190,8 +191,9 @@ void mysql_rm_db(THD *thd,char *db,bool if_exists) } if (thd->query == path) { + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query = 0; // just in case - thd->query_length = 0; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); } send_ok(&thd->net,(ulong) deleted); } diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f26be7f47e0..d8a4a5fee83 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -691,15 +691,15 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) thd->free_list = 0; thd->query = tbl_name; - if((error = mysqld_dump_create_info(thd, table, -1))) - { - my_error(ER_GET_ERRNO, MYF(0)); - goto err; - } + if ((error = mysqld_dump_create_info(thd, table, -1))) + { + my_error(ER_GET_ERRNO, MYF(0)); + goto err; + } net_flush(&thd->net); error = table->file->dump(thd,fd); - if(error) - my_error(ER_GET_ERRNO, MYF(0)); + if (error) + my_error(ER_GET_ERRNO, MYF(0)); err: @@ -776,9 +776,8 @@ bool do_command(THD *thd) *tbl_name++ = 0; memcpy(tbl_name, data + db_len + 2, tbl_len); tbl_name[tbl_len] = 0; - if(mysql_table_dump(thd, db, tbl_name, -1)) + if (mysql_table_dump(thd, db, tbl_name, -1)) send_error(&thd->net); // dump to NET - break; } case COM_CHANGE_USER: From 183df2da7fc0f9f7f8bbf54fee055f3e470932a1 Mon Sep 17 00:00:00 2001 From: "monty@mashka.mysql.fi" <> Date: Sun, 19 Jan 2003 02:00:26 +0200 Subject: [PATCH 6/6] Fixes cases where thd->query was not protected. This fixes a problem with SHOW PROCESSLIST --- sql/log_event.cc | 10 ++++++++-- sql/sql_acl.cc | 1 + sql/sql_db.cc | 10 +++++----- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/sql/log_event.cc b/sql/log_event.cc index 45f54e420de..e243a953c63 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -1702,10 +1702,11 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) { - thd->query = (char*)query; thd->set_time((time_t)when); thd->current_tablenr = 0; + thd->query_length= q_len; VOID(pthread_mutex_lock(&LOCK_thread_count)); + thd->query = (char*)query; thd->query_id = query_id++; VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->query_error = 0; // clear error @@ -1760,7 +1761,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) else { // master could be inconsistent, abort and tell DBA to check/fix it + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->db = thd->query = 0; + VOID(pthread_mutex_unlock(&LOCK_thread_count)); thd->variables.convert_set = 0; close_thread_tables(thd); free_root(&thd->mem_root,0); @@ -1768,7 +1771,9 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli) } } thd->db= 0; // prevent db from being freed + VOID(pthread_mutex_lock(&LOCK_thread_count)); thd->query= 0; // just to be sure + VOID(pthread_mutex_unlock(&LOCK_thread_count)); // assume no convert for next query unless set explictly thd->variables.convert_set = 0; close_thread_tables(thd); @@ -1816,7 +1821,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli, { init_sql_alloc(&thd->mem_root, 8192,0); thd->db = rewrite_db((char*)db); - thd->query = 0; + DBUG_ASSERT(thd->query == 0); + thd->query = 0; // Should not be needed thd->query_error = 0; if (db_ok(thd->db, replicate_do_db, replicate_ignore_db)) diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 1f8f25e5fb8..da563f0547c 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -2322,6 +2322,7 @@ my_bool grant_init(THD *org_thd) if (t_table->file->index_first(t_table->record[0])) { t_table->file->index_end(); + return_val= 0; goto end_unlock; } grant_option= TRUE; diff --git a/sql/sql_db.cc b/sql/sql_db.cc index ffb02cd36c1..4cb46c00bed 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -78,9 +78,9 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) if (!thd->query) { /* The client used the old obsolete mysql_create_db() call */ - thd->query_length = (uint) (strxmov(path,"create database `", db, "`", - NullS) - path); - thd->query = path; + thd->query_length= (uint) (strxmov(path,"create database `", db, "`", + NullS) - path); + thd->query= path; } { mysql_update_log.write(thd,thd->query, thd->query_length); @@ -93,7 +93,7 @@ int mysql_create_db(THD *thd, char *db, uint create_options, bool silent) if (thd->query == path) { VOID(pthread_mutex_lock(&LOCK_thread_count)); - thd->query = 0; // just in case + thd->query= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); } send_ok(&thd->net, result); @@ -182,7 +182,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) if (thd->query == path) { VOID(pthread_mutex_lock(&LOCK_thread_count)); - thd->query = 0; // just in case + thd->query= 0; VOID(pthread_mutex_unlock(&LOCK_thread_count)); } send_ok(&thd->net,(ulong) deleted);