1
diff -ruN a/storage/innodb_plugin/handler/ha_innodb.cc b/storage/innodb_plugin/handler/ha_innodb.cc
2
--- a/storage/innodb_plugin/handler/ha_innodb.cc 2010-04-30 14:13:25.000000000 +0900
3
+++ b/storage/innodb_plugin/handler/ha_innodb.cc 2010-04-30 14:13:51.000000000 +0900
4
@@ -10721,6 +10721,11 @@
5
"Output statistics of recovery process after it.",
8
+static MYSQL_SYSVAR_ULONG(use_purge_thread, srv_use_purge_thread,
9
+ PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
10
+ "Number of purge devoted threads. #### over 1 is EXPERIMENTAL ####",
11
+ NULL, NULL, 0, 0, 64, 0);
13
static MYSQL_SYSVAR_BOOL(overwrite_relay_log_info, innobase_overwrite_relay_log_info,
14
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
15
"During InnoDB crash recovery on slave overwrite relay-log.info "
16
@@ -11222,6 +11227,7 @@
17
MYSQL_SYSVAR(change_buffering),
18
MYSQL_SYSVAR(read_ahead_threshold),
19
MYSQL_SYSVAR(io_capacity),
20
+ MYSQL_SYSVAR(use_purge_thread),
24
diff -ruN a/storage/innodb_plugin/handler/innodb_patch_info.h b/storage/innodb_plugin/handler/innodb_patch_info.h
25
--- a/storage/innodb_plugin/handler/innodb_patch_info.h 2010-04-30 14:13:25.000000000 +0900
26
+++ b/storage/innodb_plugin/handler/innodb_patch_info.h 2010-04-30 14:13:51.000000000 +0900
28
{"innodb_split_buf_pool_mutex","More fix of buffer_pool mutex","Spliting buf_pool_mutex and optimizing based on innodb_opt_lru_count","http://www.percona.com/docs/wiki/percona-xtradb"},
29
{"innodb_stats","Additional features about InnoDB statistics/optimizer","","http://www.percona.com/docs/wiki/percona-xtradb"},
30
{"innodb_recovery_patches","Bugfixes and adjustments about recovery process","","http://www.percona.com/docs/wiki/percona-xtradb"},
31
+{"innodb_purge_thread","Enable to use purge devoted thread","","http://www.percona.com/docs/wiki/percona-xtradb"},
32
{NULL, NULL, NULL, NULL}
34
diff -ruN a/storage/innodb_plugin/include/srv0srv.h b/storage/innodb_plugin/include/srv0srv.h
35
--- a/storage/innodb_plugin/include/srv0srv.h 2010-04-30 14:13:25.000000000 +0900
36
+++ b/storage/innodb_plugin/include/srv0srv.h 2010-04-30 14:13:51.000000000 +0900
38
extern ibool srv_fast_recovery;
39
extern ibool srv_recovery_stats;
41
+extern ulint srv_use_purge_thread;
43
extern ibool srv_auto_extend_last_data_file;
44
extern ulint srv_last_file_size_max;
45
extern char** srv_log_group_home_dirs;
47
SRV_RECOVERY, /**< threads finishing a recovery */
48
SRV_INSERT, /**< thread flushing the insert buffer to disk */
50
+ SRV_PURGE, /* thread purging undo records */
51
+ SRV_PURGE_WORKER, /* thread purging undo records */
52
SRV_MASTER /**< the master thread, (whose type number must
57
void* arg); /*!< in: a dummy parameter required by
59
+/*************************************************************************
60
+The undo purge thread. */
65
+ void* arg); /* in: a dummy parameter required by
67
+/*************************************************************************
68
+The undo purge thread. */
71
+srv_purge_worker_thread(
72
+/*====================*/
74
/*******************************************************************//**
75
Tells the Innobase server that there has been activity in the database
76
and wakes up the master thread if it is suspended (not sleeping). Used
77
diff -ruN a/storage/innodb_plugin/include/trx0purge.h b/storage/innodb_plugin/include/trx0purge.h
78
--- a/storage/innodb_plugin/include/trx0purge.h 2010-04-06 23:07:13.000000000 +0900
79
+++ b/storage/innodb_plugin/include/trx0purge.h 2010-04-30 14:13:51.000000000 +0900
84
+/**********************************************************************
85
+This function runs a purge worker batch */
91
+/**********************************************************************
92
+This function waits the event for worker batch */
95
+trx_purge_worker_wait(void);
96
+/*========================*/
97
+/**********************************************************************
98
+This function wakes the waiting worker batch */
101
+trx_purge_worker_wake(void);
102
+/*========================*/
103
/******************************************************************//**
104
Prints information of the purge system to stderr. */
107
of the trx system and it never ends */
108
que_t* query; /*!< The query graph which will do the
109
parallelized purge operation */
111
+ os_event_t worker_event;
115
rw_lock_t latch; /*!< The latch protecting the purge view.
116
A purge operation must acquire an
117
x-latch here for the instant at which
118
diff -ruN a/storage/innodb_plugin/log/log0log.c b/storage/innodb_plugin/log/log0log.c
119
--- a/storage/innodb_plugin/log/log0log.c 2010-04-29 15:55:25.000000000 +0900
120
+++ b/storage/innodb_plugin/log/log0log.c 2010-04-30 14:13:51.000000000 +0900
121
@@ -3147,6 +3147,16 @@
125
+ /* Check that the purge threads ended */
126
+ if (srv_use_purge_thread
127
+ && (srv_n_threads_active[SRV_PURGE] != 0
128
+ || srv_n_threads_active[SRV_PURGE_WORKER] != 0)) {
130
+ mutex_exit(&kernel_mutex);
135
mutex_exit(&kernel_mutex);
137
mutex_enter(&(log_sys->mutex));
138
diff -ruN a/storage/innodb_plugin/srv/srv0srv.c b/storage/innodb_plugin/srv/srv0srv.c
139
--- a/storage/innodb_plugin/srv/srv0srv.c 2010-04-30 14:13:25.000000000 +0900
140
+++ b/storage/innodb_plugin/srv/srv0srv.c 2010-04-30 14:13:51.000000000 +0900
142
UNIV_INTERN ibool srv_fast_recovery = FALSE;
143
UNIV_INTERN ibool srv_recovery_stats = FALSE;
145
+UNIV_INTERN ulint srv_use_purge_thread = 0;
147
/* if TRUE, then we auto-extend the last data file */
148
UNIV_INTERN ibool srv_auto_extend_last_data_file = FALSE;
149
/* if != 0, this tells the max size auto-extending may increase the
150
@@ -2609,10 +2611,10 @@
151
srv_main_thread_process_no = os_proc_get_number();
152
srv_main_thread_id = os_thread_pf(os_thread_get_curr_id());
154
- srv_table_reserve_slot(SRV_MASTER);
156
mutex_enter(&kernel_mutex);
158
+ srv_table_reserve_slot(SRV_MASTER);
159
srv_n_threads_active[SRV_MASTER]++;
161
mutex_exit(&kernel_mutex);
162
@@ -2942,6 +2944,7 @@
163
/* Flush logs if needed */
164
srv_sync_log_buffer_in_background();
166
+ if (!srv_use_purge_thread) {
167
/* We run a full purge every 10 seconds, even if the server
170
@@ -2958,6 +2961,7 @@
171
srv_sync_log_buffer_in_background();
173
} while (n_pages_purged);
176
srv_main_thread_op_info = "flushing buffer pool pages";
178
@@ -3026,6 +3030,7 @@
179
os_thread_sleep(100000);
182
+ if (!srv_use_purge_thread) {
183
srv_main_thread_op_info = "purging";
185
/* Run a full purge */
186
@@ -3042,6 +3047,7 @@
187
srv_sync_log_buffer_in_background();
189
} while (n_pages_purged);
192
srv_main_thread_op_info = "reserving kernel mutex";
194
@@ -3194,3 +3200,143 @@
196
OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */
199
+/*************************************************************************
200
+A thread which is devoted to purge, for take over the master thread's
206
+ void* arg __attribute__((unused)))
207
+ /* in: a dummy parameter required by os_thread_create */
209
+ ulint n_pages_purged;
210
+ ulint n_pages_purged_sum = 1; /* dummy */
212
+ ulint sleep_ms= 10000; /* initial: 10 sec. */
213
+ ibool can_be_last = FALSE;
215
+#ifdef UNIV_DEBUG_THREAD_CREATION
216
+ fprintf(stderr, "Purge thread starts, id %lu\n",
217
+ os_thread_pf(os_thread_get_curr_id()));
220
+ mutex_enter(&kernel_mutex);
221
+ srv_table_reserve_slot(SRV_PURGE);
222
+ srv_n_threads_active[SRV_PURGE]++;
223
+ mutex_exit(&kernel_mutex);
226
+ if (srv_shutdown_state > 0) {
227
+ if (srv_fast_shutdown) {
228
+ /* someone other should wait the end of the workers */
232
+ mutex_enter(&kernel_mutex);
233
+ if (srv_n_threads_active[SRV_PURGE_WORKER]) {
234
+ can_be_last = FALSE;
236
+ can_be_last = TRUE;
238
+ mutex_exit(&kernel_mutex);
243
+ os_thread_sleep( sleep_ms * 1000 );
245
+ history_len = trx_sys->rseg_history_len;
246
+ if (history_len > 1000)
251
+ n_pages_purged_sum = 0;
254
+ if (srv_fast_shutdown && srv_shutdown_state > 0) {
257
+ n_pages_purged = trx_purge();
258
+ n_pages_purged_sum += n_pages_purged;
259
+ } while (n_pages_purged);
261
+ if (srv_shutdown_state > 0 && can_be_last) {
262
+ /* the last trx_purge() is executed without workers */
266
+ if (n_pages_purged_sum) {
267
+ srv_active_wake_master_thread();
270
+ if (n_pages_purged_sum == 0)
272
+ if (sleep_ms > 10000)
278
+ trx_purge_worker_wake(); /* It may not make sense. for safety only */
280
+ /* wake master thread to flush the pages */
281
+ srv_wake_master_thread();
283
+ mutex_enter(&kernel_mutex);
284
+ srv_n_threads_active[SRV_PURGE]--;
285
+ mutex_exit(&kernel_mutex);
286
+ os_thread_exit(NULL);
288
+ OS_THREAD_DUMMY_RETURN;
291
+/*************************************************************************
292
+A thread which is devoted to purge, for take over the master thread's
296
+srv_purge_worker_thread(
297
+/*====================*/
300
+ ulint worker_id; /* index for array */
302
+ worker_id = *((ulint*)arg);
304
+#ifdef UNIV_DEBUG_THREAD_CREATION
305
+ fprintf(stderr, "Purge worker thread starts, id %lu\n",
306
+ os_thread_pf(os_thread_get_curr_id()));
308
+ mutex_enter(&kernel_mutex);
309
+ srv_table_reserve_slot(SRV_PURGE_WORKER);
310
+ srv_n_threads_active[SRV_PURGE_WORKER]++;
311
+ mutex_exit(&kernel_mutex);
314
+ /* purge worker threads only works when srv_shutdown_state==0 */
315
+ /* for safety and exactness. */
316
+ if (srv_shutdown_state > 0) {
320
+ trx_purge_worker_wait();
322
+ if (srv_shutdown_state > 0) {
326
+ trx_purge_worker(worker_id);
331
+ mutex_enter(&kernel_mutex);
332
+ srv_n_threads_active[SRV_PURGE_WORKER]--;
333
+ mutex_exit(&kernel_mutex);
334
+ os_thread_exit(NULL);
336
+ OS_THREAD_DUMMY_RETURN;
338
diff -ruN a/storage/innodb_plugin/srv/srv0start.c b/storage/innodb_plugin/srv/srv0start.c
339
--- a/storage/innodb_plugin/srv/srv0start.c 2010-04-29 16:39:34.000000000 +0900
340
+++ b/storage/innodb_plugin/srv/srv0start.c 2010-04-30 14:25:25.000000000 +0900
344
/** io_handler_thread parameters for thread identification */
345
-static ulint n[SRV_MAX_N_IO_THREADS + 6];
346
+static ulint n[SRV_MAX_N_IO_THREADS + 6 + 64];
347
/** io_handler_thread identifiers */
348
-static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6];
349
+static os_thread_id_t thread_ids[SRV_MAX_N_IO_THREADS + 6 + 64];
351
/** We use this mutex to test the return value of pthread_mutex_trylock
352
on successful locking. HP-UX does NOT return 0, though Linux et al do. */
353
@@ -1699,6 +1699,20 @@
355
os_thread_create(&srv_master_thread, NULL, thread_ids
356
+ (1 + SRV_MAX_N_IO_THREADS));
358
+ if (srv_use_purge_thread) {
361
+ os_thread_create(&srv_purge_thread, NULL, thread_ids
362
+ + (5 + SRV_MAX_N_IO_THREADS));
364
+ for (i = 0; i < srv_use_purge_thread - 1; i++) {
365
+ n[6 + i + SRV_MAX_N_IO_THREADS] = i; /* using as index for arrays in purge_sys */
366
+ os_thread_create(&srv_purge_worker_thread,
367
+ n + (6 + i + SRV_MAX_N_IO_THREADS),
368
+ thread_ids + (6 + i + SRV_MAX_N_IO_THREADS));
372
/* buf_debug_prints = TRUE; */
373
#endif /* UNIV_DEBUG */
374
diff -ruN a/storage/innodb_plugin/trx/trx0purge.c b/storage/innodb_plugin/trx/trx0purge.c
375
--- a/storage/innodb_plugin/trx/trx0purge.c 2010-04-06 23:07:14.000000000 +0900
376
+++ b/storage/innodb_plugin/trx/trx0purge.c 2010-04-30 14:13:51.000000000 +0900
378
@return own: the query graph */
381
-trx_purge_graph_build(void)
382
+trx_purge_graph_build(
383
/*=======================*/
390
heap = mem_heap_create(512);
391
fork = que_fork_create(NULL, NULL, QUE_FORK_PURGE, heap);
392
- fork->trx = purge_sys->trx;
395
thr = que_thr_create(fork, heap);
397
@@ -243,10 +244,35 @@
399
ut_a(trx_start_low(purge_sys->trx, ULINT_UNDEFINED));
401
- purge_sys->query = trx_purge_graph_build();
402
+ purge_sys->query = trx_purge_graph_build(purge_sys->trx);
404
purge_sys->view = read_view_oldest_copy_or_open_new(ut_dulint_zero,
407
+ purge_sys->n_worker = 0;
408
+ if (srv_use_purge_thread > 1) {
409
+ /* Use worker threads */
412
+ purge_sys->n_worker = srv_use_purge_thread - 1;
414
+ purge_sys->sess_arr = mem_alloc(sizeof(sess_t*) * purge_sys->n_worker);
415
+ purge_sys->trx_arr = mem_alloc(sizeof(trx_t*) * purge_sys->n_worker);
416
+ purge_sys->query_arr = mem_alloc(sizeof(que_t*) * purge_sys->n_worker);
418
+ purge_sys->worker_event = os_event_create(NULL);
419
+ os_event_reset(purge_sys->worker_event);
421
+ for (i = 0; i < purge_sys->n_worker; i++) {
422
+ purge_sys->sess_arr[i] = sess_open();
424
+ purge_sys->trx_arr[i] = purge_sys->sess_arr[i]->trx;
425
+ purge_sys->trx_arr[i]->is_purge = 1;
426
+ ut_a(trx_start_low(purge_sys->trx_arr[i], ULINT_UNDEFINED));
428
+ purge_sys->query_arr[i] = trx_purge_graph_build(purge_sys->trx_arr[i]);
433
/************************************************************************
434
@@ -1148,7 +1174,7 @@
436
/* Handle at most 20 undo log pages in one purge batch */
438
- purge_sys->handle_limit = purge_sys->n_pages_handled + 20;
439
+ purge_sys->handle_limit = purge_sys->n_pages_handled + 20 * (srv_use_purge_thread + 1);
441
old_pages_handled = purge_sys->n_pages_handled;
443
@@ -1167,6 +1193,9 @@
445
mutex_exit(&kernel_mutex);
447
+ if (purge_sys->n_worker)
448
+ os_event_set(purge_sys->worker_event);
450
/* srv_que_task_enqueue(thr2); */
452
if (srv_print_thread_releases) {
453
@@ -1176,6 +1205,9 @@
455
que_run_threads(thr);
457
+ if (purge_sys->n_worker)
458
+ os_event_reset(purge_sys->worker_event);
460
if (srv_print_thread_releases) {
463
@@ -1186,6 +1218,52 @@
464
return(purge_sys->n_pages_handled - old_pages_handled);
467
+/**********************************************************************
468
+This function runs a purge worker batch */
477
+ mutex_enter(&kernel_mutex);
479
+ thr = que_fork_start_command(purge_sys->query_arr[worker_id]);
483
+ mutex_exit(&kernel_mutex);
485
+ que_run_threads(thr);
487
+ if (purge_sys->state == TRX_STOP_PURGE) { /* optimistic */
488
+ os_event_reset(purge_sys->worker_event);
492
+/**********************************************************************
493
+This function waits the event for worker batch */
496
+trx_purge_worker_wait(void)
497
+/*=======================*/
499
+ os_event_wait(purge_sys->worker_event);
502
+/**********************************************************************
503
+This function wakes the waiting worker batch */
506
+trx_purge_worker_wake(void)
507
+/*=======================*/
509
+ if (purge_sys->n_worker)
510
+ os_event_set(purge_sys->worker_event);
513
/******************************************************************//**
514
Prints information of the purge system to stderr. */