Innodb内核线程并发

Authortc-ql@163.com  

 

Innodb内核线程并发

 

Innodb内部并发工作机制。

 

Innodb_thread_concurrency变量是内部最大线程数,还有另外两个重要的参数

Innodb_thread_sleep_delay

Innodb_concurrency_tickets

 

 

解释一下他们是如何工作的

 

Mysql工作模式和其他数据库系统不一样,它是插件式存储引擎结构的,通常包含解析,优化和存储引擎。我们以存储引擎为出发点看看mysql是如何工作的,相比研究整个MYSQL要更容易一些。

 

Mysql调用存储引擎的方法:

read_row

这样的方法有好几个,例如:read by index(有序读)sequential read(连续读)random read(随机读)

 

write_row;
update_row;
delete_row;
具体函数参见源码。

 

要执行这些方法(函数),innodb需要检查innodb内部的线程计数,如果内部线程计数超过innodb_thread_concurrency,就等待innodb_thread_sleep_delay变量设置的微妙后再尝试进入。如果第二次仍然不成功-进入线程队列sleepFIFO)。

 

 

为什么innodb使用两次尝试?

减少线程等待计数和降低上下文切换。

 

一但线程ENTERED(进入),就会得到innodb_concurrency_tickets票数,以便以后的innodb_concurrency_tickets变量次数线程都不会再次检测,可以免check进入。

该参数保持默认的500即可。

 

 

就像下面的代码描述一样:

这是国外著名mysql牛人简化过的代码

  if (thread->n_tickets_to_enter_innodb  > 0)
 

{
    thread->n_tickets_to_enter_innodb--;
   

ENTER;
 

}

retry:
 

if (entered_thread < innodb_thread_concurrency)
 

{
    entered_threads++;

thread->n_tickets_to_enter_innodb = innodb_concurrency_tickets;

    ENTER;
 

}

 

if (innodb_thread_sleep_delay  > 0)
 

{
   

thread_sleep(innodb_thread_sleep_delay);
 

}

 

goto retry; // (only once)

 

WAIT_IN_FIFO_QUEUE;
 

thread->n_tickets_to_enter_innodb = innodb_concurrency_tickets;
 

ENTER;

 

完整的代码路径: srv_conc_enter_innodb function in innobase/srv/srv0srv.c

Same sql源码如此描述,一旦线程在获得ticketsrv_conc_enter_innodb)后,允许进入innodb内核执行同样SQL的次数。在这个次数内不会再次进行check验证。通过这种方式节约大量的信号操作。

 

说到这里不得不提一下INNODB的关闭:

如果下面的参数被设置为1,在关闭前我们不运行净化和插入缓冲合并。如果设置为2,关闭时不会把缓冲池刷新到数据文件:我们采用有效的手段使INNODB“崩溃”(但不丢失任何未提交的事务)。

ulint   srv_fast_shutdown       = 0;  (源代码里面默认值是0,数据库默认值是1

 

细细品味过这段代码,你会发现,对控制文件合理调整使用,再请一位善于控制SQLDBA来审核代码,数据库是不会发生崩溃这么变态的事情的,负载过高的,顶多是慢一些。(加服务器呗,还想啥呢--

 

 

 

那么什么是innodb_thread_concurrency最佳值?

这个值依赖许多因素,包括你的负载量,跑在什么样的硬件的软件上。如果你有1-2CPU,你经常能做的很好,可以禁用它(innodb_thread_concurrency=0,从5.0.19开始还有更多的默认值)。多个CPU4+CPU)的情况又有所不同。

 

MYSQL5.1以后对多核CPU支持改进了很多,将该值设置为0,或者2*CPU是一个比较好的注意。

 

waiting in InnoDB queue状态频繁出现,说明数据库并发太大,需要分析引起并发太大的原因或者增加数据库服务器(假设你根据硬件精确计算了该值)。

 

理论上你可以使用2*NUMCPU+NUMDISKS)计算值以便能够激活2倍于CPU加磁盘的资源。然后在实际环境中,实践被证明,这个值并不是最优的。

如果正在使用innodb,这个值设置的小于CPU数量,mysql将不会利用到所有的CPU资源。

 

关于innodb_commit_concurrency

如你所见innodb_commit_concurrency仅用来保护行访问,使用内部结构和锁定分阶段提交,他仍是为保护变量。他限制innodb内核激活线程的commit。一个最佳的值也依赖很多其他因素。但是从5.1.36开始mysql不允许将该值设置为非0,该值只能为默认值0mysql不限制并发提交。

 

如果没有电池保护,设置为innodb_flush_logs_at_trx_commit=1,但你可能想使用20。如果二进制日志被开启,他通常不重要,innodb会进行同步操作。

 

 

unix平台测试的结果:

日志刷新方法设置为O_DIRECT

innodb_flush_logs_at_trx_commit 改参数的调整对性能和崩溃恢复数据丢失至关重要

1                       2                              0

                    提升130%                       提升10%

 

一般设置为2是一种平衡的方法,崩溃丢失1-2秒的数据,1是默认的,但是十分影响性能,如果是在要求十分安全的应用中,建议为1,并且设置日志同步sync_log

 

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/25379809/viewspace-704001/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/25379809/viewspace-704001/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值