mirror of
https://github.com/MariaDB/server.git
synced 2025-07-27 18:02:13 +03:00
Speed up connection time:
-Change my_rnd() slightly to make it safer if two threads use it at the same time. -Avoid some sprintf and strmov in vio. -Changed thread_count to be automaticly incremented (instead of under LOCK_thread_count). -Thread cache now uses LOCK_thread_cache instead of LOCK_thread_count. -Moved delete thd out from LOCK_thread_count. -Save some mysql_cond_broadcast(&COND_thread_count) calls. -Removed call to getsockname() during connect. -Initialize random generator without locks. Other things: -Fixed test cases that depends on changes for LOCK_grant -Added thread_safe_decrement32() and thread_safe_increment32() -Removed sql_rnd_with_mutex() and get_thread_running() -In check_table_access() don't lock LOCK_grant if we can resolve the grant with user or db level grants (the normal case). -Don't use a lock for setting THD->query_id. -Fixed bug where thd->set_query_id() could be set to same value by multiple threads. Thanks to Yoshinori Matsunobu for the benchmark of connection speed and to Domas Mituzas for the inspiration for many of the fixes. include/violite.h: Change desc to a string pointer mysql-test/suite/perfschema/r/all_instances.result: Added new mutex mysql-test/suite/perfschema/t/func_mutex.test: Test for LOCK_system_variables_hash instead of LOCK_grant, as LOCK_grant is not anymore always taken for SELECT's. mysys/my_gethwaddr.c: More DBUG mysys/my_rnd.c: Change my_rnd() slightly to make it safer if two threads use it at the same time. sql/event_scheduler.cc: Changed thread_count to be automically incremented Moved some safe things out from LOCK_thread_count. Simplify deleting of THD for running thread. sql/mysqld.cc: Changed thread_count to be automically incremented Thread cache now uses LOCK_thread_cache instead of LOCK_thread_count Added delete_running_thd() Moved delete thd out from LOCK_thread_count More DBUG Only call mysql_cond_broadcast(&COND_thread_count) if thread_count is 0 Removed call to getsockname() (old not anymore needed check) sql/mysqld.h: Removed sql_rnd_with_mutex() (not needed anymore) Removed not used function get_thread_running() Added thread_safe_decrement32() and thread_safe_increment32() Simplified dec_thread_running() and inc_thread_running() next_query_id() should return the original value for global_query_id, not the next one. (Bug introduced with MySQL 5.5 merge). sql/sql_acl.cc: In check_table_access() don't lock LOCK_grant if we can resolve the grant with user or db level grants (the normal case). sql/sql_class.cc: Removed thd_lock_thread_count() and thd_unlock_thread_count() Initialize random generator without locks Don't use a lock for setting THD->query_id. (This is only accessed by thread owning the THD) sql/sql_class.h: Don't use a lock for setting THD->query_id. sql/sql_insert.cc: Changed thread_count to be automically incremented sql/sql_parse.cc: Changed thread_count to be automically incremented Fixed bug where thd->set_query_id() could be set to same value by multiple threads. vio/vio.c: Don't generate 'desc' with sprintf/strmov. Assign a pointer instead. (Good enough as this is just for debugging)
This commit is contained in:
@ -216,7 +216,7 @@ struct st_vio
|
|||||||
struct sockaddr_storage remote; /* Remote internet address */
|
struct sockaddr_storage remote; /* Remote internet address */
|
||||||
int addrLen; /* Length of remote address */
|
int addrLen; /* Length of remote address */
|
||||||
enum enum_vio_type type; /* Type of connection */
|
enum enum_vio_type type; /* Type of connection */
|
||||||
char desc[30]; /* String description */
|
const char *desc; /* String description */
|
||||||
char *read_buffer; /* buffer for vio_read_buff */
|
char *read_buffer; /* buffer for vio_read_buff */
|
||||||
char *read_pos; /* start of unfetched data in the
|
char *read_pos; /* start of unfetched data in the
|
||||||
read buffer */
|
read buffer */
|
||||||
|
@ -64,6 +64,7 @@ wait/synch/mutex/sql/LOCK_server_started
|
|||||||
wait/synch/mutex/sql/LOCK_slave_list
|
wait/synch/mutex/sql/LOCK_slave_list
|
||||||
wait/synch/mutex/sql/LOCK_stats
|
wait/synch/mutex/sql/LOCK_stats
|
||||||
wait/synch/mutex/sql/LOCK_status
|
wait/synch/mutex/sql/LOCK_status
|
||||||
|
wait/synch/mutex/sql/LOCK_thread_cache
|
||||||
wait/synch/mutex/sql/LOCK_thread_count
|
wait/synch/mutex/sql/LOCK_thread_count
|
||||||
wait/synch/mutex/sql/LOCK_user_conn
|
wait/synch/mutex/sql/LOCK_user_conn
|
||||||
wait/synch/mutex/sql/LOCK_user_locks
|
wait/synch/mutex/sql/LOCK_user_locks
|
||||||
|
@ -70,52 +70,34 @@ Success
|
|||||||
TRUNCATE TABLE performance_schema.events_waits_history_long;
|
TRUNCATE TABLE performance_schema.events_waits_history_long;
|
||||||
TRUNCATE TABLE performance_schema.events_waits_history;
|
TRUNCATE TABLE performance_schema.events_waits_history;
|
||||||
TRUNCATE TABLE performance_schema.events_waits_current;
|
TRUNCATE TABLE performance_schema.events_waits_current;
|
||||||
SELECT * FROM t1 WHERE id = 1;
|
show variables like "%not_found%";
|
||||||
id b
|
Variable_name Value
|
||||||
1 initial value
|
|
||||||
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/rwlock/sql/LOCK_grant'));
|
WHERE (EVENT_NAME = 'wait/synch/rwlock/sql/LOCK_system_variables_hash'));
|
||||||
SELECT * FROM t1;
|
show variables like "%not_found%";
|
||||||
id b
|
Variable_name Value
|
||||||
1 initial value
|
|
||||||
2 initial value
|
|
||||||
3 initial value
|
|
||||||
4 initial value
|
|
||||||
5 initial value
|
|
||||||
6 initial value
|
|
||||||
7 initial value
|
|
||||||
8 initial value
|
|
||||||
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/rwlock/sql/LOCK_grant'));
|
WHERE (EVENT_NAME = 'wait/synch/rwlock/sql/LOCK_system_variables_hash'));
|
||||||
SELECT IF((@after_count - @before_count) > 0, 'Success', 'Failure') test_fm1_rw_timed;
|
SELECT IF((@after_count - @before_count) > 0, 'Success', 'Failure') test_fm1_rw_timed;
|
||||||
test_fm1_rw_timed
|
test_fm1_rw_timed
|
||||||
Success
|
Success
|
||||||
UPDATE performance_schema.setup_instruments SET enabled = 'NO'
|
UPDATE performance_schema.setup_instruments SET enabled = 'NO'
|
||||||
WHERE NAME = 'wait/synch/rwlock/sql/LOCK_grant';
|
WHERE NAME = 'wait/synch/rwlock/sql/LOCK_system_variables_hash';
|
||||||
TRUNCATE TABLE performance_schema.events_waits_history_long;
|
TRUNCATE TABLE performance_schema.events_waits_history_long;
|
||||||
TRUNCATE TABLE performance_schema.events_waits_history;
|
TRUNCATE TABLE performance_schema.events_waits_history;
|
||||||
TRUNCATE TABLE performance_schema.events_waits_current;
|
TRUNCATE TABLE performance_schema.events_waits_current;
|
||||||
SELECT * FROM t1 WHERE id = 1;
|
show variables like "%not_found%";
|
||||||
id b
|
Variable_name Value
|
||||||
1 initial value
|
|
||||||
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/rwlock/sql/LOCK_grant'));
|
WHERE (EVENT_NAME = 'wait/synch/rwlock/sql/LOCK_system_variables_hash'));
|
||||||
SELECT * FROM t1;
|
show variables like "%not_found%";
|
||||||
id b
|
Variable_name Value
|
||||||
1 initial value
|
|
||||||
2 initial value
|
|
||||||
3 initial value
|
|
||||||
4 initial value
|
|
||||||
5 initial value
|
|
||||||
6 initial value
|
|
||||||
7 initial value
|
|
||||||
8 initial value
|
|
||||||
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/rwlock/sql/LOCK_grant'));
|
WHERE (EVENT_NAME = 'LOCK_system_variables_hash'));
|
||||||
SELECT IF((COALESCE(@after_count, 0) - COALESCE(@before_count, 0)) = 0, 'Success', 'Failure') test_fm2_rw_timed;
|
SELECT IF((COALESCE(@after_count, 0) - COALESCE(@before_count, 0)) = 0, 'Success', 'Failure') test_fm2_rw_timed;
|
||||||
test_fm2_rw_timed
|
test_fm2_rw_timed
|
||||||
Success
|
Success
|
||||||
|
@ -87,38 +87,38 @@ TRUNCATE TABLE performance_schema.events_waits_history_long;
|
|||||||
TRUNCATE TABLE performance_schema.events_waits_history;
|
TRUNCATE TABLE performance_schema.events_waits_history;
|
||||||
TRUNCATE TABLE performance_schema.events_waits_current;
|
TRUNCATE TABLE performance_schema.events_waits_current;
|
||||||
|
|
||||||
SELECT * FROM t1 WHERE id = 1;
|
show variables like "%not_found%";
|
||||||
|
|
||||||
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/rwlock/sql/LOCK_grant'));
|
WHERE (EVENT_NAME = 'wait/synch/rwlock/sql/LOCK_system_variables_hash'));
|
||||||
|
|
||||||
SELECT * FROM t1;
|
show variables like "%not_found%";
|
||||||
|
|
||||||
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/rwlock/sql/LOCK_grant'));
|
WHERE (EVENT_NAME = 'wait/synch/rwlock/sql/LOCK_system_variables_hash'));
|
||||||
|
|
||||||
SELECT IF((@after_count - @before_count) > 0, 'Success', 'Failure') test_fm1_rw_timed;
|
SELECT IF((@after_count - @before_count) > 0, 'Success', 'Failure') test_fm1_rw_timed;
|
||||||
|
|
||||||
UPDATE performance_schema.setup_instruments SET enabled = 'NO'
|
UPDATE performance_schema.setup_instruments SET enabled = 'NO'
|
||||||
WHERE NAME = 'wait/synch/rwlock/sql/LOCK_grant';
|
WHERE NAME = 'wait/synch/rwlock/sql/LOCK_system_variables_hash';
|
||||||
|
|
||||||
TRUNCATE TABLE performance_schema.events_waits_history_long;
|
TRUNCATE TABLE performance_schema.events_waits_history_long;
|
||||||
TRUNCATE TABLE performance_schema.events_waits_history;
|
TRUNCATE TABLE performance_schema.events_waits_history;
|
||||||
TRUNCATE TABLE performance_schema.events_waits_current;
|
TRUNCATE TABLE performance_schema.events_waits_current;
|
||||||
|
|
||||||
SELECT * FROM t1 WHERE id = 1;
|
show variables like "%not_found%";
|
||||||
|
|
||||||
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
SET @before_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/rwlock/sql/LOCK_grant'));
|
WHERE (EVENT_NAME = 'wait/synch/rwlock/sql/LOCK_system_variables_hash'));
|
||||||
|
|
||||||
SELECT * FROM t1;
|
show variables like "%not_found%";
|
||||||
|
|
||||||
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
SET @after_count = (SELECT SUM(TIMER_WAIT)
|
||||||
FROM performance_schema.events_waits_history_long
|
FROM performance_schema.events_waits_history_long
|
||||||
WHERE (EVENT_NAME = 'wait/synch/rwlock/sql/LOCK_grant'));
|
WHERE (EVENT_NAME = 'LOCK_system_variables_hash'));
|
||||||
|
|
||||||
SELECT IF((COALESCE(@after_count, 0) - COALESCE(@before_count, 0)) = 0, 'Success', 'Failure') test_fm2_rw_timed;
|
SELECT IF((COALESCE(@after_count, 0) - COALESCE(@before_count, 0)) = 0, 'Success', 'Failure') test_fm2_rw_timed;
|
||||||
|
|
||||||
|
@ -87,13 +87,17 @@ my_bool my_gethwaddr(uchar *to)
|
|||||||
int fd, res= 1;
|
int fd, res= 1;
|
||||||
struct ifreq ifr[32];
|
struct ifreq ifr[32];
|
||||||
struct ifconf ifc;
|
struct ifconf ifc;
|
||||||
|
DBUG_ENTER("my_gethwaddr");
|
||||||
|
|
||||||
ifc.ifc_req= ifr;
|
ifc.ifc_req= ifr;
|
||||||
ifc.ifc_len= sizeof(ifr);
|
ifc.ifc_len= sizeof(ifr);
|
||||||
|
|
||||||
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
DBUG_PRINT("error", ("socket() call failed with %d", errno));
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (ioctl(fd, SIOCGIFCONF, (char*)&ifc) >= 0)
|
if (ioctl(fd, SIOCGIFCONF, (char*)&ifc) >= 0)
|
||||||
{
|
{
|
||||||
@ -106,8 +110,8 @@ my_bool my_gethwaddr(uchar *to)
|
|||||||
ETHER_ADDR_LEN);
|
ETHER_ADDR_LEN);
|
||||||
#else
|
#else
|
||||||
/*
|
/*
|
||||||
A bug in OpenSolaris used to prevent non-root from getting a mac address:
|
A bug in OpenSolaris used to prevent non-root from getting a mac
|
||||||
{no url. Oracle killed the old OpenSolaris bug database}
|
address: {no url. Oracle killed the old OpenSolaris bug database}
|
||||||
|
|
||||||
Thus, we'll use an alternative method and extract the address from the
|
Thus, we'll use an alternative method and extract the address from the
|
||||||
arp table.
|
arp table.
|
||||||
@ -124,7 +128,7 @@ my_bool my_gethwaddr(uchar *to)
|
|||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
err:
|
err:
|
||||||
return res;
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
|
@ -45,11 +45,20 @@ void my_rnd_init(struct my_rnd_struct *rand_st, ulong seed1, ulong seed2)
|
|||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
generated pseudo random number
|
generated pseudo random number
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
This is codes so that it can be called by two threads at the same time
|
||||||
|
with minimum impact.
|
||||||
|
(As the number is supposed to be random, it doesn't matter much if
|
||||||
|
rand->seed1 or rand->seed2 are updated with slightly wrong numbers or
|
||||||
|
if two threads gets the same number.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
double my_rnd(struct my_rnd_struct *rand_st)
|
double my_rnd(struct my_rnd_struct *rand_st)
|
||||||
{
|
{
|
||||||
rand_st->seed1=(rand_st->seed1*3+rand_st->seed2) % rand_st->max_value;
|
unsigned long seed1;
|
||||||
rand_st->seed2=(rand_st->seed1+rand_st->seed2+33) % rand_st->max_value;
|
seed1= (rand_st->seed1*3+rand_st->seed2) % rand_st->max_value;
|
||||||
return (((double) rand_st->seed1)/rand_st->max_value_dbl);
|
rand_st->seed2=(seed1+rand_st->seed2+33) % rand_st->max_value;
|
||||||
|
rand_st->seed1= seed1;
|
||||||
|
return (((double) seed1)/rand_st->max_value_dbl);
|
||||||
}
|
}
|
||||||
|
@ -132,11 +132,11 @@ post_init_event_thread(THD *thd)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
thread_safe_increment32(&thread_count, &thread_count_lock);
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
mysql_mutex_lock(&LOCK_thread_count);
|
||||||
threads.append(thd);
|
threads.append(thd);
|
||||||
thread_count++;
|
|
||||||
inc_thread_running();
|
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
mysql_mutex_unlock(&LOCK_thread_count);
|
||||||
|
inc_thread_running();
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,12 +154,8 @@ deinit_event_thread(THD *thd)
|
|||||||
{
|
{
|
||||||
thd->proc_info= "Clearing";
|
thd->proc_info= "Clearing";
|
||||||
DBUG_PRINT("exit", ("Event thread finishing"));
|
DBUG_PRINT("exit", ("Event thread finishing"));
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
|
||||||
thread_count--;
|
delete_running_thd(thd);
|
||||||
dec_thread_running();
|
|
||||||
delete thd;
|
|
||||||
mysql_cond_broadcast(&COND_thread_count);
|
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -436,12 +432,7 @@ Event_scheduler::start()
|
|||||||
ret= TRUE;
|
ret= TRUE;
|
||||||
|
|
||||||
new_thd->proc_info= "Clearing";
|
new_thd->proc_info= "Clearing";
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
delete_running_thd(new_thd);
|
||||||
thread_count--;
|
|
||||||
dec_thread_running();
|
|
||||||
delete new_thd;
|
|
||||||
mysql_cond_broadcast(&COND_thread_count);
|
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
|
||||||
}
|
}
|
||||||
end:
|
end:
|
||||||
UNLOCK_DATA();
|
UNLOCK_DATA();
|
||||||
@ -570,12 +561,7 @@ error:
|
|||||||
if (new_thd)
|
if (new_thd)
|
||||||
{
|
{
|
||||||
new_thd->proc_info= "Clearing";
|
new_thd->proc_info= "Clearing";
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
delete_running_thd(new_thd);
|
||||||
thread_count--;
|
|
||||||
dec_thread_running();
|
|
||||||
delete new_thd;
|
|
||||||
mysql_cond_broadcast(&COND_thread_count);
|
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
|
||||||
}
|
}
|
||||||
delete event_name;
|
delete event_name;
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
218
sql/mysqld.cc
218
sql/mysqld.cc
@ -465,7 +465,7 @@ ulong delay_key_write_options;
|
|||||||
uint protocol_version;
|
uint protocol_version;
|
||||||
uint lower_case_table_names;
|
uint lower_case_table_names;
|
||||||
ulong tc_heuristic_recover= 0;
|
ulong tc_heuristic_recover= 0;
|
||||||
uint volatile thread_count;
|
int32 thread_count;
|
||||||
int32 thread_running;
|
int32 thread_running;
|
||||||
ulong thread_created;
|
ulong thread_created;
|
||||||
ulong back_log, connect_timeout, concurrency, server_id;
|
ulong back_log, connect_timeout, concurrency, server_id;
|
||||||
@ -489,6 +489,7 @@ ulong executed_events=0;
|
|||||||
query_id_t global_query_id;
|
query_id_t global_query_id;
|
||||||
my_atomic_rwlock_t global_query_id_lock;
|
my_atomic_rwlock_t global_query_id_lock;
|
||||||
my_atomic_rwlock_t thread_running_lock;
|
my_atomic_rwlock_t thread_running_lock;
|
||||||
|
my_atomic_rwlock_t thread_count_lock;
|
||||||
my_atomic_rwlock_t statistics_lock;
|
my_atomic_rwlock_t statistics_lock;
|
||||||
ulong aborted_threads, aborted_connects;
|
ulong aborted_threads, aborted_connects;
|
||||||
ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
|
ulong delayed_insert_timeout, delayed_insert_limit, delayed_queue_size;
|
||||||
@ -663,7 +664,7 @@ SHOW_COMP_OPTION have_openssl;
|
|||||||
|
|
||||||
pthread_key(MEM_ROOT**,THR_MALLOC);
|
pthread_key(MEM_ROOT**,THR_MALLOC);
|
||||||
pthread_key(THD*, THR_THD);
|
pthread_key(THD*, THR_THD);
|
||||||
mysql_mutex_t LOCK_thread_count;
|
mysql_mutex_t LOCK_thread_count, LOCK_thread_cache;
|
||||||
mysql_mutex_t
|
mysql_mutex_t
|
||||||
LOCK_status, LOCK_error_log, LOCK_short_uuid_generator,
|
LOCK_status, LOCK_error_log, LOCK_short_uuid_generator,
|
||||||
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
|
LOCK_delayed_insert, LOCK_delayed_status, LOCK_delayed_create,
|
||||||
@ -761,7 +762,8 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
|
|||||||
key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
|
key_relay_log_info_log_space_lock, key_relay_log_info_run_lock,
|
||||||
key_relay_log_info_sleep_lock,
|
key_relay_log_info_sleep_lock,
|
||||||
key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
|
key_structure_guard_mutex, key_TABLE_SHARE_LOCK_ha_data,
|
||||||
key_LOCK_error_messages, key_LOG_INFO_lock, key_LOCK_thread_count,
|
key_LOCK_error_messages, key_LOG_INFO_lock,
|
||||||
|
key_LOCK_thread_count, key_LOCK_thread_cache,
|
||||||
key_PARTITION_LOCK_auto_inc;
|
key_PARTITION_LOCK_auto_inc;
|
||||||
PSI_mutex_key key_RELAYLOG_LOCK_index;
|
PSI_mutex_key key_RELAYLOG_LOCK_index;
|
||||||
|
|
||||||
@ -832,6 +834,7 @@ static PSI_mutex_info all_server_mutexes[]=
|
|||||||
{ &key_LOCK_commit_ordered, "LOCK_commit_ordered", PSI_FLAG_GLOBAL},
|
{ &key_LOCK_commit_ordered, "LOCK_commit_ordered", PSI_FLAG_GLOBAL},
|
||||||
{ &key_LOG_INFO_lock, "LOG_INFO::lock", 0},
|
{ &key_LOG_INFO_lock, "LOG_INFO::lock", 0},
|
||||||
{ &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL},
|
{ &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL},
|
||||||
|
{ &key_LOCK_thread_cache, "LOCK_thread_cache", PSI_FLAG_GLOBAL},
|
||||||
{ &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0}
|
{ &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1472,7 +1475,7 @@ static void close_connections(void)
|
|||||||
end_slave();
|
end_slave();
|
||||||
|
|
||||||
/* Give threads time to die. */
|
/* Give threads time to die. */
|
||||||
for (int i= 0; thread_count && i < 100; i++)
|
for (int i= 0; *(volatile int32*) &thread_count && i < 100; i++)
|
||||||
my_sleep(20000);
|
my_sleep(20000);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1886,6 +1889,7 @@ void clean_up(bool print_message)
|
|||||||
sys_var_end();
|
sys_var_end();
|
||||||
my_atomic_rwlock_destroy(&global_query_id_lock);
|
my_atomic_rwlock_destroy(&global_query_id_lock);
|
||||||
my_atomic_rwlock_destroy(&thread_running_lock);
|
my_atomic_rwlock_destroy(&thread_running_lock);
|
||||||
|
my_atomic_rwlock_destroy(&thread_count_lock);
|
||||||
my_atomic_rwlock_destroy(&statistics_lock);
|
my_atomic_rwlock_destroy(&statistics_lock);
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
mysql_mutex_lock(&LOCK_thread_count);
|
||||||
DBUG_PRINT("quit", ("got thread count lock"));
|
DBUG_PRINT("quit", ("got thread count lock"));
|
||||||
@ -1929,6 +1933,7 @@ static void clean_up_mutexes()
|
|||||||
DBUG_ENTER("clean_up_mutexes");
|
DBUG_ENTER("clean_up_mutexes");
|
||||||
mysql_rwlock_destroy(&LOCK_grant);
|
mysql_rwlock_destroy(&LOCK_grant);
|
||||||
mysql_mutex_destroy(&LOCK_thread_count);
|
mysql_mutex_destroy(&LOCK_thread_count);
|
||||||
|
mysql_mutex_destroy(&LOCK_thread_cache);
|
||||||
mysql_mutex_destroy(&LOCK_status);
|
mysql_mutex_destroy(&LOCK_status);
|
||||||
mysql_mutex_destroy(&LOCK_delayed_insert);
|
mysql_mutex_destroy(&LOCK_delayed_insert);
|
||||||
mysql_mutex_destroy(&LOCK_delayed_status);
|
mysql_mutex_destroy(&LOCK_delayed_status);
|
||||||
@ -2455,6 +2460,28 @@ void dec_connection_count(THD *thd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Delete THD and decrement thread counters, including thread_running
|
||||||
|
*/
|
||||||
|
|
||||||
|
void delete_running_thd(THD *thd)
|
||||||
|
{
|
||||||
|
mysql_mutex_lock(&LOCK_thread_count);
|
||||||
|
thd->unlink();
|
||||||
|
mysql_mutex_unlock(&LOCK_thread_count);
|
||||||
|
|
||||||
|
delete thd;
|
||||||
|
dec_thread_running();
|
||||||
|
thread_safe_decrement32(&thread_count, &thread_count_lock);
|
||||||
|
if (!thread_count)
|
||||||
|
{
|
||||||
|
mysql_mutex_lock(&LOCK_thread_count);
|
||||||
|
mysql_cond_broadcast(&COND_thread_count);
|
||||||
|
mysql_mutex_unlock(&LOCK_thread_count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Unlink thd from global list of available connections and free thd
|
Unlink thd from global list of available connections and free thd
|
||||||
|
|
||||||
@ -2479,7 +2506,6 @@ void unlink_thd(THD *thd)
|
|||||||
mysql_mutex_unlock(&LOCK_status);
|
mysql_mutex_unlock(&LOCK_status);
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
mysql_mutex_lock(&LOCK_thread_count);
|
||||||
thread_count--;
|
|
||||||
thd->unlink();
|
thd->unlink();
|
||||||
/*
|
/*
|
||||||
Used by binlog_reset_master. It would be cleaner to use
|
Used by binlog_reset_master. It would be cleaner to use
|
||||||
@ -2487,13 +2513,11 @@ void unlink_thd(THD *thd)
|
|||||||
sync feature has been shut down at this point.
|
sync feature has been shut down at this point.
|
||||||
*/
|
*/
|
||||||
DBUG_EXECUTE_IF("sleep_after_lock_thread_count_before_delete_thd", sleep(5););
|
DBUG_EXECUTE_IF("sleep_after_lock_thread_count_before_delete_thd", sleep(5););
|
||||||
/*
|
|
||||||
We must delete thd inside the lock to ensure that we don't start cleanup
|
|
||||||
before THD is deleted
|
|
||||||
*/
|
|
||||||
delete thd;
|
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
mysql_mutex_unlock(&LOCK_thread_count);
|
||||||
|
|
||||||
|
delete thd;
|
||||||
|
thread_safe_decrement32(&thread_count, &thread_count_lock);
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2505,7 +2529,7 @@ void unlink_thd(THD *thd)
|
|||||||
cache_thread()
|
cache_thread()
|
||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
LOCK_thread_count has to be locked
|
LOCK_thread_cache is used to protect the cache variables
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
0 Thread was not put in cache
|
0 Thread was not put in cache
|
||||||
@ -2516,7 +2540,9 @@ void unlink_thd(THD *thd)
|
|||||||
|
|
||||||
static bool cache_thread()
|
static bool cache_thread()
|
||||||
{
|
{
|
||||||
mysql_mutex_assert_owner(&LOCK_thread_count);
|
DBUG_ENTER("cache_thread");
|
||||||
|
|
||||||
|
mysql_mutex_lock(&LOCK_thread_cache);
|
||||||
if (cached_thread_count < thread_cache_size &&
|
if (cached_thread_count < thread_cache_size &&
|
||||||
! abort_loop && !kill_cached_threads)
|
! abort_loop && !kill_cached_threads)
|
||||||
{
|
{
|
||||||
@ -2534,7 +2560,7 @@ static bool cache_thread()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (!abort_loop && ! wake_thread && ! kill_cached_threads)
|
while (!abort_loop && ! wake_thread && ! kill_cached_threads)
|
||||||
mysql_cond_wait(&COND_thread_cache, &LOCK_thread_count);
|
mysql_cond_wait(&COND_thread_cache, &LOCK_thread_cache);
|
||||||
cached_thread_count--;
|
cached_thread_count--;
|
||||||
if (kill_cached_threads)
|
if (kill_cached_threads)
|
||||||
mysql_cond_signal(&COND_flush_thread_cache);
|
mysql_cond_signal(&COND_flush_thread_cache);
|
||||||
@ -2543,6 +2569,8 @@ static bool cache_thread()
|
|||||||
THD *thd;
|
THD *thd;
|
||||||
wake_thread--;
|
wake_thread--;
|
||||||
thd= thread_cache.get();
|
thd= thread_cache.get();
|
||||||
|
mysql_mutex_unlock(&LOCK_thread_cache);
|
||||||
|
|
||||||
thd->thread_stack= (char*) &thd; // For store_globals
|
thd->thread_stack= (char*) &thd; // For store_globals
|
||||||
(void) thd->store_globals();
|
(void) thd->store_globals();
|
||||||
|
|
||||||
@ -2568,11 +2596,16 @@ static bool cache_thread()
|
|||||||
thd->mysys_var->abort= 0;
|
thd->mysys_var->abort= 0;
|
||||||
thd->thr_create_utime= microsecond_interval_timer();
|
thd->thr_create_utime= microsecond_interval_timer();
|
||||||
thd->start_utime= thd->thr_create_utime;
|
thd->start_utime= thd->thr_create_utime;
|
||||||
|
|
||||||
|
/* Link thd into list of all active threads (THD's) */
|
||||||
|
mysql_mutex_lock(&LOCK_thread_count);
|
||||||
threads.append(thd);
|
threads.append(thd);
|
||||||
return(1);
|
mysql_mutex_unlock(&LOCK_thread_count);
|
||||||
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return(0);
|
mysql_mutex_unlock(&LOCK_thread_cache);
|
||||||
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2603,17 +2636,23 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache)
|
|||||||
set_current_thd(0);
|
set_current_thd(0);
|
||||||
if (put_in_cache)
|
if (put_in_cache)
|
||||||
{
|
{
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
if (cache_thread())
|
||||||
put_in_cache= cache_thread();
|
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
|
||||||
if (put_in_cache)
|
|
||||||
DBUG_RETURN(0); // Thread is reused
|
DBUG_RETURN(0); // Thread is reused
|
||||||
}
|
}
|
||||||
|
|
||||||
/* It's safe to broadcast outside a lock (COND... is not deleted here) */
|
/*
|
||||||
DBUG_PRINT("signal", ("Broadcasting COND_thread_count"));
|
It's safe to check for thread_count outside of the mutex
|
||||||
mysql_cond_broadcast(&COND_thread_count);
|
as we are only interested to see if it was counted to 0 by the
|
||||||
|
above unlink_thd() call. We should only signal COND_thread_count if
|
||||||
|
thread_count is likely to be 0. (false positives are ok)
|
||||||
|
*/
|
||||||
|
if (!thread_count)
|
||||||
|
{
|
||||||
|
mysql_mutex_lock(&LOCK_thread_count);
|
||||||
|
DBUG_PRINT("signal", ("Broadcasting COND_thread_count"));
|
||||||
|
mysql_cond_broadcast(&COND_thread_count);
|
||||||
|
mysql_mutex_unlock(&LOCK_thread_count);
|
||||||
|
}
|
||||||
DBUG_LEAVE; // Must match DBUG_ENTER()
|
DBUG_LEAVE; // Must match DBUG_ENTER()
|
||||||
my_thread_end();
|
my_thread_end();
|
||||||
|
|
||||||
@ -2624,15 +2663,17 @@ bool one_thread_per_connection_end(THD *thd, bool put_in_cache)
|
|||||||
|
|
||||||
void flush_thread_cache()
|
void flush_thread_cache()
|
||||||
{
|
{
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
DBUG_ENTER("flush_thread_cache");
|
||||||
|
mysql_mutex_lock(&LOCK_thread_cache);
|
||||||
kill_cached_threads++;
|
kill_cached_threads++;
|
||||||
while (cached_thread_count)
|
while (cached_thread_count)
|
||||||
{
|
{
|
||||||
mysql_cond_broadcast(&COND_thread_cache);
|
mysql_cond_broadcast(&COND_thread_cache);
|
||||||
mysql_cond_wait(&COND_flush_thread_cache, &LOCK_thread_count);
|
mysql_cond_wait(&COND_flush_thread_cache, &LOCK_thread_cache);
|
||||||
}
|
}
|
||||||
kill_cached_threads--;
|
kill_cached_threads--;
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
mysql_mutex_unlock(&LOCK_thread_cache);
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -3973,6 +4014,7 @@ static int init_thread_environment()
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("init_thread_environment");
|
DBUG_ENTER("init_thread_environment");
|
||||||
mysql_mutex_init(key_LOCK_thread_count, &LOCK_thread_count, MY_MUTEX_INIT_FAST);
|
mysql_mutex_init(key_LOCK_thread_count, &LOCK_thread_count, MY_MUTEX_INIT_FAST);
|
||||||
|
mysql_mutex_init(key_LOCK_thread_cache, &LOCK_thread_cache, MY_MUTEX_INIT_FAST);
|
||||||
mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST);
|
mysql_mutex_init(key_LOCK_status, &LOCK_status, MY_MUTEX_INIT_FAST);
|
||||||
mysql_mutex_init(key_LOCK_delayed_insert,
|
mysql_mutex_init(key_LOCK_delayed_insert,
|
||||||
&LOCK_delayed_insert, MY_MUTEX_INIT_FAST);
|
&LOCK_delayed_insert, MY_MUTEX_INIT_FAST);
|
||||||
@ -5363,7 +5405,7 @@ static void bootstrap(MYSQL_FILE *file)
|
|||||||
thd->max_client_packet_length= thd->net.max_packet;
|
thd->max_client_packet_length= thd->net.max_packet;
|
||||||
thd->security_ctx->master_access= ~(ulong)0;
|
thd->security_ctx->master_access= ~(ulong)0;
|
||||||
thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
|
thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
|
||||||
thread_count++;
|
thread_count++; // Safe as only one thread running
|
||||||
in_bootstrap= TRUE;
|
in_bootstrap= TRUE;
|
||||||
|
|
||||||
bootstrap_file=file;
|
bootstrap_file=file;
|
||||||
@ -5444,54 +5486,69 @@ void handle_connection_in_main_thread(THD *thd)
|
|||||||
|
|
||||||
void create_thread_to_handle_connection(THD *thd)
|
void create_thread_to_handle_connection(THD *thd)
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("create_thread_to_handle_connection");
|
||||||
|
mysql_mutex_assert_owner(&LOCK_thread_count);
|
||||||
|
|
||||||
|
/* Check if we can get thread from the cache */
|
||||||
if (cached_thread_count > wake_thread)
|
if (cached_thread_count > wake_thread)
|
||||||
{
|
{
|
||||||
/* Get thread from cache */
|
mysql_mutex_lock(&LOCK_thread_cache);
|
||||||
thread_cache.push_back(thd);
|
/* Recheck condition when we have the lock */
|
||||||
wake_thread++;
|
if (cached_thread_count > wake_thread)
|
||||||
mysql_cond_signal(&COND_thread_cache);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
char error_message_buff[MYSQL_ERRMSG_SIZE];
|
|
||||||
/* Create new thread to handle connection */
|
|
||||||
int error;
|
|
||||||
thread_created++;
|
|
||||||
threads.append(thd);
|
|
||||||
DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
|
|
||||||
thd->prior_thr_create_utime= microsecond_interval_timer();
|
|
||||||
if ((error= mysql_thread_create(key_thread_one_connection,
|
|
||||||
&thd->real_id, &connection_attrib,
|
|
||||||
handle_one_connection,
|
|
||||||
(void*) thd)))
|
|
||||||
{
|
{
|
||||||
/* purecov: begin inspected */
|
|
||||||
DBUG_PRINT("error",
|
|
||||||
("Can't create thread to handle request (error %d)",
|
|
||||||
error));
|
|
||||||
thread_count--;
|
|
||||||
thd->killed= KILL_CONNECTION; // Safety
|
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
mysql_mutex_unlock(&LOCK_thread_count);
|
||||||
|
/* Get thread from cache */
|
||||||
mysql_mutex_lock(&LOCK_connection_count);
|
thread_cache.push_back(thd);
|
||||||
(*thd->scheduler->connection_count)--;
|
wake_thread++;
|
||||||
mysql_mutex_unlock(&LOCK_connection_count);
|
mysql_cond_signal(&COND_thread_cache);
|
||||||
|
mysql_mutex_unlock(&LOCK_thread_cache);
|
||||||
statistic_increment(aborted_connects,&LOCK_status);
|
DBUG_PRINT("info",("Thread created"));
|
||||||
/* Can't use my_error() since store_globals has not been called. */
|
DBUG_VOID_RETURN;
|
||||||
my_snprintf(error_message_buff, sizeof(error_message_buff),
|
|
||||||
ER_THD(thd, ER_CANT_CREATE_THREAD), error);
|
|
||||||
net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL);
|
|
||||||
close_connection(thd, ER_OUT_OF_RESOURCES);
|
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
|
||||||
delete thd;
|
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
|
||||||
return;
|
|
||||||
/* purecov: end */
|
|
||||||
}
|
}
|
||||||
|
mysql_mutex_unlock(&LOCK_thread_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
char error_message_buff[MYSQL_ERRMSG_SIZE];
|
||||||
|
/* Create new thread to handle connection */
|
||||||
|
int error;
|
||||||
|
thread_created++;
|
||||||
|
threads.append(thd);
|
||||||
|
DBUG_PRINT("info",(("creating thread %lu"), thd->thread_id));
|
||||||
|
thd->prior_thr_create_utime= microsecond_interval_timer();
|
||||||
|
if ((error= mysql_thread_create(key_thread_one_connection,
|
||||||
|
&thd->real_id, &connection_attrib,
|
||||||
|
handle_one_connection,
|
||||||
|
(void*) thd)))
|
||||||
|
{
|
||||||
|
/* purecov: begin inspected */
|
||||||
|
DBUG_PRINT("error",
|
||||||
|
("Can't create thread to handle request (error %d)",
|
||||||
|
error));
|
||||||
|
thd->killed= KILL_CONNECTION; // Safety
|
||||||
|
mysql_mutex_unlock(&LOCK_thread_count);
|
||||||
|
|
||||||
|
mysql_mutex_lock(&LOCK_connection_count);
|
||||||
|
(*thd->scheduler->connection_count)--;
|
||||||
|
mysql_mutex_unlock(&LOCK_connection_count);
|
||||||
|
|
||||||
|
statistic_increment(aborted_connects,&LOCK_status);
|
||||||
|
/* Can't use my_error() since store_globals has not been called. */
|
||||||
|
my_snprintf(error_message_buff, sizeof(error_message_buff),
|
||||||
|
ER_THD(thd, ER_CANT_CREATE_THREAD), error);
|
||||||
|
net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL);
|
||||||
|
close_connection(thd, ER_OUT_OF_RESOURCES);
|
||||||
|
|
||||||
|
mysql_mutex_lock(&LOCK_thread_count);
|
||||||
|
thd->unlink();
|
||||||
|
mysql_mutex_unlock(&LOCK_thread_count);
|
||||||
|
delete thd;
|
||||||
|
thread_safe_decrement32(&thread_count, &thread_count_lock);
|
||||||
|
return;
|
||||||
|
/* purecov: end */
|
||||||
}
|
}
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
mysql_mutex_unlock(&LOCK_thread_count);
|
||||||
DBUG_PRINT("info",("Thread created"));
|
DBUG_PRINT("info",("Thread created"));
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -5538,10 +5595,10 @@ static void create_new_thread(THD *thd)
|
|||||||
|
|
||||||
mysql_mutex_unlock(&LOCK_connection_count);
|
mysql_mutex_unlock(&LOCK_connection_count);
|
||||||
|
|
||||||
|
thread_safe_increment32(&thread_count, &thread_count_lock);
|
||||||
|
|
||||||
/* Start a new thread to handle connection. */
|
/* Start a new thread to handle connection. */
|
||||||
|
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
mysql_mutex_lock(&LOCK_thread_count);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The initialization of thread_id is done in create_embedded_thd() for
|
The initialization of thread_id is done in create_embedded_thd() for
|
||||||
the embedded library.
|
the embedded library.
|
||||||
@ -5549,8 +5606,6 @@ static void create_new_thread(THD *thd)
|
|||||||
*/
|
*/
|
||||||
thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
|
thd->thread_id= thd->variables.pseudo_thread_id= thread_id++;
|
||||||
|
|
||||||
thread_count++;
|
|
||||||
|
|
||||||
MYSQL_CALLBACK(thd->scheduler, add_connection, (thd));
|
MYSQL_CALLBACK(thd->scheduler, add_connection, (thd));
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -5758,20 +5813,6 @@ void handle_connections_sockets()
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_LIBWRAP */
|
#endif /* HAVE_LIBWRAP */
|
||||||
|
|
||||||
{
|
|
||||||
size_socket dummyLen;
|
|
||||||
struct sockaddr_storage dummy;
|
|
||||||
dummyLen = sizeof(dummy);
|
|
||||||
if ( getsockname(new_sock,(struct sockaddr *)&dummy,
|
|
||||||
(SOCKET_SIZE_TYPE *)&dummyLen) < 0 )
|
|
||||||
{
|
|
||||||
sql_perror("Error on new connection socket");
|
|
||||||
(void) mysql_socket_shutdown(new_sock, SHUT_RDWR);
|
|
||||||
(void) closesocket(new_sock);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Don't allow too many connections
|
** Don't allow too many connections
|
||||||
*/
|
*/
|
||||||
@ -7402,6 +7443,7 @@ static int mysql_init_variables(void)
|
|||||||
global_query_id= thread_id= 1L;
|
global_query_id= thread_id= 1L;
|
||||||
my_atomic_rwlock_init(&global_query_id_lock);
|
my_atomic_rwlock_init(&global_query_id_lock);
|
||||||
my_atomic_rwlock_init(&thread_running_lock);
|
my_atomic_rwlock_init(&thread_running_lock);
|
||||||
|
my_atomic_rwlock_init(&thread_count_lock);
|
||||||
my_atomic_rwlock_init(&statistics_lock);
|
my_atomic_rwlock_init(&statistics_lock);
|
||||||
strmov(server_version, MYSQL_SERVER_VERSION);
|
strmov(server_version, MYSQL_SERVER_VERSION);
|
||||||
threads.empty();
|
threads.empty();
|
||||||
@ -8461,12 +8503,8 @@ void refresh_status(THD *thd)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
Set max_used_connections to the number of currently open
|
Set max_used_connections to the number of currently open
|
||||||
connections. Lock LOCK_thread_count out of LOCK_status to avoid
|
connections. This is not perfect, but status data is not exact anyway.
|
||||||
deadlocks. Status reset becomes not atomic, but status data is
|
|
||||||
not exact anyway.
|
|
||||||
*/
|
*/
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
|
||||||
max_used_connections= thread_count-delayed_insert_threads;
|
max_used_connections= thread_count-delayed_insert_threads;
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
49
sql/mysqld.h
49
sql/mysqld.h
@ -56,6 +56,7 @@ void kill_mysql(void);
|
|||||||
void close_connection(THD *thd, uint sql_errno= 0);
|
void close_connection(THD *thd, uint sql_errno= 0);
|
||||||
void handle_connection_in_main_thread(THD *thd);
|
void handle_connection_in_main_thread(THD *thd);
|
||||||
void create_thread_to_handle_connection(THD *thd);
|
void create_thread_to_handle_connection(THD *thd);
|
||||||
|
void delete_running_thd(THD *thd);
|
||||||
void unlink_thd(THD *thd);
|
void unlink_thd(THD *thd);
|
||||||
bool one_thread_per_connection_end(THD *thd, bool put_in_cache);
|
bool one_thread_per_connection_end(THD *thd, bool put_in_cache);
|
||||||
void flush_thread_cache();
|
void flush_thread_cache();
|
||||||
@ -89,7 +90,6 @@ extern bool opt_ignore_builtin_innodb;
|
|||||||
extern my_bool opt_character_set_client_handshake;
|
extern my_bool opt_character_set_client_handshake;
|
||||||
extern bool volatile abort_loop;
|
extern bool volatile abort_loop;
|
||||||
extern bool in_bootstrap;
|
extern bool in_bootstrap;
|
||||||
extern uint volatile thread_count;
|
|
||||||
extern uint connection_count;
|
extern uint connection_count;
|
||||||
extern my_bool opt_safe_user_create;
|
extern my_bool opt_safe_user_create;
|
||||||
extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap;
|
extern my_bool opt_safe_show_db, opt_local_infile, opt_myisam_use_mmap;
|
||||||
@ -352,7 +352,8 @@ extern mysql_rwlock_t LOCK_system_variables_hash;
|
|||||||
extern mysql_cond_t COND_thread_count;
|
extern mysql_cond_t COND_thread_count;
|
||||||
extern mysql_cond_t COND_manager;
|
extern mysql_cond_t COND_manager;
|
||||||
extern int32 thread_running;
|
extern int32 thread_running;
|
||||||
extern my_atomic_rwlock_t thread_running_lock;
|
extern int32 thread_count;
|
||||||
|
extern my_atomic_rwlock_t thread_running_lock, thread_count_lock;
|
||||||
|
|
||||||
extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher,
|
extern char *opt_ssl_ca, *opt_ssl_capath, *opt_ssl_cert, *opt_ssl_cipher,
|
||||||
*opt_ssl_key;
|
*opt_ssl_key;
|
||||||
@ -449,7 +450,7 @@ inline query_id_t next_query_id()
|
|||||||
my_atomic_rwlock_wrlock(&global_query_id_lock);
|
my_atomic_rwlock_wrlock(&global_query_id_lock);
|
||||||
id= my_atomic_add64(&global_query_id, 1);
|
id= my_atomic_add64(&global_query_id, 1);
|
||||||
my_atomic_rwlock_wrunlock(&global_query_id_lock);
|
my_atomic_rwlock_wrunlock(&global_query_id_lock);
|
||||||
return (id+1);
|
return (id);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline query_id_t get_query_id()
|
inline query_id_t get_query_id()
|
||||||
@ -479,42 +480,30 @@ inline void table_case_convert(char * name, uint length)
|
|||||||
name, length, name, length);
|
name, length, name, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ulong sql_rnd_with_mutex()
|
inline void thread_safe_increment32(int32 *value, my_atomic_rwlock_t *lock)
|
||||||
{
|
{
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
my_atomic_rwlock_wrlock(lock);
|
||||||
ulong tmp=(ulong) (my_rnd(&sql_rand) * 0xffffffff); /* make all bits random */
|
(void) my_atomic_add32(value, 1);
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
my_atomic_rwlock_wrunlock(lock);
|
||||||
return tmp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int32
|
inline void thread_safe_decrement32(int32 *value, my_atomic_rwlock_t *lock)
|
||||||
|
{
|
||||||
|
my_atomic_rwlock_wrlock(lock);
|
||||||
|
(void) my_atomic_add32(value, -1);
|
||||||
|
my_atomic_rwlock_wrunlock(lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
inc_thread_running()
|
inc_thread_running()
|
||||||
{
|
{
|
||||||
int32 num_thread_running;
|
thread_safe_increment32(&thread_running, &thread_running_lock);
|
||||||
my_atomic_rwlock_wrlock(&thread_running_lock);
|
|
||||||
num_thread_running= my_atomic_add32(&thread_running, 1);
|
|
||||||
my_atomic_rwlock_wrunlock(&thread_running_lock);
|
|
||||||
return (num_thread_running+1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int32
|
inline void
|
||||||
dec_thread_running()
|
dec_thread_running()
|
||||||
{
|
{
|
||||||
int32 num_thread_running;
|
thread_safe_decrement32(&thread_running, &thread_running_lock);
|
||||||
my_atomic_rwlock_wrlock(&thread_running_lock);
|
|
||||||
num_thread_running= my_atomic_add32(&thread_running, -1);
|
|
||||||
my_atomic_rwlock_wrunlock(&thread_running_lock);
|
|
||||||
return (num_thread_running-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int32
|
|
||||||
get_thread_running()
|
|
||||||
{
|
|
||||||
int32 num_thread_running;
|
|
||||||
my_atomic_rwlock_wrlock(&thread_running_lock);
|
|
||||||
num_thread_running= my_atomic_load32(&thread_running);
|
|
||||||
my_atomic_rwlock_wrunlock(&thread_running_lock);
|
|
||||||
return num_thread_running;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_server_version(void);
|
void set_server_version(void);
|
||||||
|
@ -4530,12 +4530,16 @@ end:
|
|||||||
@see check_access
|
@see check_access
|
||||||
@see check_table_access
|
@see check_table_access
|
||||||
|
|
||||||
@note This functions assumes that either number of tables to be inspected
|
@note
|
||||||
|
This functions assumes that either number of tables to be inspected
|
||||||
by it is limited explicitly (i.e. is is not UINT_MAX) or table list
|
by it is limited explicitly (i.e. is is not UINT_MAX) or table list
|
||||||
used and thd->lex->query_tables_own_last value correspond to each
|
used and thd->lex->query_tables_own_last value correspond to each
|
||||||
other (the latter should be either 0 or point to next_global member
|
other (the latter should be either 0 or point to next_global member
|
||||||
of one of elements of this table list).
|
of one of elements of this table list).
|
||||||
|
|
||||||
|
We delay locking of LOCK_grant until we really need it as we assume that
|
||||||
|
most privileges be resolved with user or db level accesses.
|
||||||
|
|
||||||
@return Access status
|
@return Access status
|
||||||
@retval FALSE Access granted; But column privileges might need to be
|
@retval FALSE Access granted; But column privileges might need to be
|
||||||
checked.
|
checked.
|
||||||
@ -4552,6 +4556,8 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
|
|||||||
Security_context *sctx= thd->security_ctx;
|
Security_context *sctx= thd->security_ctx;
|
||||||
uint i;
|
uint i;
|
||||||
ulong orig_want_access= want_access;
|
ulong orig_want_access= want_access;
|
||||||
|
my_bool locked= 0;
|
||||||
|
GRANT_TABLE *grant_table;
|
||||||
DBUG_ENTER("check_grant");
|
DBUG_ENTER("check_grant");
|
||||||
DBUG_ASSERT(number > 0);
|
DBUG_ASSERT(number > 0);
|
||||||
|
|
||||||
@ -4575,11 +4581,9 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
|
|||||||
*/
|
*/
|
||||||
tl->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
|
tl->grant.orig_want_privilege= (want_access & ~SHOW_VIEW_ACL);
|
||||||
}
|
}
|
||||||
|
number= i;
|
||||||
|
|
||||||
mysql_rwlock_rdlock(&LOCK_grant);
|
for (tl= tables; number-- ; tl= tl->next_global)
|
||||||
for (tl= tables;
|
|
||||||
tl && number-- && tl != first_not_own_table;
|
|
||||||
tl= tl->next_global)
|
|
||||||
{
|
{
|
||||||
sctx = test(tl->security_ctx) ? tl->security_ctx : thd->security_ctx;
|
sctx = test(tl->security_ctx) ? tl->security_ctx : thd->security_ctx;
|
||||||
|
|
||||||
@ -4632,13 +4636,18 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
|
|||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
GRANT_TABLE *grant_table= table_hash_search(sctx->host, sctx->ip,
|
|
||||||
tl->get_db_name(),
|
|
||||||
sctx->priv_user,
|
|
||||||
tl->get_table_name(),
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
if (!grant_table)
|
if (!locked)
|
||||||
|
{
|
||||||
|
locked= 1;
|
||||||
|
mysql_rwlock_rdlock(&LOCK_grant);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(grant_table= table_hash_search(sctx->host, sctx->ip,
|
||||||
|
tl->get_db_name(),
|
||||||
|
sctx->priv_user,
|
||||||
|
tl->get_table_name(),
|
||||||
|
FALSE)))
|
||||||
{
|
{
|
||||||
want_access &= ~tl->grant.privilege;
|
want_access &= ~tl->grant.privilege;
|
||||||
goto err; // No grants
|
goto err; // No grants
|
||||||
@ -4665,11 +4674,13 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
|
|||||||
goto err; // impossible
|
goto err; // impossible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mysql_rwlock_unlock(&LOCK_grant);
|
if (locked)
|
||||||
|
mysql_rwlock_unlock(&LOCK_grant);
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
mysql_rwlock_unlock(&LOCK_grant);
|
if (locked)
|
||||||
|
mysql_rwlock_unlock(&LOCK_grant);
|
||||||
if (!no_errors) // Not a silent skip of table
|
if (!no_errors) // Not a silent skip of table
|
||||||
{
|
{
|
||||||
char command[128];
|
char command[128];
|
||||||
|
@ -349,29 +349,6 @@ void thd_set_thread_stack(THD *thd, char *stack_start)
|
|||||||
thd->thread_stack= stack_start;
|
thd->thread_stack= stack_start;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
Lock connection data for the set of connections this connection
|
|
||||||
belongs to
|
|
||||||
|
|
||||||
@param thd THD object
|
|
||||||
*/
|
|
||||||
void thd_lock_thread_count(THD *)
|
|
||||||
{
|
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Lock connection data for the set of connections this connection
|
|
||||||
belongs to
|
|
||||||
|
|
||||||
@param thd THD object
|
|
||||||
*/
|
|
||||||
void thd_unlock_thread_count(THD *)
|
|
||||||
{
|
|
||||||
mysql_cond_broadcast(&COND_thread_count);
|
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Close the socket used by this connection
|
Close the socket used by this connection
|
||||||
|
|
||||||
@ -947,7 +924,14 @@ THD::THD()
|
|||||||
protocol_binary.init(this);
|
protocol_binary.init(this);
|
||||||
|
|
||||||
tablespace_op=FALSE;
|
tablespace_op=FALSE;
|
||||||
tmp= sql_rnd_with_mutex();
|
|
||||||
|
/*
|
||||||
|
Initialize the random generator. We call my_rnd() without a lock as
|
||||||
|
it's not really critical if two threads modifies the structure at the
|
||||||
|
same time. We ensure that we have an unique number foreach thread
|
||||||
|
by adding the address of the stack.
|
||||||
|
*/
|
||||||
|
tmp= (ulong) (my_rnd(&sql_rand) * 0xffffffff);
|
||||||
my_rnd_init(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id);
|
my_rnd_init(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id);
|
||||||
substitute_null_with_insert_id = FALSE;
|
substitute_null_with_insert_id = FALSE;
|
||||||
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
|
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
|
||||||
@ -4342,17 +4326,8 @@ void THD::set_query_and_id(char *query_arg, uint32 query_length_arg,
|
|||||||
{
|
{
|
||||||
mysql_mutex_lock(&LOCK_thd_data);
|
mysql_mutex_lock(&LOCK_thd_data);
|
||||||
set_query_inner(query_arg, query_length_arg, cs);
|
set_query_inner(query_arg, query_length_arg, cs);
|
||||||
query_id= new_query_id;
|
|
||||||
mysql_mutex_unlock(&LOCK_thd_data);
|
mysql_mutex_unlock(&LOCK_thd_data);
|
||||||
}
|
|
||||||
|
|
||||||
/** Assign a new value to thd->query_id. */
|
|
||||||
|
|
||||||
void THD::set_query_id(query_id_t new_query_id)
|
|
||||||
{
|
|
||||||
mysql_mutex_lock(&LOCK_thd_data);
|
|
||||||
query_id= new_query_id;
|
query_id= new_query_id;
|
||||||
mysql_mutex_unlock(&LOCK_thd_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Assign a new value to thd->mysys_var. */
|
/** Assign a new value to thd->mysys_var. */
|
||||||
|
@ -3076,7 +3076,10 @@ public:
|
|||||||
{ set_query(CSET_STRING()); }
|
{ set_query(CSET_STRING()); }
|
||||||
void set_query_and_id(char *query_arg, uint32 query_length_arg,
|
void set_query_and_id(char *query_arg, uint32 query_length_arg,
|
||||||
CHARSET_INFO *cs, query_id_t new_query_id);
|
CHARSET_INFO *cs, query_id_t new_query_id);
|
||||||
void set_query_id(query_id_t new_query_id);
|
void set_query_id(query_id_t new_query_id)
|
||||||
|
{
|
||||||
|
query_id= new_query_id;
|
||||||
|
}
|
||||||
void set_open_tables(TABLE *open_tables_arg)
|
void set_open_tables(TABLE *open_tables_arg)
|
||||||
{
|
{
|
||||||
mysql_mutex_lock(&LOCK_thd_data);
|
mysql_mutex_lock(&LOCK_thd_data);
|
||||||
|
@ -2038,9 +2038,9 @@ public:
|
|||||||
thd.unlink(); // Must be unlinked under lock
|
thd.unlink(); // Must be unlinked under lock
|
||||||
my_free(thd.query());
|
my_free(thd.query());
|
||||||
thd.security_ctx->user= thd.security_ctx->host=0;
|
thd.security_ctx->user= thd.security_ctx->host=0;
|
||||||
thread_count--;
|
|
||||||
delayed_insert_threads--;
|
delayed_insert_threads--;
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
mysql_mutex_unlock(&LOCK_thread_count);
|
||||||
|
thread_safe_decrement32(&thread_count, &thread_count_lock);
|
||||||
mysql_cond_broadcast(&COND_thread_count); /* Tell main we are ready */
|
mysql_cond_broadcast(&COND_thread_count); /* Tell main we are ready */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2175,9 +2175,9 @@ bool delayed_get_table(THD *thd, MDL_request *grl_protection_request,
|
|||||||
{
|
{
|
||||||
if (!(di= new Delayed_insert()))
|
if (!(di= new Delayed_insert()))
|
||||||
goto end_create;
|
goto end_create;
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
|
||||||
thread_count++;
|
thread_safe_increment32(&thread_count, &thread_count_lock);
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
|
||||||
/*
|
/*
|
||||||
Annotating delayed inserts is not supported.
|
Annotating delayed inserts is not supported.
|
||||||
*/
|
*/
|
||||||
|
@ -645,9 +645,10 @@ end:
|
|||||||
delete thd;
|
delete thd;
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
mysql_mutex_lock(&LOCK_thread_count);
|
thread_safe_decrement32(&thread_count, &thread_count_lock);
|
||||||
thread_count--;
|
|
||||||
in_bootstrap= FALSE;
|
in_bootstrap= FALSE;
|
||||||
|
|
||||||
|
mysql_mutex_lock(&LOCK_thread_count);
|
||||||
mysql_cond_broadcast(&COND_thread_count);
|
mysql_cond_broadcast(&COND_thread_count);
|
||||||
mysql_mutex_unlock(&LOCK_thread_count);
|
mysql_mutex_unlock(&LOCK_thread_count);
|
||||||
my_thread_end();
|
my_thread_end();
|
||||||
@ -930,9 +931,16 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
thd->query_plan_flags= QPLAN_INIT;
|
thd->query_plan_flags= QPLAN_INIT;
|
||||||
thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
|
thd->lex->sql_command= SQLCOM_END; /* to avoid confusing VIEW detectors */
|
||||||
thd->set_time();
|
thd->set_time();
|
||||||
thd->set_query_id(get_query_id());
|
|
||||||
if (!(server_command_flags[command] & CF_SKIP_QUERY_ID))
|
if (!(server_command_flags[command] & CF_SKIP_QUERY_ID))
|
||||||
next_query_id();
|
thd->set_query_id(next_query_id());
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
ping, get statistics or similar stateless command.
|
||||||
|
No reason to increase query id here.
|
||||||
|
*/
|
||||||
|
thd->set_query_id(get_query_id());
|
||||||
|
}
|
||||||
inc_thread_running();
|
inc_thread_running();
|
||||||
|
|
||||||
if (!(server_command_flags[command] & CF_SKIP_QUESTIONS))
|
if (!(server_command_flags[command] & CF_SKIP_QUESTIONS))
|
||||||
@ -5021,6 +5029,10 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
|
|||||||
|
|
||||||
if ((db != NULL) && (db != any_db))
|
if ((db != NULL) && (db != any_db))
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Check if this is reserved database, like information schema or
|
||||||
|
performance schema
|
||||||
|
*/
|
||||||
const ACL_internal_schema_access *access;
|
const ACL_internal_schema_access *access;
|
||||||
access= get_cached_schema_access(grant_internal_info, db);
|
access= get_cached_schema_access(grant_internal_info, db);
|
||||||
if (access)
|
if (access)
|
||||||
|
@ -213,9 +213,7 @@ Vio *vio_new(my_socket sd, enum enum_vio_type type, uint flags)
|
|||||||
if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
|
if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
|
||||||
{
|
{
|
||||||
vio_init(vio, type, sd, 0, flags);
|
vio_init(vio, type, sd, 0, flags);
|
||||||
sprintf(vio->desc,
|
vio->desc= (vio->type == VIO_TYPE_SOCKET ? "socket" : "TCP/IP");
|
||||||
(vio->type == VIO_TYPE_SOCKET ? "socket (%d)" : "TCP/IP (%d)"),
|
|
||||||
vio->sd);
|
|
||||||
#if !defined(__WIN__)
|
#if !defined(__WIN__)
|
||||||
#if !defined(NO_FCNTL_NONBLOCK)
|
#if !defined(NO_FCNTL_NONBLOCK)
|
||||||
/*
|
/*
|
||||||
@ -257,7 +255,7 @@ Vio *vio_new_win32pipe(HANDLE hPipe)
|
|||||||
if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
|
if ((vio = (Vio*) my_malloc(sizeof(Vio),MYF(MY_WME))))
|
||||||
{
|
{
|
||||||
vio_init(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, VIO_LOCALHOST);
|
vio_init(vio, VIO_TYPE_NAMEDPIPE, 0, hPipe, VIO_LOCALHOST);
|
||||||
strmov(vio->desc, "named pipe");
|
vio->desc= "named pipe";
|
||||||
}
|
}
|
||||||
DBUG_RETURN(vio);
|
DBUG_RETURN(vio);
|
||||||
}
|
}
|
||||||
@ -282,7 +280,7 @@ Vio *vio_new_win32shared_memory(HANDLE handle_file_map, HANDLE handle_map,
|
|||||||
vio->event_conn_closed= event_conn_closed;
|
vio->event_conn_closed= event_conn_closed;
|
||||||
vio->shared_memory_remain= 0;
|
vio->shared_memory_remain= 0;
|
||||||
vio->shared_memory_pos= handle_map;
|
vio->shared_memory_pos= handle_map;
|
||||||
strmov(vio->desc, "shared memory");
|
vio->desc= "shared memory";
|
||||||
}
|
}
|
||||||
DBUG_RETURN(vio);
|
DBUG_RETURN(vio);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user