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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
6dbc48ca
Commit
6dbc48ca
authored
Dec 28, 2014
by
Sergey Vojtovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-7324 - Lock-free hash for table definition cache
parent
8883c54a
Changes
22
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
22 changed files
with
889 additions
and
751 deletions
+889
-751
include/lf.h
include/lf.h
+3
-0
mysql-test/r/ps.result
mysql-test/r/ps.result
+8
-8
mysql-test/r/show_check.result
mysql-test/r/show_check.result
+1
-1
mysql-test/suite/perfschema/r/dml_setup_instruments.result
mysql-test/suite/perfschema/r/dml_setup_instruments.result
+1
-1
mysql-test/suite/perfschema/r/func_mutex.result
mysql-test/suite/perfschema/r/func_mutex.result
+7
-7
mysql-test/suite/perfschema/t/func_mutex.test
mysql-test/suite/perfschema/t/func_mutex.test
+6
-6
mysql-test/t/ps.test
mysql-test/t/ps.test
+15
-0
mysql-test/t/show_check.test
mysql-test/t/show_check.test
+3
-0
mysys/lf_hash.c
mysys/lf_hash.c
+12
-4
sql/handler.cc
sql/handler.cc
+4
-4
sql/mysqld.cc
sql/mysqld.cc
+2
-1
sql/sql_base.cc
sql/sql_base.cc
+164
-121
sql/sql_base.h
sql/sql_base.h
+1
-1
sql/sql_class.cc
sql/sql_class.cc
+4
-1
sql/sql_class.h
sql/sql_class.h
+2
-0
sql/sql_handler.cc
sql/sql_handler.cc
+1
-1
sql/sql_insert.cc
sql/sql_insert.cc
+1
-1
sql/sql_test.cc
sql/sql_test.cc
+23
-21
sql/table.cc
sql/table.cc
+20
-32
sql/table.h
sql/table.h
+2
-26
sql/table_cache.cc
sql/table_cache.cc
+444
-500
sql/table_cache.h
sql/table_cache.h
+165
-15
No files found.
include/lf.h
View file @
6dbc48ca
...
...
@@ -231,6 +231,9 @@ void lf_hash_init(LF_HASH *hash, uint element_size, uint flags,
void
lf_hash_destroy
(
LF_HASH
*
hash
);
int
lf_hash_insert
(
LF_HASH
*
hash
,
LF_PINS
*
pins
,
const
void
*
data
);
void
*
lf_hash_search
(
LF_HASH
*
hash
,
LF_PINS
*
pins
,
const
void
*
key
,
uint
keylen
);
void
*
lf_hash_search_using_hash_value
(
LF_HASH
*
hash
,
LF_PINS
*
pins
,
my_hash_value_type
hash_value
,
const
void
*
key
,
uint
keylen
);
int
lf_hash_delete
(
LF_HASH
*
hash
,
LF_PINS
*
pins
,
const
void
*
key
,
uint
keylen
);
int
lf_hash_iterate
(
LF_HASH
*
hash
,
LF_PINS
*
pins
,
my_hash_walk_action
action
,
void
*
argument
);
...
...
mysql-test/r/ps.result
View file @
6dbc48ca
...
...
@@ -2119,9 +2119,9 @@ select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
mysql user 0 0
mysql general_log 0 0
mysql host 0 0
mysql user 0 0
call proc_1();
show open tables from mysql;
Database Table In_use Name_locked
...
...
@@ -2132,9 +2132,9 @@ select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
mysql user 0 0
mysql general_log 0 0
mysql host 0 0
mysql user 0 0
call proc_1();
show open tables from mysql;
Database Table In_use Name_locked
...
...
@@ -2145,9 +2145,9 @@ select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
mysql user 0 0
mysql general_log 0 0
mysql host 0 0
mysql user 0 0
call proc_1();
show open tables from mysql;
Database Table In_use Name_locked
...
...
@@ -2158,9 +2158,9 @@ select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
mysql user 0 0
mysql general_log 0 0
mysql host 0 0
mysql user 0 0
flush tables;
create function func_1() returns int begin flush tables; return 1; end|
ERROR 0A000: FLUSH is not allowed in stored function or trigger
...
...
@@ -2176,9 +2176,9 @@ select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
mysql user 0 0
mysql general_log 0 0
mysql host 0 0
mysql user 0 0
prepare abc from "flush tables";
execute abc;
show open tables from mysql;
...
...
@@ -2190,9 +2190,9 @@ select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
mysql user 0 0
mysql general_log 0 0
mysql host 0 0
mysql user 0 0
execute abc;
show open tables from mysql;
Database Table In_use Name_locked
...
...
@@ -2203,9 +2203,9 @@ select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
mysql user 0 0
mysql general_log 0 0
mysql host 0 0
mysql user 0 0
execute abc;
show open tables from mysql;
Database Table In_use Name_locked
...
...
@@ -2216,9 +2216,9 @@ select Host, Db from mysql.host limit 0;
Host Db
show open tables from mysql;
Database Table In_use Name_locked
mysql user 0 0
mysql general_log 0 0
mysql host 0 0
mysql user 0 0
flush tables;
deallocate prepare abc;
create procedure proc_1() flush logs;
...
...
mysql-test/r/show_check.result
View file @
6dbc48ca
...
...
@@ -259,8 +259,8 @@ create table t1(n int);
insert into t1 values (1);
show open tables;
Database Table In_use Name_locked
test t1 0 0
mysql general_log 0 0
test t1 0 0
drop table t1;
create table t1 (a int not null, b VARCHAR(10), INDEX (b) ) AVG_ROW_LENGTH=10 CHECKSUM=1 COMMENT="test" ENGINE=MYISAM MIN_ROWS=10 MAX_ROWS=100 PACK_KEYS=1 DELAY_KEY_WRITE=1 ROW_FORMAT=fixed;
show create table t1;
...
...
mysql-test/suite/perfschema/r/dml_setup_instruments.result
View file @
6dbc48ca
...
...
@@ -24,11 +24,11 @@ wait/synch/rwlock/sql/LOCK_grant YES YES
wait/synch/rwlock/sql/LOCK_system_variables_hash YES YES
wait/synch/rwlock/sql/LOCK_sys_init_connect YES YES
wait/synch/rwlock/sql/LOCK_sys_init_slave YES YES
wait/synch/rwlock/sql/LOCK_tdc YES YES
wait/synch/rwlock/sql/LOGGER::LOCK_logger YES YES
wait/synch/rwlock/sql/MDL_context::LOCK_waiting_for YES YES
wait/synch/rwlock/sql/MDL_lock::rwlock YES YES
wait/synch/rwlock/sql/Query_cache_query::lock YES YES
wait/synch/rwlock/sql/THR_LOCK_servers YES YES
select * from performance_schema.setup_instruments
where name like 'Wait/Synch/Cond/sql/%'
and name not in (
...
...
mysql-test/suite/perfschema/r/func_mutex.result
View file @
6dbc48ca
...
...
@@ -5,9 +5,9 @@ WHERE name LIKE 'wait/synch/mutex/%'
truncate table performance_schema.events_statements_summary_by_digest;
flush status;
select NAME from performance_schema.mutex_instances
where NAME = 'wait/synch/mutex/
sql/TABLE_SHARE::tdc.LOCK_table_share
' GROUP BY NAME;
where NAME = 'wait/synch/mutex/
mysys/THR_LOCK::mutex
' GROUP BY NAME;
NAME
wait/synch/mutex/
sql/TABLE_SHARE::tdc.LOCK_table_share
wait/synch/mutex/
mysys/THR_LOCK::mutex
select NAME from performance_schema.rwlock_instances
where NAME = 'wait/synch/rwlock/sql/LOCK_grant';
NAME
...
...
@@ -24,7 +24,7 @@ id b
1 initial value
SET @before_count = (SELECT SUM(TIMER_WAIT)
FROM performance_schema.events_waits_history_long
WHERE (EVENT_NAME = 'wait/synch/mutex/
sql/TABLE_SHARE::tdc.LOCK_table_share
'));
WHERE (EVENT_NAME = 'wait/synch/mutex/
mysys/THR_LOCK::mutex
'));
SELECT * FROM t1;
id b
1 initial value
...
...
@@ -37,12 +37,12 @@ id b
8 initial value
SET @after_count = (SELECT SUM(TIMER_WAIT)
FROM performance_schema.events_waits_history_long
WHERE (EVENT_NAME = 'wait/synch/mutex/
sql/TABLE_SHARE::tdc.LOCK_table_share
'));
WHERE (EVENT_NAME = 'wait/synch/mutex/
mysys/THR_LOCK::mutex
'));
SELECT IF((@after_count - @before_count) > 0, 'Success', 'Failure') test_fm1_timed;
test_fm1_timed
Success
UPDATE performance_schema.setup_instruments SET enabled = 'NO'
WHERE NAME = 'wait/synch/mutex/
sql/TABLE_SHARE::tdc.LOCK_table_share
';
WHERE NAME = 'wait/synch/mutex/
mysys/THR_LOCK::mutex
';
TRUNCATE TABLE performance_schema.events_waits_history_long;
TRUNCATE TABLE performance_schema.events_waits_history;
TRUNCATE TABLE performance_schema.events_waits_current;
...
...
@@ -51,7 +51,7 @@ id b
1 initial value
SET @before_count = (SELECT SUM(TIMER_WAIT)
FROM performance_schema.events_waits_history_long
WHERE (EVENT_NAME = 'wait/synch/mutex/
sql/TABLE_SHARE::tdc.LOCK_table_share
'));
WHERE (EVENT_NAME = 'wait/synch/mutex/
mysys/THR_LOCK::mutex
'));
SELECT * FROM t1;
id b
1 initial value
...
...
@@ -64,7 +64,7 @@ id b
8 initial value
SET @after_count = (SELECT SUM(TIMER_WAIT)
FROM performance_schema.events_waits_history_long
WHERE (EVENT_NAME = 'wait/synch/mutex/
sql/TABLE_SHARE::tdc.LOCK_table_share
'));
WHERE (EVENT_NAME = 'wait/synch/mutex/
mysys/THR_LOCK::mutex
'));
SELECT IF((COALESCE(@after_count, 0) - COALESCE(@before_count, 0)) = 0, 'Success', 'Failure') test_fm2_timed;
test_fm2_timed
Success
...
...
mysql-test/suite/perfschema/t/func_mutex.test
View file @
6dbc48ca
...
...
@@ -19,7 +19,7 @@ flush status;
# Make sure objects are instrumented
select
NAME
from
performance_schema
.
mutex_instances
where
NAME
=
'wait/synch/mutex/
sql/TABLE_SHARE::tdc.LOCK_table_share
'
GROUP
BY
NAME
;
where
NAME
=
'wait/synch/mutex/
mysys/THR_LOCK::mutex
'
GROUP
BY
NAME
;
select
NAME
from
performance_schema
.
rwlock_instances
where
NAME
=
'wait/synch/rwlock/sql/LOCK_grant'
;
...
...
@@ -49,18 +49,18 @@ SELECT * FROM t1 WHERE id = 1;
SET
@
before_count
=
(
SELECT
SUM
(
TIMER_WAIT
)
FROM
performance_schema
.
events_waits_history_long
WHERE
(
EVENT_NAME
=
'wait/synch/mutex/
sql/TABLE_SHARE::tdc.LOCK_table_share
'
));
WHERE
(
EVENT_NAME
=
'wait/synch/mutex/
mysys/THR_LOCK::mutex
'
));
SELECT
*
FROM
t1
;
SET
@
after_count
=
(
SELECT
SUM
(
TIMER_WAIT
)
FROM
performance_schema
.
events_waits_history_long
WHERE
(
EVENT_NAME
=
'wait/synch/mutex/
sql/TABLE_SHARE::tdc.LOCK_table_share
'
));
WHERE
(
EVENT_NAME
=
'wait/synch/mutex/
mysys/THR_LOCK::mutex
'
));
SELECT
IF
((
@
after_count
-
@
before_count
)
>
0
,
'Success'
,
'Failure'
)
test_fm1_timed
;
UPDATE
performance_schema
.
setup_instruments
SET
enabled
=
'NO'
WHERE
NAME
=
'wait/synch/mutex/
sql/TABLE_SHARE::tdc.LOCK_table_share
'
;
WHERE
NAME
=
'wait/synch/mutex/
mysys/THR_LOCK::mutex
'
;
TRUNCATE
TABLE
performance_schema
.
events_waits_history_long
;
TRUNCATE
TABLE
performance_schema
.
events_waits_history
;
...
...
@@ -70,13 +70,13 @@ SELECT * FROM t1 WHERE id = 1;
SET
@
before_count
=
(
SELECT
SUM
(
TIMER_WAIT
)
FROM
performance_schema
.
events_waits_history_long
WHERE
(
EVENT_NAME
=
'wait/synch/mutex/
sql/TABLE_SHARE::tdc.LOCK_table_share
'
));
WHERE
(
EVENT_NAME
=
'wait/synch/mutex/
mysys/THR_LOCK::mutex
'
));
SELECT
*
FROM
t1
;
SET
@
after_count
=
(
SELECT
SUM
(
TIMER_WAIT
)
FROM
performance_schema
.
events_waits_history_long
WHERE
(
EVENT_NAME
=
'wait/synch/mutex/
sql/TABLE_SHARE::tdc.LOCK_table_share
'
));
WHERE
(
EVENT_NAME
=
'wait/synch/mutex/
mysys/THR_LOCK::mutex
'
));
SELECT
IF
((
COALESCE
(
@
after_count
,
0
)
-
COALESCE
(
@
before_count
,
0
))
=
0
,
'Success'
,
'Failure'
)
test_fm2_timed
;
...
...
mysql-test/t/ps.test
View file @
6dbc48ca
...
...
@@ -2224,24 +2224,32 @@ deallocate prepare abc;
create
procedure
proc_1
()
flush
tables
;
flush
tables
;
--
sorted_result
show
open
tables
from
mysql
;
select
Host
,
User
from
mysql
.
user
limit
0
;
select
Host
,
Db
from
mysql
.
host
limit
0
;
--
sorted_result
show
open
tables
from
mysql
;
call
proc_1
();
--
sorted_result
show
open
tables
from
mysql
;
select
Host
,
User
from
mysql
.
user
limit
0
;
select
Host
,
Db
from
mysql
.
host
limit
0
;
--
sorted_result
show
open
tables
from
mysql
;
call
proc_1
();
--
sorted_result
show
open
tables
from
mysql
;
select
Host
,
User
from
mysql
.
user
limit
0
;
select
Host
,
Db
from
mysql
.
host
limit
0
;
--
sorted_result
show
open
tables
from
mysql
;
call
proc_1
();
--
sorted_result
show
open
tables
from
mysql
;
select
Host
,
User
from
mysql
.
user
limit
0
;
select
Host
,
Db
from
mysql
.
host
limit
0
;
--
sorted_result
show
open
tables
from
mysql
;
flush
tables
;
delimiter
|
;
...
...
@@ -2261,24 +2269,31 @@ drop procedure proc_1;
flush
tables
;
select
Host
,
User
from
mysql
.
user
limit
0
;
select
Host
,
Db
from
mysql
.
host
limit
0
;
--
sorted_result
show
open
tables
from
mysql
;
--
enable_ps_protocol
prepare
abc
from
"flush tables"
;
execute
abc
;
--
sorted_result
show
open
tables
from
mysql
;
select
Host
,
User
from
mysql
.
user
limit
0
;
select
Host
,
Db
from
mysql
.
host
limit
0
;
--
sorted_result
show
open
tables
from
mysql
;
execute
abc
;
--
sorted_result
show
open
tables
from
mysql
;
select
Host
,
User
from
mysql
.
user
limit
0
;
select
Host
,
Db
from
mysql
.
host
limit
0
;
--
sorted_result
show
open
tables
from
mysql
;
execute
abc
;
--
sorted_result
show
open
tables
from
mysql
;
select
Host
,
User
from
mysql
.
user
limit
0
;
select
Host
,
Db
from
mysql
.
host
limit
0
;
--
sorted_result
show
open
tables
from
mysql
;
flush
tables
;
deallocate
prepare
abc
;
...
...
mysql-test/t/show_check.test
View file @
6dbc48ca
...
...
@@ -135,9 +135,11 @@ show create table t1;
drop
table
t1
;
flush
tables
;
--
sorted_result
show
open
tables
;
create
table
t1
(
n
int
);
insert
into
t1
values
(
1
);
--
sorted_result
show
open
tables
;
drop
table
t1
;
...
...
@@ -617,6 +619,7 @@ show databases;
show
tables
;
show
events
;
show
table
status
;
--
sorted_result
show
open
tables
;
show
plugins
;
show
columns
in
t1
;
...
...
mysys/lf_hash.c
View file @
6dbc48ca
...
...
@@ -122,7 +122,7 @@ retry:
{
if
(
unlikely
(
callback
))
{
if
(
callback
(
cursor
->
curr
+
1
,
(
void
*
)
key
))
if
(
c
ur_hashnr
&
1
&&
c
allback
(
cursor
->
curr
+
1
,
(
void
*
)
key
))
return
1
;
}
else
if
(
cur_hashnr
>=
hashnr
)
...
...
@@ -467,12 +467,13 @@ int lf_hash_delete(LF_HASH *hash, LF_PINS *pins, const void *key, uint keylen)
NOTE
see lsearch() for pin usage notes
*/
void
*
lf_hash_search
(
LF_HASH
*
hash
,
LF_PINS
*
pins
,
const
void
*
key
,
uint
keylen
)
void
*
lf_hash_search_using_hash_value
(
LF_HASH
*
hash
,
LF_PINS
*
pins
,
my_hash_value_type
hashnr
,
const
void
*
key
,
uint
keylen
)
{
LF_SLIST
*
volatile
*
el
,
*
found
;
uint
bucket
,
hashnr
=
calc_hash
(
hash
,
(
uchar
*
)
key
,
keylen
)
;
uint
bucket
=
hashnr
%
hash
->
size
;
bucket
=
hashnr
%
hash
->
size
;
lf_rwlock_by_pins
(
pins
);
el
=
_lf_dynarray_lvalue
(
&
hash
->
array
,
bucket
);
if
(
unlikely
(
!
el
))
...
...
@@ -521,6 +522,13 @@ int lf_hash_iterate(LF_HASH *hash, LF_PINS *pins,
return
res
;
}
void
*
lf_hash_search
(
LF_HASH
*
hash
,
LF_PINS
*
pins
,
const
void
*
key
,
uint
keylen
)
{
return
lf_hash_search_using_hash_value
(
hash
,
pins
,
calc_hash
(
hash
,
(
uchar
*
)
key
,
keylen
),
key
,
keylen
);
}
static
const
uchar
*
dummy_key
=
(
uchar
*
)
""
;
/*
...
...
sql/handler.cc
View file @
6dbc48ca
...
...
@@ -5001,12 +5001,12 @@ bool ha_table_exists(THD *thd, const char *db, const char *table_name,
else
if
(
engines_with_discover
)
hton
=
&
dummy
;
T
ABLE_SHARE
*
share
=
tdc_lock_share
(
db
,
table_name
);
if
(
share
)
T
DC_element
*
element
=
tdc_lock_share
(
thd
,
db
,
table_name
);
if
(
element
&&
element
!=
MY_ERRPTR
)
{
if
(
hton
)
*
hton
=
share
->
db_type
();
tdc_unlock_share
(
share
);
*
hton
=
element
->
share
->
db_type
();
tdc_unlock_share
(
element
);
DBUG_RETURN
(
TRUE
);
}
...
...
sql/mysqld.cc
View file @
6dbc48ca
...
...
@@ -4789,7 +4789,8 @@ static int init_server_components()
all things are initialized so that unireg_abort() doesn't fail
*/
mdl_init
();
if
(
tdc_init
()
|
hostname_cache_init
())
tdc_init
();
if
(
hostname_cache_init
())
unireg_abort
(
1
);
query_cache_set_min_res_unit
(
query_cache_min_res_unit
);
...
...
sql/sql_base.cc
View file @
6dbc48ca
This diff is collapsed.
Click to expand it.
sql/sql_base.h
View file @
6dbc48ca
...
...
@@ -271,7 +271,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint counter, uint flags);
int
decide_logging_format
(
THD
*
thd
,
TABLE_LIST
*
tables
);
void
free_io_cache
(
TABLE
*
entry
);
void
intern_close_table
(
TABLE
*
entry
);
void
kill_delayed_threads_for_table
(
T
ABLE_SHARE
*
share
);
void
kill_delayed_threads_for_table
(
T
DC_element
*
element
);
void
close_thread_table
(
THD
*
thd
,
TABLE
**
table_ptr
);
bool
close_temporary_tables
(
THD
*
thd
);
TABLE_LIST
*
unique_table
(
THD
*
thd
,
TABLE_LIST
*
table
,
TABLE_LIST
*
table_list
,
...
...
sql/sql_class.cc
View file @
6dbc48ca
...
...
@@ -912,7 +912,8 @@ THD::THD(bool is_wsrep_applier)
#endif
/* defined(ENABLED_DEBUG_SYNC) */
wait_for_commit_ptr
(
0
),
main_da
(
0
,
false
,
false
),
m_stmt_da
(
&
main_da
)
m_stmt_da
(
&
main_da
),
tdc_hash_pins
(
0
)
#ifdef WITH_WSREP
,
wsrep_applier
(
is_wsrep_applier
),
...
...
@@ -1701,6 +1702,8 @@ THD::~THD()
free_root
(
&
main_mem_root
,
MYF
(
0
));
main_da
.
free_memory
();
if
(
tdc_hash_pins
)
lf_hash_put_pins
(
tdc_hash_pins
);
if
(
status_var
.
memory_used
!=
0
)
{
DBUG_PRINT
(
"error"
,
(
"memory_used: %lld"
,
status_var
.
memory_used
));
...
...
sql/sql_class.h
View file @
6dbc48ca
...
...
@@ -3769,6 +3769,8 @@ public:
(
rgi_slave
&&
rgi_have_temporary_tables
()));
}
LF_PINS
*
tdc_hash_pins
;
inline
ulong
wsrep_binlog_format
()
const
{
return
WSREP_FORMAT
(
variables
.
binlog_format
);
...
...
sql/sql_handler.cc
View file @
6dbc48ca
...
...
@@ -1134,7 +1134,7 @@ void mysql_ha_flush(THD *thd)
((
hash_tables
->
table
->
mdl_ticket
&&
hash_tables
->
table
->
mdl_ticket
->
has_pending_conflicting_lock
())
||
(
!
hash_tables
->
table
->
s
->
tmp_table
&&
hash_tables
->
table
->
s
->
tdc
.
flushed
)))
hash_tables
->
table
->
s
->
tdc
->
flushed
)))
mysql_ha_close_table
(
hash_tables
);
}
...
...
sql/sql_insert.cc
View file @
6dbc48ca
...
...
@@ -3048,7 +3048,7 @@ bool Delayed_insert::handle_inserts(void)
THD_STAGE_INFO
(
&
thd
,
stage_insert
);
max_rows
=
delayed_insert_limit
;
if
(
thd
.
killed
||
table
->
s
->
tdc
.
flushed
)
if
(
thd
.
killed
||
table
->
s
->
tdc
->
flushed
)
{
thd
.
killed
=
KILL_SYSTEM_THREAD
;
max_rows
=
ULONG_MAX
;
// Do as much as possible
...
...
sql/sql_test.cc
View file @
6dbc48ca
...
...
@@ -76,35 +76,37 @@ print_where(COND *cond,const char *info, enum_query_type query_type)
/* This is for debugging purposes */
static
void
print_cached_tables
(
void
)
static
my_bool
print_cached_tables_callback
(
TDC_element
*
element
,
void
*
arg
__attribute__
((
unused
)))
{
TABLE_SHARE
*
share
;
TABLE
*
entry
;
TDC_iterator
tdc_it
;
compile_time_assert
(
TL_WRITE_ONLY
+
1
==
array_elements
(
lock_descriptions
));
/* purecov: begin tested */
puts
(
"DB Table Version Thread Open Lock"
);
tdc_it
.
init
();
while
((
share
=
tdc_it
.
next
()))
{
mysql_mutex_lock
(
&
share
->
tdc
.
LOCK_table_share
);
TABLE_SHARE
::
All_share_tables_list
::
Iterator
it
(
share
->
tdc
.
all_tables
);
mysql_mutex_lock
(
&
element
->
LOCK_table_share
);
TDC_element
::
All_share_tables_list
::
Iterator
it
(
element
->
all_tables
);
while
((
entry
=
it
++
))
{
THD
*
in_use
=
entry
->
in_use
;
printf
(
"%-14.14s %-32s%6ld%8ld%6d %s
\n
"
,
entry
->
s
->
db
.
str
,
entry
->
s
->
table_name
.
str
,
entry
->
s
->
tdc
.
version
,
entry
->
s
->
db
.
str
,
entry
->
s
->
table_name
.
str
,
element
->
version
,
in_use
?
in_use
->
thread_id
:
0
,
entry
->
db_stat
?
1
:
0
,
in_use
?
lock_descriptions
[(
int
)
entry
->
reginfo
.
lock_type
]
:
"Not in use"
);
}
mysql_mutex_unlock
(
&
share
->
tdc
.
LOCK_table_share
);
}
tdc_it
.
deinit
();
mysql_mutex_unlock
(
&
element
->
LOCK_table_share
);
return
FALSE
;
}
static
void
print_cached_tables
(
void
)
{
compile_time_assert
(
TL_WRITE_ONLY
+
1
==
array_elements
(
lock_descriptions
));
/* purecov: begin tested */
puts
(
"DB Table Version Thread Open Lock"
);
tdc_iterate
(
0
,
(
my_hash_walk_action
)
print_cached_tables_callback
,
NULL
,
true
);
printf
(
"
\n
Current refresh version: %ld
\n
"
,
tdc_refresh_version
());
fflush
(
stdout
);
/* purecov: end */
...
...
sql/table.cc
View file @
6dbc48ca
...
...
@@ -325,7 +325,7 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name,
&
share
->
LOCK_share
,
MY_MUTEX_INIT_SLOW
);
mysql_mutex_init
(
key_TABLE_SHARE_LOCK_ha_data
,
&
share
->
LOCK_ha_data
,
MY_MUTEX_INIT_FAST
);
tdc_
init_share
(
share
);
tdc_
assign_new_table_id
(
share
);
}
DBUG_RETURN
(
share
);
}
...
...
@@ -422,7 +422,6 @@ void TABLE_SHARE::destroy()
{
mysql_mutex_destroy
(
&
LOCK_share
);
mysql_mutex_destroy
(
&
LOCK_ha_data
);
tdc_deinit_share
(
this
);
}
my_hash_free
(
&
name_hash
);
...
...
@@ -3866,11 +3865,11 @@ bool TABLE_SHARE::visit_subgraph(Wait_for_flush *wait_for_flush,
because we won't try to acquire tdc.LOCK_table_share while
holding a write-lock on MDL_lock::m_rwlock.
*/
mysql_mutex_lock
(
&
tdc
.
LOCK_table_share
);
tdc
.
all_tables_refs
++
;
mysql_mutex_unlock
(
&
tdc
.
LOCK_table_share
);
mysql_mutex_lock
(
&
tdc
->
LOCK_table_share
);
tdc
->
all_tables_refs
++
;
mysql_mutex_unlock
(
&
tdc
->
LOCK_table_share
);
All_share_tables_list
::
Iterator
tables_it
(
tdc
.
all_tables
);
TDC_element
::
All_share_tables_list
::
Iterator
tables_it
(
tdc
->
all_tables
);
/*
In case of multiple searches running in parallel, avoid going
...
...
@@ -3888,7 +3887,7 @@ bool TABLE_SHARE::visit_subgraph(Wait_for_flush *wait_for_flush,
while
((
table
=
tables_it
++
))
{
DBUG_ASSERT
(
table
->
in_use
&&
tdc
.
flushed
);
DBUG_ASSERT
(
table
->
in_use
&&
tdc
->
flushed
);
if
(
gvisitor
->
inspect_edge
(
&
table
->
in_use
->
mdl_context
))
{
goto
end_leave_node
;
...
...
@@ -3898,7 +3897,7 @@ bool TABLE_SHARE::visit_subgraph(Wait_for_flush *wait_for_flush,
tables_it
.
rewind
();
while
((
table
=
tables_it
++
))
{
DBUG_ASSERT
(
table
->
in_use
&&
tdc
.
flushed
);
DBUG_ASSERT
(
table
->
in_use
&&
tdc
->
flushed
);
if
(
table
->
in_use
->
mdl_context
.
visit_subgraph
(
gvisitor
))
{
goto
end_leave_node
;
...
...
@@ -3911,10 +3910,10 @@ end_leave_node:
gvisitor
->
leave_node
(
src_ctx
);
end:
mysql_mutex_lock
(
&
tdc
.
LOCK_table_share
);
if
(
!--
tdc
.
all_tables_refs
)
mysql_cond_broadcast
(
&
tdc
.
COND_release
);
mysql_mutex_unlock
(
&
tdc
.
LOCK_table_share
);
mysql_mutex_lock
(
&
tdc
->
LOCK_table_share
);
if
(
!--
tdc
->
all_tables_refs
)
mysql_cond_broadcast
(
&
tdc
->
COND_release
);
mysql_mutex_unlock
(
&
tdc
->
LOCK_table_share
);
return
result
;
}
...
...
@@ -3949,14 +3948,14 @@ bool TABLE_SHARE::wait_for_old_version(THD *thd, struct timespec *abstime,
Wait_for_flush
ticket
(
mdl_context
,
this
,
deadlock_weight
);
MDL_wait
::
enum_wait_status
wait_status
;
mysql_mutex_assert_owner
(
&
tdc
.
LOCK_table_share
);
DBUG_ASSERT
(
tdc
.
flushed
);
mysql_mutex_assert_owner
(
&
tdc
->
LOCK_table_share
);
DBUG_ASSERT
(
tdc
->
flushed
);
tdc
.
m_flush_tickets
.
push_front
(
&
ticket
);
tdc
->
m_flush_tickets
.
push_front
(
&
ticket
);
mdl_context
->
m_wait
.
reset_status
();
mysql_mutex_unlock
(
&
tdc
.
LOCK_table_share
);
mysql_mutex_unlock
(
&
tdc
->
LOCK_table_share
);
mdl_context
->
will_wait_for
(
&
ticket
);
...
...
@@ -3967,21 +3966,10 @@ bool TABLE_SHARE::wait_for_old_version(THD *thd, struct timespec *abstime,
mdl_context
->
done_waiting_for
();
mysql_mutex_lock
(
&
tdc
.
LOCK_table_share
);
tdc
.
m_flush_tickets
.
remove
(
&
ticket
);
if
(
tdc
.
m_flush_tickets
.
is_empty
()
&&
tdc
.
ref_count
==
0
)
{
/*
If our thread was the last one using the share,
we must destroy it here.
*/
mysql_mutex_unlock
(
&
tdc
.
LOCK_table_share
);
destroy
();
}
else
mysql_mutex_unlock
(
&
tdc
.
LOCK_table_share
);
mysql_mutex_lock
(
&
tdc
->
LOCK_table_share
);
tdc
->
m_flush_tickets
.
remove
(
&
ticket
);
mysql_cond_broadcast
(
&
tdc
->
COND_release
);
mysql_mutex_unlock
(
&
tdc
->
LOCK_table_share
);
/*
...
...
@@ -4027,7 +4015,7 @@ bool TABLE_SHARE::wait_for_old_version(THD *thd, struct timespec *abstime,
void
TABLE
::
init
(
THD
*
thd
,
TABLE_LIST
*
tl
)
{
DBUG_ASSERT
(
s
->
t
dc
.
ref_count
>
0
||
s
->
tmp_table
!=
NO_TMP_TABLE
);
DBUG_ASSERT
(
s
->
t
mp_table
!=
NO_TMP_TABLE
||
s
->
tdc
->
ref_count
>
0
);
if
(
thd
->
lex
->
need_correct_ident
())
alias_name_used
=
my_strcasecmp
(
table_alias_charset
,
...
...
sql/table.h
View file @
6dbc48ca
...
...
@@ -47,6 +47,7 @@ class ACL_internal_schema_access;
class
ACL_internal_table_access
;
class
Field
;
class
Table_statistics
;
class
TDC_element
;
/*
Used to identify NESTED_JOIN structures within a join (applicable only to
...
...
@@ -611,32 +612,7 @@ struct TABLE_SHARE
mysql_mutex_t
LOCK_ha_data
;
/* To protect access to ha_data */
mysql_mutex_t
LOCK_share
;
/* To protect TABLE_SHARE */
typedef
I_P_List
<
TABLE
,
TABLE_share
>
TABLE_list
;
typedef
I_P_List
<
TABLE
,
All_share_tables
>
All_share_tables_list
;
struct
{
/**
Protects ref_count, m_flush_tickets, all_tables, free_tables, flushed,
all_tables_refs.
*/
mysql_mutex_t
LOCK_table_share
;
mysql_cond_t
COND_release
;
TABLE_SHARE
*
next
,
**
prev
;
/* Link to unused shares */
uint
ref_count
;
/* How many TABLE objects uses this */
uint
all_tables_refs
;
/* Number of refs to all_tables */
/**
List of tickets representing threads waiting for the share to be flushed.
*/
Wait_for_flush_list
m_flush_tickets
;
/*
Doubly-linked (back-linked) lists of used and unused TABLE objects
for this share.
*/
All_share_tables_list
all_tables
;
TABLE_list
free_tables
;
ulong
version
;
bool
flushed
;
}
tdc
;
TDC_element
*
tdc
;
LEX_CUSTRING
tabledef_version
;
...
...
sql/table_cache.cc
View file @
6dbc48ca
This diff is collapsed.
Click to expand it.
sql/table_cache.h
View file @
6dbc48ca
...
...
@@ -16,6 +16,165 @@
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
extern
PSI_mutex_key
key_TABLE_SHARE_LOCK_table_share
;
extern
PSI_cond_key
key_TABLE_SHARE_COND_release
;
class
TDC_element
{
public:
uchar
m_key
[
NAME_LEN
+
1
+
NAME_LEN
+
1
];
uint
m_key_length
;
ulong
version
;
bool
flushed
;
TABLE_SHARE
*
share
;
typedef
I_P_List
<
TABLE
,
TABLE_share
>
TABLE_list
;
typedef
I_P_List
<
TABLE
,
All_share_tables
>
All_share_tables_list
;
/**
Protects ref_count, m_flush_tickets, all_tables, free_tables, flushed,
all_tables_refs.
*/
mysql_mutex_t
LOCK_table_share
;
mysql_cond_t
COND_release
;
TDC_element
*
next
,
**
prev
;
/* Link to unused shares */
uint
ref_count
;
/* How many TABLE objects uses this */
uint
all_tables_refs
;
/* Number of refs to all_tables */
/**
List of tickets representing threads waiting for the share to be flushed.
*/
Wait_for_flush_list
m_flush_tickets
;
/*
Doubly-linked (back-linked) lists of used and unused TABLE objects
for this share.
*/
All_share_tables_list
all_tables
;
TABLE_list
free_tables
;
TDC_element
()
{}
TDC_element
(
const
char
*
key
,
uint
key_length
)
:
m_key_length
(
key_length
)
{
memcpy
(
m_key
,
key
,
key_length
);
}
void
assert_clean_share
()
{
DBUG_ASSERT
(
share
==
0
);
DBUG_ASSERT
(
ref_count
==
0
);
DBUG_ASSERT
(
m_flush_tickets
.
is_empty
());
DBUG_ASSERT
(
all_tables
.
is_empty
());
DBUG_ASSERT
(
free_tables
.
is_empty
());
DBUG_ASSERT
(
all_tables_refs
==
0
);
DBUG_ASSERT
(
next
==
0
);
DBUG_ASSERT
(
prev
==
0
);
}
/**
Acquire TABLE object from table cache.
@pre share must be protected against removal.
Acquired object cannot be evicted or acquired again.
@return TABLE object, or NULL if no unused objects.
*/
TABLE
*
acquire_table
(
THD
*
thd
)
{
TABLE
*
table
;
mysql_mutex_lock
(
&
LOCK_table_share
);
table
=
free_tables
.
pop_front
();
if
(
table
)
{
DBUG_ASSERT
(
!
table
->
in_use
);
table
->
in_use
=
thd
;
/* The ex-unused table must be fully functional. */
DBUG_ASSERT
(
table
->
db_stat
&&
table
->
file
);
/* The children must be detached from the table. */
DBUG_ASSERT
(
!
table
->
file
->
extra
(
HA_EXTRA_IS_ATTACHED_CHILDREN
));
}
mysql_mutex_unlock
(
&
LOCK_table_share
);
return
table
;
}
/**
Get last element of free_tables.
*/
TABLE
*
free_tables_back
()
{
TABLE_list
::
Iterator
it
(
share
->
tdc
->
free_tables
);
TABLE
*
entry
,
*
last
=
0
;
while
((
entry
=
it
++
))
last
=
entry
;
return
last
;
}
/**
Wait for MDL deadlock detector to complete traversing tdc.all_tables.
Must be called before updating TABLE_SHARE::tdc.all_tables.
*/
void
wait_for_mdl_deadlock_detector
()
{
while
(
all_tables_refs
)
mysql_cond_wait
(
&
COND_release
,
&
LOCK_table_share
);
}
/**
Prepeare table share for use with table definition cache.
*/
static
void
lf_alloc_constructor
(
uchar
*
arg
)
{
TDC_element
*
element
=
(
TDC_element
*
)
(
arg
+
LF_HASH_OVERHEAD
);
DBUG_ENTER
(
"lf_alloc_constructor"
);
mysql_mutex_init
(
key_TABLE_SHARE_LOCK_table_share
,
&
element
->
LOCK_table_share
,
MY_MUTEX_INIT_FAST
);
mysql_cond_init
(
key_TABLE_SHARE_COND_release
,
&
element
->
COND_release
,
0
);
element
->
m_flush_tickets
.
empty
();
element
->
all_tables
.
empty
();
element
->
free_tables
.
empty
();
element
->
all_tables_refs
=
0
;
element
->
share
=
0
;
element
->
ref_count
=
0
;
element
->
next
=
0
;
element
->
prev
=
0
;
DBUG_VOID_RETURN
;
}
/**
Release table definition cache specific resources of table share.
*/
static
void
lf_alloc_destructor
(
uchar
*
arg
)
{
TDC_element
*
element
=
(
TDC_element
*
)
(
arg
+
LF_HASH_OVERHEAD
);
DBUG_ENTER
(
"lf_alloc_destructor"
);
element
->
assert_clean_share
();
mysql_cond_destroy
(
&
element
->
COND_release
);
mysql_mutex_destroy
(
&
element
->
LOCK_table_share
);
DBUG_VOID_RETURN
;
}
static
uchar
*
key
(
const
TDC_element
*
element
,
size_t
*
length
,
my_bool
not_used
__attribute__
((
unused
)))
{
*
length
=
element
->
m_key_length
;
return
(
uchar
*
)
element
->
m_key
;
}
};
enum
enum_tdc_remove_table_type
{
TDC_RT_REMOVE_ALL
,
...
...
@@ -27,15 +186,14 @@ enum enum_tdc_remove_table_type
extern
ulong
tdc_size
;
extern
ulong
tc_size
;
extern
int
tdc_init
(
void
);
extern
void
tdc_init
(
void
);
extern
void
tdc_start_shutdown
(
void
);
extern
void
tdc_deinit
(
void
);
extern
ulong
tdc_records
(
void
);
extern
void
tdc_purge
(
bool
all
);
extern
void
tdc_init_share
(
TABLE_SHARE
*
share
);
extern
void
tdc_deinit_share
(
TABLE_SHARE
*
share
);
extern
TABLE_SHARE
*
tdc_lock_share
(
const
char
*
db
,
const
char
*
table_name
);
extern
void
tdc_unlock_share
(
TABLE_SHARE
*
share
);
extern
TDC_element
*
tdc_lock_share
(
THD
*
thd
,
const
char
*
db
,
const
char
*
table_name
);
extern
void
tdc_unlock_share
(
TDC_element
*
element
);
extern
TABLE_SHARE
*
tdc_acquire_share
(
THD
*
thd
,
const
char
*
db
,
const
char
*
table_name
,
const
char
*
key
,
uint
key_length
,
...
...
@@ -52,6 +210,8 @@ extern int tdc_wait_for_old_version(THD *thd, const char *db,
extern
ulong
tdc_refresh_version
(
void
);
extern
ulong
tdc_increment_refresh_version
(
void
);
extern
void
tdc_assign_new_table_id
(
TABLE_SHARE
*
share
);
extern
int
tdc_iterate
(
THD
*
thd
,
my_hash_walk_action
action
,
void
*
argument
,
bool
no_dups
=
false
);
extern
uint
tc_records
(
void
);
extern
void
tc_purge
(
bool
mark_flushed
=
false
);
...
...
@@ -125,13 +285,3 @@ static inline TABLE_SHARE *tdc_acquire_share_shortlived(THD *thd, TABLE_LIST *tl
return
tdc_acquire_share
(
thd
,
tl
->
db
,
tl
->
table_name
,
key
,
key_length
,
tl
->
mdl_request
.
key
.
tc_hash_value
(),
flags
,
0
);
}
class
TDC_iterator
{
ulong
idx
;
public:
void
init
(
void
);
void
deinit
(
void
);
TABLE_SHARE
*
next
(
void
);
};
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