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
fd1437df
Commit
fd1437df
authored
Feb 13, 2014
by
Sergey Vojtovich
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MDEV-5597 - Reduce usage of LOCK_open: LOCK_flush
Replaced LOCK_flush with per-share conditional variable.
parent
048e9c40
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
54 additions
and
24 deletions
+54
-24
mysql-test/suite/perfschema/r/dml_setup_instruments.result
mysql-test/suite/perfschema/r/dml_setup_instruments.result
+1
-1
sql/table.h
sql/table.h
+1
-0
sql/table_cache.cc
sql/table_cache.cc
+52
-23
No files found.
mysql-test/suite/perfschema/r/dml_setup_instruments.result
View file @
fd1437df
...
...
@@ -20,7 +20,6 @@ where name like 'Wait/Synch/Rwlock/sql/%'
order by name limit 10;
NAME ENABLED TIMED
wait/synch/rwlock/sql/LOCK_dboptions YES YES
wait/synch/rwlock/sql/LOCK_flush YES YES
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
...
...
@@ -29,6 +28,7 @@ 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
select * from performance_schema.setup_instruments
where name like 'Wait/Synch/Cond/sql/%'
and name not in (
...
...
sql/table.h
View file @
fd1437df
...
...
@@ -609,6 +609,7 @@ struct TABLE_SHARE
Protects ref_count and m_flush_tickets.
*/
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 */
/**
...
...
sql/table_cache.cc
View file @
fd1437df
...
...
@@ -87,7 +87,6 @@ mysql_mutex_t LOCK_open;
static
mysql_mutex_t
LOCK_unused_shares
;
static
mysql_rwlock_t
LOCK_tdc
;
/**< Protects tdc_hash. */
static
mysql_rwlock_t
LOCK_flush
;
/**< Sync tc_purge() and tdc_remove_table(). */
my_atomic_rwlock_t
LOCK_tdc_atomics
;
/**< Protects tdc_version. */
#ifdef HAVE_PSI_INTERFACE
...
...
@@ -100,11 +99,17 @@ static PSI_mutex_info all_tc_mutexes[]=
{
&
key_TABLE_SHARE_LOCK_table_share
,
"TABLE_SHARE::tdc.LOCK_table_share"
,
0
}
};
static
PSI_rwlock_key
key_rwlock_LOCK_tdc
,
key_rwlock_LOCK_flush
;
static
PSI_rwlock_key
key_rwlock_LOCK_tdc
;
static
PSI_rwlock_info
all_tc_rwlocks
[]
=
{
{
&
key_rwlock_LOCK_tdc
,
"LOCK_tdc"
,
PSI_FLAG_GLOBAL
},
{
&
key_rwlock_LOCK_flush
,
"LOCK_flush"
,
PSI_FLAG_GLOBAL
}
{
&
key_rwlock_LOCK_tdc
,
"LOCK_tdc"
,
PSI_FLAG_GLOBAL
}
};
static
PSI_cond_key
key_TABLE_SHARE_COND_release
;
static
PSI_cond_info
all_tc_conds
[]
=
{
{
&
key_TABLE_SHARE_COND_release
,
"TABLE_SHARE::tdc.COND_release"
,
0
}
};
...
...
@@ -118,6 +123,9 @@ static void init_tc_psi_keys(void)
count
=
array_elements
(
all_tc_rwlocks
);
mysql_rwlock_register
(
category
,
all_tc_rwlocks
,
count
);
count
=
array_elements
(
all_tc_conds
);
mysql_cond_register
(
category
,
all_tc_conds
,
count
);
}
#endif
...
...
@@ -197,12 +205,10 @@ void tc_purge(bool mark_flushed)
}
}
tdc_it
.
deinit
();
mysql_rwlock_rdlock
(
&
LOCK_flush
);
mysql_mutex_unlock
(
&
LOCK_open
);
while
((
table
=
purge_tables
.
pop_front
()))
intern_close_table
(
table
);
mysql_rwlock_unlock
(
&
LOCK_flush
);
}
...
...
@@ -257,10 +263,8 @@ void tc_add_table(THD *thd, TABLE *table)
{
purge_table
->
s
->
tdc
.
free_tables
.
remove
(
purge_table
);
tc_remove_table
(
purge_table
);
mysql_rwlock_rdlock
(
&
LOCK_flush
);
mysql_mutex_unlock
(
&
LOCK_open
);
intern_close_table
(
purge_table
);
mysql_rwlock_unlock
(
&
LOCK_flush
);
}
else
mysql_mutex_unlock
(
&
LOCK_open
);
...
...
@@ -361,11 +365,9 @@ bool tc_release_table(TABLE *table)
purge:
tc_remove_table
(
table
);
mysql_rwlock_rdlock
(
&
LOCK_flush
);
mysql_mutex_unlock
(
&
LOCK_open
);
table
->
in_use
=
0
;
intern_close_table
(
table
);
mysql_rwlock_unlock
(
&
LOCK_flush
);
return
true
;
}
...
...
@@ -394,6 +396,7 @@ static int tdc_delete_share_from_hash(TABLE_SHARE *share)
mysql_mutex_lock
(
&
share
->
tdc
.
LOCK_table_share
);
if
(
--
share
->
tdc
.
ref_count
)
{
mysql_cond_broadcast
(
&
share
->
tdc
.
COND_release
);
mysql_mutex_unlock
(
&
share
->
tdc
.
LOCK_table_share
);
mysql_rwlock_unlock
(
&
LOCK_tdc
);
DBUG_RETURN
(
1
);
...
...
@@ -453,7 +456,6 @@ int tdc_init(void)
mysql_mutex_init
(
key_LOCK_unused_shares
,
&
LOCK_unused_shares
,
MY_MUTEX_INIT_FAST
);
mysql_rwlock_init
(
key_rwlock_LOCK_tdc
,
&
LOCK_tdc
);
mysql_rwlock_init
(
key_rwlock_LOCK_flush
,
&
LOCK_flush
);
my_atomic_rwlock_init
(
&
LOCK_tdc_atomics
);
oldest_unused_share
=
&
end_of_unused_share
;
end_of_unused_share
.
tdc
.
prev
=
&
oldest_unused_share
;
...
...
@@ -501,7 +503,6 @@ void tdc_deinit(void)
tdc_inited
=
false
;
my_hash_free
(
&
tdc_hash
);
my_atomic_rwlock_destroy
(
&
LOCK_tdc_atomics
);
mysql_rwlock_destroy
(
&
LOCK_flush
);
mysql_rwlock_destroy
(
&
LOCK_tdc
);
mysql_mutex_destroy
(
&
LOCK_unused_shares
);
mysql_mutex_destroy
(
&
LOCK_open
);
...
...
@@ -567,6 +568,7 @@ void tdc_init_share(TABLE_SHARE *share)
DBUG_ENTER
(
"tdc_init_share"
);
mysql_mutex_init
(
key_TABLE_SHARE_LOCK_table_share
,
&
share
->
tdc
.
LOCK_table_share
,
MY_MUTEX_INIT_FAST
);
mysql_cond_init
(
key_TABLE_SHARE_COND_release
,
&
share
->
tdc
.
COND_release
,
0
);
share
->
tdc
.
m_flush_tickets
.
empty
();
share
->
tdc
.
all_tables
.
empty
();
share
->
tdc
.
free_tables
.
empty
();
...
...
@@ -588,6 +590,7 @@ void tdc_deinit_share(TABLE_SHARE *share)
DBUG_ASSERT
(
share
->
tdc
.
m_flush_tickets
.
is_empty
());
DBUG_ASSERT
(
share
->
tdc
.
all_tables
.
is_empty
());
DBUG_ASSERT
(
share
->
tdc
.
free_tables
.
is_empty
());
mysql_cond_destroy
(
&
share
->
tdc
.
COND_release
);
mysql_mutex_destroy
(
&
share
->
tdc
.
LOCK_table_share
);
DBUG_VOID_RETURN
;
}
...
...
@@ -825,6 +828,7 @@ void tdc_release_share(TABLE_SHARE *share)
if
(
share
->
tdc
.
ref_count
>
1
)
{
share
->
tdc
.
ref_count
--
;
mysql_cond_broadcast
(
&
share
->
tdc
.
COND_release
);
mysql_mutex_unlock
(
&
share
->
tdc
.
LOCK_table_share
);
DBUG_VOID_RETURN
;
}
...
...
@@ -950,6 +954,7 @@ bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type,
if
((
share
=
tdc_delete_share
(
db
,
table_name
)))
{
I_P_List
<
TABLE
,
TABLE_share
>
purge_tables
;
uint
my_refs
=
1
;
mysql_mutex_lock
(
&
LOCK_open
);
/*
...
...
@@ -971,28 +976,52 @@ bool tdc_remove_table(THD *thd, enum_tdc_remove_table_type remove_type,
if
(
kill_delayed_threads
)
kill_delayed_threads_for_table
(
share
);
#ifndef DBUG_OFF
if
(
remove_type
==
TDC_RT_REMOVE_NOT_OWN
)
if
(
remove_type
==
TDC_RT_REMOVE_NOT_OWN
||
remove_type
==
TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE
)
{
TABLE_SHARE
::
All_share_tables_list
::
Iterator
it
(
share
->
tdc
.
all_tables
);
while
((
table
=
it
++
))
{
my_refs
++
;
DBUG_ASSERT
(
table
->
in_use
==
thd
);
}
}
#endif
mysql_rwlock_rdlock
(
&
LOCK_flush
);
DBUG_ASSERT
(
share
->
tdc
.
all_tables
.
is_empty
()
||
remove_type
!=
TDC_RT_REMOVE_ALL
);
mysql_mutex_unlock
(
&
LOCK_open
);
while
((
table
=
purge_tables
.
pop_front
()))
intern_close_table
(
table
);
mysql_rwlock_unlock
(
&
LOCK_flush
);
DBUG_ASSERT
(
share
->
tdc
.
all_tables
.
is_empty
()
||
remove_type
!=
TDC_RT_REMOVE_ALL
);
tdc_release_share
(
share
);
if
(
remove_type
!=
TDC_RT_REMOVE_UNUSED
)
{
/*
Even though current thread holds exclusive metadata lock on this share
(asserted above), concurrent FLUSH TABLES threads may be in process of
closing unused table instances belonging to this share. E.g.:
thr1 (FLUSH TABLES): table= share->tdc.free_tables.pop_front();
thr1 (FLUSH TABLES): share->tdc.all_tables.remove(table);
thr2 (ALTER TABLE): tdc_remove_table();
thr1 (FLUSH TABLES): intern_close_table(table);
Current remove type assumes that all table instances (except for those
that are owned by current thread) must be closed before
thd_remove_table() returns. Wait for such tables now.
intern_close_table() decrements ref_count and signals COND_release. When
ref_count drops down to number of references owned by current thread
waiting is completed.
Unfortunately TABLE_SHARE::wait_for_old_version() cannot be used here
because it waits for all table instances, whereas we have to wait only
for those that are not owned by current thread.
*/
mysql_mutex_lock
(
&
share
->
tdc
.
LOCK_table_share
);
while
(
share
->
tdc
.
ref_count
>
my_refs
)
mysql_cond_wait
(
&
share
->
tdc
.
COND_release
,
&
share
->
tdc
.
LOCK_table_share
);
mysql_mutex_unlock
(
&
share
->
tdc
.
LOCK_table_share
);
}
/* Wait for concurrent threads to free unused objects. */
mysql_rwlock_wrlock
(
&
LOCK_flush
);
mysql_rwlock_unlock
(
&
LOCK_flush
);
tdc_release_share
(
share
);
found
=
true
;
}
...
...
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