summaryrefslogtreecommitdiff
path: root/sql/slave.cc
diff options
context:
space:
mode:
authorKristian Nielsen <knielsen@knielsen-hq.org>2014-07-08 12:54:47 +0200
committerKristian Nielsen <knielsen@knielsen-hq.org>2014-07-08 12:54:47 +0200
commit98fc5b3af8b1954e4480ac33d30493aa4de66ec4 (patch)
tree1177381a922f146c32444cc44d5564fbd0f10d8f /sql/slave.cc
parente5149fa0d905c6702bd6dcc64c5e3194b6a630fc (diff)
downloadmariadb-git-98fc5b3af8b1954e4480ac33d30493aa4de66ec4.tar.gz
MDEV-5262, MDEV-5914, MDEV-5941, MDEV-6020: Deadlocks during parallel replication causing replication to fail.
After-review changes. For this patch in 10.0, we do not introduce a new public storage engine API, we just fix the InnoDB/XtraDB issues. In 10.1, we will make a better public API that can be used for all storage engines (MDEV-6429). Eliminate the background thread that did deadlock kills asynchroneously. Instead, we ensure that the InnoDB/XtraDB code can handle doing the kill from inside the deadlock detection code (when thd_report_wait_for() needs to kill a later thread to resolve a deadlock). (We preserve the part of the original patch that introduces dedicated mutex and condition for the slave init thread, to remove the abuse of LOCK_thread_count for start/stop synchronisation of the slave init thread).
Diffstat (limited to 'sql/slave.cc')
-rw-r--r--sql/slave.cc131
1 files changed, 21 insertions, 110 deletions
diff --git a/sql/slave.cc b/sql/slave.cc
index 8cc0c99d049..2f832309d94 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -287,22 +287,13 @@ static void init_slave_psi_keys(void)
#endif /* HAVE_PSI_INTERFACE */
-static bool slave_background_thread_running;
-static bool slave_background_thread_stop;
-static bool slave_background_thread_gtid_loaded;
-
-struct slave_background_kill_t {
- slave_background_kill_t *next;
- THD *to_kill;
-} *slave_background_kill_list;
+static bool slave_init_thread_running;
pthread_handler_t
-handle_slave_background(void *arg __attribute__((unused)))
+handle_slave_init(void *arg __attribute__((unused)))
{
THD *thd;
- PSI_stage_info old_stage;
- bool stop;
my_thread_init();
thd= new THD;
@@ -310,7 +301,7 @@ handle_slave_background(void *arg __attribute__((unused)))
mysql_mutex_lock(&LOCK_thread_count);
thd->thread_id= thread_id++;
mysql_mutex_unlock(&LOCK_thread_count);
- thd->system_thread = SYSTEM_THREAD_SLAVE_BACKGROUND;
+ thd->system_thread = SYSTEM_THREAD_SLAVE_INIT;
thd->store_globals();
thd->security_ctx->skip_grants();
thd->set_command(COM_DAEMON);
@@ -323,126 +314,49 @@ handle_slave_background(void *arg __attribute__((unused)))
thd->get_stmt_da()->sql_errno(),
thd->get_stmt_da()->message());
- mysql_mutex_lock(&LOCK_slave_background);
- slave_background_thread_gtid_loaded= true;
- mysql_cond_broadcast(&COND_slave_background);
-
- THD_STAGE_INFO(thd, stage_slave_background_process_request);
- do
- {
- slave_background_kill_t *kill_list;
-
- thd->ENTER_COND(&COND_slave_background, &LOCK_slave_background,
- &stage_slave_background_wait_request,
- &old_stage);
- for (;;)
- {
- stop= abort_loop || thd->killed || slave_background_thread_stop;
- kill_list= slave_background_kill_list;
- if (stop || kill_list)
- break;
- mysql_cond_wait(&COND_slave_background, &LOCK_slave_background);
- }
-
- slave_background_kill_list= NULL;
- thd->EXIT_COND(&old_stage);
-
- while (kill_list)
- {
- slave_background_kill_t *p = kill_list;
- kill_list= p->next;
-
- mysql_mutex_lock(&p->to_kill->LOCK_thd_data);
- p->to_kill->awake(KILL_CONNECTION);
- mysql_mutex_unlock(&p->to_kill->LOCK_thd_data);
- my_free(p);
- }
- mysql_mutex_lock(&LOCK_slave_background);
- } while (!stop);
-
- slave_background_thread_running= false;
- mysql_cond_broadcast(&COND_slave_background);
- mysql_mutex_unlock(&LOCK_slave_background);
-
mysql_mutex_lock(&LOCK_thread_count);
delete thd;
mysql_mutex_unlock(&LOCK_thread_count);
my_thread_end();
- return 0;
-}
+ mysql_mutex_lock(&LOCK_slave_init);
+ slave_init_thread_running= false;
+ mysql_cond_broadcast(&COND_slave_init);
+ mysql_mutex_unlock(&LOCK_slave_init);
-
-void
-slave_background_kill_request(THD *to_kill)
-{
- slave_background_kill_t *p=
- (slave_background_kill_t *)my_malloc(sizeof(*p), MYF(MY_WME));
- if (p)
- {
- p->to_kill= to_kill;
- to_kill->rgi_slave->killed_for_retry= true;
- mysql_mutex_lock(&LOCK_slave_background);
- p->next= slave_background_kill_list;
- slave_background_kill_list= p;
- mysql_mutex_unlock(&LOCK_slave_background);
- mysql_cond_signal(&COND_slave_background);
- }
+ return 0;
}
/*
- Start the slave background thread.
-
- This thread is currently used for two purposes:
+ Start the slave init thread.
- 1. To load the GTID state from mysql.gtid_slave_pos at server start; reading
- from table requires valid THD, which is otherwise not available during
- server init.
-
- 2. To kill worker thread transactions during parallel replication, when a
- storage engine attempts to take an errorneous conflicting lock that would
- cause a deadlock. Killing is done asynchroneously, as the kill may not
- be safe within the context of a callback from inside storage engine
- locking code.
+ This thread is used to load the GTID state from mysql.gtid_slave_pos at
+ server start; reading from table requires valid THD, which is otherwise not
+ available during server init.
*/
static int
-start_slave_background_thread()
+run_slave_init_thread()
{
pthread_t th;
- slave_background_thread_running= true;
- slave_background_thread_stop= false;
- slave_background_thread_gtid_loaded= false;
- if (mysql_thread_create(key_thread_slave_background,
- &th, &connection_attrib, handle_slave_background,
- NULL))
+ slave_init_thread_running= true;
+ if (mysql_thread_create(key_thread_slave_init, &th, &connection_attrib,
+ handle_slave_init, NULL))
{
sql_print_error("Failed to create thread while initialising slave");
return 1;
}
- mysql_mutex_lock(&LOCK_slave_background);
- while (!slave_background_thread_gtid_loaded)
- mysql_cond_wait(&COND_slave_background, &LOCK_slave_background);
- mysql_mutex_unlock(&LOCK_slave_background);
+ mysql_mutex_lock(&LOCK_slave_init);
+ while (!slave_init_thread_running)
+ mysql_cond_wait(&COND_slave_init, &LOCK_slave_init);
+ mysql_mutex_unlock(&LOCK_slave_init);
return 0;
}
-static void
-stop_slave_background_thread()
-{
- mysql_mutex_lock(&LOCK_slave_background);
- slave_background_thread_stop= true;
- mysql_cond_broadcast(&COND_slave_background);
- while (slave_background_thread_running)
- mysql_cond_wait(&COND_slave_background, &LOCK_slave_background);
- mysql_mutex_unlock(&LOCK_slave_background);
-}
-
-
/* Initialize slave structures */
int init_slave()
@@ -454,7 +368,7 @@ int init_slave()
init_slave_psi_keys();
#endif
- if (start_slave_background_thread())
+ if (run_slave_init_thread())
return 1;
/*
@@ -1084,9 +998,6 @@ void end_slave()
master_info_index= 0;
active_mi= 0;
mysql_mutex_unlock(&LOCK_active_mi);
-
- stop_slave_background_thread();
-
global_rpl_thread_pool.destroy();
free_all_rpl_filters();
DBUG_VOID_RETURN;