天天看点

[MySQL 5.6] Innodb并发控制改进

从5.6开始,如果使用了gcc build-in的原子操作,在进入innodb层的线程并发控制走与之前不同的逻辑,5.5也可以调用通过原子操作进行并发控制的逻辑,但需要打开只读选项innodb_thread_concurrency_timer_based来控制.

quoted code in 5.6:

srv_conc_enter_innodb_without_atomics是mysql5.5的调用逻辑,在5.6中开始默认编译情况下,调用srv_conc_enter_innodb_with_atomics逻辑,其不同之处在于使用gcc build-in的原子操作,来避免热点锁srv_conc_mutex的频繁加锁/释放。

原先的做法是在进入innodb层前,先查看当前在innodb中活跃的线程数是否超过innodb_thread_concurrency; 如果超过了,则sleep一段时间,再重试,如果还是超过并发限制时,就给其分配一个slot,让其进入信号量等待。

在5.6中,当使用原子操作进行并发控制时,如果innodb_adaptive_max_sleep_delay大于0, 会对另外一个参数innodb_thread_sleep_delay的值做自适应调整.它的逻辑也很简单。

我们这里假定innodb_adaptive_max_sleep_delay的值大于0 

当线程能够进入innodb层时:

a.如果当前线程之前sleep过一次,并且当前innodb_thread_sleep_delay>20,将innodb_thread_sleep_delay减1

b.如果当前没有等待的线程,将innodb_thread_sleep_delay除以2

如果线程目前因并发控制无法进入innodb层:

a.如果当前innodb_thread_sleep_delay>innodb_adaptive_max_sleep_delay

,将innodb_thread_sleep_delay的值设置为innodb_adaptive_max_sleep_delay

b.sleep  innodb_thread_sleep_delay毫秒

c.如果该线程已经sleep了超过1次,将innodb_thread_sleep_delay++

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

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

另外注意,在使用原子操作进行并发控制后,就再也没有使用信号量让线程进行等待了。

这种自适应调整策略的效率依然有待于评估,也不确定其对某些工作负载是否存在不利影响。合适的参数配置应当由性能测试来给出。

继续阅读