mysql innodbpurgethreads_[MySQL 5.6] Innodb 新特性之 multi purge thread-阿里云开发者社区

本文详细介绍了MySQL 5.6版本中InnoDB的多线程Purge机制,包括Purge Coordinator线程和Worker线程的工作原理,以及如何通过参数Innodb_purge_threads控制Purge操作的后台线程数。当innodb_fast_shutdown设置为0时,Purge线程将持续工作直至所有记录被清除。
摘要由CSDN通过智能技术生成

在做5.6.12 vs 5.6.11的性能对比时,大量update产生了很长的purge history list。手贱把innodb_fast_shutdowns设置为0了,结果Purge线程一直干活了,差不多两个小时才结束….

我们知道,在MySQL5.5版本中,就已经开始将purge 任务从master线程中独立出来,而到了5.6,已经支持多个purge线程同时进行,简单的理了下代码逻辑.

在5.6中,提供了参数Innodb_purge_threads来控制做purge操作的后台线程数,最大允许设置为32.

purge线程被分为两类,一类是coordinator thread,只有一个这样的线程,另外的Innodb_purge_threads-1个是worker线程.

线程在Innodb启动时创建

quoted code in innobase_start_or_create_for_mysql:

2584 if (!srv_read_only_mode

2585 && srv_force_recovery < SRV_FORCE_NO_BACKGROUND) {

2586

2587 os_thread_create(

2588 srv_purge_coordinator_thread,

2589 NULL, thread_ids + 5 + SRV_MAX_N_IO_THREADS);

2590

2591 ut_a(UT_ARR_SIZE(thread_ids)

2592 > 5 + srv_n_purge_threads + SRV_MAX_N_IO_THREADS);

2593

2594 /* We've already created the purge coordinator thread above. */

2595 for (i = 1; i < srv_n_purge_threads; ++i) {

2596 os_thread_create(

2597 srv_worker_thread, NULL,

2598 thread_ids + 5 + i + SRV_MAX_N_IO_THREADS);

2599 }

2600

2601 srv_start_wait_for_purge_to_start();

2602

2603 } else {

2604 purge_sys->state = PURGE_STATE_DISABLED;

2605 }

a. coordinator thread

协调线程的入口函数是srv_purge_coordinator_thread

分为三个阶段:

正常工作阶段,在一个while循环中调用:

2754 rseg_history_len = srv_do_purge(

2755 srv_n_purge_threads, &n_total_purged);

从while break的条件由函数srv_purge_should_exit确定,这里有一个特殊情况,当innodb_fast_shutdown设置为0时,如果上一次purge的Page数不为0,则返回false,表示不退出循环,这是因为当fast shutdown为0时,需要做完所有的purge操作才会结束线程任务

第二个阶段是确认innodb_fast_shutdown被设置为0时,所有的记录都被purge掉了;这可以避免在退出上述循环后,有新的记录加入。这里已经不再使用worker线程了(trx_purge的第一个参数为1)

2769 while (srv_fast_shutdown == 0 && n_pages_purged > 0) {

2770 n_pages_purged = trx_purge(1, srv_purge_batch_size, false);

2771 }

最后对history list做一次truncate,并确保所有worker线程退出

2773 /* Force a truncate of the history list. */

2774 n_pages_purged = trx_purge(1, srv_purge_batch_size, true);

这里有两个需要关注的函数:

a1)srv_do_purge:

在协调线程的主要工作都是在这个函数中,注意,不是有多少工作线程,就会用多少的,这里 实际上是把多余的线程当做一个池子,只有purge跟不上更新的时候,才会去调度这些线程:

调整n_use_threads

>>当trx_sys->rseg_history_len相比上次purge有增长时,或者超过了innodb_max_purge_lag_delay(不为0),++n_use_threads

>>否则,如果存在activity(srv_check_activity),–n_use_threads

执行purge调度

2577 n_pages_purged = trx_purge(

2578 n_use_threads, srv_purge_batch_size, false);

每128次purge, truncate一次history list,这也是为什么我们每隔一会,才看到history list长度变小的原因

2580 if (!(count++ % TRX_SYS_N_RSEGS)) {

2581 /* Force a truncate of the history list. */

2582 n_pages_purged += trx_purge(

2583 1, srv_purge_batch_size, true);

2584 }

a2)  trx_purge

trx_purge是purge任务调度的核心函数,包含三个参数:

* n_purge_threads —>使用到的worker线程数

* batch_size  —-> 由innodb_purge_batch_size控制,表示一次Purge的记录数

* truncate —>是否truncate history list

持有purge_sys->latch的x锁,并建立read view,然后释放锁

purge_sys->view = read_view_purge_open(purge_sys->heap);

读取需要purge的undo记录,记录数不超过batch size,这些purge任务被指派给n_purge_threads个thr

1213 /* Fetch the UNDO recs that need to be purged. */

1214 n_pages_handled = trx_purge_attach_undo_recs(

1215 n_purge_threads, purge_sys, &purge_sys->limit, batch_size);

当n_purge_threads>1时,会将n_purge_threads-1个thr加入到工作队列,由worker线程来消费

1221 /* Submit the tasks to the work queue. */

1222 for (i = 0; i < n_purge_threads - 1; ++i) {

1223 thr = que_fork_scheduler_round_robin(

1224 purge_sys->query, thr);

1225

1226 ut_a(thr != NULL);

1227

1228 srv_que_task_enqueue_low(thr);

1229 }

调度线程同样也需要运行一个thr任务,而不是仅仅只做分配;完成后,还需要等待其他worker线程完成任务

1243 run_synchronously:

1244 ++purge_sys->n_submitted;

1245

1246 que_run_threads(thr);

1247

1248 os_atomic_inc_ulint(

1249 &purge_sys->bh_mutex, &purge_sys->n_completed, 1);

1250

1251 if (n_purge_threads > 1) {

1252 trx_purge_wait_for_workers_to_complete(purge_sys);

1253 }

当truncate为true时,还需要调用trx_purge_truncate–>trx_purge_truncate_history从回滚段中移除历史记录。

b.worker thread

入口函数是srv_worker_thread

2473 do {

2474 srv_suspend_thread(slot);

2475

2476 os_event_wait(slot->event);

2477

2478 if (srv_task_execute()) {

2479

2480 /* If there are tasks in the queue, wakeup

2481 the purge coordinator thread. */

2482

2483 srv_wake_purge_thread_if_not_active();

2484 }

2485

2486 /* Note: we are checking the state without holding the

2487 purge_sys->latch here. */

2488 } while (purge_sys->state != PURGE_STATE_EXIT);

purge_sys->state是协调线程在将要退出前设置成PURGE_STATE_EXIT。因此worker线程总是在coordinator线程退出之后再退出

srv_task_execute()的工作流程也很简单: 持有srv_sys->tasks_mutex锁,从srv_sys->tasks中取出一个thr,然后释放tasks_mutex。再调用que_run_threads(thr)完成purge

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值