Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
63b2a551
Commit
63b2a551
authored
Mar 15, 2002
by
bell@sanja.is.com.ua
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
processing trunsactional tables in query cache
parent
12f1cba0
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
398 additions
and
127 deletions
+398
-127
Docs/manual.texi
Docs/manual.texi
+2
-3
mysql-test/r/innodb_cache.result
mysql-test/r/innodb_cache.result
+86
-1
mysql-test/t/innodb_cache.test
mysql-test/t/innodb_cache.test
+36
-1
sql/handler.cc
sql/handler.cc
+8
-5
sql/sql_cache.cc
sql/sql_cache.cc
+94
-80
sql/sql_cache.h
sql/sql_cache.h
+9
-17
sql/sql_class.cc
sql/sql_class.cc
+87
-0
sql/sql_class.h
sql/sql_class.h
+21
-2
sql/sql_delete.cc
sql/sql_delete.cc
+3
-3
sql/sql_insert.cc
sql/sql_insert.cc
+5
-5
sql/sql_parse.cc
sql/sql_parse.cc
+34
-6
sql/sql_table.cc
sql/sql_table.cc
+2
-2
sql/sql_update.cc
sql/sql_update.cc
+4
-2
sql/table.h
sql/table.h
+7
-0
No files found.
Docs/manual.texi
View file @
63b2a551
...
...
@@ -36229,9 +36229,8 @@ If a table changes (@code{INSERT}, @code{UPDATE}, @code{DELETE},
then all cached queries that used this table (possibly through a
@code{MRG_MyISAM} table!) become invalid and are removed from the cache.
Currently all @code{InnoDB} tables are invalidated on @code{COMMIT},
in the future this will be changed so only tables changed in the
transaction cause the corresponding cache entries to be invalidated.
Changed transactional @code{InnoDB} tables will be invalidated on
@code{COMMIT}.
A query cannot be cached if it contains one of the functions:
@multitable @columnfractions .25 .25 .25 .25
mysql-test/r/innodb_cache.result
View file @
63b2a551
drop table if exists t1;
drop table if exists t1, t2, t3;
flush status;
set autocommit=0;
create table t1 (a int not null) type=innodb;
insert into t1 values (1),(2),(3);
...
...
@@ -13,3 +14,87 @@ Qcache_queries_in_cache 0
drop table t1;
commit;
set autocommit=1;
begin;
create table t1 (a int not null) type=innodb;
insert into t1 values (1),(2),(3);
select * from t1;
a
1
2
3
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 0
drop table t1;
commit;
create table t1 (a int not null) type=innodb;
create table t2 (a int not null) type=innodb;
create table t3 (a int not null) type=innodb;
insert into t1 values (1),(2);
insert into t2 values (1),(2);
insert into t3 values (1),(2);
select * from t1;
a
1
2
select * from t2;
a
1
2
select * from t3;
a
1
2
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
begin;
select * from t1;
a
1
2
select * from t2;
a
1
2
select * from t3;
a
1
2
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
insert into t1 values (3);
insert into t2 values (3);
insert into t1 values (4);
select * from t1;
a
1
2
3
4
select * from t2;
a
1
2
3
select * from t3;
a
1
2
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 3
show status like "Qcache_hits";
Variable_name Value
Qcache_hits 0
commit;
show status like "Qcache_queries_in_cache";
Variable_name Value
Qcache_queries_in_cache 1
mysql-test/t/innodb_cache.test
View file @
63b2a551
...
...
@@ -3,7 +3,8 @@
#
# Without auto_commit.
#
drop
table
if
exists
t1
;
drop
table
if
exists
t1
,
t2
,
t3
;
flush
status
;
set
autocommit
=
0
;
create
table
t1
(
a
int
not
null
)
type
=
innodb
;
insert
into
t1
values
(
1
),(
2
),(
3
);
...
...
@@ -12,3 +13,37 @@ show status like "Qcache_queries_in_cache";
drop
table
t1
;
commit
;
set
autocommit
=
1
;
begin
;
create
table
t1
(
a
int
not
null
)
type
=
innodb
;
insert
into
t1
values
(
1
),(
2
),(
3
);
select
*
from
t1
;
show
status
like
"Qcache_queries_in_cache"
;
drop
table
t1
;
commit
;
create
table
t1
(
a
int
not
null
)
type
=
innodb
;
create
table
t2
(
a
int
not
null
)
type
=
innodb
;
create
table
t3
(
a
int
not
null
)
type
=
innodb
;
insert
into
t1
values
(
1
),(
2
);
insert
into
t2
values
(
1
),(
2
);
insert
into
t3
values
(
1
),(
2
);
select
*
from
t1
;
select
*
from
t2
;
select
*
from
t3
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_hits"
;
begin
;
select
*
from
t1
;
select
*
from
t2
;
select
*
from
t3
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_hits"
;
insert
into
t1
values
(
3
);
insert
into
t2
values
(
3
);
insert
into
t1
values
(
4
);
select
*
from
t1
;
select
*
from
t2
;
select
*
from
t3
;
show
status
like
"Qcache_queries_in_cache"
;
show
status
like
"Qcache_hits"
;
commit
;
show
status
like
"Qcache_queries_in_cache"
;
\ No newline at end of file
sql/handler.cc
View file @
63b2a551
...
...
@@ -271,7 +271,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
#ifdef USING_TRANSACTIONS
if
(
opt_using_transactions
)
{
bool
operation_done
=
0
;
bool
operation_done
=
0
;
bool
transaction_commited
=
0
;
/* Update the binary log if we have cached some queries */
if
(
trans
==
&
thd
->
transaction
.
all
&&
mysql_bin_log
.
is_open
()
&&
my_b_tell
(
&
thd
->
transaction
.
trans_log
))
...
...
@@ -289,6 +290,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
my_error
(
ER_ERROR_DURING_COMMIT
,
MYF
(
0
),
error
);
error
=
1
;
}
else
transaction_commited
=
1
;
trans
->
bdb_tid
=
0
;
}
#endif
...
...
@@ -302,12 +305,12 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
}
trans
->
innodb_active_trans
=
0
;
if
(
trans
==
&
thd
->
transaction
.
all
)
{
query_cache
.
invalidate
(
Query_cache_table
::
INNODB
);
operation_done
=
1
;
}
operation_done
=
transaction_commited
=
1
;
}
#endif
if
(
transaction_commited
)
query_cache
.
invalidate
(
thd
->
transaction
.
changed_tables
);
if
(
error
&&
trans
==
&
thd
->
transaction
.
all
&&
mysql_bin_log
.
is_open
())
sql_print_error
(
"Error: Got error during commit; Binlog is not up to date!"
);
thd
->
tx_isolation
=
thd
->
session_tx_isolation
;
...
...
sql/sql_cache.cc
View file @
63b2a551
...
...
@@ -271,8 +271,6 @@ If join_results allocated new block(s) then we need call pack_cache again.
TODO list:
- Invalidate queries that use innoDB tables changed in transaction & remove
invalidation by table type
- Delayed till after-parsing qache answer (for column rights processing)
- Optimize cache resizing
- if new_size < old_size then pack & shrink
...
...
@@ -280,8 +278,6 @@ TODO list:
- Move MRG_MYISAM table type processing to handlers, something like:
tables_used->table->file->register_used_filenames(callback,
first_argument);
- In Query_cache::insert_table eliminate strlen(). To do this we have to
add db_len to the TABLE_LIST and TABLE structures.
*/
#include "mysql_priv.h"
...
...
@@ -1030,7 +1026,8 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
Remove all cached queries that uses any of the tables in the list
*/
void
Query_cache
::
invalidate
(
TABLE_LIST
*
tables_used
)
void
Query_cache
::
invalidate
(
THD
*
thd
,
TABLE_LIST
*
tables_used
,
my_bool
using_transactions
)
{
DBUG_ENTER
(
"Query_cache::invalidate (table list)"
);
if
(
query_cache_size
>
0
)
...
...
@@ -1039,54 +1036,76 @@ void Query_cache::invalidate(TABLE_LIST *tables_used)
if
(
query_cache_size
>
0
)
{
DUMP
(
this
);
using_transactions
=
using_transactions
&&
(
thd
->
options
&
(
OPTION_NOT_AUTO_COMMIT
|
OPTION_BEGIN
));
for
(
;
tables_used
;
tables_used
=
tables_used
->
next
)
{
DBUG_ASSERT
(
!
using_transactions
||
tables_used
->
table
!=
0
);
if
(
using_transactions
&&
tables_used
->
table
->
file
->
has_transactions
())
/*
Tables_used->table can't be 0 in transaction.
Only 'drop' invalidate not opened table, but 'drop'
force transaction finish.
*/
thd
->
add_changed_table
(
tables_used
->
table
);
else
invalidate_table
(
tables_used
);
}
}
STRUCT_UNLOCK
(
&
structure_guard_mutex
);
}
DBUG_VOID_RETURN
;
}
/*
Remove all cached queries that uses the given table
*/
void
Query_cache
::
invalidate
(
TABLE
*
table
)
void
Query_cache
::
invalidate
(
CHANGED_TABLE_LIST
*
tables_used
)
{
DBUG_ENTER
(
"Query_cache::invalidate (
table
)"
);
if
(
query_cache_size
>
0
)
DBUG_ENTER
(
"Query_cache::invalidate (
changed table list
)"
);
if
(
query_cache_size
>
0
&&
tables_used
)
{
STRUCT_LOCK
(
&
structure_guard_mutex
);
if
(
query_cache_size
>
0
)
invalidate_table
(
table
);
{
DUMP
(
this
);
for
(
;
tables_used
;
tables_used
=
tables_used
->
next
)
{
invalidate_table
(
tables_used
->
key
,
tables_used
->
key_length
);
DBUG_PRINT
(
"qcache"
,
(
" db %s, table %s"
,
tables_used
->
key
,
tables_used
->
table_name
));
}
}
STRUCT_UNLOCK
(
&
structure_guard_mutex
);
}
DBUG_VOID_RETURN
;
}
/*
Remove all cached queries that uses the given table
type.
Remove all cached queries that uses the given table
*/
void
Query_cache
::
invalidate
(
Query_cache_table
::
query_cache_table_type
type
)
void
Query_cache
::
invalidate
(
THD
*
thd
,
TABLE
*
table
,
my_bool
using_transactions
)
{
DBUG_ENTER
(
"Query_cache::invalidate (type)"
);
DBUG_ENTER
(
"Query_cache::invalidate (table)"
);
if
(
query_cache_size
>
0
)
{
STRUCT_LOCK
(
&
structure_guard_mutex
);
DUMP
(
this
);
if
(
query_cache_size
>
0
)
{
/* invalidate_table reduce list while only root of list remain */
while
(
tables_blocks
[
type
]
!=
0
)
invalidate_table
(
tables_blocks
[
type
]);
using_transactions
=
using_transactions
&&
(
thd
->
options
&
(
OPTION_NOT_AUTO_COMMIT
|
OPTION_BEGIN
));
if
(
using_transactions
&&
table
->
file
->
has_transactions
())
thd
->
add_changed_table
(
table
);
else
invalidate_table
(
table
);
}
STRUCT_UNLOCK
(
&
structure_guard_mutex
);
}
DBUG_VOID_RETURN
;
}
/*
Remove all cached queries that uses the given database
*/
...
...
@@ -1100,12 +1119,9 @@ void Query_cache::invalidate(char *db)
if
(
query_cache_size
>
0
)
{
DUMP
(
this
);
for
(
int
i
=
0
;
i
<
(
int
)
Query_cache_table
::
TYPES_NUMBER
;
i
++
)
{
/* invalidate_table reduce list while only root of list remain */
while
(
tables_blocks
[
i
]
!=
0
)
invalidate_table
(
tables_blocks
[
i
]);
}
while
(
tables_blocks
!=
0
)
invalidate_table
(
tables_blocks
);
}
STRUCT_UNLOCK
(
&
structure_guard_mutex
);
}
...
...
@@ -1120,7 +1136,8 @@ void Query_cache::invalidate_by_MyISAM_filename(const char *filename)
{
/* Calculate the key outside the lock to make the lock shorter */
char
key
[
MAX_DBKEY_LENGTH
];
uint
key_length
=
filename_2_table_key
(
key
,
filename
);
uint32
db_length
;
uint
key_length
=
filename_2_table_key
(
key
,
filename
,
&
db_length
);
STRUCT_LOCK
(
&
structure_guard_mutex
);
if
(
query_cache_size
>
0
)
// Safety if cache removed
{
...
...
@@ -1800,11 +1817,15 @@ void Query_cache::invalidate_table(TABLE_LIST *table_list)
}
void
Query_cache
::
invalidate_table
(
TABLE
*
table
)
{
invalidate_table
((
byte
*
)
table
->
table_cache_key
,
table
->
key_length
);
}
void
Query_cache
::
invalidate_table
(
byte
*
key
,
uint32
key_length
)
{
Query_cache_block
*
table_block
;
if
((
table_block
=
((
Query_cache_block
*
)
hash_search
(
&
tables
,
(
byte
*
)
table
->
table_cache_key
,
table
->
key_length
))))
hash_search
(
&
tables
,
key
,
key_length
))))
invalidate_table
(
table_block
);
}
...
...
@@ -1842,8 +1863,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
block_table
->
n
=
n
;
if
(
!
insert_table
(
tables_used
->
table
->
key_length
,
tables_used
->
table
->
table_cache_key
,
block_table
,
Query_cache_table
::
type_convertion
(
tables_used
->
table
->
db_type
)))
tables_used
->
db_length
))
break
;
if
(
tables_used
->
table
->
db_type
==
DB_TYPE_MRG_MYISAM
)
...
...
@@ -1855,10 +1875,12 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
table
++
)
{
char
key
[
MAX_DBKEY_LENGTH
];
uint
key_length
=
filename_2_table_key
(
key
,
table
->
table
->
filename
);
uint32
db_length
;
uint
key_length
=
filename_2_table_key
(
key
,
table
->
table
->
filename
,
&
db_length
);
(
++
block_table
)
->
n
=
++
n
;
if
(
!
insert_table
(
key_length
,
key
,
block_table
,
Query_cache_table
::
type_convertion
(
DB_TYPE_MYISAM
)
))
db_length
))
goto
err
;
}
}
...
...
@@ -1885,7 +1907,7 @@ my_bool Query_cache::register_all_tables(Query_cache_block *block,
my_bool
Query_cache
::
insert_table
(
uint
key_len
,
char
*
key
,
Query_cache_block_table
*
node
,
Query_cache_table
::
query_cache_table_type
type
)
uint32
db_length
)
{
DBUG_ENTER
(
"Query_cache::insert_table"
);
DBUG_PRINT
(
"qcache"
,
(
"insert table node 0x%lx, len %d"
,
...
...
@@ -1909,9 +1931,8 @@ Query_cache::insert_table(uint key_len, char *key,
DBUG_RETURN
(
0
);
}
Query_cache_table
*
header
=
table_block
->
table
();
header
->
type
(
type
);
double_linked_list_simple_include
(
table_block
,
&
tables_blocks
[
type
]
);
&
tables_blocks
);
Query_cache_block_table
*
list_root
=
table_block
->
table
(
0
);
list_root
->
n
=
0
;
list_root
->
next
=
list_root
->
prev
=
list_root
;
...
...
@@ -1923,7 +1944,7 @@ Query_cache::insert_table(uint key_len, char *key,
DBUG_RETURN
(
0
);
}
char
*
db
=
header
->
db
();
header
->
table
(
db
+
strlen
(
db
)
+
1
);
header
->
table
(
db
+
db_length
+
1
);
}
Query_cache_block_table
*
list_root
=
table_block
->
table
(
0
);
...
...
@@ -1947,7 +1968,7 @@ void Query_cache::unlink_table(Query_cache_block_table *node)
// list is empty (neighbor is root of list)
Query_cache_block
*
table_block
=
neighbour
->
block
();
double_linked_list_exclude
(
table_block
,
&
tables_blocks
[
table_block
->
table
()
->
type
()]
);
&
tables_blocks
);
hash_delete
(
&
tables
,(
byte
*
)
table_block
);
free_memory_block
(
table_block
);
}
...
...
@@ -2033,7 +2054,7 @@ Query_cache::get_free_block(ulong len, my_bool not_less, ulong min)
block
=
block
->
prev
;
n
++
;
}
if
(
block
->
length
<
len
)
if
(
block
->
length
<
len
)
block
=
block
->
next
;
}
}
...
...
@@ -2513,8 +2534,8 @@ my_bool Query_cache::move_by_type(byte **border,
new_block
->
n_tables
=
1
;
memmove
((
char
*
)
new_block
->
data
(),
data
,
len
-
new_block
->
headers_len
());
relink
(
block
,
new_block
,
next
,
prev
,
pnext
,
pprev
);
if
(
tables_blocks
[
new_block
->
table
()
->
type
()]
==
block
)
tables_blocks
[
new_block
->
table
()
->
type
()]
=
new_block
;
if
(
tables_blocks
==
block
)
tables_blocks
=
new_block
;
Query_cache_block_table
*
nlist_root
=
new_block
->
table
(
0
);
nlist_root
->
n
=
0
;
...
...
@@ -2771,10 +2792,10 @@ my_bool Query_cache::join_results(ulong join_limit)
}
uint
Query_cache
::
filename_2_table_key
(
char
*
key
,
const
char
*
path
)
uint
Query_cache
::
filename_2_table_key
(
char
*
key
,
const
char
*
path
,
uint32
*
db_length
)
{
char
tablename
[
FN_REFLEN
+
2
],
*
filename
,
*
dbname
;
uint
db_length
;
DBUG_ENTER
(
"Query_cache::filename_2_table_key"
);
/* Safety if filename didn't have a directory name */
...
...
@@ -2785,10 +2806,10 @@ uint Query_cache::filename_2_table_key (char *key, const char *path)
filename
=
tablename
+
dirname_length
(
tablename
+
2
)
+
2
;
/* Find start of databasename */
for
(
dbname
=
filename
-
2
;
dbname
[
-
1
]
!=
FN_LIBCHAR
;
dbname
--
)
;
db_length
=
(
filename
-
dbname
)
-
1
;
DBUG_PRINT
(
"qcache"
,
(
"table '%-.*s.%s'"
,
db_length
,
dbname
,
filename
));
*
db_length
=
(
filename
-
dbname
)
-
1
;
DBUG_PRINT
(
"qcache"
,
(
"table '%-.*s.%s'"
,
*
db_length
,
dbname
,
filename
));
DBUG_RETURN
((
uint
)
(
strmov
(
strmake
(
key
,
dbname
,
db_length
)
+
1
,
DBUG_RETURN
((
uint
)
(
strmov
(
strmake
(
key
,
dbname
,
*
db_length
)
+
1
,
filename
)
-
key
)
+
1
);
}
...
...
@@ -2975,22 +2996,18 @@ void Query_cache::tables_dump()
DBUG_PRINT
(
"qcache"
,
(
"--------------------"
));
DBUG_PRINT
(
"qcache"
,
(
"TABLES"
));
DBUG_PRINT
(
"qcache"
,
(
"--------------------"
));
for
(
int
i
=
0
;
i
<
(
int
)
Query_cache_table
::
TYPES_NUMBER
;
i
++
)
if
(
tables_blocks
!=
0
)
{
DBUG_PRINT
(
"qcache"
,
(
"--- type %u"
,
i
));
if
(
tables_blocks
[
i
]
!=
0
)
{
Query_cache_block
*
table_block
=
tables_blocks
[
i
];
Query_cache_block
*
table_block
=
tables_blocks
;
do
{
Query_cache_table
*
table
=
table_block
->
table
();
DBUG_PRINT
(
"qcache"
,
(
"'%s' '%s'"
,
table
->
db
(),
table
->
table
()));
table_block
=
table_block
->
next
;
}
while
(
table_block
!=
tables_blocks
[
i
]
);
}
while
(
table_block
!=
tables_blocks
);
}
else
DBUG_PRINT
(
"qcache"
,
(
"no tables in list"
));
}
DBUG_PRINT
(
"qcache"
,
(
"--------------------"
));
}
...
...
@@ -3082,7 +3099,7 @@ my_bool Query_cache::check_integrity(bool not_locked)
break
;
}
case
Query_cache_block
:
:
TABLE
:
if
(
in_list
(
tables_blocks
[
block
->
table
()
->
type
()]
,
block
,
"tables"
))
if
(
in_list
(
tables_blocks
,
block
,
"tables"
))
result
=
1
;
if
(
in_table_list
(
block
->
table
(
0
),
block
->
table
(
0
),
"table list root"
))
result
=
1
;
...
...
@@ -3197,9 +3214,7 @@ my_bool Query_cache::check_integrity(bool not_locked)
}
DBUG_PRINT
(
"qcache"
,
(
"check tables ..."
));
for
(
i
=
0
;
(
int
)
i
<
(
int
)
Query_cache_table
::
TYPES_NUMBER
;
i
++
)
{
if
((
block
=
tables_blocks
[
i
]))
if
((
block
=
tables_blocks
))
{
do
{
...
...
@@ -3217,8 +3232,7 @@ my_bool Query_cache::check_integrity(bool not_locked)
if
(
in_blocks
(
block
))
result
=
1
;
block
=
block
->
next
;
}
while
(
block
!=
tables_blocks
[
i
]);
}
}
while
(
block
!=
tables_blocks
);
}
DBUG_PRINT
(
"qcache"
,
(
"check free blocks"
));
...
...
sql/sql_cache.h
View file @
63b2a551
...
...
@@ -148,17 +148,8 @@ struct Query_cache_query
struct
Query_cache_table
{
enum
query_cache_table_type
{
OTHER
=
0
,
INNODB
=
1
,
TYPES_NUMBER
=
2
};
inline
static
query_cache_table_type
type_convertion
(
db_type
type
)
{
return
(
type
==
DB_TYPE_INNODB
?
INNODB
:
OTHER
);
}
char
*
tbl
;
query_cache_table_type
tp
;
inline
query_cache_table_type
type
()
{
return
tp
;
}
inline
void
type
(
query_cache_table_type
t
)
{
tp
=
t
;}
inline
char
*
db
()
{
return
(
char
*
)
data
();
}
inline
char
*
table
()
{
return
tbl
;
}
inline
void
table
(
char
*
table
)
{
tbl
=
table
;
}
...
...
@@ -248,7 +239,7 @@ class Query_cache
byte
*
cache
;
// cache memory
Query_cache_block
*
first_block
;
// physical location block list
Query_cache_block
*
queries_blocks
;
// query list (LIFO)
Query_cache_block
*
tables_blocks
[
Query_cache_table
::
TYPES_NUMBER
]
;
Query_cache_block
*
tables_blocks
;
Query_cache_memory_bin
*
bins
;
// free block lists
Query_cache_memory_bin_step
*
steps
;
// bins spacing info
...
...
@@ -270,7 +261,8 @@ class Query_cache
Query_cache_block
*
tail_head
);
/* Table key generation */
static
uint
filename_2_table_key
(
char
*
key
,
const
char
*
filename
);
static
uint
filename_2_table_key
(
char
*
key
,
const
char
*
filename
,
uint32
*
db_langth
);
/* The following functions require that structure_guard_mutex is locked */
void
flush_cache
();
...
...
@@ -282,13 +274,14 @@ class Query_cache
my_bool
first_block
);
void
invalidate_table
(
TABLE_LIST
*
table
);
void
invalidate_table
(
TABLE
*
table
);
void
invalidate_table
(
byte
*
key
,
uint32
key_length
);
void
invalidate_table
(
Query_cache_block
*
table_block
);
my_bool
register_all_tables
(
Query_cache_block
*
block
,
TABLE_LIST
*
tables_used
,
TABLE_COUNTER_TYPE
tables
);
my_bool
insert_table
(
uint
key_len
,
char
*
key
,
Query_cache_block_table
*
node
,
Query_cache_table
::
query_cache_table_type
type
);
uint32
db_length
);
void
unlink_table
(
Query_cache_block_table
*
node
);
Query_cache_block
*
get_free_block
(
ulong
len
,
my_bool
not_less
,
ulong
min
);
...
...
@@ -369,11 +362,10 @@ class Query_cache
int
send_result_to_client
(
THD
*
thd
,
char
*
query
,
uint
query_length
);
/* Remove all queries that uses any of the listed following tables */
void
invalidate
(
TABLE_LIST
*
tables_used
);
void
invalidate
(
TABLE
*
table
);
/* Remove all queries that uses tables of pointed type*/
void
invalidate
(
Query_cache_table
::
query_cache_table_type
type
);
void
invalidate
(
THD
*
thd
,
TABLE_LIST
*
tables_used
,
my_bool
using_transactions
);
void
invalidate
(
CHANGED_TABLE_LIST
*
tables_used
);
void
invalidate
(
THD
*
thd
,
TABLE
*
table
,
my_bool
using_transactions
);
/* Remove all queries that uses any of the tables in following database */
void
invalidate
(
char
*
db
);
...
...
sql/sql_class.cc
View file @
63b2a551
...
...
@@ -34,6 +34,8 @@
#ifdef __WIN__
#include <io.h>
#endif
#include <mysys_err.h>
#include <assert.h>
/*****************************************************************************
** Instansiate templates
...
...
@@ -105,6 +107,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
net
.
vio
=
0
;
ull
=
0
;
system_thread
=
cleanup_done
=
0
;
transaction
.
changed_tables
=
0
;
#ifdef __WIN__
real_id
=
0
;
#endif
...
...
@@ -136,6 +139,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
/* Initialize sub structures */
bzero
((
char
*
)
&
mem_root
,
sizeof
(
mem_root
));
bzero
((
char
*
)
&
transaction
.
mem_root
,
sizeof
(
transaction
.
mem_root
));
user_connect
=
(
UC
*
)
0
;
hash_init
(
&
user_vars
,
USER_VARS_HASH_SIZE
,
0
,
0
,
(
hash_get_key
)
get_var_key
,
...
...
@@ -211,6 +215,7 @@ THD::~THD()
safeFree
(
db
);
safeFree
(
ip
);
free_root
(
&
mem_root
,
MYF
(
0
));
free_root
(
&
transaction
.
mem_root
,
MYF
(
0
));
mysys_var
=
0
;
// Safety (shouldn't be needed)
#ifdef SIGNAL_WITH_VIO_CLOSE
pthread_mutex_destroy
(
&
active_vio_lock
);
...
...
@@ -255,6 +260,88 @@ bool THD::store_globals()
my_pthread_setspecific_ptr
(
THR_NET
,
&
net
));
}
/* routings to adding tables to list of changed in transaction tables */
inline
static
void
list_include
(
CHANGED_TABLE_LIST
**
prev
,
CHANGED_TABLE_LIST
*
curr
,
CHANGED_TABLE_LIST
*
new_table
)
{
if
(
new_table
)
{
*
prev
=
new_table
;
(
*
prev
)
->
next
=
curr
;
}
}
/* add table to list of changed in transaction tables */
void
THD
::
add_changed_table
(
TABLE
*
table
)
{
DBUG_ENTER
(
"THD::add_changed_table (table)"
);
DBUG_ASSERT
((
options
&
(
OPTION_NOT_AUTO_COMMIT
|
OPTION_BEGIN
))
&&
table
->
file
->
has_transactions
());
CHANGED_TABLE_LIST
**
prev
=
&
transaction
.
changed_tables
;
CHANGED_TABLE_LIST
*
curr
=
transaction
.
changed_tables
;
for
(;
curr
;
prev
=
&
(
curr
->
next
),
curr
=
curr
->
next
)
{
int
cmp
=
(
long
)
curr
->
key_length
-
(
long
)
table
->
key_length
;
if
(
cmp
<
0
)
{
list_include
(
prev
,
curr
,
changed_table_dup
(
table
));
DBUG_PRINT
(
"info"
,
(
"key_length %u %u"
,
table
->
key_length
,
(
*
prev
)
->
key_length
));
DBUG_VOID_RETURN
;
}
else
if
(
cmp
==
0
)
{
cmp
=
memcmp
(
curr
->
key
,
table
->
table_cache_key
,
curr
->
key_length
);
if
(
cmp
<
0
)
{
list_include
(
prev
,
curr
,
changed_table_dup
(
table
));
DBUG_PRINT
(
"info"
,
(
"key_length %u %u"
,
table
->
key_length
,
(
*
prev
)
->
key_length
));
DBUG_VOID_RETURN
;
}
else
if
(
cmp
==
0
)
{
DBUG_PRINT
(
"info"
,
(
"already in list"
));
DBUG_VOID_RETURN
;
}
}
}
*
prev
=
changed_table_dup
(
table
);
DBUG_PRINT
(
"info"
,
(
"key_length %u %u"
,
table
->
key_length
,
(
*
prev
)
->
key_length
));
DBUG_VOID_RETURN
;
}
CHANGED_TABLE_LIST
*
THD
::
changed_table_dup
(
TABLE
*
table
)
{
CHANGED_TABLE_LIST
*
new_table
=
(
CHANGED_TABLE_LIST
*
)
trans_alloc
(
ALIGN_SIZE
(
sizeof
(
CHANGED_TABLE_LIST
))
+
table
->
key_length
+
1
);
if
(
!
new_table
)
{
my_error
(
EE_OUTOFMEMORY
,
MYF
(
ME_BELL
),
ALIGN_SIZE
(
sizeof
(
TABLE_LIST
))
+
table
->
key_length
+
1
);
killed
=
1
;
return
0
;
}
new_table
->
key
=
(
char
*
)
(((
byte
*
)
new_table
)
+
ALIGN_SIZE
(
sizeof
(
CHANGED_TABLE_LIST
)));
new_table
->
next
=
0
;
new_table
->
key_length
=
table
->
key_length
;
uint32
db_len
=
((
new_table
->
table_name
=
::
strmake
(
new_table
->
key
,
table
->
table_cache_key
,
table
->
key_length
)
+
1
)
-
new_table
->
key
);
::
memcpy
(
new_table
->
key
+
db_len
,
table
->
table_cache_key
+
db_len
,
table
->
key_length
-
db_len
);
return
new_table
;
}
/*****************************************************************************
** Functions to provide a interface to select results
*****************************************************************************/
...
...
sql/sql_class.h
View file @
63b2a551
...
...
@@ -258,7 +258,7 @@ class THD :public ilink {
public:
NET
net
;
// client connection descriptor
LEX
lex
;
// parse tree descriptor
MEM_ROOT
mem_root
;
// memory allocation pool
MEM_ROOT
mem_root
;
//
1 command-life
memory allocation pool
HASH
user_vars
;
// hash for user variables
String
packet
;
// dynamic string buffer used for network I/O
struct
sockaddr_in
remote
;
// client socket address
...
...
@@ -326,6 +326,19 @@ class THD :public ilink {
THD_TRANS
all
;
// Trans since BEGIN WORK
THD_TRANS
stmt
;
// Trans for current statement
uint
bdb_lock_count
;
/*
Tables changed in transaction (that must be invalidated in query cache).
List contain only transactional tables, that not invalidated in query
cache (instead of full list of changed in transaction tables).
*/
CHANGED_TABLE_LIST
*
changed_tables
;
MEM_ROOT
mem_root
;
// Transaction-life memory allocation pool
void
cleanup
()
{
changed_tables
=
0
;
free_root
(
&
mem_root
,
MYF
(
MY_KEEP_PREALLOC
));
}
}
transaction
;
Item
*
free_list
,
*
handler_items
;
CONVERT
*
convert_set
;
...
...
@@ -471,6 +484,12 @@ class THD :public ilink {
memcpy
(
ptr
,
str
,
size
);
return
ptr
;
}
inline
gptr
trans_alloc
(
unsigned
int
size
)
{
return
alloc_root
(
&
transaction
.
mem_root
,
size
);
}
void
add_changed_table
(
TABLE
*
table
);
CHANGED_TABLE_LIST
*
changed_table_dup
(
TABLE
*
table
);
};
...
...
sql/sql_delete.cc
View file @
63b2a551
...
...
@@ -182,7 +182,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
thd
->
lock
=
0
;
}
if
(
deleted
)
query_cache
.
invalidate
(
t
able_list
);
query_cache
.
invalidate
(
t
hd
,
table_list
,
1
);
delete
select
;
if
(
error
>=
0
)
// Fatal error
send_error
(
&
thd
->
net
,
thd
->
killed
?
ER_SERVER_SHUTDOWN
:
0
);
...
...
@@ -470,7 +470,7 @@ bool multi_delete::send_eof()
VOID
(
ha_autocommit_or_rollback
(
thd
,
error
>
0
));
}
if
(
deleted
)
query_cache
.
invalidate
(
delete_tables
);
query_cache
.
invalidate
(
thd
,
delete_tables
,
1
);
::
send_ok
(
&
thd
->
net
,
deleted
);
return
0
;
}
...
...
@@ -548,7 +548,7 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
bzero
((
char
*
)
&
create_info
,
sizeof
(
create_info
));
*
fn_ext
(
path
)
=
0
;
// Remove the .frm extension
error
=
ha_create_table
(
path
,
&
create_info
,
1
)
?
-
1
:
0
;
query_cache
.
invalidate
(
t
able_list
);
query_cache
.
invalidate
(
t
hd
,
table_list
,
0
);
if
(
!
dont_send_ok
)
{
...
...
sql/sql_insert.cc
View file @
63b2a551
...
...
@@ -311,7 +311,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, List<Item> &fields,
}
thd
->
proc_info
=
"end"
;
if
(
info
.
copied
||
info
.
deleted
)
query_cache
.
invalidate
(
t
able_list
);
query_cache
.
invalidate
(
t
hd
,
table_list
,
1
);
table
->
time_stamp
=
save_time_stamp
;
// Restore auto timestamp ptr
table
->
next_number_field
=
0
;
thd
->
count_cuted_fields
=
0
;
...
...
@@ -1217,7 +1217,7 @@ bool delayed_insert::handle_inserts(void)
sql_print_error
(
"%s"
,
thd
.
net
.
last_error
);
goto
err
;
}
query_cache
.
invalidate
(
table
);
query_cache
.
invalidate
(
&
thd
,
table
,
1
);
if
(
thr_reschedule_write_lock
(
*
thd
.
lock
->
locks
))
{
/* This should never happen */
...
...
@@ -1242,7 +1242,7 @@ bool delayed_insert::handle_inserts(void)
sql_print_error
(
"%s"
,
thd
.
net
.
last_error
);
goto
err
;
}
query_cache
.
invalidate
(
table
);
query_cache
.
invalidate
(
&
thd
,
table
,
1
);
pthread_mutex_lock
(
&
mutex
);
DBUG_RETURN
(
0
);
...
...
@@ -1330,7 +1330,7 @@ void select_insert::send_error(uint errcode,const char *err)
table
->
file
->
activate_all_index
(
thd
);
ha_rollback_stmt
(
thd
);
if
(
info
.
copied
||
info
.
deleted
)
query_cache
.
invalidate
(
t
able
);
query_cache
.
invalidate
(
t
hd
,
table
,
1
);
}
...
...
@@ -1343,7 +1343,7 @@ bool select_insert::send_eof()
if
((
error2
=
ha_autocommit_or_rollback
(
thd
,
error
))
&&
!
error
)
error
=
error2
;
if
(
info
.
copied
||
info
.
deleted
)
query_cache
.
invalidate
(
t
able
);
query_cache
.
invalidate
(
t
hd
,
table
,
1
);
if
(
error
)
{
...
...
sql/sql_parse.cc
View file @
63b2a551
...
...
@@ -48,6 +48,10 @@
#endif
/* HAVE_OPENSSL */
#define SCRAMBLE_LENGTH 8
#define MEM_ROOT_BLOCK_SIZE 8192
#define MEM_ROOT_PREALLOC 8192
#define TRANS_MEM_ROOT_BLOCK_SIZE 4096
#define TRANS_MEM_ROOT_PREALLOC 4096
extern
int
yyparse
(
void
);
extern
"C"
pthread_mutex_t
THR_LOCK_keycache
;
...
...
@@ -615,7 +619,9 @@ pthread_handler_decl(handle_one_connection,arg)
thd
->
command
=
COM_SLEEP
;
thd
->
version
=
refresh_version
;
thd
->
set_time
();
init_sql_alloc
(
&
thd
->
mem_root
,
8192
,
8192
);
init_sql_alloc
(
&
thd
->
mem_root
,
MEM_ROOT_BLOCK_SIZE
,
MEM_ROOT_PREALLOC
);
init_sql_alloc
(
&
thd
->
transaction
.
mem_root
,
TRANS_MEM_ROOT_BLOCK_SIZE
,
TRANS_MEM_ROOT_PREALLOC
);
while
(
!
net
->
error
&&
net
->
vio
!=
0
&&
!
thd
->
killed
)
{
if
(
do_command
(
thd
))
...
...
@@ -688,7 +694,9 @@ pthread_handler_decl(handle_bootstrap,arg)
thd
->
priv_user
=
thd
->
user
=
(
char
*
)
"boot"
;
buff
=
(
char
*
)
thd
->
net
.
buff
;
init_sql_alloc
(
&
thd
->
mem_root
,
8192
,
8192
);
init_sql_alloc
(
&
thd
->
mem_root
,
MEM_ROOT_BLOCK_SIZE
,
MEM_ROOT_PREALLOC
);
init_sql_alloc
(
&
thd
->
transaction
.
mem_root
,
TRANS_MEM_ROOT_BLOCK_SIZE
,
TRANS_MEM_ROOT_PREALLOC
);
while
(
fgets
(
buff
,
thd
->
net
.
max_packet
,
file
))
{
uint
length
=
(
uint
)
strlen
(
buff
);
...
...
@@ -712,6 +720,7 @@ pthread_handler_decl(handle_bootstrap,arg)
if
(
thd
->
fatal_error
)
break
;
free_root
(
&
thd
->
mem_root
,
MYF
(
MY_KEEP_PREALLOC
));
free_root
(
&
thd
->
transaction
.
mem_root
,
MYF
(
MY_KEEP_PREALLOC
));
}
thd
->
priv_user
=
thd
->
user
=
0
;
...
...
@@ -1084,6 +1093,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
close_connection
(
net
);
close_thread_tables
(
thd
);
// Free before kill
free_root
(
&
thd
->
mem_root
,
MYF
(
0
));
free_root
(
&
thd
->
transaction
.
mem_root
,
MYF
(
0
));
kill_mysql
();
error
=
TRUE
;
break
;
...
...
@@ -1620,7 +1630,7 @@ mysql_execute_command(void)
goto
error
;
}
}
query_cache
.
invalidate
(
t
ables
);
query_cache
.
invalidate
(
t
hd
,
tables
,
0
);
if
(
end_active_trans
(
thd
))
res
=
-
1
;
else
if
(
mysql_rename_tables
(
thd
,
tables
))
...
...
@@ -1659,7 +1669,7 @@ mysql_execute_command(void)
check_table_access
(
thd
,
SELECT_ACL
|
INSERT_ACL
,
tables
))
goto
error
;
/* purecov: inspected */
res
=
mysql_repair_table
(
thd
,
tables
,
&
lex
->
check_opt
);
query_cache
.
invalidate
(
t
ables
);
query_cache
.
invalidate
(
t
hd
,
tables
,
0
);
break
;
}
case
SQLCOM_CHECK
:
...
...
@@ -1668,7 +1678,7 @@ mysql_execute_command(void)
check_table_access
(
thd
,
SELECT_ACL
|
EXTRA_ACL
,
tables
))
goto
error
;
/* purecov: inspected */
res
=
mysql_check_table
(
thd
,
tables
,
&
lex
->
check_opt
);
query_cache
.
invalidate
(
t
ables
);
query_cache
.
invalidate
(
t
hd
,
tables
,
0
);
break
;
}
case
SQLCOM_ANALYZE
:
...
...
@@ -2392,6 +2402,7 @@ mysql_execute_command(void)
}
else
res
=
-
1
;
thd
->
transaction
.
cleanup
();
break
;
}
case
SQLCOM_ROLLBACK
:
...
...
@@ -2406,6 +2417,7 @@ mysql_execute_command(void)
else
res
=
-
1
;
thd
->
options
&=
~
(
ulong
)
(
OPTION_BEGIN
|
OPTION_STATUS_NO_TRANS_UPDATE
);
thd
->
transaction
.
cleanup
();
break
;
default:
/* Impossible */
send_ok
(
&
thd
->
net
);
...
...
@@ -3108,7 +3120,22 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
if
(
!
(
ptr
=
(
TABLE_LIST
*
)
thd
->
calloc
(
sizeof
(
TABLE_LIST
))))
DBUG_RETURN
(
0
);
/* purecov: inspected */
ptr
->
db
=
table
->
db
.
str
?
table
->
db
.
str
:
(
thd
->
db
?
thd
->
db
:
(
char
*
)
""
);
if
(
table
->
db
.
str
)
{
ptr
->
db
=
table
->
db
.
str
;
ptr
->
db_length
=
table
->
db
.
length
;
}
else
if
(
thd
->
db
)
{
ptr
->
db
=
thd
->
db
;
ptr
->
db_length
=
thd
->
db_length
;
}
else
{
ptr
->
db
=
(
char
*
)
""
;
ptr
->
db_length
=
0
;
}
ptr
->
name
=
alias_str
;
if
(
lower_case_table_names
)
{
...
...
@@ -3116,6 +3143,7 @@ TABLE_LIST *add_table_to_list(Table_ident *table, LEX_STRING *alias,
casedn_str
(
table
->
table
.
str
);
}
ptr
->
real_name
=
table
->
table
.
str
;
ptr
->
real_name_length
=
table
->
table
.
length
;
ptr
->
lock_type
=
flags
;
ptr
->
updating
=
updating
;
if
(
use_index
)
...
...
sql/sql_table.cc
View file @
63b2a551
...
...
@@ -161,7 +161,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
}
if
(
some_tables_deleted
)
{
query_cache
.
invalidate
(
t
ables
);
query_cache
.
invalidate
(
t
hd
,
tables
,
0
);
if
(
!
dont_log_query
)
{
mysql_update_log
.
write
(
thd
,
thd
->
query
,
thd
->
query_length
);
...
...
@@ -1774,7 +1774,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
VOID
(
pthread_cond_broadcast
(
&
COND_refresh
));
VOID
(
pthread_mutex_unlock
(
&
LOCK_open
));
table_list
->
table
=
0
;
// For query cache
query_cache
.
invalidate
(
t
able_list
);
query_cache
.
invalidate
(
t
hd
,
table_list
,
0
);
end_temporary:
sprintf
(
tmp_name
,
ER
(
ER_INSERT_INFO
),(
ulong
)
(
copied
+
deleted
),
...
...
sql/sql_update.cc
View file @
63b2a551
...
...
@@ -324,7 +324,8 @@ int mysql_update(THD *thd,
thd
->
lock
=
0
;
}
if
(
updated
)
query_cache
.
invalidate
(
table_list
);
query_cache
.
invalidate
(
thd
,
table_list
,
1
);
delete
select
;
if
(
error
>=
0
)
send_error
(
&
thd
->
net
,
thd
->
killed
?
ER_SERVER_SHUTDOWN
:
0
);
/* purecov: inspected */
...
...
@@ -787,7 +788,8 @@ bool multi_update::send_eof()
sprintf
(
buff
,
ER
(
ER_UPDATE_INFO
),
(
long
)
found
,
(
long
)
updated
,
(
long
)
thd
->
cuted_fields
);
if
(
updated
)
query_cache
.
invalidate
(
update_tables
);
query_cache
.
invalidate
(
thd
,
update_tables
,
1
);
::
send_ok
(
&
thd
->
net
,
(
thd
->
client_capabilities
&
CLIENT_FOUND_ROWS
)
?
found
:
updated
,
thd
->
insert_id_used
?
thd
->
insert_id
()
:
0L
,
buff
);
...
...
sql/table.h
View file @
63b2a551
...
...
@@ -137,6 +137,7 @@ struct st_table {
typedef
struct
st_table_list
{
struct
st_table_list
*
next
;
char
*
db
,
*
name
,
*
real_name
;
uint32
db_length
,
real_name_length
;
Item
*
on_expr
;
/* Used with outer join */
struct
st_table_list
*
natural_join
;
/* natural join on this table*/
List
<
String
>
*
use_index
,
*
ignore_index
;
...
...
@@ -149,6 +150,12 @@ typedef struct st_table_list {
bool
shared
;
/* Used twice in union */
}
TABLE_LIST
;
typedef
struct
st_changed_table_list
{
struct
st_changed_table_list
*
next
;
char
*
key
,
*
table_name
;
uint32
key_length
;
}
CHANGED_TABLE_LIST
;
typedef
struct
st_open_table_list
{
struct
st_open_table_list
*
next
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment