From 91bac76e039a317858aa2dc95bcfc2475321fbfd Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 21 Mar 2004 11:48:51 +0200 Subject: [PATCH 1/7] fixed BUG in query cahe statistic counting mysql-test/r/grant_cache.result: right results in query cache mysql-test/t/grant_cache.test: proving new results sql/sql_cache.cc: fixed statistic calculating in query cahe --- mysql-test/r/grant_cache.result | 42 ++++++++++++++++++++++++++++++--- mysql-test/t/grant_cache.test | 12 ++++++++++ sql/sql_cache.cc | 17 ++++++++++--- 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/grant_cache.result b/mysql-test/r/grant_cache.result index fca6864cc63..96eb9d2bc62 100644 --- a/mysql-test/r/grant_cache.result +++ b/mysql-test/r/grant_cache.result @@ -41,17 +41,53 @@ grant SELECT on mysqltest.* to mysqltest_1@localhost; grant SELECT on mysqltest.t1 to mysqltest_2@localhost; grant SELECT on test.t1 to mysqltest_2@localhost; grant SELECT(a) on mysqltest.t1 to mysqltest_3@localhost; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 6 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +show status like "Qcache_not_cached"; +Variable_name Value +Qcache_not_cached 0 select "user1"; user1 user1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 6 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +show status like "Qcache_not_cached"; +Variable_name Value +Qcache_not_cached 1 select * from t1; a b c 1 1 1 2 2 2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 6 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +show status like "Qcache_not_cached"; +Variable_name Value +Qcache_not_cached 1 select a from t1 ; a 1 2 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 6 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 2 +show status like "Qcache_not_cached"; +Variable_name Value +Qcache_not_cached 1 select c from t1; c 1 @@ -94,7 +130,7 @@ Variable_name Value Qcache_hits 7 show status like "Qcache_not_cached"; Variable_name Value -Qcache_not_cached 3 +Qcache_not_cached 2 select "user3"; user3 user3 @@ -118,7 +154,7 @@ Variable_name Value Qcache_hits 7 show status like "Qcache_not_cached"; Variable_name Value -Qcache_not_cached 8 +Qcache_not_cached 7 select "user4"; user4 user4 @@ -144,7 +180,7 @@ Variable_name Value Qcache_hits 8 show status like "Qcache_not_cached"; Variable_name Value -Qcache_not_cached 9 +Qcache_not_cached 8 delete from mysql.user where user in ("mysqltest_1","mysqltest_2","mysqltest_3"); delete from mysql.db where user in ("mysqltest_1","mysqltest_2","mysqltest_3"); delete from mysql.tables_priv where user in ("mysqltest_1","mysqltest_2","mysqltest_3"); diff --git a/mysql-test/t/grant_cache.test b/mysql-test/t/grant_cache.test index 95989d1ee99..f85584c3875 100644 --- a/mysql-test/t/grant_cache.test +++ b/mysql-test/t/grant_cache.test @@ -40,10 +40,22 @@ grant SELECT(a) on mysqltest.t1 to mysqltest_3@localhost; # The following queries should be fetched from cache connect (user1,localhost,mysqltest_1,,mysqltest,$MASTER_MYPORT,master.sock); connection user1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +show status like "Qcache_not_cached"; select "user1"; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +show status like "Qcache_not_cached"; select * from t1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +show status like "Qcache_not_cached"; # The pre and end space are intentional select a from t1 ; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_hits"; +show status like "Qcache_not_cached"; select c from t1; show status like "Qcache_queries_in_cache"; show status like "Qcache_hits"; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 77bdcb79a8d..5118421464b 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -589,7 +589,6 @@ void query_cache_insert(NET *net, const char *packet, ulong length) if (!query_cache.append_result_data(&result, length, (gptr) packet, query_block)) { - query_cache.refused++; DBUG_PRINT("warning", ("Can't append data")); header->result(result); DBUG_PRINT("qcache", ("free query 0x%lx", (ulong) query_block)); @@ -845,7 +844,8 @@ void Query_cache::store_query(THD *thd, TABLE_LIST *tables_used) } } else - statistic_increment(refused, &structure_guard_mutex); + if (thd->lex.sql_command == SQLCOM_SELECT) + statistic_increment(refused, &structure_guard_mutex); end: DBUG_VOID_RETURN; @@ -981,7 +981,6 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) DBUG_PRINT("qcache", ("probably no SELECT access to %s.%s => return to normal processing", table_list.db, table_list.alias)); - refused++; // This is actually a hit STRUCT_UNLOCK(&structure_guard_mutex); thd->safe_to_cache_query=0; // Don't try to cache this BLOCK_UNLOCK_RD(query_block); @@ -1610,6 +1609,12 @@ void Query_cache::free_query(Query_cache_block *query_block) */ if (result_block != 0) { + if (result_block->type != Query_cache_block::RESULT) + { + // removing unfinished query + refused++; + inserts--; + } Query_cache_block *block = result_block; do { @@ -1618,6 +1623,12 @@ void Query_cache::free_query(Query_cache_block *query_block) free_memory_block(current); } while (block != result_block); } + else + { + // removing unfinished query + refused++; + inserts--; + } query->unlock_n_destroy(); free_memory_block(query_block); From cc11f6f351e8056dabf47cf47f8a29aa3b6261a2 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 26 Mar 2004 14:44:52 +0200 Subject: [PATCH 2/7] Allow keys with 0 segements in MyISAM This fixed a bug in SELECT DISTINCT when all selected parts where constants. (Bug #3203) myisam/mi_create.c: Allow keys with 0 segements. mysql-test/r/myisam.result: Test for problem with SELECT DISTINCT mysql-test/t/myisam.test: Test for problem with SELECT DISTINCT --- myisam/mi_create.c | 8 +++++++- mysql-test/r/myisam.result | 22 ++++++++++++++++++++++ mysql-test/t/myisam.test | 14 ++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/myisam/mi_create.c b/myisam/mi_create.c index 9f39c6f522e..328450c70db 100644 --- a/myisam/mi_create.c +++ b/myisam/mi_create.c @@ -366,7 +366,13 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, my_errno=HA_WRONG_CREATE_OPTION; goto err; } - if ((keydef->flag & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) + /* + key_segs may be 0 in the case when we only want to be able to + add on row into the table. This can happen with some DISTINCT queries + in MySQL + */ + if ((keydef->flag & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME && + key_segs) share.state.rec_per_key_part[key_segs-1]=1L; length+=key_length; keydef->block_length= MI_BLOCK_SIZE(length,pointer,MI_MAX_KEYPTR_SIZE); diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index cc541388a5c..1fd64377f12 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -431,3 +431,25 @@ a concat(b,'.') 1 a. 3 a . drop table t1; +create table t1 (a int not null); +create table t2 (a int not null, primary key (a)); +insert into t1 values (1); +insert into t2 values (1),(2); +select sql_big_result distinct t1.a from t1,t2 order by t2.a; +a +1 +select distinct t1.a from t1,t2 order by t2.a; +a +1 +select sql_big_result distinct t1.a from t1,t2; +a +1 +explain select sql_big_result distinct t1.a from t1,t2 order by t2.a; +table type possible_keys key key_len ref rows Extra +t1 system NULL NULL NULL NULL 1 Using temporary +t2 index NULL PRIMARY 4 NULL 2 Using index; Distinct +explain select distinct t1.a from t1,t2 order by t2.a; +table type possible_keys key key_len ref rows Extra +t1 system NULL NULL NULL NULL 1 Using temporary +t2 index NULL PRIMARY 4 NULL 2 Using index; Distinct +drop table t1,t2; diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 7302e5dfdda..59b86309d77 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -422,3 +422,17 @@ update t1 set b='b ' where a > 1; delete from t1 where b='b'; select a,concat(b,'.') from t1; drop table t1; + +# +# Test keys with 0 segments. (Bug #3203) +# +create table t1 (a int not null); +create table t2 (a int not null, primary key (a)); +insert into t1 values (1); +insert into t2 values (1),(2); +select sql_big_result distinct t1.a from t1,t2 order by t2.a; +select distinct t1.a from t1,t2 order by t2.a; +select sql_big_result distinct t1.a from t1,t2; +explain select sql_big_result distinct t1.a from t1,t2 order by t2.a; +explain select distinct t1.a from t1,t2 order by t2.a; +drop table t1,t2; From 9cc7549518ac18b095895b18569ddcf58a392a9a Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 26 Mar 2004 17:01:13 +0200 Subject: [PATCH 3/7] order_by.result: result of the test case for FORCE INDEX on ORDER BY order_by.test: test case for FORCE INDEX on ORDER BY sql_select.cc: Changing behaviour that MySQL server takes FORCE INDEX clause into account when optimising ORDER BY clause sql/sql_select.cc: Changing behaviour that MySQL server takes FORCE INDEX clause into account when optimising ORDER BY clause mysql-test/t/order_by.test: test case for FORCE INDEX on ORDER BY mysql-test/r/order_by.result: result of the test case for FORCE INDEX on ORDER BY --- mysql-test/r/order_by.result | 8 ++++++++ mysql-test/t/order_by.test | 13 ++++++++++++- sql/sql_select.cc | 14 ++++++++++++-- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 093633d5f5a..859d9d4cab0 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -546,3 +546,11 @@ CREATE TABLE t1 (a INT, b INT); SET @id=0; UPDATE t1 SET a=0 ORDER BY (a=@id), b; DROP TABLE t1; +create table t1(id int not null auto_increment primary key, t char(12)); +explain select id,t from t1 order by id; +table type possible_keys key key_len ref rows Extra +t1 ALL NULL NULL NULL NULL 1000 Using filesort +explain select id,t from t1 force index (primary) order by id; +table type possible_keys key key_len ref rows Extra +t1 index NULL PRIMARY 4 NULL 1000 +drop table t1; diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 8215ec84ae3..86ecc4aa70d 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -352,4 +352,15 @@ CREATE TABLE t1 (a INT, b INT); SET @id=0; UPDATE t1 SET a=0 ORDER BY (a=@id), b; DROP TABLE t1; - +create table t1(id int not null auto_increment primary key, t char(12)); +disable_query_log; +let $1 = 1000; +while ($1) + { + eval insert into t1(t) values ('$1'); + dec $1; + } +enable_query_log; +explain select id,t from t1 order by id; +explain select id,t from t1 force index (primary) order by id; +drop table t1; \ No newline at end of file diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 87812414881..057f0bd9483 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -6021,7 +6021,7 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, /* check if we can use a key to resolve the group */ /* Tables using JT_NEXT are handled here */ uint nr; - key_map keys=usable_keys; + key_map keys_to_use=~0,keys=usable_keys; /* If not used with LIMIT, only use keys if the whole query can be @@ -6029,7 +6029,17 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit, retrieving all rows through an index. */ if (select_limit >= table->file->records) - keys&= (table->used_keys | table->file->keys_to_use_for_scanning()); + keys_to_use= (table->used_keys |table->file->keys_to_use_for_scanning()); + + /* + We are adding here also the index speified in FORCE INDEX clause, + if any. + This is to allow users to use index in ORDER BY. + */ + + if (table->force_index) + keys_to_use|= table->keys_in_use_for_query; + keys&= keys_to_use; for (nr=0; keys ; keys>>=1, nr++) { From 08d31b97b049f7b567b6b92d4a530d4d2e3f0756 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 26 Mar 2004 17:49:02 +0200 Subject: [PATCH 4/7] mem0dbg.c: Backport from 4.1: make mem_current_allocated_memory global variable innobase/mem/mem0dbg.c: Backport from 4.1: make mem_current_allocated_memory global variable --- innobase/mem/mem0dbg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/innobase/mem/mem0dbg.c b/innobase/mem/mem0dbg.c index 07f348ab82f..52a08e6faf1 100644 --- a/innobase/mem/mem0dbg.c +++ b/innobase/mem/mem0dbg.c @@ -20,7 +20,7 @@ Protected by mem_hash_mutex above. */ static ulint mem_n_created_heaps = 0; static ulint mem_n_allocations = 0; static ulint mem_total_allocated_memory = 0; -static ulint mem_current_allocated_memory = 0; +ulint mem_current_allocated_memory = 0; static ulint mem_max_allocated_memory = 0; /* Size of the hash table for memory management tracking */ From aab1e50e719f1f31629890fad650e9b0290cb906 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 27 Mar 2004 00:35:45 +0400 Subject: [PATCH 5/7] fixed bug #2342 "Running ANALYZE TABLE on bdb table inside a transaction hangs server thread" 1. added new status HA_ADMIN_REJECT and processing of it in mysql_admin_table 2. got ha_berkley::analyze to return HA_ADMIN_REJECT if there are any transactions with the table.. mysql-test/r/bdb-crash.result: added test for bug #2342 "Running ANALYZE TABLE on bdb table inside a transaction hangs server thread" mysql-test/t/bdb-crash.test: added test for bug #2342 "Running ANALYZE TABLE on bdb table inside a transaction hangs server thread" sql/ha_berkeley.cc: fixed bug #2342 "Running ANALYZE TABLE on bdb table inside a transaction hangs server thread" we have to return new status "HA_ADMIN_REJECT" for ha_berkley::analyze if there are any transaction for this table so as bdb documentation says: "The DB->stat method cannot be transaction protected" sql/handler.h: added new status of table info "HA_ADMIN_REJECT" We have to return this status for bdb tables which have any active transactions so as bdb-documentation says: "The DB->stat method cannot be transaction-protected" sql/sql_table.cc: added processing of the new status HA_ADMIN_REJECT in mysql_admin_table (reason to add this status is explained in comment for commit on sql/handler.h) --- mysql-test/r/bdb-crash.result | 7 +++++++ mysql-test/t/bdb-crash.test | 12 +++++++++++ sql/ha_berkeley.cc | 38 +++++++++++++++++++++++++++++++++++ sql/handler.h | 1 + sql/sql_table.cc | 6 ++++++ 5 files changed, 64 insertions(+) diff --git a/mysql-test/r/bdb-crash.result b/mysql-test/r/bdb-crash.result index 5079368ea21..16e51c61504 100644 --- a/mysql-test/r/bdb-crash.result +++ b/mysql-test/r/bdb-crash.result @@ -30,3 +30,10 @@ ChargeID ServiceID ChargeDate ChargeAmount FedTaxes ProvTaxes ChargeStatus Charg 1 1 2001-03-01 1.00 1.00 1.00 New blablabla NULL now 2 1 2001-03-01 1.00 1.00 1.00 New NULL NULL now drop table t1; +create table t1 (a int) engine=bdb; +set autocommit=0; +insert into t1 values(1); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Operation need committed state +drop table t1; diff --git a/mysql-test/t/bdb-crash.test b/mysql-test/t/bdb-crash.test index 4575a612728..a966ea4659d 100644 --- a/mysql-test/t/bdb-crash.test +++ b/mysql-test/t/bdb-crash.test @@ -34,3 +34,15 @@ INSERT INTO t1 VALUES(NULL,1,'2001-03-01',1,1,1,'New',NULL,NULL,'now'); select * from t1; drop table t1; + +# +# Test for bug #2342 "Running ANALYZE TABLE on bdb table +# inside a transaction hangs server thread" +# + +create table t1 (a int) engine=bdb; + +set autocommit=0; +insert into t1 values(1); +analyze table t1; +drop table t1; \ No newline at end of file diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index 35e731f20da..d0ce8f1fdb2 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -2099,6 +2099,44 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt) { DB_BTREE_STAT *stat=0; uint i; + DB_TXN_STAT *txn_stat_ptr= 0; + + /* + If it's a merge conflict here (4.0->4.1), please ignore it! + + The reason of the conflict is the difference between versions of bdb: + mysql-4.0 uses bdb 3.2.9 + mysql-4.1 uses bdb 4.1.24 + Older one has global functions txn_stat and txn_id but + newer one has DB_ENV->txn_stat and DB_TXN->id + */ + if (!txn_stat(db_env, &txn_stat_ptr, 0) && + txn_stat_ptr && txn_stat_ptr->st_nactive>=2) + { + DB_TXN_ACTIVE *atxn_stmt= 0, *atxn_all= 0; + + DB_TXN *txn_all= (DB_TXN*) thd->transaction.all.bdb_tid; + u_int32_t all_id= txn_id(txn_all); + + DB_TXN *txn_stmt= (DB_TXN*) thd->transaction.stmt.bdb_tid; + u_int32_t stmt_id= txn_id(txn_stmt); + + DB_TXN_ACTIVE *cur= txn_stat_ptr->st_txnarray; + DB_TXN_ACTIVE *end= cur + txn_stat_ptr->st_nactive; + for (; cur!=end && (!atxn_stmt || !atxn_all); cur++) + { + if (cur->txnid==all_id) atxn_all= cur; + if (cur->txnid==stmt_id) atxn_stmt= cur; + } + + if (atxn_stmt && atxn_all && + log_compare(&atxn_stmt->lsn,&atxn_all->lsn)) + { + free(txn_stat_ptr); + return HA_ADMIN_REJECT; + } + free(txn_stat_ptr); + } for (i=0 ; i < table->keys ; i++) { diff --git a/sql/handler.h b/sql/handler.h index ead0ed106c7..ac00050b777 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -40,6 +40,7 @@ #define HA_ADMIN_CORRUPT -3 #define HA_ADMIN_INTERNAL_ERROR -4 #define HA_ADMIN_INVALID -5 +#define HA_ADMIN_REJECT -6 /* Bits in table_flags() to show what database can do */ #define HA_READ_RND_SAME 1 /* Read RND-record to KEY-record diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 48151ef55b9..7507ab16968 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1330,6 +1330,12 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables, net_store_data(packet, "Operation failed"); break; + case HA_ADMIN_REJECT: + net_store_data(packet,"status"); + net_store_data(packet,"Operation need committed state"); + open_for_modify= false; + break; + case HA_ADMIN_ALREADY_DONE: net_store_data(packet, "status"); net_store_data(packet, "Table is already up to date"); From 04e879e7aedb11cb32db81bcef92169297784007 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 27 Mar 2004 02:37:05 +0400 Subject: [PATCH 6/7] some cleanup of last patch for BUG #2342 mysql-test/t/bdb-crash.test: added newline sql/ha_berkeley.cc: added a commet --- mysql-test/t/bdb-crash.test | 2 +- sql/ha_berkeley.cc | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/bdb-crash.test b/mysql-test/t/bdb-crash.test index a966ea4659d..98b542bf4c3 100644 --- a/mysql-test/t/bdb-crash.test +++ b/mysql-test/t/bdb-crash.test @@ -45,4 +45,4 @@ create table t1 (a int) engine=bdb; set autocommit=0; insert into t1 values(1); analyze table t1; -drop table t1; \ No newline at end of file +drop table t1; diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc index d0ce8f1fdb2..3522aadf349 100644 --- a/sql/ha_berkeley.cc +++ b/sql/ha_berkeley.cc @@ -2101,6 +2101,15 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt) uint i; DB_TXN_STAT *txn_stat_ptr= 0; + /* + Original bdb documentation says: + "The DB->stat method cannot be transaction-protected. + For this reason, it should be called in a thread of + control that has no open cursors or active transactions." + So, let's check if there are any changes have been done since + the beginning of the transaction.. + */ + /* If it's a merge conflict here (4.0->4.1), please ignore it! From 501c3e7a0e1770aa7b40a2b1c19b8e89388b834f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 29 Mar 2004 18:59:51 +0300 Subject: [PATCH 7/7] Fixed wrong assert (Got failure in ctype_tis620) --- include/m_string.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/m_string.h b/include/m_string.h index eac1552f8c1..934ad1c42b5 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -122,7 +122,7 @@ extern void bmove_allign(gptr dst,const gptr src,uint len); #ifdef HAVE_purify #include #define memcpy_overlap(A,B,C) \ -DBUG_ASSERT((A) == (B) || ((A)+(C)) <= (B) || ((B)+(C)) <= (A)); \ +DBUG_ASSERT((A) <= (B) || ((B)+(C)) <= (A)); \ bmove((byte*) key,(byte*) from,(size_t) length); #else #define memcpy_overlap(A,B,C) memcpy((A), (B), (C))