Commit a9de2c14 authored by monty@hundin.mysql.fi's avatar monty@hundin.mysql.fi

Some small fixes to the query cache.

parent 2597b1aa
...@@ -4744,22 +4744,23 @@ MySQL Server offers the following advantages over PostgreSQL: ...@@ -4744,22 +4744,23 @@ MySQL Server offers the following advantages over PostgreSQL:
@itemize @bullet @itemize @bullet
@item @item
@code{MySQL} Server is generally much faster than PostgreSQL. @code{MySQL} Server is generally much faster than PostgreSQL. MySQL
4.0.1 has also a query cache that can boost up the query speed for
mostly-read-only sites many times.
@item @item
MySQL has a much larger user base than PostgreSQL, therefore the MySQL has a much larger user base than PostgreSQL, therefore the code is
code is more tested and has historically proven more stable than more tested and has historically proven more stable than PostgreSQL.
PostgreSQL. MySQL Server is the much more used in production MySQL Server is more used in production environments than PostgreSQL,
environments than PostgreSQL, mostly thanks to that MySQL AB, mostly thanks to that MySQL AB, formerly TCX DataKonsult AB, has
formerly TCX DataKonsult AB, has provided top quality commercial support provided top quality commercial support for MySQL Server from the day it
for MySQL Server from the day it was released, whereas until recently was released, whereas until recently PostgreSQL was unsupported.
PostgreSQL was unsupported.
@item @item
MySQL Server works better on Windows than PostgreSQL does. MySQL Server runs as a MySQL Server works better on Windows than PostgreSQL does. MySQL Server
native Windows application (a service on NT/Win2000/WinXP), while runs as a native Windows application (a service on NT/Win2000/WinXP),
PostgreSQL is run under the @code{Cygwin} emulation. We have heard while PostgreSQL is run under the @code{Cygwin} emulation. We have
that PostgreSQL is not yet that stable on Windows but we haven't heard that PostgreSQL is not yet that stable on Windows but we haven't
been able to verify this ourselves. been able to verify this ourselves.
@item @item
...@@ -4844,19 +4845,21 @@ You can access many databases from the same connection (depending of course ...@@ -4844,19 +4845,21 @@ You can access many databases from the same connection (depending of course
on your privileges). on your privileges).
@item @item
MySQL Server is coded from the start to be multi-threaded while PostgreSQL uses MySQL Server is coded from the start to be multi-threaded while
processes. Context switching and access to common storage areas is much PostgreSQL uses processes. Context switching and access to common
faster between threads than between separate processes, this gives MySQL Server storage areas is much faster between threads than between separate
a big speed advantage in multi-user applications and also makes it easier processes, this gives MySQL Server a big speed advantage in multi-user
for MySQL Server to take full advantage of symmetric multiprocessor (SMP) systems. applications and also makes it easier for MySQL Server to take full
advantage of symmetric multiprocessor (SMP) systems.
@item @item
MySQL Server has a much more sophisticated privilege system than PostgreSQL. MySQL Server has a much more sophisticated privilege system than
While PostgreSQL only supports @code{INSERT}, @code{SELECT}, and PostgreSQL. While PostgreSQL only supports @code{INSERT},
@code{UPDATE/DELETE} grants per user on a database or a table, MySQL Server allows @code{SELECT}, and @code{UPDATE/DELETE} grants per user on a database or
you to define a full set of different privileges on database, table and a table, MySQL Server allows you to define a full set of different
column level. MySQL Server also allows you to specify the privilege on host and privileges on database, table and column level. MySQL Server also
user combinations. @xref{GRANT}. allows you to specify the privilege on host and user combinations.
@xref{GRANT}.
@item @item
MySQL Server supports a compressed client/server protocol which improves MySQL Server supports a compressed client/server protocol which improves
...@@ -4880,16 +4883,17 @@ of a data file happens, usually from a hardware failure. It allows a ...@@ -4880,16 +4883,17 @@ of a data file happens, usually from a hardware failure. It allows a
majority of the data to be recovered. majority of the data to be recovered.
@item @item
Upgrading MySQL Server is painless. When you are upgrading MySQL Server, you don't need Upgrading MySQL Server is painless. When you are upgrading MySQL
to dump/restore your data, as you have to do with most PostgreSQL upgrades. Server, you don't need to dump/restore your data, as you have to do with
most PostgreSQL upgrades.
@end itemize @end itemize
Drawbacks with MySQL Server compared to PostgreSQL: Drawbacks with MySQL Server compared to PostgreSQL:
@itemize @bullet @itemize @bullet
@item @item
The transaction support in MySQL Server is not yet as well tested as PostgreSQL's The transaction support in MySQL Server is not yet as well tested as
system. PostgreSQL's system.
@item @item
Because MySQL Server uses threads, which are not yet flawless on many OSes, one Because MySQL Server uses threads, which are not yet flawless on many OSes, one
...@@ -4914,10 +4918,10 @@ as in PostgreSQL. @xref{Adding functions}. ...@@ -4914,10 +4918,10 @@ as in PostgreSQL. @xref{Adding functions}.
@item @item
Updates that run over multiple tables is harder to do in MySQL Server. Updates that run over multiple tables is harder to do in MySQL Server.
This will, however, be fixed in MySQL Server 4.0 with multi-table @code{UPDATE} This will, however, be fixed in MySQL Server 4.0.2 with multi-table
and in MySQL Server 4.1 with subselects. @code{UPDATE} and in MySQL Server 4.1 with subselects. In MySQL Server
In MySQL Server 4.0 one can use multi-table deletes to delete from many tables 4.0 one can use multi-table deletes to delete from many tables at the
at the same time. @xref{DELETE}. same time. @xref{DELETE}.
@end itemize @end itemize
PostgreSQL currently offers the following advantages over MySQL Server: PostgreSQL currently offers the following advantages over MySQL Server:
...@@ -1127,7 +1127,7 @@ longlong Item_extract::val_int() ...@@ -1127,7 +1127,7 @@ longlong Item_extract::val_int()
void Item_typecast::print(String *str) void Item_typecast::print(String *str)
{ {
str->append("CASE("); str->append("CAST(");
args[0]->print(str); args[0]->print(str);
str->append(" AS "); str->append(" AS ");
str->append(func_name()); str->append(func_name());
......
...@@ -344,7 +344,8 @@ inline Query_cache_block * Query_cache_block_table::block() ...@@ -344,7 +344,8 @@ inline Query_cache_block * Query_cache_block_table::block()
void Query_cache_block::init(ulong block_length) void Query_cache_block::init(ulong block_length)
{ {
DBUG_ENTER("Query_cache_block::init"); DBUG_ENTER("Query_cache_block::init");
DBUG_PRINT("qcache", ("init block 0x%lx", (ulong) this)); DBUG_PRINT("qcache", ("init block 0x%lx length: %lu", (ulong) this,
block_length));
length = block_length; length = block_length;
used = 0; used = 0;
type = Query_cache_block::FREE; type = Query_cache_block::FREE;
...@@ -587,7 +588,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length) ...@@ -587,7 +588,7 @@ void query_cache_insert(NET *net, const char *packet, ulong length)
} }
else else
STRUCT_UNLOCK(&query_cache.structure_guard_mutex); STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
DBUG_EXECUTE("check_querycache",query_cache.check_integrity();); DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0););
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -615,7 +616,7 @@ void query_cache_abort(NET *net) ...@@ -615,7 +616,7 @@ void query_cache_abort(NET *net)
} }
net->query_cache_query=0; net->query_cache_query=0;
STRUCT_UNLOCK(&query_cache.structure_guard_mutex); STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
DBUG_EXECUTE("check_querycache",query_cache.check_integrity();); DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0););
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -662,7 +663,7 @@ void query_cache_end_of_result(NET *net) ...@@ -662,7 +663,7 @@ void query_cache_end_of_result(NET *net)
STRUCT_UNLOCK(&query_cache.structure_guard_mutex); STRUCT_UNLOCK(&query_cache.structure_guard_mutex);
} }
net->query_cache_query=0; net->query_cache_query=0;
DBUG_EXECUTE("check_querycache",query_cache.check_integrity();); DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0););
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -670,7 +671,7 @@ void query_cache_end_of_result(NET *net) ...@@ -670,7 +671,7 @@ void query_cache_end_of_result(NET *net)
void query_cache_invalidate_by_MyISAM_filename(const char *filename) void query_cache_invalidate_by_MyISAM_filename(const char *filename)
{ {
query_cache.invalidate_by_MyISAM_filename(filename); query_cache.invalidate_by_MyISAM_filename(filename);
DBUG_EXECUTE("check_querycache",query_cache.check_integrity();); DBUG_EXECUTE("check_querycache",query_cache.check_integrity(0););
} }
...@@ -2482,6 +2483,7 @@ my_bool Query_cache::move_by_type(byte **border, ...@@ -2482,6 +2483,7 @@ my_bool Query_cache::move_by_type(byte **border,
*pprev = block->pprev, *pprev = block->pprev,
*pnext = block->pnext, *pnext = block->pnext,
*new_block =(Query_cache_block *) *border; *new_block =(Query_cache_block *) *border;
uint tablename_offset = block->table()->table() - block->table()->db();
char *data = (char*) block->data(); char *data = (char*) block->data();
byte *key; byte *key;
uint key_length; uint key_length;
...@@ -2493,7 +2495,7 @@ my_bool Query_cache::move_by_type(byte **border, ...@@ -2493,7 +2495,7 @@ my_bool Query_cache::move_by_type(byte **border,
new_block->type=Query_cache_block::TABLE; new_block->type=Query_cache_block::TABLE;
new_block->used=used; new_block->used=used;
new_block->n_tables=1; new_block->n_tables=1;
memcpy((char*) new_block->data(), data, len-new_block->headers_len()); memmove((char*) new_block->data(), data, len-new_block->headers_len());
relink(block, new_block, next, prev, pnext, pprev); relink(block, new_block, next, prev, pnext, pprev);
if (tables_blocks[new_block->table()->type()] == block) if (tables_blocks[new_block->table()->type()] == block)
tables_blocks[new_block->table()->type()] = new_block; tables_blocks[new_block->table()->type()] = new_block;
...@@ -2515,10 +2517,18 @@ my_bool Query_cache::move_by_type(byte **border, ...@@ -2515,10 +2517,18 @@ my_bool Query_cache::move_by_type(byte **border,
nlist_root->prev = tnext; nlist_root->prev = tnext;
tprev->next = nlist_root; tprev->next = nlist_root;
} }
/*
Go through all queries that uses this table and change them to
point to the new table object
*/
Query_cache_table *new_block_table=new_block->table();
for (;tnext != nlist_root; tnext=tnext->next) for (;tnext != nlist_root; tnext=tnext->next)
tnext->parent = new_block->table(); tnext->parent= new_block_table;
*border += len; *border += len;
*before = new_block; *before = new_block;
/* Fix pointer to table name */
new_block->table()->table(new_block->table()->db() + tablename_offset);
/* Fix hash to point at moved block */ /* Fix hash to point at moved block */
hash_replace(&tables, tables.current_record, (byte*) new_block); hash_replace(&tables, tables.current_record, (byte*) new_block);
...@@ -2546,8 +2556,8 @@ my_bool Query_cache::move_by_type(byte **border, ...@@ -2546,8 +2556,8 @@ my_bool Query_cache::move_by_type(byte **border,
uint key_length; uint key_length;
key=query_cache_query_get_key((byte*) block, &key_length, 0); key=query_cache_query_get_key((byte*) block, &key_length, 0);
hash_search(&queries, (byte*) key, key_length); hash_search(&queries, (byte*) key, key_length);
// Move table of used tables
memcpy((char*) new_block->table(0), (char*) block->table(0), memmove((char*) new_block->table(0), (char*) block->table(0),
ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table))); ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table)));
block->query()->unlock_n_destroy(); block->query()->unlock_n_destroy();
block->destroy(); block->destroy();
...@@ -2555,7 +2565,7 @@ my_bool Query_cache::move_by_type(byte **border, ...@@ -2555,7 +2565,7 @@ my_bool Query_cache::move_by_type(byte **border,
new_block->type=Query_cache_block::QUERY; new_block->type=Query_cache_block::QUERY;
new_block->used=used; new_block->used=used;
new_block->n_tables=n_tables; new_block->n_tables=n_tables;
memcpy((char*) new_block->data(), data, len - new_block->headers_len()); memmove((char*) new_block->data(), data, len - new_block->headers_len());
relink(block, new_block, next, prev, pnext, pprev); relink(block, new_block, next, prev, pnext, pprev);
if (queries_blocks == block) if (queries_blocks == block)
queries_blocks = new_block; queries_blocks = new_block;
...@@ -2620,7 +2630,7 @@ my_bool Query_cache::move_by_type(byte **border, ...@@ -2620,7 +2630,7 @@ my_bool Query_cache::move_by_type(byte **border,
new_block->init(len); new_block->init(len);
new_block->type=type; new_block->type=type;
new_block->used=used; new_block->used=used;
memcpy((char*) new_block->data(), data, len - new_block->headers_len()); memmove((char*) new_block->data(), data, len - new_block->headers_len());
relink(block, new_block, next, prev, pnext, pprev); relink(block, new_block, next, prev, pnext, pprev);
new_block->result()->parent(query_block); new_block->result()->parent(query_block);
Query_cache_query *query = query_block->query(); Query_cache_query *query = query_block->query();
...@@ -2786,7 +2796,7 @@ void bins_dump() {} ...@@ -2786,7 +2796,7 @@ void bins_dump() {}
void cache_dump() {} void cache_dump() {}
void queries_dump() {} void queries_dump() {}
void tables_dump() {} void tables_dump() {}
my_bool check_integrity() { return 0; } my_bool check_integrity(bool not_locked) { return 0; }
my_bool in_list(Query_cache_block * root, Query_cache_block * point, my_bool in_list(Query_cache_block * root, Query_cache_block * point,
const char *name) { return 0;} const char *name) { return 0;}
my_bool in_blocks(Query_cache_block * point) { return 0; } my_bool in_blocks(Query_cache_block * point) { return 0; }
...@@ -2806,7 +2816,7 @@ void Query_cache::wreck(uint line, const char *message) ...@@ -2806,7 +2816,7 @@ void Query_cache::wreck(uint line, const char *message)
if (thd) if (thd)
thd->killed = 1; thd->killed = 1;
cache_dump(); cache_dump();
/* check_integrity(); */ /* Can't call it here because of locks */ /* check_integrity(0); */ /* Can't call it here because of locks */
bins_dump(); bins_dump();
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -2977,19 +2987,19 @@ void Query_cache::tables_dump() ...@@ -2977,19 +2987,19 @@ void Query_cache::tables_dump()
} }
my_bool Query_cache::check_integrity() my_bool Query_cache::check_integrity(bool not_locked)
{ {
my_bool result = 0; my_bool result = 0;
uint i; uint i;
STRUCT_LOCK(&structure_guard_mutex);
DBUG_ENTER("check_integrity"); DBUG_ENTER("check_integrity");
if ( !initialized ) if (!initialized )
{ {
STRUCT_UNLOCK(&structure_guard_mutex);
DBUG_PRINT("qcache", ("Query Cache not initialized")); DBUG_PRINT("qcache", ("Query Cache not initialized"));
DBUG_RETURN(0); DBUG_RETURN(0);
} }
if (!not_locked)
STRUCT_LOCK(&structure_guard_mutex);
if (hash_check(&queries)) if (hash_check(&queries))
{ {
...@@ -3213,7 +3223,8 @@ my_bool Query_cache::check_integrity() ...@@ -3213,7 +3223,8 @@ my_bool Query_cache::check_integrity()
} }
} }
DBUG_ASSERT(result == 0); DBUG_ASSERT(result == 0);
STRUCT_UNLOCK(&structure_guard_mutex); if (!not_locked)
STRUCT_UNLOCK(&structure_guard_mutex);
DBUG_RETURN(result); DBUG_RETURN(result);
} }
......
...@@ -391,7 +391,7 @@ protected: ...@@ -391,7 +391,7 @@ protected:
void cache_dump(); void cache_dump();
void queries_dump(); void queries_dump();
void tables_dump(); void tables_dump();
my_bool check_integrity(); my_bool check_integrity(bool not_locked);
my_bool in_list(Query_cache_block * root, Query_cache_block * point, my_bool in_list(Query_cache_block * root, Query_cache_block * point,
const char *name); const char *name);
my_bool in_blocks(Query_cache_block * point); my_bool in_blocks(Query_cache_block * point);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment