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
cfa56f90
Commit
cfa56f90
authored
Feb 16, 2012
by
Vladislav Vaintroub
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
address second round review comments
parent
8877fe73
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
103 additions
and
81 deletions
+103
-81
mysys/thr_lock.c
mysys/thr_lock.c
+1
-3
sql/scheduler.cc
sql/scheduler.cc
+8
-8
sql/scheduler.h
sql/scheduler.h
+1
-0
sql/sql_class.cc
sql/sql_class.cc
+21
-9
sql/sql_class.h
sql/sql_class.h
+2
-0
sql/threadpool.h
sql/threadpool.h
+1
-2
sql/threadpool_common.cc
sql/threadpool_common.cc
+9
-9
sql/threadpool_unix.cc
sql/threadpool_unix.cc
+60
-50
No files found.
mysys/thr_lock.c
View file @
cfa56f90
...
...
@@ -483,7 +483,7 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
struct
timespec
wait_timeout
;
enum
enum_thr_lock_result
result
=
THR_LOCK_ABORTED
;
const
char
*
old_proc_info
;
my_bool
use_wait_callbacks
;
my_bool
use_wait_callbacks
=
FALSE
;
DBUG_ENTER
(
"wait_for_lock"
);
/*
...
...
@@ -540,8 +540,6 @@ wait_for_lock(struct st_lock_list *wait, THR_LOCK_DATA *data,
use_wait_callbacks
=
TRUE
;
(
*
before_lock_wait
)();
}
else
use_wait_callbacks
=
FALSE
;
set_timespec
(
wait_timeout
,
lock_wait_timeout
);
while
(
!
thread_var
->
abort
||
in_wait_list
)
...
...
sql/scheduler.cc
View file @
cfa56f90
...
...
@@ -48,26 +48,26 @@ extern "C"
{
static
void
scheduler_wait_lock_begin
(
void
)
{
THD
*
thd
=
current_thd
;
scheduler_functions
*
func
=
thd
->
scheduler
;
MYSQL_CALLBACK
(
func
,
thd_wait_begin
,
(
thd
,
THD_WAIT_TABLE_LOCK
));
if
(
thd
)
MYSQL_CALLBACK
(
thd
->
scheduler
,
thd_wait_begin
,
(
thd
,
THD_WAIT_TABLE_LOCK
));
}
static
void
scheduler_wait_lock_end
(
void
)
{
THD
*
thd
=
current_thd
;
scheduler_functions
*
func
=
thd
->
scheduler
;
MYSQL_CALLBACK
(
func
,
thd_wait_end
,
(
thd
));
if
(
thd
)
MYSQL_CALLBACK
(
thd
->
scheduler
,
thd_wait_end
,
(
thd
));
}
static
void
scheduler_wait_sync_begin
(
void
)
{
THD
*
thd
=
current_thd
;
scheduler_functions
*
func
=
thd
?
thd
->
scheduler
:
thread_scheduler
;
MYSQL_CALLBACK
(
func
,
thd_wait_begin
,
(
thd
,
THD_WAIT_TABLE_LOCK
));
if
(
thd
)
MYSQL_CALLBACK
(
thd
->
scheduler
,
thd_wait_begin
,
(
thd
,
THD_WAIT_TABLE_LOCK
));
}
static
void
scheduler_wait_sync_end
(
void
)
{
THD
*
thd
=
current_thd
;
scheduler_functions
*
func
=
thd
?
thd
->
scheduler
:
thread_scheduler
;
MYSQL_CALLBACK
(
func
,
thd_wait_end
,
(
thd
));
if
(
thd
)
MYSQL_CALLBACK
(
thd
->
scheduler
,
thd_wait_end
,
(
thd
));
}
};
/**@}*/
...
...
sql/scheduler.h
View file @
cfa56f90
...
...
@@ -76,6 +76,7 @@ void one_thread_per_connection_scheduler(scheduler_functions *func,
ulong
*
arg_max_connections
,
uint
*
arg_connection_count
);
void
one_thread_scheduler
(
scheduler_functions
*
func
);
extern
void
scheduler_init
();
/*
To be used for pool-of-threads (implemeneted differently on various OSs)
...
...
sql/sql_class.cc
View file @
cfa56f90
...
...
@@ -1523,7 +1523,7 @@ void THD::awake(killed_state state_to_set)
if
(
state_to_set
>=
KILL_CONNECTION
||
state_to_set
==
NOT_KILLED
)
{
#ifdef SIGNAL_WITH_VIO_CLOSE
if
(
this
!=
current_thd
)
if
(
this
!=
current_thd
)
{
if
(
active_vio
)
vio_shutdown
(
active_vio
,
SHUT_RDWR
);
...
...
@@ -3935,10 +3935,16 @@ extern "C" bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd)
*/
extern
"C"
void
thd_wait_begin
(
MYSQL_THD
thd
,
int
wait_type
)
{
if
(
!
thd
)
thd
=
current_thd
;
if
(
thd
)
MYSQL_CALLBACK
(
thd
->
scheduler
,
thd_wait_begin
,
(
thd
,
wait_type
));
if
(
unlikely
(
!
thread_scheduler
)
||
!
thread_scheduler
->
thd_wait_begin
)
return
;
if
(
thd
==
NULL
)
{
thd
=
current_thd
;
if
(
unlikely
(
thd
==
NULL
))
return
;
}
MYSQL_CALLBACK
(
thd
->
scheduler
,
thd_wait_begin
,
(
thd
,
wait_type
));
}
/**
...
...
@@ -3950,10 +3956,16 @@ extern "C" void thd_wait_begin(MYSQL_THD thd, int wait_type)
*/
extern
"C"
void
thd_wait_end
(
MYSQL_THD
thd
)
{
if
(
!
thd
)
thd
=
current_thd
;
if
(
thd
)
MYSQL_CALLBACK
(
thd
->
scheduler
,
thd_wait_end
,
(
thd
));
if
(
unlikely
(
!
thread_scheduler
)
||
!
thread_scheduler
->
thd_wait_begin
)
return
;
if
(
thd
==
NULL
)
{
thd
=
current_thd
;
if
(
unlikely
(
thd
==
NULL
))
return
;
}
if
(
likely
(
thd
->
scheduler
==
thread_scheduler
))
thread_scheduler
->
thd_wait_end
(
thd
);
}
#endif // INNODB_COMPATIBILITY_HOOKS */
...
...
sql/sql_class.h
View file @
cfa56f90
...
...
@@ -4278,6 +4278,8 @@ inline int handler::ha_update_tmp_row(const uchar *old_data, uchar *new_data)
return
error
;
}
extern
pthread_attr_t
*
get_connection_attrib
(
void
);
#endif
/* MYSQL_SERVER */
#endif
/* SQL_CLASS_INCLUDED */
sql/threadpool.h
View file @
cfa56f90
...
...
@@ -46,11 +46,10 @@ extern TP_STATISTICS tp_stats;
/* Functions to set threadpool parameters */
extern
void
tp_set_min_threads
(
uint
val
);
extern
void
tp_set_max_threads
(
uint
val
);
extern
int
tp_set_threadpool_size
(
uint
val
);
extern
void
tp_set_threadpool_size
(
uint
val
);
extern
void
tp_set_threadpool_stall_limit
(
uint
val
);
/* Activate threadpool scheduler */
extern
void
tp_scheduler
(
void
);
extern
int
show_threadpool_idle_threads
(
THD
*
thd
,
SHOW_VAR
*
var
,
char
*
buff
);
sql/threadpool_common.cc
View file @
cfa56f90
...
...
@@ -136,7 +136,7 @@ int threadpool_add_connection(THD *thd)
{
retval
=
0
;
thd
->
net
.
reading_or_writing
=
1
;
thd
->
skip_wait_timeout
=
true
;
thd
->
skip_wait_timeout
=
true
;
}
}
}
...
...
@@ -185,10 +185,11 @@ int threadpool_process_request(THD *thd)
killed flag was set by timeout handler
or KILL command. Return error.
*/
worker_context
.
restore
()
;
return
1
;
retval
=
1
;
goto
end
;
}
for
(;;)
{
Vio
*
vio
;
...
...
@@ -196,12 +197,12 @@ int threadpool_process_request(THD *thd)
mysql_audit_release
(
thd
);
if
((
retval
=
do_command
(
thd
))
!=
0
)
break
;
goto
end
;
if
(
!
thd_is_connection_alive
(
thd
))
{
retval
=
1
;
break
;
goto
end
;
}
vio
=
thd
->
net
.
vio
;
...
...
@@ -210,10 +211,11 @@ int threadpool_process_request(THD *thd)
/* More info on this debug sync is in sql_parse.cc*/
DEBUG_SYNC
(
thd
,
"before_do_command_net_read"
);
thd
->
net
.
reading_or_writing
=
1
;
break
;
goto
end
;
}
}
}
end:
worker_context
.
restore
();
return
retval
;
}
...
...
@@ -234,8 +236,6 @@ static scheduler_functions tp_scheduler_functions=
tp_end
// end
};
extern
void
scheduler_init
();
void
pool_of_threads_scheduler
(
struct
scheduler_functions
*
func
,
ulong
*
arg_max_connections
,
uint
*
arg_connection_count
)
...
...
sql/threadpool_unix.cc
View file @
cfa56f90
...
...
@@ -24,6 +24,11 @@ typedef struct kevent native_event;
typedef
port_event_t
native_event
;
#endif
/** Maximum number of native events a listener can read in one go */
#define MAX_EVENTS 1024
/** Indicates that threadpool was initialized*/
static
bool
threadpool_started
=
false
;
/*
Define PSI Keys for performance schema.
...
...
@@ -130,7 +135,7 @@ static uint group_count;
Used for printing "pool blocked" message, see
print_pool_blocked_message();
*/
static
time_t
pool_block_start
;
static
ulonglong
pool_block_start
;
/* Global timer for all groups */
struct
pool_timer_t
...
...
@@ -145,11 +150,6 @@ struct pool_timer_t
static
pool_timer_t
pool_timer
;
/* Externals functions and variables we use */
extern
void
scheduler_init
();
extern
pthread_attr_t
*
get_connection_attrib
(
void
);
static
void
queue_put
(
thread_group_t
*
thread_group
,
connection_t
*
connection
);
static
int
wake_thread
(
thread_group_t
*
thread_group
);
static
void
handle_event
(
connection_t
*
connection
);
...
...
@@ -462,6 +462,9 @@ static void timeout_check(pool_timer_t *timer)
Besides checking for stalls, timer thread is also responsible for terminating
clients that have been idle for longer than wait_timeout seconds.
TODO: Let the timer sleep for long time if there is no work to be done.
Currently it wakes up rather often on and idle server.
*/
static
void
*
timer_thread
(
void
*
param
)
...
...
@@ -491,7 +494,7 @@ static void* timer_thread(void *param)
{
timer
->
current_microtime
=
microsecond_interval_timer
();
/* Check stall
l
s in thread groups */
/* Check stalls in thread groups */
for
(
i
=
0
;
i
<
array_elements
(
all_groups
);
i
++
)
{
if
(
all_groups
[
i
].
connection_count
)
...
...
@@ -574,7 +577,6 @@ static void stop_timer(pool_timer_t *timer)
DBUG_VOID_RETURN
;
}
#define MAX_EVENTS 1024
/**
Poll for socket events and distribute them to worker threads
...
...
@@ -586,10 +588,8 @@ static connection_t * listener(worker_thread_t *current_thread,
thread_group_t
*
thread_group
)
{
DBUG_ENTER
(
"listener"
);
connection_t
*
retval
=
NULL
;
for
(;;)
{
native_event
ev
[
MAX_EVENTS
];
...
...
@@ -767,7 +767,6 @@ static int create_worker(thread_group_t *thread_group)
{
my_errno
=
errno
;
}
end:
if
(
err
)
...
...
@@ -897,11 +896,10 @@ static int wake_thread(thread_group_t *thread_group)
{
thread
->
woken
=
true
;
thread_group
->
waiting_threads
.
remove
(
thread
);
if
(
mysql_cond_signal
(
&
thread
->
cond
))
abort
();
mysql_cond_signal
(
&
thread
->
cond
);
DBUG_RETURN
(
0
);
}
DBUG_RETURN
(
-
1
);
/* no thread- missed wakeup
*/
DBUG_RETURN
(
1
);
/* no thread in waiter list => missed wakeup
*/
}
...
...
@@ -1188,7 +1186,7 @@ void tp_add_connection(THD *thd)
/* Assign connection to a group. */
thread_group_t
*
group
=
&
all_groups
[
connection
->
thd
->
thread_id
%
group_count
];
&
all_groups
[
thd
->
thread_id
%
group_count
];
connection
->
thread_group
=
group
;
...
...
@@ -1416,12 +1414,13 @@ static void handle_event(connection_t *connection)
err
=
threadpool_process_request
(
connection
->
thd
);
}
if
(
!
err
)
{
set_wait_timeout
(
connection
);
err
=
start_io
(
connection
);
}
if
(
err
)
goto
end
;
set_wait_timeout
(
connection
);
err
=
start_io
(
connection
);
end:
if
(
err
)
connection_abort
(
connection
);
...
...
@@ -1481,11 +1480,10 @@ static void *worker_main(void *param)
}
static
bool
started
=
false
;
bool
tp_init
()
{
DBUG_ENTER
(
"tp_init"
);
started
=
true
;
threadpool_started
=
true
;
scheduler_init
();
for
(
uint
i
=
0
;
i
<
array_elements
(
all_groups
);
i
++
)
...
...
@@ -1493,7 +1491,12 @@ bool tp_init()
thread_group_init
(
&
all_groups
[
i
],
get_connection_attrib
());
}
tp_set_threadpool_size
(
threadpool_size
);
if
(
group_count
==
0
)
{
/* Something went wrong */
sql_print_error
(
"Can't set threadpool size to %d"
,
threadpool_size
);
DBUG_RETURN
(
1
);
}
PSI_register
(
mutex
);
PSI_register
(
cond
);
PSI_register
(
thread
);
...
...
@@ -1508,7 +1511,7 @@ void tp_end()
{
DBUG_ENTER
(
"tp_end"
);
if
(
!
started
)
if
(
!
threadpool_
started
)
DBUG_VOID_RETURN
;
stop_timer
(
&
pool_timer
);
...
...
@@ -1516,18 +1519,18 @@ void tp_end()
{
thread_group_close
(
&
all_groups
[
i
]);
}
started
=
false
;
threadpool_
started
=
false
;
DBUG_VOID_RETURN
;
}
/** Ensure that poll descriptors are created when threadpool_size changes */
int
tp_set_threadpool_size
(
uint
size
)
void
tp_set_threadpool_size
(
uint
size
)
{
bool
success
=
true
;
if
(
!
started
)
return
0
;
if
(
!
threadpool_
started
)
return
;
for
(
uint
i
=
0
;
i
<
size
;
i
++
)
{
...
...
@@ -1537,21 +1540,25 @@ int tp_set_threadpool_size(uint size)
{
group
->
pollfd
=
io_poll_create
();
success
=
(
group
->
pollfd
>=
0
);
if
(
!
success
)
{
sql_print_error
(
"io_poll_create() failed, errno=%d
\n
"
,
errno
);
break
;
}
}
mysql_mutex_unlock
(
&
all_groups
[
i
].
mutex
);
if
(
!
success
)
{
group_count
=
i
-
1
;
return
-
1
;
group_count
=
i
;
return
;
}
}
group_count
=
size
;
return
0
;
}
void
tp_set_threadpool_stall_limit
(
uint
limit
)
{
if
(
!
started
)
if
(
!
threadpool_
started
)
return
;
mysql_mutex_lock
(
&
(
pool_timer
.
mutex
));
pool_timer
.
tick_interval
=
limit
;
...
...
@@ -1582,20 +1589,23 @@ int tp_get_idle_thread_count()
/* Report threadpool problems */
#define BLOCK_MSG_DELAY 30
/**
Delay in microseconds, after which "pool blocked" message is printed.
(30 sec == 30 Mio usec)
*/
#define BLOCK_MSG_DELAY 30*1000000
static
const
char
*
max_threads_reached_msg
=
"Threadpool could not create additional thread to handle queries, because the
"
"number of allowed threads was reached. Increasing 'thread_pool_max_threads' "
"parameter can help in this situation.
\n
"
"If 'extra_port' parameter is set, you can still connect to the database with "
"superuser account (it must be TCP connection using extra_port as TCP port) "
"and troubleshoot the situation. "
"A likely cause of pool blocks are clients that lock resources for long time. "
"'show processlist' or 'show engine innodb status' can give additional hints."
;
#define MAX_THREADS_REACHED_MSG \
"Threadpool could not create additional thread to handle queries, because the
\
number of allowed threads was reached. Increasing 'thread_pool_max_threads' \
parameter can help in this situation.\n \
If 'extra_port' parameter is set, you can still connect to the database with \
superuser account (it must be TCP connection using extra_port as TCP port) \
and troubleshoot the situation. \
A likely cause of pool blocks are clients that lock resources for long time. \
'show processlist' or 'show engine innodb status' can give additional hints."
static
const
char
*
create_thread_error_msg
=
"Can't create threads in threadpool (errno=%d)."
;
#define CREATE_THREAD_ERROR_MSG "Can't create threads in threadpool (errno=%d)."
/**
Write a message when blocking situation in threadpool occurs.
...
...
@@ -1606,10 +1616,10 @@ static const char *create_thread_error_msg=
static
void
print_pool_blocked_message
(
bool
max_threads_reached
)
{
time_t
now
;
ulonglong
now
;
static
bool
msg_written
;
now
=
time
(
NULL
);
now
=
microsecond_interval_timer
(
);
if
(
pool_block_start
==
0
)
{
pool_block_start
=
now
;
...
...
@@ -1620,12 +1630,12 @@ static void print_pool_blocked_message(bool max_threads_reached)
if
(
now
>
pool_block_start
+
BLOCK_MSG_DELAY
&&
!
msg_written
)
{
if
(
max_threads_reached
)
sql_print_error
(
max_threads_reached_msg
);
sql_print_error
(
MAX_THREADS_REACHED_MSG
);
else
sql_print_error
(
create_thread_error_msg
,
my_errno
);
sql_print_error
(
CREATE_THREAD_ERROR_MSG
,
my_errno
);
sql_print_information
(
"Threadpool has been blocked for %u seconds
\n
"
,
(
uint
)(
now
-
pool_block_start
));
(
uint
)(
(
now
-
pool_block_start
)
/
1000000
));
/* avoid reperated messages for the same blocking situation */
msg_written
=
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