mysql innodb 并发_mysql并发线程控制之innodb_thread_concurrency的改进

innodb_thread_concurrency算法介绍:

1、server层到innodb层读写数据是一条一条记录进行的,每次读写都会进/出一次InnoDB层(row_search_for_mysql),进入InnoDB层的时候会检查当前并发线程数目,当超过innodb_thread_concurrency时,线程将尝试spin和sleep并再次检查,如果并发数还是超过innodb_thread_concurrency,线程将进入到一个FIFO中等待被唤醒,读写记录结束后退出InnoDB层时会将当前并发线程数减1,并检查其是否低于innodb_thread_concurrency,如果是的话,从FIFO中唤醒一个等待的线程,保证并发线程不会超过innodb_thread_concurrency参数。

2、当线程进入InnoDB层后,但在获取数据时由于锁请求无法得到满足而需要挂起时,线程将强制退出InnoDB层,当锁请求满足后,线程继续运行并强制进入到InnoDB层,这会导致实际并发线程数不是严格控制在innodb_thread_concurrency之内

代码调用逻辑

主要函数:

innodb_srv_conc_enter_innodb

innodb_srv_conc_exit_innodb

srv_conc_force_enter_innodb

srv_conc_force_exit_innodb

调用逻辑

进入/退出InnoDB层

ha_innobase::index_read

ha_innobase::general_fetch

row_check_index_for_mysql

...

innodb_srv_conc_enter_innodb(prebuilt->trx);

ret = row_search_for_mysql((byte*) buf, mode,

prebuilt,  match_mode, 0);

innodb_srv_conc_exit_innodb(prebuilt->trx);

...

锁等待逻辑:

srv_suspend_mysql_thread

...

if (trx->declared_to_be_inside_innodb)

{

was_declared_inside_innodb =

TRUE;

/* We must declare this OS

thread to exit InnoDB, since a

possible other thread holding

a lock which this thread waits

for must be allowed to enter,

sooner or later */

srv_conc_force_exit_innodb(trx);

}

/* Suspend this thread and wait for the

event. */

thd_wait_begin(trx->mysql_thd,

THD_WAIT_ROW_LOCK);

os_event_wait(event);

thd_wait_end(trx->mysql_thd);

if (was_declared_inside_innodb) {

/* Return back inside InnoDB

*/

srv_conc_force_enter_innodb(trx);

}

5.6的改进

从5.6开始,默认编译会使用GCC atomic,可避免热点锁srv_conc_mutex的频繁加锁/释放。

Pre-5.5如果超过并发限制时,就给其线程分配一个slot,让其进入信号量等待,原子操作则无需使用信号量。

function srv_conc_enter_innodb:

ifdef HAVE_ATOMIC_BUILTINS

srv_conc_enter_innodb_with_atomics(trx);

#else

srv_conc_enter_innodb_without_atomics(trx);

#endif /* HAVE_ATOMIC_BUILTINS */

5.6引入adaptive sleep,允许innodb根据系统负载进行自适应调整,当innodb_adaptive_max_sleep_delay>0,innodb_thread_sleep_delay则会动态调整(以前者为上限)。

ada还ptive 的算法是:

如果sleep了当前值以后还是不能进入,就把sleep时间+1;

如果还有线程在sleep时,已经有了空闲线程,就把当前值的sleep 时间减半。

innodb_thread_sleep_delay降低比增加的更快,这样在并发线程数很高时,当限制并发数早就达到,其他线程的每次sleep时间会缓慢拉长。而当Innodb层很空闲时,sleep时间又会快速降到非常低

调整sleep到一个优化值的目的是,过小的sleep值可能会产生太多的线程切换,但过长的sleep时间,在并发比较空闲的时候又会影响性能。新的并发控制策略有利于随着负载的变化而做自适应调整。

Innodb_thread_concurrency不足

1线程因为锁等待而退出innodb层,当获取锁时可以直接重入innodb(跳过此参数检查),因此系统并发执行的线程数可能大于此参数值。

2代码路径靠后,此时线程已经开始执行命令,进入到ha_innobase,应该在mysql_start_query前限制即thread_running。

为此好多技术高手开发了相应patch,从server层控制并发执行的线程数,下文将做描述。

参考文章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值