zoukankan      html  css  js  c++  java
  • 事务并发控制

    事务并发控制

    在MySQL5.7中,由于消除了大量临界资源的竞争,InnoDB只读查询的性能非常优化,几乎可以随着CPU线性扩展。但如果进入到读写混合的场景,就不可避免的使用到一些临界资源,例如事务、锁、日志等子系统。当竞争越激烈,就可能导致性能的下降。通常系统会有个吞吐量和响应时间最优的性能拐点。

    InnoDB本身提供了并发控制机制,一种是语句级别的并发控制,另外一种是事务提交阶段的并发控制。

    语句级别的并发通过参数innodb_thread_concurrency来控制,表示允许同时在InnoDB层活跃的并发SQL数。

    每条SQL在进入InnoDB层进行操作之前都需要先递增全局计数,并为当前SQL分配innodb_concurrency_tickets个ticket。也就是说,如果当前SQL需要进出InnoDB层很多次(例如一个大查询需要扫描很多行数据时),innodb_concurrency_tickets次都可以自由进入InnoDB,无需判断innodb_thread_concurrency。当ticket用完时,就需要重新进入,当SQL执行完成后,会将ticket重置为0。

    如果当前InnoDB层的并发度已满,用户线程就需要等待,目前的实现使用sleep一段时间的方式,sleep的时间是自适应的,但你可以通过参数innodb_adaptive_max_sleep_delay来设置一个最大sleep事件,具体的算法参阅函数srv_conc_enter_innodb_with_atomics

    提到并发控制,另外一个不得不提的问题就是热点更新问题。事务在进入InnoDB层,准备更新一条数据,但发现行记录被其他线程锁住,这时候该线程会强制退出InnoDB并发控制,同时将自己suspend住,进入睡眠等待。如果有大量并发的更新同一条记录,就意味着大量线程进入InnoDB层,访问热点竞争资源锁系统,然后再退出。最终会呈现出大量线程在InnoDB中suspend住,相当于并发控制并没有达到降低临界资源争用的效果。早期我们对该问题的优化就是将线程从堵在InnoDB层,转移到堵在进入InnoDB层时的外部排队中,这样就不涉及到InnoDB的资源争用了。具体的实现是将statement级别的并发控制提升为事务级别的并发控制,因此这个方案的缺陷是对长事务不友好。

    另外还有一些并发控制方案,例如线程池、水位限流、按pk排队等策略,我们的RDS MySQL也很早就支持了。如果你存在热点争用(例如秒杀场景),并且正在使用RDS MySQL,你可以去咨询售后如何使用这些特性。

    除了语句级别的并发外,InnoDB也提供了提交阶段的并发控制,主要通过参数innodb_commit_concurrency来控制。该参数的默认值为0,表示不控制commit阶段的并发。在进入函数innobase_commit时,如果该参数被设置,且当前并发度超过,就需要等待。然而由于当前在默认配置下所有事务都走组提交(ordered_commit),InnoDB层的提交大多数情况下只会有一个活跃线程。你只有关闭binlog或者关闭参数binlog_order_commits,这个参数设置才有意义。

  • 相关阅读:
    ztree实现树的异步加载
    form submit提交遇到的问题
    js页面刷新常用的几种方式
    IE6下的按钮效果
    实现两个div并排的三种方式
    继续推荐Android12个自测源码
    优秀程序员实现向卓越程序员跨越
    面试那点事【面试题+面试技巧+职位推荐】
    Android 开发源码分享
    Android 亲测源码分享
  • 原文地址:https://www.cnblogs.com/yuyue2014/p/5546529.html
Copyright © 2011-2022 走看看